This commit is contained in:
J. Duke 2017-07-05 20:51:27 +02:00
commit 1027d6c2a3
212 changed files with 10460 additions and 4015 deletions

View File

@ -325,3 +325,4 @@ ba08a9f79b9849716bae1f39f71333d47f604012 jdk9-b79
f7c5ae2933c0b8510a420d1713a955e4ffc7ad0b jdk9-b80
b8afcf91331d78626a583ec1b63164468d6f4181 jdk9-b81
42b56d1f418523ecb61a49d7493302c80c8009cc jdk9-b82
ce5c14d97d95084504c32b9320cb33cce4235588 jdk9-b83

View File

@ -445,6 +445,15 @@ AC_DEFUN_ONCE([BASIC_SETUP_PATHS],
# Save the current directory this script was started from
CURDIR="$PWD"
# We might need to rewrite ORIGINAL_PATH, if it includes "#", to quote them
# for make. We couldn't do this when we retrieved ORIGINAL_PATH, since SED
# was not available at that time.
REWRITTEN_PATH=`$ECHO "$ORIGINAL_PATH" | $SED -e 's/#/\\\\#/g'`
if test "x$REWRITTEN_PATH" != "x$ORIGINAL_PATH"; then
ORIGINAL_PATH="$REWRITTEN_PATH"
AC_MSG_NOTICE([Rewriting ORIGINAL_PATH to $REWRITTEN_PATH])
fi
if test "x$OPENJDK_TARGET_OS" = "xwindows"; then
PATH_SEP=";"
BASIC_CHECK_PATHS_WINDOWS
@ -935,6 +944,7 @@ AC_DEFUN_ONCE([BASIC_SETUP_COMPLEX_TOOLS],
BASIC_PATH_PROGS(HG, hg)
BASIC_PATH_PROGS(STAT, stat)
BASIC_PATH_PROGS(TIME, time)
BASIC_PATH_PROGS(PATCH, [gpatch patch])
# Check if it's GNU time
IS_GNU_TIME=`$TIME --version 2>&1 | $GREP 'GNU time'`
if test "x$IS_GNU_TIME" != x; then

View File

@ -29,47 +29,50 @@
##########################################################################################
# Substitutions from autoconf
LEGACY_BUILD_DIR=@OPENJDK_TARGET_OS@-@OPENJDK_TARGET_CPU_LEGACY@
export LEGACY_BUILD_DIR=@OPENJDK_TARGET_OS@-@OPENJDK_TARGET_CPU_LEGACY@
OPENJDK_TARGET_OS="@OPENJDK_TARGET_OS@"
OPENJDK_TARGET_CPU="@OPENJDK_TARGET_CPU@"
export OPENJDK_TARGET_OS="@OPENJDK_TARGET_OS@"
export OPENJDK_TARGET_CPU="@OPENJDK_TARGET_CPU@"
AWK="@AWK@"
CAT="@CAT@"
CMP="@CMP@"
CP="@CP@"
CUT="@CUT@"
DIFF="@DIFF@"
DUMPBIN="@FIXPATH@ @DUMPBIN@"
EXPR="@EXPR@"
FILE="@FILE@"
FIND="@FIND@"
GREP="@GREP@"
JAVAP="@FIXPATH@ @BOOT_JDK@/bin/javap @JAVA_TOOL_FLAGS_SMALL@"
JIMAGE="@FIXPATH@ @BUILD_OUTPUT@/jdk/bin/jimage"
LDD="@LDD@"
LN="@LN@"
MKDIR="@MKDIR@"
NAWK="@NAWK@"
NM="@GNM@"
OBJDUMP="@OBJDUMP@"
OTOOL="@OTOOL@"
PRINTF="@PRINTF@"
READELF="@READELF@"
RM="@RM@"
SED="@SED@"
SORT="@SORT@"
STAT="@STAT@"
STRIP="@POST_STRIP_CMD@"
TEE="@TEE@"
UNIQ="@UNIQ@"
UNPACK200="@FIXPATH@ @BOOT_JDK@/bin/unpack200"
UNZIP="@UNZIP@"
export AWK="@AWK@"
export BASH="@BASH@"
export CAT="@CAT@"
export CMP="@CMP@"
export CP="@CP@"
export CUT="@CUT@"
export DIFF="@DIFF@"
export DUMPBIN="@FIXPATH@ @DUMPBIN@"
export EXPR="@EXPR@"
export FILE="@FILE@"
export FIND="@FIND@"
export GREP="@GREP@"
export JAVAP="@FIXPATH@ @BOOT_JDK@/bin/javap @JAVA_TOOL_FLAGS_SMALL@"
export JIMAGE="@FIXPATH@ @BUILD_OUTPUT@/jdk/bin/jimage"
export LDD="@LDD@"
export LN="@LN@"
export MKDIR="@MKDIR@"
export MV="@MV@"
export NAWK="@NAWK@"
export NM="@GNM@"
export OBJDUMP="@OBJDUMP@"
export OTOOL="@OTOOL@"
export PRINTF="@PRINTF@"
export READELF="@READELF@"
export RM="@RM@"
export SED="@SED@"
export SORT="@SORT@"
export STAT="@STAT@"
export STRIP="@POST_STRIP_CMD@"
export TEE="@TEE@"
export UNIQ="@UNIQ@"
export UNPACK200="@FIXPATH@ @BOOT_JDK@/bin/unpack200"
export UNZIP="@UNZIP@"
SRC_ROOT="@TOPDIR@"
export SRC_ROOT="@TOPDIR@"
export OUTPUT_ROOT="@OUTPUT_ROOT@"
if [ "$OPENJDK_TARGET_OS" = "windows" ]; then
PATH="@VS_PATH@"
export PATH="@VS_PATH@"
fi
# Now locate the main script and run it.
@ -79,4 +82,8 @@ if [ ! -e "$REAL_COMPARE_SCRIPT" ]; then
exit 1
fi
. "$REAL_COMPARE_SCRIPT" "$@"
# Rotate logs
$RM $OUTPUT_ROOT/compare.log.old 2> /dev/null
$MV $OUTPUT_ROOT/compare.log $OUTPUT_ROOT/compare.log.old 2> /dev/null
$BASH $SRC_ROOT/common/bin/logger.sh $OUTPUT_ROOT/compare.log $BASH "$REAL_COMPARE_SCRIPT" "$@"

View File

@ -859,6 +859,7 @@ CODESIGN
XATTR
DSYMUTIL
IS_GNU_TIME
PATCH
TIME
STAT
HG
@ -1174,6 +1175,7 @@ READELF
HG
STAT
TIME
PATCH
DSYMUTIL
XATTR
CODESIGN
@ -2053,6 +2055,7 @@ Some influential environment variables:
HG Override default value for HG
STAT Override default value for STAT
TIME Override default value for TIME
PATCH Override default value for PATCH
DSYMUTIL Override default value for DSYMUTIL
XATTR Override default value for XATTR
CODESIGN Override default value for CODESIGN
@ -4359,7 +4362,7 @@ VS_SDK_PLATFORM_NAME_2013=
#CUSTOM_AUTOCONF_INCLUDE
# Do not change or remove the following line, it is needed for consistency checks:
DATE_WHEN_GENERATED=1441958217
DATE_WHEN_GENERATED=1442820958
###############################################################################
#
@ -13841,6 +13844,16 @@ $as_echo "$COMPILE_TYPE" >&6; }
# Save the current directory this script was started from
CURDIR="$PWD"
# We might need to rewrite ORIGINAL_PATH, if it includes "#", to quote them
# for make. We couldn't do this when we retrieved ORIGINAL_PATH, since SED
# was not available at that time.
REWRITTEN_PATH=`$ECHO "$ORIGINAL_PATH" | $SED -e 's/#/\\\\#/g'`
if test "x$REWRITTEN_PATH" != "x$ORIGINAL_PATH"; then
ORIGINAL_PATH="$REWRITTEN_PATH"
{ $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting ORIGINAL_PATH to $REWRITTEN_PATH" >&5
$as_echo "$as_me: Rewriting ORIGINAL_PATH to $REWRITTEN_PATH" >&6;}
fi
if test "x$OPENJDK_TARGET_OS" = "xwindows"; then
PATH_SEP=";"
@ -18865,6 +18878,192 @@ $as_echo "$tool_specified" >&6; }
fi
# Publish this variable in the help.
if test "x$PATCH" = x; then
# The variable is not set by user, try to locate tool using the code snippet
for ac_prog in gpatch patch
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_PATCH+:} false; then :
$as_echo_n "(cached) " >&6
else
case $PATCH in
[\\/]* | ?:[\\/]*)
ac_cv_path_PATCH="$PATCH" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_PATCH="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
;;
esac
fi
PATCH=$ac_cv_path_PATCH
if test -n "$PATCH"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $PATCH" >&5
$as_echo "$PATCH" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
test -n "$PATCH" && break
done
else
# The variable is set, but is it from the command line or the environment?
# Try to remove the string !PATCH! from our list.
try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!PATCH!/}
if test "x$try_remove_var" = "x$CONFIGURE_OVERRIDDEN_VARIABLES"; then
# If it failed, the variable was not from the command line. Ignore it,
# but warn the user (except for BASH, which is always set by the calling BASH).
if test "xPATCH" != xBASH; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of PATCH from the environment. Use command line variables instead." >&5
$as_echo "$as_me: WARNING: Ignoring value of PATCH from the environment. Use command line variables instead." >&2;}
fi
# Try to locate tool using the code snippet
for ac_prog in gpatch patch
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_PATCH+:} false; then :
$as_echo_n "(cached) " >&6
else
case $PATCH in
[\\/]* | ?:[\\/]*)
ac_cv_path_PATCH="$PATCH" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_PATCH="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
;;
esac
fi
PATCH=$ac_cv_path_PATCH
if test -n "$PATCH"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $PATCH" >&5
$as_echo "$PATCH" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
test -n "$PATCH" && break
done
else
# If it succeeded, then it was overridden by the user. We will use it
# for the tool.
# First remove it from the list of overridden variables, so we can test
# for unknown variables in the end.
CONFIGURE_OVERRIDDEN_VARIABLES="$try_remove_var"
# Check if the provided tool contains a complete path.
tool_specified="$PATCH"
tool_basename="${tool_specified##*/}"
if test "x$tool_basename" = "x$tool_specified"; then
# A command without a complete path is provided, search $PATH.
{ $as_echo "$as_me:${as_lineno-$LINENO}: Will search for user supplied tool PATCH=$tool_basename" >&5
$as_echo "$as_me: Will search for user supplied tool PATCH=$tool_basename" >&6;}
# Extract the first word of "$tool_basename", so it can be a program name with args.
set dummy $tool_basename; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_PATCH+:} false; then :
$as_echo_n "(cached) " >&6
else
case $PATCH in
[\\/]* | ?:[\\/]*)
ac_cv_path_PATCH="$PATCH" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_PATCH="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
;;
esac
fi
PATCH=$ac_cv_path_PATCH
if test -n "$PATCH"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $PATCH" >&5
$as_echo "$PATCH" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
if test "x$PATCH" = x; then
as_fn_error $? "User supplied tool $tool_basename could not be found" "$LINENO" 5
fi
else
# Otherwise we believe it is a complete path. Use it as it is.
{ $as_echo "$as_me:${as_lineno-$LINENO}: Will use user supplied tool PATCH=$tool_specified" >&5
$as_echo "$as_me: Will use user supplied tool PATCH=$tool_specified" >&6;}
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PATCH" >&5
$as_echo_n "checking for PATCH... " >&6; }
if test ! -x "$tool_specified"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
$as_echo "not found" >&6; }
as_fn_error $? "User supplied tool PATCH=$tool_specified does not exist or is not executable" "$LINENO" 5
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tool_specified" >&5
$as_echo "$tool_specified" >&6; }
fi
fi
fi
# Check if it's GNU time
IS_GNU_TIME=`$TIME --version 2>&1 | $GREP 'GNU time'`
if test "x$IS_GNU_TIME" != x; then

View File

@ -36,6 +36,11 @@ CONFIGURE_COMMAND_LINE:=@CONFIGURE_COMMAND_LINE@
# A self-referential reference to this file.
SPEC:=@SPEC@
# SPACE is defined in MakeBase.gmk, but it is also used in := rules here for some
# toolchains, and is needed if MakeBase.gmk is not included before this file.
X:=
SPACE:=$(X) $(X)
# What make to use for main processing, after bootstrapping top-level Makefile.
MAKE := @MAKE@
@ -495,6 +500,7 @@ LN:=@LN@
MKDIR:=@MKDIR@
MV:=@MV@
NAWK:=@NAWK@
PATCH:=@PATCH@
PRINTF:=@PRINTF@
PWD:=@THEPWDCMD@
RM:=@RM@

View File

