mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-15 08:34:30 +02:00
Merge
This commit is contained in:
commit
a5fbc1aa4d
578 changed files with 10375 additions and 4276 deletions
1
.hgtags
1
.hgtags
|
@ -189,3 +189,4 @@ cdaa6122185f9bf512dcd6600f56bfccc4824e8c jdk8-b61
|
||||||
a2cf4d4a484378caea2e827ed604b2bbae58bdba jdk8-b65
|
a2cf4d4a484378caea2e827ed604b2bbae58bdba jdk8-b65
|
||||||
17820b958ae84f7c1cc6719319c8e2232f7a4f1d jdk8-b66
|
17820b958ae84f7c1cc6719319c8e2232f7a4f1d jdk8-b66
|
||||||
76cc9bd3ece407d3a15d3bea537b57927973c5e7 jdk8-b67
|
76cc9bd3ece407d3a15d3bea537b57927973c5e7 jdk8-b67
|
||||||
|
cb33628d4e8f11e879c371959e5948b66a53376f jdk8-b68
|
||||||
|
|
|
@ -189,3 +189,4 @@ e07f499b9dccb529ecf74172cf6ac11a195ec57a jdk8-b60
|
||||||
b772de306dc24c17f7bd1398531ddeb58723b804 jdk8-b65
|
b772de306dc24c17f7bd1398531ddeb58723b804 jdk8-b65
|
||||||
13bb8c326e7b7b0b19d78c8088033e3932e3f7ca jdk8-b66
|
13bb8c326e7b7b0b19d78c8088033e3932e3f7ca jdk8-b66
|
||||||
9a6ec97ec45c1a62d5233cefa91e8390e380e13a jdk8-b67
|
9a6ec97ec45c1a62d5233cefa91e8390e380e13a jdk8-b67
|
||||||
|
cdb401a60cea6ad5ef3f498725ed1decf8dda1ea jdk8-b68
|
||||||
|
|
|
@ -90,13 +90,25 @@ AC_DEFUN([BASIC_FIXUP_EXECUTABLE],
|
||||||
tmp="$complete EOL"
|
tmp="$complete EOL"
|
||||||
arguments="${tmp#* }"
|
arguments="${tmp#* }"
|
||||||
|
|
||||||
new_path=`$WHICH $path 2> /dev/null`
|
# Cannot rely on the command "which" here since it doesn't always work.
|
||||||
|
is_absolute_path=`$ECHO "$path" | $GREP ^/`
|
||||||
|
if test -z "$is_absolute_path"; then
|
||||||
|
# Path to executable is not absolute. Find it.
|
||||||
|
IFS_save="$IFS"
|
||||||
|
IFS=:
|
||||||
|
for p in $PATH; do
|
||||||
|
if test -f "$p/$path" && test -x "$p/$path"; then
|
||||||
|
new_path="$p/$path"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
IFS="$IFS_save"
|
||||||
|
else
|
||||||
|
AC_MSG_NOTICE([Resolving $1 (as $path) failed, using $path directly.])
|
||||||
|
new_path="$path"
|
||||||
|
fi
|
||||||
|
|
||||||
if test "x$new_path" = x; then
|
if test "x$new_path" = x; then
|
||||||
is_absolute_path=`$ECHO "$path" | $GREP ^/`
|
|
||||||
if test "x$is_absolute_path" != x; then
|
|
||||||
AC_MSG_NOTICE([Resolving $1 (as $path) with 'which' failed, using $path directly.])
|
|
||||||
new_path="$path"
|
|
||||||
else
|
|
||||||
AC_MSG_NOTICE([The path of $1, which resolves as "$complete", is not found.])
|
AC_MSG_NOTICE([The path of $1, which resolves as "$complete", is not found.])
|
||||||
has_space=`$ECHO "$complete" | $GREP " "`
|
has_space=`$ECHO "$complete" | $GREP " "`
|
||||||
if test "x$has_space" != x; then
|
if test "x$has_space" != x; then
|
||||||
|
@ -104,20 +116,19 @@ AC_DEFUN([BASIC_FIXUP_EXECUTABLE],
|
||||||
fi
|
fi
|
||||||
AC_MSG_ERROR([Cannot locate the the path of $1])
|
AC_MSG_ERROR([Cannot locate the the path of $1])
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Now join together the path and the arguments once again
|
# Now join together the path and the arguments once again
|
||||||
if test "x$arguments" != xEOL; then
|
if test "x$arguments" != xEOL; then
|
||||||
new_complete="$new_path ${arguments% *}"
|
new_complete="$new_path ${arguments% *}"
|
||||||
else
|
else
|
||||||
new_complete="$new_path"
|
new_complete="$new_path"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test "x$complete" != "x$new_complete"; then
|
if test "x$complete" != "x$new_complete"; then
|
||||||
$1="$new_complete"
|
$1="$new_complete"
|
||||||
AC_MSG_NOTICE([Rewriting $1 to "$new_complete"])
|
AC_MSG_NOTICE([Rewriting $1 to "$new_complete"])
|
||||||
fi
|
fi
|
||||||
])
|
])
|
||||||
|
|
||||||
AC_DEFUN([BASIC_REMOVE_SYMBOLIC_LINKS],
|
AC_DEFUN([BASIC_REMOVE_SYMBOLIC_LINKS],
|
||||||
|
|
File diff suppressed because it is too large
Load diff
194
common/bin/hgforest.sh
Normal file
194
common/bin/hgforest.sh
Normal file
|
@ -0,0 +1,194 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright (c) 2009, 2012, 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
# Shell script for a fast parallel forest command
|
||||||
|
command="$1"
|
||||||
|
pull_extra_base="$2"
|
||||||
|
|
||||||
|
# Python always buffers stdout significantly, thus we will not see any output from hg clone jdk,
|
||||||
|
# until a lot of time has passed! By passing -u to python, we get incremental updates
|
||||||
|
# on stdout. Much nicer.
|
||||||
|
whichhg="`which hg`"
|
||||||
|
|
||||||
|
if [ "${whichhg}" = "" ] ; then
|
||||||
|
echo Cannot find hg!
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "" = "$command" ] ; then
|
||||||
|
echo No command to hg supplied!
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
has_hash_bang="`head -n 1 "${whichhg}" | cut -b 1-2`"
|
||||||
|
python=""
|
||||||
|
bpython=""
|
||||||
|
|
||||||
|
if [ "#!" = "$has_hash_bang" ] ; then
|
||||||
|
python="`head -n 1 ${whichhg} | cut -b 3-`"
|
||||||
|
bpython="`basename "$python"`"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "python" = "$bpython" -a -x "$python" ] ; then
|
||||||
|
hg="${python} -u ${whichhg}"
|
||||||
|
else
|
||||||
|
echo Cannot find python from hg launcher. Running plain hg, which probably has buffered stdout.
|
||||||
|
hg="hg"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Clean out the temporary directory that stores the pid files.
|
||||||
|
tmp=/tmp/forest.$$
|
||||||
|
rm -f -r ${tmp}
|
||||||
|
mkdir -p ${tmp}
|
||||||
|
|
||||||
|
safe_interrupt () {
|
||||||
|
if [ -d ${tmp} ]; then
|
||||||
|
if [ "`ls ${tmp}`" != "" ]; then
|
||||||
|
echo "Waiting for processes ( `cat ${tmp}/* | tr '\n' ' '`) to terminate nicely!"
|
||||||
|
sleep 1
|
||||||
|
# Pipe stderr to dev/null to silence kill, that complains when trying to kill
|
||||||
|
# a subprocess that has already exited.
|
||||||
|
kill -TERM `cat ${tmp}/* | tr '\n' ' '` 2> /dev/null
|
||||||
|
wait
|
||||||
|
echo Interrupt complete!
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
rm -f -r ${tmp}
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
nice_exit () {
|
||||||
|
if [ -d ${tmp} ]; then
|
||||||
|
if [ "`ls ${tmp}`" != "" ]; then
|
||||||
|
wait
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
rm -f -r ${tmp}
|
||||||
|
}
|
||||||
|
|
||||||
|
trap 'safe_interrupt' INT QUIT
|
||||||
|
trap 'nice_exit' EXIT
|
||||||
|
|
||||||
|
# Only look in specific locations for possible forests (avoids long searches)
|
||||||
|
pull_default=""
|
||||||
|
repos=""
|
||||||
|
repos_extra=""
|
||||||
|
if [ "${command}" = "clone" -o "${command}" = "fclone" ] ; then
|
||||||
|
subrepos="corba jaxp jaxws langtools jdk hotspot"
|
||||||
|
if [ -f .hg/hgrc ] ; then
|
||||||
|
pull_default=`hg paths default`
|
||||||
|
if [ "${pull_default}" = "" ] ; then
|
||||||
|
echo "ERROR: Need initial clone with 'hg paths default' defined"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [ "${pull_default}" = "" ] ; then
|
||||||
|
echo "ERROR: Need initial repository to use this script"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
for i in ${subrepos} ; do
|
||||||
|
if [ ! -f ${i}/.hg/hgrc ] ; then
|
||||||
|
repos="${repos} ${i}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ "${pull_extra_base}" != "" ] ; then
|
||||||
|
subrepos_extra="jdk/src/closed jdk/make/closed jdk/test/closed hotspot/make/closed hotspot/src/closed hotspot/test/closed deploy install sponsors pubs"
|
||||||
|
pull_default_tail=`echo ${pull_default} | sed -e 's@^.*://[^/]*/\(.*\)@\1@'`
|
||||||
|
pull_extra="${pull_extra_base}/${pull_default_tail}"
|
||||||
|
for i in ${subrepos_extra} ; do
|
||||||
|
if [ ! -f ${i}/.hg/hgrc ] ; then
|
||||||
|
repos_extra="${repos_extra} ${i}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
at_a_time=2
|
||||||
|
# Any repos to deal with?
|
||||||
|
if [ "${repos}" = "" -a "${repos_extra}" = "" ] ; then
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
hgdirs=`ls -d ./.hg ./*/.hg ./*/*/.hg ./*/*/*/.hg ./*/*/*/*/.hg 2>/dev/null`
|
||||||
|
# Derive repository names from the .hg directory locations
|
||||||
|
for i in ${hgdirs} ; do
|
||||||
|
repos="${repos} `echo ${i} | sed -e 's@/.hg$@@'`"
|
||||||
|
done
|
||||||
|
for i in ${repos} ; do
|
||||||
|
if [ -h ${i}/.hg/store/lock -o -f ${i}/.hg/store/lock ] ; then
|
||||||
|
locked="${i} ${locked}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
at_a_time=8
|
||||||
|
# Any repos to deal with?
|
||||||
|
if [ "${repos}" = "" ] ; then
|
||||||
|
echo "No repositories to process."
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
if [ "${locked}" != "" ] ; then
|
||||||
|
echo "These repositories are locked: ${locked}"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Echo out what repositories we do a command on.
|
||||||
|
echo "# Repositories: ${repos} ${repos_extra}"
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Run the supplied command on all repos in parallel.
|
||||||
|
n=0
|
||||||
|
for i in ${repos} ${repos_extra} ; do
|
||||||
|
n=`expr ${n} '+' 1`
|
||||||
|
repopidfile=`echo ${i} | sed -e 's@./@@' -e 's@/@_@g'`
|
||||||
|
reponame=`echo ${i} | sed -e :a -e 's/^.\{1,20\}$/ &/;ta'`
|
||||||
|
pull_base="${pull_default}"
|
||||||
|
for j in $repos_extra ; do
|
||||||
|
if [ "$i" = "$j" ] ; then
|
||||||
|
pull_base="${pull_extra}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
(
|
||||||
|
(
|
||||||
|
if [ "${command}" = "clone" -o "${command}" = "fclone" ] ; then
|
||||||
|
pull_newrepo="`echo ${pull_base}/${i} | sed -e 's@\([^:]/\)//*@\1@g'`"
|
||||||
|
echo ${hg} clone ${pull_newrepo} ${i}
|
||||||
|
${hg} clone ${pull_newrepo} ${i} &
|
||||||
|
else
|
||||||
|
echo "cd ${i} && ${hg} $*"
|
||||||
|
cd ${i} && ${hg} "$@" &
|
||||||
|
fi
|
||||||
|
echo $! > ${tmp}/${repopidfile}.pid
|
||||||
|
) 2>&1 | sed -e "s@^@${reponame}: @") &
|
||||||
|
|
||||||
|
if [ `expr ${n} '%' ${at_a_time}` -eq 0 ] ; then
|
||||||
|
sleep 2
|
||||||
|
echo Waiting 5 secs before spawning next background command.
|
||||||
|
sleep 3
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
# Wait for all hg commands to complete
|
||||||
|
wait
|
||||||
|
|
||||||
|
# Terminate with exit 0 all the time (hard to know when to say "failed")
|
||||||
|
exit 0
|
||||||
|
|
|
@ -131,6 +131,7 @@ CORE_PKGS = \
|
||||||
java.util.concurrent \
|
java.util.concurrent \
|
||||||
java.util.concurrent.atomic \
|
java.util.concurrent.atomic \
|
||||||
java.util.concurrent.locks \
|
java.util.concurrent.locks \
|
||||||
|
java.util.function \
|
||||||
java.util.jar \
|
java.util.jar \
|
||||||
java.util.logging \
|
java.util.logging \
|
||||||
java.util.prefs \
|
java.util.prefs \
|
||||||
|
|
|
@ -189,3 +189,4 @@ d54dc53e223ed9ce7d5f4d2cd02ad9d5def3c2db jdk8-b59
|
||||||
5132f7900a8f0c30c3ca7f7a32f9433f4fee7745 jdk8-b65
|
5132f7900a8f0c30c3ca7f7a32f9433f4fee7745 jdk8-b65
|
||||||
65771ad1ca557ca26e4979d4dc633cf685435cb8 jdk8-b66
|
65771ad1ca557ca26e4979d4dc633cf685435cb8 jdk8-b66
|
||||||
394515ad2a55d4d54df990b36065505d3e7a3cbb jdk8-b67
|
394515ad2a55d4d54df990b36065505d3e7a3cbb jdk8-b67
|
||||||
|
82000531feaa7baef76b6406099e5cd88943d635 jdk8-b68
|
||||||
|
|
|
@ -26,8 +26,8 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
# Get clones of all nested repositories
|
# Get clones of all nested repositories
|
||||||
sh ./make/scripts/hgforest.sh clone $*
|
sh ./common/bin/hgforest.sh clone "$@"
|
||||||
|
|
||||||
# Update all existing repositories to the latest sources
|
# Update all existing repositories to the latest sources
|
||||||
sh ./make/scripts/hgforest.sh pull -u
|
sh ./common/bin/hgforest.sh pull -u
|
||||||
|
|
||||||
|
|
|
@ -299,3 +299,7 @@ cfc5309f03b7bd6c1567618b63cf1fc74c0f2a8f hs25-b10
|
||||||
b61d9c88b759d1594b8af1655598e8fa00393672 hs25-b11
|
b61d9c88b759d1594b8af1655598e8fa00393672 hs25-b11
|
||||||
25bdce771bb3a7ae9825261a284d292cda700122 jdk8-b67
|
25bdce771bb3a7ae9825261a284d292cda700122 jdk8-b67
|
||||||
a35a72dd2e1255239d31f796f9f693e49b36bc9f hs25-b12
|
a35a72dd2e1255239d31f796f9f693e49b36bc9f hs25-b12
|
||||||
|
121aa71316af6cd877bf455e775fa3fdbcdd4b65 jdk8-b68
|
||||||
|
b6c9c0109a608eedbb6b868d260952990e3c91fe hs25-b13
|
||||||
|
cb8a4e04bc8c104de8a2f67463c7e31232bf8d68 jdk8-b69
|
||||||
|
990bbd393c239d95310ccc38094e57923bbf1d4a hs25-b14
|
||||||
|
|
|
@ -69,6 +69,8 @@ public class ConstMethod extends VMObject {
|
||||||
signatureIndex = new CIntField(type.getCIntegerField("_signature_index"), 0);
|
signatureIndex = new CIntField(type.getCIntegerField("_signature_index"), 0);
|
||||||
idnum = new CIntField(type.getCIntegerField("_method_idnum"), 0);
|
idnum = new CIntField(type.getCIntegerField("_method_idnum"), 0);
|
||||||
maxStack = new CIntField(type.getCIntegerField("_max_stack"), 0);
|
maxStack = new CIntField(type.getCIntegerField("_max_stack"), 0);
|
||||||
|
maxLocals = new CIntField(type.getCIntegerField("_max_locals"), 0);
|
||||||
|
sizeOfParameters = new CIntField(type.getCIntegerField("_size_of_parameters"), 0);
|
||||||
|
|
||||||
// start of byte code
|
// start of byte code
|
||||||
bytecodeOffset = type.getSize();
|
bytecodeOffset = type.getSize();
|
||||||
|
@ -96,6 +98,8 @@ public class ConstMethod extends VMObject {
|
||||||
private static CIntField signatureIndex;
|
private static CIntField signatureIndex;
|
||||||
private static CIntField idnum;
|
private static CIntField idnum;
|
||||||
private static CIntField maxStack;
|
private static CIntField maxStack;
|
||||||
|
private static CIntField maxLocals;
|
||||||
|
private static CIntField sizeOfParameters;
|
||||||
|
|
||||||
// start of bytecode
|
// start of bytecode
|
||||||
private static long bytecodeOffset;
|
private static long bytecodeOffset;
|
||||||
|
@ -151,6 +155,14 @@ public class ConstMethod extends VMObject {
|
||||||
return maxStack.getValue(this);
|
return maxStack.getValue(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getMaxLocals() {
|
||||||
|
return maxLocals.getValue(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getSizeOfParameters() {
|
||||||
|
return sizeOfParameters.getValue(this);
|
||||||
|
}
|
||||||
|
|
||||||
public Symbol getName() {
|
public Symbol getName() {
|
||||||
return getMethod().getName();
|
return getMethod().getName();
|
||||||
}
|
}
|
||||||
|
@ -247,6 +259,8 @@ public class ConstMethod extends VMObject {
|
||||||
visitor.doCInt(signatureIndex, true);
|
visitor.doCInt(signatureIndex, true);
|
||||||
visitor.doCInt(codeSize, true);
|
visitor.doCInt(codeSize, true);
|
||||||
visitor.doCInt(maxStack, true);
|
visitor.doCInt(maxStack, true);
|
||||||
|
visitor.doCInt(maxLocals, true);
|
||||||
|
visitor.doCInt(sizeOfParameters, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accessors
|
// Accessors
|
||||||
|
|
|
@ -50,8 +50,6 @@ public class Method extends Metadata {
|
||||||
constMethod = type.getAddressField("_constMethod");
|
constMethod = type.getAddressField("_constMethod");
|
||||||
methodData = type.getAddressField("_method_data");
|
methodData = type.getAddressField("_method_data");
|
||||||
methodSize = new CIntField(type.getCIntegerField("_method_size"), 0);
|
methodSize = new CIntField(type.getCIntegerField("_method_size"), 0);
|
||||||
maxLocals = new CIntField(type.getCIntegerField("_max_locals"), 0);
|
|
||||||
sizeOfParameters = new CIntField(type.getCIntegerField("_size_of_parameters"), 0);
|
|
||||||
accessFlags = new CIntField(type.getCIntegerField("_access_flags"), 0);
|
accessFlags = new CIntField(type.getCIntegerField("_access_flags"), 0);
|
||||||
code = type.getAddressField("_code");
|
code = type.getAddressField("_code");
|
||||||
vtableIndex = new CIntField(type.getCIntegerField("_vtable_index"), 0);
|
vtableIndex = new CIntField(type.getCIntegerField("_vtable_index"), 0);
|
||||||
|
@ -83,8 +81,6 @@ public class Method extends Metadata {
|
||||||
private static AddressField constMethod;
|
private static AddressField constMethod;
|
||||||
private static AddressField methodData;
|
private static AddressField methodData;
|
||||||
private static CIntField methodSize;
|
private static CIntField methodSize;
|
||||||
private static CIntField maxLocals;
|
|
||||||
private static CIntField sizeOfParameters;
|
|
||||||
private static CIntField accessFlags;
|
private static CIntField accessFlags;
|
||||||
private static CIntField vtableIndex;
|
private static CIntField vtableIndex;
|
||||||
private static CIntField invocationCounter;
|
private static CIntField invocationCounter;
|
||||||
|
@ -134,8 +130,8 @@ public class Method extends Metadata {
|
||||||
/** WARNING: this is in words, not useful in this system; use getObjectSize() instead */
|
/** WARNING: this is in words, not useful in this system; use getObjectSize() instead */
|
||||||
public long getMethodSize() { return methodSize.getValue(this); }
|
public long getMethodSize() { return methodSize.getValue(this); }
|
||||||
public long getMaxStack() { return getConstMethod().getMaxStack(); }
|
public long getMaxStack() { return getConstMethod().getMaxStack(); }
|
||||||
public long getMaxLocals() { return maxLocals.getValue(this); }
|
public long getMaxLocals() { return getConstMethod().getMaxLocals(); }
|
||||||
public long getSizeOfParameters() { return sizeOfParameters.getValue(this); }
|
public long getSizeOfParameters() { return getConstMethod().getSizeOfParameters(); }
|
||||||
public long getNameIndex() { return getConstMethod().getNameIndex(); }
|
public long getNameIndex() { return getConstMethod().getNameIndex(); }
|
||||||
public long getSignatureIndex() { return getConstMethod().getSignatureIndex(); }
|
public long getSignatureIndex() { return getConstMethod().getSignatureIndex(); }
|
||||||
public long getGenericSignatureIndex() { return getConstMethod().getGenericSignatureIndex(); }
|
public long getGenericSignatureIndex() { return getConstMethod().getGenericSignatureIndex(); }
|
||||||
|
@ -282,8 +278,6 @@ public class Method extends Metadata {
|
||||||
|
|
||||||
public void iterateFields(MetadataVisitor visitor) {
|
public void iterateFields(MetadataVisitor visitor) {
|
||||||
visitor.doCInt(methodSize, true);
|
visitor.doCInt(methodSize, true);
|
||||||
visitor.doCInt(maxLocals, true);
|
|
||||||
visitor.doCInt(sizeOfParameters, true);
|
|
||||||
visitor.doCInt(accessFlags, true);
|
visitor.doCInt(accessFlags, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2012
|
||||||
|
|
||||||
HS_MAJOR_VER=25
|
HS_MAJOR_VER=25
|
||||||
HS_MINOR_VER=0
|
HS_MINOR_VER=0
|
||||||
HS_BUILD_NUMBER=13
|
HS_BUILD_NUMBER=15
|
||||||
|
|
||||||
JDK_MAJOR_VER=1
|
JDK_MAJOR_VER=1
|
||||||
JDK_MINOR_VER=8
|
JDK_MINOR_VER=8
|
||||||
|
|
|
@ -298,7 +298,7 @@ void PatchingStub::emit_code(LIR_Assembler* ce) {
|
||||||
for (int i = 0; i < _bytes_to_copy; i++) {
|
for (int i = 0; i < _bytes_to_copy; i++) {
|
||||||
address ptr = (address)(_pc_start + i);
|
address ptr = (address)(_pc_start + i);
|
||||||
int a_byte = (*ptr) & 0xFF;
|
int a_byte = (*ptr) & 0xFF;
|
||||||
__ a_byte (a_byte);
|
__ emit_int8 (a_byte);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,10 +340,10 @@ void PatchingStub::emit_code(LIR_Assembler* ce) {
|
||||||
int being_initialized_entry_offset = __ offset() - being_initialized_entry + sizeof_patch_record;
|
int being_initialized_entry_offset = __ offset() - being_initialized_entry + sizeof_patch_record;
|
||||||
|
|
||||||
// Emit the patch record. We need to emit a full word, so emit an extra empty byte
|
// Emit the patch record. We need to emit a full word, so emit an extra empty byte
|
||||||
__ a_byte(0);
|
__ emit_int8(0);
|
||||||
__ a_byte(being_initialized_entry_offset);
|
__ emit_int8(being_initialized_entry_offset);
|
||||||
__ a_byte(bytes_to_skip);
|
__ emit_int8(bytes_to_skip);
|
||||||
__ a_byte(_bytes_to_copy);
|
__ emit_int8(_bytes_to_copy);
|
||||||
address patch_info_pc = __ pc();
|
address patch_info_pc = __ pc();
|
||||||
assert(patch_info_pc - end_of_patch == bytes_to_skip, "incorrect patch info");
|
assert(patch_info_pc - end_of_patch == bytes_to_skip, "incorrect patch info");
|
||||||
|
|
||||||
|
|
|
@ -582,7 +582,9 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||||
// the following temporary registers are used during frame creation
|
// the following temporary registers are used during frame creation
|
||||||
const Register Gtmp1 = G3_scratch ;
|
const Register Gtmp1 = G3_scratch ;
|
||||||
const Register Gtmp2 = G1_scratch;
|
const Register Gtmp2 = G1_scratch;
|
||||||
const Address size_of_parameters(G5_method, 0, in_bytes(Method::size_of_parameters_offset()));
|
const Register RconstMethod = Gtmp1;
|
||||||
|
const Address constMethod(G5_method, 0, in_bytes(Method::const_offset()));
|
||||||
|
const Address size_of_parameters(RconstMethod, 0, in_bytes(ConstMethod::size_of_parameters_offset()));
|
||||||
|
|
||||||
bool inc_counter = UseCompiler || CountCompiledCalls;
|
bool inc_counter = UseCompiler || CountCompiledCalls;
|
||||||
|
|
||||||
|
@ -618,6 +620,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||||
}
|
}
|
||||||
#endif // ASSERT
|
#endif // ASSERT
|
||||||
|
|
||||||
|
__ ld_ptr(constMethod, RconstMethod);
|
||||||
__ lduh(size_of_parameters, Gtmp1);
|
__ lduh(size_of_parameters, Gtmp1);
|
||||||
__ sll(Gtmp1, LogBytesPerWord, Gtmp2); // parameter size in bytes
|
__ sll(Gtmp1, LogBytesPerWord, Gtmp2); // parameter size in bytes
|
||||||
__ add(Gargs, Gtmp2, Gargs); // points to first local + BytesPerWord
|
__ add(Gargs, Gtmp2, Gargs); // points to first local + BytesPerWord
|
||||||
|
@ -1047,8 +1050,6 @@ void CppInterpreterGenerator::generate_compute_interpreter_state(const Register
|
||||||
const Register Gtmp = G3_scratch;
|
const Register Gtmp = G3_scratch;
|
||||||
const Address constMethod (G5_method, 0, in_bytes(Method::const_offset()));
|
const Address constMethod (G5_method, 0, in_bytes(Method::const_offset()));
|
||||||
const Address access_flags (G5_method, 0, in_bytes(Method::access_flags_offset()));
|
const Address access_flags (G5_method, 0, in_bytes(Method::access_flags_offset()));
|
||||||
const Address size_of_parameters(G5_method, 0, in_bytes(Method::size_of_parameters_offset()));
|
|
||||||
const Address size_of_locals (G5_method, 0, in_bytes(Method::size_of_locals_offset()));
|
|
||||||
|
|
||||||
// slop factor is two extra slots on the expression stack so that
|
// slop factor is two extra slots on the expression stack so that
|
||||||
// we always have room to store a result when returning from a call without parameters
|
// we always have room to store a result when returning from a call without parameters
|
||||||
|
@ -1066,6 +1067,9 @@ void CppInterpreterGenerator::generate_compute_interpreter_state(const Register
|
||||||
// Now compute new frame size
|
// Now compute new frame size
|
||||||
|
|
||||||
if (native) {
|
if (native) {
|
||||||
|
const Register RconstMethod = Gtmp;
|
||||||
|
const Address size_of_parameters(RconstMethod, 0, in_bytes(ConstMethod::size_of_parameters_offset()));
|
||||||
|
__ ld_ptr(constMethod, RconstMethod);
|
||||||
__ lduh( size_of_parameters, Gtmp );
|
__ lduh( size_of_parameters, Gtmp );
|
||||||
__ calc_mem_param_words(Gtmp, Gtmp); // space for native call parameters passed on the stack in words
|
__ calc_mem_param_words(Gtmp, Gtmp); // space for native call parameters passed on the stack in words
|
||||||
} else {
|
} else {
|
||||||
|
@ -1236,9 +1240,13 @@ void CppInterpreterGenerator::generate_compute_interpreter_state(const Register
|
||||||
}
|
}
|
||||||
if (init_value != noreg) {
|
if (init_value != noreg) {
|
||||||
Label clear_loop;
|
Label clear_loop;
|
||||||
|
const Register RconstMethod = O1;
|
||||||
|
const Address size_of_parameters(RconstMethod, 0, in_bytes(ConstMethod::size_of_parameters_offset()));
|
||||||
|
const Address size_of_locals (RconstMethod, 0, in_bytes(ConstMethod::size_of_locals_offset()));
|
||||||
|
|
||||||
// NOTE: If you change the frame layout, this code will need to
|
// NOTE: If you change the frame layout, this code will need to
|
||||||
// be updated!
|
// be updated!
|
||||||
|
__ ld_ptr( constMethod, RconstMethod );
|
||||||
__ lduh( size_of_locals, O2 );
|
__ lduh( size_of_locals, O2 );
|
||||||
__ lduh( size_of_parameters, O1 );
|
__ lduh( size_of_parameters, O1 );
|
||||||
__ sll( O2, LogBytesPerWord, O2);
|
__ sll( O2, LogBytesPerWord, O2);
|
||||||
|
@ -1483,13 +1491,16 @@ void CppInterpreterGenerator::adjust_callers_stack(Register args) {
|
||||||
//
|
//
|
||||||
// assert_different_registers(state, prev_state);
|
// assert_different_registers(state, prev_state);
|
||||||
const Register Gtmp = G3_scratch;
|
const Register Gtmp = G3_scratch;
|
||||||
|
const RconstMethod = G3_scratch;
|
||||||
const Register tmp = O2;
|
const Register tmp = O2;
|
||||||
const Address size_of_parameters(G5_method, 0, in_bytes(Method::size_of_parameters_offset()));
|
const Address constMethod(G5_method, 0, in_bytes(Method::const_offset()));
|
||||||
const Address size_of_locals (G5_method, 0, in_bytes(Method::size_of_locals_offset()));
|
const Address size_of_parameters(RconstMethod, 0, in_bytes(ConstMethod::size_of_parameters_offset()));
|
||||||
|
const Address size_of_locals (RconstMethod, 0, in_bytes(ConstMethod::size_of_locals_offset()));
|
||||||
|
|
||||||
|
__ ld_ptr(constMethod, RconstMethod);
|
||||||
__ lduh(size_of_parameters, tmp);
|
__ lduh(size_of_parameters, tmp);
|
||||||
__ sll(tmp, LogBytesPerWord, Gtmp); // parameter size in bytes
|
__ sll(tmp, LogBytesPerWord, Gargs); // parameter size in bytes
|
||||||
__ add(args, Gtmp, Gargs); // points to first local + BytesPerWord
|
__ add(args, Gargs, Gargs); // points to first local + BytesPerWord
|
||||||
// NEW
|
// NEW
|
||||||
__ add(Gargs, -wordSize, Gargs); // points to first local[0]
|
__ add(Gargs, -wordSize, Gargs); // points to first local[0]
|
||||||
// determine extra space for non-argument locals & adjust caller's SP
|
// determine extra space for non-argument locals & adjust caller's SP
|
||||||
|
@ -1541,8 +1552,6 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) {
|
||||||
|
|
||||||
const Address constMethod (G5_method, 0, in_bytes(Method::const_offset()));
|
const Address constMethod (G5_method, 0, in_bytes(Method::const_offset()));
|
||||||
const Address access_flags (G5_method, 0, in_bytes(Method::access_flags_offset()));
|
const Address access_flags (G5_method, 0, in_bytes(Method::access_flags_offset()));
|
||||||
const Address size_of_parameters(G5_method, 0, in_bytes(Method::size_of_parameters_offset()));
|
|
||||||
const Address size_of_locals (G5_method, 0, in_bytes(Method::size_of_locals_offset()));
|
|
||||||
|
|
||||||
address entry_point = __ pc();
|
address entry_point = __ pc();
|
||||||
__ mov(G0, prevState); // no current activation
|
__ mov(G0, prevState); // no current activation
|
||||||
|
@ -1750,7 +1759,9 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) {
|
||||||
|
|
||||||
__ ld_ptr(STATE(_result._to_call._callee), L4_scratch); // called method
|
__ ld_ptr(STATE(_result._to_call._callee), L4_scratch); // called method
|
||||||
__ ld_ptr(STATE(_stack), L1_scratch); // get top of java expr stack
|
__ ld_ptr(STATE(_stack), L1_scratch); // get top of java expr stack
|
||||||
__ lduh(L4_scratch, in_bytes(Method::size_of_parameters_offset()), L2_scratch); // get parameter size
|
// get parameter size
|
||||||
|
__ ld_ptr(L4_scratch, in_bytes(Method::const_offset()), L2_scratch);
|
||||||
|
__ lduh(L2_scratch, in_bytes(ConstMethod::size_of_parameters_offset()), L2_scratch);
|
||||||
__ sll(L2_scratch, LogBytesPerWord, L2_scratch ); // parameter size in bytes
|
__ sll(L2_scratch, LogBytesPerWord, L2_scratch ); // parameter size in bytes
|
||||||
__ add(L1_scratch, L2_scratch, L1_scratch); // stack destination for result
|
__ add(L1_scratch, L2_scratch, L1_scratch); // stack destination for result
|
||||||
__ ld(L4_scratch, in_bytes(Method::result_index_offset()), L3_scratch); // called method result type index
|
__ ld(L4_scratch, in_bytes(Method::result_index_offset()), L3_scratch); // called method result type index
|
||||||
|
|
|
@ -100,34 +100,6 @@ const char* Argument::name() const {
|
||||||
bool AbstractAssembler::pd_check_instruction_mark() { return false; }
|
bool AbstractAssembler::pd_check_instruction_mark() { return false; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void MacroAssembler::print_instruction(int inst) {
|
|
||||||
const char* s;
|
|
||||||
switch (inv_op(inst)) {
|
|
||||||
default: s = "????"; break;
|
|
||||||
case call_op: s = "call"; break;
|
|
||||||
case branch_op:
|
|
||||||
switch (inv_op2(inst)) {
|
|
||||||
case fb_op2: s = "fb"; break;
|
|
||||||
case fbp_op2: s = "fbp"; break;
|
|
||||||
case br_op2: s = "br"; break;
|
|
||||||
case bp_op2: s = "bp"; break;
|
|
||||||
case cb_op2: s = "cb"; break;
|
|
||||||
case bpr_op2: {
|
|
||||||
if (is_cbcond(inst)) {
|
|
||||||
s = is_cxb(inst) ? "cxb" : "cwb";
|
|
||||||
} else {
|
|
||||||
s = "bpr";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: s = "????"; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
::tty->print("%s", s);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Patch instruction inst at offset inst_pos to refer to dest_pos
|
// Patch instruction inst at offset inst_pos to refer to dest_pos
|
||||||
// and return the resulting instruction.
|
// and return the resulting instruction.
|
||||||
// We should have pcs, not offsets, but since all is relative, it will work out
|
// We should have pcs, not offsets, but since all is relative, it will work out
|
||||||
|
|
|
@ -603,7 +603,6 @@ class MacroAssembler : public Assembler {
|
||||||
friend class Label;
|
friend class Label;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static void print_instruction(int inst);
|
|
||||||
static int patched_branch(int dest_pos, int inst, int inst_pos);
|
static int patched_branch(int dest_pos, int inst, int inst_pos);
|
||||||
static int branch_destination(int inst, int pos);
|
static int branch_destination(int inst, int pos);
|
||||||
|
|
||||||
|
@ -759,9 +758,6 @@ class MacroAssembler : public Assembler {
|
||||||
// Required platform-specific helpers for Label::patch_instructions.
|
// Required platform-specific helpers for Label::patch_instructions.
|
||||||
// They _shadow_ the declarations in AbstractAssembler, which are undefined.
|
// They _shadow_ the declarations in AbstractAssembler, which are undefined.
|
||||||
void pd_patch_instruction(address branch, address target);
|
void pd_patch_instruction(address branch, address target);
|
||||||
#ifndef PRODUCT
|
|
||||||
static void pd_print_patched_instruction(address branch);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// sethi Macro handles optimizations and relocations
|
// sethi Macro handles optimizations and relocations
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -43,14 +43,6 @@ inline void MacroAssembler::pd_patch_instruction(address branch, address target)
|
||||||
stub_inst = patched_branch(target - branch, stub_inst, 0);
|
stub_inst = patched_branch(target - branch, stub_inst, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef PRODUCT
|
|
||||||
inline void MacroAssembler::pd_print_patched_instruction(address branch) {
|
|
||||||
jint stub_inst = *(jint*) branch;
|
|
||||||
print_instruction(stub_inst);
|
|
||||||
::tty->print("%s", " (unresolved)");
|
|
||||||
}
|
|
||||||
#endif // PRODUCT
|
|
||||||
|
|
||||||
// Use the right loads/stores for the platform
|
// Use the right loads/stores for the platform
|
||||||
inline void MacroAssembler::ld_ptr( Register s1, Register s2, Register d ) {
|
inline void MacroAssembler::ld_ptr( Register s1, Register s2, Register d ) {
|
||||||
#ifdef _LP64
|
#ifdef _LP64
|
||||||
|
|
|
@ -171,7 +171,8 @@ void MethodHandles::jump_to_lambda_form(MacroAssembler* _masm,
|
||||||
|
|
||||||
if (VerifyMethodHandles && !for_compiler_entry) {
|
if (VerifyMethodHandles && !for_compiler_entry) {
|
||||||
// make sure recv is already on stack
|
// make sure recv is already on stack
|
||||||
__ load_sized_value(Address(method_temp, Method::size_of_parameters_offset()),
|
__ ld_ptr(method_temp, in_bytes(Method::const_offset()), temp2);
|
||||||
|
__ load_sized_value(Address(temp2, ConstMethod::size_of_parameters_offset()),
|
||||||
temp2,
|
temp2,
|
||||||
sizeof(u2), /*is_signed*/ false);
|
sizeof(u2), /*is_signed*/ false);
|
||||||
// assert(sizeof(u2) == sizeof(Method::_size_of_parameters), "");
|
// assert(sizeof(u2) == sizeof(Method::_size_of_parameters), "");
|
||||||
|
@ -233,7 +234,8 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler*
|
||||||
int ref_kind = signature_polymorphic_intrinsic_ref_kind(iid);
|
int ref_kind = signature_polymorphic_intrinsic_ref_kind(iid);
|
||||||
assert(ref_kind != 0 || iid == vmIntrinsics::_invokeBasic, "must be _invokeBasic or a linkTo intrinsic");
|
assert(ref_kind != 0 || iid == vmIntrinsics::_invokeBasic, "must be _invokeBasic or a linkTo intrinsic");
|
||||||
if (ref_kind == 0 || MethodHandles::ref_kind_has_receiver(ref_kind)) {
|
if (ref_kind == 0 || MethodHandles::ref_kind_has_receiver(ref_kind)) {
|
||||||
__ load_sized_value(Address(G5_method, Method::size_of_parameters_offset()),
|
__ ld_ptr(G5_method, in_bytes(Method::const_offset()), O4_param_size);
|
||||||
|
__ load_sized_value(Address(O4_param_size, ConstMethod::size_of_parameters_offset()),
|
||||||
O4_param_size,
|
O4_param_size,
|
||||||
sizeof(u2), /*is_signed*/ false);
|
sizeof(u2), /*is_signed*/ false);
|
||||||
// assert(sizeof(u2) == sizeof(Method::_size_of_parameters), "");
|
// assert(sizeof(u2) == sizeof(Method::_size_of_parameters), "");
|
||||||
|
|
|
@ -10224,7 +10224,7 @@ instruct array_equals(o0RegP ary1, o1RegP ary2, g3RegI tmp1, notemp_iRegI result
|
||||||
|
|
||||||
//---------- Zeros Count Instructions ------------------------------------------
|
//---------- Zeros Count Instructions ------------------------------------------
|
||||||
|
|
||||||
instruct countLeadingZerosI(iRegI dst, iRegI src, iRegI tmp, flagsReg cr) %{
|
instruct countLeadingZerosI(iRegIsafe dst, iRegI src, iRegI tmp, flagsReg cr) %{
|
||||||
predicate(UsePopCountInstruction); // See Matcher::match_rule_supported
|
predicate(UsePopCountInstruction); // See Matcher::match_rule_supported
|
||||||
match(Set dst (CountLeadingZerosI src));
|
match(Set dst (CountLeadingZerosI src));
|
||||||
effect(TEMP dst, TEMP tmp, KILL cr);
|
effect(TEMP dst, TEMP tmp, KILL cr);
|
||||||
|
@ -10321,7 +10321,7 @@ instruct countLeadingZerosL(iRegIsafe dst, iRegL src, iRegL tmp, flagsReg cr) %{
|
||||||
ins_pipe(ialu_reg);
|
ins_pipe(ialu_reg);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
instruct countTrailingZerosI(iRegI dst, iRegI src, flagsReg cr) %{
|
instruct countTrailingZerosI(iRegIsafe dst, iRegI src, flagsReg cr) %{
|
||||||
predicate(UsePopCountInstruction); // See Matcher::match_rule_supported
|
predicate(UsePopCountInstruction); // See Matcher::match_rule_supported
|
||||||
match(Set dst (CountTrailingZerosI src));
|
match(Set dst (CountTrailingZerosI src));
|
||||||
effect(TEMP dst, KILL cr);
|
effect(TEMP dst, KILL cr);
|
||||||
|
@ -10364,19 +10364,21 @@ instruct countTrailingZerosL(iRegIsafe dst, iRegL src, flagsReg cr) %{
|
||||||
|
|
||||||
//---------- Population Count Instructions -------------------------------------
|
//---------- Population Count Instructions -------------------------------------
|
||||||
|
|
||||||
instruct popCountI(iRegI dst, iRegI src) %{
|
instruct popCountI(iRegIsafe dst, iRegI src) %{
|
||||||
predicate(UsePopCountInstruction);
|
predicate(UsePopCountInstruction);
|
||||||
match(Set dst (PopCountI src));
|
match(Set dst (PopCountI src));
|
||||||
|
|
||||||
format %{ "POPC $src, $dst" %}
|
format %{ "SRL $src, G0, $dst\t! clear upper word for 64 bit POPC\n\t"
|
||||||
|
"POPC $dst, $dst" %}
|
||||||
ins_encode %{
|
ins_encode %{
|
||||||
__ popc($src$$Register, $dst$$Register);
|
__ srl($src$$Register, G0, $dst$$Register);
|
||||||
|
__ popc($dst$$Register, $dst$$Register);
|
||||||
%}
|
%}
|
||||||
ins_pipe(ialu_reg);
|
ins_pipe(ialu_reg);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
// Note: Long.bitCount(long) returns an int.
|
// Note: Long.bitCount(long) returns an int.
|
||||||
instruct popCountL(iRegI dst, iRegL src) %{
|
instruct popCountL(iRegIsafe dst, iRegL src) %{
|
||||||
predicate(UsePopCountInstruction);
|
predicate(UsePopCountInstruction);
|
||||||
match(Set dst (PopCountL src));
|
match(Set dst (PopCountL src));
|
||||||
|
|
||||||
|
|
|
@ -434,7 +434,7 @@ void TemplateInterpreterGenerator::generate_stack_overflow_check(Register Rframe
|
||||||
|
|
||||||
// the frame is greater than one page in size, so check against
|
// the frame is greater than one page in size, so check against
|
||||||
// the bottom of the stack
|
// the bottom of the stack
|
||||||
__ cmp_and_brx_short(SP, Rscratch, Assembler::greater, Assembler::pt, after_frame_check);
|
__ cmp_and_brx_short(SP, Rscratch, Assembler::greaterUnsigned, Assembler::pt, after_frame_check);
|
||||||
|
|
||||||
// the stack will overflow, throw an exception
|
// the stack will overflow, throw an exception
|
||||||
|
|
||||||
|
@ -494,9 +494,6 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
|
||||||
// (gri - 2/25/2000)
|
// (gri - 2/25/2000)
|
||||||
|
|
||||||
|
|
||||||
const Address size_of_parameters(G5_method, Method::size_of_parameters_offset());
|
|
||||||
const Address size_of_locals (G5_method, Method::size_of_locals_offset());
|
|
||||||
const Address constMethod (G5_method, Method::const_offset());
|
|
||||||
int rounded_vm_local_words = round_to( frame::interpreter_frame_vm_local_words, WordsPerLong );
|
int rounded_vm_local_words = round_to( frame::interpreter_frame_vm_local_words, WordsPerLong );
|
||||||
|
|
||||||
const int extra_space =
|
const int extra_space =
|
||||||
|
@ -506,11 +503,15 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
|
||||||
(native_call ? frame::interpreter_frame_extra_outgoing_argument_words : 0);
|
(native_call ? frame::interpreter_frame_extra_outgoing_argument_words : 0);
|
||||||
|
|
||||||
const Register Glocals_size = G3;
|
const Register Glocals_size = G3;
|
||||||
|
const Register RconstMethod = Glocals_size;
|
||||||
const Register Otmp1 = O3;
|
const Register Otmp1 = O3;
|
||||||
const Register Otmp2 = O4;
|
const Register Otmp2 = O4;
|
||||||
// Lscratch can't be used as a temporary because the call_stub uses
|
// Lscratch can't be used as a temporary because the call_stub uses
|
||||||
// it to assert that the stack frame was setup correctly.
|
// it to assert that the stack frame was setup correctly.
|
||||||
|
const Address constMethod (G5_method, Method::const_offset());
|
||||||
|
const Address size_of_parameters(RconstMethod, ConstMethod::size_of_parameters_offset());
|
||||||
|
|
||||||
|
__ ld_ptr( constMethod, RconstMethod );
|
||||||
__ lduh( size_of_parameters, Glocals_size);
|
__ lduh( size_of_parameters, Glocals_size);
|
||||||
|
|
||||||
// Gargs points to first local + BytesPerWord
|
// Gargs points to first local + BytesPerWord
|
||||||
|
@ -530,6 +531,8 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
|
||||||
//
|
//
|
||||||
// Compute number of locals in method apart from incoming parameters
|
// Compute number of locals in method apart from incoming parameters
|
||||||
//
|
//
|
||||||
|
const Address size_of_locals (Otmp1, ConstMethod::size_of_locals_offset());
|
||||||
|
__ ld_ptr( constMethod, Otmp1 );
|
||||||
__ lduh( size_of_locals, Otmp1 );
|
__ lduh( size_of_locals, Otmp1 );
|
||||||
__ sub( Otmp1, Glocals_size, Glocals_size );
|
__ sub( Otmp1, Glocals_size, Glocals_size );
|
||||||
__ round_to( Glocals_size, WordsPerLong );
|
__ round_to( Glocals_size, WordsPerLong );
|
||||||
|
@ -1256,8 +1259,7 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) {
|
||||||
// make sure registers are different!
|
// make sure registers are different!
|
||||||
assert_different_registers(G2_thread, G5_method, Gargs, Gtmp1, Gtmp2);
|
assert_different_registers(G2_thread, G5_method, Gargs, Gtmp1, Gtmp2);
|
||||||
|
|
||||||
const Address size_of_parameters(G5_method, Method::size_of_parameters_offset());
|
const Address constMethod (G5_method, Method::const_offset());
|
||||||
const Address size_of_locals (G5_method, Method::size_of_locals_offset());
|
|
||||||
// Seems like G5_method is live at the point this is used. So we could make this look consistent
|
// Seems like G5_method is live at the point this is used. So we could make this look consistent
|
||||||
// and use in the asserts.
|
// and use in the asserts.
|
||||||
const Address access_flags (Lmethod, Method::access_flags_offset());
|
const Address access_flags (Lmethod, Method::access_flags_offset());
|
||||||
|
@ -1307,8 +1309,13 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) {
|
||||||
init_value = G0;
|
init_value = G0;
|
||||||
Label clear_loop;
|
Label clear_loop;
|
||||||
|
|
||||||
|
const Register RconstMethod = O1;
|
||||||
|
const Address size_of_parameters(RconstMethod, ConstMethod::size_of_parameters_offset());
|
||||||
|
const Address size_of_locals (RconstMethod, ConstMethod::size_of_locals_offset());
|
||||||
|
|
||||||
// NOTE: If you change the frame layout, this code will need to
|
// NOTE: If you change the frame layout, this code will need to
|
||||||
// be updated!
|
// be updated!
|
||||||
|
__ ld_ptr( constMethod, RconstMethod );
|
||||||
__ lduh( size_of_locals, O2 );
|
__ lduh( size_of_locals, O2 );
|
||||||
__ lduh( size_of_parameters, O1 );
|
__ lduh( size_of_parameters, O1 );
|
||||||
__ sll( O2, Interpreter::logStackElementSize, O2);
|
__ sll( O2, Interpreter::logStackElementSize, O2);
|
||||||
|
@ -1823,9 +1830,13 @@ void TemplateInterpreterGenerator::generate_throw_exception() {
|
||||||
|
|
||||||
const Register Gtmp1 = G3_scratch;
|
const Register Gtmp1 = G3_scratch;
|
||||||
const Register Gtmp2 = G1_scratch;
|
const Register Gtmp2 = G1_scratch;
|
||||||
|
const Register RconstMethod = Gtmp1;
|
||||||
|
const Address constMethod(Lmethod, Method::const_offset());
|
||||||
|
const Address size_of_parameters(RconstMethod, ConstMethod::size_of_parameters_offset());
|
||||||
|
|
||||||
// Compute size of arguments for saving when returning to deoptimized caller
|
// Compute size of arguments for saving when returning to deoptimized caller
|
||||||
__ lduh(Lmethod, in_bytes(Method::size_of_parameters_offset()), Gtmp1);
|
__ ld_ptr(constMethod, RconstMethod);
|
||||||
|
__ lduh(size_of_parameters, Gtmp1);
|
||||||
__ sll(Gtmp1, Interpreter::logStackElementSize, Gtmp1);
|
__ sll(Gtmp1, Interpreter::logStackElementSize, Gtmp1);
|
||||||
__ sub(Llocals, Gtmp1, Gtmp2);
|
__ sub(Llocals, Gtmp1, Gtmp2);
|
||||||
__ add(Gtmp2, wordSize, Gtmp2);
|
__ add(Gtmp2, wordSize, Gtmp2);
|
||||||
|
|
|
@ -3040,7 +3040,8 @@ void TemplateTable::invokevfinal_helper(Register Rscratch, Register Rret) {
|
||||||
Register Rtemp = G4_scratch;
|
Register Rtemp = G4_scratch;
|
||||||
|
|
||||||
// Load receiver from stack slot
|
// Load receiver from stack slot
|
||||||
__ lduh(G5_method, in_bytes(Method::size_of_parameters_offset()), G4_scratch);
|
__ ld_ptr(G5_method, in_bytes(Method::const_offset()), G4_scratch);
|
||||||
|
__ lduh(G4_scratch, in_bytes(ConstMethod::size_of_parameters_offset()), G4_scratch);
|
||||||
__ load_receiver(G4_scratch, O0);
|
__ load_receiver(G4_scratch, O0);
|
||||||
|
|
||||||
// receiver NULL check
|
// receiver NULL check
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -313,10 +313,10 @@ void PatchingStub::emit_code(LIR_Assembler* ce) {
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
// make a copy the code which is going to be patched.
|
// make a copy the code which is going to be patched.
|
||||||
for ( int i = 0; i < _bytes_to_copy; i++) {
|
for (int i = 0; i < _bytes_to_copy; i++) {
|
||||||
address ptr = (address)(_pc_start + i);
|
address ptr = (address)(_pc_start + i);
|
||||||
int a_byte = (*ptr) & 0xFF;
|
int a_byte = (*ptr) & 0xFF;
|
||||||
__ a_byte (a_byte);
|
__ emit_int8(a_byte);
|
||||||
*ptr = 0x90; // make the site look like a nop
|
*ptr = 0x90; // make the site look like a nop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -363,11 +363,11 @@ void PatchingStub::emit_code(LIR_Assembler* ce) {
|
||||||
// emit the offsets needed to find the code to patch
|
// emit the offsets needed to find the code to patch
|
||||||
int being_initialized_entry_offset = __ pc() - being_initialized_entry + sizeof_patch_record;
|
int being_initialized_entry_offset = __ pc() - being_initialized_entry + sizeof_patch_record;
|
||||||
|
|
||||||
__ a_byte(0xB8);
|
__ emit_int8((unsigned char)0xB8);
|
||||||
__ a_byte(0);
|
__ emit_int8(0);
|
||||||
__ a_byte(being_initialized_entry_offset);
|
__ emit_int8(being_initialized_entry_offset);
|
||||||
__ a_byte(bytes_to_skip);
|
__ emit_int8(bytes_to_skip);
|
||||||
__ a_byte(_bytes_to_copy);
|
__ emit_int8(_bytes_to_copy);
|
||||||
address patch_info_pc = __ pc();
|
address patch_info_pc = __ pc();
|
||||||
assert(patch_info_pc - end_of_patch == bytes_to_skip, "incorrect patch info");
|
assert(patch_info_pc - end_of_patch == bytes_to_skip, "incorrect patch info");
|
||||||
|
|
||||||
|
|
|
@ -611,8 +611,6 @@ void InterpreterGenerator::generate_counter_overflow(Label* do_continue) {
|
||||||
// C++ interpreter only
|
// C++ interpreter only
|
||||||
// rsi/r13 - previous interpreter state pointer
|
// rsi/r13 - previous interpreter state pointer
|
||||||
|
|
||||||
const Address size_of_parameters(rbx, Method::size_of_parameters_offset());
|
|
||||||
|
|
||||||
// InterpreterRuntime::frequency_counter_overflow takes one argument
|
// InterpreterRuntime::frequency_counter_overflow takes one argument
|
||||||
// indicating if the counter overflow occurs at a backwards branch (non-NULL bcp).
|
// indicating if the counter overflow occurs at a backwards branch (non-NULL bcp).
|
||||||
// The call returns the address of the verified entry point for the method or NULL
|
// The call returns the address of the verified entry point for the method or NULL
|
||||||
|
@ -977,15 +975,16 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||||
// to save/restore.
|
// to save/restore.
|
||||||
address entry_point = __ pc();
|
address entry_point = __ pc();
|
||||||
|
|
||||||
const Address size_of_parameters(rbx, Method::size_of_parameters_offset());
|
const Address constMethod (rbx, Method::const_offset());
|
||||||
const Address size_of_locals (rbx, Method::size_of_locals_offset());
|
|
||||||
const Address invocation_counter(rbx, Method::invocation_counter_offset() + InvocationCounter::counter_offset());
|
const Address invocation_counter(rbx, Method::invocation_counter_offset() + InvocationCounter::counter_offset());
|
||||||
const Address access_flags (rbx, Method::access_flags_offset());
|
const Address access_flags (rbx, Method::access_flags_offset());
|
||||||
|
const Address size_of_parameters(rcx, ConstMethod::size_of_parameters_offset());
|
||||||
|
|
||||||
// rsi/r13 == state/locals rdi == prevstate
|
// rsi/r13 == state/locals rdi == prevstate
|
||||||
const Register locals = rdi;
|
const Register locals = rdi;
|
||||||
|
|
||||||
// get parameter size (always needed)
|
// get parameter size (always needed)
|
||||||
|
__ movptr(rcx, constMethod);
|
||||||
__ load_unsigned_short(rcx, size_of_parameters);
|
__ load_unsigned_short(rcx, size_of_parameters);
|
||||||
|
|
||||||
// rbx: Method*
|
// rbx: Method*
|
||||||
|
@ -994,6 +993,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||||
// for natives the size of locals is zero
|
// for natives the size of locals is zero
|
||||||
|
|
||||||
// compute beginning of parameters /locals
|
// compute beginning of parameters /locals
|
||||||
|
|
||||||
__ lea(locals, Address(rsp, rcx, Address::times_ptr, -wordSize));
|
__ lea(locals, Address(rsp, rcx, Address::times_ptr, -wordSize));
|
||||||
|
|
||||||
// initialize fixed part of activation frame
|
// initialize fixed part of activation frame
|
||||||
|
@ -1107,11 +1107,14 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||||
const Register method = rbx;
|
const Register method = rbx;
|
||||||
const Register thread = LP64_ONLY(r15_thread) NOT_LP64(rdi);
|
const Register thread = LP64_ONLY(r15_thread) NOT_LP64(rdi);
|
||||||
const Register t = InterpreterRuntime::SignatureHandlerGenerator::temp(); // rcx|rscratch1
|
const Register t = InterpreterRuntime::SignatureHandlerGenerator::temp(); // rcx|rscratch1
|
||||||
|
const Address constMethod (method, Method::const_offset());
|
||||||
|
const Address size_of_parameters(t, ConstMethod::size_of_parameters_offset());
|
||||||
|
|
||||||
// allocate space for parameters
|
// allocate space for parameters
|
||||||
__ movptr(method, STATE(_method));
|
__ movptr(method, STATE(_method));
|
||||||
__ verify_method_ptr(method);
|
__ verify_method_ptr(method);
|
||||||
__ load_unsigned_short(t, Address(method, Method::size_of_parameters_offset()));
|
__ movptr(t, constMethod);
|
||||||
|
__ load_unsigned_short(t, size_of_parameters);
|
||||||
__ shll(t, 2);
|
__ shll(t, 2);
|
||||||
#ifdef _LP64
|
#ifdef _LP64
|
||||||
__ subptr(rsp, t);
|
__ subptr(rsp, t);
|
||||||
|
@ -1700,15 +1703,17 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) {
|
||||||
// save sender sp
|
// save sender sp
|
||||||
__ push(rcx);
|
__ push(rcx);
|
||||||
|
|
||||||
const Address size_of_parameters(rbx, Method::size_of_parameters_offset());
|
const Address constMethod (rbx, Method::const_offset());
|
||||||
const Address size_of_locals (rbx, Method::size_of_locals_offset());
|
|
||||||
const Address access_flags (rbx, Method::access_flags_offset());
|
const Address access_flags (rbx, Method::access_flags_offset());
|
||||||
|
const Address size_of_parameters(rdx, ConstMethod::size_of_parameters_offset());
|
||||||
|
const Address size_of_locals (rdx, ConstMethod::size_of_locals_offset());
|
||||||
|
|
||||||
// const Address monitor_block_top (rbp, frame::interpreter_frame_monitor_block_top_offset * wordSize);
|
// const Address monitor_block_top (rbp, frame::interpreter_frame_monitor_block_top_offset * wordSize);
|
||||||
// const Address monitor_block_bot (rbp, frame::interpreter_frame_initial_sp_offset * wordSize);
|
// const Address monitor_block_bot (rbp, frame::interpreter_frame_initial_sp_offset * wordSize);
|
||||||
// const Address monitor(rbp, frame::interpreter_frame_initial_sp_offset * wordSize - (int)sizeof(BasicObjectLock));
|
// const Address monitor(rbp, frame::interpreter_frame_initial_sp_offset * wordSize - (int)sizeof(BasicObjectLock));
|
||||||
|
|
||||||
// get parameter size (always needed)
|
// get parameter size (always needed)
|
||||||
|
__ movptr(rdx, constMethod);
|
||||||
__ load_unsigned_short(rcx, size_of_parameters);
|
__ load_unsigned_short(rcx, size_of_parameters);
|
||||||
|
|
||||||
// rbx: Method*
|
// rbx: Method*
|
||||||
|
@ -1989,7 +1994,9 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) {
|
||||||
__ movptr(rbx, STATE(_result._to_call._callee));
|
__ movptr(rbx, STATE(_result._to_call._callee));
|
||||||
|
|
||||||
// callee left args on top of expression stack, remove them
|
// callee left args on top of expression stack, remove them
|
||||||
__ load_unsigned_short(rcx, Address(rbx, Method::size_of_parameters_offset()));
|
__ movptr(rcx, constMethod);
|
||||||
|
__ load_unsigned_short(rcx, Address(rcx, ConstMethod::size_of_parameters_offset()));
|
||||||
|
|
||||||
__ lea(rsp, Address(rsp, rcx, Address::times_ptr));
|
__ lea(rsp, Address(rsp, rcx, Address::times_ptr));
|
||||||
|
|
||||||
__ movl(rcx, Address(rbx, Method::result_index_offset()));
|
__ movl(rcx, Address(rbx, Method::result_index_offset()));
|
||||||
|
@ -2159,7 +2166,9 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) {
|
||||||
// Make it look like call_stub calling conventions
|
// Make it look like call_stub calling conventions
|
||||||
|
|
||||||
// Get (potential) receiver
|
// Get (potential) receiver
|
||||||
__ load_unsigned_short(rcx, size_of_parameters); // get size of parameters in words
|
// get size of parameters in words
|
||||||
|
__ movptr(rcx, constMethod);
|
||||||
|
__ load_unsigned_short(rcx, Address(rcx, ConstMethod::size_of_parameters_offset()));
|
||||||
|
|
||||||
ExternalAddress recursive(CAST_FROM_FN_PTR(address, RecursiveInterpreterActivation));
|
ExternalAddress recursive(CAST_FROM_FN_PTR(address, RecursiveInterpreterActivation));
|
||||||
__ pushptr(recursive.addr()); // make it look good in the debugger
|
__ pushptr(recursive.addr()); // make it look good in the debugger
|
||||||
|
|
|
@ -1023,7 +1023,7 @@ void MacroAssembler::lea(Address dst, AddressLiteral adr) {
|
||||||
|
|
||||||
void MacroAssembler::leave() {
|
void MacroAssembler::leave() {
|
||||||
// %%% is this really better? Why not on 32bit too?
|
// %%% is this really better? Why not on 32bit too?
|
||||||
emit_byte(0xC9); // LEAVE
|
emit_int8((unsigned char)0xC9); // LEAVE
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroAssembler::lneg(Register hi, Register lo) {
|
void MacroAssembler::lneg(Register hi, Register lo) {
|
||||||
|
@ -2112,11 +2112,11 @@ void MacroAssembler::fat_nop() {
|
||||||
if (UseAddressNop) {
|
if (UseAddressNop) {
|
||||||
addr_nop_5();
|
addr_nop_5();
|
||||||
} else {
|
} else {
|
||||||
emit_byte(0x26); // es:
|
emit_int8(0x26); // es:
|
||||||
emit_byte(0x2e); // cs:
|
emit_int8(0x2e); // cs:
|
||||||
emit_byte(0x64); // fs:
|
emit_int8(0x64); // fs:
|
||||||
emit_byte(0x65); // gs:
|
emit_int8(0x65); // gs:
|
||||||
emit_byte(0x90);
|
emit_int8((unsigned char)0x90);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2534,12 +2534,12 @@ void MacroAssembler::jump_cc(Condition cc, AddressLiteral dst) {
|
||||||
int offs = (intptr_t)dst.target() - ((intptr_t)pc());
|
int offs = (intptr_t)dst.target() - ((intptr_t)pc());
|
||||||
if (dst.reloc() == relocInfo::none && is8bit(offs - short_size)) {
|
if (dst.reloc() == relocInfo::none && is8bit(offs - short_size)) {
|
||||||
// 0111 tttn #8-bit disp
|
// 0111 tttn #8-bit disp
|
||||||
emit_byte(0x70 | cc);
|
emit_int8(0x70 | cc);
|
||||||
emit_byte((offs - short_size) & 0xFF);
|
emit_int8((offs - short_size) & 0xFF);
|
||||||
} else {
|
} else {
|
||||||
// 0000 1111 1000 tttn #32-bit disp
|
// 0000 1111 1000 tttn #32-bit disp
|
||||||
emit_byte(0x0F);
|
emit_int8(0x0F);
|
||||||
emit_byte(0x80 | cc);
|
emit_int8((unsigned char)(0x80 | cc));
|
||||||
emit_long(offs - long_size);
|
emit_long(offs - long_size);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -3085,7 +3085,8 @@ void MacroAssembler::xorps(XMMRegister dst, AddressLiteral src) {
|
||||||
|
|
||||||
void MacroAssembler::pshufb(XMMRegister dst, AddressLiteral src) {
|
void MacroAssembler::pshufb(XMMRegister dst, AddressLiteral src) {
|
||||||
// Used in sign-bit flipping with aligned address.
|
// Used in sign-bit flipping with aligned address.
|
||||||
assert((UseAVX > 0) || (((intptr_t)src.target() & 15) == 0), "SSE mode requires address alignment 16 bytes");
|
bool aligned_adr = (((intptr_t)src.target() & 15) == 0);
|
||||||
|
assert((UseAVX > 0) || aligned_adr, "SSE mode requires address alignment 16 bytes");
|
||||||
if (reachable(src)) {
|
if (reachable(src)) {
|
||||||
Assembler::pshufb(dst, as_Address(src));
|
Assembler::pshufb(dst, as_Address(src));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -126,25 +126,6 @@ class MacroAssembler: public Assembler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef PRODUCT
|
|
||||||
static void pd_print_patched_instruction(address branch) {
|
|
||||||
const char* s;
|
|
||||||
unsigned char op = branch[0];
|
|
||||||
if (op == 0xE8) {
|
|
||||||
s = "call";
|
|
||||||
} else if (op == 0xE9 || op == 0xEB) {
|
|
||||||
s = "jmp";
|
|
||||||
} else if ((op & 0xF0) == 0x70) {
|
|
||||||
s = "jcc";
|
|
||||||
} else if (op == 0x0F) {
|
|
||||||
s = "jcc";
|
|
||||||
} else {
|
|
||||||
s = "????";
|
|
||||||
}
|
|
||||||
tty->print("%s (unresolved)", s);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// The following 4 methods return the offset of the appropriate move instruction
|
// The following 4 methods return the offset of the appropriate move instruction
|
||||||
|
|
||||||
// Support for fast byte/short loading with zero extension (depending on particular CPU)
|
// Support for fast byte/short loading with zero extension (depending on particular CPU)
|
||||||
|
|
|
@ -169,8 +169,9 @@ void MethodHandles::jump_to_lambda_form(MacroAssembler* _masm,
|
||||||
|
|
||||||
if (VerifyMethodHandles && !for_compiler_entry) {
|
if (VerifyMethodHandles && !for_compiler_entry) {
|
||||||
// make sure recv is already on stack
|
// make sure recv is already on stack
|
||||||
|
__ movptr(temp2, Address(method_temp, Method::const_offset()));
|
||||||
__ load_sized_value(temp2,
|
__ load_sized_value(temp2,
|
||||||
Address(method_temp, Method::size_of_parameters_offset()),
|
Address(temp2, ConstMethod::size_of_parameters_offset()),
|
||||||
sizeof(u2), /*is_signed*/ false);
|
sizeof(u2), /*is_signed*/ false);
|
||||||
// assert(sizeof(u2) == sizeof(Method::_size_of_parameters), "");
|
// assert(sizeof(u2) == sizeof(Method::_size_of_parameters), "");
|
||||||
Label L;
|
Label L;
|
||||||
|
@ -234,8 +235,9 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler*
|
||||||
int ref_kind = signature_polymorphic_intrinsic_ref_kind(iid);
|
int ref_kind = signature_polymorphic_intrinsic_ref_kind(iid);
|
||||||
assert(ref_kind != 0 || iid == vmIntrinsics::_invokeBasic, "must be _invokeBasic or a linkTo intrinsic");
|
assert(ref_kind != 0 || iid == vmIntrinsics::_invokeBasic, "must be _invokeBasic or a linkTo intrinsic");
|
||||||
if (ref_kind == 0 || MethodHandles::ref_kind_has_receiver(ref_kind)) {
|
if (ref_kind == 0 || MethodHandles::ref_kind_has_receiver(ref_kind)) {
|
||||||
|
__ movptr(rdx_argp, Address(rbx_method, Method::const_offset()));
|
||||||
__ load_sized_value(rdx_argp,
|
__ load_sized_value(rdx_argp,
|
||||||
Address(rbx_method, Method::size_of_parameters_offset()),
|
Address(rdx_argp, ConstMethod::size_of_parameters_offset()),
|
||||||
sizeof(u2), /*is_signed*/ false);
|
sizeof(u2), /*is_signed*/ false);
|
||||||
// assert(sizeof(u2) == sizeof(Method::_size_of_parameters), "");
|
// assert(sizeof(u2) == sizeof(Method::_size_of_parameters), "");
|
||||||
rdx_first_arg_addr = __ argument_address(rdx_argp, -1);
|
rdx_first_arg_addr = __ argument_address(rdx_argp, -1);
|
||||||
|
|
|
@ -2174,13 +2174,13 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
// c_rarg2 - K (key) in little endian int array
|
// c_rarg2 - K (key) in little endian int array
|
||||||
//
|
//
|
||||||
address generate_aescrypt_encryptBlock() {
|
address generate_aescrypt_encryptBlock() {
|
||||||
assert(UseAES && (UseAVX > 0), "need AES instructions and misaligned SSE support");
|
assert(UseAES, "need AES instructions and misaligned SSE support");
|
||||||
__ align(CodeEntryAlignment);
|
__ align(CodeEntryAlignment);
|
||||||
StubCodeMark mark(this, "StubRoutines", "aescrypt_encryptBlock");
|
StubCodeMark mark(this, "StubRoutines", "aescrypt_encryptBlock");
|
||||||
Label L_doLast;
|
Label L_doLast;
|
||||||
address start = __ pc();
|
address start = __ pc();
|
||||||
|
|
||||||
const Register from = rsi; // source array address
|
const Register from = rdx; // source array address
|
||||||
const Register to = rdx; // destination array address
|
const Register to = rdx; // destination array address
|
||||||
const Register key = rcx; // key array address
|
const Register key = rcx; // key array address
|
||||||
const Register keylen = rax;
|
const Register keylen = rax;
|
||||||
|
@ -2189,47 +2189,74 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
const Address key_param (rbp, 8+8);
|
const Address key_param (rbp, 8+8);
|
||||||
|
|
||||||
const XMMRegister xmm_result = xmm0;
|
const XMMRegister xmm_result = xmm0;
|
||||||
const XMMRegister xmm_temp = xmm1;
|
const XMMRegister xmm_key_shuf_mask = xmm1;
|
||||||
const XMMRegister xmm_key_shuf_mask = xmm2;
|
const XMMRegister xmm_temp1 = xmm2;
|
||||||
|
const XMMRegister xmm_temp2 = xmm3;
|
||||||
|
const XMMRegister xmm_temp3 = xmm4;
|
||||||
|
const XMMRegister xmm_temp4 = xmm5;
|
||||||
|
|
||||||
__ enter(); // required for proper stackwalking of RuntimeStub frame
|
__ enter(); // required for proper stackwalking of RuntimeStub frame
|
||||||
__ push(rsi);
|
__ movptr(from, from_param);
|
||||||
__ movptr(from , from_param);
|
__ movptr(key, key_param);
|
||||||
__ movptr(to , to_param);
|
|
||||||
__ movptr(key , key_param);
|
|
||||||
|
|
||||||
|
// keylen could be only {11, 13, 15} * 4 = {44, 52, 60}
|
||||||
__ movl(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT)));
|
__ movl(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT)));
|
||||||
// keylen = # of 32-bit words, convert to 128-bit words
|
|
||||||
__ shrl(keylen, 2);
|
|
||||||
__ subl(keylen, 11); // every key has at least 11 128-bit words, some have more
|
|
||||||
|
|
||||||
__ movdqu(xmm_key_shuf_mask, ExternalAddress(StubRoutines::x86::key_shuffle_mask_addr()));
|
__ movdqu(xmm_key_shuf_mask, ExternalAddress(StubRoutines::x86::key_shuffle_mask_addr()));
|
||||||
__ movdqu(xmm_result, Address(from, 0)); // get 16 bytes of input
|
__ movdqu(xmm_result, Address(from, 0)); // get 16 bytes of input
|
||||||
|
__ movptr(to, to_param);
|
||||||
|
|
||||||
// For encryption, the java expanded key ordering is just what we need
|
// For encryption, the java expanded key ordering is just what we need
|
||||||
|
|
||||||
load_key(xmm_temp, key, 0x00, xmm_key_shuf_mask);
|
load_key(xmm_temp1, key, 0x00, xmm_key_shuf_mask);
|
||||||
__ pxor(xmm_result, xmm_temp);
|
__ pxor(xmm_result, xmm_temp1);
|
||||||
for (int offset = 0x10; offset <= 0x90; offset += 0x10) {
|
|
||||||
aes_enc_key(xmm_result, xmm_temp, key, offset, xmm_key_shuf_mask);
|
load_key(xmm_temp1, key, 0x10, xmm_key_shuf_mask);
|
||||||
}
|
load_key(xmm_temp2, key, 0x20, xmm_key_shuf_mask);
|
||||||
load_key (xmm_temp, key, 0xa0, xmm_key_shuf_mask);
|
load_key(xmm_temp3, key, 0x30, xmm_key_shuf_mask);
|
||||||
__ cmpl(keylen, 0);
|
load_key(xmm_temp4, key, 0x40, xmm_key_shuf_mask);
|
||||||
__ jcc(Assembler::equal, L_doLast);
|
|
||||||
__ aesenc(xmm_result, xmm_temp); // only in 192 and 256 bit keys
|
__ aesenc(xmm_result, xmm_temp1);
|
||||||
aes_enc_key(xmm_result, xmm_temp, key, 0xb0, xmm_key_shuf_mask);
|
__ aesenc(xmm_result, xmm_temp2);
|
||||||
load_key(xmm_temp, key, 0xc0, xmm_key_shuf_mask);
|
__ aesenc(xmm_result, xmm_temp3);
|
||||||
__ subl(keylen, 2);
|
__ aesenc(xmm_result, xmm_temp4);
|
||||||
__ jcc(Assembler::equal, L_doLast);
|
|
||||||
__ aesenc(xmm_result, xmm_temp); // only in 256 bit keys
|
load_key(xmm_temp1, key, 0x50, xmm_key_shuf_mask);
|
||||||
aes_enc_key(xmm_result, xmm_temp, key, 0xd0, xmm_key_shuf_mask);
|
load_key(xmm_temp2, key, 0x60, xmm_key_shuf_mask);
|
||||||
load_key(xmm_temp, key, 0xe0, xmm_key_shuf_mask);
|
load_key(xmm_temp3, key, 0x70, xmm_key_shuf_mask);
|
||||||
|
load_key(xmm_temp4, key, 0x80, xmm_key_shuf_mask);
|
||||||
|
|
||||||
|
__ aesenc(xmm_result, xmm_temp1);
|
||||||
|
__ aesenc(xmm_result, xmm_temp2);
|
||||||
|
__ aesenc(xmm_result, xmm_temp3);
|
||||||
|
__ aesenc(xmm_result, xmm_temp4);
|
||||||
|
|
||||||
|
load_key(xmm_temp1, key, 0x90, xmm_key_shuf_mask);
|
||||||
|
load_key(xmm_temp2, key, 0xa0, xmm_key_shuf_mask);
|
||||||
|
|
||||||
|
__ cmpl(keylen, 44);
|
||||||
|
__ jccb(Assembler::equal, L_doLast);
|
||||||
|
|
||||||
|
__ aesenc(xmm_result, xmm_temp1);
|
||||||
|
__ aesenc(xmm_result, xmm_temp2);
|
||||||
|
|
||||||
|
load_key(xmm_temp1, key, 0xb0, xmm_key_shuf_mask);
|
||||||
|
load_key(xmm_temp2, key, 0xc0, xmm_key_shuf_mask);
|
||||||
|
|
||||||
|
__ cmpl(keylen, 52);
|
||||||
|
__ jccb(Assembler::equal, L_doLast);
|
||||||
|
|
||||||
|
__ aesenc(xmm_result, xmm_temp1);
|
||||||
|
__ aesenc(xmm_result, xmm_temp2);
|
||||||
|
|
||||||
|
load_key(xmm_temp1, key, 0xd0, xmm_key_shuf_mask);
|
||||||
|
load_key(xmm_temp2, key, 0xe0, xmm_key_shuf_mask);
|
||||||
|
|
||||||
__ BIND(L_doLast);
|
__ BIND(L_doLast);
|
||||||
__ aesenclast(xmm_result, xmm_temp);
|
__ aesenc(xmm_result, xmm_temp1);
|
||||||
|
__ aesenclast(xmm_result, xmm_temp2);
|
||||||
__ movdqu(Address(to, 0), xmm_result); // store the result
|
__ movdqu(Address(to, 0), xmm_result); // store the result
|
||||||
__ xorptr(rax, rax); // return 0
|
__ xorptr(rax, rax); // return 0
|
||||||
__ pop(rsi);
|
|
||||||
__ leave(); // required for proper stackwalking of RuntimeStub frame
|
__ leave(); // required for proper stackwalking of RuntimeStub frame
|
||||||
__ ret(0);
|
__ ret(0);
|
||||||
|
|
||||||
|
@ -2245,13 +2272,13 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
// c_rarg2 - K (key) in little endian int array
|
// c_rarg2 - K (key) in little endian int array
|
||||||
//
|
//
|
||||||
address generate_aescrypt_decryptBlock() {
|
address generate_aescrypt_decryptBlock() {
|
||||||
assert(UseAES && (UseAVX > 0), "need AES instructions and misaligned SSE support");
|
assert(UseAES, "need AES instructions and misaligned SSE support");
|
||||||
__ align(CodeEntryAlignment);
|
__ align(CodeEntryAlignment);
|
||||||
StubCodeMark mark(this, "StubRoutines", "aescrypt_decryptBlock");
|
StubCodeMark mark(this, "StubRoutines", "aescrypt_decryptBlock");
|
||||||
Label L_doLast;
|
Label L_doLast;
|
||||||
address start = __ pc();
|
address start = __ pc();
|
||||||
|
|
||||||
const Register from = rsi; // source array address
|
const Register from = rdx; // source array address
|
||||||
const Register to = rdx; // destination array address
|
const Register to = rdx; // destination array address
|
||||||
const Register key = rcx; // key array address
|
const Register key = rcx; // key array address
|
||||||
const Register keylen = rax;
|
const Register keylen = rax;
|
||||||
|
@ -2260,51 +2287,76 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
const Address key_param (rbp, 8+8);
|
const Address key_param (rbp, 8+8);
|
||||||
|
|
||||||
const XMMRegister xmm_result = xmm0;
|
const XMMRegister xmm_result = xmm0;
|
||||||
const XMMRegister xmm_temp = xmm1;
|
const XMMRegister xmm_key_shuf_mask = xmm1;
|
||||||
const XMMRegister xmm_key_shuf_mask = xmm2;
|
const XMMRegister xmm_temp1 = xmm2;
|
||||||
|
const XMMRegister xmm_temp2 = xmm3;
|
||||||
|
const XMMRegister xmm_temp3 = xmm4;
|
||||||
|
const XMMRegister xmm_temp4 = xmm5;
|
||||||
|
|
||||||
__ enter(); // required for proper stackwalking of RuntimeStub frame
|
__ enter(); // required for proper stackwalking of RuntimeStub frame
|
||||||
__ push(rsi);
|
__ movptr(from, from_param);
|
||||||
__ movptr(from , from_param);
|
__ movptr(key, key_param);
|
||||||
__ movptr(to , to_param);
|
|
||||||
__ movptr(key , key_param);
|
|
||||||
|
|
||||||
|
// keylen could be only {11, 13, 15} * 4 = {44, 52, 60}
|
||||||
__ movl(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT)));
|
__ movl(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT)));
|
||||||
// keylen = # of 32-bit words, convert to 128-bit words
|
|
||||||
__ shrl(keylen, 2);
|
|
||||||
__ subl(keylen, 11); // every key has at least 11 128-bit words, some have more
|
|
||||||
|
|
||||||
__ movdqu(xmm_key_shuf_mask, ExternalAddress(StubRoutines::x86::key_shuffle_mask_addr()));
|
__ movdqu(xmm_key_shuf_mask, ExternalAddress(StubRoutines::x86::key_shuffle_mask_addr()));
|
||||||
__ movdqu(xmm_result, Address(from, 0));
|
__ movdqu(xmm_result, Address(from, 0));
|
||||||
|
__ movptr(to, to_param);
|
||||||
|
|
||||||
// for decryption java expanded key ordering is rotated one position from what we want
|
// for decryption java expanded key ordering is rotated one position from what we want
|
||||||
// so we start from 0x10 here and hit 0x00 last
|
// so we start from 0x10 here and hit 0x00 last
|
||||||
// we don't know if the key is aligned, hence not using load-execute form
|
// we don't know if the key is aligned, hence not using load-execute form
|
||||||
load_key(xmm_temp, key, 0x10, xmm_key_shuf_mask);
|
load_key(xmm_temp1, key, 0x10, xmm_key_shuf_mask);
|
||||||
__ pxor (xmm_result, xmm_temp);
|
load_key(xmm_temp2, key, 0x20, xmm_key_shuf_mask);
|
||||||
for (int offset = 0x20; offset <= 0xa0; offset += 0x10) {
|
load_key(xmm_temp3, key, 0x30, xmm_key_shuf_mask);
|
||||||
aes_dec_key(xmm_result, xmm_temp, key, offset, xmm_key_shuf_mask);
|
load_key(xmm_temp4, key, 0x40, xmm_key_shuf_mask);
|
||||||
}
|
|
||||||
__ cmpl(keylen, 0);
|
__ pxor (xmm_result, xmm_temp1);
|
||||||
__ jcc(Assembler::equal, L_doLast);
|
__ aesdec(xmm_result, xmm_temp2);
|
||||||
// only in 192 and 256 bit keys
|
__ aesdec(xmm_result, xmm_temp3);
|
||||||
aes_dec_key(xmm_result, xmm_temp, key, 0xb0, xmm_key_shuf_mask);
|
__ aesdec(xmm_result, xmm_temp4);
|
||||||
aes_dec_key(xmm_result, xmm_temp, key, 0xc0, xmm_key_shuf_mask);
|
|
||||||
__ subl(keylen, 2);
|
load_key(xmm_temp1, key, 0x50, xmm_key_shuf_mask);
|
||||||
__ jcc(Assembler::equal, L_doLast);
|
load_key(xmm_temp2, key, 0x60, xmm_key_shuf_mask);
|
||||||
// only in 256 bit keys
|
load_key(xmm_temp3, key, 0x70, xmm_key_shuf_mask);
|
||||||
aes_dec_key(xmm_result, xmm_temp, key, 0xd0, xmm_key_shuf_mask);
|
load_key(xmm_temp4, key, 0x80, xmm_key_shuf_mask);
|
||||||
aes_dec_key(xmm_result, xmm_temp, key, 0xe0, xmm_key_shuf_mask);
|
|
||||||
|
__ aesdec(xmm_result, xmm_temp1);
|
||||||
|
__ aesdec(xmm_result, xmm_temp2);
|
||||||
|
__ aesdec(xmm_result, xmm_temp3);
|
||||||
|
__ aesdec(xmm_result, xmm_temp4);
|
||||||
|
|
||||||
|
load_key(xmm_temp1, key, 0x90, xmm_key_shuf_mask);
|
||||||
|
load_key(xmm_temp2, key, 0xa0, xmm_key_shuf_mask);
|
||||||
|
load_key(xmm_temp3, key, 0x00, xmm_key_shuf_mask);
|
||||||
|
|
||||||
|
__ cmpl(keylen, 44);
|
||||||
|
__ jccb(Assembler::equal, L_doLast);
|
||||||
|
|
||||||
|
__ aesdec(xmm_result, xmm_temp1);
|
||||||
|
__ aesdec(xmm_result, xmm_temp2);
|
||||||
|
|
||||||
|
load_key(xmm_temp1, key, 0xb0, xmm_key_shuf_mask);
|
||||||
|
load_key(xmm_temp2, key, 0xc0, xmm_key_shuf_mask);
|
||||||
|
|
||||||
|
__ cmpl(keylen, 52);
|
||||||
|
__ jccb(Assembler::equal, L_doLast);
|
||||||
|
|
||||||
|
__ aesdec(xmm_result, xmm_temp1);
|
||||||
|
__ aesdec(xmm_result, xmm_temp2);
|
||||||
|
|
||||||
|
load_key(xmm_temp1, key, 0xd0, xmm_key_shuf_mask);
|
||||||
|
load_key(xmm_temp2, key, 0xe0, xmm_key_shuf_mask);
|
||||||
|
|
||||||
__ BIND(L_doLast);
|
__ BIND(L_doLast);
|
||||||
|
__ aesdec(xmm_result, xmm_temp1);
|
||||||
|
__ aesdec(xmm_result, xmm_temp2);
|
||||||
|
|
||||||
// for decryption the aesdeclast operation is always on key+0x00
|
// for decryption the aesdeclast operation is always on key+0x00
|
||||||
load_key(xmm_temp, key, 0x00, xmm_key_shuf_mask);
|
__ aesdeclast(xmm_result, xmm_temp3);
|
||||||
__ aesdeclast(xmm_result, xmm_temp);
|
|
||||||
|
|
||||||
__ movdqu(Address(to, 0), xmm_result); // store the result
|
__ movdqu(Address(to, 0), xmm_result); // store the result
|
||||||
|
|
||||||
__ xorptr(rax, rax); // return 0
|
__ xorptr(rax, rax); // return 0
|
||||||
__ pop(rsi);
|
|
||||||
__ leave(); // required for proper stackwalking of RuntimeStub frame
|
__ leave(); // required for proper stackwalking of RuntimeStub frame
|
||||||
__ ret(0);
|
__ ret(0);
|
||||||
|
|
||||||
|
@ -2340,7 +2392,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
// c_rarg4 - input length
|
// c_rarg4 - input length
|
||||||
//
|
//
|
||||||
address generate_cipherBlockChaining_encryptAESCrypt() {
|
address generate_cipherBlockChaining_encryptAESCrypt() {
|
||||||
assert(UseAES && (UseAVX > 0), "need AES instructions and misaligned SSE support");
|
assert(UseAES, "need AES instructions and misaligned SSE support");
|
||||||
__ align(CodeEntryAlignment);
|
__ align(CodeEntryAlignment);
|
||||||
StubCodeMark mark(this, "StubRoutines", "cipherBlockChaining_encryptAESCrypt");
|
StubCodeMark mark(this, "StubRoutines", "cipherBlockChaining_encryptAESCrypt");
|
||||||
address start = __ pc();
|
address start = __ pc();
|
||||||
|
@ -2393,7 +2445,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
__ jcc(Assembler::notEqual, L_key_192_256);
|
__ jcc(Assembler::notEqual, L_key_192_256);
|
||||||
|
|
||||||
// 128 bit code follows here
|
// 128 bit code follows here
|
||||||
__ movptr(pos, 0);
|
__ movl(pos, 0);
|
||||||
__ align(OptoLoopAlignment);
|
__ align(OptoLoopAlignment);
|
||||||
__ BIND(L_loopTop_128);
|
__ BIND(L_loopTop_128);
|
||||||
__ movdqu(xmm_temp, Address(from, pos, Address::times_1, 0)); // get next 16 bytes of input
|
__ movdqu(xmm_temp, Address(from, pos, Address::times_1, 0)); // get next 16 bytes of input
|
||||||
|
@ -2423,15 +2475,15 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
__ leave(); // required for proper stackwalking of RuntimeStub frame
|
__ leave(); // required for proper stackwalking of RuntimeStub frame
|
||||||
__ ret(0);
|
__ ret(0);
|
||||||
|
|
||||||
__ BIND(L_key_192_256);
|
__ BIND(L_key_192_256);
|
||||||
// here rax = len in ints of AESCrypt.KLE array (52=192, or 60=256)
|
// here rax = len in ints of AESCrypt.KLE array (52=192, or 60=256)
|
||||||
__ cmpl(rax, 52);
|
__ cmpl(rax, 52);
|
||||||
__ jcc(Assembler::notEqual, L_key_256);
|
__ jcc(Assembler::notEqual, L_key_256);
|
||||||
|
|
||||||
// 192-bit code follows here (could be changed to use more xmm registers)
|
// 192-bit code follows here (could be changed to use more xmm registers)
|
||||||
__ movptr(pos, 0);
|
__ movl(pos, 0);
|
||||||
__ align(OptoLoopAlignment);
|
__ align(OptoLoopAlignment);
|
||||||
__ BIND(L_loopTop_192);
|
__ BIND(L_loopTop_192);
|
||||||
__ movdqu(xmm_temp, Address(from, pos, Address::times_1, 0)); // get next 16 bytes of input
|
__ movdqu(xmm_temp, Address(from, pos, Address::times_1, 0)); // get next 16 bytes of input
|
||||||
__ pxor (xmm_result, xmm_temp); // xor with the current r vector
|
__ pxor (xmm_result, xmm_temp); // xor with the current r vector
|
||||||
|
|
||||||
|
@ -2452,11 +2504,11 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
__ jcc(Assembler::notEqual, L_loopTop_192);
|
__ jcc(Assembler::notEqual, L_loopTop_192);
|
||||||
__ jmp(L_exit);
|
__ jmp(L_exit);
|
||||||
|
|
||||||
__ BIND(L_key_256);
|
__ BIND(L_key_256);
|
||||||
// 256-bit code follows here (could be changed to use more xmm registers)
|
// 256-bit code follows here (could be changed to use more xmm registers)
|
||||||
__ movptr(pos, 0);
|
__ movl(pos, 0);
|
||||||
__ align(OptoLoopAlignment);
|
__ align(OptoLoopAlignment);
|
||||||
__ BIND(L_loopTop_256);
|
__ BIND(L_loopTop_256);
|
||||||
__ movdqu(xmm_temp, Address(from, pos, Address::times_1, 0)); // get next 16 bytes of input
|
__ movdqu(xmm_temp, Address(from, pos, Address::times_1, 0)); // get next 16 bytes of input
|
||||||
__ pxor (xmm_result, xmm_temp); // xor with the current r vector
|
__ pxor (xmm_result, xmm_temp); // xor with the current r vector
|
||||||
|
|
||||||
|
@ -2495,7 +2547,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
//
|
//
|
||||||
|
|
||||||
address generate_cipherBlockChaining_decryptAESCrypt() {
|
address generate_cipherBlockChaining_decryptAESCrypt() {
|
||||||
assert(UseAES && (UseAVX > 0), "need AES instructions and misaligned SSE support");
|
assert(UseAES, "need AES instructions and misaligned SSE support");
|
||||||
__ align(CodeEntryAlignment);
|
__ align(CodeEntryAlignment);
|
||||||
StubCodeMark mark(this, "StubRoutines", "cipherBlockChaining_decryptAESCrypt");
|
StubCodeMark mark(this, "StubRoutines", "cipherBlockChaining_decryptAESCrypt");
|
||||||
address start = __ pc();
|
address start = __ pc();
|
||||||
|
@ -2556,9 +2608,9 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
|
|
||||||
|
|
||||||
// 128-bit code follows here, parallelized
|
// 128-bit code follows here, parallelized
|
||||||
__ movptr(pos, 0);
|
__ movl(pos, 0);
|
||||||
__ align(OptoLoopAlignment);
|
__ align(OptoLoopAlignment);
|
||||||
__ BIND(L_singleBlock_loopTop_128);
|
__ BIND(L_singleBlock_loopTop_128);
|
||||||
__ cmpptr(len_reg, 0); // any blocks left??
|
__ cmpptr(len_reg, 0); // any blocks left??
|
||||||
__ jcc(Assembler::equal, L_exit);
|
__ jcc(Assembler::equal, L_exit);
|
||||||
__ movdqu(xmm_result, Address(from, pos, Address::times_1, 0)); // get next 16 bytes of cipher input
|
__ movdqu(xmm_result, Address(from, pos, Address::times_1, 0)); // get next 16 bytes of cipher input
|
||||||
|
@ -2597,7 +2649,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
__ jcc(Assembler::notEqual, L_key_256);
|
__ jcc(Assembler::notEqual, L_key_256);
|
||||||
|
|
||||||
// 192-bit code follows here (could be optimized to use parallelism)
|
// 192-bit code follows here (could be optimized to use parallelism)
|
||||||
__ movptr(pos, 0);
|
__ movl(pos, 0);
|
||||||
__ align(OptoLoopAlignment);
|
__ align(OptoLoopAlignment);
|
||||||
__ BIND(L_singleBlock_loopTop_192);
|
__ BIND(L_singleBlock_loopTop_192);
|
||||||
__ movdqu(xmm_result, Address(from, pos, Address::times_1, 0)); // get next 16 bytes of cipher input
|
__ movdqu(xmm_result, Address(from, pos, Address::times_1, 0)); // get next 16 bytes of cipher input
|
||||||
|
@ -2622,7 +2674,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
|
|
||||||
__ BIND(L_key_256);
|
__ BIND(L_key_256);
|
||||||
// 256-bit code follows here (could be optimized to use parallelism)
|
// 256-bit code follows here (could be optimized to use parallelism)
|
||||||
__ movptr(pos, 0);
|
__ movl(pos, 0);
|
||||||
__ align(OptoLoopAlignment);
|
__ align(OptoLoopAlignment);
|
||||||
__ BIND(L_singleBlock_loopTop_256);
|
__ BIND(L_singleBlock_loopTop_256);
|
||||||
__ movdqu(xmm_result, Address(from, pos, Address::times_1, 0)); // get next 16 bytes of cipher input
|
__ movdqu(xmm_result, Address(from, pos, Address::times_1, 0)); // get next 16 bytes of cipher input
|
||||||
|
|
|
@ -2953,21 +2953,6 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// aesenc using specified key+offset
|
|
||||||
// can optionally specify that the shuffle mask is already in an xmmregister
|
|
||||||
void aes_enc_key(XMMRegister xmmdst, XMMRegister xmmtmp, Register key, int offset, XMMRegister xmm_shuf_mask=NULL) {
|
|
||||||
load_key(xmmtmp, key, offset, xmm_shuf_mask);
|
|
||||||
__ aesenc(xmmdst, xmmtmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
// aesdec using specified key+offset
|
|
||||||
// can optionally specify that the shuffle mask is already in an xmmregister
|
|
||||||
void aes_dec_key(XMMRegister xmmdst, XMMRegister xmmtmp, Register key, int offset, XMMRegister xmm_shuf_mask=NULL) {
|
|
||||||
load_key(xmmtmp, key, offset, xmm_shuf_mask);
|
|
||||||
__ aesdec(xmmdst, xmmtmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Arguments:
|
// Arguments:
|
||||||
//
|
//
|
||||||
// Inputs:
|
// Inputs:
|
||||||
|
@ -2976,7 +2961,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
// c_rarg2 - K (key) in little endian int array
|
// c_rarg2 - K (key) in little endian int array
|
||||||
//
|
//
|
||||||
address generate_aescrypt_encryptBlock() {
|
address generate_aescrypt_encryptBlock() {
|
||||||
assert(UseAES && (UseAVX > 0), "need AES instructions and misaligned SSE support");
|
assert(UseAES, "need AES instructions and misaligned SSE support");
|
||||||
__ align(CodeEntryAlignment);
|
__ align(CodeEntryAlignment);
|
||||||
StubCodeMark mark(this, "StubRoutines", "aescrypt_encryptBlock");
|
StubCodeMark mark(this, "StubRoutines", "aescrypt_encryptBlock");
|
||||||
Label L_doLast;
|
Label L_doLast;
|
||||||
|
@ -2988,15 +2973,17 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
const Register keylen = rax;
|
const Register keylen = rax;
|
||||||
|
|
||||||
const XMMRegister xmm_result = xmm0;
|
const XMMRegister xmm_result = xmm0;
|
||||||
const XMMRegister xmm_temp = xmm1;
|
const XMMRegister xmm_key_shuf_mask = xmm1;
|
||||||
const XMMRegister xmm_key_shuf_mask = xmm2;
|
// On win64 xmm6-xmm15 must be preserved so don't use them.
|
||||||
|
const XMMRegister xmm_temp1 = xmm2;
|
||||||
|
const XMMRegister xmm_temp2 = xmm3;
|
||||||
|
const XMMRegister xmm_temp3 = xmm4;
|
||||||
|
const XMMRegister xmm_temp4 = xmm5;
|
||||||
|
|
||||||
__ enter(); // required for proper stackwalking of RuntimeStub frame
|
__ enter(); // required for proper stackwalking of RuntimeStub frame
|
||||||
|
|
||||||
|
// keylen could be only {11, 13, 15} * 4 = {44, 52, 60}
|
||||||
__ movl(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT)));
|
__ movl(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT)));
|
||||||
// keylen = # of 32-bit words, convert to 128-bit words
|
|
||||||
__ shrl(keylen, 2);
|
|
||||||
__ subl(keylen, 11); // every key has at least 11 128-bit words, some have more
|
|
||||||
|
|
||||||
__ movdqu(xmm_key_shuf_mask, ExternalAddress(StubRoutines::x86::key_shuffle_mask_addr()));
|
__ movdqu(xmm_key_shuf_mask, ExternalAddress(StubRoutines::x86::key_shuffle_mask_addr()));
|
||||||
__ movdqu(xmm_result, Address(from, 0)); // get 16 bytes of input
|
__ movdqu(xmm_result, Address(from, 0)); // get 16 bytes of input
|
||||||
|
@ -3004,25 +2991,53 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
// For encryption, the java expanded key ordering is just what we need
|
// For encryption, the java expanded key ordering is just what we need
|
||||||
// we don't know if the key is aligned, hence not using load-execute form
|
// we don't know if the key is aligned, hence not using load-execute form
|
||||||
|
|
||||||
load_key(xmm_temp, key, 0x00, xmm_key_shuf_mask);
|
load_key(xmm_temp1, key, 0x00, xmm_key_shuf_mask);
|
||||||
__ pxor(xmm_result, xmm_temp);
|
__ pxor(xmm_result, xmm_temp1);
|
||||||
for (int offset = 0x10; offset <= 0x90; offset += 0x10) {
|
|
||||||
aes_enc_key(xmm_result, xmm_temp, key, offset, xmm_key_shuf_mask);
|
load_key(xmm_temp1, key, 0x10, xmm_key_shuf_mask);
|
||||||
}
|
load_key(xmm_temp2, key, 0x20, xmm_key_shuf_mask);
|
||||||
load_key (xmm_temp, key, 0xa0, xmm_key_shuf_mask);
|
load_key(xmm_temp3, key, 0x30, xmm_key_shuf_mask);
|
||||||
__ cmpl(keylen, 0);
|
load_key(xmm_temp4, key, 0x40, xmm_key_shuf_mask);
|
||||||
__ jcc(Assembler::equal, L_doLast);
|
|
||||||
__ aesenc(xmm_result, xmm_temp); // only in 192 and 256 bit keys
|
__ aesenc(xmm_result, xmm_temp1);
|
||||||
aes_enc_key(xmm_result, xmm_temp, key, 0xb0, xmm_key_shuf_mask);
|
__ aesenc(xmm_result, xmm_temp2);
|
||||||
load_key(xmm_temp, key, 0xc0, xmm_key_shuf_mask);
|
__ aesenc(xmm_result, xmm_temp3);
|
||||||
__ subl(keylen, 2);
|
__ aesenc(xmm_result, xmm_temp4);
|
||||||
__ jcc(Assembler::equal, L_doLast);
|
|
||||||
__ aesenc(xmm_result, xmm_temp); // only in 256 bit keys
|
load_key(xmm_temp1, key, 0x50, xmm_key_shuf_mask);
|
||||||
aes_enc_key(xmm_result, xmm_temp, key, 0xd0, xmm_key_shuf_mask);
|
load_key(xmm_temp2, key, 0x60, xmm_key_shuf_mask);
|
||||||
load_key(xmm_temp, key, 0xe0, xmm_key_shuf_mask);
|
load_key(xmm_temp3, key, 0x70, xmm_key_shuf_mask);
|
||||||
|
load_key(xmm_temp4, key, 0x80, xmm_key_shuf_mask);
|
||||||
|
|
||||||
|
__ aesenc(xmm_result, xmm_temp1);
|
||||||
|
__ aesenc(xmm_result, xmm_temp2);
|
||||||
|
__ aesenc(xmm_result, xmm_temp3);
|
||||||
|
__ aesenc(xmm_result, xmm_temp4);
|
||||||
|
|
||||||
|
load_key(xmm_temp1, key, 0x90, xmm_key_shuf_mask);
|
||||||
|
load_key(xmm_temp2, key, 0xa0, xmm_key_shuf_mask);
|
||||||
|
|
||||||
|
__ cmpl(keylen, 44);
|
||||||
|
__ jccb(Assembler::equal, L_doLast);
|
||||||
|
|
||||||
|
__ aesenc(xmm_result, xmm_temp1);
|
||||||
|
__ aesenc(xmm_result, xmm_temp2);
|
||||||
|
|
||||||
|
load_key(xmm_temp1, key, 0xb0, xmm_key_shuf_mask);
|
||||||
|
load_key(xmm_temp2, key, 0xc0, xmm_key_shuf_mask);
|
||||||
|
|
||||||
|
__ cmpl(keylen, 52);
|
||||||
|
__ jccb(Assembler::equal, L_doLast);
|
||||||
|
|
||||||
|
__ aesenc(xmm_result, xmm_temp1);
|
||||||
|
__ aesenc(xmm_result, xmm_temp2);
|
||||||
|
|
||||||
|
load_key(xmm_temp1, key, 0xd0, xmm_key_shuf_mask);
|
||||||
|
load_key(xmm_temp2, key, 0xe0, xmm_key_shuf_mask);
|
||||||
|
|
||||||
__ BIND(L_doLast);
|
__ BIND(L_doLast);
|
||||||
__ aesenclast(xmm_result, xmm_temp);
|
__ aesenc(xmm_result, xmm_temp1);
|
||||||
|
__ aesenclast(xmm_result, xmm_temp2);
|
||||||
__ movdqu(Address(to, 0), xmm_result); // store the result
|
__ movdqu(Address(to, 0), xmm_result); // store the result
|
||||||
__ xorptr(rax, rax); // return 0
|
__ xorptr(rax, rax); // return 0
|
||||||
__ leave(); // required for proper stackwalking of RuntimeStub frame
|
__ leave(); // required for proper stackwalking of RuntimeStub frame
|
||||||
|
@ -3040,7 +3055,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
// c_rarg2 - K (key) in little endian int array
|
// c_rarg2 - K (key) in little endian int array
|
||||||
//
|
//
|
||||||
address generate_aescrypt_decryptBlock() {
|
address generate_aescrypt_decryptBlock() {
|
||||||
assert(UseAES && (UseAVX > 0), "need AES instructions and misaligned SSE support");
|
assert(UseAES, "need AES instructions and misaligned SSE support");
|
||||||
__ align(CodeEntryAlignment);
|
__ align(CodeEntryAlignment);
|
||||||
StubCodeMark mark(this, "StubRoutines", "aescrypt_decryptBlock");
|
StubCodeMark mark(this, "StubRoutines", "aescrypt_decryptBlock");
|
||||||
Label L_doLast;
|
Label L_doLast;
|
||||||
|
@ -3052,15 +3067,17 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
const Register keylen = rax;
|
const Register keylen = rax;
|
||||||
|
|
||||||
const XMMRegister xmm_result = xmm0;
|
const XMMRegister xmm_result = xmm0;
|
||||||
const XMMRegister xmm_temp = xmm1;
|
const XMMRegister xmm_key_shuf_mask = xmm1;
|
||||||
const XMMRegister xmm_key_shuf_mask = xmm2;
|
// On win64 xmm6-xmm15 must be preserved so don't use them.
|
||||||
|
const XMMRegister xmm_temp1 = xmm2;
|
||||||
|
const XMMRegister xmm_temp2 = xmm3;
|
||||||
|
const XMMRegister xmm_temp3 = xmm4;
|
||||||
|
const XMMRegister xmm_temp4 = xmm5;
|
||||||
|
|
||||||
__ enter(); // required for proper stackwalking of RuntimeStub frame
|
__ enter(); // required for proper stackwalking of RuntimeStub frame
|
||||||
|
|
||||||
|
// keylen could be only {11, 13, 15} * 4 = {44, 52, 60}
|
||||||
__ movl(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT)));
|
__ movl(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT)));
|
||||||
// keylen = # of 32-bit words, convert to 128-bit words
|
|
||||||
__ shrl(keylen, 2);
|
|
||||||
__ subl(keylen, 11); // every key has at least 11 128-bit words, some have more
|
|
||||||
|
|
||||||
__ movdqu(xmm_key_shuf_mask, ExternalAddress(StubRoutines::x86::key_shuffle_mask_addr()));
|
__ movdqu(xmm_key_shuf_mask, ExternalAddress(StubRoutines::x86::key_shuffle_mask_addr()));
|
||||||
__ movdqu(xmm_result, Address(from, 0));
|
__ movdqu(xmm_result, Address(from, 0));
|
||||||
|
@ -3068,29 +3085,55 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
// for decryption java expanded key ordering is rotated one position from what we want
|
// for decryption java expanded key ordering is rotated one position from what we want
|
||||||
// so we start from 0x10 here and hit 0x00 last
|
// so we start from 0x10 here and hit 0x00 last
|
||||||
// we don't know if the key is aligned, hence not using load-execute form
|
// we don't know if the key is aligned, hence not using load-execute form
|
||||||
load_key(xmm_temp, key, 0x10, xmm_key_shuf_mask);
|
load_key(xmm_temp1, key, 0x10, xmm_key_shuf_mask);
|
||||||
__ pxor (xmm_result, xmm_temp);
|
load_key(xmm_temp2, key, 0x20, xmm_key_shuf_mask);
|
||||||
for (int offset = 0x20; offset <= 0xa0; offset += 0x10) {
|
load_key(xmm_temp3, key, 0x30, xmm_key_shuf_mask);
|
||||||
aes_dec_key(xmm_result, xmm_temp, key, offset, xmm_key_shuf_mask);
|
load_key(xmm_temp4, key, 0x40, xmm_key_shuf_mask);
|
||||||
}
|
|
||||||
__ cmpl(keylen, 0);
|
__ pxor (xmm_result, xmm_temp1);
|
||||||
__ jcc(Assembler::equal, L_doLast);
|
__ aesdec(xmm_result, xmm_temp2);
|
||||||
// only in 192 and 256 bit keys
|
__ aesdec(xmm_result, xmm_temp3);
|
||||||
aes_dec_key(xmm_result, xmm_temp, key, 0xb0, xmm_key_shuf_mask);
|
__ aesdec(xmm_result, xmm_temp4);
|
||||||
aes_dec_key(xmm_result, xmm_temp, key, 0xc0, xmm_key_shuf_mask);
|
|
||||||
__ subl(keylen, 2);
|
load_key(xmm_temp1, key, 0x50, xmm_key_shuf_mask);
|
||||||
__ jcc(Assembler::equal, L_doLast);
|
load_key(xmm_temp2, key, 0x60, xmm_key_shuf_mask);
|
||||||
// only in 256 bit keys
|
load_key(xmm_temp3, key, 0x70, xmm_key_shuf_mask);
|
||||||
aes_dec_key(xmm_result, xmm_temp, key, 0xd0, xmm_key_shuf_mask);
|
load_key(xmm_temp4, key, 0x80, xmm_key_shuf_mask);
|
||||||
aes_dec_key(xmm_result, xmm_temp, key, 0xe0, xmm_key_shuf_mask);
|
|
||||||
|
__ aesdec(xmm_result, xmm_temp1);
|
||||||
|
__ aesdec(xmm_result, xmm_temp2);
|
||||||
|
__ aesdec(xmm_result, xmm_temp3);
|
||||||
|
__ aesdec(xmm_result, xmm_temp4);
|
||||||
|
|
||||||
|
load_key(xmm_temp1, key, 0x90, xmm_key_shuf_mask);
|
||||||
|
load_key(xmm_temp2, key, 0xa0, xmm_key_shuf_mask);
|
||||||
|
load_key(xmm_temp3, key, 0x00, xmm_key_shuf_mask);
|
||||||
|
|
||||||
|
__ cmpl(keylen, 44);
|
||||||
|
__ jccb(Assembler::equal, L_doLast);
|
||||||
|
|
||||||
|
__ aesdec(xmm_result, xmm_temp1);
|
||||||
|
__ aesdec(xmm_result, xmm_temp2);
|
||||||
|
|
||||||
|
load_key(xmm_temp1, key, 0xb0, xmm_key_shuf_mask);
|
||||||
|
load_key(xmm_temp2, key, 0xc0, xmm_key_shuf_mask);
|
||||||
|
|
||||||
|
__ cmpl(keylen, 52);
|
||||||
|
__ jccb(Assembler::equal, L_doLast);
|
||||||
|
|
||||||
|
__ aesdec(xmm_result, xmm_temp1);
|
||||||
|
__ aesdec(xmm_result, xmm_temp2);
|
||||||
|
|
||||||
|
load_key(xmm_temp1, key, 0xd0, xmm_key_shuf_mask);
|
||||||
|
load_key(xmm_temp2, key, 0xe0, xmm_key_shuf_mask);
|
||||||
|
|
||||||
__ BIND(L_doLast);
|
__ BIND(L_doLast);
|
||||||
|
__ aesdec(xmm_result, xmm_temp1);
|
||||||
|
__ aesdec(xmm_result, xmm_temp2);
|
||||||
|
|
||||||
// for decryption the aesdeclast operation is always on key+0x00
|
// for decryption the aesdeclast operation is always on key+0x00
|
||||||
load_key(xmm_temp, key, 0x00, xmm_key_shuf_mask);
|
__ aesdeclast(xmm_result, xmm_temp3);
|
||||||
__ aesdeclast(xmm_result, xmm_temp);
|
|
||||||
|
|
||||||
__ movdqu(Address(to, 0), xmm_result); // store the result
|
__ movdqu(Address(to, 0), xmm_result); // store the result
|
||||||
|
|
||||||
__ xorptr(rax, rax); // return 0
|
__ xorptr(rax, rax); // return 0
|
||||||
__ leave(); // required for proper stackwalking of RuntimeStub frame
|
__ leave(); // required for proper stackwalking of RuntimeStub frame
|
||||||
__ ret(0);
|
__ ret(0);
|
||||||
|
@ -3109,7 +3152,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
// c_rarg4 - input length
|
// c_rarg4 - input length
|
||||||
//
|
//
|
||||||
address generate_cipherBlockChaining_encryptAESCrypt() {
|
address generate_cipherBlockChaining_encryptAESCrypt() {
|
||||||
assert(UseAES && (UseAVX > 0), "need AES instructions and misaligned SSE support");
|
assert(UseAES, "need AES instructions and misaligned SSE support");
|
||||||
__ align(CodeEntryAlignment);
|
__ align(CodeEntryAlignment);
|
||||||
StubCodeMark mark(this, "StubRoutines", "cipherBlockChaining_encryptAESCrypt");
|
StubCodeMark mark(this, "StubRoutines", "cipherBlockChaining_encryptAESCrypt");
|
||||||
address start = __ pc();
|
address start = __ pc();
|
||||||
|
@ -3133,16 +3176,19 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
const XMMRegister xmm_temp = xmm1;
|
const XMMRegister xmm_temp = xmm1;
|
||||||
// keys 0-10 preloaded into xmm2-xmm12
|
// keys 0-10 preloaded into xmm2-xmm12
|
||||||
const int XMM_REG_NUM_KEY_FIRST = 2;
|
const int XMM_REG_NUM_KEY_FIRST = 2;
|
||||||
const int XMM_REG_NUM_KEY_LAST = 12;
|
const int XMM_REG_NUM_KEY_LAST = 15;
|
||||||
const XMMRegister xmm_key0 = as_XMMRegister(XMM_REG_NUM_KEY_FIRST);
|
const XMMRegister xmm_key0 = as_XMMRegister(XMM_REG_NUM_KEY_FIRST);
|
||||||
const XMMRegister xmm_key10 = as_XMMRegister(XMM_REG_NUM_KEY_LAST);
|
const XMMRegister xmm_key10 = as_XMMRegister(XMM_REG_NUM_KEY_FIRST+10);
|
||||||
|
const XMMRegister xmm_key11 = as_XMMRegister(XMM_REG_NUM_KEY_FIRST+11);
|
||||||
|
const XMMRegister xmm_key12 = as_XMMRegister(XMM_REG_NUM_KEY_FIRST+12);
|
||||||
|
const XMMRegister xmm_key13 = as_XMMRegister(XMM_REG_NUM_KEY_FIRST+13);
|
||||||
|
|
||||||
__ enter(); // required for proper stackwalking of RuntimeStub frame
|
__ enter(); // required for proper stackwalking of RuntimeStub frame
|
||||||
|
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
// on win64, fill len_reg from stack position
|
// on win64, fill len_reg from stack position
|
||||||
__ movl(len_reg, len_mem);
|
__ movl(len_reg, len_mem);
|
||||||
// save the xmm registers which must be preserved 6-12
|
// save the xmm registers which must be preserved 6-15
|
||||||
__ subptr(rsp, -rsp_after_call_off * wordSize);
|
__ subptr(rsp, -rsp_after_call_off * wordSize);
|
||||||
for (int i = 6; i <= XMM_REG_NUM_KEY_LAST; i++) {
|
for (int i = 6; i <= XMM_REG_NUM_KEY_LAST; i++) {
|
||||||
__ movdqu(xmm_save(i), as_XMMRegister(i));
|
__ movdqu(xmm_save(i), as_XMMRegister(i));
|
||||||
|
@ -3151,12 +3197,11 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
|
|
||||||
const XMMRegister xmm_key_shuf_mask = xmm_temp; // used temporarily to swap key bytes up front
|
const XMMRegister xmm_key_shuf_mask = xmm_temp; // used temporarily to swap key bytes up front
|
||||||
__ movdqu(xmm_key_shuf_mask, ExternalAddress(StubRoutines::x86::key_shuffle_mask_addr()));
|
__ movdqu(xmm_key_shuf_mask, ExternalAddress(StubRoutines::x86::key_shuffle_mask_addr()));
|
||||||
// load up xmm regs 2 thru 12 with key 0x00 - 0xa0
|
// load up xmm regs xmm2 thru xmm12 with key 0x00 - 0xa0
|
||||||
for (int rnum = XMM_REG_NUM_KEY_FIRST, offset = 0x00; rnum <= XMM_REG_NUM_KEY_LAST; rnum++) {
|
for (int rnum = XMM_REG_NUM_KEY_FIRST, offset = 0x00; rnum <= XMM_REG_NUM_KEY_FIRST+10; rnum++) {
|
||||||
load_key(as_XMMRegister(rnum), key, offset, xmm_key_shuf_mask);
|
load_key(as_XMMRegister(rnum), key, offset, xmm_key_shuf_mask);
|
||||||
offset += 0x10;
|
offset += 0x10;
|
||||||
}
|
}
|
||||||
|
|
||||||
__ movdqu(xmm_result, Address(rvec, 0x00)); // initialize xmm_result with r vec
|
__ movdqu(xmm_result, Address(rvec, 0x00)); // initialize xmm_result with r vec
|
||||||
|
|
||||||
// now split to different paths depending on the keylen (len in ints of AESCrypt.KLE array (52=192, or 60=256))
|
// now split to different paths depending on the keylen (len in ints of AESCrypt.KLE array (52=192, or 60=256))
|
||||||
|
@ -3167,16 +3212,15 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
// 128 bit code follows here
|
// 128 bit code follows here
|
||||||
__ movptr(pos, 0);
|
__ movptr(pos, 0);
|
||||||
__ align(OptoLoopAlignment);
|
__ align(OptoLoopAlignment);
|
||||||
|
|
||||||
__ BIND(L_loopTop_128);
|
__ BIND(L_loopTop_128);
|
||||||
__ movdqu(xmm_temp, Address(from, pos, Address::times_1, 0)); // get next 16 bytes of input
|
__ movdqu(xmm_temp, Address(from, pos, Address::times_1, 0)); // get next 16 bytes of input
|
||||||
__ pxor (xmm_result, xmm_temp); // xor with the current r vector
|
__ pxor (xmm_result, xmm_temp); // xor with the current r vector
|
||||||
|
|
||||||
__ pxor (xmm_result, xmm_key0); // do the aes rounds
|
__ pxor (xmm_result, xmm_key0); // do the aes rounds
|
||||||
for (int rnum = XMM_REG_NUM_KEY_FIRST + 1; rnum <= XMM_REG_NUM_KEY_LAST - 1; rnum++) {
|
for (int rnum = XMM_REG_NUM_KEY_FIRST + 1; rnum <= XMM_REG_NUM_KEY_FIRST + 9; rnum++) {
|
||||||
__ aesenc(xmm_result, as_XMMRegister(rnum));
|
__ aesenc(xmm_result, as_XMMRegister(rnum));
|
||||||
}
|
}
|
||||||
__ aesenclast(xmm_result, xmm_key10);
|
__ aesenclast(xmm_result, xmm_key10);
|
||||||
|
|
||||||
__ movdqu(Address(to, pos, Address::times_1, 0), xmm_result); // store into the next 16 bytes of output
|
__ movdqu(Address(to, pos, Address::times_1, 0), xmm_result); // store into the next 16 bytes of output
|
||||||
// no need to store r to memory until we exit
|
// no need to store r to memory until we exit
|
||||||
__ addptr(pos, AESBlockSize);
|
__ addptr(pos, AESBlockSize);
|
||||||
|
@ -3198,24 +3242,23 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
|
|
||||||
__ BIND(L_key_192_256);
|
__ BIND(L_key_192_256);
|
||||||
// here rax = len in ints of AESCrypt.KLE array (52=192, or 60=256)
|
// here rax = len in ints of AESCrypt.KLE array (52=192, or 60=256)
|
||||||
|
load_key(xmm_key11, key, 0xb0, xmm_key_shuf_mask);
|
||||||
|
load_key(xmm_key12, key, 0xc0, xmm_key_shuf_mask);
|
||||||
__ cmpl(rax, 52);
|
__ cmpl(rax, 52);
|
||||||
__ jcc(Assembler::notEqual, L_key_256);
|
__ jcc(Assembler::notEqual, L_key_256);
|
||||||
|
|
||||||
// 192-bit code follows here (could be changed to use more xmm registers)
|
// 192-bit code follows here (could be changed to use more xmm registers)
|
||||||
__ movptr(pos, 0);
|
__ movptr(pos, 0);
|
||||||
__ align(OptoLoopAlignment);
|
__ align(OptoLoopAlignment);
|
||||||
|
|
||||||
__ BIND(L_loopTop_192);
|
__ BIND(L_loopTop_192);
|
||||||
__ movdqu(xmm_temp, Address(from, pos, Address::times_1, 0)); // get next 16 bytes of input
|
__ movdqu(xmm_temp, Address(from, pos, Address::times_1, 0)); // get next 16 bytes of input
|
||||||
__ pxor (xmm_result, xmm_temp); // xor with the current r vector
|
__ pxor (xmm_result, xmm_temp); // xor with the current r vector
|
||||||
|
|
||||||
__ pxor (xmm_result, xmm_key0); // do the aes rounds
|
__ pxor (xmm_result, xmm_key0); // do the aes rounds
|
||||||
for (int rnum = XMM_REG_NUM_KEY_FIRST + 1; rnum <= XMM_REG_NUM_KEY_LAST; rnum++) {
|
for (int rnum = XMM_REG_NUM_KEY_FIRST + 1; rnum <= XMM_REG_NUM_KEY_FIRST + 11; rnum++) {
|
||||||
__ aesenc(xmm_result, as_XMMRegister(rnum));
|
__ aesenc(xmm_result, as_XMMRegister(rnum));
|
||||||
}
|
}
|
||||||
aes_enc_key(xmm_result, xmm_temp, key, 0xb0);
|
__ aesenclast(xmm_result, xmm_key12);
|
||||||
load_key(xmm_temp, key, 0xc0);
|
|
||||||
__ aesenclast(xmm_result, xmm_temp);
|
|
||||||
|
|
||||||
__ movdqu(Address(to, pos, Address::times_1, 0), xmm_result); // store into the next 16 bytes of output
|
__ movdqu(Address(to, pos, Address::times_1, 0), xmm_result); // store into the next 16 bytes of output
|
||||||
// no need to store r to memory until we exit
|
// no need to store r to memory until we exit
|
||||||
__ addptr(pos, AESBlockSize);
|
__ addptr(pos, AESBlockSize);
|
||||||
|
@ -3225,22 +3268,19 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
|
|
||||||
__ BIND(L_key_256);
|
__ BIND(L_key_256);
|
||||||
// 256-bit code follows here (could be changed to use more xmm registers)
|
// 256-bit code follows here (could be changed to use more xmm registers)
|
||||||
|
load_key(xmm_key13, key, 0xd0, xmm_key_shuf_mask);
|
||||||
__ movptr(pos, 0);
|
__ movptr(pos, 0);
|
||||||
__ align(OptoLoopAlignment);
|
__ align(OptoLoopAlignment);
|
||||||
|
|
||||||
__ BIND(L_loopTop_256);
|
__ BIND(L_loopTop_256);
|
||||||
__ movdqu(xmm_temp, Address(from, pos, Address::times_1, 0)); // get next 16 bytes of input
|
__ movdqu(xmm_temp, Address(from, pos, Address::times_1, 0)); // get next 16 bytes of input
|
||||||
__ pxor (xmm_result, xmm_temp); // xor with the current r vector
|
__ pxor (xmm_result, xmm_temp); // xor with the current r vector
|
||||||
|
|
||||||
__ pxor (xmm_result, xmm_key0); // do the aes rounds
|
__ pxor (xmm_result, xmm_key0); // do the aes rounds
|
||||||
for (int rnum = XMM_REG_NUM_KEY_FIRST + 1; rnum <= XMM_REG_NUM_KEY_LAST; rnum++) {
|
for (int rnum = XMM_REG_NUM_KEY_FIRST + 1; rnum <= XMM_REG_NUM_KEY_FIRST + 13; rnum++) {
|
||||||
__ aesenc(xmm_result, as_XMMRegister(rnum));
|
__ aesenc(xmm_result, as_XMMRegister(rnum));
|
||||||
}
|
}
|
||||||
aes_enc_key(xmm_result, xmm_temp, key, 0xb0);
|
|
||||||
aes_enc_key(xmm_result, xmm_temp, key, 0xc0);
|
|
||||||
aes_enc_key(xmm_result, xmm_temp, key, 0xd0);
|
|
||||||
load_key(xmm_temp, key, 0xe0);
|
load_key(xmm_temp, key, 0xe0);
|
||||||
__ aesenclast(xmm_result, xmm_temp);
|
__ aesenclast(xmm_result, xmm_temp);
|
||||||
|
|
||||||
__ movdqu(Address(to, pos, Address::times_1, 0), xmm_result); // store into the next 16 bytes of output
|
__ movdqu(Address(to, pos, Address::times_1, 0), xmm_result); // store into the next 16 bytes of output
|
||||||
// no need to store r to memory until we exit
|
// no need to store r to memory until we exit
|
||||||
__ addptr(pos, AESBlockSize);
|
__ addptr(pos, AESBlockSize);
|
||||||
|
@ -3267,7 +3307,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
//
|
//
|
||||||
|
|
||||||
address generate_cipherBlockChaining_decryptAESCrypt_Parallel() {
|
address generate_cipherBlockChaining_decryptAESCrypt_Parallel() {
|
||||||
assert(UseAES && (UseAVX > 0), "need AES instructions and misaligned SSE support");
|
assert(UseAES, "need AES instructions and misaligned SSE support");
|
||||||
__ align(CodeEntryAlignment);
|
__ align(CodeEntryAlignment);
|
||||||
StubCodeMark mark(this, "StubRoutines", "cipherBlockChaining_decryptAESCrypt");
|
StubCodeMark mark(this, "StubRoutines", "cipherBlockChaining_decryptAESCrypt");
|
||||||
address start = __ pc();
|
address start = __ pc();
|
||||||
|
@ -3288,12 +3328,10 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
#endif
|
#endif
|
||||||
const Register pos = rax;
|
const Register pos = rax;
|
||||||
|
|
||||||
// xmm register assignments for the loops below
|
|
||||||
const XMMRegister xmm_result = xmm0;
|
|
||||||
// keys 0-10 preloaded into xmm2-xmm12
|
// keys 0-10 preloaded into xmm2-xmm12
|
||||||
const int XMM_REG_NUM_KEY_FIRST = 5;
|
const int XMM_REG_NUM_KEY_FIRST = 5;
|
||||||
const int XMM_REG_NUM_KEY_LAST = 15;
|
const int XMM_REG_NUM_KEY_LAST = 15;
|
||||||
const XMMRegister xmm_key_first = as_XMMRegister(XMM_REG_NUM_KEY_FIRST);
|
const XMMRegister xmm_key_first = as_XMMRegister(XMM_REG_NUM_KEY_FIRST);
|
||||||
const XMMRegister xmm_key_last = as_XMMRegister(XMM_REG_NUM_KEY_LAST);
|
const XMMRegister xmm_key_last = as_XMMRegister(XMM_REG_NUM_KEY_LAST);
|
||||||
|
|
||||||
__ enter(); // required for proper stackwalking of RuntimeStub frame
|
__ enter(); // required for proper stackwalking of RuntimeStub frame
|
||||||
|
@ -3312,13 +3350,14 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
const XMMRegister xmm_key_shuf_mask = xmm1; // used temporarily to swap key bytes up front
|
const XMMRegister xmm_key_shuf_mask = xmm1; // used temporarily to swap key bytes up front
|
||||||
__ movdqu(xmm_key_shuf_mask, ExternalAddress(StubRoutines::x86::key_shuffle_mask_addr()));
|
__ movdqu(xmm_key_shuf_mask, ExternalAddress(StubRoutines::x86::key_shuffle_mask_addr()));
|
||||||
// load up xmm regs 5 thru 15 with key 0x10 - 0xa0 - 0x00
|
// load up xmm regs 5 thru 15 with key 0x10 - 0xa0 - 0x00
|
||||||
for (int rnum = XMM_REG_NUM_KEY_FIRST, offset = 0x10; rnum <= XMM_REG_NUM_KEY_LAST; rnum++) {
|
for (int rnum = XMM_REG_NUM_KEY_FIRST, offset = 0x10; rnum < XMM_REG_NUM_KEY_LAST; rnum++) {
|
||||||
if (rnum == XMM_REG_NUM_KEY_LAST) offset = 0x00;
|
|
||||||
load_key(as_XMMRegister(rnum), key, offset, xmm_key_shuf_mask);
|
load_key(as_XMMRegister(rnum), key, offset, xmm_key_shuf_mask);
|
||||||
offset += 0x10;
|
offset += 0x10;
|
||||||
}
|
}
|
||||||
|
load_key(xmm_key_last, key, 0x00, xmm_key_shuf_mask);
|
||||||
|
|
||||||
const XMMRegister xmm_prev_block_cipher = xmm1; // holds cipher of previous block
|
const XMMRegister xmm_prev_block_cipher = xmm1; // holds cipher of previous block
|
||||||
|
|
||||||
// registers holding the four results in the parallelized loop
|
// registers holding the four results in the parallelized loop
|
||||||
const XMMRegister xmm_result0 = xmm0;
|
const XMMRegister xmm_result0 = xmm0;
|
||||||
const XMMRegister xmm_result1 = xmm2;
|
const XMMRegister xmm_result1 = xmm2;
|
||||||
|
@ -3376,8 +3415,12 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
__ jmp(L_multiBlock_loopTop_128);
|
__ jmp(L_multiBlock_loopTop_128);
|
||||||
|
|
||||||
// registers used in the non-parallelized loops
|
// registers used in the non-parallelized loops
|
||||||
|
// xmm register assignments for the loops below
|
||||||
|
const XMMRegister xmm_result = xmm0;
|
||||||
const XMMRegister xmm_prev_block_cipher_save = xmm2;
|
const XMMRegister xmm_prev_block_cipher_save = xmm2;
|
||||||
const XMMRegister xmm_temp = xmm3;
|
const XMMRegister xmm_key11 = xmm3;
|
||||||
|
const XMMRegister xmm_key12 = xmm4;
|
||||||
|
const XMMRegister xmm_temp = xmm4;
|
||||||
|
|
||||||
__ align(OptoLoopAlignment);
|
__ align(OptoLoopAlignment);
|
||||||
__ BIND(L_singleBlock_loopTop_128);
|
__ BIND(L_singleBlock_loopTop_128);
|
||||||
|
@ -3415,12 +3458,15 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
|
|
||||||
__ BIND(L_key_192_256);
|
__ BIND(L_key_192_256);
|
||||||
// here rax = len in ints of AESCrypt.KLE array (52=192, or 60=256)
|
// here rax = len in ints of AESCrypt.KLE array (52=192, or 60=256)
|
||||||
|
load_key(xmm_key11, key, 0xb0);
|
||||||
__ cmpl(rax, 52);
|
__ cmpl(rax, 52);
|
||||||
__ jcc(Assembler::notEqual, L_key_256);
|
__ jcc(Assembler::notEqual, L_key_256);
|
||||||
|
|
||||||
// 192-bit code follows here (could be optimized to use parallelism)
|
// 192-bit code follows here (could be optimized to use parallelism)
|
||||||
|
load_key(xmm_key12, key, 0xc0); // 192-bit key goes up to c0
|
||||||
__ movptr(pos, 0);
|
__ movptr(pos, 0);
|
||||||
__ align(OptoLoopAlignment);
|
__ align(OptoLoopAlignment);
|
||||||
|
|
||||||
__ BIND(L_singleBlock_loopTop_192);
|
__ BIND(L_singleBlock_loopTop_192);
|
||||||
__ movdqu(xmm_result, Address(from, pos, Address::times_1, 0)); // get next 16 bytes of cipher input
|
__ movdqu(xmm_result, Address(from, pos, Address::times_1, 0)); // get next 16 bytes of cipher input
|
||||||
__ movdqa(xmm_prev_block_cipher_save, xmm_result); // save for next r vector
|
__ movdqa(xmm_prev_block_cipher_save, xmm_result); // save for next r vector
|
||||||
|
@ -3428,14 +3474,13 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
for (int rnum = XMM_REG_NUM_KEY_FIRST + 1; rnum <= XMM_REG_NUM_KEY_LAST - 1; rnum++) {
|
for (int rnum = XMM_REG_NUM_KEY_FIRST + 1; rnum <= XMM_REG_NUM_KEY_LAST - 1; rnum++) {
|
||||||
__ aesdec(xmm_result, as_XMMRegister(rnum));
|
__ aesdec(xmm_result, as_XMMRegister(rnum));
|
||||||
}
|
}
|
||||||
aes_dec_key(xmm_result, xmm_temp, key, 0xb0); // 192-bit key goes up to c0
|
__ aesdec(xmm_result, xmm_key11);
|
||||||
aes_dec_key(xmm_result, xmm_temp, key, 0xc0);
|
__ aesdec(xmm_result, xmm_key12);
|
||||||
__ aesdeclast(xmm_result, xmm_key_last); // xmm15 always came from key+0
|
__ aesdeclast(xmm_result, xmm_key_last); // xmm15 always came from key+0
|
||||||
__ pxor (xmm_result, xmm_prev_block_cipher); // xor with the current r vector
|
__ pxor (xmm_result, xmm_prev_block_cipher); // xor with the current r vector
|
||||||
__ movdqu(Address(to, pos, Address::times_1, 0), xmm_result); // store into the next 16 bytes of output
|
__ movdqu(Address(to, pos, Address::times_1, 0), xmm_result); // store into the next 16 bytes of output
|
||||||
// no need to store r to memory until we exit
|
// no need to store r to memory until we exit
|
||||||
__ movdqa(xmm_prev_block_cipher, xmm_prev_block_cipher_save); // set up next r vector with cipher input from this block
|
__ movdqa(xmm_prev_block_cipher, xmm_prev_block_cipher_save); // set up next r vector with cipher input from this block
|
||||||
|
|
||||||
__ addptr(pos, AESBlockSize);
|
__ addptr(pos, AESBlockSize);
|
||||||
__ subptr(len_reg, AESBlockSize);
|
__ subptr(len_reg, AESBlockSize);
|
||||||
__ jcc(Assembler::notEqual,L_singleBlock_loopTop_192);
|
__ jcc(Assembler::notEqual,L_singleBlock_loopTop_192);
|
||||||
|
@ -3445,23 +3490,26 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
// 256-bit code follows here (could be optimized to use parallelism)
|
// 256-bit code follows here (could be optimized to use parallelism)
|
||||||
__ movptr(pos, 0);
|
__ movptr(pos, 0);
|
||||||
__ align(OptoLoopAlignment);
|
__ align(OptoLoopAlignment);
|
||||||
|
|
||||||
__ BIND(L_singleBlock_loopTop_256);
|
__ BIND(L_singleBlock_loopTop_256);
|
||||||
__ movdqu(xmm_result, Address(from, pos, Address::times_1, 0)); // get next 16 bytes of cipher input
|
__ movdqu(xmm_result, Address(from, pos, Address::times_1, 0)); // get next 16 bytes of cipher input
|
||||||
__ movdqa(xmm_prev_block_cipher_save, xmm_result); // save for next r vector
|
__ movdqa(xmm_prev_block_cipher_save, xmm_result); // save for next r vector
|
||||||
__ pxor (xmm_result, xmm_key_first); // do the aes dec rounds
|
__ pxor (xmm_result, xmm_key_first); // do the aes dec rounds
|
||||||
for (int rnum = XMM_REG_NUM_KEY_FIRST + 1; rnum <= XMM_REG_NUM_KEY_LAST - 1; rnum++) {
|
for (int rnum = XMM_REG_NUM_KEY_FIRST + 1; rnum <= XMM_REG_NUM_KEY_LAST - 1; rnum++) {
|
||||||
__ aesdec(xmm_result, as_XMMRegister(rnum));
|
__ aesdec(xmm_result, as_XMMRegister(rnum));
|
||||||
}
|
}
|
||||||
aes_dec_key(xmm_result, xmm_temp, key, 0xb0); // 256-bit key goes up to e0
|
__ aesdec(xmm_result, xmm_key11);
|
||||||
aes_dec_key(xmm_result, xmm_temp, key, 0xc0);
|
load_key(xmm_temp, key, 0xc0);
|
||||||
aes_dec_key(xmm_result, xmm_temp, key, 0xd0);
|
__ aesdec(xmm_result, xmm_temp);
|
||||||
aes_dec_key(xmm_result, xmm_temp, key, 0xe0);
|
load_key(xmm_temp, key, 0xd0);
|
||||||
__ aesdeclast(xmm_result, xmm_key_last); // xmm15 came from key+0
|
__ aesdec(xmm_result, xmm_temp);
|
||||||
|
load_key(xmm_temp, key, 0xe0); // 256-bit key goes up to e0
|
||||||
|
__ aesdec(xmm_result, xmm_temp);
|
||||||
|
__ aesdeclast(xmm_result, xmm_key_last); // xmm15 came from key+0
|
||||||
__ pxor (xmm_result, xmm_prev_block_cipher); // xor with the current r vector
|
__ pxor (xmm_result, xmm_prev_block_cipher); // xor with the current r vector
|
||||||
__ movdqu(Address(to, pos, Address::times_1, 0), xmm_result); // store into the next 16 bytes of output
|
__ movdqu(Address(to, pos, Address::times_1, 0), xmm_result); // store into the next 16 bytes of output
|
||||||
// no need to store r to memory until we exit
|
// no need to store r to memory until we exit
|
||||||
__ movdqa(xmm_prev_block_cipher, xmm_prev_block_cipher_save); // set up next r vector with cipher input from this block
|
__ movdqa(xmm_prev_block_cipher, xmm_prev_block_cipher_save); // set up next r vector with cipher input from this block
|
||||||
|
|
||||||
__ addptr(pos, AESBlockSize);
|
__ addptr(pos, AESBlockSize);
|
||||||
__ subptr(len_reg, AESBlockSize);
|
__ subptr(len_reg, AESBlockSize);
|
||||||
__ jcc(Assembler::notEqual,L_singleBlock_loopTop_256);
|
__ jcc(Assembler::notEqual,L_singleBlock_loopTop_256);
|
||||||
|
|
|
@ -424,8 +424,6 @@ void InterpreterGenerator::generate_counter_overflow(Label* do_continue) {
|
||||||
// C++ interpreter only
|
// C++ interpreter only
|
||||||
// rsi - previous interpreter state pointer
|
// rsi - previous interpreter state pointer
|
||||||
|
|
||||||
const Address size_of_parameters(rbx, Method::size_of_parameters_offset());
|
|
||||||
|
|
||||||
// InterpreterRuntime::frequency_counter_overflow takes one argument
|
// InterpreterRuntime::frequency_counter_overflow takes one argument
|
||||||
// indicating if the counter overflow occurs at a backwards branch (non-NULL bcp).
|
// indicating if the counter overflow occurs at a backwards branch (non-NULL bcp).
|
||||||
// The call returns the address of the verified entry point for the method or NULL
|
// The call returns the address of the verified entry point for the method or NULL
|
||||||
|
@ -868,12 +866,13 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||||
// rsi: previous interpreter state (C++ interpreter) must preserve
|
// rsi: previous interpreter state (C++ interpreter) must preserve
|
||||||
address entry_point = __ pc();
|
address entry_point = __ pc();
|
||||||
|
|
||||||
|
const Address constMethod (rbx, Method::const_offset());
|
||||||
const Address size_of_parameters(rbx, Method::size_of_parameters_offset());
|
|
||||||
const Address invocation_counter(rbx, Method::invocation_counter_offset() + InvocationCounter::counter_offset());
|
const Address invocation_counter(rbx, Method::invocation_counter_offset() + InvocationCounter::counter_offset());
|
||||||
const Address access_flags (rbx, Method::access_flags_offset());
|
const Address access_flags (rbx, Method::access_flags_offset());
|
||||||
|
const Address size_of_parameters(rcx, ConstMethod::size_of_parameters_offset());
|
||||||
|
|
||||||
// get parameter size (always needed)
|
// get parameter size (always needed)
|
||||||
|
__ movptr(rcx, constMethod);
|
||||||
__ load_unsigned_short(rcx, size_of_parameters);
|
__ load_unsigned_short(rcx, size_of_parameters);
|
||||||
|
|
||||||
// native calls don't need the stack size check since they have no expression stack
|
// native calls don't need the stack size check since they have no expression stack
|
||||||
|
@ -988,7 +987,9 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||||
|
|
||||||
// allocate space for parameters
|
// allocate space for parameters
|
||||||
__ get_method(method);
|
__ get_method(method);
|
||||||
__ load_unsigned_short(t, Address(method, Method::size_of_parameters_offset()));
|
__ movptr(t, Address(method, Method::const_offset()));
|
||||||
|
__ load_unsigned_short(t, Address(t, ConstMethod::size_of_parameters_offset()));
|
||||||
|
|
||||||
__ shlptr(t, Interpreter::logStackElementSize);
|
__ shlptr(t, Interpreter::logStackElementSize);
|
||||||
__ addptr(t, 2*wordSize); // allocate two more slots for JNIEnv and possible mirror
|
__ addptr(t, 2*wordSize); // allocate two more slots for JNIEnv and possible mirror
|
||||||
__ subptr(rsp, t);
|
__ subptr(rsp, t);
|
||||||
|
@ -1297,13 +1298,14 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) {
|
||||||
// rsi: sender sp
|
// rsi: sender sp
|
||||||
address entry_point = __ pc();
|
address entry_point = __ pc();
|
||||||
|
|
||||||
|
const Address constMethod (rbx, Method::const_offset());
|
||||||
const Address size_of_parameters(rbx, Method::size_of_parameters_offset());
|
|
||||||
const Address size_of_locals (rbx, Method::size_of_locals_offset());
|
|
||||||
const Address invocation_counter(rbx, Method::invocation_counter_offset() + InvocationCounter::counter_offset());
|
const Address invocation_counter(rbx, Method::invocation_counter_offset() + InvocationCounter::counter_offset());
|
||||||
const Address access_flags (rbx, Method::access_flags_offset());
|
const Address access_flags (rbx, Method::access_flags_offset());
|
||||||
|
const Address size_of_parameters(rdx, ConstMethod::size_of_parameters_offset());
|
||||||
|
const Address size_of_locals (rdx, ConstMethod::size_of_locals_offset());
|
||||||
|
|
||||||
// get parameter size (always needed)
|
// get parameter size (always needed)
|
||||||
|
__ movptr(rdx, constMethod);
|
||||||
__ load_unsigned_short(rcx, size_of_parameters);
|
__ load_unsigned_short(rcx, size_of_parameters);
|
||||||
|
|
||||||
// rbx,: Method*
|
// rbx,: Method*
|
||||||
|
@ -1734,7 +1736,8 @@ void TemplateInterpreterGenerator::generate_throw_exception() {
|
||||||
|
|
||||||
// Compute size of arguments for saving when returning to deoptimized caller
|
// Compute size of arguments for saving when returning to deoptimized caller
|
||||||
__ get_method(rax);
|
__ get_method(rax);
|
||||||
__ load_unsigned_short(rax, Address(rax, in_bytes(Method::size_of_parameters_offset())));
|
__ movptr(rax, Address(rax, Method::const_offset()));
|
||||||
|
__ load_unsigned_short(rax, Address(rax, ConstMethod::size_of_parameters_offset()));
|
||||||
__ shlptr(rax, Interpreter::logStackElementSize);
|
__ shlptr(rax, Interpreter::logStackElementSize);
|
||||||
__ restore_locals();
|
__ restore_locals();
|
||||||
__ subptr(rdi, rax);
|
__ subptr(rdi, rax);
|
||||||
|
|
|
@ -369,9 +369,6 @@ void InterpreterGenerator::generate_counter_overflow(Label* do_continue) {
|
||||||
// Everything as it was on entry
|
// Everything as it was on entry
|
||||||
// rdx is not restored. Doesn't appear to really be set.
|
// rdx is not restored. Doesn't appear to really be set.
|
||||||
|
|
||||||
const Address size_of_parameters(rbx,
|
|
||||||
Method::size_of_parameters_offset());
|
|
||||||
|
|
||||||
// InterpreterRuntime::frequency_counter_overflow takes two
|
// InterpreterRuntime::frequency_counter_overflow takes two
|
||||||
// arguments, the first (thread) is passed by call_VM, the second
|
// arguments, the first (thread) is passed by call_VM, the second
|
||||||
// indicates if the counter overflow occurs at a backwards branch
|
// indicates if the counter overflow occurs at a backwards branch
|
||||||
|
@ -844,14 +841,17 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||||
|
|
||||||
address entry_point = __ pc();
|
address entry_point = __ pc();
|
||||||
|
|
||||||
const Address size_of_parameters(rbx, Method::
|
const Address constMethod (rbx, Method::const_offset());
|
||||||
size_of_parameters_offset());
|
|
||||||
const Address invocation_counter(rbx, Method::
|
const Address invocation_counter(rbx, Method::
|
||||||
invocation_counter_offset() +
|
invocation_counter_offset() +
|
||||||
InvocationCounter::counter_offset());
|
InvocationCounter::counter_offset());
|
||||||
const Address access_flags (rbx, Method::access_flags_offset());
|
const Address access_flags (rbx, Method::access_flags_offset());
|
||||||
|
const Address size_of_parameters(rcx, ConstMethod::
|
||||||
|
size_of_parameters_offset());
|
||||||
|
|
||||||
|
|
||||||
// get parameter size (always needed)
|
// get parameter size (always needed)
|
||||||
|
__ movptr(rcx, constMethod);
|
||||||
__ load_unsigned_short(rcx, size_of_parameters);
|
__ load_unsigned_short(rcx, size_of_parameters);
|
||||||
|
|
||||||
// native calls don't need the stack size check since they have no
|
// native calls don't need the stack size check since they have no
|
||||||
|
@ -967,9 +967,8 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||||
|
|
||||||
// allocate space for parameters
|
// allocate space for parameters
|
||||||
__ get_method(method);
|
__ get_method(method);
|
||||||
__ load_unsigned_short(t,
|
__ movptr(t, Address(method, Method::const_offset()));
|
||||||
Address(method,
|
__ load_unsigned_short(t, Address(t, ConstMethod::size_of_parameters_offset()));
|
||||||
Method::size_of_parameters_offset()));
|
|
||||||
__ shll(t, Interpreter::logStackElementSize);
|
__ shll(t, Interpreter::logStackElementSize);
|
||||||
|
|
||||||
__ subptr(rsp, t);
|
__ subptr(rsp, t);
|
||||||
|
@ -1302,15 +1301,18 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) {
|
||||||
// r13: sender sp
|
// r13: sender sp
|
||||||
address entry_point = __ pc();
|
address entry_point = __ pc();
|
||||||
|
|
||||||
const Address size_of_parameters(rbx,
|
const Address constMethod(rbx, Method::const_offset());
|
||||||
Method::size_of_parameters_offset());
|
|
||||||
const Address size_of_locals(rbx, Method::size_of_locals_offset());
|
|
||||||
const Address invocation_counter(rbx,
|
const Address invocation_counter(rbx,
|
||||||
Method::invocation_counter_offset() +
|
Method::invocation_counter_offset() +
|
||||||
InvocationCounter::counter_offset());
|
InvocationCounter::counter_offset());
|
||||||
const Address access_flags(rbx, Method::access_flags_offset());
|
const Address access_flags(rbx, Method::access_flags_offset());
|
||||||
|
const Address size_of_parameters(rdx,
|
||||||
|
ConstMethod::size_of_parameters_offset());
|
||||||
|
const Address size_of_locals(rdx, ConstMethod::size_of_locals_offset());
|
||||||
|
|
||||||
|
|
||||||
// get parameter size (always needed)
|
// get parameter size (always needed)
|
||||||
|
__ movptr(rdx, constMethod);
|
||||||
__ load_unsigned_short(rcx, size_of_parameters);
|
__ load_unsigned_short(rcx, size_of_parameters);
|
||||||
|
|
||||||
// rbx: Method*
|
// rbx: Method*
|
||||||
|
@ -1752,7 +1754,8 @@ void TemplateInterpreterGenerator::generate_throw_exception() {
|
||||||
// Compute size of arguments for saving when returning to
|
// Compute size of arguments for saving when returning to
|
||||||
// deoptimized caller
|
// deoptimized caller
|
||||||
__ get_method(rax);
|
__ get_method(rax);
|
||||||
__ load_unsigned_short(rax, Address(rax, in_bytes(Method::
|
__ movptr(rax, Address(rax, Method::const_offset()));
|
||||||
|
__ load_unsigned_short(rax, Address(rax, in_bytes(ConstMethod::
|
||||||
size_of_parameters_offset())));
|
size_of_parameters_offset())));
|
||||||
__ shll(rax, Interpreter::logStackElementSize);
|
__ shll(rax, Interpreter::logStackElementSize);
|
||||||
__ restore_locals(); // XXX do we need this?
|
__ restore_locals(); // XXX do we need this?
|
||||||
|
|
|
@ -489,8 +489,8 @@ void VM_Version::get_processor_features() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// The AES intrinsic stubs require AES instruction support (of course)
|
// The AES intrinsic stubs require AES instruction support (of course)
|
||||||
// but also require AVX and sse3 modes for instructions it use.
|
// but also require sse3 mode for instructions it use.
|
||||||
if (UseAES && (UseAVX > 0) && (UseSSE > 2)) {
|
if (UseAES && (UseSSE > 2)) {
|
||||||
if (FLAG_IS_DEFAULT(UseAESIntrinsics)) {
|
if (FLAG_IS_DEFAULT(UseAESIntrinsics)) {
|
||||||
UseAESIntrinsics = true;
|
UseAESIntrinsics = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,15 +56,9 @@ void Assembler::pd_patch_instruction(address branch, address target) {
|
||||||
ShouldNotCallThis();
|
ShouldNotCallThis();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef PRODUCT
|
|
||||||
void Assembler::pd_print_patched_instruction(address branch) {
|
|
||||||
ShouldNotCallThis();
|
|
||||||
}
|
|
||||||
#endif // PRODUCT
|
|
||||||
|
|
||||||
void MacroAssembler::align(int modulus) {
|
void MacroAssembler::align(int modulus) {
|
||||||
while (offset() % modulus != 0)
|
while (offset() % modulus != 0)
|
||||||
emit_byte(AbstractAssembler::code_fill_byte());
|
emit_int8(AbstractAssembler::code_fill_byte());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroAssembler::bang_stack_with_offset(int offset) {
|
void MacroAssembler::bang_stack_with_offset(int offset) {
|
||||||
|
@ -72,8 +66,7 @@ void MacroAssembler::bang_stack_with_offset(int offset) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroAssembler::advance(int bytes) {
|
void MacroAssembler::advance(int bytes) {
|
||||||
_code_pos += bytes;
|
code_section()->set_end(code_section()->end() + bytes);
|
||||||
sync();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RegisterOrConstant MacroAssembler::delayed_value_impl(
|
RegisterOrConstant MacroAssembler::delayed_value_impl(
|
||||||
|
|
|
@ -37,9 +37,6 @@ class Assembler : public AbstractAssembler {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void pd_patch_instruction(address branch, address target);
|
void pd_patch_instruction(address branch, address target);
|
||||||
#ifndef PRODUCT
|
|
||||||
static void pd_print_patched_instruction(address branch);
|
|
||||||
#endif // PRODUCT
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class MacroAssembler : public Assembler {
|
class MacroAssembler : public Assembler {
|
||||||
|
|
|
@ -93,6 +93,47 @@ void os::wait_for_keypress_at_exit(void) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Multiple threads can race in this code, and can remap over each other with MAP_FIXED,
|
||||||
|
// so on posix, unmap the section at the start and at the end of the chunk that we mapped
|
||||||
|
// rather than unmapping and remapping the whole chunk to get requested alignment.
|
||||||
|
char* os::reserve_memory_aligned(size_t size, size_t alignment) {
|
||||||
|
assert((alignment & (os::vm_allocation_granularity() - 1)) == 0,
|
||||||
|
"Alignment must be a multiple of allocation granularity (page size)");
|
||||||
|
assert((size & (alignment -1)) == 0, "size must be 'alignment' aligned");
|
||||||
|
|
||||||
|
size_t extra_size = size + alignment;
|
||||||
|
assert(extra_size >= size, "overflow, size is too large to allow alignment");
|
||||||
|
|
||||||
|
char* extra_base = os::reserve_memory(extra_size, NULL, alignment);
|
||||||
|
|
||||||
|
if (extra_base == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do manual alignment
|
||||||
|
char* aligned_base = (char*) align_size_up((uintptr_t) extra_base, alignment);
|
||||||
|
|
||||||
|
// [ | | ]
|
||||||
|
// ^ extra_base
|
||||||
|
// ^ extra_base + begin_offset == aligned_base
|
||||||
|
// extra_base + begin_offset + size ^
|
||||||
|
// extra_base + extra_size ^
|
||||||
|
// |<>| == begin_offset
|
||||||
|
// end_offset == |<>|
|
||||||
|
size_t begin_offset = aligned_base - extra_base;
|
||||||
|
size_t end_offset = (extra_base + extra_size) - (aligned_base + size);
|
||||||
|
|
||||||
|
if (begin_offset > 0) {
|
||||||
|
os::release_memory(extra_base, begin_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end_offset > 0) {
|
||||||
|
os::release_memory(extra_base + begin_offset + size, end_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
return aligned_base;
|
||||||
|
}
|
||||||
|
|
||||||
void os::Posix::print_load_average(outputStream* st) {
|
void os::Posix::print_load_average(outputStream* st) {
|
||||||
st->print("load average:");
|
st->print("load average:");
|
||||||
double loadavg[3];
|
double loadavg[3];
|
||||||
|
|
|
@ -2895,6 +2895,36 @@ void os::pd_split_reserved_memory(char *base, size_t size, size_t split,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Multiple threads can race in this code but it's not possible to unmap small sections of
|
||||||
|
// virtual space to get requested alignment, like posix-like os's.
|
||||||
|
// Windows prevents multiple thread from remapping over each other so this loop is thread-safe.
|
||||||
|
char* os::reserve_memory_aligned(size_t size, size_t alignment) {
|
||||||
|
assert((alignment & (os::vm_allocation_granularity() - 1)) == 0,
|
||||||
|
"Alignment must be a multiple of allocation granularity (page size)");
|
||||||
|
assert((size & (alignment -1)) == 0, "size must be 'alignment' aligned");
|
||||||
|
|
||||||
|
size_t extra_size = size + alignment;
|
||||||
|
assert(extra_size >= size, "overflow, size is too large to allow alignment");
|
||||||
|
|
||||||
|
char* aligned_base = NULL;
|
||||||
|
|
||||||
|
do {
|
||||||
|
char* extra_base = os::reserve_memory(extra_size, NULL, alignment);
|
||||||
|
if (extra_base == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
// Do manual alignment
|
||||||
|
aligned_base = (char*) align_size_up((uintptr_t) extra_base, alignment);
|
||||||
|
|
||||||
|
os::release_memory(extra_base, extra_size);
|
||||||
|
|
||||||
|
aligned_base = os::reserve_memory(size, aligned_base);
|
||||||
|
|
||||||
|
} while (aligned_base == NULL);
|
||||||
|
|
||||||
|
return aligned_base;
|
||||||
|
}
|
||||||
|
|
||||||
char* os::pd_reserve_memory(size_t bytes, char* addr, size_t alignment_hint) {
|
char* os::pd_reserve_memory(size_t bytes, char* addr, size_t alignment_hint) {
|
||||||
assert((size_t)addr % os::vm_allocation_granularity() == 0,
|
assert((size_t)addr % os::vm_allocation_granularity() == 0,
|
||||||
"reserve alignment");
|
"reserve alignment");
|
||||||
|
|
|
@ -116,7 +116,7 @@ void MacroAssembler::get_thread(Register thread) {
|
||||||
ThreadLocalStorage::pd_tlsAccessMode tlsMode = ThreadLocalStorage::pd_getTlsAccessMode ();
|
ThreadLocalStorage::pd_tlsAccessMode tlsMode = ThreadLocalStorage::pd_getTlsAccessMode ();
|
||||||
if (tlsMode == ThreadLocalStorage::pd_tlsAccessIndirect) { // T1
|
if (tlsMode == ThreadLocalStorage::pd_tlsAccessIndirect) { // T1
|
||||||
// Use thread as a temporary: mov r, gs:[0]; mov r, [r+tlsOffset]
|
// Use thread as a temporary: mov r, gs:[0]; mov r, [r+tlsOffset]
|
||||||
emit_byte (segment);
|
emit_int8 (segment);
|
||||||
// ExternalAddress doesn't work because it can't take NULL
|
// ExternalAddress doesn't work because it can't take NULL
|
||||||
AddressLiteral null(0, relocInfo::none);
|
AddressLiteral null(0, relocInfo::none);
|
||||||
movptr (thread, null);
|
movptr (thread, null);
|
||||||
|
@ -125,7 +125,7 @@ void MacroAssembler::get_thread(Register thread) {
|
||||||
} else
|
} else
|
||||||
if (tlsMode == ThreadLocalStorage::pd_tlsAccessDirect) { // T2
|
if (tlsMode == ThreadLocalStorage::pd_tlsAccessDirect) { // T2
|
||||||
// mov r, gs:[tlsOffset]
|
// mov r, gs:[tlsOffset]
|
||||||
emit_byte (segment);
|
emit_int8 (segment);
|
||||||
AddressLiteral tls_off((address)ThreadLocalStorage::pd_getTlsOffset(), relocInfo::none);
|
AddressLiteral tls_off((address)ThreadLocalStorage::pd_getTlsOffset(), relocInfo::none);
|
||||||
movptr (thread, tls_off);
|
movptr (thread, tls_off);
|
||||||
return ;
|
return ;
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
|
|
||||||
void MacroAssembler::int3() {
|
void MacroAssembler::int3() {
|
||||||
emit_byte(0xCC);
|
emit_int8((unsigned char)0xCC);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef _LP64
|
#ifndef _LP64
|
||||||
|
|
|
@ -109,37 +109,6 @@ void AbstractAssembler::flush() {
|
||||||
ICache::invalidate_range(addr_at(0), offset());
|
ICache::invalidate_range(addr_at(0), offset());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void AbstractAssembler::a_byte(int x) {
|
|
||||||
emit_byte(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void AbstractAssembler::a_long(jint x) {
|
|
||||||
emit_long(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Labels refer to positions in the (to be) generated code. There are bound
|
|
||||||
// and unbound
|
|
||||||
//
|
|
||||||
// Bound labels refer to known positions in the already generated code.
|
|
||||||
// offset() is the position the label refers to.
|
|
||||||
//
|
|
||||||
// Unbound labels refer to unknown positions in the code to be generated; it
|
|
||||||
// may contain a list of unresolved displacements that refer to it
|
|
||||||
#ifndef PRODUCT
|
|
||||||
void AbstractAssembler::print(Label& L) {
|
|
||||||
if (L.is_bound()) {
|
|
||||||
tty->print_cr("bound label to %d|%d", L.loc_pos(), L.loc_sect());
|
|
||||||
} else if (L.is_unbound()) {
|
|
||||||
L.print_instructions((MacroAssembler*)this);
|
|
||||||
} else {
|
|
||||||
tty->print_cr("label in inconsistent state (loc = %d)", L.loc());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // PRODUCT
|
|
||||||
|
|
||||||
|
|
||||||
void AbstractAssembler::bind(Label& L) {
|
void AbstractAssembler::bind(Label& L) {
|
||||||
if (L.is_bound()) {
|
if (L.is_bound()) {
|
||||||
// Assembler can bind a label more than once to the same place.
|
// Assembler can bind a label more than once to the same place.
|
||||||
|
@ -342,28 +311,3 @@ bool MacroAssembler::needs_explicit_null_check(intptr_t offset) {
|
||||||
#endif
|
#endif
|
||||||
return offset < 0 || os::vm_page_size() <= offset;
|
return offset < 0 || os::vm_page_size() <= offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef PRODUCT
|
|
||||||
void Label::print_instructions(MacroAssembler* masm) const {
|
|
||||||
CodeBuffer* cb = masm->code();
|
|
||||||
for (int i = 0; i < _patch_index; ++i) {
|
|
||||||
int branch_loc;
|
|
||||||
if (i >= PatchCacheSize) {
|
|
||||||
branch_loc = _patch_overflow->at(i - PatchCacheSize);
|
|
||||||
} else {
|
|
||||||
branch_loc = _patches[i];
|
|
||||||
}
|
|
||||||
int branch_pos = CodeBuffer::locator_pos(branch_loc);
|
|
||||||
int branch_sect = CodeBuffer::locator_sect(branch_loc);
|
|
||||||
address branch = cb->locator_address(branch_loc);
|
|
||||||
tty->print_cr("unbound label");
|
|
||||||
tty->print("@ %d|%d ", branch_pos, branch_sect);
|
|
||||||
if (branch_sect == CodeBuffer::SECT_CONSTS) {
|
|
||||||
tty->print_cr(PTR_FORMAT, *(address*)branch);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
masm->pd_print_patched_instruction(branch);
|
|
||||||
tty->cr();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // ndef PRODUCT
|
|
||||||
|
|
|
@ -216,17 +216,6 @@ class AbstractAssembler : public ResourceObj {
|
||||||
bool isByte(int x) const { return 0 <= x && x < 0x100; }
|
bool isByte(int x) const { return 0 <= x && x < 0x100; }
|
||||||
bool isShiftCount(int x) const { return 0 <= x && x < 32; }
|
bool isShiftCount(int x) const { return 0 <= x && x < 32; }
|
||||||
|
|
||||||
void emit_int8( int8_t x) { code_section()->emit_int8( x); }
|
|
||||||
void emit_int16( int16_t x) { code_section()->emit_int16( x); }
|
|
||||||
void emit_int32( int32_t x) { code_section()->emit_int32( x); }
|
|
||||||
void emit_int64( int64_t x) { code_section()->emit_int64( x); }
|
|
||||||
|
|
||||||
void emit_float( jfloat x) { code_section()->emit_float( x); }
|
|
||||||
void emit_double( jdouble x) { code_section()->emit_double( x); }
|
|
||||||
void emit_address(address x) { code_section()->emit_address(x); }
|
|
||||||
|
|
||||||
void emit_byte(int x) { emit_int8 (x); } // deprecated
|
|
||||||
void emit_word(int x) { emit_int16(x); } // deprecated
|
|
||||||
void emit_long(jint x) { emit_int32(x); } // deprecated
|
void emit_long(jint x) { emit_int32(x); } // deprecated
|
||||||
|
|
||||||
// Instruction boundaries (required when emitting relocatable values).
|
// Instruction boundaries (required when emitting relocatable values).
|
||||||
|
@ -277,9 +266,6 @@ class AbstractAssembler : public ResourceObj {
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Label functions
|
|
||||||
void print(Label& L);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// Creation
|
// Creation
|
||||||
|
@ -288,6 +274,15 @@ class AbstractAssembler : public ResourceObj {
|
||||||
// ensure buf contains all code (call this before using/copying the code)
|
// ensure buf contains all code (call this before using/copying the code)
|
||||||
void flush();
|
void flush();
|
||||||
|
|
||||||
|
void emit_int8( int8_t x) { code_section()->emit_int8( x); }
|
||||||
|
void emit_int16( int16_t x) { code_section()->emit_int16( x); }
|
||||||
|
void emit_int32( int32_t x) { code_section()->emit_int32( x); }
|
||||||
|
void emit_int64( int64_t x) { code_section()->emit_int64( x); }
|
||||||
|
|
||||||
|
void emit_float( jfloat x) { code_section()->emit_float( x); }
|
||||||
|
void emit_double( jdouble x) { code_section()->emit_double( x); }
|
||||||
|
void emit_address(address x) { code_section()->emit_address(x); }
|
||||||
|
|
||||||
// min and max values for signed immediate ranges
|
// min and max values for signed immediate ranges
|
||||||
static int min_simm(int nbits) { return -(intptr_t(1) << (nbits - 1)) ; }
|
static int min_simm(int nbits) { return -(intptr_t(1) << (nbits - 1)) ; }
|
||||||
static int max_simm(int nbits) { return (intptr_t(1) << (nbits - 1)) - 1; }
|
static int max_simm(int nbits) { return (intptr_t(1) << (nbits - 1)) - 1; }
|
||||||
|
@ -327,8 +322,6 @@ class AbstractAssembler : public ResourceObj {
|
||||||
void clear_inst_mark() { code_section()->clear_mark(); }
|
void clear_inst_mark() { code_section()->clear_mark(); }
|
||||||
|
|
||||||
// Constants in code
|
// Constants in code
|
||||||
void a_byte(int x);
|
|
||||||
void a_long(jint x);
|
|
||||||
void relocate(RelocationHolder const& rspec, int format = 0) {
|
void relocate(RelocationHolder const& rspec, int format = 0) {
|
||||||
assert(!pd_check_instruction_mark()
|
assert(!pd_check_instruction_mark()
|
||||||
|| inst_mark() == NULL || inst_mark() == code_section()->end(),
|
|| inst_mark() == NULL || inst_mark() == code_section()->end(),
|
||||||
|
@ -441,15 +434,6 @@ class AbstractAssembler : public ResourceObj {
|
||||||
*/
|
*/
|
||||||
void pd_patch_instruction(address branch, address target);
|
void pd_patch_instruction(address branch, address target);
|
||||||
|
|
||||||
#ifndef PRODUCT
|
|
||||||
/**
|
|
||||||
* Platform-dependent method of printing an instruction that needs to be
|
|
||||||
* patched.
|
|
||||||
*
|
|
||||||
* @param branch the instruction to be patched in the buffer.
|
|
||||||
*/
|
|
||||||
static void pd_print_patched_instruction(address branch);
|
|
||||||
#endif // PRODUCT
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef TARGET_ARCH_x86
|
#ifdef TARGET_ARCH_x86
|
||||||
|
|
|
@ -3442,6 +3442,11 @@ bool GraphBuilder::try_inline_intrinsics(ciMethod* callee) {
|
||||||
preserves_state = true;
|
preserves_state = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case vmIntrinsics::_loadFence :
|
||||||
|
case vmIntrinsics::_storeFence:
|
||||||
|
case vmIntrinsics::_fullFence :
|
||||||
|
break;
|
||||||
|
|
||||||
default : return false; // do not inline
|
default : return false; // do not inline
|
||||||
}
|
}
|
||||||
// create intrinsic node
|
// create intrinsic node
|
||||||
|
|
|
@ -2977,6 +2977,16 @@ void LIRGenerator::do_Intrinsic(Intrinsic* x) {
|
||||||
do_CompareAndSwap(x, longType);
|
do_CompareAndSwap(x, longType);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case vmIntrinsics::_loadFence :
|
||||||
|
if (os::is_MP()) __ membar_acquire();
|
||||||
|
break;
|
||||||
|
case vmIntrinsics::_storeFence:
|
||||||
|
if (os::is_MP()) __ membar_release();
|
||||||
|
break;
|
||||||
|
case vmIntrinsics::_fullFence :
|
||||||
|
if (os::is_MP()) __ membar();
|
||||||
|
break;
|
||||||
|
|
||||||
case vmIntrinsics::_Reference_get:
|
case vmIntrinsics::_Reference_get:
|
||||||
do_Reference_get(x);
|
do_Reference_get(x);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -366,10 +366,12 @@ bool ciField::will_link(ciInstanceKlass* accessing_klass,
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// ciField::print
|
// ciField::print
|
||||||
void ciField::print() {
|
void ciField::print() {
|
||||||
tty->print("<ciField ");
|
tty->print("<ciField name=");
|
||||||
_holder->print_name();
|
_holder->print_name();
|
||||||
tty->print(".");
|
tty->print(".");
|
||||||
_name->print_symbol();
|
_name->print_symbol();
|
||||||
|
tty->print(" signature=");
|
||||||
|
_signature->print_symbol();
|
||||||
tty->print(" offset=%d type=", _offset);
|
tty->print(" offset=%d type=", _offset);
|
||||||
if (_type != NULL) _type->print_name();
|
if (_type != NULL) _type->print_name();
|
||||||
else tty->print("(reference)");
|
else tty->print("(reference)");
|
||||||
|
|
|
@ -169,16 +169,18 @@ void ClassLoaderData::add_dependency(Handle dependency, TRAPS) {
|
||||||
ok = (objArrayOop)ok->obj_at(1);
|
ok = (objArrayOop)ok->obj_at(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Must handle over GC points
|
||||||
|
assert (last != NULL, "dependencies should be initialized");
|
||||||
|
objArrayHandle last_handle(THREAD, last);
|
||||||
|
|
||||||
// Create a new dependency node with fields for (class_loader or mirror, next)
|
// Create a new dependency node with fields for (class_loader or mirror, next)
|
||||||
objArrayOop deps = oopFactory::new_objectArray(2, CHECK);
|
objArrayOop deps = oopFactory::new_objectArray(2, CHECK);
|
||||||
deps->obj_at_put(0, dependency());
|
deps->obj_at_put(0, dependency());
|
||||||
|
|
||||||
// Must handle over more GC points
|
// Must handle over GC points
|
||||||
objArrayHandle new_dependency(THREAD, deps);
|
objArrayHandle new_dependency(THREAD, deps);
|
||||||
|
|
||||||
// Add the dependency under lock
|
// Add the dependency under lock
|
||||||
assert (last != NULL, "dependencies should be initialized");
|
|
||||||
objArrayHandle last_handle(THREAD, last);
|
|
||||||
locked_add_dependency(last_handle, new_dependency);
|
locked_add_dependency(last_handle, new_dependency);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -327,14 +327,14 @@ jchar* java_lang_String::as_unicode_string(oop java_string, int& length) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int java_lang_String::to_hash(oop java_string) {
|
unsigned int java_lang_String::hash_code(oop java_string) {
|
||||||
int length = java_lang_String::length(java_string);
|
int length = java_lang_String::length(java_string);
|
||||||
// Zero length string will hash to zero with String.toHash() function.
|
// Zero length string will hash to zero with String.hashCode() function.
|
||||||
if (length == 0) return 0;
|
if (length == 0) return 0;
|
||||||
|
|
||||||
typeArrayOop value = java_lang_String::value(java_string);
|
typeArrayOop value = java_lang_String::value(java_string);
|
||||||
int offset = java_lang_String::offset(java_string);
|
int offset = java_lang_String::offset(java_string);
|
||||||
return java_lang_String::to_hash(value->char_at_addr(offset), length);
|
return java_lang_String::hash_code(value->char_at_addr(offset), length);
|
||||||
}
|
}
|
||||||
|
|
||||||
char* java_lang_String::as_quoted_ascii(oop java_string) {
|
char* java_lang_String::as_quoted_ascii(oop java_string) {
|
||||||
|
|
|
@ -166,8 +166,8 @@ class java_lang_String : AllStatic {
|
||||||
// objects in the shared archive file.
|
// objects in the shared archive file.
|
||||||
// hash P(31) from Kernighan & Ritchie
|
// hash P(31) from Kernighan & Ritchie
|
||||||
//
|
//
|
||||||
// For this reason, THIS ALGORITHM MUST MATCH String.toHash().
|
// For this reason, THIS ALGORITHM MUST MATCH String.hashCode().
|
||||||
template <typename T> static unsigned int to_hash(T* s, int len) {
|
template <typename T> static unsigned int hash_code(T* s, int len) {
|
||||||
unsigned int h = 0;
|
unsigned int h = 0;
|
||||||
while (len-- > 0) {
|
while (len-- > 0) {
|
||||||
h = 31*h + (unsigned int) *s;
|
h = 31*h + (unsigned int) *s;
|
||||||
|
@ -175,10 +175,10 @@ class java_lang_String : AllStatic {
|
||||||
}
|
}
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
static unsigned int to_hash(oop java_string);
|
static unsigned int hash_code(oop java_string);
|
||||||
|
|
||||||
// This is the string hash code used by the StringTable, which may be
|
// This is the string hash code used by the StringTable, which may be
|
||||||
// the same as String.toHash or an alternate hash code.
|
// the same as String.hashCode or an alternate hash code.
|
||||||
static unsigned int hash_string(oop java_string);
|
static unsigned int hash_string(oop java_string);
|
||||||
|
|
||||||
static bool equals(oop java_string, jchar* chars, int len);
|
static bool equals(oop java_string, jchar* chars, int len);
|
||||||
|
|
|
@ -179,7 +179,7 @@ Symbol* SymbolTable::lookup(int index, const char* name,
|
||||||
unsigned int SymbolTable::hash_symbol(const char* s, int len) {
|
unsigned int SymbolTable::hash_symbol(const char* s, int len) {
|
||||||
return use_alternate_hashcode() ?
|
return use_alternate_hashcode() ?
|
||||||
AltHashing::murmur3_32(seed(), (const jbyte*)s, len) :
|
AltHashing::murmur3_32(seed(), (const jbyte*)s, len) :
|
||||||
java_lang_String::to_hash(s, len);
|
java_lang_String::hash_code(s, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -617,7 +617,7 @@ bool StringTable::_needs_rehashing = false;
|
||||||
// Pick hashing algorithm
|
// Pick hashing algorithm
|
||||||
unsigned int StringTable::hash_string(const jchar* s, int len) {
|
unsigned int StringTable::hash_string(const jchar* s, int len) {
|
||||||
return use_alternate_hashcode() ? AltHashing::murmur3_32(seed(), s, len) :
|
return use_alternate_hashcode() ? AltHashing::murmur3_32(seed(), s, len) :
|
||||||
java_lang_String::to_hash(s, len);
|
java_lang_String::hash_code(s, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
oop StringTable::lookup(int index, jchar* name,
|
oop StringTable::lookup(int index, jchar* name,
|
||||||
|
|
|
@ -761,6 +761,15 @@
|
||||||
do_intrinsic(_unpark, sun_misc_Unsafe, unpark_name, unpark_signature, F_RN) \
|
do_intrinsic(_unpark, sun_misc_Unsafe, unpark_name, unpark_signature, F_RN) \
|
||||||
do_name( unpark_name, "unpark") \
|
do_name( unpark_name, "unpark") \
|
||||||
do_alias( unpark_signature, /*(LObject;)V*/ object_void_signature) \
|
do_alias( unpark_signature, /*(LObject;)V*/ object_void_signature) \
|
||||||
|
do_intrinsic(_loadFence, sun_misc_Unsafe, loadFence_name, loadFence_signature, F_RN) \
|
||||||
|
do_name( loadFence_name, "loadFence") \
|
||||||
|
do_alias( loadFence_signature, void_method_signature) \
|
||||||
|
do_intrinsic(_storeFence, sun_misc_Unsafe, storeFence_name, storeFence_signature, F_RN) \
|
||||||
|
do_name( storeFence_name, "storeFence") \
|
||||||
|
do_alias( storeFence_signature, void_method_signature) \
|
||||||
|
do_intrinsic(_fullFence, sun_misc_Unsafe, fullFence_name, fullFence_signature, F_RN) \
|
||||||
|
do_name( fullFence_name, "fullFence") \
|
||||||
|
do_alias( fullFence_signature, void_method_signature) \
|
||||||
\
|
\
|
||||||
/* unsafe memory references (there are a lot of them...) */ \
|
/* unsafe memory references (there are a lot of them...) */ \
|
||||||
do_signature(getObject_signature, "(Ljava/lang/Object;J)Ljava/lang/Object;") \
|
do_signature(getObject_signature, "(Ljava/lang/Object;J)Ljava/lang/Object;") \
|
||||||
|
@ -902,12 +911,14 @@
|
||||||
do_intrinsic(_getAndAddLong, sun_misc_Unsafe, getAndAddLong_name, getAndAddLong_signature, F_R) \
|
do_intrinsic(_getAndAddLong, sun_misc_Unsafe, getAndAddLong_name, getAndAddLong_signature, F_R) \
|
||||||
do_name( getAndAddLong_name, "getAndAddLong") \
|
do_name( getAndAddLong_name, "getAndAddLong") \
|
||||||
do_signature(getAndAddLong_signature, "(Ljava/lang/Object;JJ)J" ) \
|
do_signature(getAndAddLong_signature, "(Ljava/lang/Object;JJ)J" ) \
|
||||||
do_intrinsic(_getAndSetInt, sun_misc_Unsafe, getAndSet_name, getAndSetInt_signature, F_R) \
|
do_intrinsic(_getAndSetInt, sun_misc_Unsafe, getAndSetInt_name, getAndSetInt_signature, F_R) \
|
||||||
do_name( getAndSet_name, "getAndSet") \
|
do_name( getAndSetInt_name, "getAndSetInt") \
|
||||||
do_alias( getAndSetInt_signature, /*"(Ljava/lang/Object;JI)I"*/ getAndAddInt_signature) \
|
do_alias( getAndSetInt_signature, /*"(Ljava/lang/Object;JI)I"*/ getAndAddInt_signature) \
|
||||||
do_intrinsic(_getAndSetLong, sun_misc_Unsafe, getAndSet_name, getAndSetLong_signature, F_R) \
|
do_intrinsic(_getAndSetLong, sun_misc_Unsafe, getAndSetLong_name, getAndSetLong_signature, F_R) \
|
||||||
|
do_name( getAndSetLong_name, "getAndSetLong") \
|
||||||
do_alias( getAndSetLong_signature, /*"(Ljava/lang/Object;JJ)J"*/ getAndAddLong_signature) \
|
do_alias( getAndSetLong_signature, /*"(Ljava/lang/Object;JJ)J"*/ getAndAddLong_signature) \
|
||||||
do_intrinsic(_getAndSetObject, sun_misc_Unsafe, getAndSet_name, getAndSetObject_signature, F_R) \
|
do_intrinsic(_getAndSetObject, sun_misc_Unsafe, getAndSetObject_name, getAndSetObject_signature, F_R)\
|
||||||
|
do_name( getAndSetObject_name, "getAndSetObject") \
|
||||||
do_signature(getAndSetObject_signature, "(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;" ) \
|
do_signature(getAndSetObject_signature, "(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;" ) \
|
||||||
\
|
\
|
||||||
/* prefetch_signature is shared by all prefetch variants */ \
|
/* prefetch_signature is shared by all prefetch variants */ \
|
||||||
|
|
|
@ -538,6 +538,7 @@ void CompilerOracle::parse_from_line(char* line) {
|
||||||
|
|
||||||
if (match != NULL) {
|
if (match != NULL) {
|
||||||
if (!_quiet) {
|
if (!_quiet) {
|
||||||
|
ResourceMark rm;
|
||||||
tty->print("CompilerOracle: %s ", command_names[command]);
|
tty->print("CompilerOracle: %s ", command_names[command]);
|
||||||
match->print();
|
match->print();
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,27 +46,11 @@
|
||||||
|
|
||||||
// Concurrent marking bit map wrapper
|
// Concurrent marking bit map wrapper
|
||||||
|
|
||||||
CMBitMapRO::CMBitMapRO(ReservedSpace rs, int shifter) :
|
CMBitMapRO::CMBitMapRO(int shifter) :
|
||||||
_bm((uintptr_t*)NULL,0),
|
_bm(),
|
||||||
_shifter(shifter) {
|
_shifter(shifter) {
|
||||||
_bmStartWord = (HeapWord*)(rs.base());
|
_bmStartWord = 0;
|
||||||
_bmWordSize = rs.size()/HeapWordSize; // rs.size() is in bytes
|
_bmWordSize = 0;
|
||||||
ReservedSpace brs(ReservedSpace::allocation_align_size_up(
|
|
||||||
(_bmWordSize >> (_shifter + LogBitsPerByte)) + 1));
|
|
||||||
|
|
||||||
MemTracker::record_virtual_memory_type((address)brs.base(), mtGC);
|
|
||||||
|
|
||||||
guarantee(brs.is_reserved(), "couldn't allocate concurrent marking bit map");
|
|
||||||
// For now we'll just commit all of the bit map up fromt.
|
|
||||||
// Later on we'll try to be more parsimonious with swap.
|
|
||||||
guarantee(_virtual_space.initialize(brs, brs.size()),
|
|
||||||
"couldn't reseve backing store for concurrent marking bit map");
|
|
||||||
assert(_virtual_space.committed_size() == brs.size(),
|
|
||||||
"didn't reserve backing store for all of concurrent marking bit map?");
|
|
||||||
_bm.set_map((uintptr_t*)_virtual_space.low());
|
|
||||||
assert(_virtual_space.committed_size() << (_shifter + LogBitsPerByte) >=
|
|
||||||
_bmWordSize, "inconsistency in bit map sizing");
|
|
||||||
_bm.set_size(_bmWordSize >> _shifter);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HeapWord* CMBitMapRO::getNextMarkedWordAddress(HeapWord* addr,
|
HeapWord* CMBitMapRO::getNextMarkedWordAddress(HeapWord* addr,
|
||||||
|
@ -108,15 +92,40 @@ int CMBitMapRO::heapWordDiffToOffsetDiff(size_t diff) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
bool CMBitMapRO::covers(ReservedSpace rs) const {
|
bool CMBitMapRO::covers(ReservedSpace heap_rs) const {
|
||||||
// assert(_bm.map() == _virtual_space.low(), "map inconsistency");
|
// assert(_bm.map() == _virtual_space.low(), "map inconsistency");
|
||||||
assert(((size_t)_bm.size() * ((size_t)1 << _shifter)) == _bmWordSize,
|
assert(((size_t)_bm.size() * ((size_t)1 << _shifter)) == _bmWordSize,
|
||||||
"size inconsistency");
|
"size inconsistency");
|
||||||
return _bmStartWord == (HeapWord*)(rs.base()) &&
|
return _bmStartWord == (HeapWord*)(heap_rs.base()) &&
|
||||||
_bmWordSize == rs.size()>>LogHeapWordSize;
|
_bmWordSize == heap_rs.size()>>LogHeapWordSize;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool CMBitMap::allocate(ReservedSpace heap_rs) {
|
||||||
|
_bmStartWord = (HeapWord*)(heap_rs.base());
|
||||||
|
_bmWordSize = heap_rs.size()/HeapWordSize; // heap_rs.size() is in bytes
|
||||||
|
ReservedSpace brs(ReservedSpace::allocation_align_size_up(
|
||||||
|
(_bmWordSize >> (_shifter + LogBitsPerByte)) + 1));
|
||||||
|
if (!brs.is_reserved()) {
|
||||||
|
warning("ConcurrentMark marking bit map allocation failure");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
MemTracker::record_virtual_memory_type((address)brs.base(), mtGC);
|
||||||
|
// For now we'll just commit all of the bit map up front.
|
||||||
|
// Later on we'll try to be more parsimonious with swap.
|
||||||
|
if (!_virtual_space.initialize(brs, brs.size())) {
|
||||||
|
warning("ConcurrentMark marking bit map backing store failure");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
assert(_virtual_space.committed_size() == brs.size(),
|
||||||
|
"didn't reserve backing store for all of concurrent marking bit map?");
|
||||||
|
_bm.set_map((uintptr_t*)_virtual_space.low());
|
||||||
|
assert(_virtual_space.committed_size() << (_shifter + LogBitsPerByte) >=
|
||||||
|
_bmWordSize, "inconsistency in bit map sizing");
|
||||||
|
_bm.set_size(_bmWordSize >> _shifter);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void CMBitMap::clearAll() {
|
void CMBitMap::clearAll() {
|
||||||
_bm.clear();
|
_bm.clear();
|
||||||
return;
|
return;
|
||||||
|
@ -163,20 +172,79 @@ CMMarkStack::CMMarkStack(ConcurrentMark* cm) :
|
||||||
#endif
|
#endif
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void CMMarkStack::allocate(size_t size) {
|
bool CMMarkStack::allocate(size_t capacity) {
|
||||||
_base = NEW_C_HEAP_ARRAY(oop, size, mtGC);
|
// allocate a stack of the requisite depth
|
||||||
if (_base == NULL) {
|
ReservedSpace rs(ReservedSpace::allocation_align_size_up(capacity * sizeof(oop)));
|
||||||
vm_exit_during_initialization("Failed to allocate CM region mark stack");
|
if (!rs.is_reserved()) {
|
||||||
|
warning("ConcurrentMark MarkStack allocation failure");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
_index = 0;
|
MemTracker::record_virtual_memory_type((address)rs.base(), mtGC);
|
||||||
_capacity = (jint) size;
|
if (!_virtual_space.initialize(rs, rs.size())) {
|
||||||
|
warning("ConcurrentMark MarkStack backing store failure");
|
||||||
|
// Release the virtual memory reserved for the marking stack
|
||||||
|
rs.release();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
assert(_virtual_space.committed_size() == rs.size(),
|
||||||
|
"Didn't reserve backing store for all of ConcurrentMark stack?");
|
||||||
|
_base = (oop*) _virtual_space.low();
|
||||||
|
setEmpty();
|
||||||
|
_capacity = (jint) capacity;
|
||||||
_saved_index = -1;
|
_saved_index = -1;
|
||||||
NOT_PRODUCT(_max_depth = 0);
|
NOT_PRODUCT(_max_depth = 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMMarkStack::expand() {
|
||||||
|
// Called, during remark, if we've overflown the marking stack during marking.
|
||||||
|
assert(isEmpty(), "stack should been emptied while handling overflow");
|
||||||
|
assert(_capacity <= (jint) MarkStackSizeMax, "stack bigger than permitted");
|
||||||
|
// Clear expansion flag
|
||||||
|
_should_expand = false;
|
||||||
|
if (_capacity == (jint) MarkStackSizeMax) {
|
||||||
|
if (PrintGCDetails && Verbose) {
|
||||||
|
gclog_or_tty->print_cr(" (benign) Can't expand marking stack capacity, at max size limit");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Double capacity if possible
|
||||||
|
jint new_capacity = MIN2(_capacity*2, (jint) MarkStackSizeMax);
|
||||||
|
// Do not give up existing stack until we have managed to
|
||||||
|
// get the double capacity that we desired.
|
||||||
|
ReservedSpace rs(ReservedSpace::allocation_align_size_up(new_capacity *
|
||||||
|
sizeof(oop)));
|
||||||
|
if (rs.is_reserved()) {
|
||||||
|
// Release the backing store associated with old stack
|
||||||
|
_virtual_space.release();
|
||||||
|
// Reinitialize virtual space for new stack
|
||||||
|
if (!_virtual_space.initialize(rs, rs.size())) {
|
||||||
|
fatal("Not enough swap for expanded marking stack capacity");
|
||||||
|
}
|
||||||
|
_base = (oop*)(_virtual_space.low());
|
||||||
|
_index = 0;
|
||||||
|
_capacity = new_capacity;
|
||||||
|
} else {
|
||||||
|
if (PrintGCDetails && Verbose) {
|
||||||
|
// Failed to double capacity, continue;
|
||||||
|
gclog_or_tty->print(" (benign) Failed to expand marking stack capacity from "
|
||||||
|
SIZE_FORMAT"K to " SIZE_FORMAT"K",
|
||||||
|
_capacity / K, new_capacity / K);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMMarkStack::set_should_expand() {
|
||||||
|
// If we're resetting the marking state because of an
|
||||||
|
// marking stack overflow, record that we should, if
|
||||||
|
// possible, expand the stack.
|
||||||
|
_should_expand = _cm->has_overflown();
|
||||||
}
|
}
|
||||||
|
|
||||||
CMMarkStack::~CMMarkStack() {
|
CMMarkStack::~CMMarkStack() {
|
||||||
if (_base != NULL) {
|
if (_base != NULL) {
|
||||||
FREE_C_HEAP_ARRAY(oop, _base, mtGC);
|
_base = NULL;
|
||||||
|
_virtual_space.release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,7 +285,7 @@ void CMMarkStack::par_adjoin_arr(oop* ptr_arr, int n) {
|
||||||
jint res = Atomic::cmpxchg(next_index, &_index, index);
|
jint res = Atomic::cmpxchg(next_index, &_index, index);
|
||||||
if (res == index) {
|
if (res == index) {
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
int ind = index + i;
|
int ind = index + i;
|
||||||
assert(ind < _capacity, "By overflow test above.");
|
assert(ind < _capacity, "By overflow test above.");
|
||||||
_base[ind] = ptr_arr[i];
|
_base[ind] = ptr_arr[i];
|
||||||
}
|
}
|
||||||
|
@ -228,7 +296,6 @@ void CMMarkStack::par_adjoin_arr(oop* ptr_arr, int n) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CMMarkStack::par_push_arr(oop* ptr_arr, int n) {
|
void CMMarkStack::par_push_arr(oop* ptr_arr, int n) {
|
||||||
MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag);
|
MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag);
|
||||||
jint start = _index;
|
jint start = _index;
|
||||||
|
@ -244,9 +311,9 @@ void CMMarkStack::par_push_arr(oop* ptr_arr, int n) {
|
||||||
assert(ind < _capacity, "By overflow test above.");
|
assert(ind < _capacity, "By overflow test above.");
|
||||||
_base[ind] = ptr_arr[i];
|
_base[ind] = ptr_arr[i];
|
||||||
}
|
}
|
||||||
|
NOT_PRODUCT(_max_depth = MAX2(_max_depth, next_index));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool CMMarkStack::par_pop_arr(oop* ptr_arr, int max, int* n) {
|
bool CMMarkStack::par_pop_arr(oop* ptr_arr, int max, int* n) {
|
||||||
MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag);
|
MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag);
|
||||||
jint index = _index;
|
jint index = _index;
|
||||||
|
@ -255,7 +322,7 @@ bool CMMarkStack::par_pop_arr(oop* ptr_arr, int max, int* n) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
int k = MIN2(max, index);
|
int k = MIN2(max, index);
|
||||||
jint new_ind = index - k;
|
jint new_ind = index - k;
|
||||||
for (int j = 0; j < k; j++) {
|
for (int j = 0; j < k; j++) {
|
||||||
ptr_arr[j] = _base[new_ind + j];
|
ptr_arr[j] = _base[new_ind + j];
|
||||||
}
|
}
|
||||||
|
@ -404,9 +471,10 @@ uint ConcurrentMark::scale_parallel_threads(uint n_par_threads) {
|
||||||
return MAX2((n_par_threads + 2) / 4, 1U);
|
return MAX2((n_par_threads + 2) / 4, 1U);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConcurrentMark::ConcurrentMark(ReservedSpace rs, uint max_regions) :
|
ConcurrentMark::ConcurrentMark(G1CollectedHeap* g1h, ReservedSpace heap_rs) :
|
||||||
_markBitMap1(rs, MinObjAlignment - 1),
|
_g1h(g1h),
|
||||||
_markBitMap2(rs, MinObjAlignment - 1),
|
_markBitMap1(MinObjAlignment - 1),
|
||||||
|
_markBitMap2(MinObjAlignment - 1),
|
||||||
|
|
||||||
_parallel_marking_threads(0),
|
_parallel_marking_threads(0),
|
||||||
_max_parallel_marking_threads(0),
|
_max_parallel_marking_threads(0),
|
||||||
|
@ -415,10 +483,10 @@ ConcurrentMark::ConcurrentMark(ReservedSpace rs, uint max_regions) :
|
||||||
_cleanup_sleep_factor(0.0),
|
_cleanup_sleep_factor(0.0),
|
||||||
_cleanup_task_overhead(1.0),
|
_cleanup_task_overhead(1.0),
|
||||||
_cleanup_list("Cleanup List"),
|
_cleanup_list("Cleanup List"),
|
||||||
_region_bm((BitMap::idx_t) max_regions, false /* in_resource_area*/),
|
_region_bm((BitMap::idx_t)(g1h->max_regions()), false /* in_resource_area*/),
|
||||||
_card_bm((rs.size() + CardTableModRefBS::card_size - 1) >>
|
_card_bm((heap_rs.size() + CardTableModRefBS::card_size - 1) >>
|
||||||
CardTableModRefBS::card_shift,
|
CardTableModRefBS::card_shift,
|
||||||
false /* in_resource_area*/),
|
false /* in_resource_area*/),
|
||||||
|
|
||||||
_prevMarkBitMap(&_markBitMap1),
|
_prevMarkBitMap(&_markBitMap1),
|
||||||
_nextMarkBitMap(&_markBitMap2),
|
_nextMarkBitMap(&_markBitMap2),
|
||||||
|
@ -449,7 +517,8 @@ ConcurrentMark::ConcurrentMark(ReservedSpace rs, uint max_regions) :
|
||||||
_parallel_workers(NULL),
|
_parallel_workers(NULL),
|
||||||
|
|
||||||
_count_card_bitmaps(NULL),
|
_count_card_bitmaps(NULL),
|
||||||
_count_marked_bytes(NULL) {
|
_count_marked_bytes(NULL),
|
||||||
|
_completed_initialization(false) {
|
||||||
CMVerboseLevel verbose_level = (CMVerboseLevel) G1MarkingVerboseLevel;
|
CMVerboseLevel verbose_level = (CMVerboseLevel) G1MarkingVerboseLevel;
|
||||||
if (verbose_level < no_verbose) {
|
if (verbose_level < no_verbose) {
|
||||||
verbose_level = no_verbose;
|
verbose_level = no_verbose;
|
||||||
|
@ -464,61 +533,34 @@ ConcurrentMark::ConcurrentMark(ReservedSpace rs, uint max_regions) :
|
||||||
"heap end = "PTR_FORMAT, _heap_start, _heap_end);
|
"heap end = "PTR_FORMAT, _heap_start, _heap_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
_markStack.allocate(MarkStackSize);
|
if (!_markBitMap1.allocate(heap_rs)) {
|
||||||
|
warning("Failed to allocate first CM bit map");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!_markBitMap2.allocate(heap_rs)) {
|
||||||
|
warning("Failed to allocate second CM bit map");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Create & start a ConcurrentMark thread.
|
// Create & start a ConcurrentMark thread.
|
||||||
_cmThread = new ConcurrentMarkThread(this);
|
_cmThread = new ConcurrentMarkThread(this);
|
||||||
assert(cmThread() != NULL, "CM Thread should have been created");
|
assert(cmThread() != NULL, "CM Thread should have been created");
|
||||||
assert(cmThread()->cm() != NULL, "CM Thread should refer to this cm");
|
assert(cmThread()->cm() != NULL, "CM Thread should refer to this cm");
|
||||||
|
|
||||||
_g1h = G1CollectedHeap::heap();
|
|
||||||
assert(CGC_lock != NULL, "Where's the CGC_lock?");
|
assert(CGC_lock != NULL, "Where's the CGC_lock?");
|
||||||
assert(_markBitMap1.covers(rs), "_markBitMap1 inconsistency");
|
assert(_markBitMap1.covers(heap_rs), "_markBitMap1 inconsistency");
|
||||||
assert(_markBitMap2.covers(rs), "_markBitMap2 inconsistency");
|
assert(_markBitMap2.covers(heap_rs), "_markBitMap2 inconsistency");
|
||||||
|
|
||||||
SATBMarkQueueSet& satb_qs = JavaThread::satb_mark_queue_set();
|
SATBMarkQueueSet& satb_qs = JavaThread::satb_mark_queue_set();
|
||||||
satb_qs.set_buffer_size(G1SATBBufferSize);
|
satb_qs.set_buffer_size(G1SATBBufferSize);
|
||||||
|
|
||||||
_root_regions.init(_g1h, this);
|
_root_regions.init(_g1h, this);
|
||||||
|
|
||||||
_tasks = NEW_C_HEAP_ARRAY(CMTask*, _max_worker_id, mtGC);
|
|
||||||
_accum_task_vtime = NEW_C_HEAP_ARRAY(double, _max_worker_id, mtGC);
|
|
||||||
|
|
||||||
_count_card_bitmaps = NEW_C_HEAP_ARRAY(BitMap, _max_worker_id, mtGC);
|
|
||||||
_count_marked_bytes = NEW_C_HEAP_ARRAY(size_t*, _max_worker_id, mtGC);
|
|
||||||
|
|
||||||
BitMap::idx_t card_bm_size = _card_bm.size();
|
|
||||||
|
|
||||||
// so that the assertion in MarkingTaskQueue::task_queue doesn't fail
|
|
||||||
_active_tasks = _max_worker_id;
|
|
||||||
for (uint i = 0; i < _max_worker_id; ++i) {
|
|
||||||
CMTaskQueue* task_queue = new CMTaskQueue();
|
|
||||||
task_queue->initialize();
|
|
||||||
_task_queues->register_queue(i, task_queue);
|
|
||||||
|
|
||||||
_count_card_bitmaps[i] = BitMap(card_bm_size, false);
|
|
||||||
_count_marked_bytes[i] = NEW_C_HEAP_ARRAY(size_t, (size_t) max_regions, mtGC);
|
|
||||||
|
|
||||||
_tasks[i] = new CMTask(i, this,
|
|
||||||
_count_marked_bytes[i],
|
|
||||||
&_count_card_bitmaps[i],
|
|
||||||
task_queue, _task_queues);
|
|
||||||
|
|
||||||
_accum_task_vtime[i] = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate the card number for the bottom of the heap. Used
|
|
||||||
// in biasing indexes into the accounting card bitmaps.
|
|
||||||
_heap_bottom_card_num =
|
|
||||||
intptr_t(uintptr_t(_g1h->reserved_region().start()) >>
|
|
||||||
CardTableModRefBS::card_shift);
|
|
||||||
|
|
||||||
// Clear all the liveness counting data
|
|
||||||
clear_all_count_data();
|
|
||||||
|
|
||||||
if (ConcGCThreads > ParallelGCThreads) {
|
if (ConcGCThreads > ParallelGCThreads) {
|
||||||
vm_exit_during_initialization("Can't have more ConcGCThreads "
|
warning("Can't have more ConcGCThreads (" UINT32_FORMAT ") "
|
||||||
"than ParallelGCThreads.");
|
"than ParallelGCThreads (" UINT32_FORMAT ").",
|
||||||
|
ConcGCThreads, ParallelGCThreads);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (ParallelGCThreads == 0) {
|
if (ParallelGCThreads == 0) {
|
||||||
// if we are not running with any parallel GC threads we will not
|
// if we are not running with any parallel GC threads we will not
|
||||||
|
@ -590,9 +632,86 @@ ConcurrentMark::ConcurrentMark(ReservedSpace rs, uint max_regions) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (FLAG_IS_DEFAULT(MarkStackSize)) {
|
||||||
|
uintx mark_stack_size =
|
||||||
|
MIN2(MarkStackSizeMax,
|
||||||
|
MAX2(MarkStackSize, (uintx) (parallel_marking_threads() * TASKQUEUE_SIZE)));
|
||||||
|
// Verify that the calculated value for MarkStackSize is in range.
|
||||||
|
// It would be nice to use the private utility routine from Arguments.
|
||||||
|
if (!(mark_stack_size >= 1 && mark_stack_size <= MarkStackSizeMax)) {
|
||||||
|
warning("Invalid value calculated for MarkStackSize (" UINTX_FORMAT "): "
|
||||||
|
"must be between " UINTX_FORMAT " and " UINTX_FORMAT,
|
||||||
|
mark_stack_size, 1, MarkStackSizeMax);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
FLAG_SET_ERGO(uintx, MarkStackSize, mark_stack_size);
|
||||||
|
} else {
|
||||||
|
// Verify MarkStackSize is in range.
|
||||||
|
if (FLAG_IS_CMDLINE(MarkStackSize)) {
|
||||||
|
if (FLAG_IS_DEFAULT(MarkStackSizeMax)) {
|
||||||
|
if (!(MarkStackSize >= 1 && MarkStackSize <= MarkStackSizeMax)) {
|
||||||
|
warning("Invalid value specified for MarkStackSize (" UINTX_FORMAT "): "
|
||||||
|
"must be between " UINTX_FORMAT " and " UINTX_FORMAT,
|
||||||
|
MarkStackSize, 1, MarkStackSizeMax);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (FLAG_IS_CMDLINE(MarkStackSizeMax)) {
|
||||||
|
if (!(MarkStackSize >= 1 && MarkStackSize <= MarkStackSizeMax)) {
|
||||||
|
warning("Invalid value specified for MarkStackSize (" UINTX_FORMAT ")"
|
||||||
|
" or for MarkStackSizeMax (" UINTX_FORMAT ")",
|
||||||
|
MarkStackSize, MarkStackSizeMax);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_markStack.allocate(MarkStackSize)) {
|
||||||
|
warning("Failed to allocate CM marking stack");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_tasks = NEW_C_HEAP_ARRAY(CMTask*, _max_worker_id, mtGC);
|
||||||
|
_accum_task_vtime = NEW_C_HEAP_ARRAY(double, _max_worker_id, mtGC);
|
||||||
|
|
||||||
|
_count_card_bitmaps = NEW_C_HEAP_ARRAY(BitMap, _max_worker_id, mtGC);
|
||||||
|
_count_marked_bytes = NEW_C_HEAP_ARRAY(size_t*, _max_worker_id, mtGC);
|
||||||
|
|
||||||
|
BitMap::idx_t card_bm_size = _card_bm.size();
|
||||||
|
|
||||||
|
// so that the assertion in MarkingTaskQueue::task_queue doesn't fail
|
||||||
|
_active_tasks = _max_worker_id;
|
||||||
|
|
||||||
|
size_t max_regions = (size_t) _g1h->max_regions();
|
||||||
|
for (uint i = 0; i < _max_worker_id; ++i) {
|
||||||
|
CMTaskQueue* task_queue = new CMTaskQueue();
|
||||||
|
task_queue->initialize();
|
||||||
|
_task_queues->register_queue(i, task_queue);
|
||||||
|
|
||||||
|
_count_card_bitmaps[i] = BitMap(card_bm_size, false);
|
||||||
|
_count_marked_bytes[i] = NEW_C_HEAP_ARRAY(size_t, max_regions, mtGC);
|
||||||
|
|
||||||
|
_tasks[i] = new CMTask(i, this,
|
||||||
|
_count_marked_bytes[i],
|
||||||
|
&_count_card_bitmaps[i],
|
||||||
|
task_queue, _task_queues);
|
||||||
|
|
||||||
|
_accum_task_vtime[i] = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the card number for the bottom of the heap. Used
|
||||||
|
// in biasing indexes into the accounting card bitmaps.
|
||||||
|
_heap_bottom_card_num =
|
||||||
|
intptr_t(uintptr_t(_g1h->reserved_region().start()) >>
|
||||||
|
CardTableModRefBS::card_shift);
|
||||||
|
|
||||||
|
// Clear all the liveness counting data
|
||||||
|
clear_all_count_data();
|
||||||
|
|
||||||
// so that the call below can read a sensible value
|
// so that the call below can read a sensible value
|
||||||
_heap_start = (HeapWord*) rs.base();
|
_heap_start = (HeapWord*) heap_rs.base();
|
||||||
set_non_marking_state();
|
set_non_marking_state();
|
||||||
|
_completed_initialization = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConcurrentMark::update_g1_committed(bool force) {
|
void ConcurrentMark::update_g1_committed(bool force) {
|
||||||
|
@ -1165,6 +1284,11 @@ void ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) {
|
||||||
assert(!restart_for_overflow(), "sanity");
|
assert(!restart_for_overflow(), "sanity");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Expand the marking stack, if we have to and if we can.
|
||||||
|
if (_markStack.should_expand()) {
|
||||||
|
_markStack.expand();
|
||||||
|
}
|
||||||
|
|
||||||
// Reset the marking state if marking completed
|
// Reset the marking state if marking completed
|
||||||
if (!restart_for_overflow()) {
|
if (!restart_for_overflow()) {
|
||||||
set_non_marking_state();
|
set_non_marking_state();
|
||||||
|
@ -2785,7 +2909,7 @@ void ConcurrentMark::verify_no_cset_oops(bool verify_stacks,
|
||||||
// Verify entries on the task queues
|
// Verify entries on the task queues
|
||||||
for (uint i = 0; i < _max_worker_id; i += 1) {
|
for (uint i = 0; i < _max_worker_id; i += 1) {
|
||||||
cl.set_phase(VerifyNoCSetOopsQueues, i);
|
cl.set_phase(VerifyNoCSetOopsQueues, i);
|
||||||
OopTaskQueue* queue = _task_queues->queue(i);
|
CMTaskQueue* queue = _task_queues->queue(i);
|
||||||
queue->oops_do(&cl);
|
queue->oops_do(&cl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2840,8 +2964,8 @@ void ConcurrentMark::verify_no_cset_oops(bool verify_stacks,
|
||||||
#endif // PRODUCT
|
#endif // PRODUCT
|
||||||
|
|
||||||
void ConcurrentMark::clear_marking_state(bool clear_overflow) {
|
void ConcurrentMark::clear_marking_state(bool clear_overflow) {
|
||||||
_markStack.setEmpty();
|
_markStack.set_should_expand();
|
||||||
_markStack.clear_overflow();
|
_markStack.setEmpty(); // Also clears the _markStack overflow flag
|
||||||
if (clear_overflow) {
|
if (clear_overflow) {
|
||||||
clear_has_overflown();
|
clear_has_overflown();
|
||||||
} else {
|
} else {
|
||||||
|
@ -2850,7 +2974,7 @@ void ConcurrentMark::clear_marking_state(bool clear_overflow) {
|
||||||
_finger = _heap_start;
|
_finger = _heap_start;
|
||||||
|
|
||||||
for (uint i = 0; i < _max_worker_id; ++i) {
|
for (uint i = 0; i < _max_worker_id; ++i) {
|
||||||
OopTaskQueue* queue = _task_queues->queue(i);
|
CMTaskQueue* queue = _task_queues->queue(i);
|
||||||
queue->set_empty();
|
queue->set_empty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ class CMBitMapRO VALUE_OBJ_CLASS_SPEC {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// constructor
|
// constructor
|
||||||
CMBitMapRO(ReservedSpace rs, int shifter);
|
CMBitMapRO(int shifter);
|
||||||
|
|
||||||
enum { do_yield = true };
|
enum { do_yield = true };
|
||||||
|
|
||||||
|
@ -117,8 +117,11 @@ class CMBitMap : public CMBitMapRO {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// constructor
|
// constructor
|
||||||
CMBitMap(ReservedSpace rs, int shifter) :
|
CMBitMap(int shifter) :
|
||||||
CMBitMapRO(rs, shifter) {}
|
CMBitMapRO(shifter) {}
|
||||||
|
|
||||||
|
// Allocates the back store for the marking bitmap
|
||||||
|
bool allocate(ReservedSpace heap_rs);
|
||||||
|
|
||||||
// write marks
|
// write marks
|
||||||
void mark(HeapWord* addr) {
|
void mark(HeapWord* addr) {
|
||||||
|
@ -155,17 +158,18 @@ class CMBitMap : public CMBitMapRO {
|
||||||
MemRegion getAndClearMarkedRegion(HeapWord* addr, HeapWord* end_addr);
|
MemRegion getAndClearMarkedRegion(HeapWord* addr, HeapWord* end_addr);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Represents a marking stack used by the CM collector.
|
// Represents a marking stack used by ConcurrentMarking in the G1 collector.
|
||||||
// Ideally this should be GrowableArray<> just like MSC's marking stack(s).
|
|
||||||
class CMMarkStack VALUE_OBJ_CLASS_SPEC {
|
class CMMarkStack VALUE_OBJ_CLASS_SPEC {
|
||||||
|
VirtualSpace _virtual_space; // Underlying backing store for actual stack
|
||||||
ConcurrentMark* _cm;
|
ConcurrentMark* _cm;
|
||||||
oop* _base; // bottom of stack
|
oop* _base; // bottom of stack
|
||||||
jint _index; // one more than last occupied index
|
jint _index; // one more than last occupied index
|
||||||
jint _capacity; // max #elements
|
jint _capacity; // max #elements
|
||||||
jint _saved_index; // value of _index saved at start of GC
|
jint _saved_index; // value of _index saved at start of GC
|
||||||
NOT_PRODUCT(jint _max_depth;) // max depth plumbed during run
|
NOT_PRODUCT(jint _max_depth;) // max depth plumbed during run
|
||||||
|
|
||||||
bool _overflow;
|
bool _overflow;
|
||||||
|
bool _should_expand;
|
||||||
DEBUG_ONLY(bool _drain_in_progress;)
|
DEBUG_ONLY(bool _drain_in_progress;)
|
||||||
DEBUG_ONLY(bool _drain_in_progress_yields;)
|
DEBUG_ONLY(bool _drain_in_progress_yields;)
|
||||||
|
|
||||||
|
@ -173,7 +177,13 @@ class CMMarkStack VALUE_OBJ_CLASS_SPEC {
|
||||||
CMMarkStack(ConcurrentMark* cm);
|
CMMarkStack(ConcurrentMark* cm);
|
||||||
~CMMarkStack();
|
~CMMarkStack();
|
||||||
|
|
||||||
void allocate(size_t size);
|
#ifndef PRODUCT
|
||||||
|
jint max_depth() const {
|
||||||
|
return _max_depth;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool allocate(size_t capacity);
|
||||||
|
|
||||||
oop pop() {
|
oop pop() {
|
||||||
if (!isEmpty()) {
|
if (!isEmpty()) {
|
||||||
|
@ -231,11 +241,17 @@ class CMMarkStack VALUE_OBJ_CLASS_SPEC {
|
||||||
|
|
||||||
bool isEmpty() { return _index == 0; }
|
bool isEmpty() { return _index == 0; }
|
||||||
bool isFull() { return _index == _capacity; }
|
bool isFull() { return _index == _capacity; }
|
||||||
int maxElems() { return _capacity; }
|
int maxElems() { return _capacity; }
|
||||||
|
|
||||||
bool overflow() { return _overflow; }
|
bool overflow() { return _overflow; }
|
||||||
void clear_overflow() { _overflow = false; }
|
void clear_overflow() { _overflow = false; }
|
||||||
|
|
||||||
|
bool should_expand() const { return _should_expand; }
|
||||||
|
void set_should_expand();
|
||||||
|
|
||||||
|
// Expand the stack, typically in response to an overflow condition
|
||||||
|
void expand();
|
||||||
|
|
||||||
int size() { return _index; }
|
int size() { return _index; }
|
||||||
|
|
||||||
void setEmpty() { _index = 0; clear_overflow(); }
|
void setEmpty() { _index = 0; clear_overflow(); }
|
||||||
|
@ -344,6 +360,7 @@ public:
|
||||||
class ConcurrentMarkThread;
|
class ConcurrentMarkThread;
|
||||||
|
|
||||||
class ConcurrentMark: public CHeapObj<mtGC> {
|
class ConcurrentMark: public CHeapObj<mtGC> {
|
||||||
|
friend class CMMarkStack;
|
||||||
friend class ConcurrentMarkThread;
|
friend class ConcurrentMarkThread;
|
||||||
friend class CMTask;
|
friend class CMTask;
|
||||||
friend class CMBitMapClosure;
|
friend class CMBitMapClosure;
|
||||||
|
@ -577,6 +594,9 @@ protected:
|
||||||
// the card bitmaps.
|
// the card bitmaps.
|
||||||
intptr_t _heap_bottom_card_num;
|
intptr_t _heap_bottom_card_num;
|
||||||
|
|
||||||
|
// Set to true when initialization is complete
|
||||||
|
bool _completed_initialization;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Manipulation of the global mark stack.
|
// Manipulation of the global mark stack.
|
||||||
// Notice that the first mark_stack_push is CAS-based, whereas the
|
// Notice that the first mark_stack_push is CAS-based, whereas the
|
||||||
|
@ -636,7 +656,7 @@ public:
|
||||||
return _task_queues->steal(worker_id, hash_seed, obj);
|
return _task_queues->steal(worker_id, hash_seed, obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConcurrentMark(ReservedSpace rs, uint max_regions);
|
ConcurrentMark(G1CollectedHeap* g1h, ReservedSpace heap_rs);
|
||||||
~ConcurrentMark();
|
~ConcurrentMark();
|
||||||
|
|
||||||
ConcurrentMarkThread* cmThread() { return _cmThread; }
|
ConcurrentMarkThread* cmThread() { return _cmThread; }
|
||||||
|
@ -907,6 +927,11 @@ public:
|
||||||
// Should *not* be called from parallel code.
|
// Should *not* be called from parallel code.
|
||||||
inline bool mark_and_count(oop obj);
|
inline bool mark_and_count(oop obj);
|
||||||
|
|
||||||
|
// Returns true if initialization was successfully completed.
|
||||||
|
bool completed_initialization() const {
|
||||||
|
return _completed_initialization;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Clear all the per-task bitmaps and arrays used to store the
|
// Clear all the per-task bitmaps and arrays used to store the
|
||||||
// counting data.
|
// counting data.
|
||||||
|
|
|
@ -2079,7 +2079,11 @@ jint G1CollectedHeap::initialize() {
|
||||||
|
|
||||||
// Create the ConcurrentMark data structure and thread.
|
// Create the ConcurrentMark data structure and thread.
|
||||||
// (Must do this late, so that "max_regions" is defined.)
|
// (Must do this late, so that "max_regions" is defined.)
|
||||||
_cm = new ConcurrentMark(heap_rs, max_regions());
|
_cm = new ConcurrentMark(this, heap_rs);
|
||||||
|
if (_cm == NULL || !_cm->completed_initialization()) {
|
||||||
|
vm_shutdown_during_initialization("Could not create/initialize ConcurrentMark");
|
||||||
|
return JNI_ENOMEM;
|
||||||
|
}
|
||||||
_cmThread = _cm->cmThread();
|
_cmThread = _cm->cmThread();
|
||||||
|
|
||||||
// Initialize the from_card cache structure of HeapRegionRemSet.
|
// Initialize the from_card cache structure of HeapRegionRemSet.
|
||||||
|
@ -2087,7 +2091,7 @@ jint G1CollectedHeap::initialize() {
|
||||||
|
|
||||||
// Now expand into the initial heap size.
|
// Now expand into the initial heap size.
|
||||||
if (!expand(init_byte_size)) {
|
if (!expand(init_byte_size)) {
|
||||||
vm_exit_during_initialization("Failed to allocate initial heap.");
|
vm_shutdown_during_initialization("Failed to allocate initial heap.");
|
||||||
return JNI_ENOMEM;
|
return JNI_ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "gc_implementation/parallelScavenge/adjoiningVirtualSpaces.hpp"
|
#include "gc_implementation/parallelScavenge/adjoiningVirtualSpaces.hpp"
|
||||||
|
#include "memory/allocation.inline.hpp"
|
||||||
#include "runtime/java.hpp"
|
#include "runtime/java.hpp"
|
||||||
|
|
||||||
AdjoiningVirtualSpaces::AdjoiningVirtualSpaces(ReservedSpace rs,
|
AdjoiningVirtualSpaces::AdjoiningVirtualSpaces(ReservedSpace rs,
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "gc_implementation/shared/gcStats.hpp"
|
#include "gc_implementation/shared/gcStats.hpp"
|
||||||
#include "gc_implementation/shared/gcUtil.hpp"
|
#include "gc_implementation/shared/gcUtil.hpp"
|
||||||
|
#include "memory/allocation.inline.hpp"
|
||||||
|
|
||||||
GCStats::GCStats() {
|
GCStats::GCStats() {
|
||||||
_avg_promoted = new AdaptivePaddedNoZeroDevAverage(
|
_avg_promoted = new AdaptivePaddedNoZeroDevAverage(
|
||||||
|
|
|
@ -202,7 +202,7 @@ template <MEMFLAGS F> class CHeapObj ALLOCATION_SUPER_CLASS_SPEC {
|
||||||
// Calling new or delete will result in fatal error.
|
// Calling new or delete will result in fatal error.
|
||||||
|
|
||||||
class StackObj ALLOCATION_SUPER_CLASS_SPEC {
|
class StackObj ALLOCATION_SUPER_CLASS_SPEC {
|
||||||
public:
|
private:
|
||||||
void* operator new(size_t size);
|
void* operator new(size_t size);
|
||||||
void operator delete(void* p);
|
void operator delete(void* p);
|
||||||
};
|
};
|
||||||
|
@ -226,7 +226,7 @@ class StackObj ALLOCATION_SUPER_CLASS_SPEC {
|
||||||
// be defined as a an empty string "".
|
// be defined as a an empty string "".
|
||||||
//
|
//
|
||||||
class _ValueObj {
|
class _ValueObj {
|
||||||
public:
|
private:
|
||||||
void* operator new(size_t size);
|
void* operator new(size_t size);
|
||||||
void operator delete(void* p);
|
void operator delete(void* p);
|
||||||
};
|
};
|
||||||
|
|
|
@ -2192,11 +2192,6 @@ void SpaceManager::mangle_freed_chunks() {
|
||||||
|
|
||||||
// MetaspaceAux
|
// MetaspaceAux
|
||||||
|
|
||||||
size_t MetaspaceAux::used_in_bytes() {
|
|
||||||
return (Metaspace::class_space_list()->used_words_sum() +
|
|
||||||
Metaspace::space_list()->used_words_sum()) * BytesPerWord;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t MetaspaceAux::used_in_bytes(Metaspace::MetadataType mdtype) {
|
size_t MetaspaceAux::used_in_bytes(Metaspace::MetadataType mdtype) {
|
||||||
size_t used = 0;
|
size_t used = 0;
|
||||||
ClassLoaderDataGraphMetaspaceIterator iter;
|
ClassLoaderDataGraphMetaspaceIterator iter;
|
||||||
|
@ -2222,14 +2217,6 @@ size_t MetaspaceAux::free_in_bytes(Metaspace::MetadataType mdtype) {
|
||||||
return free * BytesPerWord;
|
return free * BytesPerWord;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The total words available for metadata allocation. This
|
|
||||||
// uses Metaspace capacity_words() which is the total words
|
|
||||||
// in chunks allocated for a Metaspace.
|
|
||||||
size_t MetaspaceAux::capacity_in_bytes() {
|
|
||||||
return (Metaspace::class_space_list()->capacity_words_sum() +
|
|
||||||
Metaspace::space_list()->capacity_words_sum()) * BytesPerWord;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t MetaspaceAux::capacity_in_bytes(Metaspace::MetadataType mdtype) {
|
size_t MetaspaceAux::capacity_in_bytes(Metaspace::MetadataType mdtype) {
|
||||||
size_t capacity = free_chunks_total(mdtype);
|
size_t capacity = free_chunks_total(mdtype);
|
||||||
ClassLoaderDataGraphMetaspaceIterator iter;
|
ClassLoaderDataGraphMetaspaceIterator iter;
|
||||||
|
@ -2242,11 +2229,6 @@ size_t MetaspaceAux::capacity_in_bytes(Metaspace::MetadataType mdtype) {
|
||||||
return capacity * BytesPerWord;
|
return capacity * BytesPerWord;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t MetaspaceAux::reserved_in_bytes() {
|
|
||||||
return (Metaspace::class_space_list()->virtual_space_total() +
|
|
||||||
Metaspace::space_list()->virtual_space_total()) * BytesPerWord;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t MetaspaceAux::reserved_in_bytes(Metaspace::MetadataType mdtype) {
|
size_t MetaspaceAux::reserved_in_bytes(Metaspace::MetadataType mdtype) {
|
||||||
size_t reserved = (mdtype == Metaspace::ClassType) ?
|
size_t reserved = (mdtype == Metaspace::ClassType) ?
|
||||||
Metaspace::class_space_list()->virtual_space_total() :
|
Metaspace::class_space_list()->virtual_space_total() :
|
||||||
|
|
|
@ -156,16 +156,25 @@ class MetaspaceAux : AllStatic {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Total of space allocated to metadata in all Metaspaces
|
// Total of space allocated to metadata in all Metaspaces
|
||||||
static size_t used_in_bytes();
|
static size_t used_in_bytes() {
|
||||||
|
return used_in_bytes(Metaspace::ClassType) +
|
||||||
|
used_in_bytes(Metaspace::NonClassType);
|
||||||
|
}
|
||||||
|
|
||||||
// Total of available space in all Metaspaces
|
// Total of available space in all Metaspaces
|
||||||
// Total of capacity allocated to all Metaspaces. This includes
|
// Total of capacity allocated to all Metaspaces. This includes
|
||||||
// space in Metachunks not yet allocated and in the Metachunk
|
// space in Metachunks not yet allocated and in the Metachunk
|
||||||
// freelist.
|
// freelist.
|
||||||
static size_t capacity_in_bytes();
|
static size_t capacity_in_bytes() {
|
||||||
|
return capacity_in_bytes(Metaspace::ClassType) +
|
||||||
|
capacity_in_bytes(Metaspace::NonClassType);
|
||||||
|
}
|
||||||
|
|
||||||
// Total space reserved in all Metaspaces
|
// Total space reserved in all Metaspaces
|
||||||
static size_t reserved_in_bytes();
|
static size_t reserved_in_bytes() {
|
||||||
|
return reserved_in_bytes(Metaspace::ClassType) +
|
||||||
|
reserved_in_bytes(Metaspace::NonClassType);
|
||||||
|
}
|
||||||
|
|
||||||
static size_t min_chunk_size();
|
static size_t min_chunk_size();
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,7 @@
|
||||||
// | interp_kind | flags | code_size |
|
// | interp_kind | flags | code_size |
|
||||||
// | name index | signature index |
|
// | name index | signature index |
|
||||||
// | method_idnum | max_stack |
|
// | method_idnum | max_stack |
|
||||||
|
// | max_locals | size_of_parameters |
|
||||||
// |------------------------------------------------------|
|
// |------------------------------------------------------|
|
||||||
// | |
|
// | |
|
||||||
// | byte codes |
|
// | byte codes |
|
||||||
|
@ -150,7 +151,8 @@ private:
|
||||||
// initially corresponds to the index into the methods array.
|
// initially corresponds to the index into the methods array.
|
||||||
// but this may change with redefinition
|
// but this may change with redefinition
|
||||||
u2 _max_stack; // Maximum number of entries on the expression stack
|
u2 _max_stack; // Maximum number of entries on the expression stack
|
||||||
|
u2 _max_locals; // Number of local variables used by this method
|
||||||
|
u2 _size_of_parameters; // size of the parameter block (receiver + arguments) in words
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
ConstMethod(int byte_code_size,
|
ConstMethod(int byte_code_size,
|
||||||
|
@ -338,6 +340,11 @@ public:
|
||||||
|
|
||||||
static ByteSize max_stack_offset()
|
static ByteSize max_stack_offset()
|
||||||
{ return byte_offset_of(ConstMethod, _max_stack); }
|
{ return byte_offset_of(ConstMethod, _max_stack); }
|
||||||
|
static ByteSize size_of_locals_offset()
|
||||||
|
{ return byte_offset_of(ConstMethod, _max_locals); }
|
||||||
|
static ByteSize size_of_parameters_offset()
|
||||||
|
{ return byte_offset_of(ConstMethod, _size_of_parameters); }
|
||||||
|
|
||||||
|
|
||||||
// Unique id for the method
|
// Unique id for the method
|
||||||
static const u2 MAX_IDNUM;
|
static const u2 MAX_IDNUM;
|
||||||
|
@ -349,6 +356,14 @@ public:
|
||||||
int max_stack() const { return _max_stack; }
|
int max_stack() const { return _max_stack; }
|
||||||
void set_max_stack(int size) { _max_stack = size; }
|
void set_max_stack(int size) { _max_stack = size; }
|
||||||
|
|
||||||
|
// max locals
|
||||||
|
int max_locals() const { return _max_locals; }
|
||||||
|
void set_max_locals(int size) { _max_locals = size; }
|
||||||
|
|
||||||
|
// size of parameters
|
||||||
|
int size_of_parameters() const { return _size_of_parameters; }
|
||||||
|
void set_size_of_parameters(int size) { _size_of_parameters = size; }
|
||||||
|
|
||||||
// Deallocation for RedefineClasses
|
// Deallocation for RedefineClasses
|
||||||
void deallocate_contents(ClassLoaderData* loader_data);
|
void deallocate_contents(ClassLoaderData* loader_data);
|
||||||
bool is_klass() const { return false; }
|
bool is_klass() const { return false; }
|
||||||
|
|
|
@ -73,8 +73,7 @@
|
||||||
// |------------------------------------------------------|
|
// |------------------------------------------------------|
|
||||||
// | result_index (C++ interpreter only) |
|
// | result_index (C++ interpreter only) |
|
||||||
// |------------------------------------------------------|
|
// |------------------------------------------------------|
|
||||||
// | method_size | max_locals |
|
// | method_size | intrinsic_id| flags |
|
||||||
// | size_of_parameters | intrinsic_id| flags |
|
|
||||||
// |------------------------------------------------------|
|
// |------------------------------------------------------|
|
||||||
// | throwout_count | num_breakpoints |
|
// | throwout_count | num_breakpoints |
|
||||||
// |------------------------------------------------------|
|
// |------------------------------------------------------|
|
||||||
|
@ -116,8 +115,6 @@ class Method : public Metadata {
|
||||||
int _result_index; // C++ interpreter needs for converting results to/from stack
|
int _result_index; // C++ interpreter needs for converting results to/from stack
|
||||||
#endif
|
#endif
|
||||||
u2 _method_size; // size of this object
|
u2 _method_size; // size of this object
|
||||||
u2 _max_locals; // Number of local variables used by this method
|
|
||||||
u2 _size_of_parameters; // size of the parameter block (receiver + arguments) in words
|
|
||||||
u1 _intrinsic_id; // vmSymbols::intrinsic_id (0 == _none)
|
u1 _intrinsic_id; // vmSymbols::intrinsic_id (0 == _none)
|
||||||
u1 _jfr_towrite : 1, // Flags
|
u1 _jfr_towrite : 1, // Flags
|
||||||
_force_inline : 1,
|
_force_inline : 1,
|
||||||
|
@ -299,8 +296,8 @@ class Method : public Metadata {
|
||||||
void set_max_stack(int size) { constMethod()->set_max_stack(size); }
|
void set_max_stack(int size) { constMethod()->set_max_stack(size); }
|
||||||
|
|
||||||
// max locals
|
// max locals
|
||||||
int max_locals() const { return _max_locals; }
|
int max_locals() const { return constMethod()->max_locals(); }
|
||||||
void set_max_locals(int size) { _max_locals = size; }
|
void set_max_locals(int size) { constMethod()->set_max_locals(size); }
|
||||||
|
|
||||||
int highest_comp_level() const;
|
int highest_comp_level() const;
|
||||||
void set_highest_comp_level(int level);
|
void set_highest_comp_level(int level);
|
||||||
|
@ -318,7 +315,8 @@ class Method : public Metadata {
|
||||||
void set_interpreter_throwout_count(int count) { _interpreter_throwout_count = count; }
|
void set_interpreter_throwout_count(int count) { _interpreter_throwout_count = count; }
|
||||||
|
|
||||||
// size of parameters
|
// size of parameters
|
||||||
int size_of_parameters() const { return _size_of_parameters; }
|
int size_of_parameters() const { return constMethod()->size_of_parameters(); }
|
||||||
|
void set_size_of_parameters(int size) { constMethod()->set_size_of_parameters(size); }
|
||||||
|
|
||||||
bool has_stackmap_table() const {
|
bool has_stackmap_table() const {
|
||||||
return constMethod()->has_stackmap_table();
|
return constMethod()->has_stackmap_table();
|
||||||
|
@ -595,8 +593,6 @@ class Method : public Metadata {
|
||||||
#ifdef CC_INTERP
|
#ifdef CC_INTERP
|
||||||
static ByteSize result_index_offset() { return byte_offset_of(Method, _result_index ); }
|
static ByteSize result_index_offset() { return byte_offset_of(Method, _result_index ); }
|
||||||
#endif /* CC_INTERP */
|
#endif /* CC_INTERP */
|
||||||
static ByteSize size_of_locals_offset() { return byte_offset_of(Method, _max_locals ); }
|
|
||||||
static ByteSize size_of_parameters_offset() { return byte_offset_of(Method, _size_of_parameters); }
|
|
||||||
static ByteSize from_compiled_offset() { return byte_offset_of(Method, _from_compiled_entry); }
|
static ByteSize from_compiled_offset() { return byte_offset_of(Method, _from_compiled_entry); }
|
||||||
static ByteSize code_offset() { return byte_offset_of(Method, _code); }
|
static ByteSize code_offset() { return byte_offset_of(Method, _code); }
|
||||||
static ByteSize invocation_counter_offset() { return byte_offset_of(Method, _invocation_counter); }
|
static ByteSize invocation_counter_offset() { return byte_offset_of(Method, _invocation_counter); }
|
||||||
|
@ -804,9 +800,6 @@ class Method : public Metadata {
|
||||||
Array<AnnotationArray*>* methods_type_annotations,
|
Array<AnnotationArray*>* methods_type_annotations,
|
||||||
bool idempotent = false);
|
bool idempotent = false);
|
||||||
|
|
||||||
// size of parameters
|
|
||||||
void set_size_of_parameters(int size) { _size_of_parameters = size; }
|
|
||||||
|
|
||||||
// Deallocation function for redefine classes or if an error occurs
|
// Deallocation function for redefine classes or if an error occurs
|
||||||
void deallocate_contents(ClassLoaderData* loader_data);
|
void deallocate_contents(ClassLoaderData* loader_data);
|
||||||
|
|
||||||
|
|
|
@ -189,6 +189,11 @@ Node *AddNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||||
set_req(1, addx);
|
set_req(1, addx);
|
||||||
set_req(2, a22);
|
set_req(2, a22);
|
||||||
progress = this;
|
progress = this;
|
||||||
|
PhaseIterGVN *igvn = phase->is_IterGVN();
|
||||||
|
if (add2->outcnt() == 0 && igvn) {
|
||||||
|
// add disconnected.
|
||||||
|
igvn->_worklist.push(add2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -624,6 +629,11 @@ Node *AddPNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||||
if( t22->singleton() && (t22 != Type::TOP) ) { // Right input is an add of a constant?
|
if( t22->singleton() && (t22 != Type::TOP) ) { // Right input is an add of a constant?
|
||||||
set_req(Address, phase->transform(new (phase->C) AddPNode(in(Base),in(Address),add->in(1))));
|
set_req(Address, phase->transform(new (phase->C) AddPNode(in(Base),in(Address),add->in(1))));
|
||||||
set_req(Offset, add->in(2));
|
set_req(Offset, add->in(2));
|
||||||
|
PhaseIterGVN *igvn = phase->is_IterGVN();
|
||||||
|
if (add->outcnt() == 0 && igvn) {
|
||||||
|
// add disconnected.
|
||||||
|
igvn->_worklist.push((Node*)add);
|
||||||
|
}
|
||||||
return this; // Made progress
|
return this; // Made progress
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -403,7 +403,7 @@ const char* InlineTree::check_can_parse(ciMethod* callee) {
|
||||||
//------------------------------print_inlining---------------------------------
|
//------------------------------print_inlining---------------------------------
|
||||||
// Really, the failure_msg can be a success message also.
|
// Really, the failure_msg can be a success message also.
|
||||||
void InlineTree::print_inlining(ciMethod* callee_method, int caller_bci, const char* failure_msg) const {
|
void InlineTree::print_inlining(ciMethod* callee_method, int caller_bci, const char* failure_msg) const {
|
||||||
CompileTask::print_inlining(callee_method, inline_level(), caller_bci, failure_msg ? failure_msg : "inline");
|
C->print_inlining(callee_method, inline_level(), caller_bci, failure_msg ? failure_msg : "inline");
|
||||||
if (callee_method == NULL) tty->print(" callee not monotonic or profiled");
|
if (callee_method == NULL) tty->print(" callee not monotonic or profiled");
|
||||||
if (Verbose && callee_method) {
|
if (Verbose && callee_method) {
|
||||||
const InlineTree *top = this;
|
const InlineTree *top = this;
|
||||||
|
|
|
@ -274,6 +274,9 @@ class LateInlineCallGenerator : public DirectCallGenerator {
|
||||||
virtual void do_late_inline();
|
virtual void do_late_inline();
|
||||||
|
|
||||||
virtual JVMState* generate(JVMState* jvms) {
|
virtual JVMState* generate(JVMState* jvms) {
|
||||||
|
Compile *C = Compile::current();
|
||||||
|
C->print_inlining_skip(this);
|
||||||
|
|
||||||
// Record that this call site should be revisited once the main
|
// Record that this call site should be revisited once the main
|
||||||
// parse is finished.
|
// parse is finished.
|
||||||
Compile::current()->add_late_inline(this);
|
Compile::current()->add_late_inline(this);
|
||||||
|
@ -284,7 +287,6 @@ class LateInlineCallGenerator : public DirectCallGenerator {
|
||||||
// as is done for allocations and macro expansion.
|
// as is done for allocations and macro expansion.
|
||||||
return DirectCallGenerator::generate(jvms);
|
return DirectCallGenerator::generate(jvms);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -307,7 +309,9 @@ void LateInlineCallGenerator::do_late_inline() {
|
||||||
|
|
||||||
// Make sure the state is a MergeMem for parsing.
|
// Make sure the state is a MergeMem for parsing.
|
||||||
if (!map->in(TypeFunc::Memory)->is_MergeMem()) {
|
if (!map->in(TypeFunc::Memory)->is_MergeMem()) {
|
||||||
map->set_req(TypeFunc::Memory, MergeMemNode::make(C, map->in(TypeFunc::Memory)));
|
Node* mem = MergeMemNode::make(C, map->in(TypeFunc::Memory));
|
||||||
|
C->initial_gvn()->set_type_bottom(mem);
|
||||||
|
map->set_req(TypeFunc::Memory, mem);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make enough space for the expression stack and transfer the incoming arguments
|
// Make enough space for the expression stack and transfer the incoming arguments
|
||||||
|
@ -320,6 +324,8 @@ void LateInlineCallGenerator::do_late_inline() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
C->print_inlining_insert(this);
|
||||||
|
|
||||||
CompileLog* log = C->log();
|
CompileLog* log = C->log();
|
||||||
if (log != NULL) {
|
if (log != NULL) {
|
||||||
log->head("late_inline method='%d'", log->identify(method()));
|
log->head("late_inline method='%d'", log->identify(method()));
|
||||||
|
@ -608,7 +614,7 @@ CallGenerator* CallGenerator::for_method_handle_inline(JVMState* jvms, ciMethod*
|
||||||
if (cg != NULL && cg->is_inline())
|
if (cg != NULL && cg->is_inline())
|
||||||
return cg;
|
return cg;
|
||||||
} else {
|
} else {
|
||||||
if (PrintInlining) CompileTask::print_inlining(callee, jvms->depth() - 1, jvms->bci(), "receiver not constant");
|
if (PrintInlining) C->print_inlining(callee, jvms->depth() - 1, jvms->bci(), "receiver not constant");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -147,9 +147,9 @@ class CallGenerator : public ResourceObj {
|
||||||
CallGenerator* cg);
|
CallGenerator* cg);
|
||||||
virtual Node* generate_predicate(JVMState* jvms) { return NULL; };
|
virtual Node* generate_predicate(JVMState* jvms) { return NULL; };
|
||||||
|
|
||||||
static void print_inlining(ciMethod* callee, int inline_level, int bci, const char* msg) {
|
static void print_inlining(Compile* C, ciMethod* callee, int inline_level, int bci, const char* msg) {
|
||||||
if (PrintInlining)
|
if (PrintInlining)
|
||||||
CompileTask::print_inlining(callee, inline_level, bci, msg);
|
C->print_inlining(callee, inline_level, bci, msg);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -751,7 +751,7 @@ void CallNode::extract_projections(CallProjections* projs, bool separate_io_proj
|
||||||
projs->fallthrough_ioproj = pn;
|
projs->fallthrough_ioproj = pn;
|
||||||
for (DUIterator j = pn->outs(); pn->has_out(j); j++) {
|
for (DUIterator j = pn->outs(); pn->has_out(j); j++) {
|
||||||
Node* e = pn->out(j);
|
Node* e = pn->out(j);
|
||||||
if (e->Opcode() == Op_CreateEx && e->in(0)->is_CatchProj()) {
|
if (e->Opcode() == Op_CreateEx && e->in(0)->is_CatchProj() && e->outcnt() > 0) {
|
||||||
assert(projs->exobj == NULL, "only one");
|
assert(projs->exobj == NULL, "only one");
|
||||||
projs->exobj = e;
|
projs->exobj = e;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1566,6 +1566,10 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||||
Node* n = in(j); // Get the input
|
Node* n = in(j); // Get the input
|
||||||
if (rc == NULL || phase->type(rc) == Type::TOP) {
|
if (rc == NULL || phase->type(rc) == Type::TOP) {
|
||||||
if (n != top) { // Not already top?
|
if (n != top) { // Not already top?
|
||||||
|
PhaseIterGVN *igvn = phase->is_IterGVN();
|
||||||
|
if (can_reshape && igvn != NULL) {
|
||||||
|
igvn->_worklist.push(r);
|
||||||
|
}
|
||||||
set_req(j, top); // Nuke it down
|
set_req(j, top); // Nuke it down
|
||||||
progress = this; // Record progress
|
progress = this; // Record progress
|
||||||
}
|
}
|
||||||
|
|
|
@ -610,7 +610,9 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
|
||||||
_trace_opto_output(TraceOptoOutput || method()->has_option("TraceOptoOutput")),
|
_trace_opto_output(TraceOptoOutput || method()->has_option("TraceOptoOutput")),
|
||||||
_printer(IdealGraphPrinter::printer()),
|
_printer(IdealGraphPrinter::printer()),
|
||||||
#endif
|
#endif
|
||||||
_congraph(NULL) {
|
_congraph(NULL),
|
||||||
|
_print_inlining_list(NULL),
|
||||||
|
_print_inlining(0) {
|
||||||
C = this;
|
C = this;
|
||||||
|
|
||||||
CompileWrapper cw(this);
|
CompileWrapper cw(this);
|
||||||
|
@ -666,6 +668,9 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
|
||||||
PhaseGVN gvn(node_arena(), estimated_size);
|
PhaseGVN gvn(node_arena(), estimated_size);
|
||||||
set_initial_gvn(&gvn);
|
set_initial_gvn(&gvn);
|
||||||
|
|
||||||
|
if (PrintInlining) {
|
||||||
|
_print_inlining_list = new (comp_arena())GrowableArray<PrintInliningBuffer>(comp_arena(), 1, 1, PrintInliningBuffer());
|
||||||
|
}
|
||||||
{ // Scope for timing the parser
|
{ // Scope for timing the parser
|
||||||
TracePhase t3("parse", &_t_parser, true);
|
TracePhase t3("parse", &_t_parser, true);
|
||||||
|
|
||||||
|
@ -754,6 +759,7 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(_late_inlines.length() == 0, "should have been processed");
|
assert(_late_inlines.length() == 0, "should have been processed");
|
||||||
|
dump_inlining();
|
||||||
|
|
||||||
print_method("Before RemoveUseless", 3);
|
print_method("Before RemoveUseless", 3);
|
||||||
|
|
||||||
|
@ -899,7 +905,9 @@ Compile::Compile( ciEnv* ci_env,
|
||||||
#endif
|
#endif
|
||||||
_dead_node_list(comp_arena()),
|
_dead_node_list(comp_arena()),
|
||||||
_dead_node_count(0),
|
_dead_node_count(0),
|
||||||
_congraph(NULL) {
|
_congraph(NULL),
|
||||||
|
_print_inlining_list(NULL),
|
||||||
|
_print_inlining(0) {
|
||||||
C = this;
|
C = this;
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
|
@ -3351,3 +3359,11 @@ void Compile::ConstantTable::fill_jump_table(CodeBuffer& cb, MachConstantNode* n
|
||||||
cb.consts()->relocate((address) constant_addr, relocInfo::internal_word_type);
|
cb.consts()->relocate((address) constant_addr, relocInfo::internal_word_type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Compile::dump_inlining() {
|
||||||
|
if (PrintInlining) {
|
||||||
|
for (int i = 0; i < _print_inlining_list->length(); i++) {
|
||||||
|
tty->print(_print_inlining_list->at(i).ss()->as_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "code/debugInfoRec.hpp"
|
#include "code/debugInfoRec.hpp"
|
||||||
#include "code/exceptionHandlerTable.hpp"
|
#include "code/exceptionHandlerTable.hpp"
|
||||||
#include "compiler/compilerOracle.hpp"
|
#include "compiler/compilerOracle.hpp"
|
||||||
|
#include "compiler/compileBroker.hpp"
|
||||||
#include "libadt/dict.hpp"
|
#include "libadt/dict.hpp"
|
||||||
#include "libadt/port.hpp"
|
#include "libadt/port.hpp"
|
||||||
#include "libadt/vectset.hpp"
|
#include "libadt/vectset.hpp"
|
||||||
|
@ -369,6 +370,61 @@ class Compile : public Phase {
|
||||||
GrowableArray<CallGenerator*> _late_inlines; // List of CallGenerators to be revisited after
|
GrowableArray<CallGenerator*> _late_inlines; // List of CallGenerators to be revisited after
|
||||||
// main parsing has finished.
|
// main parsing has finished.
|
||||||
|
|
||||||
|
// Inlining may not happen in parse order which would make
|
||||||
|
// PrintInlining output confusing. Keep track of PrintInlining
|
||||||
|
// pieces in order.
|
||||||
|
class PrintInliningBuffer : public ResourceObj {
|
||||||
|
private:
|
||||||
|
CallGenerator* _cg;
|
||||||
|
stringStream* _ss;
|
||||||
|
|
||||||
|
public:
|
||||||
|
PrintInliningBuffer()
|
||||||
|
: _cg(NULL) { _ss = new stringStream(); }
|
||||||
|
|
||||||
|
stringStream* ss() const { return _ss; }
|
||||||
|
CallGenerator* cg() const { return _cg; }
|
||||||
|
void set_cg(CallGenerator* cg) { _cg = cg; }
|
||||||
|
};
|
||||||
|
|
||||||
|
GrowableArray<PrintInliningBuffer>* _print_inlining_list;
|
||||||
|
int _print_inlining;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
outputStream* print_inlining_stream() const {
|
||||||
|
return _print_inlining_list->at(_print_inlining).ss();
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_inlining_skip(CallGenerator* cg) {
|
||||||
|
if (PrintInlining) {
|
||||||
|
_print_inlining_list->at(_print_inlining).set_cg(cg);
|
||||||
|
_print_inlining++;
|
||||||
|
_print_inlining_list->insert_before(_print_inlining, PrintInliningBuffer());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_inlining_insert(CallGenerator* cg) {
|
||||||
|
if (PrintInlining) {
|
||||||
|
for (int i = 0; i < _print_inlining_list->length(); i++) {
|
||||||
|
if (_print_inlining_list->at(i).cg() == cg) {
|
||||||
|
_print_inlining_list->insert_before(i+1, PrintInliningBuffer());
|
||||||
|
_print_inlining = i+1;
|
||||||
|
_print_inlining_list->at(i).set_cg(NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ShouldNotReachHere();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_inlining(ciMethod* method, int inline_level, int bci, const char* msg = NULL) {
|
||||||
|
stringStream ss;
|
||||||
|
CompileTask::print_inlining(&ss, method, inline_level, bci, msg);
|
||||||
|
print_inlining_stream()->print(ss.as_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
// Matching, CFG layout, allocation, code generation
|
// Matching, CFG layout, allocation, code generation
|
||||||
PhaseCFG* _cfg; // Results of CFG finding
|
PhaseCFG* _cfg; // Results of CFG finding
|
||||||
bool _select_24_bit_instr; // We selected an instruction with a 24-bit result
|
bool _select_24_bit_instr; // We selected an instruction with a 24-bit result
|
||||||
|
@ -591,7 +647,7 @@ class Compile : public Phase {
|
||||||
void reset_dead_node_list() { _dead_node_list.Reset();
|
void reset_dead_node_list() { _dead_node_list.Reset();
|
||||||
_dead_node_count = 0;
|
_dead_node_count = 0;
|
||||||
}
|
}
|
||||||
uint live_nodes() {
|
uint live_nodes() const {
|
||||||
int val = _unique - _dead_node_count;
|
int val = _unique - _dead_node_count;
|
||||||
assert (val >= 0, err_msg_res("number of tracked dead nodes %d more than created nodes %d", _unique, _dead_node_count));
|
assert (val >= 0, err_msg_res("number of tracked dead nodes %d more than created nodes %d", _unique, _dead_node_count));
|
||||||
return (uint) val;
|
return (uint) val;
|
||||||
|
@ -702,7 +758,7 @@ class Compile : public Phase {
|
||||||
|
|
||||||
void identify_useful_nodes(Unique_Node_List &useful);
|
void identify_useful_nodes(Unique_Node_List &useful);
|
||||||
void update_dead_node_list(Unique_Node_List &useful);
|
void update_dead_node_list(Unique_Node_List &useful);
|
||||||
void remove_useless_nodes (Unique_Node_List &useful);
|
void remove_useless_nodes (Unique_Node_List &useful);
|
||||||
|
|
||||||
WarmCallInfo* warm_calls() const { return _warm_calls; }
|
WarmCallInfo* warm_calls() const { return _warm_calls; }
|
||||||
void set_warm_calls(WarmCallInfo* l) { _warm_calls = l; }
|
void set_warm_calls(WarmCallInfo* l) { _warm_calls = l; }
|
||||||
|
@ -711,6 +767,8 @@ class Compile : public Phase {
|
||||||
// Record this CallGenerator for inlining at the end of parsing.
|
// Record this CallGenerator for inlining at the end of parsing.
|
||||||
void add_late_inline(CallGenerator* cg) { _late_inlines.push(cg); }
|
void add_late_inline(CallGenerator* cg) { _late_inlines.push(cg); }
|
||||||
|
|
||||||
|
void dump_inlining();
|
||||||
|
|
||||||
// Matching, CFG layout, allocation, code generation
|
// Matching, CFG layout, allocation, code generation
|
||||||
PhaseCFG* cfg() { return _cfg; }
|
PhaseCFG* cfg() { return _cfg; }
|
||||||
bool select_24_bit_instr() const { return _select_24_bit_instr; }
|
bool select_24_bit_instr() const { return _select_24_bit_instr; }
|
||||||
|
|
|
@ -40,19 +40,24 @@
|
||||||
#include "prims/nativeLookup.hpp"
|
#include "prims/nativeLookup.hpp"
|
||||||
#include "runtime/sharedRuntime.hpp"
|
#include "runtime/sharedRuntime.hpp"
|
||||||
|
|
||||||
void trace_type_profile(ciMethod *method, int depth, int bci, ciMethod *prof_method, ciKlass *prof_klass, int site_count, int receiver_count) {
|
void trace_type_profile(Compile* C, ciMethod *method, int depth, int bci, ciMethod *prof_method, ciKlass *prof_klass, int site_count, int receiver_count) {
|
||||||
if (TraceTypeProfile || PrintInlining NOT_PRODUCT(|| PrintOptoInlining)) {
|
if (TraceTypeProfile || PrintInlining NOT_PRODUCT(|| PrintOptoInlining)) {
|
||||||
|
outputStream* out = tty;
|
||||||
if (!PrintInlining) {
|
if (!PrintInlining) {
|
||||||
if (NOT_PRODUCT(!PrintOpto &&) !PrintCompilation) {
|
if (NOT_PRODUCT(!PrintOpto &&) !PrintCompilation) {
|
||||||
method->print_short_name();
|
method->print_short_name();
|
||||||
tty->cr();
|
tty->cr();
|
||||||
}
|
}
|
||||||
CompileTask::print_inlining(prof_method, depth, bci);
|
CompileTask::print_inlining(prof_method, depth, bci);
|
||||||
|
} else {
|
||||||
|
out = C->print_inlining_stream();
|
||||||
}
|
}
|
||||||
CompileTask::print_inline_indent(depth);
|
CompileTask::print_inline_indent(depth, out);
|
||||||
tty->print(" \\-> TypeProfile (%d/%d counts) = ", receiver_count, site_count);
|
out->print(" \\-> TypeProfile (%d/%d counts) = ", receiver_count, site_count);
|
||||||
prof_klass->name()->print_symbol();
|
stringStream ss;
|
||||||
tty->cr();
|
prof_klass->name()->print_symbol_on(&ss);
|
||||||
|
out->print(ss.as_string());
|
||||||
|
out->cr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,13 +238,13 @@ CallGenerator* Compile::call_generator(ciMethod* callee, int vtable_index, bool
|
||||||
}
|
}
|
||||||
if (miss_cg != NULL) {
|
if (miss_cg != NULL) {
|
||||||
if (next_hit_cg != NULL) {
|
if (next_hit_cg != NULL) {
|
||||||
trace_type_profile(jvms->method(), jvms->depth() - 1, jvms->bci(), next_receiver_method, profile.receiver(1), site_count, profile.receiver_count(1));
|
trace_type_profile(C, jvms->method(), jvms->depth() - 1, jvms->bci(), next_receiver_method, profile.receiver(1), site_count, profile.receiver_count(1));
|
||||||
// We don't need to record dependency on a receiver here and below.
|
// We don't need to record dependency on a receiver here and below.
|
||||||
// Whenever we inline, the dependency is added by Parse::Parse().
|
// Whenever we inline, the dependency is added by Parse::Parse().
|
||||||
miss_cg = CallGenerator::for_predicted_call(profile.receiver(1), miss_cg, next_hit_cg, PROB_MAX);
|
miss_cg = CallGenerator::for_predicted_call(profile.receiver(1), miss_cg, next_hit_cg, PROB_MAX);
|
||||||
}
|
}
|
||||||
if (miss_cg != NULL) {
|
if (miss_cg != NULL) {
|
||||||
trace_type_profile(jvms->method(), jvms->depth() - 1, jvms->bci(), receiver_method, profile.receiver(0), site_count, receiver_count);
|
trace_type_profile(C, jvms->method(), jvms->depth() - 1, jvms->bci(), receiver_method, profile.receiver(0), site_count, receiver_count);
|
||||||
CallGenerator* cg = CallGenerator::for_predicted_call(profile.receiver(0), miss_cg, hit_cg, profile.receiver_prob(0));
|
CallGenerator* cg = CallGenerator::for_predicted_call(profile.receiver(0), miss_cg, hit_cg, profile.receiver_prob(0));
|
||||||
if (cg != NULL) return cg;
|
if (cg != NULL) return cg;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1771,11 +1771,21 @@ void GraphKit::replace_call(CallNode* call, Node* result) {
|
||||||
CallProjections callprojs;
|
CallProjections callprojs;
|
||||||
call->extract_projections(&callprojs, true);
|
call->extract_projections(&callprojs, true);
|
||||||
|
|
||||||
// Replace all the old call edges with the edges from the inlining result
|
Node* init_mem = call->in(TypeFunc::Memory);
|
||||||
C->gvn_replace_by(callprojs.fallthrough_catchproj, final_state->in(TypeFunc::Control));
|
|
||||||
C->gvn_replace_by(callprojs.fallthrough_memproj, final_state->in(TypeFunc::Memory));
|
|
||||||
C->gvn_replace_by(callprojs.fallthrough_ioproj, final_state->in(TypeFunc::I_O));
|
|
||||||
Node* final_mem = final_state->in(TypeFunc::Memory);
|
Node* final_mem = final_state->in(TypeFunc::Memory);
|
||||||
|
Node* final_ctl = final_state->in(TypeFunc::Control);
|
||||||
|
Node* final_io = final_state->in(TypeFunc::I_O);
|
||||||
|
|
||||||
|
// Replace all the old call edges with the edges from the inlining result
|
||||||
|
if (callprojs.fallthrough_catchproj != NULL) {
|
||||||
|
C->gvn_replace_by(callprojs.fallthrough_catchproj, final_ctl);
|
||||||
|
}
|
||||||
|
if (callprojs.fallthrough_memproj != NULL) {
|
||||||
|
C->gvn_replace_by(callprojs.fallthrough_memproj, final_mem);
|
||||||
|
}
|
||||||
|
if (callprojs.fallthrough_ioproj != NULL) {
|
||||||
|
C->gvn_replace_by(callprojs.fallthrough_ioproj, final_io);
|
||||||
|
}
|
||||||
|
|
||||||
// Replace the result with the new result if it exists and is used
|
// Replace the result with the new result if it exists and is used
|
||||||
if (callprojs.resproj != NULL && result != NULL) {
|
if (callprojs.resproj != NULL && result != NULL) {
|
||||||
|
@ -2980,7 +2990,7 @@ Node* GraphKit::set_output_for_allocation(AllocateNode* alloc,
|
||||||
set_control( _gvn.transform(new (C) ProjNode(allocx, TypeFunc::Control) ) );
|
set_control( _gvn.transform(new (C) ProjNode(allocx, TypeFunc::Control) ) );
|
||||||
// create memory projection for i_o
|
// create memory projection for i_o
|
||||||
set_memory ( _gvn.transform( new (C) ProjNode(allocx, TypeFunc::Memory, true) ), rawidx );
|
set_memory ( _gvn.transform( new (C) ProjNode(allocx, TypeFunc::Memory, true) ), rawidx );
|
||||||
make_slow_call_ex(allocx, env()->OutOfMemoryError_klass(), true);
|
make_slow_call_ex(allocx, env()->Throwable_klass(), true);
|
||||||
|
|
||||||
// create a memory projection as for the normal control path
|
// create a memory projection as for the normal control path
|
||||||
Node* malloc = _gvn.transform(new (C) ProjNode(allocx, TypeFunc::Memory));
|
Node* malloc = _gvn.transform(new (C) ProjNode(allocx, TypeFunc::Memory));
|
||||||
|
|
|
@ -282,6 +282,7 @@ class LibraryCallKit : public GraphKit {
|
||||||
typedef enum { LS_xadd, LS_xchg, LS_cmpxchg } LoadStoreKind;
|
typedef enum { LS_xadd, LS_xchg, LS_cmpxchg } LoadStoreKind;
|
||||||
bool inline_unsafe_load_store(BasicType type, LoadStoreKind kind);
|
bool inline_unsafe_load_store(BasicType type, LoadStoreKind kind);
|
||||||
bool inline_unsafe_ordered_store(BasicType type);
|
bool inline_unsafe_ordered_store(BasicType type);
|
||||||
|
bool inline_unsafe_fence(vmIntrinsics::ID id);
|
||||||
bool inline_fp_conversions(vmIntrinsics::ID id);
|
bool inline_fp_conversions(vmIntrinsics::ID id);
|
||||||
bool inline_number_methods(vmIntrinsics::ID id);
|
bool inline_number_methods(vmIntrinsics::ID id);
|
||||||
bool inline_reference_get();
|
bool inline_reference_get();
|
||||||
|
@ -334,6 +335,9 @@ CallGenerator* Compile::make_vm_intrinsic(ciMethod* m, bool is_virtual) {
|
||||||
case vmIntrinsics::_getAndSetInt:
|
case vmIntrinsics::_getAndSetInt:
|
||||||
case vmIntrinsics::_getAndSetLong:
|
case vmIntrinsics::_getAndSetLong:
|
||||||
case vmIntrinsics::_getAndSetObject:
|
case vmIntrinsics::_getAndSetObject:
|
||||||
|
case vmIntrinsics::_loadFence:
|
||||||
|
case vmIntrinsics::_storeFence:
|
||||||
|
case vmIntrinsics::_fullFence:
|
||||||
break; // InlineNatives does not control String.compareTo
|
break; // InlineNatives does not control String.compareTo
|
||||||
case vmIntrinsics::_Reference_get:
|
case vmIntrinsics::_Reference_get:
|
||||||
break; // InlineNatives does not control Reference.get
|
break; // InlineNatives does not control Reference.get
|
||||||
|
@ -536,7 +540,7 @@ JVMState* LibraryIntrinsic::generate(JVMState* jvms) {
|
||||||
// Try to inline the intrinsic.
|
// Try to inline the intrinsic.
|
||||||
if (kit.try_to_inline()) {
|
if (kit.try_to_inline()) {
|
||||||
if (PrintIntrinsics || PrintInlining NOT_PRODUCT( || PrintOptoInlining) ) {
|
if (PrintIntrinsics || PrintInlining NOT_PRODUCT( || PrintOptoInlining) ) {
|
||||||
CompileTask::print_inlining(callee, jvms->depth() - 1, bci, is_virtual() ? "(intrinsic, virtual)" : "(intrinsic)");
|
C->print_inlining(callee, jvms->depth() - 1, bci, is_virtual() ? "(intrinsic, virtual)" : "(intrinsic)");
|
||||||
}
|
}
|
||||||
C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_worked);
|
C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_worked);
|
||||||
if (C->log()) {
|
if (C->log()) {
|
||||||
|
@ -555,7 +559,7 @@ JVMState* LibraryIntrinsic::generate(JVMState* jvms) {
|
||||||
if (jvms->has_method()) {
|
if (jvms->has_method()) {
|
||||||
// Not a root compile.
|
// Not a root compile.
|
||||||
const char* msg = is_virtual() ? "failed to inline (intrinsic, virtual)" : "failed to inline (intrinsic)";
|
const char* msg = is_virtual() ? "failed to inline (intrinsic, virtual)" : "failed to inline (intrinsic)";
|
||||||
CompileTask::print_inlining(callee, jvms->depth() - 1, bci, msg);
|
C->print_inlining(callee, jvms->depth() - 1, bci, msg);
|
||||||
} else {
|
} else {
|
||||||
// Root compile
|
// Root compile
|
||||||
tty->print("Did not generate intrinsic %s%s at bci:%d in",
|
tty->print("Did not generate intrinsic %s%s at bci:%d in",
|
||||||
|
@ -585,7 +589,7 @@ Node* LibraryIntrinsic::generate_predicate(JVMState* jvms) {
|
||||||
Node* slow_ctl = kit.try_to_predicate();
|
Node* slow_ctl = kit.try_to_predicate();
|
||||||
if (!kit.failing()) {
|
if (!kit.failing()) {
|
||||||
if (PrintIntrinsics || PrintInlining NOT_PRODUCT( || PrintOptoInlining) ) {
|
if (PrintIntrinsics || PrintInlining NOT_PRODUCT( || PrintOptoInlining) ) {
|
||||||
CompileTask::print_inlining(callee, jvms->depth() - 1, bci, is_virtual() ? "(intrinsic, virtual)" : "(intrinsic)");
|
C->print_inlining(callee, jvms->depth() - 1, bci, is_virtual() ? "(intrinsic, virtual)" : "(intrinsic)");
|
||||||
}
|
}
|
||||||
C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_worked);
|
C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_worked);
|
||||||
if (C->log()) {
|
if (C->log()) {
|
||||||
|
@ -602,12 +606,12 @@ Node* LibraryIntrinsic::generate_predicate(JVMState* jvms) {
|
||||||
if (jvms->has_method()) {
|
if (jvms->has_method()) {
|
||||||
// Not a root compile.
|
// Not a root compile.
|
||||||
const char* msg = "failed to generate predicate for intrinsic";
|
const char* msg = "failed to generate predicate for intrinsic";
|
||||||
CompileTask::print_inlining(kit.callee(), jvms->depth() - 1, bci, msg);
|
C->print_inlining(kit.callee(), jvms->depth() - 1, bci, msg);
|
||||||
} else {
|
} else {
|
||||||
// Root compile
|
// Root compile
|
||||||
tty->print("Did not generate predicate for intrinsic %s%s at bci:%d in",
|
C->print_inlining_stream()->print("Did not generate predicate for intrinsic %s%s at bci:%d in",
|
||||||
vmIntrinsics::name_at(intrinsic_id()),
|
vmIntrinsics::name_at(intrinsic_id()),
|
||||||
(is_virtual() ? " (virtual)" : ""), bci);
|
(is_virtual() ? " (virtual)" : ""), bci);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_failed);
|
C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_failed);
|
||||||
|
@ -732,6 +736,10 @@ bool LibraryCallKit::try_to_inline() {
|
||||||
case vmIntrinsics::_getAndSetLong: return inline_unsafe_load_store(T_LONG, LS_xchg);
|
case vmIntrinsics::_getAndSetLong: return inline_unsafe_load_store(T_LONG, LS_xchg);
|
||||||
case vmIntrinsics::_getAndSetObject: return inline_unsafe_load_store(T_OBJECT, LS_xchg);
|
case vmIntrinsics::_getAndSetObject: return inline_unsafe_load_store(T_OBJECT, LS_xchg);
|
||||||
|
|
||||||
|
case vmIntrinsics::_loadFence:
|
||||||
|
case vmIntrinsics::_storeFence:
|
||||||
|
case vmIntrinsics::_fullFence: return inline_unsafe_fence(intrinsic_id());
|
||||||
|
|
||||||
case vmIntrinsics::_currentThread: return inline_native_currentThread();
|
case vmIntrinsics::_currentThread: return inline_native_currentThread();
|
||||||
case vmIntrinsics::_isInterrupted: return inline_native_isInterrupted();
|
case vmIntrinsics::_isInterrupted: return inline_native_isInterrupted();
|
||||||
|
|
||||||
|
@ -2840,6 +2848,26 @@ bool LibraryCallKit::inline_unsafe_ordered_store(BasicType type) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LibraryCallKit::inline_unsafe_fence(vmIntrinsics::ID id) {
|
||||||
|
// Regardless of form, don't allow previous ld/st to move down,
|
||||||
|
// then issue acquire, release, or volatile mem_bar.
|
||||||
|
insert_mem_bar(Op_MemBarCPUOrder);
|
||||||
|
switch(id) {
|
||||||
|
case vmIntrinsics::_loadFence:
|
||||||
|
insert_mem_bar(Op_MemBarAcquire);
|
||||||
|
return true;
|
||||||
|
case vmIntrinsics::_storeFence:
|
||||||
|
insert_mem_bar(Op_MemBarRelease);
|
||||||
|
return true;
|
||||||
|
case vmIntrinsics::_fullFence:
|
||||||
|
insert_mem_bar(Op_MemBarVolatile);
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
fatal_unexpected_iid(id);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------inline_unsafe_allocate---------------------------
|
//----------------------------inline_unsafe_allocate---------------------------
|
||||||
// public native Object sun.mics.Unsafe.allocateInstance(Class<?> cls);
|
// public native Object sun.mics.Unsafe.allocateInstance(Class<?> cls);
|
||||||
bool LibraryCallKit::inline_unsafe_allocate() {
|
bool LibraryCallKit::inline_unsafe_allocate() {
|
||||||
|
@ -2952,14 +2980,23 @@ bool LibraryCallKit::inline_native_isInterrupted() {
|
||||||
|
|
||||||
// We only go to the fast case code if we pass two guards.
|
// We only go to the fast case code if we pass two guards.
|
||||||
// Paths which do not pass are accumulated in the slow_region.
|
// Paths which do not pass are accumulated in the slow_region.
|
||||||
|
|
||||||
|
enum {
|
||||||
|
no_int_result_path = 1, // t == Thread.current() && !TLS._osthread._interrupted
|
||||||
|
no_clear_result_path = 2, // t == Thread.current() && TLS._osthread._interrupted && !clear_int
|
||||||
|
slow_result_path = 3, // slow path: t.isInterrupted(clear_int)
|
||||||
|
PATH_LIMIT
|
||||||
|
};
|
||||||
|
|
||||||
|
// Ensure that it's not possible to move the load of TLS._osthread._interrupted flag
|
||||||
|
// out of the function.
|
||||||
|
insert_mem_bar(Op_MemBarCPUOrder);
|
||||||
|
|
||||||
|
RegionNode* result_rgn = new (C) RegionNode(PATH_LIMIT);
|
||||||
|
PhiNode* result_val = new (C) PhiNode(result_rgn, TypeInt::BOOL);
|
||||||
|
|
||||||
RegionNode* slow_region = new (C) RegionNode(1);
|
RegionNode* slow_region = new (C) RegionNode(1);
|
||||||
record_for_igvn(slow_region);
|
record_for_igvn(slow_region);
|
||||||
RegionNode* result_rgn = new (C) RegionNode(1+3); // fast1, fast2, slow
|
|
||||||
PhiNode* result_val = new (C) PhiNode(result_rgn, TypeInt::BOOL);
|
|
||||||
enum { no_int_result_path = 1,
|
|
||||||
no_clear_result_path = 2,
|
|
||||||
slow_result_path = 3
|
|
||||||
};
|
|
||||||
|
|
||||||
// (a) Receiving thread must be the current thread.
|
// (a) Receiving thread must be the current thread.
|
||||||
Node* rec_thr = argument(0);
|
Node* rec_thr = argument(0);
|
||||||
|
@ -2968,14 +3005,13 @@ bool LibraryCallKit::inline_native_isInterrupted() {
|
||||||
Node* cmp_thr = _gvn.transform( new (C) CmpPNode(cur_thr, rec_thr) );
|
Node* cmp_thr = _gvn.transform( new (C) CmpPNode(cur_thr, rec_thr) );
|
||||||
Node* bol_thr = _gvn.transform( new (C) BoolNode(cmp_thr, BoolTest::ne) );
|
Node* bol_thr = _gvn.transform( new (C) BoolNode(cmp_thr, BoolTest::ne) );
|
||||||
|
|
||||||
bool known_current_thread = (_gvn.type(bol_thr) == TypeInt::ZERO);
|
generate_slow_guard(bol_thr, slow_region);
|
||||||
if (!known_current_thread)
|
|
||||||
generate_slow_guard(bol_thr, slow_region);
|
|
||||||
|
|
||||||
// (b) Interrupt bit on TLS must be false.
|
// (b) Interrupt bit on TLS must be false.
|
||||||
Node* p = basic_plus_adr(top()/*!oop*/, tls_ptr, in_bytes(JavaThread::osthread_offset()));
|
Node* p = basic_plus_adr(top()/*!oop*/, tls_ptr, in_bytes(JavaThread::osthread_offset()));
|
||||||
Node* osthread = make_load(NULL, p, TypeRawPtr::NOTNULL, T_ADDRESS);
|
Node* osthread = make_load(NULL, p, TypeRawPtr::NOTNULL, T_ADDRESS);
|
||||||
p = basic_plus_adr(top()/*!oop*/, osthread, in_bytes(OSThread::interrupted_offset()));
|
p = basic_plus_adr(top()/*!oop*/, osthread, in_bytes(OSThread::interrupted_offset()));
|
||||||
|
|
||||||
// Set the control input on the field _interrupted read to prevent it floating up.
|
// Set the control input on the field _interrupted read to prevent it floating up.
|
||||||
Node* int_bit = make_load(control(), p, TypeInt::BOOL, T_INT);
|
Node* int_bit = make_load(control(), p, TypeInt::BOOL, T_INT);
|
||||||
Node* cmp_bit = _gvn.transform( new (C) CmpINode(int_bit, intcon(0)) );
|
Node* cmp_bit = _gvn.transform( new (C) CmpINode(int_bit, intcon(0)) );
|
||||||
|
@ -3020,22 +3056,20 @@ bool LibraryCallKit::inline_native_isInterrupted() {
|
||||||
Node* slow_val = set_results_for_java_call(slow_call);
|
Node* slow_val = set_results_for_java_call(slow_call);
|
||||||
// this->control() comes from set_results_for_java_call
|
// this->control() comes from set_results_for_java_call
|
||||||
|
|
||||||
// If we know that the result of the slow call will be true, tell the optimizer!
|
|
||||||
if (known_current_thread) slow_val = intcon(1);
|
|
||||||
|
|
||||||
Node* fast_io = slow_call->in(TypeFunc::I_O);
|
Node* fast_io = slow_call->in(TypeFunc::I_O);
|
||||||
Node* fast_mem = slow_call->in(TypeFunc::Memory);
|
Node* fast_mem = slow_call->in(TypeFunc::Memory);
|
||||||
|
|
||||||
// These two phis are pre-filled with copies of of the fast IO and Memory
|
// These two phis are pre-filled with copies of of the fast IO and Memory
|
||||||
Node* io_phi = PhiNode::make(result_rgn, fast_io, Type::ABIO);
|
PhiNode* result_mem = PhiNode::make(result_rgn, fast_mem, Type::MEMORY, TypePtr::BOTTOM);
|
||||||
Node* mem_phi = PhiNode::make(result_rgn, fast_mem, Type::MEMORY, TypePtr::BOTTOM);
|
PhiNode* result_io = PhiNode::make(result_rgn, fast_io, Type::ABIO);
|
||||||
|
|
||||||
result_rgn->init_req(slow_result_path, control());
|
result_rgn->init_req(slow_result_path, control());
|
||||||
io_phi ->init_req(slow_result_path, i_o());
|
result_io ->init_req(slow_result_path, i_o());
|
||||||
mem_phi ->init_req(slow_result_path, reset_memory());
|
result_mem->init_req(slow_result_path, reset_memory());
|
||||||
result_val->init_req(slow_result_path, slow_val);
|
result_val->init_req(slow_result_path, slow_val);
|
||||||
|
|
||||||
set_all_memory( _gvn.transform(mem_phi) );
|
set_all_memory(_gvn.transform(result_mem));
|
||||||
set_i_o( _gvn.transform(io_phi) );
|
set_i_o( _gvn.transform(result_io));
|
||||||
}
|
}
|
||||||
|
|
||||||
C->set_has_split_ifs(true); // Has chance for split-if optimization
|
C->set_has_split_ifs(true); // Has chance for split-if optimization
|
||||||
|
@ -3319,7 +3353,7 @@ bool LibraryCallKit::inline_native_subtype_check() {
|
||||||
Node* arg = args[which_arg];
|
Node* arg = args[which_arg];
|
||||||
arg = null_check(arg);
|
arg = null_check(arg);
|
||||||
if (stopped()) break;
|
if (stopped()) break;
|
||||||
args[which_arg] = _gvn.transform(arg);
|
args[which_arg] = arg;
|
||||||
|
|
||||||
Node* p = basic_plus_adr(arg, class_klass_offset);
|
Node* p = basic_plus_adr(arg, class_klass_offset);
|
||||||
Node* kls = LoadKlassNode::make(_gvn, immutable_memory(), p, adr_type, kls_type);
|
Node* kls = LoadKlassNode::make(_gvn, immutable_memory(), p, adr_type, kls_type);
|
||||||
|
|
|
@ -1839,15 +1839,16 @@ uint Node::match_edge(uint idx) const {
|
||||||
return idx; // True for other than index 0 (control)
|
return idx; // True for other than index 0 (control)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static RegMask _not_used_at_all;
|
||||||
// Register classes are defined for specific machines
|
// Register classes are defined for specific machines
|
||||||
const RegMask &Node::out_RegMask() const {
|
const RegMask &Node::out_RegMask() const {
|
||||||
ShouldNotCallThis();
|
ShouldNotCallThis();
|
||||||
return *(new RegMask());
|
return _not_used_at_all;
|
||||||
}
|
}
|
||||||
|
|
||||||
const RegMask &Node::in_RegMask(uint) const {
|
const RegMask &Node::in_RegMask(uint) const {
|
||||||
ShouldNotCallThis();
|
ShouldNotCallThis();
|
||||||
return *(new RegMask());
|
return _not_used_at_all;
|
||||||
}
|
}
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
|
@ -509,6 +509,7 @@ void Parse::do_multianewarray() {
|
||||||
makecon(TypeKlassPtr::make(array_klass)),
|
makecon(TypeKlassPtr::make(array_klass)),
|
||||||
dims);
|
dims);
|
||||||
}
|
}
|
||||||
|
make_slow_call_ex(c, env()->Throwable_klass(), false);
|
||||||
|
|
||||||
Node* res = _gvn.transform(new (C) ProjNode(c, TypeFunc::Parms));
|
Node* res = _gvn.transform(new (C) ProjNode(c, TypeFunc::Parms));
|
||||||
|
|
||||||
|
|
|
@ -989,7 +989,7 @@ JRT_ENTRY_NO_ASYNC(address, OptoRuntime::handle_exception_C_helper(JavaThread* t
|
||||||
// since we're notifying the VM on every catch.
|
// since we're notifying the VM on every catch.
|
||||||
// Force deoptimization and the rest of the lookup
|
// Force deoptimization and the rest of the lookup
|
||||||
// will be fine.
|
// will be fine.
|
||||||
deoptimize_caller_frame(thread, true);
|
deoptimize_caller_frame(thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the stack guard pages. If enabled, look for handler in this frame;
|
// Check the stack guard pages. If enabled, look for handler in this frame;
|
||||||
|
@ -1143,19 +1143,24 @@ const TypeFunc *OptoRuntime::rethrow_Type() {
|
||||||
|
|
||||||
|
|
||||||
void OptoRuntime::deoptimize_caller_frame(JavaThread *thread, bool doit) {
|
void OptoRuntime::deoptimize_caller_frame(JavaThread *thread, bool doit) {
|
||||||
// Deoptimize frame
|
// Deoptimize the caller before continuing, as the compiled
|
||||||
if (doit) {
|
// exception handler table may not be valid.
|
||||||
// Called from within the owner thread, so no need for safepoint
|
if (!StressCompiledExceptionHandlers && doit) {
|
||||||
RegisterMap reg_map(thread);
|
deoptimize_caller_frame(thread);
|
||||||
frame stub_frame = thread->last_frame();
|
|
||||||
assert(stub_frame.is_runtime_frame() || exception_blob()->contains(stub_frame.pc()), "sanity check");
|
|
||||||
frame caller_frame = stub_frame.sender(®_map);
|
|
||||||
|
|
||||||
// Deoptimize the caller frame.
|
|
||||||
Deoptimization::deoptimize_frame(thread, caller_frame.id());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OptoRuntime::deoptimize_caller_frame(JavaThread *thread) {
|
||||||
|
// Called from within the owner thread, so no need for safepoint
|
||||||
|
RegisterMap reg_map(thread);
|
||||||
|
frame stub_frame = thread->last_frame();
|
||||||
|
assert(stub_frame.is_runtime_frame() || exception_blob()->contains(stub_frame.pc()), "sanity check");
|
||||||
|
frame caller_frame = stub_frame.sender(®_map);
|
||||||
|
|
||||||
|
// Deoptimize the caller frame.
|
||||||
|
Deoptimization::deoptimize_frame(thread, caller_frame.id());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool OptoRuntime::is_deoptimized_caller_frame(JavaThread *thread) {
|
bool OptoRuntime::is_deoptimized_caller_frame(JavaThread *thread) {
|
||||||
// Called from within the owner thread, so no need for safepoint
|
// Called from within the owner thread, so no need for safepoint
|
||||||
|
|
|
@ -174,6 +174,7 @@ private:
|
||||||
static address handle_exception_C (JavaThread* thread);
|
static address handle_exception_C (JavaThread* thread);
|
||||||
static address handle_exception_C_helper(JavaThread* thread, nmethod*& nm);
|
static address handle_exception_C_helper(JavaThread* thread, nmethod*& nm);
|
||||||
static address rethrow_C (oopDesc* exception, JavaThread *thread, address return_pc );
|
static address rethrow_C (oopDesc* exception, JavaThread *thread, address return_pc );
|
||||||
|
static void deoptimize_caller_frame (JavaThread *thread);
|
||||||
static void deoptimize_caller_frame (JavaThread *thread, bool doit);
|
static void deoptimize_caller_frame (JavaThread *thread, bool doit);
|
||||||
static bool is_deoptimized_caller_frame (JavaThread *thread);
|
static bool is_deoptimized_caller_frame (JavaThread *thread);
|
||||||
|
|
||||||
|
|
|
@ -744,7 +744,9 @@ bool StringConcat::validate_control_flow() {
|
||||||
ctrl_path.push(cn);
|
ctrl_path.push(cn);
|
||||||
ctrl_path.push(cn->proj_out(0));
|
ctrl_path.push(cn->proj_out(0));
|
||||||
ctrl_path.push(cn->proj_out(0)->unique_out());
|
ctrl_path.push(cn->proj_out(0)->unique_out());
|
||||||
ctrl_path.push(cn->proj_out(0)->unique_out()->as_Catch()->proj_out(0));
|
if (cn->proj_out(0)->unique_out()->as_Catch()->proj_out(0) != NULL) {
|
||||||
|
ctrl_path.push(cn->proj_out(0)->unique_out()->as_Catch()->proj_out(0));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ShouldNotReachHere();
|
ShouldNotReachHere();
|
||||||
}
|
}
|
||||||
|
@ -762,6 +764,12 @@ bool StringConcat::validate_control_flow() {
|
||||||
} else if (ptr->is_IfTrue()) {
|
} else if (ptr->is_IfTrue()) {
|
||||||
IfNode* iff = ptr->in(0)->as_If();
|
IfNode* iff = ptr->in(0)->as_If();
|
||||||
BoolNode* b = iff->in(1)->isa_Bool();
|
BoolNode* b = iff->in(1)->isa_Bool();
|
||||||
|
|
||||||
|
if (b == NULL) {
|
||||||
|
fail = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
Node* cmp = b->in(1);
|
Node* cmp = b->in(1);
|
||||||
Node* v1 = cmp->in(1);
|
Node* v1 = cmp->in(1);
|
||||||
Node* v2 = cmp->in(2);
|
Node* v2 = cmp->in(2);
|
||||||
|
@ -1408,71 +1416,76 @@ void PhaseStringOpts::replace_string_concat(StringConcat* sc) {
|
||||||
Deoptimization::Action_make_not_entrant);
|
Deoptimization::Action_make_not_entrant);
|
||||||
}
|
}
|
||||||
|
|
||||||
// length now contains the number of characters needed for the
|
Node* result;
|
||||||
// char[] so create a new AllocateArray for the char[]
|
if (!kit.stopped()) {
|
||||||
Node* char_array = NULL;
|
|
||||||
{
|
|
||||||
PreserveReexecuteState preexecs(&kit);
|
|
||||||
// The original jvms is for an allocation of either a String or
|
|
||||||
// StringBuffer so no stack adjustment is necessary for proper
|
|
||||||
// reexecution. If we deoptimize in the slow path the bytecode
|
|
||||||
// will be reexecuted and the char[] allocation will be thrown away.
|
|
||||||
kit.jvms()->set_should_reexecute(true);
|
|
||||||
char_array = kit.new_array(__ makecon(TypeKlassPtr::make(ciTypeArrayKlass::make(T_CHAR))),
|
|
||||||
length, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mark the allocation so that zeroing is skipped since the code
|
// length now contains the number of characters needed for the
|
||||||
// below will overwrite the entire array
|
// char[] so create a new AllocateArray for the char[]
|
||||||
AllocateArrayNode* char_alloc = AllocateArrayNode::Ideal_array_allocation(char_array, _gvn);
|
Node* char_array = NULL;
|
||||||
char_alloc->maybe_set_complete(_gvn);
|
{
|
||||||
|
PreserveReexecuteState preexecs(&kit);
|
||||||
// Now copy the string representations into the final char[]
|
// The original jvms is for an allocation of either a String or
|
||||||
Node* start = __ intcon(0);
|
// StringBuffer so no stack adjustment is necessary for proper
|
||||||
for (int argi = 0; argi < sc->num_arguments(); argi++) {
|
// reexecution. If we deoptimize in the slow path the bytecode
|
||||||
Node* arg = sc->argument(argi);
|
// will be reexecuted and the char[] allocation will be thrown away.
|
||||||
switch (sc->mode(argi)) {
|
kit.jvms()->set_should_reexecute(true);
|
||||||
case StringConcat::IntMode: {
|
char_array = kit.new_array(__ makecon(TypeKlassPtr::make(ciTypeArrayKlass::make(T_CHAR))),
|
||||||
Node* end = __ AddI(start, string_sizes->in(argi));
|
length, 1);
|
||||||
// getChars words backwards so pass the ending point as well as the start
|
|
||||||
int_getChars(kit, arg, char_array, start, end);
|
|
||||||
start = end;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case StringConcat::StringNullCheckMode:
|
|
||||||
case StringConcat::StringMode: {
|
|
||||||
start = copy_string(kit, arg, char_array, start);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case StringConcat::CharMode: {
|
|
||||||
__ store_to_memory(kit.control(), kit.array_element_address(char_array, start, T_CHAR),
|
|
||||||
arg, T_CHAR, char_adr_idx);
|
|
||||||
start = __ AddI(start, __ intcon(1));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
ShouldNotReachHere();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// If we're not reusing an existing String allocation then allocate one here.
|
// Mark the allocation so that zeroing is skipped since the code
|
||||||
Node* result = sc->string_alloc();
|
// below will overwrite the entire array
|
||||||
if (result == NULL) {
|
AllocateArrayNode* char_alloc = AllocateArrayNode::Ideal_array_allocation(char_array, _gvn);
|
||||||
PreserveReexecuteState preexecs(&kit);
|
char_alloc->maybe_set_complete(_gvn);
|
||||||
// The original jvms is for an allocation of either a String or
|
|
||||||
// StringBuffer so no stack adjustment is necessary for proper
|
|
||||||
// reexecution.
|
|
||||||
kit.jvms()->set_should_reexecute(true);
|
|
||||||
result = kit.new_instance(__ makecon(TypeKlassPtr::make(C->env()->String_klass())));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Intialize the string
|
// Now copy the string representations into the final char[]
|
||||||
if (java_lang_String::has_offset_field()) {
|
Node* start = __ intcon(0);
|
||||||
kit.store_String_offset(kit.control(), result, __ intcon(0));
|
for (int argi = 0; argi < sc->num_arguments(); argi++) {
|
||||||
kit.store_String_length(kit.control(), result, length);
|
Node* arg = sc->argument(argi);
|
||||||
}
|
switch (sc->mode(argi)) {
|
||||||
kit.store_String_value(kit.control(), result, char_array);
|
case StringConcat::IntMode: {
|
||||||
|
Node* end = __ AddI(start, string_sizes->in(argi));
|
||||||
|
// getChars words backwards so pass the ending point as well as the start
|
||||||
|
int_getChars(kit, arg, char_array, start, end);
|
||||||
|
start = end;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case StringConcat::StringNullCheckMode:
|
||||||
|
case StringConcat::StringMode: {
|
||||||
|
start = copy_string(kit, arg, char_array, start);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case StringConcat::CharMode: {
|
||||||
|
__ store_to_memory(kit.control(), kit.array_element_address(char_array, start, T_CHAR),
|
||||||
|
arg, T_CHAR, char_adr_idx);
|
||||||
|
start = __ AddI(start, __ intcon(1));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
ShouldNotReachHere();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're not reusing an existing String allocation then allocate one here.
|
||||||
|
result = sc->string_alloc();
|
||||||
|
if (result == NULL) {
|
||||||
|
PreserveReexecuteState preexecs(&kit);
|
||||||
|
// The original jvms is for an allocation of either a String or
|
||||||
|
// StringBuffer so no stack adjustment is necessary for proper
|
||||||
|
// reexecution.
|
||||||
|
kit.jvms()->set_should_reexecute(true);
|
||||||
|
result = kit.new_instance(__ makecon(TypeKlassPtr::make(C->env()->String_klass())));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Intialize the string
|
||||||
|
if (java_lang_String::has_offset_field()) {
|
||||||
|
kit.store_String_offset(kit.control(), result, __ intcon(0));
|
||||||
|
kit.store_String_length(kit.control(), result, length);
|
||||||
|
}
|
||||||
|
kit.store_String_value(kit.control(), result, char_array);
|
||||||
|
} else {
|
||||||
|
result = C->top();
|
||||||
|
}
|
||||||
// hook up the outgoing control and result
|
// hook up the outgoing control and result
|
||||||
kit.replace_call(sc->end(), result);
|
kit.replace_call(sc->end(), result);
|
||||||
|
|
||||||
|
|
|
@ -1168,8 +1168,8 @@ JVM_ENTRY(void, MHN_setCallSiteTargetNormal(JNIEnv* env, jobject igcls, jobject
|
||||||
// Walk all nmethods depending on this call site.
|
// Walk all nmethods depending on this call site.
|
||||||
MutexLocker mu(Compile_lock, thread);
|
MutexLocker mu(Compile_lock, thread);
|
||||||
Universe::flush_dependents_on(call_site, target);
|
Universe::flush_dependents_on(call_site, target);
|
||||||
|
java_lang_invoke_CallSite::set_target(call_site(), target());
|
||||||
}
|
}
|
||||||
java_lang_invoke_CallSite::set_target(call_site(), target());
|
|
||||||
}
|
}
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
@ -1180,8 +1180,8 @@ JVM_ENTRY(void, MHN_setCallSiteTargetVolatile(JNIEnv* env, jobject igcls, jobjec
|
||||||
// Walk all nmethods depending on this call site.
|
// Walk all nmethods depending on this call site.
|
||||||
MutexLocker mu(Compile_lock, thread);
|
MutexLocker mu(Compile_lock, thread);
|
||||||
Universe::flush_dependents_on(call_site, target);
|
Universe::flush_dependents_on(call_site, target);
|
||||||
|
java_lang_invoke_CallSite::set_target_volatile(call_site(), target());
|
||||||
}
|
}
|
||||||
java_lang_invoke_CallSite::set_target_volatile(call_site(), target());
|
|
||||||
}
|
}
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
|
|
@ -468,6 +468,21 @@ UNSAFE_ENTRY(void, Unsafe_SetOrderedLong(JNIEnv *env, jobject unsafe, jobject ob
|
||||||
#endif
|
#endif
|
||||||
UNSAFE_END
|
UNSAFE_END
|
||||||
|
|
||||||
|
UNSAFE_ENTRY(void, Unsafe_LoadFence(JNIEnv *env, jobject unsafe))
|
||||||
|
UnsafeWrapper("Unsafe_LoadFence");
|
||||||
|
OrderAccess::acquire();
|
||||||
|
UNSAFE_END
|
||||||
|
|
||||||
|
UNSAFE_ENTRY(void, Unsafe_StoreFence(JNIEnv *env, jobject unsafe))
|
||||||
|
UnsafeWrapper("Unsafe_StoreFence");
|
||||||
|
OrderAccess::release();
|
||||||
|
UNSAFE_END
|
||||||
|
|
||||||
|
UNSAFE_ENTRY(void, Unsafe_FullFence(JNIEnv *env, jobject unsafe))
|
||||||
|
UnsafeWrapper("Unsafe_FullFence");
|
||||||
|
OrderAccess::fence();
|
||||||
|
UNSAFE_END
|
||||||
|
|
||||||
////// Data in the C heap.
|
////// Data in the C heap.
|
||||||
|
|
||||||
// Note: These do not throw NullPointerException for bad pointers.
|
// Note: These do not throw NullPointerException for bad pointers.
|
||||||
|
@ -1550,6 +1565,9 @@ static JNINativeMethod methods[] = {
|
||||||
{CC"putOrderedObject", CC"("OBJ"J"OBJ")V", FN_PTR(Unsafe_SetOrderedObject)},
|
{CC"putOrderedObject", CC"("OBJ"J"OBJ")V", FN_PTR(Unsafe_SetOrderedObject)},
|
||||||
{CC"putOrderedInt", CC"("OBJ"JI)V", FN_PTR(Unsafe_SetOrderedInt)},
|
{CC"putOrderedInt", CC"("OBJ"JI)V", FN_PTR(Unsafe_SetOrderedInt)},
|
||||||
{CC"putOrderedLong", CC"("OBJ"JJ)V", FN_PTR(Unsafe_SetOrderedLong)},
|
{CC"putOrderedLong", CC"("OBJ"JJ)V", FN_PTR(Unsafe_SetOrderedLong)},
|
||||||
|
{CC"loadFence", CC"()V", FN_PTR(Unsafe_LoadFence)},
|
||||||
|
{CC"storeFence", CC"()V", FN_PTR(Unsafe_StoreFence)},
|
||||||
|
{CC"fullFence", CC"()V", FN_PTR(Unsafe_FullFence)},
|
||||||
{CC"park", CC"(ZJ)V", FN_PTR(Unsafe_Park)},
|
{CC"park", CC"(ZJ)V", FN_PTR(Unsafe_Park)},
|
||||||
{CC"unpark", CC"("OBJ")V", FN_PTR(Unsafe_Unpark)}
|
{CC"unpark", CC"("OBJ")V", FN_PTR(Unsafe_Unpark)}
|
||||||
|
|
||||||
|
|
|
@ -1499,13 +1499,12 @@ void Arguments::set_g1_gc_flags() {
|
||||||
Abstract_VM_Version::parallel_worker_threads());
|
Abstract_VM_Version::parallel_worker_threads());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FLAG_IS_DEFAULT(MarkStackSize)) {
|
// MarkStackSize will be set (if it hasn't been set by the user)
|
||||||
FLAG_SET_DEFAULT(MarkStackSize, 128 * TASKQUEUE_SIZE);
|
// when concurrent marking is initialized.
|
||||||
}
|
// Its value will be based upon the number of parallel marking threads.
|
||||||
if (PrintGCDetails && Verbose) {
|
// But we do set the maximum mark stack size here.
|
||||||
tty->print_cr("MarkStackSize: %uk MarkStackSizeMax: %uk",
|
if (FLAG_IS_DEFAULT(MarkStackSizeMax)) {
|
||||||
MarkStackSize / K, MarkStackSizeMax / K);
|
FLAG_SET_DEFAULT(MarkStackSizeMax, 128 * TASKQUEUE_SIZE);
|
||||||
tty->print_cr("ConcGCThreads: %u", ConcGCThreads);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FLAG_IS_DEFAULT(GCTimeRatio) || GCTimeRatio == 0) {
|
if (FLAG_IS_DEFAULT(GCTimeRatio) || GCTimeRatio == 0) {
|
||||||
|
@ -1517,6 +1516,12 @@ void Arguments::set_g1_gc_flags() {
|
||||||
// is allocation). We might consider increase it further.
|
// is allocation). We might consider increase it further.
|
||||||
FLAG_SET_DEFAULT(GCTimeRatio, 9);
|
FLAG_SET_DEFAULT(GCTimeRatio, 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (PrintGCDetails && Verbose) {
|
||||||
|
tty->print_cr("MarkStackSize: %uk MarkStackSizeMax: %uk",
|
||||||
|
MarkStackSize / K, MarkStackSizeMax / K);
|
||||||
|
tty->print_cr("ConcGCThreads: %u", ConcGCThreads);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Arguments::set_heap_size() {
|
void Arguments::set_heap_size() {
|
||||||
|
@ -1980,6 +1985,9 @@ bool Arguments::check_vm_args_consistency() {
|
||||||
status = status && verify_min_value(ClassMetaspaceSize, 1*M,
|
status = status && verify_min_value(ClassMetaspaceSize, 1*M,
|
||||||
"ClassMetaspaceSize");
|
"ClassMetaspaceSize");
|
||||||
|
|
||||||
|
status = status && verify_interval(MarkStackSizeMax,
|
||||||
|
1, (max_jint - 1), "MarkStackSizeMax");
|
||||||
|
|
||||||
#ifdef SPARC
|
#ifdef SPARC
|
||||||
if (UseConcMarkSweepGC || UseG1GC) {
|
if (UseConcMarkSweepGC || UseG1GC) {
|
||||||
// Issue a stern warning if the user has explicitly set
|
// Issue a stern warning if the user has explicitly set
|
||||||
|
|
|
@ -922,6 +922,9 @@ class CommandLineFlags {
|
||||||
develop(bool, PrintExceptionHandlers, false, \
|
develop(bool, PrintExceptionHandlers, false, \
|
||||||
"Print exception handler tables for all nmethods when generated") \
|
"Print exception handler tables for all nmethods when generated") \
|
||||||
\
|
\
|
||||||
|
develop(bool, StressCompiledExceptionHandlers, false, \
|
||||||
|
"Exercise compiled exception handlers") \
|
||||||
|
\
|
||||||
develop(bool, InterceptOSException, false, \
|
develop(bool, InterceptOSException, false, \
|
||||||
"Starts debugger when an implicit OS (e.g., NULL) " \
|
"Starts debugger when an implicit OS (e.g., NULL) " \
|
||||||
"exception happens") \
|
"exception happens") \
|
||||||
|
|
|
@ -255,6 +255,7 @@ class os: AllStatic {
|
||||||
static int vm_allocation_granularity();
|
static int vm_allocation_granularity();
|
||||||
static char* reserve_memory(size_t bytes, char* addr = 0,
|
static char* reserve_memory(size_t bytes, char* addr = 0,
|
||||||
size_t alignment_hint = 0);
|
size_t alignment_hint = 0);
|
||||||
|
static char* reserve_memory_aligned(size_t size, size_t alignment);
|
||||||
static char* attempt_reserve_memory_at(size_t bytes, char* addr);
|
static char* attempt_reserve_memory_at(size_t bytes, char* addr);
|
||||||
static void split_reserved_memory(char *base, size_t size,
|
static void split_reserved_memory(char *base, size_t size,
|
||||||
size_t split, bool realloc);
|
size_t split, bool realloc);
|
||||||
|
|
|
@ -2190,7 +2190,7 @@ void JavaThread::send_thread_stop(oop java_throwable) {
|
||||||
// BiasedLocking needs an updated RegisterMap for the revoke monitors pass
|
// BiasedLocking needs an updated RegisterMap for the revoke monitors pass
|
||||||
RegisterMap reg_map(this, UseBiasedLocking);
|
RegisterMap reg_map(this, UseBiasedLocking);
|
||||||
frame compiled_frame = f.sender(®_map);
|
frame compiled_frame = f.sender(®_map);
|
||||||
if (compiled_frame.can_be_deoptimized()) {
|
if (!StressCompiledExceptionHandlers && compiled_frame.can_be_deoptimized()) {
|
||||||
Deoptimization::deoptimize(this, compiled_frame, ®_map);
|
Deoptimization::deoptimize(this, compiled_frame, ®_map);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3527,11 +3527,12 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
|
||||||
java_lang_Thread::set_thread_status(thread_object,
|
java_lang_Thread::set_thread_status(thread_object,
|
||||||
java_lang_Thread::RUNNABLE);
|
java_lang_Thread::RUNNABLE);
|
||||||
|
|
||||||
// The VM preresolve methods to these classes. Make sure that get initialized
|
|
||||||
initialize_class(vmSymbols::java_lang_reflect_Method(), CHECK_0);
|
|
||||||
initialize_class(vmSymbols::java_lang_ref_Finalizer(), CHECK_0);
|
|
||||||
// The VM creates & returns objects of this class. Make sure it's initialized.
|
// The VM creates & returns objects of this class. Make sure it's initialized.
|
||||||
initialize_class(vmSymbols::java_lang_Class(), CHECK_0);
|
initialize_class(vmSymbols::java_lang_Class(), CHECK_0);
|
||||||
|
|
||||||
|
// The VM preresolves methods to these classes. Make sure that they get initialized
|
||||||
|
initialize_class(vmSymbols::java_lang_reflect_Method(), CHECK_0);
|
||||||
|
initialize_class(vmSymbols::java_lang_ref_Finalizer(), CHECK_0);
|
||||||
call_initializeSystemClass(CHECK_0);
|
call_initializeSystemClass(CHECK_0);
|
||||||
|
|
||||||
// get the Java runtime name after java.lang.System is initialized
|
// get the Java runtime name after java.lang.System is initialized
|
||||||
|
|
|
@ -329,20 +329,9 @@ void ReservedSpace::initialize(size_t size, size_t alignment, bool large,
|
||||||
if ((((size_t)base + noaccess_prefix) & (alignment - 1)) != 0) {
|
if ((((size_t)base + noaccess_prefix) & (alignment - 1)) != 0) {
|
||||||
// Base not aligned, retry
|
// Base not aligned, retry
|
||||||
if (!os::release_memory(base, size)) fatal("os::release_memory failed");
|
if (!os::release_memory(base, size)) fatal("os::release_memory failed");
|
||||||
// Reserve size large enough to do manual alignment and
|
// Make sure that size is aligned
|
||||||
// increase size to a multiple of the desired alignment
|
|
||||||
size = align_size_up(size, alignment);
|
size = align_size_up(size, alignment);
|
||||||
size_t extra_size = size + alignment;
|
base = os::reserve_memory_aligned(size, alignment);
|
||||||
do {
|
|
||||||
char* extra_base = os::reserve_memory(extra_size, NULL, alignment);
|
|
||||||
if (extra_base == NULL) return;
|
|
||||||
// Do manual alignement
|
|
||||||
base = (char*) align_size_up((uintptr_t) extra_base, alignment);
|
|
||||||
assert(base >= extra_base, "just checking");
|
|
||||||
// Re-reserve the region at the aligned base address.
|
|
||||||
os::release_memory(extra_base, extra_size);
|
|
||||||
base = os::reserve_memory(size, base);
|
|
||||||
} while (base == NULL);
|
|
||||||
|
|
||||||
if (requested_address != 0 &&
|
if (requested_address != 0 &&
|
||||||
failed_to_reserve_as_requested(base, requested_address, size, false)) {
|
failed_to_reserve_as_requested(base, requested_address, size, false)) {
|
||||||
|
|
|
@ -355,8 +355,6 @@ typedef BinaryTreeDictionary<Metablock, FreeList> MetablockTreeDictionary;
|
||||||
nonstatic_field(Method, _access_flags, AccessFlags) \
|
nonstatic_field(Method, _access_flags, AccessFlags) \
|
||||||
nonstatic_field(Method, _vtable_index, int) \
|
nonstatic_field(Method, _vtable_index, int) \
|
||||||
nonstatic_field(Method, _method_size, u2) \
|
nonstatic_field(Method, _method_size, u2) \
|
||||||
nonstatic_field(Method, _max_locals, u2) \
|
|
||||||
nonstatic_field(Method, _size_of_parameters, u2) \
|
|
||||||
nonstatic_field(Method, _interpreter_throwout_count, u2) \
|
nonstatic_field(Method, _interpreter_throwout_count, u2) \
|
||||||
nonstatic_field(Method, _number_of_breakpoints, u2) \
|
nonstatic_field(Method, _number_of_breakpoints, u2) \
|
||||||
nonstatic_field(Method, _invocation_counter, InvocationCounter) \
|
nonstatic_field(Method, _invocation_counter, InvocationCounter) \
|
||||||
|
@ -378,6 +376,8 @@ typedef BinaryTreeDictionary<Metablock, FreeList> MetablockTreeDictionary;
|
||||||
nonstatic_field(ConstMethod, _signature_index, u2) \
|
nonstatic_field(ConstMethod, _signature_index, u2) \
|
||||||
nonstatic_field(ConstMethod, _method_idnum, u2) \
|
nonstatic_field(ConstMethod, _method_idnum, u2) \
|
||||||
nonstatic_field(ConstMethod, _max_stack, u2) \
|
nonstatic_field(ConstMethod, _max_stack, u2) \
|
||||||
|
nonstatic_field(ConstMethod, _max_locals, u2) \
|
||||||
|
nonstatic_field(ConstMethod, _size_of_parameters, u2) \
|
||||||
nonstatic_field(ObjArrayKlass, _element_klass, Klass*) \
|
nonstatic_field(ObjArrayKlass, _element_klass, Klass*) \
|
||||||
nonstatic_field(ObjArrayKlass, _bottom_klass, Klass*) \
|
nonstatic_field(ObjArrayKlass, _bottom_klass, Klass*) \
|
||||||
volatile_nonstatic_field(Symbol, _refcount, int) \
|
volatile_nonstatic_field(Symbol, _refcount, int) \
|
||||||
|
|
|
@ -334,7 +334,7 @@ class MemBaseline : public _ValueObj {
|
||||||
// create a memory baseline
|
// create a memory baseline
|
||||||
MemBaseline();
|
MemBaseline();
|
||||||
|
|
||||||
virtual ~MemBaseline();
|
~MemBaseline();
|
||||||
|
|
||||||
inline bool baselined() const {
|
inline bool baselined() const {
|
||||||
return _baselined;
|
return _baselined;
|
||||||
|
|
|
@ -90,7 +90,7 @@ protected:
|
||||||
NOT_PRODUCT(_name = name);
|
NOT_PRODUCT(_name = name);
|
||||||
_counter = 0;
|
_counter = 0;
|
||||||
}
|
}
|
||||||
virtual ~AbstractGangTask() { }
|
~AbstractGangTask() { }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
};
|
};
|
||||||
|
|
|
@ -106,7 +106,7 @@ protected:
|
||||||
_status(INACTIVE),
|
_status(INACTIVE),
|
||||||
_gang(NULL) { }
|
_gang(NULL) { }
|
||||||
|
|
||||||
virtual ~YieldingFlexibleGangTask() { }
|
~YieldingFlexibleGangTask() { }
|
||||||
|
|
||||||
friend class YieldingFlexibleWorkGang;
|
friend class YieldingFlexibleWorkGang;
|
||||||
friend class YieldingFlexibleGangWorker;
|
friend class YieldingFlexibleGangWorker;
|
||||||
|
|
|
@ -54,7 +54,6 @@ abstract public class TestAESBase {
|
||||||
String paddingStr = "PKCS5Padding";
|
String paddingStr = "PKCS5Padding";
|
||||||
AlgorithmParameters algParams;
|
AlgorithmParameters algParams;
|
||||||
SecretKey key;
|
SecretKey key;
|
||||||
int ivLen;
|
|
||||||
|
|
||||||
static int numThreads = 0;
|
static int numThreads = 0;
|
||||||
int threadId;
|
int threadId;
|
||||||
|
@ -68,7 +67,7 @@ abstract public class TestAESBase {
|
||||||
|
|
||||||
public void prepare() {
|
public void prepare() {
|
||||||
try {
|
try {
|
||||||
System.out.println("\nmsgSize=" + msgSize + ", key size=" + keySize + ", reInit=" + !noReinit + ", checkOutput=" + checkOutput);
|
System.out.println("\nalgorithm=" + algorithm + ", mode=" + mode + ", msgSize=" + msgSize + ", keySize=" + keySize + ", noReinit=" + noReinit + ", checkOutput=" + checkOutput);
|
||||||
|
|
||||||
int keyLenBytes = (keySize == 0 ? 16 : keySize/8);
|
int keyLenBytes = (keySize == 0 ? 16 : keySize/8);
|
||||||
byte keyBytes[] = new byte[keyLenBytes];
|
byte keyBytes[] = new byte[keyLenBytes];
|
||||||
|
@ -90,10 +89,14 @@ abstract public class TestAESBase {
|
||||||
cipher = Cipher.getInstance(algorithm + "/" + mode + "/" + paddingStr, "SunJCE");
|
cipher = Cipher.getInstance(algorithm + "/" + mode + "/" + paddingStr, "SunJCE");
|
||||||
dCipher = Cipher.getInstance(algorithm + "/" + mode + "/" + paddingStr, "SunJCE");
|
dCipher = Cipher.getInstance(algorithm + "/" + mode + "/" + paddingStr, "SunJCE");
|
||||||
|
|
||||||
ivLen = (algorithm.equals("AES") ? 16 : algorithm.equals("DES") ? 8 : 0);
|
if (mode.equals("CBC")) {
|
||||||
IvParameterSpec initVector = new IvParameterSpec(new byte[ivLen]);
|
int ivLen = (algorithm.equals("AES") ? 16 : algorithm.equals("DES") ? 8 : 0);
|
||||||
|
IvParameterSpec initVector = new IvParameterSpec(new byte[ivLen]);
|
||||||
cipher.init(Cipher.ENCRYPT_MODE, key, initVector);
|
cipher.init(Cipher.ENCRYPT_MODE, key, initVector);
|
||||||
|
} else {
|
||||||
|
algParams = cipher.getParameters();
|
||||||
|
cipher.init(Cipher.ENCRYPT_MODE, key, algParams);
|
||||||
|
}
|
||||||
algParams = cipher.getParameters();
|
algParams = cipher.getParameters();
|
||||||
dCipher.init(Cipher.DECRYPT_MODE, key, algParams);
|
dCipher.init(Cipher.DECRYPT_MODE, key, algParams);
|
||||||
if (threadId == 0) {
|
if (threadId == 0) {
|
||||||
|
|
|
@ -27,7 +27,8 @@
|
||||||
* @bug 7184394
|
* @bug 7184394
|
||||||
* @summary add intrinsics to use AES instructions
|
* @summary add intrinsics to use AES instructions
|
||||||
*
|
*
|
||||||
* @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true TestAESMain
|
* @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=CBC TestAESMain
|
||||||
|
* @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=ECB TestAESMain
|
||||||
*
|
*
|
||||||
* @author Tom Deneau
|
* @author Tom Deneau
|
||||||
*/
|
*/
|
||||||
|
|
94
hotspot/test/compiler/8004741/Test8004741.java
Normal file
94
hotspot/test/compiler/8004741/Test8004741.java
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test Test8004741.java
|
||||||
|
* @bug 8004741
|
||||||
|
* @summary Missing compiled exception handle table entry for multidimensional array allocation
|
||||||
|
* @run main/othervm -Xmx64m -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:+StressCompiledExceptionHandlers Test8004741
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class Test8004741 extends Thread {
|
||||||
|
|
||||||
|
static int[][] test(int a, int b) throws Exception {
|
||||||
|
int[][] ar = null;
|
||||||
|
try {
|
||||||
|
ar = new int[a][b];
|
||||||
|
} catch (Error e) {
|
||||||
|
System.out.println("test got Error");
|
||||||
|
passed = true;
|
||||||
|
throw(e);
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("test got Exception");
|
||||||
|
throw(e);
|
||||||
|
}
|
||||||
|
return ar;
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean passed = false;
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
System.out.println("test started");
|
||||||
|
try {
|
||||||
|
while(true) {
|
||||||
|
test(2,20000);
|
||||||
|
}
|
||||||
|
} catch (ThreadDeath e) {
|
||||||
|
System.out.println("test got ThreadDeath");
|
||||||
|
passed = true;
|
||||||
|
} catch (Error e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
System.out.println("test got Error");
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
System.out.println("test got Exception");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
for (int n = 0; n < 11000; n++) {
|
||||||
|
test(2, 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
// First test exception catch
|
||||||
|
Test8004741 t = new Test8004741();
|
||||||
|
|
||||||
|
passed = false;
|
||||||
|
t.start();
|
||||||
|
Thread.sleep(1000);
|
||||||
|
t.stop();
|
||||||
|
|
||||||
|
Thread.sleep(5000);
|
||||||
|
t.join();
|
||||||
|
if (passed) {
|
||||||
|
System.out.println("PASSED");
|
||||||
|
} else {
|
||||||
|
System.out.println("FAILED");
|
||||||
|
System.exit(97);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
50
hotspot/test/compiler/8005033/Test8005033.java
Normal file
50
hotspot/test/compiler/8005033/Test8005033.java
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012 SAP AG. 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @bug 8005033
|
||||||
|
* @summary On sparcv9, C2's intrinsic for Integer.bitCount(OV) returns wrong result if OV is the result of an operation with int overflow.
|
||||||
|
* @run main/othervm -Xcomp -XX:CompileOnly=Test8005033::testBitCount Test8005033
|
||||||
|
* @author Richard Reingruber richard DOT reingruber AT sap DOT com
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Test8005033 {
|
||||||
|
public static int MINUS_ONE = -1;
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
System.out.println("EXECUTING test.");
|
||||||
|
Integer.bitCount(1); // load class
|
||||||
|
int expectedBitCount = 0;
|
||||||
|
int calculatedBitCount = testBitCount();
|
||||||
|
if (expectedBitCount != calculatedBitCount) {
|
||||||
|
throw new InternalError("got " + calculatedBitCount + " but expected " + expectedBitCount);
|
||||||
|
}
|
||||||
|
System.out.println("SUCCESSFULLY passed test.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// testBitCount will be compiled using the Integer.bitCount() intrinsic if possible
|
||||||
|
private static int testBitCount() {
|
||||||
|
return Integer.bitCount(MINUS_ONE+1); // -1 + 1 => int overflow
|
||||||
|
}
|
||||||
|
}
|
40
hotspot/test/sanity/ExecuteInternalVMTests.java
Normal file
40
hotspot/test/sanity/ExecuteInternalVMTests.java
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* @test ExecuteInternalVMTests
|
||||||
|
* @bug 8004691
|
||||||
|
* @summary Add a jtreg test that exercises the ExecuteInternalVMTests flag
|
||||||
|
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+ExecuteInternalVMTests ExecuteInternalVMTests
|
||||||
|
*/
|
||||||
|
public class ExecuteInternalVMTests {
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
// The tests that are run are the HotSpot internal tests which are
|
||||||
|
// executed only when the flag -XX:+ExecuteInternalVMTests is used.
|
||||||
|
|
||||||
|
// The flag -XX:+ExecuteInternalVMTests can only be used for
|
||||||
|
// non-product builds of HotSpot. Therefore, the flag
|
||||||
|
// -XX:+IgnoreUnrecognizedVMOptions is also used, which means that this
|
||||||
|
// test will do nothing on a product build.
|
||||||
|
}
|
||||||
|
}
|
|
@ -189,3 +189,4 @@ af9e8b0f1900b631a8a0fcccff9f1514fe58c808 jdk8-b59
|
||||||
5cf3c69a93d6d088a1cdfa28031d4f0f9438c0de jdk8-b65
|
5cf3c69a93d6d088a1cdfa28031d4f0f9438c0de jdk8-b65
|
||||||
e6af1ad464e3d9b1154b9f9ed9a5373b97d129fc jdk8-b66
|
e6af1ad464e3d9b1154b9f9ed9a5373b97d129fc jdk8-b66
|
||||||
83df3493ca3cf0be077f1d0dd90119456f266f54 jdk8-b67
|
83df3493ca3cf0be077f1d0dd90119456f266f54 jdk8-b67
|
||||||
|
b854e70084214e9dcf1b37373f6e4b1a68760e03 jdk8-b68
|
||||||
|
|
|
@ -189,3 +189,4 @@ d265b9b4c0f55c23a1c9fda02a8052fd9df2eec5 jdk8-b62
|
||||||
fbe54291c9d337ea4dfef4d846f1d9a22f76249c jdk8-b65
|
fbe54291c9d337ea4dfef4d846f1d9a22f76249c jdk8-b65
|
||||||
3eb7f11cb4e000555c1b6f0f1a10fe2919633c8e jdk8-b66
|
3eb7f11cb4e000555c1b6f0f1a10fe2919633c8e jdk8-b66
|
||||||
eb06aa51dfc225614dba2d89ae7ca6cedddff982 jdk8-b67
|
eb06aa51dfc225614dba2d89ae7ca6cedddff982 jdk8-b67
|
||||||
|
d3fe408f3a9ad250bc9a4e9365bdfc3f28c1d3f4 jdk8-b68
|
||||||
|
|
|
@ -189,3 +189,4 @@ f117a3e06f78a258074674ad17601f99bcb1ce0d jdk8-b63
|
||||||
130d3a54d28becaac0846137256c2684adb34c33 jdk8-b65
|
130d3a54d28becaac0846137256c2684adb34c33 jdk8-b65
|
||||||
4d337fae2250135729ee9ed2bf8baf3c60da5d6d jdk8-b66
|
4d337fae2250135729ee9ed2bf8baf3c60da5d6d jdk8-b66
|
||||||
ce9b02a3a17edd1983201002cfa0f364e4ab7524 jdk8-b67
|
ce9b02a3a17edd1983201002cfa0f364e4ab7524 jdk8-b67
|
||||||
|
53fb43e4d614c92310e1fb00ec41d1960fd9facf jdk8-b68
|
||||||
|
|
|
@ -35,7 +35,7 @@ SUBDIRS_MAKEFLAGS += JAVAC_WARNINGS_FATAL=true
|
||||||
include $(BUILDDIR)/common/Defs.gmk
|
include $(BUILDDIR)/common/Defs.gmk
|
||||||
|
|
||||||
SUBDIRS = auth
|
SUBDIRS = auth
|
||||||
SUBDIRS_misc = jgss sasl auth/module
|
SUBDIRS_misc = jgss sasl auth/module ntlm
|
||||||
include $(BUILDDIR)/common/Subdirs.gmk
|
include $(BUILDDIR)/common/Subdirs.gmk
|
||||||
|
|
||||||
all build clean clobber::
|
all build clean clobber::
|
||||||
|
|
39
jdk/make/com/sun/security/ntlm/Makefile
Normal file
39
jdk/make/com/sun/security/ntlm/Makefile
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#
|
||||||
|
# Copyright (c) 2012, 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
BUILDDIR = ../../../..
|
||||||
|
PACKAGE = com.sun.security.ntlm
|
||||||
|
PRODUCT = sun
|
||||||
|
include $(BUILDDIR)/common/Defs.gmk
|
||||||
|
|
||||||
|
#
|
||||||
|
# Files
|
||||||
|
#
|
||||||
|
AUTO_FILES_JAVA_DIRS = com/sun/security/ntlm
|
||||||
|
|
||||||
|
#
|
||||||
|
# Rules
|
||||||
|
#
|
||||||
|
include $(BUILDDIR)/common/Classes.gmk
|
|
@ -40,7 +40,8 @@ AUTO_FILES_JAVA_DIRS = java/security
|
||||||
# Directories
|
# Directories
|
||||||
#
|
#
|
||||||
|
|
||||||
PROPS_SRC = $(TOPDIR)/src/share/lib/security/java.security
|
# The default security properties file is for linux
|
||||||
|
PROPS_SRC = $(TOPDIR)/src/share/lib/security/java.security-linux
|
||||||
|
|
||||||
ifeq ($(PLATFORM), solaris)
|
ifeq ($(PLATFORM), solaris)
|
||||||
PROPS_SRC = $(TOPDIR)/src/share/lib/security/java.security-solaris
|
PROPS_SRC = $(TOPDIR)/src/share/lib/security/java.security-solaris
|
||||||
|
|
|
@ -38,10 +38,12 @@ SUBDIRS_MAKEFLAGS += JAVAC_MAX_WARNINGS=true
|
||||||
SUBDIRS_MAKEFLAGS += JAVAC_WARNINGS_FATAL=true
|
SUBDIRS_MAKEFLAGS += JAVAC_WARNINGS_FATAL=true
|
||||||
include $(BUILDDIR)/common/Defs.gmk
|
include $(BUILDDIR)/common/Defs.gmk
|
||||||
|
|
||||||
# build sun/security/jgss/wrapper on non-windows platform
|
# build sun/security/jgss/wrapper on non-windows non-macosx platforms
|
||||||
JGSS_WRAPPER =
|
JGSS_WRAPPER =
|
||||||
ifneq ($(PLATFORM), windows)
|
ifneq ($(PLATFORM), windows)
|
||||||
JGSS_WRAPPER = jgss/wrapper
|
ifneq ($(PLATFORM), macosx)
|
||||||
|
JGSS_WRAPPER = jgss/wrapper
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Build PKCS#11 on all platforms
|
# Build PKCS#11 on all platforms
|
||||||
|
|
|
@ -29,6 +29,7 @@ import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -86,7 +87,23 @@ class Bundle {
|
||||||
private final static String[] ERA_KEYS = {
|
private final static String[] ERA_KEYS = {
|
||||||
"long.Eras",
|
"long.Eras",
|
||||||
"Eras",
|
"Eras",
|
||||||
"short.Eras"
|
"narrow.Eras"
|
||||||
|
};
|
||||||
|
|
||||||
|
// Keys for individual time zone names
|
||||||
|
private final static String TZ_GEN_LONG_KEY = "timezone.displayname.generic.long";
|
||||||
|
private final static String TZ_GEN_SHORT_KEY = "timezone.displayname.generic.short";
|
||||||
|
private final static String TZ_STD_LONG_KEY = "timezone.displayname.standard.long";
|
||||||
|
private final static String TZ_STD_SHORT_KEY = "timezone.displayname.standard.short";
|
||||||
|
private final static String TZ_DST_LONG_KEY = "timezone.displayname.daylight.long";
|
||||||
|
private final static String TZ_DST_SHORT_KEY = "timezone.displayname.daylight.short";
|
||||||
|
private final static String[] ZONE_NAME_KEYS = {
|
||||||
|
TZ_STD_LONG_KEY,
|
||||||
|
TZ_STD_SHORT_KEY,
|
||||||
|
TZ_DST_LONG_KEY,
|
||||||
|
TZ_DST_SHORT_KEY,
|
||||||
|
TZ_GEN_LONG_KEY,
|
||||||
|
TZ_GEN_SHORT_KEY
|
||||||
};
|
};
|
||||||
|
|
||||||
private final String id;
|
private final String id;
|
||||||
|
@ -98,6 +115,7 @@ class Bundle {
|
||||||
return bundles.get(id);
|
return bundles.get(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("ConvertToStringSwitch")
|
||||||
Bundle(String id, String cldrPath, String bundles, String currencies) {
|
Bundle(String id, String cldrPath, String bundles, String currencies) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.cldrPath = cldrPath;
|
this.cldrPath = cldrPath;
|
||||||
|
@ -242,9 +260,12 @@ class Bundle {
|
||||||
// handle multiple inheritance for month and day names
|
// handle multiple inheritance for month and day names
|
||||||
handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "MonthNames");
|
handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "MonthNames");
|
||||||
handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "MonthAbbreviations");
|
handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "MonthAbbreviations");
|
||||||
|
handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "MonthNarrows");
|
||||||
handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "DayNames");
|
handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "DayNames");
|
||||||
handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "DayAbbreviations");
|
handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "DayAbbreviations");
|
||||||
|
handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "DayNarrows");
|
||||||
handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "AmPmMarkers");
|
handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "AmPmMarkers");
|
||||||
|
handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "narrow.AmPmMarkers");
|
||||||
|
|
||||||
adjustEraNames(myMap, calendarType);
|
adjustEraNames(myMap, calendarType);
|
||||||
|
|
||||||
|
@ -253,6 +274,99 @@ class Bundle {
|
||||||
handleDateTimeFormatPatterns(DATETIME_PATTERN_KEYS, myMap, parentsMap, calendarType, "DateTimePatterns");
|
handleDateTimeFormatPatterns(DATETIME_PATTERN_KEYS, myMap, parentsMap, calendarType, "DateTimePatterns");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if myMap has any empty timezone or metazone names, weed out them.
|
||||||
|
// Fill in any missing abbreviations if locale is "en".
|
||||||
|
for (Iterator<String> it = myMap.keySet().iterator(); it.hasNext();) {
|
||||||
|
String key = it.next();
|
||||||
|
if (key.startsWith(CLDRConverter.TIMEZONE_ID_PREFIX)
|
||||||
|
|| key.startsWith(CLDRConverter.METAZONE_ID_PREFIX)) {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Map<String, String> nameMap = (Map<String, String>) myMap.get(key);
|
||||||
|
if (nameMap.isEmpty()) {
|
||||||
|
// Some zones have only exemplarCity, which become empty.
|
||||||
|
// Remove those from the map.
|
||||||
|
it.remove();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id.startsWith("en")) {
|
||||||
|
fillInAbbrs(key, nameMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (Iterator<String> it = myMap.keySet().iterator(); it.hasNext();) {
|
||||||
|
String key = it.next();
|
||||||
|
if (key.startsWith(CLDRConverter.TIMEZONE_ID_PREFIX)
|
||||||
|
|| key.startsWith(CLDRConverter.METAZONE_ID_PREFIX)) {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Map<String, String> nameMap = (Map<String, String>) myMap.get(key);
|
||||||
|
// Convert key/value pairs to an array.
|
||||||
|
String[] names = new String[ZONE_NAME_KEYS.length];
|
||||||
|
int ix = 0;
|
||||||
|
for (String nameKey : ZONE_NAME_KEYS) {
|
||||||
|
String name = nameMap.get(nameKey);
|
||||||
|
if (name == null) {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Map<String, String> parentNames = (Map<String, String>) parentsMap.get(key);
|
||||||
|
if (parentNames != null) {
|
||||||
|
name = parentNames.get(nameKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
names[ix++] = name;
|
||||||
|
}
|
||||||
|
if (hasNulls(names)) {
|
||||||
|
String metaKey = toMetaZoneKey(key);
|
||||||
|
if (metaKey != null) {
|
||||||
|
Object obj = myMap.get(metaKey);
|
||||||
|
if (obj instanceof String[]) {
|
||||||
|
String[] metaNames = (String[]) obj;
|
||||||
|
for (int i = 0; i < names.length; i++) {
|
||||||
|
if (names[i] == null) {
|
||||||
|
names[i] = metaNames[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (obj instanceof Map) {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Map<String, String> m = (Map<String, String>) obj;
|
||||||
|
for (int i = 0; i < names.length; i++) {
|
||||||
|
if (names[i] == null) {
|
||||||
|
names[i] = m.get(ZONE_NAME_KEYS[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If there are still any nulls, try filling in them from en data.
|
||||||
|
if (hasNulls(names) && !id.equals("en")) {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
String[] enNames = (String[]) Bundle.getBundle("en").getTargetMap().get(key);
|
||||||
|
if (enNames == null) {
|
||||||
|
if (metaKey != null) {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
String[] metaNames = (String[]) Bundle.getBundle("en").getTargetMap().get(metaKey);
|
||||||
|
enNames = metaNames;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (enNames != null) {
|
||||||
|
for (int i = 0; i < names.length; i++) {
|
||||||
|
if (names[i] == null) {
|
||||||
|
names[i] = enNames[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If there are still nulls, give up names.
|
||||||
|
if (hasNulls(names)) {
|
||||||
|
names = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// replace the Map with the array
|
||||||
|
if (names != null) {
|
||||||
|
myMap.put(key, names);
|
||||||
|
} else {
|
||||||
|
it.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return myMap;
|
return myMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,20 +466,10 @@ class Bundle {
|
||||||
realKeys[index] = realKey;
|
realKeys[index] = realKey;
|
||||||
eraNames[index++] = value;
|
eraNames[index++] = value;
|
||||||
}
|
}
|
||||||
if (eraNames[0] != null) {
|
for (int i = 0; i < eraNames.length; i++) {
|
||||||
if (eraNames[1] != null) {
|
if (eraNames[i] == null) {
|
||||||
if (eraNames[2] == null) {
|
map.put(realKeys[i], null);
|
||||||
// Eras -> short.Eras
|
|
||||||
// long.Eras -> Eras
|
|
||||||
map.put(realKeys[2], map.get(realKeys[1]));
|
|
||||||
map.put(realKeys[1], map.get(realKeys[0]));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// long.Eras -> Eras
|
|
||||||
map.put(realKeys[1], map.get(realKeys[0]));
|
|
||||||
}
|
}
|
||||||
// remove long.Eras
|
|
||||||
map.remove(realKeys[0]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -473,6 +577,86 @@ class Bundle {
|
||||||
return jrePattern.toString();
|
return jrePattern.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String toMetaZoneKey(String tzKey) {
|
||||||
|
if (tzKey.startsWith(CLDRConverter.TIMEZONE_ID_PREFIX)) {
|
||||||
|
String tz = tzKey.substring(CLDRConverter.TIMEZONE_ID_PREFIX.length());
|
||||||
|
String meta = CLDRConverter.handlerMetaZones.get(tz);
|
||||||
|
if (meta != null) {
|
||||||
|
return CLDRConverter.METAZONE_ID_PREFIX + meta;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fillInAbbrs(String key, Map<String, String> map) {
|
||||||
|
fillInAbbrs(TZ_STD_LONG_KEY, TZ_STD_SHORT_KEY, map);
|
||||||
|
fillInAbbrs(TZ_DST_LONG_KEY, TZ_DST_SHORT_KEY, map);
|
||||||
|
fillInAbbrs(TZ_GEN_LONG_KEY, TZ_GEN_SHORT_KEY, map);
|
||||||
|
|
||||||
|
// If the standard std is "Standard Time" and daylight std is "Summer Time",
|
||||||
|
// replace the standard std with the generic std to avoid using
|
||||||
|
// the same abbrivation except for Australia time zone names.
|
||||||
|
String std = map.get(TZ_STD_SHORT_KEY);
|
||||||
|
String dst = map.get(TZ_DST_SHORT_KEY);
|
||||||
|
String gen = map.get(TZ_GEN_SHORT_KEY);
|
||||||
|
if (std != null) {
|
||||||
|
if (dst == null) {
|
||||||
|
// if dst is null, create long and short names from the standard
|
||||||
|
// std. ("Something Standard Time" to "Something Daylight Time",
|
||||||
|
// or "Something Time" to "Something Summer Time")
|
||||||
|
String name = map.get(TZ_STD_LONG_KEY);
|
||||||
|
if (name != null) {
|
||||||
|
if (name.contains("Standard Time")) {
|
||||||
|
name = name.replace("Standard Time", "Daylight Time");
|
||||||
|
} else if (name.endsWith("Mean Time")) {
|
||||||
|
name = name.replace("Mean Time", "Summer Time");
|
||||||
|
} else if (name.endsWith(" Time")) {
|
||||||
|
name = name.replace(" Time", " Summer Time");
|
||||||
|
}
|
||||||
|
map.put(TZ_DST_LONG_KEY, name);
|
||||||
|
fillInAbbrs(TZ_DST_LONG_KEY, TZ_DST_SHORT_KEY, map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (gen == null) {
|
||||||
|
String name = map.get(TZ_STD_LONG_KEY);
|
||||||
|
if (name != null) {
|
||||||
|
if (name.endsWith("Standard Time")) {
|
||||||
|
name = name.replace("Standard Time", "Time");
|
||||||
|
} else if (name.endsWith("Mean Time")) {
|
||||||
|
name = name.replace("Mean Time", "Time");
|
||||||
|
}
|
||||||
|
map.put(TZ_GEN_LONG_KEY, name);
|
||||||
|
fillInAbbrs(TZ_GEN_LONG_KEY, TZ_GEN_SHORT_KEY, map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fillInAbbrs(String longKey, String shortKey, Map<String, String> map) {
|
||||||
|
String abbr = map.get(shortKey);
|
||||||
|
if (abbr == null) {
|
||||||
|
String name = map.get(longKey);
|
||||||
|
if (name != null) {
|
||||||
|
abbr = toAbbr(name);
|
||||||
|
if (abbr != null) {
|
||||||
|
map.put(shortKey, abbr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String toAbbr(String name) {
|
||||||
|
String[] substrs = name.split("\\s+");
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (String s : substrs) {
|
||||||
|
char c = s.charAt(0);
|
||||||
|
if (c >= 'A' && c <= 'Z') {
|
||||||
|
sb.append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.length() > 0 ? sb.toString() : null;
|
||||||
|
}
|
||||||
|
|
||||||
private void convert(CalendarType calendarType, char cldrLetter, int count, StringBuilder sb) {
|
private void convert(CalendarType calendarType, char cldrLetter, int count, StringBuilder sb) {
|
||||||
switch (cldrLetter) {
|
switch (cldrLetter) {
|
||||||
case 'G':
|
case 'G':
|
||||||
|
@ -539,4 +723,13 @@ class Bundle {
|
||||||
sb.append(c);
|
sb.append(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean hasNulls(Object[] array) {
|
||||||
|
for (int i = 0; i < array.length; i++) {
|
||||||
|
if (array[i] == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,8 +30,27 @@ import java.util.Map;
|
||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
|
|
||||||
public interface BundleGenerator {
|
public interface BundleGenerator {
|
||||||
|
static enum BundleType {
|
||||||
|
PLAIN("java.util.ListResourceBundle"),
|
||||||
|
OPEN("sun.util.resources.OpenListResourceBundle"),
|
||||||
|
TIMEZONE("sun.util.resources.TimeZoneNamesBundle");
|
||||||
|
|
||||||
|
private final String pathName, className;
|
||||||
|
private BundleType(String name) {
|
||||||
|
pathName = name;
|
||||||
|
int x = name.lastIndexOf('.');
|
||||||
|
className = name.substring(x + 1);
|
||||||
|
}
|
||||||
|
String getPathName() {
|
||||||
|
return pathName;
|
||||||
|
}
|
||||||
|
String getClassName() {
|
||||||
|
return className;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
public void generateBundle(String packageName, String baseName, String localeID,
|
public void generateBundle(String packageName, String baseName, String localeID,
|
||||||
boolean useJava, Map<String, ?> map, boolean open) throws IOException;
|
boolean useJava, Map<String, ?> map, BundleType type) throws IOException;
|
||||||
|
|
||||||
public void generateMetaInfo(Map<String, SortedSet<String>> metaInfo) throws IOException;
|
public void generateMetaInfo(Map<String, SortedSet<String>> metaInfo) throws IOException;
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue