This commit is contained in:
J. Duke 2017-07-05 20:51:33 +02:00
commit d0723cb05b
401 changed files with 11343 additions and 4878 deletions

View File

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

View File

@ -445,6 +445,15 @@ AC_DEFUN_ONCE([BASIC_SETUP_PATHS],
# Save the current directory this script was started from # Save the current directory this script was started from
CURDIR="$PWD" 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 if test "x$OPENJDK_TARGET_OS" = "xwindows"; then
PATH_SEP=";" PATH_SEP=";"
BASIC_CHECK_PATHS_WINDOWS BASIC_CHECK_PATHS_WINDOWS
@ -935,6 +944,7 @@ AC_DEFUN_ONCE([BASIC_SETUP_COMPLEX_TOOLS],
BASIC_PATH_PROGS(HG, hg) BASIC_PATH_PROGS(HG, hg)
BASIC_PATH_PROGS(STAT, stat) BASIC_PATH_PROGS(STAT, stat)
BASIC_PATH_PROGS(TIME, time) BASIC_PATH_PROGS(TIME, time)
BASIC_PATH_PROGS(PATCH, [gpatch patch])
# Check if it's GNU time # Check if it's GNU time
IS_GNU_TIME=`$TIME --version 2>&1 | $GREP 'GNU time'` IS_GNU_TIME=`$TIME --version 2>&1 | $GREP 'GNU time'`
if test "x$IS_GNU_TIME" != x; then if test "x$IS_GNU_TIME" != x; then

View File

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

View File

@ -859,6 +859,7 @@ CODESIGN
XATTR XATTR
DSYMUTIL DSYMUTIL
IS_GNU_TIME IS_GNU_TIME
PATCH
TIME TIME
STAT STAT
HG HG
@ -1174,6 +1175,7 @@ READELF
HG HG
STAT STAT
TIME TIME
PATCH
DSYMUTIL DSYMUTIL
XATTR XATTR
CODESIGN CODESIGN
@ -2053,6 +2055,7 @@ Some influential environment variables:
HG Override default value for HG HG Override default value for HG
STAT Override default value for STAT STAT Override default value for STAT
TIME Override default value for TIME TIME Override default value for TIME
PATCH Override default value for PATCH
DSYMUTIL Override default value for DSYMUTIL DSYMUTIL Override default value for DSYMUTIL
XATTR Override default value for XATTR XATTR Override default value for XATTR
CODESIGN Override default value for CODESIGN CODESIGN Override default value for CODESIGN
@ -4359,7 +4362,7 @@ VS_SDK_PLATFORM_NAME_2013=
#CUSTOM_AUTOCONF_INCLUDE #CUSTOM_AUTOCONF_INCLUDE
# Do not change or remove the following line, it is needed for consistency checks: # 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 # Save the current directory this script was started from
CURDIR="$PWD" 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 if test "x$OPENJDK_TARGET_OS" = "xwindows"; then
PATH_SEP=";" PATH_SEP=";"
@ -18865,6 +18878,192 @@ $as_echo "$tool_specified" >&6; }
fi 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 # Check if it's GNU time
IS_GNU_TIME=`$TIME --version 2>&1 | $GREP 'GNU time'` IS_GNU_TIME=`$TIME --version 2>&1 | $GREP 'GNU time'`
if test "x$IS_GNU_TIME" != x; then if test "x$IS_GNU_TIME" != x; then

View File

@ -36,6 +36,11 @@ CONFIGURE_COMMAND_LINE:=@CONFIGURE_COMMAND_LINE@
# A self-referential reference to this file. # A self-referential reference to this file.
SPEC:=@SPEC@ 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. # What make to use for main processing, after bootstrapping top-level Makefile.
MAKE := @MAKE@ MAKE := @MAKE@
@ -495,6 +500,7 @@ LN:=@LN@
MKDIR:=@MKDIR@ MKDIR:=@MKDIR@
MV:=@MV@ MV:=@MV@
NAWK:=@NAWK@ NAWK:=@NAWK@
PATCH:=@PATCH@
PRINTF:=@PRINTF@ PRINTF:=@PRINTF@
PWD:=@THEPWDCMD@ PWD:=@THEPWDCMD@
RM:=@RM@ RM:=@RM@

View File

@ -88,23 +88,19 @@ diff_text() {
TMP=$(LC_ALL=C $DIFF $OTHER_FILE $THIS_FILE | \ TMP=$(LC_ALL=C $DIFF $OTHER_FILE $THIS_FILE | \
$GREP '^[<>]' | \ $GREP '^[<>]' | \
$SED -e '/[<>] \* from.*\.idl/d' \ $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 '/[<>] \*.*[0-9]\{4\} [0-9][0-9]*:[0-9]\{2\}:[0-9]\{2\}.*/d' \
-e '/\/\/ Generated from input file.*/d' \ -e '/\/\/ Generated from input file.*/d' \
-e '/\/\/ This file was generated AUTOMATICALLY from a template file.*/d' \ -e '/\/\/ This file was generated AUTOMATICALLY from a template file.*/d' \
-e '/\/\/ java GenerateCharacter.*/d') -e '/\/\/ java GenerateCharacter.*/d')
fi fi
# Ignore date strings in class files. # 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. # Anonymous lambda classes get randomly assigned counters in their names.
if test "x$SUFFIX" = "xclass"; then if test "x$SUFFIX" = "xclass"; then
# To improve performance when large diffs are found, do a rough filtering of classes # To improve performance when large diffs are found, do a rough filtering of classes
# elibeble for these exceptions # 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\}' \ 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 '[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 -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 "${OTHER_FILE}" > ${OTHER_FILE}.javap
$JAVAP -c -constants -l -p "${THIS_FILE}" > ${THIS_FILE}.javap $JAVAP -c -constants -l -p "${THIS_FILE}" > ${THIS_FILE}.javap
@ -112,9 +108,6 @@ diff_text() {
$GREP '^[<>]' | \ $GREP '^[<>]' | \
$SED -e '/[<>].*[0-9]\{4\}_[0-9]\{2\}_[0-9]\{2\}_[0-9]\{2\}_[0-9]\{2\}-b[0-9]\{2\}.*/d' \ $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 '/[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') -e '/[<>].*lambda\$[a-zA-Z0-9]*\$[0-9]*/d')
fi fi
fi fi
@ -313,7 +306,7 @@ compare_general_files() {
! -name "jspawnhelper" \ ! -name "jspawnhelper" \
| $GREP -v "./bin/" | $SORT | $FILTER) | $GREP -v "./bin/" | $SORT | $FILTER)
echo General files... echo Other files with binary differences...
for f in $GENERAL_FILES for f in $GENERAL_FILES
do do
if [ -e $OTHER_DIR/$f ]; then if [ -e $OTHER_DIR/$f ]; then
@ -590,7 +583,7 @@ compare_bin_file() {
ORIG_THIS_FILE="$THIS_FILE" ORIG_THIS_FILE="$THIS_FILE"
ORIG_OTHER_FILE="$OTHER_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 THIS_STRIPPED_FILE=$FILE_WORK_DIR/this/$NAME
OTHER_STRIPPED_FILE=$FILE_WORK_DIR/other/$NAME OTHER_STRIPPED_FILE=$FILE_WORK_DIR/other/$NAME
$MKDIR -p $FILE_WORK_DIR/this $FILE_WORK_DIR/other $MKDIR -p $FILE_WORK_DIR/this $FILE_WORK_DIR/other
@ -722,7 +715,7 @@ compare_bin_file() {
fi fi
fi fi
if [[ "$SORT_SYMBOLS" = *"$BIN_FILE"* ]]; then if [ "$SORT_ALL_SYMBOLS" = "true" ] || [[ "$SORT_SYMBOLS" = *"$BIN_FILE"* ]]; then
SYM_SORT_CMD="sort" SYM_SORT_CMD="sort"
else else
SYM_SORT_CMD="cat" SYM_SORT_CMD="cat"
@ -810,31 +803,34 @@ compare_bin_file() {
if [ -z "$FULLDUMP_DIFF_FILTER" ]; then if [ -z "$FULLDUMP_DIFF_FILTER" ]; then
FULLDUMP_DIFF_FILTER="$CAT" FULLDUMP_DIFF_FILTER="$CAT"
fi fi
$FULLDUMP_CMD $OTHER_FILE | eval "$FULLDUMP_DIFF_FILTER" > $WORK_FILE_BASE.fulldump.other 2>&1 $FULLDUMP_CMD $OTHER_FILE | eval "$FULLDUMP_DIFF_FILTER" \
$FULLDUMP_CMD $THIS_FILE | eval "$FULLDUMP_DIFF_FILTER" > $WORK_FILE_BASE.fulldump.this 2>&1 > $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 if [ -s $WORK_FILE_BASE.fulldump.diff ]; then
ELF_DIFF_SIZE=$(ls -n $WORK_FILE_BASE.fulldump.diff | awk '{print $5}') FULLDUMP_DIFF_SIZE=$(ls -n $WORK_FILE_BASE.fulldump.diff | awk '{print $5}')
ELF_MSG=$($PRINTF "%8d" $ELF_DIFF_SIZE) FULLDUMP_MSG=$($PRINTF "%8d" $FULLDUMP_DIFF_SIZE)
if [[ "$ACCEPTED_ELF_DIFF" != *"$BIN_FILE"* ]]; then if [[ "$ACCEPTED_FULLDUMP_DIFF" != *"$BIN_FILE"* ]]; then
DIFF_ELF=true DIFF_FULLDUMP=true
if [[ "$KNOWN_ELF_DIFF" != *"$BIN_FILE"* ]]; then if [[ "$KNOWN_FULLDUMP_DIFF" != *"$BIN_FILE"* ]]; then
ELF_MSG="*$ELF_MSG*" FULLDUMP_MSG="*$FULLDUMP_MSG*"
REGRESSIONS=true REGRESSIONS=true
else else
ELF_MSG=" $ELF_MSG " FULLDUMP_MSG=" $FULLDUMP_MSG "
fi fi
else else
ELF_MSG="($ELF_MSG)" FULLDUMP_MSG="($FULLDUMP_MSG)"
DIFF_ELF= DIFF_FULLDUMP=
fi fi
else else
ELF_MSG=" " FULLDUMP_MSG=" "
DIFF_ELF= DIFF_FULLDUMP=
if [[ "$KNOWN_DEP_DIFF $ACCEPTED_DEP_DIFF" = *"$BIN_FILE"* ]]; then if [[ "$KNOWN_FULLDUMP_DIFF $ACCEPTED_FULLDUMP_DIFF" = *"$BIN_FILE"* ]]; then
ELF_MSG=" ! " FULLDUMP_MSG=" ! "
fi fi
fi fi
fi fi
@ -845,7 +841,7 @@ compare_bin_file() {
# To get a raw diff with the complete disassembly, set # To get a raw diff with the complete disassembly, set
# DIS_DIFF_FILTER="$CAT" # DIS_DIFF_FILTER="$CAT"
if [ -z "$DIS_DIFF_FILTER" ]; then 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 fi
$DIS_CMD $OTHER_FILE | $GREP -v $NAME | eval "$DIS_DIFF_FILTER" > $WORK_FILE_BASE.dis.other 2>&1 $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 $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 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 "$BIN_MSG" ]; then echo -n "$BIN_MSG:"; fi
if [ -n "$SIZE_MSG" ]; then echo -n "$SIZE_MSG:"; fi if [ -n "$SIZE_MSG" ]; then echo -n "$SIZE_MSG:"; fi
if [ -n "$SYM_MSG" ]; then echo -n "$SYM_MSG:"; fi if [ -n "$SYM_MSG" ]; then echo -n "$SYM_MSG:"; fi
if [ -n "$DEP_MSG" ]; then echo -n "$DEP_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 if [ -n "$DIS_MSG" ]; then echo -n "$DIS_MSG:"; fi
echo " $BIN_FILE" echo " $BIN_FILE"
if [ "$SHOW_DIFFS" = "true" ]; then 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 "-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 "-o [OTHER] Compare with build in other directory. Will default to the old build directory"
echo "" 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 "[FILTER] List filenames in the image to compare, works for jars, zips, libs and execs"
echo "Example:" echo "Example:"
echo "bash ./common/bin/compareimages.sh CodePointIM.jar" echo "bash ./common/bin/compareimages.sh CodePointIM.jar"
@ -1107,6 +1106,12 @@ while [ -n "$1" ]; do
shift shift
shift shift
;; ;;
--sort-symbols)
SORT_ALL_SYMBOLS=true
;;
--strip)
STRIP_ALL=true
;;
*) *)
CMP_NAMES=false CMP_NAMES=false
CMP_PERMS=false CMP_PERMS=false
@ -1223,7 +1228,7 @@ if [ "$SKIP_DEFAULT" != "true" ]; then
OTHER_JDK_BUNDLE="$OTHER/images/jdk-bundle" OTHER_JDK_BUNDLE="$OTHER/images/jdk-bundle"
OTHER_JRE_BUNDLE="$OTHER/images/jre-bundle" OTHER_JRE_BUNDLE="$OTHER/images/jre-bundle"
fi fi
echo "Also comparing macosx bundles" echo "Also comparing jdk macosx bundles"
echo " $THIS_JDK_BUNDLE" echo " $THIS_JDK_BUNDLE"
echo " $OTHER_JDK_BUNDLE" echo " $OTHER_JDK_BUNDLE"
fi fi

View File

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

View File

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

View File

