Merge
This commit is contained in:
commit
1027d6c2a3
@ -325,3 +325,4 @@ ba08a9f79b9849716bae1f39f71333d47f604012 jdk9-b79
|
||||
f7c5ae2933c0b8510a420d1713a955e4ffc7ad0b jdk9-b80
|
||||
b8afcf91331d78626a583ec1b63164468d6f4181 jdk9-b81
|
||||
42b56d1f418523ecb61a49d7493302c80c8009cc jdk9-b82
|
||||
ce5c14d97d95084504c32b9320cb33cce4235588 jdk9-b83
|
||||
|
@ -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
|
||||
|
@ -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" "$@"
|
||||
|
@ -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
|
||||
|
@ -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@
|
||||
|
@ -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
|
||||
|
@ -325,3 +325,4 @@ d8126bc88fa5cd1ae4e44d86a4b1280ca1c9e2aa jdk9-b76
|
||||
821a0373ef2d1642a9824facb938b901ad010413 jdk9-b80
|
||||
45c35b7f5b40d5af0085e4a7b3a4d6e3e0347c35 jdk9-b81
|
||||
c20d8ebddaa6fb09cc81d3edf3d1d05f4232700a jdk9-b82
|
||||
ca8a1719588424f6e04e943790c7fcb7cb0b8c8f jdk9-b83
|
||||
|
@ -485,3 +485,4 @@ e9e63d93bbfe2c6c23447e2c1f5cc71c98671cba jdk9-b79
|
||||
8e8377739c06b99b9011c003c77e0bef84c91e09 jdk9-b80
|
||||
4142c190cd5ca4fb70ec367b4f97ef936272d8ef jdk9-b81
|
||||
1c453a12be3036d482abef1dd470f8aff536b6b9 jdk9-b82
|
||||
3ed0df2c553a80e0e26b91a6ce08806ea17a066a jdk9-b83
|
||||
|
@ -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);
|
||||
%}
|
||||
|
@ -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
@ -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);
|
||||
|
@ -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");
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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); }
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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",
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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; }
|
||||
|
@ -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() {
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)));
|
||||
|
@ -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
|
||||
|
31
hotspot/src/share/vm/gc/g1/g1ParScanThreadState_ext.cpp
Normal file
31
hotspot/src/share/vm/gc/g1/g1ParScanThreadState_ext.cpp
Normal 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);
|
||||
}
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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; }
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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() {
|
||||
|
@ -290,6 +290,7 @@ macro(MulVD)
|
||||
macro(MulReductionVD)
|
||||
macro(DivVF)
|
||||
macro(DivVD)
|
||||
macro(SqrtVD)
|
||||
macro(LShiftCntV)
|
||||
macro(RShiftCntV)
|
||||
macro(LShiftVB)
|
||||
|
@ -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) {
|
||||
|
@ -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++)
|
||||
|
@ -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");
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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))
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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");
|
||||
}
|
||||
|
@ -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
|
||||
*
|
||||
*/
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
60
hotspot/test/testlibrary_tests/whitebox/BlobSanityTest.java
Normal file
60
hotspot/test/testlibrary_tests/whitebox/BlobSanityTest.java
Normal 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);
|
||||
}
|
||||
}
|
@ -325,3 +325,4 @@ cf809edc840ff7546677d38b13ebd8b3cae2bbda jdk9-b79
|
||||
f464f9b2fb1178f6a957e5730b4b5252c6149ed9 jdk9-b80
|
||||
6a418934997fc4b56664b88f8417e2f0fe658091 jdk9-b81
|
||||
53fe3c103b6fdf48e2b2676c0c4818ef5a10fa21 jdk9-b82
|
||||
497bc2654e11684b11de46744227883d7e760f35 jdk9-b83
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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();
|
||||
}
|
112
jaxp/test/javax/xml/jaxp/unittest/dom/ElementTraversal.java
Normal file
112
jaxp/test/javax/xml/jaxp/unittest/dom/ElementTraversal.java
Normal 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;
|
||||
}
|
||||
}
|
24
jaxp/test/javax/xml/jaxp/unittest/dom/ElementTraversal.xml
Normal file
24
jaxp/test/javax/xml/jaxp/unittest/dom/ElementTraversal.xml
Normal 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>
|
@ -325,3 +325,4 @@ d99c2ffdd0f15753e69126583688f2f075a0a5e8 jdk9-b79
|
||||
4947810137ae53abba3028cc366af953d90fa81a jdk9-b80
|
||||
fdc13a2d32867ca3c57b7fa2620c6b59c83168cb jdk9-b81
|
||||
b10b64263b563e21f055c881444f625ec618b826 jdk9-b82
|
||||
d11f25ce3c545823f53bb978d454a4d2901abac3 jdk9-b83
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
*
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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")
|
||||
*/
|
||||
|
@ -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> -1. Note that for values of
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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>
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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());}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user