@ -88,23 +88,19 @@ diff_text() {
TMP=$(LC_ALL=C $DIFF $OTHER_FILE $THIS_FILE | \
$GREP '^[<>]' | \
$SED -e '/[<>] \* from.*\.idl/d' \
-e '/[<>] \*.*[0-9]\{4\}_[0-9]\{2\}_[0-9]\{2\}_[0-9]\{2\}_[0-9]\{2\}-b[0-9]\{2\}.*/d' \
-e '/[<>] .*[0-9]\{4\}_[0-9]\{2\}_[0-9]\{2\}_[0-9]\{2\}_[0-9]\{2\}-b[0-9]\{2\}.*/d' \
-e '/[<>] \*.*[0-9]\{4\} [0-9][0-9]*:[0-9]\{2\}:[0-9]\{2\}.*/d' \
-e '/\/\/ Generated from input file.*/d' \
-e '/\/\/ This file was generated AUTOMATICALLY from a template file.*/d' \
-e '/\/\/ java GenerateCharacter.*/d')
fi
# Ignore date strings in class files.
# On Macosx the system sources for generated java classes produce different output on
# consequtive invocations seemingly randomly.
# For example a method parameter randomly named "thePoint" or "aPoint". Ignore this.
# Anonymous lambda classes get randomly assigned counters in their names.
if test "x$SUFFIX" = "xclass"; then
# To improve performance when large diffs are found, do a rough filtering of classes
# elibeble for these exceptions
if $GREP -R -e '[0-9]\{4\}_[0-9]\{2\}_[0-9]\{2\}_[0-9]\{2\}_[0-9]\{2\}-b[0-9]\{2\}' \
-e '[0-9]\{2\}/[0-9]\{2\}/[0-9]\{4\}' \
-e thePoint -e aPoint -e setItemsPtr \
-e 'lambda\$[a-zA-Z0-9]*\$[0-9]' ${THIS_FILE} > /dev/null; then
$JAVAP -c -constants -l -p "${OTHER_FILE}" > ${OTHER_FILE}.javap
$JAVAP -c -constants -l -p "${THIS_FILE}" > ${THIS_FILE}.javap
@ -112,9 +108,6 @@ diff_text() {
$GREP '^[<>]' | \
$SED -e '/[<>].*[0-9]\{4\}_[0-9]\{2\}_[0-9]\{2\}_[0-9]\{2\}_[0-9]\{2\}-b[0-9]\{2\}.*/d' \
-e '/[0-9]\{2\}\/[0-9]\{2\}\/[0-9]\{4\}/d' \
-e '/[<>].*Point Lcom\/apple\/jobjc\/foundation\/NSPoint;/d' \
-e '/[<>].*public com\.apple\.jobjc\.Pointer<com\.apple\.jobjc\..*itemsPtr();/d' \
-e '/[<>].*public void setItemsPtr(com\.apple\.jobjc\.Pointer<com\.apple\.jobjc\..*);/d' \
-e '/[<>].*lambda\$[a-zA-Z0-9]*\$[0-9]*/d')
fi
fi
@ -313,7 +306,7 @@ compare_general_files() {
! -name "jspawnhelper" \
| $GREP -v "./bin/" | $SORT | $FILTER)
echo General files...
echo Other files with binary differences...
for f in $GENERAL_FILES
do
if [ -e $OTHER_DIR/$f ]; then
@ -590,7 +583,7 @@ compare_bin_file() {
ORIG_THIS_FILE="$THIS_FILE"
ORIG_OTHER_FILE="$OTHER_FILE"
if [[ "$STRIP_BEFORE_COMPARE" = *"$BIN_FILE"* ]]; then
if [ "$STRIP_ALL" = "true" ] || [[ "$STRIP_BEFORE_COMPARE" = *"$BIN_FILE"* ]]; then
THIS_STRIPPED_FILE=$FILE_WORK_DIR/this/$NAME
OTHER_STRIPPED_FILE=$FILE_WORK_DIR/other/$NAME
$MKDIR -p $FILE_WORK_DIR/this $FILE_WORK_DIR/other
@ -722,7 +715,7 @@ compare_bin_file() {
fi
fi
if [[ "$SORT_SYMBOLS" = *"$BIN_FILE"* ]]; then
if [ "$SORT_ALL_SYMBOLS" = "true" ] || [[ "$SORT_SYMBOLS" = *"$BIN_FILE"* ]]; then
SYM_SORT_CMD="sort"
else
SYM_SORT_CMD="cat"
@ -810,31 +803,34 @@ compare_bin_file() {
if [ -z "$FULLDUMP_DIFF_FILTER" ]; then
FULLDUMP_DIFF_FILTER="$CAT"
fi
$FULLDUMP_CMD $OTHER_FILE | eval "$FULLDUMP_DIFF_FILTER" > $WORK_FILE_BASE.fulldump.other 2>&1
$FULLDUMP_CMD $THIS_FILE | eval "$FULLDUMP_DIFF_FILTER" > $WORK_FILE_BASE.fulldump.this 2>&1
$FULLDUMP_CMD $OTHER_FILE | eval "$FULLDUMP_DIFF_FILTER" \
> $WORK_FILE_BASE.fulldump.other 2>&1
$FULLDUMP_CMD $THIS_FILE | eval "$FULLDUMP_DIFF_FILTER" \
> $WORK_FILE_BASE.fulldump.this 2>&1
LC_ALL=C $DIFF $WORK_FILE_BASE.fulldump.other $WORK_FILE_BASE.fulldump.this > $WORK_FILE_BASE.fulldump.diff
LC_ALL=C $DIFF $WORK_FILE_BASE.fulldump.other $WORK_FILE_BASE.fulldump.this \
> $WORK_FILE_BASE.fulldump.diff
if [ -s $WORK_FILE_BASE.fulldump.diff ]; then
ELF_DIFF_SIZE=$(ls -n $WORK_FILE_BASE.fulldump.diff | awk '{print $5}')
ELF_MSG=$($PRINTF "%8d" $ELF_DIFF_SIZE)
if [[ "$ACCEPTED_ELF_DIFF" != *"$BIN_FILE"* ]]; then
DIFF_ELF=true
if [[ "$KNOWN_ELF_DIFF" != *"$BIN_FILE"* ]]; then
ELF_MSG="*$ELF_MSG*"
FULLDUMP_DIFF_SIZE=$(ls -n $WORK_FILE_BASE.fulldump.diff | awk '{print $5}')
FULLDUMP_MSG=$($PRINTF "%8d" $FULLDUMP_DIFF_SIZE)
if [[ "$ACCEPTED_FULLDUMP_DIFF" != *"$BIN_FILE"* ]]; then
DIFF_FULLDUMP=true
if [[ "$KNOWN_FULLDUMP_DIFF" != *"$BIN_FILE"* ]]; then
FULLDUMP_MSG="*$FULLDUMP_MSG*"
REGRESSIONS=true
else
ELF_MSG=" $ELF_MSG "
FULLDUMP_MSG=" $FULLDUMP_MSG "
fi
else
ELF_MSG="($ELF_MSG)"
DIFF_ELF=
FULLDUMP_MSG="($FULLDUMP_MSG)"
DIFF_FULLDUMP=
fi
else
ELF_MSG=" "
DIFF_ELF=
if [[ "$KNOWN_DEP_DIFF $ACCEPTED_DEP_DIFF" = *"$BIN_FILE"* ]]; then
ELF_MSG=" ! "
FULLDUMP_MSG=" "
DIFF_FULLDUMP=
if [[ "$KNOWN_FULLDUMP_DIFF $ACCEPTED_FULLDUMP_DIFF" = *"$BIN_FILE"* ]]; then
FULLDUMP_MSG=" ! "
fi
fi
fi
@ -845,7 +841,7 @@ compare_bin_file() {
# To get a raw diff with the complete disassembly, set
# DIS_DIFF_FILTER="$CAT"
if [ -z "$DIS_DIFF_FILTER" ]; then
DIS_DIFF_FILTER="$GREP -v ' # .* <.*>$'"
DIS_DIFF_FILTER="$GREP -v ' # .* <.*>$' | $SED -r -e 's/(\b|x)([0-9a-fA-F]+)(\b|:|>)/X/g'"
fi
$DIS_CMD $OTHER_FILE | $GREP -v $NAME | eval "$DIS_DIFF_FILTER" > $WORK_FILE_BASE.dis.other 2>&1
$DIS_CMD $THIS_FILE | $GREP -v $NAME | eval "$DIS_DIFF_FILTER" > $WORK_FILE_BASE.dis.this 2>&1
@ -877,12 +873,12 @@ compare_bin_file() {
fi
if [ -n "$DIFF_BIN$DIFF_SIZE$DIFF_SYM$DIFF_DEP$DIFF_ELF$DIFF_DIS" ] || [ -n "$VERBOSE" ]; then
if [ -n "$DIFF_BIN$DIFF_SIZE$DIFF_SYM$DIFF_DEP$DIFF_FULLDUMP$DIFF_DIS" ] || [ -n "$VERBOSE" ]; then
if [ -n "$BIN_MSG" ]; then echo -n "$BIN_MSG:"; fi
if [ -n "$SIZE_MSG" ]; then echo -n "$SIZE_MSG:"; fi
if [ -n "$SYM_MSG" ]; then echo -n "$SYM_MSG:"; fi
if [ -n "$DEP_MSG" ]; then echo -n "$DEP_MSG:"; fi
if [ -n "$ELF_MSG" ]; then echo -n "$ELF_MSG:"; fi
if [ -n "$FULLDUMP_MSG" ]; then echo -n "$FULLDUMP_MSG:"; fi
if [ -n "$DIS_MSG" ]; then echo -n "$DIS_MSG:"; fi
echo " $BIN_FILE"
if [ "$SHOW_DIFFS" = "true" ]; then
@ -1015,6 +1011,9 @@ if [ -z "$1" ] || [ "$1" = "-h" ] || [ "$1" = "-?" ] || [ "$1" = "/h" ] || [ "$1
echo "-vv More verbose output, shows diff output of all comparisons"
echo "-o [OTHER] Compare with build in other directory. Will default to the old build directory"
echo ""
echo "--sort-symbols Sort all symbols before comparing"
echo "--strip Strip all binaries before comparing"
echo ""
echo "[FILTER] List filenames in the image to compare, works for jars, zips, libs and execs"
echo "Example:"
echo "bash ./common/bin/compareimages.sh CodePointIM.jar"
@ -1107,6 +1106,12 @@ while [ -n "$1" ]; do
shift
shift
;;
--sort-symbols)
SORT_ALL_SYMBOLS=true
;;
--strip)
STRIP_ALL=true
;;
*)
CMP_NAMES=false
CMP_PERMS=false
@ -1223,7 +1228,7 @@ if [ "$SKIP_DEFAULT" != "true" ]; then
OTHER_JDK_BUNDLE="$OTHER/images/jdk-bundle"
OTHER_JRE_BUNDLE="$OTHER/images/jre-bundle"
fi
echo "Also comparing macosx bundles"
echo "Also comparing jdk macosx bundles"
echo " $THIS_JDK_BUNDLE"
echo " $OTHER_JDK_BUNDLE"
fi

View File

@ -325,3 +325,4 @@ d8126bc88fa5cd1ae4e44d86a4b1280ca1c9e2aa jdk9-b76
821a0373ef2d1642a9824facb938b901ad010413 jdk9-b80
45c35b7f5b40d5af0085e4a7b3a4d6e3e0347c35 jdk9-b81
c20d8ebddaa6fb09cc81d3edf3d1d05f4232700a jdk9-b82
ca8a1719588424f6e04e943790c7fcb7cb0b8c8f jdk9-b83

View File

@ -485,3 +485,4 @@ e9e63d93bbfe2c6c23447e2c1f5cc71c98671cba jdk9-b79
8e8377739c06b99b9011c003c77e0bef84c91e09 jdk9-b80
4142c190cd5ca4fb70ec367b4f97ef936272d8ef jdk9-b81
1c453a12be3036d482abef1dd470f8aff536b6b9 jdk9-b82
3ed0df2c553a80e0e26b91a6ce08806ea17a066a jdk9-b83

View File

@ -3803,82 +3803,38 @@ encode %{
enc_class aarch64_enc_cmpxchg(memory mem, iRegLNoSp oldval, iRegLNoSp newval) %{
MacroAssembler _masm(&cbuf);
Register old_reg = as_Register($oldval$$reg);
Register new_reg = as_Register($newval$$reg);
Register base = as_Register($mem$$base);
Register addr_reg;
int index = $mem$$index;
int scale = $mem$$scale;
int disp = $mem$$disp;
if (index == -1) {
if (disp != 0) {
__ lea(rscratch2, Address(base, disp));
addr_reg = rscratch2;
} else {
// TODO
// should we ever get anything other than this case?
addr_reg = base;
}
} else {
Register index_reg = as_Register(index);
if (disp == 0) {
__ lea(rscratch2, Address(base, index_reg, Address::lsl(scale)));
addr_reg = rscratch2;
} else {
__ lea(rscratch2, Address(base, disp));
__ lea(rscratch2, Address(rscratch2, index_reg, Address::lsl(scale)));
addr_reg = rscratch2;
}
}
Label retry_load, done;
__ bind(retry_load);
__ ldxr(rscratch1, addr_reg);
__ cmp(rscratch1, old_reg);
__ br(Assembler::NE, done);
__ stlxr(rscratch1, new_reg, addr_reg);
__ cbnzw(rscratch1, retry_load);
__ bind(done);
guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
__ cmpxchg($mem$$base$$Register, $oldval$$Register, $newval$$Register,
&Assembler::ldxr, &MacroAssembler::cmp, &Assembler::stlxr);
%}
enc_class aarch64_enc_cmpxchgw(memory mem, iRegINoSp oldval, iRegINoSp newval) %{
MacroAssembler _masm(&cbuf);
Register old_reg = as_Register($oldval$$reg);
Register new_reg = as_Register($newval$$reg);
Register base = as_Register($mem$$base);
Register addr_reg;
int index = $mem$$index;
int scale = $mem$$scale;
int disp = $mem$$disp;
if (index == -1) {
if (disp != 0) {
__ lea(rscratch2, Address(base, disp));
addr_reg = rscratch2;
} else {
// TODO
// should we ever get anything other than this case?
addr_reg = base;
}
} else {
Register index_reg = as_Register(index);
if (disp == 0) {
__ lea(rscratch2, Address(base, index_reg, Address::lsl(scale)));
addr_reg = rscratch2;
} else {
__ lea(rscratch2, Address(base, disp));
__ lea(rscratch2, Address(rscratch2, index_reg, Address::lsl(scale)));
addr_reg = rscratch2;
}
}
Label retry_load, done;
__ bind(retry_load);
__ ldxrw(rscratch1, addr_reg);
__ cmpw(rscratch1, old_reg);
__ br(Assembler::NE, done);
__ stlxrw(rscratch1, new_reg, addr_reg);
__ cbnzw(rscratch1, retry_load);
__ bind(done);
guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
__ cmpxchg($mem$$base$$Register, $oldval$$Register, $newval$$Register,
&Assembler::ldxrw, &MacroAssembler::cmpw, &Assembler::stlxrw);
%}
// The only difference between aarch64_enc_cmpxchg and
// aarch64_enc_cmpxchg_acq is that we use load-acquire in the
// CompareAndSwap sequence to serve as a barrier on acquiring a
// lock.
enc_class aarch64_enc_cmpxchg_acq(memory mem, iRegLNoSp oldval, iRegLNoSp newval) %{
MacroAssembler _masm(&cbuf);
guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
__ cmpxchg($mem$$base$$Register, $oldval$$Register, $newval$$Register,
&Assembler::ldaxr, &MacroAssembler::cmp, &Assembler::stlxr);
%}
enc_class aarch64_enc_cmpxchgw_acq(memory mem, iRegINoSp oldval, iRegINoSp newval) %{
MacroAssembler _masm(&cbuf);
guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
__ cmpxchg($mem$$base$$Register, $oldval$$Register, $newval$$Register,
&Assembler::ldaxrw, &MacroAssembler::cmpw, &Assembler::stlxrw);
%}
// auxiliary used for CompareAndSwapX to set result register
enc_class aarch64_enc_cset_eq(iRegINoSp res) %{
MacroAssembler _masm(&cbuf);
@ -4398,13 +4354,10 @@ encode %{
// Compare object markOop with mark and if equal exchange scratch1
// with object markOop.
// Note that this is simply a CAS: it does not generate any
// barriers. These are separately generated by
// membar_acquire_lock().
{
Label retry_load;
__ bind(retry_load);
__ ldxr(tmp, oop);
__ ldaxr(tmp, oop);
__ cmp(tmp, disp_hdr);
__ br(Assembler::NE, cas_failed);
// use stlxr to ensure update is immediately visible
@ -4454,7 +4407,7 @@ encode %{
{
Label retry_load, fail;
__ bind(retry_load);
__ ldxr(rscratch1, tmp);
__ ldaxr(rscratch1, tmp);
__ cmp(disp_hdr, rscratch1);
__ br(Assembler::NE, fail);
// use stlxr to ensure update is immediately visible
@ -8017,10 +7970,10 @@ instruct membar_acquire_lock() %{
match(MemBarAcquireLock);
ins_cost(VOLATILE_REF_COST);
format %{ "membar_acquire_lock" %}
format %{ "membar_acquire_lock (elided)" %}
ins_encode %{
__ membar(Assembler::LoadLoad|Assembler::LoadStore);
__ block_comment("membar_acquire_lock (elided)");
%}
ins_pipe(pipe_serial);
@ -8080,10 +8033,10 @@ instruct membar_release_lock() %{
match(MemBarReleaseLock);
ins_cost(VOLATILE_REF_COST);
format %{ "membar_release_lock" %}
format %{ "membar_release_lock (elided)" %}
ins_encode %{
__ membar(Assembler::LoadStore|Assembler::StoreStore);
__ block_comment("membar_release_lock (elided)");
%}
ins_pipe(pipe_serial);
@ -8369,7 +8322,11 @@ instruct storePConditional(memory heap_top_ptr, iRegP oldval, iRegP newval, rFla
ins_pipe(pipe_serial);
%}
// this has to be implemented as a CAS
// storeLConditional is used by PhaseMacroExpand::expand_lock_node
// when attempting to rebias a lock towards the current thread. We
// must use the acquire form of cmpxchg in order to guarantee acquire
// semantics in this case.
instruct storeLConditional(indirect mem, iRegLNoSp oldval, iRegLNoSp newval, rFlagsReg cr)
%{
match(Set cr (StoreLConditional mem (Binary oldval newval)));
@ -8381,12 +8338,14 @@ instruct storeLConditional(indirect mem, iRegLNoSp oldval, iRegLNoSp newval, rFl
"cmpw rscratch1, zr\t# EQ on successful write"
%}
ins_encode(aarch64_enc_cmpxchg(mem, oldval, newval));
ins_encode(aarch64_enc_cmpxchg_acq(mem, oldval, newval));
ins_pipe(pipe_slow);
%}
// this has to be implemented as a CAS
// storeIConditional also has acquire semantics, for no better reason
// than matching storeLConditional. At the time of writing this
// comment storeIConditional was not used anywhere by AArch64.
instruct storeIConditional(indirect mem, iRegINoSp oldval, iRegINoSp newval, rFlagsReg cr)
%{
match(Set cr (StoreIConditional mem (Binary oldval newval)));
@ -8398,7 +8357,7 @@ instruct storeIConditional(indirect mem, iRegINoSp oldval, iRegINoSp newval, rFl
"cmpw rscratch1, zr\t# EQ on successful write"
%}
ins_encode(aarch64_enc_cmpxchgw(mem, oldval, newval));
ins_encode(aarch64_enc_cmpxchgw_acq(mem, oldval, newval));
ins_pipe(pipe_slow);
%}

View File

@ -917,6 +917,8 @@ public:
void cmpptr(Register src1, Address src2);
// Various forms of CAS
void cmpxchgptr(Register oldv, Register newv, Register addr, Register tmp,
Label &suceed, Label *fail);
@ -938,6 +940,23 @@ public:
str(rscratch2, adr);
}
// A generic CAS; success or failure is in the EQ flag.
template <typename T1, typename T2>
void cmpxchg(Register addr, Register expected, Register new_val,
T1 load_insn,
void (MacroAssembler::*cmp_insn)(Register, Register),
T2 store_insn,
Register tmp = rscratch1) {
Label retry_load, done;
bind(retry_load);
(this->*load_insn)(tmp, addr);
(this->*cmp_insn)(tmp, expected);
br(Assembler::NE, done);
(this->*store_insn)(tmp, new_val, addr);
cbnzw(tmp, retry_load);
bind(done);
}
// Calls
address trampoline_call(Address entry, CodeBuffer *cbuf = NULL);

File diff suppressed because it is too large Load Diff

View File

@ -438,7 +438,9 @@ class ArrayAddress VALUE_OBJ_CLASS_SPEC {
};
const int FPUStateSizeInWords = NOT_LP64(27) LP64_ONLY( 512*2 / wordSize);
// 64-bit refect the fxsave size which is 512 bytes and the new xsave area on EVEX which is another 2176 bytes
// See fxsave and xsave(EVEX enabled) documentation for layout
const int FPUStateSizeInWords = NOT_LP64(27) LP64_ONLY(2688 / wordSize);
// The Intel x86/Amd64 Assembler: Pure assembler doing NO optimizations on the instruction
// level (e.g. mov rax, 0 is not translated into xor rax, rax!); i.e., what you write
@ -594,11 +596,16 @@ class Assembler : public AbstractAssembler {
private:
int evex_encoding;
int input_size_in_bits;
int avx_vector_len;
int tuple_type;
bool is_evex_instruction;
int _evex_encoding;
int _input_size_in_bits;
int _avx_vector_len;
int _tuple_type;
bool _is_evex_instruction;
bool _legacy_mode_bw;
bool _legacy_mode_dq;
bool _legacy_mode_vl;
bool _legacy_mode_vlbw;
bool _instruction_uses_vl;
// 64bit prefixes
int prefix_and_encode(int reg_enc, bool byteinst = false);
@ -972,11 +979,16 @@ private:
// belong in macro assembler but there is no need for both varieties to exist
void init_attributes(void) {
evex_encoding = 0;
input_size_in_bits = 0;
avx_vector_len = AVX_NoVec;
tuple_type = EVEX_ETUP;
is_evex_instruction = false;
_evex_encoding = 0;
_input_size_in_bits = 0;
_avx_vector_len = AVX_NoVec;
_tuple_type = EVEX_ETUP;
_is_evex_instruction = false;
_legacy_mode_bw = (VM_Version::supports_avx512bw() == false);
_legacy_mode_dq = (VM_Version::supports_avx512dq() == false);
_legacy_mode_vl = (VM_Version::supports_avx512vl() == false);
_legacy_mode_vlbw = (VM_Version::supports_avx512vlbw() == false);
_instruction_uses_vl = false;
}
void lea(Register dst, Address src);
@ -1344,8 +1356,10 @@ private:
void fxch(int i = 1);
void fxrstor(Address src);
void xrstor(Address src);
void fxsave(Address dst);
void xsave(Address dst);
void fyl2x();
void frndint();
@ -1479,11 +1493,12 @@ private:
void movb(Address dst, int imm8);
void movb(Register dst, Address src);
void kmovq(KRegister dst, KRegister src);
void kmovql(KRegister dst, KRegister src);
void kmovql(KRegister dst, Register src);
void kmovdl(KRegister dst, Register src);
void kmovq(Address dst, KRegister src);
void kmovq(KRegister dst, Address src);
void kmovwl(KRegister dst, Register src);
void kmovql(Address dst, KRegister src);
void kmovql(KRegister dst, Address src);
void movdl(XMMRegister dst, Register src);
void movdl(Register dst, XMMRegister src);
@ -1509,9 +1524,12 @@ private:
void vmovdqu(XMMRegister dst, XMMRegister src);
// Move Unaligned 512bit Vector
void evmovdqu(Address dst, XMMRegister src, int vector_len);
void evmovdqu(XMMRegister dst, Address src, int vector_len);
void evmovdqu(XMMRegister dst, XMMRegister src, int vector_len);
void evmovdqul(Address dst, XMMRegister src, int vector_len);
void evmovdqul(XMMRegister dst, Address src, int vector_len);
void evmovdqul(XMMRegister dst, XMMRegister src, int vector_len);
void evmovdquq(Address dst, XMMRegister src, int vector_len);
void evmovdquq(XMMRegister dst, Address src, int vector_len);
void evmovdquq(XMMRegister dst, XMMRegister src, int vector_len);
// Move lower 64bit to high 64bit in 128bit register
void movlhps(XMMRegister dst, XMMRegister src);
@ -1643,6 +1661,7 @@ private:
// Pemutation of 64bit words
void vpermq(XMMRegister dst, XMMRegister src, int imm8, int vector_len);
void vpermq(XMMRegister dst, XMMRegister src, int imm8);
void pause();
@ -1920,6 +1939,10 @@ private:
void vdivpd(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
void vdivps(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
// Sqrt Packed Floating-Point Values - Double precision only
void vsqrtpd(XMMRegister dst, XMMRegister src, int vector_len);
void vsqrtpd(XMMRegister dst, Address src, int vector_len);
// Bitwise Logical AND of Packed Floating-Point Values
void andpd(XMMRegister dst, XMMRegister src);
void andps(XMMRegister dst, XMMRegister src);
@ -2057,6 +2080,9 @@ private:
void vextracti64x2h(XMMRegister dst, XMMRegister src, int value);
void vextractf64x2h(XMMRegister dst, XMMRegister src, int value);
void vextractf32x4h(XMMRegister dst, XMMRegister src, int value);
void vextractf32x4h(Address dst, XMMRegister src, int value);
void vinsertf32x4h(XMMRegister dst, XMMRegister nds, XMMRegister src, int value);
void vinsertf32x4h(XMMRegister dst, Address src, int value);
// duplicate 4-bytes integer data from src into 8 locations in dest
void vpbroadcastd(XMMRegister dst, XMMRegister src);

View File

@ -3798,16 +3798,24 @@ void LIR_Assembler::negate(LIR_Opr left, LIR_Opr dest) {
if (left->as_xmm_float_reg() != dest->as_xmm_float_reg()) {
__ movflt(dest->as_xmm_float_reg(), left->as_xmm_float_reg());
}
__ xorps(dest->as_xmm_float_reg(),
ExternalAddress((address)float_signflip_pool));
if (UseAVX > 1) {
__ vnegatess(dest->as_xmm_float_reg(), dest->as_xmm_float_reg(),
ExternalAddress((address)float_signflip_pool));
} else {
__ xorps(dest->as_xmm_float_reg(),
ExternalAddress((address)float_signflip_pool));
}
} else if (dest->is_double_xmm()) {
if (left->as_xmm_double_reg() != dest->as_xmm_double_reg()) {
__ movdbl(dest->as_xmm_double_reg(), left->as_xmm_double_reg());
}
__ xorpd(dest->as_xmm_double_reg(),
ExternalAddress((address)double_signflip_pool));
if (UseAVX > 1) {
__ vnegatesd(dest->as_xmm_double_reg(), dest->as_xmm_double_reg(),
ExternalAddress((address)double_signflip_pool));
} else {
__ xorpd(dest->as_xmm_double_reg(),
ExternalAddress((address)double_signflip_pool));
}
} else if (left->is_single_fpu() || left->is_double_fpu()) {
assert(left->fpu() == 0, "arg must be on TOS");
assert(dest->fpu() == 0, "dest must be TOS");

View File

@ -401,11 +401,9 @@ static OopMap* generate_oop_map(StubAssembler* sasm, int num_rt_args,
} else if (UseSSE == 1) {
int xmm_off = xmm_regs_as_doubles_off;
for (int n = 0; n < FrameMap::nof_xmm_regs; n++) {
if (n < xmm_bypass_limit) {
VMReg xmm_name_0 = as_XMMRegister(n)->as_VMReg();
map->set_callee_saved(VMRegImpl::stack2reg(xmm_off + num_rt_args), xmm_name_0);
}
for (int n = 0; n < FrameMap::nof_fpu_regs; n++) {
VMReg xmm_name_0 = as_XMMRegister(n)->as_VMReg();
map->set_callee_saved(VMRegImpl::stack2reg(xmm_off + num_rt_args), xmm_name_0);
xmm_off += 2;
}
assert(xmm_off == float_regs_as_doubles_off, "incorrect number of xmm registers");
@ -452,14 +450,11 @@ static OopMap* save_live_registers(StubAssembler* sasm, int num_rt_args,
__ frstor(Address(rsp, fpu_state_off * VMRegImpl::stack_slot_size));
// Save the FPU registers in de-opt-able form
__ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 0));
__ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 8));
__ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 16));
__ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 24));
__ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 32));
__ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 40));
__ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 48));
__ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 56));
int offset = 0;
for (int n = 0; n < FrameMap::nof_fpu_regs; n++) {
__ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + offset));
offset += 8;
}
}
if (UseSSE >= 2) {
@ -468,52 +463,26 @@ static OopMap* save_live_registers(StubAssembler* sasm, int num_rt_args,
// so always save them as doubles.
// note that float values are _not_ converted automatically, so for float values
// the second word contains only garbage data.
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 0), xmm0);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 8), xmm1);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 16), xmm2);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 24), xmm3);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 32), xmm4);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 40), xmm5);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 48), xmm6);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 56), xmm7);
int xmm_bypass_limit = FrameMap::nof_xmm_regs;
int offset = 0;
#ifdef _LP64
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 64), xmm8);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 72), xmm9);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 80), xmm10);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 88), xmm11);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 96), xmm12);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 104), xmm13);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 112), xmm14);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 120), xmm15);
if (UseAVX > 2) {
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 128), xmm16);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 136), xmm17);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 144), xmm18);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 152), xmm19);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 160), xmm20);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 168), xmm21);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 176), xmm22);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 184), xmm23);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 192), xmm24);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 200), xmm25);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 208), xmm26);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 216), xmm27);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 224), xmm28);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 232), xmm29);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 240), xmm30);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 248), xmm31);
if (UseAVX < 3) {
xmm_bypass_limit = xmm_bypass_limit / 2;
}
#endif
for (int n = 0; n < xmm_bypass_limit; n++) {
XMMRegister xmm_name = as_XMMRegister(n);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + offset), xmm_name);
offset += 8;
}
#endif // _LP64
} else if (UseSSE == 1) {
// save XMM registers as float because double not supported without SSE2
__ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 0), xmm0);
__ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 8), xmm1);
__ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 16), xmm2);
__ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 24), xmm3);
__ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 32), xmm4);
__ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 40), xmm5);
__ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 48), xmm6);
__ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 56), xmm7);
// save XMM registers as float because double not supported without SSE2(num MMX == num fpu)
int offset = 0;
for (int n = 0; n < FrameMap::nof_fpu_regs; n++) {
XMMRegister xmm_name = as_XMMRegister(n);
__ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + offset), xmm_name);
offset += 8;
}
}
}
@ -528,52 +497,26 @@ static void restore_fpu(StubAssembler* sasm, bool restore_fpu_registers = true)
if (restore_fpu_registers) {
if (UseSSE >= 2) {
// restore XMM registers
__ movdbl(xmm0, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 0));
__ movdbl(xmm1, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 8));
__ movdbl(xmm2, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 16));
__ movdbl(xmm3, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 24));
__ movdbl(xmm4, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 32));
__ movdbl(xmm5, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 40));
__ movdbl(xmm6, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 48));
__ movdbl(xmm7, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 56));
int xmm_bypass_limit = FrameMap::nof_xmm_regs;
#ifdef _LP64
__ movdbl(xmm8, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 64));
__ movdbl(xmm9, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 72));
__ movdbl(xmm10, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 80));
__ movdbl(xmm11, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 88));
__ movdbl(xmm12, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 96));
__ movdbl(xmm13, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 104));
__ movdbl(xmm14, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 112));
__ movdbl(xmm15, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 120));
if (UseAVX > 2) {
__ movdbl(xmm16, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 128));
__ movdbl(xmm17, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 136));
__ movdbl(xmm18, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 144));
__ movdbl(xmm19, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 152));
__ movdbl(xmm20, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 160));
__ movdbl(xmm21, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 168));
__ movdbl(xmm22, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 176));
__ movdbl(xmm23, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 184));
__ movdbl(xmm24, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 192));
__ movdbl(xmm25, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 200));
__ movdbl(xmm26, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 208));
__ movdbl(xmm27, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 216));
__ movdbl(xmm28, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 224));
__ movdbl(xmm29, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 232));
__ movdbl(xmm30, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 240));
__ movdbl(xmm31, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 248));
if (UseAVX < 3) {
xmm_bypass_limit = xmm_bypass_limit / 2;
}
#endif
int offset = 0;
for (int n = 0; n < xmm_bypass_limit; n++) {
XMMRegister xmm_name = as_XMMRegister(n);
__ movdbl(xmm_name, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + offset));
offset += 8;
}
#endif // _LP64
} else if (UseSSE == 1) {
// restore XMM registers
__ movflt(xmm0, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 0));
__ movflt(xmm1, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 8));
__ movflt(xmm2, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 16));
__ movflt(xmm3, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 24));
__ movflt(xmm4, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 32));
__ movflt(xmm5, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 40));
__ movflt(xmm6, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 48));
__ movflt(xmm7, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 56));
// restore XMM registers(num MMX == num fpu)
int offset = 0;
for (int n = 0; n < FrameMap::nof_fpu_regs; n++) {
XMMRegister xmm_name = as_XMMRegister(n);
__ movflt(xmm_name, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + offset));
offset += 8;
}
}
if (UseSSE < 2) {

View File

@ -3751,8 +3751,31 @@ void MacroAssembler::pop_CPU_state() {
}
void MacroAssembler::pop_FPU_state() {
NOT_LP64(frstor(Address(rsp, 0));)
LP64_ONLY(fxrstor(Address(rsp, 0));)
#ifndef _LP64
frstor(Address(rsp, 0));
#else
// AVX will continue to use the fxsave area.
// EVEX needs to utilize the xsave area, which is under different
// management.
if(VM_Version::supports_evex()) {
// EDX:EAX describe the XSAVE header and
// are obtained while fetching info for XCR0 via cpuid.
// These two registers make up 64-bits in the header for which bits
// 62:10 are currently reserved for future implementations and unused. Bit 63
// is unused for our implementation as we do not utilize
// compressed XSAVE areas. Bits 9..8 are currently ignored as we do not use
// the functionality for PKRU state and MSR tracing.
// Ergo we are primarily concerned with bits 7..0, which define
// which ISA extensions and features are enabled for a given machine and are
// defined in XemXcr0Eax and is used to map the XSAVE area
// for restoring registers as described via XCR0.
movl(rdx,VM_Version::get_xsave_header_upper_segment());
movl(rax,VM_Version::get_xsave_header_lower_segment());
xrstor(Address(rsp, 0));
} else {
fxrstor(Address(rsp, 0));
}
#endif
addptr(rsp, FPUStateSizeInWords * wordSize);
}
@ -3769,13 +3792,49 @@ void MacroAssembler::push_CPU_state() {
push_FPU_state();
}
#ifdef _LP64
#define XSTATE_BV 0x200
#endif
void MacroAssembler::push_FPU_state() {
subptr(rsp, FPUStateSizeInWords * wordSize);
#ifndef _LP64
fnsave(Address(rsp, 0));
fwait();
#else
fxsave(Address(rsp, 0));
// AVX will continue to use the fxsave area.
// EVEX needs to utilize the xsave area, which is under different
// management.
if(VM_Version::supports_evex()) {
// Save a copy of EAX and EDX
push(rax);
push(rdx);
// EDX:EAX describe the XSAVE header and
// are obtained while fetching info for XCR0 via cpuid.
// These two registers make up 64-bits in the header for which bits
// 62:10 are currently reserved for future implementations and unused. Bit 63
// is unused for our implementation as we do not utilize
// compressed XSAVE areas. Bits 9..8 are currently ignored as we do not use
// the functionality for PKRU state and MSR tracing.
// Ergo we are primarily concerned with bits 7..0, which define
// which ISA extensions and features are enabled for a given machine and are
// defined in XemXcr0Eax and is used to program XSAVE area
// for saving the required registers as defined in XCR0.
int xcr0_edx = VM_Version::get_xsave_header_upper_segment();
int xcr0_eax = VM_Version::get_xsave_header_lower_segment();
movl(rdx,xcr0_edx);
movl(rax,xcr0_eax);
xsave(Address(rsp, wordSize*2));
// now Apply control bits and clear bytes 8..23 in the header
pop(rdx);
pop(rax);
movl(Address(rsp, XSTATE_BV), xcr0_eax);
movl(Address(rsp, XSTATE_BV+4), xcr0_edx);
andq(Address(rsp, XSTATE_BV+8), 0);
andq(Address(rsp, XSTATE_BV+16), 0);
} else {
fxsave(Address(rsp, 0));
}
#endif // LP64
}
@ -4082,6 +4141,84 @@ void MacroAssembler::vsubss(XMMRegister dst, XMMRegister nds, AddressLiteral src
}
}
void MacroAssembler::vnegatess(XMMRegister dst, XMMRegister nds, AddressLiteral src) {
int nds_enc = nds->encoding();
int dst_enc = dst->encoding();
bool dst_upper_bank = (dst_enc > 15);
bool nds_upper_bank = (nds_enc > 15);
if (VM_Version::supports_avx512novl() &&
(nds_upper_bank || dst_upper_bank)) {
if (dst_upper_bank) {
subptr(rsp, 64);
evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
movflt(xmm0, nds);
if (reachable(src)) {
vxorps(xmm0, xmm0, as_Address(src), Assembler::AVX_128bit);
} else {
lea(rscratch1, src);
vxorps(xmm0, xmm0, Address(rscratch1, 0), Assembler::AVX_128bit);
}
movflt(dst, xmm0);
evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
addptr(rsp, 64);
} else {
movflt(dst, nds);
if (reachable(src)) {
vxorps(dst, dst, as_Address(src), Assembler::AVX_128bit);
} else {
lea(rscratch1, src);
vxorps(dst, dst, Address(rscratch1, 0), Assembler::AVX_128bit);
}
}
} else {
if (reachable(src)) {
vxorps(dst, nds, as_Address(src), Assembler::AVX_128bit);
} else {
lea(rscratch1, src);
vxorps(dst, nds, Address(rscratch1, 0), Assembler::AVX_128bit);
}
}
}
void MacroAssembler::vnegatesd(XMMRegister dst, XMMRegister nds, AddressLiteral src) {
int nds_enc = nds->encoding();
int dst_enc = dst->encoding();
bool dst_upper_bank = (dst_enc > 15);
bool nds_upper_bank = (nds_enc > 15);
if (VM_Version::supports_avx512novl() &&
(nds_upper_bank || dst_upper_bank)) {
if (dst_upper_bank) {
subptr(rsp, 64);
evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
movdbl(xmm0, nds);
if (reachable(src)) {
vxorps(xmm0, xmm0, as_Address(src), Assembler::AVX_128bit);
} else {
lea(rscratch1, src);
vxorps(xmm0, xmm0, Address(rscratch1, 0), Assembler::AVX_128bit);
}
movdbl(dst, xmm0);
evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
addptr(rsp, 64);
} else {
movdbl(dst, nds);
if (reachable(src)) {
vxorps(dst, dst, as_Address(src), Assembler::AVX_128bit);
} else {
lea(rscratch1, src);
vxorps(dst, dst, Address(rscratch1, 0), Assembler::AVX_128bit);
}
}
} else {
if (reachable(src)) {
vxorpd(dst, nds, as_Address(src), Assembler::AVX_128bit);
} else {
lea(rscratch1, src);
vxorpd(dst, nds, Address(rscratch1, 0), Assembler::AVX_128bit);
}
}
}
void MacroAssembler::vxorpd(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len) {
if (reachable(src)) {
vxorpd(dst, nds, as_Address(src), vector_len);
@ -4318,7 +4455,6 @@ void MacroAssembler::store_check(Register obj, Address dst) {
void MacroAssembler::store_check(Register obj) {
// Does a store check for the oop in register obj. The content of
// register obj is destroyed afterwards.
BarrierSet* bs = Universe::heap()->barrier_set();
assert(bs->kind() == BarrierSet::CardTableForRS ||
bs->kind() == BarrierSet::CardTableExtension,
@ -4572,69 +4708,58 @@ void MacroAssembler::fp_runtime_fallback(address runtime_entry, int nb_args, int
// if we are coming from c1, xmm registers may be live
int off = 0;
int num_xmm_regs = LP64_ONLY(16) NOT_LP64(8);
if (UseAVX > 2) {
num_xmm_regs = LP64_ONLY(32) NOT_LP64(8);
}
if (UseSSE == 1) {
subptr(rsp, sizeof(jdouble)*8);
movflt(Address(rsp,off++*sizeof(jdouble)),xmm0);
movflt(Address(rsp,off++*sizeof(jdouble)),xmm1);
movflt(Address(rsp,off++*sizeof(jdouble)),xmm2);
movflt(Address(rsp,off++*sizeof(jdouble)),xmm3);
movflt(Address(rsp,off++*sizeof(jdouble)),xmm4);
movflt(Address(rsp,off++*sizeof(jdouble)),xmm5);
movflt(Address(rsp,off++*sizeof(jdouble)),xmm6);
movflt(Address(rsp,off++*sizeof(jdouble)),xmm7);
for (int n = 0; n < 8; n++) {
movflt(Address(rsp, off++*sizeof(jdouble)), as_XMMRegister(n));
}
} else if (UseSSE >= 2) {
if (UseAVX > 2) {
push(rbx);
movl(rbx, 0xffff);
#ifdef _LP64
kmovql(k1, rbx);
#else
kmovdl(k1, rbx);
#endif
kmovwl(k1, rbx);
pop(rbx);
}
#ifdef COMPILER2
if (MaxVectorSize > 16) {
assert(UseAVX > 0, "256bit vectors are supported only with AVX");
if(UseAVX > 2) {
// Save upper half of ZMM registes
subptr(rsp, 32*num_xmm_regs);
for (int n = 0; n < num_xmm_regs; n++) {
vextractf64x4h(Address(rsp, off++*32), as_XMMRegister(n));
}
off = 0;
}
assert(UseAVX > 0, "256 bit vectors are supported only with AVX");
// Save upper half of YMM registes
subptr(rsp, 16 * LP64_ONLY(16) NOT_LP64(8));
vextractf128h(Address(rsp, 0),xmm0);
vextractf128h(Address(rsp, 16),xmm1);
vextractf128h(Address(rsp, 32),xmm2);
vextractf128h(Address(rsp, 48),xmm3);
vextractf128h(Address(rsp, 64),xmm4);
vextractf128h(Address(rsp, 80),xmm5);
vextractf128h(Address(rsp, 96),xmm6);
vextractf128h(Address(rsp,112),xmm7);
#ifdef _LP64
vextractf128h(Address(rsp,128),xmm8);
vextractf128h(Address(rsp,144),xmm9);
vextractf128h(Address(rsp,160),xmm10);
vextractf128h(Address(rsp,176),xmm11);
vextractf128h(Address(rsp,192),xmm12);
vextractf128h(Address(rsp,208),xmm13);
vextractf128h(Address(rsp,224),xmm14);
vextractf128h(Address(rsp,240),xmm15);
#endif
subptr(rsp, 16*num_xmm_regs);
for (int n = 0; n < num_xmm_regs; n++) {
vextractf128h(Address(rsp, off++*16), as_XMMRegister(n));
}
}
#endif
// Save whole 128bit (16 bytes) XMM regiters
subptr(rsp, 16 * LP64_ONLY(16) NOT_LP64(8));
movdqu(Address(rsp,off++*16),xmm0);
movdqu(Address(rsp,off++*16),xmm1);
movdqu(Address(rsp,off++*16),xmm2);
movdqu(Address(rsp,off++*16),xmm3);
movdqu(Address(rsp,off++*16),xmm4);
movdqu(Address(rsp,off++*16),xmm5);
movdqu(Address(rsp,off++*16),xmm6);
movdqu(Address(rsp,off++*16),xmm7);
// Save whole 128bit (16 bytes) XMM registers
subptr(rsp, 16*num_xmm_regs);
off = 0;
#ifdef _LP64
movdqu(Address(rsp,off++*16),xmm8);
movdqu(Address(rsp,off++*16),xmm9);
movdqu(Address(rsp,off++*16),xmm10);
movdqu(Address(rsp,off++*16),xmm11);
movdqu(Address(rsp,off++*16),xmm12);
movdqu(Address(rsp,off++*16),xmm13);
movdqu(Address(rsp,off++*16),xmm14);
movdqu(Address(rsp,off++*16),xmm15);
if (VM_Version::supports_avx512novl()) {
for (int n = 0; n < num_xmm_regs; n++) {
vextractf32x4h(Address(rsp, off++*16), as_XMMRegister(n), 0);
}
} else {
for (int n = 0; n < num_xmm_regs; n++) {
movdqu(Address(rsp, off++*16), as_XMMRegister(n));
}
}
#else
for (int n = 0; n < num_xmm_regs; n++) {
movdqu(Address(rsp, off++*16), as_XMMRegister(n));
}
#endif
}
@ -4689,7 +4814,7 @@ void MacroAssembler::fp_runtime_fallback(address runtime_entry, int nb_args, int
movsd(Address(rsp, 0), xmm0);
fld_d(Address(rsp, 0));
#endif // _LP64
addptr(rsp, sizeof(jdouble) * nb_args);
addptr(rsp, sizeof(jdouble)*nb_args);
if (num_fpu_regs_in_use > 1) {
// Must save return value to stack and then restore entire FPU
// stack except incoming arguments
@ -4699,63 +4824,50 @@ void MacroAssembler::fp_runtime_fallback(address runtime_entry, int nb_args, int
addptr(rsp, sizeof(jdouble));
}
fld_d(Address(rsp, (nb_args-1)*sizeof(jdouble)));
addptr(rsp, sizeof(jdouble) * nb_args);
addptr(rsp, sizeof(jdouble)*nb_args);
}
off = 0;
if (UseSSE == 1) {
movflt(xmm0, Address(rsp,off++*sizeof(jdouble)));
movflt(xmm1, Address(rsp,off++*sizeof(jdouble)));
movflt(xmm2, Address(rsp,off++*sizeof(jdouble)));
movflt(xmm3, Address(rsp,off++*sizeof(jdouble)));
movflt(xmm4, Address(rsp,off++*sizeof(jdouble)));
movflt(xmm5, Address(rsp,off++*sizeof(jdouble)));
movflt(xmm6, Address(rsp,off++*sizeof(jdouble)));
movflt(xmm7, Address(rsp,off++*sizeof(jdouble)));
for (int n = 0; n < 8; n++) {
movflt(as_XMMRegister(n), Address(rsp, off++*sizeof(jdouble)));
}
addptr(rsp, sizeof(jdouble)*8);
} else if (UseSSE >= 2) {
// Restore whole 128bit (16 bytes) XMM regiters
movdqu(xmm0, Address(rsp,off++*16));
movdqu(xmm1, Address(rsp,off++*16));
movdqu(xmm2, Address(rsp,off++*16));
movdqu(xmm3, Address(rsp,off++*16));
movdqu(xmm4, Address(rsp,off++*16));
movdqu(xmm5, Address(rsp,off++*16));
movdqu(xmm6, Address(rsp,off++*16));
movdqu(xmm7, Address(rsp,off++*16));
#ifdef _LP64
movdqu(xmm8, Address(rsp,off++*16));
movdqu(xmm9, Address(rsp,off++*16));
movdqu(xmm10, Address(rsp,off++*16));
movdqu(xmm11, Address(rsp,off++*16));
movdqu(xmm12, Address(rsp,off++*16));
movdqu(xmm13, Address(rsp,off++*16));
movdqu(xmm14, Address(rsp,off++*16));
movdqu(xmm15, Address(rsp,off++*16));
if (VM_Version::supports_avx512novl()) {
for (int n = 0; n < num_xmm_regs; n++) {
vinsertf32x4h(as_XMMRegister(n), Address(rsp, off++*16), 0);
}
}
else {
for (int n = 0; n < num_xmm_regs; n++) {
movdqu(as_XMMRegister(n), Address(rsp, off++*16));
}
}
#else
for (int n = 0; n < num_xmm_regs; n++) {
movdqu(as_XMMRegister(n), Address(rsp, off++ * 16));
}
#endif
addptr(rsp, 16 * LP64_ONLY(16) NOT_LP64(8));
addptr(rsp, 16*num_xmm_regs);
#ifdef COMPILER2
if (MaxVectorSize > 16) {
// Restore upper half of YMM registes.
vinsertf128h(xmm0, Address(rsp, 0));
vinsertf128h(xmm1, Address(rsp, 16));
vinsertf128h(xmm2, Address(rsp, 32));
vinsertf128h(xmm3, Address(rsp, 48));
vinsertf128h(xmm4, Address(rsp, 64));
vinsertf128h(xmm5, Address(rsp, 80));
vinsertf128h(xmm6, Address(rsp, 96));
vinsertf128h(xmm7, Address(rsp,112));
#ifdef _LP64
vinsertf128h(xmm8, Address(rsp,128));
vinsertf128h(xmm9, Address(rsp,144));
vinsertf128h(xmm10, Address(rsp,160));
vinsertf128h(xmm11, Address(rsp,176));
vinsertf128h(xmm12, Address(rsp,192));
vinsertf128h(xmm13, Address(rsp,208));
vinsertf128h(xmm14, Address(rsp,224));
vinsertf128h(xmm15, Address(rsp,240));
#endif
addptr(rsp, 16 * LP64_ONLY(16) NOT_LP64(8));
off = 0;
for (int n = 0; n < num_xmm_regs; n++) {
vinsertf128h(as_XMMRegister(n), Address(rsp, off++*16));
}
addptr(rsp, 16*num_xmm_regs);
if(UseAVX > 2) {
off = 0;
for (int n = 0; n < num_xmm_regs; n++) {
vinsertf64x4h(as_XMMRegister(n), Address(rsp, off++*32));
}
addptr(rsp, 32*num_xmm_regs);
}
}
#endif
}
@ -7095,11 +7207,7 @@ void MacroAssembler::generate_fill(BasicType t, bool aligned,
Label L_fill_32_bytes_loop, L_check_fill_8_bytes, L_fill_8_bytes_loop, L_fill_8_bytes;
if (UseAVX > 2) {
movl(rtmp, 0xffff);
#ifdef _LP64
kmovql(k1, rtmp);
#else
kmovdl(k1, rtmp);
#endif
kmovwl(k1, rtmp);
}
movdl(xtmp, value);
if (UseAVX > 2 && UseUnalignedLoadStores) {
@ -7112,7 +7220,7 @@ void MacroAssembler::generate_fill(BasicType t, bool aligned,
align(16);
BIND(L_fill_64_bytes_loop);
evmovdqu(Address(to, 0), xtmp, Assembler::AVX_512bit);
evmovdqul(Address(to, 0), xtmp, Assembler::AVX_512bit);
addptr(to, 64);
subl(count, 16 << shift);
jcc(Assembler::greaterEqual, L_fill_64_bytes_loop);
@ -7120,7 +7228,7 @@ void MacroAssembler::generate_fill(BasicType t, bool aligned,
BIND(L_check_fill_32_bytes);
addl(count, 8 << shift);
jccb(Assembler::less, L_check_fill_8_bytes);
evmovdqu(Address(to, 0), xtmp, Assembler::AVX_256bit);
evmovdqul(Address(to, 0), xtmp, Assembler::AVX_256bit);
addptr(to, 32);
subl(count, 8 << shift);
@ -8399,6 +8507,14 @@ void MacroAssembler::kernel_crc32(Register crc, Register buf, Register len, Regi
Label L_tail, L_tail_restore, L_tail_loop, L_exit, L_align_loop, L_aligned;
Label L_fold_tail, L_fold_128b, L_fold_512b, L_fold_512b_loop, L_fold_tail_loop;
// For EVEX with VL and BW, provide a standard mask, VL = 128 will guide the merge
// context for the registers used, where all instructions below are using 128-bit mode
// On EVEX without VL and BW, these instructions will all be AVX.
if (VM_Version::supports_avx512vlbw()) {
movl(tmp, 0xffff);
kmovwl(k1, tmp);
}
lea(table, ExternalAddress(StubRoutines::crc_table_addr()));
notl(crc); // ~crc
cmpl(len, 16);

View File

@ -1069,6 +1069,9 @@ public:
void vsubss(XMMRegister dst, XMMRegister nds, Address src) { Assembler::vsubss(dst, nds, src); }
void vsubss(XMMRegister dst, XMMRegister nds, AddressLiteral src);
void vnegatess(XMMRegister dst, XMMRegister nds, AddressLiteral src);
void vnegatesd(XMMRegister dst, XMMRegister nds, AddressLiteral src);
// AVX Vector instructions
void vxorpd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { Assembler::vxorpd(dst, nds, src, vector_len); }

View File

@ -115,6 +115,7 @@ class RegisterSaver {
OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_frame_words,
int* total_frame_words, bool verify_fpu, bool save_vectors) {
int vect_words = 0;
int num_xmm_regs = XMMRegisterImpl::number_of_registers;
#ifdef COMPILER2
if (save_vectors) {
assert(UseAVX > 0, "512bit vectors are supported only with EVEX");
@ -173,59 +174,50 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
__ fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std()));
}
int off = st0_off;
int delta = st1_off - off;
// Save the FPU registers in de-opt-able form
for (int n = 0; n < FloatRegisterImpl::number_of_registers; n++) {
__ fstp_d(Address(rsp, off*wordSize));
off += delta;
}
__ fstp_d(Address(rsp, st0_off*wordSize)); // st(0)
__ fstp_d(Address(rsp, st1_off*wordSize)); // st(1)
__ fstp_d(Address(rsp, st2_off*wordSize)); // st(2)
__ fstp_d(Address(rsp, st3_off*wordSize)); // st(3)
__ fstp_d(Address(rsp, st4_off*wordSize)); // st(4)
__ fstp_d(Address(rsp, st5_off*wordSize)); // st(5)
__ fstp_d(Address(rsp, st6_off*wordSize)); // st(6)
__ fstp_d(Address(rsp, st7_off*wordSize)); // st(7)
if( UseSSE == 1 ) { // Save the XMM state
__ movflt(Address(rsp,xmm0_off*wordSize),xmm0);
__ movflt(Address(rsp,xmm1_off*wordSize),xmm1);
__ movflt(Address(rsp,xmm2_off*wordSize),xmm2);
__ movflt(Address(rsp,xmm3_off*wordSize),xmm3);
__ movflt(Address(rsp,xmm4_off*wordSize),xmm4);
__ movflt(Address(rsp,xmm5_off*wordSize),xmm5);
__ movflt(Address(rsp,xmm6_off*wordSize),xmm6);
__ movflt(Address(rsp,xmm7_off*wordSize),xmm7);
} else if( UseSSE >= 2 ) {
off = xmm0_off;
delta = xmm1_off - off;
if(UseSSE == 1) { // Save the XMM state
for (int n = 0; n < num_xmm_regs; n++) {
__ movflt(Address(rsp, off*wordSize), as_XMMRegister(n));
off += delta;
}
} else if(UseSSE >= 2) {
// Save whole 128bit (16 bytes) XMM regiters
__ movdqu(Address(rsp,xmm0_off*wordSize),xmm0);
__ movdqu(Address(rsp,xmm1_off*wordSize),xmm1);
__ movdqu(Address(rsp,xmm2_off*wordSize),xmm2);
__ movdqu(Address(rsp,xmm3_off*wordSize),xmm3);
__ movdqu(Address(rsp,xmm4_off*wordSize),xmm4);
__ movdqu(Address(rsp,xmm5_off*wordSize),xmm5);
__ movdqu(Address(rsp,xmm6_off*wordSize),xmm6);
__ movdqu(Address(rsp,xmm7_off*wordSize),xmm7);
if (VM_Version::supports_avx512novl()) {
for (int n = 0; n < num_xmm_regs; n++) {
__ vextractf32x4h(Address(rsp, off*wordSize), as_XMMRegister(n), 0);
off += delta;
}
} else {
for (int n = 0; n < num_xmm_regs; n++) {
__ movdqu(Address(rsp, off*wordSize), as_XMMRegister(n));
off += delta;
}
}
}
if (vect_words > 0) {
assert(vect_words*wordSize == 128, "");
__ subptr(rsp, 128); // Save upper half of YMM registes
__ vextractf128h(Address(rsp, 0),xmm0);
__ vextractf128h(Address(rsp, 16),xmm1);
__ vextractf128h(Address(rsp, 32),xmm2);
__ vextractf128h(Address(rsp, 48),xmm3);
__ vextractf128h(Address(rsp, 64),xmm4);
__ vextractf128h(Address(rsp, 80),xmm5);
__ vextractf128h(Address(rsp, 96),xmm6);
__ vextractf128h(Address(rsp,112),xmm7);
off = 0;
for (int n = 0; n < num_xmm_regs; n++) {
__ vextractf128h(Address(rsp, off++*16), as_XMMRegister(n));
}
if (UseAVX > 2) {
__ subptr(rsp, 256); // Save upper half of ZMM registes
__ vextractf64x4h(Address(rsp, 0), xmm0);
__ vextractf64x4h(Address(rsp, 32), xmm1);
__ vextractf64x4h(Address(rsp, 64), xmm2);
__ vextractf64x4h(Address(rsp, 96), xmm3);
__ vextractf64x4h(Address(rsp, 128), xmm4);
__ vextractf64x4h(Address(rsp, 160), xmm5);
__ vextractf64x4h(Address(rsp, 192), xmm6);
__ vextractf64x4h(Address(rsp, 224), xmm7);
off = 0;
for (int n = 0; n < num_xmm_regs; n++) {
__ vextractf64x4h(Address(rsp, off++*32), as_XMMRegister(n));
}
}
}
@ -238,58 +230,40 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
OopMap* map = new OopMap( frame_words, 0 );
#define STACK_OFFSET(x) VMRegImpl::stack2reg((x) + additional_frame_words)
map->set_callee_saved(STACK_OFFSET( rax_off), rax->as_VMReg());
map->set_callee_saved(STACK_OFFSET( rcx_off), rcx->as_VMReg());
map->set_callee_saved(STACK_OFFSET( rdx_off), rdx->as_VMReg());
map->set_callee_saved(STACK_OFFSET( rbx_off), rbx->as_VMReg());
// rbp, location is known implicitly, no oopMap
map->set_callee_saved(STACK_OFFSET( rsi_off), rsi->as_VMReg());
map->set_callee_saved(STACK_OFFSET( rdi_off), rdi->as_VMReg());
map->set_callee_saved(STACK_OFFSET(st0_off), as_FloatRegister(0)->as_VMReg());
map->set_callee_saved(STACK_OFFSET(st1_off), as_FloatRegister(1)->as_VMReg());
map->set_callee_saved(STACK_OFFSET(st2_off), as_FloatRegister(2)->as_VMReg());
map->set_callee_saved(STACK_OFFSET(st3_off), as_FloatRegister(3)->as_VMReg());
map->set_callee_saved(STACK_OFFSET(st4_off), as_FloatRegister(4)->as_VMReg());
map->set_callee_saved(STACK_OFFSET(st5_off), as_FloatRegister(5)->as_VMReg());
map->set_callee_saved(STACK_OFFSET(st6_off), as_FloatRegister(6)->as_VMReg());
map->set_callee_saved(STACK_OFFSET(st7_off), as_FloatRegister(7)->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm0_off), xmm0->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm1_off), xmm1->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm2_off), xmm2->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm3_off), xmm3->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm4_off), xmm4->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm5_off), xmm5->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm6_off), xmm6->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm7_off), xmm7->as_VMReg());
// %%% This is really a waste but we'll keep things as they were for now
if (true) {
#define NEXTREG(x) (x)->as_VMReg()->next()
map->set_callee_saved(STACK_OFFSET(st0H_off), NEXTREG(as_FloatRegister(0)));
map->set_callee_saved(STACK_OFFSET(st1H_off), NEXTREG(as_FloatRegister(1)));
map->set_callee_saved(STACK_OFFSET(st2H_off), NEXTREG(as_FloatRegister(2)));
map->set_callee_saved(STACK_OFFSET(st3H_off), NEXTREG(as_FloatRegister(3)));
map->set_callee_saved(STACK_OFFSET(st4H_off), NEXTREG(as_FloatRegister(4)));
map->set_callee_saved(STACK_OFFSET(st5H_off), NEXTREG(as_FloatRegister(5)));
map->set_callee_saved(STACK_OFFSET(st6H_off), NEXTREG(as_FloatRegister(6)));
map->set_callee_saved(STACK_OFFSET(st7H_off), NEXTREG(as_FloatRegister(7)));
map->set_callee_saved(STACK_OFFSET(xmm0H_off), NEXTREG(xmm0));
map->set_callee_saved(STACK_OFFSET(xmm1H_off), NEXTREG(xmm1));
map->set_callee_saved(STACK_OFFSET(xmm2H_off), NEXTREG(xmm2));
map->set_callee_saved(STACK_OFFSET(xmm3H_off), NEXTREG(xmm3));
map->set_callee_saved(STACK_OFFSET(xmm4H_off), NEXTREG(xmm4));
map->set_callee_saved(STACK_OFFSET(xmm5H_off), NEXTREG(xmm5));
map->set_callee_saved(STACK_OFFSET(xmm6H_off), NEXTREG(xmm6));
map->set_callee_saved(STACK_OFFSET(xmm7H_off), NEXTREG(xmm7));
map->set_callee_saved(STACK_OFFSET(rax_off), rax->as_VMReg());
map->set_callee_saved(STACK_OFFSET(rcx_off), rcx->as_VMReg());
map->set_callee_saved(STACK_OFFSET(rdx_off), rdx->as_VMReg());
map->set_callee_saved(STACK_OFFSET(rbx_off), rbx->as_VMReg());
// rbp, location is known implicitly, no oopMap
map->set_callee_saved(STACK_OFFSET(rsi_off), rsi->as_VMReg());
map->set_callee_saved(STACK_OFFSET(rdi_off), rdi->as_VMReg());
// %%% This is really a waste but we'll keep things as they were for now for the upper component
off = st0_off;
delta = st1_off - off;
for (int n = 0; n < FloatRegisterImpl::number_of_registers; n++) {
FloatRegister freg_name = as_FloatRegister(n);
map->set_callee_saved(STACK_OFFSET(off), freg_name->as_VMReg());
map->set_callee_saved(STACK_OFFSET(off+1), NEXTREG(freg_name));
off += delta;
}
off = xmm0_off;
delta = xmm1_off - off;
for (int n = 0; n < num_xmm_regs; n++) {
XMMRegister xmm_name = as_XMMRegister(n);
map->set_callee_saved(STACK_OFFSET(off), xmm_name->as_VMReg());
map->set_callee_saved(STACK_OFFSET(off+1), NEXTREG(xmm_name));
off += delta;
}
#undef NEXTREG
#undef STACK_OFFSET
}
return map;
}
void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_vectors) {
int num_xmm_regs = XMMRegisterImpl::number_of_registers;
// Recover XMM & FPU state
int additional_frame_bytes = 0;
#ifdef COMPILER2
@ -301,52 +275,43 @@ void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_ve
#else
assert(!restore_vectors, "vectors are generated only by C2");
#endif
int off = xmm0_off;
int delta = xmm1_off - off;
if (UseSSE == 1) {
assert(additional_frame_bytes == 0, "");
__ movflt(xmm0,Address(rsp,xmm0_off*wordSize));
__ movflt(xmm1,Address(rsp,xmm1_off*wordSize));
__ movflt(xmm2,Address(rsp,xmm2_off*wordSize));
__ movflt(xmm3,Address(rsp,xmm3_off*wordSize));
__ movflt(xmm4,Address(rsp,xmm4_off*wordSize));
__ movflt(xmm5,Address(rsp,xmm5_off*wordSize));
__ movflt(xmm6,Address(rsp,xmm6_off*wordSize));
__ movflt(xmm7,Address(rsp,xmm7_off*wordSize));
for (int n = 0; n < num_xmm_regs; n++) {
__ movflt(as_XMMRegister(n), Address(rsp, off*wordSize));
off += delta;
}
} else if (UseSSE >= 2) {
#define STACK_ADDRESS(x) Address(rsp,(x)*wordSize + additional_frame_bytes)
__ movdqu(xmm0,STACK_ADDRESS(xmm0_off));
__ movdqu(xmm1,STACK_ADDRESS(xmm1_off));
__ movdqu(xmm2,STACK_ADDRESS(xmm2_off));
__ movdqu(xmm3,STACK_ADDRESS(xmm3_off));
__ movdqu(xmm4,STACK_ADDRESS(xmm4_off));
__ movdqu(xmm5,STACK_ADDRESS(xmm5_off));
__ movdqu(xmm6,STACK_ADDRESS(xmm6_off));
__ movdqu(xmm7,STACK_ADDRESS(xmm7_off));
#undef STACK_ADDRESS
if (VM_Version::supports_avx512novl()) {
for (int n = 0; n < num_xmm_regs; n++) {
__ vinsertf32x4h(as_XMMRegister(n), Address(rsp, off*wordSize+additional_frame_bytes), 0);
off += delta;
}
} else {
for (int n = 0; n < num_xmm_regs; n++) {
__ movdqu(as_XMMRegister(n), Address(rsp, off*wordSize+additional_frame_bytes));
off += delta;
}
}
}
if (restore_vectors) {
if (UseAVX > 2) {
off = 0;
for (int n = 0; n < num_xmm_regs; n++) {
__ vinsertf64x4h(as_XMMRegister(n), Address(rsp, off++*32));
}
__ addptr(rsp, additional_frame_bytes*2); // Save upper half of ZMM registes
}
// Restore upper half of YMM registes.
assert(additional_frame_bytes == 128, "");
__ vinsertf128h(xmm0, Address(rsp, 0));
__ vinsertf128h(xmm1, Address(rsp, 16));
__ vinsertf128h(xmm2, Address(rsp, 32));
__ vinsertf128h(xmm3, Address(rsp, 48));
__ vinsertf128h(xmm4, Address(rsp, 64));
__ vinsertf128h(xmm5, Address(rsp, 80));
__ vinsertf128h(xmm6, Address(rsp, 96));
__ vinsertf128h(xmm7, Address(rsp,112));
__ addptr(rsp, additional_frame_bytes);
if (UseAVX > 2) {
additional_frame_bytes = 256;
__ vinsertf64x4h(xmm0, Address(rsp, 0));
__ vinsertf64x4h(xmm1, Address(rsp, 32));
__ vinsertf64x4h(xmm2, Address(rsp, 64));
__ vinsertf64x4h(xmm3, Address(rsp, 96));
__ vinsertf64x4h(xmm4, Address(rsp, 128));
__ vinsertf64x4h(xmm5, Address(rsp, 160));
__ vinsertf64x4h(xmm6, Address(rsp, 192));
__ vinsertf64x4h(xmm7, Address(rsp, 224));
__ addptr(rsp, additional_frame_bytes);
off = 0;
for (int n = 0; n < num_xmm_regs; n++) {
__ vinsertf128h(as_XMMRegister(n), Address(rsp, off++*16));
}
__ addptr(rsp, additional_frame_bytes); // Save upper half of YMM registes
}
__ pop_FPU_state();
__ addptr(rsp, FPU_regs_live*wordSize); // Pop FPU registers

View File

@ -69,7 +69,9 @@ class SimpleRuntimeFrame {
class RegisterSaver {
// Capture info about frame layout. Layout offsets are in jint
// units because compiler frame slots are jints.
#define HALF_ZMM_BANK_WORDS 128
#define DEF_XMM_OFFS(regnum) xmm ## regnum ## _off = xmm_off + (regnum)*16/BytesPerInt, xmm ## regnum ## H_off
#define DEF_ZMM_OFFS(regnum) zmm ## regnum ## _off = zmm_off + (regnum-16)*64/BytesPerInt, zmm ## regnum ## H_off
enum layout {
fpu_state_off = frame::arg_reg_save_area_bytes/BytesPerInt, // fxsave save area
xmm_off = fpu_state_off + 160/BytesPerInt, // offset in fxsave save area
@ -89,23 +91,24 @@ class RegisterSaver {
DEF_XMM_OFFS(13),
DEF_XMM_OFFS(14),
DEF_XMM_OFFS(15),
DEF_XMM_OFFS(16),
DEF_XMM_OFFS(17),
DEF_XMM_OFFS(18),
DEF_XMM_OFFS(19),
DEF_XMM_OFFS(20),
DEF_XMM_OFFS(21),
DEF_XMM_OFFS(22),
DEF_XMM_OFFS(23),
DEF_XMM_OFFS(24),
DEF_XMM_OFFS(25),
DEF_XMM_OFFS(26),
DEF_XMM_OFFS(27),
DEF_XMM_OFFS(28),
DEF_XMM_OFFS(29),
DEF_XMM_OFFS(30),
DEF_XMM_OFFS(31),
fpu_state_end = fpu_state_off + ((FPUStateSizeInWords - 1)*wordSize / BytesPerInt),
zmm_off = fpu_state_off + ((FPUStateSizeInWords - (HALF_ZMM_BANK_WORDS + 1))*wordSize / BytesPerInt),
DEF_ZMM_OFFS(16),
DEF_ZMM_OFFS(17),
DEF_ZMM_OFFS(18),
DEF_ZMM_OFFS(19),
DEF_ZMM_OFFS(20),
DEF_ZMM_OFFS(21),
DEF_ZMM_OFFS(22),
DEF_ZMM_OFFS(23),
DEF_ZMM_OFFS(24),
DEF_ZMM_OFFS(25),
DEF_ZMM_OFFS(26),
DEF_ZMM_OFFS(27),
DEF_ZMM_OFFS(28),
DEF_ZMM_OFFS(29),
DEF_ZMM_OFFS(30),
DEF_ZMM_OFFS(31),
fpu_state_end = fpu_state_off + ((FPUStateSizeInWords-1)*wordSize / BytesPerInt),
fpu_stateH_end,
r15_off, r15H_off,
r14_off, r14H_off,
@ -155,9 +158,10 @@ class RegisterSaver {
OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words, bool save_vectors) {
int vect_words = 0;
int num_xmm_regs = 16;
if (UseAVX > 2) {
num_xmm_regs = 32;
int off = 0;
int num_xmm_regs = XMMRegisterImpl::number_of_registers;
if (UseAVX < 3) {
num_xmm_regs = num_xmm_regs/2;
}
#ifdef COMPILER2
if (save_vectors) {
@ -165,9 +169,7 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
assert(MaxVectorSize == 64, "only 512bit vectors are supported now");
// Save upper half of YMM registers
vect_words = 16 * num_xmm_regs / wordSize;
additional_frame_words += vect_words;
if (UseAVX > 2) {
// Save upper half of ZMM registers as well
if (UseAVX < 3) {
additional_frame_words += vect_words;
}
}
@ -195,77 +197,13 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
__ enter(); // rsp becomes 16-byte aligned here
__ push_CPU_state(); // Push a multiple of 16 bytes
if (vect_words > 0) {
// push cpu state handles this on EVEX enabled targets
if ((vect_words > 0) && (UseAVX < 3)) {
assert(vect_words*wordSize >= 256, "");
__ subptr(rsp, 256); // Save upper half of YMM registes(0..15)
__ vextractf128h(Address(rsp, 0), xmm0);
__ vextractf128h(Address(rsp, 16), xmm1);
__ vextractf128h(Address(rsp, 32), xmm2);
__ vextractf128h(Address(rsp, 48), xmm3);
__ vextractf128h(Address(rsp, 64), xmm4);
__ vextractf128h(Address(rsp, 80), xmm5);
__ vextractf128h(Address(rsp, 96), xmm6);
__ vextractf128h(Address(rsp, 112), xmm7);
__ vextractf128h(Address(rsp, 128), xmm8);
__ vextractf128h(Address(rsp, 144), xmm9);
__ vextractf128h(Address(rsp, 160), xmm10);
__ vextractf128h(Address(rsp, 176), xmm11);
__ vextractf128h(Address(rsp, 192), xmm12);
__ vextractf128h(Address(rsp, 208), xmm13);
__ vextractf128h(Address(rsp, 224), xmm14);
__ vextractf128h(Address(rsp, 240), xmm15);
if (UseAVX > 2) {
__ subptr(rsp, 256); // Save upper half of YMM registes(16..31)
__ vextractf128h(Address(rsp, 0), xmm16);
__ vextractf128h(Address(rsp, 16), xmm17);
__ vextractf128h(Address(rsp, 32), xmm18);
__ vextractf128h(Address(rsp, 48), xmm19);
__ vextractf128h(Address(rsp, 64), xmm20);
__ vextractf128h(Address(rsp, 80), xmm21);
__ vextractf128h(Address(rsp, 96), xmm22);
__ vextractf128h(Address(rsp, 112), xmm23);
__ vextractf128h(Address(rsp, 128), xmm24);
__ vextractf128h(Address(rsp, 144), xmm25);
__ vextractf128h(Address(rsp, 160), xmm26);
__ vextractf128h(Address(rsp, 176), xmm27);
__ vextractf128h(Address(rsp, 192), xmm28);
__ vextractf128h(Address(rsp, 208), xmm29);
__ vextractf128h(Address(rsp, 224), xmm30);
__ vextractf128h(Address(rsp, 240), xmm31);
// Now handle the ZMM registers (0..31)
__ subptr(rsp, 1024); // Save upper half of ZMM registes
__ vextractf64x4h(Address(rsp, 0), xmm0);
__ vextractf64x4h(Address(rsp, 32), xmm1);
__ vextractf64x4h(Address(rsp, 64), xmm2);
__ vextractf64x4h(Address(rsp, 96), xmm3);
__ vextractf64x4h(Address(rsp, 128), xmm4);
__ vextractf64x4h(Address(rsp, 160), xmm5);
__ vextractf64x4h(Address(rsp, 192), xmm6);
__ vextractf64x4h(Address(rsp, 224), xmm7);
__ vextractf64x4h(Address(rsp, 256), xmm8);
__ vextractf64x4h(Address(rsp, 288), xmm9);
__ vextractf64x4h(Address(rsp, 320), xmm10);
__ vextractf64x4h(Address(rsp, 352), xmm11);
__ vextractf64x4h(Address(rsp, 384), xmm12);
__ vextractf64x4h(Address(rsp, 416), xmm13);
__ vextractf64x4h(Address(rsp, 448), xmm14);
__ vextractf64x4h(Address(rsp, 480), xmm15);
__ vextractf64x4h(Address(rsp, 512), xmm16);
__ vextractf64x4h(Address(rsp, 544), xmm17);
__ vextractf64x4h(Address(rsp, 576), xmm18);
__ vextractf64x4h(Address(rsp, 608), xmm19);
__ vextractf64x4h(Address(rsp, 640), xmm20);
__ vextractf64x4h(Address(rsp, 672), xmm21);
__ vextractf64x4h(Address(rsp, 704), xmm22);
__ vextractf64x4h(Address(rsp, 736), xmm23);
__ vextractf64x4h(Address(rsp, 768), xmm24);
__ vextractf64x4h(Address(rsp, 800), xmm25);
__ vextractf64x4h(Address(rsp, 832), xmm26);
__ vextractf64x4h(Address(rsp, 864), xmm27);
__ vextractf64x4h(Address(rsp, 896), xmm28);
__ vextractf64x4h(Address(rsp, 928), xmm29);
__ vextractf64x4h(Address(rsp, 960), xmm30);
__ vextractf64x4h(Address(rsp, 992), xmm31);
// Save upper half of YMM registes(0..num_xmm_regs)
__ subptr(rsp, num_xmm_regs*16);
for (int n = 0; n < num_xmm_regs; n++) {
__ vextractf128h(Address(rsp, off++*16), as_XMMRegister(n));
}
}
if (frame::arg_reg_save_area_bytes != 0) {
@ -299,39 +237,24 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
map->set_callee_saved(STACK_OFFSET( r13_off ), r13->as_VMReg());
map->set_callee_saved(STACK_OFFSET( r14_off ), r14->as_VMReg());
map->set_callee_saved(STACK_OFFSET( r15_off ), r15->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm0_off ), xmm0->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm1_off ), xmm1->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm2_off ), xmm2->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm3_off ), xmm3->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm4_off ), xmm4->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm5_off ), xmm5->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm6_off ), xmm6->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm7_off ), xmm7->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm8_off ), xmm8->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm9_off ), xmm9->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm10_off), xmm10->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm11_off), xmm11->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm12_off), xmm12->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm13_off), xmm13->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm14_off), xmm14->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm15_off), xmm15->as_VMReg());
if (UseAVX > 2) {
map->set_callee_saved(STACK_OFFSET(xmm16_off), xmm16->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm17_off), xmm17->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm18_off), xmm18->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm19_off), xmm19->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm20_off), xmm20->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm21_off), xmm21->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm22_off), xmm22->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm23_off), xmm23->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm24_off), xmm24->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm25_off), xmm25->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm26_off), xmm26->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm27_off), xmm27->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm28_off), xmm28->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm29_off), xmm29->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm30_off), xmm30->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm31_off), xmm31->as_VMReg());
// For both AVX and EVEX we will use the legacy FXSAVE area for xmm0..xmm15,
// on EVEX enabled targets, we get it included in the xsave area
off = xmm0_off;
int delta = xmm1_off - off;
for (int n = 0; n < 16; n++) {
XMMRegister xmm_name = as_XMMRegister(n);
map->set_callee_saved(STACK_OFFSET(off), xmm_name->as_VMReg());
off += delta;
}
if(UseAVX > 2) {
// Obtain xmm16..xmm31 from the XSAVE area on EVEX enabled targets
off = zmm16_off;
delta = zmm17_off - off;
for (int n = 16; n < num_xmm_regs; n++) {
XMMRegister xmm_name = as_XMMRegister(n);
map->set_callee_saved(STACK_OFFSET(off), xmm_name->as_VMReg());
off += delta;
}
}
// %%% These should all be a waste but we'll keep things as they were for now
@ -351,39 +274,24 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
map->set_callee_saved(STACK_OFFSET( r13H_off ), r13->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET( r14H_off ), r14->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET( r15H_off ), r15->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET(xmm0H_off ), xmm0->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET(xmm1H_off ), xmm1->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET(xmm2H_off ), xmm2->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET(xmm3H_off ), xmm3->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET(xmm4H_off ), xmm4->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET(xmm5H_off ), xmm5->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET(xmm6H_off ), xmm6->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET(xmm7H_off ), xmm7->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET(xmm8H_off ), xmm8->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET(xmm9H_off ), xmm9->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET(xmm10H_off), xmm10->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET(xmm11H_off), xmm11->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET(xmm12H_off), xmm12->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET(xmm13H_off), xmm13->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET(xmm14H_off), xmm14->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET(xmm15H_off), xmm15->as_VMReg()->next());
// For both AVX and EVEX we will use the legacy FXSAVE area for xmm0..xmm15,
// on EVEX enabled targets, we get it included in the xsave area
off = xmm0H_off;
delta = xmm1H_off - off;
for (int n = 0; n < 16; n++) {
XMMRegister xmm_name = as_XMMRegister(n);
map->set_callee_saved(STACK_OFFSET(off), xmm_name->as_VMReg()->next());
off += delta;
}
if (UseAVX > 2) {
map->set_callee_saved(STACK_OFFSET(xmm16H_off), xmm16->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET(xmm17H_off), xmm17->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET(xmm18H_off), xmm18->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET(xmm19H_off), xmm19->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET(xmm20H_off), xmm20->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET(xmm21H_off), xmm21->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET(xmm22H_off), xmm22->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET(xmm23H_off), xmm23->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET(xmm24H_off), xmm24->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET(xmm25H_off), xmm25->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET(xmm26H_off), xmm26->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET(xmm27H_off), xmm27->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET(xmm28H_off), xmm28->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET(xmm29H_off), xmm29->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET(xmm30H_off), xmm30->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET(xmm31H_off), xmm31->as_VMReg()->next());
// Obtain xmm16..xmm31 from the XSAVE area on EVEX enabled targets
off = zmm16H_off;
delta = zmm17H_off - off;
for (int n = 16; n < num_xmm_regs; n++) {
XMMRegister xmm_name = as_XMMRegister(n);
map->set_callee_saved(STACK_OFFSET(off), xmm_name->as_VMReg()->next());
off += delta;
}
}
}
@ -391,86 +299,25 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
}
void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_vectors) {
int num_xmm_regs = XMMRegisterImpl::number_of_registers;
if (UseAVX < 3) {
num_xmm_regs = num_xmm_regs/2;
}
if (frame::arg_reg_save_area_bytes != 0) {
// Pop arg register save area
__ addptr(rsp, frame::arg_reg_save_area_bytes);
}
#ifdef COMPILER2
if (restore_vectors) {
// Restore upper half of YMM registes (0..15)
assert(UseAVX > 0, "512bit vectors are supported only with AVX");
assert(MaxVectorSize == 64, "only 512bit vectors are supported now");
__ vinsertf128h(xmm0, Address(rsp, 0));
__ vinsertf128h(xmm1, Address(rsp, 16));
__ vinsertf128h(xmm2, Address(rsp, 32));
__ vinsertf128h(xmm3, Address(rsp, 48));
__ vinsertf128h(xmm4, Address(rsp, 64));
__ vinsertf128h(xmm5, Address(rsp, 80));
__ vinsertf128h(xmm6, Address(rsp, 96));
__ vinsertf128h(xmm7, Address(rsp,112));
__ vinsertf128h(xmm8, Address(rsp,128));
__ vinsertf128h(xmm9, Address(rsp,144));
__ vinsertf128h(xmm10, Address(rsp,160));
__ vinsertf128h(xmm11, Address(rsp,176));
__ vinsertf128h(xmm12, Address(rsp,192));
__ vinsertf128h(xmm13, Address(rsp,208));
__ vinsertf128h(xmm14, Address(rsp,224));
__ vinsertf128h(xmm15, Address(rsp,240));
__ addptr(rsp, 256);
if (UseAVX > 2) {
// Restore upper half of YMM registes (16..31)
__ vinsertf128h(xmm16, Address(rsp, 0));
__ vinsertf128h(xmm17, Address(rsp, 16));
__ vinsertf128h(xmm18, Address(rsp, 32));
__ vinsertf128h(xmm19, Address(rsp, 48));
__ vinsertf128h(xmm20, Address(rsp, 64));
__ vinsertf128h(xmm21, Address(rsp, 80));
__ vinsertf128h(xmm22, Address(rsp, 96));
__ vinsertf128h(xmm23, Address(rsp,112));
__ vinsertf128h(xmm24, Address(rsp,128));
__ vinsertf128h(xmm25, Address(rsp,144));
__ vinsertf128h(xmm26, Address(rsp,160));
__ vinsertf128h(xmm27, Address(rsp,176));
__ vinsertf128h(xmm28, Address(rsp,192));
__ vinsertf128h(xmm29, Address(rsp,208));
__ vinsertf128h(xmm30, Address(rsp,224));
__ vinsertf128h(xmm31, Address(rsp,240));
__ addptr(rsp, 256);
// Restore upper half of ZMM registes.
__ vinsertf64x4h(xmm0, Address(rsp, 0));
__ vinsertf64x4h(xmm1, Address(rsp, 32));
__ vinsertf64x4h(xmm2, Address(rsp, 64));
__ vinsertf64x4h(xmm3, Address(rsp, 96));
__ vinsertf64x4h(xmm4, Address(rsp, 128));
__ vinsertf64x4h(xmm5, Address(rsp, 160));
__ vinsertf64x4h(xmm6, Address(rsp, 192));
__ vinsertf64x4h(xmm7, Address(rsp, 224));
__ vinsertf64x4h(xmm8, Address(rsp, 256));
__ vinsertf64x4h(xmm9, Address(rsp, 288));
__ vinsertf64x4h(xmm10, Address(rsp, 320));
__ vinsertf64x4h(xmm11, Address(rsp, 352));
__ vinsertf64x4h(xmm12, Address(rsp, 384));
__ vinsertf64x4h(xmm13, Address(rsp, 416));
__ vinsertf64x4h(xmm14, Address(rsp, 448));
__ vinsertf64x4h(xmm15, Address(rsp, 480));
__ vinsertf64x4h(xmm16, Address(rsp, 512));
__ vinsertf64x4h(xmm17, Address(rsp, 544));
__ vinsertf64x4h(xmm18, Address(rsp, 576));
__ vinsertf64x4h(xmm19, Address(rsp, 608));
__ vinsertf64x4h(xmm20, Address(rsp, 640));
__ vinsertf64x4h(xmm21, Address(rsp, 672));
__ vinsertf64x4h(xmm22, Address(rsp, 704));
__ vinsertf64x4h(xmm23, Address(rsp, 736));
__ vinsertf64x4h(xmm24, Address(rsp, 768));
__ vinsertf64x4h(xmm25, Address(rsp, 800));
__ vinsertf64x4h(xmm26, Address(rsp, 832));
__ vinsertf64x4h(xmm27, Address(rsp, 864));
__ vinsertf64x4h(xmm28, Address(rsp, 896));
__ vinsertf64x4h(xmm29, Address(rsp, 928));
__ vinsertf64x4h(xmm30, Address(rsp, 960));
__ vinsertf64x4h(xmm31, Address(rsp, 992));
__ addptr(rsp, 1024);
// On EVEX enabled targets everything is handled in pop fpu state
if ((restore_vectors) && (UseAVX < 3)) {
assert(UseAVX > 0, "256/512-bit vectors are supported only with AVX");
assert(MaxVectorSize == 64, "up to 512bit vectors are supported now");
int off = 0;
// Restore upper half of YMM registes (0..num_xmm_regs)
for (int n = 0; n < num_xmm_regs; n++) {
__ vinsertf128h(as_XMMRegister(n), Address(rsp, off++*16));
}
__ addptr(rsp, num_xmm_regs*16);
}
#else
assert(!restore_vectors, "vectors are generated only by C2");

View File

@ -795,6 +795,12 @@ class StubGenerator: public StubCodeGenerator {
void xmm_copy_forward(Register from, Register to_from, Register qword_count) {
assert( UseSSE >= 2, "supported cpu only" );
Label L_copy_64_bytes_loop, L_copy_64_bytes, L_copy_8_bytes, L_exit;
if (UseAVX > 2) {
__ push(rbx);
__ movl(rbx, 0xffff);
__ kmovdl(k1, rbx);
__ pop(rbx);
}
// Copy 64-byte chunks
__ jmpb(L_copy_64_bytes);
__ align(OptoLoopAlignment);
@ -802,8 +808,8 @@ class StubGenerator: public StubCodeGenerator {
if (UseUnalignedLoadStores) {
if (UseAVX > 2) {
__ evmovdqu(xmm0, Address(from, 0), Assembler::AVX_512bit);
__ evmovdqu(Address(from, to_from, Address::times_1, 0), xmm0, Assembler::AVX_512bit);
__ evmovdqul(xmm0, Address(from, 0), Assembler::AVX_512bit);
__ evmovdqul(Address(from, to_from, Address::times_1, 0), xmm0, Assembler::AVX_512bit);
} else if (UseAVX == 2) {
__ vmovdqu(xmm0, Address(from, 0));
__ vmovdqu(Address(from, to_from, Address::times_1, 0), xmm0);
@ -2217,6 +2223,15 @@ class StubGenerator: public StubCodeGenerator {
const XMMRegister xmm_temp4 = xmm5;
__ enter(); // required for proper stackwalking of RuntimeStub frame
// For EVEX with VL and BW, provide a standard mask, VL = 128 will guide the merge
// context for the registers used, where all instructions below are using 128-bit mode
// On EVEX without VL and BW, these instructions will all be AVX.
if (VM_Version::supports_avx512vlbw()) {
__ movl(rdx, 0xffff);
__ kmovdl(k1, rdx);
}
__ movptr(from, from_param);
__ movptr(key, key_param);
@ -2315,6 +2330,15 @@ class StubGenerator: public StubCodeGenerator {
const XMMRegister xmm_temp4 = xmm5;
__ enter(); // required for proper stackwalking of RuntimeStub frame
// For EVEX with VL and BW, provide a standard mask, VL = 128 will guide the merge
// context for the registers used, where all instructions below are using 128-bit mode
// On EVEX without VL and BW, these instructions will all be AVX.
if (VM_Version::supports_avx512vlbw()) {
__ movl(rdx, 0xffff);
__ kmovdl(k1, rdx);
}
__ movptr(from, from_param);
__ movptr(key, key_param);
@ -2441,6 +2465,14 @@ class StubGenerator: public StubCodeGenerator {
__ enter(); // required for proper stackwalking of RuntimeStub frame
handleSOERegisters(true /*saving*/);
// For EVEX with VL and BW, provide a standard mask, VL = 128 will guide the merge
// context for the registers used, where all instructions below are using 128-bit mode
// On EVEX without VL and BW, these instructions will all be AVX.
if (VM_Version::supports_avx512vlbw()) {
__ movl(rdx, 0xffff);
__ kmovdl(k1, rdx);
}
// load registers from incoming parameters
const Address from_param(rbp, 8+0);
const Address to_param (rbp, 8+4);
@ -2602,6 +2634,14 @@ class StubGenerator: public StubCodeGenerator {
__ enter(); // required for proper stackwalking of RuntimeStub frame
handleSOERegisters(true /*saving*/);
// For EVEX with VL and BW, provide a standard mask, VL = 128 will guide the merge
// context for the registers used, where all instructions below are using 128-bit mode
// On EVEX without VL and BW, these instructions will all be AVX.
if (VM_Version::supports_avx512vlbw()) {
__ movl(rdx, 0xffff);
__ kmovdl(k1, rdx);
}
// load registers from incoming parameters
const Address from_param(rbp, 8+0);
const Address to_param (rbp, 8+4);
@ -2782,6 +2822,14 @@ class StubGenerator: public StubCodeGenerator {
__ enter();
handleSOERegisters(true); // Save registers
// For EVEX with VL and BW, provide a standard mask, VL = 128 will guide the merge
// context for the registers used, where all instructions below are using 128-bit mode
// On EVEX without VL and BW, these instructions will all be AVX.
if (VM_Version::supports_avx512vlbw()) {
__ movl(rdx, 0xffff);
__ kmovdl(k1, rdx);
}
__ movptr(state, state_param);
__ movptr(subkeyH, subkeyH_param);
__ movptr(data, data_param);

View File

@ -269,12 +269,16 @@ class StubGenerator: public StubCodeGenerator {
__ kmovql(k1, rbx);
}
#ifdef _WIN64
int last_reg = 15;
if (UseAVX > 2) {
for (int i = 6; i <= 31; i++) {
__ movdqu(xmm_save(i), as_XMMRegister(i));
last_reg = 31;
}
if (VM_Version::supports_avx512novl()) {
for (int i = xmm_save_first; i <= last_reg; i++) {
__ vextractf32x4h(xmm_save(i), as_XMMRegister(i), 0);
}
} else {
for (int i = 6; i <= 15; i++) {
for (int i = xmm_save_first; i <= last_reg; i++) {
__ movdqu(xmm_save(i), as_XMMRegister(i));
}
}
@ -386,13 +390,15 @@ class StubGenerator: public StubCodeGenerator {
// restore regs belonging to calling function
#ifdef _WIN64
int xmm_ub = 15;
if (UseAVX > 2) {
xmm_ub = 31;
}
// emit the restores for xmm regs
for (int i = 6; i <= xmm_ub; i++) {
__ movdqu(as_XMMRegister(i), xmm_save(i));
if (VM_Version::supports_avx512novl()) {
for (int i = xmm_save_first; i <= last_reg; i++) {
__ vinsertf32x4h(as_XMMRegister(i), xmm_save(i), 0);
}
} else {
for (int i = xmm_save_first; i <= last_reg; i++) {
__ movdqu(as_XMMRegister(i), xmm_save(i));
}
}
#endif
__ movptr(r15, r15_save);
@ -1342,11 +1348,15 @@ class StubGenerator: public StubCodeGenerator {
__ align(OptoLoopAlignment);
if (UseUnalignedLoadStores) {
Label L_end;
if (UseAVX > 2) {
__ movl(to, 0xffff);
__ kmovql(k1, to);
}
// Copy 64-bytes per iteration
__ BIND(L_loop);
if (UseAVX > 2) {
__ evmovdqu(xmm0, Address(end_from, qword_count, Address::times_8, -56), Assembler::AVX_512bit);
__ evmovdqu(Address(end_to, qword_count, Address::times_8, -56), xmm0, Assembler::AVX_512bit);
__ evmovdqul(xmm0, Address(end_from, qword_count, Address::times_8, -56), Assembler::AVX_512bit);
__ evmovdqul(Address(end_to, qword_count, Address::times_8, -56), xmm0, Assembler::AVX_512bit);
} else if (UseAVX == 2) {
__ vmovdqu(xmm0, Address(end_from, qword_count, Address::times_8, -56));
__ vmovdqu(Address(end_to, qword_count, Address::times_8, -56), xmm0);
@ -1422,11 +1432,15 @@ class StubGenerator: public StubCodeGenerator {
__ align(OptoLoopAlignment);
if (UseUnalignedLoadStores) {
Label L_end;
if (UseAVX > 2) {
__ movl(to, 0xffff);
__ kmovql(k1, to);
}
// Copy 64-bytes per iteration
__ BIND(L_loop);
if (UseAVX > 2) {
__ evmovdqu(xmm0, Address(from, qword_count, Address::times_8, 32), Assembler::AVX_512bit);
__ evmovdqu(Address(dest, qword_count, Address::times_8, 32), xmm0, Assembler::AVX_512bit);
__ evmovdqul(xmm0, Address(from, qword_count, Address::times_8, 32), Assembler::AVX_512bit);
__ evmovdqul(Address(dest, qword_count, Address::times_8, 32), xmm0, Assembler::AVX_512bit);
} else if (UseAVX == 2) {
__ vmovdqu(xmm0, Address(from, qword_count, Address::times_8, 32));
__ vmovdqu(Address(dest, qword_count, Address::times_8, 32), xmm0);
@ -3106,6 +3120,14 @@ class StubGenerator: public StubCodeGenerator {
__ enter(); // required for proper stackwalking of RuntimeStub frame
// For EVEX with VL and BW, provide a standard mask, VL = 128 will guide the merge
// context for the registers used, where all instructions below are using 128-bit mode
// On EVEX without VL and BW, these instructions will all be AVX.
if (VM_Version::supports_avx512vlbw()) {
__ movl(rax, 0xffff);
__ kmovql(k1, rax);
}
// 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)));
@ -3200,6 +3222,14 @@ class StubGenerator: public StubCodeGenerator {
__ enter(); // required for proper stackwalking of RuntimeStub frame
// For EVEX with VL and BW, provide a standard mask, VL = 128 will guide the merge
// context for the registers used, where all instructions below are using 128-bit mode
// On EVEX without VL and BW, these instructions will all be AVX.
if (VM_Version::supports_avx512vlbw()) {
__ movl(rax, 0xffff);
__ kmovql(k1, rax);
}
// 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)));
@ -3312,6 +3342,14 @@ class StubGenerator: public StubCodeGenerator {
__ enter(); // required for proper stackwalking of RuntimeStub frame
// For EVEX with VL and BW, provide a standard mask, VL = 128 will guide the merge
// context for the registers used, where all instructions below are using 128-bit mode
// On EVEX without VL and BW, these instructions will all be AVX.
if (VM_Version::supports_avx512vlbw()) {
__ movl(rax, 0xffff);
__ kmovql(k1, rax);
}
#ifdef _WIN64
// on win64, fill len_reg from stack position
__ movl(len_reg, len_mem);
@ -3508,6 +3546,14 @@ class StubGenerator: public StubCodeGenerator {
__ enter(); // required for proper stackwalking of RuntimeStub frame
// For EVEX with VL and BW, provide a standard mask, VL = 128 will guide the merge
// context for the registers used, where all instructions below are using 128-bit mode
// On EVEX without VL and BW, these instructions will all be AVX.
if (VM_Version::supports_avx512vlbw()) {
__ movl(rax, 0xffff);
__ kmovql(k1, rax);
}
#ifdef _WIN64
// on win64, fill len_reg from stack position
__ movl(len_reg, len_mem);
@ -3746,6 +3792,14 @@ class StubGenerator: public StubCodeGenerator {
__ enter();
// For EVEX with VL and BW, provide a standard mask, VL = 128 will guide the merge
// context for the registers used, where all instructions below are using 128-bit mode
// On EVEX without VL and BW, these instructions will all be AVX.
if (VM_Version::supports_avx512vlbw()) {
__ movl(rax, 0xffff);
__ kmovql(k1, rax);
}
#ifdef _WIN64
// save the xmm registers which must be preserved 6-10
__ subptr(rsp, -rsp_after_call_off * wordSize);

View File

@ -31,7 +31,7 @@
enum platform_dependent_constants {
code_size1 = 9000, // simply increase if too small (assembler will crash if too small)
code_size2 = 22000 // simply increase if too small (assembler will crash if too small)
code_size2 = 30000 // simply increase if too small (assembler will crash if too small)
};
class x86 {

View File

@ -33,7 +33,7 @@ static bool returns_to_call_stub(address return_pc) { return return_pc == _
enum platform_dependent_constants {
code_size1 = 19000, // simply increase if too small (assembler will crash if too small)
code_size2 = 24000 // simply increase if too small (assembler will crash if too small)
code_size2 = 32000 // simply increase if too small (assembler will crash if too small)
};
class x86 {

View File

@ -367,16 +367,12 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
__ movl(rcx, VM_Version::ymm_test_value());
__ movdl(xmm0, rcx);
__ movl(rcx, 0xffff);
#ifdef _LP64
__ kmovql(k1, rcx);
#else
__ kmovdl(k1, rcx);
#endif
__ kmovwl(k1, rcx);
__ evpbroadcastd(xmm0, xmm0, Assembler::AVX_512bit);
__ evmovdqu(xmm7, xmm0, Assembler::AVX_512bit);
__ evmovdqul(xmm7, xmm0, Assembler::AVX_512bit);
#ifdef _LP64
__ evmovdqu(xmm8, xmm0, Assembler::AVX_512bit);
__ evmovdqu(xmm31, xmm0, Assembler::AVX_512bit);
__ evmovdqul(xmm8, xmm0, Assembler::AVX_512bit);
__ evmovdqul(xmm31, xmm0, Assembler::AVX_512bit);
#endif
VM_Version::clean_cpuFeatures();
__ jmp(save_restore_except);
@ -427,11 +423,11 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
UseAVX = 3;
UseSSE = 2;
__ lea(rsi, Address(rbp, in_bytes(VM_Version::zmm_save_offset())));
__ evmovdqu(Address(rsi, 0), xmm0, Assembler::AVX_512bit);
__ evmovdqu(Address(rsi, 64), xmm7, Assembler::AVX_512bit);
__ evmovdqul(Address(rsi, 0), xmm0, Assembler::AVX_512bit);
__ evmovdqul(Address(rsi, 64), xmm7, Assembler::AVX_512bit);
#ifdef _LP64
__ evmovdqu(Address(rsi, 128), xmm8, Assembler::AVX_512bit);
__ evmovdqu(Address(rsi, 192), xmm31, Assembler::AVX_512bit);
__ evmovdqul(Address(rsi, 128), xmm8, Assembler::AVX_512bit);
__ evmovdqul(Address(rsi, 192), xmm31, Assembler::AVX_512bit);
#endif
VM_Version::clean_cpuFeatures();
UseAVX = saved_useavx;

View File

@ -227,14 +227,15 @@ public:
union XemXcr0Eax {
uint32_t value;
struct {
uint32_t x87 : 1,
sse : 1,
ymm : 1,
: 2,
opmask : 1,
zmm512 : 1,
zmm32 : 1,
: 24;
uint32_t x87 : 1,
sse : 1,
ymm : 1,
bndregs : 1,
bndcsr : 1,
opmask : 1,
zmm512 : 1,
zmm32 : 1,
: 24;
} bits;
};
@ -703,6 +704,7 @@ public:
static bool supports_avx512bw() { return (_cpuFeatures & CPU_AVX512BW) != 0; }
static bool supports_avx512vl() { return (_cpuFeatures & CPU_AVX512VL) != 0; }
static bool supports_avx512vlbw() { return (supports_avx512bw() && supports_avx512vl()); }
static bool supports_avx512novl() { return (supports_evex() && !supports_avx512vl()); }
// Intel features
static bool is_intel_family_core() { return is_intel() &&
extended_cpu_family() == CPU_FAMILY_INTEL_CORE; }
@ -817,6 +819,12 @@ public:
intx count = PrefetchFieldsAhead;
return count >= 0 ? count : 1;
}
static uint32_t get_xsave_header_lower_segment() {
return _cpuid_info.xem_xcr0_eax.value;
}
static uint32_t get_xsave_header_upper_segment() {
return _cpuid_info.xem_xcr0_edx;
}
};
#endif // CPU_X86_VM_VM_VERSION_X86_HPP

View File

@ -1661,46 +1661,55 @@ const bool Matcher::match_rule_supported(int opcode) {
if (!has_match_rule(opcode))
return false;
bool ret_value = true;
switch (opcode) {
case Op_PopCountI:
case Op_PopCountL:
if (!UsePopCountInstruction)
return false;
break;
ret_value = false;
break;
case Op_MulVI:
if ((UseSSE < 4) && (UseAVX < 1)) // only with SSE4_1 or AVX
return false;
break;
ret_value = false;
break;
case Op_MulVL:
case Op_MulReductionVL:
if (VM_Version::supports_avx512dq() == false)
return false;
ret_value = false;
break;
case Op_AddReductionVL:
if (UseAVX < 3) // only EVEX : vector connectivity becomes an issue here
return false;
ret_value = false;
break;
case Op_AddReductionVI:
if (UseSSE < 3) // requires at least SSE3
return false;
ret_value = false;
break;
case Op_MulReductionVI:
if (UseSSE < 4) // requires at least SSE4
return false;
ret_value = false;
break;
case Op_AddReductionVF:
case Op_AddReductionVD:
case Op_MulReductionVF:
case Op_MulReductionVD:
if (UseSSE < 1) // requires at least SSE
return false;
break;
ret_value = false;
break;
case Op_SqrtVD:
if (UseAVX < 1) // enabled for AVX only
ret_value = false;
break;
case Op_CompareAndSwapL:
#ifdef _LP64
case Op_CompareAndSwapP:
#endif
if (!VM_Version::supports_cx8())
return false;
break;
ret_value = false;
break;
}
return true; // Per default match rules are supported.
return ret_value; // Per default match rules are supported.
}
// Max vector size in bytes. 0 if not supported.
@ -1721,14 +1730,24 @@ const int Matcher::vector_width_in_bytes(BasicType bt) {
case T_DOUBLE:
case T_LONG:
if (size < 16) return 0;
break;
case T_FLOAT:
case T_INT:
if (size < 8) return 0;
break;
case T_BOOLEAN:
case T_BYTE:
if (size < 4) return 0;
break;
case T_CHAR:
if (size < 4) return 0;
break;
case T_BYTE:
if (size < 4) return 0;
if ((size > 32) && !VM_Version::supports_avx512bw()) return 0;
break;
case T_SHORT:
if (size < 4) return 0;
if ((size > 16) && !VM_Version::supports_avx512bw()) return 0;
break;
default:
ShouldNotReachHere();
@ -1800,7 +1819,7 @@ static int vec_mov_helper(CodeBuffer *cbuf, bool do_size, int src_lo, int dst_lo
__ vmovdqu(as_XMMRegister(Matcher::_regEncode[dst_lo]), as_XMMRegister(Matcher::_regEncode[src_lo]));
break;
case Op_VecZ:
__ evmovdqu(as_XMMRegister(Matcher::_regEncode[dst_lo]), as_XMMRegister(Matcher::_regEncode[src_lo]), 2);
__ evmovdqul(as_XMMRegister(Matcher::_regEncode[dst_lo]), as_XMMRegister(Matcher::_regEncode[src_lo]), 2);
break;
default:
ShouldNotReachHere();
@ -1855,7 +1874,7 @@ static int vec_spill_helper(CodeBuffer *cbuf, bool do_size, bool is_load,
__ vmovdqu(as_XMMRegister(Matcher::_regEncode[reg]), Address(rsp, stack_offset));
break;
case Op_VecZ:
__ evmovdqu(as_XMMRegister(Matcher::_regEncode[reg]), Address(rsp, stack_offset), 2);
__ evmovdqul(as_XMMRegister(Matcher::_regEncode[reg]), Address(rsp, stack_offset), 2);
break;
default:
ShouldNotReachHere();
@ -1875,7 +1894,7 @@ static int vec_spill_helper(CodeBuffer *cbuf, bool do_size, bool is_load,
__ vmovdqu(Address(rsp, stack_offset), as_XMMRegister(Matcher::_regEncode[reg]));
break;
case Op_VecZ:
__ evmovdqu(Address(rsp, stack_offset), as_XMMRegister(Matcher::_regEncode[reg]), 2);
__ evmovdqul(Address(rsp, stack_offset), as_XMMRegister(Matcher::_regEncode[reg]), 2);
break;
default:
ShouldNotReachHere();
@ -1929,9 +1948,40 @@ static int vec_spill_helper(CodeBuffer *cbuf, bool do_size, bool is_load,
}
#endif
}
int offset_size = (stack_offset == 0) ? 0 : ((stack_offset < 0x80) ? 1 : (UseAVX > 2) ? 6 : 4);
bool is_single_byte = false;
int vec_len = 0;
if ((UseAVX > 2) && (stack_offset != 0)) {
switch (ireg) {
case Op_VecS:
case Op_VecD:
case Op_VecX:
break;
case Op_VecY:
vec_len = 1;
break;
case Op_VecZ:
vec_len = 2;
break;
}
is_single_byte = Assembler::query_compressed_disp_byte(stack_offset, true, vec_len, Assembler::EVEX_FVM, Assembler::EVEX_32bit, 0);
}
int offset_size = 0;
int size = 5;
if (UseAVX > 2 ) {
if ((VM_Version::supports_avx512vl() == false) && (vec_len == 2)) {
offset_size = (stack_offset == 0) ? 0 : ((is_single_byte) ? 1 : 4);
size += 2; // Need an additional two bytes for EVEX encoding
} else if ((VM_Version::supports_avx512vl() == false) && (vec_len < 2)) {
offset_size = (stack_offset == 0) ? 0 : ((stack_offset <= 127) ? 1 : 4);
} else {
offset_size = (stack_offset == 0) ? 0 : ((is_single_byte) ? 1 : 4);
size += 2; // Need an additional two bytes for EVEX encodding
}
} else {
offset_size = (stack_offset == 0) ? 0 : ((stack_offset <= 127) ? 1 : 4);
}
// VEX_2bytes prefix is used if UseAVX > 0, so it takes the same 2 bytes as SIMD prefix.
return 5+offset_size;
return size+offset_size;
}
static inline jfloat replicate4_imm(int con, int width) {
@ -2675,11 +2725,10 @@ instruct negF_reg_reg(regF dst, regF src) %{
predicate(UseAVX > 0);
match(Set dst (NegF src));
ins_cost(150);
format %{ "vxorps $dst, $src, [0x80000000]\t# neg float by sign flipping" %}
format %{ "vnegatess $dst, $src, [0x80000000]\t# neg float by sign flipping" %}
ins_encode %{
int vector_len = 0;
__ vxorps($dst$$XMMRegister, $src$$XMMRegister,
ExternalAddress(float_signflip()), vector_len);
__ vnegatess($dst$$XMMRegister, $src$$XMMRegister,
ExternalAddress(float_signflip()));
%}
ins_pipe(pipe_slow);
%}
@ -2700,12 +2749,11 @@ instruct negD_reg_reg(regD dst, regD src) %{
predicate(UseAVX > 0);
match(Set dst (NegD src));
ins_cost(150);
format %{ "vxorpd $dst, $src, [0x8000000000000000]\t"
format %{ "vnegatess $dst, $src, [0x8000000000000000]\t"
"# neg double by sign flipping" %}
ins_encode %{
int vector_len = 0;
__ vxorpd($dst$$XMMRegister, $src$$XMMRegister,
ExternalAddress(double_signflip()), vector_len);
__ vnegatesd($dst$$XMMRegister, $src$$XMMRegister,
ExternalAddress(double_signflip()));
%}
ins_pipe(pipe_slow);
%}
@ -2838,7 +2886,7 @@ instruct loadV64(vecZ dst, memory mem) %{
format %{ "vmovdqu $dst k0,$mem\t! load vector (64 bytes)" %}
ins_encode %{
int vector_len = 2;
__ evmovdqu($dst$$XMMRegister, $mem$$Address, vector_len);
__ evmovdqul($dst$$XMMRegister, $mem$$Address, vector_len);
%}
ins_pipe( pipe_slow );
%}
@ -2895,7 +2943,7 @@ instruct storeV64(memory mem, vecZ src) %{
format %{ "vmovdqu $mem k0,$src\t! store vector (64 bytes)" %}
ins_encode %{
int vector_len = 2;
__ evmovdqu($mem$$Address, $src$$XMMRegister, vector_len);
__ evmovdqul($mem$$Address, $src$$XMMRegister, vector_len);
%}
ins_pipe( pipe_slow );
%}
@ -3315,6 +3363,37 @@ instruct Repl8F_mem(vecY dst, memory mem) %{
ins_pipe( pipe_slow );
%}
instruct Repl2F_zero(vecD dst, immF0 zero) %{
predicate(n->as_Vector()->length() == 2 && UseAVX < 3);
match(Set dst (ReplicateF zero));
format %{ "xorps $dst,$dst\t! replicate2F zero" %}
ins_encode %{
__ xorps($dst$$XMMRegister, $dst$$XMMRegister);
%}
ins_pipe( fpu_reg_reg );
%}
instruct Repl4F_zero(vecX dst, immF0 zero) %{
predicate(n->as_Vector()->length() == 4 && UseAVX < 3);
match(Set dst (ReplicateF zero));
format %{ "xorps $dst,$dst\t! replicate4F zero" %}
ins_encode %{
__ xorps($dst$$XMMRegister, $dst$$XMMRegister);
%}
ins_pipe( fpu_reg_reg );
%}
instruct Repl8F_zero(vecY dst, immF0 zero) %{
predicate(n->as_Vector()->length() == 8 && UseAVX < 3);
match(Set dst (ReplicateF zero));
format %{ "vxorps $dst,$dst,$dst\t! replicate8F zero" %}
ins_encode %{
int vector_len = 1;
__ vxorps($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, vector_len);
%}
ins_pipe( fpu_reg_reg );
%}
instruct Repl2D_mem(vecX dst, memory mem) %{
predicate(n->as_Vector()->length() == 2 && UseAVX > 0 && !VM_Version::supports_avx512vl());
match(Set dst (ReplicateD (LoadD mem)));
@ -3349,6 +3428,28 @@ instruct Repl4D_mem(vecY dst, memory mem) %{
ins_pipe( pipe_slow );
%}
// Replicate double (8 byte) scalar zero to be vector
instruct Repl2D_zero(vecX dst, immD0 zero) %{
predicate(n->as_Vector()->length() == 2 && UseAVX < 3);
match(Set dst (ReplicateD zero));
format %{ "xorpd $dst,$dst\t! replicate2D zero" %}
ins_encode %{
__ xorpd($dst$$XMMRegister, $dst$$XMMRegister);
%}
ins_pipe( fpu_reg_reg );
%}
instruct Repl4D_zero(vecY dst, immD0 zero) %{
predicate(n->as_Vector()->length() == 4 && UseAVX < 3);
match(Set dst (ReplicateD zero));
format %{ "vxorpd $dst,$dst,$dst,vect256\t! replicate4D zero" %}
ins_encode %{
int vector_len = 1;
__ vxorpd($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, vector_len);
%}
ins_pipe( fpu_reg_reg );
%}
// ====================GENERIC REPLICATE==========================================
// Replicate byte scalar to be vector
@ -3680,38 +3781,6 @@ instruct Repl4F(vecX dst, regF src) %{
ins_pipe( pipe_slow );
%}
// Replicate float (4 byte) scalar zero to be vector
instruct Repl2F_zero(vecD dst, immF0 zero) %{
predicate(n->as_Vector()->length() == 2);
match(Set dst (ReplicateF zero));
format %{ "xorps $dst,$dst\t! replicate2F zero" %}
ins_encode %{
__ xorps($dst$$XMMRegister, $dst$$XMMRegister);
%}
ins_pipe( fpu_reg_reg );
%}
instruct Repl4F_zero(vecX dst, immF0 zero) %{
predicate(n->as_Vector()->length() == 4);
match(Set dst (ReplicateF zero));
format %{ "xorps $dst,$dst\t! replicate4F zero" %}
ins_encode %{
__ xorps($dst$$XMMRegister, $dst$$XMMRegister);
%}
ins_pipe( fpu_reg_reg );
%}
instruct Repl8F_zero(vecY dst, immF0 zero) %{
predicate(n->as_Vector()->length() == 8);
match(Set dst (ReplicateF zero));
format %{ "vxorps $dst,$dst,$dst\t! replicate8F zero" %}
ins_encode %{
int vector_len = 1;
__ vxorps($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, vector_len);
%}
ins_pipe( fpu_reg_reg );
%}
// Replicate double (8 bytes) scalar to be vector
instruct Repl2D(vecX dst, regD src) %{
predicate(n->as_Vector()->length() == 2);
@ -3723,28 +3792,6 @@ instruct Repl2D(vecX dst, regD src) %{
ins_pipe( pipe_slow );
%}
// Replicate double (8 byte) scalar zero to be vector
instruct Repl2D_zero(vecX dst, immD0 zero) %{
predicate(n->as_Vector()->length() == 2);
match(Set dst (ReplicateD zero));
format %{ "xorpd $dst,$dst\t! replicate2D zero" %}
ins_encode %{
__ xorpd($dst$$XMMRegister, $dst$$XMMRegister);
%}
ins_pipe( fpu_reg_reg );
%}
instruct Repl4D_zero(vecY dst, immD0 zero) %{
predicate(n->as_Vector()->length() == 4);
match(Set dst (ReplicateD zero));
format %{ "vxorpd $dst,$dst,$dst,vect256\t! replicate4D zero" %}
ins_encode %{
int vector_len = 1;
__ vxorpd($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, vector_len);
%}
ins_pipe( fpu_reg_reg );
%}
// ====================EVEX REPLICATE=============================================
instruct Repl4B_mem_evex(vecS dst, memory mem) %{
@ -3814,7 +3861,7 @@ instruct Repl32B_mem_evex(vecY dst, memory mem) %{
%}
instruct Repl64B_evex(vecZ dst, rRegI src) %{
predicate(n->as_Vector()->length() == 64 && UseAVX > 2);
predicate(n->as_Vector()->length() == 64 && VM_Version::supports_avx512bw());
match(Set dst (ReplicateB src));
format %{ "vpbroadcastb $dst,$src\t! upper replicate64B" %}
ins_encode %{
@ -3825,7 +3872,7 @@ instruct Repl64B_evex(vecZ dst, rRegI src) %{
%}
instruct Repl64B_mem_evex(vecZ dst, memory mem) %{
predicate(n->as_Vector()->length() == 64 && VM_Version::supports_avx512vlbw());
predicate(n->as_Vector()->length() == 64 && VM_Version::supports_avx512bw());
match(Set dst (ReplicateB (LoadB mem)));
format %{ "vpbroadcastb $dst,$mem\t! replicate64B" %}
ins_encode %{
@ -3862,7 +3909,7 @@ instruct Repl32B_imm_evex(vecY dst, immI con) %{
%}
instruct Repl64B_imm_evex(vecZ dst, immI con) %{
predicate(n->as_Vector()->length() == 64 && UseAVX > 2);
predicate(n->as_Vector()->length() == 64 && VM_Version::supports_avx512bw());
match(Set dst (ReplicateB con));
format %{ "movq $dst,[$constantaddress]\n\t"
"vpbroadcastb $dst,$dst\t! upper replicate64B" %}
@ -3953,7 +4000,7 @@ instruct Repl16S_mem_evex(vecY dst, memory mem) %{
%}
instruct Repl32S_evex(vecZ dst, rRegI src) %{
predicate(n->as_Vector()->length() == 32 && UseAVX > 2);
predicate(n->as_Vector()->length() == 32 && VM_Version::supports_avx512bw());
match(Set dst (ReplicateS src));
format %{ "vpbroadcastw $dst,$src\t! replicate32S" %}
ins_encode %{
@ -3964,7 +4011,7 @@ instruct Repl32S_evex(vecZ dst, rRegI src) %{
%}
instruct Repl32S_mem_evex(vecZ dst, memory mem) %{
predicate(n->as_Vector()->length() == 32 && UseAVX > 2);
predicate(n->as_Vector()->length() == 32 && VM_Version::supports_avx512bw());
match(Set dst (ReplicateS (LoadS mem)));
format %{ "vpbroadcastw $dst,$mem\t! replicate32S" %}
ins_encode %{
@ -4001,7 +4048,7 @@ instruct Repl16S_imm_evex(vecY dst, immI con) %{
%}
instruct Repl32S_imm_evex(vecZ dst, immI con) %{
predicate(n->as_Vector()->length() == 32 && UseAVX > 2);
predicate(n->as_Vector()->length() == 32 && VM_Version::supports_avx512bw());
match(Set dst (ReplicateS con));
format %{ "movq $dst,[$constantaddress]\n\t"
"vpbroadcastw $dst,$dst\t! replicate32S" %}
@ -4318,13 +4365,50 @@ instruct Repl16F_mem_evex(vecZ dst, memory mem) %{
ins_pipe( pipe_slow );
%}
instruct Repl2F_zero_evex(vecD dst, immF0 zero) %{
predicate(n->as_Vector()->length() == 2 && UseAVX > 2);
match(Set dst (ReplicateF zero));
format %{ "vpxor $dst k0,$dst,$dst\t! replicate2F zero" %}
ins_encode %{
// Use vpxor in place of vxorps since EVEX has a constriant on dq for vxorps: this is a 512-bit operation
int vector_len = 2;
__ vpxor($dst$$XMMRegister,$dst$$XMMRegister, $dst$$XMMRegister, vector_len);
%}
ins_pipe( fpu_reg_reg );
%}
instruct Repl4F_zero_evex(vecX dst, immF0 zero) %{
predicate(n->as_Vector()->length() == 4 && UseAVX > 2);
match(Set dst (ReplicateF zero));
format %{ "vpxor $dst k0,$dst,$dst\t! replicate4F zero" %}
ins_encode %{
// Use vpxor in place of vxorps since EVEX has a constriant on dq for vxorps: this is a 512-bit operation
int vector_len = 2;
__ vpxor($dst$$XMMRegister,$dst$$XMMRegister, $dst$$XMMRegister, vector_len);
%}
ins_pipe( fpu_reg_reg );
%}
instruct Repl8F_zero_evex(vecY dst, immF0 zero) %{
predicate(n->as_Vector()->length() == 8 && UseAVX > 2);
match(Set dst (ReplicateF zero));
format %{ "vpxor $dst k0,$dst,$dst\t! replicate8F zero" %}
ins_encode %{
// Use vpxor in place of vxorps since EVEX has a constriant on dq for vxorps: this is a 512-bit operation
int vector_len = 2;
__ vpxor($dst$$XMMRegister,$dst$$XMMRegister, $dst$$XMMRegister, vector_len);
%}
ins_pipe( fpu_reg_reg );
%}
instruct Repl16F_zero_evex(vecZ dst, immF0 zero) %{
predicate(n->as_Vector()->length() == 16 && UseAVX > 2);
match(Set dst (ReplicateF zero));
format %{ "vxorps $dst k0,$dst,$dst\t! replicate16F zero" %}
format %{ "vpxor $dst k0,$dst,$dst\t! replicate16F zero" %}
ins_encode %{
// Use vpxor in place of vxorps since EVEX has a constriant on dq for vxorps: this is a 512-bit operation
int vector_len = 2;
__ vxorps($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, vector_len);
__ vpxor($dst$$XMMRegister,$dst$$XMMRegister, $dst$$XMMRegister, vector_len);
%}
ins_pipe( fpu_reg_reg );
%}
@ -4373,13 +4457,38 @@ instruct Repl8D_mem_evex(vecZ dst, memory mem) %{
ins_pipe( pipe_slow );
%}
instruct Repl2D_zero_evex(vecX dst, immD0 zero) %{
predicate(n->as_Vector()->length() == 2 && UseAVX > 2);
match(Set dst (ReplicateD zero));
format %{ "vpxor $dst k0,$dst,$dst\t! replicate2D zero" %}
ins_encode %{
// Use vpxor in place of vxorpd since EVEX has a constriant on dq for vxorpd: this is a 512-bit operation
int vector_len = 2;
__ vpxor($dst$$XMMRegister,$dst$$XMMRegister, $dst$$XMMRegister, vector_len);
%}
ins_pipe( fpu_reg_reg );
%}
instruct Repl4D_zero_evex(vecY dst, immD0 zero) %{
predicate(n->as_Vector()->length() == 4 && UseAVX > 2);
match(Set dst (ReplicateD zero));
format %{ "vpxor $dst k0,$dst,$dst\t! replicate4D zero" %}
ins_encode %{
// Use vpxor in place of vxorpd since EVEX has a constriant on dq for vxorpd: this is a 512-bit operation
int vector_len = 2;
__ vpxor($dst$$XMMRegister,$dst$$XMMRegister, $dst$$XMMRegister, vector_len);
%}
ins_pipe( fpu_reg_reg );
%}
instruct Repl8D_zero_evex(vecZ dst, immD0 zero) %{
predicate(n->as_Vector()->length() == 8 && UseAVX > 2);
match(Set dst (ReplicateD zero));
format %{ "vxorpd $dst k0,$dst,$dst,vect512\t! replicate8D zero" %}
format %{ "vpxor $dst k0,$dst,$dst,vect512\t! replicate8D zero" %}
ins_encode %{
// Use vpxor in place of vxorpd since EVEX has a constriant on dq for vxorpd: this is a 512-bit operation
int vector_len = 2;
__ vxorpd($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, vector_len);
__ vpxor($dst$$XMMRegister,$dst$$XMMRegister, $dst$$XMMRegister, vector_len);
%}
ins_pipe( fpu_reg_reg );
%}
@ -7474,6 +7583,75 @@ instruct vshiftcnt(vecS dst, rRegI cnt) %{
ins_pipe( pipe_slow );
%}
// --------------------------------- Sqrt --------------------------------------
// Floating point vector sqrt - double precision only
instruct vsqrt2D_reg(vecX dst, vecX src) %{
predicate(UseAVX > 0 && n->as_Vector()->length() == 2);
match(Set dst (SqrtVD src));
format %{ "vsqrtpd $dst,$src\t! sqrt packed2D" %}
ins_encode %{
int vector_len = 0;
__ vsqrtpd($dst$$XMMRegister, $src$$XMMRegister, vector_len);
%}
ins_pipe( pipe_slow );
%}
instruct vsqrt2D_mem(vecX dst, memory mem) %{
predicate(UseAVX > 0 && n->as_Vector()->length() == 2);
match(Set dst (SqrtVD (LoadVector mem)));
format %{ "vsqrtpd $dst,$mem\t! sqrt packed2D" %}
ins_encode %{
int vector_len = 0;
__ vsqrtpd($dst$$XMMRegister, $mem$$Address, vector_len);
%}
ins_pipe( pipe_slow );
%}
instruct vsqrt4D_reg(vecY dst, vecY src) %{
predicate(UseAVX > 0 && n->as_Vector()->length() == 4);
match(Set dst (SqrtVD src));
format %{ "vsqrtpd $dst,$src\t! sqrt packed4D" %}
ins_encode %{
int vector_len = 1;
__ vsqrtpd($dst$$XMMRegister, $src$$XMMRegister, vector_len);
%}
ins_pipe( pipe_slow );
%}
instruct vsqrt4D_mem(vecY dst, memory mem) %{
predicate(UseAVX > 0 && n->as_Vector()->length() == 4);
match(Set dst (SqrtVD (LoadVector mem)));
format %{ "vsqrtpd $dst,$mem\t! sqrt packed4D" %}
ins_encode %{
int vector_len = 1;
__ vsqrtpd($dst$$XMMRegister, $mem$$Address, vector_len);
%}
ins_pipe( pipe_slow );
%}
instruct vsqrt8D_reg(vecZ dst, vecZ src) %{
predicate(UseAVX > 2 && n->as_Vector()->length() == 8);
match(Set dst (SqrtVD src));
format %{ "vsqrtpd $dst,$src\t! sqrt packed8D" %}
ins_encode %{
int vector_len = 2;
__ vsqrtpd($dst$$XMMRegister, $src$$XMMRegister, vector_len);
%}
ins_pipe( pipe_slow );
%}
instruct vsqrt8D_mem(vecZ dst, memory mem) %{
predicate(UseAVX > 2 && n->as_Vector()->length() == 8);
match(Set dst (SqrtVD (LoadVector mem)));
format %{ "vsqrtpd $dst,$mem\t! sqrt packed8D" %}
ins_encode %{
int vector_len = 2;
__ vsqrtpd($dst$$XMMRegister, $mem$$Address, vector_len);
%}
ins_pipe( pipe_slow );
%}
// ------------------------------ LeftShift -----------------------------------
// Shorts/Chars vector left shift

View File

@ -1004,10 +1004,10 @@ static int vec_stack_to_stack_helper(CodeBuffer *cbuf, bool do_size, int src_off
__ vmovdqu(Address(rsp, dst_offset), xmm0);
__ vmovdqu(xmm0, Address(rsp, -32));
case Op_VecZ:
__ evmovdqu(Address(rsp, -64), xmm0, 2);
__ evmovdqu(xmm0, Address(rsp, src_offset), 2);
__ evmovdqu(Address(rsp, dst_offset), xmm0, 2);
__ evmovdqu(xmm0, Address(rsp, -64), 2);
__ evmovdqul(Address(rsp, -64), xmm0, 2);
__ evmovdqul(xmm0, Address(rsp, src_offset), 2);
__ evmovdqul(Address(rsp, dst_offset), xmm0, 2);
__ evmovdqul(xmm0, Address(rsp, -64), 2);
break;
default:
ShouldNotReachHere();

View File

@ -1075,10 +1075,10 @@ static void vec_stack_to_stack_helper(CodeBuffer *cbuf, int src_offset,
__ vmovdqu(Address(rsp, dst_offset), xmm0);
__ vmovdqu(xmm0, Address(rsp, -32));
case Op_VecZ:
__ evmovdqu(Address(rsp, -64), xmm0, 2);
__ evmovdqu(xmm0, Address(rsp, src_offset), 2);
__ evmovdqu(Address(rsp, dst_offset), xmm0, 2);
__ evmovdqu(xmm0, Address(rsp, -64), 2);
__ evmovdqul(Address(rsp, -64), xmm0, 2);
__ evmovdqul(xmm0, Address(rsp, src_offset), 2);
__ evmovdqul(Address(rsp, dst_offset), xmm0, 2);
__ evmovdqul(xmm0, Address(rsp, -64), 2);
break;
default:
ShouldNotReachHere();

View File

@ -2211,9 +2211,13 @@ void os::pd_print_cpu_info(outputStream* st, char* buf, size_t buflen) {
}
}
const char* search_string = IA32_ONLY("model name") AMD64_ONLY("model name")
IA64_ONLY("") SPARC_ONLY("cpu")
ARM32_ONLY("Processor") PPC_ONLY("Processor") AARCH64_ONLY("Processor");
#if defined(AMD64) || defined(IA32) || defined(X32)
const char* search_string = "model name";
#elif defined(SPARC)
const char* search_string = "cpu";
#else
const char* search_string = "Processor";
#endif
// Parses the cpuinfo file for string representing the model name.
void os::get_summary_cpu_info(char* cpuinfo, size_t length) {
@ -2248,9 +2252,25 @@ void os::get_summary_cpu_info(char* cpuinfo, size_t length) {
}
// cpuinfo not found or parsing failed, just print generic string. The entire
// /proc/cpuinfo file will be printed later in the file (or enough of it for x86)
strncpy(cpuinfo, IA32_ONLY("x86_32") AMD64_ONLY("x86_32")
IA64_ONLY("IA64") SPARC_ONLY("sparcv9")
ARM32_ONLY("ARM") PPC_ONLY("PPC64") AARCH64_ONLY("AArch64"), length);
#if defined(AMD64)
strncpy(cpuinfo, "x86_64", length);
#elif defined(IA32)
strncpy(cpuinfo, "x86_32", length);
#elif defined(IA64)
strncpy(cpuinfo, "IA64", length);
#elif defined(SPARC)
strncpy(cpuinfo, "sparcv9", length);
#elif defined(AARCH64)
strncpy(cpuinfo, "AArch64", length);
#elif defined(ARM)
strncpy(cpuinfo, "ARM", length);
#elif defined(PPC)
strncpy(cpuinfo, "PPC64", length);
#elif defined(ZERO_LIBARCH)
strncpy(cpuinfo, ZERO_LIBARCH, length);
#else
strncpy(cpuinfo, "unknown", length);
#endif
}
void os::print_siginfo(outputStream* st, void* siginfo) {

View File

@ -4877,6 +4877,26 @@ char* os::pd_remap_memory(int fd, const char* file_name, size_t file_offset,
// Returns true=success, otherwise false.
bool os::pd_unmap_memory(char* addr, size_t bytes) {
MEMORY_BASIC_INFORMATION mem_info;
if (VirtualQuery(addr, &mem_info, sizeof(mem_info)) == 0) {
if (PrintMiscellaneous && Verbose) {
DWORD err = GetLastError();
tty->print_cr("VirtualQuery() failed: GetLastError->%ld.", err);
}
return false;
}
// Executable memory was not mapped using CreateFileMapping/MapViewOfFileEx.
// Instead, executable region was allocated using VirtualAlloc(). See
// pd_map_memory() above.
//
// The following flags should match the 'exec_access' flages used for
// VirtualProtect() in pd_map_memory().
if (mem_info.Protect == PAGE_EXECUTE_READ ||
mem_info.Protect == PAGE_EXECUTE_READWRITE) {
return pd_release_memory(addr, bytes);
}
BOOL result = UnmapViewOfFile(addr);
if (result == 0) {
if (PrintMiscellaneous && Verbose) {

View File

@ -4143,6 +4143,7 @@ bool MatchRule::is_vector() const {
"SubVB","SubVS","SubVI","SubVL","SubVF","SubVD",
"MulVS","MulVI","MulVL","MulVF","MulVD",
"DivVF","DivVD",
"SqrtVD",
"AndV" ,"XorV" ,"OrV",
"AddReductionVI", "AddReductionVL",
"AddReductionVF", "AddReductionVD",

View File

@ -304,8 +304,7 @@ AdaptiveSizePolicy* CMSCollector::size_policy() {
void ConcurrentMarkSweepGeneration::initialize_performance_counters() {
const char* gen_name = "old";
GenCollectorPolicy* gcp = (GenCollectorPolicy*) GenCollectedHeap::heap()->collector_policy();
GenCollectorPolicy* gcp = GenCollectedHeap::heap()->gen_policy();
// Generation Counters - generation 1, 1 subspace
_gen_counters = new GenerationCounters(gen_name, 1, 1,
gcp->min_old_size(), gcp->max_old_size(), &_virtual_space);

View File

@ -83,7 +83,7 @@ CollectionSetChooser::CollectionSetChooser() :
_regions((ResourceObj::set_allocation_type((address) &_regions,
ResourceObj::C_HEAP),
100), true /* C_Heap */),
_curr_index(0), _length(0), _first_par_unreserved_idx(0),
_front(0), _end(0), _first_par_unreserved_idx(0),
_region_live_threshold_bytes(0), _remaining_reclaimable_bytes(0) {
_region_live_threshold_bytes =
HeapRegion::GrainBytes * (size_t) G1MixedGCLiveThresholdPercent / 100;
@ -91,19 +91,19 @@ CollectionSetChooser::CollectionSetChooser() :
#ifndef PRODUCT
void CollectionSetChooser::verify() {
guarantee(_length <= regions_length(),
err_msg("_length: %u regions length: %u", _length, regions_length()));
guarantee(_curr_index <= _length,
err_msg("_curr_index: %u _length: %u", _curr_index, _length));
guarantee(_end <= regions_length(),
err_msg("_end: %u regions length: %u", _end, regions_length()));
guarantee(_front <= _end,
err_msg("_front: %u _end: %u", _front, _end));
uint index = 0;
size_t sum_of_reclaimable_bytes = 0;
while (index < _curr_index) {
while (index < _front) {
guarantee(regions_at(index) == NULL,
"all entries before _curr_index should be NULL");
"all entries before _front should be NULL");
index += 1;
}
HeapRegion *prev = NULL;
while (index < _length) {
while (index < _end) {
HeapRegion *curr = regions_at(index++);
guarantee(curr != NULL, "Regions in _regions array cannot be NULL");
guarantee(!curr->is_young(), "should not be young!");
@ -132,15 +132,15 @@ void CollectionSetChooser::sort_regions() {
regions_trunc_to(_first_par_unreserved_idx);
}
_regions.sort(order_regions);
assert(_length <= regions_length(), "Requirement");
assert(_end <= regions_length(), "Requirement");
#ifdef ASSERT
for (uint i = 0; i < _length; i++) {
for (uint i = 0; i < _end; i++) {
assert(regions_at(i) != NULL, "Should be true by sorting!");
}
#endif // ASSERT
if (G1PrintRegionLivenessInfo) {
G1PrintRegionLivenessInfoClosure cl(gclog_or_tty, "Post-Sorting");
for (uint i = 0; i < _length; ++i) {
for (uint i = 0; i < _end; ++i) {
HeapRegion* r = regions_at(i);
cl.doHeapRegion(r);
}
@ -154,11 +154,19 @@ void CollectionSetChooser::add_region(HeapRegion* hr) {
err_msg("Pinned region shouldn't be added to the collection set (index %u)", hr->hrm_index()));
assert(!hr->is_young(), "should not be young!");
_regions.append(hr);
_length++;
_end++;
_remaining_reclaimable_bytes += hr->reclaimable_bytes();
hr->calc_gc_efficiency();
}
void CollectionSetChooser::push(HeapRegion* hr) {
assert(hr != NULL, "Can't put back a NULL region");
assert(_front >= 1, "Too many regions have been put back");
_front--;
regions_at_put(_front, hr);
_remaining_reclaimable_bytes += hr->reclaimable_bytes();
}
void CollectionSetChooser::prepare_for_par_region_addition(uint n_threads,
uint n_regions,
uint chunk_size) {
@ -193,7 +201,7 @@ void CollectionSetChooser::update_totals(uint region_num,
// We could have just used atomics instead of taking the
// lock. However, we currently don't have an atomic add for size_t.
MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag);
_length += region_num;
_end += region_num;
_remaining_reclaimable_bytes += reclaimable_bytes;
} else {
assert(reclaimable_bytes == 0, "invariant");
@ -202,7 +210,7 @@ void CollectionSetChooser::update_totals(uint region_num,
void CollectionSetChooser::clear() {
_regions.clear();
_curr_index = 0;
_length = 0;
_front = 0;
_end = 0;
_remaining_reclaimable_bytes = 0;
};

View File

@ -48,12 +48,10 @@ class CollectionSetChooser: public CHeapObj<mtGC> {
// The index of the next candidate old region to be considered for
// addition to the CSet.
uint _curr_index;
uint _front;
// The number of candidate old regions added to the CSet chooser.
// Note: this is not updated when removing a region using
// remove_and_move_to_next() below.
uint _length;
// The index of the last candidate old region
uint _end;
// Keeps track of the start of the next array chunk to be claimed by
// parallel GC workers.
@ -73,31 +71,33 @@ public:
// collection without removing it from the CSet chooser.
HeapRegion* peek() {
HeapRegion* res = NULL;
if (_curr_index < _length) {
res = regions_at(_curr_index);
if (_front < _end) {
res = regions_at(_front);
assert(res != NULL,
err_msg("Unexpected NULL hr in _regions at index %u",
_curr_index));
_front));
}
return res;
}
// Remove the given region from the CSet chooser and move to the
// next one. The given region should be the current candidate region
// in the CSet chooser.
void remove_and_move_to_next(HeapRegion* hr) {
// next one.
HeapRegion* pop() {
HeapRegion* hr = regions_at(_front);
assert(hr != NULL, "pre-condition");
assert(_curr_index < _length, "pre-condition");
assert(regions_at(_curr_index) == hr, "pre-condition");
regions_at_put(_curr_index, NULL);
assert(_front < _end, "pre-condition");
regions_at_put(_front, NULL);
assert(hr->reclaimable_bytes() <= _remaining_reclaimable_bytes,
err_msg("remaining reclaimable bytes inconsistent "
"from region: " SIZE_FORMAT " remaining: " SIZE_FORMAT,
hr->reclaimable_bytes(), _remaining_reclaimable_bytes));
_remaining_reclaimable_bytes -= hr->reclaimable_bytes();
_curr_index += 1;
_front += 1;
return hr;
}
void push(HeapRegion* hr);
CollectionSetChooser();
void sort_regions();
@ -113,7 +113,7 @@ public:
}
// Returns the number candidate old regions added
uint length() { return _length; }
uint length() { return _end; }
// Serial version.
void add_region(HeapRegion *hr);
@ -135,7 +135,7 @@ public:
void clear();
// Return the number of candidate regions that remain to be collected.
uint remaining_regions() { return _length - _curr_index; }
uint remaining_regions() { return _end - _front; }
// Determine whether the CSet chooser has more candidate regions or not.
bool is_empty() { return remaining_regions() == 0; }

View File

@ -29,7 +29,7 @@
#include "gc/g1/g1HotCardCache.hpp"
#include "runtime/java.hpp"
ConcurrentG1Refine::ConcurrentG1Refine(G1CollectedHeap* g1h, CardTableEntryClosure* refine_closure) :
ConcurrentG1Refine::ConcurrentG1Refine(G1CollectedHeap* g1h) :
_threads(NULL), _n_threads(0),
_hot_card_cache(g1h)
{
@ -48,29 +48,46 @@ ConcurrentG1Refine::ConcurrentG1Refine(G1CollectedHeap* g1h, CardTableEntryClosu
FLAG_SET_DEFAULT(G1ConcRefinementRedZone, yellow_zone() * 2);
}
set_red_zone(MAX2<int>(G1ConcRefinementRedZone, yellow_zone()));
}
_n_worker_threads = thread_num();
ConcurrentG1Refine* ConcurrentG1Refine::create(G1CollectedHeap* g1h, CardTableEntryClosure* refine_closure, jint* ecode) {
ConcurrentG1Refine* cg1r = new ConcurrentG1Refine(g1h);
if (cg1r == NULL) {
*ecode = JNI_ENOMEM;
vm_shutdown_during_initialization("Could not create ConcurrentG1Refine");
return NULL;
}
cg1r->_n_worker_threads = thread_num();
// We need one extra thread to do the young gen rset size sampling.
_n_threads = _n_worker_threads + 1;
cg1r->_n_threads = cg1r->_n_worker_threads + 1;
reset_threshold_step();
cg1r->reset_threshold_step();
_threads = NEW_C_HEAP_ARRAY(ConcurrentG1RefineThread*, _n_threads, mtGC);
cg1r->_threads = NEW_C_HEAP_ARRAY_RETURN_NULL(ConcurrentG1RefineThread*, cg1r->_n_threads, mtGC);
if (cg1r->_threads == NULL) {
*ecode = JNI_ENOMEM;
vm_shutdown_during_initialization("Could not allocate an array for ConcurrentG1RefineThread");
return NULL;
}
uint worker_id_offset = DirtyCardQueueSet::num_par_ids();
ConcurrentG1RefineThread *next = NULL;
for (uint i = _n_threads - 1; i != UINT_MAX; i--) {
ConcurrentG1RefineThread* t = new ConcurrentG1RefineThread(this, next, refine_closure, worker_id_offset, i);
for (uint i = cg1r->_n_threads - 1; i != UINT_MAX; i--) {
ConcurrentG1RefineThread* t = new ConcurrentG1RefineThread(cg1r, next, refine_closure, worker_id_offset, i);
assert(t != NULL, "Conc refine should have been created");
if (t->osthread() == NULL) {
vm_shutdown_during_initialization("Could not create ConcurrentG1RefineThread");
*ecode = JNI_ENOMEM;
vm_shutdown_during_initialization("Could not create ConcurrentG1RefineThread");
return NULL;
}
assert(t->cg1r() == this, "Conc refine thread should refer to this");
_threads[i] = t;
assert(t->cg1r() == cg1r, "Conc refine thread should refer to this");
cg1r->_threads[i] = t;
next = t;
}
*ecode = JNI_OK;
return cg1r;
}
void ConcurrentG1Refine::reset_threshold_step() {

View File

@ -71,10 +71,15 @@ class ConcurrentG1Refine: public CHeapObj<mtGC> {
// Reset the threshold step value based of the current zone boundaries.
void reset_threshold_step();
ConcurrentG1Refine(G1CollectedHeap* g1h);
public:
ConcurrentG1Refine(G1CollectedHeap* g1h, CardTableEntryClosure* refine_closure);
~ConcurrentG1Refine();
// Returns ConcurrentG1Refine instance if succeeded to create/initialize ConcurrentG1Refine and ConcurrentG1RefineThread.
// Otherwise, returns NULL with error code.
static ConcurrentG1Refine* create(G1CollectedHeap* g1h, CardTableEntryClosure* refine_closure, jint* ecode);
void init(G1RegionToSpaceMapper* card_counts_storage);
void stop();

View File

@ -2025,7 +2025,6 @@ G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* policy_) :
_survivor_evac_stats(YoungPLABSize, PLABWeight),
_old_evac_stats(OldPLABSize, PLABWeight),
_expand_heap_after_alloc_failure(true),
_surviving_young_words(NULL),
_old_marking_cycles_started(0),
_old_marking_cycles_completed(0),
_heap_summary_sent(false),
@ -2126,7 +2125,11 @@ jint G1CollectedHeap::initialize() {
_refine_cte_cl = new RefineCardTableEntryClosure();
_cg1r = new ConcurrentG1Refine(this, _refine_cte_cl);
jint ecode = JNI_OK;
_cg1r = ConcurrentG1Refine::create(this, _refine_cte_cl, &ecode);
if (_cg1r == NULL) {
return ecode;
}
// Reserve the maximum.
@ -2397,6 +2400,10 @@ void G1CollectedHeap::ref_processing_init() {
// (for efficiency/performance)
}
CollectorPolicy* G1CollectedHeap::collector_policy() const {
return g1_policy();
}
size_t G1CollectedHeap::capacity() const {
return _hrm.length() * HeapRegion::GrainBytes;
}
@ -3694,10 +3701,6 @@ size_t G1CollectedHeap::pending_card_num() {
return (buffer_size * buffer_num + extra_cards) / oopSize;
}
size_t G1CollectedHeap::cards_scanned() {
return g1_rem_set()->cardsScanned();
}
class RegisterHumongousWithInCSetFastTestClosure : public HeapRegionClosure {
private:
size_t _total_humongous;
@ -3838,36 +3841,6 @@ void G1CollectedHeap::register_humongous_regions_with_cset() {
cl.flush_rem_set_entries();
}
void G1CollectedHeap::setup_surviving_young_words() {
assert(_surviving_young_words == NULL, "pre-condition");
uint array_length = g1_policy()->young_cset_region_length();
_surviving_young_words = NEW_C_HEAP_ARRAY(size_t, (size_t) array_length, mtGC);
if (_surviving_young_words == NULL) {
vm_exit_out_of_memory(sizeof(size_t) * array_length, OOM_MALLOC_ERROR,
"Not enough space for young surv words summary.");
}
memset(_surviving_young_words, 0, (size_t) array_length * sizeof(size_t));
#ifdef ASSERT
for (uint i = 0; i < array_length; ++i) {
assert( _surviving_young_words[i] == 0, "memset above" );
}
#endif // !ASSERT
}
void G1CollectedHeap::update_surviving_young_words(size_t* surv_young_words) {
assert_at_safepoint(true);
uint array_length = g1_policy()->young_cset_region_length();
for (uint i = 0; i < array_length; ++i) {
_surviving_young_words[i] += surv_young_words[i];
}
}
void G1CollectedHeap::cleanup_surviving_young_words() {
guarantee( _surviving_young_words != NULL, "pre-condition" );
FREE_C_HEAP_ARRAY(size_t, _surviving_young_words);
_surviving_young_words = NULL;
}
#ifdef ASSERT
class VerifyCSetClosure: public HeapRegionClosure {
public:
@ -4129,7 +4102,8 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
g1_policy()->print_collection_set(g1_policy()->inc_cset_head(), gclog_or_tty);
#endif // YOUNG_LIST_VERBOSE
g1_policy()->finalize_cset(target_pause_time_ms);
double time_remaining_ms = g1_policy()->finalize_young_cset_part(target_pause_time_ms);
g1_policy()->finalize_old_cset_part(time_remaining_ms);
evacuation_info.set_collectionset_regions(g1_policy()->cset_region_length());
@ -4155,22 +4129,20 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
collection_set_iterate(&cl);
#endif // ASSERT
setup_surviving_young_words();
// Initialize the GC alloc regions.
_allocator->init_gc_alloc_regions(evacuation_info);
G1ParScanThreadStateSet per_thread_states(this, workers()->active_workers(), g1_policy()->young_cset_region_length());
// Actually do the work...
evacuate_collection_set(evacuation_info);
evacuate_collection_set(evacuation_info, &per_thread_states);
free_collection_set(g1_policy()->collection_set(), evacuation_info);
const size_t* surviving_young_words = per_thread_states.surviving_young_words();
free_collection_set(g1_policy()->collection_set(), evacuation_info, surviving_young_words);
eagerly_reclaim_humongous_regions();
g1_policy()->clear_collection_set();
cleanup_surviving_young_words();
// Start a new incremental collection set for the next pause.
g1_policy()->start_incremental_cset_building();
@ -4255,7 +4227,8 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
// investigate this in CR 7178365.
double sample_end_time_sec = os::elapsedTime();
double pause_time_ms = (sample_end_time_sec - sample_start_time_sec) * MILLIUNITS;
g1_policy()->record_collection_pause_end(pause_time_ms);
size_t total_cards_scanned = per_thread_states.total_cards_scanned();
g1_policy()->record_collection_pause_end(pause_time_ms, total_cards_scanned);
evacuation_info.set_collectionset_used_before(g1_policy()->collection_set_bytes_used_before());
evacuation_info.set_bytes_copied(g1_policy()->bytes_copied_during_gc());
@ -4541,15 +4514,15 @@ class G1KlassScanClosure : public KlassClosure {
class G1ParTask : public AbstractGangTask {
protected:
G1CollectedHeap* _g1h;
G1ParScanThreadState** _pss;
RefToScanQueueSet* _queues;
G1RootProcessor* _root_processor;
ParallelTaskTerminator _terminator;
uint _n_workers;
G1CollectedHeap* _g1h;
G1ParScanThreadStateSet* _pss;
RefToScanQueueSet* _queues;
G1RootProcessor* _root_processor;
ParallelTaskTerminator _terminator;
uint _n_workers;
public:
G1ParTask(G1CollectedHeap* g1h, G1ParScanThreadState** per_thread_states, RefToScanQueueSet *task_queues, G1RootProcessor* root_processor, uint n_workers)
G1ParTask(G1CollectedHeap* g1h, G1ParScanThreadStateSet* per_thread_states, RefToScanQueueSet *task_queues, G1RootProcessor* root_processor, uint n_workers)
: AbstractGangTask("G1 collection"),
_g1h(g1h),
_pss(per_thread_states),
@ -4607,7 +4580,7 @@ public:
ReferenceProcessor* rp = _g1h->ref_processor_stw();
G1ParScanThreadState* pss = _pss[worker_id];
G1ParScanThreadState* pss = _pss->state_for_worker(worker_id);
pss->set_ref_processor(rp);
bool only_young = _g1h->collector_state()->gcs_are_young();
@ -4664,9 +4637,12 @@ public:
worker_id);
G1ParPushHeapRSClosure push_heap_rs_cl(_g1h, pss);
_g1h->g1_rem_set()->oops_into_collection_set_do(&push_heap_rs_cl,
weak_root_cl,
worker_id);
size_t cards_scanned = _g1h->g1_rem_set()->oops_into_collection_set_do(&push_heap_rs_cl,
weak_root_cl,
worker_id);
_pss->add_cards_scanned(worker_id, cards_scanned);
double strong_roots_sec = os::elapsedTime() - start_strong_roots_sec;
double term_sec = 0.0;
@ -5263,15 +5239,15 @@ public:
class G1STWRefProcTaskExecutor: public AbstractRefProcTaskExecutor {
private:
G1CollectedHeap* _g1h;
G1ParScanThreadState** _pss;
RefToScanQueueSet* _queues;
WorkGang* _workers;
uint _active_workers;
G1CollectedHeap* _g1h;
G1ParScanThreadStateSet* _pss;
RefToScanQueueSet* _queues;
WorkGang* _workers;
uint _active_workers;
public:
G1STWRefProcTaskExecutor(G1CollectedHeap* g1h,
G1ParScanThreadState** per_thread_states,
G1ParScanThreadStateSet* per_thread_states,
WorkGang* workers,
RefToScanQueueSet *task_queues,
uint n_workers) :
@ -5295,14 +5271,14 @@ class G1STWRefProcTaskProxy: public AbstractGangTask {
typedef AbstractRefProcTaskExecutor::ProcessTask ProcessTask;
ProcessTask& _proc_task;
G1CollectedHeap* _g1h;
G1ParScanThreadState** _pss;
G1ParScanThreadStateSet* _pss;
RefToScanQueueSet* _task_queues;
ParallelTaskTerminator* _terminator;
public:
G1STWRefProcTaskProxy(ProcessTask& proc_task,
G1CollectedHeap* g1h,
G1ParScanThreadState** per_thread_states,
G1ParScanThreadStateSet* per_thread_states,
RefToScanQueueSet *task_queues,
ParallelTaskTerminator* terminator) :
AbstractGangTask("Process reference objects in parallel"),
@ -5320,7 +5296,7 @@ public:
G1STWIsAliveClosure is_alive(_g1h);
G1ParScanThreadState* pss = _pss[worker_id];
G1ParScanThreadState* pss = _pss->state_for_worker(worker_id);
pss->set_ref_processor(NULL);
G1ParScanExtRootClosure only_copy_non_heap_cl(_g1h, pss);
@ -5399,14 +5375,14 @@ void G1STWRefProcTaskExecutor::execute(EnqueueTask& enq_task) {
class G1ParPreserveCMReferentsTask: public AbstractGangTask {
protected:
G1CollectedHeap* _g1h;
G1ParScanThreadState** _pss;
RefToScanQueueSet* _queues;
ParallelTaskTerminator _terminator;
uint _n_workers;
G1CollectedHeap* _g1h;
G1ParScanThreadStateSet* _pss;
RefToScanQueueSet* _queues;
ParallelTaskTerminator _terminator;
uint _n_workers;
public:
G1ParPreserveCMReferentsTask(G1CollectedHeap* g1h, G1ParScanThreadState** per_thread_states, int workers, RefToScanQueueSet *task_queues) :
G1ParPreserveCMReferentsTask(G1CollectedHeap* g1h, G1ParScanThreadStateSet* per_thread_states, int workers, RefToScanQueueSet *task_queues) :
AbstractGangTask("ParPreserveCMReferents"),
_g1h(g1h),
_pss(per_thread_states),
@ -5419,7 +5395,7 @@ public:
ResourceMark rm;
HandleMark hm;
G1ParScanThreadState* pss = _pss[worker_id];
G1ParScanThreadState* pss = _pss->state_for_worker(worker_id);
pss->set_ref_processor(NULL);
assert(pss->queue_is_empty(), "both queue and overflow should be empty");
@ -5480,7 +5456,7 @@ public:
};
// Weak Reference processing during an evacuation pause (part 1).
void G1CollectedHeap::process_discovered_references(G1ParScanThreadState** per_thread_states) {
void G1CollectedHeap::process_discovered_references(G1ParScanThreadStateSet* per_thread_states) {
double ref_proc_start = os::elapsedTime();
ReferenceProcessor* rp = _ref_processor_stw;
@ -5525,7 +5501,7 @@ void G1CollectedHeap::process_discovered_references(G1ParScanThreadState** per_t
// JNI refs.
// Use only a single queue for this PSS.
G1ParScanThreadState* pss = per_thread_states[0];
G1ParScanThreadState* pss = per_thread_states->state_for_worker(0);
pss->set_ref_processor(NULL);
assert(pss->queue_is_empty(), "pre-condition");
@ -5586,7 +5562,7 @@ void G1CollectedHeap::process_discovered_references(G1ParScanThreadState** per_t
}
// Weak Reference processing during an evacuation pause (part 2).
void G1CollectedHeap::enqueue_discovered_references(G1ParScanThreadState** per_thread_states) {
void G1CollectedHeap::enqueue_discovered_references(G1ParScanThreadStateSet* per_thread_states) {
double ref_enq_start = os::elapsedTime();
ReferenceProcessor* rp = _ref_processor_stw;
@ -5621,7 +5597,7 @@ void G1CollectedHeap::enqueue_discovered_references(G1ParScanThreadState** per_t
g1_policy()->phase_times()->record_ref_enq_time(ref_enq_time * 1000.0);
}
void G1CollectedHeap::evacuate_collection_set(EvacuationInfo& evacuation_info) {
void G1CollectedHeap::evacuate_collection_set(EvacuationInfo& evacuation_info, G1ParScanThreadStateSet* per_thread_states) {
_expand_heap_after_alloc_failure = true;
_evacuation_failed = false;
@ -5641,11 +5617,6 @@ void G1CollectedHeap::evacuate_collection_set(EvacuationInfo& evacuation_info) {
double start_par_time_sec = os::elapsedTime();
double end_par_time_sec;
G1ParScanThreadState** per_thread_states = NEW_C_HEAP_ARRAY(G1ParScanThreadState*, n_workers, mtGC);
for (uint i = 0; i < n_workers; i++) {
per_thread_states[i] = new_par_scan_state(i);
}
{
G1RootProcessor root_processor(this, n_workers);
G1ParTask g1_par_task(this, per_thread_states, _task_queues, &root_processor, n_workers);
@ -5699,11 +5670,7 @@ void G1CollectedHeap::evacuate_collection_set(EvacuationInfo& evacuation_info) {
_allocator->release_gc_alloc_regions(evacuation_info);
g1_rem_set()->cleanup_after_oops_into_collection_set_do();
for (uint i = 0; i < n_workers; i++) {
G1ParScanThreadState* pss = per_thread_states[i];
delete pss;
}
FREE_C_HEAP_ARRAY(G1ParScanThreadState*, per_thread_states);
per_thread_states->flush();
record_obj_copy_mem_stats();
@ -6054,7 +6021,7 @@ void G1CollectedHeap::cleanUpCardTable() {
g1_policy()->phase_times()->record_clear_ct_time(elapsed * 1000.0);
}
void G1CollectedHeap::free_collection_set(HeapRegion* cs_head, EvacuationInfo& evacuation_info) {
void G1CollectedHeap::free_collection_set(HeapRegion* cs_head, EvacuationInfo& evacuation_info, const size_t* surviving_young_words) {
size_t pre_used = 0;
FreeRegionList local_free_list("Local List for CSet Freeing");
@ -6108,7 +6075,7 @@ void G1CollectedHeap::free_collection_set(HeapRegion* cs_head, EvacuationInfo& e
int index = cur->young_index_in_cset();
assert(index != -1, "invariant");
assert((uint) index < policy->young_cset_region_length(), "invariant");
size_t words_survived = _surviving_young_words[index];
size_t words_survived = surviving_young_words[index];
cur->record_surv_words_in_group(words_survived);
// At this point the we have 'popped' cur from the collection set

View File

@ -56,6 +56,7 @@ class HRRSCleanupTask;
class GenerationSpec;
class OopsInHeapRegionClosure;
class G1ParScanThreadState;
class G1ParScanThreadStateSet;
class G1KlassScanClosure;
class G1ParScanThreadState;
class ObjectClosure;
@ -192,6 +193,7 @@ class G1CollectedHeap : public CollectedHeap {
// Closures used in implementation.
friend class G1ParScanThreadState;
friend class G1ParScanThreadStateSet;
friend class G1ParTask;
friend class G1PLABAllocator;
friend class G1PrepareCompactClosure;
@ -309,14 +311,8 @@ private:
volatile unsigned _gc_time_stamp;
size_t* _surviving_young_words;
G1HRPrinter _hr_printer;
void setup_surviving_young_words();
void update_surviving_young_words(size_t* surv_young_words);
void cleanup_surviving_young_words();
// It decides whether an explicit GC should start a concurrent cycle
// instead of doing a STW GC. Currently, a concurrent cycle is
// explicitly started if:
@ -584,11 +580,11 @@ protected:
// Process any reference objects discovered during
// an incremental evacuation pause.
void process_discovered_references(G1ParScanThreadState** per_thread_states);
void process_discovered_references(G1ParScanThreadStateSet* per_thread_states);
// Enqueue any remaining discovered references
// after processing.
void enqueue_discovered_references(G1ParScanThreadState** per_thread_states);
void enqueue_discovered_references(G1ParScanThreadStateSet* per_thread_states);
public:
WorkGang* workers() const { return _workers; }
@ -683,9 +679,6 @@ public:
// Allocates a new heap region instance.
HeapRegion* new_heap_region(uint hrs_index, MemRegion mr);
// Allocates a new per thread par scan state for the given thread id.
G1ParScanThreadState* new_par_scan_state(uint worker_id);
// Allocate the highest free region in the reserved heap. This will commit
// regions as necessary.
HeapRegion* alloc_highest_free_region();
@ -799,7 +792,7 @@ protected:
bool do_collection_pause_at_safepoint(double target_pause_time_ms);
// Actually do the work of evacuating the collection set.
void evacuate_collection_set(EvacuationInfo& evacuation_info);
void evacuate_collection_set(EvacuationInfo& evacuation_info, G1ParScanThreadStateSet* per_thread_states);
// Print the header for the per-thread termination statistics.
static void print_termination_stats_hdr(outputStream* const st);
@ -833,7 +826,7 @@ protected:
// After a collection pause, make the regions in the CS into free
// regions.
void free_collection_set(HeapRegion* cs_head, EvacuationInfo& evacuation_info);
void free_collection_set(HeapRegion* cs_head, EvacuationInfo& evacuation_info, const size_t* surviving_young_words);
// Abandon the current collection set without recording policy
// statistics or updating free lists.
@ -1057,7 +1050,7 @@ public:
// The current policy object for the collector.
G1CollectorPolicy* g1_policy() const { return _g1_policy; }
virtual CollectorPolicy* collector_policy() const { return (CollectorPolicy*) g1_policy(); }
virtual CollectorPolicy* collector_policy() const;
// Adaptive size policy. No such thing for g1.
virtual AdaptiveSizePolicy* size_policy() { return NULL; }
@ -1610,7 +1603,6 @@ public:
public:
size_t pending_card_num();
size_t cards_scanned();
protected:
size_t _max_heap_capacity;

View File

@ -38,7 +38,3 @@ HeapRegion* G1CollectedHeap::new_heap_region(uint hrs_index,
MemRegion mr) {
return new HeapRegion(hrs_index, bot_shared(), mr);
}
G1ParScanThreadState* G1CollectedHeap::new_par_scan_state(uint worker_id) {
return new G1ParScanThreadState(this, worker_id);
}

View File

@ -923,7 +923,7 @@ bool G1CollectorPolicy::need_to_start_conc_mark(const char* source, size_t alloc
// Anything below that is considered to be zero
#define MIN_TIMER_GRANULARITY 0.0000001
void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms) {
void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms, size_t cards_scanned) {
double end_time_sec = os::elapsedTime();
assert(_cur_collection_pause_used_regions_at_start >= cset_region_length(),
"otherwise, the subtraction below does not make sense");
@ -1052,8 +1052,6 @@ void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms) {
_cost_per_card_ms_seq->add(cost_per_card_ms);
}
size_t cards_scanned = _g1->cards_scanned();
double cost_per_entry_ms = 0.0;
if (cards_scanned > 10) {
cost_per_entry_ms = phase_times()->average_time_ms(G1GCPhaseTimes::ScanRS) / (double) cards_scanned;
@ -1871,7 +1869,7 @@ uint G1CollectorPolicy::calc_max_old_cset_length() {
}
void G1CollectorPolicy::finalize_cset(double target_pause_time_ms) {
double G1CollectorPolicy::finalize_young_cset_part(double target_pause_time_ms) {
double young_start_time_sec = os::elapsedTime();
YoungList* young_list = _g1->young_list();
@ -1883,7 +1881,6 @@ void G1CollectorPolicy::finalize_cset(double target_pause_time_ms) {
guarantee(_collection_set == NULL, "Precondition");
double base_time_ms = predict_base_elapsed_time_ms(_pending_cards);
double predicted_pause_time_ms = base_time_ms;
double time_remaining_ms = MAX2(target_pause_time_ms - base_time_ms, 0.0);
ergo_verbose4(ErgoCSetConstruction | ErgoHigh,
@ -1927,15 +1924,16 @@ void G1CollectorPolicy::finalize_cset(double target_pause_time_ms) {
_collection_set = _inc_cset_head;
_collection_set_bytes_used_before = _inc_cset_bytes_used_before;
time_remaining_ms = MAX2(time_remaining_ms - _inc_cset_predicted_elapsed_time_ms, 0.0);
predicted_pause_time_ms += _inc_cset_predicted_elapsed_time_ms;
ergo_verbose3(ErgoCSetConstruction | ErgoHigh,
ergo_verbose4(ErgoCSetConstruction | ErgoHigh,
"add young regions to CSet",
ergo_format_region("eden")
ergo_format_region("survivors")
ergo_format_ms("predicted young region time"),
ergo_format_ms("predicted young region time")
ergo_format_ms("target pause time"),
eden_region_length, survivor_region_length,
_inc_cset_predicted_elapsed_time_ms);
_inc_cset_predicted_elapsed_time_ms,
target_pause_time_ms);
// The number of recorded young regions is the incremental
// collection set's current size
@ -1944,8 +1942,13 @@ void G1CollectorPolicy::finalize_cset(double target_pause_time_ms) {
double young_end_time_sec = os::elapsedTime();
phase_times()->record_young_cset_choice_time_ms((young_end_time_sec - young_start_time_sec) * 1000.0);
// Set the start of the non-young choice time.
double non_young_start_time_sec = young_end_time_sec;
return time_remaining_ms;
}
void G1CollectorPolicy::finalize_old_cset_part(double time_remaining_ms) {
double non_young_start_time_sec = os::elapsedTime();
double predicted_old_time_ms = 0.0;
if (!collector_state()->gcs_are_young()) {
CollectionSetChooser* cset_chooser = _collectionSetChooser;
@ -2033,8 +2036,8 @@ void G1CollectorPolicy::finalize_cset(double target_pause_time_ms) {
// We will add this region to the CSet.
time_remaining_ms = MAX2(time_remaining_ms - predicted_time_ms, 0.0);
predicted_pause_time_ms += predicted_time_ms;
cset_chooser->remove_and_move_to_next(hr);
predicted_old_time_ms += predicted_time_ms;
cset_chooser->pop(); // already have region via peek()
_g1->old_set_remove(hr);
add_old_region_to_cset(hr);
@ -2068,16 +2071,13 @@ void G1CollectorPolicy::finalize_cset(double target_pause_time_ms) {
stop_incremental_cset_building();
ergo_verbose5(ErgoCSetConstruction,
ergo_verbose3(ErgoCSetConstruction,
"finish choosing CSet",
ergo_format_region("eden")
ergo_format_region("survivors")
ergo_format_region("old")
ergo_format_ms("predicted pause time")
ergo_format_ms("target pause time"),
eden_region_length, survivor_region_length,
ergo_format_ms("predicted old region time")
ergo_format_ms("time remaining"),
old_cset_region_length(),
predicted_pause_time_ms, target_pause_time_ms);
predicted_old_time_ms, time_remaining_ms);
double non_young_end_time_sec = os::elapsedTime();
phase_times()->record_non_young_cset_choice_time_ms((non_young_end_time_sec - non_young_start_time_sec) * 1000.0);

View File

@ -473,7 +473,7 @@ private:
// The number of bytes in the collection set before the pause. Set from
// the incrementally built collection set at the start of an evacuation
// pause, and incremented in finalize_cset() when adding old regions
// pause, and incremented in finalize_old_cset_part() when adding old regions
// (if any) to the collection set.
size_t _collection_set_bytes_used_before;
@ -634,7 +634,7 @@ public:
// Record the start and end of an evacuation pause.
void record_collection_pause_start(double start_time_sec);
void record_collection_pause_end(double pause_time_ms);
void record_collection_pause_end(double pause_time_ms, size_t cards_scanned);
// Record the start and end of a full collection.
void record_full_collection_start();
@ -689,7 +689,8 @@ public:
// Choose a new collection set. Marks the chosen regions as being
// "in_collection_set", and links them together. The head and number of
// the collection set are available via access methods.
void finalize_cset(double target_pause_time_ms);
double finalize_young_cset_part(double target_pause_time_ms);
virtual void finalize_old_cset_part(double time_remaining_ms);
// The head of the list (via "next_in_collection_set()") representing the
// current collection set.
@ -865,8 +866,8 @@ public:
return _recorded_survivor_regions;
}
void record_thread_age_table(ageTable* age_table) {
_survivors_age_table.merge_par(age_table);
void record_age_table(ageTable* age_table) {
_survivors_age_table.merge(age_table);
}
void update_max_gc_locker_expansion();

View File

@ -46,11 +46,11 @@ void G1EvacStats::adjust_desired_plab_sz() {
if (_allocated == 0) {
assert((_unused == 0),
err_msg("Inconsistency in PLAB stats: "
"_allocated: "SIZE_FORMAT", "
"_wasted: "SIZE_FORMAT", "
"_region_end_waste: "SIZE_FORMAT", "
"_unused: "SIZE_FORMAT", "
"_used : "SIZE_FORMAT,
"_allocated: " SIZE_FORMAT ", "
"_wasted: " SIZE_FORMAT ", "
"_region_end_waste: " SIZE_FORMAT ", "
"_unused: " SIZE_FORMAT ", "
"_used : " SIZE_FORMAT,
_allocated, _wasted, _region_end_waste, _unused, used()));
_allocated = 1;
}

View File

@ -32,7 +32,7 @@
#include "oops/oop.inline.hpp"
#include "runtime/prefetch.inline.hpp"
G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint worker_id)
G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint worker_id, size_t young_cset_length)
: _g1h(g1h),
_refs(g1h->task_queue(worker_id)),
_dcq(&g1h->dirty_card_queue_set()),
@ -51,8 +51,8 @@ G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint worker_id)
// non-young regions (where the age is -1)
// We also add a few elements at the beginning and at the end in
// an attempt to eliminate cache contention
uint real_length = 1 + _g1h->g1_policy()->young_cset_region_length();
uint array_length = PADDING_ELEM_NUM +
size_t real_length = 1 + young_cset_length;
size_t array_length = PADDING_ELEM_NUM +
real_length +
PADDING_ELEM_NUM;
_surviving_young_words_base = NEW_C_HEAP_ARRAY(size_t, array_length, mtGC);
@ -60,7 +60,7 @@ G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint worker_id)
vm_exit_out_of_memory(array_length * sizeof(size_t), OOM_MALLOC_ERROR,
"Not enough space for young surv histo.");
_surviving_young_words = _surviving_young_words_base + PADDING_ELEM_NUM;
memset(_surviving_young_words, 0, (size_t) real_length * sizeof(size_t));
memset(_surviving_young_words, 0, real_length * sizeof(size_t));
_plab_allocator = G1PLABAllocator::create_allocator(_g1h->allocator());
@ -71,13 +71,21 @@ G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint worker_id)
_dest[InCSetState::Old] = InCSetState::Old;
}
G1ParScanThreadState::~G1ParScanThreadState() {
// Pass locally gathered statistics to global state.
void G1ParScanThreadState::flush(size_t* surviving_young_words) {
_dcq.flush();
// Update allocation statistics.
_plab_allocator->flush_and_retire_stats();
_g1h->g1_policy()->record_age_table(&_age_table);
uint length = _g1h->g1_policy()->young_cset_region_length();
for (uint region_index = 0; region_index < length; region_index++) {
surviving_young_words[region_index] += _surviving_young_words[region_index];
}
}
G1ParScanThreadState::~G1ParScanThreadState() {
delete _plab_allocator;
_g1h->g1_policy()->record_thread_age_table(&_age_table);
// Update heap statistics.
_g1h->update_surviving_young_words(_surviving_young_words);
FREE_C_HEAP_ARRAY(size_t, _surviving_young_words_base);
}
@ -314,6 +322,42 @@ oop G1ParScanThreadState::copy_to_survivor_space(InCSetState const state,
}
}
G1ParScanThreadState* G1ParScanThreadStateSet::state_for_worker(uint worker_id) {
assert(worker_id < _n_workers, "out of bounds access");
return _states[worker_id];
}
void G1ParScanThreadStateSet::add_cards_scanned(uint worker_id, size_t cards_scanned) {
assert(worker_id < _n_workers, "out of bounds access");
_cards_scanned[worker_id] += cards_scanned;
}
size_t G1ParScanThreadStateSet::total_cards_scanned() const {
assert(_flushed, "thread local state from the per thread states should have been flushed");
return _total_cards_scanned;
}
const size_t* G1ParScanThreadStateSet::surviving_young_words() const {
assert(_flushed, "thread local state from the per thread states should have been flushed");
return _surviving_young_words_total;
}
void G1ParScanThreadStateSet::flush() {
assert(!_flushed, "thread local state from the per thread states should be flushed once");
assert(_total_cards_scanned == 0, "should have been cleared");
for (uint worker_index = 0; worker_index < _n_workers; ++worker_index) {
G1ParScanThreadState* pss = _states[worker_index];
_total_cards_scanned += _cards_scanned[worker_index];
pss->flush(_surviving_young_words_total);
delete pss;
_states[worker_index] = NULL;
}
_flushed = true;
}
oop G1ParScanThreadState::handle_evacuation_failure_par(oop old, markOop m) {
assert(_g1h->obj_in_cs(old),
err_msg("Object " PTR_FORMAT " should be in the CSet", p2i(old)));

View File

@ -82,7 +82,7 @@ class G1ParScanThreadState : public CHeapObj<mtGC> {
}
public:
G1ParScanThreadState(G1CollectedHeap* g1h, uint worker_id);
G1ParScanThreadState(G1CollectedHeap* g1h, uint worker_id, size_t young_cset_length);
~G1ParScanThreadState();
void set_ref_processor(ReferenceProcessor* rp) { _scanner.set_ref_processor(rp); }
@ -121,6 +121,8 @@ class G1ParScanThreadState : public CHeapObj<mtGC> {
return _surviving_young_words + 1;
}
void flush(size_t* surviving_young_words);
private:
#define G1_PARTIAL_ARRAY_MASK 0x2
@ -189,4 +191,48 @@ class G1ParScanThreadState : public CHeapObj<mtGC> {
oop handle_evacuation_failure_par(oop obj, markOop m);
};
class G1ParScanThreadStateSet : public StackObj {
G1CollectedHeap* _g1h;
G1ParScanThreadState** _states;
size_t* _surviving_young_words_total;
size_t* _cards_scanned;
size_t _total_cards_scanned;
uint _n_workers;
bool _flushed;
public:
G1ParScanThreadStateSet(G1CollectedHeap* g1h, uint n_workers, size_t young_cset_length) :
_g1h(g1h),
_states(NEW_C_HEAP_ARRAY(G1ParScanThreadState*, n_workers, mtGC)),
_surviving_young_words_total(NEW_C_HEAP_ARRAY(size_t, young_cset_length, mtGC)),
_cards_scanned(NEW_C_HEAP_ARRAY(size_t, n_workers, mtGC)),
_total_cards_scanned(0),
_n_workers(n_workers),
_flushed(false) {
for (uint i = 0; i < n_workers; ++i) {
_states[i] = new_par_scan_state(i, young_cset_length);
}
memset(_surviving_young_words_total, 0, young_cset_length * sizeof(size_t));
memset(_cards_scanned, 0, n_workers * sizeof(size_t));
}
~G1ParScanThreadStateSet() {
assert(_flushed, "thread local state from the per thread states should have been flushed");
FREE_C_HEAP_ARRAY(G1ParScanThreadState*, _states);
FREE_C_HEAP_ARRAY(size_t, _surviving_young_words_total);
FREE_C_HEAP_ARRAY(size_t, _cards_scanned);
}
void flush();
G1ParScanThreadState* state_for_worker(uint worker_id);
void add_cards_scanned(uint worker_id, size_t cards_scanned);
size_t total_cards_scanned() const;
const size_t* surviving_young_words() const;
private:
G1ParScanThreadState* new_par_scan_state(uint worker_id, size_t young_cset_length);
};
#endif // SHARE_VM_GC_G1_G1PARSCANTHREADSTATE_HPP

View File

@ -0,0 +1,31 @@
/*
* Copyright (c) 2015, 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.
*
*/
#include "precompiled.hpp"
#include "gc/g1/g1ParScanThreadState.hpp"
G1ParScanThreadState* G1ParScanThreadStateSet::new_par_scan_state(uint worker_id, size_t young_cset_length) {
return new G1ParScanThreadState(_g1h, worker_id, young_cset_length);
}

View File

@ -76,7 +76,6 @@ G1RemSet::G1RemSet(G1CollectedHeap* g1, CardTableModRefBS* ct_bs)
_ct_bs(ct_bs), _g1p(_g1->g1_policy()),
_cg1r(g1->concurrent_g1_refine()),
_cset_rs_update_cl(NULL),
_cards_scanned(NULL), _total_cards_scanned(0),
_prev_period_summary()
{
_cset_rs_update_cl = NEW_C_HEAP_ARRAY(G1ParPushHeapRSClosure*, n_workers(), mtGC);
@ -228,9 +227,9 @@ public:
size_t cards_looked_up() { return _cards;}
};
void G1RemSet::scanRS(G1ParPushHeapRSClosure* oc,
OopClosure* non_heap_roots,
uint worker_i) {
size_t G1RemSet::scanRS(G1ParPushHeapRSClosure* oc,
OopClosure* non_heap_roots,
uint worker_i) {
double rs_time_start = os::elapsedTime();
G1CodeBlobClosure code_root_cl(non_heap_roots);
@ -246,11 +245,10 @@ void G1RemSet::scanRS(G1ParPushHeapRSClosure* oc,
double scan_rs_time_sec = (os::elapsedTime() - rs_time_start)
- scanRScl.strong_code_root_scan_time_sec();
assert(_cards_scanned != NULL, "invariant");
_cards_scanned[worker_i] = scanRScl.cards_done();
_g1p->phase_times()->record_time_secs(G1GCPhaseTimes::ScanRS, worker_i, scan_rs_time_sec);
_g1p->phase_times()->record_time_secs(G1GCPhaseTimes::CodeRoots, worker_i, scanRScl.strong_code_root_scan_time_sec());
return scanRScl.cards_done();
}
// Closure used for updating RSets and recording references that
@ -298,9 +296,9 @@ void G1RemSet::cleanupHRRS() {
HeapRegionRemSet::cleanup();
}
void G1RemSet::oops_into_collection_set_do(G1ParPushHeapRSClosure* oc,
OopClosure* non_heap_roots,
uint worker_i) {
size_t G1RemSet::oops_into_collection_set_do(G1ParPushHeapRSClosure* oc,
OopClosure* non_heap_roots,
uint worker_i) {
#if CARD_REPEAT_HISTO
ct_freq_update_histo_and_reset();
#endif
@ -322,10 +320,11 @@ void G1RemSet::oops_into_collection_set_do(G1ParPushHeapRSClosure* oc,
DirtyCardQueue into_cset_dcq(&_g1->into_cset_dirty_card_queue_set());
updateRS(&into_cset_dcq, worker_i);
scanRS(oc, non_heap_roots, worker_i);
size_t cards_scanned = scanRS(oc, non_heap_roots, worker_i);
// We now clear the cached values of _cset_rs_update_cl for this worker
_cset_rs_update_cl[worker_i] = NULL;
return cards_scanned;
}
void G1RemSet::prepare_for_oops_into_collection_set_do() {
@ -333,23 +332,9 @@ void G1RemSet::prepare_for_oops_into_collection_set_do() {
_g1->set_refine_cte_cl_concurrency(false);
DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
dcqs.concatenate_logs();
guarantee( _cards_scanned == NULL, "invariant" );
_cards_scanned = NEW_C_HEAP_ARRAY(size_t, n_workers(), mtGC);
for (uint i = 0; i < n_workers(); ++i) {
_cards_scanned[i] = 0;
}
_total_cards_scanned = 0;
}
void G1RemSet::cleanup_after_oops_into_collection_set_do() {
guarantee( _cards_scanned != NULL, "invariant" );
_total_cards_scanned = 0;
for (uint i = 0; i < n_workers(); ++i) {
_total_cards_scanned += _cards_scanned[i];
}
FREE_C_HEAP_ARRAY(size_t, _cards_scanned);
_cards_scanned = NULL;
// Cleanup after copy
_g1->set_refine_cte_cl_concurrency(true);
// Set all cards back to clean.

View File

@ -62,9 +62,6 @@ protected:
ConcurrentG1Refine* _cg1r;
size_t* _cards_scanned;
size_t _total_cards_scanned;
// Used for caching the closure that is responsible for scanning
// references into the collection set.
G1ParPushHeapRSClosure** _cset_rs_update_cl;
@ -94,9 +91,12 @@ public:
// partitioning the work to be done. It should be the same as
// the "i" passed to the calling thread's work(i) function.
// In the sequential case this param will be ignored.
void oops_into_collection_set_do(G1ParPushHeapRSClosure* blk,
OopClosure* non_heap_roots,
uint worker_i);
//
// Returns the number of cards scanned while looking for pointers
// into the collection set.
size_t oops_into_collection_set_do(G1ParPushHeapRSClosure* blk,
OopClosure* non_heap_roots,
uint worker_i);
// Prepare for and cleanup after an oops_into_collection_set_do
// call. Must call each of these once before and after (in sequential
@ -106,14 +106,13 @@ public:
void prepare_for_oops_into_collection_set_do();
void cleanup_after_oops_into_collection_set_do();
void scanRS(G1ParPushHeapRSClosure* oc,
OopClosure* non_heap_roots,
uint worker_i);
size_t scanRS(G1ParPushHeapRSClosure* oc,
OopClosure* non_heap_roots,
uint worker_i);
void updateRS(DirtyCardQueue* into_cset_dcq, uint worker_i);
CardTableModRefBS* ct_bs() { return _ct_bs; }
size_t cardsScanned() { return _total_cards_scanned; }
// Record, if necessary, the fact that *p (where "p" is in region "from",
// which is required to be non-NULL) has changed to a new non-NULL value.

View File

@ -87,7 +87,7 @@ class ParallelScavengeHeap : public CollectedHeap {
return CollectedHeap::ParallelScavengeHeap;
}
virtual CollectorPolicy* collector_policy() const { return (CollectorPolicy*) _collector_policy; }
virtual CollectorPolicy* collector_policy() const { return _collector_policy; }
static PSYoungGen* young_gen() { return _young_gen; }
static PSOldGen* old_gen() { return _old_gen; }

View File

@ -213,7 +213,7 @@ DefNewGeneration::DefNewGeneration(ReservedSpace rs,
_max_eden_size = size - (2*_max_survivor_size);
// allocate the performance counters
GenCollectorPolicy* gcp = (GenCollectorPolicy*)gch->collector_policy();
GenCollectorPolicy* gcp = gch->gen_policy();
// Generation counters -- generation 0, 3 subspaces
_gen_counters = new GenerationCounters("new", 0, 3,

View File

@ -57,8 +57,7 @@ TenuredGeneration::TenuredGeneration(ReservedSpace rs,
// initialize performance counters
const char* gen_name = "old";
GenCollectorPolicy* gcp = (GenCollectorPolicy*) GenCollectedHeap::heap()->collector_policy();
GenCollectorPolicy* gcp = GenCollectedHeap::heap()->gen_policy();
// Generation Counters -- generation 1, 1 subspace
_gen_counters = new GenerationCounters(gen_name, 1, 1,
gcp->min_old_size(), gcp->max_old_size(), &_virtual_space);

View File

@ -28,7 +28,6 @@
#include "gc/shared/collectorPolicy.hpp"
#include "gc/shared/gcPolicyCounters.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/atomic.inline.hpp"
#include "utilities/copy.hpp"
/* Copyright (c) 1992, 2015, Oracle and/or its affiliates, and Stanford University.
@ -73,12 +72,6 @@ void ageTable::merge(ageTable* subTable) {
}
}
void ageTable::merge_par(ageTable* subTable) {
for (int i = 0; i < table_size; i++) {
Atomic::add_ptr(subTable->sizes[i], &sizes[i]);
}
}
uint ageTable::compute_tenuring_threshold(size_t survivor_capacity, GCPolicyCounters* gc_counters) {
size_t desired_survivor_size = (size_t)((((double) survivor_capacity)*TargetSurvivorRatio)/100);
uint result;

View File

@ -68,7 +68,6 @@ class ageTable VALUE_OBJ_CLASS_SPEC {
// Merge another age table with the current one. Used
// for parallel young generation gc.
void merge(ageTable* subTable);
void merge_par(ageTable* subTable);
// calculate new tenuring threshold based on age information
uint compute_tenuring_threshold(size_t survivor_capacity, GCPolicyCounters* gc_counters);

View File

@ -447,14 +447,16 @@ void BlockOffsetArrayNonContigSpace::split_block(HeapWord* blk,
} else {
// Unilaterally fix the first (num_pref_cards - 1) following
// the "offset card" in the suffix block.
const size_t right_most_fixed_index = suff_index + num_pref_cards - 1;
set_remainder_to_point_to_start_incl(suff_index + 1,
suff_index + num_pref_cards - 1, true /* reducing */);
right_most_fixed_index, true /* reducing */);
// Fix the appropriate cards in the remainder of the
// suffix block -- these are the last num_pref_cards
// cards in each power block of the "new" range plumbed
// from suff_addr.
bool more = true;
uint i = 1;
// Fix the first power block with back_by > num_pref_cards.
while (more && (i < N_powers)) {
size_t back_by = power_to_cards_back(i);
size_t right_index = suff_index + back_by - 1;
@ -463,6 +465,9 @@ void BlockOffsetArrayNonContigSpace::split_block(HeapWord* blk,
right_index = end_index - 1;
more = false;
}
if (left_index <= right_most_fixed_index) {
left_index = right_most_fixed_index + 1;
}
if (back_by > num_pref_cards) {
// Fill in the remainder of this "power block", if it
// is non-null.
@ -471,12 +476,14 @@ void BlockOffsetArrayNonContigSpace::split_block(HeapWord* blk,
N_words + i - 1, true /* reducing */);
} else {
more = false; // we are done
assert((end_index - 1) == right_index, "Must be at the end.");
}
i++;
break;
}
i++;
}
// Fix the rest of the power blocks.
while (more && (i < N_powers)) {
size_t back_by = power_to_cards_back(i);
size_t right_index = suff_index + back_by - 1;

View File

@ -172,8 +172,6 @@ char* GenCollectedHeap::allocate(size_t alignment,
void GenCollectedHeap::post_initialize() {
CollectedHeap::post_initialize();
ref_processing_init();
GenCollectorPolicy *policy = (GenCollectorPolicy *)collector_policy();
guarantee(policy->is_generation_policy(), "Illegal policy type");
assert((_young_gen->kind() == Generation::DefNew) ||
(_young_gen->kind() == Generation::ParNew),
"Wrong youngest generation type");
@ -183,10 +181,10 @@ void GenCollectedHeap::post_initialize() {
_old_gen->kind() == Generation::MarkSweepCompact,
"Wrong generation kind");
policy->initialize_size_policy(def_new_gen->eden()->capacity(),
_old_gen->capacity(),
def_new_gen->from()->capacity());
policy->initialize_gc_policy_counters();
_gen_policy->initialize_size_policy(def_new_gen->eden()->capacity(),
_old_gen->capacity(),
def_new_gen->from()->capacity());
_gen_policy->initialize_gc_policy_counters();
}
void GenCollectedHeap::ref_processing_init() {
@ -822,10 +820,11 @@ bool GenCollectedHeap::create_cms_collector() {
"Unexpected generation kinds");
// Skip two header words in the block content verification
NOT_PRODUCT(_skip_header_HeapWords = CMSCollector::skip_header_HeapWords();)
CMSCollector* collector = new CMSCollector(
(ConcurrentMarkSweepGeneration*)_old_gen,
_rem_set->as_CardTableRS(),
(ConcurrentMarkSweepPolicy*) collector_policy());
assert(_gen_policy->is_concurrent_mark_sweep_policy(), "Unexpected policy type");
CMSCollector* collector =
new CMSCollector((ConcurrentMarkSweepGeneration*)_old_gen,
_rem_set->as_CardTableRS(),
_gen_policy->as_concurrent_mark_sweep_policy());
if (collector == NULL || !collector->completed_initialization()) {
if (collector) {

View File

@ -153,7 +153,7 @@ public:
// The generational collector policy.
GenCollectorPolicy* gen_policy() const { return _gen_policy; }
virtual CollectorPolicy* collector_policy() const { return (CollectorPolicy*) gen_policy(); }
virtual CollectorPolicy* collector_policy() const { return gen_policy(); }
// Adaptive size policy
virtual AdaptiveSizePolicy* size_policy() {

View File

@ -290,6 +290,7 @@ macro(MulVD)
macro(MulReductionVD)
macro(DivVF)
macro(DivVD)
macro(SqrtVD)
macro(LShiftCntV)
macro(RShiftCntV)
macro(LShiftVB)

View File

@ -858,18 +858,29 @@ bool IfNode::fold_compares_helper(ProjNode* proj, ProjNode* success, ProjNode* f
// this_bool = <=
// dom_bool = >= (proj = True) or dom_bool = < (proj = False)
// x in [a, b] on the fail (= True) projection, b+1 > a-1:
// lo = a, hi = b, adjusted_lim = b-a, cond = <=u
// lo = a, hi = b, adjusted_lim = b-a+1, cond = <u
// lo = a, hi = b, adjusted_lim = b-a, cond = <=u doesn't work because b = a - 1 is possible, then b-a = -1
// dom_bool = > (proj = True) or dom_bool = <= (proj = False)
// x in ]a, b] on the fail (= True) projection b+1 > a:
// lo = a+1, hi = b, adjusted_lim = b-a, cond = <u
// lo = a+1, hi = b, adjusted_lim = b-a-1, cond = <=u doesn't work because a = b is possible, then hi-lo = -1
// lo = a+1, hi = b, adjusted_lim = b-a-1, cond = <=u doesn't work because a = b is possible, then b-a-1 = -1
if (lo_test == BoolTest::gt || lo_test == BoolTest::le) {
if (hi_test == BoolTest::le) {
if (hi_test == BoolTest::lt) {
if (lo_test == BoolTest::gt || lo_test == BoolTest::le) {
lo = igvn->transform(new AddINode(lo, igvn->intcon(1)));
}
} else {
assert(hi_test == BoolTest::le, "bad test");
if (lo_test == BoolTest::ge || lo_test == BoolTest::lt) {
adjusted_lim = igvn->transform(new SubINode(hi, lo));
adjusted_lim = igvn->transform(new AddINode(adjusted_lim, igvn->intcon(1)));
cond = BoolTest::lt;
} else {
assert(lo_test == BoolTest::gt || lo_test == BoolTest::le, "bad test");
adjusted_lim = igvn->transform(new SubINode(hi, lo));
lo = igvn->transform(new AddINode(lo, igvn->intcon(1)));
cond = BoolTest::lt;
}
lo = igvn->transform(new AddINode(lo, igvn->intcon(1)));
}
} else if (lo_type->_lo > hi_type->_hi && lo_type->_hi == max_jint && hi_type->_lo == min_jint) {
@ -879,7 +890,8 @@ bool IfNode::fold_compares_helper(ProjNode* proj, ProjNode* success, ProjNode* f
// lo = b, hi = a, adjusted_lim = a-b, cond = >=u
// dom_bool = <= (proj = True) or dom_bool = > (proj = False)
// x in [b, a] on the fail (= False) projection, a+1 > b-1:
// lo = b, hi = a, adjusted_lim = a-b, cond = >u
// lo = b, hi = a, adjusted_lim = a-b+1, cond = >=u
// lo = b, hi = a, adjusted_lim = a-b, cond = >u doesn't work because a = b - 1 is possible, then b-a = -1
// this_bool = <=
// dom_bool = < (proj = True) or dom_bool = >= (proj = False)
// x in ]b, a[ on the fail (= False) projection, a > b:
@ -887,7 +899,7 @@ bool IfNode::fold_compares_helper(ProjNode* proj, ProjNode* success, ProjNode* f
// dom_bool = <= (proj = True) or dom_bool = > (proj = False)
// x in ]b, a] on the fail (= False) projection, a+1 > b:
// lo = b+1, hi = a, adjusted_lim = a-b, cond = >=u
// lo = b+1, hi = a, adjusted_lim = a-b-1, cond = >u doesn't work because a = b is possible, then hi-lo = -1
// lo = b+1, hi = a, adjusted_lim = a-b-1, cond = >u doesn't work because a = b is possible, then b-a-1 = -1
swap(lo, hi);
swap(lo_type, hi_type);
@ -900,14 +912,26 @@ bool IfNode::fold_compares_helper(ProjNode* proj, ProjNode* success, ProjNode* f
cond = (hi_test == BoolTest::le || hi_test == BoolTest::gt) ? BoolTest::gt : BoolTest::ge;
if (lo_test == BoolTest::le) {
if (cond == BoolTest::gt) {
if (lo_test == BoolTest::lt) {
if (hi_test == BoolTest::lt || hi_test == BoolTest::ge) {
cond = BoolTest::ge;
} else {
assert(hi_test == BoolTest::le || hi_test == BoolTest::gt, "bad test");
adjusted_lim = igvn->transform(new SubINode(hi, lo));
adjusted_lim = igvn->transform(new AddINode(adjusted_lim, igvn->intcon(1)));
cond = BoolTest::ge;
}
} else if (lo_test == BoolTest::le) {
if (hi_test == BoolTest::lt || hi_test == BoolTest::ge) {
lo = igvn->transform(new AddINode(lo, igvn->intcon(1)));
cond = BoolTest::ge;
} else {
assert(hi_test == BoolTest::le || hi_test == BoolTest::gt, "bad test");
adjusted_lim = igvn->transform(new SubINode(hi, lo));
lo = igvn->transform(new AddINode(lo, igvn->intcon(1)));
cond = BoolTest::ge;
}
lo = igvn->transform(new AddINode(lo, igvn->intcon(1)));
}
} else {
const TypeInt* failtype = filtered_int_type(igvn, n, proj);
if (failtype != NULL) {

View File

@ -112,6 +112,13 @@ ProjNode* PhaseIdealLoop::create_new_if_for_predicate(ProjNode* cont_proj, Node*
if (_idom != NULL) {
set_idom(call, rgn, dom_depth(rgn));
}
for (DUIterator_Fast imax, i = uncommon_proj->fast_outs(imax); i < imax; i++) {
Node* n = uncommon_proj->fast_out(i);
if (n->is_Load() || n->is_Store()) {
_igvn.replace_input_of(n, 0, rgn);
--i; --imax;
}
}
} else {
// Find region's edge corresponding to uncommon_proj
for (; proj_index < rgn->req(); proj_index++)

View File

@ -1901,7 +1901,7 @@ void IdealLoopTree::dump_head( ) const {
if (stride_con > 0) tty->print("+");
tty->print("%d", stride_con);
tty->print(" (%d iters) ", (int)cl->profile_trip_cnt());
tty->print(" (%0.f iters) ", cl->profile_trip_cnt());
if (cl->is_pre_loop ()) tty->print(" pre" );
if (cl->is_main_loop()) tty->print(" main");

View File

@ -1858,6 +1858,11 @@ void SuperWord::output() {
vn = VectorNode::make(opc, in1, in2, vlen, velt_basic_type(n));
vlen_in_bytes = vn->as_Vector()->length_in_bytes();
}
} else if (opc == Op_SqrtD) {
// Promote operand to vector (Sqrt is a 2 address instruction)
Node* in = vector_opd(p, 1);
vn = VectorNode::make(opc, in, NULL, vlen, velt_basic_type(n));
vlen_in_bytes = vn->as_Vector()->length_in_bytes();
} else {
ShouldNotReachHere();
}

View File

@ -92,6 +92,9 @@ int VectorNode::opcode(int sopc, BasicType bt) {
case Op_DivD:
assert(bt == T_DOUBLE, "must be");
return Op_DivVD;
case Op_SqrtD:
assert(bt == T_DOUBLE, "must be");
return Op_SqrtVD;
case Op_LShiftI:
switch (bt) {
case T_BOOLEAN:
@ -277,6 +280,9 @@ VectorNode* VectorNode::make(int opc, Node* n1, Node* n2, uint vlen, BasicType b
case Op_DivVF: return new DivVFNode(n1, n2, vt);
case Op_DivVD: return new DivVDNode(n1, n2, vt);
// Currently only supports double precision sqrt
case Op_SqrtVD: return new SqrtVDNode(n1, vt);
case Op_LShiftVB: return new LShiftVBNode(n1, n2, vt);
case Op_LShiftVS: return new LShiftVSNode(n1, n2, vt);
case Op_LShiftVI: return new LShiftVINode(n1, n2, vt);

View File

@ -309,6 +309,14 @@ class DivVDNode : public VectorNode {
virtual int Opcode() const;
};
//------------------------------SqrtVDNode--------------------------------------
// Vector Sqrt double
class SqrtVDNode : public VectorNode {
public:
SqrtVDNode(Node* in, const TypeVect* vt) : VectorNode(in,vt) {}
virtual int Opcode() const;
};
//------------------------------LShiftVBNode-----------------------------------
// Vector left shift bytes
class LShiftVBNode : public VectorNode {

View File

@ -1041,11 +1041,18 @@ CodeBlob* WhiteBox::allocate_code_blob(int size, int blob_type) {
}
WB_ENTRY(jlong, WB_AllocateCodeBlob(JNIEnv* env, jobject o, jint size, jint blob_type))
return (jlong) WhiteBox::allocate_code_blob(size, blob_type);
if (size < 0) {
THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("WB_AllocateCodeBlob: size is negative: " INT32_FORMAT, size));
}
return (jlong) WhiteBox::allocate_code_blob(size, blob_type);
WB_END
WB_ENTRY(void, WB_FreeCodeBlob(JNIEnv* env, jobject o, jlong addr))
BufferBlob::free((BufferBlob*) addr);
if (addr == 0) {
return;
}
BufferBlob::free((BufferBlob*) addr);
WB_END
WB_ENTRY(jobjectArray, WB_GetCodeHeapEntries(JNIEnv* env, jobject o, jint blob_type))
@ -1090,9 +1097,13 @@ WB_ENTRY(jint, WB_GetCompilationActivityMode(JNIEnv* env, jobject o))
WB_END
WB_ENTRY(jobjectArray, WB_GetCodeBlob(JNIEnv* env, jobject o, jlong addr))
ThreadToNativeFromVM ttn(thread);
CodeBlobStub stub((CodeBlob*) addr);
return codeBlob2objectArray(thread, env, &stub);
if (addr == 0) {
THROW_MSG_NULL(vmSymbols::java_lang_NullPointerException(),
"WB_GetCodeBlob: addr is null");
}
ThreadToNativeFromVM ttn(thread);
CodeBlobStub stub((CodeBlob*) addr);
return codeBlob2objectArray(thread, env, &stub);
WB_END
WB_ENTRY(jlong, WB_GetThreadStackSize(JNIEnv* env, jobject o))

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2015, 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
@ -200,9 +200,10 @@ SensorInfo::SensorInfo() {
// any clears unless the usage becomes greater than or equal
// to the high threshold.
//
// If the current level is between high and low threhsold, no change.
// If the current level is between high and low threshold, no change.
//
void SensorInfo::set_gauge_sensor_level(MemoryUsage usage, ThresholdSupport* high_low_threshold) {
assert(Service_lock->owned_by_self(), "Must own Service_lock");
assert(high_low_threshold->is_high_threshold_supported(), "just checking");
bool is_over_high = high_low_threshold->is_high_threshold_crossed(usage);
@ -257,6 +258,7 @@ void SensorInfo::set_gauge_sensor_level(MemoryUsage usage, ThresholdSupport* hig
// the sensor will be on (i.e. sensor is currently off
// and has pending trigger requests).
void SensorInfo::set_counter_sensor_level(MemoryUsage usage, ThresholdSupport* counter_threshold) {
assert(Service_lock->owned_by_self(), "Must own Service_lock");
assert(counter_threshold->is_high_threshold_supported(), "just checking");
bool is_over_high = counter_threshold->is_high_threshold_crossed(usage);
@ -278,9 +280,7 @@ void SensorInfo::oops_do(OopClosure* f) {
}
void SensorInfo::process_pending_requests(TRAPS) {
if (!has_pending_requests()) {
return;
}
assert(has_pending_requests(), "Must have pending request");
int pending_count = pending_trigger_count();
if (pending_clear_count() > 0) {
@ -293,7 +293,6 @@ void SensorInfo::process_pending_requests(TRAPS) {
void SensorInfo::trigger(int count, TRAPS) {
assert(count <= _pending_trigger_count, "just checking");
if (_sensor_obj != NULL) {
Klass* k = Management::sun_management_Sensor_klass(CHECK);
instanceKlassHandle sensorKlass (THREAD, k);
@ -316,6 +315,7 @@ void SensorInfo::trigger(int count, TRAPS) {
{
// Holds Service_lock and update the sensor state
MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
assert(_pending_trigger_count > 0, "Must have pending trigger");
_sensor_on = true;
_sensor_count += count;
_pending_trigger_count = _pending_trigger_count - count;
@ -323,6 +323,20 @@ void SensorInfo::trigger(int count, TRAPS) {
}
void SensorInfo::clear(int count, TRAPS) {
{
// Holds Service_lock and update the sensor state
MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
if (_pending_clear_count == 0) {
// Bail out if we lost a race to set_*_sensor_level() which may have
// reactivated the sensor in the meantime because it was triggered again.
return;
}
_sensor_on = false;
_sensor_count += count;
_pending_clear_count = 0;
_pending_trigger_count = _pending_trigger_count - count;
}
if (_sensor_obj != NULL) {
Klass* k = Management::sun_management_Sensor_klass(CHECK);
instanceKlassHandle sensorKlass (THREAD, k);
@ -338,14 +352,6 @@ void SensorInfo::clear(int count, TRAPS) {
&args,
CHECK);
}
{
// Holds Service_lock and update the sensor state
MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
_sensor_on = false;
_pending_clear_count = 0;
_pending_trigger_count = _pending_trigger_count - count;
}
}
//--------------------------------------------------------------

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2015, 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
@ -180,7 +180,7 @@ public:
// any clears unless the usage becomes greater than or equal
// to the high threshold.
//
// If the current level is between high and low threhsold, no change.
// If the current level is between high and low threshold, no change.
//
void set_gauge_sensor_level(MemoryUsage usage, ThresholdSupport* high_low_threshold);

View File

@ -0,0 +1,53 @@
/*
* Copyright (c) 2015, 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
* @bug 8134974
* @summary Cannot pin eliminated arraycopy loads for deopt state in uncommon trap path if it is a loop predicate unc
* @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestEliminatedArrayLoopPredicateCopyDeopt
*
*/
public class TestEliminatedArrayLoopPredicateCopyDeopt {
static boolean test(int[] array_src) {
int[] array_dst = new int[10];
System.arraycopy(array_src, 0, array_dst, 0, 10);
for (int i = 0; i < 100; i++) {
array_src[i] = i;
}
if (array_dst[0] == 0) {
return true;
}
return false;
}
static public void main(String[] args) {
int[] array_src = new int[100];
for (int i = 0; i < 20000; i++) {
test(array_src);
}
}
}

View File

@ -0,0 +1,95 @@
/*
* Copyright (c) 2014, 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
* @summary Add C2 x86 Superword support for scalar sum reduction optimizations : double sqrt test
*
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=2 -XX:CompileThresholdScaling=0.1 SumRedSqrt_Double
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=2 -XX:CompileThresholdScaling=0.1 SumRedSqrt_Double
*
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=4 -XX:CompileThresholdScaling=0.1 SumRedSqrt_Double
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=4 -XX:CompileThresholdScaling=0.1 SumRedSqrt_Double
*
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=8 -XX:CompileThresholdScaling=0.1 SumRedSqrt_Double
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=8 -XX:CompileThresholdScaling=0.1 SumRedSqrt_Double
*
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=16 -XX:CompileThresholdScaling=0.1 SumRedSqrt_Double
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=16 -XX:CompileThresholdScaling=0.1 SumRedSqrt_Double
*/
public class SumRedSqrt_Double
{
public static void main(String[] args) throws Exception {
double[] a = new double[256*1024];
double[] b = new double[256*1024];
double[] c = new double[256*1024];
double[] d = new double[256*1024];
sumReductionInit(a,b,c);
double total = 0;
double valid = 2.06157643776E14;
for(int j = 0; j < 2000; j++) {
total = sumReductionImplement(a,b,c,d,total);
}
if(total == valid) {
System.out.println("Success");
} else {
System.out.println("Invalid sum of elements variable in total: " + total);
System.out.println("Expected value = " + valid);
throw new Exception("Failed");
}
}
public static void sumReductionInit(
double[] a,
double[] b,
double[] c)
{
for(int j = 0; j < 1; j++)
{
for(int i = 0; i < a.length; i++)
{
a[i] = i * 1 + j;
b[i] = i * 1 - j;
c[i] = i + j;
}
}
}
public static double sumReductionImplement(
double[] a,
double[] b,
double[] c,
double[] d,
double total)
{
for(int i = 0; i < a.length; i++)
{
d[i]= Math.sqrt(a[i] * b[i]) + Math.sqrt(a[i] * c[i]) + Math.sqrt(b[i] * c[i]);
total += d[i];
}
return total;
}
}

View File

@ -24,7 +24,8 @@
/*
* @test
* @bug 8085832
* @summary x <= 0 || x > 0 wrongly folded as (x-1) >u -1
* @bug 8135069
* @summary x <= 0 || x > 0 wrongly folded as (x-1) >u -1 and x < 0 || x > -1 wrongly folded as x >u -1
* @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestBadFoldCompare
*/
@ -58,6 +59,34 @@ public class TestBadFoldCompare {
helper2(i, 0, 0, flag);
}
static boolean test3_taken;
static void helper3(int i, int a, int b, boolean flag) {
if (flag) {
if (i < a || i > b - 1) {
test3_taken = true;
}
}
}
static void test3(int i, boolean flag) {
helper3(i, 0, 0, flag);
}
static boolean test4_taken;
static void helper4(int i, int a, int b, boolean flag) {
if (flag) {
if (i > b - 1 || i < a) {
test4_taken = true;
}
}
}
static void test4(int i, boolean flag) {
helper4(i, 0, 0, flag);
}
static public void main(String[] args) {
boolean success = true;
@ -87,6 +116,35 @@ public class TestBadFoldCompare {
System.out.println("Test2 failed");
success = false;
}
for (int i = 0; i < 20000; i++) {
helper3(5, 0, 10, (i%2)==0);
helper3(-1, 0, 10, (i%2)==0);
helper3(15, 0, 10, (i%2)==0);
test3(0, false);
}
test3_taken = false;
test3(0, true);
if (!test3_taken) {
System.out.println("Test3 failed");
success = false;
}
for (int i = 0; i < 20000; i++) {
helper4(5, 0, 10, (i%2)==0);
helper4(-1, 0, 10, (i%2)==0);
helper4(15, 0, 10, (i%2)==0);
test4(0, false);
}
test4_taken = false;
test4(0, true);
if (!test4_taken) {
System.out.println("Test4 failed");
success = false;
}
if (!success) {
throw new RuntimeException("Some tests failed");
}

View File

@ -56,11 +56,11 @@ import sun.hotspot.WhiteBox;
* gc.g1.humongousObjects.TestHumongousThreshold
*
* @run main/othervm -XX:+UseG1GC -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
* -XX:G1HeapRegionSize=16M
* -Xms128M -XX:G1HeapRegionSize=16M
* gc.g1.humongousObjects.TestHumongousThreshold
*
* @run main/othervm -XX:+UseG1GC -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
* -XX:G1HeapRegionSize=32M
* -Xms200M -XX:G1HeapRegionSize=32M
* gc.g1.humongousObjects.TestHumongousThreshold
*
*/

View File

@ -90,6 +90,9 @@ public class CodelistTest {
if (methodPrintedInLogFormat.contains("MethodHandle")) {
continue;
}
if (methodPrintedInLogFormat.contains("sun.misc.Unsafe.getUnsafe")) {
continue;
}
MethodIdentifierParser mf = new MethodIdentifierParser(methodPrintedInLogFormat);
Method m = null;

View File

@ -428,4 +428,28 @@ public final class Utils {
public static long adjustTimeout(long tOut) {
return Math.round(tOut * Utils.TIMEOUT_FACTOR);
}
/**
* Runs runnable and checks that it throws expected exception. If exceptionException is null it means
* that we expect no exception to be thrown.
* @param runnable what we run
* @param expectedException expected exception
*/
public static void runAndCheckException(Runnable runnable, Class<? extends Throwable> expectedException) {
try {
runnable.run();
if (expectedException != null) {
throw new AssertionError("Didn't get expected exception " + expectedException.getSimpleName());
}
} catch (Throwable t) {
if (expectedException == null) {
throw new AssertionError("Got unexpected exception ", t);
}
if (!expectedException.isAssignableFrom(t.getClass())) {
throw new AssertionError(String.format("Got unexpected exception %s instead of %s",
t.getClass().getSimpleName(), expectedException.getSimpleName()), t);
}
}
}
}

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2015, 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 BlobSanityTest
* @bug 8132980
* @library /testlibrary /../../test/lib
* @modules java.management/sun.management
* @build BlobSanityTest
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI BlobSanityTest
* @summary sanity testing of allocateCodeBlob, freeCodeBlob and getCodeBlob
*/
import sun.hotspot.WhiteBox;
import java.util.function.Consumer;
import jdk.test.lib.Utils;
public class BlobSanityTest {
private static void runTest(Consumer<Integer> consumer, int val, String testCaseName, Class<? extends Throwable>
expectedException) {
System.out.println("Calling " + testCaseName);
Utils.runAndCheckException(() -> consumer.accept(val), expectedException);
System.out.println("Looks ok");
}
public static void main(String[] args) throws Exception {
System.out.println("Crash means that sanity check failed");
WhiteBox wb = WhiteBox.getWhiteBox();
runTest(wb::freeCodeBlob, 0, "wb::freeCodeBlob(0)", null);
runTest(wb::getCodeBlob, 0, "wb::getCodeBlob(0)", NullPointerException.class);
runTest(x -> wb.allocateCodeBlob(x, 0), -1, "wb::allocateCodeBlob(-1,0)", IllegalArgumentException.class);
}
}

View File

@ -325,3 +325,4 @@ cf809edc840ff7546677d38b13ebd8b3cae2bbda jdk9-b79
f464f9b2fb1178f6a957e5730b4b5252c6149ed9 jdk9-b80
6a418934997fc4b56664b88f8417e2f0fe658091 jdk9-b81
53fe3c103b6fdf48e2b2676c0c4818ef5a10fa21 jdk9-b82
497bc2654e11684b11de46744227883d7e760f35 jdk9-b83

View File

@ -0,0 +1,103 @@
/*
* 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.
*/
/*
* Copyright (c) 2015 World Wide Web Consortium,
*
* (Massachusetts Institute of Technology, European Research Consortium for
* Informatics and Mathematics, Keio University, Beihang). All Rights Reserved.
* This work is distributed under the W3C(r) Software License [1] 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.
*
* [1] http://www.w3.org/Consortium/Legal/copyright-software
*/
package org.w3c.dom;
/**
* The {@code ElementTraversal} interface is a set of read-only attributes
* which allow an author to easily navigate between elements in a document.
* <p>
* In conforming implementations of Element Traversal, all objects that
* implement {@link Element} must also implement the {@code ElementTraversal}
* interface. Four of the methods,
* {@link #getFirstElementChild}, {@link #getLastElementChild},
* {@link #getPreviousElementSibling}, and {@link #getNextElementSibling},
* each provides a live reference to another element with the defined
* relationship to the current element, if the related element exists. The
* fifth method, {@link #getChildElementCount}, exposes the number of child
* elements of an element, for preprocessing before navigation.
*
* @see
* <a href='http://www.w3.org/TR/ElementTraversal/'><cite>Element Traversal Specification</cite></a>.
*
* @since 9
*/
public interface ElementTraversal {
/**
* Returns a reference to the first child node of the element which is of
* the {@link Element} type.
*
* @return a reference to an element child, {@code null} if the element has
* no child of the {@link Element} type.
*/
Element getFirstElementChild();
/**
* Returns a reference to the last child node of the element which is of
* the {@link Element} type.
*
* @return a reference to an element child, {@code null} if the element has
* no child of the {@link Element} type.
*/
Element getLastElementChild();
/**
* Returns a reference to the sibling node of the element which most immediately
* precedes the element in document order, and which is of the {@link Element} type.
*
* @return a reference to an element child, {@code null} if the element has
* no sibling node of the {@link Element} type that comes before this one.
*/
Element getPreviousElementSibling();
/**
* Returns a reference to the sibling node of the element which most immediately
* follows the element in document order, and which is of the {@link Element} type.
*
* @return a reference to an element child, {@code null} if the element has
* no sibling node of the {@link Element} type that comes after this one.
*/
Element getNextElementSibling();
/**
* Returns the current number of child nodes of the element which are of
* the {@link Element} type.
*
* @return the number of element children, or {@code 0} if the element has
* no element children.
*/
int getChildElementCount();
}

View File

@ -0,0 +1,112 @@
/*
* Copyright (c) 2015, 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.
*/
package dom;
import java.io.IOException;
import java.io.InputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
/*
* @bug 8135283
* @summary Tests for the Element Traversal interface.
*/
public class ElementTraversal {
/*
Verifies the ElementTraversal interface by exercising all of its five
methods while reading through the xml document.
*/
@Test(dataProvider = "doc")
public void test(Document doc) {
org.w3c.dom.ElementTraversal et = (org.w3c.dom.ElementTraversal)doc.getDocumentElement();
//4 toys are listed
Assert.assertEquals(et.getChildElementCount(), 4);
//The 1st is the Martian
Element toy1 = et.getFirstElementChild();
verify(toy1, "1", "The Martian");
//toy1 has no previous element
Element noE = ((org.w3c.dom.ElementTraversal)toy1).getPreviousElementSibling();
Assert.assertEquals(noE, null);
//The 1st toy's next element is toy2, the Doll
Element toy2 = ((org.w3c.dom.ElementTraversal)toy1).getNextElementSibling();
verify(toy2, "2", "The Doll");
//The last toy is toy4, the Spaceship
Element toy4 = et.getLastElementChild();
verify(toy4, "4", "The Spaceship");
//toy4 has no next element
noE = ((org.w3c.dom.ElementTraversal)toy4).getNextElementSibling();
Assert.assertEquals(noE, null);
//toy4's previous element is toy3, Transformer X
//toy3 is also an EntityReference
Element toy3 = ((org.w3c.dom.ElementTraversal)toy4).getPreviousElementSibling();
verify(toy3, "3", "Transformer X");
}
/**
* Verifies that the values matches the specified element.
* @param id the value of the id attribute
* @param name the value of its name element
*/
void verify(Element e, String id, String name) {
Assert.assertEquals(e.getAttribute("id"), id);
Element toyName = ((org.w3c.dom.ElementTraversal)e).getFirstElementChild();
Assert.assertEquals(toyName.getTextContent(), name);
}
/*
* DataProvider: a Document object
*/
@DataProvider(name = "doc")
Object[][] getXPath() {
return new Object[][]{{getDoc()}};
}
Document getDoc() {
InputStream xmlFile = getClass().getResourceAsStream("ElementTraversal.xml");
Document doc = null;
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);
DocumentBuilder db = dbf.newDocumentBuilder();
doc = db.parse(xmlFile);
} catch (ParserConfigurationException | SAXException | IOException e) {
System.out.println("fail: " + e.getMessage());
}
return doc;
}
}

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE toys [
<!ENTITY toy3 "<name>Transformer X</name><price>519</price>">
]>
<toys>
<toy id="1">
<name>The Martian</name>
<price>98470</price>
</toy>
<toy id="2">
<name>The Doll</name>
<price>345</price>
</toy>
<toy id="3">
&toy3;
</toy>
<toy id="4">
<name>The Spaceship</name>
<price>725</price>
</toy>
</toys>

View File

@ -325,3 +325,4 @@ d99c2ffdd0f15753e69126583688f2f075a0a5e8 jdk9-b79
4947810137ae53abba3028cc366af953d90fa81a jdk9-b80
fdc13a2d32867ca3c57b7fa2620c6b59c83168cb jdk9-b81
b10b64263b563e21f055c881444f625ec618b826 jdk9-b82
d11f25ce3c545823f53bb978d454a4d2901abac3 jdk9-b83

View File

@ -157,7 +157,6 @@ SUNWprivate_1.1 {
Java_java_lang_StrictMath_cosh;
Java_java_lang_StrictMath_sinh;
Java_java_lang_StrictMath_tanh;
Java_java_lang_StrictMath_hypot;
Java_java_lang_StrictMath_log1p;
Java_java_lang_StrictMath_expm1;
Java_java_lang_Object_getClass;

View File

@ -26,7 +26,8 @@
package java.lang;
/**
* Port of the "Freely Distributable Math Library", version 5.3, from C to Java.
* Port of the "Freely Distributable Math Library", version 5.3, from
* C to Java.
*
* <p>The C version of fdlibm relied on the idiom of pointer aliasing
* a 64-bit double floating-point value as a two-element array of
@ -37,7 +38,7 @@ package java.lang;
* operated on as integer values, the standard library methods for
* bitwise floating-point to integer conversion,
* Double.longBitsToDouble and Double.doubleToRawLongBits, are directly
* or indirectly used .
* or indirectly used.
*
* <p>The C version of fdlibm also took some pains to signal the
* correct IEEE 754 exceptional conditions divide by zero, invalid,
@ -47,13 +48,21 @@ package java.lang;
* handling is not supported natively in the JVM, such coding patterns
* have been omitted from this port. For example, rather than {@code
* return huge * huge}, this port will use {@code return INFINITY}.
*
* <p>Various comparison and arithmetic operations in fdlibm could be
* done either based on the integer view of a value or directly on the
* floating-point representation. Which idiom is faster may depend on
* platform specific factors. However, for code clarity if no other
* reason, this port will favor expressing the semantics of those
* operations in terms of floating-point operations when convenient to
* do so.
*/
class FdLibm {
// Constants used by multiple algorithms
private static final double INFINITY = Double.POSITIVE_INFINITY;
private FdLibm() {
throw new UnsupportedOperationException("No instances for you.");
throw new UnsupportedOperationException("No FdLibm instances for you.");
}
/**
@ -90,6 +99,139 @@ class FdLibm {
return Double.longBitsToDouble((transX & 0x0000_0000_FFFF_FFFFL)|( ((long)high)) << 32 );
}
/**
* hypot(x,y)
*
* Method :
* If (assume round-to-nearest) z = x*x + y*y
* has error less than sqrt(2)/2 ulp, than
* sqrt(z) has error less than 1 ulp (exercise).
*
* So, compute sqrt(x*x + y*y) with some care as
* follows to get the error below 1 ulp:
*
* Assume x > y > 0;
* (if possible, set rounding to round-to-nearest)
* 1. if x > 2y use
* x1*x1 + (y*y + (x2*(x + x1))) for x*x + y*y
* where x1 = x with lower 32 bits cleared, x2 = x - x1; else
* 2. if x <= 2y use
* t1*y1 + ((x-y) * (x-y) + (t1*y2 + t2*y))
* where t1 = 2x with lower 32 bits cleared, t2 = 2x - t1,
* y1= y with lower 32 bits chopped, y2 = y - y1.
*
* NOTE: scaling may be necessary if some argument is too
* large or too tiny
*
* Special cases:
* hypot(x,y) is INF if x or y is +INF or -INF; else
* hypot(x,y) is NAN if x or y is NAN.
*
* Accuracy:
* hypot(x,y) returns sqrt(x^2 + y^2) with error less
* than 1 ulp (unit in the last place)
*/
public static class Hypot {
public static final double TWO_MINUS_600 = 0x1.0p-600;
public static final double TWO_PLUS_600 = 0x1.0p+600;
public static strictfp double compute(double x, double y) {
double a = Math.abs(x);
double b = Math.abs(y);
if (!Double.isFinite(a) || !Double.isFinite(b)) {
if (a == INFINITY || b == INFINITY)
return INFINITY;
else
return a + b; // Propagate NaN significand bits
}
if (b > a) {
double tmp = a;
a = b;
b = tmp;
}
assert a >= b;
// Doing bitwise conversion after screening for NaN allows
// the code to not worry about the possibility of
// "negative" NaN values.
// Note: the ha and hb variables are the high-order
// 32-bits of a and b stored as integer values. The ha and
// hb values are used first for a rough magnitude
// comparison of a and b and second for simulating higher
// precision by allowing a and b, respectively, to be
// decomposed into non-overlapping portions. Both of these
// uses could be eliminated. The magnitude comparison
// could be eliminated by extracting and comparing the
// exponents of a and b or just be performing a
// floating-point divide. Splitting a floating-point
// number into non-overlapping portions can be
// accomplished by judicious use of multiplies and
// additions. For details see T. J. Dekker, A Floating
// Point Technique for Extending the Available Precision ,
// Numerische Mathematik, vol. 18, 1971, pp.224-242 and
// subsequent work.
int ha = __HI(a); // high word of a
int hb = __HI(b); // high word of b
if ((ha - hb) > 0x3c00000) {
return a + b; // x / y > 2**60
}
int k = 0;
if (a > 0x1.0p500) { // a > 2**500
// scale a and b by 2**-600
ha -= 0x25800000;
hb -= 0x25800000;
a = a * TWO_MINUS_600;
b = b * TWO_MINUS_600;
k += 600;
}
double t1, t2;
if (b < 0x1.0p-500) { // b < 2**-500
if (b < Double.MIN_NORMAL) { // subnormal b or 0 */
if (b == 0.0)
return a;
t1 = 0x1.0p1022; // t1 = 2^1022
b *= t1;
a *= t1;
k -= 1022;
} else { // scale a and b by 2^600
ha += 0x25800000; // a *= 2^600
hb += 0x25800000; // b *= 2^600
a = a * TWO_PLUS_600;
b = b * TWO_PLUS_600;
k -= 600;
}
}
// medium size a and b
double w = a - b;
if (w > b) {
t1 = 0;
t1 = __HI(t1, ha);
t2 = a - t1;
w = Math.sqrt(t1*t1 - (b*(-b) - t2 * (a + t1)));
} else {
double y1, y2;
a = a + a;
y1 = 0;
y1 = __HI(y1, hb);
y2 = b - y1;
t1 = 0;
t1 = __HI(t1, ha + 0x00100000);
t2 = a - t1;
w = Math.sqrt(t1*y1 - (w*(-w) - (t1*y2 + t2*b)));
}
if (k != 0) {
return Math.powerOfTwoD(k) * w;
} else
return w;
}
}
/**
* Compute x**y
* n
@ -97,7 +239,7 @@ class FdLibm {
* 1. Compute and return log2(x) in two pieces:
* log2(x) = w1 + w2,
* where w1 has 53 - 24 = 29 bit trailing zeros.
* 2. Perform y*log2(x) = n+y' by simulating muti-precision
* 2. Perform y*log2(x) = n+y' by simulating multi-precision
* arithmetic, where |y'| <= 0.5.
* 3. Return x**y = 2**n*exp(y'*log2)
*

View File

@ -500,7 +500,8 @@ public abstract class Process {
/**
* Returns a snapshot of the direct children of the process.
* A process that is {@link #isAlive not alive} has zero children.
* The parent of a direct child process is the process.
* Typically, a process that is {@link #isAlive not alive} has no children.
* <p>
* <em>Note that processes are created and terminate asynchronously.
* There is no guarantee that a process is {@link #isAlive alive}.
@ -510,8 +511,8 @@ public abstract class Process {
* This implementation returns the direct children as:
* {@link #toHandle toHandle().children()}.
*
* @return a Stream of ProcessHandles for processes that are direct children
* of the process
* @return a sequential Stream of ProcessHandles for processes that are
* direct children of the process
* @throws UnsupportedOperationException if the Process implementation
* does not support this operation
* @throws SecurityException if a security manager has been installed and
@ -524,7 +525,9 @@ public abstract class Process {
/**
* Returns a snapshot of the direct and indirect children of the process.
* A process that is {@link #isAlive not alive} has zero children.
* An indirect child is one whose parent is either a direct child or
* another indirect child.
* Typically, a process that is {@link #isAlive not alive} has no children.
* <p>
* <em>Note that processes are created and terminate asynchronously.
* There is no guarantee that a process is {@link #isAlive alive}.
@ -534,8 +537,8 @@ public abstract class Process {
* This implementation returns all children as:
* {@link #toHandle toHandle().allChildren()}.
*
* @return a Stream of ProcessHandles for processes that are direct and
* indirect children of the process
* @return a sequential Stream of ProcessHandles for processes that are
* direct and indirect children of the process
* @throws UnsupportedOperationException if the Process implementation
* does not support this operation
* @throws SecurityException if a security manager has been installed and

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2015, 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
@ -33,7 +33,8 @@ import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.security.AccessController;
import java.security.PrivilegedAction;
/**
* This class is used to create operating system processes.
*
@ -445,6 +446,7 @@ public final class ProcessBuilder
* <ul>
* <li>the special value {@link #PIPE Redirect.PIPE}
* <li>the special value {@link #INHERIT Redirect.INHERIT}
* <li>the special value {@link #DISCARD Redirect.DISCARD}
* <li>a redirection to read from a file, created by an invocation of
* {@link Redirect#from Redirect.from(File)}
* <li>a redirection to write to a file, created by an invocation of
@ -459,6 +461,13 @@ public final class ProcessBuilder
* @since 1.7
*/
public abstract static class Redirect {
private static final File NULL_FILE = AccessController.doPrivileged(
(PrivilegedAction<File>) () -> {
return new File((System.getProperty("os.name")
.startsWith("Windows") ? "NUL" : "/dev/null"));
}
);
/**
* The type of a {@link Redirect}.
*/
@ -529,6 +538,28 @@ public final class ProcessBuilder
public Type type() { return Type.INHERIT; }
public String toString() { return type().toString(); }};
/**
* Indicates that subprocess output will be discarded.
* A typical implementation discards the output by writing to
* an operating system specific "null file".
*
* <p>It will always be true that
* <pre> {@code
* Redirect.DISCARD.file() the filename appropriate for the operating system
* and may be null &&
* Redirect.DISCARD.type() == Redirect.Type.WRITE &&
* Redirect.DISCARD.append() == false
* }</pre>
* @since 9
*/
public static final Redirect DISCARD = new Redirect() {
public Type type() { return Type.WRITE; }
public String toString() { return type().toString(); }
public File file() { return NULL_FILE; }
boolean append() { return false; }
};
/**
* Returns the {@link File} source or destination associated
* with this redirect, or {@code null} if there is no such file.

View File

@ -149,14 +149,15 @@ public interface ProcessHandle extends Comparable<ProcessHandle> {
/**
* Returns a snapshot of the current direct children of the process.
* A process that is {@link #isAlive not alive} has zero children.
* The {@link #parent} of a direct child process is the process.
* Typically, a process that is {@link #isAlive not alive} has no children.
* <p>
* <em>Note that processes are created and terminate asynchronously.
* There is no guarantee that a process is {@link #isAlive alive}.
* </em>
*
* @return a Stream of ProcessHandles for processes that are direct children
* of the process
* @return a sequential Stream of ProcessHandles for processes that are
* direct children of the process
* @throws SecurityException if a security manager has been installed and
* it denies RuntimePermission("manageProcess")
*/
@ -164,14 +165,16 @@ public interface ProcessHandle extends Comparable<ProcessHandle> {
/**
* Returns a snapshot of the current direct and indirect children of the process.
* A process that is {@link #isAlive not alive} has zero children.
* An indirect child is one whose parent is either a direct child or
* another indirect child.
* Typically, a process that is {@link #isAlive not alive} has no children.
* <p>
* <em>Note that processes are created and terminate asynchronously.
* There is no guarantee that a process is {@link #isAlive alive}.
* </em>
*
* @return a Stream of ProcessHandles for processes that are direct and
* indirect children of the process
* @return a sequential Stream of ProcessHandles for processes that are
* direct and indirect children of the process
* @throws SecurityException if a security manager has been installed and
* it denies RuntimePermission("manageProcess")
*/

View File

@ -1329,7 +1329,9 @@ public final class StrictMath {
* without intermediate overflow or underflow
* @since 1.5
*/
public static native double hypot(double x, double y);
public static double hypot(double x, double y) {
return FdLibm.Hypot.compute(x, y);
}
/**
* Returns <i>e</i><sup>x</sup>&nbsp;-1. Note that for values of

View File

@ -404,6 +404,14 @@ import jdk.internal.org.objectweb.asm.Type;
d = lookupCache(types);
// Class loading must have upgraded the cache.
assert(d != null && !d.isPlaceholder());
if (OBSERVE_BMH_SPECIES_CREATION) {
if (d == null) {
throw new IllegalStateException("d == null");
}
if (d.isPlaceholder()) {
throw new IllegalStateException("d is place holder");
}
}
return d;
}
static SpeciesData getForClass(String types, Class<? extends BoundMethodHandle> clazz) {
@ -415,6 +423,9 @@ import jdk.internal.org.objectweb.asm.Type;
if (d != null) return d;
d = new SpeciesData(types);
assert(d.isPlaceholder());
if (OBSERVE_BMH_SPECIES_CREATION && !d.isPlaceholder()) {
throw new IllegalStateException("d is not place holder");
}
CACHE.put(types, d);
return d;
}
@ -422,6 +433,15 @@ import jdk.internal.org.objectweb.asm.Type;
SpeciesData d2;
assert((d2 = CACHE.get(types)) == null || d2.isPlaceholder());
assert(!d.isPlaceholder());
if (OBSERVE_BMH_SPECIES_CREATION) {
d2 = CACHE.get(types);
if (d2 != null && !d2.isPlaceholder()) {
throw new IllegalStateException("non-null d2 is not place holder");
}
if (d.isPlaceholder()) {
throw new IllegalStateException("d is place holder");
}
}
CACHE.put(types, d);
return d;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2015, 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
@ -51,8 +51,12 @@ import sun.misc.Unsafe;
static final boolean PROFILE_GWT;
static final int CUSTOMIZE_THRESHOLD;
// This is a temporary property added for improved error reporting; it will
// be removed once it has served its purpose.
static final boolean OBSERVE_BMH_SPECIES_CREATION;
static {
final Object[] values = new Object[9];
final Object[] values = new Object[10];
AccessController.doPrivileged(new PrivilegedAction<>() {
public Void run() {
values[0] = Boolean.getBoolean("java.lang.invoke.MethodHandle.DEBUG_NAMES");
@ -64,6 +68,7 @@ import sun.misc.Unsafe;
values[6] = Integer.getInteger("java.lang.invoke.MethodHandle.PROFILE_LEVEL", 0);
values[7] = Boolean.parseBoolean(System.getProperty("java.lang.invoke.MethodHandle.PROFILE_GWT", "true"));
values[8] = Integer.getInteger("java.lang.invoke.MethodHandle.CUSTOMIZE_THRESHOLD", 127);
values[9] = Boolean.getBoolean("java.lang.invoke.MethodHandle.OBSERVE_BMH_SPECIES_CREATION");
return null;
}
});
@ -77,6 +82,8 @@ import sun.misc.Unsafe;
PROFILE_GWT = (Boolean) values[7];
CUSTOMIZE_THRESHOLD = (Integer) values[8];
OBSERVE_BMH_SPECIES_CREATION = (Boolean) values[9];
if (CUSTOMIZE_THRESHOLD < -1 || CUSTOMIZE_THRESHOLD > 127) {
throw newInternalError("CUSTOMIZE_THRESHOLD should be in [-1...127] range");
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2015, 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
@ -379,7 +379,7 @@ public enum Month implements TemporalAccessor, TemporalAdjuster {
//-----------------------------------------------------------------------
/**
* Returns the month-of-year that is the specified number of quarters after this one.
* Returns the month-of-year that is the specified number of months after this one.
* <p>
* The calculation rolls around the end of the year from December to January.
* The specified period may be negative.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2015, 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
@ -313,7 +313,7 @@ public final class TemporalAdjusters {
/**
* Returns the day-of-week in month adjuster, which returns a new date
* in the same month with the ordinal day-of-week.
* with the ordinal day-of-week based on the month.
* This is used for expressions like the 'second Tuesday in March'.
* <p>
* The ISO calendar system behaves as follows:<br>

View File

@ -825,7 +825,7 @@ public final class Locale implements Cloneable, Serializable {
* setDefault(Locale.Category, Locale) method.
*
* @param category - the specified category to get the default locale
* @throws NullPointerException - if category is null
* @throws NullPointerException if category is null
* @return the default locale for the specified Category for this instance
* of the Java Virtual Machine
* @see #setDefault(Locale.Category, Locale)
@ -954,9 +954,9 @@ public final class Locale implements Cloneable, Serializable {
*
* @param category - the specified category to set the default locale
* @param newLocale - the new default locale
* @throws SecurityException - if a security manager exists and its
* @throws SecurityException if a security manager exists and its
* checkPermission method doesn't allow the operation.
* @throws NullPointerException - if category and/or newLocale is null
* @throws NullPointerException if category and/or newLocale is null
* @see SecurityManager#checkPermission(java.security.Permission)
* @see PropertyPermission
* @see #getDefault(Locale.Category)

View File

@ -504,7 +504,7 @@ public final class Collectors {
*/
public static <T> Collector<T, ?, Long>
counting() {
return reducing(0L, e -> 1L, Long::sum);
return summingLong(e -> 1L);
}
/**

View File

@ -328,6 +328,7 @@ public class FileChannelImpl
int rv = -1;
long p = -1;
int ti = -1;
long rp = -1;
try {
begin();
ti = threads.add();
@ -363,8 +364,8 @@ public class FileChannelImpl
if (p > newSize)
p = newSize;
do {
rv = (int)position0(fd, p);
} while ((rv == IOStatus.INTERRUPTED) && isOpen());
rp = position0(fd, p);
} while ((rp == IOStatus.INTERRUPTED) && isOpen());
return this;
} finally {
threads.remove(ti);

View File

@ -70,20 +70,20 @@ public class CoreReflectionFactory implements GenericsFactory {
/**
* Factory for this class. Returns an instance of
* <tt>CoreReflectionFactory</tt> for the declaration and scope
* {@code CoreReflectionFactory} for the declaration and scope
* provided.
* This factory will produce reflective objects of the appropriate
* kind. Classes produced will be those that would be loaded by the
* defining class loader of the declaration <tt>d</tt> (if <tt>d</tt>
* defining class loader of the declaration {@code d} (if {@code d}
* is a type declaration, or by the defining loader of the declaring
* class of <tt>d</tt> otherwise.
* class of {@code d} otherwise.
* <p> Type variables will be created or lookup as necessary in the
* scope <tt> s</tt>.
* scope {@code s}.
* @param d - the generic declaration (class, interface, method or
* constructor) that this factory services
* @param s the scope in which the factory will allocate and search for
* type variables
* @return an instance of <tt>CoreReflectionFactory</tt>
* @return an instance of {@code CoreReflectionFactory}
*/
public static CoreReflectionFactory make(GenericDeclaration d, Scope s) {
return new CoreReflectionFactory(d, s);

View File

@ -47,32 +47,32 @@ import sun.reflect.generics.tree.FieldTypeSignature;
*/
public interface GenericsFactory {
/**
* Returns a new type variable declaration. Note that <tt>name</tt>
* may be empty (but not <tt>null</tt>). If <tt>bounds</tt> is
* empty, a bound of <tt>java.lang.Object</tt> is used.
* Returns a new type variable declaration. Note that {@code name}
* may be empty (but not {@code null}). If {@code bounds} is
* empty, a bound of {@code java.lang.Object} is used.
* @param name The name of the type variable
* @param bounds An array of abstract syntax trees representing
* the upper bound(s) on the type variable being declared
* @return a new type variable declaration
* @throws NullPointerException - if any of the actual parameters
* or any of the elements of <tt>bounds</tt> are <tt>null</tt>.
* @throws NullPointerException if any of the actual parameters
* or any of the elements of {@code bounds} are {@code null}.
*/
TypeVariable<?> makeTypeVariable(String name,
FieldTypeSignature[] bounds);
/**
* Returns an instance of the <tt>ParameterizedType</tt> interface
* Returns an instance of the {@code ParameterizedType} interface
* that corresponds to a generic type instantiation of the
* generic declaration <tt>declaration</tt> with actual type arguments
* <tt>typeArgs</tt>.
* If <tt>owner</tt> is <tt>null</tt>, the declaring class of
* <tt>declaration</tt> is used as the owner of this parameterized
* generic declaration {@code declaration} with actual type arguments
* {@code typeArgs}.
* If {@code owner} is {@code null}, the declaring class of
* {@code declaration} is used as the owner of this parameterized
* type.
* <p> This method throws a MalformedParameterizedTypeException
* under the following circumstances:
* If the type declaration does not represent a generic declaration
* (i.e., it is not an instance of <tt>GenericDeclaration</tt>).
* (i.e., it is not an instance of {@code GenericDeclaration}).
* If the number of actual type arguments (i.e., the size of the
* array <tt>typeArgs</tt>) does not correspond to the number of
* array {@code typeArgs}) does not correspond to the number of
* formal type arguments.
* If any of the actual type arguments is not an instance of the
* bounds on the corresponding formal.
@ -81,39 +81,39 @@ public interface GenericsFactory {
* @param typeArgs - the list of actual type arguments
* @return - a parameterized type representing the instantiation
* of the declaration with the actual type arguments
* @throws MalformedParameterizedTypeException - if the instantiation
* @throws MalformedParameterizedTypeException if the instantiation
* is invalid
* @throws NullPointerException - if any of <tt>declaration</tt>
* , <tt>typeArgs</tt>
* or any of the elements of <tt>typeArgs</tt> are <tt>null</tt>
* @throws NullPointerException if any of {@code declaration},
* {@code typeArgs}
* or any of the elements of {@code typeArgs} are {@code null}
*/
ParameterizedType makeParameterizedType(Type declaration,
Type[] typeArgs,
Type owner);
/**
* Returns the type variable with name <tt>name</tt>, if such
* Returns the type variable with name {@code name}, if such
* a type variable is declared in the
* scope used to create this factory.
* Returns <tt>null</tt> otherwise.
* Returns {@code null} otherwise.
* @param name - the name of the type variable to search for
* @return - the type variable with name <tt>name</tt>, or <tt>null</tt>
* @throws NullPointerException - if any of actual parameters are
* <tt>null</tt>
* @return - the type variable with name {@code name}, or {@code null}
* @throws NullPointerException if any of actual parameters are
* {@code null}
*/
TypeVariable<?> findTypeVariable(String name);
/**
* Returns a new wildcard type variable. If
* <tt>ubs</tt> is empty, a bound of <tt>java.lang.Object</tt> is used.
* {@code ubs} is empty, a bound of {@code java.lang.Object} is used.
* @param ubs An array of abstract syntax trees representing
* the upper bound(s) on the type variable being declared
* @param lbs An array of abstract syntax trees representing
* the lower bound(s) on the type variable being declared
* @return a new wildcard type variable
* @throws NullPointerException - if any of the actual parameters
* or any of the elements of <tt>ubs</tt> or <tt>lbs</tt>are
* <tt>null</tt>
* @throws NullPointerException if any of the actual parameters
* or any of the elements of {@code ubs} or {@code lbs} are
* {@code null}
*/
WildcardType makeWildcard(FieldTypeSignature[] ubs,
FieldTypeSignature[] lbs);
@ -127,64 +127,64 @@ public interface GenericsFactory {
* a MalformedParameterizedTypeException is thrown.
* @param componentType - the component type of the array
* @return a (possibly generic) array type.
* @throws MalformedParameterizedTypeException if <tt>componentType</tt>
* @throws MalformedParameterizedTypeException if {@code componentType}
* is a parameterized type with non-wildcard type arguments
* @throws NullPointerException - if any of the actual parameters
* are <tt>null</tt>
* @throws NullPointerException if any of the actual parameters
* are {@code null}
*/
Type makeArrayType(Type componentType);
/**
* Returns the reflective representation of type <tt>byte</tt>.
* @return the reflective representation of type <tt>byte</tt>.
* Returns the reflective representation of type {@code byte}.
* @return the reflective representation of type {@code byte}.
*/
Type makeByte();
/**
* Returns the reflective representation of type <tt>boolean</tt>.
* @return the reflective representation of type <tt>boolean</tt>.
* Returns the reflective representation of type {@code boolean}.
* @return the reflective representation of type {@code boolean}.
*/
Type makeBool();
/**
* Returns the reflective representation of type <tt>short</tt>.
* @return the reflective representation of type <tt>short</tt>.
* Returns the reflective representation of type {@code short}.
* @return the reflective representation of type {@code short}.
*/
Type makeShort();
/**
* Returns the reflective representation of type <tt>char</tt>.
* @return the reflective representation of type <tt>char</tt>.
* Returns the reflective representation of type {@code char}.
* @return the reflective representation of type {@code char}.
*/
Type makeChar();
/**
* Returns the reflective representation of type <tt>int</tt>.
* @return the reflective representation of type <tt>int</tt>.
* Returns the reflective representation of type {@code int}.
* @return the reflective representation of type {@code int}.
*/
Type makeInt();
/**
* Returns the reflective representation of type <tt>long</tt>.
* @return the reflective representation of type <tt>long</tt>.
* Returns the reflective representation of type {@code long}.
* @return the reflective representation of type {@code long}.
*/
Type makeLong();
/**
* Returns the reflective representation of type <tt>float</tt>.
* @return the reflective representation of type <tt>float</tt>.
* Returns the reflective representation of type {@code float}.
* @return the reflective representation of type {@code float}.
*/
Type makeFloat();
/**
* Returns the reflective representation of type <tt>double</tt>.
* @return the reflective representation of type <tt>double</tt>.
* Returns the reflective representation of type {@code double}.
* @return the reflective representation of type {@code double}.
*/
Type makeDouble();
/**
* Returns the reflective representation of <tt>void</tt>.
* @return the reflective representation of <tt>void</tt>.
* Returns the reflective representation of {@code void}.
* @return the reflective representation of {@code void}.
*/
Type makeVoid();
}

View File

@ -135,7 +135,7 @@ public class SignatureParser {
/**
* Static factory method. Produces a parser instance.
* @return an instance of <tt>SignatureParser</tt>
* @return an instance of {@code SignatureParser}
*/
public static SignatureParser make() {
return new SignatureParser();

View File

@ -53,10 +53,10 @@ public class GenericArrayTypeImpl
/**
* Returns a <tt>Type</tt> object representing the component type
* Returns a {@code Type} object representing the component type
* of this array.
*
* @return a <tt>Type</tt> object representing the component type
* @return a {@code Type} object representing the component type
* of this array
* @since 1.5
*/

View File

@ -46,7 +46,7 @@ import sun.reflect.generics.visitor.Reifier;
import sun.reflect.misc.ReflectUtil;
/**
* Implementation of <tt>java.lang.reflect.TypeVariable</tt> interface
* Implementation of {@code java.lang.reflect.TypeVariable} interface
* for core reflection.
*/
public class TypeVariableImpl<D extends GenericDeclaration>
@ -99,9 +99,9 @@ public class TypeVariableImpl<D extends GenericDeclaration>
/**
* Returns an array of <tt>Type</tt> objects representing the
* Returns an array of {@code Type} objects representing the
* upper bound(s) of this type variable. Note that if no upper bound is
* explicitly declared, the upper bound is <tt>Object</tt>.
* explicitly declared, the upper bound is {@code Object}.
*
* <p>For each upper bound B:
* <ul>
@ -111,9 +111,9 @@ public class TypeVariableImpl<D extends GenericDeclaration>
* <li>Otherwise, B is resolved.
* </ul>
*
* @throws <tt>TypeNotPresentException</tt> if any of the
* @throws {@code TypeNotPresentException} if any of the
* bounds refers to a non-existent type declaration
* @throws <tt>MalformedParameterizedTypeException</tt> if any of the
* @throws {@code MalformedParameterizedTypeException} if any of the
* bounds refer to a parameterized type that cannot be instantiated
* for any reason
* @return an array of Types representing the upper bound(s) of this
@ -129,7 +129,7 @@ public class TypeVariableImpl<D extends GenericDeclaration>
}
/**
* Returns the <tt>GenericDeclaration</tt> object representing the
* Returns the {@code GenericDeclaration} object representing the
* generic declaration that declared this type variable.
*
* @return the generic declaration that declared this type variable.

View File

@ -78,9 +78,9 @@ public class WildcardTypeImpl extends LazyReflectiveObjectGenerator
}
/**
* Returns an array of <tt>Type</tt> objects representing the upper
* Returns an array of {@code Type} objects representing the upper
* bound(s) of this type variable. Note that if no upper bound is
* explicitly declared, the upper bound is <tt>Object</tt>.
* explicitly declared, the upper bound is {@code Object}.
*
* <p>For each upper bound B :
* <ul>
@ -92,9 +92,9 @@ public class WildcardTypeImpl extends LazyReflectiveObjectGenerator
*
* @return an array of Types representing the upper bound(s) of this
* type variable
* @throws <tt>TypeNotPresentException</tt> if any of the
* @throws {@code TypeNotPresentException} if any of the
* bounds refers to a non-existent type declaration
* @throws <tt>MalformedParameterizedTypeException</tt> if any of the
* @throws {@code MalformedParameterizedTypeException} if any of the
* bounds refer to a parameterized type that cannot be instantiated
* for any reason
*/
@ -108,9 +108,9 @@ public class WildcardTypeImpl extends LazyReflectiveObjectGenerator
}
/**
* Returns an array of <tt>Type</tt> objects representing the
* Returns an array of {@code Type} objects representing the
* lower bound(s) of this type variable. Note that if no lower bound is
* explicitly declared, the lower bound is the type of <tt>null</tt>.
* explicitly declared, the lower bound is the type of {@code null}.
* In this case, a zero length array is returned.
*
* <p>For each lower bound B :
@ -123,9 +123,9 @@ public class WildcardTypeImpl extends LazyReflectiveObjectGenerator
*
* @return an array of Types representing the lower bound(s) of this
* type variable
* @throws <tt>TypeNotPresentException</tt> if any of the
* @throws {@code TypeNotPresentException} if any of the
* bounds refers to a non-existent type declaration
* @throws <tt>MalformedParameterizedTypeException</tt> if any of the
* @throws {@code MalformedParameterizedTypeException} if any of the
* bounds refer to a parameterized type that cannot be instantiated
* for any reason
*/

View File

@ -48,15 +48,15 @@ public abstract class AbstractRepository<T extends Tree> {
private GenericsFactory getFactory() { return factory;}
/**
* Accessor for <tt>tree</tt>.
* Accessor for {@code tree}.
* @return the cached AST this repository holds
*/
protected T getTree(){ return tree;}
/**
* Returns a <tt>Reifier</tt> used to convert parts of the
* Returns a {@code Reifier} used to convert parts of the
* AST into reflective objects.
* @return a <tt>Reifier</tt> used to convert parts of the
* @return a {@code Reifier} used to convert parts of the
* AST into reflective objects
*/
protected Reifier getReifier(){return Reifier.make(getFactory());}

View File

@ -63,8 +63,8 @@ public class ClassRepository extends GenericDeclRepository<ClassSignature> {
* that this repository is servicing
* @param f - a factory that will provide instances of reflective
* objects when this repository converts its AST
* @return a <tt>ClassRepository</tt> that manages the generic type
* information represented in the signature <tt>rawSig</tt>
* @return a {@code ClassRepository} that manages the generic type
* information represented in the signature {@code rawSig}
*/
public static ClassRepository make(String rawSig, GenericsFactory f) {
return new ClassRepository(rawSig, f);

View File

@ -64,8 +64,8 @@ public class ConstructorRepository
* that this repository is servicing
* @param f - a factory that will provide instances of reflective
* objects when this repository converts its AST
* @return a <tt>ConstructorRepository</tt> that manages the generic type
* information represented in the signature <tt>rawSig</tt>
* @return a {@code ConstructorRepository} that manages the generic type
* information represented in the signature {@code rawSig}
*/
public static ConstructorRepository make(String rawSig, GenericsFactory f) {
return new ConstructorRepository(rawSig, f);

View File

@ -59,8 +59,8 @@ public class FieldRepository extends AbstractRepository<TypeSignature> {
* that this repository is servicing
* @param f - a factory that will provide instances of reflective
* objects when this repository converts its AST
* @return a <tt>FieldRepository</tt> that manages the generic type
* information represented in the signature <tt>rawSig</tt>
* @return a {@code FieldRepository} that manages the generic type
* information represented in the signature {@code rawSig}
*/
public static FieldRepository make(String rawSig, GenericsFactory f) {
return new FieldRepository(rawSig, f);

Some files were not shown because too many files have changed in this diff Show More