@ -3803,82 +3803,38 @@ encode %{
enc_class aarch64_enc_cmpxchg(memory mem, iRegLNoSp oldval, iRegLNoSp newval) %{ enc_class aarch64_enc_cmpxchg(memory mem, iRegLNoSp oldval, iRegLNoSp newval) %{
MacroAssembler _masm(&cbuf); MacroAssembler _masm(&cbuf);
Register old_reg = as_Register($oldval$$reg); guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
Register new_reg = as_Register($newval$$reg); __ cmpxchg($mem$$base$$Register, $oldval$$Register, $newval$$Register,
Register base = as_Register($mem$$base); &Assembler::ldxr, &MacroAssembler::cmp, &Assembler::stlxr);
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);
%} %}
enc_class aarch64_enc_cmpxchgw(memory mem, iRegINoSp oldval, iRegINoSp newval) %{ enc_class aarch64_enc_cmpxchgw(memory mem, iRegINoSp oldval, iRegINoSp newval) %{
MacroAssembler _masm(&cbuf); MacroAssembler _masm(&cbuf);
Register old_reg = as_Register($oldval$$reg); guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
Register new_reg = as_Register($newval$$reg); __ cmpxchg($mem$$base$$Register, $oldval$$Register, $newval$$Register,
Register base = as_Register($mem$$base); &Assembler::ldxrw, &MacroAssembler::cmpw, &Assembler::stlxrw);
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);
%} %}
// 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 // auxiliary used for CompareAndSwapX to set result register
enc_class aarch64_enc_cset_eq(iRegINoSp res) %{ enc_class aarch64_enc_cset_eq(iRegINoSp res) %{
MacroAssembler _masm(&cbuf); MacroAssembler _masm(&cbuf);
@ -4398,13 +4354,10 @@ encode %{
// Compare object markOop with mark and if equal exchange scratch1 // Compare object markOop with mark and if equal exchange scratch1
// with object markOop. // 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; Label retry_load;
__ bind(retry_load); __ bind(retry_load);
__ ldxr(tmp, oop); __ ldaxr(tmp, oop);
__ cmp(tmp, disp_hdr); __ cmp(tmp, disp_hdr);
__ br(Assembler::NE, cas_failed); __ br(Assembler::NE, cas_failed);
// use stlxr to ensure update is immediately visible // use stlxr to ensure update is immediately visible
@ -4454,7 +4407,7 @@ encode %{
{ {
Label retry_load, fail; Label retry_load, fail;
__ bind(retry_load); __ bind(retry_load);
__ ldxr(rscratch1, tmp); __ ldaxr(rscratch1, tmp);
__ cmp(disp_hdr, rscratch1); __ cmp(disp_hdr, rscratch1);
__ br(Assembler::NE, fail); __ br(Assembler::NE, fail);
// use stlxr to ensure update is immediately visible // use stlxr to ensure update is immediately visible
@ -8017,10 +7970,10 @@ instruct membar_acquire_lock() %{
match(MemBarAcquireLock); match(MemBarAcquireLock);
ins_cost(VOLATILE_REF_COST); ins_cost(VOLATILE_REF_COST);
format %{ "membar_acquire_lock" %} format %{ "membar_acquire_lock (elided)" %}
ins_encode %{ ins_encode %{
__ membar(Assembler::LoadLoad|Assembler::LoadStore); __ block_comment("membar_acquire_lock (elided)");
%} %}
ins_pipe(pipe_serial); ins_pipe(pipe_serial);
@ -8080,10 +8033,10 @@ instruct membar_release_lock() %{
match(MemBarReleaseLock); match(MemBarReleaseLock);
ins_cost(VOLATILE_REF_COST); ins_cost(VOLATILE_REF_COST);
format %{ "membar_release_lock" %} format %{ "membar_release_lock (elided)" %}
ins_encode %{ ins_encode %{
__ membar(Assembler::LoadStore|Assembler::StoreStore); __ block_comment("membar_release_lock (elided)");
%} %}
ins_pipe(pipe_serial); ins_pipe(pipe_serial);
@ -8369,7 +8322,11 @@ instruct storePConditional(memory heap_top_ptr, iRegP oldval, iRegP newval, rFla
ins_pipe(pipe_serial); 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) instruct storeLConditional(indirect mem, iRegLNoSp oldval, iRegLNoSp newval, rFlagsReg cr)
%{ %{
match(Set cr (StoreLConditional mem (Binary oldval newval))); 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" "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); 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) instruct storeIConditional(indirect mem, iRegINoSp oldval, iRegINoSp newval, rFlagsReg cr)
%{ %{
match(Set cr (StoreIConditional mem (Binary oldval newval))); 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" "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); ins_pipe(pipe_slow);
%} %}

View File

@ -917,6 +917,8 @@ public:
void cmpptr(Register src1, Address src2); void cmpptr(Register src1, Address src2);
// Various forms of CAS
void cmpxchgptr(Register oldv, Register newv, Register addr, Register tmp, void cmpxchgptr(Register oldv, Register newv, Register addr, Register tmp,
Label &suceed, Label *fail); Label &suceed, Label *fail);
@ -938,6 +940,23 @@ public:
str(rscratch2, adr); 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 // Calls
address trampoline_call(Address entry, CodeBuffer *cbuf = NULL); address trampoline_call(Address entry, CodeBuffer *cbuf = NULL);

File diff suppressed because it is too large Load Diff

View File

@ -438,7 +438,9 @@ class ArrayAddress VALUE_OBJ_CLASS_SPEC {
}; };
const int FPUStateSizeInWords = NOT_LP64(27) LP64_ONLY( 512*2 / wordSize); // 64-bit refect the fxsave size which is 512 bytes and the new xsave area on EVEX which is another 2176 bytes
// See fxsave and xsave(EVEX enabled) documentation for layout
const int FPUStateSizeInWords = NOT_LP64(27) LP64_ONLY(2688 / wordSize);
// The Intel x86/Amd64 Assembler: Pure assembler doing NO optimizations on the instruction // 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 // 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: private:
int evex_encoding; int _evex_encoding;
int input_size_in_bits; int _input_size_in_bits;
int avx_vector_len; int _avx_vector_len;
int tuple_type; int _tuple_type;
bool is_evex_instruction; 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 // 64bit prefixes
int prefix_and_encode(int reg_enc, bool byteinst = false); 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 // belong in macro assembler but there is no need for both varieties to exist
void init_attributes(void) { void init_attributes(void) {
evex_encoding = 0; _evex_encoding = 0;
input_size_in_bits = 0; _input_size_in_bits = 0;
avx_vector_len = AVX_NoVec; _avx_vector_len = AVX_NoVec;
tuple_type = EVEX_ETUP; _tuple_type = EVEX_ETUP;
is_evex_instruction = false; _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); void lea(Register dst, Address src);
@ -1344,8 +1356,10 @@ private:
void fxch(int i = 1); void fxch(int i = 1);
void fxrstor(Address src); void fxrstor(Address src);
void xrstor(Address src);
void fxsave(Address dst); void fxsave(Address dst);
void xsave(Address dst);
void fyl2x(); void fyl2x();
void frndint(); void frndint();
@ -1479,11 +1493,12 @@ private:
void movb(Address dst, int imm8); void movb(Address dst, int imm8);
void movb(Register dst, Address src); 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 kmovql(KRegister dst, Register src);
void kmovdl(KRegister dst, Register src); void kmovdl(KRegister dst, Register src);
void kmovq(Address dst, KRegister src); void kmovwl(KRegister dst, Register src);
void kmovq(KRegister dst, Address src); void kmovql(Address dst, KRegister src);
void kmovql(KRegister dst, Address src);
void movdl(XMMRegister dst, Register src); void movdl(XMMRegister dst, Register src);
void movdl(Register dst, XMMRegister src); void movdl(Register dst, XMMRegister src);
@ -1509,9 +1524,12 @@ private:
void vmovdqu(XMMRegister dst, XMMRegister src); void vmovdqu(XMMRegister dst, XMMRegister src);
// Move Unaligned 512bit Vector // Move Unaligned 512bit Vector
void evmovdqu(Address dst, XMMRegister src, int vector_len); void evmovdqul(Address dst, XMMRegister src, int vector_len);
void evmovdqu(XMMRegister dst, Address src, int vector_len); void evmovdqul(XMMRegister dst, Address src, int vector_len);
void evmovdqu(XMMRegister dst, XMMRegister 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 // Move lower 64bit to high 64bit in 128bit register
void movlhps(XMMRegister dst, XMMRegister src); void movlhps(XMMRegister dst, XMMRegister src);
@ -1643,6 +1661,7 @@ private:
// Pemutation of 64bit words // Pemutation of 64bit words
void vpermq(XMMRegister dst, XMMRegister src, int imm8, int vector_len); void vpermq(XMMRegister dst, XMMRegister src, int imm8, int vector_len);
void vpermq(XMMRegister dst, XMMRegister src, int imm8);
void pause(); void pause();
@ -1920,6 +1939,10 @@ private:
void vdivpd(XMMRegister dst, XMMRegister nds, Address src, int vector_len); void vdivpd(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
void vdivps(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 // Bitwise Logical AND of Packed Floating-Point Values
void andpd(XMMRegister dst, XMMRegister src); void andpd(XMMRegister dst, XMMRegister src);
void andps(XMMRegister dst, XMMRegister src); void andps(XMMRegister dst, XMMRegister src);
@ -2057,6 +2080,9 @@ private:
void vextracti64x2h(XMMRegister dst, XMMRegister src, int value); void vextracti64x2h(XMMRegister dst, XMMRegister src, int value);
void vextractf64x2h(XMMRegister dst, XMMRegister src, int value); void vextractf64x2h(XMMRegister dst, XMMRegister src, int value);
void vextractf32x4h(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 // duplicate 4-bytes integer data from src into 8 locations in dest
void vpbroadcastd(XMMRegister dst, XMMRegister src); void vpbroadcastd(XMMRegister dst, XMMRegister src);

View File

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

View File

@ -401,11 +401,9 @@ static OopMap* generate_oop_map(StubAssembler* sasm, int num_rt_args,
} else if (UseSSE == 1) { } else if (UseSSE == 1) {
int xmm_off = xmm_regs_as_doubles_off; int xmm_off = xmm_regs_as_doubles_off;
for (int n = 0; n < FrameMap::nof_xmm_regs; n++) { for (int n = 0; n < FrameMap::nof_fpu_regs; n++) {
if (n < xmm_bypass_limit) { VMReg xmm_name_0 = as_XMMRegister(n)->as_VMReg();
VMReg xmm_name_0 = as_XMMRegister(n)->as_VMReg(); map->set_callee_saved(VMRegImpl::stack2reg(xmm_off + num_rt_args), xmm_name_0);
map->set_callee_saved(VMRegImpl::stack2reg(xmm_off + num_rt_args), xmm_name_0);
}
xmm_off += 2; xmm_off += 2;
} }
assert(xmm_off == float_regs_as_doubles_off, "incorrect number of xmm registers"); 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)); __ frstor(Address(rsp, fpu_state_off * VMRegImpl::stack_slot_size));
// Save the FPU registers in de-opt-able form // Save the FPU registers in de-opt-able form
__ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 0)); int offset = 0;
__ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 8)); for (int n = 0; n < FrameMap::nof_fpu_regs; n++) {
__ 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 + offset));
__ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 24)); offset += 8;
__ 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));
} }
if (UseSSE >= 2) { if (UseSSE >= 2) {
@ -468,52 +463,26 @@ static OopMap* save_live_registers(StubAssembler* sasm, int num_rt_args,
// so always save them as doubles. // so always save them as doubles.
// note that float values are _not_ converted automatically, so for float values // note that float values are _not_ converted automatically, so for float values
// the second word contains only garbage data. // the second word contains only garbage data.
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 0), xmm0); int xmm_bypass_limit = FrameMap::nof_xmm_regs;
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 8), xmm1); int offset = 0;
__ 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);
#ifdef _LP64 #ifdef _LP64
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 64), xmm8); if (UseAVX < 3) {
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 72), xmm9); xmm_bypass_limit = xmm_bypass_limit / 2;
__ 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); #endif
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 96), xmm12); for (int n = 0; n < xmm_bypass_limit; n++) {
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 104), xmm13); XMMRegister xmm_name = as_XMMRegister(n);
__ 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 + offset), xmm_name);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 120), xmm15); offset += 8;
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);
} }
#endif // _LP64
} else if (UseSSE == 1) { } else if (UseSSE == 1) {
// save XMM registers as float because double not supported without SSE2 // save XMM registers as float because double not supported without SSE2(num MMX == num fpu)
__ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 0), xmm0); int offset = 0;
__ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 8), xmm1); for (int n = 0; n < FrameMap::nof_fpu_regs; n++) {
__ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 16), xmm2); XMMRegister xmm_name = as_XMMRegister(n);
__ 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 + offset), xmm_name);
__ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 32), xmm4); offset += 8;
__ 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);
} }
} }
@ -528,52 +497,26 @@ static void restore_fpu(StubAssembler* sasm, bool restore_fpu_registers = true)
if (restore_fpu_registers) { if (restore_fpu_registers) {
if (UseSSE >= 2) { if (UseSSE >= 2) {
// restore XMM registers // restore XMM registers
__ movdbl(xmm0, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 0)); int xmm_bypass_limit = FrameMap::nof_xmm_regs;
__ 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));
#ifdef _LP64 #ifdef _LP64
__ movdbl(xmm8, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 64)); if (UseAVX < 3) {
__ movdbl(xmm9, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 72)); xmm_bypass_limit = xmm_bypass_limit / 2;
__ 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)); #endif
__ movdbl(xmm12, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 96)); int offset = 0;
__ movdbl(xmm13, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 104)); for (int n = 0; n < xmm_bypass_limit; n++) {
__ movdbl(xmm14, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 112)); XMMRegister xmm_name = as_XMMRegister(n);
__ movdbl(xmm15, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 120)); __ movdbl(xmm_name, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + offset));
if (UseAVX > 2) { offset += 8;
__ 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));
} }
#endif // _LP64
} else if (UseSSE == 1) { } else if (UseSSE == 1) {
// restore XMM registers // restore XMM registers(num MMX == num fpu)
__ movflt(xmm0, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 0)); int offset = 0;
__ movflt(xmm1, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 8)); for (int n = 0; n < FrameMap::nof_fpu_regs; n++) {
__ movflt(xmm2, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 16)); XMMRegister xmm_name = as_XMMRegister(n);
__ movflt(xmm3, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 24)); __ movflt(xmm_name, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + offset));
__ movflt(xmm4, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 32)); offset += 8;
__ 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));
} }
if (UseSSE < 2) { if (UseSSE < 2) {

View File

@ -3751,8 +3751,31 @@ void MacroAssembler::pop_CPU_state() {
} }
void MacroAssembler::pop_FPU_state() { void MacroAssembler::pop_FPU_state() {
NOT_LP64(frstor(Address(rsp, 0));) #ifndef _LP64
LP64_ONLY(fxrstor(Address(rsp, 0));) 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); addptr(rsp, FPUStateSizeInWords * wordSize);
} }
@ -3769,13 +3792,49 @@ void MacroAssembler::push_CPU_state() {
push_FPU_state(); push_FPU_state();
} }
#ifdef _LP64
#define XSTATE_BV 0x200
#endif
void MacroAssembler::push_FPU_state() { void MacroAssembler::push_FPU_state() {
subptr(rsp, FPUStateSizeInWords * wordSize); subptr(rsp, FPUStateSizeInWords * wordSize);
#ifndef _LP64 #ifndef _LP64
fnsave(Address(rsp, 0)); fnsave(Address(rsp, 0));
fwait(); fwait();
#else #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 #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) { void MacroAssembler::vxorpd(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len) {
if (reachable(src)) { if (reachable(src)) {
vxorpd(dst, nds, as_Address(src), vector_len); 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) { void MacroAssembler::store_check(Register obj) {
// Does a store check for the oop in register obj. The content of // Does a store check for the oop in register obj. The content of
// register obj is destroyed afterwards. // register obj is destroyed afterwards.
BarrierSet* bs = Universe::heap()->barrier_set(); BarrierSet* bs = Universe::heap()->barrier_set();
assert(bs->kind() == BarrierSet::CardTableForRS || assert(bs->kind() == BarrierSet::CardTableForRS ||
bs->kind() == BarrierSet::CardTableExtension, 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 // if we are coming from c1, xmm registers may be live
int off = 0; 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) { if (UseSSE == 1) {
subptr(rsp, sizeof(jdouble)*8); subptr(rsp, sizeof(jdouble)*8);
movflt(Address(rsp,off++*sizeof(jdouble)),xmm0); for (int n = 0; n < 8; n++) {
movflt(Address(rsp,off++*sizeof(jdouble)),xmm1); movflt(Address(rsp, off++*sizeof(jdouble)), as_XMMRegister(n));
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);
} else if (UseSSE >= 2) { } else if (UseSSE >= 2) {
if (UseAVX > 2) { if (UseAVX > 2) {
push(rbx);
movl(rbx, 0xffff); movl(rbx, 0xffff);
#ifdef _LP64 kmovwl(k1, rbx);
kmovql(k1, rbx); pop(rbx);
#else
kmovdl(k1, rbx);
#endif
} }
#ifdef COMPILER2 #ifdef COMPILER2
if (MaxVectorSize > 16) { 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 // Save upper half of YMM registes
subptr(rsp, 16 * LP64_ONLY(16) NOT_LP64(8)); subptr(rsp, 16*num_xmm_regs);
vextractf128h(Address(rsp, 0),xmm0); for (int n = 0; n < num_xmm_regs; n++) {
vextractf128h(Address(rsp, 16),xmm1); vextractf128h(Address(rsp, off++*16), as_XMMRegister(n));
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
} }
#endif #endif
// Save whole 128bit (16 bytes) XMM regiters // Save whole 128bit (16 bytes) XMM registers
subptr(rsp, 16 * LP64_ONLY(16) NOT_LP64(8)); subptr(rsp, 16*num_xmm_regs);
movdqu(Address(rsp,off++*16),xmm0); off = 0;
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);
#ifdef _LP64 #ifdef _LP64
movdqu(Address(rsp,off++*16),xmm8); if (VM_Version::supports_avx512novl()) {
movdqu(Address(rsp,off++*16),xmm9); for (int n = 0; n < num_xmm_regs; n++) {
movdqu(Address(rsp,off++*16),xmm10); vextractf32x4h(Address(rsp, off++*16), as_XMMRegister(n), 0);
movdqu(Address(rsp,off++*16),xmm11); }
movdqu(Address(rsp,off++*16),xmm12); } else {
movdqu(Address(rsp,off++*16),xmm13); for (int n = 0; n < num_xmm_regs; n++) {
movdqu(Address(rsp,off++*16),xmm14); movdqu(Address(rsp, off++*16), as_XMMRegister(n));
movdqu(Address(rsp,off++*16),xmm15); }
}
#else
for (int n = 0; n < num_xmm_regs; n++) {
movdqu(Address(rsp, off++*16), as_XMMRegister(n));
}
#endif #endif
} }
@ -4689,7 +4814,7 @@ void MacroAssembler::fp_runtime_fallback(address runtime_entry, int nb_args, int
movsd(Address(rsp, 0), xmm0); movsd(Address(rsp, 0), xmm0);
fld_d(Address(rsp, 0)); fld_d(Address(rsp, 0));
#endif // _LP64 #endif // _LP64
addptr(rsp, sizeof(jdouble) * nb_args); addptr(rsp, sizeof(jdouble)*nb_args);
if (num_fpu_regs_in_use > 1) { if (num_fpu_regs_in_use > 1) {
// Must save return value to stack and then restore entire FPU // Must save return value to stack and then restore entire FPU
// stack except incoming arguments // stack except incoming arguments
@ -4699,63 +4824,50 @@ void MacroAssembler::fp_runtime_fallback(address runtime_entry, int nb_args, int
addptr(rsp, sizeof(jdouble)); addptr(rsp, sizeof(jdouble));
} }
fld_d(Address(rsp, (nb_args-1)*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; off = 0;
if (UseSSE == 1) { if (UseSSE == 1) {
movflt(xmm0, Address(rsp,off++*sizeof(jdouble))); for (int n = 0; n < 8; n++) {
movflt(xmm1, Address(rsp,off++*sizeof(jdouble))); movflt(as_XMMRegister(n), 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)));
addptr(rsp, sizeof(jdouble)*8); addptr(rsp, sizeof(jdouble)*8);
} else if (UseSSE >= 2) { } else if (UseSSE >= 2) {
// Restore whole 128bit (16 bytes) XMM regiters // 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 #ifdef _LP64
movdqu(xmm8, Address(rsp,off++*16)); if (VM_Version::supports_avx512novl()) {
movdqu(xmm9, Address(rsp,off++*16)); for (int n = 0; n < num_xmm_regs; n++) {
movdqu(xmm10, Address(rsp,off++*16)); vinsertf32x4h(as_XMMRegister(n), Address(rsp, off++*16), 0);
movdqu(xmm11, Address(rsp,off++*16)); }
movdqu(xmm12, Address(rsp,off++*16)); }
movdqu(xmm13, Address(rsp,off++*16)); else {
movdqu(xmm14, Address(rsp,off++*16)); for (int n = 0; n < num_xmm_regs; n++) {
movdqu(xmm15, Address(rsp,off++*16)); 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 #endif
addptr(rsp, 16 * LP64_ONLY(16) NOT_LP64(8)); addptr(rsp, 16*num_xmm_regs);
#ifdef COMPILER2 #ifdef COMPILER2
if (MaxVectorSize > 16) { if (MaxVectorSize > 16) {
// Restore upper half of YMM registes. // Restore upper half of YMM registes.
vinsertf128h(xmm0, Address(rsp, 0)); off = 0;
vinsertf128h(xmm1, Address(rsp, 16)); for (int n = 0; n < num_xmm_regs; n++) {
vinsertf128h(xmm2, Address(rsp, 32)); vinsertf128h(as_XMMRegister(n), Address(rsp, off++*16));
vinsertf128h(xmm3, Address(rsp, 48)); }
vinsertf128h(xmm4, Address(rsp, 64)); addptr(rsp, 16*num_xmm_regs);
vinsertf128h(xmm5, Address(rsp, 80)); if(UseAVX > 2) {
vinsertf128h(xmm6, Address(rsp, 96)); off = 0;
vinsertf128h(xmm7, Address(rsp,112)); for (int n = 0; n < num_xmm_regs; n++) {
#ifdef _LP64 vinsertf64x4h(as_XMMRegister(n), Address(rsp, off++*32));
vinsertf128h(xmm8, Address(rsp,128)); }
vinsertf128h(xmm9, Address(rsp,144)); addptr(rsp, 32*num_xmm_regs);
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));
} }
#endif #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; Label L_fill_32_bytes_loop, L_check_fill_8_bytes, L_fill_8_bytes_loop, L_fill_8_bytes;
if (UseAVX > 2) { if (UseAVX > 2) {
movl(rtmp, 0xffff); movl(rtmp, 0xffff);
#ifdef _LP64 kmovwl(k1, rtmp);
kmovql(k1, rtmp);
#else
kmovdl(k1, rtmp);
#endif
} }
movdl(xtmp, value); movdl(xtmp, value);
if (UseAVX > 2 && UseUnalignedLoadStores) { if (UseAVX > 2 && UseUnalignedLoadStores) {
@ -7112,7 +7220,7 @@ void MacroAssembler::generate_fill(BasicType t, bool aligned,
align(16); align(16);
BIND(L_fill_64_bytes_loop); 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); addptr(to, 64);
subl(count, 16 << shift); subl(count, 16 << shift);
jcc(Assembler::greaterEqual, L_fill_64_bytes_loop); 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); BIND(L_check_fill_32_bytes);
addl(count, 8 << shift); addl(count, 8 << shift);
jccb(Assembler::less, L_check_fill_8_bytes); 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); addptr(to, 32);
subl(count, 8 << shift); 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_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; 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())); lea(table, ExternalAddress(StubRoutines::crc_table_addr()));
notl(crc); // ~crc notl(crc); // ~crc
cmpl(len, 16); cmpl(len, 16);

View File

@ -1069,6 +1069,9 @@ public:
void vsubss(XMMRegister dst, XMMRegister nds, Address src) { Assembler::vsubss(dst, nds, src); } void vsubss(XMMRegister dst, XMMRegister nds, Address src) { Assembler::vsubss(dst, nds, src); }
void vsubss(XMMRegister dst, XMMRegister nds, AddressLiteral 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 // AVX Vector instructions
void vxorpd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { Assembler::vxorpd(dst, nds, src, vector_len); } void vxorpd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { Assembler::vxorpd(dst, nds, src, vector_len); }

View File

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

View File

@ -69,7 +69,9 @@ class SimpleRuntimeFrame {
class RegisterSaver { class RegisterSaver {
// Capture info about frame layout. Layout offsets are in jint // Capture info about frame layout. Layout offsets are in jint
// units because compiler frame slots are jints. // 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_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 { enum layout {
fpu_state_off = frame::arg_reg_save_area_bytes/BytesPerInt, // fxsave save area 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 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(13),
DEF_XMM_OFFS(14), DEF_XMM_OFFS(14),
DEF_XMM_OFFS(15), DEF_XMM_OFFS(15),
DEF_XMM_OFFS(16), zmm_off = fpu_state_off + ((FPUStateSizeInWords - (HALF_ZMM_BANK_WORDS + 1))*wordSize / BytesPerInt),
DEF_XMM_OFFS(17), DEF_ZMM_OFFS(16),
DEF_XMM_OFFS(18), DEF_ZMM_OFFS(17),
DEF_XMM_OFFS(19), DEF_ZMM_OFFS(18),
DEF_XMM_OFFS(20), DEF_ZMM_OFFS(19),
DEF_XMM_OFFS(21), DEF_ZMM_OFFS(20),
DEF_XMM_OFFS(22), DEF_ZMM_OFFS(21),
DEF_XMM_OFFS(23), DEF_ZMM_OFFS(22),
DEF_XMM_OFFS(24), DEF_ZMM_OFFS(23),
DEF_XMM_OFFS(25), DEF_ZMM_OFFS(24),
DEF_XMM_OFFS(26), DEF_ZMM_OFFS(25),
DEF_XMM_OFFS(27), DEF_ZMM_OFFS(26),
DEF_XMM_OFFS(28), DEF_ZMM_OFFS(27),
DEF_XMM_OFFS(29), DEF_ZMM_OFFS(28),
DEF_XMM_OFFS(30), DEF_ZMM_OFFS(29),
DEF_XMM_OFFS(31), DEF_ZMM_OFFS(30),
fpu_state_end = fpu_state_off + ((FPUStateSizeInWords - 1)*wordSize / BytesPerInt), DEF_ZMM_OFFS(31),
fpu_state_end = fpu_state_off + ((FPUStateSizeInWords-1)*wordSize / BytesPerInt),
fpu_stateH_end, fpu_stateH_end,
r15_off, r15H_off, r15_off, r15H_off,
r14_off, r14H_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) { OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words, bool save_vectors) {
int vect_words = 0; int vect_words = 0;
int num_xmm_regs = 16; int off = 0;
if (UseAVX > 2) { int num_xmm_regs = XMMRegisterImpl::number_of_registers;
num_xmm_regs = 32; if (UseAVX < 3) {
num_xmm_regs = num_xmm_regs/2;
} }
#ifdef COMPILER2 #ifdef COMPILER2
if (save_vectors) { 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"); assert(MaxVectorSize == 64, "only 512bit vectors are supported now");
// Save upper half of YMM registers // Save upper half of YMM registers
vect_words = 16 * num_xmm_regs / wordSize; vect_words = 16 * num_xmm_regs / wordSize;
additional_frame_words += vect_words; if (UseAVX < 3) {
if (UseAVX > 2) {
// Save upper half of ZMM registers as well
additional_frame_words += vect_words; 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 __ enter(); // rsp becomes 16-byte aligned here
__ push_CPU_state(); // Push a multiple of 16 bytes __ 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, ""); assert(vect_words*wordSize >= 256, "");
__ subptr(rsp, 256); // Save upper half of YMM registes(0..15) // Save upper half of YMM registes(0..num_xmm_regs)
__ vextractf128h(Address(rsp, 0), xmm0); __ subptr(rsp, num_xmm_regs*16);
__ vextractf128h(Address(rsp, 16), xmm1); for (int n = 0; n < num_xmm_regs; n++) {
__ vextractf128h(Address(rsp, 32), xmm2); __ vextractf128h(Address(rsp, off++*16), as_XMMRegister(n));
__ 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);
} }
} }
if (frame::arg_reg_save_area_bytes != 0) { 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( r13_off ), r13->as_VMReg());
map->set_callee_saved(STACK_OFFSET( r14_off ), r14->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( r15_off ), r15->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm0_off ), xmm0->as_VMReg()); // For both AVX and EVEX we will use the legacy FXSAVE area for xmm0..xmm15,
map->set_callee_saved(STACK_OFFSET(xmm1_off ), xmm1->as_VMReg()); // on EVEX enabled targets, we get it included in the xsave area
map->set_callee_saved(STACK_OFFSET(xmm2_off ), xmm2->as_VMReg()); off = xmm0_off;
map->set_callee_saved(STACK_OFFSET(xmm3_off ), xmm3->as_VMReg()); int delta = xmm1_off - off;
map->set_callee_saved(STACK_OFFSET(xmm4_off ), xmm4->as_VMReg()); for (int n = 0; n < 16; n++) {
map->set_callee_saved(STACK_OFFSET(xmm5_off ), xmm5->as_VMReg()); XMMRegister xmm_name = as_XMMRegister(n);
map->set_callee_saved(STACK_OFFSET(xmm6_off ), xmm6->as_VMReg()); map->set_callee_saved(STACK_OFFSET(off), xmm_name->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm7_off ), xmm7->as_VMReg()); off += delta;
map->set_callee_saved(STACK_OFFSET(xmm8_off ), xmm8->as_VMReg()); }
map->set_callee_saved(STACK_OFFSET(xmm9_off ), xmm9->as_VMReg()); if(UseAVX > 2) {
map->set_callee_saved(STACK_OFFSET(xmm10_off), xmm10->as_VMReg()); // Obtain xmm16..xmm31 from the XSAVE area on EVEX enabled targets
map->set_callee_saved(STACK_OFFSET(xmm11_off), xmm11->as_VMReg()); off = zmm16_off;
map->set_callee_saved(STACK_OFFSET(xmm12_off), xmm12->as_VMReg()); delta = zmm17_off - off;
map->set_callee_saved(STACK_OFFSET(xmm13_off), xmm13->as_VMReg()); for (int n = 16; n < num_xmm_regs; n++) {
map->set_callee_saved(STACK_OFFSET(xmm14_off), xmm14->as_VMReg()); XMMRegister xmm_name = as_XMMRegister(n);
map->set_callee_saved(STACK_OFFSET(xmm15_off), xmm15->as_VMReg()); map->set_callee_saved(STACK_OFFSET(off), xmm_name->as_VMReg());
if (UseAVX > 2) { off += delta;
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());
} }
// %%% These should all be a waste but we'll keep things as they were for now // %%% 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( r13H_off ), r13->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET( r14H_off ), r14->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( r15H_off ), r15->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET(xmm0H_off ), xmm0->as_VMReg()->next()); // For both AVX and EVEX we will use the legacy FXSAVE area for xmm0..xmm15,
map->set_callee_saved(STACK_OFFSET(xmm1H_off ), xmm1->as_VMReg()->next()); // on EVEX enabled targets, we get it included in the xsave area
map->set_callee_saved(STACK_OFFSET(xmm2H_off ), xmm2->as_VMReg()->next()); off = xmm0H_off;
map->set_callee_saved(STACK_OFFSET(xmm3H_off ), xmm3->as_VMReg()->next()); delta = xmm1H_off - off;
map->set_callee_saved(STACK_OFFSET(xmm4H_off ), xmm4->as_VMReg()->next()); for (int n = 0; n < 16; n++) {
map->set_callee_saved(STACK_OFFSET(xmm5H_off ), xmm5->as_VMReg()->next()); XMMRegister xmm_name = as_XMMRegister(n);
map->set_callee_saved(STACK_OFFSET(xmm6H_off ), xmm6->as_VMReg()->next()); map->set_callee_saved(STACK_OFFSET(off), xmm_name->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET(xmm7H_off ), xmm7->as_VMReg()->next()); off += delta;
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());
if (UseAVX > 2) { if (UseAVX > 2) {
map->set_callee_saved(STACK_OFFSET(xmm16H_off), xmm16->as_VMReg()->next()); // Obtain xmm16..xmm31 from the XSAVE area on EVEX enabled targets
map->set_callee_saved(STACK_OFFSET(xmm17H_off), xmm17->as_VMReg()->next()); off = zmm16H_off;
map->set_callee_saved(STACK_OFFSET(xmm18H_off), xmm18->as_VMReg()->next()); delta = zmm17H_off - off;
map->set_callee_saved(STACK_OFFSET(xmm19H_off), xmm19->as_VMReg()->next()); for (int n = 16; n < num_xmm_regs; n++) {
map->set_callee_saved(STACK_OFFSET(xmm20H_off), xmm20->as_VMReg()->next()); XMMRegister xmm_name = as_XMMRegister(n);
map->set_callee_saved(STACK_OFFSET(xmm21H_off), xmm21->as_VMReg()->next()); map->set_callee_saved(STACK_OFFSET(off), xmm_name->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET(xmm22H_off), xmm22->as_VMReg()->next()); off += delta;
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());
} }
} }
@ -391,86 +299,25 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
} }
void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_vectors) { 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) { if (frame::arg_reg_save_area_bytes != 0) {
// Pop arg register save area // Pop arg register save area
__ addptr(rsp, frame::arg_reg_save_area_bytes); __ addptr(rsp, frame::arg_reg_save_area_bytes);
} }
#ifdef COMPILER2 #ifdef COMPILER2
if (restore_vectors) { // On EVEX enabled targets everything is handled in pop fpu state
// Restore upper half of YMM registes (0..15) if ((restore_vectors) && (UseAVX < 3)) {
assert(UseAVX > 0, "512bit vectors are supported only with AVX"); assert(UseAVX > 0, "256/512-bit vectors are supported only with AVX");
assert(MaxVectorSize == 64, "only 512bit vectors are supported now"); assert(MaxVectorSize == 64, "up to 512bit vectors are supported now");
__ vinsertf128h(xmm0, Address(rsp, 0)); int off = 0;
__ vinsertf128h(xmm1, Address(rsp, 16)); // Restore upper half of YMM registes (0..num_xmm_regs)
__ vinsertf128h(xmm2, Address(rsp, 32)); for (int n = 0; n < num_xmm_regs; n++) {
__ vinsertf128h(xmm3, Address(rsp, 48)); __ vinsertf128h(as_XMMRegister(n), Address(rsp, off++*16));
__ 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);
} }
__ addptr(rsp, num_xmm_regs*16);
} }
#else #else
assert(!restore_vectors, "vectors are generated only by C2"); assert(!restore_vectors, "vectors are generated only by C2");

View File

@ -795,6 +795,12 @@ class StubGenerator: public StubCodeGenerator {
void xmm_copy_forward(Register from, Register to_from, Register qword_count) { void xmm_copy_forward(Register from, Register to_from, Register qword_count) {
assert( UseSSE >= 2, "supported cpu only" ); assert( UseSSE >= 2, "supported cpu only" );
Label L_copy_64_bytes_loop, L_copy_64_bytes, L_copy_8_bytes, L_exit; 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 // Copy 64-byte chunks
__ jmpb(L_copy_64_bytes); __ jmpb(L_copy_64_bytes);
__ align(OptoLoopAlignment); __ align(OptoLoopAlignment);
@ -802,8 +808,8 @@ class StubGenerator: public StubCodeGenerator {
if (UseUnalignedLoadStores) { if (UseUnalignedLoadStores) {
if (UseAVX > 2) { if (UseAVX > 2) {
__ evmovdqu(xmm0, Address(from, 0), Assembler::AVX_512bit); __ evmovdqul(xmm0, Address(from, 0), Assembler::AVX_512bit);
__ evmovdqu(Address(from, to_from, Address::times_1, 0), xmm0, Assembler::AVX_512bit); __ evmovdqul(Address(from, to_from, Address::times_1, 0), xmm0, Assembler::AVX_512bit);
} else if (UseAVX == 2) { } else if (UseAVX == 2) {
__ vmovdqu(xmm0, Address(from, 0)); __ vmovdqu(xmm0, Address(from, 0));
__ vmovdqu(Address(from, to_from, Address::times_1, 0), xmm0); __ vmovdqu(Address(from, to_from, Address::times_1, 0), xmm0);
@ -2217,6 +2223,15 @@ class StubGenerator: public StubCodeGenerator {
const XMMRegister xmm_temp4 = xmm5; const XMMRegister xmm_temp4 = xmm5;
__ enter(); // required for proper stackwalking of RuntimeStub frame __ 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(from, from_param);
__ movptr(key, key_param); __ movptr(key, key_param);
@ -2315,6 +2330,15 @@ class StubGenerator: public StubCodeGenerator {
const XMMRegister xmm_temp4 = xmm5; const XMMRegister xmm_temp4 = xmm5;
__ enter(); // required for proper stackwalking of RuntimeStub frame __ 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(from, from_param);
__ movptr(key, key_param); __ movptr(key, key_param);
@ -2441,6 +2465,14 @@ class StubGenerator: public StubCodeGenerator {
__ enter(); // required for proper stackwalking of RuntimeStub frame __ enter(); // required for proper stackwalking of RuntimeStub frame
handleSOERegisters(true /*saving*/); 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 // load registers from incoming parameters
const Address from_param(rbp, 8+0); const Address from_param(rbp, 8+0);
const Address to_param (rbp, 8+4); const Address to_param (rbp, 8+4);
@ -2602,6 +2634,14 @@ class StubGenerator: public StubCodeGenerator {
__ enter(); // required for proper stackwalking of RuntimeStub frame __ enter(); // required for proper stackwalking of RuntimeStub frame
handleSOERegisters(true /*saving*/); 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 // load registers from incoming parameters
const Address from_param(rbp, 8+0); const Address from_param(rbp, 8+0);
const Address to_param (rbp, 8+4); const Address to_param (rbp, 8+4);
@ -2782,6 +2822,14 @@ class StubGenerator: public StubCodeGenerator {
__ enter(); __ enter();
handleSOERegisters(true); // Save registers 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(state, state_param);
__ movptr(subkeyH, subkeyH_param); __ movptr(subkeyH, subkeyH_param);
__ movptr(data, data_param); __ movptr(data, data_param);

View File

@ -269,12 +269,16 @@ class StubGenerator: public StubCodeGenerator {
__ kmovql(k1, rbx); __ kmovql(k1, rbx);
} }
#ifdef _WIN64 #ifdef _WIN64
int last_reg = 15;
if (UseAVX > 2) { if (UseAVX > 2) {
for (int i = 6; i <= 31; i++) { last_reg = 31;
__ movdqu(xmm_save(i), as_XMMRegister(i)); }
if (VM_Version::supports_avx512novl()) {
for (int i = xmm_save_first; i <= last_reg; i++) {
__ vextractf32x4h(xmm_save(i), as_XMMRegister(i), 0);
} }
} else { } 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)); __ movdqu(xmm_save(i), as_XMMRegister(i));
} }
} }
@ -386,13 +390,15 @@ class StubGenerator: public StubCodeGenerator {
// restore regs belonging to calling function // restore regs belonging to calling function
#ifdef _WIN64 #ifdef _WIN64
int xmm_ub = 15;
if (UseAVX > 2) {
xmm_ub = 31;
}
// emit the restores for xmm regs // emit the restores for xmm regs
for (int i = 6; i <= xmm_ub; i++) { if (VM_Version::supports_avx512novl()) {
__ movdqu(as_XMMRegister(i), xmm_save(i)); 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 #endif
__ movptr(r15, r15_save); __ movptr(r15, r15_save);
@ -1342,11 +1348,15 @@ class StubGenerator: public StubCodeGenerator {
__ align(OptoLoopAlignment); __ align(OptoLoopAlignment);
if (UseUnalignedLoadStores) { if (UseUnalignedLoadStores) {
Label L_end; Label L_end;
if (UseAVX > 2) {
__ movl(to, 0xffff);
__ kmovql(k1, to);
}
// Copy 64-bytes per iteration // Copy 64-bytes per iteration
__ BIND(L_loop); __ BIND(L_loop);
if (UseAVX > 2) { if (UseAVX > 2) {
__ evmovdqu(xmm0, Address(end_from, qword_count, Address::times_8, -56), Assembler::AVX_512bit); __ evmovdqul(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(Address(end_to, qword_count, Address::times_8, -56), xmm0, Assembler::AVX_512bit);
} else if (UseAVX == 2) { } else if (UseAVX == 2) {
__ vmovdqu(xmm0, Address(end_from, qword_count, Address::times_8, -56)); __ vmovdqu(xmm0, Address(end_from, qword_count, Address::times_8, -56));
__ vmovdqu(Address(end_to, qword_count, Address::times_8, -56), xmm0); __ vmovdqu(Address(end_to, qword_count, Address::times_8, -56), xmm0);
@ -1422,11 +1432,15 @@ class StubGenerator: public StubCodeGenerator {
__ align(OptoLoopAlignment); __ align(OptoLoopAlignment);
if (UseUnalignedLoadStores) { if (UseUnalignedLoadStores) {
Label L_end; Label L_end;
if (UseAVX > 2) {
__ movl(to, 0xffff);
__ kmovql(k1, to);
}
// Copy 64-bytes per iteration // Copy 64-bytes per iteration
__ BIND(L_loop); __ BIND(L_loop);
if (UseAVX > 2) { if (UseAVX > 2) {
__ evmovdqu(xmm0, Address(from, qword_count, Address::times_8, 32), Assembler::AVX_512bit); __ evmovdqul(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(Address(dest, qword_count, Address::times_8, 32), xmm0, Assembler::AVX_512bit);
} else if (UseAVX == 2) { } else if (UseAVX == 2) {
__ vmovdqu(xmm0, Address(from, qword_count, Address::times_8, 32)); __ vmovdqu(xmm0, Address(from, qword_count, Address::times_8, 32));
__ vmovdqu(Address(dest, qword_count, Address::times_8, 32), xmm0); __ 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 __ 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} // keylen could be only {11, 13, 15} * 4 = {44, 52, 60}
__ movl(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT))); __ movl(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT)));
@ -3200,6 +3222,14 @@ class StubGenerator: public StubCodeGenerator {
__ enter(); // required for proper stackwalking of RuntimeStub frame __ 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} // keylen could be only {11, 13, 15} * 4 = {44, 52, 60}
__ movl(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT))); __ movl(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT)));
@ -3312,6 +3342,14 @@ class StubGenerator: public StubCodeGenerator {
__ enter(); // required for proper stackwalking of RuntimeStub frame __ 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 #ifdef _WIN64
// on win64, fill len_reg from stack position // on win64, fill len_reg from stack position
__ movl(len_reg, len_mem); __ movl(len_reg, len_mem);
@ -3508,6 +3546,14 @@ class StubGenerator: public StubCodeGenerator {
__ enter(); // required for proper stackwalking of RuntimeStub frame __ 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 #ifdef _WIN64
// on win64, fill len_reg from stack position // on win64, fill len_reg from stack position
__ movl(len_reg, len_mem); __ movl(len_reg, len_mem);
@ -3746,6 +3792,14 @@ class StubGenerator: public StubCodeGenerator {
__ enter(); __ 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 #ifdef _WIN64
// save the xmm registers which must be preserved 6-10 // save the xmm registers which must be preserved 6-10
__ subptr(rsp, -rsp_after_call_off * wordSize); __ subptr(rsp, -rsp_after_call_off * wordSize);

View File

@ -31,7 +31,7 @@
enum platform_dependent_constants { enum platform_dependent_constants {
code_size1 = 9000, // simply increase if too small (assembler will crash if too small) 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 { class x86 {

View File

@ -33,7 +33,7 @@ static bool returns_to_call_stub(address return_pc) { return return_pc == _
enum platform_dependent_constants { enum platform_dependent_constants {
code_size1 = 19000, // simply increase if too small (assembler will crash if too small) 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 { class x86 {

View File

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

View File

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

View File

@ -1661,46 +1661,55 @@ const bool Matcher::match_rule_supported(int opcode) {
if (!has_match_rule(opcode)) if (!has_match_rule(opcode))
return false; return false;
bool ret_value = true;
switch (opcode) { switch (opcode) {
case Op_PopCountI: case Op_PopCountI:
case Op_PopCountL: case Op_PopCountL:
if (!UsePopCountInstruction) if (!UsePopCountInstruction)
return false; ret_value = false;
break; break;
case Op_MulVI: case Op_MulVI:
if ((UseSSE < 4) && (UseAVX < 1)) // only with SSE4_1 or AVX if ((UseSSE < 4) && (UseAVX < 1)) // only with SSE4_1 or AVX
return false; ret_value = false;
break; break;
case Op_MulVL: case Op_MulVL:
case Op_MulReductionVL: case Op_MulReductionVL:
if (VM_Version::supports_avx512dq() == false) if (VM_Version::supports_avx512dq() == false)
return false; ret_value = false;
break;
case Op_AddReductionVL: case Op_AddReductionVL:
if (UseAVX < 3) // only EVEX : vector connectivity becomes an issue here if (UseAVX < 3) // only EVEX : vector connectivity becomes an issue here
return false; ret_value = false;
break;
case Op_AddReductionVI: case Op_AddReductionVI:
if (UseSSE < 3) // requires at least SSE3 if (UseSSE < 3) // requires at least SSE3
return false; ret_value = false;
break;
case Op_MulReductionVI: case Op_MulReductionVI:
if (UseSSE < 4) // requires at least SSE4 if (UseSSE < 4) // requires at least SSE4
return false; ret_value = false;
break;
case Op_AddReductionVF: case Op_AddReductionVF:
case Op_AddReductionVD: case Op_AddReductionVD:
case Op_MulReductionVF: case Op_MulReductionVF:
case Op_MulReductionVD: case Op_MulReductionVD:
if (UseSSE < 1) // requires at least SSE if (UseSSE < 1) // requires at least SSE
return false; ret_value = false;
break; break;
case Op_SqrtVD:
if (UseAVX < 1) // enabled for AVX only
ret_value = false;
break;
case Op_CompareAndSwapL: case Op_CompareAndSwapL:
#ifdef _LP64 #ifdef _LP64
case Op_CompareAndSwapP: case Op_CompareAndSwapP:
#endif #endif
if (!VM_Version::supports_cx8()) if (!VM_Version::supports_cx8())
return false; ret_value = false;
break; 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. // 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_DOUBLE:
case T_LONG: case T_LONG:
if (size < 16) return 0; if (size < 16) return 0;
break;
case T_FLOAT: case T_FLOAT:
case T_INT: case T_INT:
if (size < 8) return 0; if (size < 8) return 0;
break;
case T_BOOLEAN: case T_BOOLEAN:
case T_BYTE: if (size < 4) return 0;
break;
case T_CHAR: 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: case T_SHORT:
if (size < 4) return 0; if (size < 4) return 0;
if ((size > 16) && !VM_Version::supports_avx512bw()) return 0;
break; break;
default: default:
ShouldNotReachHere(); 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])); __ vmovdqu(as_XMMRegister(Matcher::_regEncode[dst_lo]), as_XMMRegister(Matcher::_regEncode[src_lo]));
break; break;
case Op_VecZ: 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; break;
default: default:
ShouldNotReachHere(); 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)); __ vmovdqu(as_XMMRegister(Matcher::_regEncode[reg]), Address(rsp, stack_offset));
break; break;
case Op_VecZ: 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; break;
default: default:
ShouldNotReachHere(); 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])); __ vmovdqu(Address(rsp, stack_offset), as_XMMRegister(Matcher::_regEncode[reg]));
break; break;
case Op_VecZ: 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; break;
default: default:
ShouldNotReachHere(); ShouldNotReachHere();
@ -1929,9 +1948,40 @@ static int vec_spill_helper(CodeBuffer *cbuf, bool do_size, bool is_load,
} }
#endif #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. // 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) { static inline jfloat replicate4_imm(int con, int width) {
@ -2675,11 +2725,10 @@ instruct negF_reg_reg(regF dst, regF src) %{
predicate(UseAVX > 0); predicate(UseAVX > 0);
match(Set dst (NegF src)); match(Set dst (NegF src));
ins_cost(150); 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 %{ ins_encode %{
int vector_len = 0; __ vnegatess($dst$$XMMRegister, $src$$XMMRegister,
__ vxorps($dst$$XMMRegister, $src$$XMMRegister, ExternalAddress(float_signflip()));
ExternalAddress(float_signflip()), vector_len);
%} %}
ins_pipe(pipe_slow); ins_pipe(pipe_slow);
%} %}
@ -2700,12 +2749,11 @@ instruct negD_reg_reg(regD dst, regD src) %{
predicate(UseAVX > 0); predicate(UseAVX > 0);
match(Set dst (NegD src)); match(Set dst (NegD src));
ins_cost(150); ins_cost(150);
format %{ "vxorpd $dst, $src, [0x8000000000000000]\t" format %{ "vnegatess $dst, $src, [0x8000000000000000]\t"
"# neg double by sign flipping" %} "# neg double by sign flipping" %}
ins_encode %{ ins_encode %{
int vector_len = 0; __ vnegatesd($dst$$XMMRegister, $src$$XMMRegister,
__ vxorpd($dst$$XMMRegister, $src$$XMMRegister, ExternalAddress(double_signflip()));
ExternalAddress(double_signflip()), vector_len);
%} %}
ins_pipe(pipe_slow); ins_pipe(pipe_slow);
%} %}
@ -2838,7 +2886,7 @@ instruct loadV64(vecZ dst, memory mem) %{
format %{ "vmovdqu $dst k0,$mem\t! load vector (64 bytes)" %} format %{ "vmovdqu $dst k0,$mem\t! load vector (64 bytes)" %}
ins_encode %{ ins_encode %{
int vector_len = 2; int vector_len = 2;
__ evmovdqu($dst$$XMMRegister, $mem$$Address, vector_len); __ evmovdqul($dst$$XMMRegister, $mem$$Address, vector_len);
%} %}
ins_pipe( pipe_slow ); ins_pipe( pipe_slow );
%} %}
@ -2895,7 +2943,7 @@ instruct storeV64(memory mem, vecZ src) %{
format %{ "vmovdqu $mem k0,$src\t! store vector (64 bytes)" %} format %{ "vmovdqu $mem k0,$src\t! store vector (64 bytes)" %}
ins_encode %{ ins_encode %{
int vector_len = 2; int vector_len = 2;
__ evmovdqu($mem$$Address, $src$$XMMRegister, vector_len); __ evmovdqul($mem$$Address, $src$$XMMRegister, vector_len);
%} %}
ins_pipe( pipe_slow ); ins_pipe( pipe_slow );
%} %}
@ -3315,6 +3363,37 @@ instruct Repl8F_mem(vecY dst, memory mem) %{
ins_pipe( pipe_slow ); 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) %{ instruct Repl2D_mem(vecX dst, memory mem) %{
predicate(n->as_Vector()->length() == 2 && UseAVX > 0 && !VM_Version::supports_avx512vl()); predicate(n->as_Vector()->length() == 2 && UseAVX > 0 && !VM_Version::supports_avx512vl());
match(Set dst (ReplicateD (LoadD mem))); match(Set dst (ReplicateD (LoadD mem)));
@ -3349,6 +3428,28 @@ instruct Repl4D_mem(vecY dst, memory mem) %{
ins_pipe( pipe_slow ); 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========================================== // ====================GENERIC REPLICATE==========================================
// Replicate byte scalar to be vector // Replicate byte scalar to be vector
@ -3680,38 +3781,6 @@ instruct Repl4F(vecX dst, regF src) %{
ins_pipe( pipe_slow ); 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 // Replicate double (8 bytes) scalar to be vector
instruct Repl2D(vecX dst, regD src) %{ instruct Repl2D(vecX dst, regD src) %{
predicate(n->as_Vector()->length() == 2); predicate(n->as_Vector()->length() == 2);
@ -3723,28 +3792,6 @@ instruct Repl2D(vecX dst, regD src) %{
ins_pipe( pipe_slow ); 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============================================= // ====================EVEX REPLICATE=============================================
instruct Repl4B_mem_evex(vecS dst, memory mem) %{ 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) %{ 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)); match(Set dst (ReplicateB src));
format %{ "vpbroadcastb $dst,$src\t! upper replicate64B" %} format %{ "vpbroadcastb $dst,$src\t! upper replicate64B" %}
ins_encode %{ ins_encode %{
@ -3825,7 +3872,7 @@ instruct Repl64B_evex(vecZ dst, rRegI src) %{
%} %}
instruct Repl64B_mem_evex(vecZ dst, memory mem) %{ 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))); match(Set dst (ReplicateB (LoadB mem)));
format %{ "vpbroadcastb $dst,$mem\t! replicate64B" %} format %{ "vpbroadcastb $dst,$mem\t! replicate64B" %}
ins_encode %{ ins_encode %{
@ -3862,7 +3909,7 @@ instruct Repl32B_imm_evex(vecY dst, immI con) %{
%} %}
instruct Repl64B_imm_evex(vecZ 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)); match(Set dst (ReplicateB con));
format %{ "movq $dst,[$constantaddress]\n\t" format %{ "movq $dst,[$constantaddress]\n\t"
"vpbroadcastb $dst,$dst\t! upper replicate64B" %} "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) %{ 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)); match(Set dst (ReplicateS src));
format %{ "vpbroadcastw $dst,$src\t! replicate32S" %} format %{ "vpbroadcastw $dst,$src\t! replicate32S" %}
ins_encode %{ ins_encode %{
@ -3964,7 +4011,7 @@ instruct Repl32S_evex(vecZ dst, rRegI src) %{
%} %}
instruct Repl32S_mem_evex(vecZ dst, memory mem) %{ 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))); match(Set dst (ReplicateS (LoadS mem)));
format %{ "vpbroadcastw $dst,$mem\t! replicate32S" %} format %{ "vpbroadcastw $dst,$mem\t! replicate32S" %}
ins_encode %{ ins_encode %{
@ -4001,7 +4048,7 @@ instruct Repl16S_imm_evex(vecY dst, immI con) %{
%} %}
instruct Repl32S_imm_evex(vecZ 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)); match(Set dst (ReplicateS con));
format %{ "movq $dst,[$constantaddress]\n\t" format %{ "movq $dst,[$constantaddress]\n\t"
"vpbroadcastw $dst,$dst\t! replicate32S" %} "vpbroadcastw $dst,$dst\t! replicate32S" %}
@ -4318,13 +4365,50 @@ instruct Repl16F_mem_evex(vecZ dst, memory mem) %{
ins_pipe( pipe_slow ); 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) %{ instruct Repl16F_zero_evex(vecZ dst, immF0 zero) %{
predicate(n->as_Vector()->length() == 16 && UseAVX > 2); predicate(n->as_Vector()->length() == 16 && UseAVX > 2);
match(Set dst (ReplicateF zero)); 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 %{ 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; 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 ); ins_pipe( fpu_reg_reg );
%} %}
@ -4373,13 +4457,38 @@ instruct Repl8D_mem_evex(vecZ dst, memory mem) %{
ins_pipe( pipe_slow ); 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) %{ instruct Repl8D_zero_evex(vecZ dst, immD0 zero) %{
predicate(n->as_Vector()->length() == 8 && UseAVX > 2); predicate(n->as_Vector()->length() == 8 && UseAVX > 2);
match(Set dst (ReplicateD zero)); 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 %{ 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; 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 ); ins_pipe( fpu_reg_reg );
%} %}
@ -7474,6 +7583,75 @@ instruct vshiftcnt(vecS dst, rRegI cnt) %{
ins_pipe( pipe_slow ); 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 ----------------------------------- // ------------------------------ LeftShift -----------------------------------
// Shorts/Chars vector left shift // Shorts/Chars vector left shift

View File

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

View File

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

View File

@ -2211,9 +2211,13 @@ void os::pd_print_cpu_info(outputStream* st, char* buf, size_t buflen) {
} }
} }
const char* search_string = IA32_ONLY("model name") AMD64_ONLY("model name") #if defined(AMD64) || defined(IA32) || defined(X32)
IA64_ONLY("") SPARC_ONLY("cpu") const char* search_string = "model name";
ARM32_ONLY("Processor") PPC_ONLY("Processor") AARCH64_ONLY("Processor"); #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. // Parses the cpuinfo file for string representing the model name.
void os::get_summary_cpu_info(char* cpuinfo, size_t length) { 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 // 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) // /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") #if defined(AMD64)
IA64_ONLY("IA64") SPARC_ONLY("sparcv9") strncpy(cpuinfo, "x86_64", length);
ARM32_ONLY("ARM") PPC_ONLY("PPC64") AARCH64_ONLY("AArch64"), 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) { void os::print_siginfo(outputStream* st, void* siginfo) {

View File

@ -4877,6 +4877,26 @@ char* os::pd_remap_memory(int fd, const char* file_name, size_t file_offset,
// Returns true=success, otherwise false. // Returns true=success, otherwise false.
bool os::pd_unmap_memory(char* addr, size_t bytes) { 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); BOOL result = UnmapViewOfFile(addr);
if (result == 0) { if (result == 0) {
if (PrintMiscellaneous && Verbose) { if (PrintMiscellaneous && Verbose) {

View File

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

View File

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

View File

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

View File

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

View File

@ -29,7 +29,7 @@
#include "gc/g1/g1HotCardCache.hpp" #include "gc/g1/g1HotCardCache.hpp"
#include "runtime/java.hpp" #include "runtime/java.hpp"
ConcurrentG1Refine::ConcurrentG1Refine(G1CollectedHeap* g1h, CardTableEntryClosure* refine_closure) : ConcurrentG1Refine::ConcurrentG1Refine(G1CollectedHeap* g1h) :
_threads(NULL), _n_threads(0), _threads(NULL), _n_threads(0),
_hot_card_cache(g1h) _hot_card_cache(g1h)
{ {
@ -48,29 +48,46 @@ ConcurrentG1Refine::ConcurrentG1Refine(G1CollectedHeap* g1h, CardTableEntryClosu
FLAG_SET_DEFAULT(G1ConcRefinementRedZone, yellow_zone() * 2); FLAG_SET_DEFAULT(G1ConcRefinementRedZone, yellow_zone() * 2);
} }
set_red_zone(MAX2<int>(G1ConcRefinementRedZone, yellow_zone())); 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. // 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(); uint worker_id_offset = DirtyCardQueueSet::num_par_ids();
ConcurrentG1RefineThread *next = NULL; ConcurrentG1RefineThread *next = NULL;
for (uint i = _n_threads - 1; i != UINT_MAX; i--) { for (uint i = cg1r->_n_threads - 1; i != UINT_MAX; i--) {
ConcurrentG1RefineThread* t = new ConcurrentG1RefineThread(this, next, refine_closure, worker_id_offset, i); ConcurrentG1RefineThread* t = new ConcurrentG1RefineThread(cg1r, next, refine_closure, worker_id_offset, i);
assert(t != NULL, "Conc refine should have been created"); assert(t != NULL, "Conc refine should have been created");
if (t->osthread() == NULL) { 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"); assert(t->cg1r() == cg1r, "Conc refine thread should refer to this");
_threads[i] = t; cg1r->_threads[i] = t;
next = t; next = t;
} }
*ecode = JNI_OK;
return cg1r;
} }
void ConcurrentG1Refine::reset_threshold_step() { void ConcurrentG1Refine::reset_threshold_step() {

View File

@ -71,10 +71,15 @@ class ConcurrentG1Refine: public CHeapObj<mtGC> {
// Reset the threshold step value based of the current zone boundaries. // Reset the threshold step value based of the current zone boundaries.
void reset_threshold_step(); void reset_threshold_step();
ConcurrentG1Refine(G1CollectedHeap* g1h);
public: public:
ConcurrentG1Refine(G1CollectedHeap* g1h, CardTableEntryClosure* refine_closure);
~ConcurrentG1Refine(); ~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 init(G1RegionToSpaceMapper* card_counts_storage);
void stop(); void stop();

View File

@ -2025,7 +2025,6 @@ G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* policy_) :
_survivor_evac_stats(YoungPLABSize, PLABWeight), _survivor_evac_stats(YoungPLABSize, PLABWeight),
_old_evac_stats(OldPLABSize, PLABWeight), _old_evac_stats(OldPLABSize, PLABWeight),
_expand_heap_after_alloc_failure(true), _expand_heap_after_alloc_failure(true),
_surviving_young_words(NULL),
_old_marking_cycles_started(0), _old_marking_cycles_started(0),
_old_marking_cycles_completed(0), _old_marking_cycles_completed(0),
_heap_summary_sent(false), _heap_summary_sent(false),
@ -2126,7 +2125,11 @@ jint G1CollectedHeap::initialize() {
_refine_cte_cl = new RefineCardTableEntryClosure(); _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. // Reserve the maximum.
@ -2397,6 +2400,10 @@ void G1CollectedHeap::ref_processing_init() {
// (for efficiency/performance) // (for efficiency/performance)
} }
CollectorPolicy* G1CollectedHeap::collector_policy() const {
return g1_policy();
}
size_t G1CollectedHeap::capacity() const { size_t G1CollectedHeap::capacity() const {
return _hrm.length() * HeapRegion::GrainBytes; return _hrm.length() * HeapRegion::GrainBytes;
} }
@ -3694,10 +3701,6 @@ size_t G1CollectedHeap::pending_card_num() {
return (buffer_size * buffer_num + extra_cards) / oopSize; return (buffer_size * buffer_num + extra_cards) / oopSize;
} }
size_t G1CollectedHeap::cards_scanned() {
return g1_rem_set()->cardsScanned();
}
class RegisterHumongousWithInCSetFastTestClosure : public HeapRegionClosure { class RegisterHumongousWithInCSetFastTestClosure : public HeapRegionClosure {
private: private:
size_t _total_humongous; size_t _total_humongous;
@ -3838,36 +3841,6 @@ void G1CollectedHeap::register_humongous_regions_with_cset() {
cl.flush_rem_set_entries(); 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 #ifdef ASSERT
class VerifyCSetClosure: public HeapRegionClosure { class VerifyCSetClosure: public HeapRegionClosure {
public: 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); g1_policy()->print_collection_set(g1_policy()->inc_cset_head(), gclog_or_tty);
#endif // YOUNG_LIST_VERBOSE #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()); 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); collection_set_iterate(&cl);
#endif // ASSERT #endif // ASSERT
setup_surviving_young_words();
// Initialize the GC alloc regions. // Initialize the GC alloc regions.
_allocator->init_gc_alloc_regions(evacuation_info); _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... // 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(); eagerly_reclaim_humongous_regions();
g1_policy()->clear_collection_set(); g1_policy()->clear_collection_set();
cleanup_surviving_young_words();
// Start a new incremental collection set for the next pause. // Start a new incremental collection set for the next pause.
g1_policy()->start_incremental_cset_building(); 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. // investigate this in CR 7178365.
double sample_end_time_sec = os::elapsedTime(); double sample_end_time_sec = os::elapsedTime();
double pause_time_ms = (sample_end_time_sec - sample_start_time_sec) * MILLIUNITS; 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_collectionset_used_before(g1_policy()->collection_set_bytes_used_before());
evacuation_info.set_bytes_copied(g1_policy()->bytes_copied_during_gc()); evacuation_info.set_bytes_copied(g1_policy()->bytes_copied_during_gc());
@ -4541,15 +4514,15 @@ class G1KlassScanClosure : public KlassClosure {
class G1ParTask : public AbstractGangTask { class G1ParTask : public AbstractGangTask {
protected: protected:
G1CollectedHeap* _g1h; G1CollectedHeap* _g1h;
G1ParScanThreadState** _pss; G1ParScanThreadStateSet* _pss;
RefToScanQueueSet* _queues; RefToScanQueueSet* _queues;
G1RootProcessor* _root_processor; G1RootProcessor* _root_processor;
ParallelTaskTerminator _terminator; ParallelTaskTerminator _terminator;
uint _n_workers; uint _n_workers;
public: 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"), : AbstractGangTask("G1 collection"),
_g1h(g1h), _g1h(g1h),
_pss(per_thread_states), _pss(per_thread_states),
@ -4607,7 +4580,7 @@ public:
ReferenceProcessor* rp = _g1h->ref_processor_stw(); ReferenceProcessor* rp = _g1h->ref_processor_stw();
G1ParScanThreadState* pss = _pss[worker_id]; G1ParScanThreadState* pss = _pss->state_for_worker(worker_id);
pss->set_ref_processor(rp); pss->set_ref_processor(rp);
bool only_young = _g1h->collector_state()->gcs_are_young(); bool only_young = _g1h->collector_state()->gcs_are_young();
@ -4664,9 +4637,12 @@ public:
worker_id); worker_id);
G1ParPushHeapRSClosure push_heap_rs_cl(_g1h, pss); G1ParPushHeapRSClosure push_heap_rs_cl(_g1h, pss);
_g1h->g1_rem_set()->oops_into_collection_set_do(&push_heap_rs_cl, size_t cards_scanned = _g1h->g1_rem_set()->oops_into_collection_set_do(&push_heap_rs_cl,
weak_root_cl, weak_root_cl,
worker_id); worker_id);
_pss->add_cards_scanned(worker_id, cards_scanned);
double strong_roots_sec = os::elapsedTime() - start_strong_roots_sec; double strong_roots_sec = os::elapsedTime() - start_strong_roots_sec;
double term_sec = 0.0; double term_sec = 0.0;
@ -5263,15 +5239,15 @@ public:
class G1STWRefProcTaskExecutor: public AbstractRefProcTaskExecutor { class G1STWRefProcTaskExecutor: public AbstractRefProcTaskExecutor {
private: private:
G1CollectedHeap* _g1h; G1CollectedHeap* _g1h;
G1ParScanThreadState** _pss; G1ParScanThreadStateSet* _pss;
RefToScanQueueSet* _queues; RefToScanQueueSet* _queues;
WorkGang* _workers; WorkGang* _workers;
uint _active_workers; uint _active_workers;
public: public:
G1STWRefProcTaskExecutor(G1CollectedHeap* g1h, G1STWRefProcTaskExecutor(G1CollectedHeap* g1h,
G1ParScanThreadState** per_thread_states, G1ParScanThreadStateSet* per_thread_states,
WorkGang* workers, WorkGang* workers,
RefToScanQueueSet *task_queues, RefToScanQueueSet *task_queues,
uint n_workers) : uint n_workers) :
@ -5295,14 +5271,14 @@ class G1STWRefProcTaskProxy: public AbstractGangTask {
typedef AbstractRefProcTaskExecutor::ProcessTask ProcessTask; typedef AbstractRefProcTaskExecutor::ProcessTask ProcessTask;
ProcessTask& _proc_task; ProcessTask& _proc_task;
G1CollectedHeap* _g1h; G1CollectedHeap* _g1h;
G1ParScanThreadState** _pss; G1ParScanThreadStateSet* _pss;
RefToScanQueueSet* _task_queues; RefToScanQueueSet* _task_queues;
ParallelTaskTerminator* _terminator; ParallelTaskTerminator* _terminator;
public: public:
G1STWRefProcTaskProxy(ProcessTask& proc_task, G1STWRefProcTaskProxy(ProcessTask& proc_task,
G1CollectedHeap* g1h, G1CollectedHeap* g1h,
G1ParScanThreadState** per_thread_states, G1ParScanThreadStateSet* per_thread_states,
RefToScanQueueSet *task_queues, RefToScanQueueSet *task_queues,
ParallelTaskTerminator* terminator) : ParallelTaskTerminator* terminator) :
AbstractGangTask("Process reference objects in parallel"), AbstractGangTask("Process reference objects in parallel"),
@ -5320,7 +5296,7 @@ public:
G1STWIsAliveClosure is_alive(_g1h); G1STWIsAliveClosure is_alive(_g1h);
G1ParScanThreadState* pss = _pss[worker_id]; G1ParScanThreadState* pss = _pss->state_for_worker(worker_id);
pss->set_ref_processor(NULL); pss->set_ref_processor(NULL);
G1ParScanExtRootClosure only_copy_non_heap_cl(_g1h, pss); G1ParScanExtRootClosure only_copy_non_heap_cl(_g1h, pss);
@ -5399,14 +5375,14 @@ void G1STWRefProcTaskExecutor::execute(EnqueueTask& enq_task) {
class G1ParPreserveCMReferentsTask: public AbstractGangTask { class G1ParPreserveCMReferentsTask: public AbstractGangTask {
protected: protected:
G1CollectedHeap* _g1h; G1CollectedHeap* _g1h;
G1ParScanThreadState** _pss; G1ParScanThreadStateSet* _pss;
RefToScanQueueSet* _queues; RefToScanQueueSet* _queues;
ParallelTaskTerminator _terminator; ParallelTaskTerminator _terminator;
uint _n_workers; uint _n_workers;
public: 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"), AbstractGangTask("ParPreserveCMReferents"),
_g1h(g1h), _g1h(g1h),
_pss(per_thread_states), _pss(per_thread_states),
@ -5419,7 +5395,7 @@ public:
ResourceMark rm; ResourceMark rm;
HandleMark hm; HandleMark hm;
G1ParScanThreadState* pss = _pss[worker_id]; G1ParScanThreadState* pss = _pss->state_for_worker(worker_id);
pss->set_ref_processor(NULL); pss->set_ref_processor(NULL);
assert(pss->queue_is_empty(), "both queue and overflow should be empty"); 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). // 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(); double ref_proc_start = os::elapsedTime();
ReferenceProcessor* rp = _ref_processor_stw; ReferenceProcessor* rp = _ref_processor_stw;
@ -5525,7 +5501,7 @@ void G1CollectedHeap::process_discovered_references(G1ParScanThreadState** per_t
// JNI refs. // JNI refs.
// Use only a single queue for this PSS. // 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); pss->set_ref_processor(NULL);
assert(pss->queue_is_empty(), "pre-condition"); 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). // 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(); double ref_enq_start = os::elapsedTime();
ReferenceProcessor* rp = _ref_processor_stw; 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); 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; _expand_heap_after_alloc_failure = true;
_evacuation_failed = false; _evacuation_failed = false;
@ -5641,11 +5617,6 @@ void G1CollectedHeap::evacuate_collection_set(EvacuationInfo& evacuation_info) {
double start_par_time_sec = os::elapsedTime(); double start_par_time_sec = os::elapsedTime();
double end_par_time_sec; 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); G1RootProcessor root_processor(this, n_workers);
G1ParTask g1_par_task(this, per_thread_states, _task_queues, &root_processor, 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); _allocator->release_gc_alloc_regions(evacuation_info);
g1_rem_set()->cleanup_after_oops_into_collection_set_do(); g1_rem_set()->cleanup_after_oops_into_collection_set_do();
for (uint i = 0; i < n_workers; i++) { per_thread_states->flush();
G1ParScanThreadState* pss = per_thread_states[i];
delete pss;
}
FREE_C_HEAP_ARRAY(G1ParScanThreadState*, per_thread_states);
record_obj_copy_mem_stats(); record_obj_copy_mem_stats();
@ -6054,7 +6021,7 @@ void G1CollectedHeap::cleanUpCardTable() {
g1_policy()->phase_times()->record_clear_ct_time(elapsed * 1000.0); 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; size_t pre_used = 0;
FreeRegionList local_free_list("Local List for CSet Freeing"); 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(); int index = cur->young_index_in_cset();
assert(index != -1, "invariant"); assert(index != -1, "invariant");
assert((uint) index < policy->young_cset_region_length(), "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); cur->record_surv_words_in_group(words_survived);
// At this point the we have 'popped' cur from the collection set // At this point the we have 'popped' cur from the collection set

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -32,7 +32,7 @@
#include "oops/oop.inline.hpp" #include "oops/oop.inline.hpp"
#include "runtime/prefetch.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), : _g1h(g1h),
_refs(g1h->task_queue(worker_id)), _refs(g1h->task_queue(worker_id)),
_dcq(&g1h->dirty_card_queue_set()), _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) // non-young regions (where the age is -1)
// We also add a few elements at the beginning and at the end in // We also add a few elements at the beginning and at the end in
// an attempt to eliminate cache contention // an attempt to eliminate cache contention
uint real_length = 1 + _g1h->g1_policy()->young_cset_region_length(); size_t real_length = 1 + young_cset_length;
uint array_length = PADDING_ELEM_NUM + size_t array_length = PADDING_ELEM_NUM +
real_length + real_length +
PADDING_ELEM_NUM; PADDING_ELEM_NUM;
_surviving_young_words_base = NEW_C_HEAP_ARRAY(size_t, array_length, mtGC); _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, vm_exit_out_of_memory(array_length * sizeof(size_t), OOM_MALLOC_ERROR,
"Not enough space for young surv histo."); "Not enough space for young surv histo.");
_surviving_young_words = _surviving_young_words_base + PADDING_ELEM_NUM; _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()); _plab_allocator = G1PLABAllocator::create_allocator(_g1h->allocator());
@ -71,13 +71,21 @@ G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint worker_id)
_dest[InCSetState::Old] = InCSetState::Old; _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. // Update allocation statistics.
_plab_allocator->flush_and_retire_stats(); _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; 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); 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) { oop G1ParScanThreadState::handle_evacuation_failure_par(oop old, markOop m) {
assert(_g1h->obj_in_cs(old), assert(_g1h->obj_in_cs(old),
err_msg("Object " PTR_FORMAT " should be in the CSet", p2i(old))); err_msg("Object " PTR_FORMAT " should be in the CSet", p2i(old)));

View File

@ -82,7 +82,7 @@ class G1ParScanThreadState : public CHeapObj<mtGC> {
} }
public: public:
G1ParScanThreadState(G1CollectedHeap* g1h, uint worker_id); G1ParScanThreadState(G1CollectedHeap* g1h, uint worker_id, size_t young_cset_length);
~G1ParScanThreadState(); ~G1ParScanThreadState();
void set_ref_processor(ReferenceProcessor* rp) { _scanner.set_ref_processor(rp); } 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; return _surviving_young_words + 1;
} }
void flush(size_t* surviving_young_words);
private: private:
#define G1_PARTIAL_ARRAY_MASK 0x2 #define G1_PARTIAL_ARRAY_MASK 0x2
@ -189,4 +191,48 @@ class G1ParScanThreadState : public CHeapObj<mtGC> {
oop handle_evacuation_failure_par(oop obj, markOop m); 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 #endif // SHARE_VM_GC_G1_G1PARSCANTHREADSTATE_HPP

View File

@ -0,0 +1,31 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "gc/g1/g1ParScanThreadState.hpp"
G1ParScanThreadState* G1ParScanThreadStateSet::new_par_scan_state(uint worker_id, size_t young_cset_length) {
return new G1ParScanThreadState(_g1h, worker_id, young_cset_length);
}

View File

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

View File

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

View File

@ -87,7 +87,7 @@ class ParallelScavengeHeap : public CollectedHeap {
return CollectedHeap::ParallelScavengeHeap; 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 PSYoungGen* young_gen() { return _young_gen; }
static PSOldGen* old_gen() { return _old_gen; } static PSOldGen* old_gen() { return _old_gen; }

View File

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

View File

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

View File

@ -28,7 +28,6 @@
#include "gc/shared/collectorPolicy.hpp" #include "gc/shared/collectorPolicy.hpp"
#include "gc/shared/gcPolicyCounters.hpp" #include "gc/shared/gcPolicyCounters.hpp"
#include "memory/resourceArea.hpp" #include "memory/resourceArea.hpp"
#include "runtime/atomic.inline.hpp"
#include "utilities/copy.hpp" #include "utilities/copy.hpp"
/* Copyright (c) 1992, 2015, Oracle and/or its affiliates, and Stanford University. /* 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) { uint ageTable::compute_tenuring_threshold(size_t survivor_capacity, GCPolicyCounters* gc_counters) {
size_t desired_survivor_size = (size_t)((((double) survivor_capacity)*TargetSurvivorRatio)/100); size_t desired_survivor_size = (size_t)((((double) survivor_capacity)*TargetSurvivorRatio)/100);
uint result; uint result;

View File

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

View File

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

View File

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

View File

@ -153,7 +153,7 @@ public:
// The generational collector policy. // The generational collector policy.
GenCollectorPolicy* gen_policy() const { return _gen_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 // Adaptive size policy
virtual AdaptiveSizePolicy* size_policy() { virtual AdaptiveSizePolicy* size_policy() {

View File

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

View File

@ -858,18 +858,29 @@ bool IfNode::fold_compares_helper(ProjNode* proj, ProjNode* success, ProjNode* f
// this_bool = <= // this_bool = <=
// dom_bool = >= (proj = True) or dom_bool = < (proj = False) // dom_bool = >= (proj = True) or dom_bool = < (proj = False)
// x in [a, b] on the fail (= True) projection, b+1 > a-1: // 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) // dom_bool = > (proj = True) or dom_bool = <= (proj = False)
// x in ]a, b] on the fail (= True) projection b+1 > a: // 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, 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::lt) {
if (hi_test == BoolTest::le) { 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 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; 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) { } 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 // lo = b, hi = a, adjusted_lim = a-b, cond = >=u
// dom_bool = <= (proj = True) or dom_bool = > (proj = False) // dom_bool = <= (proj = True) or dom_bool = > (proj = False)
// x in [b, a] on the fail (= False) projection, a+1 > b-1: // 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 = <= // this_bool = <=
// dom_bool = < (proj = True) or dom_bool = >= (proj = False) // dom_bool = < (proj = True) or dom_bool = >= (proj = False)
// x in ]b, a[ on the fail (= False) projection, a > b: // 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) // dom_bool = <= (proj = True) or dom_bool = > (proj = False)
// x in ]b, a] on the fail (= False) projection, a+1 > b: // 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, 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, hi);
swap(lo_type, hi_type); 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; cond = (hi_test == BoolTest::le || hi_test == BoolTest::gt) ? BoolTest::gt : BoolTest::ge;
if (lo_test == BoolTest::le) { if (lo_test == BoolTest::lt) {
if (cond == BoolTest::gt) { 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 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; cond = BoolTest::ge;
} }
lo = igvn->transform(new AddINode(lo, igvn->intcon(1)));
} }
} else { } else {
const TypeInt* failtype = filtered_int_type(igvn, n, proj); const TypeInt* failtype = filtered_int_type(igvn, n, proj);
if (failtype != NULL) { if (failtype != NULL) {

View File

@ -112,6 +112,13 @@ ProjNode* PhaseIdealLoop::create_new_if_for_predicate(ProjNode* cont_proj, Node*
if (_idom != NULL) { if (_idom != NULL) {
set_idom(call, rgn, dom_depth(rgn)); 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 { } else {
// Find region's edge corresponding to uncommon_proj // Find region's edge corresponding to uncommon_proj
for (; proj_index < rgn->req(); proj_index++) for (; proj_index < rgn->req(); proj_index++)

View File

@ -1901,7 +1901,7 @@ void IdealLoopTree::dump_head( ) const {
if (stride_con > 0) tty->print("+"); if (stride_con > 0) tty->print("+");
tty->print("%d", stride_con); 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_pre_loop ()) tty->print(" pre" );
if (cl->is_main_loop()) tty->print(" main"); if (cl->is_main_loop()) tty->print(" main");

View File

@ -1858,6 +1858,11 @@ void SuperWord::output() {
vn = VectorNode::make(opc, in1, in2, vlen, velt_basic_type(n)); vn = VectorNode::make(opc, in1, in2, vlen, velt_basic_type(n));
vlen_in_bytes = vn->as_Vector()->length_in_bytes(); 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 { } else {
ShouldNotReachHere(); ShouldNotReachHere();
} }

View File

@ -92,6 +92,9 @@ int VectorNode::opcode(int sopc, BasicType bt) {
case Op_DivD: case Op_DivD:
assert(bt == T_DOUBLE, "must be"); assert(bt == T_DOUBLE, "must be");
return Op_DivVD; return Op_DivVD;
case Op_SqrtD:
assert(bt == T_DOUBLE, "must be");
return Op_SqrtVD;
case Op_LShiftI: case Op_LShiftI:
switch (bt) { switch (bt) {
case T_BOOLEAN: 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_DivVF: return new DivVFNode(n1, n2, vt);
case Op_DivVD: return new DivVDNode(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_LShiftVB: return new LShiftVBNode(n1, n2, vt);
case Op_LShiftVS: return new LShiftVSNode(n1, n2, vt); case Op_LShiftVS: return new LShiftVSNode(n1, n2, vt);
case Op_LShiftVI: return new LShiftVINode(n1, n2, vt); case Op_LShiftVI: return new LShiftVINode(n1, n2, vt);

View File

@ -309,6 +309,14 @@ class DivVDNode : public VectorNode {
virtual int Opcode() const; 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----------------------------------- //------------------------------LShiftVBNode-----------------------------------
// Vector left shift bytes // Vector left shift bytes
class LShiftVBNode : public VectorNode { class LShiftVBNode : public VectorNode {

View File

@ -1041,11 +1041,18 @@ CodeBlob* WhiteBox::allocate_code_blob(int size, int blob_type) {
} }
WB_ENTRY(jlong, WB_AllocateCodeBlob(JNIEnv* env, jobject o, jint size, jint blob_type)) 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_END
WB_ENTRY(void, WB_FreeCodeBlob(JNIEnv* env, jobject o, jlong addr)) 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_END
WB_ENTRY(jobjectArray, WB_GetCodeHeapEntries(JNIEnv* env, jobject o, jint blob_type)) 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_END
WB_ENTRY(jobjectArray, WB_GetCodeBlob(JNIEnv* env, jobject o, jlong addr)) WB_ENTRY(jobjectArray, WB_GetCodeBlob(JNIEnv* env, jobject o, jlong addr))
ThreadToNativeFromVM ttn(thread); if (addr == 0) {
CodeBlobStub stub((CodeBlob*) addr); THROW_MSG_NULL(vmSymbols::java_lang_NullPointerException(),
return codeBlob2objectArray(thread, env, &stub); "WB_GetCodeBlob: addr is null");
}
ThreadToNativeFromVM ttn(thread);
CodeBlobStub stub((CodeBlob*) addr);
return codeBlob2objectArray(thread, env, &stub);
WB_END WB_END
WB_ENTRY(jlong, WB_GetThreadStackSize(JNIEnv* env, jobject o)) WB_ENTRY(jlong, WB_GetThreadStackSize(JNIEnv* env, jobject o))

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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 // any clears unless the usage becomes greater than or equal
// to the high threshold. // 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) { 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"); assert(high_low_threshold->is_high_threshold_supported(), "just checking");
bool is_over_high = high_low_threshold->is_high_threshold_crossed(usage); 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 // the sensor will be on (i.e. sensor is currently off
// and has pending trigger requests). // and has pending trigger requests).
void SensorInfo::set_counter_sensor_level(MemoryUsage usage, ThresholdSupport* counter_threshold) { 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"); assert(counter_threshold->is_high_threshold_supported(), "just checking");
bool is_over_high = counter_threshold->is_high_threshold_crossed(usage); 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) { void SensorInfo::process_pending_requests(TRAPS) {
if (!has_pending_requests()) { assert(has_pending_requests(), "Must have pending request");
return;
}
int pending_count = pending_trigger_count(); int pending_count = pending_trigger_count();
if (pending_clear_count() > 0) { if (pending_clear_count() > 0) {
@ -293,7 +293,6 @@ void SensorInfo::process_pending_requests(TRAPS) {
void SensorInfo::trigger(int count, TRAPS) { void SensorInfo::trigger(int count, TRAPS) {
assert(count <= _pending_trigger_count, "just checking"); assert(count <= _pending_trigger_count, "just checking");
if (_sensor_obj != NULL) { if (_sensor_obj != NULL) {
Klass* k = Management::sun_management_Sensor_klass(CHECK); Klass* k = Management::sun_management_Sensor_klass(CHECK);
instanceKlassHandle sensorKlass (THREAD, k); instanceKlassHandle sensorKlass (THREAD, k);
@ -316,6 +315,7 @@ void SensorInfo::trigger(int count, TRAPS) {
{ {
// Holds Service_lock and update the sensor state // Holds Service_lock and update the sensor state
MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag); MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
assert(_pending_trigger_count > 0, "Must have pending trigger");
_sensor_on = true; _sensor_on = true;
_sensor_count += count; _sensor_count += count;
_pending_trigger_count = _pending_trigger_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) { 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) { if (_sensor_obj != NULL) {
Klass* k = Management::sun_management_Sensor_klass(CHECK); Klass* k = Management::sun_management_Sensor_klass(CHECK);
instanceKlassHandle sensorKlass (THREAD, k); instanceKlassHandle sensorKlass (THREAD, k);
@ -338,14 +352,6 @@ void SensorInfo::clear(int count, TRAPS) {
&args, &args,
CHECK); CHECK);
} }
{
// Holds Service_lock and update the sensor state
MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
_sensor_on = false;
_pending_clear_count = 0;
_pending_trigger_count = _pending_trigger_count - count;
}
} }
//-------------------------------------------------------------- //--------------------------------------------------------------

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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 // any clears unless the usage becomes greater than or equal
// to the high threshold. // 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); void set_gauge_sensor_level(MemoryUsage usage, ThresholdSupport* high_low_threshold);

View File

@ -0,0 +1,53 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8134974
* @summary Cannot pin eliminated arraycopy loads for deopt state in uncommon trap path if it is a loop predicate unc
* @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestEliminatedArrayLoopPredicateCopyDeopt
*
*/
public class TestEliminatedArrayLoopPredicateCopyDeopt {
static boolean test(int[] array_src) {
int[] array_dst = new int[10];
System.arraycopy(array_src, 0, array_dst, 0, 10);
for (int i = 0; i < 100; i++) {
array_src[i] = i;
}
if (array_dst[0] == 0) {
return true;
}
return false;
}
static public void main(String[] args) {
int[] array_src = new int[100];
for (int i = 0; i < 20000; i++) {
test(array_src);
}
}
}

View File

@ -0,0 +1,95 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/**
* @test
* @summary Add C2 x86 Superword support for scalar sum reduction optimizations : double sqrt test
*
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=2 -XX:CompileThresholdScaling=0.1 SumRedSqrt_Double
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=2 -XX:CompileThresholdScaling=0.1 SumRedSqrt_Double
*
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=4 -XX:CompileThresholdScaling=0.1 SumRedSqrt_Double
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=4 -XX:CompileThresholdScaling=0.1 SumRedSqrt_Double
*
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=8 -XX:CompileThresholdScaling=0.1 SumRedSqrt_Double
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=8 -XX:CompileThresholdScaling=0.1 SumRedSqrt_Double
*
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=16 -XX:CompileThresholdScaling=0.1 SumRedSqrt_Double
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-SuperWordReductions -XX:LoopUnrollLimit=250 -XX:LoopMaxUnroll=16 -XX:CompileThresholdScaling=0.1 SumRedSqrt_Double
*/
public class SumRedSqrt_Double
{
public static void main(String[] args) throws Exception {
double[] a = new double[256*1024];
double[] b = new double[256*1024];
double[] c = new double[256*1024];
double[] d = new double[256*1024];
sumReductionInit(a,b,c);
double total = 0;
double valid = 2.06157643776E14;
for(int j = 0; j < 2000; j++) {
total = sumReductionImplement(a,b,c,d,total);
}
if(total == valid) {
System.out.println("Success");
} else {
System.out.println("Invalid sum of elements variable in total: " + total);
System.out.println("Expected value = " + valid);
throw new Exception("Failed");
}
}
public static void sumReductionInit(
double[] a,
double[] b,
double[] c)
{
for(int j = 0; j < 1; j++)
{
for(int i = 0; i < a.length; i++)
{
a[i] = i * 1 + j;
b[i] = i * 1 - j;
c[i] = i + j;
}
}
}
public static double sumReductionImplement(
double[] a,
double[] b,
double[] c,
double[] d,
double total)
{
for(int i = 0; i < a.length; i++)
{
d[i]= Math.sqrt(a[i] * b[i]) + Math.sqrt(a[i] * c[i]) + Math.sqrt(b[i] * c[i]);
total += d[i];
}
return total;
}
}

View File

@ -24,7 +24,8 @@
/* /*
* @test * @test
* @bug 8085832 * @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 * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestBadFoldCompare
*/ */
@ -58,6 +59,34 @@ public class TestBadFoldCompare {
helper2(i, 0, 0, flag); 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) { static public void main(String[] args) {
boolean success = true; boolean success = true;
@ -87,6 +116,35 @@ public class TestBadFoldCompare {
System.out.println("Test2 failed"); System.out.println("Test2 failed");
success = false; 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) { if (!success) {
throw new RuntimeException("Some tests failed"); throw new RuntimeException("Some tests failed");
} }

View File

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

View File

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

View File

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

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test BlobSanityTest
* @bug 8132980
* @library /testlibrary /../../test/lib
* @modules java.management/sun.management
* @build BlobSanityTest
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI BlobSanityTest
* @summary sanity testing of allocateCodeBlob, freeCodeBlob and getCodeBlob
*/
import sun.hotspot.WhiteBox;
import java.util.function.Consumer;
import jdk.test.lib.Utils;
public class BlobSanityTest {
private static void runTest(Consumer<Integer> consumer, int val, String testCaseName, Class<? extends Throwable>
expectedException) {
System.out.println("Calling " + testCaseName);
Utils.runAndCheckException(() -> consumer.accept(val), expectedException);
System.out.println("Looks ok");
}
public static void main(String[] args) throws Exception {
System.out.println("Crash means that sanity check failed");
WhiteBox wb = WhiteBox.getWhiteBox();
runTest(wb::freeCodeBlob, 0, "wb::freeCodeBlob(0)", null);
runTest(wb::getCodeBlob, 0, "wb::getCodeBlob(0)", NullPointerException.class);
runTest(x -> wb.allocateCodeBlob(x, 0), -1, "wb::allocateCodeBlob(-1,0)", IllegalArgumentException.class);
}
}

View File

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

View File

@ -0,0 +1,103 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* Copyright (c) 2015 World Wide Web Consortium,
*
* (Massachusetts Institute of Technology, European Research Consortium for
* Informatics and Mathematics, Keio University, Beihang). All Rights Reserved.
* This work is distributed under the W3C(r) Software License [1] in the hope that
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* [1] http://www.w3.org/Consortium/Legal/copyright-software
*/
package org.w3c.dom;
/**
* The {@code ElementTraversal} interface is a set of read-only attributes
* which allow an author to easily navigate between elements in a document.
* <p>
* In conforming implementations of Element Traversal, all objects that
* implement {@link Element} must also implement the {@code ElementTraversal}
* interface. Four of the methods,
* {@link #getFirstElementChild}, {@link #getLastElementChild},
* {@link #getPreviousElementSibling}, and {@link #getNextElementSibling},
* each provides a live reference to another element with the defined
* relationship to the current element, if the related element exists. The
* fifth method, {@link #getChildElementCount}, exposes the number of child
* elements of an element, for preprocessing before navigation.
*
* @see
* <a href='http://www.w3.org/TR/ElementTraversal/'><cite>Element Traversal Specification</cite></a>.
*
* @since 9
*/
public interface ElementTraversal {
/**
* Returns a reference to the first child node of the element which is of
* the {@link Element} type.
*
* @return a reference to an element child, {@code null} if the element has
* no child of the {@link Element} type.
*/
Element getFirstElementChild();
/**
* Returns a reference to the last child node of the element which is of
* the {@link Element} type.
*
* @return a reference to an element child, {@code null} if the element has
* no child of the {@link Element} type.
*/
Element getLastElementChild();
/**
* Returns a reference to the sibling node of the element which most immediately
* precedes the element in document order, and which is of the {@link Element} type.
*
* @return a reference to an element child, {@code null} if the element has
* no sibling node of the {@link Element} type that comes before this one.
*/
Element getPreviousElementSibling();
/**
* Returns a reference to the sibling node of the element which most immediately
* follows the element in document order, and which is of the {@link Element} type.
*
* @return a reference to an element child, {@code null} if the element has
* no sibling node of the {@link Element} type that comes after this one.
*/
Element getNextElementSibling();
/**
* Returns the current number of child nodes of the element which are of
* the {@link Element} type.
*
* @return the number of element children, or {@code 0} if the element has
* no element children.
*/
int getChildElementCount();
}

View File

@ -0,0 +1,112 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package dom;
import java.io.IOException;
import java.io.InputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
/*
* @bug 8135283
* @summary Tests for the Element Traversal interface.
*/
public class ElementTraversal {
/*
Verifies the ElementTraversal interface by exercising all of its five
methods while reading through the xml document.
*/
@Test(dataProvider = "doc")
public void test(Document doc) {
org.w3c.dom.ElementTraversal et = (org.w3c.dom.ElementTraversal)doc.getDocumentElement();
//4 toys are listed
Assert.assertEquals(et.getChildElementCount(), 4);
//The 1st is the Martian
Element toy1 = et.getFirstElementChild();
verify(toy1, "1", "The Martian");
//toy1 has no previous element
Element noE = ((org.w3c.dom.ElementTraversal)toy1).getPreviousElementSibling();
Assert.assertEquals(noE, null);
//The 1st toy's next element is toy2, the Doll
Element toy2 = ((org.w3c.dom.ElementTraversal)toy1).getNextElementSibling();
verify(toy2, "2", "The Doll");
//The last toy is toy4, the Spaceship
Element toy4 = et.getLastElementChild();
verify(toy4, "4", "The Spaceship");
//toy4 has no next element
noE = ((org.w3c.dom.ElementTraversal)toy4).getNextElementSibling();
Assert.assertEquals(noE, null);
//toy4's previous element is toy3, Transformer X
//toy3 is also an EntityReference
Element toy3 = ((org.w3c.dom.ElementTraversal)toy4).getPreviousElementSibling();
verify(toy3, "3", "Transformer X");
}
/**
* Verifies that the values matches the specified element.
* @param id the value of the id attribute
* @param name the value of its name element
*/
void verify(Element e, String id, String name) {
Assert.assertEquals(e.getAttribute("id"), id);
Element toyName = ((org.w3c.dom.ElementTraversal)e).getFirstElementChild();
Assert.assertEquals(toyName.getTextContent(), name);
}
/*
* DataProvider: a Document object
*/
@DataProvider(name = "doc")
Object[][] getXPath() {
return new Object[][]{{getDoc()}};
}
Document getDoc() {
InputStream xmlFile = getClass().getResourceAsStream("ElementTraversal.xml");
Document doc = null;
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);
DocumentBuilder db = dbf.newDocumentBuilder();
doc = db.parse(xmlFile);
} catch (ParserConfigurationException | SAXException | IOException e) {
System.out.println("fail: " + e.getMessage());
}
return doc;
}
}

View File

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

View File

@ -328,3 +328,4 @@ ac1748bab0743137574be3451307b6a6361719eb jdk9-b78
e9940bf1c8ddaa6f1f5f1813846b080f0ccaf50b jdk9-b80 e9940bf1c8ddaa6f1f5f1813846b080f0ccaf50b jdk9-b80
139338618c77d793ab8b550f06819ddb8381316f jdk9-b81 139338618c77d793ab8b550f06819ddb8381316f jdk9-b81
52d9ad2536ba6c6f1cc5561c0a0ee2b4847fd62c jdk9-b82 52d9ad2536ba6c6f1cc5561c0a0ee2b4847fd62c jdk9-b82
d7ee8157f4feced67924e421225c6f844079a03d jdk9-b83

View File

@ -55,7 +55,7 @@ public interface CycleRecoverable {
* *
* *
* @return * @return
* the object to be marshalled instead of <tt>this</tt> object. * the object to be marshalled instead of {@code this} object.
* Or return null to indicate that the JAXB RI should behave * Or return null to indicate that the JAXB RI should behave
* just like when your object does not implement {@link CycleRecoverable} * just like when your object does not implement {@link CycleRecoverable}
* (IOW, cut the cycle arbitrarily and try to go on.) * (IOW, cut the cycle arbitrarily and try to go on.)

View File

@ -134,10 +134,10 @@ public abstract class IDResolver {
* and it is used as the target object. * and it is used as the target object.
* *
* <p> * <p>
* When a forward-reference happens, the <tt>call</tt> method * When a forward-reference happens, the {@code call} method
* should return null. In this case the JAXB RI unmarshaller invokes * should return null. In this case the JAXB RI unmarshaller invokes
* the <tt>call</tt> method again after all the documents are fully unmarshalled. * the {@code call} method again after all the documents are fully unmarshalled.
* If the <tt>call</tt> method still returns null, then the JAXB RI unmarshaller * If the {@code call} method still returns null, then the JAXB RI unmarshaller
* treats it as an error. * treats it as an error.
* *
* <p> * <p>

View File

@ -58,9 +58,9 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
* marshaller.marshal(new Foo()); * marshaller.marshal(new Foo());
* </pre> * </pre>
* and you get: * and you get:
* <pre><xmp> * <pre>{@code
* <foo><x>0</x></foo> * <foo><x>0</x></foo>
* </xmp></pre> * }</pre>
* *
* <p> * <p>
* By creating a side boolean field/property that has this annotation, * By creating a side boolean field/property that has this annotation,
@ -81,14 +81,14 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
* *
* marshaller.marshal(f); * marshaller.marshal(f);
* *
* <xmp> * {@code
* <foo/> * <foo/>
* </xmp> * }
* *
* f.xIsPresent = true; * f.xIsPresent = true;
* <xmp> * {@code
* <foo><x>5</x></foo> * <foo><x>5</x></foo>
* </xmp> * }
* </pre> * </pre>
* *
* <p> * <p>

View File

@ -60,7 +60,7 @@ import com.sun.istack.internal.Nullable;
* <p> * <p>
* When an {@link Unmarshaller} encounters (i) an unknown root element or (ii) unknown * When an {@link Unmarshaller} encounters (i) an unknown root element or (ii) unknown
* elements where unmarshaller is trying to unmarshal into {@link XmlAnyElement} with * elements where unmarshaller is trying to unmarshal into {@link XmlAnyElement} with
* <tt>lax=true</tt>, unmarshaller calls {@link #resolveElementName(String, String)} * {@code lax=true}, unmarshaller calls {@link #resolveElementName(String, String)}
* method to see if the application may be able to supply a class that corresponds * method to see if the application may be able to supply a class that corresponds
* to that class. * to that class.
* *

View File

@ -352,7 +352,7 @@ public abstract class JAXBRIContext extends JAXBContext {
* Accordingly, this method may return an identifier that collides with reserved words. * Accordingly, this method may return an identifier that collides with reserved words.
* *
* <p> * <p>
* Use <tt>JJavaName.isJavaIdentifier(String)</tt> to check for such collision. * Use {@code JJavaName.isJavaIdentifier(String)} to check for such collision.
* *
* @return * @return
* Typically, this method returns "nameLikeThis". * Typically, this method returns "nameLikeThis".
@ -394,17 +394,17 @@ public abstract class JAXBRIContext extends JAXBContext {
* *
* <p> * <p>
* For example, given the following * For example, given the following
* <pre><xmp> * <pre>{@code
* interface Foo<T> extends List<List<T>> {} * interface Foo<T> extends List<List<T>> {}
* interface Bar extends Foo<String> {} * interface Bar extends Foo<String> {}
* </xmp></pre> * }</pre>
* This method works like this: * This method works like this:
* <pre><xmp> * <pre>{@code
* getBaseClass( Bar, List ) = List<List<String> * getBaseClass( Bar, List ) = List<List<String>
* getBaseClass( Bar, Foo ) = Foo<String> * getBaseClass( Bar, Foo ) = Foo<String>
* getBaseClass( Foo<? extends Number>, Collection ) = Collection<List<? extends Number>> * getBaseClass( Foo<? extends Number>, Collection ) = Collection<List<? extends Number>>
* getBaseClass( ArrayList<? extends BigInteger>, List ) = List<? extends BigInteger> * getBaseClass( ArrayList<? extends BigInteger>, List ) = List<? extends BigInteger>
* </xmp></pre> * }</pre>
* *
* @param type * @param type
* The type that derives from {@code baseType} * The type that derives from {@code baseType}
@ -460,7 +460,7 @@ public abstract class JAXBRIContext extends JAXBContext {
/** /**
* The property that you can specify to {@link JAXBContext#newInstance} * The property that you can specify to {@link JAXBContext#newInstance}
* to allow unmarshaller to honor <tt>xsi:nil</tt> anywhere, even if they are * to allow unmarshaller to honor {@code xsi:nil} anywhere, even if they are
* not specifically allowed by the schema. * not specifically allowed by the schema.
* *
* Boolean * Boolean

View File

@ -125,7 +125,7 @@ public abstract class NamespacePrefixMapper {
* they are necessary, only at where they are used. Because of this * they are necessary, only at where they are used. Because of this
* lack of look-ahead, sometimes the marshaller produces a lot of * lack of look-ahead, sometimes the marshaller produces a lot of
* namespace declarations that look redundant to human eyes. For example, * namespace declarations that look redundant to human eyes. For example,
* <pre><xmp> * <pre>{@code
* <?xml version="1.0"?> * <?xml version="1.0"?>
* <root> * <root>
* <ns1:child xmlns:ns1="urn:foo"> ... </ns1:child> * <ns1:child xmlns:ns1="urn:foo"> ... </ns1:child>
@ -133,7 +133,7 @@ public abstract class NamespacePrefixMapper {
* <ns3:child xmlns:ns3="urn:foo"> ... </ns3:child> * <ns3:child xmlns:ns3="urn:foo"> ... </ns3:child>
* ... * ...
* </root> * </root>
* </xmp></pre> * }</pre>
* *
* <p> * <p>
* The JAXB RI 2.x mostly doesn't exhibit this behavior any more, * The JAXB RI 2.x mostly doesn't exhibit this behavior any more,
@ -152,7 +152,7 @@ public abstract class NamespacePrefixMapper {
* <p> * <p>
* For example, by returning <code>new String[]{"urn:foo"}</code>, * For example, by returning <code>new String[]{"urn:foo"}</code>,
* the marshaller will produce: * the marshaller will produce:
* <pre><xmp> * <pre>{@code
* <?xml version="1.0"?> * <?xml version="1.0"?>
* <root xmlns:ns1="urn:foo"> * <root xmlns:ns1="urn:foo">
* <ns1:child> ... </ns1:child> * <ns1:child> ... </ns1:child>
@ -160,7 +160,7 @@ public abstract class NamespacePrefixMapper {
* <ns1:child> ... </ns1:child> * <ns1:child> ... </ns1:child>
* ... * ...
* </root> * </root>
* </xmp></pre> * }</pre>
* <p> * <p>
* To control prefixes assigned to those namespace URIs, use the * To control prefixes assigned to those namespace URIs, use the
* {@link #getPreferredPrefix(String, String, boolean)} method. * {@link #getPreferredPrefix(String, String, boolean)} method.
@ -232,7 +232,7 @@ public abstract class NamespacePrefixMapper {
* the receiver a conflicting binding information. * the receiver a conflicting binding information.
* It's a responsibility of the caller to make sure that this doesn't happen * It's a responsibility of the caller to make sure that this doesn't happen
* even if the ancestor elements look like: * even if the ancestor elements look like:
* <pre><xmp> * <pre>{@code
* <foo:abc xmlns:foo="abc"> * <foo:abc xmlns:foo="abc">
* <foo:abc xmlns:foo="def"> * <foo:abc xmlns:foo="def">
* <foo:abc xmlns:foo="abc"> * <foo:abc xmlns:foo="abc">
@ -240,7 +240,7 @@ public abstract class NamespacePrefixMapper {
* </foo:abc> * </foo:abc>
* </foo:abc> * </foo:abc>
* </foo:abc> * </foo:abc>
* </xmp></pre> * }</pre>
* *
* @return * @return
* always return a non-null (but possibly empty) array. The array stores * always return a non-null (but possibly empty) array. The array stores

View File

@ -46,7 +46,7 @@ public class Adapter<TypeT,ClassDeclT> {
/** /**
* The type that the JAXB can handle natively. * The type that the JAXB can handle natively.
* The <tt>Default</tt> parameter of <tt>XmlAdapter&lt;Default,Custom></tt>. * The {@code Default} parameter of {@code XmlAdapter<Default,Custom>}.
* *
* Always non-null. * Always non-null.
*/ */
@ -54,7 +54,7 @@ public class Adapter<TypeT,ClassDeclT> {
/** /**
* The type that is stored in memory. * The type that is stored in memory.
* The <tt>Custom</tt> parameter of <tt>XmlAdapter&lt;Default,Custom></tt>. * The {@code Custom} parameter of {@code XmlAdapter<Default,Custom>}.
*/ */
public final TypeT customType; public final TypeT customType;

View File

@ -143,8 +143,8 @@ public interface ClassInfo<T,C> extends MaybeElement<T,C> {
* False if it't not. * False if it't not.
* *
* <p> * <p>
* In RELAX NG context, ordered properties mean &lt;group> and * In RELAX NG context, ordered properties mean {@code <group>} and
* unordered properties mean &lt;interleave>. * unordered properties mean {@code <interleave>}.
*/ */
boolean isOrdered(); boolean isOrdered();

View File

@ -56,9 +56,9 @@ public interface ElementPropertyInfo<T,C> extends PropertyInfo<T,C> {
* &#64;XmlElements({ * &#64;XmlElements({
* &#64;XmlElement(name="a",type=String.class), * &#64;XmlElement(name="a",type=String.class),
* &#64;XmlElement(name="b",type=Integer.class), * &#64;XmlElement(name="b",type=Integer.class),
* }) * }) {@code
* List&lt;Object> abc; * List<Object> abc;
* </pre> * }</pre>
* <p> * <p>
* In this case this method returns a list of two {@link TypeRef}s. * In this case this method returns a list of two {@link TypeRef}s.
* *
@ -107,7 +107,7 @@ public interface ElementPropertyInfo<T,C> extends PropertyInfo<T,C> {
* If {@link #isCollection()}==false, this property is always false. * If {@link #isCollection()}==false, this property is always false.
* *
* <p> * <p>
* When this flag is true, <tt>getTypes().size()==1</tt> always holds. * When this flag is true, {@code getTypes().size()==1} always holds.
*/ */
boolean isValueList(); boolean isValueList();

View File

@ -32,7 +32,7 @@ import javax.xml.namespace.QName;
/** /**
* Property that maps to the following schema fragment. * Property that maps to the following schema fragment.
* *
* <pre><xmp> * <pre>{@code
* <xs:complexType> * <xs:complexType>
* <xs:sequence> * <xs:sequence>
* <xs:element name="entry" minOccurs="0" maxOccurs="unbounded"> * <xs:element name="entry" minOccurs="0" maxOccurs="unbounded">
@ -45,7 +45,7 @@ import javax.xml.namespace.QName;
* </xs:element> * </xs:element>
* </xs:sequence> * </xs:sequence>
* </xs:complexType> * </xs:complexType>
* </xmp></pre> * }</pre>
* *
* <p> * <p>
* This property is used to represent a default binding of a {@link Map} property. * This property is used to represent a default binding of a {@link Map} property.

View File

@ -153,7 +153,7 @@ public interface TypeInfoSet<T,C,F,M> {
* A map from namespace URI to the value of the location. * A map from namespace URI to the value of the location.
* If the entry is missing, that means a schema should be generated for that namespace. * If the entry is missing, that means a schema should be generated for that namespace.
* If the value is "", that means the schema location is implied * If the value is "", that means the schema location is implied
* (&lt;xs:schema namespace="..."/> w/o schemaLocation.) * ({@code <xs:schema namespace="..."/>} w/o schemaLocation.)
*/ */
Map<String,String> getSchemaLocations(); Map<String,String> getSchemaLocations();

View File

@ -35,7 +35,7 @@ import com.sun.xml.internal.bind.v2.model.nav.Navigator;
import com.sun.xml.internal.bind.v2.model.annotation.Locatable; import com.sun.xml.internal.bind.v2.model.annotation.Locatable;
/** /**
* {@link TypeInfo} implementation for <tt>xs:anyType</tt>. * {@link TypeInfo} implementation for {@code xs:anyType}.
* *
* @author Kohsuke Kawaguchi * @author Kohsuke Kawaguchi
*/ */

View File

@ -119,7 +119,7 @@ class TypeInfoSetImpl<T,C,F,M> implements TypeInfoSet<T,C,F,M> {
}; };
/** /**
* {@link TypeInfo} for <tt>xs:anyType</tt>. * {@link TypeInfo} for {@code xs:anyType}.
* *
* anyType is the only {@link TypeInfo} that works with an interface, * anyType is the only {@link TypeInfo} that works with an interface,
* and accordingly it requires a lot of special casing. * and accordingly it requires a lot of special casing.

View File

@ -40,10 +40,10 @@ final class GenericArrayTypeImpl implements GenericArrayType {
} }
/** /**
* Returns a <tt>Type</tt> object representing the component type * Returns a {@code Type} object representing the component type
* of this array. * 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 * of this array
* @since 1.5 * @since 1.5
*/ */

View File

@ -70,17 +70,17 @@ public interface Navigator<T,C,F,M> {
* *
* <p> * <p>
* For example, given the following * For example, given the following
* <pre><xmp> * <pre>{@code
* interface Foo<T> extends List<List<T>> {} * interface Foo<T> extends List<List<T>> {}
* interface Bar extends Foo<String> {} * interface Bar extends Foo<String> {}
* </xmp></pre> * }</pre>
* This method works like this: * This method works like this:
* <pre><xmp> * <pre>{@code
* getBaseClass( Bar, List ) = List<List<String> * getBaseClass( Bar, List ) = List<List<String>>
* getBaseClass( Bar, Foo ) = Foo<String> * getBaseClass( Bar, Foo ) = Foo<String>
* getBaseClass( Foo<? extends Number>, Collection ) = Collection<List<? extends Number>> * getBaseClass( Foo<? extends Number>, Collection ) = Collection<List<? extends Number>>
* getBaseClass( ArrayList<? extends BigInteger>, List ) = List<? extends BigInteger> * getBaseClass( ArrayList<? extends BigInteger>, List ) = List<? extends BigInteger>
* </xmp></pre> * }</pre>
* *
* @param type * @param type
* The type that derives from {@code baseType} * The type that derives from {@code baseType}

View File

@ -418,7 +418,7 @@ import com.sun.xml.internal.bind.v2.runtime.Location;
} }
/** /**
* Returns the {@link Type} object that represents {@code clazz&lt;T1,T2,T3>}. * Returns the {@link Type} object that represents {@code clazz<T1,T2,T3>}.
*/ */
public Type createParameterizedType(Class rawType, Type... arguments) { public Type createParameterizedType(Class rawType, Type... arguments) {
return new ParameterizedTypeImpl(rawType, arguments, null); return new ParameterizedTypeImpl(rawType, arguments, null);

View File

@ -35,7 +35,7 @@ import com.sun.xml.internal.bind.v2.model.core.TypeInfo;
*/ */
public interface RuntimeArrayInfo extends ArrayInfo<Type,Class>, RuntimeNonElement { public interface RuntimeArrayInfo extends ArrayInfo<Type,Class>, RuntimeNonElement {
/** /**
* Represents <tt>T[]</tt>. * Represents {@code T[]}.
* *
* The same as {@link TypeInfo#getType()} but at the runtime, an array * The same as {@link TypeInfo#getType()} but at the runtime, an array
* is guaranteed to have a {@link Class} representation, not just any {@link Type}. * is guaranteed to have a {@link Class} representation, not just any {@link Type}.

View File

@ -48,7 +48,7 @@ import org.w3c.dom.NodeList;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
/** /**
* {@link JaxBeanInfo} for handling <tt>xs:anyType</tt>. * {@link JaxBeanInfo} for handling {@code xs:anyType}.
* *
* @author Kohsuke Kawaguchi * @author Kohsuke Kawaguchi
*/ */

View File

@ -119,7 +119,7 @@ public class IllegalAnnotationException extends JAXBException {
* annotation, in which case this method returns a list that * annotation, in which case this method returns a list that
* contains another list, which in turn contains the location * contains another list, which in turn contains the location
* information that leads to the error location * information that leads to the error location
* (IOW, <tt>[ [pos1,pos2,...,posN] ]</tt>) * (IOW, {@code [ [pos1,pos2,...,posN] ]})
* *
* <p> * <p>
* Sometimes, an error could occur because of two or more conflicting * Sometimes, an error could occur because of two or more conflicting
@ -127,12 +127,12 @@ public class IllegalAnnotationException extends JAXBException {
* that contains many lists, where each list contains * that contains many lists, where each list contains
* the location information that leads to each of the conflicting * the location information that leads to each of the conflicting
* annotations * annotations
* (IOW, <tt>[ [pos11,pos12,...,pos1N],[pos21,pos22,...,pos2M], ... ]</tt>) * (IOW, {@code [ [pos11,pos12,...,pos1N],[pos21,pos22,...,pos2M], ... ]})
* *
* <p> * <p>
* Yet some other time, the runtime can fail to provide any * Yet some other time, the runtime can fail to provide any
* error location, in which case this method returns an empty list. * error location, in which case this method returns an empty list.
* (IOW, <tt>[]</tt>). We do try hard to make sure this won't happen, * (IOW, {@code []}). We do try hard to make sure this won't happen,
* so please <a href="http://jaxb.dev.java.net/">let us know</a> * so please <a href="http://jaxb.dev.java.net/">let us know</a>
* if you see this behavior. * if you see this behavior.
* *
@ -146,13 +146,13 @@ public class IllegalAnnotationException extends JAXBException {
* to the first in the list, sort of like a stack trace. * to the first in the list, sort of like a stack trace.
* *
* <p> * <p>
* For example, suppose you specify class <tt>Foo</tt> to {@link JAXBContext}, * For example, suppose you specify class {@code Foo} to {@link JAXBContext},
* <tt>Foo</tt> derives from <tt>Bar</tt>, <tt>Bar</tt> has a field <tt>pea</tt> * {@code Foo} derives from {@code Bar}, {@code Bar} has a field {@code pea}
* that points to <tt>Zot</tt>, <tt>Zot</tt> contains a <tt>gum</tt> * that points to {@code Zot}, {@code Zot} contains a {@code gum}
* property, and this property has an errornous annotation. * property, and this property has an errornous annotation.
* Then when this exception is thrown, the list of {@link Location}s * Then when this exception is thrown, the list of {@link Location}s
* will look something like * will look something like
* <tt>[ "gum property", "Zot class", "pea property", "Bar class", "Foo class" ]</tt> * {@code [ "gum property", "Zot class", "pea property", "Bar class", "Foo class" ]}
* *
* *
* @return * @return

View File

@ -533,7 +533,7 @@ public final class JAXBContextImpl extends JAXBRIContext {
* This method traverses the base classes of the given object. * This method traverses the base classes of the given object.
* *
* @return null * @return null
* if <tt>c</tt> isn't a JAXB-bound class and <tt>fatal==false</tt>. * if {@code c} isn't a JAXB-bound class and {@code fatal==false}.
*/ */
public final JaxBeanInfo getBeanInfo(Object o) { public final JaxBeanInfo getBeanInfo(Object o) {
// don't allow xs:anyType beanInfo to handle all the unbound objects // don't allow xs:anyType beanInfo to handle all the unbound objects
@ -577,7 +577,7 @@ public final class JAXBContextImpl extends JAXBRIContext {
* This method doesn't look for base classes. * This method doesn't look for base classes.
* *
* @return null * @return null
* if <tt>c</tt> isn't a JAXB-bound class and <tt>fatal==false</tt>. * if {@code c} isn't a JAXB-bound class and {@code fatal==false}.
*/ */
public final <T> JaxBeanInfo<T> getBeanInfo(Class<T> clazz) { public final <T> JaxBeanInfo<T> getBeanInfo(Class<T> clazz) {
return (JaxBeanInfo<T>)beanInfoMap.get(clazz); return (JaxBeanInfo<T>)beanInfoMap.get(clazz);

View File

@ -68,7 +68,7 @@ import org.xml.sax.SAXException;
* <p> * <p>
* Typically, {@link JaxBeanInfo} implementations should be generated * Typically, {@link JaxBeanInfo} implementations should be generated
* by XJC/JXC. Those impl classes will register themselves to their * by XJC/JXC. Those impl classes will register themselves to their
* master <tt>ObjectFactory</tt> class. * master {@code ObjectFactory} class.
* *
* <p> * <p>
* The type parameter BeanT is the Java class of the bean that this represents. * The type parameter BeanT is the Java class of the bean that this represents.

View File

@ -378,7 +378,7 @@ public final class XMLSerializer extends Coordinator {
* c.endElement(); * c.endElement();
* </pre> * </pre>
* *
* will generate <code>&lt;foo>abc def&lt;bar/>ghi&lt;/foo></code>. * will generate {@code <foo>abc def<bar/>ghi</foo>}.
*/ */
public void text( String text, String fieldName ) throws SAXException, IOException, XMLStreamException { public void text( String text, String fieldName ) throws SAXException, IOException, XMLStreamException {
// If the assertion fails, it must be a bug of xjc. // If the assertion fails, it must be a bug of xjc.
@ -492,7 +492,7 @@ public final class XMLSerializer extends Coordinator {
* When a cycle is found, this method tries to recover from it. * When a cycle is found, this method tries to recover from it.
* *
* @return * @return
* the object that should be marshalled instead of the given <tt>obj</tt>, * the object that should be marshalled instead of the given {@code obj},
* or null if the error is found and we need to avoid marshalling this object * or null if the error is found and we need to avoid marshalling this object
* to prevent infinite recursion. When this method returns null, the error * to prevent infinite recursion. When this method returns null, the error
* has already been reported. * has already been reported.

View File

@ -134,7 +134,7 @@ final class SingleMapNodeProperty<BeanT,ValueT extends Map> extends PropertyImpl
private Loader valueLoader; private Loader valueLoader;
/** /**
* Handles &lt;items> and &lt;/items>. * Handles {@code <items>} and {@code </items>}.
* *
* The target will be set to a {@link Map}. * The target will be set to a {@link Map}.
*/ */
@ -190,7 +190,7 @@ final class SingleMapNodeProperty<BeanT,ValueT extends Map> extends PropertyImpl
}; };
/** /**
* Handles &lt;entry> and &lt;/entry>. * Handles {@code <entry>} and {@code </entry>}.
* *
* The target will be set to a {@link Map}. * The target will be set to a {@link Map}.
*/ */

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