--- a/.hgtags-top-repo Sat Sep 26 09:22:24 2015 -0700
+++ b/.hgtags-top-repo Wed Jul 05 20:51:27 2017 +0200
@@ -325,3 +325,4 @@
f7c5ae2933c0b8510a420d1713a955e4ffc7ad0b jdk9-b80
b8afcf91331d78626a583ec1b63164468d6f4181 jdk9-b81
42b56d1f418523ecb61a49d7493302c80c8009cc jdk9-b82
+ce5c14d97d95084504c32b9320cb33cce4235588 jdk9-b83
--- a/common/autoconf/basics.m4 Sat Sep 26 09:22:24 2015 -0700
+++ b/common/autoconf/basics.m4 Wed Jul 05 20:51:27 2017 +0200
@@ -445,6 +445,15 @@
# Save the current directory this script was started from
CURDIR="$PWD"
+ # We might need to rewrite ORIGINAL_PATH, if it includes "#", to quote them
+ # for make. We couldn't do this when we retrieved ORIGINAL_PATH, since SED
+ # was not available at that time.
+ REWRITTEN_PATH=`$ECHO "$ORIGINAL_PATH" | $SED -e 's/#/\\\\#/g'`
+ if test "x$REWRITTEN_PATH" != "x$ORIGINAL_PATH"; then
+ ORIGINAL_PATH="$REWRITTEN_PATH"
+ AC_MSG_NOTICE([Rewriting ORIGINAL_PATH to $REWRITTEN_PATH])
+ fi
+
if test "x$OPENJDK_TARGET_OS" = "xwindows"; then
PATH_SEP=";"
BASIC_CHECK_PATHS_WINDOWS
@@ -935,6 +944,7 @@
BASIC_PATH_PROGS(HG, hg)
BASIC_PATH_PROGS(STAT, stat)
BASIC_PATH_PROGS(TIME, time)
+ BASIC_PATH_PROGS(PATCH, [gpatch patch])
# Check if it's GNU time
IS_GNU_TIME=`$TIME --version 2>&1 | $GREP 'GNU time'`
if test "x$IS_GNU_TIME" != x; then
--- a/common/autoconf/compare.sh.in Sat Sep 26 09:22:24 2015 -0700
+++ b/common/autoconf/compare.sh.in Wed Jul 05 20:51:27 2017 +0200
@@ -29,47 +29,50 @@
##########################################################################################
# Substitutions from autoconf
-LEGACY_BUILD_DIR=@OPENJDK_TARGET_OS@-@OPENJDK_TARGET_CPU_LEGACY@
+export LEGACY_BUILD_DIR=@OPENJDK_TARGET_OS@-@OPENJDK_TARGET_CPU_LEGACY@
-OPENJDK_TARGET_OS="@OPENJDK_TARGET_OS@"
-OPENJDK_TARGET_CPU="@OPENJDK_TARGET_CPU@"
+export OPENJDK_TARGET_OS="@OPENJDK_TARGET_OS@"
+export OPENJDK_TARGET_CPU="@OPENJDK_TARGET_CPU@"
-AWK="@AWK@"
-CAT="@CAT@"
-CMP="@CMP@"
-CP="@CP@"
-CUT="@CUT@"
-DIFF="@DIFF@"
-DUMPBIN="@FIXPATH@ @DUMPBIN@"
-EXPR="@EXPR@"
-FILE="@FILE@"
-FIND="@FIND@"
-GREP="@GREP@"
-JAVAP="@FIXPATH@ @BOOT_JDK@/bin/javap @JAVA_TOOL_FLAGS_SMALL@"
-JIMAGE="@FIXPATH@ @BUILD_OUTPUT@/jdk/bin/jimage"
-LDD="@LDD@"
-LN="@LN@"
-MKDIR="@MKDIR@"
-NAWK="@NAWK@"
-NM="@GNM@"
-OBJDUMP="@OBJDUMP@"
-OTOOL="@OTOOL@"
-PRINTF="@PRINTF@"
-READELF="@READELF@"
-RM="@RM@"
-SED="@SED@"
-SORT="@SORT@"
-STAT="@STAT@"
-STRIP="@POST_STRIP_CMD@"
-TEE="@TEE@"
-UNIQ="@UNIQ@"
-UNPACK200="@FIXPATH@ @BOOT_JDK@/bin/unpack200"
-UNZIP="@UNZIP@"
+export AWK="@AWK@"
+export BASH="@BASH@"
+export CAT="@CAT@"
+export CMP="@CMP@"
+export CP="@CP@"
+export CUT="@CUT@"
+export DIFF="@DIFF@"
+export DUMPBIN="@FIXPATH@ @DUMPBIN@"
+export EXPR="@EXPR@"
+export FILE="@FILE@"
+export FIND="@FIND@"
+export GREP="@GREP@"
+export JAVAP="@FIXPATH@ @BOOT_JDK@/bin/javap @JAVA_TOOL_FLAGS_SMALL@"
+export JIMAGE="@FIXPATH@ @BUILD_OUTPUT@/jdk/bin/jimage"
+export LDD="@LDD@"
+export LN="@LN@"
+export MKDIR="@MKDIR@"
+export MV="@MV@"
+export NAWK="@NAWK@"
+export NM="@GNM@"
+export OBJDUMP="@OBJDUMP@"
+export OTOOL="@OTOOL@"
+export PRINTF="@PRINTF@"
+export READELF="@READELF@"
+export RM="@RM@"
+export SED="@SED@"
+export SORT="@SORT@"
+export STAT="@STAT@"
+export STRIP="@POST_STRIP_CMD@"
+export TEE="@TEE@"
+export UNIQ="@UNIQ@"
+export UNPACK200="@FIXPATH@ @BOOT_JDK@/bin/unpack200"
+export UNZIP="@UNZIP@"
-SRC_ROOT="@TOPDIR@"
+export SRC_ROOT="@TOPDIR@"
+export OUTPUT_ROOT="@OUTPUT_ROOT@"
if [ "$OPENJDK_TARGET_OS" = "windows" ]; then
- PATH="@VS_PATH@"
+ export PATH="@VS_PATH@"
fi
# Now locate the main script and run it.
@@ -79,4 +82,8 @@
exit 1
fi
-. "$REAL_COMPARE_SCRIPT" "$@"
+# Rotate logs
+$RM $OUTPUT_ROOT/compare.log.old 2> /dev/null
+$MV $OUTPUT_ROOT/compare.log $OUTPUT_ROOT/compare.log.old 2> /dev/null
+
+$BASH $SRC_ROOT/common/bin/logger.sh $OUTPUT_ROOT/compare.log $BASH "$REAL_COMPARE_SCRIPT" "$@"
--- a/common/autoconf/generated-configure.sh Sat Sep 26 09:22:24 2015 -0700
+++ b/common/autoconf/generated-configure.sh Wed Jul 05 20:51:27 2017 +0200
@@ -859,6 +859,7 @@
XATTR
DSYMUTIL
IS_GNU_TIME
+PATCH
TIME
STAT
HG
@@ -1174,6 +1175,7 @@
HG
STAT
TIME
+PATCH
DSYMUTIL
XATTR
CODESIGN
@@ -2053,6 +2055,7 @@
HG Override default value for HG
STAT Override default value for STAT
TIME Override default value for TIME
+ PATCH Override default value for PATCH
DSYMUTIL Override default value for DSYMUTIL
XATTR Override default value for XATTR
CODESIGN Override default value for CODESIGN
@@ -4359,7 +4362,7 @@
#CUSTOM_AUTOCONF_INCLUDE
# Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1441958217
+DATE_WHEN_GENERATED=1442820958
###############################################################################
#
@@ -13841,6 +13844,16 @@
# Save the current directory this script was started from
CURDIR="$PWD"
+ # We might need to rewrite ORIGINAL_PATH, if it includes "#", to quote them
+ # for make. We couldn't do this when we retrieved ORIGINAL_PATH, since SED
+ # was not available at that time.
+ REWRITTEN_PATH=`$ECHO "$ORIGINAL_PATH" | $SED -e 's/#/\\\\#/g'`
+ if test "x$REWRITTEN_PATH" != "x$ORIGINAL_PATH"; then
+ ORIGINAL_PATH="$REWRITTEN_PATH"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting ORIGINAL_PATH to $REWRITTEN_PATH" >&5
+$as_echo "$as_me: Rewriting ORIGINAL_PATH to $REWRITTEN_PATH" >&6;}
+ fi
+
if test "x$OPENJDK_TARGET_OS" = "xwindows"; then
PATH_SEP=";"
@@ -18865,6 +18878,192 @@
fi
+
+
+ # Publish this variable in the help.
+
+
+ if test "x$PATCH" = x; then
+ # The variable is not set by user, try to locate tool using the code snippet
+ for ac_prog in gpatch patch
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PATCH+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $PATCH in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PATCH="$PATCH" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_PATCH="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+PATCH=$ac_cv_path_PATCH
+if test -n "$PATCH"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PATCH" >&5
+$as_echo "$PATCH" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$PATCH" && break
+done
+
+ else
+ # The variable is set, but is it from the command line or the environment?
+
+ # Try to remove the string !PATCH! from our list.
+ try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!PATCH!/}
+ if test "x$try_remove_var" = "x$CONFIGURE_OVERRIDDEN_VARIABLES"; then
+ # If it failed, the variable was not from the command line. Ignore it,
+ # but warn the user (except for BASH, which is always set by the calling BASH).
+ if test "xPATCH" != xBASH; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of PATCH from the environment. Use command line variables instead." >&5
+$as_echo "$as_me: WARNING: Ignoring value of PATCH from the environment. Use command line variables instead." >&2;}
+ fi
+ # Try to locate tool using the code snippet
+ for ac_prog in gpatch patch
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PATCH+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $PATCH in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PATCH="$PATCH" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_PATCH="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+PATCH=$ac_cv_path_PATCH
+if test -n "$PATCH"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PATCH" >&5
+$as_echo "$PATCH" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$PATCH" && break
+done
+
+ else
+ # If it succeeded, then it was overridden by the user. We will use it
+ # for the tool.
+
+ # First remove it from the list of overridden variables, so we can test
+ # for unknown variables in the end.
+ CONFIGURE_OVERRIDDEN_VARIABLES="$try_remove_var"
+
+ # Check if the provided tool contains a complete path.
+ tool_specified="$PATCH"
+ tool_basename="${tool_specified##*/}"
+ if test "x$tool_basename" = "x$tool_specified"; then
+ # A command without a complete path is provided, search $PATH.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Will search for user supplied tool PATCH=$tool_basename" >&5
+$as_echo "$as_me: Will search for user supplied tool PATCH=$tool_basename" >&6;}
+ # Extract the first word of "$tool_basename", so it can be a program name with args.
+set dummy $tool_basename; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PATCH+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $PATCH in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PATCH="$PATCH" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_PATCH="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+PATCH=$ac_cv_path_PATCH
+if test -n "$PATCH"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PATCH" >&5
+$as_echo "$PATCH" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ if test "x$PATCH" = x; then
+ as_fn_error $? "User supplied tool $tool_basename could not be found" "$LINENO" 5
+ fi
+ else
+ # Otherwise we believe it is a complete path. Use it as it is.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Will use user supplied tool PATCH=$tool_specified" >&5
+$as_echo "$as_me: Will use user supplied tool PATCH=$tool_specified" >&6;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PATCH" >&5
+$as_echo_n "checking for PATCH... " >&6; }
+ if test ! -x "$tool_specified"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+$as_echo "not found" >&6; }
+ as_fn_error $? "User supplied tool PATCH=$tool_specified does not exist or is not executable" "$LINENO" 5
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tool_specified" >&5
+$as_echo "$tool_specified" >&6; }
+ fi
+ fi
+ fi
+
+
# Check if it's GNU time
IS_GNU_TIME=`$TIME --version 2>&1 | $GREP 'GNU time'`
if test "x$IS_GNU_TIME" != x; then
--- a/common/autoconf/spec.gmk.in Sat Sep 26 09:22:24 2015 -0700
+++ b/common/autoconf/spec.gmk.in Wed Jul 05 20:51:27 2017 +0200
@@ -36,6 +36,11 @@
# A self-referential reference to this file.
SPEC:=@SPEC@
+# SPACE is defined in MakeBase.gmk, but it is also used in := rules here for some
+# toolchains, and is needed if MakeBase.gmk is not included before this file.
+X:=
+SPACE:=$(X) $(X)
+
# What make to use for main processing, after bootstrapping top-level Makefile.
MAKE := @MAKE@
@@ -495,6 +500,7 @@
MKDIR:=@MKDIR@
MV:=@MV@
NAWK:=@NAWK@
+PATCH:=@PATCH@
PRINTF:=@PRINTF@
PWD:=@THEPWDCMD@
RM:=@RM@
--- a/common/bin/compare.sh Sat Sep 26 09:22:24 2015 -0700
+++ b/common/bin/compare.sh Wed Jul 05 20:51:27 2017 +0200
@@ -88,23 +88,19 @@
TMP=$(LC_ALL=C $DIFF $OTHER_FILE $THIS_FILE | \
$GREP '^[<>]' | \
$SED -e '/[<>] \* from.*\.idl/d' \
- -e '/[<>] \*.*[0-9]\{4\}_[0-9]\{2\}_[0-9]\{2\}_[0-9]\{2\}_[0-9]\{2\}-b[0-9]\{2\}.*/d' \
+ -e '/[<>] .*[0-9]\{4\}_[0-9]\{2\}_[0-9]\{2\}_[0-9]\{2\}_[0-9]\{2\}-b[0-9]\{2\}.*/d' \
-e '/[<>] \*.*[0-9]\{4\} [0-9][0-9]*:[0-9]\{2\}:[0-9]\{2\}.*/d' \
-e '/\/\/ Generated from input file.*/d' \
-e '/\/\/ This file was generated AUTOMATICALLY from a template file.*/d' \
-e '/\/\/ java GenerateCharacter.*/d')
fi
# Ignore date strings in class files.
- # On Macosx the system sources for generated java classes produce different output on
- # consequtive invocations seemingly randomly.
- # For example a method parameter randomly named "thePoint" or "aPoint". Ignore this.
# Anonymous lambda classes get randomly assigned counters in their names.
if test "x$SUFFIX" = "xclass"; then
# To improve performance when large diffs are found, do a rough filtering of classes
# elibeble for these exceptions
if $GREP -R -e '[0-9]\{4\}_[0-9]\{2\}_[0-9]\{2\}_[0-9]\{2\}_[0-9]\{2\}-b[0-9]\{2\}' \
-e '[0-9]\{2\}/[0-9]\{2\}/[0-9]\{4\}' \
- -e thePoint -e aPoint -e setItemsPtr \
-e 'lambda\$[a-zA-Z0-9]*\$[0-9]' ${THIS_FILE} > /dev/null; then
$JAVAP -c -constants -l -p "${OTHER_FILE}" > ${OTHER_FILE}.javap
$JAVAP -c -constants -l -p "${THIS_FILE}" > ${THIS_FILE}.javap
@@ -112,9 +108,6 @@
$GREP '^[<>]' | \
$SED -e '/[<>].*[0-9]\{4\}_[0-9]\{2\}_[0-9]\{2\}_[0-9]\{2\}_[0-9]\{2\}-b[0-9]\{2\}.*/d' \
-e '/[0-9]\{2\}\/[0-9]\{2\}\/[0-9]\{4\}/d' \
- -e '/[<>].*Point Lcom\/apple\/jobjc\/foundation\/NSPoint;/d' \
- -e '/[<>].*public com\.apple\.jobjc\.Pointer<com\.apple\.jobjc\..*itemsPtr();/d' \
- -e '/[<>].*public void setItemsPtr(com\.apple\.jobjc\.Pointer<com\.apple\.jobjc\..*);/d' \
-e '/[<>].*lambda\$[a-zA-Z0-9]*\$[0-9]*/d')
fi
fi
@@ -313,7 +306,7 @@
! -name "jspawnhelper" \
| $GREP -v "./bin/" | $SORT | $FILTER)
- echo General files...
+ echo Other files with binary differences...
for f in $GENERAL_FILES
do
if [ -e $OTHER_DIR/$f ]; then
@@ -590,7 +583,7 @@
ORIG_THIS_FILE="$THIS_FILE"
ORIG_OTHER_FILE="$OTHER_FILE"
- if [[ "$STRIP_BEFORE_COMPARE" = *"$BIN_FILE"* ]]; then
+ if [ "$STRIP_ALL" = "true" ] || [[ "$STRIP_BEFORE_COMPARE" = *"$BIN_FILE"* ]]; then
THIS_STRIPPED_FILE=$FILE_WORK_DIR/this/$NAME
OTHER_STRIPPED_FILE=$FILE_WORK_DIR/other/$NAME
$MKDIR -p $FILE_WORK_DIR/this $FILE_WORK_DIR/other
@@ -722,7 +715,7 @@
fi
fi
- if [[ "$SORT_SYMBOLS" = *"$BIN_FILE"* ]]; then
+ if [ "$SORT_ALL_SYMBOLS" = "true" ] || [[ "$SORT_SYMBOLS" = *"$BIN_FILE"* ]]; then
SYM_SORT_CMD="sort"
else
SYM_SORT_CMD="cat"
@@ -810,31 +803,34 @@
if [ -z "$FULLDUMP_DIFF_FILTER" ]; then
FULLDUMP_DIFF_FILTER="$CAT"
fi
- $FULLDUMP_CMD $OTHER_FILE | eval "$FULLDUMP_DIFF_FILTER" > $WORK_FILE_BASE.fulldump.other 2>&1
- $FULLDUMP_CMD $THIS_FILE | eval "$FULLDUMP_DIFF_FILTER" > $WORK_FILE_BASE.fulldump.this 2>&1
+ $FULLDUMP_CMD $OTHER_FILE | eval "$FULLDUMP_DIFF_FILTER" \
+ > $WORK_FILE_BASE.fulldump.other 2>&1
+ $FULLDUMP_CMD $THIS_FILE | eval "$FULLDUMP_DIFF_FILTER" \
+ > $WORK_FILE_BASE.fulldump.this 2>&1
- LC_ALL=C $DIFF $WORK_FILE_BASE.fulldump.other $WORK_FILE_BASE.fulldump.this > $WORK_FILE_BASE.fulldump.diff
+ LC_ALL=C $DIFF $WORK_FILE_BASE.fulldump.other $WORK_FILE_BASE.fulldump.this \
+ > $WORK_FILE_BASE.fulldump.diff
if [ -s $WORK_FILE_BASE.fulldump.diff ]; then
- ELF_DIFF_SIZE=$(ls -n $WORK_FILE_BASE.fulldump.diff | awk '{print $5}')
- ELF_MSG=$($PRINTF "%8d" $ELF_DIFF_SIZE)
- if [[ "$ACCEPTED_ELF_DIFF" != *"$BIN_FILE"* ]]; then
- DIFF_ELF=true
- if [[ "$KNOWN_ELF_DIFF" != *"$BIN_FILE"* ]]; then
- ELF_MSG="*$ELF_MSG*"
+ FULLDUMP_DIFF_SIZE=$(ls -n $WORK_FILE_BASE.fulldump.diff | awk '{print $5}')
+ FULLDUMP_MSG=$($PRINTF "%8d" $FULLDUMP_DIFF_SIZE)
+ if [[ "$ACCEPTED_FULLDUMP_DIFF" != *"$BIN_FILE"* ]]; then
+ DIFF_FULLDUMP=true
+ if [[ "$KNOWN_FULLDUMP_DIFF" != *"$BIN_FILE"* ]]; then
+ FULLDUMP_MSG="*$FULLDUMP_MSG*"
REGRESSIONS=true
else
- ELF_MSG=" $ELF_MSG "
+ FULLDUMP_MSG=" $FULLDUMP_MSG "
fi
else
- ELF_MSG="($ELF_MSG)"
- DIFF_ELF=
+ FULLDUMP_MSG="($FULLDUMP_MSG)"
+ DIFF_FULLDUMP=
fi
else
- ELF_MSG=" "
- DIFF_ELF=
- if [[ "$KNOWN_DEP_DIFF $ACCEPTED_DEP_DIFF" = *"$BIN_FILE"* ]]; then
- ELF_MSG=" ! "
+ FULLDUMP_MSG=" "
+ DIFF_FULLDUMP=
+ if [[ "$KNOWN_FULLDUMP_DIFF $ACCEPTED_FULLDUMP_DIFF" = *"$BIN_FILE"* ]]; then
+ FULLDUMP_MSG=" ! "
fi
fi
fi
@@ -845,7 +841,7 @@
# To get a raw diff with the complete disassembly, set
# DIS_DIFF_FILTER="$CAT"
if [ -z "$DIS_DIFF_FILTER" ]; then
- DIS_DIFF_FILTER="$GREP -v ' # .* <.*>$'"
+ DIS_DIFF_FILTER="$GREP -v ' # .* <.*>$' | $SED -r -e 's/(\b|x)([0-9a-fA-F]+)(\b|:|>)/X/g'"
fi
$DIS_CMD $OTHER_FILE | $GREP -v $NAME | eval "$DIS_DIFF_FILTER" > $WORK_FILE_BASE.dis.other 2>&1
$DIS_CMD $THIS_FILE | $GREP -v $NAME | eval "$DIS_DIFF_FILTER" > $WORK_FILE_BASE.dis.this 2>&1
@@ -877,12 +873,12 @@
fi
- if [ -n "$DIFF_BIN$DIFF_SIZE$DIFF_SYM$DIFF_DEP$DIFF_ELF$DIFF_DIS" ] || [ -n "$VERBOSE" ]; then
+ if [ -n "$DIFF_BIN$DIFF_SIZE$DIFF_SYM$DIFF_DEP$DIFF_FULLDUMP$DIFF_DIS" ] || [ -n "$VERBOSE" ]; then
if [ -n "$BIN_MSG" ]; then echo -n "$BIN_MSG:"; fi
if [ -n "$SIZE_MSG" ]; then echo -n "$SIZE_MSG:"; fi
if [ -n "$SYM_MSG" ]; then echo -n "$SYM_MSG:"; fi
if [ -n "$DEP_MSG" ]; then echo -n "$DEP_MSG:"; fi
- if [ -n "$ELF_MSG" ]; then echo -n "$ELF_MSG:"; fi
+ if [ -n "$FULLDUMP_MSG" ]; then echo -n "$FULLDUMP_MSG:"; fi
if [ -n "$DIS_MSG" ]; then echo -n "$DIS_MSG:"; fi
echo " $BIN_FILE"
if [ "$SHOW_DIFFS" = "true" ]; then
@@ -1015,6 +1011,9 @@
echo "-vv More verbose output, shows diff output of all comparisons"
echo "-o [OTHER] Compare with build in other directory. Will default to the old build directory"
echo ""
+ echo "--sort-symbols Sort all symbols before comparing"
+ echo "--strip Strip all binaries before comparing"
+ echo ""
echo "[FILTER] List filenames in the image to compare, works for jars, zips, libs and execs"
echo "Example:"
echo "bash ./common/bin/compareimages.sh CodePointIM.jar"
@@ -1107,6 +1106,12 @@
shift
shift
;;
+ --sort-symbols)
+ SORT_ALL_SYMBOLS=true
+ ;;
+ --strip)
+ STRIP_ALL=true
+ ;;
*)
CMP_NAMES=false
CMP_PERMS=false
@@ -1223,7 +1228,7 @@
OTHER_JDK_BUNDLE="$OTHER/images/jdk-bundle"
OTHER_JRE_BUNDLE="$OTHER/images/jre-bundle"
fi
- echo "Also comparing macosx bundles"
+ echo "Also comparing jdk macosx bundles"
echo " $THIS_JDK_BUNDLE"
echo " $OTHER_JDK_BUNDLE"
fi
--- a/corba/.hgtags Sat Sep 26 09:22:24 2015 -0700
+++ b/corba/.hgtags Wed Jul 05 20:51:27 2017 +0200
@@ -325,3 +325,4 @@
821a0373ef2d1642a9824facb938b901ad010413 jdk9-b80
45c35b7f5b40d5af0085e4a7b3a4d6e3e0347c35 jdk9-b81
c20d8ebddaa6fb09cc81d3edf3d1d05f4232700a jdk9-b82
+ca8a1719588424f6e04e943790c7fcb7cb0b8c8f jdk9-b83
--- a/hotspot/.hgtags Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/.hgtags Wed Jul 05 20:51:27 2017 +0200
@@ -485,3 +485,4 @@
8e8377739c06b99b9011c003c77e0bef84c91e09 jdk9-b80
4142c190cd5ca4fb70ec367b4f97ef936272d8ef jdk9-b81
1c453a12be3036d482abef1dd470f8aff536b6b9 jdk9-b82
+3ed0df2c553a80e0e26b91a6ce08806ea17a066a jdk9-b83
--- a/hotspot/src/cpu/aarch64/vm/aarch64.ad Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad Wed Jul 05 20:51:27 2017 +0200
@@ -3803,81 +3803,37 @@
enc_class aarch64_enc_cmpxchg(memory mem, iRegLNoSp oldval, iRegLNoSp newval) %{
MacroAssembler _masm(&cbuf);
- Register old_reg = as_Register($oldval$$reg);
- Register new_reg = as_Register($newval$$reg);
- Register base = as_Register($mem$$base);
- Register addr_reg;
- int index = $mem$$index;
- int scale = $mem$$scale;
- int disp = $mem$$disp;
- if (index == -1) {
- if (disp != 0) {
- __ lea(rscratch2, Address(base, disp));
- addr_reg = rscratch2;
- } else {
- // TODO
- // should we ever get anything other than this case?
- addr_reg = base;
- }
- } else {
- Register index_reg = as_Register(index);
- if (disp == 0) {
- __ lea(rscratch2, Address(base, index_reg, Address::lsl(scale)));
- addr_reg = rscratch2;
- } else {
- __ lea(rscratch2, Address(base, disp));
- __ lea(rscratch2, Address(rscratch2, index_reg, Address::lsl(scale)));
- addr_reg = rscratch2;
- }
- }
- Label retry_load, done;
- __ bind(retry_load);
- __ ldxr(rscratch1, addr_reg);
- __ cmp(rscratch1, old_reg);
- __ br(Assembler::NE, done);
- __ stlxr(rscratch1, new_reg, addr_reg);
- __ cbnzw(rscratch1, retry_load);
- __ bind(done);
+ guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
+ __ cmpxchg($mem$$base$$Register, $oldval$$Register, $newval$$Register,
+ &Assembler::ldxr, &MacroAssembler::cmp, &Assembler::stlxr);
%}
enc_class aarch64_enc_cmpxchgw(memory mem, iRegINoSp oldval, iRegINoSp newval) %{
MacroAssembler _masm(&cbuf);
- Register old_reg = as_Register($oldval$$reg);
- Register new_reg = as_Register($newval$$reg);
- Register base = as_Register($mem$$base);
- Register addr_reg;
- int index = $mem$$index;
- int scale = $mem$$scale;
- int disp = $mem$$disp;
- if (index == -1) {
- if (disp != 0) {
- __ lea(rscratch2, Address(base, disp));
- addr_reg = rscratch2;
- } else {
- // TODO
- // should we ever get anything other than this case?
- addr_reg = base;
- }
- } else {
- Register index_reg = as_Register(index);
- if (disp == 0) {
- __ lea(rscratch2, Address(base, index_reg, Address::lsl(scale)));
- addr_reg = rscratch2;
- } else {
- __ lea(rscratch2, Address(base, disp));
- __ lea(rscratch2, Address(rscratch2, index_reg, Address::lsl(scale)));
- addr_reg = rscratch2;
- }
- }
- Label retry_load, done;
- __ bind(retry_load);
- __ ldxrw(rscratch1, addr_reg);
- __ cmpw(rscratch1, old_reg);
- __ br(Assembler::NE, done);
- __ stlxrw(rscratch1, new_reg, addr_reg);
- __ cbnzw(rscratch1, retry_load);
- __ bind(done);
- %}
+ guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
+ __ cmpxchg($mem$$base$$Register, $oldval$$Register, $newval$$Register,
+ &Assembler::ldxrw, &MacroAssembler::cmpw, &Assembler::stlxrw);
+ %}
+
+
+ // The only difference between aarch64_enc_cmpxchg and
+ // aarch64_enc_cmpxchg_acq is that we use load-acquire in the
+ // CompareAndSwap sequence to serve as a barrier on acquiring a
+ // lock.
+ enc_class aarch64_enc_cmpxchg_acq(memory mem, iRegLNoSp oldval, iRegLNoSp newval) %{
+ MacroAssembler _masm(&cbuf);
+ guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
+ __ cmpxchg($mem$$base$$Register, $oldval$$Register, $newval$$Register,
+ &Assembler::ldaxr, &MacroAssembler::cmp, &Assembler::stlxr);
+ %}
+
+ enc_class aarch64_enc_cmpxchgw_acq(memory mem, iRegINoSp oldval, iRegINoSp newval) %{
+ MacroAssembler _masm(&cbuf);
+ guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
+ __ cmpxchg($mem$$base$$Register, $oldval$$Register, $newval$$Register,
+ &Assembler::ldaxrw, &MacroAssembler::cmpw, &Assembler::stlxrw);
+ %}
+
// auxiliary used for CompareAndSwapX to set result register
enc_class aarch64_enc_cset_eq(iRegINoSp res) %{
@@ -4398,13 +4354,10 @@
// Compare object markOop with mark and if equal exchange scratch1
// with object markOop.
- // Note that this is simply a CAS: it does not generate any
- // barriers. These are separately generated by
- // membar_acquire_lock().
{
Label retry_load;
__ bind(retry_load);
- __ ldxr(tmp, oop);
+ __ ldaxr(tmp, oop);
__ cmp(tmp, disp_hdr);
__ br(Assembler::NE, cas_failed);
// use stlxr to ensure update is immediately visible
@@ -4454,7 +4407,7 @@
{
Label retry_load, fail;
__ bind(retry_load);
- __ ldxr(rscratch1, tmp);
+ __ ldaxr(rscratch1, tmp);
__ cmp(disp_hdr, rscratch1);
__ br(Assembler::NE, fail);
// use stlxr to ensure update is immediately visible
@@ -8017,10 +7970,10 @@
match(MemBarAcquireLock);
ins_cost(VOLATILE_REF_COST);
- format %{ "membar_acquire_lock" %}
-
- ins_encode %{
- __ membar(Assembler::LoadLoad|Assembler::LoadStore);
+ format %{ "membar_acquire_lock (elided)" %}
+
+ ins_encode %{
+ __ block_comment("membar_acquire_lock (elided)");
%}
ins_pipe(pipe_serial);
@@ -8080,10 +8033,10 @@
match(MemBarReleaseLock);
ins_cost(VOLATILE_REF_COST);
- format %{ "membar_release_lock" %}
-
- ins_encode %{
- __ membar(Assembler::LoadStore|Assembler::StoreStore);
+ format %{ "membar_release_lock (elided)" %}
+
+ ins_encode %{
+ __ block_comment("membar_release_lock (elided)");
%}
ins_pipe(pipe_serial);
@@ -8369,7 +8322,11 @@
ins_pipe(pipe_serial);
%}
-// this has to be implemented as a CAS
+
+// storeLConditional is used by PhaseMacroExpand::expand_lock_node
+// when attempting to rebias a lock towards the current thread. We
+// must use the acquire form of cmpxchg in order to guarantee acquire
+// semantics in this case.
instruct storeLConditional(indirect mem, iRegLNoSp oldval, iRegLNoSp newval, rFlagsReg cr)
%{
match(Set cr (StoreLConditional mem (Binary oldval newval)));
@@ -8381,12 +8338,14 @@
"cmpw rscratch1, zr\t# EQ on successful write"
%}
- ins_encode(aarch64_enc_cmpxchg(mem, oldval, newval));
+ ins_encode(aarch64_enc_cmpxchg_acq(mem, oldval, newval));
ins_pipe(pipe_slow);
%}
-// this has to be implemented as a CAS
+// storeIConditional also has acquire semantics, for no better reason
+// than matching storeLConditional. At the time of writing this
+// comment storeIConditional was not used anywhere by AArch64.
instruct storeIConditional(indirect mem, iRegINoSp oldval, iRegINoSp newval, rFlagsReg cr)
%{
match(Set cr (StoreIConditional mem (Binary oldval newval)));
@@ -8398,7 +8357,7 @@
"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);
%}
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp Wed Jul 05 20:51:27 2017 +0200
@@ -917,6 +917,8 @@
void cmpptr(Register src1, Address src2);
+ // Various forms of CAS
+
void cmpxchgptr(Register oldv, Register newv, Register addr, Register tmp,
Label &suceed, Label *fail);
@@ -938,6 +940,23 @@
str(rscratch2, adr);
}
+ // A generic CAS; success or failure is in the EQ flag.
+ template <typename T1, typename T2>
+ void cmpxchg(Register addr, Register expected, Register new_val,
+ T1 load_insn,
+ void (MacroAssembler::*cmp_insn)(Register, Register),
+ T2 store_insn,
+ Register tmp = rscratch1) {
+ Label retry_load, done;
+ bind(retry_load);
+ (this->*load_insn)(tmp, addr);
+ (this->*cmp_insn)(tmp, expected);
+ br(Assembler::NE, done);
+ (this->*store_insn)(tmp, new_val, addr);
+ cbnzw(tmp, retry_load);
+ bind(done);
+ }
+
// Calls
address trampoline_call(Address entry, CodeBuffer *cbuf = NULL);
--- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -394,25 +394,25 @@
int mod_idx = 0;
// We will test if the displacement fits the compressed format and if so
// apply the compression to the displacment iff the result is8bit.
- if (VM_Version::supports_evex() && is_evex_instruction) {
- switch (tuple_type) {
+ if (VM_Version::supports_evex() && _is_evex_instruction) {
+ switch (_tuple_type) {
case EVEX_FV:
- if ((evex_encoding & VEX_W) == VEX_W) {
- mod_idx += 2 + ((evex_encoding & EVEX_Rb) == EVEX_Rb) ? 1 : 0;
+ if ((_evex_encoding & VEX_W) == VEX_W) {
+ mod_idx += 2 + ((_evex_encoding & EVEX_Rb) == EVEX_Rb) ? 1 : 0;
} else {
- mod_idx = ((evex_encoding & EVEX_Rb) == EVEX_Rb) ? 1 : 0;
+ mod_idx = ((_evex_encoding & EVEX_Rb) == EVEX_Rb) ? 1 : 0;
}
break;
case EVEX_HV:
- mod_idx = ((evex_encoding & EVEX_Rb) == EVEX_Rb) ? 1 : 0;
+ mod_idx = ((_evex_encoding & EVEX_Rb) == EVEX_Rb) ? 1 : 0;
break;
case EVEX_FVM:
break;
case EVEX_T1S:
- switch (input_size_in_bits) {
+ switch (_input_size_in_bits) {
case EVEX_8bit:
break;
@@ -433,7 +433,7 @@
case EVEX_T1F:
case EVEX_T2:
case EVEX_T4:
- mod_idx = (input_size_in_bits == EVEX_64bit) ? 1 : 0;
+ mod_idx = (_input_size_in_bits == EVEX_64bit) ? 1 : 0;
break;
case EVEX_T8:
@@ -459,8 +459,8 @@
break;
}
- if (avx_vector_len >= AVX_128bit && avx_vector_len <= AVX_512bit) {
- int disp_factor = tuple_table[tuple_type + mod_idx][avx_vector_len];
+ if (_avx_vector_len >= AVX_128bit && _avx_vector_len <= AVX_512bit) {
+ int disp_factor = tuple_table[_tuple_type + mod_idx][_avx_vector_len];
if ((disp % disp_factor) == 0) {
int new_disp = disp / disp_factor;
if (is8bit(new_disp)) {
@@ -591,7 +591,7 @@
emit_data(disp, rspec, disp32_operand);
}
}
- is_evex_instruction = false;
+ _is_evex_instruction = false;
}
void Assembler::emit_operand(XMMRegister reg, Register base, Register index,
@@ -1229,8 +1229,8 @@
void Assembler::addsd(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_64bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_64bit;
emit_simd_arith_q(0x58, dst, src, VEX_SIMD_F2);
} else {
emit_simd_arith(0x58, dst, src, VEX_SIMD_F2);
@@ -1245,8 +1245,8 @@
void Assembler::addss(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
}
emit_simd_arith(0x58, dst, src, VEX_SIMD_F3);
}
@@ -1254,16 +1254,16 @@
void Assembler::aesdec(XMMRegister dst, Address src) {
assert(VM_Version::supports_aes(), "");
InstructionMark im(this);
- simd_prefix(dst, dst, src, VEX_SIMD_66, false,
- VEX_OPCODE_0F_38, false, AVX_128bit, true);
+ simd_prefix(dst, dst, src, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F_38, /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
emit_int8((unsigned char)0xDE);
emit_operand(dst, src);
}
void Assembler::aesdec(XMMRegister dst, XMMRegister src) {
assert(VM_Version::supports_aes(), "");
- int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, false,
- VEX_OPCODE_0F_38, false, AVX_128bit, true);
+ int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F_38, /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
emit_int8((unsigned char)0xDE);
emit_int8(0xC0 | encode);
}
@@ -1271,16 +1271,16 @@
void Assembler::aesdeclast(XMMRegister dst, Address src) {
assert(VM_Version::supports_aes(), "");
InstructionMark im(this);
- simd_prefix(dst, dst, src, VEX_SIMD_66, false,
- VEX_OPCODE_0F_38, false, AVX_128bit, true);
+ simd_prefix(dst, dst, src, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F_38, /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
emit_int8((unsigned char)0xDF);
emit_operand(dst, src);
}
void Assembler::aesdeclast(XMMRegister dst, XMMRegister src) {
assert(VM_Version::supports_aes(), "");
- int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, false,
- VEX_OPCODE_0F_38, false, AVX_128bit, true);
+ int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F_38, /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
emit_int8((unsigned char)0xDF);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -1288,16 +1288,16 @@
void Assembler::aesenc(XMMRegister dst, Address src) {
assert(VM_Version::supports_aes(), "");
InstructionMark im(this);
- simd_prefix(dst, dst, src, VEX_SIMD_66, false,
- VEX_OPCODE_0F_38, false, AVX_128bit, true);
+ simd_prefix(dst, dst, src, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F_38, /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
emit_int8((unsigned char)0xDC);
emit_operand(dst, src);
}
void Assembler::aesenc(XMMRegister dst, XMMRegister src) {
assert(VM_Version::supports_aes(), "");
- int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, false,
- VEX_OPCODE_0F_38, false, AVX_128bit, true);
+ int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F_38, /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
emit_int8((unsigned char)0xDC);
emit_int8(0xC0 | encode);
}
@@ -1305,21 +1305,20 @@
void Assembler::aesenclast(XMMRegister dst, Address src) {
assert(VM_Version::supports_aes(), "");
InstructionMark im(this);
- simd_prefix(dst, dst, src, VEX_SIMD_66, false,
- VEX_OPCODE_0F_38, false, AVX_128bit, true);
+ simd_prefix(dst, dst, src, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F_38, /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
emit_int8((unsigned char)0xDD);
emit_operand(dst, src);
}
void Assembler::aesenclast(XMMRegister dst, XMMRegister src) {
assert(VM_Version::supports_aes(), "");
- int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, false,
- VEX_OPCODE_0F_38, false, AVX_128bit, true);
+ int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F_38, /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
emit_int8((unsigned char)0xDD);
emit_int8((unsigned char)(0xC0 | encode));
}
-
void Assembler::andl(Address dst, int32_t imm32) {
InstructionMark im(this);
prefix(dst);
@@ -1347,7 +1346,7 @@
void Assembler::andnl(Register dst, Register src1, Register src2) {
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
- int encode = vex_prefix_0F38_and_encode_legacy(dst, src1, src2, false);
+ int encode = vex_prefix_0F38_and_encode_legacy(dst, src1, src2);
emit_int8((unsigned char)0xF2);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -1355,7 +1354,7 @@
void Assembler::andnl(Register dst, Register src1, Address src2) {
InstructionMark im(this);
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
- vex_prefix_0F38_legacy(dst, src1, src2, false);
+ vex_prefix_0F38_legacy(dst, src1, src2);
emit_int8((unsigned char)0xF2);
emit_operand(dst, src2);
}
@@ -1382,7 +1381,7 @@
void Assembler::blsil(Register dst, Register src) {
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
- int encode = vex_prefix_0F38_and_encode_legacy(rbx, dst, src, false);
+ int encode = vex_prefix_0F38_and_encode_legacy(rbx, dst, src);
emit_int8((unsigned char)0xF3);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -1390,14 +1389,14 @@
void Assembler::blsil(Register dst, Address src) {
InstructionMark im(this);
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
- vex_prefix_0F38_legacy(rbx, dst, src, false);
+ vex_prefix_0F38_legacy(rbx, dst, src);
emit_int8((unsigned char)0xF3);
emit_operand(rbx, src);
}
void Assembler::blsmskl(Register dst, Register src) {
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
- int encode = vex_prefix_0F38_and_encode_legacy(rdx, dst, src, false);
+ int encode = vex_prefix_0F38_and_encode_legacy(rdx, dst, src);
emit_int8((unsigned char)0xF3);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -1405,14 +1404,14 @@
void Assembler::blsmskl(Register dst, Address src) {
InstructionMark im(this);
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
- vex_prefix_0F38(rdx, dst, src, false);
+ vex_prefix_0F38_legacy(rdx, dst, src);
emit_int8((unsigned char)0xF3);
emit_operand(rdx, src);
}
void Assembler::blsrl(Register dst, Register src) {
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
- int encode = vex_prefix_0F38_and_encode_legacy(rcx, dst, src, false);
+ int encode = vex_prefix_0F38_and_encode_legacy(rcx, dst, src);
emit_int8((unsigned char)0xF3);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -1420,7 +1419,7 @@
void Assembler::blsrl(Register dst, Address src) {
InstructionMark im(this);
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
- vex_prefix_0F38_legacy(rcx, dst, src, false);
+ vex_prefix_0F38_legacy(rcx, dst, src);
emit_int8((unsigned char)0xF3);
emit_operand(rcx, src);
}
@@ -1569,9 +1568,9 @@
// 0x66 is there. Strangly ucomisd comes out correct
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_64bit;
- emit_simd_arith_nonds_q(0x2F, dst, src, VEX_SIMD_66, true);
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_64bit;
+ emit_simd_arith_nonds_q(0x2F, dst, src, VEX_SIMD_66, /* no_mask_reg */ true);
} else {
emit_simd_arith_nonds(0x2F, dst, src, VEX_SIMD_66);
}
@@ -1580,7 +1579,7 @@
void Assembler::comisd(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- emit_simd_arith_nonds_q(0x2F, dst, src, VEX_SIMD_66, true);
+ emit_simd_arith_nonds_q(0x2F, dst, src, VEX_SIMD_66, /* no_mask_reg */ true);
} else {
emit_simd_arith_nonds(0x2F, dst, src, VEX_SIMD_66);
}
@@ -1588,16 +1587,16 @@
void Assembler::comiss(XMMRegister dst, Address src) {
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
}
NOT_LP64(assert(VM_Version::supports_sse(), ""));
- emit_simd_arith_nonds(0x2F, dst, src, VEX_SIMD_NONE, true);
+ emit_simd_arith_nonds(0x2F, dst, src, VEX_SIMD_NONE, /* no_mask_reg */ true);
}
void Assembler::comiss(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
- emit_simd_arith_nonds(0x2F, dst, src, VEX_SIMD_NONE, true);
+ emit_simd_arith_nonds(0x2F, dst, src, VEX_SIMD_NONE, /* no_mask_reg */ true);
}
void Assembler::cpuid() {
@@ -1607,12 +1606,12 @@
void Assembler::cvtdq2pd(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- emit_simd_arith_nonds(0xE6, dst, src, VEX_SIMD_F3);
+ emit_simd_arith_nonds(0xE6, dst, src, VEX_SIMD_F3, /* no_mask_reg */ false, /* legacy_mode */ true);
}
void Assembler::cvtdq2ps(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- emit_simd_arith_nonds(0x5B, dst, src, VEX_SIMD_NONE);
+ emit_simd_arith_nonds(0x5B, dst, src, VEX_SIMD_NONE, /* no_mask_reg */ false, /* legacy_mode */ true);
}
void Assembler::cvtsd2ss(XMMRegister dst, XMMRegister src) {
@@ -1627,8 +1626,8 @@
void Assembler::cvtsd2ss(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1F;
- input_size_in_bits = EVEX_64bit;
+ _tuple_type = EVEX_T1F;
+ _input_size_in_bits = EVEX_64bit;
emit_simd_arith_q(0x5A, dst, src, VEX_SIMD_F2);
} else {
emit_simd_arith(0x5A, dst, src, VEX_SIMD_F2);
@@ -1637,12 +1636,7 @@
void Assembler::cvtsi2sdl(XMMRegister dst, Register src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- int encode = 0;
- if (VM_Version::supports_evex()) {
- encode = simd_prefix_and_encode_q(dst, dst, src, VEX_SIMD_F2, true);
- } else {
- encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F2, false);
- }
+ int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F2, VM_Version::supports_evex());
emit_int8(0x2A);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -1650,9 +1644,9 @@
void Assembler::cvtsi2sdl(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
- emit_simd_arith_q(0x2A, dst, src, VEX_SIMD_F2, true);
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
+ emit_simd_arith(0x2A, dst, src, VEX_SIMD_F2, /* no_mask_reg */ true);
} else {
emit_simd_arith(0x2A, dst, src, VEX_SIMD_F2);
}
@@ -1660,23 +1654,23 @@
void Assembler::cvtsi2ssl(XMMRegister dst, Register src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
- int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F3, true);
+ int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F3, /* no_mask_reg */ true);
emit_int8(0x2A);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::cvtsi2ssl(XMMRegister dst, Address src) {
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
}
NOT_LP64(assert(VM_Version::supports_sse(), ""));
- emit_simd_arith(0x2A, dst, src, VEX_SIMD_F3, true);
+ emit_simd_arith(0x2A, dst, src, VEX_SIMD_F3, /* no_mask_reg */ true);
}
void Assembler::cvtsi2ssq(XMMRegister dst, Register src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
- int encode = simd_prefix_and_encode_q(dst, dst, src, VEX_SIMD_F3, true);
+ int encode = simd_prefix_and_encode_q(dst, dst, src, VEX_SIMD_F3, /* no_mask_reg */ true);
emit_int8(0x2A);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -1688,8 +1682,8 @@
void Assembler::cvtss2sd(XMMRegister dst, Address src) {
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
}
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
emit_simd_arith(0x5A, dst, src, VEX_SIMD_F3);
@@ -1698,14 +1692,14 @@
void Assembler::cvttsd2sil(Register dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_F2, VEX_OPCODE_0F, true);
+ int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_F2, VEX_OPCODE_0F, /* no_mask_reg */ true);
emit_int8(0x2C);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::cvttss2sil(Register dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
- int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_F3, VEX_OPCODE_0F, true);
+ int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_F3, VEX_OPCODE_0F, /* no_mask_reg */ true);
emit_int8(0x2C);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -1721,8 +1715,8 @@
void Assembler::divsd(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_64bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_64bit;
emit_simd_arith_q(0x5E, dst, src, VEX_SIMD_F2);
} else {
emit_simd_arith(0x5E, dst, src, VEX_SIMD_F2);
@@ -1740,8 +1734,8 @@
void Assembler::divss(XMMRegister dst, Address src) {
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
}
NOT_LP64(assert(VM_Version::supports_sse(), ""));
emit_simd_arith(0x5E, dst, src, VEX_SIMD_F3);
@@ -1995,8 +1989,16 @@
void Assembler::movapd(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- if (VM_Version::supports_evex()) {
- emit_simd_arith_nonds_q(0x28, dst, src, VEX_SIMD_66, true);
+ if (VM_Version::supports_avx512novl()) {
+ int vector_len = AVX_512bit;
+ int dst_enc = dst->encoding();
+ int src_enc = src->encoding();
+ int encode = vex_prefix_and_encode(dst_enc, 0, src_enc, VEX_SIMD_66, VEX_OPCODE_0F,
+ /* vex_w */ true, vector_len, /* legacy_mode */ false, /* no_mask_reg */ false);
+ emit_int8(0x28);
+ emit_int8((unsigned char)(0xC0 | encode));
+ } else if (VM_Version::supports_evex()) {
+ emit_simd_arith_nonds_q(0x28, dst, src, VEX_SIMD_66);
} else {
emit_simd_arith_nonds(0x28, dst, src, VEX_SIMD_66);
}
@@ -2004,13 +2006,19 @@
void Assembler::movaps(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
- emit_simd_arith_nonds(0x28, dst, src, VEX_SIMD_NONE);
+ if (VM_Version::supports_avx512novl()) {
+ int vector_len = AVX_512bit;
+ int encode = vex_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_NONE, vector_len);
+ emit_int8(0x28);
+ emit_int8((unsigned char)(0xC0 | encode));
+ } else {
+ emit_simd_arith_nonds(0x28, dst, src, VEX_SIMD_NONE);
+ }
}
void Assembler::movlhps(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
- int encode = simd_prefix_and_encode(dst, src, src, VEX_SIMD_NONE, true, VEX_OPCODE_0F,
- false, AVX_128bit);
+ int encode = simd_prefix_and_encode(dst, src, src, VEX_SIMD_NONE, /* no_mask_reg */ true);
emit_int8(0x16);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -2023,48 +2031,54 @@
emit_operand(dst, src);
}
-void Assembler::kmovq(KRegister dst, KRegister src) {
+void Assembler::kmovql(KRegister dst, KRegister src) {
NOT_LP64(assert(VM_Version::supports_evex(), ""));
int encode = kreg_prefix_and_encode(dst, knoreg, src, VEX_SIMD_NONE,
- true, VEX_OPCODE_0F, true);
+ /* no_mask_reg */ true, VEX_OPCODE_0F, /* rex_w */ true);
emit_int8((unsigned char)0x90);
emit_int8((unsigned char)(0xC0 | encode));
}
-void Assembler::kmovq(KRegister dst, Address src) {
+void Assembler::kmovql(KRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_evex(), ""));
int dst_enc = dst->encoding();
int nds_enc = 0;
vex_prefix(src, nds_enc, dst_enc, VEX_SIMD_NONE,
- VEX_OPCODE_0F, true, AVX_128bit, true, true);
+ VEX_OPCODE_0F, /* vex_w */ true, AVX_128bit, /* legacy_mode */ true, /* no_reg_mask */ true);
emit_int8((unsigned char)0x90);
emit_operand((Register)dst, src);
}
-void Assembler::kmovq(Address dst, KRegister src) {
+void Assembler::kmovql(Address dst, KRegister src) {
NOT_LP64(assert(VM_Version::supports_evex(), ""));
int src_enc = src->encoding();
int nds_enc = 0;
vex_prefix(dst, nds_enc, src_enc, VEX_SIMD_NONE,
- VEX_OPCODE_0F, true, AVX_128bit, true, true);
+ VEX_OPCODE_0F, /* vex_w */ true, AVX_128bit, /* legacy_mode */ true, /* no_reg_mask */ true);
emit_int8((unsigned char)0x90);
emit_operand((Register)src, dst);
}
void Assembler::kmovql(KRegister dst, Register src) {
NOT_LP64(assert(VM_Version::supports_evex(), ""));
- bool supports_bw = VM_Version::supports_avx512bw();
- VexSimdPrefix pre = supports_bw ? VEX_SIMD_F2 : VEX_SIMD_NONE;
- int encode = kreg_prefix_and_encode(dst, knoreg, src, pre, true,
- VEX_OPCODE_0F, supports_bw);
+ VexSimdPrefix pre = !_legacy_mode_bw ? VEX_SIMD_F2 : VEX_SIMD_NONE;
+ int encode = kreg_prefix_and_encode(dst, knoreg, src, pre, /* no_mask_reg */ true,
+ VEX_OPCODE_0F, /* legacy_mode */ !_legacy_mode_bw);
emit_int8((unsigned char)0x92);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::kmovdl(KRegister dst, Register src) {
NOT_LP64(assert(VM_Version::supports_evex(), ""));
- VexSimdPrefix pre = VM_Version::supports_avx512bw() ? VEX_SIMD_F2 : VEX_SIMD_NONE;
- int encode = kreg_prefix_and_encode(dst, knoreg, src, pre, true, VEX_OPCODE_0F, false);
+ VexSimdPrefix pre = !_legacy_mode_bw ? VEX_SIMD_F2 : VEX_SIMD_NONE;
+ int encode = kreg_prefix_and_encode(dst, knoreg, src, pre, /* no_mask_reg */ true);
+ emit_int8((unsigned char)0x92);
+ emit_int8((unsigned char)(0xC0 | encode));
+}
+
+void Assembler::kmovwl(KRegister dst, Register src) {
+ NOT_LP64(assert(VM_Version::supports_evex(), ""));
+ int encode = kreg_prefix_and_encode(dst, knoreg, src, VEX_SIMD_NONE, /* no_mask_reg */ true);
emit_int8((unsigned char)0x92);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -2088,7 +2102,7 @@
void Assembler::movdl(XMMRegister dst, Register src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_66, true);
+ int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_66, /* no_mask_reg */ true);
emit_int8(0x6E);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -2096,7 +2110,7 @@
void Assembler::movdl(Register dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
// swap src/dst to get correct prefix
- int encode = simd_prefix_and_encode(src, dst, VEX_SIMD_66, true);
+ int encode = simd_prefix_and_encode(src, dst, VEX_SIMD_66, /* no_mask_reg */ true);
emit_int8(0x7E);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -2104,11 +2118,11 @@
void Assembler::movdl(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
- }
- InstructionMark im(this);
- simd_prefix(dst, src, VEX_SIMD_66, true, VEX_OPCODE_0F);
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
+ }
+ InstructionMark im(this);
+ simd_prefix(dst, src, VEX_SIMD_66, /* no_reg_mask */ true);
emit_int8(0x6E);
emit_operand(dst, src);
}
@@ -2116,58 +2130,61 @@
void Assembler::movdl(Address dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
- }
- InstructionMark im(this);
- simd_prefix(dst, src, VEX_SIMD_66, true);
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
+ }
+ InstructionMark im(this);
+ simd_prefix(dst, src, VEX_SIMD_66, /* no_reg_mask */ true);
emit_int8(0x7E);
emit_operand(src, dst);
}
void Assembler::movdqa(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
emit_simd_arith_nonds(0x6F, dst, src, VEX_SIMD_66);
}
void Assembler::movdqa(XMMRegister dst, Address src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FVM;
+ _tuple_type = EVEX_FVM;
}
emit_simd_arith_nonds(0x6F, dst, src, VEX_SIMD_66);
}
void Assembler::movdqu(XMMRegister dst, Address src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FVM;
+ _tuple_type = EVEX_FVM;
}
emit_simd_arith_nonds(0x6F, dst, src, VEX_SIMD_F3);
}
void Assembler::movdqu(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
emit_simd_arith_nonds(0x6F, dst, src, VEX_SIMD_F3);
}
void Assembler::movdqu(Address dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FVM;
- }
- InstructionMark im(this);
- simd_prefix(dst, src, VEX_SIMD_F3, false);
+ _tuple_type = EVEX_FVM;
+ }
+ InstructionMark im(this);
+ simd_prefix(dst, src, VEX_SIMD_F3, /* no_mask_reg */ false);
emit_int8(0x7F);
emit_operand(src, dst);
}
// Move Unaligned 256bit Vector
void Assembler::vmovdqu(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "");
- if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FVM;
- }
int vector_len = AVX_256bit;
int encode = vex_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_F3, vector_len);
emit_int8(0x6F);
@@ -2175,67 +2192,100 @@
}
void Assembler::vmovdqu(XMMRegister dst, Address src) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FVM;
+ _tuple_type = EVEX_FVM;
}
InstructionMark im(this);
int vector_len = AVX_256bit;
- vex_prefix(dst, xnoreg, src, VEX_SIMD_F3, vector_len, false);
+ vex_prefix(dst, xnoreg, src, VEX_SIMD_F3, vector_len);
emit_int8(0x6F);
emit_operand(dst, src);
}
void Assembler::vmovdqu(Address dst, XMMRegister src) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FVM;
+ _tuple_type = EVEX_FVM;
}
InstructionMark im(this);
int vector_len = AVX_256bit;
// swap src<->dst for encoding
assert(src != xnoreg, "sanity");
- vex_prefix(src, xnoreg, dst, VEX_SIMD_F3, vector_len, false);
+ vex_prefix(src, xnoreg, dst, VEX_SIMD_F3, vector_len);
emit_int8(0x7F);
emit_operand(src, dst);
}
// Move Unaligned EVEX enabled Vector (programmable : 8,16,32,64)
-void Assembler::evmovdqu(XMMRegister dst, XMMRegister src, int vector_len) {
+void Assembler::evmovdqul(XMMRegister dst, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "");
int src_enc = src->encoding();
int dst_enc = dst->encoding();
int encode = vex_prefix_and_encode(dst_enc, 0, src_enc, VEX_SIMD_F3, VEX_OPCODE_0F,
- true, vector_len, false, false);
+ /* vex_w */ false, vector_len, /* legacy_mode */ false, /* no_mask_reg */ false);
emit_int8(0x6F);
emit_int8((unsigned char)(0xC0 | encode));
}
-void Assembler::evmovdqu(XMMRegister dst, Address src, int vector_len) {
+void Assembler::evmovdqul(XMMRegister dst, Address src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "");
InstructionMark im(this);
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FVM;
- vex_prefix_q(dst, xnoreg, src, VEX_SIMD_F3, vector_len, false);
- } else {
- vex_prefix(dst, xnoreg, src, VEX_SIMD_F3, vector_len, false);
- }
+ _tuple_type = EVEX_FVM;
+ }
+ vex_prefix(dst, xnoreg, src, VEX_SIMD_F3, vector_len);
emit_int8(0x6F);
emit_operand(dst, src);
}
-void Assembler::evmovdqu(Address dst, XMMRegister src, int vector_len) {
+void Assembler::evmovdqul(Address dst, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "");
InstructionMark im(this);
assert(src != xnoreg, "sanity");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FVM;
- // swap src<->dst for encoding
- vex_prefix_q(src, xnoreg, dst, VEX_SIMD_F3, vector_len, false);
- } else {
- // swap src<->dst for encoding
- vex_prefix(src, xnoreg, dst, VEX_SIMD_F3, vector_len, false);
- }
+ _tuple_type = EVEX_FVM;
+ }
+ // swap src<->dst for encoding
+ vex_prefix(src, xnoreg, dst, VEX_SIMD_F3, vector_len);
+ emit_int8(0x7F);
+ emit_operand(src, dst);
+}
+
+void Assembler::evmovdquq(XMMRegister dst, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
+ assert(UseAVX > 0, "");
+ int src_enc = src->encoding();
+ int dst_enc = dst->encoding();
+ int encode = vex_prefix_and_encode(dst_enc, 0, src_enc, VEX_SIMD_F3, VEX_OPCODE_0F,
+ /* vex_w */ true, vector_len, /* legacy_mode */ false, /* no_mask_reg */ false);
+ emit_int8(0x6F);
+ emit_int8((unsigned char)(0xC0 | encode));
+}
+
+void Assembler::evmovdquq(XMMRegister dst, Address src, int vector_len) {
+ _instruction_uses_vl = true;
+ assert(UseAVX > 2, "");
+ InstructionMark im(this);
+ _tuple_type = EVEX_FVM;
+ vex_prefix_q(dst, xnoreg, src, VEX_SIMD_F3, vector_len);
+ emit_int8(0x6F);
+ emit_operand(dst, src);
+}
+
+void Assembler::evmovdquq(Address dst, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
+ assert(UseAVX > 2, "");
+ InstructionMark im(this);
+ assert(src != xnoreg, "sanity");
+ _tuple_type = EVEX_FVM;
+ // swap src<->dst for encoding
+ vex_prefix_q(src, xnoreg, dst, VEX_SIMD_F3, vector_len);
emit_int8(0x7F);
emit_operand(src, dst);
}
@@ -2282,10 +2332,12 @@
void Assembler::movlpd(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
- }
- emit_simd_arith(0x12, dst, src, VEX_SIMD_66, true);
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
+ emit_simd_arith_q(0x12, dst, src, VEX_SIMD_66, /* no_mask_reg */ true);
+ } else {
+ emit_simd_arith(0x12, dst, src, VEX_SIMD_66, /* no_mask_reg */ true);
+ }
}
void Assembler::movq( MMXRegister dst, Address src ) {
@@ -2312,11 +2364,11 @@
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
InstructionMark im(this);
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_64bit;
- simd_prefix_q(dst, xnoreg, src, VEX_SIMD_F3, true);
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_64bit;
+ simd_prefix_q(dst, xnoreg, src, VEX_SIMD_F3, /* no_mask_reg */ true);
} else {
- simd_prefix(dst, src, VEX_SIMD_F3, true, VEX_OPCODE_0F);
+ simd_prefix(dst, src, VEX_SIMD_F3, /* no_mask_reg */ true);
}
emit_int8(0x7E);
emit_operand(dst, src);
@@ -2326,12 +2378,12 @@
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
InstructionMark im(this);
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_64bit;
- simd_prefix(src, xnoreg, dst, VEX_SIMD_66, true,
- VEX_OPCODE_0F, true, AVX_128bit);
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_64bit;
+ simd_prefix(src, xnoreg, dst, VEX_SIMD_66, /* no_mask_reg */ true,
+ VEX_OPCODE_0F, /* rex_w */ true);
} else {
- simd_prefix(dst, src, VEX_SIMD_66, true);
+ simd_prefix(dst, src, VEX_SIMD_66, /* no_mask_reg */ true);
}
emit_int8((unsigned char)0xD6);
emit_operand(src, dst);
@@ -2356,7 +2408,7 @@
void Assembler::movsd(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- emit_simd_arith_q(0x10, dst, src, VEX_SIMD_F2, true);
+ emit_simd_arith_q(0x10, dst, src, VEX_SIMD_F2, /* no_mask_reg */ true);
} else {
emit_simd_arith(0x10, dst, src, VEX_SIMD_F2);
}
@@ -2365,9 +2417,9 @@
void Assembler::movsd(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_64bit;
- emit_simd_arith_nonds_q(0x10, dst, src, VEX_SIMD_F2, true);
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_64bit;
+ emit_simd_arith_nonds_q(0x10, dst, src, VEX_SIMD_F2, /* no_mask_reg */ true);
} else {
emit_simd_arith_nonds(0x10, dst, src, VEX_SIMD_F2);
}
@@ -2377,11 +2429,11 @@
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
InstructionMark im(this);
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_64bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_64bit;
simd_prefix_q(src, xnoreg, dst, VEX_SIMD_F2);
} else {
- simd_prefix(src, xnoreg, dst, VEX_SIMD_F2, false);
+ simd_prefix(src, xnoreg, dst, VEX_SIMD_F2, /* no_mask_reg */ false);
}
emit_int8(0x11);
emit_operand(src, dst);
@@ -2389,26 +2441,26 @@
void Assembler::movss(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
- emit_simd_arith(0x10, dst, src, VEX_SIMD_F3, true);
+ emit_simd_arith(0x10, dst, src, VEX_SIMD_F3, /* no_mask_reg */ true);
}
void Assembler::movss(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
- }
- emit_simd_arith_nonds(0x10, dst, src, VEX_SIMD_F3, true);
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
+ }
+ emit_simd_arith_nonds(0x10, dst, src, VEX_SIMD_F3, /* no_mask_reg */ true);
}
void Assembler::movss(Address dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
- }
- InstructionMark im(this);
- simd_prefix(dst, src, VEX_SIMD_F3, false);
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
+ }
+ InstructionMark im(this);
+ simd_prefix(dst, src, VEX_SIMD_F3, /* no_mask_reg */ false);
emit_int8(0x11);
emit_operand(src, dst);
}
@@ -2501,8 +2553,8 @@
void Assembler::mulsd(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_64bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_64bit;
emit_simd_arith_q(0x59, dst, src, VEX_SIMD_F2);
} else {
emit_simd_arith(0x59, dst, src, VEX_SIMD_F2);
@@ -2521,8 +2573,8 @@
void Assembler::mulss(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
}
emit_simd_arith(0x59, dst, src, VEX_SIMD_F3);
}
@@ -2831,29 +2883,27 @@
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_32bit;
- }
- emit_simd_arith(0x67, dst, src, VEX_SIMD_66,
- false, (VM_Version::supports_avx512dq() == false));
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_32bit;
+ }
+ emit_simd_arith(0x67, dst, src, VEX_SIMD_66, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::packuswb(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- emit_simd_arith(0x67, dst, src, VEX_SIMD_66,
- false, (VM_Version::supports_avx512dq() == false));
+ emit_simd_arith(0x67, dst, src, VEX_SIMD_66, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::vpackuswb(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
assert(UseAVX > 0, "some form of AVX must be enabled");
- emit_vex_arith(0x67, dst, nds, src, VEX_SIMD_66, vector_len,
- false, (VM_Version::supports_avx512dq() == false));
+ emit_vex_arith(0x67, dst, nds, src, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::vpermq(XMMRegister dst, XMMRegister src, int imm8, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_avx2(), "");
- int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, false,
- VEX_OPCODE_0F_3A, true, vector_len);
+ int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F_3A, /* rex_w */ true, vector_len);
emit_int8(0x00);
emit_int8(0xC0 | encode);
emit_int8(imm8);
@@ -2867,8 +2917,8 @@
void Assembler::pcmpestri(XMMRegister dst, Address src, int imm8) {
assert(VM_Version::supports_sse4_2(), "");
InstructionMark im(this);
- simd_prefix(dst, xnoreg, src, VEX_SIMD_66, false, VEX_OPCODE_0F_3A,
- false, AVX_128bit, true);
+ simd_prefix(dst, xnoreg, src, VEX_SIMD_66, /* no_mask_reg */ false, VEX_OPCODE_0F_3A,
+ /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
emit_int8(0x61);
emit_operand(dst, src);
emit_int8(imm8);
@@ -2876,8 +2926,8 @@
void Assembler::pcmpestri(XMMRegister dst, XMMRegister src, int imm8) {
assert(VM_Version::supports_sse4_2(), "");
- int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, false,
- VEX_OPCODE_0F_3A, false, AVX_128bit, true);
+ int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F_3A, /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
emit_int8(0x61);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8(imm8);
@@ -2885,8 +2935,8 @@
void Assembler::pextrd(Register dst, XMMRegister src, int imm8) {
assert(VM_Version::supports_sse4_1(), "");
- int encode = simd_prefix_and_encode(as_XMMRegister(dst->encoding()), xnoreg, src, VEX_SIMD_66, true, VEX_OPCODE_0F_3A,
- false, AVX_128bit, (VM_Version::supports_avx512dq() == false));
+ int encode = simd_prefix_and_encode(as_XMMRegister(dst->encoding()), xnoreg, src, VEX_SIMD_66, /* no_mask_reg */ true,
+ VEX_OPCODE_0F_3A, /* rex_w */ false, AVX_128bit, /* legacy_mode */ _legacy_mode_dq);
emit_int8(0x16);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8(imm8);
@@ -2894,8 +2944,8 @@
void Assembler::pextrq(Register dst, XMMRegister src, int imm8) {
assert(VM_Version::supports_sse4_1(), "");
- int encode = simd_prefix_and_encode(as_XMMRegister(dst->encoding()), xnoreg, src, VEX_SIMD_66, true, VEX_OPCODE_0F_3A,
- false, AVX_128bit, (VM_Version::supports_avx512dq() == false));
+ int encode = simd_prefix_and_encode(as_XMMRegister(dst->encoding()), xnoreg, src, VEX_SIMD_66, /* no_mask_reg */ true,
+ VEX_OPCODE_0F_3A, /* rex_w */ true, AVX_128bit, /* legacy_mode */ _legacy_mode_dq);
emit_int8(0x16);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8(imm8);
@@ -2903,8 +2953,8 @@
void Assembler::pinsrd(XMMRegister dst, Register src, int imm8) {
assert(VM_Version::supports_sse4_1(), "");
- int encode = simd_prefix_and_encode(dst, dst, as_XMMRegister(src->encoding()), VEX_SIMD_66, true, VEX_OPCODE_0F_3A,
- false, AVX_128bit, (VM_Version::supports_avx512dq() == false));
+ int encode = simd_prefix_and_encode(dst, dst, as_XMMRegister(src->encoding()), VEX_SIMD_66, /* no_mask_reg */ true,
+ VEX_OPCODE_0F_3A, /* rex_w */ false, AVX_128bit, /* legacy_mode */ _legacy_mode_dq);
emit_int8(0x22);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8(imm8);
@@ -2912,8 +2962,8 @@
void Assembler::pinsrq(XMMRegister dst, Register src, int imm8) {
assert(VM_Version::supports_sse4_1(), "");
- int encode = simd_prefix_and_encode(dst, dst, as_XMMRegister(src->encoding()), VEX_SIMD_66, true, VEX_OPCODE_0F_3A,
- false, AVX_128bit, (VM_Version::supports_avx512dq() == false));
+ int encode = simd_prefix_and_encode(dst, dst, as_XMMRegister(src->encoding()), VEX_SIMD_66, /* no_mask_reg */ true,
+ VEX_OPCODE_0F_3A, /* rex_w */ true, AVX_128bit, /* legacy_mode */ _legacy_mode_dq);
emit_int8(0x22);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8(imm8);
@@ -2922,17 +2972,17 @@
void Assembler::pmovzxbw(XMMRegister dst, Address src) {
assert(VM_Version::supports_sse4_1(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_HVM;
- }
- InstructionMark im(this);
- simd_prefix(dst, src, VEX_SIMD_66, false, VEX_OPCODE_0F_38);
+ _tuple_type = EVEX_HVM;
+ }
+ InstructionMark im(this);
+ simd_prefix(dst, src, VEX_SIMD_66, /* no_mask_reg */ false, VEX_OPCODE_0F_38);
emit_int8(0x30);
emit_operand(dst, src);
}
void Assembler::pmovzxbw(XMMRegister dst, XMMRegister src) {
assert(VM_Version::supports_sse4_1(), "");
- int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, false, VEX_OPCODE_0F_38);
+ int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, /* no_mask_reg */ false, VEX_OPCODE_0F_38);
emit_int8(0x30);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -3035,8 +3085,8 @@
void Assembler::pshufb(XMMRegister dst, XMMRegister src) {
assert(VM_Version::supports_ssse3(), "");
- int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, false, VEX_OPCODE_0F_38,
- false, AVX_128bit, (VM_Version::supports_avx512bw() == false));
+ int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F_38, /* rex_w */ false, AVX_128bit, /* legacy_mode */ _legacy_mode_bw);
emit_int8(0x00);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -3044,33 +3094,34 @@
void Assembler::pshufb(XMMRegister dst, Address src) {
assert(VM_Version::supports_ssse3(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FVM;
- }
- InstructionMark im(this);
- simd_prefix(dst, dst, src, VEX_SIMD_66, false, VEX_OPCODE_0F_38,
- false, AVX_128bit, (VM_Version::supports_avx512bw() == false));
+ _tuple_type = EVEX_FVM;
+ }
+ InstructionMark im(this);
+ simd_prefix(dst, dst, src, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F_38, /* rex_w */ false, AVX_128bit, /* legacy_mode */ _legacy_mode_bw);
emit_int8(0x00);
emit_operand(dst, src);
}
void Assembler::pshufd(XMMRegister dst, XMMRegister src, int mode) {
+ _instruction_uses_vl = true;
assert(isByte(mode), "invalid value");
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
emit_simd_arith_nonds(0x70, dst, src, VEX_SIMD_66);
emit_int8(mode & 0xFF);
-
}
void Assembler::pshufd(XMMRegister dst, Address src, int mode) {
+ _instruction_uses_vl = true;
assert(isByte(mode), "invalid value");
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_32bit;
- }
- InstructionMark im(this);
- simd_prefix(dst, src, VEX_SIMD_66, false);
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_32bit;
+ }
+ InstructionMark im(this);
+ simd_prefix(dst, src, VEX_SIMD_66, /* no_mask_reg */ false);
emit_int8(0x70);
emit_operand(dst, src);
emit_int8(mode & 0xFF);
@@ -3079,8 +3130,7 @@
void Assembler::pshuflw(XMMRegister dst, XMMRegister src, int mode) {
assert(isByte(mode), "invalid value");
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- emit_simd_arith_nonds(0x70, dst, src, VEX_SIMD_F2, false,
- (VM_Version::supports_avx512bw() == false));
+ emit_simd_arith_nonds(0x70, dst, src, VEX_SIMD_F2, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
emit_int8(mode & 0xFF);
}
@@ -3089,29 +3139,33 @@
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FVM;
- }
- InstructionMark im(this);
- simd_prefix(dst, xnoreg, src, VEX_SIMD_F2, false, VEX_OPCODE_0F,
- false, AVX_128bit, (VM_Version::supports_avx512bw() == false));
+ _tuple_type = EVEX_FVM;
+ }
+ InstructionMark im(this);
+ simd_prefix(dst, xnoreg, src, VEX_SIMD_F2, /* no_mask_reg */ false,
+ VEX_OPCODE_0F, /* rex_w */ false, AVX_128bit, /* legacy_mode */ _legacy_mode_bw);
emit_int8(0x70);
emit_operand(dst, src);
emit_int8(mode & 0xFF);
}
void Assembler::psrldq(XMMRegister dst, int shift) {
- // Shift 128 bit value in xmm register by number of bytes.
+ // Shift left 128 bit value in dst XMMRegister by shift number of bytes.
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- int encode = simd_prefix_and_encode(xmm3, dst, dst, VEX_SIMD_66, true, VEX_OPCODE_0F, false, AVX_128bit, (VM_Version::supports_avx512bw() == false));
+ // XMM3 is for /3 encoding: 66 0F 73 /3 ib
+ int encode = simd_prefix_and_encode(xmm3, dst, dst, VEX_SIMD_66, /* no_mask_reg */ true,
+ VEX_OPCODE_0F, /* rex_w */ false, AVX_128bit, /* legacy_mode */ _legacy_mode_bw);
emit_int8(0x73);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8(shift);
}
void Assembler::pslldq(XMMRegister dst, int shift) {
- // Shift left 128 bit value in xmm register by number of bytes.
+ // Shift left 128 bit value in dst XMMRegister by shift number of bytes.
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- int encode = simd_prefix_and_encode(xmm7, dst, dst, VEX_SIMD_66, true, VEX_OPCODE_0F, false, AVX_128bit, (VM_Version::supports_avx512bw() == false));
+ // XMM7 is for /7 encoding: 66 0F 73 /7 ib
+ int encode = simd_prefix_and_encode(xmm7, dst, dst, VEX_SIMD_66, /* no_mask_reg */ true,
+ VEX_OPCODE_0F, /* rex_w */ false, AVX_128bit, /* legacy_mode */ _legacy_mode_bw);
emit_int8(0x73);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8(shift);
@@ -3121,16 +3175,16 @@
assert(VM_Version::supports_sse4_1(), "");
assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes");
InstructionMark im(this);
- simd_prefix(dst, xnoreg, src, VEX_SIMD_66, false,
- VEX_OPCODE_0F_38, false, AVX_128bit, true);
+ simd_prefix(dst, xnoreg, src, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F_38, /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
emit_int8(0x17);
emit_operand(dst, src);
}
void Assembler::ptest(XMMRegister dst, XMMRegister src) {
assert(VM_Version::supports_sse4_1(), "");
- int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, false,
- VEX_OPCODE_0F_38, false, AVX_128bit, true);
+ int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F_38, /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
emit_int8(0x17);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -3142,7 +3196,8 @@
assert(dst != xnoreg, "sanity");
int dst_enc = dst->encoding();
// swap src<->dst for encoding
- vex_prefix(src, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, false, vector_len, true, false);
+ vex_prefix(src, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, /* rex_w */ false,
+ vector_len, /* legacy_mode */ true, /* no_mask_reg */ false);
emit_int8(0x17);
emit_operand(dst, src);
}
@@ -3150,8 +3205,7 @@
void Assembler::vptest(XMMRegister dst, XMMRegister src) {
assert(VM_Version::supports_avx(), "");
int vector_len = AVX_256bit;
- int encode = vex_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66,
- vector_len, VEX_OPCODE_0F_38, true, false);
+ int encode = vex_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, vector_len, VEX_OPCODE_0F_38, /* legacy_mode */ true);
emit_int8(0x17);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -3160,34 +3214,41 @@
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FVM;
- }
- emit_simd_arith(0x60, dst, src, VEX_SIMD_66, false, (VM_Version::supports_avx512vlbw() == false));
+ _tuple_type = EVEX_FVM;
+ }
+ emit_simd_arith(0x60, dst, src, VEX_SIMD_66, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_vlbw);
}
void Assembler::punpcklbw(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- emit_simd_arith(0x60, dst, src, VEX_SIMD_66, false, (VM_Version::supports_avx512vlbw() == false));
+ emit_simd_arith(0x60, dst, src, VEX_SIMD_66, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_vlbw);
}
void Assembler::punpckldq(XMMRegister dst, Address src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_32bit;
}
emit_simd_arith(0x62, dst, src, VEX_SIMD_66);
}
void Assembler::punpckldq(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
emit_simd_arith(0x62, dst, src, VEX_SIMD_66);
}
void Assembler::punpcklqdq(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- emit_simd_arith(0x6C, dst, src, VEX_SIMD_66);
+ if (VM_Version::supports_evex()) {
+ emit_simd_arith_q(0x6C, dst, src, VEX_SIMD_66);
+ } else {
+ emit_simd_arith(0x6C, dst, src, VEX_SIMD_66);
+ }
}
void Assembler::push(int32_t imm32) {
@@ -3396,8 +3457,8 @@
void Assembler::sqrtsd(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_64bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_64bit;
emit_simd_arith_q(0x51, dst, src, VEX_SIMD_F2);
} else {
emit_simd_arith(0x51, dst, src, VEX_SIMD_F2);
@@ -3416,8 +3477,8 @@
void Assembler::sqrtss(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
}
emit_simd_arith(0x51, dst, src, VEX_SIMD_F3);
}
@@ -3479,10 +3540,14 @@
void Assembler::subsd(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_64bit;
- }
- emit_simd_arith_q(0x5C, dst, src, VEX_SIMD_F2);
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_64bit;
+ }
+ if (VM_Version::supports_evex()) {
+ emit_simd_arith_q(0x5C, dst, src, VEX_SIMD_F2);
+ } else {
+ emit_simd_arith(0x5C, dst, src, VEX_SIMD_F2);
+ }
}
void Assembler::subss(XMMRegister dst, XMMRegister src) {
@@ -3493,8 +3558,8 @@
void Assembler::subss(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
}
emit_simd_arith(0x5C, dst, src, VEX_SIMD_F3);
}
@@ -3553,9 +3618,9 @@
void Assembler::ucomisd(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_64bit;
- emit_simd_arith_nonds_q(0x2E, dst, src, VEX_SIMD_66, true);
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_64bit;
+ emit_simd_arith_nonds_q(0x2E, dst, src, VEX_SIMD_66, /* no_mask_reg */ true);
} else {
emit_simd_arith_nonds(0x2E, dst, src, VEX_SIMD_66);
}
@@ -3564,7 +3629,7 @@
void Assembler::ucomisd(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- emit_simd_arith_nonds_q(0x2E, dst, src, VEX_SIMD_66, true);
+ emit_simd_arith_nonds_q(0x2E, dst, src, VEX_SIMD_66, /* no_mask_reg */ true);
} else {
emit_simd_arith_nonds(0x2E, dst, src, VEX_SIMD_66);
}
@@ -3573,15 +3638,15 @@
void Assembler::ucomiss(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
- }
- emit_simd_arith_nonds(0x2E, dst, src, VEX_SIMD_NONE, true);
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
+ }
+ emit_simd_arith_nonds(0x2E, dst, src, VEX_SIMD_NONE, /* no_mask_reg */ true);
}
void Assembler::ucomiss(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
- emit_simd_arith_nonds(0x2E, dst, src, VEX_SIMD_NONE, true);
+ emit_simd_arith_nonds(0x2E, dst, src, VEX_SIMD_NONE, /* no_mask_reg */ true);
}
void Assembler::xabort(int8_t imm8) {
@@ -3664,8 +3729,8 @@
void Assembler::vaddsd(XMMRegister dst, XMMRegister nds, Address src) {
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_64bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_64bit;
emit_vex_arith_q(0x58, dst, nds, src, VEX_SIMD_F2, AVX_128bit);
} else {
emit_vex_arith(0x58, dst, nds, src, VEX_SIMD_F2, AVX_128bit);
@@ -3684,8 +3749,8 @@
void Assembler::vaddss(XMMRegister dst, XMMRegister nds, Address src) {
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
}
emit_vex_arith(0x58, dst, nds, src, VEX_SIMD_F3, AVX_128bit);
}
@@ -3698,8 +3763,8 @@
void Assembler::vdivsd(XMMRegister dst, XMMRegister nds, Address src) {
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_64bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_64bit;
emit_vex_arith_q(0x5E, dst, nds, src, VEX_SIMD_F2, AVX_128bit);
} else {
emit_vex_arith(0x5E, dst, nds, src, VEX_SIMD_F2, AVX_128bit);
@@ -3718,8 +3783,8 @@
void Assembler::vdivss(XMMRegister dst, XMMRegister nds, Address src) {
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
}
emit_vex_arith(0x5E, dst, nds, src, VEX_SIMD_F3, AVX_128bit);
}
@@ -3732,8 +3797,8 @@
void Assembler::vmulsd(XMMRegister dst, XMMRegister nds, Address src) {
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_64bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_64bit;
emit_vex_arith_q(0x59, dst, nds, src, VEX_SIMD_F2, AVX_128bit);
} else {
emit_vex_arith(0x59, dst, nds, src, VEX_SIMD_F2, AVX_128bit);
@@ -3752,8 +3817,8 @@
void Assembler::vmulss(XMMRegister dst, XMMRegister nds, Address src) {
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
}
emit_vex_arith(0x59, dst, nds, src, VEX_SIMD_F3, AVX_128bit);
}
@@ -3766,8 +3831,8 @@
void Assembler::vsubsd(XMMRegister dst, XMMRegister nds, Address src) {
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_64bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_64bit;
emit_vex_arith_q(0x5C, dst, nds, src, VEX_SIMD_F2, AVX_128bit);
} else {
emit_vex_arith(0x5C, dst, nds, src, VEX_SIMD_F2, AVX_128bit);
@@ -3786,8 +3851,8 @@
void Assembler::vsubss(XMMRegister dst, XMMRegister nds, Address src) {
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
}
emit_vex_arith(0x5C, dst, nds, src, VEX_SIMD_F3, AVX_128bit);
}
@@ -3802,6 +3867,7 @@
// Float-point vector arithmetic
void Assembler::addpd(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
emit_simd_arith_q(0x58, dst, src, VEX_SIMD_66);
@@ -3811,11 +3877,13 @@
}
void Assembler::addps(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
emit_simd_arith(0x58, dst, src, VEX_SIMD_NONE);
}
void Assembler::vaddpd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
emit_vex_arith_q(0x58, dst, nds, src, VEX_SIMD_66, vector_len);
@@ -3825,15 +3893,17 @@
}
void Assembler::vaddps(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_avx(), "");
emit_vex_arith(0x58, dst, nds, src, VEX_SIMD_NONE, vector_len);
}
void Assembler::vaddpd(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_64bit;
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_64bit;
emit_vex_arith_q(0x58, dst, nds, src, VEX_SIMD_66, vector_len);
} else {
emit_vex_arith(0x58, dst, nds, src, VEX_SIMD_66, vector_len);
@@ -3841,15 +3911,17 @@
}
void Assembler::vaddps(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_32bit;
}
emit_vex_arith(0x58, dst, nds, src, VEX_SIMD_NONE, vector_len);
}
void Assembler::subpd(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
emit_simd_arith_q(0x5C, dst, src, VEX_SIMD_66);
@@ -3859,11 +3931,13 @@
}
void Assembler::subps(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
emit_simd_arith(0x5C, dst, src, VEX_SIMD_NONE);
}
void Assembler::vsubpd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
emit_vex_arith_q(0x5C, dst, nds, src, VEX_SIMD_66, vector_len);
@@ -3873,15 +3947,17 @@
}
void Assembler::vsubps(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_avx(), "");
emit_vex_arith(0x5C, dst, nds, src, VEX_SIMD_NONE, vector_len);
}
void Assembler::vsubpd(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_64bit;
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_64bit;
emit_vex_arith_q(0x5C, dst, nds, src, VEX_SIMD_66, vector_len);
} else {
emit_vex_arith(0x5C, dst, nds, src, VEX_SIMD_66, vector_len);
@@ -3889,15 +3965,17 @@
}
void Assembler::vsubps(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_32bit;
}
emit_vex_arith(0x5C, dst, nds, src, VEX_SIMD_NONE, vector_len);
}
void Assembler::mulpd(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
emit_simd_arith_q(0x59, dst, src, VEX_SIMD_66);
@@ -3907,11 +3985,13 @@
}
void Assembler::mulps(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
emit_simd_arith(0x59, dst, src, VEX_SIMD_NONE);
}
void Assembler::vmulpd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
emit_vex_arith_q(0x59, dst, nds, src, VEX_SIMD_66, vector_len);
@@ -3921,15 +4001,17 @@
}
void Assembler::vmulps(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_avx(), "");
emit_vex_arith(0x59, dst, nds, src, VEX_SIMD_NONE, vector_len);
}
void Assembler::vmulpd(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_64bit;
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_64bit;
emit_vex_arith_q(0x59, dst, nds, src, VEX_SIMD_66, vector_len);
} else {
emit_vex_arith(0x59, dst, nds, src, VEX_SIMD_66, vector_len);
@@ -3937,15 +4019,17 @@
}
void Assembler::vmulps(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_32bit;
}
emit_vex_arith(0x59, dst, nds, src, VEX_SIMD_NONE, vector_len);
}
void Assembler::divpd(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
emit_simd_arith_q(0x5E, dst, src, VEX_SIMD_66);
@@ -3955,11 +4039,13 @@
}
void Assembler::divps(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
emit_simd_arith(0x5E, dst, src, VEX_SIMD_NONE);
}
void Assembler::vdivpd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
emit_vex_arith_q(0x5E, dst, nds, src, VEX_SIMD_66, vector_len);
@@ -3969,15 +4055,17 @@
}
void Assembler::vdivps(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_avx(), "");
emit_vex_arith(0x5E, dst, nds, src, VEX_SIMD_NONE, vector_len);
}
void Assembler::vdivpd(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_64bit;
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_64bit;
emit_vex_arith_q(0x5E, dst, nds, src, VEX_SIMD_66, vector_len);
} else {
emit_vex_arith(0x5E, dst, nds, src, VEX_SIMD_66, vector_len);
@@ -3985,164 +4073,178 @@
}
void Assembler::vdivps(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
+ _instruction_uses_vl = true;
+ assert(VM_Version::supports_avx(), "");
+ if (VM_Version::supports_evex()) {
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_32bit;
+ }
+ emit_vex_arith(0x5E, dst, nds, src, VEX_SIMD_NONE, vector_len);
+}
+
+void Assembler::vsqrtpd(XMMRegister dst, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_32bit;
- }
- emit_vex_arith(0x5E, dst, nds, src, VEX_SIMD_NONE, vector_len);
+ emit_vex_arith_q(0x51, dst, xnoreg, src, VEX_SIMD_66, vector_len);
+ } else {
+ emit_vex_arith(0x51, dst, xnoreg, src, VEX_SIMD_66, vector_len);
+ }
+}
+
+void Assembler::vsqrtpd(XMMRegister dst, Address src, int vector_len) {
+ _instruction_uses_vl = true;
+ assert(VM_Version::supports_avx(), "");
+ if (VM_Version::supports_evex()) {
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_64bit;
+ emit_vex_arith_q(0x51, dst, xnoreg, src, VEX_SIMD_66, vector_len);
+ } else {
+ emit_vex_arith(0x51, dst, xnoreg, src, VEX_SIMD_66, vector_len);
+ }
}
void Assembler::andpd(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- if (VM_Version::supports_evex() && VM_Version::supports_avx512dq()) {
+ if (VM_Version::supports_avx512dq()) {
emit_simd_arith_q(0x54, dst, src, VEX_SIMD_66);
} else {
- emit_simd_arith(0x54, dst, src, VEX_SIMD_66, false, true);
+ emit_simd_arith(0x54, dst, src, VEX_SIMD_66, /* no_mask_reg */ false, /* legacy_mode */ true);
}
}
void Assembler::andps(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
- emit_simd_arith(0x54, dst, src, VEX_SIMD_NONE, false,
- (VM_Version::supports_avx512dq() == false));
+ emit_simd_arith(0x54, dst, src, VEX_SIMD_NONE, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_dq);
}
void Assembler::andps(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_32bit;
- }
- emit_simd_arith(0x54, dst, src, VEX_SIMD_NONE,
- false, (VM_Version::supports_avx512dq() == false));
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_32bit;
+ }
+ emit_simd_arith(0x54, dst, src, VEX_SIMD_NONE, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_dq);
}
void Assembler::andpd(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- if (VM_Version::supports_evex() && VM_Version::supports_avx512dq()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_64bit;
+ if (VM_Version::supports_avx512dq()) {
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_64bit;
emit_simd_arith_q(0x54, dst, src, VEX_SIMD_66);
} else {
- emit_simd_arith(0x54, dst, src, VEX_SIMD_66, false, true);
+ emit_simd_arith(0x54, dst, src, VEX_SIMD_66, /* no_mask_reg */ false, /* legacy_mode */ true);
}
}
void Assembler::vandpd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
assert(VM_Version::supports_avx(), "");
- if (VM_Version::supports_evex() && VM_Version::supports_avx512dq()) {
+ if (VM_Version::supports_avx512dq()) {
emit_vex_arith_q(0x54, dst, nds, src, VEX_SIMD_66, vector_len);
} else {
- emit_vex_arith(0x54, dst, nds, src, VEX_SIMD_66, vector_len, true);
+ emit_vex_arith(0x54, dst, nds, src, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ true);
}
}
void Assembler::vandps(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
assert(VM_Version::supports_avx(), "");
- bool legacy_mode = (VM_Version::supports_avx512dq() == false);
- emit_vex_arith(0x54, dst, nds, src, VEX_SIMD_NONE, vector_len, legacy_mode);
+ emit_vex_arith(0x54, dst, nds, src, VEX_SIMD_NONE, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_dq);
}
void Assembler::vandpd(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
assert(VM_Version::supports_avx(), "");
- if (VM_Version::supports_evex() && VM_Version::supports_avx512dq()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_64bit;
+ if (VM_Version::supports_avx512dq()) {
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_64bit;
emit_vex_arith_q(0x54, dst, nds, src, VEX_SIMD_66, vector_len);
} else {
- emit_vex_arith(0x54, dst, nds, src, VEX_SIMD_66, vector_len, true);
+ emit_vex_arith(0x54, dst, nds, src, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ true);
}
}
void Assembler::vandps(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_32bit;
- }
- emit_vex_arith(0x54, dst, nds, src, VEX_SIMD_NONE, vector_len,
- (VM_Version::supports_avx512dq() == false));
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_32bit;
+ }
+ emit_vex_arith(0x54, dst, nds, src, VEX_SIMD_NONE, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_dq);
}
void Assembler::xorpd(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- if (VM_Version::supports_evex() && VM_Version::supports_avx512dq()) {
+ if (VM_Version::supports_avx512dq()) {
emit_simd_arith_q(0x57, dst, src, VEX_SIMD_66);
} else {
- emit_simd_arith(0x57, dst, src, VEX_SIMD_66, false, true);
+ emit_simd_arith(0x57, dst, src, VEX_SIMD_66, /* no_mask_reg */ false, /* legacy_mode */ true);
}
}
void Assembler::xorps(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
- emit_simd_arith(0x57, dst, src, VEX_SIMD_NONE,
- false, (VM_Version::supports_avx512dq() == false));
+ emit_simd_arith(0x57, dst, src, VEX_SIMD_NONE, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_dq);
}
void Assembler::xorpd(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- if (VM_Version::supports_evex() && VM_Version::supports_avx512dq()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_64bit;
+ if (VM_Version::supports_avx512dq()) {
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_64bit;
emit_simd_arith_q(0x57, dst, src, VEX_SIMD_66);
} else {
- emit_simd_arith(0x57, dst, src, VEX_SIMD_66, false, true);
+ emit_simd_arith(0x57, dst, src, VEX_SIMD_66, /* no_mask_reg */ false, /* legacy_mode */ true);
}
}
void Assembler::xorps(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_32bit;
- }
- emit_simd_arith(0x57, dst, src, VEX_SIMD_NONE, false,
- (VM_Version::supports_avx512dq() == false));
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_32bit;
+ }
+ emit_simd_arith(0x57, dst, src, VEX_SIMD_NONE, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_dq);
}
void Assembler::vxorpd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
assert(VM_Version::supports_avx(), "");
- if (VM_Version::supports_evex() && VM_Version::supports_avx512dq()) {
+ if (VM_Version::supports_avx512dq()) {
emit_vex_arith_q(0x57, dst, nds, src, VEX_SIMD_66, vector_len);
} else {
- emit_vex_arith(0x57, dst, nds, src, VEX_SIMD_66, vector_len, true);
+ emit_vex_arith(0x57, dst, nds, src, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ true);
}
}
void Assembler::vxorps(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
assert(VM_Version::supports_avx(), "");
- emit_vex_arith(0x57, dst, nds, src, VEX_SIMD_NONE, vector_len,
- (VM_Version::supports_avx512dq() == false));
+ emit_vex_arith(0x57, dst, nds, src, VEX_SIMD_NONE, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_dq);
}
void Assembler::vxorpd(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
assert(VM_Version::supports_avx(), "");
- if (VM_Version::supports_evex() && VM_Version::supports_avx512dq()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_64bit;
+ if (VM_Version::supports_avx512dq()) {
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_64bit;
emit_vex_arith_q(0x57, dst, nds, src, VEX_SIMD_66, vector_len);
} else {
- emit_vex_arith(0x57, dst, nds, src, VEX_SIMD_66, vector_len, true);
+ emit_vex_arith(0x57, dst, nds, src, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ true);
}
}
void Assembler::vxorps(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
assert(VM_Version::supports_avx(), "");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_32bit;
- }
- emit_vex_arith(0x57, dst, nds, src, VEX_SIMD_NONE, vector_len,
- (VM_Version::supports_avx512dq() == false));
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_32bit;
+ }
+ emit_vex_arith(0x57, dst, nds, src, VEX_SIMD_NONE, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_dq);
}
// Integer vector arithmetic
void Assembler::vphaddw(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
assert(VM_Version::supports_avx() && (vector_len == 0) ||
VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2");
- int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66, vector_len,
- VEX_OPCODE_0F_38, true, false);
+ int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66, vector_len, VEX_OPCODE_0F_38, /* legacy_mode */ true);
emit_int8(0x01);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -4150,28 +4252,29 @@
void Assembler::vphaddd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
assert(VM_Version::supports_avx() && (vector_len == 0) ||
VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2");
- int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66, vector_len,
- VEX_OPCODE_0F_38, true, false);
+ int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66, vector_len, VEX_OPCODE_0F_38, /* legacy_mode */ true);
emit_int8(0x02);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::paddb(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- emit_simd_arith(0xFC, dst, src, VEX_SIMD_66);
+ emit_simd_arith(0xFC, dst, src, VEX_SIMD_66, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::paddw(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- emit_simd_arith(0xFD, dst, src, VEX_SIMD_66);
+ emit_simd_arith(0xFD, dst, src, VEX_SIMD_66, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::paddd(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
emit_simd_arith(0xFE, dst, src, VEX_SIMD_66);
}
void Assembler::paddq(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
emit_simd_arith_q(0xD4, dst, src, VEX_SIMD_66);
@@ -4182,38 +4285,38 @@
void Assembler::phaddw(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse3(), ""));
- int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, false,
- VEX_OPCODE_0F_38, false, AVX_128bit, true);
+ int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F_38, /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
emit_int8(0x01);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::phaddd(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse3(), ""));
- int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, false,
- VEX_OPCODE_0F_38, false, AVX_128bit, true);
+ int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F_38, /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
emit_int8(0x02);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::vpaddb(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
assert(UseAVX > 0, "requires some form of AVX");
- emit_vex_arith(0xFC, dst, nds, src, VEX_SIMD_66, vector_len,
- (VM_Version::supports_avx512bw() == false));
+ emit_vex_arith(0xFC, dst, nds, src, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::vpaddw(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
assert(UseAVX > 0, "requires some form of AVX");
- emit_vex_arith(0xFD, dst, nds, src, VEX_SIMD_66, vector_len,
- (VM_Version::supports_avx512bw() == false));
+ emit_vex_arith(0xFD, dst, nds, src, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::vpaddd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
emit_vex_arith(0xFE, dst, nds, src, VEX_SIMD_66, vector_len);
}
void Assembler::vpaddq(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
if (VM_Version::supports_evex()) {
emit_vex_arith_q(0xD4, dst, nds, src, VEX_SIMD_66, vector_len);
@@ -4225,33 +4328,35 @@
void Assembler::vpaddb(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
assert(UseAVX > 0, "requires some form of AVX");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FVM;
- }
- emit_vex_arith(0xFC, dst, nds, src, VEX_SIMD_66, vector_len);
+ _tuple_type = EVEX_FVM;
+ }
+ emit_vex_arith(0xFC, dst, nds, src, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::vpaddw(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
assert(UseAVX > 0, "requires some form of AVX");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FVM;
- }
- emit_vex_arith(0xFD, dst, nds, src, VEX_SIMD_66, vector_len);
+ _tuple_type = EVEX_FVM;
+ }
+ emit_vex_arith(0xFD, dst, nds, src, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::vpaddd(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_32bit;
}
emit_vex_arith(0xFE, dst, nds, src, VEX_SIMD_66, vector_len);
}
void Assembler::vpaddq(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_64bit;
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_64bit;
emit_vex_arith_q(0xD4, dst, nds, src, VEX_SIMD_66, vector_len);
} else {
emit_vex_arith(0xD4, dst, nds, src, VEX_SIMD_66, vector_len);
@@ -4260,20 +4365,22 @@
void Assembler::psubb(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- emit_simd_arith(0xF8, dst, src, VEX_SIMD_66);
+ emit_simd_arith(0xF8, dst, src, VEX_SIMD_66, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::psubw(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- emit_simd_arith(0xF9, dst, src, VEX_SIMD_66);
+ emit_simd_arith(0xF9, dst, src, VEX_SIMD_66, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::psubd(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
emit_simd_arith(0xFA, dst, src, VEX_SIMD_66);
}
void Assembler::psubq(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
emit_simd_arith_q(0xFB, dst, src, VEX_SIMD_66);
@@ -4284,22 +4391,22 @@
void Assembler::vpsubb(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
assert(UseAVX > 0, "requires some form of AVX");
- emit_vex_arith(0xF8, dst, nds, src, VEX_SIMD_66, vector_len,
- (VM_Version::supports_avx512bw() == false));
+ emit_vex_arith(0xF8, dst, nds, src, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::vpsubw(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
assert(UseAVX > 0, "requires some form of AVX");
- emit_vex_arith(0xF9, dst, nds, src, VEX_SIMD_66, vector_len,
- (VM_Version::supports_avx512bw() == false));
+ emit_vex_arith(0xF9, dst, nds, src, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::vpsubd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
emit_vex_arith(0xFA, dst, nds, src, VEX_SIMD_66, vector_len);
}
void Assembler::vpsubq(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
if (VM_Version::supports_evex()) {
emit_vex_arith_q(0xFB, dst, nds, src, VEX_SIMD_66, vector_len);
@@ -4311,35 +4418,35 @@
void Assembler::vpsubb(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
assert(UseAVX > 0, "requires some form of AVX");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FVM;
- }
- emit_vex_arith(0xF8, dst, nds, src, VEX_SIMD_66, vector_len,
- (VM_Version::supports_avx512bw() == false));
+ _tuple_type = EVEX_FVM;
+ }
+ emit_vex_arith(0xF8, dst, nds, src, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::vpsubw(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
assert(UseAVX > 0, "requires some form of AVX");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FVM;
- }
- emit_vex_arith(0xF9, dst, nds, src, VEX_SIMD_66, vector_len,
- (VM_Version::supports_avx512bw() == false));
+ _tuple_type = EVEX_FVM;
+ }
+ emit_vex_arith(0xF9, dst, nds, src, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::vpsubd(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_32bit;
}
emit_vex_arith(0xFA, dst, nds, src, VEX_SIMD_66, vector_len);
}
void Assembler::vpsubq(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_64bit;
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_64bit;
emit_vex_arith_q(0xFB, dst, nds, src, VEX_SIMD_66, vector_len);
} else {
emit_vex_arith(0xFB, dst, nds, src, VEX_SIMD_66, vector_len);
@@ -4348,28 +4455,27 @@
void Assembler::pmullw(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- emit_simd_arith(0xD5, dst, src, VEX_SIMD_66,
- (VM_Version::supports_avx512bw() == false));
+ emit_simd_arith(0xD5, dst, src, VEX_SIMD_66, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::pmulld(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_sse4_1(), "");
int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66,
- false, VEX_OPCODE_0F_38);
+ /* no_mask_reg */ false, VEX_OPCODE_0F_38);
emit_int8(0x40);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::vpmullw(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
assert(UseAVX > 0, "requires some form of AVX");
- emit_vex_arith(0xD5, dst, nds, src, VEX_SIMD_66, vector_len,
- (VM_Version::supports_avx512bw() == false));
+ emit_vex_arith(0xD5, dst, nds, src, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::vpmulld(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
- int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66,
- vector_len, VEX_OPCODE_0F_38);
+ int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66, vector_len, VEX_OPCODE_0F_38);
emit_int8(0x40);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -4379,8 +4485,8 @@
int src_enc = src->encoding();
int dst_enc = dst->encoding();
int nds_enc = nds->is_valid() ? nds->encoding() : 0;
- int encode = vex_prefix_and_encode(dst_enc, nds_enc, src_enc, VEX_SIMD_66,
- VEX_OPCODE_0F_38, true, vector_len, false, false);
+ int encode = vex_prefix_and_encode(dst_enc, nds_enc, src_enc, VEX_SIMD_66, VEX_OPCODE_0F_38,
+ /* vex_w */ true, vector_len, /* legacy_mode */ _legacy_mode_dq, /* no_mask_reg */ false);
emit_int8(0x40);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -4388,22 +4494,23 @@
void Assembler::vpmullw(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
assert(UseAVX > 0, "requires some form of AVX");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FVM;
- }
- emit_vex_arith(0xD5, dst, nds, src, VEX_SIMD_66, vector_len);
+ _tuple_type = EVEX_FVM;
+ }
+ emit_vex_arith(0xD5, dst, nds, src, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::vpmulld(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_32bit;
}
InstructionMark im(this);
int dst_enc = dst->encoding();
int nds_enc = nds->is_valid() ? nds->encoding() : 0;
vex_prefix(src, nds_enc, dst_enc, VEX_SIMD_66,
- VEX_OPCODE_0F_38, false, vector_len);
+ VEX_OPCODE_0F_38, /* vex_w */ false, vector_len);
emit_int8(0x40);
emit_operand(dst, src);
}
@@ -4411,13 +4518,14 @@
void Assembler::vpmullq(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
assert(UseAVX > 0, "requires some form of AVX");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_64bit;
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_64bit;
}
InstructionMark im(this);
int dst_enc = dst->encoding();
int nds_enc = nds->is_valid() ? nds->encoding() : 0;
- vex_prefix(src, nds_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, true, vector_len);
+ vex_prefix(src, nds_enc, dst_enc, VEX_SIMD_66,
+ VEX_OPCODE_0F_38, /* vex_w */ true, vector_len, /* legacy_mode */ _legacy_mode_dq);
emit_int8(0x40);
emit_operand(dst, src);
}
@@ -4426,26 +4534,28 @@
void Assembler::psllw(XMMRegister dst, int shift) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
// XMM6 is for /6 encoding: 66 0F 71 /6 ib
- int encode = simd_prefix_and_encode(xmm6, dst, dst, VEX_SIMD_66, false, VEX_OPCODE_0F,
- false, AVX_128bit, (VM_Version::supports_avx512bw() == false));
+ int encode = simd_prefix_and_encode(xmm6, dst, dst, VEX_SIMD_66, /* no_mask_reg */ false, VEX_OPCODE_0F,
+ /* rex_w */ false, AVX_128bit, /* legacy_mode */ _legacy_mode_bw);
emit_int8(0x71);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8(shift & 0xFF);
}
void Assembler::pslld(XMMRegister dst, int shift) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
// XMM6 is for /6 encoding: 66 0F 72 /6 ib
- int encode = simd_prefix_and_encode(xmm6, dst, dst, VEX_SIMD_66, false);
+ int encode = simd_prefix_and_encode(xmm6, dst, dst, VEX_SIMD_66, /* no_mask_reg */ false);
emit_int8(0x72);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8(shift & 0xFF);
}
void Assembler::psllq(XMMRegister dst, int shift) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
// XMM6 is for /6 encoding: 66 0F 73 /6 ib
- int encode = simd_prefix_and_encode(xmm6, dst, dst, VEX_SIMD_66, false, VEX_OPCODE_0F, true);
+ int encode = simd_prefix_and_encode(xmm6, dst, dst, VEX_SIMD_66, /* no_mask_reg */ false, VEX_OPCODE_0F, /* rex_w */ true);
emit_int8(0x73);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8(shift & 0xFF);
@@ -4453,16 +4563,17 @@
void Assembler::psllw(XMMRegister dst, XMMRegister shift) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- emit_simd_arith(0xF1, dst, shift, VEX_SIMD_66, false,
- (VM_Version::supports_avx512bw() == false));
+ emit_simd_arith(0xF1, dst, shift, VEX_SIMD_66, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::pslld(XMMRegister dst, XMMRegister shift) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
emit_simd_arith(0xF2, dst, shift, VEX_SIMD_66);
}
void Assembler::psllq(XMMRegister dst, XMMRegister shift) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
emit_simd_arith_q(0xF3, dst, shift, VEX_SIMD_66);
@@ -4474,12 +4585,12 @@
void Assembler::vpsllw(XMMRegister dst, XMMRegister src, int shift, int vector_len) {
assert(UseAVX > 0, "requires some form of AVX");
// XMM6 is for /6 encoding: 66 0F 71 /6 ib
- emit_vex_arith(0x71, xmm6, dst, src, VEX_SIMD_66, vector_len,
- (VM_Version::supports_avx512bw() == false));
+ emit_vex_arith(0x71, xmm6, dst, src, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
emit_int8(shift & 0xFF);
}
void Assembler::vpslld(XMMRegister dst, XMMRegister src, int shift, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
// XMM6 is for /6 encoding: 66 0F 72 /6 ib
emit_vex_arith(0x72, xmm6, dst, src, VEX_SIMD_66, vector_len);
@@ -4487,6 +4598,7 @@
}
void Assembler::vpsllq(XMMRegister dst, XMMRegister src, int shift, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
// XMM6 is for /6 encoding: 66 0F 73 /6 ib
if (VM_Version::supports_evex()) {
@@ -4499,16 +4611,17 @@
void Assembler::vpsllw(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len) {
assert(UseAVX > 0, "requires some form of AVX");
- emit_vex_arith(0xF1, dst, src, shift, VEX_SIMD_66, vector_len,
- (VM_Version::supports_avx512bw() == false));
+ emit_vex_arith(0xF1, dst, src, shift, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::vpslld(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
emit_vex_arith(0xF2, dst, src, shift, VEX_SIMD_66, vector_len);
}
void Assembler::vpsllq(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
if (VM_Version::supports_evex()) {
emit_vex_arith_q(0xF3, dst, src, shift, VEX_SIMD_66, vector_len);
@@ -4521,33 +4634,31 @@
void Assembler::psrlw(XMMRegister dst, int shift) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
// XMM2 is for /2 encoding: 66 0F 71 /2 ib
- int encode = simd_prefix_and_encode(xmm2, dst, dst, VEX_SIMD_66, false, VEX_OPCODE_0F,
- (VM_Version::supports_avx512bw() == false));
+ int encode = simd_prefix_and_encode(xmm2, dst, dst, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F, /* rex_w */ false, AVX_128bit, /* legacy_mode */ _legacy_mode_bw);
emit_int8(0x71);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8(shift & 0xFF);
}
void Assembler::psrld(XMMRegister dst, int shift) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
// XMM2 is for /2 encoding: 66 0F 72 /2 ib
- int encode = simd_prefix_and_encode(xmm2, dst, dst, VEX_SIMD_66, false);
+ int encode = simd_prefix_and_encode(xmm2, dst, dst, VEX_SIMD_66, /* no_mask_reg */ false);
emit_int8(0x72);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8(shift & 0xFF);
}
void Assembler::psrlq(XMMRegister dst, int shift) {
+ _instruction_uses_vl = true;
// Do not confuse it with psrldq SSE2 instruction which
// shifts 128 bit value in xmm register by number of bytes.
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
// XMM2 is for /2 encoding: 66 0F 73 /2 ib
- int encode = 0;
- if (VM_Version::supports_evex() && VM_Version::supports_avx512bw()) {
- encode = simd_prefix_and_encode(xmm2, dst, dst, VEX_SIMD_66, true, VEX_OPCODE_0F, false);
- } else {
- encode = simd_prefix_and_encode(xmm2, dst, dst, VEX_SIMD_66, false, VEX_OPCODE_0F, true);
- }
+ int encode = simd_prefix_and_encode(xmm2, dst, dst, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F, /* rex_w */ VM_Version::supports_evex());
emit_int8(0x73);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8(shift & 0xFF);
@@ -4555,16 +4666,17 @@
void Assembler::psrlw(XMMRegister dst, XMMRegister shift) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- emit_simd_arith(0xD1, dst, shift, VEX_SIMD_66, false,
- (VM_Version::supports_avx512bw() == false));
+ emit_simd_arith(0xD1, dst, shift, VEX_SIMD_66, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::psrld(XMMRegister dst, XMMRegister shift) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
emit_simd_arith(0xD2, dst, shift, VEX_SIMD_66);
}
void Assembler::psrlq(XMMRegister dst, XMMRegister shift) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
emit_simd_arith_q(0xD3, dst, shift, VEX_SIMD_66);
@@ -4575,20 +4687,21 @@
void Assembler::vpsrlw(XMMRegister dst, XMMRegister src, int shift, int vector_len) {
assert(UseAVX > 0, "requires some form of AVX");
- // XMM2 is for /2 encoding: 66 0F 73 /2 ib
- emit_vex_arith(0x71, xmm2, dst, src, VEX_SIMD_66, vector_len,
- (VM_Version::supports_avx512bw() == false));
+ // XMM2 is for /2 encoding: 66 0F 71 /2 ib
+ emit_vex_arith(0x71, xmm2, dst, src, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
emit_int8(shift & 0xFF);
}
void Assembler::vpsrld(XMMRegister dst, XMMRegister src, int shift, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
- // XMM2 is for /2 encoding: 66 0F 73 /2 ib
+ // XMM2 is for /2 encoding: 66 0F 72 /2 ib
emit_vex_arith(0x72, xmm2, dst, src, VEX_SIMD_66, vector_len);
emit_int8(shift & 0xFF);
}
void Assembler::vpsrlq(XMMRegister dst, XMMRegister src, int shift, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
// XMM2 is for /2 encoding: 66 0F 73 /2 ib
if (VM_Version::supports_evex()) {
@@ -4601,16 +4714,17 @@
void Assembler::vpsrlw(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len) {
assert(UseAVX > 0, "requires some form of AVX");
- emit_vex_arith(0xD1, dst, src, shift, VEX_SIMD_66, vector_len,
- (VM_Version::supports_avx512bw() == false));
+ emit_vex_arith(0xD1, dst, src, shift, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::vpsrld(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
emit_vex_arith(0xD2, dst, src, shift, VEX_SIMD_66, vector_len);
}
void Assembler::vpsrlq(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
if (VM_Version::supports_evex()) {
emit_vex_arith_q(0xD3, dst, src, shift, VEX_SIMD_66, vector_len);
@@ -4623,17 +4737,18 @@
void Assembler::psraw(XMMRegister dst, int shift) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
// XMM4 is for /4 encoding: 66 0F 71 /4 ib
- int encode = simd_prefix_and_encode(xmm4, dst, dst, VEX_SIMD_66, false, VEX_OPCODE_0F,
- (VM_Version::supports_avx512bw() == false));
+ int encode = simd_prefix_and_encode(xmm4, dst, dst, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F, /* rex_w */ false, AVX_128bit, /* legacy_mode */ _legacy_mode_bw);
emit_int8(0x71);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8(shift & 0xFF);
}
void Assembler::psrad(XMMRegister dst, int shift) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
// XMM4 is for /4 encoding: 66 0F 72 /4 ib
- int encode = simd_prefix_and_encode(xmm4, dst, dst, VEX_SIMD_66, false);
+ int encode = simd_prefix_and_encode(xmm4, dst, dst, VEX_SIMD_66, /* no_mask_reg */ false);
emit_int8(0x72);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8(shift & 0xFF);
@@ -4641,11 +4756,11 @@
void Assembler::psraw(XMMRegister dst, XMMRegister shift) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- emit_simd_arith(0xE1, dst, shift, VEX_SIMD_66,
- (VM_Version::supports_avx512bw() == false));
+ emit_simd_arith(0xE1, dst, shift, VEX_SIMD_66, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::psrad(XMMRegister dst, XMMRegister shift) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
emit_simd_arith(0xE2, dst, shift, VEX_SIMD_66);
}
@@ -4653,12 +4768,12 @@
void Assembler::vpsraw(XMMRegister dst, XMMRegister src, int shift, int vector_len) {
assert(UseAVX > 0, "requires some form of AVX");
// XMM4 is for /4 encoding: 66 0F 71 /4 ib
- emit_vex_arith(0x71, xmm4, dst, src, VEX_SIMD_66, vector_len,
- (VM_Version::supports_avx512bw() == false));
+ emit_vex_arith(0x71, xmm4, dst, src, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
emit_int8(shift & 0xFF);
}
void Assembler::vpsrad(XMMRegister dst, XMMRegister src, int shift, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
// XMM4 is for /4 encoding: 66 0F 71 /4 ib
emit_vex_arith(0x72, xmm4, dst, src, VEX_SIMD_66, vector_len);
@@ -4667,11 +4782,11 @@
void Assembler::vpsraw(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len) {
assert(UseAVX > 0, "requires some form of AVX");
- emit_vex_arith(0xE1, dst, src, shift, VEX_SIMD_66, vector_len,
- (VM_Version::supports_avx512bw() == false));
+ emit_vex_arith(0xE1, dst, src, shift, VEX_SIMD_66, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_bw);
}
void Assembler::vpsrad(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
emit_vex_arith(0xE2, dst, src, shift, VEX_SIMD_66, vector_len);
}
@@ -4684,53 +4799,61 @@
}
void Assembler::vpand(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
emit_vex_arith(0xDB, dst, nds, src, VEX_SIMD_66, vector_len);
}
void Assembler::vpand(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_32bit;
}
emit_vex_arith(0xDB, dst, nds, src, VEX_SIMD_66, vector_len);
}
void Assembler::por(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
emit_simd_arith(0xEB, dst, src, VEX_SIMD_66);
}
void Assembler::vpor(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
emit_vex_arith(0xEB, dst, nds, src, VEX_SIMD_66, vector_len);
}
void Assembler::vpor(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_32bit;
}
emit_vex_arith(0xEB, dst, nds, src, VEX_SIMD_66, vector_len);
}
void Assembler::pxor(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
emit_simd_arith(0xEF, dst, src, VEX_SIMD_66);
}
void Assembler::vpxor(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
emit_vex_arith(0xEF, dst, nds, src, VEX_SIMD_66, vector_len);
}
void Assembler::vpxor(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
+ _instruction_uses_vl = true;
assert(UseAVX > 0, "requires some form of AVX");
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_FV;
- input_size_in_bits = EVEX_32bit;
+ _tuple_type = EVEX_FV;
+ _input_size_in_bits = EVEX_32bit;
}
emit_vex_arith(0xEF, dst, nds, src, VEX_SIMD_66, vector_len);
}
@@ -4739,6 +4862,9 @@
void Assembler::vinsertf128h(XMMRegister dst, XMMRegister nds, XMMRegister src) {
assert(VM_Version::supports_avx(), "");
int vector_len = AVX_256bit;
+ if (VM_Version::supports_evex()) {
+ vector_len = AVX_512bit;
+ }
int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66, vector_len, VEX_OPCODE_0F_3A);
emit_int8(0x18);
emit_int8((unsigned char)(0xC0 | encode));
@@ -4753,8 +4879,8 @@
int src_enc = src->encoding();
int dst_enc = dst->encoding();
int nds_enc = nds->is_valid() ? nds->encoding() : 0;
- int encode = vex_prefix_and_encode(dst_enc, nds_enc, src_enc, VEX_SIMD_66,
- VEX_OPCODE_0F_3A, true, vector_len, false, false);
+ int encode = vex_prefix_and_encode(dst_enc, nds_enc, src_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A,
+ /* vex_w */ true, vector_len, /* legacy_mode */ false, /* no_mask_reg */ false);
emit_int8(0x1A);
emit_int8((unsigned char)(0xC0 | encode));
// 0x00 - insert into lower 256 bits
@@ -4763,35 +4889,70 @@
}
void Assembler::vinsertf64x4h(XMMRegister dst, Address src) {
- assert(VM_Version::supports_avx(), "");
- if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T4;
- input_size_in_bits = EVEX_64bit;
- }
+ assert(VM_Version::supports_evex(), "");
+ _tuple_type = EVEX_T4;
+ _input_size_in_bits = EVEX_64bit;
InstructionMark im(this);
int vector_len = AVX_512bit;
assert(dst != xnoreg, "sanity");
int dst_enc = dst->encoding();
// swap src<->dst for encoding
- vex_prefix(src, dst_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A, true, vector_len);
+ vex_prefix(src, dst_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A, /* vex_w */ true, vector_len);
emit_int8(0x1A);
emit_operand(dst, src);
// 0x01 - insert into upper 128 bits
emit_int8(0x01);
}
+void Assembler::vinsertf32x4h(XMMRegister dst, XMMRegister nds, XMMRegister src, int value) {
+ assert(VM_Version::supports_evex(), "");
+ int vector_len = AVX_512bit;
+ int src_enc = src->encoding();
+ int dst_enc = dst->encoding();
+ int nds_enc = nds->is_valid() ? nds->encoding() : 0;
+ int encode = vex_prefix_and_encode(dst_enc, nds_enc, src_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A,
+ /* vex_w */ false, vector_len, /* legacy_mode */ false, /* no_mask_reg */ false);
+ emit_int8(0x18);
+ emit_int8((unsigned char)(0xC0 | encode));
+ // 0x00 - insert into q0 128 bits (0..127)
+ // 0x01 - insert into q1 128 bits (128..255)
+ // 0x02 - insert into q2 128 bits (256..383)
+ // 0x03 - insert into q3 128 bits (384..511)
+ emit_int8(value & 0x3);
+}
+
+void Assembler::vinsertf32x4h(XMMRegister dst, Address src, int value) {
+ assert(VM_Version::supports_evex(), "");
+ _tuple_type = EVEX_T4;
+ _input_size_in_bits = EVEX_32bit;
+ InstructionMark im(this);
+ int vector_len = AVX_512bit;
+ assert(dst != xnoreg, "sanity");
+ int dst_enc = dst->encoding();
+ // swap src<->dst for encoding
+ vex_prefix(src, dst_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A, /* vex_w */ false, vector_len);
+ emit_int8(0x18);
+ emit_operand(dst, src);
+ // 0x00 - insert into q0 128 bits (0..127)
+ // 0x01 - insert into q1 128 bits (128..255)
+ // 0x02 - insert into q2 128 bits (256..383)
+ // 0x03 - insert into q3 128 bits (384..511)
+ emit_int8(value & 0x3);
+}
+
void Assembler::vinsertf128h(XMMRegister dst, Address src) {
assert(VM_Version::supports_avx(), "");
+ int vector_len = AVX_256bit;
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T4;
- input_size_in_bits = EVEX_32bit;
- }
- InstructionMark im(this);
- int vector_len = AVX_256bit;
+ _tuple_type = EVEX_T4;
+ _input_size_in_bits = EVEX_32bit;
+ vector_len = AVX_512bit;
+ }
+ InstructionMark im(this);
assert(dst != xnoreg, "sanity");
int dst_enc = dst->encoding();
// swap src<->dst for encoding
- vex_prefix(src, dst_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A, false, vector_len);
+ vex_prefix(src, dst_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A, /* vex_w */ false, vector_len);
emit_int8(0x18);
emit_operand(dst, src);
// 0x01 - insert into upper 128 bits
@@ -4801,6 +4962,9 @@
void Assembler::vextractf128h(XMMRegister dst, XMMRegister src) {
assert(VM_Version::supports_avx(), "");
int vector_len = AVX_256bit;
+ if (VM_Version::supports_evex()) {
+ vector_len = AVX_512bit;
+ }
int encode = vex_prefix_and_encode(src, xnoreg, dst, VEX_SIMD_66, vector_len, VEX_OPCODE_0F_3A);
emit_int8(0x19);
emit_int8((unsigned char)(0xC0 | encode));
@@ -4811,15 +4975,16 @@
void Assembler::vextractf128h(Address dst, XMMRegister src) {
assert(VM_Version::supports_avx(), "");
+ int vector_len = AVX_256bit;
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T4;
- input_size_in_bits = EVEX_32bit;
- }
- InstructionMark im(this);
- int vector_len = AVX_256bit;
+ _tuple_type = EVEX_T4;
+ _input_size_in_bits = EVEX_32bit;
+ vector_len = AVX_512bit;
+ }
+ InstructionMark im(this);
assert(src != xnoreg, "sanity");
int src_enc = src->encoding();
- vex_prefix(dst, 0, src_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A, false, vector_len);
+ vex_prefix(dst, 0, src_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A, /* vex_w */ false, vector_len);
emit_int8(0x19);
emit_operand(src, dst);
// 0x01 - extract from upper 128 bits
@@ -4829,6 +4994,9 @@
void Assembler::vinserti128h(XMMRegister dst, XMMRegister nds, XMMRegister src) {
assert(VM_Version::supports_avx2(), "");
int vector_len = AVX_256bit;
+ if (VM_Version::supports_evex()) {
+ vector_len = AVX_512bit;
+ }
int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66, vector_len, VEX_OPCODE_0F_3A);
emit_int8(0x38);
emit_int8((unsigned char)(0xC0 | encode));
@@ -4844,7 +5012,7 @@
int dst_enc = dst->encoding();
int nds_enc = nds->is_valid() ? nds->encoding() : 0;
int encode = vex_prefix_and_encode(dst_enc, nds_enc, src_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A,
- VM_Version::supports_avx512dq(), vector_len, false, false);
+ /* vex_w */ true, vector_len, /* legacy_mode */ false, /* no_reg_mask */ false);
emit_int8(0x38);
emit_int8((unsigned char)(0xC0 | encode));
// 0x00 - insert into lower 256 bits
@@ -4854,16 +5022,17 @@
void Assembler::vinserti128h(XMMRegister dst, Address src) {
assert(VM_Version::supports_avx2(), "");
+ int vector_len = AVX_256bit;
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T4;
- input_size_in_bits = EVEX_32bit;
- }
- InstructionMark im(this);
- int vector_len = AVX_256bit;
+ _tuple_type = EVEX_T4;
+ _input_size_in_bits = EVEX_32bit;
+ vector_len = AVX_512bit;
+ }
+ InstructionMark im(this);
assert(dst != xnoreg, "sanity");
int dst_enc = dst->encoding();
// swap src<->dst for encoding
- vex_prefix(src, dst_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A, false, vector_len);
+ vex_prefix(src, dst_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A, /* vex_w */ false, vector_len);
emit_int8(0x38);
emit_operand(dst, src);
// 0x01 - insert into upper 128 bits
@@ -4873,6 +5042,9 @@
void Assembler::vextracti128h(XMMRegister dst, XMMRegister src) {
assert(VM_Version::supports_avx(), "");
int vector_len = AVX_256bit;
+ if (VM_Version::supports_evex()) {
+ vector_len = AVX_512bit;
+ }
int encode = vex_prefix_and_encode(src, xnoreg, dst, VEX_SIMD_66, vector_len, VEX_OPCODE_0F_3A);
emit_int8(0x39);
emit_int8((unsigned char)(0xC0 | encode));
@@ -4883,15 +5055,16 @@
void Assembler::vextracti128h(Address dst, XMMRegister src) {
assert(VM_Version::supports_avx2(), "");
+ int vector_len = AVX_256bit;
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T4;
- input_size_in_bits = EVEX_32bit;
- }
- InstructionMark im(this);
- int vector_len = AVX_256bit;
+ _tuple_type = EVEX_T4;
+ _input_size_in_bits = EVEX_32bit;
+ vector_len = AVX_512bit;
+ }
+ InstructionMark im(this);
assert(src != xnoreg, "sanity");
int src_enc = src->encoding();
- vex_prefix(dst, 0, src_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A, false, vector_len);
+ vex_prefix(dst, 0, src_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A, /* vex_w */ false, vector_len);
emit_int8(0x39);
emit_operand(src, dst);
// 0x01 - extract from upper 128 bits
@@ -4904,7 +5077,7 @@
int src_enc = src->encoding();
int dst_enc = dst->encoding();
int encode = vex_prefix_and_encode(src_enc, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A,
- true, vector_len, false, false);
+ /* vex_w */ true, vector_len, /* legacy_mode */ false, /* no_mask_reg */ false);
emit_int8(0x3B);
emit_int8((unsigned char)(0xC0 | encode));
// 0x01 - extract from upper 256 bits
@@ -4916,8 +5089,14 @@
int vector_len = AVX_512bit;
int src_enc = src->encoding();
int dst_enc = dst->encoding();
- int encode = vex_prefix_and_encode(src_enc, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A,
- VM_Version::supports_avx512dq(), vector_len, false, false);
+ int encode;
+ if (VM_Version::supports_avx512dq()) {
+ encode = vex_prefix_and_encode(src_enc, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A,
+ /* vex_w */ true, vector_len, /* legacy_mode */ false, /* no_mask_reg */ false);
+ } else {
+ encode = vex_prefix_and_encode(src_enc, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A,
+ /* vex_w */ false, vector_len, /* legacy_mode */ true, /* no_mask_reg */ false);
+ }
emit_int8(0x39);
emit_int8((unsigned char)(0xC0 | encode));
// 0x01 - extract from bits 255:128
@@ -4932,7 +5111,7 @@
int src_enc = src->encoding();
int dst_enc = dst->encoding();
int encode = vex_prefix_and_encode(src_enc, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A,
- VM_Version::supports_avx512dq(), vector_len, false, false);
+ /* vex_w */ true, vector_len, /* legacy_mode */ false, /* no_mask_reg */ false);
emit_int8(0x1B);
emit_int8((unsigned char)(0xC0 | encode));
// 0x01 - extract from upper 256 bits
@@ -4940,18 +5119,18 @@
}
void Assembler::vextractf64x4h(Address dst, XMMRegister src) {
- assert(VM_Version::supports_avx2(), "");
- tuple_type = EVEX_T4;
- input_size_in_bits = EVEX_64bit;
+ assert(VM_Version::supports_evex(), "");
+ _tuple_type = EVEX_T4;
+ _input_size_in_bits = EVEX_64bit;
InstructionMark im(this);
int vector_len = AVX_512bit;
assert(src != xnoreg, "sanity");
int src_enc = src->encoding();
vex_prefix(dst, 0, src_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A,
- VM_Version::supports_avx512dq(), vector_len);
+ /* vex_w */ true, vector_len);
emit_int8(0x1B);
emit_operand(src, dst);
- // 0x01 - extract from upper 128 bits
+ // 0x01 - extract from upper 256 bits
emit_int8(0x01);
}
@@ -4960,10 +5139,29 @@
int vector_len = AVX_512bit;
int src_enc = src->encoding();
int dst_enc = dst->encoding();
- int encode = vex_prefix_and_encode(src_enc, 0, dst_enc, VEX_SIMD_66,
- VEX_OPCODE_0F_3A, false, vector_len, false, false);
+ int encode = vex_prefix_and_encode(src_enc, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A,
+ /* vex_w */ false, vector_len, /* legacy_mode */ false, /* no_mask_reg */ false);
emit_int8(0x19);
emit_int8((unsigned char)(0xC0 | encode));
+ // 0x00 - extract from bits 127:0
+ // 0x01 - extract from bits 255:128
+ // 0x02 - extract from bits 383:256
+ // 0x03 - extract from bits 511:384
+ emit_int8(value & 0x3);
+}
+
+void Assembler::vextractf32x4h(Address dst, XMMRegister src, int value) {
+ assert(VM_Version::supports_evex(), "");
+ _tuple_type = EVEX_T4;
+ _input_size_in_bits = EVEX_32bit;
+ InstructionMark im(this);
+ int vector_len = AVX_512bit;
+ assert(src != xnoreg, "sanity");
+ int src_enc = src->encoding();
+ vex_prefix(dst, 0, src_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A, /* vex_w */ false, vector_len);
+ emit_int8(0x19);
+ emit_operand(src, dst);
+ // 0x00 - extract from bits 127:0
// 0x01 - extract from bits 255:128
// 0x02 - extract from bits 383:256
// 0x03 - extract from bits 511:384
@@ -4976,7 +5174,7 @@
int src_enc = src->encoding();
int dst_enc = dst->encoding();
int encode = vex_prefix_and_encode(src_enc, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_3A,
- VM_Version::supports_avx512dq(), vector_len, false, false);
+ /* vex_w */ !_legacy_mode_dq, vector_len, /* legacy_mode */ false, /* no_mask_reg */ false);
emit_int8(0x19);
emit_int8((unsigned char)(0xC0 | encode));
// 0x01 - extract from bits 255:128
@@ -4987,178 +5185,190 @@
// duplicate 4-bytes integer data from src into 8 locations in dest
void Assembler::vpbroadcastd(XMMRegister dst, XMMRegister src) {
- assert(VM_Version::supports_avx2(), "");
+ _instruction_uses_vl = true;
+ assert(UseAVX > 1, "");
int vector_len = AVX_256bit;
- int encode = vex_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66,
- vector_len, VEX_OPCODE_0F_38, false);
+ int encode = vex_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, vector_len, VEX_OPCODE_0F_38);
emit_int8(0x58);
emit_int8((unsigned char)(0xC0 | encode));
}
// duplicate 1-byte integer data from src into 16||32|64 locations in dest : requires AVX512BW and AVX512VL
void Assembler::evpbroadcastb(XMMRegister dst, XMMRegister src, int vector_len) {
- assert(VM_Version::supports_evex(), "");
- int encode = vex_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66,
- vector_len, VEX_OPCODE_0F_38, false);
+ _instruction_uses_vl = true;
+ assert(UseAVX > 1, "");
+ int encode = vex_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, vector_len, VEX_OPCODE_0F_38);
emit_int8(0x78);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::evpbroadcastb(XMMRegister dst, Address src, int vector_len) {
- assert(VM_Version::supports_evex(), "");
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_8bit;
+ _instruction_uses_vl = true;
+ assert(UseAVX > 1, "");
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_8bit;
InstructionMark im(this);
assert(dst != xnoreg, "sanity");
int dst_enc = dst->encoding();
// swap src<->dst for encoding
- vex_prefix(src, dst_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, false, vector_len);
+ vex_prefix(src, dst_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, /* vex_w */ false, vector_len);
emit_int8(0x78);
emit_operand(dst, src);
}
// duplicate 2-byte integer data from src into 8|16||32 locations in dest : requires AVX512BW and AVX512VL
void Assembler::evpbroadcastw(XMMRegister dst, XMMRegister src, int vector_len) {
- assert(VM_Version::supports_evex(), "");
- int encode = vex_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66,
- vector_len, VEX_OPCODE_0F_38, false);
+ _instruction_uses_vl = true;
+ assert(UseAVX > 1, "");
+ int encode = vex_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, vector_len, VEX_OPCODE_0F_38);
emit_int8(0x79);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::evpbroadcastw(XMMRegister dst, Address src, int vector_len) {
- assert(VM_Version::supports_evex(), "");
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_16bit;
+ _instruction_uses_vl = true;
+ assert(UseAVX > 1, "");
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_16bit;
InstructionMark im(this);
assert(dst != xnoreg, "sanity");
int dst_enc = dst->encoding();
// swap src<->dst for encoding
- vex_prefix(src, dst_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, false, vector_len);
+ vex_prefix(src, dst_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, /* vex_w */ false, vector_len);
emit_int8(0x79);
emit_operand(dst, src);
}
// duplicate 4-byte integer data from src into 4|8|16 locations in dest : requires AVX512VL
void Assembler::evpbroadcastd(XMMRegister dst, XMMRegister src, int vector_len) {
- assert(VM_Version::supports_evex(), "");
- int encode = vex_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66,
- vector_len, VEX_OPCODE_0F_38, false);
+ _instruction_uses_vl = true;
+ assert(UseAVX > 1, "");
+ int encode = vex_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, vector_len, VEX_OPCODE_0F_38);
emit_int8(0x58);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::evpbroadcastd(XMMRegister dst, Address src, int vector_len) {
- assert(VM_Version::supports_evex(), "");
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
+ _instruction_uses_vl = true;
+ assert(UseAVX > 1, "");
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
InstructionMark im(this);
assert(dst != xnoreg, "sanity");
int dst_enc = dst->encoding();
// swap src<->dst for encoding
- vex_prefix(src, dst_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, false, vector_len);
+ vex_prefix(src, dst_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, /* vex_w */ false, vector_len);
emit_int8(0x58);
emit_operand(dst, src);
}
// duplicate 8-byte integer data from src into 4|8|16 locations in dest : requires AVX512VL
void Assembler::evpbroadcastq(XMMRegister dst, XMMRegister src, int vector_len) {
- assert(VM_Version::supports_evex(), "");
- int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66,
- VEX_OPCODE_0F_38, true, vector_len, false, false);
+ _instruction_uses_vl = true;
+ assert(UseAVX > 1, "");
+ int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38,
+ /* vex_w */ true, vector_len, /* legacy_mode */ false, /* no_mask_reg */ false);
emit_int8(0x59);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::evpbroadcastq(XMMRegister dst, Address src, int vector_len) {
- assert(VM_Version::supports_evex(), "");
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_64bit;
+ _instruction_uses_vl = true;
+ assert(UseAVX > 1, "");
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_64bit;
InstructionMark im(this);
assert(dst != xnoreg, "sanity");
int dst_enc = dst->encoding();
// swap src<->dst for encoding
- vex_prefix(src, dst_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, true, vector_len);
+ vex_prefix(src, dst_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, /* vex_w */ true, vector_len);
emit_int8(0x59);
emit_operand(dst, src);
}
// duplicate single precision fp from src into 4|8|16 locations in dest : requires AVX512VL
void Assembler::evpbroadcastss(XMMRegister dst, XMMRegister src, int vector_len) {
- assert(VM_Version::supports_evex(), "");
- int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66,
- VEX_OPCODE_0F_38, false, vector_len, false, false);
+ _instruction_uses_vl = true;
+ assert(UseAVX > 1, "");
+ int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38,
+ /* vex_w */ false, vector_len, /* legacy_mode */ false, /*no_mask_reg */ false);
emit_int8(0x18);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::evpbroadcastss(XMMRegister dst, Address src, int vector_len) {
- assert(VM_Version::supports_evex(), "");
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
+ assert(UseAVX > 1, "");
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
InstructionMark im(this);
assert(dst != xnoreg, "sanity");
int dst_enc = dst->encoding();
// swap src<->dst for encoding
- vex_prefix(src, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, false, vector_len);
+ vex_prefix(src, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, /* vex_w */ false, vector_len);
emit_int8(0x18);
emit_operand(dst, src);
}
// duplicate double precision fp from src into 2|4|8 locations in dest : requires AVX512VL
void Assembler::evpbroadcastsd(XMMRegister dst, XMMRegister src, int vector_len) {
- assert(VM_Version::supports_evex(), "");
- int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66,
- VEX_OPCODE_0F_38, true, vector_len, false, false);
+ _instruction_uses_vl = true;
+ assert(UseAVX > 1, "");
+ int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38,
+ /*vex_w */ true, vector_len, /* legacy_mode */ false, /*no_mask_reg */ false);
emit_int8(0x19);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::evpbroadcastsd(XMMRegister dst, Address src, int vector_len) {
- assert(VM_Version::supports_evex(), "");
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_64bit;
+ _instruction_uses_vl = true;
+ assert(UseAVX > 1, "");
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_64bit;
InstructionMark im(this);
assert(dst != xnoreg, "sanity");
int dst_enc = dst->encoding();
// swap src<->dst for encoding
- vex_prefix(src, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, true, vector_len);
+ vex_prefix(src, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, /* vex_w */ true, vector_len);
emit_int8(0x19);
emit_operand(dst, src);
}
// duplicate 1-byte integer data from src into 16||32|64 locations in dest : requires AVX512BW and AVX512VL
void Assembler::evpbroadcastb(XMMRegister dst, Register src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_evex(), "");
- int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66,
- VEX_OPCODE_0F_38, false, vector_len, false, false);
+ int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38,
+ /*vex_w */ false, vector_len, /* legacy_mode */ false, /*no_mask_reg */ false);
emit_int8(0x7A);
emit_int8((unsigned char)(0xC0 | encode));
}
// duplicate 2-byte integer data from src into 8|16||32 locations in dest : requires AVX512BW and AVX512VL
void Assembler::evpbroadcastw(XMMRegister dst, Register src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_evex(), "");
- int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66,
- VEX_OPCODE_0F_38, false, vector_len, false, false);
+ int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38,
+ /* vex_w */ false, vector_len, /* legacy_mode */ false, /*no_mask_reg */ false);
emit_int8(0x7B);
emit_int8((unsigned char)(0xC0 | encode));
}
// duplicate 4-byte integer data from src into 4|8|16 locations in dest : requires AVX512VL
void Assembler::evpbroadcastd(XMMRegister dst, Register src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_evex(), "");
- int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66,
- VEX_OPCODE_0F_38, false, vector_len, false, false);
+ int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38,
+ /* vex_w */ false, vector_len, /* legacy_mode */ false, /*no_mask_reg */ false);
emit_int8(0x7C);
emit_int8((unsigned char)(0xC0 | encode));
}
// duplicate 8-byte integer data from src into 4|8|16 locations in dest : requires AVX512VL
void Assembler::evpbroadcastq(XMMRegister dst, Register src, int vector_len) {
+ _instruction_uses_vl = true;
assert(VM_Version::supports_evex(), "");
- int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66,
- VEX_OPCODE_0F_38, true, vector_len, false, false);
+ int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38,
+ /* vex_w */ true, vector_len, /* legacy_mode */ false, /*no_mask_reg */ false);
emit_int8(0x7C);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -5166,8 +5376,8 @@
// Carry-Less Multiplication Quadword
void Assembler::pclmulqdq(XMMRegister dst, XMMRegister src, int mask) {
assert(VM_Version::supports_clmul(), "");
- int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, false,
- VEX_OPCODE_0F_3A, false, AVX_128bit, true);
+ int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, /* no_mask_reg */ false,
+ VEX_OPCODE_0F_3A, /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
emit_int8(0x44);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8((unsigned char)mask);
@@ -5177,8 +5387,7 @@
void Assembler::vpclmulqdq(XMMRegister dst, XMMRegister nds, XMMRegister src, int mask) {
assert(VM_Version::supports_avx() && VM_Version::supports_clmul(), "");
int vector_len = AVX_128bit;
- int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66,
- vector_len, VEX_OPCODE_0F_3A, true);
+ int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66, vector_len, VEX_OPCODE_0F_3A, /* legacy_mode */ true);
emit_int8(0x44);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8((unsigned char)mask);
@@ -5737,7 +5946,7 @@
int vector_len, bool no_mask_reg ){
// EVEX 0x62 prefix
prefix(EVEX_4bytes);
- evex_encoding = (vex_w ? VEX_W : 0) | (evex_r ? EVEX_Rb : 0);
+ _evex_encoding = (vex_w ? VEX_W : 0) | (evex_r ? EVEX_Rb : 0);
// P0: byte 2, initialized to RXBR`00mm
// instead of not'd
@@ -5776,10 +5985,10 @@
bool vex_r = ((xreg_enc & 8) == 8) ? 1 : 0;
bool vex_b = adr.base_needs_rex();
bool vex_x = adr.index_needs_rex();
- avx_vector_len = vector_len;
-
- // if vector length is turned off, revert to AVX for vectors smaller than AVX_512bit
- if (VM_Version::supports_avx512vl() == false) {
+ _avx_vector_len = vector_len;
+
+ // if vector length is turned off, revert to AVX for vectors smaller than 512-bit
+ if (_legacy_mode_vl && _instruction_uses_vl) {
switch (vector_len) {
case AVX_128bit:
case AVX_256bit:
@@ -5792,11 +6001,12 @@
{
bool evex_r = (xreg_enc >= 16);
bool evex_v = (nds_enc >= 16);
- is_evex_instruction = true;
+ _is_evex_instruction = true;
evex_prefix(vex_r, vex_b, vex_x, vex_w, evex_r, evex_v, nds_enc, pre, opc, false, false, vector_len, no_mask_reg);
} else {
vex_prefix(vex_r, vex_b, vex_x, vex_w, nds_enc, pre, opc, vector_len);
}
+ _instruction_uses_vl = false;
}
int Assembler::vex_prefix_and_encode(int dst_enc, int nds_enc, int src_enc, VexSimdPrefix pre, VexOpcode opc,
@@ -5804,10 +6014,10 @@
bool vex_r = ((dst_enc & 8) == 8) ? 1 : 0;
bool vex_b = ((src_enc & 8) == 8) ? 1 : 0;
bool vex_x = false;
- avx_vector_len = vector_len;
-
- // if vector length is turned off, revert to AVX for vectors smaller than AVX_512bit
- if (VM_Version::supports_avx512vl() == false) {
+ _avx_vector_len = vector_len;
+
+ // if vector length is turned off, revert to AVX for vectors smaller than 512-bit
+ if (_legacy_mode_vl && _instruction_uses_vl) {
switch (vector_len) {
case AVX_128bit:
case AVX_256bit:
@@ -5827,6 +6037,8 @@
vex_prefix(vex_r, vex_b, vex_x, vex_w, nds_enc, pre, opc, vector_len);
}
+ _instruction_uses_vl = false;
+
// return modrm byte components for operands
return (((dst_enc & 7) << 3) | (src_enc & 7));
}
@@ -5915,13 +6127,13 @@
}
void Assembler::emit_simd_arith_nonds(int opcode, XMMRegister dst, XMMRegister src, VexSimdPrefix pre, bool no_mask_reg, bool legacy_mode) {
- int encode = simd_prefix_and_encode(dst, xnoreg, src, pre, no_mask_reg, VEX_OPCODE_0F, legacy_mode, AVX_128bit);
+ int encode = simd_prefix_and_encode(dst, xnoreg, src, pre, no_mask_reg, VEX_OPCODE_0F, false, AVX_128bit, legacy_mode);
emit_int8(opcode);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::emit_simd_arith_nonds_q(int opcode, XMMRegister dst, XMMRegister src, VexSimdPrefix pre, bool no_mask_reg) {
- int encode = simd_prefix_and_encode(dst, xnoreg, src, pre, no_mask_reg, VEX_OPCODE_0F, true, AVX_128bit);
+ int encode = simd_prefix_and_encode(dst, xnoreg, src, pre, no_mask_reg, VEX_OPCODE_0F, true);
emit_int8(opcode);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -5945,7 +6157,7 @@
void Assembler::emit_vex_arith(int opcode, XMMRegister dst, XMMRegister nds, XMMRegister src,
VexSimdPrefix pre, int vector_len, bool no_mask_reg, bool legacy_mode) {
- int encode = vex_prefix_and_encode(dst, nds, src, pre, vector_len, VEX_OPCODE_0F, false, no_mask_reg);
+ int encode = vex_prefix_and_encode(dst, nds, src, pre, vector_len, VEX_OPCODE_0F, legacy_mode, no_mask_reg);
emit_int8(opcode);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -6594,7 +6806,7 @@
void Assembler::cvtsi2sdq(XMMRegister dst, Register src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- int encode = simd_prefix_and_encode_q(dst, dst, src, VEX_SIMD_F2, true);
+ int encode = simd_prefix_and_encode_q(dst, dst, src, VEX_SIMD_F2, /* no_mask_reg */ true);
emit_int8(0x2A);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -6602,11 +6814,11 @@
void Assembler::cvtsi2sdq(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
- }
- InstructionMark im(this);
- simd_prefix_q(dst, dst, src, VEX_SIMD_F2, true);
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
+ }
+ InstructionMark im(this);
+ simd_prefix_q(dst, dst, src, VEX_SIMD_F2, /* no_mask_reg */ true);
emit_int8(0x2A);
emit_operand(dst, src);
}
@@ -6614,25 +6826,25 @@
void Assembler::cvtsi2ssq(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
if (VM_Version::supports_evex()) {
- tuple_type = EVEX_T1S;
- input_size_in_bits = EVEX_32bit;
- }
- InstructionMark im(this);
- simd_prefix_q(dst, dst, src, VEX_SIMD_F3, true);
+ _tuple_type = EVEX_T1S;
+ _input_size_in_bits = EVEX_32bit;
+ }
+ InstructionMark im(this);
+ simd_prefix_q(dst, dst, src, VEX_SIMD_F3, /* no_mask_reg */ true);
emit_int8(0x2A);
emit_operand(dst, src);
}
void Assembler::cvttsd2siq(Register dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- int encode = simd_prefix_and_encode_q(dst, src, VEX_SIMD_F2, VEX_OPCODE_0F, true);
+ int encode = simd_prefix_and_encode_q(dst, src, VEX_SIMD_F2, VEX_OPCODE_0F, /* no_mask_reg */ true);
emit_int8(0x2C);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::cvttss2siq(Register dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
- int encode = simd_prefix_and_encode_q(dst, src, VEX_SIMD_F3, VEX_OPCODE_0F, true);
+ int encode = simd_prefix_and_encode_q(dst, src, VEX_SIMD_F3, VEX_OPCODE_0F, /* no_mask_reg */ true);
emit_int8(0x2C);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -6668,6 +6880,13 @@
emit_operand(as_Register(1), src);
}
+void Assembler::xrstor(Address src) {
+ prefixq(src);
+ emit_int8(0x0F);
+ emit_int8((unsigned char)0xAE);
+ emit_operand(as_Register(5), src);
+}
+
void Assembler::fxsave(Address dst) {
prefixq(dst);
emit_int8(0x0F);
@@ -6675,6 +6894,13 @@
emit_operand(as_Register(0), dst);
}
+void Assembler::xsave(Address dst) {
+ prefixq(dst);
+ emit_int8(0x0F);
+ emit_int8((unsigned char)0xAE);
+ emit_operand(as_Register(4), dst);
+}
+
void Assembler::idivq(Register src) {
int encode = prefixq_and_encode(src->encoding());
emit_int8((unsigned char)0xF7);
@@ -6801,7 +7027,7 @@
void Assembler::movdq(XMMRegister dst, Register src) {
// table D-1 says MMX/SSE2
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- int encode = simd_prefix_and_encode_q(dst, src, VEX_SIMD_66, true);
+ int encode = simd_prefix_and_encode_q(dst, src, VEX_SIMD_66, /* no_mask_reg */ true);
emit_int8(0x6E);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -6810,7 +7036,7 @@
// table D-1 says MMX/SSE2
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
// swap src/dst to get correct prefix
- int encode = simd_prefix_and_encode_q(src, dst, VEX_SIMD_66, true);
+ int encode = simd_prefix_and_encode_q(src, dst, VEX_SIMD_66, /* no_mask_reg */ true);
emit_int8(0x7E);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -6943,8 +7169,8 @@
void Assembler::mulxq(Register dst1, Register dst2, Register src) {
assert(VM_Version::supports_bmi2(), "bit manipulation instructions not supported");
- int encode = vex_prefix_and_encode(dst1->encoding(), dst2->encoding(), src->encoding(),
- VEX_SIMD_F2, VEX_OPCODE_0F_38, true, AVX_128bit, true, false);
+ int encode = vex_prefix_and_encode(dst1->encoding(), dst2->encoding(), src->encoding(), VEX_SIMD_F2, VEX_OPCODE_0F_38,
+ /* vex_w */ true, AVX_128bit, /* legacy_mode */ true, /* no_mask_reg */ false);
emit_int8((unsigned char)0xF6);
emit_int8((unsigned char)(0xC0 | encode));
}
@@ -7106,8 +7332,8 @@
void Assembler::rorxq(Register dst, Register src, int imm8) {
assert(VM_Version::supports_bmi2(), "bit manipulation instructions not supported");
- int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_F2,
- VEX_OPCODE_0F_3A, true, AVX_128bit, true, false);
+ int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_F2, VEX_OPCODE_0F_3A,
+ /* vex_w */ true, AVX_128bit, /* legacy_mode */ true, /* no_mask_reg */ false);
emit_int8((unsigned char)0xF0);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8(imm8);
--- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp Wed Jul 05 20:51:27 2017 +0200
@@ -438,7 +438,9 @@
};
-const int FPUStateSizeInWords = NOT_LP64(27) LP64_ONLY( 512*2 / wordSize);
+// 64-bit refect the fxsave size which is 512 bytes and the new xsave area on EVEX which is another 2176 bytes
+// See fxsave and xsave(EVEX enabled) documentation for layout
+const int FPUStateSizeInWords = NOT_LP64(27) LP64_ONLY(2688 / wordSize);
// The Intel x86/Amd64 Assembler: Pure assembler doing NO optimizations on the instruction
// level (e.g. mov rax, 0 is not translated into xor rax, rax!); i.e., what you write
@@ -594,11 +596,16 @@
private:
- int evex_encoding;
- int input_size_in_bits;
- int avx_vector_len;
- int tuple_type;
- bool is_evex_instruction;
+ int _evex_encoding;
+ int _input_size_in_bits;
+ int _avx_vector_len;
+ int _tuple_type;
+ bool _is_evex_instruction;
+ bool _legacy_mode_bw;
+ bool _legacy_mode_dq;
+ bool _legacy_mode_vl;
+ bool _legacy_mode_vlbw;
+ bool _instruction_uses_vl;
// 64bit prefixes
int prefix_and_encode(int reg_enc, bool byteinst = false);
@@ -972,11 +979,16 @@
// belong in macro assembler but there is no need for both varieties to exist
void init_attributes(void) {
- evex_encoding = 0;
- input_size_in_bits = 0;
- avx_vector_len = AVX_NoVec;
- tuple_type = EVEX_ETUP;
- is_evex_instruction = false;
+ _evex_encoding = 0;
+ _input_size_in_bits = 0;
+ _avx_vector_len = AVX_NoVec;
+ _tuple_type = EVEX_ETUP;
+ _is_evex_instruction = false;
+ _legacy_mode_bw = (VM_Version::supports_avx512bw() == false);
+ _legacy_mode_dq = (VM_Version::supports_avx512dq() == false);
+ _legacy_mode_vl = (VM_Version::supports_avx512vl() == false);
+ _legacy_mode_vlbw = (VM_Version::supports_avx512vlbw() == false);
+ _instruction_uses_vl = false;
}
void lea(Register dst, Address src);
@@ -1344,8 +1356,10 @@
void fxch(int i = 1);
void fxrstor(Address src);
+ void xrstor(Address src);
void fxsave(Address dst);
+ void xsave(Address dst);
void fyl2x();
void frndint();
@@ -1479,11 +1493,12 @@
void movb(Address dst, int imm8);
void movb(Register dst, Address src);
- void kmovq(KRegister dst, KRegister src);
+ void kmovql(KRegister dst, KRegister src);
void kmovql(KRegister dst, Register src);
void kmovdl(KRegister dst, Register src);
- void kmovq(Address dst, KRegister src);
- void kmovq(KRegister dst, Address src);
+ void kmovwl(KRegister dst, Register src);
+ void kmovql(Address dst, KRegister src);
+ void kmovql(KRegister dst, Address src);
void movdl(XMMRegister dst, Register src);
void movdl(Register dst, XMMRegister src);
@@ -1509,9 +1524,12 @@
void vmovdqu(XMMRegister dst, XMMRegister src);
// Move Unaligned 512bit Vector
- void evmovdqu(Address dst, XMMRegister src, int vector_len);
- void evmovdqu(XMMRegister dst, Address src, int vector_len);
- void evmovdqu(XMMRegister dst, XMMRegister src, int vector_len);
+ void evmovdqul(Address dst, XMMRegister src, int vector_len);
+ void evmovdqul(XMMRegister dst, Address src, int vector_len);
+ void evmovdqul(XMMRegister dst, XMMRegister src, int vector_len);
+ void evmovdquq(Address dst, XMMRegister src, int vector_len);
+ void evmovdquq(XMMRegister dst, Address src, int vector_len);
+ void evmovdquq(XMMRegister dst, XMMRegister src, int vector_len);
// Move lower 64bit to high 64bit in 128bit register
void movlhps(XMMRegister dst, XMMRegister src);
@@ -1643,6 +1661,7 @@
// Pemutation of 64bit words
void vpermq(XMMRegister dst, XMMRegister src, int imm8, int vector_len);
+ void vpermq(XMMRegister dst, XMMRegister src, int imm8);
void pause();
@@ -1920,6 +1939,10 @@
void vdivpd(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
void vdivps(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
+ // Sqrt Packed Floating-Point Values - Double precision only
+ void vsqrtpd(XMMRegister dst, XMMRegister src, int vector_len);
+ void vsqrtpd(XMMRegister dst, Address src, int vector_len);
+
// Bitwise Logical AND of Packed Floating-Point Values
void andpd(XMMRegister dst, XMMRegister src);
void andps(XMMRegister dst, XMMRegister src);
@@ -2057,6 +2080,9 @@
void vextracti64x2h(XMMRegister dst, XMMRegister src, int value);
void vextractf64x2h(XMMRegister dst, XMMRegister src, int value);
void vextractf32x4h(XMMRegister dst, XMMRegister src, int value);
+ void vextractf32x4h(Address dst, XMMRegister src, int value);
+ void vinsertf32x4h(XMMRegister dst, XMMRegister nds, XMMRegister src, int value);
+ void vinsertf32x4h(XMMRegister dst, Address src, int value);
// duplicate 4-bytes integer data from src into 8 locations in dest
void vpbroadcastd(XMMRegister dst, XMMRegister src);
--- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -3798,16 +3798,24 @@
if (left->as_xmm_float_reg() != dest->as_xmm_float_reg()) {
__ movflt(dest->as_xmm_float_reg(), left->as_xmm_float_reg());
}
- __ xorps(dest->as_xmm_float_reg(),
- ExternalAddress((address)float_signflip_pool));
-
+ if (UseAVX > 1) {
+ __ vnegatess(dest->as_xmm_float_reg(), dest->as_xmm_float_reg(),
+ ExternalAddress((address)float_signflip_pool));
+ } else {
+ __ xorps(dest->as_xmm_float_reg(),
+ ExternalAddress((address)float_signflip_pool));
+ }
} else if (dest->is_double_xmm()) {
if (left->as_xmm_double_reg() != dest->as_xmm_double_reg()) {
__ movdbl(dest->as_xmm_double_reg(), left->as_xmm_double_reg());
}
- __ xorpd(dest->as_xmm_double_reg(),
- ExternalAddress((address)double_signflip_pool));
-
+ if (UseAVX > 1) {
+ __ vnegatesd(dest->as_xmm_double_reg(), dest->as_xmm_double_reg(),
+ ExternalAddress((address)double_signflip_pool));
+ } else {
+ __ xorpd(dest->as_xmm_double_reg(),
+ ExternalAddress((address)double_signflip_pool));
+ }
} else if (left->is_single_fpu() || left->is_double_fpu()) {
assert(left->fpu() == 0, "arg must be on TOS");
assert(dest->fpu() == 0, "dest must be TOS");
--- a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -401,11 +401,9 @@
} else if (UseSSE == 1) {
int xmm_off = xmm_regs_as_doubles_off;
- for (int n = 0; n < FrameMap::nof_xmm_regs; n++) {
- if (n < xmm_bypass_limit) {
- VMReg xmm_name_0 = as_XMMRegister(n)->as_VMReg();
- map->set_callee_saved(VMRegImpl::stack2reg(xmm_off + num_rt_args), xmm_name_0);
- }
+ for (int n = 0; n < FrameMap::nof_fpu_regs; n++) {
+ VMReg xmm_name_0 = as_XMMRegister(n)->as_VMReg();
+ map->set_callee_saved(VMRegImpl::stack2reg(xmm_off + num_rt_args), xmm_name_0);
xmm_off += 2;
}
assert(xmm_off == float_regs_as_doubles_off, "incorrect number of xmm registers");
@@ -452,14 +450,11 @@
__ frstor(Address(rsp, fpu_state_off * VMRegImpl::stack_slot_size));
// Save the FPU registers in de-opt-able form
- __ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 0));
- __ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 8));
- __ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 16));
- __ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 24));
- __ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 32));
- __ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 40));
- __ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 48));
- __ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 56));
+ int offset = 0;
+ for (int n = 0; n < FrameMap::nof_fpu_regs; n++) {
+ __ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + offset));
+ offset += 8;
+ }
}
if (UseSSE >= 2) {
@@ -468,52 +463,26 @@
// so always save them as doubles.
// note that float values are _not_ converted automatically, so for float values
// the second word contains only garbage data.
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 0), xmm0);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 8), xmm1);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 16), xmm2);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 24), xmm3);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 32), xmm4);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 40), xmm5);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 48), xmm6);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 56), xmm7);
+ int xmm_bypass_limit = FrameMap::nof_xmm_regs;
+ int offset = 0;
#ifdef _LP64
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 64), xmm8);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 72), xmm9);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 80), xmm10);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 88), xmm11);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 96), xmm12);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 104), xmm13);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 112), xmm14);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 120), xmm15);
- if (UseAVX > 2) {
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 128), xmm16);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 136), xmm17);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 144), xmm18);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 152), xmm19);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 160), xmm20);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 168), xmm21);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 176), xmm22);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 184), xmm23);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 192), xmm24);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 200), xmm25);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 208), xmm26);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 216), xmm27);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 224), xmm28);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 232), xmm29);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 240), xmm30);
- __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 248), xmm31);
+ if (UseAVX < 3) {
+ xmm_bypass_limit = xmm_bypass_limit / 2;
+ }
+#endif
+ for (int n = 0; n < xmm_bypass_limit; n++) {
+ XMMRegister xmm_name = as_XMMRegister(n);
+ __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + offset), xmm_name);
+ offset += 8;
}
-#endif // _LP64
} else if (UseSSE == 1) {
- // save XMM registers as float because double not supported without SSE2
- __ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 0), xmm0);
- __ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 8), xmm1);
- __ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 16), xmm2);
- __ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 24), xmm3);
- __ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 32), xmm4);
- __ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 40), xmm5);
- __ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 48), xmm6);
- __ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 56), xmm7);
+ // save XMM registers as float because double not supported without SSE2(num MMX == num fpu)
+ int offset = 0;
+ for (int n = 0; n < FrameMap::nof_fpu_regs; n++) {
+ XMMRegister xmm_name = as_XMMRegister(n);
+ __ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + offset), xmm_name);
+ offset += 8;
+ }
}
}
@@ -528,52 +497,26 @@
if (restore_fpu_registers) {
if (UseSSE >= 2) {
// restore XMM registers
- __ movdbl(xmm0, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 0));
- __ movdbl(xmm1, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 8));
- __ movdbl(xmm2, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 16));
- __ movdbl(xmm3, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 24));
- __ movdbl(xmm4, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 32));
- __ movdbl(xmm5, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 40));
- __ movdbl(xmm6, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 48));
- __ movdbl(xmm7, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 56));
+ int xmm_bypass_limit = FrameMap::nof_xmm_regs;
#ifdef _LP64
- __ movdbl(xmm8, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 64));
- __ movdbl(xmm9, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 72));
- __ movdbl(xmm10, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 80));
- __ movdbl(xmm11, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 88));
- __ movdbl(xmm12, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 96));
- __ movdbl(xmm13, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 104));
- __ movdbl(xmm14, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 112));
- __ movdbl(xmm15, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 120));
- if (UseAVX > 2) {
- __ movdbl(xmm16, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 128));
- __ movdbl(xmm17, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 136));
- __ movdbl(xmm18, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 144));
- __ movdbl(xmm19, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 152));
- __ movdbl(xmm20, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 160));
- __ movdbl(xmm21, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 168));
- __ movdbl(xmm22, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 176));
- __ movdbl(xmm23, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 184));
- __ movdbl(xmm24, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 192));
- __ movdbl(xmm25, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 200));
- __ movdbl(xmm26, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 208));
- __ movdbl(xmm27, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 216));
- __ movdbl(xmm28, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 224));
- __ movdbl(xmm29, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 232));
- __ movdbl(xmm30, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 240));
- __ movdbl(xmm31, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 248));
+ if (UseAVX < 3) {
+ xmm_bypass_limit = xmm_bypass_limit / 2;
}
-#endif // _LP64
+#endif
+ int offset = 0;
+ for (int n = 0; n < xmm_bypass_limit; n++) {
+ XMMRegister xmm_name = as_XMMRegister(n);
+ __ movdbl(xmm_name, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + offset));
+ offset += 8;
+ }
} else if (UseSSE == 1) {
- // restore XMM registers
- __ movflt(xmm0, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 0));
- __ movflt(xmm1, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 8));
- __ movflt(xmm2, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 16));
- __ movflt(xmm3, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 24));
- __ movflt(xmm4, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 32));
- __ movflt(xmm5, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 40));
- __ movflt(xmm6, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 48));
- __ movflt(xmm7, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 56));
+ // restore XMM registers(num MMX == num fpu)
+ int offset = 0;
+ for (int n = 0; n < FrameMap::nof_fpu_regs; n++) {
+ XMMRegister xmm_name = as_XMMRegister(n);
+ __ movflt(xmm_name, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + offset));
+ offset += 8;
+ }
}
if (UseSSE < 2) {
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -3751,8 +3751,31 @@
}
void MacroAssembler::pop_FPU_state() {
- NOT_LP64(frstor(Address(rsp, 0));)
- LP64_ONLY(fxrstor(Address(rsp, 0));)
+#ifndef _LP64
+ frstor(Address(rsp, 0));
+#else
+ // AVX will continue to use the fxsave area.
+ // EVEX needs to utilize the xsave area, which is under different
+ // management.
+ if(VM_Version::supports_evex()) {
+ // EDX:EAX describe the XSAVE header and
+ // are obtained while fetching info for XCR0 via cpuid.
+ // These two registers make up 64-bits in the header for which bits
+ // 62:10 are currently reserved for future implementations and unused. Bit 63
+ // is unused for our implementation as we do not utilize
+ // compressed XSAVE areas. Bits 9..8 are currently ignored as we do not use
+ // the functionality for PKRU state and MSR tracing.
+ // Ergo we are primarily concerned with bits 7..0, which define
+ // which ISA extensions and features are enabled for a given machine and are
+ // defined in XemXcr0Eax and is used to map the XSAVE area
+ // for restoring registers as described via XCR0.
+ movl(rdx,VM_Version::get_xsave_header_upper_segment());
+ movl(rax,VM_Version::get_xsave_header_lower_segment());
+ xrstor(Address(rsp, 0));
+ } else {
+ fxrstor(Address(rsp, 0));
+ }
+#endif
addptr(rsp, FPUStateSizeInWords * wordSize);
}
@@ -3769,13 +3792,49 @@
push_FPU_state();
}
+#ifdef _LP64
+#define XSTATE_BV 0x200
+#endif
+
void MacroAssembler::push_FPU_state() {
subptr(rsp, FPUStateSizeInWords * wordSize);
#ifndef _LP64
fnsave(Address(rsp, 0));
fwait();
#else
- fxsave(Address(rsp, 0));
+ // AVX will continue to use the fxsave area.
+ // EVEX needs to utilize the xsave area, which is under different
+ // management.
+ if(VM_Version::supports_evex()) {
+ // Save a copy of EAX and EDX
+ push(rax);
+ push(rdx);
+ // EDX:EAX describe the XSAVE header and
+ // are obtained while fetching info for XCR0 via cpuid.
+ // These two registers make up 64-bits in the header for which bits
+ // 62:10 are currently reserved for future implementations and unused. Bit 63
+ // is unused for our implementation as we do not utilize
+ // compressed XSAVE areas. Bits 9..8 are currently ignored as we do not use
+ // the functionality for PKRU state and MSR tracing.
+ // Ergo we are primarily concerned with bits 7..0, which define
+ // which ISA extensions and features are enabled for a given machine and are
+ // defined in XemXcr0Eax and is used to program XSAVE area
+ // for saving the required registers as defined in XCR0.
+ int xcr0_edx = VM_Version::get_xsave_header_upper_segment();
+ int xcr0_eax = VM_Version::get_xsave_header_lower_segment();
+ movl(rdx,xcr0_edx);
+ movl(rax,xcr0_eax);
+ xsave(Address(rsp, wordSize*2));
+ // now Apply control bits and clear bytes 8..23 in the header
+ pop(rdx);
+ pop(rax);
+ movl(Address(rsp, XSTATE_BV), xcr0_eax);
+ movl(Address(rsp, XSTATE_BV+4), xcr0_edx);
+ andq(Address(rsp, XSTATE_BV+8), 0);
+ andq(Address(rsp, XSTATE_BV+16), 0);
+ } else {
+ fxsave(Address(rsp, 0));
+ }
#endif // LP64
}
@@ -4082,6 +4141,84 @@
}
}
+void MacroAssembler::vnegatess(XMMRegister dst, XMMRegister nds, AddressLiteral src) {
+ int nds_enc = nds->encoding();
+ int dst_enc = dst->encoding();
+ bool dst_upper_bank = (dst_enc > 15);
+ bool nds_upper_bank = (nds_enc > 15);
+ if (VM_Version::supports_avx512novl() &&
+ (nds_upper_bank || dst_upper_bank)) {
+ if (dst_upper_bank) {
+ subptr(rsp, 64);
+ evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ movflt(xmm0, nds);
+ if (reachable(src)) {
+ vxorps(xmm0, xmm0, as_Address(src), Assembler::AVX_128bit);
+ } else {
+ lea(rscratch1, src);
+ vxorps(xmm0, xmm0, Address(rscratch1, 0), Assembler::AVX_128bit);
+ }
+ movflt(dst, xmm0);
+ evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
+ addptr(rsp, 64);
+ } else {
+ movflt(dst, nds);
+ if (reachable(src)) {
+ vxorps(dst, dst, as_Address(src), Assembler::AVX_128bit);
+ } else {
+ lea(rscratch1, src);
+ vxorps(dst, dst, Address(rscratch1, 0), Assembler::AVX_128bit);
+ }
+ }
+ } else {
+ if (reachable(src)) {
+ vxorps(dst, nds, as_Address(src), Assembler::AVX_128bit);
+ } else {
+ lea(rscratch1, src);
+ vxorps(dst, nds, Address(rscratch1, 0), Assembler::AVX_128bit);
+ }
+ }
+}
+
+void MacroAssembler::vnegatesd(XMMRegister dst, XMMRegister nds, AddressLiteral src) {
+ int nds_enc = nds->encoding();
+ int dst_enc = dst->encoding();
+ bool dst_upper_bank = (dst_enc > 15);
+ bool nds_upper_bank = (nds_enc > 15);
+ if (VM_Version::supports_avx512novl() &&
+ (nds_upper_bank || dst_upper_bank)) {
+ if (dst_upper_bank) {
+ subptr(rsp, 64);
+ evmovdqul(Address(rsp, 0), xmm0, Assembler::AVX_512bit);
+ movdbl(xmm0, nds);
+ if (reachable(src)) {
+ vxorps(xmm0, xmm0, as_Address(src), Assembler::AVX_128bit);
+ } else {
+ lea(rscratch1, src);
+ vxorps(xmm0, xmm0, Address(rscratch1, 0), Assembler::AVX_128bit);
+ }
+ movdbl(dst, xmm0);
+ evmovdqul(xmm0, Address(rsp, 0), Assembler::AVX_512bit);
+ addptr(rsp, 64);
+ } else {
+ movdbl(dst, nds);
+ if (reachable(src)) {
+ vxorps(dst, dst, as_Address(src), Assembler::AVX_128bit);
+ } else {
+ lea(rscratch1, src);
+ vxorps(dst, dst, Address(rscratch1, 0), Assembler::AVX_128bit);
+ }
+ }
+ } else {
+ if (reachable(src)) {
+ vxorpd(dst, nds, as_Address(src), Assembler::AVX_128bit);
+ } else {
+ lea(rscratch1, src);
+ vxorpd(dst, nds, Address(rscratch1, 0), Assembler::AVX_128bit);
+ }
+ }
+}
+
void MacroAssembler::vxorpd(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len) {
if (reachable(src)) {
vxorpd(dst, nds, as_Address(src), vector_len);
@@ -4318,7 +4455,6 @@
void MacroAssembler::store_check(Register obj) {
// Does a store check for the oop in register obj. The content of
// register obj is destroyed afterwards.
-
BarrierSet* bs = Universe::heap()->barrier_set();
assert(bs->kind() == BarrierSet::CardTableForRS ||
bs->kind() == BarrierSet::CardTableExtension,
@@ -4572,69 +4708,58 @@
// if we are coming from c1, xmm registers may be live
int off = 0;
+ int num_xmm_regs = LP64_ONLY(16) NOT_LP64(8);
+ if (UseAVX > 2) {
+ num_xmm_regs = LP64_ONLY(32) NOT_LP64(8);
+ }
+
if (UseSSE == 1) {
subptr(rsp, sizeof(jdouble)*8);
- movflt(Address(rsp,off++*sizeof(jdouble)),xmm0);
- movflt(Address(rsp,off++*sizeof(jdouble)),xmm1);
- movflt(Address(rsp,off++*sizeof(jdouble)),xmm2);
- movflt(Address(rsp,off++*sizeof(jdouble)),xmm3);
- movflt(Address(rsp,off++*sizeof(jdouble)),xmm4);
- movflt(Address(rsp,off++*sizeof(jdouble)),xmm5);
- movflt(Address(rsp,off++*sizeof(jdouble)),xmm6);
- movflt(Address(rsp,off++*sizeof(jdouble)),xmm7);
+ for (int n = 0; n < 8; n++) {
+ movflt(Address(rsp, off++*sizeof(jdouble)), as_XMMRegister(n));
+ }
} else if (UseSSE >= 2) {
if (UseAVX > 2) {
+ push(rbx);
movl(rbx, 0xffff);
-#ifdef _LP64
- kmovql(k1, rbx);
-#else
- kmovdl(k1, rbx);
-#endif
+ kmovwl(k1, rbx);
+ pop(rbx);
}
#ifdef COMPILER2
if (MaxVectorSize > 16) {
- assert(UseAVX > 0, "256bit vectors are supported only with AVX");
+ if(UseAVX > 2) {
+ // Save upper half of ZMM registes
+ subptr(rsp, 32*num_xmm_regs);
+ for (int n = 0; n < num_xmm_regs; n++) {
+ vextractf64x4h(Address(rsp, off++*32), as_XMMRegister(n));
+ }
+ off = 0;
+ }
+ assert(UseAVX > 0, "256 bit vectors are supported only with AVX");
// Save upper half of YMM registes
- subptr(rsp, 16 * LP64_ONLY(16) NOT_LP64(8));
- vextractf128h(Address(rsp, 0),xmm0);
- vextractf128h(Address(rsp, 16),xmm1);
- vextractf128h(Address(rsp, 32),xmm2);
- vextractf128h(Address(rsp, 48),xmm3);
- vextractf128h(Address(rsp, 64),xmm4);
- vextractf128h(Address(rsp, 80),xmm5);
- vextractf128h(Address(rsp, 96),xmm6);
- vextractf128h(Address(rsp,112),xmm7);
-#ifdef _LP64
- vextractf128h(Address(rsp,128),xmm8);
- vextractf128h(Address(rsp,144),xmm9);
- vextractf128h(Address(rsp,160),xmm10);
- vextractf128h(Address(rsp,176),xmm11);
- vextractf128h(Address(rsp,192),xmm12);
- vextractf128h(Address(rsp,208),xmm13);
- vextractf128h(Address(rsp,224),xmm14);
- vextractf128h(Address(rsp,240),xmm15);
-#endif
+ subptr(rsp, 16*num_xmm_regs);
+ for (int n = 0; n < num_xmm_regs; n++) {
+ vextractf128h(Address(rsp, off++*16), as_XMMRegister(n));
+ }
}
#endif
- // Save whole 128bit (16 bytes) XMM regiters
- subptr(rsp, 16 * LP64_ONLY(16) NOT_LP64(8));
- movdqu(Address(rsp,off++*16),xmm0);
- movdqu(Address(rsp,off++*16),xmm1);
- movdqu(Address(rsp,off++*16),xmm2);
- movdqu(Address(rsp,off++*16),xmm3);
- movdqu(Address(rsp,off++*16),xmm4);
- movdqu(Address(rsp,off++*16),xmm5);
- movdqu(Address(rsp,off++*16),xmm6);
- movdqu(Address(rsp,off++*16),xmm7);
+ // Save whole 128bit (16 bytes) XMM registers
+ subptr(rsp, 16*num_xmm_regs);
+ off = 0;
#ifdef _LP64
- movdqu(Address(rsp,off++*16),xmm8);
- movdqu(Address(rsp,off++*16),xmm9);
- movdqu(Address(rsp,off++*16),xmm10);
- movdqu(Address(rsp,off++*16),xmm11);
- movdqu(Address(rsp,off++*16),xmm12);
- movdqu(Address(rsp,off++*16),xmm13);
- movdqu(Address(rsp,off++*16),xmm14);
- movdqu(Address(rsp,off++*16),xmm15);
+ if (VM_Version::supports_avx512novl()) {
+ for (int n = 0; n < num_xmm_regs; n++) {
+ vextractf32x4h(Address(rsp, off++*16), as_XMMRegister(n), 0);
+ }
+ } else {
+ for (int n = 0; n < num_xmm_regs; n++) {
+ movdqu(Address(rsp, off++*16), as_XMMRegister(n));
+ }
+ }
+#else
+ for (int n = 0; n < num_xmm_regs; n++) {
+ movdqu(Address(rsp, off++*16), as_XMMRegister(n));
+ }
#endif
}
@@ -4689,7 +4814,7 @@
movsd(Address(rsp, 0), xmm0);
fld_d(Address(rsp, 0));
#endif // _LP64
- addptr(rsp, sizeof(jdouble) * nb_args);
+ addptr(rsp, sizeof(jdouble)*nb_args);
if (num_fpu_regs_in_use > 1) {
// Must save return value to stack and then restore entire FPU
// stack except incoming arguments
@@ -4699,63 +4824,50 @@
addptr(rsp, sizeof(jdouble));
}
fld_d(Address(rsp, (nb_args-1)*sizeof(jdouble)));
- addptr(rsp, sizeof(jdouble) * nb_args);
+ addptr(rsp, sizeof(jdouble)*nb_args);
}
off = 0;
if (UseSSE == 1) {
- movflt(xmm0, Address(rsp,off++*sizeof(jdouble)));
- movflt(xmm1, Address(rsp,off++*sizeof(jdouble)));
- movflt(xmm2, Address(rsp,off++*sizeof(jdouble)));
- movflt(xmm3, Address(rsp,off++*sizeof(jdouble)));
- movflt(xmm4, Address(rsp,off++*sizeof(jdouble)));
- movflt(xmm5, Address(rsp,off++*sizeof(jdouble)));
- movflt(xmm6, Address(rsp,off++*sizeof(jdouble)));
- movflt(xmm7, Address(rsp,off++*sizeof(jdouble)));
+ for (int n = 0; n < 8; n++) {
+ movflt(as_XMMRegister(n), Address(rsp, off++*sizeof(jdouble)));
+ }
addptr(rsp, sizeof(jdouble)*8);
} else if (UseSSE >= 2) {
// Restore whole 128bit (16 bytes) XMM regiters
- movdqu(xmm0, Address(rsp,off++*16));
- movdqu(xmm1, Address(rsp,off++*16));
- movdqu(xmm2, Address(rsp,off++*16));
- movdqu(xmm3, Address(rsp,off++*16));
- movdqu(xmm4, Address(rsp,off++*16));
- movdqu(xmm5, Address(rsp,off++*16));
- movdqu(xmm6, Address(rsp,off++*16));
- movdqu(xmm7, Address(rsp,off++*16));
#ifdef _LP64
- movdqu(xmm8, Address(rsp,off++*16));
- movdqu(xmm9, Address(rsp,off++*16));
- movdqu(xmm10, Address(rsp,off++*16));
- movdqu(xmm11, Address(rsp,off++*16));
- movdqu(xmm12, Address(rsp,off++*16));
- movdqu(xmm13, Address(rsp,off++*16));
- movdqu(xmm14, Address(rsp,off++*16));
- movdqu(xmm15, Address(rsp,off++*16));
+ if (VM_Version::supports_avx512novl()) {
+ for (int n = 0; n < num_xmm_regs; n++) {
+ vinsertf32x4h(as_XMMRegister(n), Address(rsp, off++*16), 0);
+ }
+ }
+ else {
+ for (int n = 0; n < num_xmm_regs; n++) {
+ movdqu(as_XMMRegister(n), Address(rsp, off++*16));
+ }
+ }
+#else
+ for (int n = 0; n < num_xmm_regs; n++) {
+ movdqu(as_XMMRegister(n), Address(rsp, off++ * 16));
+ }
#endif
- addptr(rsp, 16 * LP64_ONLY(16) NOT_LP64(8));
+ addptr(rsp, 16*num_xmm_regs);
+
#ifdef COMPILER2
if (MaxVectorSize > 16) {
// Restore upper half of YMM registes.
- vinsertf128h(xmm0, Address(rsp, 0));
- vinsertf128h(xmm1, Address(rsp, 16));
- vinsertf128h(xmm2, Address(rsp, 32));
- vinsertf128h(xmm3, Address(rsp, 48));
- vinsertf128h(xmm4, Address(rsp, 64));
- vinsertf128h(xmm5, Address(rsp, 80));
- vinsertf128h(xmm6, Address(rsp, 96));
- vinsertf128h(xmm7, Address(rsp,112));
-#ifdef _LP64
- vinsertf128h(xmm8, Address(rsp,128));
- vinsertf128h(xmm9, Address(rsp,144));
- vinsertf128h(xmm10, Address(rsp,160));
- vinsertf128h(xmm11, Address(rsp,176));
- vinsertf128h(xmm12, Address(rsp,192));
- vinsertf128h(xmm13, Address(rsp,208));
- vinsertf128h(xmm14, Address(rsp,224));
- vinsertf128h(xmm15, Address(rsp,240));
-#endif
- addptr(rsp, 16 * LP64_ONLY(16) NOT_LP64(8));
+ off = 0;
+ for (int n = 0; n < num_xmm_regs; n++) {
+ vinsertf128h(as_XMMRegister(n), Address(rsp, off++*16));
+ }
+ addptr(rsp, 16*num_xmm_regs);
+ if(UseAVX > 2) {
+ off = 0;
+ for (int n = 0; n < num_xmm_regs; n++) {
+ vinsertf64x4h(as_XMMRegister(n), Address(rsp, off++*32));
+ }
+ addptr(rsp, 32*num_xmm_regs);
+ }
}
#endif
}
@@ -7095,11 +7207,7 @@
Label L_fill_32_bytes_loop, L_check_fill_8_bytes, L_fill_8_bytes_loop, L_fill_8_bytes;
if (UseAVX > 2) {
movl(rtmp, 0xffff);
-#ifdef _LP64
- kmovql(k1, rtmp);
-#else
- kmovdl(k1, rtmp);
-#endif
+ kmovwl(k1, rtmp);
}
movdl(xtmp, value);
if (UseAVX > 2 && UseUnalignedLoadStores) {
@@ -7112,7 +7220,7 @@
align(16);
BIND(L_fill_64_bytes_loop);
- evmovdqu(Address(to, 0), xtmp, Assembler::AVX_512bit);
+ evmovdqul(Address(to, 0), xtmp, Assembler::AVX_512bit);
addptr(to, 64);
subl(count, 16 << shift);
jcc(Assembler::greaterEqual, L_fill_64_bytes_loop);
@@ -7120,7 +7228,7 @@
BIND(L_check_fill_32_bytes);
addl(count, 8 << shift);
jccb(Assembler::less, L_check_fill_8_bytes);
- evmovdqu(Address(to, 0), xtmp, Assembler::AVX_256bit);
+ evmovdqul(Address(to, 0), xtmp, Assembler::AVX_256bit);
addptr(to, 32);
subl(count, 8 << shift);
@@ -8399,6 +8507,14 @@
Label L_tail, L_tail_restore, L_tail_loop, L_exit, L_align_loop, L_aligned;
Label L_fold_tail, L_fold_128b, L_fold_512b, L_fold_512b_loop, L_fold_tail_loop;
+ // For EVEX with VL and BW, provide a standard mask, VL = 128 will guide the merge
+ // context for the registers used, where all instructions below are using 128-bit mode
+ // On EVEX without VL and BW, these instructions will all be AVX.
+ if (VM_Version::supports_avx512vlbw()) {
+ movl(tmp, 0xffff);
+ kmovwl(k1, tmp);
+ }
+
lea(table, ExternalAddress(StubRoutines::crc_table_addr()));
notl(crc); // ~crc
cmpl(len, 16);
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp Wed Jul 05 20:51:27 2017 +0200
@@ -1069,6 +1069,9 @@
void vsubss(XMMRegister dst, XMMRegister nds, Address src) { Assembler::vsubss(dst, nds, src); }
void vsubss(XMMRegister dst, XMMRegister nds, AddressLiteral src);
+ void vnegatess(XMMRegister dst, XMMRegister nds, AddressLiteral src);
+ void vnegatesd(XMMRegister dst, XMMRegister nds, AddressLiteral src);
+
// AVX Vector instructions
void vxorpd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { Assembler::vxorpd(dst, nds, src, vector_len); }
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -115,6 +115,7 @@
OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_frame_words,
int* total_frame_words, bool verify_fpu, bool save_vectors) {
int vect_words = 0;
+ int num_xmm_regs = XMMRegisterImpl::number_of_registers;
#ifdef COMPILER2
if (save_vectors) {
assert(UseAVX > 0, "512bit vectors are supported only with EVEX");
@@ -173,59 +174,50 @@
__ 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
-
- __ fstp_d(Address(rsp, st0_off*wordSize)); // st(0)
- __ fstp_d(Address(rsp, st1_off*wordSize)); // st(1)
- __ fstp_d(Address(rsp, st2_off*wordSize)); // st(2)
- __ fstp_d(Address(rsp, st3_off*wordSize)); // st(3)
- __ fstp_d(Address(rsp, st4_off*wordSize)); // st(4)
- __ fstp_d(Address(rsp, st5_off*wordSize)); // st(5)
- __ fstp_d(Address(rsp, st6_off*wordSize)); // st(6)
- __ fstp_d(Address(rsp, st7_off*wordSize)); // st(7)
-
- if( UseSSE == 1 ) { // Save the XMM state
- __ movflt(Address(rsp,xmm0_off*wordSize),xmm0);
- __ movflt(Address(rsp,xmm1_off*wordSize),xmm1);
- __ movflt(Address(rsp,xmm2_off*wordSize),xmm2);
- __ movflt(Address(rsp,xmm3_off*wordSize),xmm3);
- __ movflt(Address(rsp,xmm4_off*wordSize),xmm4);
- __ movflt(Address(rsp,xmm5_off*wordSize),xmm5);
- __ movflt(Address(rsp,xmm6_off*wordSize),xmm6);
- __ movflt(Address(rsp,xmm7_off*wordSize),xmm7);
- } else if( UseSSE >= 2 ) {
+ for (int n = 0; n < FloatRegisterImpl::number_of_registers; n++) {
+ __ fstp_d(Address(rsp, off*wordSize));
+ off += delta;
+ }
+
+ off = xmm0_off;
+ delta = xmm1_off - off;
+ if(UseSSE == 1) { // Save the XMM state
+ for (int n = 0; n < num_xmm_regs; n++) {
+ __ movflt(Address(rsp, off*wordSize), as_XMMRegister(n));
+ off += delta;
+ }
+ } else if(UseSSE >= 2) {
// Save whole 128bit (16 bytes) XMM regiters
- __ movdqu(Address(rsp,xmm0_off*wordSize),xmm0);
- __ movdqu(Address(rsp,xmm1_off*wordSize),xmm1);
- __ movdqu(Address(rsp,xmm2_off*wordSize),xmm2);
- __ movdqu(Address(rsp,xmm3_off*wordSize),xmm3);
- __ movdqu(Address(rsp,xmm4_off*wordSize),xmm4);
- __ movdqu(Address(rsp,xmm5_off*wordSize),xmm5);
- __ movdqu(Address(rsp,xmm6_off*wordSize),xmm6);
- __ movdqu(Address(rsp,xmm7_off*wordSize),xmm7);
+ if (VM_Version::supports_avx512novl()) {
+ for (int n = 0; n < num_xmm_regs; n++) {
+ __ vextractf32x4h(Address(rsp, off*wordSize), as_XMMRegister(n), 0);
+ off += delta;
+ }
+ } else {
+ for (int n = 0; n < num_xmm_regs; n++) {
+ __ movdqu(Address(rsp, off*wordSize), as_XMMRegister(n));
+ off += delta;
+ }
+ }
}
if (vect_words > 0) {
assert(vect_words*wordSize == 128, "");
__ subptr(rsp, 128); // Save upper half of YMM registes
- __ vextractf128h(Address(rsp, 0),xmm0);
- __ vextractf128h(Address(rsp, 16),xmm1);
- __ vextractf128h(Address(rsp, 32),xmm2);
- __ vextractf128h(Address(rsp, 48),xmm3);
- __ vextractf128h(Address(rsp, 64),xmm4);
- __ vextractf128h(Address(rsp, 80),xmm5);
- __ vextractf128h(Address(rsp, 96),xmm6);
- __ vextractf128h(Address(rsp,112),xmm7);
+ off = 0;
+ for (int n = 0; n < num_xmm_regs; n++) {
+ __ vextractf128h(Address(rsp, off++*16), as_XMMRegister(n));
+ }
if (UseAVX > 2) {
__ subptr(rsp, 256); // Save upper half of ZMM registes
- __ vextractf64x4h(Address(rsp, 0), xmm0);
- __ vextractf64x4h(Address(rsp, 32), xmm1);
- __ vextractf64x4h(Address(rsp, 64), xmm2);
- __ vextractf64x4h(Address(rsp, 96), xmm3);
- __ vextractf64x4h(Address(rsp, 128), xmm4);
- __ vextractf64x4h(Address(rsp, 160), xmm5);
- __ vextractf64x4h(Address(rsp, 192), xmm6);
- __ vextractf64x4h(Address(rsp, 224), xmm7);
+ off = 0;
+ for (int n = 0; n < num_xmm_regs; n++) {
+ __ vextractf64x4h(Address(rsp, off++*32), as_XMMRegister(n));
+ }
}
}
@@ -238,58 +230,40 @@
OopMap* map = new OopMap( frame_words, 0 );
#define STACK_OFFSET(x) VMRegImpl::stack2reg((x) + additional_frame_words)
-
- map->set_callee_saved(STACK_OFFSET( rax_off), rax->as_VMReg());
- map->set_callee_saved(STACK_OFFSET( rcx_off), rcx->as_VMReg());
- map->set_callee_saved(STACK_OFFSET( rdx_off), rdx->as_VMReg());
- map->set_callee_saved(STACK_OFFSET( rbx_off), rbx->as_VMReg());
+#define NEXTREG(x) (x)->as_VMReg()->next()
+
+ map->set_callee_saved(STACK_OFFSET(rax_off), rax->as_VMReg());
+ map->set_callee_saved(STACK_OFFSET(rcx_off), rcx->as_VMReg());
+ map->set_callee_saved(STACK_OFFSET(rdx_off), rdx->as_VMReg());
+ map->set_callee_saved(STACK_OFFSET(rbx_off), rbx->as_VMReg());
// rbp, location is known implicitly, no oopMap
- map->set_callee_saved(STACK_OFFSET( rsi_off), rsi->as_VMReg());
- map->set_callee_saved(STACK_OFFSET( rdi_off), rdi->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(st0_off), as_FloatRegister(0)->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(st1_off), as_FloatRegister(1)->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(st2_off), as_FloatRegister(2)->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(st3_off), as_FloatRegister(3)->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(st4_off), as_FloatRegister(4)->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(st5_off), as_FloatRegister(5)->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(st6_off), as_FloatRegister(6)->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(st7_off), as_FloatRegister(7)->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm0_off), xmm0->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm1_off), xmm1->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm2_off), xmm2->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm3_off), xmm3->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm4_off), xmm4->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm5_off), xmm5->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm6_off), xmm6->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm7_off), xmm7->as_VMReg());
- // %%% This is really a waste but we'll keep things as they were for now
- if (true) {
-#define NEXTREG(x) (x)->as_VMReg()->next()
- map->set_callee_saved(STACK_OFFSET(st0H_off), NEXTREG(as_FloatRegister(0)));
- map->set_callee_saved(STACK_OFFSET(st1H_off), NEXTREG(as_FloatRegister(1)));
- map->set_callee_saved(STACK_OFFSET(st2H_off), NEXTREG(as_FloatRegister(2)));
- map->set_callee_saved(STACK_OFFSET(st3H_off), NEXTREG(as_FloatRegister(3)));
- map->set_callee_saved(STACK_OFFSET(st4H_off), NEXTREG(as_FloatRegister(4)));
- map->set_callee_saved(STACK_OFFSET(st5H_off), NEXTREG(as_FloatRegister(5)));
- map->set_callee_saved(STACK_OFFSET(st6H_off), NEXTREG(as_FloatRegister(6)));
- map->set_callee_saved(STACK_OFFSET(st7H_off), NEXTREG(as_FloatRegister(7)));
- map->set_callee_saved(STACK_OFFSET(xmm0H_off), NEXTREG(xmm0));
- map->set_callee_saved(STACK_OFFSET(xmm1H_off), NEXTREG(xmm1));
- map->set_callee_saved(STACK_OFFSET(xmm2H_off), NEXTREG(xmm2));
- map->set_callee_saved(STACK_OFFSET(xmm3H_off), NEXTREG(xmm3));
- map->set_callee_saved(STACK_OFFSET(xmm4H_off), NEXTREG(xmm4));
- map->set_callee_saved(STACK_OFFSET(xmm5H_off), NEXTREG(xmm5));
- map->set_callee_saved(STACK_OFFSET(xmm6H_off), NEXTREG(xmm6));
- map->set_callee_saved(STACK_OFFSET(xmm7H_off), NEXTREG(xmm7));
+ map->set_callee_saved(STACK_OFFSET(rsi_off), rsi->as_VMReg());
+ map->set_callee_saved(STACK_OFFSET(rdi_off), rdi->as_VMReg());
+ // %%% This is really a waste but we'll keep things as they were for now for the upper component
+ off = st0_off;
+ delta = st1_off - off;
+ for (int n = 0; n < FloatRegisterImpl::number_of_registers; n++) {
+ FloatRegister freg_name = as_FloatRegister(n);
+ map->set_callee_saved(STACK_OFFSET(off), freg_name->as_VMReg());
+ map->set_callee_saved(STACK_OFFSET(off+1), NEXTREG(freg_name));
+ off += delta;
+ }
+ off = xmm0_off;
+ delta = xmm1_off - off;
+ for (int n = 0; n < num_xmm_regs; n++) {
+ XMMRegister xmm_name = as_XMMRegister(n);
+ map->set_callee_saved(STACK_OFFSET(off), xmm_name->as_VMReg());
+ map->set_callee_saved(STACK_OFFSET(off+1), NEXTREG(xmm_name));
+ off += delta;
+ }
#undef NEXTREG
#undef STACK_OFFSET
- }
return map;
-
}
void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_vectors) {
+ int num_xmm_regs = XMMRegisterImpl::number_of_registers;
// Recover XMM & FPU state
int additional_frame_bytes = 0;
#ifdef COMPILER2
@@ -301,52 +275,43 @@
#else
assert(!restore_vectors, "vectors are generated only by C2");
#endif
+ int off = xmm0_off;
+ int delta = xmm1_off - off;
+
if (UseSSE == 1) {
assert(additional_frame_bytes == 0, "");
- __ movflt(xmm0,Address(rsp,xmm0_off*wordSize));
- __ movflt(xmm1,Address(rsp,xmm1_off*wordSize));
- __ movflt(xmm2,Address(rsp,xmm2_off*wordSize));
- __ movflt(xmm3,Address(rsp,xmm3_off*wordSize));
- __ movflt(xmm4,Address(rsp,xmm4_off*wordSize));
- __ movflt(xmm5,Address(rsp,xmm5_off*wordSize));
- __ movflt(xmm6,Address(rsp,xmm6_off*wordSize));
- __ movflt(xmm7,Address(rsp,xmm7_off*wordSize));
+ for (int n = 0; n < num_xmm_regs; n++) {
+ __ movflt(as_XMMRegister(n), Address(rsp, off*wordSize));
+ off += delta;
+ }
} else if (UseSSE >= 2) {
-#define STACK_ADDRESS(x) Address(rsp,(x)*wordSize + additional_frame_bytes)
- __ movdqu(xmm0,STACK_ADDRESS(xmm0_off));
- __ movdqu(xmm1,STACK_ADDRESS(xmm1_off));
- __ movdqu(xmm2,STACK_ADDRESS(xmm2_off));
- __ movdqu(xmm3,STACK_ADDRESS(xmm3_off));
- __ movdqu(xmm4,STACK_ADDRESS(xmm4_off));
- __ movdqu(xmm5,STACK_ADDRESS(xmm5_off));
- __ movdqu(xmm6,STACK_ADDRESS(xmm6_off));
- __ movdqu(xmm7,STACK_ADDRESS(xmm7_off));
-#undef STACK_ADDRESS
+ if (VM_Version::supports_avx512novl()) {
+ for (int n = 0; n < num_xmm_regs; n++) {
+ __ vinsertf32x4h(as_XMMRegister(n), Address(rsp, off*wordSize+additional_frame_bytes), 0);
+ off += delta;
+ }
+ } else {
+ for (int n = 0; n < num_xmm_regs; n++) {
+ __ movdqu(as_XMMRegister(n), Address(rsp, off*wordSize+additional_frame_bytes));
+ off += delta;
+ }
+ }
}
if (restore_vectors) {
+ if (UseAVX > 2) {
+ off = 0;
+ for (int n = 0; n < num_xmm_regs; n++) {
+ __ vinsertf64x4h(as_XMMRegister(n), Address(rsp, off++*32));
+ }
+ __ addptr(rsp, additional_frame_bytes*2); // Save upper half of ZMM registes
+ }
// Restore upper half of YMM registes.
assert(additional_frame_bytes == 128, "");
- __ vinsertf128h(xmm0, Address(rsp, 0));
- __ vinsertf128h(xmm1, Address(rsp, 16));
- __ vinsertf128h(xmm2, Address(rsp, 32));
- __ vinsertf128h(xmm3, Address(rsp, 48));
- __ vinsertf128h(xmm4, Address(rsp, 64));
- __ vinsertf128h(xmm5, Address(rsp, 80));
- __ vinsertf128h(xmm6, Address(rsp, 96));
- __ vinsertf128h(xmm7, Address(rsp,112));
- __ addptr(rsp, additional_frame_bytes);
- if (UseAVX > 2) {
- additional_frame_bytes = 256;
- __ vinsertf64x4h(xmm0, Address(rsp, 0));
- __ vinsertf64x4h(xmm1, Address(rsp, 32));
- __ vinsertf64x4h(xmm2, Address(rsp, 64));
- __ vinsertf64x4h(xmm3, Address(rsp, 96));
- __ vinsertf64x4h(xmm4, Address(rsp, 128));
- __ vinsertf64x4h(xmm5, Address(rsp, 160));
- __ vinsertf64x4h(xmm6, Address(rsp, 192));
- __ vinsertf64x4h(xmm7, Address(rsp, 224));
- __ addptr(rsp, additional_frame_bytes);
+ off = 0;
+ for (int n = 0; n < num_xmm_regs; n++) {
+ __ vinsertf128h(as_XMMRegister(n), Address(rsp, off++*16));
}
+ __ addptr(rsp, additional_frame_bytes); // Save upper half of YMM registes
}
__ pop_FPU_state();
__ addptr(rsp, FPU_regs_live*wordSize); // Pop FPU registers
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -69,7 +69,9 @@
class RegisterSaver {
// Capture info about frame layout. Layout offsets are in jint
// units because compiler frame slots are jints.
+#define HALF_ZMM_BANK_WORDS 128
#define DEF_XMM_OFFS(regnum) xmm ## regnum ## _off = xmm_off + (regnum)*16/BytesPerInt, xmm ## regnum ## H_off
+#define DEF_ZMM_OFFS(regnum) zmm ## regnum ## _off = zmm_off + (regnum-16)*64/BytesPerInt, zmm ## regnum ## H_off
enum layout {
fpu_state_off = frame::arg_reg_save_area_bytes/BytesPerInt, // fxsave save area
xmm_off = fpu_state_off + 160/BytesPerInt, // offset in fxsave save area
@@ -89,23 +91,24 @@
DEF_XMM_OFFS(13),
DEF_XMM_OFFS(14),
DEF_XMM_OFFS(15),
- DEF_XMM_OFFS(16),
- DEF_XMM_OFFS(17),
- DEF_XMM_OFFS(18),
- DEF_XMM_OFFS(19),
- DEF_XMM_OFFS(20),
- DEF_XMM_OFFS(21),
- DEF_XMM_OFFS(22),
- DEF_XMM_OFFS(23),
- DEF_XMM_OFFS(24),
- DEF_XMM_OFFS(25),
- DEF_XMM_OFFS(26),
- DEF_XMM_OFFS(27),
- DEF_XMM_OFFS(28),
- DEF_XMM_OFFS(29),
- DEF_XMM_OFFS(30),
- DEF_XMM_OFFS(31),
- fpu_state_end = fpu_state_off + ((FPUStateSizeInWords - 1)*wordSize / BytesPerInt),
+ zmm_off = fpu_state_off + ((FPUStateSizeInWords - (HALF_ZMM_BANK_WORDS + 1))*wordSize / BytesPerInt),
+ DEF_ZMM_OFFS(16),
+ DEF_ZMM_OFFS(17),
+ DEF_ZMM_OFFS(18),
+ DEF_ZMM_OFFS(19),
+ DEF_ZMM_OFFS(20),
+ DEF_ZMM_OFFS(21),
+ DEF_ZMM_OFFS(22),
+ DEF_ZMM_OFFS(23),
+ DEF_ZMM_OFFS(24),
+ DEF_ZMM_OFFS(25),
+ DEF_ZMM_OFFS(26),
+ DEF_ZMM_OFFS(27),
+ DEF_ZMM_OFFS(28),
+ DEF_ZMM_OFFS(29),
+ DEF_ZMM_OFFS(30),
+ DEF_ZMM_OFFS(31),
+ fpu_state_end = fpu_state_off + ((FPUStateSizeInWords-1)*wordSize / BytesPerInt),
fpu_stateH_end,
r15_off, r15H_off,
r14_off, r14H_off,
@@ -155,9 +158,10 @@
OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words, bool save_vectors) {
int vect_words = 0;
- int num_xmm_regs = 16;
- if (UseAVX > 2) {
- num_xmm_regs = 32;
+ int off = 0;
+ int num_xmm_regs = XMMRegisterImpl::number_of_registers;
+ if (UseAVX < 3) {
+ num_xmm_regs = num_xmm_regs/2;
}
#ifdef COMPILER2
if (save_vectors) {
@@ -165,9 +169,7 @@
assert(MaxVectorSize == 64, "only 512bit vectors are supported now");
// Save upper half of YMM registers
vect_words = 16 * num_xmm_regs / wordSize;
- additional_frame_words += vect_words;
- if (UseAVX > 2) {
- // Save upper half of ZMM registers as well
+ if (UseAVX < 3) {
additional_frame_words += vect_words;
}
}
@@ -195,77 +197,13 @@
__ enter(); // rsp becomes 16-byte aligned here
__ push_CPU_state(); // Push a multiple of 16 bytes
- if (vect_words > 0) {
+ // push cpu state handles this on EVEX enabled targets
+ if ((vect_words > 0) && (UseAVX < 3)) {
assert(vect_words*wordSize >= 256, "");
- __ subptr(rsp, 256); // Save upper half of YMM registes(0..15)
- __ vextractf128h(Address(rsp, 0), xmm0);
- __ vextractf128h(Address(rsp, 16), xmm1);
- __ vextractf128h(Address(rsp, 32), xmm2);
- __ vextractf128h(Address(rsp, 48), xmm3);
- __ vextractf128h(Address(rsp, 64), xmm4);
- __ vextractf128h(Address(rsp, 80), xmm5);
- __ vextractf128h(Address(rsp, 96), xmm6);
- __ vextractf128h(Address(rsp, 112), xmm7);
- __ vextractf128h(Address(rsp, 128), xmm8);
- __ vextractf128h(Address(rsp, 144), xmm9);
- __ vextractf128h(Address(rsp, 160), xmm10);
- __ vextractf128h(Address(rsp, 176), xmm11);
- __ vextractf128h(Address(rsp, 192), xmm12);
- __ vextractf128h(Address(rsp, 208), xmm13);
- __ vextractf128h(Address(rsp, 224), xmm14);
- __ vextractf128h(Address(rsp, 240), xmm15);
- if (UseAVX > 2) {
- __ subptr(rsp, 256); // Save upper half of YMM registes(16..31)
- __ vextractf128h(Address(rsp, 0), xmm16);
- __ vextractf128h(Address(rsp, 16), xmm17);
- __ vextractf128h(Address(rsp, 32), xmm18);
- __ vextractf128h(Address(rsp, 48), xmm19);
- __ vextractf128h(Address(rsp, 64), xmm20);
- __ vextractf128h(Address(rsp, 80), xmm21);
- __ vextractf128h(Address(rsp, 96), xmm22);
- __ vextractf128h(Address(rsp, 112), xmm23);
- __ vextractf128h(Address(rsp, 128), xmm24);
- __ vextractf128h(Address(rsp, 144), xmm25);
- __ vextractf128h(Address(rsp, 160), xmm26);
- __ vextractf128h(Address(rsp, 176), xmm27);
- __ vextractf128h(Address(rsp, 192), xmm28);
- __ vextractf128h(Address(rsp, 208), xmm29);
- __ vextractf128h(Address(rsp, 224), xmm30);
- __ vextractf128h(Address(rsp, 240), xmm31);
- // Now handle the ZMM registers (0..31)
- __ subptr(rsp, 1024); // Save upper half of ZMM registes
- __ vextractf64x4h(Address(rsp, 0), xmm0);
- __ vextractf64x4h(Address(rsp, 32), xmm1);
- __ vextractf64x4h(Address(rsp, 64), xmm2);
- __ vextractf64x4h(Address(rsp, 96), xmm3);
- __ vextractf64x4h(Address(rsp, 128), xmm4);
- __ vextractf64x4h(Address(rsp, 160), xmm5);
- __ vextractf64x4h(Address(rsp, 192), xmm6);
- __ vextractf64x4h(Address(rsp, 224), xmm7);
- __ vextractf64x4h(Address(rsp, 256), xmm8);
- __ vextractf64x4h(Address(rsp, 288), xmm9);
- __ vextractf64x4h(Address(rsp, 320), xmm10);
- __ vextractf64x4h(Address(rsp, 352), xmm11);
- __ vextractf64x4h(Address(rsp, 384), xmm12);
- __ vextractf64x4h(Address(rsp, 416), xmm13);
- __ vextractf64x4h(Address(rsp, 448), xmm14);
- __ vextractf64x4h(Address(rsp, 480), xmm15);
- __ vextractf64x4h(Address(rsp, 512), xmm16);
- __ vextractf64x4h(Address(rsp, 544), xmm17);
- __ vextractf64x4h(Address(rsp, 576), xmm18);
- __ vextractf64x4h(Address(rsp, 608), xmm19);
- __ vextractf64x4h(Address(rsp, 640), xmm20);
- __ vextractf64x4h(Address(rsp, 672), xmm21);
- __ vextractf64x4h(Address(rsp, 704), xmm22);
- __ vextractf64x4h(Address(rsp, 736), xmm23);
- __ vextractf64x4h(Address(rsp, 768), xmm24);
- __ vextractf64x4h(Address(rsp, 800), xmm25);
- __ vextractf64x4h(Address(rsp, 832), xmm26);
- __ vextractf64x4h(Address(rsp, 864), xmm27);
- __ vextractf64x4h(Address(rsp, 896), xmm28);
- __ vextractf64x4h(Address(rsp, 928), xmm29);
- __ vextractf64x4h(Address(rsp, 960), xmm30);
- __ vextractf64x4h(Address(rsp, 992), xmm31);
+ // Save upper half of YMM registes(0..num_xmm_regs)
+ __ subptr(rsp, num_xmm_regs*16);
+ for (int n = 0; n < num_xmm_regs; n++) {
+ __ vextractf128h(Address(rsp, off++*16), as_XMMRegister(n));
}
}
if (frame::arg_reg_save_area_bytes != 0) {
@@ -299,39 +237,24 @@
map->set_callee_saved(STACK_OFFSET( r13_off ), r13->as_VMReg());
map->set_callee_saved(STACK_OFFSET( r14_off ), r14->as_VMReg());
map->set_callee_saved(STACK_OFFSET( r15_off ), r15->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm0_off ), xmm0->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm1_off ), xmm1->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm2_off ), xmm2->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm3_off ), xmm3->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm4_off ), xmm4->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm5_off ), xmm5->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm6_off ), xmm6->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm7_off ), xmm7->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm8_off ), xmm8->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm9_off ), xmm9->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm10_off), xmm10->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm11_off), xmm11->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm12_off), xmm12->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm13_off), xmm13->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm14_off), xmm14->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm15_off), xmm15->as_VMReg());
- if (UseAVX > 2) {
- map->set_callee_saved(STACK_OFFSET(xmm16_off), xmm16->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm17_off), xmm17->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm18_off), xmm18->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm19_off), xmm19->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm20_off), xmm20->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm21_off), xmm21->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm22_off), xmm22->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm23_off), xmm23->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm24_off), xmm24->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm25_off), xmm25->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm26_off), xmm26->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm27_off), xmm27->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm28_off), xmm28->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm29_off), xmm29->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm30_off), xmm30->as_VMReg());
- map->set_callee_saved(STACK_OFFSET(xmm31_off), xmm31->as_VMReg());
+ // For both AVX and EVEX we will use the legacy FXSAVE area for xmm0..xmm15,
+ // on EVEX enabled targets, we get it included in the xsave area
+ off = xmm0_off;
+ int delta = xmm1_off - off;
+ for (int n = 0; n < 16; n++) {
+ XMMRegister xmm_name = as_XMMRegister(n);
+ map->set_callee_saved(STACK_OFFSET(off), xmm_name->as_VMReg());
+ off += delta;
+ }
+ if(UseAVX > 2) {
+ // Obtain xmm16..xmm31 from the XSAVE area on EVEX enabled targets
+ off = zmm16_off;
+ delta = zmm17_off - off;
+ for (int n = 16; n < num_xmm_regs; n++) {
+ XMMRegister xmm_name = as_XMMRegister(n);
+ map->set_callee_saved(STACK_OFFSET(off), xmm_name->as_VMReg());
+ off += delta;
+ }
}
// %%% These should all be a waste but we'll keep things as they were for now
@@ -351,39 +274,24 @@
map->set_callee_saved(STACK_OFFSET( r13H_off ), r13->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET( r14H_off ), r14->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET( r15H_off ), r15->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm0H_off ), xmm0->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm1H_off ), xmm1->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm2H_off ), xmm2->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm3H_off ), xmm3->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm4H_off ), xmm4->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm5H_off ), xmm5->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm6H_off ), xmm6->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm7H_off ), xmm7->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm8H_off ), xmm8->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm9H_off ), xmm9->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm10H_off), xmm10->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm11H_off), xmm11->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm12H_off), xmm12->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm13H_off), xmm13->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm14H_off), xmm14->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm15H_off), xmm15->as_VMReg()->next());
+ // For both AVX and EVEX we will use the legacy FXSAVE area for xmm0..xmm15,
+ // on EVEX enabled targets, we get it included in the xsave area
+ off = xmm0H_off;
+ delta = xmm1H_off - off;
+ for (int n = 0; n < 16; n++) {
+ XMMRegister xmm_name = as_XMMRegister(n);
+ map->set_callee_saved(STACK_OFFSET(off), xmm_name->as_VMReg()->next());
+ off += delta;
+ }
if (UseAVX > 2) {
- map->set_callee_saved(STACK_OFFSET(xmm16H_off), xmm16->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm17H_off), xmm17->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm18H_off), xmm18->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm19H_off), xmm19->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm20H_off), xmm20->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm21H_off), xmm21->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm22H_off), xmm22->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm23H_off), xmm23->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm24H_off), xmm24->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm25H_off), xmm25->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm26H_off), xmm26->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm27H_off), xmm27->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm28H_off), xmm28->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm29H_off), xmm29->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm30H_off), xmm30->as_VMReg()->next());
- map->set_callee_saved(STACK_OFFSET(xmm31H_off), xmm31->as_VMReg()->next());
+ // Obtain xmm16..xmm31 from the XSAVE area on EVEX enabled targets
+ off = zmm16H_off;
+ delta = zmm17H_off - off;
+ for (int n = 16; n < num_xmm_regs; n++) {
+ XMMRegister xmm_name = as_XMMRegister(n);
+ map->set_callee_saved(STACK_OFFSET(off), xmm_name->as_VMReg()->next());
+ off += delta;
+ }
}
}
@@ -391,86 +299,25 @@
}
void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_vectors) {
+ int num_xmm_regs = XMMRegisterImpl::number_of_registers;
+ if (UseAVX < 3) {
+ num_xmm_regs = num_xmm_regs/2;
+ }
if (frame::arg_reg_save_area_bytes != 0) {
// Pop arg register save area
__ addptr(rsp, frame::arg_reg_save_area_bytes);
}
#ifdef COMPILER2
- if (restore_vectors) {
- // Restore upper half of YMM registes (0..15)
- assert(UseAVX > 0, "512bit vectors are supported only with AVX");
- assert(MaxVectorSize == 64, "only 512bit vectors are supported now");
- __ vinsertf128h(xmm0, Address(rsp, 0));
- __ vinsertf128h(xmm1, Address(rsp, 16));
- __ vinsertf128h(xmm2, Address(rsp, 32));
- __ vinsertf128h(xmm3, Address(rsp, 48));
- __ vinsertf128h(xmm4, Address(rsp, 64));
- __ vinsertf128h(xmm5, Address(rsp, 80));
- __ vinsertf128h(xmm6, Address(rsp, 96));
- __ vinsertf128h(xmm7, Address(rsp,112));
- __ vinsertf128h(xmm8, Address(rsp,128));
- __ vinsertf128h(xmm9, Address(rsp,144));
- __ vinsertf128h(xmm10, Address(rsp,160));
- __ vinsertf128h(xmm11, Address(rsp,176));
- __ vinsertf128h(xmm12, Address(rsp,192));
- __ vinsertf128h(xmm13, Address(rsp,208));
- __ vinsertf128h(xmm14, Address(rsp,224));
- __ vinsertf128h(xmm15, Address(rsp,240));
- __ addptr(rsp, 256);
- if (UseAVX > 2) {
- // Restore upper half of YMM registes (16..31)
- __ vinsertf128h(xmm16, Address(rsp, 0));
- __ vinsertf128h(xmm17, Address(rsp, 16));
- __ vinsertf128h(xmm18, Address(rsp, 32));
- __ vinsertf128h(xmm19, Address(rsp, 48));
- __ vinsertf128h(xmm20, Address(rsp, 64));
- __ vinsertf128h(xmm21, Address(rsp, 80));
- __ vinsertf128h(xmm22, Address(rsp, 96));
- __ vinsertf128h(xmm23, Address(rsp,112));
- __ vinsertf128h(xmm24, Address(rsp,128));
- __ vinsertf128h(xmm25, Address(rsp,144));
- __ vinsertf128h(xmm26, Address(rsp,160));
- __ vinsertf128h(xmm27, Address(rsp,176));
- __ vinsertf128h(xmm28, Address(rsp,192));
- __ vinsertf128h(xmm29, Address(rsp,208));
- __ vinsertf128h(xmm30, Address(rsp,224));
- __ vinsertf128h(xmm31, Address(rsp,240));
- __ addptr(rsp, 256);
- // Restore upper half of ZMM registes.
- __ vinsertf64x4h(xmm0, Address(rsp, 0));
- __ vinsertf64x4h(xmm1, Address(rsp, 32));
- __ vinsertf64x4h(xmm2, Address(rsp, 64));
- __ vinsertf64x4h(xmm3, Address(rsp, 96));
- __ vinsertf64x4h(xmm4, Address(rsp, 128));
- __ vinsertf64x4h(xmm5, Address(rsp, 160));
- __ vinsertf64x4h(xmm6, Address(rsp, 192));
- __ vinsertf64x4h(xmm7, Address(rsp, 224));
- __ vinsertf64x4h(xmm8, Address(rsp, 256));
- __ vinsertf64x4h(xmm9, Address(rsp, 288));
- __ vinsertf64x4h(xmm10, Address(rsp, 320));
- __ vinsertf64x4h(xmm11, Address(rsp, 352));
- __ vinsertf64x4h(xmm12, Address(rsp, 384));
- __ vinsertf64x4h(xmm13, Address(rsp, 416));
- __ vinsertf64x4h(xmm14, Address(rsp, 448));
- __ vinsertf64x4h(xmm15, Address(rsp, 480));
- __ vinsertf64x4h(xmm16, Address(rsp, 512));
- __ vinsertf64x4h(xmm17, Address(rsp, 544));
- __ vinsertf64x4h(xmm18, Address(rsp, 576));
- __ vinsertf64x4h(xmm19, Address(rsp, 608));
- __ vinsertf64x4h(xmm20, Address(rsp, 640));
- __ vinsertf64x4h(xmm21, Address(rsp, 672));
- __ vinsertf64x4h(xmm22, Address(rsp, 704));
- __ vinsertf64x4h(xmm23, Address(rsp, 736));
- __ vinsertf64x4h(xmm24, Address(rsp, 768));
- __ vinsertf64x4h(xmm25, Address(rsp, 800));
- __ vinsertf64x4h(xmm26, Address(rsp, 832));
- __ vinsertf64x4h(xmm27, Address(rsp, 864));
- __ vinsertf64x4h(xmm28, Address(rsp, 896));
- __ vinsertf64x4h(xmm29, Address(rsp, 928));
- __ vinsertf64x4h(xmm30, Address(rsp, 960));
- __ vinsertf64x4h(xmm31, Address(rsp, 992));
- __ addptr(rsp, 1024);
+ // On EVEX enabled targets everything is handled in pop fpu state
+ if ((restore_vectors) && (UseAVX < 3)) {
+ assert(UseAVX > 0, "256/512-bit vectors are supported only with AVX");
+ assert(MaxVectorSize == 64, "up to 512bit vectors are supported now");
+ int off = 0;
+ // Restore upper half of YMM registes (0..num_xmm_regs)
+ for (int n = 0; n < num_xmm_regs; n++) {
+ __ vinsertf128h(as_XMMRegister(n), Address(rsp, off++*16));
}
+ __ addptr(rsp, num_xmm_regs*16);
}
#else
assert(!restore_vectors, "vectors are generated only by C2");
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -795,6 +795,12 @@
void xmm_copy_forward(Register from, Register to_from, Register qword_count) {
assert( UseSSE >= 2, "supported cpu only" );
Label L_copy_64_bytes_loop, L_copy_64_bytes, L_copy_8_bytes, L_exit;
+ if (UseAVX > 2) {
+ __ push(rbx);
+ __ movl(rbx, 0xffff);
+ __ kmovdl(k1, rbx);
+ __ pop(rbx);
+ }
// Copy 64-byte chunks
__ jmpb(L_copy_64_bytes);
__ align(OptoLoopAlignment);
@@ -802,8 +808,8 @@
if (UseUnalignedLoadStores) {
if (UseAVX > 2) {
- __ evmovdqu(xmm0, Address(from, 0), Assembler::AVX_512bit);
- __ evmovdqu(Address(from, to_from, Address::times_1, 0), xmm0, Assembler::AVX_512bit);
+ __ evmovdqul(xmm0, Address(from, 0), Assembler::AVX_512bit);
+ __ evmovdqul(Address(from, to_from, Address::times_1, 0), xmm0, Assembler::AVX_512bit);
} else if (UseAVX == 2) {
__ vmovdqu(xmm0, Address(from, 0));
__ vmovdqu(Address(from, to_from, Address::times_1, 0), xmm0);
@@ -2217,6 +2223,15 @@
const XMMRegister xmm_temp4 = xmm5;
__ enter(); // required for proper stackwalking of RuntimeStub frame
+
+ // For EVEX with VL and BW, provide a standard mask, VL = 128 will guide the merge
+ // context for the registers used, where all instructions below are using 128-bit mode
+ // On EVEX without VL and BW, these instructions will all be AVX.
+ if (VM_Version::supports_avx512vlbw()) {
+ __ movl(rdx, 0xffff);
+ __ kmovdl(k1, rdx);
+ }
+
__ movptr(from, from_param);
__ movptr(key, key_param);
@@ -2315,6 +2330,15 @@
const XMMRegister xmm_temp4 = xmm5;
__ enter(); // required for proper stackwalking of RuntimeStub frame
+
+ // For EVEX with VL and BW, provide a standard mask, VL = 128 will guide the merge
+ // context for the registers used, where all instructions below are using 128-bit mode
+ // On EVEX without VL and BW, these instructions will all be AVX.
+ if (VM_Version::supports_avx512vlbw()) {
+ __ movl(rdx, 0xffff);
+ __ kmovdl(k1, rdx);
+ }
+
__ movptr(from, from_param);
__ movptr(key, key_param);
@@ -2441,6 +2465,14 @@
__ enter(); // required for proper stackwalking of RuntimeStub frame
handleSOERegisters(true /*saving*/);
+ // For EVEX with VL and BW, provide a standard mask, VL = 128 will guide the merge
+ // context for the registers used, where all instructions below are using 128-bit mode
+ // On EVEX without VL and BW, these instructions will all be AVX.
+ if (VM_Version::supports_avx512vlbw()) {
+ __ movl(rdx, 0xffff);
+ __ kmovdl(k1, rdx);
+ }
+
// load registers from incoming parameters
const Address from_param(rbp, 8+0);
const Address to_param (rbp, 8+4);
@@ -2602,6 +2634,14 @@
__ enter(); // required for proper stackwalking of RuntimeStub frame
handleSOERegisters(true /*saving*/);
+ // For EVEX with VL and BW, provide a standard mask, VL = 128 will guide the merge
+ // context for the registers used, where all instructions below are using 128-bit mode
+ // On EVEX without VL and BW, these instructions will all be AVX.
+ if (VM_Version::supports_avx512vlbw()) {
+ __ movl(rdx, 0xffff);
+ __ kmovdl(k1, rdx);
+ }
+
// load registers from incoming parameters
const Address from_param(rbp, 8+0);
const Address to_param (rbp, 8+4);
@@ -2782,6 +2822,14 @@
__ enter();
handleSOERegisters(true); // Save registers
+ // For EVEX with VL and BW, provide a standard mask, VL = 128 will guide the merge
+ // context for the registers used, where all instructions below are using 128-bit mode
+ // On EVEX without VL and BW, these instructions will all be AVX.
+ if (VM_Version::supports_avx512vlbw()) {
+ __ movl(rdx, 0xffff);
+ __ kmovdl(k1, rdx);
+ }
+
__ movptr(state, state_param);
__ movptr(subkeyH, subkeyH_param);
__ movptr(data, data_param);
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -269,12 +269,16 @@
__ kmovql(k1, rbx);
}
#ifdef _WIN64
+ int last_reg = 15;
if (UseAVX > 2) {
- for (int i = 6; i <= 31; i++) {
- __ movdqu(xmm_save(i), as_XMMRegister(i));
+ last_reg = 31;
+ }
+ if (VM_Version::supports_avx512novl()) {
+ for (int i = xmm_save_first; i <= last_reg; i++) {
+ __ vextractf32x4h(xmm_save(i), as_XMMRegister(i), 0);
}
} else {
- for (int i = 6; i <= 15; i++) {
+ for (int i = xmm_save_first; i <= last_reg; i++) {
__ movdqu(xmm_save(i), as_XMMRegister(i));
}
}
@@ -386,13 +390,15 @@
// restore regs belonging to calling function
#ifdef _WIN64
- int xmm_ub = 15;
- if (UseAVX > 2) {
- xmm_ub = 31;
- }
// emit the restores for xmm regs
- for (int i = 6; i <= xmm_ub; i++) {
- __ movdqu(as_XMMRegister(i), xmm_save(i));
+ if (VM_Version::supports_avx512novl()) {
+ for (int i = xmm_save_first; i <= last_reg; i++) {
+ __ vinsertf32x4h(as_XMMRegister(i), xmm_save(i), 0);
+ }
+ } else {
+ for (int i = xmm_save_first; i <= last_reg; i++) {
+ __ movdqu(as_XMMRegister(i), xmm_save(i));
+ }
}
#endif
__ movptr(r15, r15_save);
@@ -1342,11 +1348,15 @@
__ align(OptoLoopAlignment);
if (UseUnalignedLoadStores) {
Label L_end;
+ if (UseAVX > 2) {
+ __ movl(to, 0xffff);
+ __ kmovql(k1, to);
+ }
// Copy 64-bytes per iteration
__ BIND(L_loop);
if (UseAVX > 2) {
- __ evmovdqu(xmm0, Address(end_from, qword_count, Address::times_8, -56), Assembler::AVX_512bit);
- __ evmovdqu(Address(end_to, qword_count, Address::times_8, -56), xmm0, Assembler::AVX_512bit);
+ __ evmovdqul(xmm0, Address(end_from, qword_count, Address::times_8, -56), Assembler::AVX_512bit);
+ __ evmovdqul(Address(end_to, qword_count, Address::times_8, -56), xmm0, Assembler::AVX_512bit);
} else if (UseAVX == 2) {
__ vmovdqu(xmm0, Address(end_from, qword_count, Address::times_8, -56));
__ vmovdqu(Address(end_to, qword_count, Address::times_8, -56), xmm0);
@@ -1422,11 +1432,15 @@
__ align(OptoLoopAlignment);
if (UseUnalignedLoadStores) {
Label L_end;
+ if (UseAVX > 2) {
+ __ movl(to, 0xffff);
+ __ kmovql(k1, to);
+ }
// Copy 64-bytes per iteration
__ BIND(L_loop);
if (UseAVX > 2) {
- __ evmovdqu(xmm0, Address(from, qword_count, Address::times_8, 32), Assembler::AVX_512bit);
- __ evmovdqu(Address(dest, qword_count, Address::times_8, 32), xmm0, Assembler::AVX_512bit);
+ __ evmovdqul(xmm0, Address(from, qword_count, Address::times_8, 32), Assembler::AVX_512bit);
+ __ evmovdqul(Address(dest, qword_count, Address::times_8, 32), xmm0, Assembler::AVX_512bit);
} else if (UseAVX == 2) {
__ vmovdqu(xmm0, Address(from, qword_count, Address::times_8, 32));
__ vmovdqu(Address(dest, qword_count, Address::times_8, 32), xmm0);
@@ -3106,6 +3120,14 @@
__ enter(); // required for proper stackwalking of RuntimeStub frame
+ // For EVEX with VL and BW, provide a standard mask, VL = 128 will guide the merge
+ // context for the registers used, where all instructions below are using 128-bit mode
+ // On EVEX without VL and BW, these instructions will all be AVX.
+ if (VM_Version::supports_avx512vlbw()) {
+ __ movl(rax, 0xffff);
+ __ kmovql(k1, rax);
+ }
+
// keylen could be only {11, 13, 15} * 4 = {44, 52, 60}
__ movl(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT)));
@@ -3200,6 +3222,14 @@
__ enter(); // required for proper stackwalking of RuntimeStub frame
+ // For EVEX with VL and BW, provide a standard mask, VL = 128 will guide the merge
+ // context for the registers used, where all instructions below are using 128-bit mode
+ // On EVEX without VL and BW, these instructions will all be AVX.
+ if (VM_Version::supports_avx512vlbw()) {
+ __ movl(rax, 0xffff);
+ __ kmovql(k1, rax);
+ }
+
// keylen could be only {11, 13, 15} * 4 = {44, 52, 60}
__ movl(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT)));
@@ -3312,6 +3342,14 @@
__ enter(); // required for proper stackwalking of RuntimeStub frame
+ // For EVEX with VL and BW, provide a standard mask, VL = 128 will guide the merge
+ // context for the registers used, where all instructions below are using 128-bit mode
+ // On EVEX without VL and BW, these instructions will all be AVX.
+ if (VM_Version::supports_avx512vlbw()) {
+ __ movl(rax, 0xffff);
+ __ kmovql(k1, rax);
+ }
+
#ifdef _WIN64
// on win64, fill len_reg from stack position
__ movl(len_reg, len_mem);
@@ -3508,6 +3546,14 @@
__ enter(); // required for proper stackwalking of RuntimeStub frame
+ // For EVEX with VL and BW, provide a standard mask, VL = 128 will guide the merge
+ // context for the registers used, where all instructions below are using 128-bit mode
+ // On EVEX without VL and BW, these instructions will all be AVX.
+ if (VM_Version::supports_avx512vlbw()) {
+ __ movl(rax, 0xffff);
+ __ kmovql(k1, rax);
+ }
+
#ifdef _WIN64
// on win64, fill len_reg from stack position
__ movl(len_reg, len_mem);
@@ -3746,6 +3792,14 @@
__ enter();
+ // For EVEX with VL and BW, provide a standard mask, VL = 128 will guide the merge
+ // context for the registers used, where all instructions below are using 128-bit mode
+ // On EVEX without VL and BW, these instructions will all be AVX.
+ if (VM_Version::supports_avx512vlbw()) {
+ __ movl(rax, 0xffff);
+ __ kmovql(k1, rax);
+ }
+
#ifdef _WIN64
// save the xmm registers which must be preserved 6-10
__ subptr(rsp, -rsp_after_call_off * wordSize);
--- a/hotspot/src/cpu/x86/vm/stubRoutines_x86_32.hpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/stubRoutines_x86_32.hpp Wed Jul 05 20:51:27 2017 +0200
@@ -31,7 +31,7 @@
enum platform_dependent_constants {
code_size1 = 9000, // simply increase if too small (assembler will crash if too small)
- code_size2 = 22000 // simply increase if too small (assembler will crash if too small)
+ code_size2 = 30000 // simply increase if too small (assembler will crash if too small)
};
class x86 {
--- a/hotspot/src/cpu/x86/vm/stubRoutines_x86_64.hpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/stubRoutines_x86_64.hpp Wed Jul 05 20:51:27 2017 +0200
@@ -33,7 +33,7 @@
enum platform_dependent_constants {
code_size1 = 19000, // simply increase if too small (assembler will crash if too small)
- code_size2 = 24000 // simply increase if too small (assembler will crash if too small)
+ code_size2 = 32000 // simply increase if too small (assembler will crash if too small)
};
class x86 {
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -367,16 +367,12 @@
__ movl(rcx, VM_Version::ymm_test_value());
__ movdl(xmm0, rcx);
__ movl(rcx, 0xffff);
+ __ kmovwl(k1, rcx);
+ __ evpbroadcastd(xmm0, xmm0, Assembler::AVX_512bit);
+ __ evmovdqul(xmm7, xmm0, Assembler::AVX_512bit);
#ifdef _LP64
- __ kmovql(k1, rcx);
-#else
- __ kmovdl(k1, rcx);
-#endif
- __ evpbroadcastd(xmm0, xmm0, Assembler::AVX_512bit);
- __ evmovdqu(xmm7, xmm0, Assembler::AVX_512bit);
-#ifdef _LP64
- __ evmovdqu(xmm8, xmm0, Assembler::AVX_512bit);
- __ evmovdqu(xmm31, xmm0, Assembler::AVX_512bit);
+ __ evmovdqul(xmm8, xmm0, Assembler::AVX_512bit);
+ __ evmovdqul(xmm31, xmm0, Assembler::AVX_512bit);
#endif
VM_Version::clean_cpuFeatures();
__ jmp(save_restore_except);
@@ -427,11 +423,11 @@
UseAVX = 3;
UseSSE = 2;
__ lea(rsi, Address(rbp, in_bytes(VM_Version::zmm_save_offset())));
- __ evmovdqu(Address(rsi, 0), xmm0, Assembler::AVX_512bit);
- __ evmovdqu(Address(rsi, 64), xmm7, Assembler::AVX_512bit);
+ __ evmovdqul(Address(rsi, 0), xmm0, Assembler::AVX_512bit);
+ __ evmovdqul(Address(rsi, 64), xmm7, Assembler::AVX_512bit);
#ifdef _LP64
- __ evmovdqu(Address(rsi, 128), xmm8, Assembler::AVX_512bit);
- __ evmovdqu(Address(rsi, 192), xmm31, Assembler::AVX_512bit);
+ __ evmovdqul(Address(rsi, 128), xmm8, Assembler::AVX_512bit);
+ __ evmovdqul(Address(rsi, 192), xmm31, Assembler::AVX_512bit);
#endif
VM_Version::clean_cpuFeatures();
UseAVX = saved_useavx;
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.hpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.hpp Wed Jul 05 20:51:27 2017 +0200
@@ -227,14 +227,15 @@
union XemXcr0Eax {
uint32_t value;
struct {
- uint32_t x87 : 1,
- sse : 1,
- ymm : 1,
- : 2,
- opmask : 1,
- zmm512 : 1,
- zmm32 : 1,
- : 24;
+ uint32_t x87 : 1,
+ sse : 1,
+ ymm : 1,
+ bndregs : 1,
+ bndcsr : 1,
+ opmask : 1,
+ zmm512 : 1,
+ zmm32 : 1,
+ : 24;
} bits;
};
@@ -703,6 +704,7 @@
static bool supports_avx512bw() { return (_cpuFeatures & CPU_AVX512BW) != 0; }
static bool supports_avx512vl() { return (_cpuFeatures & CPU_AVX512VL) != 0; }
static bool supports_avx512vlbw() { return (supports_avx512bw() && supports_avx512vl()); }
+ static bool supports_avx512novl() { return (supports_evex() && !supports_avx512vl()); }
// Intel features
static bool is_intel_family_core() { return is_intel() &&
extended_cpu_family() == CPU_FAMILY_INTEL_CORE; }
@@ -817,6 +819,12 @@
intx count = PrefetchFieldsAhead;
return count >= 0 ? count : 1;
}
+ static uint32_t get_xsave_header_lower_segment() {
+ return _cpuid_info.xem_xcr0_eax.value;
+ }
+ static uint32_t get_xsave_header_upper_segment() {
+ return _cpuid_info.xem_xcr0_edx;
+ }
};
#endif // CPU_X86_VM_VM_VERSION_X86_HPP
--- a/hotspot/src/cpu/x86/vm/x86.ad Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/x86.ad Wed Jul 05 20:51:27 2017 +0200
@@ -1661,46 +1661,55 @@
if (!has_match_rule(opcode))
return false;
+ bool ret_value = true;
switch (opcode) {
case Op_PopCountI:
case Op_PopCountL:
if (!UsePopCountInstruction)
- return false;
- break;
+ ret_value = false;
+ break;
case Op_MulVI:
if ((UseSSE < 4) && (UseAVX < 1)) // only with SSE4_1 or AVX
- return false;
- break;
+ ret_value = false;
+ break;
case Op_MulVL:
case Op_MulReductionVL:
if (VM_Version::supports_avx512dq() == false)
- return false;
+ ret_value = false;
+ break;
case Op_AddReductionVL:
if (UseAVX < 3) // only EVEX : vector connectivity becomes an issue here
- return false;
+ ret_value = false;
+ break;
case Op_AddReductionVI:
if (UseSSE < 3) // requires at least SSE3
- return false;
+ ret_value = false;
+ break;
case Op_MulReductionVI:
if (UseSSE < 4) // requires at least SSE4
- return false;
+ ret_value = false;
+ break;
case Op_AddReductionVF:
case Op_AddReductionVD:
case Op_MulReductionVF:
case Op_MulReductionVD:
if (UseSSE < 1) // requires at least SSE
- return false;
- break;
+ ret_value = false;
+ break;
+ case Op_SqrtVD:
+ if (UseAVX < 1) // enabled for AVX only
+ ret_value = false;
+ break;
case Op_CompareAndSwapL:
#ifdef _LP64
case Op_CompareAndSwapP:
#endif
if (!VM_Version::supports_cx8())
- return false;
- break;
+ ret_value = false;
+ break;
}
- return true; // Per default match rules are supported.
+ return ret_value; // Per default match rules are supported.
}
// Max vector size in bytes. 0 if not supported.
@@ -1721,14 +1730,24 @@
case T_DOUBLE:
case T_LONG:
if (size < 16) return 0;
+ break;
case T_FLOAT:
case T_INT:
if (size < 8) return 0;
+ break;
case T_BOOLEAN:
+ if (size < 4) return 0;
+ break;
+ case T_CHAR:
+ if (size < 4) return 0;
+ break;
case T_BYTE:
- case T_CHAR:
+ if (size < 4) return 0;
+ if ((size > 32) && !VM_Version::supports_avx512bw()) return 0;
+ break;
case T_SHORT:
if (size < 4) return 0;
+ if ((size > 16) && !VM_Version::supports_avx512bw()) return 0;
break;
default:
ShouldNotReachHere();
@@ -1800,7 +1819,7 @@
__ vmovdqu(as_XMMRegister(Matcher::_regEncode[dst_lo]), as_XMMRegister(Matcher::_regEncode[src_lo]));
break;
case Op_VecZ:
- __ evmovdqu(as_XMMRegister(Matcher::_regEncode[dst_lo]), as_XMMRegister(Matcher::_regEncode[src_lo]), 2);
+ __ evmovdqul(as_XMMRegister(Matcher::_regEncode[dst_lo]), as_XMMRegister(Matcher::_regEncode[src_lo]), 2);
break;
default:
ShouldNotReachHere();
@@ -1855,7 +1874,7 @@
__ vmovdqu(as_XMMRegister(Matcher::_regEncode[reg]), Address(rsp, stack_offset));
break;
case Op_VecZ:
- __ evmovdqu(as_XMMRegister(Matcher::_regEncode[reg]), Address(rsp, stack_offset), 2);
+ __ evmovdqul(as_XMMRegister(Matcher::_regEncode[reg]), Address(rsp, stack_offset), 2);
break;
default:
ShouldNotReachHere();
@@ -1875,7 +1894,7 @@
__ vmovdqu(Address(rsp, stack_offset), as_XMMRegister(Matcher::_regEncode[reg]));
break;
case Op_VecZ:
- __ evmovdqu(Address(rsp, stack_offset), as_XMMRegister(Matcher::_regEncode[reg]), 2);
+ __ evmovdqul(Address(rsp, stack_offset), as_XMMRegister(Matcher::_regEncode[reg]), 2);
break;
default:
ShouldNotReachHere();
@@ -1929,9 +1948,40 @@
}
#endif
}
- int offset_size = (stack_offset == 0) ? 0 : ((stack_offset < 0x80) ? 1 : (UseAVX > 2) ? 6 : 4);
+ bool is_single_byte = false;
+ int vec_len = 0;
+ if ((UseAVX > 2) && (stack_offset != 0)) {
+ switch (ireg) {
+ case Op_VecS:
+ case Op_VecD:
+ case Op_VecX:
+ break;
+ case Op_VecY:
+ vec_len = 1;
+ break;
+ case Op_VecZ:
+ vec_len = 2;
+ break;
+ }
+ is_single_byte = Assembler::query_compressed_disp_byte(stack_offset, true, vec_len, Assembler::EVEX_FVM, Assembler::EVEX_32bit, 0);
+ }
+ int offset_size = 0;
+ int size = 5;
+ if (UseAVX > 2 ) {
+ if ((VM_Version::supports_avx512vl() == false) && (vec_len == 2)) {
+ offset_size = (stack_offset == 0) ? 0 : ((is_single_byte) ? 1 : 4);
+ size += 2; // Need an additional two bytes for EVEX encoding
+ } else if ((VM_Version::supports_avx512vl() == false) && (vec_len < 2)) {
+ offset_size = (stack_offset == 0) ? 0 : ((stack_offset <= 127) ? 1 : 4);
+ } else {
+ offset_size = (stack_offset == 0) ? 0 : ((is_single_byte) ? 1 : 4);
+ size += 2; // Need an additional two bytes for EVEX encodding
+ }
+ } else {
+ offset_size = (stack_offset == 0) ? 0 : ((stack_offset <= 127) ? 1 : 4);
+ }
// VEX_2bytes prefix is used if UseAVX > 0, so it takes the same 2 bytes as SIMD prefix.
- return 5+offset_size;
+ return size+offset_size;
}
static inline jfloat replicate4_imm(int con, int width) {
@@ -2675,11 +2725,10 @@
predicate(UseAVX > 0);
match(Set dst (NegF src));
ins_cost(150);
- format %{ "vxorps $dst, $src, [0x80000000]\t# neg float by sign flipping" %}
- ins_encode %{
- int vector_len = 0;
- __ vxorps($dst$$XMMRegister, $src$$XMMRegister,
- ExternalAddress(float_signflip()), vector_len);
+ format %{ "vnegatess $dst, $src, [0x80000000]\t# neg float by sign flipping" %}
+ ins_encode %{
+ __ vnegatess($dst$$XMMRegister, $src$$XMMRegister,
+ ExternalAddress(float_signflip()));
%}
ins_pipe(pipe_slow);
%}
@@ -2700,12 +2749,11 @@
predicate(UseAVX > 0);
match(Set dst (NegD src));
ins_cost(150);
- format %{ "vxorpd $dst, $src, [0x8000000000000000]\t"
+ format %{ "vnegatess $dst, $src, [0x8000000000000000]\t"
"# neg double by sign flipping" %}
ins_encode %{
- int vector_len = 0;
- __ vxorpd($dst$$XMMRegister, $src$$XMMRegister,
- ExternalAddress(double_signflip()), vector_len);
+ __ vnegatesd($dst$$XMMRegister, $src$$XMMRegister,
+ ExternalAddress(double_signflip()));
%}
ins_pipe(pipe_slow);
%}
@@ -2838,7 +2886,7 @@
format %{ "vmovdqu $dst k0,$mem\t! load vector (64 bytes)" %}
ins_encode %{
int vector_len = 2;
- __ evmovdqu($dst$$XMMRegister, $mem$$Address, vector_len);
+ __ evmovdqul($dst$$XMMRegister, $mem$$Address, vector_len);
%}
ins_pipe( pipe_slow );
%}
@@ -2895,7 +2943,7 @@
format %{ "vmovdqu $mem k0,$src\t! store vector (64 bytes)" %}
ins_encode %{
int vector_len = 2;
- __ evmovdqu($mem$$Address, $src$$XMMRegister, vector_len);
+ __ evmovdqul($mem$$Address, $src$$XMMRegister, vector_len);
%}
ins_pipe( pipe_slow );
%}
@@ -3315,6 +3363,37 @@
ins_pipe( pipe_slow );
%}
+instruct Repl2F_zero(vecD dst, immF0 zero) %{
+ predicate(n->as_Vector()->length() == 2 && UseAVX < 3);
+ match(Set dst (ReplicateF zero));
+ format %{ "xorps $dst,$dst\t! replicate2F zero" %}
+ ins_encode %{
+ __ xorps($dst$$XMMRegister, $dst$$XMMRegister);
+ %}
+ ins_pipe( fpu_reg_reg );
+%}
+
+instruct Repl4F_zero(vecX dst, immF0 zero) %{
+ predicate(n->as_Vector()->length() == 4 && UseAVX < 3);
+ match(Set dst (ReplicateF zero));
+ format %{ "xorps $dst,$dst\t! replicate4F zero" %}
+ ins_encode %{
+ __ xorps($dst$$XMMRegister, $dst$$XMMRegister);
+ %}
+ ins_pipe( fpu_reg_reg );
+%}
+
+instruct Repl8F_zero(vecY dst, immF0 zero) %{
+ predicate(n->as_Vector()->length() == 8 && UseAVX < 3);
+ match(Set dst (ReplicateF zero));
+ format %{ "vxorps $dst,$dst,$dst\t! replicate8F zero" %}
+ ins_encode %{
+ int vector_len = 1;
+ __ vxorps($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, vector_len);
+ %}
+ ins_pipe( fpu_reg_reg );
+%}
+
instruct Repl2D_mem(vecX dst, memory mem) %{
predicate(n->as_Vector()->length() == 2 && UseAVX > 0 && !VM_Version::supports_avx512vl());
match(Set dst (ReplicateD (LoadD mem)));
@@ -3349,6 +3428,28 @@
ins_pipe( pipe_slow );
%}
+// Replicate double (8 byte) scalar zero to be vector
+instruct Repl2D_zero(vecX dst, immD0 zero) %{
+ predicate(n->as_Vector()->length() == 2 && UseAVX < 3);
+ match(Set dst (ReplicateD zero));
+ format %{ "xorpd $dst,$dst\t! replicate2D zero" %}
+ ins_encode %{
+ __ xorpd($dst$$XMMRegister, $dst$$XMMRegister);
+ %}
+ ins_pipe( fpu_reg_reg );
+%}
+
+instruct Repl4D_zero(vecY dst, immD0 zero) %{
+ predicate(n->as_Vector()->length() == 4 && UseAVX < 3);
+ match(Set dst (ReplicateD zero));
+ format %{ "vxorpd $dst,$dst,$dst,vect256\t! replicate4D zero" %}
+ ins_encode %{
+ int vector_len = 1;
+ __ vxorpd($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, vector_len);
+ %}
+ ins_pipe( fpu_reg_reg );
+%}
+
// ====================GENERIC REPLICATE==========================================
// Replicate byte scalar to be vector
@@ -3680,38 +3781,6 @@
ins_pipe( pipe_slow );
%}
-// Replicate float (4 byte) scalar zero to be vector
-instruct Repl2F_zero(vecD dst, immF0 zero) %{
- predicate(n->as_Vector()->length() == 2);
- match(Set dst (ReplicateF zero));
- format %{ "xorps $dst,$dst\t! replicate2F zero" %}
- ins_encode %{
- __ xorps($dst$$XMMRegister, $dst$$XMMRegister);
- %}
- ins_pipe( fpu_reg_reg );
-%}
-
-instruct Repl4F_zero(vecX dst, immF0 zero) %{
- predicate(n->as_Vector()->length() == 4);
- match(Set dst (ReplicateF zero));
- format %{ "xorps $dst,$dst\t! replicate4F zero" %}
- ins_encode %{
- __ xorps($dst$$XMMRegister, $dst$$XMMRegister);
- %}
- ins_pipe( fpu_reg_reg );
-%}
-
-instruct Repl8F_zero(vecY dst, immF0 zero) %{
- predicate(n->as_Vector()->length() == 8);
- match(Set dst (ReplicateF zero));
- format %{ "vxorps $dst,$dst,$dst\t! replicate8F zero" %}
- ins_encode %{
- int vector_len = 1;
- __ vxorps($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, vector_len);
- %}
- ins_pipe( fpu_reg_reg );
-%}
-
// Replicate double (8 bytes) scalar to be vector
instruct Repl2D(vecX dst, regD src) %{
predicate(n->as_Vector()->length() == 2);
@@ -3723,28 +3792,6 @@
ins_pipe( pipe_slow );
%}
-// Replicate double (8 byte) scalar zero to be vector
-instruct Repl2D_zero(vecX dst, immD0 zero) %{
- predicate(n->as_Vector()->length() == 2);
- match(Set dst (ReplicateD zero));
- format %{ "xorpd $dst,$dst\t! replicate2D zero" %}
- ins_encode %{
- __ xorpd($dst$$XMMRegister, $dst$$XMMRegister);
- %}
- ins_pipe( fpu_reg_reg );
-%}
-
-instruct Repl4D_zero(vecY dst, immD0 zero) %{
- predicate(n->as_Vector()->length() == 4);
- match(Set dst (ReplicateD zero));
- format %{ "vxorpd $dst,$dst,$dst,vect256\t! replicate4D zero" %}
- ins_encode %{
- int vector_len = 1;
- __ vxorpd($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, vector_len);
- %}
- ins_pipe( fpu_reg_reg );
-%}
-
// ====================EVEX REPLICATE=============================================
instruct Repl4B_mem_evex(vecS dst, memory mem) %{
@@ -3814,7 +3861,7 @@
%}
instruct Repl64B_evex(vecZ dst, rRegI src) %{
- predicate(n->as_Vector()->length() == 64 && UseAVX > 2);
+ predicate(n->as_Vector()->length() == 64 && VM_Version::supports_avx512bw());
match(Set dst (ReplicateB src));
format %{ "vpbroadcastb $dst,$src\t! upper replicate64B" %}
ins_encode %{
@@ -3825,7 +3872,7 @@
%}
instruct Repl64B_mem_evex(vecZ dst, memory mem) %{
- predicate(n->as_Vector()->length() == 64 && VM_Version::supports_avx512vlbw());
+ predicate(n->as_Vector()->length() == 64 && VM_Version::supports_avx512bw());
match(Set dst (ReplicateB (LoadB mem)));
format %{ "vpbroadcastb $dst,$mem\t! replicate64B" %}
ins_encode %{
@@ -3862,7 +3909,7 @@
%}
instruct Repl64B_imm_evex(vecZ dst, immI con) %{
- predicate(n->as_Vector()->length() == 64 && UseAVX > 2);
+ predicate(n->as_Vector()->length() == 64 && VM_Version::supports_avx512bw());
match(Set dst (ReplicateB con));
format %{ "movq $dst,[$constantaddress]\n\t"
"vpbroadcastb $dst,$dst\t! upper replicate64B" %}
@@ -3953,7 +4000,7 @@
%}
instruct Repl32S_evex(vecZ dst, rRegI src) %{
- predicate(n->as_Vector()->length() == 32 && UseAVX > 2);
+ predicate(n->as_Vector()->length() == 32 && VM_Version::supports_avx512bw());
match(Set dst (ReplicateS src));
format %{ "vpbroadcastw $dst,$src\t! replicate32S" %}
ins_encode %{
@@ -3964,7 +4011,7 @@
%}
instruct Repl32S_mem_evex(vecZ dst, memory mem) %{
- predicate(n->as_Vector()->length() == 32 && UseAVX > 2);
+ predicate(n->as_Vector()->length() == 32 && VM_Version::supports_avx512bw());
match(Set dst (ReplicateS (LoadS mem)));
format %{ "vpbroadcastw $dst,$mem\t! replicate32S" %}
ins_encode %{
@@ -4001,7 +4048,7 @@
%}
instruct Repl32S_imm_evex(vecZ dst, immI con) %{
- predicate(n->as_Vector()->length() == 32 && UseAVX > 2);
+ predicate(n->as_Vector()->length() == 32 && VM_Version::supports_avx512bw());
match(Set dst (ReplicateS con));
format %{ "movq $dst,[$constantaddress]\n\t"
"vpbroadcastw $dst,$dst\t! replicate32S" %}
@@ -4318,13 +4365,50 @@
ins_pipe( pipe_slow );
%}
+instruct Repl2F_zero_evex(vecD dst, immF0 zero) %{
+ predicate(n->as_Vector()->length() == 2 && UseAVX > 2);
+ match(Set dst (ReplicateF zero));
+ format %{ "vpxor $dst k0,$dst,$dst\t! replicate2F zero" %}
+ ins_encode %{
+ // Use vpxor in place of vxorps since EVEX has a constriant on dq for vxorps: this is a 512-bit operation
+ int vector_len = 2;
+ __ vpxor($dst$$XMMRegister,$dst$$XMMRegister, $dst$$XMMRegister, vector_len);
+ %}
+ ins_pipe( fpu_reg_reg );
+%}
+
+instruct Repl4F_zero_evex(vecX dst, immF0 zero) %{
+ predicate(n->as_Vector()->length() == 4 && UseAVX > 2);
+ match(Set dst (ReplicateF zero));
+ format %{ "vpxor $dst k0,$dst,$dst\t! replicate4F zero" %}
+ ins_encode %{
+ // Use vpxor in place of vxorps since EVEX has a constriant on dq for vxorps: this is a 512-bit operation
+ int vector_len = 2;
+ __ vpxor($dst$$XMMRegister,$dst$$XMMRegister, $dst$$XMMRegister, vector_len);
+ %}
+ ins_pipe( fpu_reg_reg );
+%}
+
+instruct Repl8F_zero_evex(vecY dst, immF0 zero) %{
+ predicate(n->as_Vector()->length() == 8 && UseAVX > 2);
+ match(Set dst (ReplicateF zero));
+ format %{ "vpxor $dst k0,$dst,$dst\t! replicate8F zero" %}
+ ins_encode %{
+ // Use vpxor in place of vxorps since EVEX has a constriant on dq for vxorps: this is a 512-bit operation
+ int vector_len = 2;
+ __ vpxor($dst$$XMMRegister,$dst$$XMMRegister, $dst$$XMMRegister, vector_len);
+ %}
+ ins_pipe( fpu_reg_reg );
+%}
+
instruct Repl16F_zero_evex(vecZ dst, immF0 zero) %{
predicate(n->as_Vector()->length() == 16 && UseAVX > 2);
match(Set dst (ReplicateF zero));
- format %{ "vxorps $dst k0,$dst,$dst\t! replicate16F zero" %}
- ins_encode %{
+ format %{ "vpxor $dst k0,$dst,$dst\t! replicate16F zero" %}
+ ins_encode %{
+ // Use vpxor in place of vxorps since EVEX has a constriant on dq for vxorps: this is a 512-bit operation
int vector_len = 2;
- __ vxorps($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, vector_len);
+ __ vpxor($dst$$XMMRegister,$dst$$XMMRegister, $dst$$XMMRegister, vector_len);
%}
ins_pipe( fpu_reg_reg );
%}
@@ -4373,13 +4457,38 @@
ins_pipe( pipe_slow );
%}
+instruct Repl2D_zero_evex(vecX dst, immD0 zero) %{
+ predicate(n->as_Vector()->length() == 2 && UseAVX > 2);
+ match(Set dst (ReplicateD zero));
+ format %{ "vpxor $dst k0,$dst,$dst\t! replicate2D zero" %}
+ ins_encode %{
+ // Use vpxor in place of vxorpd since EVEX has a constriant on dq for vxorpd: this is a 512-bit operation
+ int vector_len = 2;
+ __ vpxor($dst$$XMMRegister,$dst$$XMMRegister, $dst$$XMMRegister, vector_len);
+ %}
+ ins_pipe( fpu_reg_reg );
+%}
+
+instruct Repl4D_zero_evex(vecY dst, immD0 zero) %{
+ predicate(n->as_Vector()->length() == 4 && UseAVX > 2);
+ match(Set dst (ReplicateD zero));
+ format %{ "vpxor $dst k0,$dst,$dst\t! replicate4D zero" %}
+ ins_encode %{
+ // Use vpxor in place of vxorpd since EVEX has a constriant on dq for vxorpd: this is a 512-bit operation
+ int vector_len = 2;
+ __ vpxor($dst$$XMMRegister,$dst$$XMMRegister, $dst$$XMMRegister, vector_len);
+ %}
+ ins_pipe( fpu_reg_reg );
+%}
+
instruct Repl8D_zero_evex(vecZ dst, immD0 zero) %{
predicate(n->as_Vector()->length() == 8 && UseAVX > 2);
match(Set dst (ReplicateD zero));
- format %{ "vxorpd $dst k0,$dst,$dst,vect512\t! replicate8D zero" %}
- ins_encode %{
+ format %{ "vpxor $dst k0,$dst,$dst,vect512\t! replicate8D zero" %}
+ ins_encode %{
+ // Use vpxor in place of vxorpd since EVEX has a constriant on dq for vxorpd: this is a 512-bit operation
int vector_len = 2;
- __ vxorpd($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, vector_len);
+ __ vpxor($dst$$XMMRegister,$dst$$XMMRegister, $dst$$XMMRegister, vector_len);
%}
ins_pipe( fpu_reg_reg );
%}
@@ -7474,6 +7583,75 @@
ins_pipe( pipe_slow );
%}
+// --------------------------------- Sqrt --------------------------------------
+
+// Floating point vector sqrt - double precision only
+instruct vsqrt2D_reg(vecX dst, vecX src) %{
+ predicate(UseAVX > 0 && n->as_Vector()->length() == 2);
+ match(Set dst (SqrtVD src));
+ format %{ "vsqrtpd $dst,$src\t! sqrt packed2D" %}
+ ins_encode %{
+ int vector_len = 0;
+ __ vsqrtpd($dst$$XMMRegister, $src$$XMMRegister, vector_len);
+ %}
+ ins_pipe( pipe_slow );
+%}
+
+instruct vsqrt2D_mem(vecX dst, memory mem) %{
+ predicate(UseAVX > 0 && n->as_Vector()->length() == 2);
+ match(Set dst (SqrtVD (LoadVector mem)));
+ format %{ "vsqrtpd $dst,$mem\t! sqrt packed2D" %}
+ ins_encode %{
+ int vector_len = 0;
+ __ vsqrtpd($dst$$XMMRegister, $mem$$Address, vector_len);
+ %}
+ ins_pipe( pipe_slow );
+%}
+
+instruct vsqrt4D_reg(vecY dst, vecY src) %{
+ predicate(UseAVX > 0 && n->as_Vector()->length() == 4);
+ match(Set dst (SqrtVD src));
+ format %{ "vsqrtpd $dst,$src\t! sqrt packed4D" %}
+ ins_encode %{
+ int vector_len = 1;
+ __ vsqrtpd($dst$$XMMRegister, $src$$XMMRegister, vector_len);
+ %}
+ ins_pipe( pipe_slow );
+%}
+
+instruct vsqrt4D_mem(vecY dst, memory mem) %{
+ predicate(UseAVX > 0 && n->as_Vector()->length() == 4);
+ match(Set dst (SqrtVD (LoadVector mem)));
+ format %{ "vsqrtpd $dst,$mem\t! sqrt packed4D" %}
+ ins_encode %{
+ int vector_len = 1;
+ __ vsqrtpd($dst$$XMMRegister, $mem$$Address, vector_len);
+ %}
+ ins_pipe( pipe_slow );
+%}
+
+instruct vsqrt8D_reg(vecZ dst, vecZ src) %{
+ predicate(UseAVX > 2 && n->as_Vector()->length() == 8);
+ match(Set dst (SqrtVD src));
+ format %{ "vsqrtpd $dst,$src\t! sqrt packed8D" %}
+ ins_encode %{
+ int vector_len = 2;
+ __ vsqrtpd($dst$$XMMRegister, $src$$XMMRegister, vector_len);
+ %}
+ ins_pipe( pipe_slow );
+%}
+
+instruct vsqrt8D_mem(vecZ dst, memory mem) %{
+ predicate(UseAVX > 2 && n->as_Vector()->length() == 8);
+ match(Set dst (SqrtVD (LoadVector mem)));
+ format %{ "vsqrtpd $dst,$mem\t! sqrt packed8D" %}
+ ins_encode %{
+ int vector_len = 2;
+ __ vsqrtpd($dst$$XMMRegister, $mem$$Address, vector_len);
+ %}
+ ins_pipe( pipe_slow );
+%}
+
// ------------------------------ LeftShift -----------------------------------
// Shorts/Chars vector left shift
--- a/hotspot/src/cpu/x86/vm/x86_32.ad Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/x86_32.ad Wed Jul 05 20:51:27 2017 +0200
@@ -1004,10 +1004,10 @@
__ vmovdqu(Address(rsp, dst_offset), xmm0);
__ vmovdqu(xmm0, Address(rsp, -32));
case Op_VecZ:
- __ evmovdqu(Address(rsp, -64), xmm0, 2);
- __ evmovdqu(xmm0, Address(rsp, src_offset), 2);
- __ evmovdqu(Address(rsp, dst_offset), xmm0, 2);
- __ evmovdqu(xmm0, Address(rsp, -64), 2);
+ __ evmovdqul(Address(rsp, -64), xmm0, 2);
+ __ evmovdqul(xmm0, Address(rsp, src_offset), 2);
+ __ evmovdqul(Address(rsp, dst_offset), xmm0, 2);
+ __ evmovdqul(xmm0, Address(rsp, -64), 2);
break;
default:
ShouldNotReachHere();
--- a/hotspot/src/cpu/x86/vm/x86_64.ad Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/x86_64.ad Wed Jul 05 20:51:27 2017 +0200
@@ -1075,10 +1075,10 @@
__ vmovdqu(Address(rsp, dst_offset), xmm0);
__ vmovdqu(xmm0, Address(rsp, -32));
case Op_VecZ:
- __ evmovdqu(Address(rsp, -64), xmm0, 2);
- __ evmovdqu(xmm0, Address(rsp, src_offset), 2);
- __ evmovdqu(Address(rsp, dst_offset), xmm0, 2);
- __ evmovdqu(xmm0, Address(rsp, -64), 2);
+ __ evmovdqul(Address(rsp, -64), xmm0, 2);
+ __ evmovdqul(xmm0, Address(rsp, src_offset), 2);
+ __ evmovdqul(Address(rsp, dst_offset), xmm0, 2);
+ __ evmovdqul(xmm0, Address(rsp, -64), 2);
break;
default:
ShouldNotReachHere();
--- a/hotspot/src/os/linux/vm/os_linux.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/os/linux/vm/os_linux.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -2211,9 +2211,13 @@
}
}
-const char* search_string = IA32_ONLY("model name") AMD64_ONLY("model name")
- IA64_ONLY("") SPARC_ONLY("cpu")
- ARM32_ONLY("Processor") PPC_ONLY("Processor") AARCH64_ONLY("Processor");
+#if defined(AMD64) || defined(IA32) || defined(X32)
+const char* search_string = "model name";
+#elif defined(SPARC)
+const char* search_string = "cpu";
+#else
+const char* search_string = "Processor";
+#endif
// Parses the cpuinfo file for string representing the model name.
void os::get_summary_cpu_info(char* cpuinfo, size_t length) {
@@ -2248,9 +2252,25 @@
}
// cpuinfo not found or parsing failed, just print generic string. The entire
// /proc/cpuinfo file will be printed later in the file (or enough of it for x86)
- strncpy(cpuinfo, IA32_ONLY("x86_32") AMD64_ONLY("x86_32")
- IA64_ONLY("IA64") SPARC_ONLY("sparcv9")
- ARM32_ONLY("ARM") PPC_ONLY("PPC64") AARCH64_ONLY("AArch64"), length);
+#if defined(AMD64)
+ strncpy(cpuinfo, "x86_64", length);
+#elif defined(IA32)
+ strncpy(cpuinfo, "x86_32", length);
+#elif defined(IA64)
+ strncpy(cpuinfo, "IA64", length);
+#elif defined(SPARC)
+ strncpy(cpuinfo, "sparcv9", length);
+#elif defined(AARCH64)
+ strncpy(cpuinfo, "AArch64", length);
+#elif defined(ARM)
+ strncpy(cpuinfo, "ARM", length);
+#elif defined(PPC)
+ strncpy(cpuinfo, "PPC64", length);
+#elif defined(ZERO_LIBARCH)
+ strncpy(cpuinfo, ZERO_LIBARCH, length);
+#else
+ strncpy(cpuinfo, "unknown", length);
+#endif
}
void os::print_siginfo(outputStream* st, void* siginfo) {
--- a/hotspot/src/os/windows/vm/os_windows.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/os/windows/vm/os_windows.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -4877,6 +4877,26 @@
// Returns true=success, otherwise false.
bool os::pd_unmap_memory(char* addr, size_t bytes) {
+ MEMORY_BASIC_INFORMATION mem_info;
+ if (VirtualQuery(addr, &mem_info, sizeof(mem_info)) == 0) {
+ if (PrintMiscellaneous && Verbose) {
+ DWORD err = GetLastError();
+ tty->print_cr("VirtualQuery() failed: GetLastError->%ld.", err);
+ }
+ return false;
+ }
+
+ // Executable memory was not mapped using CreateFileMapping/MapViewOfFileEx.
+ // Instead, executable region was allocated using VirtualAlloc(). See
+ // pd_map_memory() above.
+ //
+ // The following flags should match the 'exec_access' flages used for
+ // VirtualProtect() in pd_map_memory().
+ if (mem_info.Protect == PAGE_EXECUTE_READ ||
+ mem_info.Protect == PAGE_EXECUTE_READWRITE) {
+ return pd_release_memory(addr, bytes);
+ }
+
BOOL result = UnmapViewOfFile(addr);
if (result == 0) {
if (PrintMiscellaneous && Verbose) {
--- a/hotspot/src/share/vm/adlc/formssel.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/share/vm/adlc/formssel.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -4143,6 +4143,7 @@
"SubVB","SubVS","SubVI","SubVL","SubVF","SubVD",
"MulVS","MulVI","MulVL","MulVF","MulVD",
"DivVF","DivVD",
+ "SqrtVD",
"AndV" ,"XorV" ,"OrV",
"AddReductionVI", "AddReductionVL",
"AddReductionVF", "AddReductionVD",
--- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -304,8 +304,7 @@
void ConcurrentMarkSweepGeneration::initialize_performance_counters() {
const char* gen_name = "old";
- GenCollectorPolicy* gcp = (GenCollectorPolicy*) GenCollectedHeap::heap()->collector_policy();
-
+ GenCollectorPolicy* gcp = GenCollectedHeap::heap()->gen_policy();
// Generation Counters - generation 1, 1 subspace
_gen_counters = new GenerationCounters(gen_name, 1, 1,
gcp->min_old_size(), gcp->max_old_size(), &_virtual_space);
--- a/hotspot/src/share/vm/gc/g1/collectionSetChooser.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/collectionSetChooser.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -83,7 +83,7 @@
_regions((ResourceObj::set_allocation_type((address) &_regions,
ResourceObj::C_HEAP),
100), true /* C_Heap */),
- _curr_index(0), _length(0), _first_par_unreserved_idx(0),
+ _front(0), _end(0), _first_par_unreserved_idx(0),
_region_live_threshold_bytes(0), _remaining_reclaimable_bytes(0) {
_region_live_threshold_bytes =
HeapRegion::GrainBytes * (size_t) G1MixedGCLiveThresholdPercent / 100;
@@ -91,19 +91,19 @@
#ifndef PRODUCT
void CollectionSetChooser::verify() {
- guarantee(_length <= regions_length(),
- err_msg("_length: %u regions length: %u", _length, regions_length()));
- guarantee(_curr_index <= _length,
- err_msg("_curr_index: %u _length: %u", _curr_index, _length));
+ guarantee(_end <= regions_length(),
+ err_msg("_end: %u regions length: %u", _end, regions_length()));
+ guarantee(_front <= _end,
+ err_msg("_front: %u _end: %u", _front, _end));
uint index = 0;
size_t sum_of_reclaimable_bytes = 0;
- while (index < _curr_index) {
+ while (index < _front) {
guarantee(regions_at(index) == NULL,
- "all entries before _curr_index should be NULL");
+ "all entries before _front should be NULL");
index += 1;
}
HeapRegion *prev = NULL;
- while (index < _length) {
+ while (index < _end) {
HeapRegion *curr = regions_at(index++);
guarantee(curr != NULL, "Regions in _regions array cannot be NULL");
guarantee(!curr->is_young(), "should not be young!");
@@ -132,15 +132,15 @@
regions_trunc_to(_first_par_unreserved_idx);
}
_regions.sort(order_regions);
- assert(_length <= regions_length(), "Requirement");
+ assert(_end <= regions_length(), "Requirement");
#ifdef ASSERT
- for (uint i = 0; i < _length; i++) {
+ for (uint i = 0; i < _end; i++) {
assert(regions_at(i) != NULL, "Should be true by sorting!");
}
#endif // ASSERT
if (G1PrintRegionLivenessInfo) {
G1PrintRegionLivenessInfoClosure cl(gclog_or_tty, "Post-Sorting");
- for (uint i = 0; i < _length; ++i) {
+ for (uint i = 0; i < _end; ++i) {
HeapRegion* r = regions_at(i);
cl.doHeapRegion(r);
}
@@ -154,11 +154,19 @@
err_msg("Pinned region shouldn't be added to the collection set (index %u)", hr->hrm_index()));
assert(!hr->is_young(), "should not be young!");
_regions.append(hr);
- _length++;
+ _end++;
_remaining_reclaimable_bytes += hr->reclaimable_bytes();
hr->calc_gc_efficiency();
}
+void CollectionSetChooser::push(HeapRegion* hr) {
+ assert(hr != NULL, "Can't put back a NULL region");
+ assert(_front >= 1, "Too many regions have been put back");
+ _front--;
+ regions_at_put(_front, hr);
+ _remaining_reclaimable_bytes += hr->reclaimable_bytes();
+}
+
void CollectionSetChooser::prepare_for_par_region_addition(uint n_threads,
uint n_regions,
uint chunk_size) {
@@ -193,7 +201,7 @@
// We could have just used atomics instead of taking the
// lock. However, we currently don't have an atomic add for size_t.
MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag);
- _length += region_num;
+ _end += region_num;
_remaining_reclaimable_bytes += reclaimable_bytes;
} else {
assert(reclaimable_bytes == 0, "invariant");
@@ -202,7 +210,7 @@
void CollectionSetChooser::clear() {
_regions.clear();
- _curr_index = 0;
- _length = 0;
+ _front = 0;
+ _end = 0;
_remaining_reclaimable_bytes = 0;
};
--- a/hotspot/src/share/vm/gc/g1/collectionSetChooser.hpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/collectionSetChooser.hpp Wed Jul 05 20:51:27 2017 +0200
@@ -48,12 +48,10 @@
// The index of the next candidate old region to be considered for
// addition to the CSet.
- uint _curr_index;
+ uint _front;
- // The number of candidate old regions added to the CSet chooser.
- // Note: this is not updated when removing a region using
- // remove_and_move_to_next() below.
- uint _length;
+ // The index of the last candidate old region
+ uint _end;
// Keeps track of the start of the next array chunk to be claimed by
// parallel GC workers.
@@ -73,31 +71,33 @@
// collection without removing it from the CSet chooser.
HeapRegion* peek() {
HeapRegion* res = NULL;
- if (_curr_index < _length) {
- res = regions_at(_curr_index);
+ if (_front < _end) {
+ res = regions_at(_front);
assert(res != NULL,
err_msg("Unexpected NULL hr in _regions at index %u",
- _curr_index));
+ _front));
}
return res;
}
// Remove the given region from the CSet chooser and move to the
- // next one. The given region should be the current candidate region
- // in the CSet chooser.
- void remove_and_move_to_next(HeapRegion* hr) {
+ // next one.
+ HeapRegion* pop() {
+ HeapRegion* hr = regions_at(_front);
assert(hr != NULL, "pre-condition");
- assert(_curr_index < _length, "pre-condition");
- assert(regions_at(_curr_index) == hr, "pre-condition");
- regions_at_put(_curr_index, NULL);
+ assert(_front < _end, "pre-condition");
+ regions_at_put(_front, NULL);
assert(hr->reclaimable_bytes() <= _remaining_reclaimable_bytes,
err_msg("remaining reclaimable bytes inconsistent "
"from region: " SIZE_FORMAT " remaining: " SIZE_FORMAT,
hr->reclaimable_bytes(), _remaining_reclaimable_bytes));
_remaining_reclaimable_bytes -= hr->reclaimable_bytes();
- _curr_index += 1;
+ _front += 1;
+ return hr;
}
+ void push(HeapRegion* hr);
+
CollectionSetChooser();
void sort_regions();
@@ -113,7 +113,7 @@
}
// Returns the number candidate old regions added
- uint length() { return _length; }
+ uint length() { return _end; }
// Serial version.
void add_region(HeapRegion *hr);
@@ -135,7 +135,7 @@
void clear();
// Return the number of candidate regions that remain to be collected.
- uint remaining_regions() { return _length - _curr_index; }
+ uint remaining_regions() { return _end - _front; }
// Determine whether the CSet chooser has more candidate regions or not.
bool is_empty() { return remaining_regions() == 0; }
--- a/hotspot/src/share/vm/gc/g1/concurrentG1Refine.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/concurrentG1Refine.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -29,7 +29,7 @@
#include "gc/g1/g1HotCardCache.hpp"
#include "runtime/java.hpp"
-ConcurrentG1Refine::ConcurrentG1Refine(G1CollectedHeap* g1h, CardTableEntryClosure* refine_closure) :
+ConcurrentG1Refine::ConcurrentG1Refine(G1CollectedHeap* g1h) :
_threads(NULL), _n_threads(0),
_hot_card_cache(g1h)
{
@@ -48,29 +48,46 @@
FLAG_SET_DEFAULT(G1ConcRefinementRedZone, yellow_zone() * 2);
}
set_red_zone(MAX2<int>(G1ConcRefinementRedZone, yellow_zone()));
+}
- _n_worker_threads = thread_num();
+ConcurrentG1Refine* ConcurrentG1Refine::create(G1CollectedHeap* g1h, CardTableEntryClosure* refine_closure, jint* ecode) {
+ ConcurrentG1Refine* cg1r = new ConcurrentG1Refine(g1h);
+ if (cg1r == NULL) {
+ *ecode = JNI_ENOMEM;
+ vm_shutdown_during_initialization("Could not create ConcurrentG1Refine");
+ return NULL;
+ }
+ cg1r->_n_worker_threads = thread_num();
// We need one extra thread to do the young gen rset size sampling.
- _n_threads = _n_worker_threads + 1;
+ cg1r->_n_threads = cg1r->_n_worker_threads + 1;
+
+ cg1r->reset_threshold_step();
- reset_threshold_step();
-
- _threads = NEW_C_HEAP_ARRAY(ConcurrentG1RefineThread*, _n_threads, mtGC);
+ cg1r->_threads = NEW_C_HEAP_ARRAY_RETURN_NULL(ConcurrentG1RefineThread*, cg1r->_n_threads, mtGC);
+ if (cg1r->_threads == NULL) {
+ *ecode = JNI_ENOMEM;
+ vm_shutdown_during_initialization("Could not allocate an array for ConcurrentG1RefineThread");
+ return NULL;
+ }
uint worker_id_offset = DirtyCardQueueSet::num_par_ids();
ConcurrentG1RefineThread *next = NULL;
- for (uint i = _n_threads - 1; i != UINT_MAX; i--) {
- ConcurrentG1RefineThread* t = new ConcurrentG1RefineThread(this, next, refine_closure, worker_id_offset, i);
+ for (uint i = cg1r->_n_threads - 1; i != UINT_MAX; i--) {
+ ConcurrentG1RefineThread* t = new ConcurrentG1RefineThread(cg1r, next, refine_closure, worker_id_offset, i);
assert(t != NULL, "Conc refine should have been created");
if (t->osthread() == NULL) {
- vm_shutdown_during_initialization("Could not create ConcurrentG1RefineThread");
+ *ecode = JNI_ENOMEM;
+ vm_shutdown_during_initialization("Could not create ConcurrentG1RefineThread");
+ return NULL;
}
- assert(t->cg1r() == this, "Conc refine thread should refer to this");
- _threads[i] = t;
+ assert(t->cg1r() == cg1r, "Conc refine thread should refer to this");
+ cg1r->_threads[i] = t;
next = t;
}
+ *ecode = JNI_OK;
+ return cg1r;
}
void ConcurrentG1Refine::reset_threshold_step() {
--- a/hotspot/src/share/vm/gc/g1/concurrentG1Refine.hpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/concurrentG1Refine.hpp Wed Jul 05 20:51:27 2017 +0200
@@ -71,10 +71,15 @@
// Reset the threshold step value based of the current zone boundaries.
void reset_threshold_step();
+ ConcurrentG1Refine(G1CollectedHeap* g1h);
+
public:
- ConcurrentG1Refine(G1CollectedHeap* g1h, CardTableEntryClosure* refine_closure);
~ConcurrentG1Refine();
+ // Returns ConcurrentG1Refine instance if succeeded to create/initialize ConcurrentG1Refine and ConcurrentG1RefineThread.
+ // Otherwise, returns NULL with error code.
+ static ConcurrentG1Refine* create(G1CollectedHeap* g1h, CardTableEntryClosure* refine_closure, jint* ecode);
+
void init(G1RegionToSpaceMapper* card_counts_storage);
void stop();
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -2025,7 +2025,6 @@
_survivor_evac_stats(YoungPLABSize, PLABWeight),
_old_evac_stats(OldPLABSize, PLABWeight),
_expand_heap_after_alloc_failure(true),
- _surviving_young_words(NULL),
_old_marking_cycles_started(0),
_old_marking_cycles_completed(0),
_heap_summary_sent(false),
@@ -2126,7 +2125,11 @@
_refine_cte_cl = new RefineCardTableEntryClosure();
- _cg1r = new ConcurrentG1Refine(this, _refine_cte_cl);
+ jint ecode = JNI_OK;
+ _cg1r = ConcurrentG1Refine::create(this, _refine_cte_cl, &ecode);
+ if (_cg1r == NULL) {
+ return ecode;
+ }
// Reserve the maximum.
@@ -2397,6 +2400,10 @@
// (for efficiency/performance)
}
+CollectorPolicy* G1CollectedHeap::collector_policy() const {
+ return g1_policy();
+}
+
size_t G1CollectedHeap::capacity() const {
return _hrm.length() * HeapRegion::GrainBytes;
}
@@ -3694,10 +3701,6 @@
return (buffer_size * buffer_num + extra_cards) / oopSize;
}
-size_t G1CollectedHeap::cards_scanned() {
- return g1_rem_set()->cardsScanned();
-}
-
class RegisterHumongousWithInCSetFastTestClosure : public HeapRegionClosure {
private:
size_t _total_humongous;
@@ -3838,36 +3841,6 @@
cl.flush_rem_set_entries();
}
-void G1CollectedHeap::setup_surviving_young_words() {
- assert(_surviving_young_words == NULL, "pre-condition");
- uint array_length = g1_policy()->young_cset_region_length();
- _surviving_young_words = NEW_C_HEAP_ARRAY(size_t, (size_t) array_length, mtGC);
- if (_surviving_young_words == NULL) {
- vm_exit_out_of_memory(sizeof(size_t) * array_length, OOM_MALLOC_ERROR,
- "Not enough space for young surv words summary.");
- }
- memset(_surviving_young_words, 0, (size_t) array_length * sizeof(size_t));
-#ifdef ASSERT
- for (uint i = 0; i < array_length; ++i) {
- assert( _surviving_young_words[i] == 0, "memset above" );
- }
-#endif // !ASSERT
-}
-
-void G1CollectedHeap::update_surviving_young_words(size_t* surv_young_words) {
- assert_at_safepoint(true);
- uint array_length = g1_policy()->young_cset_region_length();
- for (uint i = 0; i < array_length; ++i) {
- _surviving_young_words[i] += surv_young_words[i];
- }
-}
-
-void G1CollectedHeap::cleanup_surviving_young_words() {
- guarantee( _surviving_young_words != NULL, "pre-condition" );
- FREE_C_HEAP_ARRAY(size_t, _surviving_young_words);
- _surviving_young_words = NULL;
-}
-
#ifdef ASSERT
class VerifyCSetClosure: public HeapRegionClosure {
public:
@@ -4129,7 +4102,8 @@
g1_policy()->print_collection_set(g1_policy()->inc_cset_head(), gclog_or_tty);
#endif // YOUNG_LIST_VERBOSE
- g1_policy()->finalize_cset(target_pause_time_ms);
+ double time_remaining_ms = g1_policy()->finalize_young_cset_part(target_pause_time_ms);
+ g1_policy()->finalize_old_cset_part(time_remaining_ms);
evacuation_info.set_collectionset_regions(g1_policy()->cset_region_length());
@@ -4155,22 +4129,20 @@
collection_set_iterate(&cl);
#endif // ASSERT
- setup_surviving_young_words();
-
// Initialize the GC alloc regions.
_allocator->init_gc_alloc_regions(evacuation_info);
+ G1ParScanThreadStateSet per_thread_states(this, workers()->active_workers(), g1_policy()->young_cset_region_length());
// Actually do the work...
- evacuate_collection_set(evacuation_info);
-
- free_collection_set(g1_policy()->collection_set(), evacuation_info);
+ evacuate_collection_set(evacuation_info, &per_thread_states);
+
+ const size_t* surviving_young_words = per_thread_states.surviving_young_words();
+ free_collection_set(g1_policy()->collection_set(), evacuation_info, surviving_young_words);
eagerly_reclaim_humongous_regions();
g1_policy()->clear_collection_set();
- cleanup_surviving_young_words();
-
// Start a new incremental collection set for the next pause.
g1_policy()->start_incremental_cset_building();
@@ -4255,7 +4227,8 @@
// investigate this in CR 7178365.
double sample_end_time_sec = os::elapsedTime();
double pause_time_ms = (sample_end_time_sec - sample_start_time_sec) * MILLIUNITS;
- g1_policy()->record_collection_pause_end(pause_time_ms);
+ size_t total_cards_scanned = per_thread_states.total_cards_scanned();
+ g1_policy()->record_collection_pause_end(pause_time_ms, total_cards_scanned);
evacuation_info.set_collectionset_used_before(g1_policy()->collection_set_bytes_used_before());
evacuation_info.set_bytes_copied(g1_policy()->bytes_copied_during_gc());
@@ -4541,15 +4514,15 @@
class G1ParTask : public AbstractGangTask {
protected:
- G1CollectedHeap* _g1h;
- G1ParScanThreadState** _pss;
- RefToScanQueueSet* _queues;
- G1RootProcessor* _root_processor;
- ParallelTaskTerminator _terminator;
- uint _n_workers;
+ G1CollectedHeap* _g1h;
+ G1ParScanThreadStateSet* _pss;
+ RefToScanQueueSet* _queues;
+ G1RootProcessor* _root_processor;
+ ParallelTaskTerminator _terminator;
+ uint _n_workers;
public:
- G1ParTask(G1CollectedHeap* g1h, G1ParScanThreadState** per_thread_states, RefToScanQueueSet *task_queues, G1RootProcessor* root_processor, uint n_workers)
+ G1ParTask(G1CollectedHeap* g1h, G1ParScanThreadStateSet* per_thread_states, RefToScanQueueSet *task_queues, G1RootProcessor* root_processor, uint n_workers)
: AbstractGangTask("G1 collection"),
_g1h(g1h),
_pss(per_thread_states),
@@ -4607,7 +4580,7 @@
ReferenceProcessor* rp = _g1h->ref_processor_stw();
- G1ParScanThreadState* pss = _pss[worker_id];
+ G1ParScanThreadState* pss = _pss->state_for_worker(worker_id);
pss->set_ref_processor(rp);
bool only_young = _g1h->collector_state()->gcs_are_young();
@@ -4664,9 +4637,12 @@
worker_id);
G1ParPushHeapRSClosure push_heap_rs_cl(_g1h, pss);
- _g1h->g1_rem_set()->oops_into_collection_set_do(&push_heap_rs_cl,
- weak_root_cl,
- worker_id);
+ size_t cards_scanned = _g1h->g1_rem_set()->oops_into_collection_set_do(&push_heap_rs_cl,
+ weak_root_cl,
+ worker_id);
+
+ _pss->add_cards_scanned(worker_id, cards_scanned);
+
double strong_roots_sec = os::elapsedTime() - start_strong_roots_sec;
double term_sec = 0.0;
@@ -5263,15 +5239,15 @@
class G1STWRefProcTaskExecutor: public AbstractRefProcTaskExecutor {
private:
- G1CollectedHeap* _g1h;
- G1ParScanThreadState** _pss;
- RefToScanQueueSet* _queues;
- WorkGang* _workers;
- uint _active_workers;
+ G1CollectedHeap* _g1h;
+ G1ParScanThreadStateSet* _pss;
+ RefToScanQueueSet* _queues;
+ WorkGang* _workers;
+ uint _active_workers;
public:
G1STWRefProcTaskExecutor(G1CollectedHeap* g1h,
- G1ParScanThreadState** per_thread_states,
+ G1ParScanThreadStateSet* per_thread_states,
WorkGang* workers,
RefToScanQueueSet *task_queues,
uint n_workers) :
@@ -5295,14 +5271,14 @@
typedef AbstractRefProcTaskExecutor::ProcessTask ProcessTask;
ProcessTask& _proc_task;
G1CollectedHeap* _g1h;
- G1ParScanThreadState** _pss;
+ G1ParScanThreadStateSet* _pss;
RefToScanQueueSet* _task_queues;
ParallelTaskTerminator* _terminator;
public:
G1STWRefProcTaskProxy(ProcessTask& proc_task,
G1CollectedHeap* g1h,
- G1ParScanThreadState** per_thread_states,
+ G1ParScanThreadStateSet* per_thread_states,
RefToScanQueueSet *task_queues,
ParallelTaskTerminator* terminator) :
AbstractGangTask("Process reference objects in parallel"),
@@ -5320,7 +5296,7 @@
G1STWIsAliveClosure is_alive(_g1h);
- G1ParScanThreadState* pss = _pss[worker_id];
+ G1ParScanThreadState* pss = _pss->state_for_worker(worker_id);
pss->set_ref_processor(NULL);
G1ParScanExtRootClosure only_copy_non_heap_cl(_g1h, pss);
@@ -5399,14 +5375,14 @@
class G1ParPreserveCMReferentsTask: public AbstractGangTask {
protected:
- G1CollectedHeap* _g1h;
- G1ParScanThreadState** _pss;
- RefToScanQueueSet* _queues;
- ParallelTaskTerminator _terminator;
- uint _n_workers;
+ G1CollectedHeap* _g1h;
+ G1ParScanThreadStateSet* _pss;
+ RefToScanQueueSet* _queues;
+ ParallelTaskTerminator _terminator;
+ uint _n_workers;
public:
- G1ParPreserveCMReferentsTask(G1CollectedHeap* g1h, G1ParScanThreadState** per_thread_states, int workers, RefToScanQueueSet *task_queues) :
+ G1ParPreserveCMReferentsTask(G1CollectedHeap* g1h, G1ParScanThreadStateSet* per_thread_states, int workers, RefToScanQueueSet *task_queues) :
AbstractGangTask("ParPreserveCMReferents"),
_g1h(g1h),
_pss(per_thread_states),
@@ -5419,7 +5395,7 @@
ResourceMark rm;
HandleMark hm;
- G1ParScanThreadState* pss = _pss[worker_id];
+ G1ParScanThreadState* pss = _pss->state_for_worker(worker_id);
pss->set_ref_processor(NULL);
assert(pss->queue_is_empty(), "both queue and overflow should be empty");
@@ -5480,7 +5456,7 @@
};
// Weak Reference processing during an evacuation pause (part 1).
-void G1CollectedHeap::process_discovered_references(G1ParScanThreadState** per_thread_states) {
+void G1CollectedHeap::process_discovered_references(G1ParScanThreadStateSet* per_thread_states) {
double ref_proc_start = os::elapsedTime();
ReferenceProcessor* rp = _ref_processor_stw;
@@ -5525,7 +5501,7 @@
// JNI refs.
// Use only a single queue for this PSS.
- G1ParScanThreadState* pss = per_thread_states[0];
+ G1ParScanThreadState* pss = per_thread_states->state_for_worker(0);
pss->set_ref_processor(NULL);
assert(pss->queue_is_empty(), "pre-condition");
@@ -5586,7 +5562,7 @@
}
// Weak Reference processing during an evacuation pause (part 2).
-void G1CollectedHeap::enqueue_discovered_references(G1ParScanThreadState** per_thread_states) {
+void G1CollectedHeap::enqueue_discovered_references(G1ParScanThreadStateSet* per_thread_states) {
double ref_enq_start = os::elapsedTime();
ReferenceProcessor* rp = _ref_processor_stw;
@@ -5621,7 +5597,7 @@
g1_policy()->phase_times()->record_ref_enq_time(ref_enq_time * 1000.0);
}
-void G1CollectedHeap::evacuate_collection_set(EvacuationInfo& evacuation_info) {
+void G1CollectedHeap::evacuate_collection_set(EvacuationInfo& evacuation_info, G1ParScanThreadStateSet* per_thread_states) {
_expand_heap_after_alloc_failure = true;
_evacuation_failed = false;
@@ -5641,11 +5617,6 @@
double start_par_time_sec = os::elapsedTime();
double end_par_time_sec;
- G1ParScanThreadState** per_thread_states = NEW_C_HEAP_ARRAY(G1ParScanThreadState*, n_workers, mtGC);
- for (uint i = 0; i < n_workers; i++) {
- per_thread_states[i] = new_par_scan_state(i);
- }
-
{
G1RootProcessor root_processor(this, n_workers);
G1ParTask g1_par_task(this, per_thread_states, _task_queues, &root_processor, n_workers);
@@ -5699,11 +5670,7 @@
_allocator->release_gc_alloc_regions(evacuation_info);
g1_rem_set()->cleanup_after_oops_into_collection_set_do();
- for (uint i = 0; i < n_workers; i++) {
- G1ParScanThreadState* pss = per_thread_states[i];
- delete pss;
- }
- FREE_C_HEAP_ARRAY(G1ParScanThreadState*, per_thread_states);
+ per_thread_states->flush();
record_obj_copy_mem_stats();
@@ -6054,7 +6021,7 @@
g1_policy()->phase_times()->record_clear_ct_time(elapsed * 1000.0);
}
-void G1CollectedHeap::free_collection_set(HeapRegion* cs_head, EvacuationInfo& evacuation_info) {
+void G1CollectedHeap::free_collection_set(HeapRegion* cs_head, EvacuationInfo& evacuation_info, const size_t* surviving_young_words) {
size_t pre_used = 0;
FreeRegionList local_free_list("Local List for CSet Freeing");
@@ -6108,7 +6075,7 @@
int index = cur->young_index_in_cset();
assert(index != -1, "invariant");
assert((uint) index < policy->young_cset_region_length(), "invariant");
- size_t words_survived = _surviving_young_words[index];
+ size_t words_survived = surviving_young_words[index];
cur->record_surv_words_in_group(words_survived);
// At this point the we have 'popped' cur from the collection set
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp Wed Jul 05 20:51:27 2017 +0200
@@ -56,6 +56,7 @@
class GenerationSpec;
class OopsInHeapRegionClosure;
class G1ParScanThreadState;
+class G1ParScanThreadStateSet;
class G1KlassScanClosure;
class G1ParScanThreadState;
class ObjectClosure;
@@ -192,6 +193,7 @@
// Closures used in implementation.
friend class G1ParScanThreadState;
+ friend class G1ParScanThreadStateSet;
friend class G1ParTask;
friend class G1PLABAllocator;
friend class G1PrepareCompactClosure;
@@ -309,14 +311,8 @@
volatile unsigned _gc_time_stamp;
- size_t* _surviving_young_words;
-
G1HRPrinter _hr_printer;
- void setup_surviving_young_words();
- void update_surviving_young_words(size_t* surv_young_words);
- void cleanup_surviving_young_words();
-
// It decides whether an explicit GC should start a concurrent cycle
// instead of doing a STW GC. Currently, a concurrent cycle is
// explicitly started if:
@@ -584,11 +580,11 @@
// Process any reference objects discovered during
// an incremental evacuation pause.
- void process_discovered_references(G1ParScanThreadState** per_thread_states);
+ void process_discovered_references(G1ParScanThreadStateSet* per_thread_states);
// Enqueue any remaining discovered references
// after processing.
- void enqueue_discovered_references(G1ParScanThreadState** per_thread_states);
+ void enqueue_discovered_references(G1ParScanThreadStateSet* per_thread_states);
public:
WorkGang* workers() const { return _workers; }
@@ -683,9 +679,6 @@
// Allocates a new heap region instance.
HeapRegion* new_heap_region(uint hrs_index, MemRegion mr);
- // Allocates a new per thread par scan state for the given thread id.
- G1ParScanThreadState* new_par_scan_state(uint worker_id);
-
// Allocate the highest free region in the reserved heap. This will commit
// regions as necessary.
HeapRegion* alloc_highest_free_region();
@@ -799,7 +792,7 @@
bool do_collection_pause_at_safepoint(double target_pause_time_ms);
// Actually do the work of evacuating the collection set.
- void evacuate_collection_set(EvacuationInfo& evacuation_info);
+ void evacuate_collection_set(EvacuationInfo& evacuation_info, G1ParScanThreadStateSet* per_thread_states);
// Print the header for the per-thread termination statistics.
static void print_termination_stats_hdr(outputStream* const st);
@@ -833,7 +826,7 @@
// After a collection pause, make the regions in the CS into free
// regions.
- void free_collection_set(HeapRegion* cs_head, EvacuationInfo& evacuation_info);
+ void free_collection_set(HeapRegion* cs_head, EvacuationInfo& evacuation_info, const size_t* surviving_young_words);
// Abandon the current collection set without recording policy
// statistics or updating free lists.
@@ -1057,7 +1050,7 @@
// The current policy object for the collector.
G1CollectorPolicy* g1_policy() const { return _g1_policy; }
- virtual CollectorPolicy* collector_policy() const { return (CollectorPolicy*) g1_policy(); }
+ virtual CollectorPolicy* collector_policy() const;
// Adaptive size policy. No such thing for g1.
virtual AdaptiveSizePolicy* size_policy() { return NULL; }
@@ -1610,7 +1603,6 @@
public:
size_t pending_card_num();
- size_t cards_scanned();
protected:
size_t _max_heap_capacity;
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap_ext.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap_ext.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -38,7 +38,3 @@
MemRegion mr) {
return new HeapRegion(hrs_index, bot_shared(), mr);
}
-
-G1ParScanThreadState* G1CollectedHeap::new_par_scan_state(uint worker_id) {
- return new G1ParScanThreadState(this, worker_id);
-}
--- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -923,7 +923,7 @@
// Anything below that is considered to be zero
#define MIN_TIMER_GRANULARITY 0.0000001
-void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms) {
+void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms, size_t cards_scanned) {
double end_time_sec = os::elapsedTime();
assert(_cur_collection_pause_used_regions_at_start >= cset_region_length(),
"otherwise, the subtraction below does not make sense");
@@ -1052,8 +1052,6 @@
_cost_per_card_ms_seq->add(cost_per_card_ms);
}
- size_t cards_scanned = _g1->cards_scanned();
-
double cost_per_entry_ms = 0.0;
if (cards_scanned > 10) {
cost_per_entry_ms = phase_times()->average_time_ms(G1GCPhaseTimes::ScanRS) / (double) cards_scanned;
@@ -1871,7 +1869,7 @@
}
-void G1CollectorPolicy::finalize_cset(double target_pause_time_ms) {
+double G1CollectorPolicy::finalize_young_cset_part(double target_pause_time_ms) {
double young_start_time_sec = os::elapsedTime();
YoungList* young_list = _g1->young_list();
@@ -1883,7 +1881,6 @@
guarantee(_collection_set == NULL, "Precondition");
double base_time_ms = predict_base_elapsed_time_ms(_pending_cards);
- double predicted_pause_time_ms = base_time_ms;
double time_remaining_ms = MAX2(target_pause_time_ms - base_time_ms, 0.0);
ergo_verbose4(ErgoCSetConstruction | ErgoHigh,
@@ -1927,15 +1924,16 @@
_collection_set = _inc_cset_head;
_collection_set_bytes_used_before = _inc_cset_bytes_used_before;
time_remaining_ms = MAX2(time_remaining_ms - _inc_cset_predicted_elapsed_time_ms, 0.0);
- predicted_pause_time_ms += _inc_cset_predicted_elapsed_time_ms;
- ergo_verbose3(ErgoCSetConstruction | ErgoHigh,
+ ergo_verbose4(ErgoCSetConstruction | ErgoHigh,
"add young regions to CSet",
ergo_format_region("eden")
ergo_format_region("survivors")
- ergo_format_ms("predicted young region time"),
+ ergo_format_ms("predicted young region time")
+ ergo_format_ms("target pause time"),
eden_region_length, survivor_region_length,
- _inc_cset_predicted_elapsed_time_ms);
+ _inc_cset_predicted_elapsed_time_ms,
+ target_pause_time_ms);
// The number of recorded young regions is the incremental
// collection set's current size
@@ -1944,8 +1942,13 @@
double young_end_time_sec = os::elapsedTime();
phase_times()->record_young_cset_choice_time_ms((young_end_time_sec - young_start_time_sec) * 1000.0);
- // Set the start of the non-young choice time.
- double non_young_start_time_sec = young_end_time_sec;
+ return time_remaining_ms;
+}
+
+void G1CollectorPolicy::finalize_old_cset_part(double time_remaining_ms) {
+ double non_young_start_time_sec = os::elapsedTime();
+ double predicted_old_time_ms = 0.0;
+
if (!collector_state()->gcs_are_young()) {
CollectionSetChooser* cset_chooser = _collectionSetChooser;
@@ -2033,8 +2036,8 @@
// We will add this region to the CSet.
time_remaining_ms = MAX2(time_remaining_ms - predicted_time_ms, 0.0);
- predicted_pause_time_ms += predicted_time_ms;
- cset_chooser->remove_and_move_to_next(hr);
+ predicted_old_time_ms += predicted_time_ms;
+ cset_chooser->pop(); // already have region via peek()
_g1->old_set_remove(hr);
add_old_region_to_cset(hr);
@@ -2068,16 +2071,13 @@
stop_incremental_cset_building();
- ergo_verbose5(ErgoCSetConstruction,
+ ergo_verbose3(ErgoCSetConstruction,
"finish choosing CSet",
- ergo_format_region("eden")
- ergo_format_region("survivors")
ergo_format_region("old")
- ergo_format_ms("predicted pause time")
- ergo_format_ms("target pause time"),
- eden_region_length, survivor_region_length,
+ ergo_format_ms("predicted old region time")
+ ergo_format_ms("time remaining"),
old_cset_region_length(),
- predicted_pause_time_ms, target_pause_time_ms);
+ predicted_old_time_ms, time_remaining_ms);
double non_young_end_time_sec = os::elapsedTime();
phase_times()->record_non_young_cset_choice_time_ms((non_young_end_time_sec - non_young_start_time_sec) * 1000.0);
--- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp Wed Jul 05 20:51:27 2017 +0200
@@ -473,7 +473,7 @@
// The number of bytes in the collection set before the pause. Set from
// the incrementally built collection set at the start of an evacuation
- // pause, and incremented in finalize_cset() when adding old regions
+ // pause, and incremented in finalize_old_cset_part() when adding old regions
// (if any) to the collection set.
size_t _collection_set_bytes_used_before;
@@ -634,7 +634,7 @@
// Record the start and end of an evacuation pause.
void record_collection_pause_start(double start_time_sec);
- void record_collection_pause_end(double pause_time_ms);
+ void record_collection_pause_end(double pause_time_ms, size_t cards_scanned);
// Record the start and end of a full collection.
void record_full_collection_start();
@@ -689,7 +689,8 @@
// Choose a new collection set. Marks the chosen regions as being
// "in_collection_set", and links them together. The head and number of
// the collection set are available via access methods.
- void finalize_cset(double target_pause_time_ms);
+ double finalize_young_cset_part(double target_pause_time_ms);
+ virtual void finalize_old_cset_part(double time_remaining_ms);
// The head of the list (via "next_in_collection_set()") representing the
// current collection set.
@@ -865,8 +866,8 @@
return _recorded_survivor_regions;
}
- void record_thread_age_table(ageTable* age_table) {
- _survivors_age_table.merge_par(age_table);
+ void record_age_table(ageTable* age_table) {
+ _survivors_age_table.merge(age_table);
}
void update_max_gc_locker_expansion();
--- a/hotspot/src/share/vm/gc/g1/g1EvacStats.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1EvacStats.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -46,11 +46,11 @@
if (_allocated == 0) {
assert((_unused == 0),
err_msg("Inconsistency in PLAB stats: "
- "_allocated: "SIZE_FORMAT", "
- "_wasted: "SIZE_FORMAT", "
- "_region_end_waste: "SIZE_FORMAT", "
- "_unused: "SIZE_FORMAT", "
- "_used : "SIZE_FORMAT,
+ "_allocated: " SIZE_FORMAT ", "
+ "_wasted: " SIZE_FORMAT ", "
+ "_region_end_waste: " SIZE_FORMAT ", "
+ "_unused: " SIZE_FORMAT ", "
+ "_used : " SIZE_FORMAT,
_allocated, _wasted, _region_end_waste, _unused, used()));
_allocated = 1;
}
--- a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -32,7 +32,7 @@
#include "oops/oop.inline.hpp"
#include "runtime/prefetch.inline.hpp"
-G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint worker_id)
+G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint worker_id, size_t young_cset_length)
: _g1h(g1h),
_refs(g1h->task_queue(worker_id)),
_dcq(&g1h->dirty_card_queue_set()),
@@ -51,8 +51,8 @@
// non-young regions (where the age is -1)
// We also add a few elements at the beginning and at the end in
// an attempt to eliminate cache contention
- uint real_length = 1 + _g1h->g1_policy()->young_cset_region_length();
- uint array_length = PADDING_ELEM_NUM +
+ size_t real_length = 1 + young_cset_length;
+ size_t array_length = PADDING_ELEM_NUM +
real_length +
PADDING_ELEM_NUM;
_surviving_young_words_base = NEW_C_HEAP_ARRAY(size_t, array_length, mtGC);
@@ -60,7 +60,7 @@
vm_exit_out_of_memory(array_length * sizeof(size_t), OOM_MALLOC_ERROR,
"Not enough space for young surv histo.");
_surviving_young_words = _surviving_young_words_base + PADDING_ELEM_NUM;
- memset(_surviving_young_words, 0, (size_t) real_length * sizeof(size_t));
+ memset(_surviving_young_words, 0, real_length * sizeof(size_t));
_plab_allocator = G1PLABAllocator::create_allocator(_g1h->allocator());
@@ -71,13 +71,21 @@
_dest[InCSetState::Old] = InCSetState::Old;
}
-G1ParScanThreadState::~G1ParScanThreadState() {
+// Pass locally gathered statistics to global state.
+void G1ParScanThreadState::flush(size_t* surviving_young_words) {
+ _dcq.flush();
// Update allocation statistics.
_plab_allocator->flush_and_retire_stats();
+ _g1h->g1_policy()->record_age_table(&_age_table);
+
+ uint length = _g1h->g1_policy()->young_cset_region_length();
+ for (uint region_index = 0; region_index < length; region_index++) {
+ surviving_young_words[region_index] += _surviving_young_words[region_index];
+ }
+}
+
+G1ParScanThreadState::~G1ParScanThreadState() {
delete _plab_allocator;
- _g1h->g1_policy()->record_thread_age_table(&_age_table);
- // Update heap statistics.
- _g1h->update_surviving_young_words(_surviving_young_words);
FREE_C_HEAP_ARRAY(size_t, _surviving_young_words_base);
}
@@ -314,6 +322,42 @@
}
}
+G1ParScanThreadState* G1ParScanThreadStateSet::state_for_worker(uint worker_id) {
+ assert(worker_id < _n_workers, "out of bounds access");
+ return _states[worker_id];
+}
+
+void G1ParScanThreadStateSet::add_cards_scanned(uint worker_id, size_t cards_scanned) {
+ assert(worker_id < _n_workers, "out of bounds access");
+ _cards_scanned[worker_id] += cards_scanned;
+}
+
+size_t G1ParScanThreadStateSet::total_cards_scanned() const {
+ assert(_flushed, "thread local state from the per thread states should have been flushed");
+ return _total_cards_scanned;
+}
+
+const size_t* G1ParScanThreadStateSet::surviving_young_words() const {
+ assert(_flushed, "thread local state from the per thread states should have been flushed");
+ return _surviving_young_words_total;
+}
+
+void G1ParScanThreadStateSet::flush() {
+ assert(!_flushed, "thread local state from the per thread states should be flushed once");
+ assert(_total_cards_scanned == 0, "should have been cleared");
+
+ for (uint worker_index = 0; worker_index < _n_workers; ++worker_index) {
+ G1ParScanThreadState* pss = _states[worker_index];
+
+ _total_cards_scanned += _cards_scanned[worker_index];
+
+ pss->flush(_surviving_young_words_total);
+ delete pss;
+ _states[worker_index] = NULL;
+ }
+ _flushed = true;
+}
+
oop G1ParScanThreadState::handle_evacuation_failure_par(oop old, markOop m) {
assert(_g1h->obj_in_cs(old),
err_msg("Object " PTR_FORMAT " should be in the CSet", p2i(old)));
--- a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp Wed Jul 05 20:51:27 2017 +0200
@@ -82,7 +82,7 @@
}
public:
- G1ParScanThreadState(G1CollectedHeap* g1h, uint worker_id);
+ G1ParScanThreadState(G1CollectedHeap* g1h, uint worker_id, size_t young_cset_length);
~G1ParScanThreadState();
void set_ref_processor(ReferenceProcessor* rp) { _scanner.set_ref_processor(rp); }
@@ -121,6 +121,8 @@
return _surviving_young_words + 1;
}
+ void flush(size_t* surviving_young_words);
+
private:
#define G1_PARTIAL_ARRAY_MASK 0x2
@@ -189,4 +191,48 @@
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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState_ext.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -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);
+}
--- a/hotspot/src/share/vm/gc/g1/g1RemSet.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1RemSet.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -76,7 +76,6 @@
_ct_bs(ct_bs), _g1p(_g1->g1_policy()),
_cg1r(g1->concurrent_g1_refine()),
_cset_rs_update_cl(NULL),
- _cards_scanned(NULL), _total_cards_scanned(0),
_prev_period_summary()
{
_cset_rs_update_cl = NEW_C_HEAP_ARRAY(G1ParPushHeapRSClosure*, n_workers(), mtGC);
@@ -228,9 +227,9 @@
size_t cards_looked_up() { return _cards;}
};
-void G1RemSet::scanRS(G1ParPushHeapRSClosure* oc,
- OopClosure* non_heap_roots,
- uint worker_i) {
+size_t G1RemSet::scanRS(G1ParPushHeapRSClosure* oc,
+ OopClosure* non_heap_roots,
+ uint worker_i) {
double rs_time_start = os::elapsedTime();
G1CodeBlobClosure code_root_cl(non_heap_roots);
@@ -246,11 +245,10 @@
double scan_rs_time_sec = (os::elapsedTime() - rs_time_start)
- scanRScl.strong_code_root_scan_time_sec();
- assert(_cards_scanned != NULL, "invariant");
- _cards_scanned[worker_i] = scanRScl.cards_done();
-
_g1p->phase_times()->record_time_secs(G1GCPhaseTimes::ScanRS, worker_i, scan_rs_time_sec);
_g1p->phase_times()->record_time_secs(G1GCPhaseTimes::CodeRoots, worker_i, scanRScl.strong_code_root_scan_time_sec());
+
+ return scanRScl.cards_done();
}
// Closure used for updating RSets and recording references that
@@ -298,9 +296,9 @@
HeapRegionRemSet::cleanup();
}
-void G1RemSet::oops_into_collection_set_do(G1ParPushHeapRSClosure* oc,
- OopClosure* non_heap_roots,
- uint worker_i) {
+size_t G1RemSet::oops_into_collection_set_do(G1ParPushHeapRSClosure* oc,
+ OopClosure* non_heap_roots,
+ uint worker_i) {
#if CARD_REPEAT_HISTO
ct_freq_update_histo_and_reset();
#endif
@@ -322,10 +320,11 @@
DirtyCardQueue into_cset_dcq(&_g1->into_cset_dirty_card_queue_set());
updateRS(&into_cset_dcq, worker_i);
- scanRS(oc, non_heap_roots, worker_i);
+ size_t cards_scanned = scanRS(oc, non_heap_roots, worker_i);
// We now clear the cached values of _cset_rs_update_cl for this worker
_cset_rs_update_cl[worker_i] = NULL;
+ return cards_scanned;
}
void G1RemSet::prepare_for_oops_into_collection_set_do() {
@@ -333,23 +332,9 @@
_g1->set_refine_cte_cl_concurrency(false);
DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
dcqs.concatenate_logs();
-
- guarantee( _cards_scanned == NULL, "invariant" );
- _cards_scanned = NEW_C_HEAP_ARRAY(size_t, n_workers(), mtGC);
- for (uint i = 0; i < n_workers(); ++i) {
- _cards_scanned[i] = 0;
- }
- _total_cards_scanned = 0;
}
void G1RemSet::cleanup_after_oops_into_collection_set_do() {
- guarantee( _cards_scanned != NULL, "invariant" );
- _total_cards_scanned = 0;
- for (uint i = 0; i < n_workers(); ++i) {
- _total_cards_scanned += _cards_scanned[i];
- }
- FREE_C_HEAP_ARRAY(size_t, _cards_scanned);
- _cards_scanned = NULL;
// Cleanup after copy
_g1->set_refine_cte_cl_concurrency(true);
// Set all cards back to clean.
--- a/hotspot/src/share/vm/gc/g1/g1RemSet.hpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1RemSet.hpp Wed Jul 05 20:51:27 2017 +0200
@@ -62,9 +62,6 @@
ConcurrentG1Refine* _cg1r;
- size_t* _cards_scanned;
- size_t _total_cards_scanned;
-
// Used for caching the closure that is responsible for scanning
// references into the collection set.
G1ParPushHeapRSClosure** _cset_rs_update_cl;
@@ -94,9 +91,12 @@
// partitioning the work to be done. It should be the same as
// the "i" passed to the calling thread's work(i) function.
// In the sequential case this param will be ignored.
- void oops_into_collection_set_do(G1ParPushHeapRSClosure* blk,
- OopClosure* non_heap_roots,
- uint worker_i);
+ //
+ // Returns the number of cards scanned while looking for pointers
+ // into the collection set.
+ size_t oops_into_collection_set_do(G1ParPushHeapRSClosure* blk,
+ OopClosure* non_heap_roots,
+ uint worker_i);
// Prepare for and cleanup after an oops_into_collection_set_do
// call. Must call each of these once before and after (in sequential
@@ -106,14 +106,13 @@
void prepare_for_oops_into_collection_set_do();
void cleanup_after_oops_into_collection_set_do();
- void scanRS(G1ParPushHeapRSClosure* oc,
- OopClosure* non_heap_roots,
- uint worker_i);
+ size_t scanRS(G1ParPushHeapRSClosure* oc,
+ OopClosure* non_heap_roots,
+ uint worker_i);
void updateRS(DirtyCardQueue* into_cset_dcq, uint worker_i);
CardTableModRefBS* ct_bs() { return _ct_bs; }
- size_t cardsScanned() { return _total_cards_scanned; }
// Record, if necessary, the fact that *p (where "p" is in region "from",
// which is required to be non-NULL) has changed to a new non-NULL value.
--- a/hotspot/src/share/vm/gc/parallel/parallelScavengeHeap.hpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/parallel/parallelScavengeHeap.hpp Wed Jul 05 20:51:27 2017 +0200
@@ -87,7 +87,7 @@
return CollectedHeap::ParallelScavengeHeap;
}
- virtual CollectorPolicy* collector_policy() const { return (CollectorPolicy*) _collector_policy; }
+ virtual CollectorPolicy* collector_policy() const { return _collector_policy; }
static PSYoungGen* young_gen() { return _young_gen; }
static PSOldGen* old_gen() { return _old_gen; }
--- a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -213,7 +213,7 @@
_max_eden_size = size - (2*_max_survivor_size);
// allocate the performance counters
- GenCollectorPolicy* gcp = (GenCollectorPolicy*)gch->collector_policy();
+ GenCollectorPolicy* gcp = gch->gen_policy();
// Generation counters -- generation 0, 3 subspaces
_gen_counters = new GenerationCounters("new", 0, 3,
--- a/hotspot/src/share/vm/gc/serial/tenuredGeneration.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/serial/tenuredGeneration.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -57,8 +57,7 @@
// initialize performance counters
const char* gen_name = "old";
- GenCollectorPolicy* gcp = (GenCollectorPolicy*) GenCollectedHeap::heap()->collector_policy();
-
+ GenCollectorPolicy* gcp = GenCollectedHeap::heap()->gen_policy();
// Generation Counters -- generation 1, 1 subspace
_gen_counters = new GenerationCounters(gen_name, 1, 1,
gcp->min_old_size(), gcp->max_old_size(), &_virtual_space);
--- a/hotspot/src/share/vm/gc/shared/ageTable.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/shared/ageTable.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -28,7 +28,6 @@
#include "gc/shared/collectorPolicy.hpp"
#include "gc/shared/gcPolicyCounters.hpp"
#include "memory/resourceArea.hpp"
-#include "runtime/atomic.inline.hpp"
#include "utilities/copy.hpp"
/* Copyright (c) 1992, 2015, Oracle and/or its affiliates, and Stanford University.
@@ -73,12 +72,6 @@
}
}
-void ageTable::merge_par(ageTable* subTable) {
- for (int i = 0; i < table_size; i++) {
- Atomic::add_ptr(subTable->sizes[i], &sizes[i]);
- }
-}
-
uint ageTable::compute_tenuring_threshold(size_t survivor_capacity, GCPolicyCounters* gc_counters) {
size_t desired_survivor_size = (size_t)((((double) survivor_capacity)*TargetSurvivorRatio)/100);
uint result;
--- a/hotspot/src/share/vm/gc/shared/ageTable.hpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/shared/ageTable.hpp Wed Jul 05 20:51:27 2017 +0200
@@ -68,7 +68,6 @@
// Merge another age table with the current one. Used
// for parallel young generation gc.
void merge(ageTable* subTable);
- void merge_par(ageTable* subTable);
// calculate new tenuring threshold based on age information
uint compute_tenuring_threshold(size_t survivor_capacity, GCPolicyCounters* gc_counters);
--- a/hotspot/src/share/vm/gc/shared/blockOffsetTable.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/shared/blockOffsetTable.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -447,14 +447,16 @@
} else {
// Unilaterally fix the first (num_pref_cards - 1) following
// the "offset card" in the suffix block.
+ const size_t right_most_fixed_index = suff_index + num_pref_cards - 1;
set_remainder_to_point_to_start_incl(suff_index + 1,
- suff_index + num_pref_cards - 1, true /* reducing */);
+ right_most_fixed_index, true /* reducing */);
// Fix the appropriate cards in the remainder of the
// suffix block -- these are the last num_pref_cards
// cards in each power block of the "new" range plumbed
// from suff_addr.
bool more = true;
uint i = 1;
+ // Fix the first power block with back_by > num_pref_cards.
while (more && (i < N_powers)) {
size_t back_by = power_to_cards_back(i);
size_t right_index = suff_index + back_by - 1;
@@ -463,6 +465,9 @@
right_index = end_index - 1;
more = false;
}
+ if (left_index <= right_most_fixed_index) {
+ left_index = right_most_fixed_index + 1;
+ }
if (back_by > num_pref_cards) {
// Fill in the remainder of this "power block", if it
// is non-null.
@@ -471,12 +476,14 @@
N_words + i - 1, true /* reducing */);
} else {
more = false; // we are done
+ assert((end_index - 1) == right_index, "Must be at the end.");
}
i++;
break;
}
i++;
}
+ // Fix the rest of the power blocks.
while (more && (i < N_powers)) {
size_t back_by = power_to_cards_back(i);
size_t right_index = suff_index + back_by - 1;
--- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -172,8 +172,6 @@
void GenCollectedHeap::post_initialize() {
CollectedHeap::post_initialize();
ref_processing_init();
- GenCollectorPolicy *policy = (GenCollectorPolicy *)collector_policy();
- guarantee(policy->is_generation_policy(), "Illegal policy type");
assert((_young_gen->kind() == Generation::DefNew) ||
(_young_gen->kind() == Generation::ParNew),
"Wrong youngest generation type");
@@ -183,10 +181,10 @@
_old_gen->kind() == Generation::MarkSweepCompact,
"Wrong generation kind");
- policy->initialize_size_policy(def_new_gen->eden()->capacity(),
- _old_gen->capacity(),
- def_new_gen->from()->capacity());
- policy->initialize_gc_policy_counters();
+ _gen_policy->initialize_size_policy(def_new_gen->eden()->capacity(),
+ _old_gen->capacity(),
+ def_new_gen->from()->capacity());
+ _gen_policy->initialize_gc_policy_counters();
}
void GenCollectedHeap::ref_processing_init() {
@@ -822,10 +820,11 @@
"Unexpected generation kinds");
// Skip two header words in the block content verification
NOT_PRODUCT(_skip_header_HeapWords = CMSCollector::skip_header_HeapWords();)
- CMSCollector* collector = new CMSCollector(
- (ConcurrentMarkSweepGeneration*)_old_gen,
- _rem_set->as_CardTableRS(),
- (ConcurrentMarkSweepPolicy*) collector_policy());
+ assert(_gen_policy->is_concurrent_mark_sweep_policy(), "Unexpected policy type");
+ CMSCollector* collector =
+ new CMSCollector((ConcurrentMarkSweepGeneration*)_old_gen,
+ _rem_set->as_CardTableRS(),
+ _gen_policy->as_concurrent_mark_sweep_policy());
if (collector == NULL || !collector->completed_initialization()) {
if (collector) {
--- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.hpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.hpp Wed Jul 05 20:51:27 2017 +0200
@@ -153,7 +153,7 @@
// The generational collector policy.
GenCollectorPolicy* gen_policy() const { return _gen_policy; }
- virtual CollectorPolicy* collector_policy() const { return (CollectorPolicy*) gen_policy(); }
+ virtual CollectorPolicy* collector_policy() const { return gen_policy(); }
// Adaptive size policy
virtual AdaptiveSizePolicy* size_policy() {
--- a/hotspot/src/share/vm/opto/classes.hpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/share/vm/opto/classes.hpp Wed Jul 05 20:51:27 2017 +0200
@@ -290,6 +290,7 @@
macro(MulReductionVD)
macro(DivVF)
macro(DivVD)
+macro(SqrtVD)
macro(LShiftCntV)
macro(RShiftCntV)
macro(LShiftVB)
--- a/hotspot/src/share/vm/opto/ifnode.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/share/vm/opto/ifnode.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -858,18 +858,29 @@
// this_bool = <=
// dom_bool = >= (proj = True) or dom_bool = < (proj = False)
// x in [a, b] on the fail (= True) projection, b+1 > a-1:
- // lo = a, hi = b, adjusted_lim = b-a, cond = <=u
+ // lo = a, hi = b, adjusted_lim = b-a+1, cond = <u
+ // lo = a, hi = b, adjusted_lim = b-a, cond = <=u doesn't work because b = a - 1 is possible, then b-a = -1
// dom_bool = > (proj = True) or dom_bool = <= (proj = False)
// x in ]a, b] on the fail (= True) projection b+1 > a:
// lo = a+1, hi = b, adjusted_lim = b-a, cond = <u
- // lo = a+1, hi = b, adjusted_lim = b-a-1, cond = <=u doesn't work because a = b is possible, then hi-lo = -1
+ // lo = a+1, hi = b, adjusted_lim = b-a-1, cond = <=u doesn't work because a = b is possible, then b-a-1 = -1
- if (lo_test == BoolTest::gt || lo_test == BoolTest::le) {
- if (hi_test == BoolTest::le) {
+ if (hi_test == BoolTest::lt) {
+ if (lo_test == BoolTest::gt || lo_test == BoolTest::le) {
+ lo = igvn->transform(new AddINode(lo, igvn->intcon(1)));
+ }
+ } else {
+ assert(hi_test == BoolTest::le, "bad test");
+ if (lo_test == BoolTest::ge || lo_test == BoolTest::lt) {
adjusted_lim = igvn->transform(new SubINode(hi, lo));
+ adjusted_lim = igvn->transform(new AddINode(adjusted_lim, igvn->intcon(1)));
+ cond = BoolTest::lt;
+ } else {
+ assert(lo_test == BoolTest::gt || lo_test == BoolTest::le, "bad test");
+ adjusted_lim = igvn->transform(new SubINode(hi, lo));
+ lo = igvn->transform(new AddINode(lo, igvn->intcon(1)));
cond = BoolTest::lt;
}
- lo = igvn->transform(new AddINode(lo, igvn->intcon(1)));
}
} else if (lo_type->_lo > hi_type->_hi && lo_type->_hi == max_jint && hi_type->_lo == min_jint) {
@@ -879,7 +890,8 @@
// lo = b, hi = a, adjusted_lim = a-b, cond = >=u
// dom_bool = <= (proj = True) or dom_bool = > (proj = False)
// x in [b, a] on the fail (= False) projection, a+1 > b-1:
- // lo = b, hi = a, adjusted_lim = a-b, cond = >u
+ // lo = b, hi = a, adjusted_lim = a-b+1, cond = >=u
+ // lo = b, hi = a, adjusted_lim = a-b, cond = >u doesn't work because a = b - 1 is possible, then b-a = -1
// this_bool = <=
// dom_bool = < (proj = True) or dom_bool = >= (proj = False)
// x in ]b, a[ on the fail (= False) projection, a > b:
@@ -887,7 +899,7 @@
// dom_bool = <= (proj = True) or dom_bool = > (proj = False)
// x in ]b, a] on the fail (= False) projection, a+1 > b:
// lo = b+1, hi = a, adjusted_lim = a-b, cond = >=u
- // lo = b+1, hi = a, adjusted_lim = a-b-1, cond = >u doesn't work because a = b is possible, then hi-lo = -1
+ // lo = b+1, hi = a, adjusted_lim = a-b-1, cond = >u doesn't work because a = b is possible, then b-a-1 = -1
swap(lo, hi);
swap(lo_type, hi_type);
@@ -900,14 +912,26 @@
cond = (hi_test == BoolTest::le || hi_test == BoolTest::gt) ? BoolTest::gt : BoolTest::ge;
- if (lo_test == BoolTest::le) {
- if (cond == BoolTest::gt) {
+ if (lo_test == BoolTest::lt) {
+ if (hi_test == BoolTest::lt || hi_test == BoolTest::ge) {
+ cond = BoolTest::ge;
+ } else {
+ assert(hi_test == BoolTest::le || hi_test == BoolTest::gt, "bad test");
adjusted_lim = igvn->transform(new SubINode(hi, lo));
+ adjusted_lim = igvn->transform(new AddINode(adjusted_lim, igvn->intcon(1)));
cond = BoolTest::ge;
}
- lo = igvn->transform(new AddINode(lo, igvn->intcon(1)));
+ } 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;
+ }
}
-
} else {
const TypeInt* failtype = filtered_int_type(igvn, n, proj);
if (failtype != NULL) {
--- a/hotspot/src/share/vm/opto/loopPredicate.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/share/vm/opto/loopPredicate.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -112,6 +112,13 @@
if (_idom != NULL) {
set_idom(call, rgn, dom_depth(rgn));
}
+ for (DUIterator_Fast imax, i = uncommon_proj->fast_outs(imax); i < imax; i++) {
+ Node* n = uncommon_proj->fast_out(i);
+ if (n->is_Load() || n->is_Store()) {
+ _igvn.replace_input_of(n, 0, rgn);
+ --i; --imax;
+ }
+ }
} else {
// Find region's edge corresponding to uncommon_proj
for (; proj_index < rgn->req(); proj_index++)
--- a/hotspot/src/share/vm/opto/loopnode.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/share/vm/opto/loopnode.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -1901,7 +1901,7 @@
if (stride_con > 0) tty->print("+");
tty->print("%d", stride_con);
- tty->print(" (%d iters) ", (int)cl->profile_trip_cnt());
+ tty->print(" (%0.f iters) ", cl->profile_trip_cnt());
if (cl->is_pre_loop ()) tty->print(" pre" );
if (cl->is_main_loop()) tty->print(" main");
--- a/hotspot/src/share/vm/opto/superword.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/share/vm/opto/superword.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -1858,6 +1858,11 @@
vn = VectorNode::make(opc, in1, in2, vlen, velt_basic_type(n));
vlen_in_bytes = vn->as_Vector()->length_in_bytes();
}
+ } else if (opc == Op_SqrtD) {
+ // Promote operand to vector (Sqrt is a 2 address instruction)
+ Node* in = vector_opd(p, 1);
+ vn = VectorNode::make(opc, in, NULL, vlen, velt_basic_type(n));
+ vlen_in_bytes = vn->as_Vector()->length_in_bytes();
} else {
ShouldNotReachHere();
}
--- a/hotspot/src/share/vm/opto/vectornode.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/share/vm/opto/vectornode.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -92,6 +92,9 @@
case Op_DivD:
assert(bt == T_DOUBLE, "must be");
return Op_DivVD;
+ case Op_SqrtD:
+ assert(bt == T_DOUBLE, "must be");
+ return Op_SqrtVD;
case Op_LShiftI:
switch (bt) {
case T_BOOLEAN:
@@ -277,6 +280,9 @@
case Op_DivVF: return new DivVFNode(n1, n2, vt);
case Op_DivVD: return new DivVDNode(n1, n2, vt);
+ // Currently only supports double precision sqrt
+ case Op_SqrtVD: return new SqrtVDNode(n1, vt);
+
case Op_LShiftVB: return new LShiftVBNode(n1, n2, vt);
case Op_LShiftVS: return new LShiftVSNode(n1, n2, vt);
case Op_LShiftVI: return new LShiftVINode(n1, n2, vt);
--- a/hotspot/src/share/vm/opto/vectornode.hpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/share/vm/opto/vectornode.hpp Wed Jul 05 20:51:27 2017 +0200
@@ -309,6 +309,14 @@
virtual int Opcode() const;
};
+//------------------------------SqrtVDNode--------------------------------------
+// Vector Sqrt double
+class SqrtVDNode : public VectorNode {
+ public:
+ SqrtVDNode(Node* in, const TypeVect* vt) : VectorNode(in,vt) {}
+ virtual int Opcode() const;
+};
+
//------------------------------LShiftVBNode-----------------------------------
// Vector left shift bytes
class LShiftVBNode : public VectorNode {
--- a/hotspot/src/share/vm/prims/whitebox.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/share/vm/prims/whitebox.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -1041,11 +1041,18 @@
}
WB_ENTRY(jlong, WB_AllocateCodeBlob(JNIEnv* env, jobject o, jint size, jint blob_type))
- return (jlong) WhiteBox::allocate_code_blob(size, blob_type);
+ if (size < 0) {
+ THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
+ err_msg("WB_AllocateCodeBlob: size is negative: " INT32_FORMAT, size));
+ }
+ return (jlong) WhiteBox::allocate_code_blob(size, blob_type);
WB_END
WB_ENTRY(void, WB_FreeCodeBlob(JNIEnv* env, jobject o, jlong addr))
- BufferBlob::free((BufferBlob*) addr);
+ if (addr == 0) {
+ return;
+ }
+ BufferBlob::free((BufferBlob*) addr);
WB_END
WB_ENTRY(jobjectArray, WB_GetCodeHeapEntries(JNIEnv* env, jobject o, jint blob_type))
@@ -1090,9 +1097,13 @@
WB_END
WB_ENTRY(jobjectArray, WB_GetCodeBlob(JNIEnv* env, jobject o, jlong addr))
- ThreadToNativeFromVM ttn(thread);
- CodeBlobStub stub((CodeBlob*) addr);
- return codeBlob2objectArray(thread, env, &stub);
+ if (addr == 0) {
+ THROW_MSG_NULL(vmSymbols::java_lang_NullPointerException(),
+ "WB_GetCodeBlob: addr is null");
+ }
+ ThreadToNativeFromVM ttn(thread);
+ CodeBlobStub stub((CodeBlob*) addr);
+ return codeBlob2objectArray(thread, env, &stub);
WB_END
WB_ENTRY(jlong, WB_GetThreadStackSize(JNIEnv* env, jobject o))
--- a/hotspot/src/share/vm/services/lowMemoryDetector.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/share/vm/services/lowMemoryDetector.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -200,9 +200,10 @@
// any clears unless the usage becomes greater than or equal
// to the high threshold.
//
-// If the current level is between high and low threhsold, no change.
+// If the current level is between high and low threshold, no change.
//
void SensorInfo::set_gauge_sensor_level(MemoryUsage usage, ThresholdSupport* high_low_threshold) {
+ assert(Service_lock->owned_by_self(), "Must own Service_lock");
assert(high_low_threshold->is_high_threshold_supported(), "just checking");
bool is_over_high = high_low_threshold->is_high_threshold_crossed(usage);
@@ -257,6 +258,7 @@
// the sensor will be on (i.e. sensor is currently off
// and has pending trigger requests).
void SensorInfo::set_counter_sensor_level(MemoryUsage usage, ThresholdSupport* counter_threshold) {
+ assert(Service_lock->owned_by_self(), "Must own Service_lock");
assert(counter_threshold->is_high_threshold_supported(), "just checking");
bool is_over_high = counter_threshold->is_high_threshold_crossed(usage);
@@ -278,9 +280,7 @@
}
void SensorInfo::process_pending_requests(TRAPS) {
- if (!has_pending_requests()) {
- return;
- }
+ assert(has_pending_requests(), "Must have pending request");
int pending_count = pending_trigger_count();
if (pending_clear_count() > 0) {
@@ -293,7 +293,6 @@
void SensorInfo::trigger(int count, TRAPS) {
assert(count <= _pending_trigger_count, "just checking");
-
if (_sensor_obj != NULL) {
Klass* k = Management::sun_management_Sensor_klass(CHECK);
instanceKlassHandle sensorKlass (THREAD, k);
@@ -316,6 +315,7 @@
{
// Holds Service_lock and update the sensor state
MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
+ assert(_pending_trigger_count > 0, "Must have pending trigger");
_sensor_on = true;
_sensor_count += count;
_pending_trigger_count = _pending_trigger_count - count;
@@ -323,6 +323,20 @@
}
void SensorInfo::clear(int count, TRAPS) {
+ {
+ // Holds Service_lock and update the sensor state
+ MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
+ if (_pending_clear_count == 0) {
+ // Bail out if we lost a race to set_*_sensor_level() which may have
+ // reactivated the sensor in the meantime because it was triggered again.
+ return;
+ }
+ _sensor_on = false;
+ _sensor_count += count;
+ _pending_clear_count = 0;
+ _pending_trigger_count = _pending_trigger_count - count;
+ }
+
if (_sensor_obj != NULL) {
Klass* k = Management::sun_management_Sensor_klass(CHECK);
instanceKlassHandle sensorKlass (THREAD, k);
@@ -338,14 +352,6 @@
&args,
CHECK);
}
-
- {
- // Holds Service_lock and update the sensor state
- MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
- _sensor_on = false;
- _pending_clear_count = 0;
- _pending_trigger_count = _pending_trigger_count - count;
- }
}
//--------------------------------------------------------------
--- a/hotspot/src/share/vm/services/lowMemoryDetector.hpp Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/src/share/vm/services/lowMemoryDetector.hpp Wed Jul 05 20:51:27 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -180,7 +180,7 @@
// any clears unless the usage becomes greater than or equal
// to the high threshold.
//
- // If the current level is between high and low threhsold, no change.
+ // If the current level is between high and low threshold, no change.
//
void set_gauge_sensor_level(MemoryUsage usage, ThresholdSupport* high_low_threshold);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/arraycopy/TestEliminatedArrayLoopPredicateCopyDeopt.java Wed Jul 05 20:51:27 2017 +0200
@@ -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);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/loopopts/superword/SumRedSqrt_Double.java Wed Jul 05 20:51:27 2017 +0200
@@ -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;
+ }
+
+}
--- a/hotspot/test/compiler/rangechecks/TestBadFoldCompare.java Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/test/compiler/rangechecks/TestBadFoldCompare.java Wed Jul 05 20:51:27 2017 +0200
@@ -24,7 +24,8 @@
/*
* @test
* @bug 8085832
- * @summary x <= 0 || x > 0 wrongly folded as (x-1) >u -1
+ * @bug 8135069
+ * @summary x <= 0 || x > 0 wrongly folded as (x-1) >u -1 and x < 0 || x > -1 wrongly folded as x >u -1
* @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestBadFoldCompare
*/
@@ -58,6 +59,34 @@
helper2(i, 0, 0, flag);
}
+ static boolean test3_taken;
+
+ static void helper3(int i, int a, int b, boolean flag) {
+ if (flag) {
+ if (i < a || i > b - 1) {
+ test3_taken = true;
+ }
+ }
+ }
+
+ static void test3(int i, boolean flag) {
+ helper3(i, 0, 0, flag);
+ }
+
+ static boolean test4_taken;
+
+ static void helper4(int i, int a, int b, boolean flag) {
+ if (flag) {
+ if (i > b - 1 || i < a) {
+ test4_taken = true;
+ }
+ }
+ }
+
+ static void test4(int i, boolean flag) {
+ helper4(i, 0, 0, flag);
+ }
+
static public void main(String[] args) {
boolean success = true;
@@ -87,6 +116,35 @@
System.out.println("Test2 failed");
success = false;
}
+
+ for (int i = 0; i < 20000; i++) {
+ helper3(5, 0, 10, (i%2)==0);
+ helper3(-1, 0, 10, (i%2)==0);
+ helper3(15, 0, 10, (i%2)==0);
+ test3(0, false);
+ }
+ test3_taken = false;
+ test3(0, true);
+
+ if (!test3_taken) {
+ System.out.println("Test3 failed");
+ success = false;
+ }
+
+ for (int i = 0; i < 20000; i++) {
+ helper4(5, 0, 10, (i%2)==0);
+ helper4(-1, 0, 10, (i%2)==0);
+ helper4(15, 0, 10, (i%2)==0);
+ test4(0, false);
+ }
+ test4_taken = false;
+ test4(0, true);
+
+ if (!test4_taken) {
+ System.out.println("Test4 failed");
+ success = false;
+ }
+
if (!success) {
throw new RuntimeException("Some tests failed");
}
--- a/hotspot/test/gc/g1/humongousObjects/TestHumongousThreshold.java Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/test/gc/g1/humongousObjects/TestHumongousThreshold.java Wed Jul 05 20:51:27 2017 +0200
@@ -56,11 +56,11 @@
* gc.g1.humongousObjects.TestHumongousThreshold
*
* @run main/othervm -XX:+UseG1GC -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
- * -XX:G1HeapRegionSize=16M
+ * -Xms128M -XX:G1HeapRegionSize=16M
* gc.g1.humongousObjects.TestHumongousThreshold
*
* @run main/othervm -XX:+UseG1GC -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
- * -XX:G1HeapRegionSize=32M
+ * -Xms200M -XX:G1HeapRegionSize=32M
* gc.g1.humongousObjects.TestHumongousThreshold
*
*/
--- a/hotspot/test/serviceability/dcmd/compiler/CodelistTest.java Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/test/serviceability/dcmd/compiler/CodelistTest.java Wed Jul 05 20:51:27 2017 +0200
@@ -90,6 +90,9 @@
if (methodPrintedInLogFormat.contains("MethodHandle")) {
continue;
}
+ if (methodPrintedInLogFormat.contains("sun.misc.Unsafe.getUnsafe")) {
+ continue;
+ }
MethodIdentifierParser mf = new MethodIdentifierParser(methodPrintedInLogFormat);
Method m = null;
--- a/hotspot/test/testlibrary/jdk/test/lib/Utils.java Sat Sep 26 09:22:24 2015 -0700
+++ b/hotspot/test/testlibrary/jdk/test/lib/Utils.java Wed Jul 05 20:51:27 2017 +0200
@@ -428,4 +428,28 @@
public static long adjustTimeout(long tOut) {
return Math.round(tOut * Utils.TIMEOUT_FACTOR);
}
+
+ /**
+ * Runs runnable and checks that it throws expected exception. If exceptionException is null it means
+ * that we expect no exception to be thrown.
+ * @param runnable what we run
+ * @param expectedException expected exception
+ */
+ public static void runAndCheckException(Runnable runnable, Class<? extends Throwable> expectedException) {
+ try {
+ runnable.run();
+ if (expectedException != null) {
+ throw new AssertionError("Didn't get expected exception " + expectedException.getSimpleName());
+ }
+ } catch (Throwable t) {
+ if (expectedException == null) {
+ throw new AssertionError("Got unexpected exception ", t);
+ }
+ if (!expectedException.isAssignableFrom(t.getClass())) {
+ throw new AssertionError(String.format("Got unexpected exception %s instead of %s",
+ t.getClass().getSimpleName(), expectedException.getSimpleName()), t);
+ }
+ }
+ }
+
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary_tests/whitebox/BlobSanityTest.java Wed Jul 05 20:51:27 2017 +0200
@@ -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);
+ }
+}
--- a/jaxp/.hgtags Sat Sep 26 09:22:24 2015 -0700
+++ b/jaxp/.hgtags Wed Jul 05 20:51:27 2017 +0200
@@ -325,3 +325,4 @@
f464f9b2fb1178f6a957e5730b4b5252c6149ed9 jdk9-b80
6a418934997fc4b56664b88f8417e2f0fe658091 jdk9-b81
53fe3c103b6fdf48e2b2676c0c4818ef5a10fa21 jdk9-b82
+497bc2654e11684b11de46744227883d7e760f35 jdk9-b83
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/ElementImpl.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/ElementImpl.java Wed Jul 05 20:51:27 2017 +0200
@@ -3,11 +3,12 @@
* DO NOT REMOVE OR ALTER!
*/
/*
- * Copyright 1999-2002,2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
@@ -17,70 +18,75 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.sun.org.apache.xerces.internal.dom;
import org.w3c.dom.Attr;
import org.w3c.dom.DOMException;
import org.w3c.dom.Element;
+import org.w3c.dom.ElementTraversal;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
-
import org.w3c.dom.TypeInfo;
import com.sun.org.apache.xerces.internal.util.URI;
/**
- * Elements represent most of the "markup" and structure of the
- * document. They contain both the data for the element itself
- * (element name and attributes), and any contained nodes, including
- * document text (as children).
+ * Elements represent most of the "markup" and structure of the document. They
+ * contain both the data for the element itself (element name and attributes),
+ * and any contained nodes, including document text (as children).
* <P>
* Elements may have Attributes associated with them; the API for this is
* defined in Node, but the function is implemented here. In general, XML
* applications should retrive Attributes as Nodes, since they may contain
- * entity references and hence be a fairly complex sub-tree. HTML users will
- * be dealing with simple string values, and convenience methods are provided
- * to work in terms of Strings.
+ * entity references and hence be a fairly complex sub-tree. HTML users will be
+ * dealing with simple string values, and convenience methods are provided to
+ * work in terms of Strings.
* <P>
* ElementImpl does not support Namespaces. ElementNSImpl, which inherits from
* it, does.
+ *
* @see ElementNSImpl
*
* @xerces.internal
*
- * @author Arnaud Le Hors, IBM
+ * @author Arnaud Le Hors, IBM
* @author Joe Kesselman, IBM
* @author Andy Clark, IBM
* @author Ralf Pfeiffer, IBM
- * @since PR-DOM-Level-1-19980818.
+ * @since PR-DOM-Level-1-19980818.
*/
public class ElementImpl
- extends ParentNode
- implements Element, TypeInfo {
+ extends ParentNode
+ implements Element, ElementTraversal, TypeInfo {
//
// Constants
//
-
- /** Serialization version. */
+ /**
+ * Serialization version.
+ */
static final long serialVersionUID = 3717253516652722278L;
//
// Data
//
- /** Element name. */
+ /**
+ * Element name.
+ */
protected String name;
- /** Attributes. */
+ /**
+ * Attributes.
+ */
protected AttributeMap attributes;
//
// Constructors
//
-
- /** Factory constructor. */
+ /**
+ * Factory constructor.
+ */
public ElementImpl(CoreDocumentImpl ownerDoc, String name) {
super(ownerDoc);
this.name = name;
@@ -88,7 +94,8 @@
}
// for ElementNSImpl
- protected ElementImpl() {}
+ protected ElementImpl() {
+ }
// Support for DOM Level 3 renameNode method.
// Note: This only deals with part of the pb. CoreDocumentImpl
@@ -97,26 +104,45 @@
if (needsSyncData()) {
synchronizeData();
}
- this.name = name;
+ if (ownerDocument.errorChecking) {
+ int colon1 = name.indexOf(':');
+ if (colon1 != -1) {
+ String msg
+ = DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "NAMESPACE_ERR",
+ null);
+ throw new DOMException(DOMException.NAMESPACE_ERR, msg);
+ }
+ if (!CoreDocumentImpl.isXMLName(name, ownerDocument.isXML11Version())) {
+ String msg = DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "INVALID_CHARACTER_ERR", null);
+ throw new DOMException(DOMException.INVALID_CHARACTER_ERR,
+ msg);
+ }
+ }
+ this.name = name;
reconcileDefaultAttributes();
}
//
// Node methods
//
-
-
/**
- * A short integer indicating what type of node this is. The named
- * constants for this value are defined in the org.w3c.dom.Node interface.
+ * A short integer indicating what type of node this is. The named constants
+ * for this value are defined in the org.w3c.dom.Node interface.
*/
public short getNodeType() {
return Node.ELEMENT_NODE;
}
/**
- * Returns the element name
+ * Returns the node name
+ *
+ * @return the node name
*/
+ @Override
public String getNodeName() {
if (needsSyncData()) {
synchronizeData();
@@ -129,7 +155,10 @@
* from Node rather than specified on Element; in fact only Elements will
* ever have Attributes, but they want to allow folks to "blindly" operate
* on the tree as a set of Nodes.
+ *
+ * @return all Attributes
*/
+ @Override
public NamedNodeMap getAttributes() {
if (needsSyncData()) {
@@ -143,12 +172,13 @@
} // getAttributes():NamedNodeMap
/**
- * Return a duplicate copy of this Element. Note that its children
- * will not be copied unless the "deep" flag is true, but Attributes
- * are <i>always</i> replicated.
+ * Return a duplicate copy of this Element. Note that its children will not
+ * be copied unless the "deep" flag is true, but Attributes are
+ * {@code always} replicated.
*
* @see org.w3c.dom.Node#cloneNode(boolean)
*/
+ @Override
public Node cloneNode(boolean deep) {
ElementImpl newnode = (ElementImpl) super.cloneNode(deep);
@@ -160,10 +190,12 @@
} // cloneNode(boolean):Node
- /**
- * DOM Level 3 WD - Experimental.
- * Retrieve baseURI
+ /**
+ * DOM Level 3 WD - Experimental. Retrieve baseURI
+ *
+ * @return the baseURI
*/
+ @Override
public String getBaseURI() {
if (needsSyncData()) {
@@ -174,62 +206,61 @@
// 1. The base URI specified by an xml:base attribute on the element,
// if one exists
if (attributes != null) {
- Attr attrNode = (Attr)attributes.getNamedItem("xml:base");
+ final Attr attrNode = getXMLBaseAttribute();
if (attrNode != null) {
- String uri = attrNode.getNodeValue();
- if (uri.length() != 0 ) {// attribute value is always empty string
+ final String uri = attrNode.getNodeValue();
+ if (uri.length() != 0) {// attribute value is always empty string
try {
- uri = new URI(uri).toString();
- }
- catch (com.sun.org.apache.xerces.internal.util.URI.MalformedURIException e) {
- // This may be a relative URI.
+ URI _uri = new URI(uri, true);
+ // If the URI is already absolute return it; otherwise it's relative and we need to resolve it.
+ if (_uri.isAbsoluteURI()) {
+ return _uri.toString();
+ }
// Make any parentURI into a URI object to use with the URI(URI, String) constructor
String parentBaseURI = (this.ownerNode != null) ? this.ownerNode.getBaseURI() : null;
- if (parentBaseURI != null){
- try{
- uri = new URI(new URI(parentBaseURI), uri).toString();
- }
- catch (com.sun.org.apache.xerces.internal.util.URI.MalformedURIException ex){
+ if (parentBaseURI != null) {
+ try {
+ URI _parentBaseURI = new URI(parentBaseURI);
+ _uri.absolutize(_parentBaseURI);
+ return _uri.toString();
+ } catch (com.sun.org.apache.xerces.internal.util.URI.MalformedURIException ex) {
// This should never happen: parent should have checked the URI and returned null if invalid.
return null;
}
- return uri;
}
+ // REVISIT: what should happen in this case?
+ return null;
+ } catch (com.sun.org.apache.xerces.internal.util.URI.MalformedURIException ex) {
return null;
}
- return uri;
}
}
}
// 2.the base URI of the element's parent element within the
// document or external entity, if one exists
- // 3. the base URI of the document entity or external entity
- // containing the element
-
- // ownerNode serves as a parent or as document
- String baseURI = (this.ownerNode != null) ? this.ownerNode.getBaseURI() : null ;
- //base URI of parent element is not null
- if(baseURI != null){
- try {
- //return valid absolute base URI
- return new URI(baseURI).toString();
- }
- catch (com.sun.org.apache.xerces.internal.util.URI.MalformedURIException e){
- return null;
- }
- }
- return null;
+ // 3. the base URI of the document entity or external entity
+ // containing the element
+ // ownerNode serves as a parent or as document
+ return (this.ownerNode != null) ? this.ownerNode.getBaseURI() : null;
} //getBaseURI
-
+ /**
+ * NON-DOM Returns the xml:base attribute.
+ *
+ * @return the xml:base attribute
+ */
+ protected Attr getXMLBaseAttribute() {
+ return (Attr) attributes.getNamedItem("xml:base");
+ } // getXMLBaseAttribute():Attr
/**
- * NON-DOM
- * set the ownerDocument of this node, its children, and its attributes
+ * NON-DOM set the ownerDocument of this node, its children, and its
+ * attributes
*/
- void setOwnerDocument(CoreDocumentImpl doc) {
+ @Override
+ protected void setOwnerDocument(CoreDocumentImpl doc) {
super.setOwnerDocument(doc);
if (attributes != null) {
attributes.setOwnerDocument(doc);
@@ -239,15 +270,14 @@
//
// Element methods
//
-
/**
- * Look up a single Attribute by name. Returns the Attribute's
- * string value, or an empty string (NOT null!) to indicate that the
- * name did not map to a currently defined attribute.
+ * Look up a single Attribute by name. Returns the Attribute's string value,
+ * or an empty string (NOT null!) to indicate that the name did not map to a
+ * currently defined attribute.
* <p>
- * Note: Attributes may contain complex node trees. This method
- * returns the "flattened" string obtained from Attribute.getValue().
- * If you need the structure information, see getAttributeNode().
+ * Note: Attributes may contain complex node trees. This method returns the
+ * "flattened" string obtained from Attribute.getValue(). If you need the
+ * structure information, see getAttributeNode().
*/
public String getAttribute(String name) {
@@ -257,16 +287,15 @@
if (attributes == null) {
return "";
}
- Attr attr = (Attr)(attributes.getNamedItem(name));
+ Attr attr = (Attr) (attributes.getNamedItem(name));
return (attr == null) ? "" : attr.getValue();
} // getAttribute(String):String
-
/**
- * Look up a single Attribute by name. Returns the Attribute Node,
- * so its complete child tree is available. This could be important in
- * XML, where the string rendering may not be sufficient information.
+ * Look up a single Attribute by name. Returns the Attribute Node, so its
+ * complete child tree is available. This could be important in XML, where
+ * the string rendering may not be sufficient information.
* <p>
* If no matching attribute is available, returns null.
*/
@@ -278,36 +307,32 @@
if (attributes == null) {
return null;
}
- return (Attr)attributes.getNamedItem(name);
+ return (Attr) attributes.getNamedItem(name);
} // getAttributeNode(String):Attr
-
/**
- * Returns a NodeList of all descendent nodes (children,
- * grandchildren, and so on) which are Elements and which have the
- * specified tag name.
+ * Returns a NodeList of all descendent nodes (children, grandchildren, and
+ * so on) which are Elements and which have the specified tag name.
* <p>
- * Note: NodeList is a "live" view of the DOM. Its contents will
- * change as the DOM changes, and alterations made to the NodeList
- * will be reflected in the DOM.
+ * Note: NodeList is a "live" view of the DOM. Its contents will change as
+ * the DOM changes, and alterations made to the NodeList will be reflected
+ * in the DOM.
*
- * @param tagname The type of element to gather. To obtain a list of
- * all elements no matter what their names, use the wild-card tag
- * name "*".
+ * @param tagname The type of element to gather. To obtain a list of all
+ * elements no matter what their names, use the wild-card tag name "*".
*
* @see DeepNodeListImpl
*/
public NodeList getElementsByTagName(String tagname) {
- return new DeepNodeListImpl(this,tagname);
+ return new DeepNodeListImpl(this, tagname);
}
/**
- * Returns the name of the Element. Note that Element.nodeName() is
- * defined to also return the tag name.
+ * Returns the name of the Element. Note that Element.nodeName() is defined
+ * to also return the tag name.
* <p>
- * This is case-preserving in XML. HTML should uppercasify it on the
- * way in.
+ * This is case-preserving in XML. HTML should uppercasify it on the way in.
*/
public String getTagName() {
if (needsSyncData()) {
@@ -326,9 +351,9 @@
* <p>
* To normalize a Document, normalize its top-level Element child.
* <p>
- * As of PR-DOM-Level-1-19980818, CDATA -- despite being a subclass of
- * Text -- is considered "markup" and will _not_ be merged either with
- * normal Text or with other CDATASections.
+ * As of PR-DOM-Level-1-19980818, CDATA -- despite being a subclass of Text
+ * -- is considered "markup" and will _not_ be merged either with normal
+ * Text or with other CDATASections.
*/
public void normalize() {
// No need to normalize if already normalized.
@@ -347,35 +372,27 @@
// 1) There is an adjacent text node
// 2) There is no adjacent text node, but kid is
// an empty text node.
- if ( kid.getNodeType() == Node.TEXT_NODE )
- {
+ if (kid.getNodeType() == Node.TEXT_NODE) {
// If an adjacent text node, merge it with kid
- if ( next!=null && next.getNodeType() == Node.TEXT_NODE )
- {
- ((Text)kid).appendData(next.getNodeValue());
- removeChild( next );
+ if (next != null && next.getNodeType() == Node.TEXT_NODE) {
+ ((Text) kid).appendData(next.getNodeValue());
+ removeChild(next);
next = kid; // Don't advance; there might be another.
- }
- else
- {
+ } else {
// If kid is empty, remove it
- if ( kid.getNodeValue() == null || kid.getNodeValue().length() == 0 ) {
- removeChild( kid );
+ if (kid.getNodeValue() == null || kid.getNodeValue().length() == 0) {
+ removeChild(kid);
}
}
- }
-
- // Otherwise it might be an Element, which is handled recursively
+ } // Otherwise it might be an Element, which is handled recursively
else if (kid.getNodeType() == Node.ELEMENT_NODE) {
kid.normalize();
}
}
// We must also normalize all of the attributes
- if ( attributes!=null )
- {
- for( int i=0; i<attributes.getLength(); ++i )
- {
+ if (attributes != null) {
+ for (int i = 0; i < attributes.getLength(); ++i) {
Node attr = attributes.item(i);
attr.normalize();
}
@@ -383,21 +400,20 @@
// changed() will have occurred when the removeChild() was done,
// so does not have to be reissued.
-
isNormalized(true);
} // normalize()
/**
- * Remove the named attribute from this Element. If the removed
- * Attribute has a default value, it is immediately replaced thereby.
+ * Remove the named attribute from this Element. If the removed Attribute
+ * has a default value, it is immediately replaced thereby.
* <P>
* The default logic is actually implemented in NamedNodeMapImpl.
- * PR-DOM-Level-1-19980818 doesn't fully address the DTD, so some
- * of this behavior is likely to change in future versions. ?????
+ * PR-DOM-Level-1-19980818 doesn't fully address the DTD, so some of this
+ * behavior is likely to change in future versions. ?????
* <P>
- * Note that this call "succeeds" even if no attribute by this name
- * existed -- unlike removeAttributeNode, which will throw a not-found
- * exception in that case.
+ * Note that this call "succeeds" even if no attribute by this name existed
+ * -- unlike removeAttributeNode, which will throw a not-found exception in
+ * that case.
*
* @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if the node is
* readonly.
@@ -421,16 +437,14 @@
} // removeAttribute(String)
-
/**
- * Remove the specified attribute/value pair. If the removed
- * Attribute has a default value, it is immediately replaced.
+ * Remove the specified attribute/value pair. If the removed Attribute has a
+ * default value, it is immediately replaced.
* <p>
- * NOTE: Specifically removes THIS NODE -- not the node with this
- * name, nor the node with these contents. If the specific Attribute
- * object passed in is not stored in this Element, we throw a
- * DOMException. If you really want to remove an attribute by name,
- * use removeAttribute().
+ * NOTE: Specifically removes THIS NODE -- not the node with this name, nor
+ * the node with these contents. If the specific Attribute object passed in
+ * is not stored in this Element, we throw a DOMException. If you really
+ * want to remove an attribute by name, use removeAttribute().
*
* @return the Attribute object that was removed.
* @throws DOMException(NOT_FOUND_ERR) if oldattr is not an attribute of
@@ -439,7 +453,7 @@
* readonly.
*/
public Attr removeAttributeNode(Attr oldAttr)
- throws DOMException {
+ throws DOMException {
if (ownerDocument.errorChecking && isReadOnly()) {
String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
@@ -458,19 +472,18 @@
} // removeAttributeNode(Attr):Attr
-
/**
- * Add a new name/value pair, or replace the value of the existing
- * attribute having that name.
+ * Add a new name/value pair, or replace the value of the existing attribute
+ * having that name.
*
- * Note: this method supports only the simplest kind of Attribute,
- * one whose value is a string contained in a single Text node.
- * If you want to assert a more complex value (which XML permits,
- * though HTML doesn't), see setAttributeNode().
+ * Note: this method supports only the simplest kind of Attribute, one whose
+ * value is a string contained in a single Text node. If you want to assert
+ * a more complex value (which XML permits, though HTML doesn't), see
+ * setAttributeNode().
*
- * The attribute is created with specified=true, meaning it's an
- * explicit value rather than inherited from the DTD as a default.
- * Again, setAttributeNode can be used to achieve other results.
+ * The attribute is created with specified=true, meaning it's an explicit
+ * value rather than inherited from the DTD as a default. Again,
+ * setAttributeNode can be used to achieve other results.
*
* @throws DOMException(INVALID_NAME_ERR) if the name is not acceptable.
* (Attribute factory will do that test for us.)
@@ -478,54 +491,52 @@
* @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if the node is
* readonly.
*/
- public void setAttribute(String name, String value) {
+ public void setAttribute(String name, String value) {
- if (ownerDocument.errorChecking && isReadOnly()) {
- String msg =
- DOMMessageFormatter.formatMessage(
- DOMMessageFormatter.DOM_DOMAIN,
- "NO_MODIFICATION_ALLOWED_ERR",
- null);
- throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
- }
+ if (ownerDocument.errorChecking && isReadOnly()) {
+ String msg
+ = DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "NO_MODIFICATION_ALLOWED_ERR",
+ null);
+ throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
+ }
- if (needsSyncData()) {
- synchronizeData();
- }
+ if (needsSyncData()) {
+ synchronizeData();
+ }
- Attr newAttr = getAttributeNode(name);
- if (newAttr == null) {
- newAttr = getOwnerDocument().createAttribute(name);
+ Attr newAttr = getAttributeNode(name);
+ if (newAttr == null) {
+ newAttr = getOwnerDocument().createAttribute(name);
- if (attributes == null) {
- attributes = new AttributeMap(this, null);
- }
+ if (attributes == null) {
+ attributes = new AttributeMap(this, null);
+ }
- newAttr.setNodeValue(value);
- attributes.setNamedItem(newAttr);
- }
- else {
- newAttr.setNodeValue(value);
- }
+ newAttr.setNodeValue(value);
+ attributes.setNamedItem(newAttr);
+ } else {
+ newAttr.setNodeValue(value);
+ }
- } // setAttribute(String,String)
+ } // setAttribute(String,String)
/**
- * Add a new attribute/value pair, or replace the value of the
- * existing attribute with that name.
+ * Add a new attribute/value pair, or replace the value of the existing
+ * attribute with that name.
* <P>
* This method allows you to add an Attribute that has already been
* constructed, and hence avoids the limitations of the simple
- * setAttribute() call. It can handle attribute values that have
- * arbitrarily complex tree structure -- in particular, those which
- * had entity references mixed into their text.
+ * setAttribute() call. It can handle attribute values that have arbitrarily
+ * complex tree structure -- in particular, those which had entity
+ * references mixed into their text.
*
- * @throws DOMException(INUSE_ATTRIBUTE_ERR) if the Attribute object
- * has already been assigned to another Element.
+ * @throws DOMException(INUSE_ATTRIBUTE_ERR) if the Attribute object has
+ * already been assigned to another Element.
*/
public Attr setAttributeNode(Attr newAttr)
- throws DOMException
- {
+ throws DOMException {
if (needsSyncData()) {
synchronizeData();
@@ -535,13 +546,13 @@
if (isReadOnly()) {
String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
throw new DOMException(
- DOMException.NO_MODIFICATION_ALLOWED_ERR,
- msg);
+ DOMException.NO_MODIFICATION_ALLOWED_ERR,
+ msg);
}
if (newAttr.getOwnerDocument() != ownerDocument) {
String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null);
- throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, msg);
+ throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, msg);
}
}
@@ -556,19 +567,16 @@
//
// DOM2: Namespace methods
//
-
/**
- * Introduced in DOM Level 2. <p>
+ * Introduced in DOM Level 2.
+ * <p>
*
* Retrieves an attribute value by local name and namespace URI.
*
- * @param namespaceURI
- * The namespace URI of the attribute to
- * retrieve.
- * @param localName The local name of the attribute to retrieve.
- * @return String The Attr value as a string, or empty string
- * if that attribute
- * does not have a specified or default value.
+ * @param namespaceURI The namespace URI of the attribute to retrieve.
+ * @param localName The local name of the attribute to retrieve.
+ * @return String The Attr value as a string, or empty string if that
+ * attribute does not have a specified or default value.
* @since WD-DOM-Level-2-19990923
*/
public String getAttributeNS(String namespaceURI, String localName) {
@@ -581,89 +589,85 @@
return "";
}
- Attr attr = (Attr)(attributes.getNamedItemNS(namespaceURI, localName));
+ Attr attr = (Attr) (attributes.getNamedItemNS(namespaceURI, localName));
return (attr == null) ? "" : attr.getValue();
} // getAttributeNS(String,String):String
/**
- * Introduced in DOM Level 2. <p>
- *
- * Adds a new attribute.
- * If the given namespaceURI is null or an empty string and the
- * qualifiedName has a prefix that is "xml", the new attribute is bound to
- * the predefined namespace "http://www.w3.org/XML/1998/namespace"
- * [Namespaces]. If an attribute with the same local name and namespace
- * URI is already present on the element, its prefix is changed to be the
- * prefix part of the qualifiedName, and its value is changed to be the
- * value parameter. This value is a simple string, it is not parsed as it
- * is being set. So any markup (such as syntax to be recognized as an
- * entity reference) is treated as literal text, and needs to be
- * appropriately escaped by the implementation when it is written out. In
- * order to assign an attribute value that contains entity references, the
- * user must create an Attr node plus any Text and EntityReference nodes,
- * build the appropriate subtree, and use setAttributeNodeNS or
- * setAttributeNode to assign it as the value of an attribute.
+ * Introduced in DOM Level 2.
+ * <p>
*
- * @param namespaceURI The namespace URI of the attribute to create
- * or alter.
- * @param qualifiedName The qualified name of the attribute to create or
- * alter.
- * @param value The value to set in string form.
- * @throws INVALID_CHARACTER_ERR: Raised if the specified
- * name contains an invalid character.
+ * Adds a new attribute. If the given namespaceURI is null or an empty
+ * string and the qualifiedName has a prefix that is "xml", the new
+ * attribute is bound to the predefined namespace
+ * "http://www.w3.org/XML/1998/namespace" [Namespaces]. If an attribute with
+ * the same local name and namespace URI is already present on the element,
+ * its prefix is changed to be the prefix part of the qualifiedName, and its
+ * value is changed to be the value parameter. This value is a simple
+ * string, it is not parsed as it is being set. So any markup (such as
+ * syntax to be recognized as an entity reference) is treated as literal
+ * text, and needs to be appropriately escaped by the implementation when it
+ * is written out. In order to assign an attribute value that contains
+ * entity references, the user must create an Attr node plus any Text and
+ * EntityReference nodes, build the appropriate subtree, and use
+ * setAttributeNodeNS or setAttributeNode to assign it as the value of an
+ * attribute.
*
- * @throws NO_MODIFICATION_ALLOWED_ERR: Raised if this
- * node is readonly.
+ * @param namespaceURI The namespace URI of the attribute to create or
+ * alter.
+ * @param qualifiedName The qualified name of the attribute to create or
+ * alter.
+ * @param value The value to set in string form.
+ * @throws INVALID_CHARACTER_ERR: Raised if the specified name contains an
+ * invalid character.
*
- * @throws NAMESPACE_ERR: Raised if the qualifiedName
- * has a prefix that is "xml" and the namespaceURI
- * is neither null nor an empty string nor
- * "http://www.w3.org/XML/1998/namespace", or if
- * the qualifiedName has a prefix that is "xmlns"
- * but the namespaceURI is neither null nor an
- * empty string, or if if the qualifiedName has a
- * prefix different from "xml" and "xmlns" and the
- * namespaceURI is null or an empty string.
+ * @throws NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
+ *
+ * @throws NAMESPACE_ERR: Raised if the qualifiedName has a prefix that is
+ * "xml" and the namespaceURI is neither null nor an empty string nor
+ * "http://www.w3.org/XML/1998/namespace", or if the qualifiedName has a
+ * prefix that is "xmlns" but the namespaceURI is neither null nor an empty
+ * string, or if if the qualifiedName has a prefix different from "xml" and
+ * "xmlns" and the namespaceURI is null or an empty string.
* @since WD-DOM-Level-2-19990923
*/
- public void setAttributeNS(String namespaceURI,String qualifiedName,
- String value) {
- if (ownerDocument.errorChecking && isReadOnly()) {
- String msg =
- DOMMessageFormatter.formatMessage(
- DOMMessageFormatter.DOM_DOMAIN,
- "NO_MODIFICATION_ALLOWED_ERR",
- null);
- throw new DOMException(
- DOMException.NO_MODIFICATION_ALLOWED_ERR,
- msg);
- }
- if (needsSyncData()) {
- synchronizeData();
- }
- int index = qualifiedName.indexOf(':');
- String prefix, localName;
- if (index < 0) {
- prefix = null;
- localName = qualifiedName;
- }
- else {
- prefix = qualifiedName.substring(0, index);
- localName = qualifiedName.substring(index + 1);
- }
- Attr newAttr = getAttributeNodeNS(namespaceURI, localName);
- if (newAttr == null) {
+ public void setAttributeNS(String namespaceURI, String qualifiedName,
+ String value) {
+ if (ownerDocument.errorChecking && isReadOnly()) {
+ String msg
+ = DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "NO_MODIFICATION_ALLOWED_ERR",
+ null);
+ throw new DOMException(
+ DOMException.NO_MODIFICATION_ALLOWED_ERR,
+ msg);
+ }
+ if (needsSyncData()) {
+ synchronizeData();
+ }
+ int index = qualifiedName.indexOf(':');
+ String prefix, localName;
+ if (index < 0) {
+ prefix = null;
+ localName = qualifiedName;
+ } else {
+ prefix = qualifiedName.substring(0, index);
+ localName = qualifiedName.substring(index + 1);
+ }
+ Attr newAttr = getAttributeNodeNS(namespaceURI, localName);
+ if (newAttr == null) {
// REVISIT: this is not efficient, we are creating twice the same
// strings for prefix and localName.
- newAttr = getOwnerDocument().createAttributeNS(
- namespaceURI,
- qualifiedName);
- if (attributes == null) {
- attributes = new AttributeMap(this, null);
- }
- newAttr.setNodeValue(value);
- attributes.setNamedItemNS(newAttr);
+ newAttr = getOwnerDocument().createAttributeNS(
+ namespaceURI,
+ qualifiedName);
+ if (attributes == null) {
+ attributes = new AttributeMap(this, null);
+ }
+ newAttr.setNodeValue(value);
+ attributes.setNamedItemNS(newAttr);
}
else {
if (newAttr instanceof AttrNSImpl){
@@ -694,25 +698,24 @@
attributes.setNamedItemNS(newAttr);
}
- newAttr.setNodeValue(value);
- }
+ newAttr.setNodeValue(value);
+ }
} // setAttributeNS(String,String,String)
-
/**
- * Introduced in DOM Level 2. <p>
+ * Introduced in DOM Level 2.
+ * <p>
*
* Removes an attribute by local name and namespace URI. If the removed
- * attribute has a default value it is immediately replaced.
- * The replacing attribute has the same namespace URI and local name,
- * as well as the original prefix.<p>
+ * attribute has a default value it is immediately replaced. The replacing
+ * attribute has the same namespace URI and local name, as well as the
+ * original prefix.<p>
*
- * @param namespaceURI The namespace URI of the attribute to remove.
+ * @param namespaceURI The namespace URI of the attribute to remove.
*
- * @param localName The local name of the attribute to remove.
- * @throws NO_MODIFICATION_ALLOWED_ERR: Raised if this
- * node is readonly.
+ * @param localName The local name of the attribute to remove.
+ * @throws NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
* @since WD-DOM-Level-2-19990923
*/
public void removeAttributeNS(String namespaceURI, String localName) {
@@ -737,15 +740,13 @@
/**
* Retrieves an Attr node by local name and namespace URI.
*
- * @param namespaceURI The namespace URI of the attribute to
- * retrieve.
- * @param localName The local name of the attribute to retrieve.
- * @return Attr The Attr node with the specified attribute
- * local name and namespace
- * URI or null if there is no such attribute.
+ * @param namespaceURI The namespace URI of the attribute to retrieve.
+ * @param localName The local name of the attribute to retrieve.
+ * @return Attr The Attr node with the specified attribute local name and
+ * namespace URI or null if there is no such attribute.
* @since WD-DOM-Level-2-19990923
*/
- public Attr getAttributeNodeNS(String namespaceURI, String localName){
+ public Attr getAttributeNodeNS(String namespaceURI, String localName) {
if (needsSyncData()) {
synchronizeData();
@@ -753,40 +754,34 @@
if (attributes == null) {
return null;
}
- return (Attr)attributes.getNamedItemNS(namespaceURI, localName);
+ return (Attr) attributes.getNamedItemNS(namespaceURI, localName);
} // getAttributeNodeNS(String,String):Attr
/**
- * Introduced in DOM Level 2. <p>
+ * Introduced in DOM Level 2.
+ * <p>
*
- * Adds a new attribute. If an attribute with that local name and
- * namespace URI is already present in the element, it is replaced
- * by the new one.
+ * Adds a new attribute. If an attribute with that local name and namespace
+ * URI is already present in the element, it is replaced by the new one.
*
- * @param Attr The Attr node to add to the attribute list. When
- * the Node has no namespaceURI, this method behaves
- * like setAttributeNode.
- * @return Attr If the newAttr attribute replaces an existing attribute
- * with the same local name and namespace URI, the *
- * previously existing Attr node is returned, otherwise
- * null is returned.
- * @throws WRONG_DOCUMENT_ERR: Raised if newAttr
- * was created from a different document than the one that
- * created the element.
+ * @param newAttr The Attr node to add to the attribute list. When the Node
+ * has no namespaceURI, this method behaves like setAttributeNode.
+ * @return Attr If the newAttr attribute replaces an existing attribute with
+ * the same local name and namespace URI, the * previously existing Attr
+ * node is returned, otherwise null is returned.
+ * @throws WRONG_DOCUMENT_ERR: Raised if newAttr was created from a
+ * different document than the one that created the element.
*
- * @throws NO_MODIFICATION_ALLOWED_ERR: Raised if
- * this node is readonly.
+ * @throws NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
*
- * @throws INUSE_ATTRIBUTE_ERR: Raised if newAttr is
- * already an attribute of another Element object. The
- * DOM user must explicitly clone Attr nodes to re-use
- * them in other elements.
+ * @throws INUSE_ATTRIBUTE_ERR: Raised if newAttr is already an attribute of
+ * another Element object. The DOM user must explicitly clone Attr nodes to
+ * re-use them in other elements.
* @since WD-DOM-Level-2-19990923
*/
public Attr setAttributeNodeNS(Attr newAttr)
- throws DOMException
- {
+ throws DOMException {
if (needsSyncData()) {
synchronizeData();
@@ -794,9 +789,9 @@
if (ownerDocument.errorChecking) {
if (isReadOnly()) {
String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
- throw new DOMException(
- DOMException.NO_MODIFICATION_ALLOWED_ERR,
- msg);
+ throw new DOMException(
+ DOMException.NO_MODIFICATION_ALLOWED_ERR,
+ msg);
}
if (newAttr.getOwnerDocument() != ownerDocument) {
String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null);
@@ -813,9 +808,9 @@
} // setAttributeNodeNS(Attr):Attr
/**
- * NON-DOM: sets attribute node for this element
- */
- protected int setXercesAttributeNode (Attr attr){
+ * NON-DOM: sets attribute node for this element
+ */
+ protected int setXercesAttributeNode(Attr attr) {
if (needsSyncData()) {
synchronizeData();
@@ -829,9 +824,9 @@
}
/**
- * NON-DOM: get inded of an attribute
- */
- protected int getXercesAttribute(String namespaceURI, String localName){
+ * NON-DOM: get inded of an attribute
+ */
+ protected int getXercesAttribute(String namespaceURI, String localName) {
if (needsSyncData()) {
synchronizeData();
@@ -868,32 +863,30 @@
}
/**
- * Introduced in DOM Level 2. <p>
+ * Introduced in DOM Level 2.
+ * <p>
*
* Returns a NodeList of all the Elements with a given local name and
* namespace URI in the order in which they would be encountered in a
* preorder traversal of the Document tree, starting from this node.
*
- * @param namespaceURI The namespace URI of the elements to match
- * on. The special value "*" matches all
- * namespaces. When it is null or an empty
- * string, this method behaves like
- * getElementsByTagName.
- * @param localName The local name of the elements to match on.
- * The special value "*" matches all local names.
- * @return NodeList A new NodeList object containing all the matched
- * Elements.
+ * @param namespaceURI The namespace URI of the elements to match on. The
+ * special value "*" matches all namespaces. When it is null or an empty
+ * string, this method behaves like getElementsByTagName.
+ * @param localName The local name of the elements to match on. The special
+ * value "*" matches all local names.
+ * @return NodeList A new NodeList object containing all the matched
+ * Elements.
* @since WD-DOM-Level-2-19990923
*/
public NodeList getElementsByTagNameNS(String namespaceURI,
- String localName) {
+ String localName) {
return new DeepNodeListImpl(this, namespaceURI, localName);
}
/**
- * DOM Level 3 WD- Experimental.
- * Override inherited behavior from NodeImpl and ParentNode to check on
- * attributes
+ * DOM Level 3 WD- Experimental. Override inherited behavior from NodeImpl
+ * and ParentNode to check on attributes
*/
public boolean isEqualNode(Node arg) {
if (!super.isEqualNode(arg)) {
@@ -917,10 +910,9 @@
if (n2 == null || !((NodeImpl) n1).isEqualNode(n2)) {
return false;
}
- }
- else {
+ } else {
Node n2 = map2.getNamedItemNS(n1.getNamespaceURI(),
- n1.getLocalName());
+ n1.getLocalName());
if (n2 == null || !((NodeImpl) n1).isEqualNode(n2)) {
return false;
}
@@ -941,8 +933,8 @@
if (isReadOnly()) {
String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
throw new DOMException(
- DOMException.NO_MODIFICATION_ALLOWED_ERR,
- msg);
+ DOMException.NO_MODIFICATION_ALLOWED_ERR,
+ msg);
}
if (at.getOwnerElement() != this) {
@@ -953,8 +945,7 @@
((AttrImpl) at).isIdAttribute(makeId);
if (!makeId) {
ownerDocument.removeIdentifier(at.getValue());
- }
- else {
+ } else {
ownerDocument.putIdentifier(at.getValue(), this);
}
}
@@ -968,19 +959,19 @@
}
Attr at = getAttributeNode(name);
- if( at == null){
- String msg = DOMMessageFormatter.formatMessage(
- DOMMessageFormatter.DOM_DOMAIN,
- "NOT_FOUND_ERR", null);
+ if (at == null) {
+ String msg = DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "NOT_FOUND_ERR", null);
throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
- }
+ }
- if (ownerDocument.errorChecking) {
+ if (ownerDocument.errorChecking) {
if (isReadOnly()) {
String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
throw new DOMException(
- DOMException.NO_MODIFICATION_ALLOWED_ERR,
- msg);
+ DOMException.NO_MODIFICATION_ALLOWED_ERR,
+ msg);
}
if (at.getOwnerElement() != this) {
@@ -992,8 +983,7 @@
((AttrImpl) at).isIdAttribute(makeId);
if (!makeId) {
ownerDocument.removeIdentifier(at.getValue());
- }
- else {
+ } else {
ownerDocument.putIdentifier(at.getValue(), this);
}
}
@@ -1002,51 +992,52 @@
* DOM Level 3: register the given attribute node as an ID attribute
*/
public void setIdAttributeNS(String namespaceURI, String localName,
- boolean makeId) {
+ boolean makeId) {
if (needsSyncData()) {
synchronizeData();
}
//if namespace uri is empty string, set it to 'null'
if (namespaceURI != null) {
- namespaceURI = (namespaceURI.length() == 0)? null : namespaceURI;
+ namespaceURI = (namespaceURI.length() == 0) ? null : namespaceURI;
}
Attr at = getAttributeNodeNS(namespaceURI, localName);
- if( at == null){
- String msg = DOMMessageFormatter.formatMessage(
- DOMMessageFormatter.DOM_DOMAIN,
- "NOT_FOUND_ERR", null);
+ if (at == null) {
+ String msg = DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN,
+ "NOT_FOUND_ERR", null);
throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
- }
+ }
- if (ownerDocument.errorChecking) {
+ if (ownerDocument.errorChecking) {
if (isReadOnly()) {
- String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
+ String msg = DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
throw new DOMException(
- DOMException.NO_MODIFICATION_ALLOWED_ERR,
- msg);
+ DOMException.NO_MODIFICATION_ALLOWED_ERR,
+ msg);
}
if (at.getOwnerElement() != this) {
- String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
+ String msg = DOMMessageFormatter.formatMessage(
+ DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
}
}
((AttrImpl) at).isIdAttribute(makeId);
if (!makeId) {
ownerDocument.removeIdentifier(at.getValue());
- }
- else {
+ } else {
ownerDocument.putIdentifier(at.getValue(), this);
}
- }
+ }
/**
* @see org.w3c.dom.TypeInfo#getTypeName()
*/
- public String getTypeName() {
+ public String getTypeName() {
return null;
- }
+ }
/**
* @see org.w3c.dom.TypeInfo#getTypeNamespace()
@@ -1056,33 +1047,32 @@
}
/**
- * Introduced in DOM Level 3. <p>
+ * Introduced in DOM Level 3.
+ * <p>
* Checks if a type is derived from another by restriction. See:
* http://www.w3.org/TR/DOM-Level-3-Core/core.html#TypeInfo-isDerivedFrom
*
- * @param ancestorNS
- * The namspace of the ancestor type declaration
- * @param ancestorName
- * The name of the ancestor type declaration
- * @param type
- * The reference type definition
+ * @param typeNamespaceArg The namspace of the ancestor type declaration
+ * @param typeNameArg The name of the ancestor type declaration
+ * @param derivationMethod The derivation method
*
- * @return boolean True if the type is derived by restriciton for the
- * reference type
+ * @return boolean True if the type is derived by restriction for the
+ * reference type
*/
public boolean isDerivedFrom(String typeNamespaceArg,
- String typeNameArg,
- int derivationMethod) {
+ String typeNameArg,
+ int derivationMethod) {
return false;
}
- /**
- * Method getSchemaTypeInfo.
- * @return TypeInfo
- */
- public TypeInfo getSchemaTypeInfo(){
- if(needsSyncData()) {
+ /**
+ * Method getSchemaTypeInfo.
+ *
+ * @return TypeInfo
+ */
+ public TypeInfo getSchemaTypeInfo() {
+ if (needsSyncData()) {
synchronizeData();
}
return this;
@@ -1091,25 +1081,24 @@
//
// Public methods
//
-
/**
* NON-DOM: Subclassed to flip the attributes' readonly switch as well.
+ *
* @see NodeImpl#setReadOnly
*/
public void setReadOnly(boolean readOnly, boolean deep) {
- super.setReadOnly(readOnly,deep);
+ super.setReadOnly(readOnly, deep);
if (attributes != null) {
- attributes.setReadOnly(readOnly,true);
+ attributes.setReadOnly(readOnly, true);
}
}
-
-
//
// Protected methods
//
-
- /** Synchronizes the data (name and value) for fast nodes. */
+ /**
+ * Synchronizes the data (name and value) for fast nodes.
+ */
protected void synchronizeData() {
// no need to sync in the future
@@ -1141,7 +1130,9 @@
}
}
- /** Setup the default attributes. */
+ /**
+ * Setup the default attributes.
+ */
protected void setupDefaultAttributes() {
NamedNodeMapImpl defaults = getDefaultAttributes();
if (defaults != null) {
@@ -1149,7 +1140,9 @@
}
}
- /** Reconcile default attributes. */
+ /**
+ * Reconcile default attributes.
+ */
protected void reconcileDefaultAttributes() {
if (attributes != null) {
NamedNodeMapImpl defaults = getDefaultAttributes();
@@ -1157,17 +1150,19 @@
}
}
- /** Get the default attributes. */
+ /**
+ * Get the default attributes.
+ */
protected NamedNodeMapImpl getDefaultAttributes() {
- DocumentTypeImpl doctype =
- (DocumentTypeImpl) ownerDocument.getDoctype();
+ DocumentTypeImpl doctype
+ = (DocumentTypeImpl) ownerDocument.getDoctype();
if (doctype == null) {
return null;
}
- ElementDefinitionImpl eldef =
- (ElementDefinitionImpl)doctype.getElements()
- .getNamedItem(getNodeName());
+ ElementDefinitionImpl eldef
+ = (ElementDefinitionImpl) doctype.getElements()
+ .getNamedItem(getNodeName());
if (eldef == null) {
return null;
}
@@ -1175,4 +1170,208 @@
} // getDefaultAttributes()
+ //
+ // ElementTraversal methods
+ //
+ /**
+ * @see <a
+ * href="http://www.w3.org/TR/2008/REC-ElementTraversal-20081222/#attribute-childElementCount">
+ * Element Traversal Specification</a>
+ */
+ @Override
+ public final int getChildElementCount() {
+ int count = 0;
+ Element child = getFirstElementChild();
+ while (child != null) {
+ ++count;
+ child = ((ElementImpl) child).getNextElementSibling();
+ }
+ return count;
+ } // getChildElementCount():int
+
+ /**
+ * @see <a
+ * href="http://www.w3.org/TR/2008/REC-ElementTraversal-20081222/#attribute-firstElementChild">
+ * Element Traversal Specification</a>
+ */
+ @Override
+ public final Element getFirstElementChild() {
+ Node n = getFirstChild();
+ while (n != null) {
+ switch (n.getNodeType()) {
+ case Node.ELEMENT_NODE:
+ return (Element) n;
+ case Node.ENTITY_REFERENCE_NODE:
+ final Element e = getFirstElementChild(n);
+ if (e != null) {
+ return e;
+ }
+ break;
+ }
+ n = n.getNextSibling();
+ }
+ return null;
+ } // getFirstElementChild():Element
+
+ /**
+ * @see <a
+ * href="http://www.w3.org/TR/2008/REC-ElementTraversal-20081222/#attribute-lastElementChild">
+ * Element Traversal Specification</a>
+ */
+ @Override
+ public final Element getLastElementChild() {
+ Node n = getLastChild();
+ while (n != null) {
+ switch (n.getNodeType()) {
+ case Node.ELEMENT_NODE:
+ return (Element) n;
+ case Node.ENTITY_REFERENCE_NODE:
+ final Element e = getLastElementChild(n);
+ if (e != null) {
+ return e;
+ }
+ break;
+ }
+ n = n.getPreviousSibling();
+ }
+ return null;
+ } // getLastElementChild():Element
+
+ /**
+ * @see <a
+ * href="http://www.w3.org/TR/2008/REC-ElementTraversal-20081222/#attribute-nextElementSibling">
+ * Element Traversal Specification</a>
+ */
+ @Override
+ public final Element getNextElementSibling() {
+ Node n = getNextLogicalSibling(this);
+ while (n != null) {
+ switch (n.getNodeType()) {
+ case Node.ELEMENT_NODE:
+ return (Element) n;
+ case Node.ENTITY_REFERENCE_NODE:
+ final Element e = getFirstElementChild(n);
+ if (e != null) {
+ return e;
+ }
+ break;
+ }
+ n = getNextLogicalSibling(n);
+ }
+ return null;
+ } // getNextElementSibling():Element
+
+ /**
+ * @see <a
+ * href="http://www.w3.org/TR/2008/REC-ElementTraversal-20081222/#attribute-previousElementSibling">
+ * Element Traversal Specification</a>
+ */
+ @Override
+ public final Element getPreviousElementSibling() {
+ Node n = getPreviousLogicalSibling(this);
+ while (n != null) {
+ switch (n.getNodeType()) {
+ case Node.ELEMENT_NODE:
+ return (Element) n;
+ case Node.ENTITY_REFERENCE_NODE:
+ final Element e = getLastElementChild(n);
+ if (e != null) {
+ return e;
+ }
+ break;
+ }
+ n = getPreviousLogicalSibling(n);
+ }
+ return null;
+ } // getPreviousElementSibling():Element
+
+ // Returns the first element node found from a
+ // non-recursive in order traversal of the given node.
+ private Element getFirstElementChild(Node n) {
+ final Node top = n;
+ while (n != null) {
+ if (n.getNodeType() == Node.ELEMENT_NODE) {
+ return (Element) n;
+ }
+ Node next = n.getFirstChild();
+ while (next == null) {
+ if (top == n) {
+ break;
+ }
+ next = n.getNextSibling();
+ if (next == null) {
+ n = n.getParentNode();
+ if (n == null || top == n) {
+ return null;
+ }
+ }
+ }
+ n = next;
+ }
+ return null;
+ } // getFirstElementChild(Node):Element
+
+ // Returns the first element node found from a
+ // non-recursive reverse order traversal of the given node.
+ private Element getLastElementChild(Node n) {
+ final Node top = n;
+ while (n != null) {
+ if (n.getNodeType() == Node.ELEMENT_NODE) {
+ return (Element) n;
+ }
+ Node next = n.getLastChild();
+ while (next == null) {
+ if (top == n) {
+ break;
+ }
+ next = n.getPreviousSibling();
+ if (next == null) {
+ n = n.getParentNode();
+ if (n == null || top == n) {
+ return null;
+ }
+ }
+ }
+ n = next;
+ }
+ return null;
+ } // getLastElementChild(Node):Element
+
+ // Returns the next logical sibling with respect to the given node.
+ private Node getNextLogicalSibling(Node n) {
+ Node next = n.getNextSibling();
+ // If "n" has no following sibling and its parent is an entity reference node we
+ // need to continue the search through the following siblings of the entity
+ // reference as these are logically siblings of the given node.
+ if (next == null) {
+ Node parent = n.getParentNode();
+ while (parent != null && parent.getNodeType() == Node.ENTITY_REFERENCE_NODE) {
+ next = parent.getNextSibling();
+ if (next != null) {
+ break;
+ }
+ parent = parent.getParentNode();
+ }
+ }
+ return next;
+ } // getNextLogicalSibling(Node):Node
+
+ // Returns the previous logical sibling with respect to the given node.
+ private Node getPreviousLogicalSibling(Node n) {
+ Node prev = n.getPreviousSibling();
+ // If "n" has no previous sibling and its parent is an entity reference node we
+ // need to continue the search through the previous siblings of the entity
+ // reference as these are logically siblings of the given node.
+ if (prev == null) {
+ Node parent = n.getParentNode();
+ while (parent != null && parent.getNodeType() == Node.ENTITY_REFERENCE_NODE) {
+ prev = parent.getPreviousSibling();
+ if (prev != null) {
+ break;
+ }
+ parent = parent.getParentNode();
+ }
+ }
+ return prev;
+ } // getPreviousLogicalSibling(Node):Node
} // class ElementImpl
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/org/w3c/dom/ElementTraversal.java Wed Jul 05 20:51:27 2017 +0200
@@ -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();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/dom/ElementTraversal.java Wed Jul 05 20:51:27 2017 +0200
@@ -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;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/dom/ElementTraversal.xml Wed Jul 05 20:51:27 2017 +0200
@@ -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>
\ No newline at end of file
--- a/jdk/.hgtags Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/.hgtags Wed Jul 05 20:51:27 2017 +0200
@@ -325,3 +325,4 @@
4947810137ae53abba3028cc366af953d90fa81a jdk9-b80
fdc13a2d32867ca3c57b7fa2620c6b59c83168cb jdk9-b81
b10b64263b563e21f055c881444f625ec618b826 jdk9-b82
+d11f25ce3c545823f53bb978d454a4d2901abac3 jdk9-b83
--- a/jdk/make/mapfiles/libjava/mapfile-vers Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/make/mapfiles/libjava/mapfile-vers Wed Jul 05 20:51:27 2017 +0200
@@ -157,7 +157,6 @@
Java_java_lang_StrictMath_cosh;
Java_java_lang_StrictMath_sinh;
Java_java_lang_StrictMath_tanh;
- Java_java_lang_StrictMath_hypot;
Java_java_lang_StrictMath_log1p;
Java_java_lang_StrictMath_expm1;
Java_java_lang_Object_getClass;
--- a/jdk/src/java.base/share/classes/java/lang/FdLibm.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/FdLibm.java Wed Jul 05 20:51:27 2017 +0200
@@ -26,7 +26,8 @@
package java.lang;
/**
- * Port of the "Freely Distributable Math Library", version 5.3, from C to Java.
+ * Port of the "Freely Distributable Math Library", version 5.3, from
+ * C to Java.
*
* <p>The C version of fdlibm relied on the idiom of pointer aliasing
* a 64-bit double floating-point value as a two-element array of
@@ -37,7 +38,7 @@
* operated on as integer values, the standard library methods for
* bitwise floating-point to integer conversion,
* Double.longBitsToDouble and Double.doubleToRawLongBits, are directly
- * or indirectly used .
+ * or indirectly used.
*
* <p>The C version of fdlibm also took some pains to signal the
* correct IEEE 754 exceptional conditions divide by zero, invalid,
@@ -47,13 +48,21 @@
* handling is not supported natively in the JVM, such coding patterns
* have been omitted from this port. For example, rather than {@code
* return huge * huge}, this port will use {@code return INFINITY}.
+ *
+ * <p>Various comparison and arithmetic operations in fdlibm could be
+ * done either based on the integer view of a value or directly on the
+ * floating-point representation. Which idiom is faster may depend on
+ * platform specific factors. However, for code clarity if no other
+ * reason, this port will favor expressing the semantics of those
+ * operations in terms of floating-point operations when convenient to
+ * do so.
*/
class FdLibm {
// Constants used by multiple algorithms
private static final double INFINITY = Double.POSITIVE_INFINITY;
private FdLibm() {
- throw new UnsupportedOperationException("No instances for you.");
+ throw new UnsupportedOperationException("No FdLibm instances for you.");
}
/**
@@ -91,13 +100,146 @@
}
/**
+ * hypot(x,y)
+ *
+ * Method :
+ * If (assume round-to-nearest) z = x*x + y*y
+ * has error less than sqrt(2)/2 ulp, than
+ * sqrt(z) has error less than 1 ulp (exercise).
+ *
+ * So, compute sqrt(x*x + y*y) with some care as
+ * follows to get the error below 1 ulp:
+ *
+ * Assume x > y > 0;
+ * (if possible, set rounding to round-to-nearest)
+ * 1. if x > 2y use
+ * x1*x1 + (y*y + (x2*(x + x1))) for x*x + y*y
+ * where x1 = x with lower 32 bits cleared, x2 = x - x1; else
+ * 2. if x <= 2y use
+ * t1*y1 + ((x-y) * (x-y) + (t1*y2 + t2*y))
+ * where t1 = 2x with lower 32 bits cleared, t2 = 2x - t1,
+ * y1= y with lower 32 bits chopped, y2 = y - y1.
+ *
+ * NOTE: scaling may be necessary if some argument is too
+ * large or too tiny
+ *
+ * Special cases:
+ * hypot(x,y) is INF if x or y is +INF or -INF; else
+ * hypot(x,y) is NAN if x or y is NAN.
+ *
+ * Accuracy:
+ * hypot(x,y) returns sqrt(x^2 + y^2) with error less
+ * than 1 ulp (unit in the last place)
+ */
+ public static class Hypot {
+ public static final double TWO_MINUS_600 = 0x1.0p-600;
+ public static final double TWO_PLUS_600 = 0x1.0p+600;
+
+ public static strictfp double compute(double x, double y) {
+ double a = Math.abs(x);
+ double b = Math.abs(y);
+
+ if (!Double.isFinite(a) || !Double.isFinite(b)) {
+ if (a == INFINITY || b == INFINITY)
+ return INFINITY;
+ else
+ return a + b; // Propagate NaN significand bits
+ }
+
+ if (b > a) {
+ double tmp = a;
+ a = b;
+ b = tmp;
+ }
+ assert a >= b;
+
+ // Doing bitwise conversion after screening for NaN allows
+ // the code to not worry about the possibility of
+ // "negative" NaN values.
+
+ // Note: the ha and hb variables are the high-order
+ // 32-bits of a and b stored as integer values. The ha and
+ // hb values are used first for a rough magnitude
+ // comparison of a and b and second for simulating higher
+ // precision by allowing a and b, respectively, to be
+ // decomposed into non-overlapping portions. Both of these
+ // uses could be eliminated. The magnitude comparison
+ // could be eliminated by extracting and comparing the
+ // exponents of a and b or just be performing a
+ // floating-point divide. Splitting a floating-point
+ // number into non-overlapping portions can be
+ // accomplished by judicious use of multiplies and
+ // additions. For details see T. J. Dekker, A Floating
+ // Point Technique for Extending the Available Precision ,
+ // Numerische Mathematik, vol. 18, 1971, pp.224-242 and
+ // subsequent work.
+
+ int ha = __HI(a); // high word of a
+ int hb = __HI(b); // high word of b
+
+ if ((ha - hb) > 0x3c00000) {
+ return a + b; // x / y > 2**60
+ }
+
+ int k = 0;
+ if (a > 0x1.0p500) { // a > 2**500
+ // scale a and b by 2**-600
+ ha -= 0x25800000;
+ hb -= 0x25800000;
+ a = a * TWO_MINUS_600;
+ b = b * TWO_MINUS_600;
+ k += 600;
+ }
+ double t1, t2;
+ if (b < 0x1.0p-500) { // b < 2**-500
+ if (b < Double.MIN_NORMAL) { // subnormal b or 0 */
+ if (b == 0.0)
+ return a;
+ t1 = 0x1.0p1022; // t1 = 2^1022
+ b *= t1;
+ a *= t1;
+ k -= 1022;
+ } else { // scale a and b by 2^600
+ ha += 0x25800000; // a *= 2^600
+ hb += 0x25800000; // b *= 2^600
+ a = a * TWO_PLUS_600;
+ b = b * TWO_PLUS_600;
+ k -= 600;
+ }
+ }
+ // medium size a and b
+ double w = a - b;
+ if (w > b) {
+ t1 = 0;
+ t1 = __HI(t1, ha);
+ t2 = a - t1;
+ w = Math.sqrt(t1*t1 - (b*(-b) - t2 * (a + t1)));
+ } else {
+ double y1, y2;
+ a = a + a;
+ y1 = 0;
+ y1 = __HI(y1, hb);
+ y2 = b - y1;
+ t1 = 0;
+ t1 = __HI(t1, ha + 0x00100000);
+ t2 = a - t1;
+ w = Math.sqrt(t1*y1 - (w*(-w) - (t1*y2 + t2*b)));
+ }
+ if (k != 0) {
+ return Math.powerOfTwoD(k) * w;
+ } else
+ return w;
+ }
+ }
+
+ /**
* Compute x**y
* n
* Method: Let x = 2 * (1+f)
* 1. Compute and return log2(x) in two pieces:
* log2(x) = w1 + w2,
* where w1 has 53 - 24 = 29 bit trailing zeros.
- * 2. Perform y*log2(x) = n+y' by simulating muti-precision
+ * 2. Perform y*log2(x) = n+y' by simulating multi-precision
* arithmetic, where |y'| <= 0.5.
* 3. Return x**y = 2**n*exp(y'*log2)
*
--- a/jdk/src/java.base/share/classes/java/lang/Process.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/Process.java Wed Jul 05 20:51:27 2017 +0200
@@ -500,7 +500,8 @@
/**
* Returns a snapshot of the direct children of the process.
- * A process that is {@link #isAlive not alive} has zero children.
+ * The parent of a direct child process is the process.
+ * Typically, a process that is {@link #isAlive not alive} has no children.
* <p>
* <em>Note that processes are created and terminate asynchronously.
* There is no guarantee that a process is {@link #isAlive alive}.
@@ -510,8 +511,8 @@
* This implementation returns the direct children as:
* {@link #toHandle toHandle().children()}.
*
- * @return a Stream of ProcessHandles for processes that are direct children
- * of the process
+ * @return a sequential Stream of ProcessHandles for processes that are
+ * direct children of the process
* @throws UnsupportedOperationException if the Process implementation
* does not support this operation
* @throws SecurityException if a security manager has been installed and
@@ -524,7 +525,9 @@
/**
* Returns a snapshot of the direct and indirect children of the process.
- * A process that is {@link #isAlive not alive} has zero children.
+ * An indirect child is one whose parent is either a direct child or
+ * another indirect child.
+ * Typically, a process that is {@link #isAlive not alive} has no children.
* <p>
* <em>Note that processes are created and terminate asynchronously.
* There is no guarantee that a process is {@link #isAlive alive}.
@@ -534,8 +537,8 @@
* This implementation returns all children as:
* {@link #toHandle toHandle().allChildren()}.
*
- * @return a Stream of ProcessHandles for processes that are direct and
- * indirect children of the process
+ * @return a sequential Stream of ProcessHandles for processes that are
+ * direct and indirect children of the process
* @throws UnsupportedOperationException if the Process implementation
* does not support this operation
* @throws SecurityException if a security manager has been installed and
--- a/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java Wed Jul 05 20:51:27 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -33,7 +33,8 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
-
+import java.security.AccessController;
+import java.security.PrivilegedAction;
/**
* This class is used to create operating system processes.
*
@@ -445,6 +446,7 @@
* <ul>
* <li>the special value {@link #PIPE Redirect.PIPE}
* <li>the special value {@link #INHERIT Redirect.INHERIT}
+ * <li>the special value {@link #DISCARD Redirect.DISCARD}
* <li>a redirection to read from a file, created by an invocation of
* {@link Redirect#from Redirect.from(File)}
* <li>a redirection to write to a file, created by an invocation of
@@ -459,6 +461,13 @@
* @since 1.7
*/
public abstract static class Redirect {
+ private static final File NULL_FILE = AccessController.doPrivileged(
+ (PrivilegedAction<File>) () -> {
+ return new File((System.getProperty("os.name")
+ .startsWith("Windows") ? "NUL" : "/dev/null"));
+ }
+ );
+
/**
* The type of a {@link Redirect}.
*/
@@ -529,6 +538,28 @@
public Type type() { return Type.INHERIT; }
public String toString() { return type().toString(); }};
+
+ /**
+ * Indicates that subprocess output will be discarded.
+ * A typical implementation discards the output by writing to
+ * an operating system specific "null file".
+ *
+ * <p>It will always be true that
+ * <pre> {@code
+ * Redirect.DISCARD.file() the filename appropriate for the operating system
+ * and may be null &&
+ * Redirect.DISCARD.type() == Redirect.Type.WRITE &&
+ * Redirect.DISCARD.append() == false
+ * }</pre>
+ * @since 9
+ */
+ public static final Redirect DISCARD = new Redirect() {
+ public Type type() { return Type.WRITE; }
+ public String toString() { return type().toString(); }
+ public File file() { return NULL_FILE; }
+ boolean append() { return false; }
+ };
+
/**
* Returns the {@link File} source or destination associated
* with this redirect, or {@code null} if there is no such file.
--- a/jdk/src/java.base/share/classes/java/lang/ProcessHandle.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/ProcessHandle.java Wed Jul 05 20:51:27 2017 +0200
@@ -149,14 +149,15 @@
/**
* Returns a snapshot of the current direct children of the process.
- * A process that is {@link #isAlive not alive} has zero children.
+ * The {@link #parent} of a direct child process is the process.
+ * Typically, a process that is {@link #isAlive not alive} has no children.
* <p>
* <em>Note that processes are created and terminate asynchronously.
* There is no guarantee that a process is {@link #isAlive alive}.
* </em>
*
- * @return a Stream of ProcessHandles for processes that are direct children
- * of the process
+ * @return a sequential Stream of ProcessHandles for processes that are
+ * direct children of the process
* @throws SecurityException if a security manager has been installed and
* it denies RuntimePermission("manageProcess")
*/
@@ -164,14 +165,16 @@
/**
* Returns a snapshot of the current direct and indirect children of the process.
- * A process that is {@link #isAlive not alive} has zero children.
+ * An indirect child is one whose parent is either a direct child or
+ * another indirect child.
+ * Typically, a process that is {@link #isAlive not alive} has no children.
* <p>
* <em>Note that processes are created and terminate asynchronously.
* There is no guarantee that a process is {@link #isAlive alive}.
* </em>
*
- * @return a Stream of ProcessHandles for processes that are direct and
- * indirect children of the process
+ * @return a sequential Stream of ProcessHandles for processes that are
+ * direct and indirect children of the process
* @throws SecurityException if a security manager has been installed and
* it denies RuntimePermission("manageProcess")
*/
--- a/jdk/src/java.base/share/classes/java/lang/StrictMath.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/StrictMath.java Wed Jul 05 20:51:27 2017 +0200
@@ -1329,7 +1329,9 @@
* without intermediate overflow or underflow
* @since 1.5
*/
- public static native double hypot(double x, double y);
+ public static double hypot(double x, double y) {
+ return FdLibm.Hypot.compute(x, y);
+ }
/**
* Returns <i>e</i><sup>x</sup> -1. Note that for values of
--- a/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java Wed Jul 05 20:51:27 2017 +0200
@@ -404,6 +404,14 @@
d = lookupCache(types);
// Class loading must have upgraded the cache.
assert(d != null && !d.isPlaceholder());
+ if (OBSERVE_BMH_SPECIES_CREATION) {
+ if (d == null) {
+ throw new IllegalStateException("d == null");
+ }
+ if (d.isPlaceholder()) {
+ throw new IllegalStateException("d is place holder");
+ }
+ }
return d;
}
static SpeciesData getForClass(String types, Class<? extends BoundMethodHandle> clazz) {
@@ -415,6 +423,9 @@
if (d != null) return d;
d = new SpeciesData(types);
assert(d.isPlaceholder());
+ if (OBSERVE_BMH_SPECIES_CREATION && !d.isPlaceholder()) {
+ throw new IllegalStateException("d is not place holder");
+ }
CACHE.put(types, d);
return d;
}
@@ -422,6 +433,15 @@
SpeciesData d2;
assert((d2 = CACHE.get(types)) == null || d2.isPlaceholder());
assert(!d.isPlaceholder());
+ if (OBSERVE_BMH_SPECIES_CREATION) {
+ d2 = CACHE.get(types);
+ if (d2 != null && !d2.isPlaceholder()) {
+ throw new IllegalStateException("non-null d2 is not place holder");
+ }
+ if (d.isPlaceholder()) {
+ throw new IllegalStateException("d is place holder");
+ }
+ }
CACHE.put(types, d);
return d;
}
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java Wed Jul 05 20:51:27 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -51,8 +51,12 @@
static final boolean PROFILE_GWT;
static final int CUSTOMIZE_THRESHOLD;
+ // This is a temporary property added for improved error reporting; it will
+ // be removed once it has served its purpose.
+ static final boolean OBSERVE_BMH_SPECIES_CREATION;
+
static {
- final Object[] values = new Object[9];
+ final Object[] values = new Object[10];
AccessController.doPrivileged(new PrivilegedAction<>() {
public Void run() {
values[0] = Boolean.getBoolean("java.lang.invoke.MethodHandle.DEBUG_NAMES");
@@ -64,6 +68,7 @@
values[6] = Integer.getInteger("java.lang.invoke.MethodHandle.PROFILE_LEVEL", 0);
values[7] = Boolean.parseBoolean(System.getProperty("java.lang.invoke.MethodHandle.PROFILE_GWT", "true"));
values[8] = Integer.getInteger("java.lang.invoke.MethodHandle.CUSTOMIZE_THRESHOLD", 127);
+ values[9] = Boolean.getBoolean("java.lang.invoke.MethodHandle.OBSERVE_BMH_SPECIES_CREATION");
return null;
}
});
@@ -77,6 +82,8 @@
PROFILE_GWT = (Boolean) values[7];
CUSTOMIZE_THRESHOLD = (Integer) values[8];
+ OBSERVE_BMH_SPECIES_CREATION = (Boolean) values[9];
+
if (CUSTOMIZE_THRESHOLD < -1 || CUSTOMIZE_THRESHOLD > 127) {
throw newInternalError("CUSTOMIZE_THRESHOLD should be in [-1...127] range");
}
--- a/jdk/src/java.base/share/classes/java/time/Month.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/time/Month.java Wed Jul 05 20:51:27 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -379,7 +379,7 @@
//-----------------------------------------------------------------------
/**
- * Returns the month-of-year that is the specified number of quarters after this one.
+ * Returns the month-of-year that is the specified number of months after this one.
* <p>
* The calculation rolls around the end of the year from December to January.
* The specified period may be negative.
--- a/jdk/src/java.base/share/classes/java/time/temporal/TemporalAdjusters.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/time/temporal/TemporalAdjusters.java Wed Jul 05 20:51:27 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -313,7 +313,7 @@
/**
* Returns the day-of-week in month adjuster, which returns a new date
- * in the same month with the ordinal day-of-week.
+ * with the ordinal day-of-week based on the month.
* This is used for expressions like the 'second Tuesday in March'.
* <p>
* The ISO calendar system behaves as follows:<br>
--- a/jdk/src/java.base/share/classes/java/util/Locale.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/util/Locale.java Wed Jul 05 20:51:27 2017 +0200
@@ -825,7 +825,7 @@
* setDefault(Locale.Category, Locale) method.
*
* @param category - the specified category to get the default locale
- * @throws NullPointerException - if category is null
+ * @throws NullPointerException if category is null
* @return the default locale for the specified Category for this instance
* of the Java Virtual Machine
* @see #setDefault(Locale.Category, Locale)
@@ -954,9 +954,9 @@
*
* @param category - the specified category to set the default locale
* @param newLocale - the new default locale
- * @throws SecurityException - if a security manager exists and its
+ * @throws SecurityException if a security manager exists and its
* checkPermission method doesn't allow the operation.
- * @throws NullPointerException - if category and/or newLocale is null
+ * @throws NullPointerException if category and/or newLocale is null
* @see SecurityManager#checkPermission(java.security.Permission)
* @see PropertyPermission
* @see #getDefault(Locale.Category)
--- a/jdk/src/java.base/share/classes/java/util/stream/Collectors.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/java/util/stream/Collectors.java Wed Jul 05 20:51:27 2017 +0200
@@ -504,7 +504,7 @@
*/
public static <T> Collector<T, ?, Long>
counting() {
- return reducing(0L, e -> 1L, Long::sum);
+ return summingLong(e -> 1L);
}
/**
--- a/jdk/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java Wed Jul 05 20:51:27 2017 +0200
@@ -328,6 +328,7 @@
int rv = -1;
long p = -1;
int ti = -1;
+ long rp = -1;
try {
begin();
ti = threads.add();
@@ -363,8 +364,8 @@
if (p > newSize)
p = newSize;
do {
- rv = (int)position0(fd, p);
- } while ((rv == IOStatus.INTERRUPTED) && isOpen());
+ rp = position0(fd, p);
+ } while ((rp == IOStatus.INTERRUPTED) && isOpen());
return this;
} finally {
threads.remove(ti);
--- a/jdk/src/java.base/share/classes/sun/reflect/generics/factory/CoreReflectionFactory.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/generics/factory/CoreReflectionFactory.java Wed Jul 05 20:51:27 2017 +0200
@@ -70,20 +70,20 @@
/**
* Factory for this class. Returns an instance of
- * <tt>CoreReflectionFactory</tt> for the declaration and scope
+ * {@code CoreReflectionFactory} for the declaration and scope
* provided.
* This factory will produce reflective objects of the appropriate
* kind. Classes produced will be those that would be loaded by the
- * defining class loader of the declaration <tt>d</tt> (if <tt>d</tt>
+ * defining class loader of the declaration {@code d} (if {@code d}
* is a type declaration, or by the defining loader of the declaring
- * class of <tt>d</tt> otherwise.
+ * class of {@code d} otherwise.
* <p> Type variables will be created or lookup as necessary in the
- * scope <tt> s</tt>.
+ * scope {@code s}.
* @param d - the generic declaration (class, interface, method or
* constructor) that this factory services
* @param s the scope in which the factory will allocate and search for
* type variables
- * @return an instance of <tt>CoreReflectionFactory</tt>
+ * @return an instance of {@code CoreReflectionFactory}
*/
public static CoreReflectionFactory make(GenericDeclaration d, Scope s) {
return new CoreReflectionFactory(d, s);
--- a/jdk/src/java.base/share/classes/sun/reflect/generics/factory/GenericsFactory.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/generics/factory/GenericsFactory.java Wed Jul 05 20:51:27 2017 +0200
@@ -47,32 +47,32 @@
*/
public interface GenericsFactory {
/**
- * Returns a new type variable declaration. Note that <tt>name</tt>
- * may be empty (but not <tt>null</tt>). If <tt>bounds</tt> is
- * empty, a bound of <tt>java.lang.Object</tt> is used.
+ * Returns a new type variable declaration. Note that {@code name}
+ * may be empty (but not {@code null}). If {@code bounds} is
+ * empty, a bound of {@code java.lang.Object} is used.
* @param name The name of the type variable
* @param bounds An array of abstract syntax trees representing
* the upper bound(s) on the type variable being declared
* @return a new type variable declaration
- * @throws NullPointerException - if any of the actual parameters
- * or any of the elements of <tt>bounds</tt> are <tt>null</tt>.
+ * @throws NullPointerException if any of the actual parameters
+ * or any of the elements of {@code bounds} are {@code null}.
*/
TypeVariable<?> makeTypeVariable(String name,
FieldTypeSignature[] bounds);
/**
- * Returns an instance of the <tt>ParameterizedType</tt> interface
+ * Returns an instance of the {@code ParameterizedType} interface
* that corresponds to a generic type instantiation of the
- * generic declaration <tt>declaration</tt> with actual type arguments
- * <tt>typeArgs</tt>.
- * If <tt>owner</tt> is <tt>null</tt>, the declaring class of
- * <tt>declaration</tt> is used as the owner of this parameterized
+ * generic declaration {@code declaration} with actual type arguments
+ * {@code typeArgs}.
+ * If {@code owner} is {@code null}, the declaring class of
+ * {@code declaration} is used as the owner of this parameterized
* type.
* <p> This method throws a MalformedParameterizedTypeException
* under the following circumstances:
* If the type declaration does not represent a generic declaration
- * (i.e., it is not an instance of <tt>GenericDeclaration</tt>).
+ * (i.e., it is not an instance of {@code GenericDeclaration}).
* If the number of actual type arguments (i.e., the size of the
- * array <tt>typeArgs</tt>) does not correspond to the number of
+ * array {@code typeArgs}) does not correspond to the number of
* formal type arguments.
* If any of the actual type arguments is not an instance of the
* bounds on the corresponding formal.
@@ -81,39 +81,39 @@
* @param typeArgs - the list of actual type arguments
* @return - a parameterized type representing the instantiation
* of the declaration with the actual type arguments
- * @throws MalformedParameterizedTypeException - if the instantiation
+ * @throws MalformedParameterizedTypeException if the instantiation
* is invalid
- * @throws NullPointerException - if any of <tt>declaration</tt>
- * , <tt>typeArgs</tt>
- * or any of the elements of <tt>typeArgs</tt> are <tt>null</tt>
+ * @throws NullPointerException if any of {@code declaration},
+ * {@code typeArgs}
+ * or any of the elements of {@code typeArgs} are {@code null}
*/
ParameterizedType makeParameterizedType(Type declaration,
Type[] typeArgs,
Type owner);
/**
- * Returns the type variable with name <tt>name</tt>, if such
+ * Returns the type variable with name {@code name}, if such
* a type variable is declared in the
* scope used to create this factory.
- * Returns <tt>null</tt> otherwise.
+ * Returns {@code null} otherwise.
* @param name - the name of the type variable to search for
- * @return - the type variable with name <tt>name</tt>, or <tt>null</tt>
- * @throws NullPointerException - if any of actual parameters are
- * <tt>null</tt>
+ * @return - the type variable with name {@code name}, or {@code null}
+ * @throws NullPointerException if any of actual parameters are
+ * {@code null}
*/
TypeVariable<?> findTypeVariable(String name);
/**
* Returns a new wildcard type variable. If
- * <tt>ubs</tt> is empty, a bound of <tt>java.lang.Object</tt> is used.
+ * {@code ubs} is empty, a bound of {@code java.lang.Object} is used.
* @param ubs An array of abstract syntax trees representing
* the upper bound(s) on the type variable being declared
* @param lbs An array of abstract syntax trees representing
* the lower bound(s) on the type variable being declared
* @return a new wildcard type variable
- * @throws NullPointerException - if any of the actual parameters
- * or any of the elements of <tt>ubs</tt> or <tt>lbs</tt>are
- * <tt>null</tt>
+ * @throws NullPointerException if any of the actual parameters
+ * or any of the elements of {@code ubs} or {@code lbs} are
+ * {@code null}
*/
WildcardType makeWildcard(FieldTypeSignature[] ubs,
FieldTypeSignature[] lbs);
@@ -127,64 +127,64 @@
* a MalformedParameterizedTypeException is thrown.
* @param componentType - the component type of the array
* @return a (possibly generic) array type.
- * @throws MalformedParameterizedTypeException if <tt>componentType</tt>
+ * @throws MalformedParameterizedTypeException if {@code componentType}
* is a parameterized type with non-wildcard type arguments
- * @throws NullPointerException - if any of the actual parameters
- * are <tt>null</tt>
+ * @throws NullPointerException if any of the actual parameters
+ * are {@code null}
*/
Type makeArrayType(Type componentType);
/**
- * Returns the reflective representation of type <tt>byte</tt>.
- * @return the reflective representation of type <tt>byte</tt>.
+ * Returns the reflective representation of type {@code byte}.
+ * @return the reflective representation of type {@code byte}.
*/
Type makeByte();
/**
- * Returns the reflective representation of type <tt>boolean</tt>.
- * @return the reflective representation of type <tt>boolean</tt>.
+ * Returns the reflective representation of type {@code boolean}.
+ * @return the reflective representation of type {@code boolean}.
*/
Type makeBool();
/**
- * Returns the reflective representation of type <tt>short</tt>.
- * @return the reflective representation of type <tt>short</tt>.
+ * Returns the reflective representation of type {@code short}.
+ * @return the reflective representation of type {@code short}.
*/
Type makeShort();
/**
- * Returns the reflective representation of type <tt>char</tt>.
- * @return the reflective representation of type <tt>char</tt>.
+ * Returns the reflective representation of type {@code char}.
+ * @return the reflective representation of type {@code char}.
*/
Type makeChar();
/**
- * Returns the reflective representation of type <tt>int</tt>.
- * @return the reflective representation of type <tt>int</tt>.
+ * Returns the reflective representation of type {@code int}.
+ * @return the reflective representation of type {@code int}.
*/
Type makeInt();
/**
- * Returns the reflective representation of type <tt>long</tt>.
- * @return the reflective representation of type <tt>long</tt>.
+ * Returns the reflective representation of type {@code long}.
+ * @return the reflective representation of type {@code long}.
*/
Type makeLong();
/**
- * Returns the reflective representation of type <tt>float</tt>.
- * @return the reflective representation of type <tt>float</tt>.
+ * Returns the reflective representation of type {@code float}.
+ * @return the reflective representation of type {@code float}.
*/
Type makeFloat();
/**
- * Returns the reflective representation of type <tt>double</tt>.
- * @return the reflective representation of type <tt>double</tt>.
+ * Returns the reflective representation of type {@code double}.
+ * @return the reflective representation of type {@code double}.
*/
Type makeDouble();
/**
- * Returns the reflective representation of <tt>void</tt>.
- * @return the reflective representation of <tt>void</tt>.
+ * Returns the reflective representation of {@code void}.
+ * @return the reflective representation of {@code void}.
*/
Type makeVoid();
}
--- a/jdk/src/java.base/share/classes/sun/reflect/generics/parser/SignatureParser.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/generics/parser/SignatureParser.java Wed Jul 05 20:51:27 2017 +0200
@@ -135,7 +135,7 @@
/**
* Static factory method. Produces a parser instance.
- * @return an instance of <tt>SignatureParser</tt>
+ * @return an instance of {@code SignatureParser}
*/
public static SignatureParser make() {
return new SignatureParser();
--- a/jdk/src/java.base/share/classes/sun/reflect/generics/reflectiveObjects/GenericArrayTypeImpl.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/generics/reflectiveObjects/GenericArrayTypeImpl.java Wed Jul 05 20:51:27 2017 +0200
@@ -53,10 +53,10 @@
/**
- * Returns a <tt>Type</tt> object representing the component type
+ * Returns a {@code Type} object representing the component type
* of this array.
*
- * @return a <tt>Type</tt> object representing the component type
+ * @return a {@code Type} object representing the component type
* of this array
* @since 1.5
*/
--- a/jdk/src/java.base/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java Wed Jul 05 20:51:27 2017 +0200
@@ -46,7 +46,7 @@
import sun.reflect.misc.ReflectUtil;
/**
- * Implementation of <tt>java.lang.reflect.TypeVariable</tt> interface
+ * Implementation of {@code java.lang.reflect.TypeVariable} interface
* for core reflection.
*/
public class TypeVariableImpl<D extends GenericDeclaration>
@@ -99,9 +99,9 @@
/**
- * Returns an array of <tt>Type</tt> objects representing the
+ * Returns an array of {@code Type} objects representing the
* upper bound(s) of this type variable. Note that if no upper bound is
- * explicitly declared, the upper bound is <tt>Object</tt>.
+ * explicitly declared, the upper bound is {@code Object}.
*
* <p>For each upper bound B:
* <ul>
@@ -111,9 +111,9 @@
* <li>Otherwise, B is resolved.
* </ul>
*
- * @throws <tt>TypeNotPresentException</tt> if any of the
+ * @throws {@code TypeNotPresentException} if any of the
* bounds refers to a non-existent type declaration
- * @throws <tt>MalformedParameterizedTypeException</tt> if any of the
+ * @throws {@code MalformedParameterizedTypeException} if any of the
* bounds refer to a parameterized type that cannot be instantiated
* for any reason
* @return an array of Types representing the upper bound(s) of this
@@ -129,7 +129,7 @@
}
/**
- * Returns the <tt>GenericDeclaration</tt> object representing the
+ * Returns the {@code GenericDeclaration} object representing the
* generic declaration that declared this type variable.
*
* @return the generic declaration that declared this type variable.
--- a/jdk/src/java.base/share/classes/sun/reflect/generics/reflectiveObjects/WildcardTypeImpl.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/generics/reflectiveObjects/WildcardTypeImpl.java Wed Jul 05 20:51:27 2017 +0200
@@ -78,9 +78,9 @@
}
/**
- * Returns an array of <tt>Type</tt> objects representing the upper
+ * Returns an array of {@code Type} objects representing the upper
* bound(s) of this type variable. Note that if no upper bound is
- * explicitly declared, the upper bound is <tt>Object</tt>.
+ * explicitly declared, the upper bound is {@code Object}.
*
* <p>For each upper bound B :
* <ul>
@@ -92,9 +92,9 @@
*
* @return an array of Types representing the upper bound(s) of this
* type variable
- * @throws <tt>TypeNotPresentException</tt> if any of the
+ * @throws {@code TypeNotPresentException} if any of the
* bounds refers to a non-existent type declaration
- * @throws <tt>MalformedParameterizedTypeException</tt> if any of the
+ * @throws {@code MalformedParameterizedTypeException} if any of the
* bounds refer to a parameterized type that cannot be instantiated
* for any reason
*/
@@ -108,9 +108,9 @@
}
/**
- * Returns an array of <tt>Type</tt> objects representing the
+ * Returns an array of {@code Type} objects representing the
* lower bound(s) of this type variable. Note that if no lower bound is
- * explicitly declared, the lower bound is the type of <tt>null</tt>.
+ * explicitly declared, the lower bound is the type of {@code null}.
* In this case, a zero length array is returned.
*
* <p>For each lower bound B :
@@ -123,9 +123,9 @@
*
* @return an array of Types representing the lower bound(s) of this
* type variable
- * @throws <tt>TypeNotPresentException</tt> if any of the
+ * @throws {@code TypeNotPresentException} if any of the
* bounds refers to a non-existent type declaration
- * @throws <tt>MalformedParameterizedTypeException</tt> if any of the
+ * @throws {@code MalformedParameterizedTypeException} if any of the
* bounds refer to a parameterized type that cannot be instantiated
* for any reason
*/
--- a/jdk/src/java.base/share/classes/sun/reflect/generics/repository/AbstractRepository.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/generics/repository/AbstractRepository.java Wed Jul 05 20:51:27 2017 +0200
@@ -48,15 +48,15 @@
private GenericsFactory getFactory() { return factory;}
/**
- * Accessor for <tt>tree</tt>.
+ * Accessor for {@code tree}.
* @return the cached AST this repository holds
*/
protected T getTree(){ return tree;}
/**
- * Returns a <tt>Reifier</tt> used to convert parts of the
+ * Returns a {@code Reifier} used to convert parts of the
* AST into reflective objects.
- * @return a <tt>Reifier</tt> used to convert parts of the
+ * @return a {@code Reifier} used to convert parts of the
* AST into reflective objects
*/
protected Reifier getReifier(){return Reifier.make(getFactory());}
--- a/jdk/src/java.base/share/classes/sun/reflect/generics/repository/ClassRepository.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/generics/repository/ClassRepository.java Wed Jul 05 20:51:27 2017 +0200
@@ -63,8 +63,8 @@
* that this repository is servicing
* @param f - a factory that will provide instances of reflective
* objects when this repository converts its AST
- * @return a <tt>ClassRepository</tt> that manages the generic type
- * information represented in the signature <tt>rawSig</tt>
+ * @return a {@code ClassRepository} that manages the generic type
+ * information represented in the signature {@code rawSig}
*/
public static ClassRepository make(String rawSig, GenericsFactory f) {
return new ClassRepository(rawSig, f);
--- a/jdk/src/java.base/share/classes/sun/reflect/generics/repository/ConstructorRepository.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/generics/repository/ConstructorRepository.java Wed Jul 05 20:51:27 2017 +0200
@@ -64,8 +64,8 @@
* that this repository is servicing
* @param f - a factory that will provide instances of reflective
* objects when this repository converts its AST
- * @return a <tt>ConstructorRepository</tt> that manages the generic type
- * information represented in the signature <tt>rawSig</tt>
+ * @return a {@code ConstructorRepository} that manages the generic type
+ * information represented in the signature {@code rawSig}
*/
public static ConstructorRepository make(String rawSig, GenericsFactory f) {
return new ConstructorRepository(rawSig, f);
--- a/jdk/src/java.base/share/classes/sun/reflect/generics/repository/FieldRepository.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/generics/repository/FieldRepository.java Wed Jul 05 20:51:27 2017 +0200
@@ -59,8 +59,8 @@
* that this repository is servicing
* @param f - a factory that will provide instances of reflective
* objects when this repository converts its AST
- * @return a <tt>FieldRepository</tt> that manages the generic type
- * information represented in the signature <tt>rawSig</tt>
+ * @return a {@code FieldRepository} that manages the generic type
+ * information represented in the signature {@code rawSig}
*/
public static FieldRepository make(String rawSig, GenericsFactory f) {
return new FieldRepository(rawSig, f);
--- a/jdk/src/java.base/share/classes/sun/reflect/generics/repository/MethodRepository.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/generics/repository/MethodRepository.java Wed Jul 05 20:51:27 2017 +0200
@@ -53,8 +53,8 @@
* that this repository is servicing
* @param f - a factory that will provide instances of reflective
* objects when this repository converts its AST
- * @return a <tt>MethodRepository</tt> that manages the generic type
- * information represented in the signature <tt>rawSig</tt>
+ * @return a {@code MethodRepository} that manages the generic type
+ * information represented in the signature {@code rawSig}
*/
public static MethodRepository make(String rawSig, GenericsFactory f) {
return new MethodRepository(rawSig, f);
--- a/jdk/src/java.base/share/classes/sun/reflect/generics/scope/AbstractScope.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/generics/scope/AbstractScope.java Wed Jul 05 20:51:27 2017 +0200
@@ -32,10 +32,10 @@
/**
* Abstract superclass for lazy scope objects, used when building
* factories for generic information repositories.
- * The type parameter <tt>D</tt> represents the type of reflective
+ * The type parameter {@code D} represents the type of reflective
* object whose scope this class is representing.
* <p> To subclass this, all one needs to do is implement
- * <tt>computeEnclosingScope</tt> and the subclass' constructor.
+ * {@code computeEnclosingScope} and the subclass' constructor.
*/
public abstract class AbstractScope<D extends GenericDeclaration>
implements Scope {
@@ -54,9 +54,9 @@
protected AbstractScope(D decl){ recvr = decl;}
/**
- * Accessor for the receiver - the object whose scope this <tt>Scope</tt>
+ * Accessor for the receiver - the object whose scope this {@code Scope}
* object represents.
- * @return The object whose scope this <tt>Scope</tt> object represents
+ * @return The object whose scope this {@code Scope} object represents
*/
protected D getRecvr() {return recvr;}
--- a/jdk/src/java.base/share/classes/sun/reflect/generics/scope/ClassScope.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/generics/scope/ClassScope.java Wed Jul 05 20:51:27 2017 +0200
@@ -73,7 +73,7 @@
}
/**
- * Factory method. Takes a <tt>Class</tt> object and creates a
+ * Factory method. Takes a {@code Class} object and creates a
* scope for it.
* @param c - a Class whose scope we want to obtain
* @return The type-variable scope for the class c
--- a/jdk/src/java.base/share/classes/sun/reflect/generics/scope/DummyScope.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/generics/scope/DummyScope.java Wed Jul 05 20:51:27 2017 +0200
@@ -29,9 +29,9 @@
/**
* This class is used to provide enclosing scopes for top level classes.
- * We cannot use <tt>null</tt> to represent such a scope, since the
+ * We cannot use {@code null} to represent such a scope, since the
* enclosing scope is computed lazily, and so the field storing it is
- * null until it has been computed. Therefore, <tt>null</tt> is reserved
+ * null until it has been computed. Therefore, {@code null} is reserved
* to represent an as-yet-uncomputed scope, and cannot be used for any
* other kind of scope.
*/
@@ -53,7 +53,7 @@
/**
* Lookup a type variable in the scope, using its name. Always returns
- * <tt>null</tt>.
+ * {@code null}.
* @param name - the name of the type variable being looked up
* @return null
*/
--- a/jdk/src/java.base/share/classes/sun/reflect/generics/scope/MethodScope.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/generics/scope/MethodScope.java Wed Jul 05 20:51:27 2017 +0200
@@ -56,7 +56,7 @@
}
/**
- * Factory method. Takes a <tt>Method</tt> object and creates a
+ * Factory method. Takes a {@code Method} object and creates a
* scope for it.
* @param m - A Method whose scope we want to obtain
* @return The type-variable scope for the method m
--- a/jdk/src/java.base/share/classes/sun/reflect/generics/tree/TypeTree.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/generics/tree/TypeTree.java Wed Jul 05 20:51:27 2017 +0200
@@ -33,7 +33,7 @@
public interface TypeTree extends Tree {
/**
* Accept method for the visitor pattern.
- * @param v - a <tt>TypeTreeVisitor</tt> that will process this
+ * @param v a {@code TypeTreeVisitor} that will process this
* tree
*/
void accept(TypeTreeVisitor<?> v);
--- a/jdk/src/java.base/share/classes/sun/reflect/generics/visitor/Reifier.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/classes/sun/reflect/generics/visitor/Reifier.java Wed Jul 05 20:51:27 2017 +0200
@@ -50,7 +50,7 @@
/**
* Factory method. The resulting visitor will convert an AST
* representing generic signatures into corresponding reflective
- * objects, using the provided factory, <tt>f</tt>.
+ * objects, using the provided factory, {@code f}.
* @param f - a factory that can be used to manufacture reflective
* objects returned by this visitor
* @return A visitor that can be used to reify ASTs representing
--- a/jdk/src/java.base/share/native/libfdlibm/e_hypot.c Sat Sep 26 09:22:24 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,128 +0,0 @@
-
-/*
- * Copyright (c) 1998, 2001, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/* __ieee754_hypot(x,y)
- *
- * Method :
- * If (assume round-to-nearest) z=x*x+y*y
- * has error less than sqrt(2)/2 ulp, than
- * sqrt(z) has error less than 1 ulp (exercise).
- *
- * So, compute sqrt(x*x+y*y) with some care as
- * follows to get the error below 1 ulp:
- *
- * Assume x>y>0;
- * (if possible, set rounding to round-to-nearest)
- * 1. if x > 2y use
- * x1*x1+(y*y+(x2*(x+x1))) for x*x+y*y
- * where x1 = x with lower 32 bits cleared, x2 = x-x1; else
- * 2. if x <= 2y use
- * t1*y1+((x-y)*(x-y)+(t1*y2+t2*y))
- * where t1 = 2x with lower 32 bits cleared, t2 = 2x-t1,
- * y1= y with lower 32 bits chopped, y2 = y-y1.
- *
- * NOTE: scaling may be necessary if some argument is too
- * large or too tiny
- *
- * Special cases:
- * hypot(x,y) is INF if x or y is +INF or -INF; else
- * hypot(x,y) is NAN if x or y is NAN.
- *
- * Accuracy:
- * hypot(x,y) returns sqrt(x^2+y^2) with error less
- * than 1 ulps (units in the last place)
- */
-
-#include "fdlibm.h"
-
-#ifdef __STDC__
- double __ieee754_hypot(double x, double y)
-#else
- double __ieee754_hypot(x,y)
- double x, y;
-#endif
-{
- double a=x,b=y,t1,t2,y1,y2,w;
- int j,k,ha,hb;
-
- ha = __HI(x)&0x7fffffff; /* high word of x */
- hb = __HI(y)&0x7fffffff; /* high word of y */
- if(hb > ha) {a=y;b=x;j=ha; ha=hb;hb=j;} else {a=x;b=y;}
- __HI(a) = ha; /* a <- |a| */
- __HI(b) = hb; /* b <- |b| */
- if((ha-hb)>0x3c00000) {return a+b;} /* x/y > 2**60 */
- k=0;
- if(ha > 0x5f300000) { /* a>2**500 */
- if(ha >= 0x7ff00000) { /* Inf or NaN */
- w = a+b; /* for sNaN */
- if(((ha&0xfffff)|__LO(a))==0) w = a;
- if(((hb^0x7ff00000)|__LO(b))==0) w = b;
- return w;
- }
- /* scale a and b by 2**-600 */
- ha -= 0x25800000; hb -= 0x25800000; k += 600;
- __HI(a) = ha;
- __HI(b) = hb;
- }
- if(hb < 0x20b00000) { /* b < 2**-500 */
- if(hb <= 0x000fffff) { /* subnormal b or 0 */
- if((hb|(__LO(b)))==0) return a;
- t1=0;
- __HI(t1) = 0x7fd00000; /* t1=2^1022 */
- b *= t1;
- a *= t1;
- k -= 1022;
- } else { /* scale a and b by 2^600 */
- ha += 0x25800000; /* a *= 2^600 */
- hb += 0x25800000; /* b *= 2^600 */
- k -= 600;
- __HI(a) = ha;
- __HI(b) = hb;
- }
- }
- /* medium size a and b */
- w = a-b;
- if (w>b) {
- t1 = 0;
- __HI(t1) = ha;
- t2 = a-t1;
- w = sqrt(t1*t1-(b*(-b)-t2*(a+t1)));
- } else {
- a = a+a;
- y1 = 0;
- __HI(y1) = hb;
- y2 = b - y1;
- t1 = 0;
- __HI(t1) = ha+0x00100000;
- t2 = a - t1;
- w = sqrt(t1*y1-(w*(-w)-(t1*y2+t2*b)));
- }
- if(k!=0) {
- t1 = 1.0;
- __HI(t1) += (k<<20);
- return t1*w;
- } else return w;
-}
--- a/jdk/src/java.base/share/native/libfdlibm/w_hypot.c Sat Sep 26 09:22:24 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-
-/*
- * Copyright (c) 1998, 2001, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * wrapper hypot(x,y)
- */
-
-#include "fdlibm.h"
-
-
-#ifdef __STDC__
- double hypot(double x, double y)/* wrapper hypot */
-#else
- double hypot(x,y) /* wrapper hypot */
- double x,y;
-#endif
-{
-#ifdef _IEEE_LIBM
- return __ieee754_hypot(x,y);
-#else
- double z;
- z = __ieee754_hypot(x,y);
- if(_LIB_VERSION == _IEEE_) return z;
- if((!finite(z))&&finite(x)&&finite(y))
- return __kernel_standard(x,y,4); /* hypot overflow */
- else
- return z;
-#endif
-}
--- a/jdk/src/java.base/share/native/libjava/StrictMath.c Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/native/libjava/StrictMath.c Wed Jul 05 20:51:27 2017 +0200
@@ -127,14 +127,6 @@
}
JNIEXPORT jdouble JNICALL
-Java_java_lang_StrictMath_hypot(JNIEnv *env, jclass unused, jdouble x, jdouble y)
-{
- return (jdouble) jhypot((double)x, (double)y);
-}
-
-
-
-JNIEXPORT jdouble JNICALL
Java_java_lang_StrictMath_log1p(JNIEnv *env, jclass unused, jdouble d)
{
return (jdouble) jlog1p((double)d);
--- a/jdk/src/java.base/share/native/libjimage/ImageNativeSubstrate.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/native/libjimage/ImageNativeSubstrate.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
@@ -19,7 +21,6 @@
* 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 <string.h>
--- a/jdk/src/java.base/share/native/libjimage/endian.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/native/libjimage/endian.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -4,11 +4,13 @@
*
* 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.
+ * 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
+ * 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).
*
@@ -19,7 +21,6 @@
* 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 "endian.hpp"
@@ -27,20 +28,20 @@
// Most modern compilers optimize the bswap routines to native instructions.
inline static u2 bswap_16(u2 x) {
- return ((x & 0xFF) << 8) |
- ((x >> 8) & 0xFF);
+ return ((x & 0xFF) << 8) |
+ ((x >> 8) & 0xFF);
}
inline static u4 bswap_32(u4 x) {
- return ((x & 0xFF) << 24) |
- ((x & 0xFF00) << 8) |
- ((x >> 8) & 0xFF00) |
- ((x >> 24) & 0xFF);
+ return ((x & 0xFF) << 24) |
+ ((x & 0xFF00) << 8) |
+ ((x >> 8) & 0xFF00) |
+ ((x >> 24) & 0xFF);
}
inline static u8 bswap_64(u8 x) {
- return (u8)bswap_32((u4)x) << 32 |
- (u8)bswap_32((u4)(x >> 32));
+ return (u8)bswap_32((u4)x) << 32 |
+ (u8)bswap_32((u4)(x >> 32));
}
u2 NativeEndian::get(u2 x) { return x; }
@@ -76,27 +77,27 @@
SwappingEndian SwappingEndian::_swapping;
Endian* Endian::get_handler(bool big_endian) {
- // If requesting little endian on a little endian machine or
- // big endian on a big endian machine use native handler
- if (big_endian == is_big_endian()) {
- return NativeEndian::get_native();
- } else {
- // Use swapping handler.
- return SwappingEndian::get_swapping();
- }
+ // If requesting little endian on a little endian machine or
+ // big endian on a big endian machine use native handler
+ if (big_endian == is_big_endian()) {
+ return NativeEndian::get_native();
+ } else {
+ // Use swapping handler.
+ return SwappingEndian::get_swapping();
+ }
}
// Return a platform u2 from an array in which Big Endian is applied.
u2 Endian::get_java(u1* x) {
- return (u2) (x[0]<<8 | x[1]);
+ return (u2) (x[0]<<8 | x[1]);
}
// Add a platform u2 to the array as a Big Endian u2
void Endian::set_java(u1* p, u2 x) {
- p[0] = (x >> 8) & 0xff;
- p[1] = x & 0xff;
+ p[0] = (x >> 8) & 0xff;
+ p[1] = x & 0xff;
}
Endian* Endian::get_native_handler() {
- return NativeEndian::get_native();
+ return NativeEndian::get_native();
}
--- a/jdk/src/java.base/share/native/libjimage/endian.hpp Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/native/libjimage/endian.hpp Wed Jul 05 20:51:27 2017 +0200
@@ -4,11 +4,13 @@
*
* 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.
+ * 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
+ * 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).
*
@@ -19,7 +21,6 @@
* 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.
- *
*/
#ifndef LIBJIMAGE_ENDIAN_HPP
@@ -36,89 +37,89 @@
// To retrieve a value using the approprate endian, use one of the overloaded
// calls to get. To set a value, then use one of the overloaded set calls.
// Ex.
-// s4 value; // Imported value;
-// ...
-// Endian* endian = Endian::get_handler(true); // Use big endian
-// s4 corrected = endian->get(value);
-// endian->set(value, 1);
+// s4 value; // Imported value;
+// ...
+// Endian* endian = Endian::get_handler(true); // Use big endian
+// s4 corrected = endian->get(value);
+// endian->set(value, 1);
//
class Endian {
public:
- virtual u2 get(u2 x) = 0;
- virtual u4 get(u4 x) = 0;
- virtual u8 get(u8 x) = 0;
- virtual s2 get(s2 x) = 0;
- virtual s4 get(s4 x) = 0;
- virtual s8 get(s8 x) = 0;
+ virtual u2 get(u2 x) = 0;
+ virtual u4 get(u4 x) = 0;
+ virtual u8 get(u8 x) = 0;
+ virtual s2 get(s2 x) = 0;
+ virtual s4 get(s4 x) = 0;
+ virtual s8 get(s8 x) = 0;
- virtual void set(u2& x, u2 y) = 0;
- virtual void set(u4& x, u4 y) = 0;
- virtual void set(u8& x, u8 y) = 0;
- virtual void set(s2& x, s2 y) = 0;
- virtual void set(s4& x, s4 y) = 0;
- virtual void set(s8& x, s8 y) = 0;
+ virtual void set(u2& x, u2 y) = 0;
+ virtual void set(u4& x, u4 y) = 0;
+ virtual void set(u8& x, u8 y) = 0;
+ virtual void set(s2& x, s2 y) = 0;
+ virtual void set(s4& x, s4 y) = 0;
+ virtual void set(s8& x, s8 y) = 0;
- // Quick little endian test.
- static bool is_little_endian() { u4 x = 1; return *(u1 *)&x != 0; }
+ // Quick little endian test.
+ static bool is_little_endian() { u4 x = 1; return *(u1 *)&x != 0; }
- // Quick big endian test.
- static bool is_big_endian() { return !is_little_endian(); }
+ // Quick big endian test.
+ static bool is_big_endian() { return !is_little_endian(); }
- // Select an appropriate endian handler.
- static Endian* get_handler(bool big_endian);
+ // Select an appropriate endian handler.
+ static Endian* get_handler(bool big_endian);
- // Return the native endian handler.
- static Endian* get_native_handler();
+ // Return the native endian handler.
+ static Endian* get_native_handler();
- // get platform u2 from Java Big endian
- static u2 get_java(u1* x);
- // set platform u2 to Java Big endian
- static void set_java(u1* p, u2 x);
+ // get platform u2 from Java Big endian
+ static u2 get_java(u1* x);
+ // set platform u2 to Java Big endian
+ static void set_java(u1* p, u2 x);
};
// Normal endian handling.
class NativeEndian : public Endian {
private:
- static NativeEndian _native;
+ static NativeEndian _native;
public:
- u2 get(u2 x);
- u4 get(u4 x);
- u8 get(u8 x);
- s2 get(s2 x);
- s4 get(s4 x);
- s8 get(s8 x);
+ u2 get(u2 x);
+ u4 get(u4 x);
+ u8 get(u8 x);
+ s2 get(s2 x);
+ s4 get(s4 x);
+ s8 get(s8 x);
- void set(u2& x, u2 y);
- void set(u4& x, u4 y);
- void set(u8& x, u8 y);
- void set(s2& x, s2 y);
- void set(s4& x, s4 y);
- void set(s8& x, s8 y);
+ void set(u2& x, u2 y);
+ void set(u4& x, u4 y);
+ void set(u8& x, u8 y);
+ void set(s2& x, s2 y);
+ void set(s4& x, s4 y);
+ void set(s8& x, s8 y);
- static Endian* get_native() { return &_native; }
+ static Endian* get_native() { return &_native; }
};
// Swapping endian handling.
class SwappingEndian : public Endian {
private:
- static SwappingEndian _swapping;
+ static SwappingEndian _swapping;
public:
- u2 get(u2 x);
- u4 get(u4 x);
- u8 get(u8 x);
- s2 get(s2 x);
- s4 get(s4 x);
- s8 get(s8 x);
+ u2 get(u2 x);
+ u4 get(u4 x);
+ u8 get(u8 x);
+ s2 get(s2 x);
+ s4 get(s4 x);
+ s8 get(s8 x);
- void set(u2& x, u2 y);
- void set(u4& x, u4 y);
- void set(u8& x, u8 y);
- void set(s2& x, s2 y);
- void set(s4& x, s4 y);
- void set(s8& x, s8 y);
+ void set(u2& x, u2 y);
+ void set(u4& x, u4 y);
+ void set(u8& x, u8 y);
+ void set(s2& x, s2 y);
+ void set(s4& x, s4 y);
+ void set(s8& x, s8 y);
- static Endian* get_swapping() { return &_swapping; }
+ static Endian* get_swapping() { return &_swapping; }
};
#endif // LIBJIMAGE_ENDIAN_HPP
--- a/jdk/src/java.base/share/native/libjimage/imageDecompressor.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/native/libjimage/imageDecompressor.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -4,11 +4,13 @@
*
* 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.
+ * 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
+ * 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).
*
@@ -19,10 +21,8 @@
* 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 "jni.h"
#include "imageDecompressor.hpp"
#include "endian.hpp"
@@ -32,16 +32,17 @@
#include <dlfcn.h>
#endif
-typedef jboolean (JNICALL *ZipInflateFully_t)(void *inBuf, jlong inLen, void *outBuf, jlong outLen, char **pmsg);
-static ZipInflateFully_t ZipInflateFully = NULL;
+typedef jboolean (JNICALL *ZipInflateFully_t)(void *inBuf, jlong inLen,
+ void *outBuf, jlong outLen, char **pmsg);
+static ZipInflateFully_t ZipInflateFully = NULL;
#ifndef WIN32
- #define JNI_LIB_PREFIX "lib"
- #ifdef __APPLE__
- #define JNI_LIB_SUFFIX ".dylib"
- #else
- #define JNI_LIB_SUFFIX ".so"
- #endif
+ #define JNI_LIB_PREFIX "lib"
+ #ifdef __APPLE__
+ #define JNI_LIB_SUFFIX ".dylib"
+ #else
+ #define JNI_LIB_SUFFIX ".so"
+ #endif
#endif
/**
@@ -50,21 +51,21 @@
* @return the address of the entry point or NULL
*/
static void* findEntry(const char* name) {
- void *addr = NULL;
+ void *addr = NULL;
#ifdef WIN32
- HMODULE handle = GetModuleHandle("zip.dll");
- if (handle == NULL) {
- return NULL;
- }
- addr = (void*) GetProcAddress(handle, name);
- return addr;
+ HMODULE handle = GetModuleHandle("zip.dll");
+ if (handle == NULL) {
+ return NULL;
+ }
+ addr = (void*) GetProcAddress(handle, name);
+ return addr;
#else
- addr = dlopen(JNI_LIB_PREFIX "zip" JNI_LIB_SUFFIX, RTLD_GLOBAL|RTLD_LAZY);
- if (addr == NULL) {
- return NULL;
- }
- addr = dlsym(addr, name);
- return addr;
+ addr = dlopen(JNI_LIB_PREFIX "zip" JNI_LIB_SUFFIX, RTLD_GLOBAL|RTLD_LAZY);
+ if (addr == NULL) {
+ return NULL;
+ }
+ addr = dlsym(addr, name);
+ return addr;
#endif
}
@@ -74,87 +75,87 @@
int ImageDecompressor::_decompressors_num = 0;
ImageDecompressor** ImageDecompressor::_decompressors = NULL;
void ImageDecompressor::image_decompressor_init() {
- if (_decompressors == NULL) {
- ZipInflateFully = (ZipInflateFully_t) findEntry("ZIP_InflateFully");
- assert(ZipInflateFully != NULL && "ZIP decompressor not found.");
- _decompressors_num = 2;
- _decompressors = new ImageDecompressor*[_decompressors_num];
- _decompressors[0] = new ZipDecompressor("zip");
- _decompressors[1] = new SharedStringDecompressor("compact-cp");
- }
+ if (_decompressors == NULL) {
+ ZipInflateFully = (ZipInflateFully_t) findEntry("ZIP_InflateFully");
+ assert(ZipInflateFully != NULL && "ZIP decompressor not found.");
+ _decompressors_num = 2;
+ _decompressors = new ImageDecompressor*[_decompressors_num];
+ _decompressors[0] = new ZipDecompressor("zip");
+ _decompressors[1] = new SharedStringDecompressor("compact-cp");
+ }
}
void ImageDecompressor::image_decompressor_close() {
- delete _decompressors;
+ delete _decompressors;
}
/*
* Locate decompressor.
*/
ImageDecompressor* ImageDecompressor::get_decompressor(const char * decompressor_name) {
- image_decompressor_init();
- for (int i = 0; i < _decompressors_num; i++) {
- ImageDecompressor* decompressor = _decompressors[i];
- assert(decompressor != NULL && "Decompressors not initialized.");
- if (strcmp(decompressor->get_name(), decompressor_name) == 0) {
- return decompressor;
+ image_decompressor_init();
+ for (int i = 0; i < _decompressors_num; i++) {
+ ImageDecompressor* decompressor = _decompressors[i];
+ assert(decompressor != NULL && "Decompressors not initialized.");
+ if (strcmp(decompressor->get_name(), decompressor_name) == 0) {
+ return decompressor;
+ }
}
- }
- assert(false && "No decompressor found.");
- return NULL;
+ assert(false && "No decompressor found.");
+ return NULL;
}
/*
* Decompression entry point. Called from ImageFileReader::get_resource.
*/
void ImageDecompressor::decompress_resource(u1* compressed, u1* uncompressed,
- u4 uncompressed_size, const ImageStrings* strings) {
- bool has_header = false;
- u1* decompressed_resource = compressed;
- u1* compressed_resource = compressed;
+ u4 uncompressed_size, const ImageStrings* strings) {
+ bool has_header = false;
+ u1* decompressed_resource = compressed;
+ u1* compressed_resource = compressed;
- // Resource could have been transformed by a stack of decompressors.
- // Iterate and decompress resources until there is no more header.
- do {
- ResourceHeader _header;
- memcpy(&_header, compressed_resource, sizeof (ResourceHeader));
- has_header = _header._magic == ResourceHeader::resource_header_magic;
- if (has_header) {
- // decompressed_resource array contains the result of decompression
- decompressed_resource = new u1[_header._uncompressed_size];
- // Retrieve the decompressor name
- const char* decompressor_name = strings->get(_header._decompressor_name_offset);
- assert(decompressor_name && "image decompressor not found");
- // Retrieve the decompressor instance
- ImageDecompressor* decompressor = get_decompressor(decompressor_name);
- assert(decompressor && "image decompressor not found");
- u1* compressed_resource_base = compressed_resource;
- compressed_resource += ResourceHeader::resource_header_length;
- // Ask the decompressor to decompress the compressed content
- decompressor->decompress_resource(compressed_resource, decompressed_resource,
- &_header, strings);
- if (compressed_resource_base != compressed) {
- delete compressed_resource_base;
- }
- compressed_resource = decompressed_resource;
- }
- } while (has_header);
- memcpy(uncompressed, decompressed_resource, uncompressed_size);
- delete decompressed_resource;
+ // Resource could have been transformed by a stack of decompressors.
+ // Iterate and decompress resources until there is no more header.
+ do {
+ ResourceHeader _header;
+ memcpy(&_header, compressed_resource, sizeof (ResourceHeader));
+ has_header = _header._magic == ResourceHeader::resource_header_magic;
+ if (has_header) {
+ // decompressed_resource array contains the result of decompression
+ decompressed_resource = new u1[_header._uncompressed_size];
+ // Retrieve the decompressor name
+ const char* decompressor_name = strings->get(_header._decompressor_name_offset);
+ assert(decompressor_name && "image decompressor not found");
+ // Retrieve the decompressor instance
+ ImageDecompressor* decompressor = get_decompressor(decompressor_name);
+ assert(decompressor && "image decompressor not found");
+ u1* compressed_resource_base = compressed_resource;
+ compressed_resource += ResourceHeader::resource_header_length;
+ // Ask the decompressor to decompress the compressed content
+ decompressor->decompress_resource(compressed_resource, decompressed_resource,
+ &_header, strings);
+ if (compressed_resource_base != compressed) {
+ delete compressed_resource_base;
+ }
+ compressed_resource = decompressed_resource;
+ }
+ } while (has_header);
+ memcpy(uncompressed, decompressed_resource, uncompressed_size);
+ delete decompressed_resource;
}
// Zip decompressor
void ZipDecompressor::decompress_resource(u1* data, u1* uncompressed,
- ResourceHeader* header, const ImageStrings* strings) {
- char* msg = NULL;
- jboolean res = ZipDecompressor::decompress(data, header->_size, uncompressed,
- header->_uncompressed_size, &msg);
- assert(res && "decompression failed");
+ ResourceHeader* header, const ImageStrings* strings) {
+ char* msg = NULL;
+ jboolean res = ZipDecompressor::decompress(data, header->_size, uncompressed,
+ header->_uncompressed_size, &msg);
+ assert(res && "decompression failed");
}
jboolean ZipDecompressor::decompress(void *in, u8 inSize, void *out, u8 outSize, char **pmsg) {
- return (*ZipInflateFully)(in, inSize, out, outSize, pmsg);
+ return (*ZipInflateFully)(in, inSize, out, outSize, pmsg);
}
// END Zip Decompressor
@@ -163,141 +164,143 @@
// array index is the constant pool tag. value is size.
// eg: array[5] = 8; means size of long is 8 bytes.
-const u1 SharedStringDecompressor::sizes[] = {0, 0, 0, 4, 4, 8, 8, 2, 2, 4, 4, 4, 4, 0, 0, 3, 2, 0, 4};
+const u1 SharedStringDecompressor::sizes[] = {
+ 0, 0, 0, 4, 4, 8, 8, 2, 2, 4, 4, 4, 4, 0, 0, 3, 2, 0, 4
+};
/**
* Recreate the class by reconstructing the constant pool.
*/
void SharedStringDecompressor::decompress_resource(u1* data,
- u1* uncompressed_resource,
- ResourceHeader* header, const ImageStrings* strings) {
- u1* uncompressed_base = uncompressed_resource;
- u1* data_base = data;
- int header_size = 8; // magic + major + minor
- memcpy(uncompressed_resource, data, header_size + 2); //+ cp count
- uncompressed_resource += header_size + 2;
- data += header_size;
- u2 cp_count = Endian::get_java(data);
- data += 2;
- for (int i = 1; i < cp_count; i++) {
- u1 tag = *data;
- data += 1;
- switch (tag) {
+ u1* uncompressed_resource,
+ ResourceHeader* header, const ImageStrings* strings) {
+ u1* uncompressed_base = uncompressed_resource;
+ u1* data_base = data;
+ int header_size = 8; // magic + major + minor
+ memcpy(uncompressed_resource, data, header_size + 2); //+ cp count
+ uncompressed_resource += header_size + 2;
+ data += header_size;
+ u2 cp_count = Endian::get_java(data);
+ data += 2;
+ for (int i = 1; i < cp_count; i++) {
+ u1 tag = *data;
+ data += 1;
+ switch (tag) {
- case externalized_string:
- { // String in Strings table
- *uncompressed_resource = 1;
- uncompressed_resource += 1;
- int i = decompress_int(data);
- const char * string = strings->get(i);
- int str_length = (int) strlen(string);
- Endian::set_java(uncompressed_resource, str_length);
- uncompressed_resource += 2;
- memcpy(uncompressed_resource, string, str_length);
- uncompressed_resource += str_length;
- break;
- }
- // Descriptor String has been split and types added to Strings table
- case externalized_string_descriptor:
- {
- *uncompressed_resource = 1;
- uncompressed_resource += 1;
- int descriptor_index = decompress_int(data);
- int indexes_length = decompress_int(data);
- u1* length_address = uncompressed_resource;
- uncompressed_resource += 2;
- int desc_length = 0;
- const char * desc_string = strings->get(descriptor_index);
- if (indexes_length > 0) {
- u1* indexes_base = data;
- data += indexes_length;
- char c = *desc_string;
- do {
- *uncompressed_resource = c;
- uncompressed_resource++;
- desc_length += 1;
- /*
- * Every L character is the marker we are looking at in order
- * to reconstruct the descriptor. Each time an L is found, then
- * we retrieve the couple token/token at the current index and
- * add it to the descriptor.
- * "(L;I)V" and "java/lang","String" couple of tokens,
- * this becomes "(Ljava/lang/String;I)V"
- */
- if (c == 'L') {
- int index = decompress_int(indexes_base);
- const char * pkg = strings->get(index);
- int str_length = (int) strlen(pkg);
- // the case where we have a package.
- // reconstruct the type full name
- if (str_length > 0) {
- int len = str_length + 1;
- char* fullpkg = new char[len];
- char* pkg_base = fullpkg;
- memcpy(fullpkg, pkg, str_length);
- fullpkg += str_length;
- *fullpkg = '/';
- memcpy(uncompressed_resource, pkg_base, len);
+ case externalized_string:
+ { // String in Strings table
+ *uncompressed_resource = 1;
+ uncompressed_resource += 1;
+ int i = decompress_int(data);
+ const char * string = strings->get(i);
+ int str_length = (int) strlen(string);
+ Endian::set_java(uncompressed_resource, str_length);
+ uncompressed_resource += 2;
+ memcpy(uncompressed_resource, string, str_length);
+ uncompressed_resource += str_length;
+ break;
+ }
+ // Descriptor String has been split and types added to Strings table
+ case externalized_string_descriptor:
+ {
+ *uncompressed_resource = 1;
+ uncompressed_resource += 1;
+ int descriptor_index = decompress_int(data);
+ int indexes_length = decompress_int(data);
+ u1* length_address = uncompressed_resource;
+ uncompressed_resource += 2;
+ int desc_length = 0;
+ const char * desc_string = strings->get(descriptor_index);
+ if (indexes_length > 0) {
+ u1* indexes_base = data;
+ data += indexes_length;
+ char c = *desc_string;
+ do {
+ *uncompressed_resource = c;
+ uncompressed_resource++;
+ desc_length += 1;
+ /*
+ * Every L character is the marker we are looking at in order
+ * to reconstruct the descriptor. Each time an L is found, then
+ * we retrieve the couple token/token at the current index and
+ * add it to the descriptor.
+ * "(L;I)V" and "java/lang","String" couple of tokens,
+ * this becomes "(Ljava/lang/String;I)V"
+ */
+ if (c == 'L') {
+ int index = decompress_int(indexes_base);
+ const char * pkg = strings->get(index);
+ int str_length = (int) strlen(pkg);
+ // the case where we have a package.
+ // reconstruct the type full name
+ if (str_length > 0) {
+ int len = str_length + 1;
+ char* fullpkg = new char[len];
+ char* pkg_base = fullpkg;
+ memcpy(fullpkg, pkg, str_length);
+ fullpkg += str_length;
+ *fullpkg = '/';
+ memcpy(uncompressed_resource, pkg_base, len);
+ uncompressed_resource += len;
+ delete pkg_base;
+ desc_length += len;
+ } else { // Empty package
+ // Nothing to do.
+ }
+ int classIndex = decompress_int(indexes_base);
+ const char * clazz = strings->get(classIndex);
+ int clazz_length = (int) strlen(clazz);
+ memcpy(uncompressed_resource, clazz, clazz_length);
+ uncompressed_resource += clazz_length;
+ desc_length += clazz_length;
+ }
+ desc_string += 1;
+ c = *desc_string;
+ } while (c != '\0');
+ } else {
+ desc_length = (int) strlen(desc_string);
+ memcpy(uncompressed_resource, desc_string, desc_length);
+ uncompressed_resource += desc_length;
+ }
+ Endian::set_java(length_address, desc_length);
+ break;
+ }
+
+ case constant_utf8:
+ { // UTF-8
+ *uncompressed_resource = tag;
+ uncompressed_resource += 1;
+ u2 str_length = Endian::get_java(data);
+ int len = str_length + 2;
+ memcpy(uncompressed_resource, data, len);
uncompressed_resource += len;
- delete pkg_base;
- desc_length += len;
- } else { // Empty package
- // Nothing to do.
- }
- int classIndex = decompress_int(indexes_base);
- const char * clazz = strings->get(classIndex);
- int clazz_length = (int) strlen(clazz);
- memcpy(uncompressed_resource, clazz, clazz_length);
- uncompressed_resource += clazz_length;
- desc_length += clazz_length;
+ data += len;
+ break;
}
- desc_string += 1;
- c = *desc_string;
- } while (c != '\0');
- } else {
- desc_length = (int) strlen(desc_string);
- memcpy(uncompressed_resource, desc_string, desc_length);
- uncompressed_resource += desc_length;
- }
- Endian::set_java(length_address, desc_length);
- break;
- }
- case constant_utf8:
- { // UTF-8
- *uncompressed_resource = tag;
- uncompressed_resource += 1;
- u2 str_length = Endian::get_java(data);
- int len = str_length + 2;
- memcpy(uncompressed_resource, data, len);
- uncompressed_resource += len;
- data += len;
- break;
- }
-
- case constant_long:
- case constant_double:
- {
- i++;
- }
- default:
- {
- *uncompressed_resource = tag;
- uncompressed_resource += 1;
- int size = sizes[tag];
- memcpy(uncompressed_resource, data, size);
- uncompressed_resource += size;
- data += size;
- }
+ case constant_long:
+ case constant_double:
+ {
+ i++;
+ }
+ default:
+ {
+ *uncompressed_resource = tag;
+ uncompressed_resource += 1;
+ int size = sizes[tag];
+ memcpy(uncompressed_resource, data, size);
+ uncompressed_resource += size;
+ data += size;
+ }
+ }
}
- }
- u4 remain = header->_size - (int)(data - data_base);
- u4 computed = (u4)(uncompressed_resource - uncompressed_base) + remain;
- if (header->_uncompressed_size != computed)
- printf("Failure, expecting %d but getting %d\n", header->_uncompressed_size,
- computed);
- assert(header->_uncompressed_size == computed &&
- "Constant Pool reconstruction failed");
- memcpy(uncompressed_resource, data, remain);
+ u4 remain = header->_size - (int)(data - data_base);
+ u4 computed = (u4)(uncompressed_resource - uncompressed_base) + remain;
+ if (header->_uncompressed_size != computed)
+ printf("Failure, expecting %d but getting %d\n", header->_uncompressed_size,
+ computed);
+ assert(header->_uncompressed_size == computed &&
+ "Constant Pool reconstruction failed");
+ memcpy(uncompressed_resource, data, remain);
}
/*
@@ -308,25 +311,25 @@
* Example of compression: 1 is compressed on 1 byte: 10100001
*/
int SharedStringDecompressor::decompress_int(unsigned char*& value) {
- int len = 4;
- int res = 0;
- char b1 = *value;
- if (is_compressed((signed char)b1)) { // compressed
- len = get_compressed_length(b1);
- char clearedValue = b1 &= 0x1F;
- if (len == 1) {
- res = clearedValue;
+ int len = 4;
+ int res = 0;
+ char b1 = *value;
+ if (is_compressed((signed char)b1)) { // compressed
+ len = get_compressed_length(b1);
+ char clearedValue = b1 &= 0x1F;
+ if (len == 1) {
+ res = clearedValue;
+ } else {
+ res = (clearedValue & 0xFF) << 8 * (len - 1);
+ for (int i = 1; i < len; i++) {
+ res |= (value[i]&0xFF) << 8 * (len - i - 1);
+ }
+ }
} else {
- res = (clearedValue & 0xFF) << 8 * (len - 1);
- for (int i = 1; i < len; i++) {
- res |= (value[i]&0xFF) << 8 * (len - i - 1);
- }
+ res = (value[0] & 0xFF) << 24 | (value[1]&0xFF) << 16 |
+ (value[2]&0xFF) << 8 | (value[3]&0xFF);
}
- } else {
- res = (value[0] & 0xFF) << 24 | (value[1]&0xFF) << 16 |
- (value[2]&0xFF) << 8 | (value[3]&0xFF);
- }
- value += len;
- return res;
+ value += len;
+ return res;
}
// END Shared String decompressor
--- a/jdk/src/java.base/share/native/libjimage/imageDecompressor.hpp Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/native/libjimage/imageDecompressor.hpp Wed Jul 05 20:51:27 2017 +0200
@@ -4,11 +4,13 @@
*
* 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.
+ * 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
+ * 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).
*
@@ -19,7 +21,6 @@
* 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.
- *
*/
#ifndef LIBJIMAGE_IMAGEDECOMPRESSOR_HPP
@@ -47,16 +48,16 @@
* have been used to compress the resource.
*/
struct ResourceHeader {
- /* Length of header, needed to retrieve content offset */
- static const u1 resource_header_length = 21;
- /* magic bytes that identifies a compressed resource header*/
- static const u4 resource_header_magic = 0xCAFEFAFA;
- u4 _magic; // Resource header
- u4 _size; // Resource size
- u4 _uncompressed_size; // Expected uncompressed size
- u4 _decompressor_name_offset; // Strings table decompressor offset
- u4 _decompressor_config_offset; // Strings table config offset
- u1 _is_terminal; // Last decompressor 1, otherwise 0.
+ /* Length of header, needed to retrieve content offset */
+ static const u1 resource_header_length = 21;
+ /* magic bytes that identifies a compressed resource header*/
+ static const u4 resource_header_magic = 0xCAFEFAFA;
+ u4 _magic; // Resource header
+ u4 _size; // Resource size
+ u4 _uncompressed_size; // Expected uncompressed size
+ u4 _decompressor_name_offset; // Strings table decompressor offset
+ u4 _decompressor_config_offset; // Strings table config offset
+ u1 _is_terminal; // Last decompressor 1, otherwise 0.
};
/*
@@ -77,36 +78,36 @@
class ImageDecompressor {
private:
- const char* _name;
+ const char* _name;
- /*
- * Array of concrete decompressors. This array is used to retrieve the decompressor
- * that can handle resource decompression.
- */
- static ImageDecompressor** _decompressors;
- /**
- * Num of decompressors
- */
- static int _decompressors_num;
- /*
- * Identifier of a decompressor. This name is the identification key to retrieve
- * decompressor from a resource header.
- */
- inline const char* get_name() const { return _name; }
+ /*
+ * Array of concrete decompressors. This array is used to retrieve the decompressor
+ * that can handle resource decompression.
+ */
+ static ImageDecompressor** _decompressors;
+ /**
+ * Num of decompressors
+ */
+ static int _decompressors_num;
+ /*
+ * Identifier of a decompressor. This name is the identification key to retrieve
+ * decompressor from a resource header.
+ */
+ inline const char* get_name() const { return _name; }
protected:
- ImageDecompressor(const char* name) : _name(name) {
- }
- virtual void decompress_resource(u1* data, u1* uncompressed,
- ResourceHeader* header, const ImageStrings* strings) = 0;
+ ImageDecompressor(const char* name) : _name(name) {
+ }
+ virtual void decompress_resource(u1* data, u1* uncompressed,
+ ResourceHeader* header, const ImageStrings* strings) = 0;
public:
- static void image_decompressor_init();
- static void image_decompressor_close();
- static ImageDecompressor* get_decompressor(const char * decompressor_name) ;
- static void decompress_resource(u1* compressed, u1* uncompressed,
- u4 uncompressed_size, const ImageStrings* strings);
+ static void image_decompressor_init();
+ static void image_decompressor_close();
+ static ImageDecompressor* get_decompressor(const char * decompressor_name) ;
+ static void decompress_resource(u1* compressed, u1* uncompressed,
+ u4 uncompressed_size, const ImageStrings* strings);
};
/**
@@ -114,10 +115,10 @@
*/
class ZipDecompressor : public ImageDecompressor {
public:
- ZipDecompressor(const char* sym) : ImageDecompressor(sym) { }
- void decompress_resource(u1* data, u1* uncompressed, ResourceHeader* header,
- const ImageStrings* strings);
- static jboolean decompress(void *in, u8 inSize, void *out, u8 outSize, char **pmsg);
+ ZipDecompressor(const char* sym) : ImageDecompressor(sym) { }
+ void decompress_resource(u1* data, u1* uncompressed, ResourceHeader* header,
+ const ImageStrings* strings);
+ static jboolean decompress(void *in, u8 inSize, void *out, u8 outSize, char **pmsg);
};
/*
@@ -131,32 +132,34 @@
*/
class SharedStringDecompressor : public ImageDecompressor {
private:
- // the constant pool tag for UTF8 string located in strings table
- static const int externalized_string = 23;
- // the constant pool tag for UTF8 descriptors string located in strings table
- static const int externalized_string_descriptor = 25;
- // the constant pool tag for UTF8
- static const int constant_utf8 = 1;
- // the constant pool tag for long
- static const int constant_long = 5;
- // the constant pool tag for double
- static const int constant_double = 6;
- // array index is the constant pool tag. value is size.
- // eg: array[5] = 8; means size of long is 8 bytes.
- static const u1 sizes[];
- // bit 5 and 6 are used to store the length of the compressed integer.
- // size can be 1 (01), 2 (10), 3 (11).
- // 0x60 ==> 0110000
- static const int compressed_index_size_mask = 0x60;
- /*
- * mask the length bits (5 and 6) and move to the right 5 bits.
- */
- inline static int get_compressed_length(char c) { return ((char) (c & compressed_index_size_mask) >> 5); }
- inline static bool is_compressed(signed char b1) { return b1 < 0; }
- static int decompress_int(unsigned char*& value);
+ // the constant pool tag for UTF8 string located in strings table
+ static const int externalized_string = 23;
+ // the constant pool tag for UTF8 descriptors string located in strings table
+ static const int externalized_string_descriptor = 25;
+ // the constant pool tag for UTF8
+ static const int constant_utf8 = 1;
+ // the constant pool tag for long
+ static const int constant_long = 5;
+ // the constant pool tag for double
+ static const int constant_double = 6;
+ // array index is the constant pool tag. value is size.
+ // eg: array[5] = 8; means size of long is 8 bytes.
+ static const u1 sizes[];
+ // bit 5 and 6 are used to store the length of the compressed integer.
+ // size can be 1 (01), 2 (10), 3 (11).
+ // 0x60 ==> 0110000
+ static const int compressed_index_size_mask = 0x60;
+ /*
+ * mask the length bits (5 and 6) and move to the right 5 bits.
+ */
+ inline static int get_compressed_length(char c) {
+ return ((char) (c & compressed_index_size_mask) >> 5);
+ }
+ inline static bool is_compressed(signed char b1) { return b1 < 0; }
+ static int decompress_int(unsigned char*& value);
public:
- SharedStringDecompressor(const char* sym) : ImageDecompressor(sym){}
- void decompress_resource(u1* data, u1* uncompressed, ResourceHeader* header,
- const ImageStrings* strings);
+ SharedStringDecompressor(const char* sym) : ImageDecompressor(sym){}
+ void decompress_resource(u1* data, u1* uncompressed, ResourceHeader* header,
+ const ImageStrings* strings);
};
#endif // LIBJIMAGE_IMAGEDECOMPRESSOR_HPP
--- a/jdk/src/java.base/share/native/libjimage/imageFile.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/native/libjimage/imageFile.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -4,11 +4,13 @@
*
* 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.
+ * 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
+ * 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).
*
@@ -19,7 +21,6 @@
* 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 <assert.h>
@@ -50,268 +51,268 @@
// Compute the Perfect Hashing hash code for the supplied UTF-8 string.
s4 ImageStrings::hash_code(const char* string, s4 seed) {
- // Access bytes as unsigned.
- u1* bytes = (u1*)string;
- // Compute hash code.
- for (u1 byte = *bytes++; byte; byte = *bytes++) {
- seed = (seed * HASH_MULTIPLIER) ^ byte;
- }
- // Ensure the result is not signed.
- return seed & 0x7FFFFFFF;
+ // Access bytes as unsigned.
+ u1* bytes = (u1*)string;
+ // Compute hash code.
+ for (u1 byte = *bytes++; byte; byte = *bytes++) {
+ seed = (seed * HASH_MULTIPLIER) ^ byte;
+ }
+ // Ensure the result is not signed.
+ return seed & 0x7FFFFFFF;
}
// Match up a string in a perfect hash table.
// Returns the index where the name should be.
// Result still needs validation for precise match (false positive.)
s4 ImageStrings::find(Endian* endian, const char* name, s4* redirect, u4 length) {
- // If the table is empty, then short cut.
- if (!redirect || !length) {
+ // If the table is empty, then short cut.
+ if (!redirect || !length) {
+ return NOT_FOUND;
+ }
+ // Compute the basic perfect hash for name.
+ s4 hash_code = ImageStrings::hash_code(name);
+ // Modulo table size.
+ s4 index = hash_code % length;
+ // Get redirect entry.
+ // value == 0 then not found
+ // value < 0 then -1 - value is true index
+ // value > 0 then value is seed for recomputing hash.
+ s4 value = endian->get(redirect[index]);
+ // if recompute is required.
+ if (value > 0 ) {
+ // Entry collision value, need to recompute hash.
+ hash_code = ImageStrings::hash_code(name, value);
+ // Modulo table size.
+ return hash_code % length;
+ } else if (value < 0) {
+ // Compute direct index.
+ return -1 - value;
+ }
+ // No entry found.
return NOT_FOUND;
- }
- // Compute the basic perfect hash for name.
- s4 hash_code = ImageStrings::hash_code(name);
- // Modulo table size.
- s4 index = hash_code % length;
- // Get redirect entry.
- // value == 0 then not found
- // value < 0 then -1 - value is true index
- // value > 0 then value is seed for recomputing hash.
- s4 value = endian->get(redirect[index]);
- // if recompute is required.
- if (value > 0 ) {
- // Entry collision value, need to recompute hash.
- hash_code = ImageStrings::hash_code(name, value);
- // Modulo table size.
- return hash_code % length;
- } else if (value < 0) {
- // Compute direct index.
- return -1 - value;
- }
- // No entry found.
- return NOT_FOUND;
}
// Test to see if UTF-8 string begins with the start UTF-8 string. If so,
// return non-NULL address of remaining portion of string. Otherwise, return
-// NULL. Used to test sections of a path without copying from image string
+// NULL. Used to test sections of a path without copying from image string
// table.
const char* ImageStrings::starts_with(const char* string, const char* start) {
- char ch1, ch2;
- // Match up the strings the best we can.
- while ((ch1 = *string) && (ch2 = *start)) {
- if (ch1 != ch2) {
- // Mismatch, return NULL.
- return NULL;
+ char ch1, ch2;
+ // Match up the strings the best we can.
+ while ((ch1 = *string) && (ch2 = *start)) {
+ if (ch1 != ch2) {
+ // Mismatch, return NULL.
+ return NULL;
+ }
+ // Next characters.
+ string++, start++;
}
- // Next characters.
- string++, start++;
- }
- // Return remainder of string.
- return string;
+ // Return remainder of string.
+ return string;
}
// Inflates the attribute stream into individual values stored in the long
// array _attributes. This allows an attribute value to be quickly accessed by
// direct indexing. Unspecified values default to zero (from constructor.)
void ImageLocation::set_data(u1* data) {
- // Deflate the attribute stream into an array of attributes.
- u1 byte;
- // Repeat until end header is found.
- while ((byte = *data)) {
- // Extract kind from header byte.
- u1 kind = attribute_kind(byte);
- assert(kind < ATTRIBUTE_COUNT && "invalid image location attribute");
- // Extract length of data (in bytes).
- u1 n = attribute_length(byte);
- // Read value (most significant first.)
- _attributes[kind] = attribute_value(data + 1, n);
- // Position to next attribute by skipping attribute header and data bytes.
- data += n + 1;
- }
+ // Deflate the attribute stream into an array of attributes.
+ u1 byte;
+ // Repeat until end header is found.
+ while ((byte = *data)) {
+ // Extract kind from header byte.
+ u1 kind = attribute_kind(byte);
+ assert(kind < ATTRIBUTE_COUNT && "invalid image location attribute");
+ // Extract length of data (in bytes).
+ u1 n = attribute_length(byte);
+ // Read value (most significant first.)
+ _attributes[kind] = attribute_value(data + 1, n);
+ // Position to next attribute by skipping attribute header and data bytes.
+ data += n + 1;
+ }
}
// Zero all attribute values.
void ImageLocation::clear_data() {
- // Set defaults to zero.
- memset(_attributes, 0, sizeof(_attributes));
+ // Set defaults to zero.
+ memset(_attributes, 0, sizeof(_attributes));
}
// ImageModuleData constructor maps out sub-tables for faster access.
ImageModuleData::ImageModuleData(const ImageFileReader* image_file,
- const char* module_data_name) :
- _image_file(image_file),
- _endian(image_file->endian()),
- _strings(image_file->get_strings()) {
- // Retrieve the resource containing the module data for the image file.
- ImageLocation location;
- bool found = image_file->find_location(module_data_name, location);
- if (found) {
- u8 data_size = location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED);
- _data = new u1[(size_t)data_size];
- _image_file->get_resource(location, _data);
- // Map out the header.
- _header = (Header*)_data;
- // Get the package to module entry count.
- u4 ptm_count = _header->ptm_count(_endian);
- // Get the module to package entry count.
- u4 mtp_count = _header->mtp_count(_endian);
- // Compute the offset of the package to module perfect hash redirect.
- u4 ptm_redirect_offset = sizeof(Header);
- // Compute the offset of the package to module data.
- u4 ptm_data_offset = ptm_redirect_offset + ptm_count * sizeof(s4);
- // Compute the offset of the module to package perfect hash redirect.
- u4 mtp_redirect_offset = ptm_data_offset + ptm_count * sizeof(PTMData);
- // Compute the offset of the module to package data.
- u4 mtp_data_offset = mtp_redirect_offset + mtp_count * sizeof(s4);
- // Compute the offset of the module to package tables.
- u4 mtp_packages_offset = mtp_data_offset + mtp_count * sizeof(MTPData);
- // Compute the address of the package to module perfect hash redirect.
- _ptm_redirect = (s4*)(_data + ptm_redirect_offset);
- // Compute the address of the package to module data.
- _ptm_data = (PTMData*)(_data + ptm_data_offset);
- // Compute the address of the module to package perfect hash redirect.
- _mtp_redirect = (s4*)(_data + mtp_redirect_offset);
- // Compute the address of the module to package data.
- _mtp_data = (MTPData*)(_data + mtp_data_offset);
- // Compute the address of the module to package tables.
- _mtp_packages = (s4*)(_data + mtp_packages_offset);
- } else {
- // No module data present.
- _data = NULL;
- _header = NULL;
- _ptm_redirect = NULL;
- _ptm_data = NULL;
- _mtp_redirect = NULL;
- _mtp_data = NULL;
- _mtp_packages = NULL;
- }
+ const char* module_data_name) :
+ _image_file(image_file),
+ _endian(image_file->endian()),
+ _strings(image_file->get_strings()) {
+ // Retrieve the resource containing the module data for the image file.
+ ImageLocation location;
+ bool found = image_file->find_location(module_data_name, location);
+ if (found) {
+ u8 data_size = location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED);
+ _data = new u1[(size_t)data_size];
+ _image_file->get_resource(location, _data);
+ // Map out the header.
+ _header = (Header*)_data;
+ // Get the package to module entry count.
+ u4 ptm_count = _header->ptm_count(_endian);
+ // Get the module to package entry count.
+ u4 mtp_count = _header->mtp_count(_endian);
+ // Compute the offset of the package to module perfect hash redirect.
+ u4 ptm_redirect_offset = sizeof(Header);
+ // Compute the offset of the package to module data.
+ u4 ptm_data_offset = ptm_redirect_offset + ptm_count * sizeof(s4);
+ // Compute the offset of the module to package perfect hash redirect.
+ u4 mtp_redirect_offset = ptm_data_offset + ptm_count * sizeof(PTMData);
+ // Compute the offset of the module to package data.
+ u4 mtp_data_offset = mtp_redirect_offset + mtp_count * sizeof(s4);
+ // Compute the offset of the module to package tables.
+ u4 mtp_packages_offset = mtp_data_offset + mtp_count * sizeof(MTPData);
+ // Compute the address of the package to module perfect hash redirect.
+ _ptm_redirect = (s4*)(_data + ptm_redirect_offset);
+ // Compute the address of the package to module data.
+ _ptm_data = (PTMData*)(_data + ptm_data_offset);
+ // Compute the address of the module to package perfect hash redirect.
+ _mtp_redirect = (s4*)(_data + mtp_redirect_offset);
+ // Compute the address of the module to package data.
+ _mtp_data = (MTPData*)(_data + mtp_data_offset);
+ // Compute the address of the module to package tables.
+ _mtp_packages = (s4*)(_data + mtp_packages_offset);
+ } else {
+ // No module data present.
+ _data = NULL;
+ _header = NULL;
+ _ptm_redirect = NULL;
+ _ptm_data = NULL;
+ _mtp_redirect = NULL;
+ _mtp_data = NULL;
+ _mtp_packages = NULL;
+ }
}
// Release module data resource.
ImageModuleData::~ImageModuleData() {
- if (_data) {
- delete _data;
- }
+ if (_data) {
+ delete _data;
+ }
}
// Return the name of the module data resource. Ex. "./lib/modules/file.jimage"
// yields "file.jdata"
void ImageModuleData::module_data_name(char* buffer, const char* image_file_name) {
- // Locate the last slash in the file name path.
- const char* slash = strrchr(image_file_name, FileSeparator);
- // Trim the path to name and extension.
- const char* name = slash ? slash + 1 : (char *)image_file_name;
- // Locate the extension period.
- const char* dot = strrchr(name, '.');
- assert(dot && "missing extension on jimage name");
- // Trim to only base name.
- int length = (int)(dot - name);
- strncpy(buffer, name, length);
- buffer[length] = '\0';
- // Append extension.
- strcat(buffer, ".jdata");
+ // Locate the last slash in the file name path.
+ const char* slash = strrchr(image_file_name, FileSeparator);
+ // Trim the path to name and extension.
+ const char* name = slash ? slash + 1 : (char *)image_file_name;
+ // Locate the extension period.
+ const char* dot = strrchr(name, '.');
+ assert(dot && "missing extension on jimage name");
+ // Trim to only base name.
+ int length = (int)(dot - name);
+ strncpy(buffer, name, length);
+ buffer[length] = '\0';
+ // Append extension.
+ strcat(buffer, ".jdata");
}
-// Return the module in which a package resides. Returns NULL if not found.
+// Return the module in which a package resides. Returns NULL if not found.
const char* ImageModuleData::package_to_module(const char* package_name) {
- // Test files may contain no module data.
- if (_data != NULL) {
- // Search the package to module table.
- s4 index = ImageStrings::find(_endian, package_name, _ptm_redirect,
- _header->ptm_count(_endian));
- // If entry is found.
- if (index != ImageStrings::NOT_FOUND) {
- // Retrieve the package to module entry.
- PTMData* data = _ptm_data + index;
- // Verify that it is the correct data.
- if (strcmp(package_name, get_string(data->name_offset(_endian))) != 0) {
- return NULL;
- }
- // Return the module name.
- return get_string(data->module_name_offset(_endian));
+ // Test files may contain no module data.
+ if (_data != NULL) {
+ // Search the package to module table.
+ s4 index = ImageStrings::find(_endian, package_name, _ptm_redirect,
+ _header->ptm_count(_endian));
+ // If entry is found.
+ if (index != ImageStrings::NOT_FOUND) {
+ // Retrieve the package to module entry.
+ PTMData* data = _ptm_data + index;
+ // Verify that it is the correct data.
+ if (strcmp(package_name, get_string(data->name_offset(_endian))) != 0) {
+ return NULL;
+ }
+ // Return the module name.
+ return get_string(data->module_name_offset(_endian));
+ }
}
- }
- return NULL;
+ return NULL;
}
// Returns all the package names in a module in a NULL terminated array.
// Returns NULL if module not found.
const char** ImageModuleData::module_to_packages(const char* module_name) {
- // Test files may contain no module data.
- if (_data != NULL) {
- // Search the module to package table.
- s4 index = ImageStrings::find(_endian, module_name, _mtp_redirect,
- _header->mtp_count(_endian));
- // If entry is found.
- if (index != ImageStrings::NOT_FOUND) {
- // Retrieve the module to package entry.
- MTPData* data = _mtp_data + index;
- // Verify that it is the correct data.
- if (strcmp(module_name, get_string(data->name_offset(_endian))) != 0) {
- return NULL;
- }
- // Construct an array of all the package entries.
- u4 count = data->package_count(_endian);
- const char** packages = new const char*[count + 1];
- s4 package_offset = data->package_offset(_endian);
- for (u4 i = 0; i < count; i++) {
- u4 package_name_offset = mtp_package(package_offset + i);
- const char* package_name = get_string(package_name_offset);
- packages[i] = package_name;
- }
- packages[count] = NULL;
- return packages;
+ // Test files may contain no module data.
+ if (_data != NULL) {
+ // Search the module to package table.
+ s4 index = ImageStrings::find(_endian, module_name, _mtp_redirect,
+ _header->mtp_count(_endian));
+ // If entry is found.
+ if (index != ImageStrings::NOT_FOUND) {
+ // Retrieve the module to package entry.
+ MTPData* data = _mtp_data + index;
+ // Verify that it is the correct data.
+ if (strcmp(module_name, get_string(data->name_offset(_endian))) != 0) {
+ return NULL;
+ }
+ // Construct an array of all the package entries.
+ u4 count = data->package_count(_endian);
+ const char** packages = new const char*[count + 1];
+ s4 package_offset = data->package_offset(_endian);
+ for (u4 i = 0; i < count; i++) {
+ u4 package_name_offset = mtp_package(package_offset + i);
+ const char* package_name = get_string(package_name_offset);
+ packages[i] = package_name;
+ }
+ packages[count] = NULL;
+ return packages;
+ }
}
- }
- return NULL;
+ return NULL;
}
// Manage a table of open image files. This table allows multiple access points
// to share an open image.
ImageFileReaderTable::ImageFileReaderTable() : _count(0), _max(_growth) {
- _table = new ImageFileReader*[_max];
+ _table = new ImageFileReader*[_max];
}
ImageFileReaderTable::~ImageFileReaderTable() {
- delete _table;
+ delete _table;
}
// Add a new image entry to the table.
void ImageFileReaderTable::add(ImageFileReader* image) {
- if (_count == _max) {
- _max += _growth;
- _table = static_cast<ImageFileReader**>(realloc(_table, _max * sizeof(ImageFileReader*)));
- }
- _table[_count++] = image;
+ if (_count == _max) {
+ _max += _growth;
+ _table = static_cast<ImageFileReader**>(realloc(_table, _max * sizeof(ImageFileReader*)));
+ }
+ _table[_count++] = image;
}
// Remove an image entry from the table.
void ImageFileReaderTable::remove(ImageFileReader* image) {
- s4 last = _count - 1;
- for (s4 i = 0; _count; i++) {
- if (_table[i] == image) {
- if (i != last) {
- _table[i] = _table[last];
- _count = last;
- }
- break;
+ s4 last = _count - 1;
+ for (s4 i = 0; _count; i++) {
+ if (_table[i] == image) {
+ if (i != last) {
+ _table[i] = _table[last];
+ _count = last;
+ }
+ break;
+ }
}
- }
- if (_count != 0 && _count == _max - _growth) {
- _max -= _growth;
- _table = static_cast<ImageFileReader**>(realloc(_table, _max * sizeof(ImageFileReader*)));
- }
+ if (_count != 0 && _count == _max - _growth) {
+ _max -= _growth;
+ _table = static_cast<ImageFileReader**>(realloc(_table, _max * sizeof(ImageFileReader*)));
+ }
}
// Determine if image entry is in table.
bool ImageFileReaderTable::contains(ImageFileReader* image) {
- for (s4 i = 0; _count; i++) {
- if (_table[i] == image) {
- return true;
+ for (s4 i = 0; _count; i++) {
+ if (_table[i] == image) {
+ return true;
+ }
}
- }
- return false;
+ return false;
}
// Table to manage multiple opens of an image file.
@@ -321,362 +322,362 @@
// Open an image file, reuse structure if file already open.
ImageFileReader* ImageFileReader::open(const char* name, bool big_endian) {
- {
- // Lock out _reader_table.
+ {
+ // Lock out _reader_table.
+ SimpleCriticalSectionLock cs(&_reader_table_lock);
+ // Search for an exist image file.
+ for (u4 i = 0; i < _reader_table.count(); i++) {
+ // Retrieve table entry.
+ ImageFileReader* reader = _reader_table.get(i);
+ // If name matches, then reuse (bump up use count.)
+ if (strcmp(reader->name(), name) == 0) {
+ reader->inc_use();
+ return reader;
+ }
+ }
+ } // Unlock the mutex
+
+ // Need a new image reader.
+ ImageFileReader* reader = new ImageFileReader(name, big_endian);
+ bool opened = reader->open();
+ // If failed to open.
+ if (!opened) {
+ delete reader;
+ return NULL;
+ }
+
+ // Lock to update
SimpleCriticalSectionLock cs(&_reader_table_lock);
// Search for an exist image file.
for (u4 i = 0; i < _reader_table.count(); i++) {
- // Retrieve table entry.
- ImageFileReader* reader = _reader_table.get(i);
- // If name matches, then reuse (bump up use count.)
- if (strcmp(reader->name(), name) == 0) {
- reader->inc_use();
- return reader;
- }
+ // Retrieve table entry.
+ ImageFileReader* existing_reader = _reader_table.get(i);
+ // If name matches, then reuse (bump up use count.)
+ if (strcmp(existing_reader->name(), name) == 0) {
+ existing_reader->inc_use();
+ reader->close();
+ delete reader;
+ return existing_reader;
+ }
}
- } // Unlock the mutex
-
- // Need a new image reader.
- ImageFileReader* reader = new ImageFileReader(name, big_endian);
- bool opened = reader->open();
- // If failed to open.
- if (!opened) {
- delete reader;
- return NULL;
- }
-
- // Lock to update
- SimpleCriticalSectionLock cs(&_reader_table_lock);
- // Search for an exist image file.
- for (u4 i = 0; i < _reader_table.count(); i++) {
- // Retrieve table entry.
- ImageFileReader* existing_reader = _reader_table.get(i);
- // If name matches, then reuse (bump up use count.)
- if (strcmp(existing_reader->name(), name) == 0) {
- existing_reader->inc_use();
- reader->close();
- delete reader;
- return existing_reader;
- }
- }
- // Bump use count and add to table.
- reader->inc_use();
- _reader_table.add(reader);
- return reader;
+ // Bump use count and add to table.
+ reader->inc_use();
+ _reader_table.add(reader);
+ return reader;
}
// Close an image file if the file is not in use elsewhere.
void ImageFileReader::close(ImageFileReader *reader) {
- // Lock out _reader_table.
- SimpleCriticalSectionLock cs(&_reader_table_lock);
- // If last use then remove from table and then close.
- if (reader->dec_use()) {
- _reader_table.remove(reader);
- delete reader;
- }
+ // Lock out _reader_table.
+ SimpleCriticalSectionLock cs(&_reader_table_lock);
+ // If last use then remove from table and then close.
+ if (reader->dec_use()) {
+ _reader_table.remove(reader);
+ delete reader;
+ }
}
// Return an id for the specifed ImageFileReader.
u8 ImageFileReader::readerToID(ImageFileReader *reader) {
- // ID is just the cloaked reader address.
- return (u8)reader;
+ // ID is just the cloaked reader address.
+ return (u8)reader;
}
// Validate the image id.
bool ImageFileReader::idCheck(u8 id) {
- // Make sure the ID is a managed (_reader_table) reader.
- SimpleCriticalSectionLock cs(&_reader_table_lock);
- return _reader_table.contains((ImageFileReader*)id);
+ // Make sure the ID is a managed (_reader_table) reader.
+ SimpleCriticalSectionLock cs(&_reader_table_lock);
+ return _reader_table.contains((ImageFileReader*)id);
}
// Return an id for the specifed ImageFileReader.
ImageFileReader* ImageFileReader::idToReader(u8 id) {
- assert(idCheck(id) && "invalid image id");
- return (ImageFileReader*)id;
+ assert(idCheck(id) && "invalid image id");
+ return (ImageFileReader*)id;
}
// Constructor intializes to a closed state.
ImageFileReader::ImageFileReader(const char* name, bool big_endian) {
- // Copy the image file name.
- int len = (int) strlen(name) + 1;
- _name = new char[len];
- strncpy(_name, name, len);
- // Initialize for a closed file.
- _fd = -1;
- _endian = Endian::get_handler(big_endian);
- _index_data = NULL;
+ // Copy the image file name.
+ int len = (int) strlen(name) + 1;
+ _name = new char[len];
+ strncpy(_name, name, len);
+ // Initialize for a closed file.
+ _fd = -1;
+ _endian = Endian::get_handler(big_endian);
+ _index_data = NULL;
}
// Close image and free up data structures.
ImageFileReader::~ImageFileReader() {
- // Ensure file is closed.
- close();
- // Free up name.
- if (_name) {
- delete _name;
- _name = NULL;
- }
+ // Ensure file is closed.
+ close();
+ // Free up name.
+ if (_name) {
+ delete _name;
+ _name = NULL;
+ }
}
// Open image file for read access.
bool ImageFileReader::open() {
- char buffer[IMAGE_MAX_PATH];
+ char buffer[IMAGE_MAX_PATH];
- // If file exists open for reading.
- _fd = osSupport::openReadOnly(_name);
- if (_fd == -1) {
- return false;
- }
- // Retrieve the file size.
- _file_size = osSupport::size(_name);
- // Read image file header and verify it has a valid header.
- size_t header_size = sizeof(ImageHeader);
- if (_file_size < header_size ||
- !read_at((u1*)&_header, header_size, 0) ||
- _header.magic(_endian) != IMAGE_MAGIC ||
- _header.major_version(_endian) != MAJOR_VERSION ||
- _header.minor_version(_endian) != MINOR_VERSION) {
- close();
- return false;
- }
- // Size of image index.
- _index_size = index_size();
- // Make sure file is large enough to contain the index.
- if (_file_size < _index_size) {
- return false;
- }
- // Determine how much of the image is memory mapped.
- size_t map_size = (size_t)(MemoryMapImage ? _file_size : _index_size);
- // Memory map image (minimally the index.)
- _index_data = (u1*)osSupport::map_memory(_fd, _name, 0, map_size);
- assert(_index_data && "image file not memory mapped");
- // Retrieve length of index perfect hash table.
- u4 length = table_length();
- // Compute offset of the perfect hash table redirect table.
- u4 redirect_table_offset = (u4)header_size;
- // Compute offset of index attribute offsets.
- u4 offsets_table_offset = redirect_table_offset + length * sizeof(s4);
- // Compute offset of index location attribute data.
- u4 location_bytes_offset = offsets_table_offset + length * sizeof(u4);
- // Compute offset of index string table.
- u4 string_bytes_offset = location_bytes_offset + locations_size();
- // Compute address of the perfect hash table redirect table.
- _redirect_table = (s4*)(_index_data + redirect_table_offset);
- // Compute address of index attribute offsets.
- _offsets_table = (u4*)(_index_data + offsets_table_offset);
- // Compute address of index location attribute data.
- _location_bytes = _index_data + location_bytes_offset;
- // Compute address of index string table.
- _string_bytes = _index_data + string_bytes_offset;
+ // If file exists open for reading.
+ _fd = osSupport::openReadOnly(_name);
+ if (_fd == -1) {
+ return false;
+ }
+ // Retrieve the file size.
+ _file_size = osSupport::size(_name);
+ // Read image file header and verify it has a valid header.
+ size_t header_size = sizeof(ImageHeader);
+ if (_file_size < header_size ||
+ !read_at((u1*)&_header, header_size, 0) ||
+ _header.magic(_endian) != IMAGE_MAGIC ||
+ _header.major_version(_endian) != MAJOR_VERSION ||
+ _header.minor_version(_endian) != MINOR_VERSION) {
+ close();
+ return false;
+ }
+ // Size of image index.
+ _index_size = index_size();
+ // Make sure file is large enough to contain the index.
+ if (_file_size < _index_size) {
+ return false;
+ }
+ // Determine how much of the image is memory mapped.
+ size_t map_size = (size_t)(MemoryMapImage ? _file_size : _index_size);
+ // Memory map image (minimally the index.)
+ _index_data = (u1*)osSupport::map_memory(_fd, _name, 0, map_size);
+ assert(_index_data && "image file not memory mapped");
+ // Retrieve length of index perfect hash table.
+ u4 length = table_length();
+ // Compute offset of the perfect hash table redirect table.
+ u4 redirect_table_offset = (u4)header_size;
+ // Compute offset of index attribute offsets.
+ u4 offsets_table_offset = redirect_table_offset + length * sizeof(s4);
+ // Compute offset of index location attribute data.
+ u4 location_bytes_offset = offsets_table_offset + length * sizeof(u4);
+ // Compute offset of index string table.
+ u4 string_bytes_offset = location_bytes_offset + locations_size();
+ // Compute address of the perfect hash table redirect table.
+ _redirect_table = (s4*)(_index_data + redirect_table_offset);
+ // Compute address of index attribute offsets.
+ _offsets_table = (u4*)(_index_data + offsets_table_offset);
+ // Compute address of index location attribute data.
+ _location_bytes = _index_data + location_bytes_offset;
+ // Compute address of index string table.
+ _string_bytes = _index_data + string_bytes_offset;
- // Initialize the module data
- ImageModuleData::module_data_name(buffer, _name);
- module_data = new ImageModuleData(this, buffer);
- // Successful open.
- return true;
+ // Initialize the module data
+ ImageModuleData::module_data_name(buffer, _name);
+ module_data = new ImageModuleData(this, buffer);
+ // Successful open.
+ return true;
}
// Close image file.
void ImageFileReader::close() {
- // Deallocate the index.
- if (_index_data) {
- osSupport::unmap_memory((char*)_index_data, _index_size);
- _index_data = NULL;
- }
- // Close file.
- if (_fd != -1) {
- osSupport::close(_fd);
- _fd = -1;
- }
+ // Deallocate the index.
+ if (_index_data) {
+ osSupport::unmap_memory((char*)_index_data, _index_size);
+ _index_data = NULL;
+ }
+ // Close file.
+ if (_fd != -1) {
+ osSupport::close(_fd);
+ _fd = -1;
+ }
}
// Read directly from the file.
bool ImageFileReader::read_at(u1* data, u8 size, u8 offset) const {
- return (u8)osSupport::read(_fd, (char*)data, size, offset) == size;
+ return (u8)osSupport::read(_fd, (char*)data, size, offset) == size;
}
-// Find the location attributes associated with the path. Returns true if
+// Find the location attributes associated with the path. Returns true if
// the location is found, false otherwise.
bool ImageFileReader::find_location(const char* path, ImageLocation& location) const {
- // Locate the entry in the index perfect hash table.
- s4 index = ImageStrings::find(_endian, path, _redirect_table, table_length());
- // If is found.
- if (index != ImageStrings::NOT_FOUND) {
- // Get address of first byte of location attribute stream.
- u1* data = get_location_data(index);
- // Expand location attributes.
- location.set_data(data);
- // Make sure result is not a false positive.
- return verify_location(location, path);
- }
- return false;
+ // Locate the entry in the index perfect hash table.
+ s4 index = ImageStrings::find(_endian, path, _redirect_table, table_length());
+ // If is found.
+ if (index != ImageStrings::NOT_FOUND) {
+ // Get address of first byte of location attribute stream.
+ u1* data = get_location_data(index);
+ // Expand location attributes.
+ location.set_data(data);
+ // Make sure result is not a false positive.
+ return verify_location(location, path);
+ }
+ return false;
}
// Find the location index and size associated with the path.
// Returns the location index and size if the location is found, 0 otherwise.
u4 ImageFileReader::find_location_index(const char* path, u8 *size) const {
- // Locate the entry in the index perfect hash table.
- s4 index = ImageStrings::find(_endian, path, _redirect_table, table_length());
- // If found.
- if (index != ImageStrings::NOT_FOUND) {
- // Get address of first byte of location attribute stream.
- u4 offset = get_location_offset(index);
- u1* data = get_location_offset_data(offset);
- // Expand location attributes.
- ImageLocation location(data);
- // Make sure result is not a false positive.
- if (verify_location(location, path)) {
- *size = (jlong)location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED);
- return offset;
+ // Locate the entry in the index perfect hash table.
+ s4 index = ImageStrings::find(_endian, path, _redirect_table, table_length());
+ // If found.
+ if (index != ImageStrings::NOT_FOUND) {
+ // Get address of first byte of location attribute stream.
+ u4 offset = get_location_offset(index);
+ u1* data = get_location_offset_data(offset);
+ // Expand location attributes.
+ ImageLocation location(data);
+ // Make sure result is not a false positive.
+ if (verify_location(location, path)) {
+ *size = (jlong)location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED);
+ return offset;
+ }
}
- }
- return 0; // not found
+ return 0; // not found
}
// Assemble the location path from the string fragments indicated in the location attributes.
void ImageFileReader::location_path(ImageLocation& location, char* path, size_t max) const {
- // Manage the image string table.
- ImageStrings strings(_string_bytes, _header.strings_size(_endian));
- // Position to first character of the path buffer.
- char* next = path;
- // Temp for string length.
- size_t length;
- // Get module string.
- const char* module = location.get_attribute(ImageLocation::ATTRIBUTE_MODULE, strings);
- // If module string is not empty string.
- if (*module != '\0') {
- // Get length of module name.
- length = strlen(module);
- // Make sure there is no buffer overflow.
- assert(next - path + length + 2 < max && "buffer overflow");
- // Append '/module/'.
- *next++ = '/';
- strncpy(next, module, length); next += length;
- *next++ = '/';
- }
- // Get parent (package) string.
- const char* parent = location.get_attribute(ImageLocation::ATTRIBUTE_PARENT, strings);
- // If parent string is not empty string.
- if (*parent != '\0') {
- // Get length of module string.
- length = strlen(parent);
+ // Manage the image string table.
+ ImageStrings strings(_string_bytes, _header.strings_size(_endian));
+ // Position to first character of the path buffer.
+ char* next = path;
+ // Temp for string length.
+ size_t length;
+ // Get module string.
+ const char* module = location.get_attribute(ImageLocation::ATTRIBUTE_MODULE, strings);
+ // If module string is not empty string.
+ if (*module != '\0') {
+ // Get length of module name.
+ length = strlen(module);
+ // Make sure there is no buffer overflow.
+ assert(next - path + length + 2 < max && "buffer overflow");
+ // Append '/module/'.
+ *next++ = '/';
+ strncpy(next, module, length); next += length;
+ *next++ = '/';
+ }
+ // Get parent (package) string.
+ const char* parent = location.get_attribute(ImageLocation::ATTRIBUTE_PARENT, strings);
+ // If parent string is not empty string.
+ if (*parent != '\0') {
+ // Get length of module string.
+ length = strlen(parent);
+ // Make sure there is no buffer overflow.
+ assert(next - path + length + 1 < max && "buffer overflow");
+ // Append 'patent/' .
+ strncpy(next, parent, length); next += length;
+ *next++ = '/';
+ }
+ // Get base name string.
+ const char* base = location.get_attribute(ImageLocation::ATTRIBUTE_BASE, strings);
+ // Get length of base name.
+ length = strlen(base);
// Make sure there is no buffer overflow.
- assert(next - path + length + 1 < max && "buffer overflow");
- // Append 'patent/' .
- strncpy(next, parent, length); next += length;
- *next++ = '/';
- }
- // Get base name string.
- const char* base = location.get_attribute(ImageLocation::ATTRIBUTE_BASE, strings);
- // Get length of base name.
- length = strlen(base);
- // Make sure there is no buffer overflow.
- assert(next - path + length < max && "buffer overflow");
- // Append base name.
- strncpy(next, base, length); next += length;
- // Get extension string.
- const char* extension = location.get_attribute(ImageLocation::ATTRIBUTE_EXTENSION, strings);
- // If extension string is not empty string.
- if (*extension != '\0') {
- // Get length of extension string.
- length = strlen(extension);
+ assert(next - path + length < max && "buffer overflow");
+ // Append base name.
+ strncpy(next, base, length); next += length;
+ // Get extension string.
+ const char* extension = location.get_attribute(ImageLocation::ATTRIBUTE_EXTENSION, strings);
+ // If extension string is not empty string.
+ if (*extension != '\0') {
+ // Get length of extension string.
+ length = strlen(extension);
+ // Make sure there is no buffer overflow.
+ assert(next - path + length + 1 < max && "buffer overflow");
+ // Append '.extension' .
+ *next++ = '.';
+ strncpy(next, extension, length); next += length;
+ }
// Make sure there is no buffer overflow.
- assert(next - path + length + 1 < max && "buffer overflow");
- // Append '.extension' .
- *next++ = '.';
- strncpy(next, extension, length); next += length;
- }
- // Make sure there is no buffer overflow.
- assert((size_t)(next - path) < max && "buffer overflow");
- // Terminate string.
- *next = '\0';
+ assert((size_t)(next - path) < max && "buffer overflow");
+ // Terminate string.
+ *next = '\0';
}
// Verify that a found location matches the supplied path (without copying.)
bool ImageFileReader::verify_location(ImageLocation& location, const char* path) const {
- // Manage the image string table.
- ImageStrings strings(_string_bytes, _header.strings_size(_endian));
- // Position to first character of the path string.
- const char* next = path;
- // Get module name string.
- const char* module = location.get_attribute(ImageLocation::ATTRIBUTE_MODULE, strings);
- // If module string is not empty.
- if (*module != '\0') {
- // Compare '/module/' .
- if (*next++ != '/') return false;
- if (!(next = ImageStrings::starts_with(next, module))) return false;
- if (*next++ != '/') return false;
- }
- // Get parent (package) string
- const char* parent = location.get_attribute(ImageLocation::ATTRIBUTE_PARENT, strings);
- // If parent string is not empty string.
- if (*parent != '\0') {
- // Compare 'parent/' .
- if (!(next = ImageStrings::starts_with(next, parent))) return false;
- if (*next++ != '/') return false;
- }
- // Get base name string.
- const char* base = location.get_attribute(ImageLocation::ATTRIBUTE_BASE, strings);
- // Compare with basne name.
- if (!(next = ImageStrings::starts_with(next, base))) return false;
- // Get extension string.
- const char* extension = location.get_attribute(ImageLocation::ATTRIBUTE_EXTENSION, strings);
- // If extension is not empty.
- if (*extension != '\0') {
- // Compare '.extension' .
- if (*next++ != '.') return false;
- if (!(next = ImageStrings::starts_with(next, extension))) return false;
- }
- // True only if complete match and no more characters.
- return *next == '\0';
+ // Manage the image string table.
+ ImageStrings strings(_string_bytes, _header.strings_size(_endian));
+ // Position to first character of the path string.
+ const char* next = path;
+ // Get module name string.
+ const char* module = location.get_attribute(ImageLocation::ATTRIBUTE_MODULE, strings);
+ // If module string is not empty.
+ if (*module != '\0') {
+ // Compare '/module/' .
+ if (*next++ != '/') return false;
+ if (!(next = ImageStrings::starts_with(next, module))) return false;
+ if (*next++ != '/') return false;
+ }
+ // Get parent (package) string
+ const char* parent = location.get_attribute(ImageLocation::ATTRIBUTE_PARENT, strings);
+ // If parent string is not empty string.
+ if (*parent != '\0') {
+ // Compare 'parent/' .
+ if (!(next = ImageStrings::starts_with(next, parent))) return false;
+ if (*next++ != '/') return false;
+ }
+ // Get base name string.
+ const char* base = location.get_attribute(ImageLocation::ATTRIBUTE_BASE, strings);
+ // Compare with basne name.
+ if (!(next = ImageStrings::starts_with(next, base))) return false;
+ // Get extension string.
+ const char* extension = location.get_attribute(ImageLocation::ATTRIBUTE_EXTENSION, strings);
+ // If extension is not empty.
+ if (*extension != '\0') {
+ // Compare '.extension' .
+ if (*next++ != '.') return false;
+ if (!(next = ImageStrings::starts_with(next, extension))) return false;
+ }
+ // True only if complete match and no more characters.
+ return *next == '\0';
}
// Return the resource for the supplied location offset.
void ImageFileReader::get_resource(u4 offset, u1* uncompressed_data) const {
- // Get address of first byte of location attribute stream.
- u1* data = get_location_offset_data(offset);
- // Expand location attributes.
- ImageLocation location(data);
- // Read the data
- get_resource(location, uncompressed_data);
+ // Get address of first byte of location attribute stream.
+ u1* data = get_location_offset_data(offset);
+ // Expand location attributes.
+ ImageLocation location(data);
+ // Read the data
+ get_resource(location, uncompressed_data);
}
// Return the resource for the supplied location.
void ImageFileReader::get_resource(ImageLocation& location, u1* uncompressed_data) const {
- // Retrieve the byte offset and size of the resource.
- u8 offset = location.get_attribute(ImageLocation::ATTRIBUTE_OFFSET);
- u8 uncompressed_size = location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED);
- u8 compressed_size = location.get_attribute(ImageLocation::ATTRIBUTE_COMPRESSED);
- // If the resource is compressed.
- if (compressed_size != 0) {
- u1* compressed_data;
- // If not memory mapped read in bytes.
- if (!MemoryMapImage) {
- // Allocate buffer for compression.
- compressed_data = new u1[(u4)compressed_size];
- // Read bytes from offset beyond the image index.
- bool is_read = read_at(compressed_data, compressed_size, _index_size + offset);
- assert(is_read && "error reading from image or short read");
+ // Retrieve the byte offset and size of the resource.
+ u8 offset = location.get_attribute(ImageLocation::ATTRIBUTE_OFFSET);
+ u8 uncompressed_size = location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED);
+ u8 compressed_size = location.get_attribute(ImageLocation::ATTRIBUTE_COMPRESSED);
+ // If the resource is compressed.
+ if (compressed_size != 0) {
+ u1* compressed_data;
+ // If not memory mapped read in bytes.
+ if (!MemoryMapImage) {
+ // Allocate buffer for compression.
+ compressed_data = new u1[(u4)compressed_size];
+ // Read bytes from offset beyond the image index.
+ bool is_read = read_at(compressed_data, compressed_size, _index_size + offset);
+ assert(is_read && "error reading from image or short read");
+ } else {
+ compressed_data = get_data_address() + offset;
+ }
+ // Get image string table.
+ const ImageStrings strings = get_strings();
+ // Decompress resource.
+ ImageDecompressor::decompress_resource(compressed_data, uncompressed_data, (u4)uncompressed_size,
+ &strings);
+ // If not memory mapped then release temporary buffer.
+ if (!MemoryMapImage) {
+ delete compressed_data;
+ }
} else {
- compressed_data = get_data_address() + offset;
+ // Read bytes from offset beyond the image index.
+ bool is_read = read_at(uncompressed_data, uncompressed_size, _index_size + offset);
+ assert(is_read && "error reading from image or short read");
}
- // Get image string table.
- const ImageStrings strings = get_strings();
- // Decompress resource.
- ImageDecompressor::decompress_resource(compressed_data, uncompressed_data, (u4)uncompressed_size,
- &strings);
- // If not memory mapped then release temporary buffer.
- if (!MemoryMapImage) {
- delete compressed_data;
- }
- } else {
- // Read bytes from offset beyond the image index.
- bool is_read = read_at(uncompressed_data, uncompressed_size, _index_size + offset);
- assert(is_read && "error reading from image or short read");
- }
}
// Return the ImageModuleData for this image
ImageModuleData * ImageFileReader::get_image_module_data() {
- return module_data;
+ return module_data;
}
--- a/jdk/src/java.base/share/native/libjimage/imageFile.hpp Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/native/libjimage/imageFile.hpp Wed Jul 05 20:51:27 2017 +0200
@@ -1,14 +1,16 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ * 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
+ * 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).
*
@@ -19,7 +21,6 @@
* 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.
- *
*/
#ifndef LIBJIMAGE_IMAGEFILE_HPP
@@ -145,52 +146,52 @@
// Manage image file string table.
class ImageStrings {
private:
- u1* _data; // Data bytes for strings.
- u4 _size; // Number of bytes in the string table.
+ u1* _data; // Data bytes for strings.
+ u4 _size; // Number of bytes in the string table.
public:
- enum {
- // Not found result from find routine.
- NOT_FOUND = -1,
- // Prime used to generate hash for Perfect Hashing.
- HASH_MULTIPLIER = 0x01000193
- };
+ enum {
+ // Not found result from find routine.
+ NOT_FOUND = -1,
+ // Prime used to generate hash for Perfect Hashing.
+ HASH_MULTIPLIER = 0x01000193
+ };
- ImageStrings(u1* data, u4 size) : _data(data), _size(size) {}
+ ImageStrings(u1* data, u4 size) : _data(data), _size(size) {}
- // Return the UTF-8 string beginning at offset.
- inline const char* get(u4 offset) const {
- assert(offset < _size && "offset exceeds string table size");
- return (const char*)(_data + offset);
- }
+ // Return the UTF-8 string beginning at offset.
+ inline const char* get(u4 offset) const {
+ assert(offset < _size && "offset exceeds string table size");
+ return (const char*)(_data + offset);
+ }
- // Compute the Perfect Hashing hash code for the supplied UTF-8 string.
- inline static u4 hash_code(const char* string) {
- return hash_code(string, HASH_MULTIPLIER);
- }
+ // Compute the Perfect Hashing hash code for the supplied UTF-8 string.
+ inline static u4 hash_code(const char* string) {
+ return hash_code(string, HASH_MULTIPLIER);
+ }
- // Compute the Perfect Hashing hash code for the supplied string, starting at seed.
- static s4 hash_code(const char* string, s4 seed);
+ // Compute the Perfect Hashing hash code for the supplied string, starting at seed.
+ static s4 hash_code(const char* string, s4 seed);
- // Match up a string in a perfect hash table. Result still needs validation
- // for precise match.
- static s4 find(Endian* endian, const char* name, s4* redirect, u4 length);
+ // Match up a string in a perfect hash table. Result still needs validation
+ // for precise match.
+ static s4 find(Endian* endian, const char* name, s4* redirect, u4 length);
- // Test to see if UTF-8 string begins with the start UTF-8 string. If so,
- // return non-NULL address of remaining portion of string. Otherwise, return
- // NULL. Used to test sections of a path without copying from image string
- // table.
- static const char* starts_with(const char* string, const char* start);
+ // Test to see if UTF-8 string begins with the start UTF-8 string. If so,
+ // return non-NULL address of remaining portion of string. Otherwise, return
+ // NULL. Used to test sections of a path without copying from image string
+ // table.
+ static const char* starts_with(const char* string, const char* start);
- // Test to see if UTF-8 string begins with start char. If so, return non-NULL
- // address of remaining portion of string. Otherwise, return NULL. Used
- // to test a character of a path without copying.
- inline static const char* starts_with(const char* string, const char ch) {
- return *string == ch ? string + 1 : NULL;
- }
+ // Test to see if UTF-8 string begins with start char. If so, return non-NULL
+ // address of remaining portion of string. Otherwise, return NULL. Used
+ // to test a character of a path without copying.
+ inline static const char* starts_with(const char* string, const char ch) {
+ return *string == ch ? string + 1 : NULL;
+ }
};
-// Manage image file location attribute data. Within an image, a location's
-// attributes are compressed into a stream of bytes. An attribute stream is
+// Manage image file location attribute data. Within an image, a location's
+// attributes are compressed into a stream of bytes. An attribute stream is
// composed of individual attribute sequences. Each attribute sequence begins with
// a header byte containing the attribute 'kind' (upper 5 bits of header) and the
// 'length' less 1 (lower 3 bits of header) of bytes that follow containing the
@@ -208,91 +209,91 @@
//
// Notes:
// - Even though ATTRIBUTE_END is used to mark the end of the attribute stream,
-// streams will contain zero byte values to represent lesser significant bits.
-// Thus, detecting a zero byte is not sufficient to detect the end of an attribute
-// stream.
+// streams will contain zero byte values to represent lesser significant bits.
+// Thus, detecting a zero byte is not sufficient to detect the end of an attribute
+// stream.
// - ATTRIBUTE_OFFSET represents the number of bytes from the beginning of the region
-// storing the resources. Thus, in an image this represents the number of bytes
-// after the index.
+// storing the resources. Thus, in an image this represents the number of bytes
+// after the index.
// - Currently, compressed resources are represented by having a non-zero
-// ATTRIBUTE_COMPRESSED value. This represents the number of bytes stored in the
-// image, and the value of ATTRIBUTE_UNCOMPRESSED represents number of bytes of the
-// inflated resource in memory. If the ATTRIBUTE_COMPRESSED is zero then the value
-// of ATTRIBUTE_UNCOMPRESSED represents both the number of bytes in the image and
-// in memory. In the future, additional compression techniques will be used and
-// represented differently.
+// ATTRIBUTE_COMPRESSED value. This represents the number of bytes stored in the
+// image, and the value of ATTRIBUTE_UNCOMPRESSED represents number of bytes of the
+// inflated resource in memory. If the ATTRIBUTE_COMPRESSED is zero then the value
+// of ATTRIBUTE_UNCOMPRESSED represents both the number of bytes in the image and
+// in memory. In the future, additional compression techniques will be used and
+// represented differently.
// - Package strings include trailing slash and extensions include prefix period.
//
class ImageLocation {
public:
- enum {
- ATTRIBUTE_END, // End of attribute stream marker
- ATTRIBUTE_MODULE, // String table offset of module name
- ATTRIBUTE_PARENT, // String table offset of resource path parent
- ATTRIBUTE_BASE, // String table offset of resource path base
- ATTRIBUTE_EXTENSION, // String table offset of resource path extension
- ATTRIBUTE_OFFSET, // Container byte offset of resource
- ATTRIBUTE_COMPRESSED, // In image byte size of the compressed resource
- ATTRIBUTE_UNCOMPRESSED, // In memory byte size of the uncompressed resource
- ATTRIBUTE_COUNT // Number of attribute kinds
- };
+ enum {
+ ATTRIBUTE_END, // End of attribute stream marker
+ ATTRIBUTE_MODULE, // String table offset of module name
+ ATTRIBUTE_PARENT, // String table offset of resource path parent
+ ATTRIBUTE_BASE, // String table offset of resource path base
+ ATTRIBUTE_EXTENSION, // String table offset of resource path extension
+ ATTRIBUTE_OFFSET, // Container byte offset of resource
+ ATTRIBUTE_COMPRESSED, // In image byte size of the compressed resource
+ ATTRIBUTE_UNCOMPRESSED, // In memory byte size of the uncompressed resource
+ ATTRIBUTE_COUNT // Number of attribute kinds
+ };
private:
- // Values of inflated attributes.
- u8 _attributes[ATTRIBUTE_COUNT];
+ // Values of inflated attributes.
+ u8 _attributes[ATTRIBUTE_COUNT];
- // Return the attribute value number of bytes.
- inline static u1 attribute_length(u1 data) {
- return (data & 0x7) + 1;
- }
+ // Return the attribute value number of bytes.
+ inline static u1 attribute_length(u1 data) {
+ return (data & 0x7) + 1;
+ }
- // Return the attribute kind.
- inline static u1 attribute_kind(u1 data) {
- u1 kind = data >> 3;
- assert(kind < ATTRIBUTE_COUNT && "invalid attribute kind");
- return kind;
- }
+ // Return the attribute kind.
+ inline static u1 attribute_kind(u1 data) {
+ u1 kind = data >> 3;
+ assert(kind < ATTRIBUTE_COUNT && "invalid attribute kind");
+ return kind;
+ }
- // Return the attribute length.
- inline static u8 attribute_value(u1* data, u1 n) {
- assert(0 < n && n <= 8 && "invalid attribute value length");
- u8 value = 0;
- // Most significant bytes first.
- for (u1 i = 0; i < n; i++) {
- value <<= 8;
- value |= data[i];
+ // Return the attribute length.
+ inline static u8 attribute_value(u1* data, u1 n) {
+ assert(0 < n && n <= 8 && "invalid attribute value length");
+ u8 value = 0;
+ // Most significant bytes first.
+ for (u1 i = 0; i < n; i++) {
+ value <<= 8;
+ value |= data[i];
+ }
+ return value;
}
- return value;
- }
public:
- ImageLocation() {
- clear_data();
- }
+ ImageLocation() {
+ clear_data();
+ }
- ImageLocation(u1* data) {
- clear_data();
- set_data(data);
- }
+ ImageLocation(u1* data) {
+ clear_data();
+ set_data(data);
+ }
- // Inflates the attribute stream into individual values stored in the long
- // array _attributes. This allows an attribute value to be quickly accessed by
- // direct indexing. Unspecified values default to zero.
- void set_data(u1* data);
+ // Inflates the attribute stream into individual values stored in the long
+ // array _attributes. This allows an attribute value to be quickly accessed by
+ // direct indexing. Unspecified values default to zero.
+ void set_data(u1* data);
- // Zero all attribute values.
- void clear_data();
+ // Zero all attribute values.
+ void clear_data();
- // Retrieve an attribute value from the inflated array.
- inline u8 get_attribute(u1 kind) const {
- assert(ATTRIBUTE_END < kind && kind < ATTRIBUTE_COUNT && "invalid attribute kind");
- return _attributes[kind];
- }
+ // Retrieve an attribute value from the inflated array.
+ inline u8 get_attribute(u1 kind) const {
+ assert(ATTRIBUTE_END < kind && kind < ATTRIBUTE_COUNT && "invalid attribute kind");
+ return _attributes[kind];
+ }
- // Retrieve an attribute string value from the inflated array.
- inline const char* get_attribute(u4 kind, const ImageStrings& strings) const {
- return strings.get((u4)get_attribute(kind));
- }
+ // Retrieve an attribute string value from the inflated array.
+ inline const char* get_attribute(u4 kind, const ImageStrings& strings) const {
+ return strings.get((u4)get_attribute(kind));
+ }
};
//
@@ -306,133 +307,133 @@
// padding for hash table lookup.)
//
// Format:
-// Count of package to module entries
-// Count of module to package entries
-// Perfect Hash redirect table[Count of package to module entries]
-// Package to module entries[Count of package to module entries]
-// Offset to package name in string table
-// Offset to module name in string table
-// Perfect Hash redirect table[Count of module to package entries]
-// Module to package entries[Count of module to package entries]
-// Offset to module name in string table
-// Count of packages in module
-// Offset to first package in packages table
-// Packages[]
-// Offset to package name in string table
+// Count of package to module entries
+// Count of module to package entries
+// Perfect Hash redirect table[Count of package to module entries]
+// Package to module entries[Count of package to module entries]
+// Offset to package name in string table
+// Offset to module name in string table
+// Perfect Hash redirect table[Count of module to package entries]
+// Module to package entries[Count of module to package entries]
+// Offset to module name in string table
+// Count of packages in module
+// Offset to first package in packages table
+// Packages[]
+// Offset to package name in string table
//
// Manage the image module meta data.
class ImageModuleData {
- class Header {
- private:
- u4 _ptm_count; // Count of package to module entries
- u4 _mtp_count; // Count of module to package entries
- public:
- inline u4 ptm_count(Endian* endian) const { return endian->get(_ptm_count); }
- inline u4 mtp_count(Endian* endian) const { return endian->get(_mtp_count); }
- };
+ class Header {
+ private:
+ u4 _ptm_count; // Count of package to module entries
+ u4 _mtp_count; // Count of module to package entries
+ public:
+ inline u4 ptm_count(Endian* endian) const { return endian->get(_ptm_count); }
+ inline u4 mtp_count(Endian* endian) const { return endian->get(_mtp_count); }
+ };
- // Hashtable entry
- class HashData {
- private:
- u4 _name_offset; // Name offset in string table
- public:
- inline s4 name_offset(Endian* endian) const { return endian->get(_name_offset); }
- };
+ // Hashtable entry
+ class HashData {
+ private:
+ u4 _name_offset; // Name offset in string table
+ public:
+ inline s4 name_offset(Endian* endian) const { return endian->get(_name_offset); }
+ };
- // Package to module hashtable entry
- class PTMData : public HashData {
- private:
- u4 _module_name_offset; // Module name offset in string table
- public:
- inline s4 module_name_offset(Endian* endian) const { return endian->get(_module_name_offset); }
- };
+ // Package to module hashtable entry
+ class PTMData : public HashData {
+ private:
+ u4 _module_name_offset; // Module name offset in string table
+ public:
+ inline s4 module_name_offset(Endian* endian) const { return endian->get(_module_name_offset); }
+ };
- // Module to package hashtable entry
- class MTPData : public HashData {
- private:
- u4 _package_count; // Number of packages in module
- u4 _package_offset; // Offset in package list
- public:
- inline u4 package_count(Endian* endian) const { return endian->get(_package_count); }
- inline u4 package_offset(Endian* endian) const { return endian->get(_package_offset); }
- };
+ // Module to package hashtable entry
+ class MTPData : public HashData {
+ private:
+ u4 _package_count; // Number of packages in module
+ u4 _package_offset; // Offset in package list
+ public:
+ inline u4 package_count(Endian* endian) const { return endian->get(_package_count); }
+ inline u4 package_offset(Endian* endian) const { return endian->get(_package_offset); }
+ };
- const ImageFileReader* _image_file; // Source image file
- Endian* _endian; // Endian handler
- ImageStrings _strings; // Image file strings
- u1* _data; // Module data resource data
- u8 _data_size; // Size of resource data
- Header* _header; // Module data header
- s4* _ptm_redirect; // Package to module hashtable redirect
- PTMData* _ptm_data; // Package to module data
- s4* _mtp_redirect; // Module to packages hashtable redirect
- MTPData* _mtp_data; // Module to packages data
- s4* _mtp_packages; // Package data (name offsets)
+ const ImageFileReader* _image_file; // Source image file
+ Endian* _endian; // Endian handler
+ ImageStrings _strings; // Image file strings
+ u1* _data; // Module data resource data
+ u8 _data_size; // Size of resource data
+ Header* _header; // Module data header
+ s4* _ptm_redirect; // Package to module hashtable redirect
+ PTMData* _ptm_data; // Package to module data
+ s4* _mtp_redirect; // Module to packages hashtable redirect
+ MTPData* _mtp_data; // Module to packages data
+ s4* _mtp_packages; // Package data (name offsets)
- // Return a string from the string table.
- inline const char* get_string(u4 offset) {
- return _strings.get(offset);
- }
+ // Return a string from the string table.
+ inline const char* get_string(u4 offset) {
+ return _strings.get(offset);
+ }
- inline u4 mtp_package(u4 index) {
- return _endian->get(_mtp_packages[index]);
- }
+ inline u4 mtp_package(u4 index) {
+ return _endian->get(_mtp_packages[index]);
+ }
public:
- ImageModuleData(const ImageFileReader* image_file, const char* module_data_name);
- ~ImageModuleData();
+ ImageModuleData(const ImageFileReader* image_file, const char* module_data_name);
+ ~ImageModuleData();
- // Return the name of the module data resource.
- static void module_data_name(char* buffer, const char* image_file_name);
+ // Return the name of the module data resource.
+ static void module_data_name(char* buffer, const char* image_file_name);
- // Return the module in which a package resides. Returns NULL if not found.
- const char* package_to_module(const char* package_name);
+ // Return the module in which a package resides. Returns NULL if not found.
+ const char* package_to_module(const char* package_name);
- // Returns all the package names in a module in a NULL terminated array.
- // Returns NULL if module not found.
- const char** module_to_packages(const char* module_name);
+ // Returns all the package names in a module in a NULL terminated array.
+ // Returns NULL if module not found.
+ const char** module_to_packages(const char* module_name);
};
// Image file header, starting at offset 0.
class ImageHeader {
private:
- u4 _magic; // Image file marker
- u4 _version; // Image file major version number
- u4 _flags; // Image file flags
- u4 _resource_count; // Number of resources in file
- u4 _table_length; // Number of slots in index tables
- u4 _locations_size; // Number of bytes in attribute table
- u4 _strings_size; // Number of bytes in string table
+ u4 _magic; // Image file marker
+ u4 _version; // Image file major version number
+ u4 _flags; // Image file flags
+ u4 _resource_count; // Number of resources in file
+ u4 _table_length; // Number of slots in index tables
+ u4 _locations_size; // Number of bytes in attribute table
+ u4 _strings_size; // Number of bytes in string table
public:
- u4 magic() const { return _magic; }
- u4 magic(Endian* endian) const { return endian->get(_magic); }
- void set_magic(Endian* endian, u4 magic) { return endian->set(_magic, magic); }
+ u4 magic() const { return _magic; }
+ u4 magic(Endian* endian) const { return endian->get(_magic); }
+ void set_magic(Endian* endian, u4 magic) { return endian->set(_magic, magic); }
- u4 major_version(Endian* endian) const { return endian->get(_version) >> 16; }
- u4 minor_version(Endian* endian) const { return endian->get(_version) & 0xFFFF; }
- void set_version(Endian* endian, u4 major_version, u4 minor_version) {
- return endian->set(_version, major_version << 16 | minor_version);
- }
+ u4 major_version(Endian* endian) const { return endian->get(_version) >> 16; }
+ u4 minor_version(Endian* endian) const { return endian->get(_version) & 0xFFFF; }
+ void set_version(Endian* endian, u4 major_version, u4 minor_version) {
+ return endian->set(_version, major_version << 16 | minor_version);
+ }
- u4 flags(Endian* endian) const { return endian->get(_flags); }
- void set_flags(Endian* endian, u4 value) { return endian->set(_flags, value); }
+ u4 flags(Endian* endian) const { return endian->get(_flags); }
+ void set_flags(Endian* endian, u4 value) { return endian->set(_flags, value); }
- u4 resource_count(Endian* endian) const { return endian->get(_resource_count); }
- void set_resource_count(Endian* endian, u4 count) { return endian->set(_resource_count, count); }
+ u4 resource_count(Endian* endian) const { return endian->get(_resource_count); }
+ void set_resource_count(Endian* endian, u4 count) { return endian->set(_resource_count, count); }
- u4 table_length(Endian* endian) const { return endian->get(_table_length); }
- void set_table_length(Endian* endian, u4 count) { return endian->set(_table_length, count); }
+ u4 table_length(Endian* endian) const { return endian->get(_table_length); }
+ void set_table_length(Endian* endian, u4 count) { return endian->set(_table_length, count); }
- u4 locations_size(Endian* endian) const { return endian->get(_locations_size); }
- void set_locations_size(Endian* endian, u4 size) { return endian->set(_locations_size, size); }
+ u4 locations_size(Endian* endian) const { return endian->get(_locations_size); }
+ void set_locations_size(Endian* endian, u4 size) { return endian->set(_locations_size, size); }
- u4 strings_size(Endian* endian) const { return endian->get(_strings_size); }
- void set_strings_size(Endian* endian, u4 size) { return endian->set(_strings_size, size); }
+ u4 strings_size(Endian* endian) const { return endian->get(_strings_size); }
+ void set_strings_size(Endian* endian, u4 size) { return endian->set(_strings_size, size); }
};
-// Max path length limit independent of platform. Windows max path is 1024,
-// other platforms use 4096. The JCK fails several tests when 1024 is used.
+// Max path length limit independent of platform. Windows max path is 1024,
+// other platforms use 4096. The JCK fails several tests when 1024 is used.
#define IMAGE_MAX_PATH 4096
class ImageFileReader;
@@ -441,29 +442,29 @@
// to share an open image.
class ImageFileReaderTable {
private:
- const static u4 _growth = 8; // Growth rate of the table
- u4 _count; // Number of entries in the table
- u4 _max; // Maximum number of entries allocated
- ImageFileReader** _table; // Growable array of entries
+ const static u4 _growth = 8; // Growth rate of the table
+ u4 _count; // Number of entries in the table
+ u4 _max; // Maximum number of entries allocated
+ ImageFileReader** _table; // Growable array of entries
public:
- ImageFileReaderTable();
- ~ImageFileReaderTable();
+ ImageFileReaderTable();
+ ~ImageFileReaderTable();
- // Return the number of entries.
- inline u4 count() { return _count; }
+ // Return the number of entries.
+ inline u4 count() { return _count; }
- // Return the ith entry from the table.
- inline ImageFileReader* get(u4 i) { return _table[i]; }
+ // Return the ith entry from the table.
+ inline ImageFileReader* get(u4 i) { return _table[i]; }
- // Add a new image entry to the table.
- void add(ImageFileReader* image);
+ // Add a new image entry to the table.
+ void add(ImageFileReader* image);
- // Remove an image entry from the table.
- void remove(ImageFileReader* image);
+ // Remove an image entry from the table.
+ void remove(ImageFileReader* image);
- // Determine if image entry is in table.
- bool contains(ImageFileReader* image);
+ // Determine if image entry is in table.
+ bool contains(ImageFileReader* image);
};
// Manage the image file.
@@ -473,176 +474,176 @@
// index is then memory mapped to allow load on demand and sharing. The
// -XX:+MemoryMapImage flag determines if the entire file is loaded (server use.)
// An image can be used by Hotspot and multiple reference points in the JDK, thus
-// it is desirable to share a reader. To accomodate sharing, a share table is
+// it is desirable to share a reader. To accomodate sharing, a share table is
// defined (see ImageFileReaderTable in imageFile.cpp) To track the number of
// uses, ImageFileReader keeps a use count (_use). Use is incremented when
-// 'opened' by reference point and decremented when 'closed'. Use of zero
+// 'opened' by reference point and decremented when 'closed'. Use of zero
// leads the ImageFileReader to be actually closed and discarded.
class ImageFileReader {
private:
- // Manage a number of image files such that an image can be shared across
- // multiple uses (ex. loader.)
- static ImageFileReaderTable _reader_table;
+ // Manage a number of image files such that an image can be shared across
+ // multiple uses (ex. loader.)
+ static ImageFileReaderTable _reader_table;
- char* _name; // Name of image
- s4 _use; // Use count
- int _fd; // File descriptor
- Endian* _endian; // Endian handler
- u8 _file_size; // File size in bytes
- ImageHeader _header; // Image header
- size_t _index_size; // Total size of index
- u1* _index_data; // Raw index data
- s4* _redirect_table; // Perfect hash redirect table
- u4* _offsets_table; // Location offset table
- u1* _location_bytes; // Location attributes
- u1* _string_bytes; // String table
- ImageModuleData *module_data; // The ImageModuleData for this image
+ char* _name; // Name of image
+ s4 _use; // Use count
+ int _fd; // File descriptor
+ Endian* _endian; // Endian handler
+ u8 _file_size; // File size in bytes
+ ImageHeader _header; // Image header
+ size_t _index_size; // Total size of index
+ u1* _index_data; // Raw index data
+ s4* _redirect_table; // Perfect hash redirect table
+ u4* _offsets_table; // Location offset table
+ u1* _location_bytes; // Location attributes
+ u1* _string_bytes; // String table
+ ImageModuleData *module_data; // The ImageModuleData for this image
- ImageFileReader(const char* name, bool big_endian);
- ~ImageFileReader();
+ ImageFileReader(const char* name, bool big_endian);
+ ~ImageFileReader();
- // Compute number of bytes in image file index.
- inline size_t index_size() {
- return sizeof(ImageHeader) +
- table_length() * sizeof(u4) * 2 + locations_size() + strings_size();
- }
+ // Compute number of bytes in image file index.
+ inline size_t index_size() {
+ return sizeof(ImageHeader) +
+ table_length() * sizeof(u4) * 2 + locations_size() + strings_size();
+ }
public:
- enum {
- // Image file marker.
- IMAGE_MAGIC = 0xCAFEDADA,
- // Endian inverted Image file marker.
- IMAGE_MAGIC_INVERT = 0xDADAFECA,
- // Image file major version number.
- MAJOR_VERSION = 1,
- // Image file minor version number.
- MINOR_VERSION = 0
- };
+ enum {
+ // Image file marker.
+ IMAGE_MAGIC = 0xCAFEDADA,
+ // Endian inverted Image file marker.
+ IMAGE_MAGIC_INVERT = 0xDADAFECA,
+ // Image file major version number.
+ MAJOR_VERSION = 1,
+ // Image file minor version number.
+ MINOR_VERSION = 0
+ };
- // Open an image file, reuse structure if file already open.
- static ImageFileReader* open(const char* name, bool big_endian = Endian::is_big_endian());
+ // Open an image file, reuse structure if file already open.
+ static ImageFileReader* open(const char* name, bool big_endian = Endian::is_big_endian());
- // Close an image file if the file is not in use elsewhere.
- static void close(ImageFileReader *reader);
+ // Close an image file if the file is not in use elsewhere.
+ static void close(ImageFileReader *reader);
- // Return an id for the specifed ImageFileReader.
- static u8 readerToID(ImageFileReader *reader);
+ // Return an id for the specifed ImageFileReader.
+ static u8 readerToID(ImageFileReader *reader);
- // Validate the image id.
- static bool idCheck(u8 id);
+ // Validate the image id.
+ static bool idCheck(u8 id);
- // Return an id for the specifed ImageFileReader.
- static ImageFileReader* idToReader(u8 id);
+ // Return an id for the specifed ImageFileReader.
+ static ImageFileReader* idToReader(u8 id);
- // Open image file for read access.
- bool open();
+ // Open image file for read access.
+ bool open();
- // Close image file.
- void close();
+ // Close image file.
+ void close();
- // Read directly from the file.
- bool read_at(u1* data, u8 size, u8 offset) const;
+ // Read directly from the file.
+ bool read_at(u1* data, u8 size, u8 offset) const;
- inline Endian* endian() const { return _endian; }
+ inline Endian* endian() const { return _endian; }
- // Retrieve name of image file.
- inline const char* name() const {
- return _name;
- }
+ // Retrieve name of image file.
+ inline const char* name() const {
+ return _name;
+ }
- // Retrieve size of image file.
- inline u8 file_size() const {
- return _file_size;
- }
+ // Retrieve size of image file.
+ inline u8 file_size() const {
+ return _file_size;
+ }
- // Return first address of index data.
- inline u1* get_index_address() const {
- return _index_data;
- }
+ // Return first address of index data.
+ inline u1* get_index_address() const {
+ return _index_data;
+ }
- // Return first address of resource data.
- inline u1* get_data_address() const {
- return _index_data + _index_size;
- }
+ // Return first address of resource data.
+ inline u1* get_data_address() const {
+ return _index_data + _index_size;
+ }
- // Get the size of the index data.
- size_t get_index_size() const {
- return _index_size;
- }
+ // Get the size of the index data.
+ size_t get_index_size() const {
+ return _index_size;
+ }
- inline u4 table_length() const {
- return _header.table_length(_endian);
- }
+ inline u4 table_length() const {
+ return _header.table_length(_endian);
+ }
- inline u4 locations_size() const {
- return _header.locations_size(_endian);
- }
+ inline u4 locations_size() const {
+ return _header.locations_size(_endian);
+ }
- inline u4 strings_size()const {
- return _header.strings_size(_endian);
- }
+ inline u4 strings_size()const {
+ return _header.strings_size(_endian);
+ }
- inline u4* offsets_table() const {
- return _offsets_table;
- }
+ inline u4* offsets_table() const {
+ return _offsets_table;
+ }
- // Increment use count.
- inline void inc_use() {
- _use++;
- }
+ // Increment use count.
+ inline void inc_use() {
+ _use++;
+ }
- // Decrement use count.
- inline bool dec_use() {
- return --_use == 0;
- }
+ // Decrement use count.
+ inline bool dec_use() {
+ return --_use == 0;
+ }
- // Return a string table accessor.
- inline const ImageStrings get_strings() const {
- return ImageStrings(_string_bytes, _header.strings_size(_endian));
- }
+ // Return a string table accessor.
+ inline const ImageStrings get_strings() const {
+ return ImageStrings(_string_bytes, _header.strings_size(_endian));
+ }
- // Return location attribute stream at offset.
- inline u1* get_location_offset_data(u4 offset) const {
- assert((u4)offset < _header.locations_size(_endian) &&
- "offset exceeds location attributes size");
- return offset != 0 ? _location_bytes + offset : NULL;
- }
+ // Return location attribute stream at offset.
+ inline u1* get_location_offset_data(u4 offset) const {
+ assert((u4)offset < _header.locations_size(_endian) &&
+ "offset exceeds location attributes size");
+ return offset != 0 ? _location_bytes + offset : NULL;
+ }
- // Return location attribute stream for location i.
- inline u1* get_location_data(u4 index) const {
- return get_location_offset_data(get_location_offset(index));
- }
+ // Return location attribute stream for location i.
+ inline u1* get_location_data(u4 index) const {
+ return get_location_offset_data(get_location_offset(index));
+ }
- // Return the location offset for index.
- inline u4 get_location_offset(u4 index) const {
- assert((u4)index < _header.table_length(_endian) &&
- "index exceeds location count");
- return _endian->get(_offsets_table[index]);
- }
+ // Return the location offset for index.
+ inline u4 get_location_offset(u4 index) const {
+ assert((u4)index < _header.table_length(_endian) &&
+ "index exceeds location count");
+ return _endian->get(_offsets_table[index]);
+ }
- // Find the location attributes associated with the path. Returns true if
- // the location is found, false otherwise.
- bool find_location(const char* path, ImageLocation& location) const;
+ // Find the location attributes associated with the path. Returns true if
+ // the location is found, false otherwise.
+ bool find_location(const char* path, ImageLocation& location) const;
- // Find the location index and size associated with the path.
- // Returns the location index and size if the location is found,
- // ImageFileReader::NOT_FOUND otherwise.
- u4 find_location_index(const char* path, u8 *size) const;
+ // Find the location index and size associated with the path.
+ // Returns the location index and size if the location is found,
+ // ImageFileReader::NOT_FOUND otherwise.
+ u4 find_location_index(const char* path, u8 *size) const;
- // Assemble the location path.
- void location_path(ImageLocation& location, char* path, size_t max) const;
+ // Assemble the location path.
+ void location_path(ImageLocation& location, char* path, size_t max) const;
- // Verify that a found location matches the supplied path.
- bool verify_location(ImageLocation& location, const char* path) const;
+ // Verify that a found location matches the supplied path.
+ bool verify_location(ImageLocation& location, const char* path) const;
- // Return the resource for the supplied location index.
- void get_resource(u4 index, u1* uncompressed_data) const;
+ // Return the resource for the supplied location index.
+ void get_resource(u4 index, u1* uncompressed_data) const;
- // Return the resource for the supplied path.
- void get_resource(ImageLocation& location, u1* uncompressed_data) const;
+ // Return the resource for the supplied path.
+ void get_resource(ImageLocation& location, u1* uncompressed_data) const;
- // Return the ImageModuleData for this image
- ImageModuleData * get_image_module_data();
+ // Return the ImageModuleData for this image
+ ImageModuleData * get_image_module_data();
};
#endif // LIBJIMAGE_IMAGEFILE_HPP
--- a/jdk/src/java.base/share/native/libjimage/inttypes.hpp Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/native/libjimage/inttypes.hpp Wed Jul 05 20:51:27 2017 +0200
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
@@ -19,7 +21,6 @@
* 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.
- *
*/
#ifndef LIBJIMAGE_INTTYPES_HPP
--- a/jdk/src/java.base/share/native/libjimage/jimage.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/native/libjimage/jimage.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -1,10 +1,12 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ * 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
@@ -19,7 +21,6 @@
* 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 <string.h>
@@ -97,7 +98,8 @@
*
* Ex.
* jlong size;
- * JImageLocationRef location = (*JImageFindResource)(image, "java.base", "9.0", "java/lang/String.class", &size);
+ * JImageLocationRef location = (*JImageFindResource)(image,
+ * "java.base", "9.0", "java/lang/String.class", &size);
*/
extern "C" JImageLocationRef JIMAGE_FindResource(JImageFile* image,
const char* module_name, const char* version, const char* name,
@@ -129,7 +131,8 @@
*
* Ex.
* jlong size;
- * JImageLocationRef* location = (*JImageFindResource)(image, "java.base", "9.0", "java/lang/String.class", &size);
+ * JImageLocationRef location = (*JImageFindResource)(image,
+ * "java.base", "9.0", "java/lang/String.class", &size);
* char* buffer = new char[size];
* (*JImageGetResource)(image, location, buffer, size);
*/
@@ -148,7 +151,8 @@
* required. All strings are utf-8, zero byte terminated.file.
*
* Ex.
- * bool ctw_visitor(JImageFile* jimage, const char* module_name, const char* version, const char* package, const char* name, const char* extension, void* arg) {
+ * bool ctw_visitor(JImageFile* jimage, const char* module_name, const char* version,
+ * const char* package, const char* name, const char* extension, void* arg) {
* if (strcmp(extension, “class”) == 0) {
* char path[JIMAGE_MAX_PATH];
* Thread* THREAD = Thread::current();
--- a/jdk/src/java.base/share/native/libjimage/jimage.hpp Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/native/libjimage/jimage.hpp Wed Jul 05 20:51:27 2017 +0200
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
@@ -19,7 +21,6 @@
* 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 "jni.h"
@@ -111,7 +112,8 @@
*
* Ex.
* jlong size;
- * JImageLocationRef location = (*JImageFindResource)(image, "java.base", "9.0", "java/lang/String.class", &size);
+ * JImageLocationRef location = (*JImageFindResource)(image,
+ * "java.base", "9.0", "java/lang/String.class", &size);
*/
extern "C" JImageLocationRef JIMAGE_FindResource(JImageFile* jimage,
const char* module_name, const char* version, const char* name,
@@ -132,7 +134,8 @@
*
* Ex.
* jlong size;
- * JImageLocationRef location = (*JImageFindResource)(image, "java.base", "9.0", "java/lang/String.class", &size);
+ * JImageLocationRef location = (*JImageFindResource)(image,
+ * "java.base", "9.0", "java/lang/String.class", &size);
* char* buffer = new char[size];
* (*JImageGetResource)(image, location, buffer, size);
*/
@@ -152,7 +155,8 @@
* required. All strings are utf-8, zero byte terminated.file.
*
* Ex.
- * bool ctw_visitor(JImageFile* jimage, const char* module_name, const char* version, const char* package, const char* name, const char* extension, void* arg) {
+ * bool ctw_visitor(JImageFile* jimage, const char* module_name, const char* version,
+ * const char* package, const char* name, const char* extension, void* arg) {
* if (strcmp(extension, “class”) == 0) {
* char path[JIMAGE_MAX_PATH];
* Thread* THREAD = Thread::current();
--- a/jdk/src/java.base/share/native/libjimage/osSupport.hpp Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/share/native/libjimage/osSupport.hpp Wed Jul 05 20:51:27 2017 +0200
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
@@ -19,7 +21,6 @@
* 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.
- *
*/
#ifndef LIBJIMAGE_OSSUPPORT_HPP
--- a/jdk/src/java.base/unix/native/libjimage/osSupport_unix.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/unix/native/libjimage/osSupport_unix.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
@@ -19,10 +21,8 @@
* 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 <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
--- a/jdk/src/java.base/windows/native/libjimage/osSupport_windows.cpp Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.base/windows/native/libjimage/osSupport_windows.cpp Wed Jul 05 20:51:27 2017 +0200
@@ -4,7 +4,9 @@
*
* 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.
+ * 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
@@ -19,7 +21,6 @@
* 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 <windows.h>
--- a/jdk/src/java.scripting/share/classes/javax/script/Bindings.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.scripting/share/classes/javax/script/Bindings.java Wed Jul 05 20:51:27 2017 +0200
@@ -28,7 +28,7 @@
/**
* A mapping of key/value pairs, all of whose keys are
- * <code>Strings</code>.
+ * {@code Strings}.
*
* @author Mike Grogan
* @since 1.6
@@ -49,8 +49,8 @@
public Object put(String name, Object value);
/**
- * Adds all the mappings in a given <code>Map</code> to this <code>Bindings</code>.
- * @param toMerge The <code>Map</code> to merge with this one.
+ * Adds all the mappings in a given {@code Map} to this {@code Bindings}.
+ * @param toMerge The {@code Map} to merge with this one.
*
* @throws NullPointerException
* if toMerge map is null or if some key in the map is null.
@@ -60,14 +60,14 @@
public void putAll(Map<? extends String, ? extends Object> toMerge);
/**
- * Returns <tt>true</tt> if this map contains a mapping for the specified
- * key. More formally, returns <tt>true</tt> if and only if
- * this map contains a mapping for a key <tt>k</tt> such that
- * <tt>(key==null ? k==null : key.equals(k))</tt>. (There can be
+ * Returns {@code true} if this map contains a mapping for the specified
+ * key. More formally, returns {@code true} if and only if
+ * this map contains a mapping for a key {@code k} such that
+ * {@code (key==null ? k==null : key.equals(k))}. (There can be
* at most one such mapping.)
*
* @param key key whose presence in this map is to be tested.
- * @return <tt>true</tt> if this map contains a mapping for the specified
+ * @return {@code true} if this map contains a mapping for the specified
* key.
*
* @throws NullPointerException if key is null
@@ -78,20 +78,21 @@
/**
* Returns the value to which this map maps the specified key. Returns
- * <tt>null</tt> if the map contains no mapping for this key. A return
- * value of <tt>null</tt> does not <i>necessarily</i> indicate that the
+ * {@code null} if the map contains no mapping for this key. A return
+ * value of {@code null} does not <i>necessarily</i> indicate that the
* map contains no mapping for the key; it's also possible that the map
- * explicitly maps the key to <tt>null</tt>. The <tt>containsKey</tt>
+ * explicitly maps the key to {@code null}. The {@code containsKey}
* operation may be used to distinguish these two cases.
*
* <p>More formally, if this map contains a mapping from a key
- * <tt>k</tt> to a value <tt>v</tt> such that <tt>(key==null ? k==null :
- * key.equals(k))</tt>, then this method returns <tt>v</tt>; otherwise
- * it returns <tt>null</tt>. (There can be at most one such mapping.)
+ * {@code k} to a value {@code v} such that
+ * {@code (key==null ? k==null : key.equals(k))},
+ * then this method returns {@code v}; otherwise
+ * it returns {@code null}. (There can be at most one such mapping.)
*
* @param key key whose associated value is to be returned.
* @return the value to which this map maps the specified key, or
- * <tt>null</tt> if the map contains no mapping for this key.
+ * {@code null} if the map contains no mapping for this key.
*
* @throws NullPointerException if key is null
* @throws ClassCastException if key is not String
@@ -102,19 +103,19 @@
/**
* Removes the mapping for this key from this map if it is present
* (optional operation). More formally, if this map contains a mapping
- * from key <tt>k</tt> to value <tt>v</tt> such that
- * <code>(key==null ? k==null : key.equals(k))</code>, that mapping
+ * from key {@code k} to value {@code v} such that
+ * {@code (key==null ? k==null : key.equals(k))}, that mapping
* is removed. (The map can contain at most one such mapping.)
*
* <p>Returns the value to which the map previously associated the key, or
- * <tt>null</tt> if the map contained no mapping for this key. (A
- * <tt>null</tt> return can also indicate that the map previously
- * associated <tt>null</tt> with the specified key if the implementation
- * supports <tt>null</tt> values.) The map will not contain a mapping for
+ * {@code null} if the map contained no mapping for this key. (A
+ * {@code null} return can also indicate that the map previously
+ * associated {@code null} with the specified key if the implementation
+ * supports {@code null} values.) The map will not contain a mapping for
* the specified key once the call returns.
*
* @param key key whose mapping is to be removed from the map.
- * @return previous value associated with specified key, or <tt>null</tt>
+ * @return previous value associated with specified key, or {@code null}
* if there was no mapping for key.
*
* @throws NullPointerException if key is null
--- a/jdk/src/java.scripting/share/classes/javax/script/SimpleBindings.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/java.scripting/share/classes/javax/script/SimpleBindings.java Wed Jul 05 20:51:27 2017 +0200
@@ -32,7 +32,7 @@
/**
* A simple implementation of Bindings backed by
- * a <code>HashMap</code> or some other specified <code>Map</code>.
+ * a {@code HashMap} or some other specified {@code Map}.
*
* @author Mike Grogan
* @since 1.6
@@ -40,13 +40,13 @@
public class SimpleBindings implements Bindings {
/**
- * The <code>Map</code> field stores the attributes.
+ * The {@code Map} field stores the attributes.
*/
private Map<String,Object> map;
/**
- * Constructor uses an existing <code>Map</code> to store the values.
- * @param m The <code>Map</code> backing this <code>SimpleBindings</code>.
+ * Constructor uses an existing {@code Map} to store the values.
+ * @param m The {@code Map} backing this {@code SimpleBindings}.
* @throws NullPointerException if m is null
*/
public SimpleBindings(Map<String,Object> m) {
@@ -57,14 +57,14 @@
}
/**
- * Default constructor uses a <code>HashMap</code>.
+ * Default constructor uses a {@code HashMap}.
*/
public SimpleBindings() {
this(new HashMap<String,Object>());
}
/**
- * Sets the specified key/value in the underlying <code>map</code> field.
+ * Sets the specified key/value in the underlying {@code map} field.
*
* @param name Name of value
* @param value Value to set.
@@ -81,9 +81,9 @@
}
/**
- * <code>putAll</code> is implemented using <code>Map.putAll</code>.
+ * {@code putAll} is implemented using {@code Map.putAll}.
*
- * @param toMerge The <code>Map</code> of values to add.
+ * @param toMerge The {@code Map} of values to add.
*
* @throws NullPointerException
* if toMerge map is null or if some key in the map is null.
@@ -107,14 +107,14 @@
}
/**
- * Returns <tt>true</tt> if this map contains a mapping for the specified
- * key. More formally, returns <tt>true</tt> if and only if
- * this map contains a mapping for a key <tt>k</tt> such that
- * <tt>(key==null ? k==null : key.equals(k))</tt>. (There can be
+ * Returns {@code true} if this map contains a mapping for the specified
+ * key. More formally, returns {@code true} if and only if
+ * this map contains a mapping for a key {@code k} such that
+ * {@code (key==null ? k==null : key.equals(k))}. (There can be
* at most one such mapping.)
*
* @param key key whose presence in this map is to be tested.
- * @return <tt>true</tt> if this map contains a mapping for the specified
+ * @return {@code true} if this map contains a mapping for the specified
* key.
*
* @throws NullPointerException if key is null
@@ -138,20 +138,21 @@
/**
* Returns the value to which this map maps the specified key. Returns
- * <tt>null</tt> if the map contains no mapping for this key. A return
- * value of <tt>null</tt> does not <i>necessarily</i> indicate that the
+ * {@code null} if the map contains no mapping for this key. A return
+ * value of {@code null} does not <i>necessarily</i> indicate that the
* map contains no mapping for the key; it's also possible that the map
- * explicitly maps the key to <tt>null</tt>. The <tt>containsKey</tt>
+ * explicitly maps the key to {@code null}. The {@code containsKey}
* operation may be used to distinguish these two cases.
*
* <p>More formally, if this map contains a mapping from a key
- * <tt>k</tt> to a value <tt>v</tt> such that <tt>(key==null ? k==null :
- * key.equals(k))</tt>, then this method returns <tt>v</tt>; otherwise
- * it returns <tt>null</tt>. (There can be at most one such mapping.)
+ * {@code k} to a value {@code v} such that
+ * {@code (key==null ? k==null : key.equals(k))},
+ * then this method returns {@code v}; otherwise
+ * it returns {@code null}. (There can be at most one such mapping.)
*
* @param key key whose associated value is to be returned.
* @return the value to which this map maps the specified key, or
- * <tt>null</tt> if the map contains no mapping for this key.
+ * {@code null} if the map contains no mapping for this key.
*
* @throws NullPointerException if key is null
* @throws ClassCastException if key is not String
@@ -175,19 +176,19 @@
/**
* Removes the mapping for this key from this map if it is present
* (optional operation). More formally, if this map contains a mapping
- * from key <tt>k</tt> to value <tt>v</tt> such that
- * <code>(key==null ? k==null : key.equals(k))</code>, that mapping
+ * from key {@code k} to value {@code v} such that
+ * {@code (key==null ? k==null : key.equals(k))}, that mapping
* is removed. (The map can contain at most one such mapping.)
*
* <p>Returns the value to which the map previously associated the key, or
- * <tt>null</tt> if the map contained no mapping for this key. (A
- * <tt>null</tt> return can also indicate that the map previously
- * associated <tt>null</tt> with the specified key if the implementation
- * supports <tt>null</tt> values.) The map will not contain a mapping for
+ * {@code null} if the map contained no mapping for this key. (A
+ * {@code null} return can also indicate that the map previously
+ * associated {@code null} with the specified key if the implementation
+ * supports {@code null} values.) The map will not contain a mapping for
* the specified key once the call returns.
*
* @param key key whose mapping is to be removed from the map.
- * @return previous value associated with specified key, or <tt>null</tt>
+ * @return previous value associated with specified key, or {@code null}
* if there was no mapping for key.
*
* @throws NullPointerException if key is null
--- a/jdk/src/jdk.jconsole/share/classes/com/sun/tools/jconsole/JConsolePlugin.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/jdk.jconsole/share/classes/com/sun/tools/jconsole/JConsolePlugin.java Wed Jul 05 20:51:27 2017 +0200
@@ -54,7 +54,7 @@
* <blockquote><pre>
* jconsole -pluginpath <plugin-path> </pre></blockquote>
*
- * <p> where <tt><plugin-path></tt> specifies the paths of JConsole
+ * <p> where {@code <plugin-path>} specifies the paths of JConsole
* plugins to look up which can be a directory or a jar file. Multiple
* paths are separated by the path separator character of the platform.
*
@@ -106,7 +106,7 @@
/**
* Returns the {@link JConsoleContext JConsoleContext} object representing
- * the connection to an application. This method may return <tt>null</tt>
+ * the connection to an application. This method may return {@code null}
* if it is called before the {@link #setContext context} is initialized.
*
* @return the {@link JConsoleContext JConsoleContext} object representing
@@ -146,24 +146,24 @@
* method to schedule the returned {@code SwingWorker} for execution
* if:
* <ul>
- * <li> the <tt>SwingWorker</tt> object has not been executed
+ * <li> the {@code SwingWorker} object has not been executed
* (i.e. the {@link SwingWorker#getState} method
* returns {@link javax.swing.SwingWorker.StateValue#PENDING PENDING}
* state); and</li>
- * <li> the <tt>SwingWorker</tt> object returned in the previous
- * update has completed the task if it was not <tt>null</tt>
+ * <li> the {@code SwingWorker} object returned in the previous
+ * update has completed the task if it was not {@code null}
* (i.e. the {@link SwingWorker#isDone SwingWorker.isDone} method
- * returns <tt>true</tt>).</li>
+ * returns {@code true}).</li>
* </ul>
* <br>
- * Otherwise, <tt>SwingWorker</tt> object will not be scheduled to work.
+ * Otherwise, {@code SwingWorker} object will not be scheduled to work.
*
* <p>
* A plugin can schedule its own GUI update and this method
- * will return <tt>null</tt>.
+ * will return {@code null}.
*
- * @return a <tt>SwingWorker</tt> to perform the GUI update; or
- * <tt>null</tt>.
+ * @return a {@code SwingWorker} to perform the GUI update; or
+ * {@code null}.
*/
public abstract SwingWorker<?,?> newSwingWorker();
--- a/jdk/src/jdk.jconsole/share/classes/sun/tools/jconsole/ProxyClient.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/jdk.jconsole/share/classes/sun/tools/jconsole/ProxyClient.java Wed Jul 05 20:51:27 2017 +0200
@@ -581,7 +581,7 @@
/**
* Returns a map of MBeans with ObjectName as the key and MBeanInfo value
- * of a given domain. If domain is <tt>null</tt>, all MBeans
+ * of a given domain. If domain is {@code null}, all MBeans
* are returned. If no MBean found, an empty map is returned.
*
*/
--- a/jdk/src/jdk.rmic/share/classes/sun/tools/java/ClassDefinition.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/jdk.rmic/share/classes/sun/tools/java/ClassDefinition.java Wed Jul 05 20:51:27 2017 +0200
@@ -259,7 +259,7 @@
* Tell if the class is inner.
* This predicate also returns true for top-level nested types.
* To test for a true inner class as seen by the programmer,
- * use <tt>!isTopLevel()</tt>.
+ * use {@code !isTopLevel()}.
*/
public final boolean isInnerClass() {
return outerClass != null;
@@ -911,7 +911,7 @@
}
/**
- * Note that this class is being used somehow by <tt>ref</tt>.
+ * Note that this class is being used somehow by {@code ref}.
* Report deprecation errors, etc.
*/
public void noteUsedBy(ClassDefinition ref, long where, Environment env) {
--- a/jdk/src/jdk.rmic/share/classes/sun/tools/java/Identifier.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/jdk.rmic/share/classes/sun/tools/java/Identifier.java Wed Jul 05 20:51:27 2017 +0200
@@ -200,7 +200,7 @@
/** A space character, which precedes the first inner class
* name in a qualified name, and thus marks the qualification
* as involving inner classes, instead of merely packages.<p>
- * Ex: <tt>java.util.Vector. Enumerator</tt>.
+ * Ex: {@code java.util.Vector. Enumerator}.
*/
public static final char INNERCLASS_PREFIX = ' ';
@@ -229,7 +229,7 @@
* and with any nesting flattened into a new qualfication structure.
* If the original identifier is inner,
* the result will be qualified, and can be further
- * decomposed by means of <tt>getQualifier</tt> and <tt>getName</tt>.
+ * decomposed by means of {@code getQualifier} and {@code getName}.
* <p>
* For example:
* <pre>
--- a/jdk/src/jdk.rmic/share/classes/sun/tools/javac/SourceMember.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/jdk.rmic/share/classes/sun/tools/javac/SourceMember.java Wed Jul 05 20:51:27 2017 +0200
@@ -394,7 +394,7 @@
* <p>
* This is the method which requests checking.
* The real work is done by
- * <tt>Vset check(Environment, Context, Vset)</tt>.
+ * {@code Vset check(Environment, Context, Vset)}.
*/
public void check(Environment env) throws ClassNotFound {
if (tracing) env.dtEnter("SourceMember.check: " +
--- a/jdk/src/jdk.rmic/share/classes/sun/tools/tree/Expression.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/src/jdk.rmic/share/classes/sun/tools/tree/Expression.java Wed Jul 05 20:51:27 2017 +0200
@@ -210,8 +210,8 @@
}
/**
- * Return a <code>FieldUpdater</code> object to be used in updating the
- * value of the location denoted by <code>this</code>, which must be an
+ * Return a {@code FieldUpdater} object to be used in updating the
+ * value of the location denoted by {@code this}, which must be an
* expression suitable for the left-hand side of an assignment.
* This is used for implementing assignments to private fields for which
* an access method is required. Returns null if no access method is
@@ -228,8 +228,8 @@
}
/**
- * Return a <code>FieldUpdater</code> object to be used in updating the value of the
- * location denoted by <code>this</code>, which must be an expression suitable for the
+ * Return a {@code FieldUpdater} object to be used in updating the value of the
+ * location denoted by {@code this}, which must be an expression suitable for the
* left-hand side of an assignment. This is used for implementing the assignment
* operators and the increment/decrement operators on private fields that require an
* access method, e.g., uplevel from an inner class. Returns null if no access method
@@ -260,9 +260,9 @@
* <li> a type name followed by fields or types
* <li> a package name followed a type and then fields or types
* </nl>
- * If a type name is found, it rewrites itself as a <tt>TypeExpression</tt>.
+ * If a type name is found, it rewrites itself as a {@code TypeExpression}.
* If a node decides it can only be a package prefix, it sets its
- * type to <tt>Type.tPackage</tt>. The caller must detect this
+ * type to {@code Type.tPackage}. The caller must detect this
* and act appropriately to verify the full package name.
* @arg loc the expression containing the ambiguous expression
*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/crypto/provider/CICO/CICOChainingTest.java Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2007, 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.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.util.Arrays;
+import javax.crypto.CipherInputStream;
+import javax.crypto.CipherOutputStream;
+
+/*
+ * @test
+ * @bug 8048604
+ * @summary This test verifies the assertion "The chaining feature of
+ * Filter streams should be supported." for feature "CipherInputStream &
+ * CipherOutputStream"
+ * @run main CICOChainingTest
+ */
+public class CICOChainingTest {
+ /**
+ * Plain text length.
+ */
+ private static final int PLAIN_TEXT_LENGTH = 200;
+
+ public static void main(String argv[]) throws Exception {
+ CICOChainingTest test = new CICOChainingTest();
+ test.chainTest(true);
+ test.chainTest(false);
+ }
+
+ /**
+ * Chain CipherInputStream/CipherOutputStream with other stream, encrypt
+ * the text and decrypt it, recovered text is supposed to be same as
+ * original text.
+ * @param useInt true if read byte by byte false if read with buffer.
+ * @throws IOException any I/O operation failed.
+ */
+ public void chainTest(boolean useInt) throws IOException {
+ byte[] plainText = TestUtilities.generateBytes(PLAIN_TEXT_LENGTH);
+ byte[] recoveredText = new byte[plainText.length];
+ // Do initialization
+ try (MyNullCipherInputStream ciInput1 = new MyNullCipherInputStream(
+ new ByteArrayInputStream(plainText));
+ PipedOutputStream piOut = new PipedOutputStream();
+ MyNullCipherInputStream ciInput2 = new MyNullCipherInputStream(
+ new PipedInputStream(piOut));
+ MyNullCipherOutputStream ciOut = new MyNullCipherOutputStream(
+ piOut);) {
+ if (useInt) {
+ int buffer = ciInput1.read();
+ while (buffer != -1) {
+ piOut.write(buffer);
+ buffer = ciInput1.read();
+ }
+ } else {
+ byte[] buffer = new byte[20];
+ int len = ciInput1.read(buffer);
+ while (len != -1) {
+ ciOut.write(buffer, 0, len);
+ len = ciInput1.read(buffer);
+ }
+ }
+ ciOut.flush();
+ piOut.flush();
+ // Get the output
+ ciInput2.read(recoveredText);
+ if (ciInput2.available() > 0) {
+ throw new RuntimeException("Expected no data from ciInput2, but"
+ + " ciInput2.available() = " + ciInput2.available());
+ }
+ }
+ // Verify output is same to input.
+ if (!Arrays.equals(plainText, recoveredText)) {
+ throw new RuntimeException("plainText:" + new String(plainText)
+ + " recoveredText:" + new String(recoveredText)
+ + " Test failed due to result compare fail");
+ }
+ }
+}
+
+class MyNullCipherInputStream extends CipherInputStream {
+
+ public MyNullCipherInputStream(InputStream is) {
+ super(is);
+ }
+}
+
+class MyNullCipherOutputStream extends CipherOutputStream {
+
+ public MyNullCipherOutputStream(OutputStream os) {
+ super(os);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/crypto/provider/CICO/CICODESFuncTest.java Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2007, 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.
+ */
+import static java.lang.System.out;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.Security;
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.Arrays;
+import javax.crypto.CipherInputStream;
+import javax.crypto.CipherOutputStream;
+import javax.crypto.SecretKey;
+import javax.crypto.Cipher;
+import javax.crypto.KeyGenerator;
+import javax.crypto.spec.IvParameterSpec;
+
+/*
+ * @test
+ * @bug 8048604
+ * @summary to verify cipherInputStream and cipherInputStream cipher function
+ * @run main CICODESFuncTest
+ */
+public class CICODESFuncTest {
+ /**
+ * Algorithms name.
+ */
+ private static final String[] ALGORITHMS = { "DES", "DESede", "Blowfish" };
+ private static final String[] MODES = { "ECB", "CBC", "CFB", "CFB24",
+ "CFB32", "CFB40", "CFB72", "OFB", "OFB20", "OFB48", "OFB56",
+ "OFB64", "PCBC" };
+ /**
+ * Padding mode.
+ */
+ private static final String[] PADDINGS = { "noPadding", "pkcs5padding" };
+ /**
+ * Plain text length.
+ */
+ private static final int TEXT_LENGTH = 80;
+ /**
+ * Initialization vector length.
+ */
+ private static final int IV_LENGTH = 8;
+
+ public static void main(String[] args) throws Exception {
+ Provider provider = Security.getProvider("SunJCE");
+ if (provider == null) {
+ throw new RuntimeException("SunJCE provider does not exist.");
+ }
+ for (String algorithm : ALGORITHMS) {
+ for (String mode : MODES) {
+ // We only test noPadding and pkcs5padding for CFB72, OFB20, ECB
+ // PCBC and CBC. Otherwise test noPadding only.
+ int padKinds = 1;
+ if (mode.equalsIgnoreCase("CFB72")
+ || mode.equalsIgnoreCase("OFB20")
+ || mode.equalsIgnoreCase("ECB")
+ || mode.equalsIgnoreCase("PCBC")
+ || mode.equalsIgnoreCase("CBC")) {
+ padKinds = PADDINGS.length;
+ }
+ // PKCS5padding is meaningful only for ECB, CBC, PCBC
+ for (int k = 0; k < padKinds; k++) {
+ for (ReadModel readMode : ReadModel.values()) {
+ runTest(provider, algorithm, mode, PADDINGS[k], readMode);
+ }
+ }
+ }
+ }
+ }
+
+ private static void runTest(Provider p, String algo, String mo, String pad,
+ ReadModel whichRead) throws GeneralSecurityException, IOException {
+ // Do initialization
+ byte[] plainText = TestUtilities.generateBytes(TEXT_LENGTH);
+ byte[] iv = TestUtilities.generateBytes(IV_LENGTH);
+ AlgorithmParameterSpec aps = new IvParameterSpec(iv);
+ try {
+ KeyGenerator kg = KeyGenerator.getInstance(algo, p);
+ out.println(algo + "/" + mo + "/" + pad + "/" + whichRead);
+ SecretKey key = kg.generateKey();
+ Cipher ci1 = Cipher.getInstance(algo + "/" + mo + "/" + pad, p);
+ if ("CFB72".equalsIgnoreCase(mo) || "OFB20".equalsIgnoreCase(mo)) {
+ throw new RuntimeException(
+ "NoSuchAlgorithmException not throw when mode"
+ + " is CFB72 or OFB20");
+ }
+ Cipher ci2 = Cipher.getInstance(algo + "/" + mo + "/" + pad, p);
+ if ("ECB".equalsIgnoreCase(mo)) {
+ ci1.init(Cipher.ENCRYPT_MODE, key);
+ ci2.init(Cipher.DECRYPT_MODE, key);
+ } else {
+ ci1.init(Cipher.ENCRYPT_MODE, key, aps);
+ ci2.init(Cipher.DECRYPT_MODE, key, aps);
+ }
+ ByteArrayOutputStream baOutput = new ByteArrayOutputStream();
+ try (CipherInputStream cInput
+ = new CipherInputStream(
+ new ByteArrayInputStream(plainText), ci1);
+ CipherOutputStream ciOutput
+ = new CipherOutputStream(baOutput, ci2);) {
+ // Read from the input and write to the output using 2 types
+ // of buffering : byte[] and int
+ whichRead.read(cInput, ciOutput, ci1, plainText.length);
+ }
+ // Verify input and output are same.
+ if (!Arrays.equals(plainText, baOutput.toByteArray())) {
+ throw new RuntimeException("Test failed due to compare fail ");
+ }
+ } catch (NoSuchAlgorithmException nsaEx) {
+ if ("CFB72".equalsIgnoreCase(mo) || "OFB20".equalsIgnoreCase(mo)) {
+ out.println("NoSuchAlgorithmException is expected for CFB72 and OFB20");
+ } else {
+ throw new RuntimeException("Unexpected exception testing: "
+ + algo + "/" + mo + "/" + pad + "/" + whichRead, nsaEx);
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/crypto/provider/CICO/CICOSkipTest.java Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 2007, 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.
+ */
+
+import static java.lang.System.out;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.Security;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidKeySpecException;
+import javax.crypto.Cipher;
+import javax.crypto.CipherInputStream;
+import javax.crypto.KeyGenerator;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.PBEKeySpec;
+import javax.crypto.spec.PBEParameterSpec;
+
+/*
+ * @test
+ * @bug 8048604
+ * @summary This test verifies the assertion "The skip feature of Filter
+ * streams should be supported." for feature
+ * CipherInputStream and CipherOutputStream
+ */
+public class CICOSkipTest {
+ /**
+ * Block length.
+ */
+ private static final int BLOCK = 50;
+
+ /**
+ * Saving bytes length.
+ */
+ private static final int SAVE = 45;
+
+ /**
+ * Plain text length.
+ */
+ private static final int PLAIN_TEXT_LENGTH = 800;
+
+ /**
+ * Skip reading byte size. This should be same to BLOCK - SAVE
+ */
+ private static final int DISCARD = BLOCK - SAVE;
+
+ private static final String[] ALGOS = {"DES", "DESede", "Blowfish"};
+ private static final String[] MODES = {"ECB", "CBC", "CFB", "CFB32",
+ "OFB", "OFB64", "PCBC"};
+ private static final String[] PADDINGS = {"NoPadding", "Pkcs5Padding"};
+ private static final String[] PBE_ALGOS = {"PBEWithMD5AndDES",
+ "PBEWithMD5AndDES/CBC/PKCS5Padding"};
+
+ public static void main(String[] args) throws Exception {
+ // how many kinds of padding mode such as PKCS5padding and NoPadding
+ for (String algo : ALGOS) {
+ for (String mode : MODES) {
+ int padKinds = 1;
+ if (mode.equalsIgnoreCase("ECB")
+ || mode.equalsIgnoreCase("PCBC")
+ || mode.equalsIgnoreCase("CBC")) {
+ padKinds = PADDINGS.length;
+ }
+ // PKCS5padding is meaningful only for ECB, CBC, PCBC
+ for (int k = 0; k < padKinds; k++) {
+ String info = algo + "/" + mode + "/" + PADDINGS[k];
+ try {
+ CipherGenerator cg = new CipherGenerator(algo, mode,
+ PADDINGS[k]);
+ for (ReadMethod model : ReadMethod.values()) {
+ runTest(cg.getPair(), info, model);
+ }
+ } catch (LengthLimitException exp) {
+ // skip this if this key length is larger than what's
+ // configured in the jce jurisdiction policy files
+ out.println(exp.getMessage() + " is expected.");
+ }
+ }
+ }
+ }
+ for (String pbeAlgo : PBE_ALGOS) {
+ for (ReadMethod model : ReadMethod.values()) {
+ System.out.println("Testing Algorithm : " + pbeAlgo
+ + " ReadMethod : " + model);
+ runTest(new CipherGenerator(pbeAlgo).getPair(), pbeAlgo, model);
+ }
+ }
+ }
+
+ private static void runTest(Cipher[] pair, String info, ReadMethod whichRead)
+ throws IOException {
+ byte[] plainText = TestUtilities.generateBytes(PLAIN_TEXT_LENGTH);
+ out.println("Testing: " + info + "/" + whichRead);
+ try (ByteArrayInputStream baInput = new ByteArrayInputStream(plainText);
+ CipherInputStream ciInput1 = new CipherInputStream(baInput,
+ pair[0]);
+ CipherInputStream ciInput2 = new CipherInputStream(ciInput1,
+ pair[1]);) {
+ // Skip 5 bytes after read 45 bytes and repeat until finish
+ // (Read from the input and write to the output using 2 types
+ // of buffering : byte[] and int)
+ // So output has size:
+ // (OVERALL/BLOCK)* SAVE = (800 / 50) * 45 = 720 bytes
+ int numOfBlocks = plainText.length / BLOCK;
+
+ // Output buffer.
+ byte[] outputText = new byte[numOfBlocks * SAVE];
+ int index = 0;
+ for (int i = 0; i < numOfBlocks; i++) {
+ index = whichRead.readByte(ciInput2, outputText, SAVE, index);
+ // If available is more than expected discard byte size. Skip
+ // discard bytes, otherwise try to read discard bytes by read.
+ if (ciInput2.available() >= DISCARD) {
+ ciInput2.skip(DISCARD);
+ } else {
+ for (int k = 0; k < DISCARD; k++) {
+ ciInput2.read();
+ }
+ }
+ }
+ // Verify output is same as input
+ if (!TestUtilities
+ .equalsBlockPartial(plainText, outputText, BLOCK, SAVE)) {
+ throw new RuntimeException("Test failed with compare fail");
+ }
+ }
+ }
+}
+
+class CipherGenerator {
+ /**
+ * Initialization vector length.
+ */
+ private static final int IV_LENGTH = 8;
+
+ private static final String PASSWD = "Sesame!(@#$%^&*)";
+
+ private final Cipher[] pair = new Cipher[2];
+
+ // For DES/DESede ciphers
+ CipherGenerator(String algo, String mo, String pad)
+ throws NoSuchAlgorithmException,
+ InvalidAlgorithmParameterException, InvalidKeyException,
+ NoSuchPaddingException, SecurityException, LengthLimitException {
+ // Do initialization
+ KeyGenerator kg = KeyGenerator.getInstance(algo);
+ SecretKey key = kg.generateKey();
+ if (key.getEncoded().length * 8 > Cipher.getMaxAllowedKeyLength(algo)) {
+ // skip this if this key length is larger than what's
+ // configured in the jce jurisdiction policy files
+ throw new LengthLimitException(
+ "Skip this test if key length is larger than what's"
+ + "configured in the jce jurisdiction policy files");
+ }
+ AlgorithmParameterSpec aps = null;
+ if (!mo.equalsIgnoreCase("ECB")) {
+ byte[] iv = TestUtilities.generateBytes(IV_LENGTH);
+ aps = new IvParameterSpec(iv);
+ }
+ initCiphers(algo + "/" + mo + "/" + pad, key, aps);
+ }
+
+ // For PBE ciphers
+ CipherGenerator(String algo) throws NoSuchAlgorithmException,
+ InvalidAlgorithmParameterException, InvalidKeyException,
+ NoSuchPaddingException, InvalidKeySpecException {
+ // Do initialization
+ byte[] salt = TestUtilities.generateBytes(IV_LENGTH);
+ int iterCnt = 6;
+ SecretKeyFactory skf = SecretKeyFactory.getInstance(algo.split("/")[0]);
+ SecretKey key = skf
+ .generateSecret(new PBEKeySpec(PASSWD.toCharArray()));
+ AlgorithmParameterSpec aps = new PBEParameterSpec(salt, iterCnt);
+ initCiphers(algo, key, aps);
+ }
+
+ private void initCiphers(String algo, SecretKey key,
+ AlgorithmParameterSpec aps) throws NoSuchAlgorithmException,
+ NoSuchPaddingException, InvalidKeyException,
+ InvalidAlgorithmParameterException {
+ Provider provider = Security.getProvider("SunJCE");
+ if (provider == null) {
+ throw new RuntimeException("SunJCE provider does not exist.");
+ }
+ Cipher ci1 = Cipher.getInstance(algo, provider);
+ ci1.init(Cipher.ENCRYPT_MODE, key, aps);
+ pair[0] = ci1;
+ Cipher ci2 = Cipher.getInstance(algo, provider);
+ ci2.init(Cipher.DECRYPT_MODE, key, aps);
+ pair[1] = ci2;
+ }
+
+ Cipher[] getPair() {
+ return pair;
+ }
+}
+
+enum ReadMethod {
+ // read one byte at a time for save times
+ READ_ONE_BYTE {
+ @Override
+ int readByte(CipherInputStream ciIn2, byte[] outputText, int save,
+ int index) throws IOException {
+ for (int j = 0; j < save; j++, index++) {
+ int buffer0 = ciIn2.read();
+ if (buffer0 != -1) {
+ outputText[index] = (byte) buffer0;
+ } else {
+ break;
+ }
+ }
+ return index;
+ }
+ },
+ // read a chunk of save bytes if possible
+ READ_BLOCK {
+ @Override
+ int readByte(CipherInputStream ciIn2, byte[] outputText, int save,
+ int index) throws IOException {
+ int len1 = ciIn2.read(outputText, index, save);
+ out.println("Init: index=" + index + ",len=" + len1);
+ // read more until save bytes
+ index += len1;
+ int len2 = 0;
+ while (len1 != save && len2 != -1) {
+ len2 = ciIn2.read(outputText, index, save - len1);
+ out.println("Cont: index=" + index + ",len=" + len2);
+ len1 += len2;
+ index += len2;
+ }
+ return index;
+ }
+ };
+
+ abstract int readByte(CipherInputStream ciIn2, byte[] outputText, int save,
+ int index) throws IOException;
+};
+
+class LengthLimitException extends Exception {
+
+ public LengthLimitException(String string) {
+ super(string);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/crypto/provider/CICO/PBEFunc/AESPBEWrapper.java Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2007, 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.
+ */
+
+import java.security.AlgorithmParameters;
+import java.security.GeneralSecurityException;
+import java.security.Provider;
+import java.security.Security;
+import javax.crypto.SecretKey;
+import javax.crypto.Cipher;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.PBEKeySpec;
+
+/**
+ * Wrapper class to test a given AES-based PBE algorithm.
+ */
+public class AESPBEWrapper extends AbstractPBEWrapper {
+ /**
+ * the algorithm parameters.
+ */
+ private AlgorithmParameters pbeParams;
+
+ /**
+ * the encryption key.
+ */
+ private final SecretKey key;
+
+ /**
+ * The Wrapper constructor. Instantiate Cipher using the given AES-based PBE
+ * algorithm.
+ *
+ * @param algo AES-based PBE algorithm.
+ * @param passwd password phrase.
+ * @throws GeneralSecurityException all security exceptions are thrown.
+ */
+ public AESPBEWrapper(PBEAlgorithm algo, String passwd)
+ throws GeneralSecurityException {
+ // salt and iteration count will be generated during encryption
+ super(algo, passwd, 0);
+
+ // Generate secret key. We expect no mode and padding specified.
+ SecretKeyFactory skf = SecretKeyFactory.getInstance(algo.baseAlgo);
+ key = skf.generateSecret(new PBEKeySpec(passwd.toCharArray()));
+ }
+
+ /**
+ * Initiate the Cipher object using given "mode".
+ * @return a cipher object.
+ * @throws GeneralSecurityException all security exceptions are thrown.
+ */
+ @Override
+ protected Cipher initCipher(int mode) throws GeneralSecurityException {
+ Provider provider = Security.getProvider("SunJCE");
+ if (provider == null) {
+ throw new RuntimeException("SunJCE provider does not exist.");
+ }
+ // get Cipher instance
+ Cipher ci = Cipher.getInstance(transformation, provider);
+ if (Cipher.ENCRYPT_MODE == mode) {
+ ci.init(Cipher.ENCRYPT_MODE, key);
+ pbeParams = ci.getParameters();
+ } else {
+ ci.init(Cipher.DECRYPT_MODE, key, pbeParams);
+ }
+ return ci;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/crypto/provider/CICO/PBEFunc/AbstractPBEWrapper.java Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2007, 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.
+ */
+import java.security.GeneralSecurityException;
+import javax.crypto.Cipher;
+
+/**
+ * PBEWrapper is an abstract class for all concrete PBE Cipher wrappers.
+ */
+public abstract class AbstractPBEWrapper {
+ /**
+ * Iteration count.
+ */
+ public static final int DEFAULT_ITERATION = 1000;
+
+ public static final String PBKDF2 = "PBKDF2";
+ public static final String AES = "AES";
+ public static final String DEFAULT = "default";
+
+ /**
+ * transformation the name of the transformation, e.g.,
+ * DES/CBC/PKCS5Padding
+ */
+ protected final String transformation;
+
+ /**
+ * the standard name of the requested secret-key algorithm.
+ */
+ protected final String baseAlgo;
+
+ /**
+ * The contents of salt are copied to protect against subsequent
+ * modification.
+ */
+ protected final byte[] salt;
+
+ /**
+ * Password.
+ */
+ protected final String password;
+
+ /**
+ * PBEWrapper creator.
+ *
+ * @param algo PBE algorithm to test
+ * @param passwd a password phrase
+ * @return PBEWrapper in accordance to requested algo.
+ * @throws GeneralSecurityException all exceptions are thrown.
+ */
+ public static AbstractPBEWrapper createWrapper(PBEAlgorithm algo, String passwd)
+ throws GeneralSecurityException {
+ switch (algo.type) {
+ case PBKDF2:
+ return new PBKDF2Wrapper(algo, passwd);
+ case AES:
+ return new AESPBEWrapper(algo, passwd);
+ default:
+ return new DefaultPBEWrapper(algo, passwd);
+ }
+ }
+
+ /**
+ * PBEWrapper constructor.
+ *
+ * @param algo algorithm to wrap
+ * @param password password phrase
+ * @param saltSize salt size (defined in subclasses)
+ */
+ protected AbstractPBEWrapper(PBEAlgorithm algo, String password, int saltSize) {
+ this.transformation = algo.getTransformation();
+ this.baseAlgo = algo.baseAlgo;
+ this.salt = TestUtilities.generateBytes(saltSize);
+ this.password = password;
+ }
+
+ /**
+ * Initialize Cipher object for the operation requested in the mode parameter.
+ *
+ * @param mode encryption or decryption
+ * @return a cipher initialize by mode.
+ * @throws GeneralSecurityException all security exceptions are thrown.
+ */
+ protected abstract Cipher initCipher(int mode) throws GeneralSecurityException;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/crypto/provider/CICO/PBEFunc/CICOPBEFuncTest.java Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2007, 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 8048604
+ * @summary This test verifies the assertion "The encrypt/decrypt
+ * mechanism of cipher should perform correctly." for feature
+ * "CipherInputStream & CipherOutputStream".
+ * @library ../
+ * @run main CICOPBEFuncTest
+ */
+
+import java.util.Arrays;
+import javax.crypto.Cipher;
+
+public class CICOPBEFuncTest {
+
+ public static void main(String[] args) throws Exception {
+ for (PBEAlgorithm algorithm : PBEAlgorithm.values()) {
+ // int buffertin test
+ String algo = algorithm.baseAlgo.toUpperCase();
+ if (!algo.contains("TRIPLEDES") && !algo.contains("AES_256")
+ || Cipher.getMaxAllowedKeyLength(algo) > 128) {
+ // skip this if this key length is larger than what's
+ // configured in the jce jurisdiction policy files
+ System.out.println("Testing " + algorithm.getTransformation());
+ for (String type : Arrays.asList(CICO_PBE_Test.INT_BYTE_BUFFER,
+ CICO_PBE_Test.BYTE_ARR_BUFFER)) {
+ new CICO_PBE_RW_Test(algorithm)
+ .proceedTest(type);
+ new CICO_PBE_SKIP_Test(algorithm)
+ .proceedTest(type);
+ }
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/crypto/provider/CICO/PBEFunc/CICO_PBE_RW_Test.java Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2007, 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.
+ */
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+
+import javax.crypto.CipherOutputStream;
+
+/**
+ * CICO PBE Read/Write functional test.
+ *
+ * Verifies for the given PBE algorithm if the encrypt/decrypt mechanism is
+ * performed correctly for CipherInputStream and CipherOutputStream.
+ *
+ * Test scenario:
+ * 1. initializes plain text with random generated data.
+ * 2. for the given PBE algorithm instantiates encrypt and decrypt Ciphers.
+ * 3. instantiates CipherInputStream with the encrypt Cipher.
+ * 4. instantiates CipherOutputStream with the decrypt Cipher.
+ * 5. performs reading from the CipherInputStream (encryption data) and writing
+ * to the CipherOutputStream (decryption). As a result the output of the
+ * CipherOutputStream should be the same as an original plain text.
+ * 6. compares if the original plain text is the same as the output of the
+ * CipherOutputStream.
+ *
+ * The test implements 2 test cases in accordance with buffering type:
+ * 1. byte array buffering
+ * 2. int buffering
+ */
+public class CICO_PBE_RW_Test extends CICO_PBE_Test {
+
+ public CICO_PBE_RW_Test(PBEAlgorithm pbeAlgo)
+ throws GeneralSecurityException {
+ super(pbeAlgo);
+ }
+
+ /**
+ * The CICO PBE RW test specific part of the super.doTest(). Implements the
+ * scenario in accordance to the class description.
+ * @param type byteArrayBuffering or intByteBuffering
+ * @throws IOException any I/O operation failed.
+ * @throws GeneralSecurityException any security error.
+ */
+ @Override
+ public void proceedTest(String type) throws IOException,
+ GeneralSecurityException {
+ ByteArrayOutputStream baOutput = new ByteArrayOutputStream();
+ try (CipherOutputStream ciOutput = new CipherOutputStream(baOutput,
+ getDecryptCipher())) {
+ if (type.equals(CICO_PBE_Test.BYTE_ARR_BUFFER)) {
+ proceedTestUsingByteArrayBuffer(ciOutput);
+ } else {
+ proceedTestUsingIntBuffer(ciOutput);
+ }
+ ciOutput.flush();
+ }
+ // Compare input and output
+ if (!TestUtilities.equalsBlock(plainText, baOutput.toByteArray(), TEXT_SIZE)) {
+ throw new RuntimeException("outputText not same with expectedText"
+ + " when test " + type);
+ }
+ }
+
+ /**
+ * Implements byte array buffering type test case of the CICO PBE RW test.
+ * @param ciOutput output stream for data written.
+ * @throws java.io.IOException any I/O operation failed.
+ */
+ public void proceedTestUsingByteArrayBuffer(
+ CipherOutputStream ciOutput) throws IOException {
+ byte[] buffer = new byte[TEXT_SIZE];
+ int len = getCiInput().read(buffer);
+ while (len != -1) {
+ ciOutput.write(buffer, 0, len);
+ len = getCiInput().read(buffer);
+ }
+ }
+
+ /**
+ * Implements int buffering type test case.
+ * @param ciOutput output stream for data written.
+ * @throws java.io.IOException any I/O operation failed.
+ */
+ public void proceedTestUsingIntBuffer(CipherOutputStream ciOutput)
+ throws IOException {
+ int buffer = getCiInput().read();
+ while (buffer != -1) {
+ ciOutput.write(buffer);
+ buffer = getCiInput().read();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/crypto/provider/CICO/PBEFunc/CICO_PBE_SKIP_Test.java Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2007, 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.
+ */
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import javax.crypto.CipherInputStream;
+
+/**
+ * CICO PBE SKIP functional test.
+ *
+ * Verifies for the given PBE algorithm if the encrypt/decrypt mechanism is
+ * performed correctly for CipherInputStream when skip() method is used.
+ *
+ * Test scenario:
+ * 1. initializes plain text with random generated data with length TEXT_SIZE.
+ * 2. for the given PBE algorithm instantiates encrypt and decrypt Ciphers.
+ * 3. instantiates CipherInputStream 1 with the encrypt Cipher.
+ * 4. instantiates CipherInputStream 2 with the CipherInputStream 1 and decrypt
+ * Cipher.
+ * 5. the plain text is divided on TEXT_SIZE/BLOCK blocks. Reading from
+ * CipherInputStream 2 one block at time. The last BLOCK - SAVE bytes are
+ * skipping for each block. Therefor the plain text data go through
+ * CipherInputStream 1 (encrypting) and CipherInputStream 2 (decrypting).
+ * As a result the output should equal to the original text except DISCARD
+ * byte for each block are skipped.
+ * 6. get the standard output.
+ * 7. compares the expected standard output with the output of the
+ * CipherInputStream 2. If it is the same the test passed. Otherwise it
+ * failed. Any uncaught exceptions should be considered as an error.
+ * The test implements 2 test cases in accordance with a buffering type:
+ * 1. byte array buffering
+ * 2. int buffering
+ */
+public class CICO_PBE_SKIP_Test extends CICO_PBE_Test {
+ /**
+ * Block size.
+ */
+ private static final int BLOCK = 50;
+
+ /**
+ * Valid reading byte size.
+ */
+ private static final int SAVE = 45;
+
+ /**
+ * Skip reading byte size. This should be same to BLOCK - SAVE
+ */
+ private static final int DISCARD = BLOCK - SAVE;
+
+ /**
+ * Number of blocks.
+ */
+ private static final int NUMBER_OF_BLOCKS = TEXT_SIZE / BLOCK;
+
+ private final byte[] outputText;
+ /**
+ * CICO PBE Skip test constructor
+ *
+ * @param pbeAlgo the PBE algorithm to test.
+ * @throws java.security.GeneralSecurityException
+ */
+ public CICO_PBE_SKIP_Test(PBEAlgorithm pbeAlgo)
+ throws GeneralSecurityException {
+ super(pbeAlgo);
+ outputText = new byte[NUMBER_OF_BLOCKS * SAVE];
+ }
+
+ /**
+ * Implements byte array buffering type test case of the CICO SKIP test.
+ *
+ * @param blockNum block number to read.
+ */
+ private void proceedSkipTestUsingByteArrayBufferingType(
+ CipherInputStream ciIn2, int blockNum) throws IOException {
+ int index = blockNum * SAVE;
+ int len1 = ciIn2.read(outputText, index, SAVE);
+ // read more until SAVE bytes
+ index += len1;
+ int len2 = 0;
+ int totalRead = len1;
+ while (len1 != SAVE && len2 != -1) {
+ len2 = ciIn2.read(outputText, index, SAVE - len1);
+ len1 += len2;
+ index += len2;
+ totalRead += len2;
+ }
+ if (totalRead != SAVE) {
+ throw new RuntimeException("Read bytes number " + totalRead
+ + " does not equal to given number " + SAVE);
+ }
+ }
+
+ /**
+ * Implements int buffering type test case of the CICO SKIP test.
+ *
+ * @param blockNum block number to read.
+ */
+ private void proceedSkipTestUsingIntBufferingType(CipherInputStream ciIn2,
+ int blockNum) throws IOException {
+ int index = blockNum * SAVE;
+ int totalRead = 0;
+ for (int j = 0; j < SAVE; j++, index++) {
+ int buffer0 = ciIn2.read();
+ if (buffer0 != -1) {
+ outputText[index] = (byte) buffer0;
+ totalRead++;
+ } else {
+ break;
+ }
+ }
+ if (totalRead != SAVE) {
+ throw new RuntimeException("Read bytes number " + totalRead
+ + " does not equal to given number " + SAVE);
+ }
+ }
+
+ /**
+ * The CICO PBE SKIP test specific part of the super.doTest(). Implements
+ * the scenario in accordance to the class description.
+ * @throws java.io.IOException any I/O failed.
+ */
+ @Override
+ public void proceedTest(String type) throws IOException {
+ System.out.println("Test type: " + type);
+ // init second input stream with decrypt Cipher
+ try (CipherInputStream ciIn2 = new CipherInputStream(getCiInput(),
+ getDecryptCipher())) {
+ for (int i = 0; i < NUMBER_OF_BLOCKS; i++) {
+ if (type.equals(CICO_PBE_Test.BYTE_ARR_BUFFER)) {
+ proceedSkipTestUsingByteArrayBufferingType(ciIn2, i);
+ } else {
+ proceedSkipTestUsingIntBufferingType(ciIn2, i);
+ }
+ if (ciIn2.available() >= DISCARD) {
+ ciIn2.skip(DISCARD);
+ } else {
+ for (int k = 0; k < DISCARD; k++) {
+ ciIn2.read();
+ }
+ }
+ }
+ }
+ if (!TestUtilities.equalsBlockPartial(plainText, outputText, BLOCK, SAVE)) {
+ throw new RuntimeException("outputText not same with expectedText"
+ + " when test " + type);
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/crypto/provider/CICO/PBEFunc/CICO_PBE_Test.java Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2007, 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.
+ */
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import javax.crypto.Cipher;
+import javax.crypto.CipherInputStream;
+
+/**
+ * This is an abstract class for CipherInputStream/CipherOutputStream PBE
+ * functional tests.
+ */
+public abstract class CICO_PBE_Test {
+ /**
+ * Sample string for byte buffer.
+ */
+ public static final String BYTE_ARR_BUFFER = "byteArrayBuffering";
+
+ /**
+ * Sample string for int buffer.
+ */
+ public static final String INT_BYTE_BUFFER = "intByteBuffering";
+ public static final String PASS_PHRASE = "Some password phrase!";
+
+ /**
+ * Text string size.
+ */
+ public static final int TEXT_SIZE = 800;
+
+ protected final byte[] plainText;
+ private final Cipher encryptCipher, decryptCipher;
+
+ /**
+ * An CipherInputStream for reading cipher and plain text.
+ */
+ private final CipherInputStream ciInput;
+
+ /**
+ * Constructor by algorithm.
+ * @param pbeAlgo PBE algorithm to test.
+ * @throws GeneralSecurityException if any security error.
+ */
+ public CICO_PBE_Test(PBEAlgorithm pbeAlgo) throws GeneralSecurityException {
+ // Do initialization of the plainText
+ plainText = TestUtilities.generateBytes(TEXT_SIZE);
+ // Do initialization of the ciphers
+ AbstractPBEWrapper pbeWrap = AbstractPBEWrapper.createWrapper(pbeAlgo, PASS_PHRASE);
+ encryptCipher = pbeWrap.initCipher(Cipher.ENCRYPT_MODE);
+ decryptCipher = pbeWrap.initCipher(Cipher.DECRYPT_MODE);
+ // init cipher input stream
+ ciInput = new CipherInputStream(new ByteArrayInputStream(plainText),
+ encryptCipher);
+ }
+
+ protected byte[] getPlainText() {
+ return plainText;
+ }
+
+ /**
+ * The body of the test. Should be defined in subclasses.
+ * @param type byteArrayBuffering or intByteBuffering
+ * @throws IOException I/O operation failed.
+ * @throws GeneralSecurityException all exceptions thrown.
+ */
+ protected abstract void proceedTest(String type)
+ throws IOException, GeneralSecurityException;
+
+ protected Cipher getEncryptCipher() {
+ return encryptCipher;
+ }
+
+ public CipherInputStream getCiInput() {
+ return ciInput;
+ }
+
+ public Cipher getDecryptCipher() {
+ return decryptCipher;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/crypto/provider/CICO/PBEFunc/CipherNCFuncTest.java Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2001, 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 8048604
+ * @library ../ /lib/testlibrary
+ * @summary This test verifies the assertion "There should be no transformation
+ * on the plaintext/ciphertext in encryption/decryption mechanism" for
+ * feature "NullCipher".
+ */
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NullCipher;
+import javax.crypto.ShortBufferException;
+import jdk.testlibrary.RandomFactory;
+
+public class CipherNCFuncTest {
+ public static void main(String[] args) throws ShortBufferException,
+ IllegalBlockSizeException, BadPaddingException {
+ byte[] plainText = new byte[801];
+ // Initialization
+ RandomFactory.getRandom().nextBytes(plainText);
+ Cipher ci = new NullCipher();
+ // Encryption
+ byte[] cipherText = new byte[ci.getOutputSize(plainText.length)];
+ int offset = ci.update(plainText, 0, plainText.length, cipherText, 0);
+ ci.doFinal(cipherText, offset);
+ // Decryption
+ byte[] recoveredText = new byte[ci.getOutputSize(cipherText.length)];
+ int len = ci.doFinal(cipherText, 0, cipherText.length, recoveredText);
+ // Comparison
+ if (len != plainText.length ||
+ !TestUtilities.equalsBlock(plainText, cipherText, len) ||
+ !TestUtilities.equalsBlock(plainText, recoveredText, len)) {
+ throw new RuntimeException(
+ "Test failed because plainText not equal to cipherText and revoveredText");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/crypto/provider/CICO/PBEFunc/DefaultPBEWrapper.java Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2007, 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.
+ */
+import java.security.GeneralSecurityException;
+import java.security.Provider;
+import java.security.Security;
+import javax.crypto.SecretKey;
+import javax.crypto.Cipher;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.PBEKeySpec;
+import javax.crypto.spec.PBEParameterSpec;
+
+/**
+ * Default wrapper for a password based encryption Cipher.
+ */
+
+public class DefaultPBEWrapper extends AbstractPBEWrapper {
+ /**
+ * Define default SALT size as 8.
+ */
+ private static final int PBE_SALT_SIZE = 8;
+
+ /**
+ * Default PBE wrapper constructor.
+ *
+ * @param algo PGE algorithm to wrap.
+ * @param passwd password phrase
+ */
+ public DefaultPBEWrapper(PBEAlgorithm algo, String passwd) {
+ super(algo, passwd, PBE_SALT_SIZE);
+ }
+
+ /**
+ * Instantiate Cipher for the PBE algorithm.
+ *
+ * @param mode Cipher mode: encrypt or decrypt.
+ * @return Cipher in accordance to the PBE algorithm
+ * @throws java.security.GeneralSecurityException
+ */
+ @Override
+ protected Cipher initCipher(int mode) throws GeneralSecurityException {
+ Provider provider = Security.getProvider("SunJCE");
+ if (provider == null) {
+ throw new RuntimeException("SunJCE provider does not exist.");
+ }
+ SecretKey key = SecretKeyFactory.getInstance(baseAlgo)
+ .generateSecret(new PBEKeySpec(password.toCharArray()));
+ Cipher ci = Cipher.getInstance(transformation, provider);
+ ci.init(mode, key, new PBEParameterSpec(salt, DEFAULT_ITERATION));
+ return ci;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/crypto/provider/CICO/PBEFunc/PBEAlgorithm.java Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2007, 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.
+ */
+
+import java.util.StringJoiner;
+
+public enum PBEAlgorithm {
+ MD5_DES("PBEWithMD5ANDdes", "", "", AbstractPBEWrapper.DEFAULT),
+ MD5_DES_CBC_PKCS5("PBEWithMD5AndDES", "CBC", "PKCS5Padding",
+ AbstractPBEWrapper.DEFAULT),
+ MD5_TRIPLEDES("PBEWithMD5ANDtripledes", "", "", AbstractPBEWrapper.DEFAULT),
+ MD5_TRIPLEDES_CBC_PKCS5("PBEWithMD5AndTRIPLEDES", "CBC", "PKCS5Padding",
+ AbstractPBEWrapper.DEFAULT),
+ SHA1_DESEDE("PBEwithSHA1AndDESede", "", "", AbstractPBEWrapper.DEFAULT),
+ SHA1_DESEDE_CBC_PKCS5("PBEwithSHA1AndDESede", "CBC", "PKCS5Padding",
+ AbstractPBEWrapper.DEFAULT),
+ SHA1_RC2_40("PBEwithSHA1AndRC2_40", "", "", AbstractPBEWrapper.DEFAULT),
+ SHA1_RC2_40_PKCS5("PBEwithSHA1Andrc2_40", "CBC", "PKCS5Padding",
+ AbstractPBEWrapper.DEFAULT),
+ SHA1_RC2_128("PBEWithSHA1AndRC2_128", "", "", AbstractPBEWrapper.DEFAULT),
+ SHA1_RC2_128_PKCS5("PBEWithSHA1andRC2_128", "CBC", "PKCS5Padding",
+ AbstractPBEWrapper.DEFAULT),
+ SHA1_RC4_40("PBEWithSHA1AndRC4_40", "", "", AbstractPBEWrapper.DEFAULT),
+ SHA1_RC4_40_ECB_NOPADDING("PBEWithsha1AndRC4_40", "ECB", "NoPadding",
+ AbstractPBEWrapper.DEFAULT),
+ SHA1_RC4_128("PBEWithSHA1AndRC4_128", "", "", AbstractPBEWrapper.DEFAULT),
+ SHA1_RC4_128_ECB_NOPADDING("pbeWithSHA1AndRC4_128", "ECB", "NoPadding",
+ AbstractPBEWrapper.DEFAULT),
+ HMAC_SHA1_AES_128("PBEWithHmacSHA1AndAES_128", "", "", AbstractPBEWrapper.AES),
+ HMAC_SHA224_AES_128("PBEWithHmacSHA224AndAES_128", "", "", AbstractPBEWrapper.AES),
+ HMAC_SHA256_AES_128("PBEWithHmacSHA256AndAES_128", "", "", AbstractPBEWrapper.AES),
+ HMAC_SHA384_AES_128("PBEWithHmacSHA384AndAES_128", "", "", AbstractPBEWrapper.AES),
+ HMAC_SHA512_AES_128("PBEWithHmacSHA512AndAES_128", "", "", AbstractPBEWrapper.AES),
+ HMAC_SHA1_AES_256("PBEWithHmacSHA1AndAES_256", "", "", AbstractPBEWrapper.AES),
+ HMAC_SHA224_AES_256("PBEWithHmacSHA224AndAES_256", "", "", AbstractPBEWrapper.AES),
+ HMAC_SHA256_AES_256("PBEWithHmacSHA256AndAES_256", "", "", AbstractPBEWrapper.AES),
+ HMAC_SHA384_AES_256("PBEWithHmacSHA384AndAES_256", "", "", AbstractPBEWrapper.AES),
+ HMAC_SHA512_AES_256("PBEWithHmacSHA512AndAES_256", "", "", AbstractPBEWrapper.AES),
+ PBKDF_HMAC_SHA1("PBKDF2WithHmacSHA1", "", "", AbstractPBEWrapper.PBKDF2),
+ PBKDF_HMAC_SHA224("PBKDF2WithHmacSHA224", "", "", AbstractPBEWrapper.PBKDF2),
+ PBKDF_HMAC_SHA256("PBKDF2WithHmacSHA256", "", "", AbstractPBEWrapper.PBKDF2),
+ PBKDF_HMAC_SHA384("PBKDF2WithHmacSHA384", "", "", AbstractPBEWrapper.PBKDF2),
+ PBKDF_HMAC_SHA512("PBKDF2WithHmacSHA512", "", "", AbstractPBEWrapper.PBKDF2);
+ final String baseAlgo;
+ final String mode;
+ final String padding;
+ final String type;
+
+ PBEAlgorithm(String alg, String mode, String padding, String type) {
+ this.baseAlgo = alg;
+ this.mode = mode;
+ this.padding = padding;
+ this.type = type;
+ }
+
+ public String getTransformation() {
+ StringJoiner sj = new StringJoiner("/");
+ sj.add(baseAlgo);
+ if (!mode.equals("")) {
+ sj.add(this.mode);
+ }
+ if (!padding.equals("")) {
+ sj.add(this.padding);
+ }
+ return sj.toString();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/crypto/provider/CICO/PBEFunc/PBKDF2Wrapper.java Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2007, 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.
+ */
+
+import java.security.GeneralSecurityException;
+import java.security.Provider;
+import java.security.Security;
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.PBEKeySpec;
+import javax.crypto.spec.SecretKeySpec;
+
+/**
+ * Wrapper class to test a given SecretKeyFactory.PBKDF2 algorithm.
+ */
+public class PBKDF2Wrapper extends AbstractPBEWrapper {
+ /**
+ * Default salt size.
+ */
+ public static final int PBKDF2_SALT_SIZE = 64;
+
+ /**
+ * Default key length.
+ */
+ public static final int PKDF2_DEFAULT_KEY_LEN = 128;
+
+ /**
+ * Default transformation.
+ */
+ public static final String CIPHER_TRANSFORMATION = "AES/CBC/PKCS5Padding";
+
+ /**
+ * Algorithm name.
+ */
+ public static final String KEY_ALGORITHM = "AES";
+
+ /**
+ * Initialization vector length.
+ */
+ private static final int IV_LENGTH = 16;
+
+ /**
+ * The buffer with the IV.
+ */
+ private final byte[] iv;
+
+ /**
+ * PBKDF2Wrapper constructor. Instantiate Cipher using
+ * "AES/CBC/PKCS5Padding" transformation. Generate a secret key using PKDF2
+ * algorithms given in the "algo" parameter.
+ *
+ * @param algo AES-based PBE algorithm.
+ * @param passwd password phrase.
+ * @throws GeneralSecurityException all security exceptions are thrown.
+ */
+ public PBKDF2Wrapper(PBEAlgorithm algo, String passwd)
+ throws GeneralSecurityException {
+ super(algo, passwd, PBKDF2_SALT_SIZE);
+ iv = TestUtilities.generateBytes(IV_LENGTH);
+ }
+
+ /**
+ * Initiate the Cipher object for PBKDF2 algorithm using given "mode".
+ *
+ * @param mode Cipher mode: encrypt or decrypt
+ * @return Cipher object for PBKDF2 algorithm
+ * @throws GeneralSecurityException all security exceptions are thrown.
+ */
+ @Override
+ protected Cipher initCipher(int mode) throws GeneralSecurityException {
+ Provider provider = Security.getProvider("SunJCE");
+ if (provider == null) {
+ throw new RuntimeException("SunJCE provider does not exist.");
+ }
+ // Generate secret key
+ PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray(),
+ salt, DEFAULT_ITERATION, PKDF2_DEFAULT_KEY_LEN);
+ SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(baseAlgo);
+ SecretKey key = keyFactory.generateSecret(pbeKeySpec);
+
+ // get Cipher instance
+ Cipher cipher = Cipher.getInstance(CIPHER_TRANSFORMATION, provider);
+ cipher.init(mode,
+ new SecretKeySpec(key.getEncoded(),KEY_ALGORITHM),
+ new IvParameterSpec(iv));
+ return cipher;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/crypto/provider/CICO/ReadModel.java Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2007, 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.
+ */
+import java.io.IOException;
+
+import javax.crypto.Cipher;
+import javax.crypto.CipherInputStream;
+import javax.crypto.CipherOutputStream;
+
+/**
+ * ReadModel provides different way to test
+ * CipherInputStream.read()/read(byte[])/read(byte[], int, int) and
+ * CipherOutputStream.write(int)/write(byte[], int, int)/read(byte[]) API
+ */
+enum ReadModel {
+ READ_BYTE {
+ @Override
+ public void read(CipherInputStream cInput, CipherOutputStream ciOutput,
+ Cipher ciIn, int inputLen) throws IOException {
+ int buffer0 = cInput.read();
+ while (buffer0 != -1) {
+ ciOutput.write(buffer0);
+ buffer0 = cInput.read();
+ }
+ }
+ },
+ READ_BUFFER {
+ @Override
+ public void read(CipherInputStream cInput, CipherOutputStream ciOutput,
+ Cipher ciIn, int inputLen) throws IOException {
+ byte[] buffer1 = new byte[20];
+ int len1;
+ while ((len1 = cInput.read(buffer1)) != -1) {
+ ciOutput.write(buffer1, 0, len1);
+ }
+
+ }
+ },
+ READ_BUFFER_OFFSET {
+ @Override
+ public void read(CipherInputStream cInput, CipherOutputStream ciOutput,
+ Cipher ciIn, int inputLen) throws IOException {
+ byte[] buffer2 = new byte[ciIn.getOutputSize(inputLen)];
+ int offset2 = 0;
+ int len2 = 0;
+ while (len2 != -1) {
+ len2 = cInput.read(buffer2, offset2, buffer2.length - offset2);
+ offset2 += len2;
+ }
+ ciOutput.write(buffer2);
+
+ }
+ };
+
+ abstract public void read(CipherInputStream cInput,
+ CipherOutputStream ciOutput, Cipher ciIn, int inputLen)
+ throws IOException;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/crypto/provider/CICO/TestUtilities.java Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2007, 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.
+ */
+
+/*
+ * utility class
+ */
+
+public class TestUtilities {
+ public static boolean equalsBlock(byte[] b1, byte[] b2, int len) {
+ for (int i = 0; i < len; i++) {
+ if (b1[i] != b2[i]) {
+ System.err.println("b1[" + i + "] : " + b1[i]
+ + " b2[" + i + "] : " + b2[i]);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static boolean equals(byte[] b1, byte[] b2) {
+ if (b2.length != b1.length) {
+ System.err.println("b1.length = " + b1.length
+ + " b2.length = " + b2.length );
+ return false;
+ }
+ return equalsBlock(b1, b2, b1.length);
+ }
+
+ /**
+ * Verify b1's partial part is same as b2. compares b1 and b2 by chopping up
+ * b1 into blocks of b1BKSize and b2 into blocks of b2BKSize, and then
+ * compare the first b2BKSize bytes of each block, return true if they equal
+ * , otherwise return false.
+ * @param b1 byte array to be compared.
+ * @param b2 saved byte array.
+ * @param b1BKSize b1's block size.
+ * @param b2BKSize b2's block size.
+ * @return true is same. false otherwise.
+ */
+ public static boolean equalsBlockPartial(byte[] b1, byte[] b2, int b1BKSize,
+ int b2BKSize) {
+ int numOfBlock = b1.length / b1BKSize;
+ for (int b = 0; b < numOfBlock; b++) {
+ for (int i = 0; i < b2BKSize; i++) {
+ int j1 = b * b1BKSize + i;
+ int j2 = b * b2BKSize + i;
+ if (b1[j1] != b2[j2]) {
+ System.err.println("Compare failed at b1[" + j1 + "]:" +
+ b1[j1] + " b2[" + j2 + "]:" + b2[j2]);
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Generate a byte block by given length. The content of byte block
+ * is determined by the index.
+ * @param length length of byte array
+ * @return a byte array
+ */
+ public static byte[] generateBytes(int length) {
+ byte[] bytes = new byte[length];
+ for (int i = 0; i < length; i++) {
+ bytes[i] = (byte) (i & 0xff);
+ }
+ return bytes;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/crypto/provider/Cipher/DES/TextPKCS5PaddingTest.java Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2001, 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 8048604
+ * @summary This test checks boundary conditions for testing
+ * ShortBufferException.
+ */
+import static java.lang.System.out;
+
+import java.security.AlgorithmParameters;
+import java.security.Provider;
+import java.security.Security;
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+
+public class TextPKCS5PaddingTest {
+ /**
+ * Test plain text.
+ */
+ private static final byte[] PLAIN_TEXT = {
+ 0b10001, 0b10001, 0b10001, 0b10001,
+ 0b10001, 0b10001, 0b11, 0b11
+ };
+
+ public static void main(String[] args) throws Exception {
+ Provider provider = Security.getProvider("SunJCE");
+ if (provider == null) {
+ throw new RuntimeException("SunJCE provider not exist");
+ }
+ // generate no-padding cipher with secret key
+ Cipher c = Cipher.getInstance("DES/CBC/NoPadding", provider);
+ KeyGenerator kgen = KeyGenerator.getInstance("DES", provider);
+ SecretKey skey = kgen.generateKey();
+ // this is the improperly padded plaintext
+
+ c.init(Cipher.ENCRYPT_MODE, skey);
+ // encrypt plaintext
+ byte[] cipher = c.doFinal(PLAIN_TEXT);
+ AlgorithmParameters params = c.getParameters();
+ // generate cipher that enforces PKCS5 padding
+ c = Cipher.getInstance("DES/CBC/PKCS5Padding", provider);
+ c.init(Cipher.DECRYPT_MODE, skey, params);
+ try {
+ c.doFinal(cipher);
+ throw new RuntimeException(
+ "ERROR: Expected BadPaddingException not thrown");
+ } catch (BadPaddingException expected) {
+ out.println("Expected BadPaddingException thrown");
+ }
+
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/crypto/provider/NSASuiteB/TestAESOids.java Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,194 @@
+/*
+ * 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.
+ */
+
+import static javax.crypto.Cipher.ENCRYPT_MODE;
+import static javax.crypto.Cipher.getMaxAllowedKeyLength;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.KeyGenerator;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.ShortBufferException;
+import javax.crypto.spec.IvParameterSpec;
+
+/*
+ * @test
+ * @bug 8075286
+ * @summary Test the AES algorithm OIDs in JDK.
+ * OID and Algorithm transformation string should match.
+ * Both could be able to be used to generate the algorithm instance.
+ * @run main TestAESOids
+ */
+public class TestAESOids {
+
+ private static final String PROVIDER_NAME = "SunJCE";
+ private static final byte[] INPUT = "1234567890123456".getBytes();
+
+ private static final List<DataTuple> DATA = Arrays.asList(
+ new DataTuple("2.16.840.1.101.3.4.1.1", "AES_128/ECB/NoPadding",
+ 128, "ECB"),
+ new DataTuple("2.16.840.1.101.3.4.1.2", "AES_128/CBC/NoPadding",
+ 128, "CBC"),
+ new DataTuple("2.16.840.1.101.3.4.1.3", "AES_128/OFB/NoPadding",
+ 128, "OFB"),
+ new DataTuple("2.16.840.1.101.3.4.1.4", "AES_128/CFB/NoPadding",
+ 128, "CFB"),
+ new DataTuple("2.16.840.1.101.3.4.1.21", "AES_192/ECB/NoPadding",
+ 192, "ECB"),
+ new DataTuple("2.16.840.1.101.3.4.1.22", "AES_192/CBC/NoPadding",
+ 192, "CBC"),
+ new DataTuple("2.16.840.1.101.3.4.1.23", "AES_192/OFB/NoPadding",
+ 192, "OFB"),
+ new DataTuple("2.16.840.1.101.3.4.1.24", "AES_192/CFB/NoPadding",
+ 192, "CFB"),
+ new DataTuple("2.16.840.1.101.3.4.1.41", "AES_256/ECB/NoPadding",
+ 256, "ECB"),
+ new DataTuple("2.16.840.1.101.3.4.1.42", "AES_256/CBC/NoPadding",
+ 256, "CBC"),
+ new DataTuple("2.16.840.1.101.3.4.1.43", "AES_256/OFB/NoPadding",
+ 256, "OFB"),
+ new DataTuple("2.16.840.1.101.3.4.1.44", "AES_256/CFB/NoPadding",
+ 256, "CFB"));
+
+ public static void main(String[] args) throws Exception {
+ for (DataTuple dataTuple : DATA) {
+ int maxAllowedKeyLength =
+ getMaxAllowedKeyLength(dataTuple.algorithm);
+ boolean supportedKeyLength =
+ maxAllowedKeyLength >= dataTuple.keyLength;
+
+ try {
+ runTest(dataTuple, supportedKeyLength);
+ System.out.println("passed");
+ } catch (InvalidKeyException ike) {
+ if (supportedKeyLength) {
+ throw new RuntimeException(String.format(
+ "The key length %d is supported, but test failed.",
+ dataTuple.keyLength), ike);
+ } else {
+ System.out.printf(
+ "Catch expected InvalidKeyException due "
+ + "to the key length %d is greater than "
+ + "max supported key length %d%n",
+ dataTuple.keyLength, maxAllowedKeyLength);
+ }
+ }
+ }
+ }
+
+ private static void runTest(DataTuple dataTuple,
+ boolean supportedKeyLength) throws NoSuchAlgorithmException,
+ NoSuchProviderException, NoSuchPaddingException,
+ InvalidKeyException, ShortBufferException,
+ IllegalBlockSizeException, BadPaddingException,
+ InvalidAlgorithmParameterException {
+ Cipher algorithmCipher = Cipher.getInstance(dataTuple.algorithm,
+ PROVIDER_NAME);
+ Cipher oidCipher = Cipher.getInstance(dataTuple.oid, PROVIDER_NAME);
+
+ if (algorithmCipher == null) {
+ throw new RuntimeException(
+ String.format("Test failed: algorithm string %s getInstance"
+ + " failed.%n", dataTuple.algorithm));
+ }
+
+ if (oidCipher == null) {
+ throw new RuntimeException(
+ String.format("Test failed: OID %s getInstance failed.%n",
+ dataTuple.oid));
+ }
+
+ if (!algorithmCipher.getAlgorithm().equals(dataTuple.algorithm)) {
+ throw new RuntimeException(String.format(
+ "Test failed: algorithm string %s getInstance "
+ + "doesn't generate expected algorithm.%n",
+ dataTuple.algorithm));
+ }
+
+ KeyGenerator kg = KeyGenerator.getInstance("AES");
+ kg.init(dataTuple.keyLength);
+ SecretKey key = kg.generateKey();
+
+ // encrypt
+ algorithmCipher.init(ENCRYPT_MODE, key);
+ if (!supportedKeyLength) {
+ throw new RuntimeException(String.format(
+ "The key length %d is not supported, so the initialization "
+ + "of algorithmCipher should fail.%n",
+ dataTuple.keyLength));
+ }
+
+ byte[] cipherText = new byte[algorithmCipher.getOutputSize(INPUT.length)];
+ int offset = algorithmCipher.update(INPUT, 0, INPUT.length,
+ cipherText, 0);
+ algorithmCipher.doFinal(cipherText, offset);
+
+ AlgorithmParameterSpec aps = null;
+ if (!dataTuple.mode.equalsIgnoreCase("ECB")) {
+ aps = new IvParameterSpec(algorithmCipher.getIV());
+ }
+
+ oidCipher.init(Cipher.DECRYPT_MODE, key, aps);
+ if (!supportedKeyLength) {
+ throw new RuntimeException(String.format(
+ "The key length %d is not supported, so the "
+ + "initialization of oidCipher should fail.%n",
+ dataTuple.keyLength));
+ }
+
+ byte[] recoveredText = new byte[oidCipher.getOutputSize(cipherText.length)];
+ oidCipher.doFinal(cipherText, 0, cipherText.length, recoveredText);
+
+ // Comparison
+ if (!Arrays.equals(INPUT, recoveredText)) {
+ throw new RuntimeException(
+ "Decrypted data is not the same as the original text");
+ }
+ }
+
+ private static class DataTuple {
+
+ private final String oid;
+ private final String algorithm;
+ private final int keyLength;
+ private final String mode;
+
+ private DataTuple(String oid, String algorithm, int keyLength,
+ String mode) {
+ this.oid = oid;
+ this.algorithm = algorithm;
+ this.keyLength = keyLength;
+ this.mode = mode;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/crypto/provider/NSASuiteB/TestAESWrapOids.java Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,154 @@
+/*
+ * 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.
+ */
+
+import static javax.crypto.Cipher.getMaxAllowedKeyLength;
+
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.KeyGenerator;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+
+/*
+ * @test
+ * @bug 8075286
+ * @summary Test the AESWrap algorithm OIDs in JDK.
+ * OID and Algorithm transformation string should match.
+ * Both could be able to be used to generate the algorithm instance.
+ * @run main TestAESWrapOids
+ */
+public class TestAESWrapOids {
+
+ private static final String PROVIDER_NAME = "SunJCE";
+
+ private static final List<DataTuple> DATA = Arrays.asList(
+ new DataTuple("2.16.840.1.101.3.4.1.5", "AESWrap_128", 128),
+ new DataTuple("2.16.840.1.101.3.4.1.25", "AESWrap_192", 192),
+ new DataTuple("2.16.840.1.101.3.4.1.45", "AESWrap_256", 256));
+
+ public static void main(String[] args) throws Exception {
+ for (DataTuple dataTuple : DATA) {
+ int maxAllowedKeyLength = getMaxAllowedKeyLength(
+ dataTuple.algorithm);
+ boolean supportedKeyLength =
+ maxAllowedKeyLength >= dataTuple.keyLength;
+
+ try {
+ runTest(dataTuple, supportedKeyLength);
+ System.out.println("passed");
+ } catch (InvalidKeyException ike) {
+ if (supportedKeyLength) {
+ throw new RuntimeException(String.format(
+ "The key length %d is supported, but test failed.",
+ dataTuple.keyLength), ike);
+ } else {
+ System.out.printf(
+ "Catch expected InvalidKeyException "
+ + "due to the key length %d is greater "
+ + "than max supported key length %d%n",
+ dataTuple.keyLength, maxAllowedKeyLength);
+ }
+ }
+ }
+ }
+
+ private static void runTest(DataTuple dataTuple, boolean supportedKeyLength)
+ throws NoSuchAlgorithmException, NoSuchProviderException,
+ NoSuchPaddingException, InvalidKeyException,
+ IllegalBlockSizeException {
+ Cipher algorithmCipher = Cipher.getInstance(
+ dataTuple.algorithm, PROVIDER_NAME);
+ Cipher oidCipher = Cipher.getInstance(dataTuple.oid, PROVIDER_NAME);
+
+ if (algorithmCipher == null) {
+ throw new RuntimeException(String.format(
+ "Test failed: algorithm string %s getInstance failed.%n",
+ dataTuple.algorithm));
+ }
+
+ if (oidCipher == null) {
+ throw new RuntimeException(
+ String.format("Test failed: OID %s getInstance failed.%n",
+ dataTuple.oid));
+ }
+
+ if (!algorithmCipher.getAlgorithm().equals(
+ dataTuple.algorithm)) {
+ throw new RuntimeException(String.format(
+ "Test failed: algorithm string %s getInstance "
+ + "doesn't generate expected algorithm.%n",
+ dataTuple.oid));
+ }
+
+ KeyGenerator kg = KeyGenerator.getInstance("AES");
+ kg.init(dataTuple.keyLength);
+ SecretKey key = kg.generateKey();
+
+ // Wrap the key
+ algorithmCipher.init(Cipher.WRAP_MODE, key);
+ if (!supportedKeyLength) {
+ throw new RuntimeException(String.format(
+ "The key length %d is not supported, so the initialization"
+ + " of algorithmCipher should fail.%n",
+ dataTuple.keyLength));
+ }
+
+ // Unwrap the key
+ oidCipher.init(Cipher.UNWRAP_MODE, key);
+ if (!supportedKeyLength) {
+ throw new RuntimeException(String.format(
+ "The key length %d is not supported, so the initialization"
+ + " of oidCipher should fail.%n",
+ dataTuple.keyLength));
+ }
+
+ byte[] keyWrapper = algorithmCipher.wrap(key);
+ Key unwrappedKey = oidCipher.unwrap(keyWrapper, "AES",
+ Cipher.SECRET_KEY);
+
+ // Comparison
+ if (!Arrays.equals(key.getEncoded(), unwrappedKey.getEncoded())) {
+ throw new RuntimeException("Key comparison failed");
+ }
+ }
+
+ private static class DataTuple {
+
+ private final String oid;
+ private final String algorithm;
+ private final int keyLength;
+
+ private DataTuple(String oid, String algorithm, int keyLength) {
+ this.oid = oid;
+ this.algorithm = algorithm;
+ this.keyLength = keyLength;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/crypto/provider/NSASuiteB/TestHmacSHAOids.java Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,116 @@
+/*
+ * 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.
+ */
+
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.crypto.KeyGenerator;
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+
+/*
+ * @test
+ * @bug 8075286
+ * @summary Test the HmacSHA algorithm OIDs in JDK.
+ * OID and Algorithm transformation string should match.
+ * Both could be able to be used to generate the algorithm instance.
+ * @run main TestHmacSHAOids
+ */
+public class TestHmacSHAOids {
+
+ private static final String PROVIDER_NAME = "SunJCE";
+ private static final byte[] INPUT = "1234567890".getBytes();
+
+ private static final List<DataTuple> DATA = Arrays.asList(
+ new DataTuple("1.2.840.113549.2.7", "HmacSHA1"),
+ new DataTuple("1.2.840.113549.2.8", "HmacSHA224"),
+ new DataTuple("1.2.840.113549.2.9", "HmacSHA256"),
+ new DataTuple("1.2.840.113549.2.10", "HmacSHA384"),
+ new DataTuple("1.2.840.113549.2.11", "HmacSHA512"));
+
+ public static void main(String[] args) throws Exception {
+ for (DataTuple dataTuple : DATA) {
+ runTest(dataTuple);
+ System.out.println("passed");
+ }
+ System.out.println("All tests passed");
+ }
+
+ private static void runTest(DataTuple dataTuple)
+ throws NoSuchAlgorithmException, NoSuchProviderException,
+ InvalidKeyException {
+ Mac mcAlgorithm = Mac.getInstance(dataTuple.algorithm,
+ PROVIDER_NAME);
+ Mac mcOid = Mac.getInstance(dataTuple.oid, PROVIDER_NAME);
+
+ if (mcAlgorithm == null) {
+ throw new RuntimeException(String.format(
+ "Test failed: Mac using algorithm "
+ + "string %s getInstance failed.%n",
+ dataTuple.algorithm));
+ }
+
+ if (mcOid == null) {
+ throw new RuntimeException(String.format(
+ "Test failed: Mac using OID %s getInstance failed.%n",
+ dataTuple.oid));
+ }
+
+ if (!mcAlgorithm.getAlgorithm().equals(dataTuple.algorithm)) {
+ throw new RuntimeException(String.format(
+ "Test failed: Mac using algorithm string %s getInstance "
+ + "doesn't generate expected algorithm.%n",
+ dataTuple.algorithm));
+ }
+
+ KeyGenerator kg = KeyGenerator.getInstance(dataTuple.algorithm,
+ PROVIDER_NAME);
+ SecretKey key = kg.generateKey();
+
+ mcAlgorithm.init(key);
+ mcAlgorithm.update(INPUT);
+
+ mcOid.init(key);
+ mcOid.update(INPUT);
+
+ // Comparison
+ if (!Arrays.equals(mcAlgorithm.doFinal(), mcOid.doFinal())) {
+ throw new RuntimeException("Digest comparison failed: "
+ + "the two MACs are not the same");
+ }
+ }
+
+ private static class DataTuple {
+
+ private final String oid;
+ private final String algorithm;
+
+ private DataTuple(String oid, String algorithm) {
+ this.oid = oid;
+ this.algorithm = algorithm;
+ }
+ }
+}
--- a/jdk/test/com/sun/jndi/ldap/LdapTimeoutTest.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/test/com/sun/jndi/ldap/LdapTimeoutTest.java Wed Jul 05 20:51:27 2017 +0200
@@ -412,11 +412,14 @@
// run the ReadServerTest with connect / read timeouts set
// this should exit after the connect timeout expires
- System.out.println("Running read timeout test with 10ms connect timeout, 3000ms read timeout");
- Hashtable env4 = createEnv();
- env4.put("com.sun.jndi.ldap.connect.timeout", "10");
- env4.put("com.sun.jndi.ldap.read.timeout", "3000");
- results.add(testPool.submit(new ReadServerTimeoutTest(env4)));
+ //
+ // NOTE: commenting this test out as it is failing intermittently.
+ //
+ // System.out.println("Running read timeout test with 10ms connect timeout, 3000ms read timeout");
+ // Hashtable env4 = createEnv();
+ // env4.put("com.sun.jndi.ldap.connect.timeout", "10");
+ // env4.put("com.sun.jndi.ldap.read.timeout", "3000");
+ // results.add(testPool.submit(new ReadServerTimeoutTest(env4)));
// run the DeadServerTest with connect timeout set
// this should exit after the connect timeout expires
--- a/jdk/test/java/lang/ProcessBuilder/Basic.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/test/java/lang/ProcessBuilder/Basic.java Wed Jul 05 20:51:27 2017 +0200
@@ -738,7 +738,7 @@
* Remove it from the list of env variables
*/
private static String removeAixExpectedVars(String vars) {
- return vars.replace("AIXTHREAD_GUARDPAGES=0,","");
+ return vars.replace("AIXTHREAD_GUARDPAGES=0,", "");
}
private static String sortByLinesWindowsly(String text) {
@@ -785,8 +785,8 @@
equal(entry.getKey(), key);
equal(entry.getValue(), value);
}
- check(! kIter.hasNext() &&
- ! vIter.hasNext());
+ check(!kIter.hasNext() &&
+ !vIter.hasNext());
} catch (Throwable t) { unexpected(t); }
}
@@ -815,9 +815,9 @@
static void checkRedirects(ProcessBuilder pb,
Redirect in, Redirect out, Redirect err) {
- equal(pb.redirectInput(), in);
+ equal(pb.redirectInput(), in);
equal(pb.redirectOutput(), out);
- equal(pb.redirectError(), err);
+ equal(pb.redirectError(), err);
}
static void redirectIO(ProcessBuilder pb,
@@ -862,6 +862,7 @@
Redirect[] redirects =
{ PIPE,
INHERIT,
+ DISCARD,
Redirect.from(ifile),
Redirect.to(ifile),
Redirect.appendTo(ifile),
@@ -884,6 +885,10 @@
equal(INHERIT.toString(), "INHERIT");
equal(INHERIT.file(), null);
+ equal(DISCARD.type(), Redirect.Type.WRITE);
+ equal(DISCARD.toString(), "WRITE");
+ equal(DISCARD.file(), new File((Windows.is() ? "NUL" : "/dev/null")));
+
equal(Redirect.from(ifile).type(), Redirect.Type.READ);
equal(Redirect.from(ifile).toString(),
"redirect to read from file \"ifile\"");
@@ -926,6 +931,12 @@
checkRedirects(pb, INHERIT, INHERIT, INHERIT);
//----------------------------------------------------------------
+ // Check DISCARD for stdout,stderr
+ //----------------------------------------------------------------
+ redirectIO(pb, INHERIT, DISCARD, DISCARD);
+ checkRedirects(pb, INHERIT, DISCARD, DISCARD);
+
+ //----------------------------------------------------------------
// Check setters and getters agree
//----------------------------------------------------------------
pb.redirectInput(ifile);
@@ -943,7 +954,8 @@
THROWS(IllegalArgumentException.class,
() -> pb.redirectInput(Redirect.to(ofile)),
() -> pb.redirectOutput(Redirect.from(ifile)),
- () -> pb.redirectError(Redirect.from(ifile)));
+ () -> pb.redirectError(Redirect.from(ifile)),
+ () -> pb.redirectInput(DISCARD));
THROWS(NullPointerException.class,
() -> pb.redirectInput((File)null),
@@ -980,7 +992,7 @@
ProcessResults r = run(pb);
equal(r.exitValue(), 0);
equal(fileContents(ofile),
- "standard error" + "standard output");
+ "standard error" + "standard output");
equal(fileContents(efile), "");
equal(r.out(), "");
equal(r.err(), "");
@@ -1051,6 +1063,79 @@
}
//----------------------------------------------------------------
+ // DISCARDing output
+ //----------------------------------------------------------------
+ {
+ setFileContents(ifile, "standard input");
+ pb.redirectOutput(DISCARD);
+ pb.redirectError(DISCARD);
+ ProcessResults r = run(pb);
+ equal(r.exitValue(), 0);
+ equal(r.out(), "");
+ equal(r.err(), "");
+ }
+
+ //----------------------------------------------------------------
+ // DISCARDing output and redirecting error
+ //----------------------------------------------------------------
+ {
+ setFileContents(ifile, "standard input");
+ setFileContents(ofile, "ofile-contents");
+ setFileContents(efile, "efile-contents");
+ pb.redirectOutput(DISCARD);
+ pb.redirectError(efile);
+ ProcessResults r = run(pb);
+ equal(r.exitValue(), 0);
+ equal(fileContents(ofile), "ofile-contents");
+ equal(fileContents(efile), "standard error");
+ equal(r.out(), "");
+ equal(r.err(), "");
+ ofile.delete();
+ efile.delete();
+ }
+
+ //----------------------------------------------------------------
+ // DISCARDing error and redirecting output
+ //----------------------------------------------------------------
+ {
+ setFileContents(ifile, "standard input");
+ setFileContents(ofile, "ofile-contents");
+ setFileContents(efile, "efile-contents");
+ pb.redirectOutput(ofile);
+ pb.redirectError(DISCARD);
+ ProcessResults r = run(pb);
+ equal(r.exitValue(), 0);
+ equal(fileContents(ofile), "standard output");
+ equal(fileContents(efile), "efile-contents");
+ equal(r.out(), "");
+ equal(r.err(), "");
+ ofile.delete();
+ efile.delete();
+ }
+
+ //----------------------------------------------------------------
+ // DISCARDing output and merging error into output
+ //----------------------------------------------------------------
+ {
+ setFileContents(ifile, "standard input");
+ setFileContents(ofile, "ofile-contents");
+ setFileContents(efile, "efile-contents");
+ pb.redirectOutput(DISCARD);
+ pb.redirectErrorStream(true);
+ pb.redirectError(efile);
+ ProcessResults r = run(pb);
+ equal(r.exitValue(), 0);
+ equal(fileContents(ofile), "ofile-contents"); // untouched
+ equal(fileContents(efile), ""); // empty
+ equal(r.out(), "");
+ equal(r.err(), "");
+ ifile.delete();
+ ofile.delete();
+ efile.delete();
+ pb.redirectErrorStream(false); // reset for next test
+ }
+
+ //----------------------------------------------------------------
// Testing INHERIT is harder.
// Note that this requires __FOUR__ nested JVMs involved in one test,
// if you count the harness JVM.
--- a/jdk/test/java/lang/StrictMath/HypotTests.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/test/java/lang/StrictMath/HypotTests.java Wed Jul 05 20:51:27 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -42,9 +42,37 @@
public class HypotTests {
private HypotTests(){}
+ /**
+ * The hypot implementation is commutative, {@code hypot(a, b) ==
+ * hypot(b, a)}, and independent of sign, {@code hypot(a, b) ==
+ * hypot(-a, b) == hypot(a, -b) == hypot(-a, -b)}.
+ */
static int testHypotCase(double input1, double input2, double expected) {
- return Tests.test("StrictMath.hypot(double)", input1, input2,
- StrictMath.hypot(input1, input2), expected);
+ int failures = 0;
+ failures += Tests.test("StrictMath.hypot(double)", input1, input2,
+ StrictMath.hypot(input1, input2), expected);
+
+ failures += Tests.test("StrictMath.hypot(double)", input2, input1,
+ StrictMath.hypot(input2, input1), expected);
+
+ failures += Tests.test("StrictMath.hypot(double)", -input1, input2,
+ StrictMath.hypot(-input1, input2), expected);
+
+ failures += Tests.test("StrictMath.hypot(double)", input2, -input1,
+ StrictMath.hypot(input2, -input1), expected);
+
+ failures += Tests.test("StrictMath.hypot(double)", input1, -input2,
+ StrictMath.hypot(input1, -input2), expected);
+
+ failures += Tests.test("StrictMath.hypot(double)", -input2, input1,
+ StrictMath.hypot(-input2, input1), expected);
+
+ failures += Tests.test("StrictMath.hypot(double)", -input1, -input2,
+ StrictMath.hypot(-input1, -input2), expected);
+
+ failures += Tests.test("StrictMath.hypot(double)", -input2, -input1,
+ StrictMath.hypot(-input2, -input1), expected);
+ return failures;
}
static int testHypot() {
@@ -611,21 +639,60 @@
{0x1.8p1, 0x1.8bffffffffff6p6, 0x1.8c2e88e6f44b1p6},
{0x1.8p1, 0x1.8ffffffffffe8p6, 0x1.902e11d3b5549p6},
{0x1.8p1, 0x1.8fffffffffffep6, 0x1.902e11d3b556p6},
+
+ // Test near decision points of the fdlibm algorithm
+ {0x1.0000000000001p501, 0x1.000000000000p501, 0x1.6a09e667f3bcdp501},
+ {0x1.0p501, 0x1.0p499, 0x1.07e0f66afed07p501},
+
+ {0x1.0p500, 0x1.0p450, 0x1.0p500},
+ {0x1.0000000000001p500, 0x1.0p450, 0x1.0000000000001p500},
+
+ {0x1.0p500, 0x1.0p440, 0x1.0p500},
+ {0x1.0000000000001p500, 0x1.0p440, 0x1.0000000000001p500},
+ {0x1.0p500, 0x1.0p439, 0x1.0p500},
+ {0x1.0000000000001p500, 0x1.0p439, 0x1.0000000000001p500},
+
+ {0x1.0p-450, 0x1.0p-500, 0x1.0p-450},
+ {0x1.0000000000001p-450, 0x1.0p-500, 0x1.0000000000001p-450},
+ {0x1.0p-450, 0x1.fffffffffffffp-499, 0x1.0p-450},
+ {0x1.0000000000001p-450, 0x1.fffffffffffffp-499, 0x1.0000000000001p-450},
+
+
+ {0x1.0p-450, 0x1.0p-500, 0x1.0p-450},
+ {0x1.0000000000001p-450, 0x1.0p-500, 0x1.0000000000001p-450},
+ {0x1.0p-450, 0x1.fffffffffffffp-499, 0x1.0p-450},
+ {0x1.0000000000001p-450, 0x1.fffffffffffffp-499, 0x1.0000000000001p-450},
+
+ // 0x1.0p-1022 is MIN_NORMAL
+ {0x1.0000000000001p-1022, 0x1.0000000000001p-1022, 0x1.6a09e667f3bcep-1022},
+ {0x1.0000000000001p-1022, 0x1.0p-1022, 0x1.6a09e667f3bcdp-1022},
+ {0x1.0000000000001p-1022, 0x0.fffffffffffffp-1022, 0x1.6a09e667f3bcdp-1022},
+ {0x1.0000000000001p-1022, 0x0.0000000000001P-1022, 0x1.0000000000001p-1022},
+ {0x1.0000000000001p-1022, 0.0, 0x1.0000000000001p-1022},
+
+ {0x1.0000000000000p-1022, 0x0.fffffffffffffp-1022, 0x1.6a09e667f3bccp-1022},
+ {0x1.0000000000000p-1021, 0x0.fffffffffffffp-1022, 0x1.1e3779b97f4a8p-1021},
+ {0x1.0000000000000p-1020, 0x0.fffffffffffffp-1022, 0x1.07e0f66afed07p-1020},
+
+ // 0x0.0000000000001P-1022 is MIN_VALUE (smallest nonzero number)
+ {0x0.0000000000001p-1022, 0x0.0000000000001p-1022, 0x0.0000000000001p-1022},
+ {0x0.0000000000002p-1022, 0x0.0000000000001p-1022, 0x0.0000000000002p-1022},
+ {0x0.0000000000003p-1022, 0x0.0000000000002p-1022, 0x0.0000000000004p-1022},
};
for (double[] testCase: testCases)
- failures+=testHypotCase(testCase[0], testCase[1], testCase[2]);
+ failures += testHypotCase(testCase[0], testCase[1], testCase[2]);
return failures;
}
- public static void main(String [] argv) {
+ public static void main(String... args) {
int failures = 0;
failures += testHypot();
if (failures > 0) {
- System.err.println("Testing log1p incurred "
+ System.err.println("Testing hypot incurred "
+ failures + " failures.");
throw new RuntimeException();
}
--- a/jdk/test/java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/test/java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java Wed Jul 05 20:51:27 2017 +0200
@@ -32,7 +32,7 @@
* @build LambdaFormTestCase
* @build LFCachingTestCase
* @build LFMultiThreadCachingTest
- * @run main/othervm LFMultiThreadCachingTest
+ * @run main/othervm -Djava.lang.invoke.MethodHandle.OBSERVE_BMH_SPECIES_CREATION=true LFMultiThreadCachingTest
*/
import java.lang.invoke.MethodHandle;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/channels/FileChannel/LoopingTruncate.java Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,66 @@
+/*
+ * 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 8137121
+ * @summary (fc) Infinite loop FileChannel.truncate
+ * @run main/othervm LoopingTruncate
+ */
+
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import static java.nio.file.StandardOpenOption.*;
+
+public class LoopingTruncate {
+
+ // (int)FATEFUL_SIZE == -3 == IOStatus.INTERRUPTED
+ static long FATEFUL_SIZE = 0x1FFFFFFFDL;
+
+ static long TIMEOUT = 10_000; // 10 seconds
+
+ public static void main(String[] args) throws Throwable {
+ Path path = Files.createTempFile("LoopingTruncate.tmp", null);
+ try {
+ Thread th = new Thread(() -> {
+ try (FileChannel fc = FileChannel.open(path, CREATE, WRITE)) {
+ fc.position(FATEFUL_SIZE + 1L);
+ fc.write(ByteBuffer.wrap(new byte[] {0}));
+ fc.truncate(FATEFUL_SIZE);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }});
+ th.start();
+ th.join(TIMEOUT);
+
+ if (th.isAlive()) {
+ th.interrupt();
+ throw new RuntimeException("Failed to complete on time");
+ }
+ } finally {
+ Files.deleteIfExists(path);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/security/Policy/ExtensiblePolicy/ExtensiblePolicyTest.java Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+
+import TVJar.TVPermission;
+import java.security.AccessController;
+
+/**
+ * @test @bug 8050402
+ * @summary Check policy is extensible with user defined permissions
+ * @run main/othervm/policy=ExtensiblePolicyTest1.policy
+ * ExtensiblePolicyTest false
+ * @run main/othervm/policy=ExtensiblePolicyTest2.policy
+ * ExtensiblePolicyTest true
+ * @run main/othervm/policy=ExtensiblePolicyTest3.policy
+ * ExtensiblePolicyTest true
+ */
+public class ExtensiblePolicyTest {
+
+ public static void main(String args[]) throws Throwable {
+ // ExtensiblePolicyTest1.policy: policy file grants permission to
+ // watch TVChannel 3-6
+ // ExtensiblePolicyTest2.policy: policy file grants permission to
+ // watch TVChanel 4
+ // ExtensiblePolicyTest3.policy: policy file grants permission signed
+ // by duke2 to watch TVChanel 5
+
+ TVPermission perm = new TVPermission("channel:5", "watch");
+ boolean getException = false;
+ String exceptionMessage = null;
+ boolean expectException = Boolean.parseBoolean(args[0]);
+ try {
+ AccessController.checkPermission(perm);
+ } catch (SecurityException se) {
+ getException = true;
+ exceptionMessage = se.getMessage();
+ }
+
+ if (expectException ^ getException) {
+ throw new RuntimeException("Test Failed: expectException = "
+ + expectException + " getException = " + getException
+ + "\n" + exceptionMessage);
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/security/Policy/ExtensiblePolicy/ExtensiblePolicyTest1.policy Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,4 @@
+grant {
+ permission TVJar.TVPermission "channel:3-6", "watch";
+};
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/security/Policy/ExtensiblePolicy/ExtensiblePolicyTest2.policy Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,3 @@
+grant {
+ permission TVJar.TVPermission "channel:4", "watch";
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/security/Policy/ExtensiblePolicy/ExtensiblePolicyTest3.policy Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,5 @@
+keystore "file:${user.dir}/epkeystore";
+
+grant {
+ permission TVJar.TVPermission "channel:5", "watch", SignedBy "duke2";
+};
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/security/Policy/ExtensiblePolicy/ExtensiblePolicyWithJarTest.java Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,113 @@
+/*
+ * 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.
+ */
+
+import TVJar.TVPermission;
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.security.AccessController;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.JarUtils;
+
+/**
+ * @test
+ * @bug 8050402
+ * @summary Check policy is extensible with user defined permissions
+ * @library /lib/testlibrary
+ * @compile TVJar/TVPermission.java
+ * @run main ExtensiblePolicyWithJarTest
+ */
+public class ExtensiblePolicyWithJarTest {
+
+ public static void main(String args[]) throws Throwable {
+ final String FS = File.separator;
+ final String PS = File.pathSeparator;
+ final String POL = "ExtensiblePolicyTest3.policy";
+ final String JAVA_HOME = System.getProperty("test.jdk");
+ final String KEYTOOL = JAVA_HOME + FS + "bin" + FS + "keytool";
+ final String JARSIGNER = JAVA_HOME + FS + "bin" + FS + "jarsigner";
+ final String KEYSTORE = "epkeystore";
+ final String PASSWORD = "password";
+ final String ALIAS = "duke2";
+ final String CLASSPATH = System.getProperty("test.class.path", "");
+ final String TESTCLASSES = System.getProperty("test.classes", "");
+ final String TVPERMJAR = "tvPerm.jar";
+ final String PATHTOJAR = System.getProperty("user.dir", "")
+ + FS + TVPERMJAR;
+
+ // create jar file for TVpermission
+ new File("TVJar").mkdir();
+ Files.copy(Paths.get(TESTCLASSES + FS + "TVJar", "TVPermission.class"),
+ Paths.get("TVJar", "TVPermission.class"));
+ Files.copy(Paths.get(TESTCLASSES + FS + "TVJar",
+ "TVPermissionCollection.class"),
+ Paths.get("TVJar", "TVPermissionCollection.class"));
+ JarUtils.createJar(TVPERMJAR, "TVJar/TVPermission.class",
+ "TVJar/TVPermissionCollection.class");
+
+ // create key pair for jar signing
+ ProcessTools.executeCommand(KEYTOOL,
+ "-genkey",
+ "-alias", ALIAS,
+ "-keystore", KEYSTORE,
+ "-storetype", "JKS",
+ "-keypass", PASSWORD,
+ "-dname", "cn=Blah",
+ "-storepass", PASSWORD
+ ).shouldHaveExitValue(0);
+ // sign jar
+ ProcessTools.executeCommand(JARSIGNER,
+ "-keystore", KEYSTORE,
+ "-storepass", PASSWORD,
+ "-keypass", PASSWORD,
+ TVPERMJAR,
+ ALIAS).shouldHaveExitValue(0);
+ // add jar file to classpath
+ String cp = PATHTOJAR + PS + CLASSPATH;
+
+ // policy file grants permission signed by duke2 to watch TVChanel 5
+ try {
+ String[] cmd = {
+ "-classpath", cp,
+ "-Djava.security.manager",
+ "-Djava.security.policy=" + POL,
+ "ExtensiblePolicyTest_orig$TestMain"};
+ ProcessTools.executeTestJvm(cmd).shouldHaveExitValue(0);
+ } catch (Exception ex) {
+ System.out.println("ExtensiblePolicyWithJarTest Failed");
+ }
+
+ }
+
+ public static class TestMain {
+ public static void main(String args[]) {
+ TVPermission perm = new TVPermission("channel:5", "watch");
+ try {
+ AccessController.checkPermission(perm);
+ } catch (SecurityException se) {
+ throw new RuntimeException(se);
+ }
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/security/Policy/ExtensiblePolicy/TVJar/TVPermission.java Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,358 @@
+/*
+ * Copyright (c) 1999, 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 TVJar;
+
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.StringJoiner;
+import java.util.StringTokenizer;
+
+public class TVPermission extends Permission {
+
+ /**
+ * Watch
+ */
+ private final static int WATCH = 0x1;
+
+ /**
+ * Preview
+ */
+ private final static int PREVIEW = 0x2;
+
+ /**
+ * No actions
+ */
+ private final static int NONE = 0x0;
+
+ /**
+ * All actions
+ */
+ private final static int ALL = WATCH | PREVIEW;
+
+ // the actions mask
+ private int mask;
+
+ // the actions string
+ private String actions;
+
+ // the canonical name of the channel
+ private String cname;
+
+ // true if the channelname is a wildcard
+ private boolean wildcard;
+
+ // num range on channel
+ private int[] numrange;
+
+ // various num constants
+ private final static int NUM_MIN = 1;
+ private final static int NUM_MAX = 128;
+
+ public TVPermission(String channel, String action) {
+ this(channel, getMask(action));
+ }
+
+ TVPermission(String channel, int mask) {
+ super(channel);
+ init(channel, mask);
+ }
+
+ private synchronized int[] parseNum(String num)
+ throws Exception {
+
+ if (num == null || num.equals("") || num.equals("*")) {
+ wildcard = true;
+ return new int[]{NUM_MIN, NUM_MAX};
+ }
+
+ int dash = num.indexOf('-');
+
+ if (dash == -1) {
+ int p = 0;
+ try {
+ p = Integer.parseInt(num);
+ } catch (NumberFormatException nfe) {
+ throw new IllegalArgumentException("invalid input" + num);
+ }
+ return new int[]{p, p};
+ } else {
+ String low = num.substring(0, dash);
+ String high = num.substring(dash + 1);
+ int l, h;
+
+ if (low.equals("")) {
+ l = NUM_MIN;
+ } else {
+ try {
+ l = Integer.parseInt(low);
+ } catch (NumberFormatException nfe) {
+ throw new IllegalArgumentException("invalid input" + num);
+ }
+ }
+
+ if (high.equals("")) {
+ h = NUM_MAX;
+ } else {
+ try {
+ h = Integer.parseInt(high);
+ } catch (NumberFormatException nfe) {
+ throw new IllegalArgumentException("invalid input" + num);
+ }
+ }
+ if (h < l || l < NUM_MIN || h > NUM_MAX) {
+ throw new IllegalArgumentException("invalid num range");
+ }
+
+ return new int[]{l, h};
+ }
+ }
+
+ /**
+ * Initialize the TVPermission object.
+ */
+ private synchronized void init(String channel, int mask) {
+
+ // Parse the channel name.
+ int sep = channel.indexOf(':');
+
+ if (sep != -1) {
+ String num = channel.substring(sep + 1);
+ cname = channel.substring(0, sep);
+ try {
+ numrange = parseNum(num);
+ } catch (Exception e) {
+ throw new IllegalArgumentException("invalid num range: " + num);
+ }
+ } else {
+ numrange = new int[]{NUM_MIN, NUM_MAX};
+ }
+ }
+
+ /**
+ * Convert an action string to an integer actions mask.
+ *
+ * @param action the action string
+ * @return the action mask
+ */
+ private synchronized static int getMask(String action) {
+ int mask = NONE;
+
+ if (action == null) {
+ return mask;
+ }
+
+ StringTokenizer st = new StringTokenizer(action.toLowerCase(), ",");
+ while (st.hasMoreTokens()) {
+ String token = st.nextToken();
+ if (token.equals("watch")) {
+ mask |= WATCH;
+ } else if (token.equals("preview")) {
+ mask |= PREVIEW;
+ } else {
+ throw new IllegalArgumentException("invalid TV permission: " + token);
+ }
+ }
+ return mask;
+ }
+
+ @Override
+ public boolean implies(Permission p) {
+ if (!(p instanceof TVPermission)) {
+ return false;
+ }
+
+ if (this.wildcard) {
+ return true;
+ }
+
+ TVPermission that = (TVPermission) p;
+
+ if ((this.mask & that.mask) != that.mask) {
+ System.out.println("Masks are not ok this = "
+ + this.mask + "THat = " + that.mask);
+ return false;
+ }
+
+ if ((this.numrange[0] > that.numrange[0])
+ || (this.numrange[1] < that.numrange[1])) {
+
+ System.out.println("This 0= " + this.numrange[0]
+ + " 1 = " + this.numrange[1]);
+ System.out.println("That 0= " + that.numrange[0]
+ + " 1 = " + that.numrange[1]);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Checks two TVPermission objects for equality.
+ * <p>
+ * @param obj the object we are testing for equality.
+ * @return true if obj is a TVPermission, and has the same channelname and
+ * action mask as this TVPermission object.
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+
+ if (!(obj instanceof TVPermission)) {
+ return false;
+ }
+
+ TVPermission that = (TVPermission) obj;
+
+ // check the mask first
+ if (this.mask != that.mask) {
+ return false;
+ }
+
+ // now check the num range...
+ if ((this.numrange[0] != that.numrange[0])
+ || (this.numrange[1] != that.numrange[1])) {
+ return false;
+ }
+
+ return this.getName().equals(that.getName());
+ }
+
+ /**
+ * Returns the hash code value for this object.
+ *
+ * @return a hash code value for this object.
+ */
+ @Override
+ public int hashCode() {
+ return this.getName().hashCode();
+ }
+
+ /**
+ * Return the canonical string representation of the actions. Always returns
+ * actions in the following order: watch,preview.
+ *
+ * @param mask a specific integer action mask to translate into a string
+ * @return the canonical string representation of the actions
+ */
+ private synchronized static String getActions(int mask) {
+ StringJoiner sj = new StringJoiner(",");
+ if ((mask & WATCH) == WATCH) {
+ sj.add("watch");
+ }
+ if ((mask & PREVIEW) == PREVIEW) {
+ sj.add("preview");
+ }
+ return sj.toString();
+ }
+
+ /**
+ * Return the canonical string representation of the actions. Always returns
+ * actions in the following order: watch,preview.
+ *
+ * @return the canonical string representation of the actions.
+ */
+ @Override
+ public String getActions() {
+ if (actions == null) {
+ actions = getActions(this.mask);
+ }
+
+ return actions;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + "\n"
+ + "cname = " + cname + "\n"
+ + "wildcard = " + wildcard + "\n"
+ + "numrange = " + numrange[0] + "," + numrange[1] + "\n";
+
+ }
+
+ @Override
+ public PermissionCollection newPermissionCollection() {
+ return new TVPermissionCollection();
+ }
+}
+
+final class TVPermissionCollection extends PermissionCollection {
+
+ /**
+ * The TVPermissions for this set.
+ */
+ private final ArrayList<TVPermission> permissions = new ArrayList<>();
+
+ /**
+ * Adds a permission to the TVPermissions. The key for the hash is the name
+ * in the case of wildcards, or all the IP addresses.
+ *
+ * @param permission the Permission object to add.
+ */
+ @Override
+ public void add(Permission permission) {
+ if (!(permission instanceof TVPermission)) {
+ throw new IllegalArgumentException("invalid permission: " + permission);
+ }
+ permissions.add((TVPermission) permission);
+ }
+
+ /**
+ * Check and see if this collection of permissions implies the permissions
+ * expressed in "permission".
+ *
+ * @param p the Permission object to compare
+ *
+ * @return true if "permission" is a proper subset of a permission in the
+ * collection, false if not.
+ */
+ @Override
+ public boolean implies(Permission p) {
+ if (!(p instanceof TVPermission)) {
+ return false;
+ }
+
+ Iterator<TVPermission> i = permissions.iterator();
+ while (i.hasNext()) {
+ if (((TVPermission) i.next()).implies(p)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns an enumeration of all the TVPermission objects in the container.
+ *
+ * @return an enumeration of all the TVPermission objects.
+ */
+ @Override
+ public Enumeration elements() {
+ return Collections.enumeration(permissions);
+ }
+
+}
--- a/jdk/test/java/util/TimeZone/CLDRDisplayNamesTest.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/test/java/util/TimeZone/CLDRDisplayNamesTest.java Wed Jul 05 20:51:27 2017 +0200
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8005471 8008577 8129881 8130845
+ * @bug 8005471 8008577 8129881 8130845 8136518
* @run main/othervm -Djava.locale.providers=CLDR CLDRDisplayNamesTest
* @summary Make sure that localized time zone names of CLDR are used
* if specified.
@@ -93,7 +93,7 @@
// for 8129881
tz = TimeZone.getTimeZone("Europe/Vienna");
- String name = tz.getDisplayName(false, SHORT);
+ String name = tz.getDisplayName(false, SHORT, Locale.ENGLISH);
if (!"CET".equals(name)) {
System.err.printf("error: got '%s' expected 'CET' %n", name);
errors++;
--- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CountTest.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CountTest.java Wed Jul 05 20:51:27 2017 +0200
@@ -31,6 +31,7 @@
import java.util.HashSet;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
import java.util.stream.DoubleStream;
import java.util.stream.DoubleStreamTestDataProvider;
import java.util.stream.IntStream;
@@ -61,6 +62,12 @@
expectedResult(expectedCount).
exercise();
+ // Test counting collector
+ withData(data).
+ terminal(s -> s, s -> s.collect(Collectors.counting())).
+ expectedResult(expectedCount).
+ exercise();
+
// Test with stateful distinct op that is a barrier or lazy
// depending if source is not already distinct and encounter order is
// preserved or not
--- a/jdk/test/javax/crypto/KeyGenerator/TestKGParity.java Sat Sep 26 09:22:24 2015 -0700
+++ b/jdk/test/javax/crypto/KeyGenerator/TestKGParity.java Wed Jul 05 20:51:27 2017 +0200
@@ -34,6 +34,7 @@
* @test
* @bug 8048607
* @compile ../../../com/sun/crypto/provider/Cipher/DES/TestUtility.java
+ * @run main TestKGParity
* @summary Test key generation of DES and DESEDE
* @key randomness
*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/security/auth/login/JAASConfigSyntaxCheck/JAASConfigSyntaxTest.java Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,57 @@
+
+/**
+ * Copyright (c) 2007, 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.
+ */
+
+import javax.security.auth.login.LoginContext;
+
+/**
+ * @test
+ * @bug 8050461
+ * @summary Test should throw Configuration error if configuration file contains
+ * syntax error
+ * @build SampleLoginModule JAASConfigSyntaxTest
+ * @run main/othervm -Djava.security.auth.login.config=file:${test.src}/JAASSynWithOutApplication.config JAASConfigSyntaxTest
+ * @run main/othervm -Djava.security.auth.login.config=file:${test.src}/JAASSynWithOutBraces.config JAASConfigSyntaxTest
+ * @run main/othervm -Djava.security.auth.login.config=file:${test.src}/JAASSynWithOutFlag.config JAASConfigSyntaxTest
+ * @run main/othervm -Djava.security.auth.login.config=file:${test.src}/JAASSynWithOutLoginModule.config JAASConfigSyntaxTest
+ * @run main/othervm -Djava.security.auth.login.config=file:${test.src}/JAASSynWithOutSemiColen.config JAASConfigSyntaxTest
+ */
+public class JAASConfigSyntaxTest {
+
+ private static final String TEST_NAME = "JAASConfigSyntaxTest";
+
+ public static void main(String[] args) throws Exception {
+ try {
+ LoginContext lc = new LoginContext(TEST_NAME);
+ lc.login();
+ throw new RuntimeException("Test Case Failed, did not get "
+ + "expected exception");
+ } catch (Exception ex) {
+ if (ex.getMessage().contains("java.io.IOException: "
+ + "Configuration Error:")) {
+ System.out.println("Test case passed");
+ } else {
+ throw new RuntimeException(ex);
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/security/auth/login/JAASConfigSyntaxCheck/JAASSynWithOutApplication.config Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,5 @@
+{
+SampleLoginModule Required;
+SampleLoginModule Required;
+SampleLoginModule Required;
+};
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/security/auth/login/JAASConfigSyntaxCheck/JAASSynWithOutBraces.config Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,5 @@
+JAASConfigSyntaxTest
+SampleLoginModule Required;
+SampleLoginModule Required;
+SampleLoginModule Required;
+;
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/security/auth/login/JAASConfigSyntaxCheck/JAASSynWithOutFlag.config Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,5 @@
+JAASConfigSyntaxTest{
+SampleLoginModule ;
+SampleLoginModule ;
+SampleLoginModule ;
+};
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/security/auth/login/JAASConfigSyntaxCheck/JAASSynWithOutLoginModule.config Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,5 @@
+JAASConfigSyntaxTest{
+;
+;
+;
+};
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/security/auth/login/JAASConfigSyntaxCheck/JAASSynWithOutSemiColen.config Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,5 @@
+JAASConfigSyntaxTest{
+SampleLoginModule Required;
+SampleLoginModule Required
+SampleLoginModule Required;
+};
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/security/auth/login/JAASConfigSyntaxCheck/SampleLoginModule.java Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,75 @@
+/**
+ * Copyright (c) 2007, 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.
+ */
+
+import static java.lang.System.out;
+import java.util.Map;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.spi.LoginModule;
+
+/**
+ * Login module which passes all the time
+ */
+
+public class SampleLoginModule implements LoginModule {
+
+ private final String name;
+
+ public SampleLoginModule() {
+ name = this.getClass().getName();
+ }
+
+ @Override
+ public void initialize(Subject subject, CallbackHandler callbackHandler,
+ Map<String, ?> sharedState, Map<String, ?> options) {
+ }
+
+ @Override
+ public boolean login() throws LoginException {
+ out.println(name + " Login method of AbstractLoginModule is called ");
+ out.println(name + ":login:PASS");
+ return true;
+ }
+
+ @Override
+ public boolean commit() throws LoginException {
+ out.println("Commit of AbstractLoginModule is called");
+ out.println(name + ":commit:PASS");
+ return true;
+
+ }
+
+ @Override
+ public boolean abort() throws LoginException {
+ out.println("Abourt is called in AbstractLoginModule");
+ out.println(name + ":abort:PASS");
+ return true;
+ }
+
+ @Override
+ public boolean logout() throws LoginException {
+ out.println("logout is called in AbstractLoginModule");
+ out.println(name + ":logout:PASS");
+ return true;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/security/auth/login/LoginContext/DummyLoginModule.java Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2004, 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.
+ */
+
+import javax.security.auth.login.LoginException;
+
+/**
+ * Login module which passes all the time
+ */
+
+public class DummyLoginModule extends SmartLoginModule {
+ private final String header;
+
+ public DummyLoginModule() {
+ header = "DummyLoginModule: ";
+ }
+
+ @Override
+ public boolean login() throws LoginException {
+ System.out.println("\t\t" + header + " login method is called ");
+ System.out.println("\t\t" + header + " login:PASS");
+ return true;
+ }
+
+ @Override
+ public boolean commit() throws LoginException {
+ System.out.println("\t\t" + header + " commit method is called");
+ System.out.println("\t\t" + header + " commit:PASS");
+ return true;
+ }
+
+ @Override
+ public boolean abort() throws LoginException {
+ System.out.println("\t\t" + header + " abort method is called ");
+ System.out.println("\t\t" + header + " abort:PASS");
+
+ return true;
+ }
+
+ @Override
+ public boolean logout() throws LoginException {
+ System.out.println("\t\t" + header + " logout method is called");
+ System.out.println("\t\t" + header + " logout:PASS");
+ return true;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/security/auth/login/LoginContext/DynamicConfigurationTest.java Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2004, 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.
+ */
+
+import java.io.IOException;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.Configuration;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+
+/**
+ * @test
+ * @bug 8050427 4703361
+ * @summary Test case for RFE: 4703361. Tests the Dynamic Configuration of
+ * Authentication Modules with different methods
+ * @compile SmartLoginModule.java DummyLoginModule.java MyConfiguration.java
+ * @run main/othervm DynamicConfigurationTest
+ */
+public class DynamicConfigurationTest {
+
+ public static void main(String... args) {
+ String rightConfigName = "PT";
+ String wrongConfigName = "NT";
+ char[] rightPwd = new char[]{'t', 'e', 's', 't', 'P', 'a', 's', 's',
+ 'w', 'o', 'r', 'd', '1'};
+ char[] wrongPwd = new char[]{'w', 'r', 'o', 'n', 'g', 'P', 'a', 's',
+ 's','w', 'o', 'r', 'd'};
+
+ // Test with wrong configuration name
+ // Expect LoginException when initiate a new LoginContext object
+ testConfigName(wrongConfigName, true);
+ System.out.println("Wrong Config Name Test passed ");
+
+ // Spedify two loginModules: SmartLoginModule and DummyLoginModule
+ // Flags: required-required
+ // Test with right password for SmartLoginModule
+ // No exception is expected
+ Configuration cf = new MyConfiguration();
+ testLogin(rightConfigName, rightPwd, cf, false);
+ System.out.println("Positive test passed");
+
+ // Spedify two loginModules: SmartLoginModule and DummyLoginModule
+ // Flags: required-required
+ // Test with wrong password for SmartLoginModule
+ // Expect LoginException by calling LoginContext.login() method
+ testLogin(rightConfigName, wrongPwd, cf, true);
+ System.out.println("Should fail test passed");
+
+ // Spedify two loginModules: SmartLoginModule and DummyLoginModule
+ // Change the flags from required-required to optional-sufficient
+ // Test with wrong password for SmartLoginModule, while DummyLoginModule
+ // always passes
+ // No Exception is expected
+ cf = new MyConfiguration(true);
+ testLogin(rightConfigName, wrongPwd, cf, false);
+ System.out.println("One module fails where are other module succeeeds "
+ + "Test passed with optional-sufficient flags");
+ }
+
+ public static void testConfigName(String confName,
+ boolean expectException) {
+ String expectedMsg = "No LoginModules configured for " + confName;
+ try {
+ LoginContext lc = new LoginContext(confName, new Subject(),
+ new MyCallbackHandler(), new MyConfiguration());
+
+ if (expectException) {
+ throw new RuntimeException("Wrong Config Name Test failed: "
+ + "expected LoginException not thrown.");
+ }
+ } catch (LoginException le) {
+ if (!expectException || !le.getMessage().equals(expectedMsg)) {
+ System.out.println("Wrong Config Name Test failed: "
+ + "received Unexpected exception.");
+ throw new RuntimeException(le);
+ }
+ }
+ }
+
+ public static void testLogin(String confName, char[] passwd,
+ Configuration cf, boolean expectException) {
+ try {
+ CallbackHandler ch = new MyCallbackHandler("testUser", passwd);
+ LoginContext lc = new LoginContext(confName, new Subject(),
+ ch, cf);
+ lc.login();
+ if (expectException) {
+ throw new RuntimeException("Login Test failed: "
+ + "expected LoginException not thrown");
+ }
+ } catch (LoginException le) {
+ if (!expectException) {
+ System.out.println("Login Test failed: "
+ + "received Unexpected exception.");
+ throw new RuntimeException(le);
+ }
+ }
+ }
+}
+
+/**
+ * The application simulates the CallbackHandler. It simulates! which means all
+ * process to get username and password is ignored. We have to take this
+ * approach for automation purpose. So, this is not a real world example at all.
+ */
+class MyCallbackHandler implements CallbackHandler {
+
+ String userName;
+ char[] password;
+
+ /**
+ * This is simply a workaround approach for IO approach to get username and
+ * password. For automation purpose only.
+ */
+ public MyCallbackHandler() {
+ super();
+ }
+
+ public MyCallbackHandler(String username, char[] password) {
+ super();
+ userName = username;
+ this.password = password;
+ }
+
+ @Override
+ public void handle(Callback[] callbacks) throws IOException,
+ UnsupportedCallbackException {
+ for (Callback callback : callbacks) {
+ if (callback instanceof NameCallback) {
+ NameCallback nc = (NameCallback) callback;
+ nc.setName(userName);
+ } else if (callback instanceof PasswordCallback) {
+ PasswordCallback pc = (PasswordCallback) callback;
+ pc.setPassword(password);
+ } else {
+ throw new UnsupportedCallbackException(callback,
+ "Unrecognized Callback");
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/security/auth/login/LoginContext/MyConfiguration.java Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2004, 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.
+ */
+
+import java.util.HashMap;
+import javax.security.auth.login.AppConfigurationEntry;
+import static javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag.OPTIONAL;
+import static javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag.REQUIRED;
+import static javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT;
+import javax.security.auth.login.Configuration;
+
+/**
+ * This class is used to test LoginContext constructor API. It simply contains
+ * one configuration entry: PT.
+ */
+public class MyConfiguration extends Configuration {
+
+ private static final AppConfigurationEntry[] ptAE
+ = new AppConfigurationEntry[2];
+ private static final HashMap<String, String> map = new HashMap<>();
+ private boolean optionOrder = false;
+
+ public MyConfiguration() {
+ setupConfiguration();
+ }
+
+ public MyConfiguration(boolean optionOrder) {
+ this.optionOrder = optionOrder;
+ setupConfiguration();
+ }
+
+ private void setupConfiguration() {
+ ptAE[0] = new AppConfigurationEntry("SmartLoginModule",
+ optionOrder ? OPTIONAL : REQUIRED,
+ map);
+ ptAE[1] = new AppConfigurationEntry("DummyLoginModule",
+ optionOrder ? SUFFICIENT : REQUIRED,
+ map);
+ }
+
+ @Override
+ public AppConfigurationEntry[]
+ getAppConfigurationEntry(String applicationName) {
+ if (applicationName.equals("PT")) {
+ return ptAE;
+ } else {
+ return null;
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/security/auth/login/LoginContext/SmartLoginModule.java Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2004, 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.
+ */
+
+import java.security.Principal;
+import java.util.Arrays;
+import java.util.Map;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.FailedLoginException;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.spi.LoginModule;
+
+/**
+ * This code was based on JAAS demo code, small modification is made for testing
+ * purpose.
+ */
+public class SmartLoginModule implements LoginModule {
+
+ // initial state
+ private Subject subject;
+ private CallbackHandler callbackHandler;
+
+ // the authentication status
+ private boolean succeeded = false;
+ private boolean commitSucceeded = false;
+
+ // username and password
+ private String username;
+ private char[] password;
+
+ // Default values for this login module. In real world,
+ // don't do it in this way!
+ private String myUsername;
+ private char[] myPassword;
+ private String header;
+
+ // testUser's SamplePrincipal
+ private SamplePrincipal userPrincipal;
+
+ public SmartLoginModule() {
+ this("testUser",
+ new char[]{'t', 'e', 's', 't', 'P', 'a', 's', 's',
+ 'w', 'o', 'r', 'd', '1'},
+ "SmartLoginModule1: ");
+ }
+
+ public SmartLoginModule(String userName, char[] password, String header) {
+ myUsername = userName;
+ myPassword = password;
+ this.header = header;
+ }
+
+ @Override
+ public boolean abort() throws LoginException {
+ if (!succeeded) {
+ return false;
+ } else if (succeeded && !commitSucceeded) {
+ // login succeeded but overall authentication failed
+ succeeded = false;
+ username = null;
+ password = null;
+ userPrincipal = null;
+ } else {
+ // overall authentication succeeded and commit succeeded,
+ // but someone else's commit failed
+ logout();
+ }
+ return true;
+ }
+
+ @Override
+ public boolean commit() throws LoginException {
+ if (!succeeded) {
+ return false;
+ } else {
+ // add a Principal (authenticated identity) to the Subject
+ // assume the user we authenticated is the SamplePrincipal
+ userPrincipal = new SamplePrincipal(username);
+ if (!subject.getPrincipals().contains(userPrincipal)) {
+ subject.getPrincipals().add(userPrincipal);
+ }
+ // in any case, clean out state
+ username = null;
+ password = null;
+ commitSucceeded = true;
+ return true;
+ }
+ }
+
+ @Override
+ public void initialize(Subject subject, CallbackHandler callbackHandler,
+ Map<String, ?> sharedState, Map<String, ?> options) {
+ this.subject = subject;
+ this.callbackHandler = callbackHandler;
+ }
+
+ @Override
+ public boolean login() throws LoginException {
+ if (callbackHandler == null) {
+ throw new LoginException("Error: no CallbackHandler available to "
+ + "garner authentication information from the user");
+ }
+
+ Callback[] callbacks = new Callback[2];
+ callbacks[0] = new NameCallback(header + "user name: ");
+ callbacks[1] = new PasswordCallback(header + "password: ", false);
+
+ try {
+ callbackHandler.handle(callbacks);
+ username = ((NameCallback) callbacks[0]).getName();
+ char[] tmpPassword
+ = ((PasswordCallback) callbacks[1]).getPassword();
+ if (tmpPassword == null) {
+ tmpPassword = new char[0];
+ }
+ password = new char[tmpPassword.length];
+ System.arraycopy(tmpPassword, 0, password, 0, tmpPassword.length);
+ ((PasswordCallback) callbacks[1]).clearPassword();
+ } catch (java.io.IOException ioe) {
+ throw (LoginException) new LoginException().initCause(ioe);
+ } catch (UnsupportedCallbackException uce) {
+ throw new LoginException("Error: " + header
+ + uce.getCallback().toString()
+ + " not available to garner authentication information "
+ + "from the user");
+ }
+
+ // verify the username/password
+ if (username.equals(myUsername)
+ && Arrays.equals(password, myPassword)) {
+ System.out.println("\t\t" + header + " authentication succeeded");
+ succeeded = true;
+ return true;
+ } else {
+ // authentication failed -- clean out state
+ System.out.println("\t\t" + header + " authentication failed");
+ printDebugInfo();
+ succeeded = false;
+ username = null;
+ password = null;
+ throw new FailedLoginException("User Name or Password Incorrect");
+ }
+ }
+
+ @Override
+ public boolean logout() throws LoginException {
+ subject.getPrincipals().remove(userPrincipal);
+ succeeded = false;
+ succeeded = commitSucceeded;
+ username = null;
+ password = null;
+ userPrincipal = null;
+ return true;
+ }
+
+ // print debugging information
+ private void printDebugInfo() {
+ System.out.println("\t\t" + header + " correct user name: "
+ + myUsername);
+ System.out.println("\t\t" + header + " user entered user name: "
+ + username);
+ System.out.print("\t\t" + header + " correct password: ");
+ for (char c : myPassword) {
+ System.out.print(c);
+ }
+ System.out.println();
+ System.out.print("\t\t" + header + " user entered password: ");
+ for (char c : password) {
+ System.out.print(c);
+ }
+ System.out.println();
+ }
+}
+
+class SamplePrincipal implements Principal, java.io.Serializable {
+
+ /**
+ * @serial
+ */
+ private String name;
+
+ /**
+ * Create a SamplePrincipal with a Sample username.
+ *
+ * @param name the Sample username for this user.
+ * @exception NullPointerException if the <code>name</code> is
+ * <code>null</code>.
+ */
+ public SamplePrincipal(String name) {
+ if (name == null) {
+ throw new NullPointerException("illegal null input");
+ }
+
+ this.name = name;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String toString() {
+ return "SamplePrincipal: " + name;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == null) {
+ return false;
+ }
+
+ if (this == o) {
+ return true;
+ }
+
+ if (!(o instanceof SamplePrincipal)) {
+ return false;
+ }
+ SamplePrincipal that = (SamplePrincipal) o;
+
+ return this.getName().equals(that.getName());
+ }
+
+ @Override
+ public int hashCode() {
+ return name.hashCode();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/TestSignatureOidHelper.java Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,124 @@
+/*
+ * 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.
+ */
+
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.util.List;
+
+/*
+ * Utilities for testing the signature algorithm OIDs.
+ */
+public class TestSignatureOidHelper {
+
+ private static final byte[] INPUT = "1234567890".getBytes();
+
+ private final String algorithm;
+
+ private final String provider;
+
+ private final int keySize;
+
+ private final List<OidAlgorithmPair> data;
+
+ public TestSignatureOidHelper(String algorithm, String provider,
+ int keySize, List<OidAlgorithmPair> data) {
+ this.algorithm = algorithm;
+ this.provider = provider;
+ this.keySize = keySize;
+ this.data = data;
+ }
+
+ public void execute() throws Exception {
+ KeyPair keyPair = createKeyPair();
+ for (OidAlgorithmPair oidAlgorithmPair : data) {
+ runTest(oidAlgorithmPair, keyPair);
+ System.out.println("passed");
+ }
+ System.out.println("All tests passed");
+ }
+
+ private KeyPair createKeyPair()
+ throws NoSuchAlgorithmException, NoSuchProviderException {
+ KeyPairGenerator keyGen = KeyPairGenerator.getInstance(algorithm,
+ provider);
+ keyGen.initialize(keySize);
+ return keyGen.generateKeyPair();
+ }
+
+ private void runTest(OidAlgorithmPair oidAlgorithmPair, KeyPair keyPair)
+ throws NoSuchAlgorithmException, NoSuchProviderException,
+ InvalidKeyException, SignatureException {
+ Signature sgAlgorithm =
+ Signature.getInstance(oidAlgorithmPair.algorithm, provider);
+ Signature sgOid = Signature.getInstance(oidAlgorithmPair.oid, provider);
+
+ if (sgAlgorithm == null) {
+ throw new RuntimeException(String.format(
+ "Test failed: algorithm string %s getInstance failed.%n",
+ oidAlgorithmPair.algorithm));
+ }
+
+ if (sgOid == null) {
+ throw new RuntimeException(
+ String.format("Test failed: OID %s getInstance failed.%n",
+ oidAlgorithmPair.oid));
+ }
+
+ if (!sgAlgorithm.getAlgorithm().equals(oidAlgorithmPair.algorithm)) {
+ throw new RuntimeException(String.format(
+ "Test failed: algorithm string %s getInstance "
+ + "doesn't generate expected algorithm.%n",
+ oidAlgorithmPair.algorithm));
+ }
+
+ sgAlgorithm.initSign(keyPair.getPrivate());
+ sgAlgorithm.update(INPUT);
+ sgOid.initVerify(keyPair.getPublic());
+ sgOid.update(INPUT);
+ if (!sgOid.verify(sgAlgorithm.sign())) {
+ throw new RuntimeException(
+ "Signature verification failed unexpectedly");
+ }
+ }
+}
+
+class OidAlgorithmPair {
+
+ public final String oid;
+ public final String algorithm;
+
+ public OidAlgorithmPair(String oid, String algorithm) {
+ this.oid = oid;
+ this.algorithm = algorithm;
+ }
+
+ @Override
+ public String toString() {
+ return "[oid=" + oid + ", algorithm=" + algorithm + "]";
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/ec/NSASuiteB/TestSHAwithECDSASignatureOids.java Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+import java.util.Arrays;
+import java.util.List;
+
+/*
+ * @test
+ * @bug 8075286
+ * @summary Test the SHAwithECDSA signature algorithm OIDs in JDK.
+ * OID and algorithm transformation string should match.
+ * Both could be able to be used to generate the algorithm instance.
+ * @compile ../../TestSignatureOidHelper.java
+ * @run main TestSHAwithECDSASignatureOids
+ */
+public class TestSHAwithECDSASignatureOids {
+
+ private static final List<OidAlgorithmPair> DATA = Arrays.asList(
+ new OidAlgorithmPair("1.2.840.10045.4.1", "SHA1withECDSA"),
+ new OidAlgorithmPair("1.2.840.10045.4.3.1", "SHA224withECDSA"),
+ new OidAlgorithmPair("1.2.840.10045.4.3.2", "SHA256withECDSA"),
+ new OidAlgorithmPair("1.2.840.10045.4.3.3", "SHA384withECDSA"),
+ new OidAlgorithmPair("1.2.840.10045.4.3.4", "SHA512withECDSA"));
+
+ public static void main(String[] args) throws Exception {
+ TestSignatureOidHelper helper = new TestSignatureOidHelper("EC",
+ "SunEC", 256, DATA);
+ helper.execute();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/provider/NSASuiteB/TestDSAGenParameterSpec.java Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,185 @@
+/*
+ * 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.
+ */
+
+import java.security.AlgorithmParameterGenerator;
+import java.security.AlgorithmParameters;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidParameterException;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.spec.DSAGenParameterSpec;
+import java.security.spec.DSAParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+import java.util.Arrays;
+import java.util.List;
+
+/*
+ * @test
+ * @bug 8075286
+ * @summary Verify that DSAGenParameterSpec can and can only be used to generate
+ * DSA within some certain range of key sizes as described in the class
+ * specification (L, N) as (1024, 160), (2048, 224), (2048, 256) and
+ * (3072, 256) should be OK for DSAGenParameterSpec. But the real
+ * implementation SUN doesn't support (3072, 256).
+ * @run main TestDSAGenParameterSpec
+ */
+public class TestDSAGenParameterSpec {
+
+ private static final String ALGORITHM_NAME = "DSA";
+ private static final String PROVIDER_NAME = "SUN";
+
+ private static final List<DataTuple> DATA = Arrays.asList(
+ new DataTuple(1024, 160, true, true),
+ new DataTuple(2048, 224, true, true),
+ new DataTuple(2048, 256, true, true),
+ new DataTuple(3072, 256, true, false),
+ new DataTuple(1024, 224),
+ new DataTuple(2048, 160),
+ new DataTuple(4096, 256),
+ new DataTuple(512, 160),
+ new DataTuple(3072, 224));
+
+ private static void testDSAGenParameterSpec(DataTuple dataTuple)
+ throws NoSuchAlgorithmException, NoSuchProviderException,
+ InvalidParameterSpecException, InvalidAlgorithmParameterException {
+ System.out.printf("Test case: primePLen=%d, " + "subprimeQLen=%d%n",
+ dataTuple.primePLen, dataTuple.subprimeQLen);
+
+ AlgorithmParameterGenerator apg =
+ AlgorithmParameterGenerator.getInstance(ALGORITHM_NAME,
+ PROVIDER_NAME);
+
+ DSAGenParameterSpec genParamSpec = createGenParameterSpec(dataTuple);
+ // genParamSpec will be null if IllegalAE is thrown when expected.
+ if (genParamSpec == null) {
+ return;
+ }
+
+ try {
+ apg.init(genParamSpec, null);
+ AlgorithmParameters param = apg.generateParameters();
+
+ checkParam(param, genParamSpec);
+ System.out.println("Test case passed");
+ } catch (InvalidParameterException ipe) {
+ // The DSAGenParameterSpec API support this, but the real
+ // implementation in SUN doesn't
+ if (!dataTuple.isSunProviderSupported) {
+ System.out.println("Test case passed: expected "
+ + "InvalidParameterException is caught");
+ } else {
+ throw new RuntimeException("Test case failed.", ipe);
+ }
+ }
+ }
+
+ private static void checkParam(AlgorithmParameters param,
+ DSAGenParameterSpec genParam) throws InvalidParameterSpecException,
+ NoSuchAlgorithmException, NoSuchProviderException,
+ InvalidAlgorithmParameterException {
+ String algorithm = param.getAlgorithm();
+ if (!algorithm.equalsIgnoreCase(ALGORITHM_NAME)) {
+ throw new RuntimeException(
+ "Unexpected type of parameters: " + algorithm);
+ }
+
+ DSAParameterSpec spec = param.getParameterSpec(DSAParameterSpec.class);
+ int valueL = spec.getP().bitLength();
+ int strengthP = genParam.getPrimePLength();
+ if (strengthP != valueL) {
+ System.out.printf("P: Expected %d but actual %d%n", strengthP,
+ valueL);
+ throw new RuntimeException("Wrong P strength");
+ }
+
+ int valueN = spec.getQ().bitLength();
+ int strengthQ = genParam.getSubprimeQLength();
+ if (strengthQ != valueN) {
+ System.out.printf("Q: Expected %d but actual %d%n", strengthQ,
+ valueN);
+ throw new RuntimeException("Wrong Q strength");
+ }
+
+ if (genParam.getSubprimeQLength() != genParam.getSeedLength()) {
+ System.out.println("Defaut seed length should be the same as Q.");
+ throw new RuntimeException("Wrong seed length");
+ }
+
+ // use the parameters to generate real DSA keys
+ KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ALGORITHM_NAME,
+ PROVIDER_NAME);
+ keyGen.initialize(spec);
+ keyGen.generateKeyPair();
+ }
+
+ private static DSAGenParameterSpec createGenParameterSpec(
+ DataTuple dataTuple) {
+ DSAGenParameterSpec genParamSpec = null;
+ try {
+ genParamSpec = new DSAGenParameterSpec(dataTuple.primePLen,
+ dataTuple.subprimeQLen);
+ if (!dataTuple.isDSASpecSupported) {
+ throw new RuntimeException(
+ "Test case failed: the key length must not supported");
+ }
+ } catch (IllegalArgumentException e) {
+ if (!dataTuple.isDSASpecSupported) {
+ System.out.println("Test case passed: expected "
+ + "IllegalArgumentException is caught");
+ } else {
+ throw new RuntimeException("Test case failed: unexpected "
+ + "IllegalArgumentException is thrown", e);
+ }
+ }
+
+ return genParamSpec;
+ }
+
+ public static void main(String[] args) throws Exception {
+ for (DataTuple dataTuple : DATA) {
+ testDSAGenParameterSpec(dataTuple);
+ }
+ System.out.println("All tests passed");
+ }
+
+ private static class DataTuple {
+
+ private int primePLen;
+ private int subprimeQLen;
+ private boolean isDSASpecSupported;
+ private boolean isSunProviderSupported;
+
+ private DataTuple(int primePLen, int subprimeQLen,
+ boolean isDSASpecSupported, boolean isSunProviderSupported) {
+ this.primePLen = primePLen;
+ this.subprimeQLen = subprimeQLen;
+ this.isDSASpecSupported = isDSASpecSupported;
+ this.isSunProviderSupported = isSunProviderSupported;
+ }
+
+ private DataTuple(int primePLen, int subprimeQLen) {
+ this(primePLen, subprimeQLen, false, false);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/provider/NSASuiteB/TestSHAOids.java Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,103 @@
+/*
+ * 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.
+ */
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.util.Arrays;
+import java.util.List;
+
+/*
+ * @test
+ * @bug 8075286
+ * @summary Test the SHA algorithm OIDs in JDK.
+ * OID and algorithm transformation string should match.
+ * Both could be able to be used to generate the algorithm instance.
+ * @run main TestSHAOids
+ */
+public class TestSHAOids {
+
+ private static final String PROVIDER_NAME = "SUN";
+ private static final byte[] INPUT = "1234567890".getBytes();
+
+ private static final List<DataTuple> DATA = Arrays.asList(
+ new DataTuple("2.16.840.1.101.3.4.2.1", "SHA-256"),
+ new DataTuple("2.16.840.1.101.3.4.2.2", "SHA-384"),
+ new DataTuple("2.16.840.1.101.3.4.2.3", "SHA-512"),
+ new DataTuple("2.16.840.1.101.3.4.2.4", "SHA-224"));
+
+ public static void main(String[] args) throws Exception {
+ for (DataTuple dataTuple : DATA) {
+ runTest(dataTuple);
+ System.out.println("passed");
+ }
+ System.out.println("All tests passed");
+ }
+
+ private static void runTest(DataTuple dataTuple)
+ throws NoSuchAlgorithmException, NoSuchProviderException {
+ MessageDigest mdAlgorithm = MessageDigest.getInstance(
+ dataTuple.algorithm, PROVIDER_NAME);
+ MessageDigest mdOid = MessageDigest.getInstance(dataTuple.oid,
+ PROVIDER_NAME);
+
+ if (mdAlgorithm == null) {
+ throw new RuntimeException(String.format(
+ "Test failed: algorithm string %s getInstance failed.%n",
+ dataTuple.algorithm));
+ }
+
+ if (mdOid == null) {
+ throw new RuntimeException(
+ String.format("Test failed: OID %s getInstance failed.%n",
+ dataTuple.oid));
+ }
+
+ if (!mdAlgorithm.getAlgorithm().equals(dataTuple.algorithm)) {
+ throw new RuntimeException(String.format(
+ "Test failed: algorithm string %s getInstance doesn't "
+ + "generate expected algorithm.%n",
+ dataTuple.algorithm));
+ }
+
+ mdAlgorithm.update(INPUT);
+ mdOid.update(INPUT);
+
+ // Comparison
+ if (!Arrays.equals(mdAlgorithm.digest(), mdOid.digest())) {
+ throw new RuntimeException("Digest comparison failed: "
+ + "the two digests are not the same");
+ }
+ }
+
+ private static class DataTuple {
+
+ private final String oid;
+ private final String algorithm;
+
+ private DataTuple(String oid, String algorithm) {
+ this.oid = oid;
+ this.algorithm = algorithm;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/provider/NSASuiteB/TestSHAwithDSASignatureOids.java Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+import java.util.Arrays;
+import java.util.List;
+
+/*
+ * @test
+ * @bug 8075286
+ * @summary Test the SHAwithDSA signature algorithm OIDs in JDK.
+ * OID and algorithm transformation string should match.
+ * Both could be able to be used to generate the algorithm instance.
+ * @compile ../../TestSignatureOidHelper.java
+ * @run main TestSHAwithDSASignatureOids
+ */
+public class TestSHAwithDSASignatureOids {
+
+ private static final List<OidAlgorithmPair> DATA = Arrays.asList(
+ new OidAlgorithmPair("2.16.840.1.101.3.4.3.1", "SHA224withDSA"),
+ new OidAlgorithmPair("2.16.840.1.101.3.4.3.2", "SHA256withDSA"));
+
+ public static void main(String[] args) throws Exception {
+ TestSignatureOidHelper helper = new TestSignatureOidHelper("DSA",
+ "SUN", 1024, DATA);
+ helper.execute();
+ }
+}
--- a/make/Init.gmk Sat Sep 26 09:22:24 2015 -0700
+++ b/make/Init.gmk Wed Jul 05 20:51:27 2017 +0200
@@ -50,7 +50,8 @@
include $(topdir)/make/Help.gmk
# Targets provided by Init.gmk.
- ALL_INIT_TARGETS := print-modules print-targets print-configuration reconfigure
+ ALL_INIT_TARGETS := print-modules print-targets print-configuration \
+ reconfigure pre-compare-build post-compare-build
# CALLED_TARGETS is the list of targets that the user provided,
# or "default" if unspecified.
@@ -163,25 +164,39 @@
$(COMMAND_LINE_VARIABLES) $(MAKECMDGOALS))')
endif
+ MAKE_INIT_WITH_SPEC_ARGUMENTS := ACTUAL_TOPDIR=$(topdir) \
+ USER_MAKE_VARS="$(USER_MAKE_VARS)" MAKE_LOG_FLAGS=$(MAKE_LOG_FLAGS) \
+ LOG_LEVEL=$(LOG_LEVEL) LOG_NOFILE=$(LOG_NOFILE) \
+ INIT_TARGETS="$(INIT_TARGETS)" \
+ SEQUENTIAL_TARGETS="$(SEQUENTIAL_TARGETS)" \
+ PARALLEL_TARGETS="$(PARALLEL_TARGETS)"
+
# Now the init and main targets will be called, once for each SPEC. The
# recipe will be run once for every target specified, but we only want to
# execute the recipe a single time, hence the TARGET_DONE with a dummy
# command if true.
+ # The COMPARE_BUILD part implements special support for makefile development.
$(ALL_INIT_TARGETS) $(ALL_MAIN_TARGETS): make-info
@$(if $(TARGET_DONE), \
true \
, \
+ ( cd $(topdir) && \
$(foreach spec, $(SPECS), \
- ( cd $(topdir) && \
$(MAKE) $(MFLAGS) $(MAKE_LOG_FLAGS) -r -R -j 1 -f $(topdir)/make/Init.gmk \
- SPEC=$(spec) HAS_SPEC=true ACTUAL_TOPDIR=$(topdir) \
- USER_MAKE_VARS="$(USER_MAKE_VARS)" MAKE_LOG_FLAGS=$(MAKE_LOG_FLAGS) \
- LOG_LEVEL=$(LOG_LEVEL) LOG_NOFILE=$(LOG_NOFILE) \
- INIT_TARGETS="$(INIT_TARGETS)" \
- SEQUENTIAL_TARGETS="$(SEQUENTIAL_TARGETS)" \
- PARALLEL_TARGETS="$(PARALLEL_TARGETS)" \
- main ) && \
- ) true \
+ SPEC=$(spec) HAS_SPEC=true $(MAKE_INIT_WITH_SPEC_ARGUMENTS) \
+ main && \
+ $(if $(and $(COMPARE_BUILD), $(PARALLEL_TARGETS)), \
+ $(MAKE) $(MFLAGS) $(MAKE_LOG_FLAGS) -r -R -f $(topdir)/make/Init.gmk \
+ SPEC=$(spec) HAS_SPEC=true ACTUAL_TOPDIR=$(topdir) \
+ COMPARE_BUILD="$(COMPARE_BUILD)" pre-compare-build && \
+ $(MAKE) $(MFLAGS) $(MAKE_LOG_FLAGS) -r -R -j 1 -f $(topdir)/make/Init.gmk \
+ SPEC=$(spec) HAS_SPEC=true $(MAKE_INIT_WITH_SPEC_ARGUMENTS) \
+ COMPARE_BUILD="$(COMPARE_BUILD)" main && \
+ $(MAKE) $(MFLAGS) $(MAKE_LOG_FLAGS) -r -R -f $(topdir)/make/Init.gmk \
+ SPEC=$(spec) HAS_SPEC=true ACTUAL_TOPDIR=$(topdir) \
+ COMPARE_BUILD="$(COMPARE_BUILD)" post-compare-build && \
+ ) \
+ ) true ) \
$(eval TARGET_DONE=true) \
)
@@ -205,6 +220,9 @@
# Verify that the spec file we included seems okay.
$(eval $(call CheckSpecSanity))
+ # Parse COMPARE_BUILD (for makefile development)
+ $(eval $(call ParseCompareBuild))
+
ifeq ($(LOG_NOFILE), true)
# Disable log wrapper if LOG=[level,]nofile was given
override BUILD_LOG_WRAPPER :=
@@ -244,7 +262,7 @@
# The main target, for delegating into Main.gmk
##############################################################################
- MAIN_TARGETS := $(SEQUENTIAL_TARGETS) $(PARALLEL_TARGETS)
+ MAIN_TARGETS := $(SEQUENTIAL_TARGETS) $(PARALLEL_TARGETS) $(COMPARE_BUILD_MAKE)
TARGET_DESCRIPTION := target$(if $(word 2, $(MAIN_TARGETS)),s) \
'$(strip $(MAIN_TARGETS))' in configuration '$(CONF_NAME)'
@@ -271,7 +289,7 @@
( cd $(TOPDIR) && \
$(BUILD_LOG_WRAPPER) $(MAKE) $(MAKE_ARGS) $(OUTPUT_SYNC_FLAG) \
-j $(JOBS) -f make/Main.gmk $(USER_MAKE_VARS) \
- $(PARALLEL_TARGETS) || \
+ $(PARALLEL_TARGETS) $(COMPARE_BUILD_MAKE) || \
( exitcode=$$? && $(BUILD_LOG_WRAPPER) \
$(PRINTF) "\nERROR: Build failed for $(TARGET_DESCRIPTION) (exit code $$exitcode) \n" && \
cd $(TOPDIR) && $(MAKE) $(MAKE_ARGS) -j 1 -f make/Init.gmk \
@@ -304,5 +322,30 @@
fi
$(PRINTF) "Hint: If caused by a warning, try configure --disable-warnings-as-errors.\n\n"
+ # Support targets for COMPARE_BUILD, used for makefile development
+ pre-compare-build:
+ $(ECHO) "Preparing for comparison rebuild"
+ # Apply patch, if any
+ ifneq ($(COMPARE_BUILD_PATCH), )
+ $(PATCH) -p1 < $(COMPARE_BUILD_PATCH)
+ endif
+ # Move the first build away and re-create the output directory
+ ( cd $(TOPDIR) && \
+ $(MV) $(OUTPUT_ROOT) $(OUTPUT_ROOT).OLD && \
+ $(MKDIR) -p $(OUTPUT_ROOT) )
+ # Re-run configure with the same arguments (and possibly some additional),
+ # must be done after patching.
+ ( cd $(OUTPUT_ROOT) && PATH="$(ORIGINAL_PATH)" \
+ $(BASH) $(TOPDIR)/configure $(CONFIGURE_COMMAND_LINE) $(COMPARE_BUILD_CONF))
+
+ post-compare-build:
+ # Compare first and second build. Ignore any error code from compare.sh.
+ $(ECHO) "Comparing between comparison rebuild (this/new) and baseline (other/old)"
+ ifneq ($(COMPARE_BUILD_COMP_DIR), )
+ +(cd $(OUTPUT_ROOT) && ./compare.sh $(COMPARE_BUILD_COMP_OPTS) -2dirs $(OUTPUT_ROOT)/$(COMPARE_BUILD_COMP_DIR) $(OUTPUT_ROOT).OLD/$(COMPARE_BUILD_COMP_DIR) || true)
+ else
+ +(cd $(OUTPUT_ROOT) && ./compare.sh $(COMPARE_BUILD_COMP_OPTS) -o $(OUTPUT_ROOT).OLD || true)
+ endif
+
.PHONY: print-targets print-modules reconfigure main on-failure
endif
--- a/make/InitSupport.gmk Sat Sep 26 09:22:24 2015 -0700
+++ b/make/InitSupport.gmk Wed Jul 05 20:51:27 2017 +0200
@@ -40,7 +40,7 @@
##############################################################################
# Make control variables, handled by Init.gmk
- INIT_CONTROL_VARIABLES := LOG CONF SPEC JOBS CONF_CHECK
+ INIT_CONTROL_VARIABLES := LOG CONF SPEC JOBS CONF_CHECK COMPARE_BUILD
# All known make control variables
MAKE_CONTROL_VARIABLES := $(INIT_CONTROL_VARIABLES) TEST JDK_FILTER
@@ -53,12 +53,14 @@
# The variable MAKEOVERRIDES contains variable assignments from the command
# line, but in reverse order to what the user entered.
+ # The '\#' <=> '\ 'dance is needed to keep values with space in them connected.
COMMAND_LINE_VARIABLES := $(subst \#,\ , $(call reverse, $(subst \ ,\#,$(MAKEOVERRIDES))))
# A list like FOO="val1" BAR="val2" containing all user-supplied make
# variables that we should propagate.
- USER_MAKE_VARS := $(filter-out $(addsuffix =%, $(INIT_CONTROL_VARIABLES)), \
- $(MAKEOVERRIDES))
+ # The '\#' <=> '\ 'dance is needed to keep values with space in them connected.
+ USER_MAKE_VARS := $(subst \#,\ , $(filter-out $(addsuffix =%, $(INIT_CONTROL_VARIABLES)), \
+ $(subst \ ,\#,$(MAKEOVERRIDES))))
# Setup information about available configurations, if any.
build_dir=$(topdir)/build
@@ -309,6 +311,59 @@
endif
endef
+ # Parse COMPARE_BUILD into COMPARE_BUILD_*
+ # Syntax: COMPARE_BUILD=CONF=<configure options>:PATCH=<patch file>:
+ # MAKE=<make targets>:COMP_OPTS=<compare script options>:
+ # COMP_DIR=<compare script base dir>|<default>
+ # If neither CONF or PATCH is given, assume <default> means CONF if it
+ # begins with "--", otherwise assume it means PATCH.
+ # MAKE and COMP_OPTS can only be used with CONF and/or PATCH specified.
+ # If any value contains "+", it will be replaced by space.
+ define ParseCompareBuild
+ ifneq ($$(COMPARE_BUILD), )
+ ifneq ($$(findstring :, $$(COMPARE_BUILD)), )
+ $$(foreach part, $$(subst :, , $$(COMPARE_BUILD)), \
+ $$(if $$(filter PATCH=%, $$(part)), \
+ $$(eval COMPARE_BUILD_PATCH=$$(strip $$(patsubst PATCH=%, %, $$(part)))) \
+ ) \
+ $$(if $$(filter CONF=%, $$(part)), \
+ $$(eval COMPARE_BUILD_CONF=$$(strip $$(subst +, , $$(patsubst CONF=%, %, $$(part))))) \
+ ) \
+ $$(if $$(filter MAKE=%, $$(part)), \
+ $$(eval COMPARE_BUILD_MAKE=$$(strip $$(subst +, , $$(patsubst MAKE=%, %, $$(part))))) \
+ ) \
+ $$(if $$(filter COMP_OPTS=%, $$(part)), \
+ $$(eval COMPARE_BUILD_COMP_OPTS=$$(strip $$(subst +, , $$(patsubst COMP_OPTS=%, %, $$(part))))) \
+ ) \
+ $$(if $$(filter COMP_DIR=%, $$(part)), \
+ $$(eval COMPARE_BUILD_COMP_DIR=$$(strip $$(subst +, , $$(patsubst COMP_DIR=%, %, $$(part))))) \
+ ) \
+ )
+ else
+ # Separate handling for single field case, to allow for spaces in values.
+ ifneq ($$(filter PATCH=%, $$(COMPARE_BUILD)), )
+ COMPARE_BUILD_PATCH=$$(strip $$(patsubst PATCH=%, %, $$(COMPARE_BUILD)))
+ else ifneq ($$(filter CONF=%, $$(COMPARE_BUILD)), )
+ COMPARE_BUILD_CONF=$$(strip $$(subst +, , $$(patsubst CONF=%, %, $$(COMPARE_BUILD))))
+ else ifneq ($$(filter --%, $$(COMPARE_BUILD)), )
+ # Assume CONF if value begins with --
+ COMPARE_BUILD_CONF=$$(strip $$(subst +, , $$(COMPARE_BUILD)))
+ else
+ # Otherwise assume patch file
+ COMPARE_BUILD_PATCH=$$(strip $$(COMPARE_BUILD))
+ endif
+ endif
+ ifneq ($$(COMPARE_BUILD_PATCH), )
+ ifneq ($$(wildcard $$(TOPDIR)/$$(COMPARE_BUILD_PATCH)), )
+ # Assume relative path, if file exists
+ COMPARE_BUILD_PATCH := $$(wildcard $$(TOPDIR)/$$(COMPARE_BUILD_PATCH))
+ else ifeq ($$(wildcard $$(COMPARE_BUILD_PATCH)), )
+ $$(error Patch file $$(COMPARE_BUILD_PATCH) does not exist)
+ endif
+ endif
+ endif
+ endef
+
define RotateLogFiles
$(RM) $(BUILD_LOG).old 2> /dev/null
$(MV) $(BUILD_LOG) $(BUILD_LOG).old 2> /dev/null || true
--- a/make/common/JavaCompilation.gmk Sat Sep 26 09:22:24 2015 -0700
+++ b/make/common/JavaCompilation.gmk Wed Jul 05 20:51:27 2017 +0200
@@ -155,6 +155,7 @@
# When this macro is run in the same makefile as the java compilation, dependencies are
# transfered in make variables. When the macro is run in a different makefile than the
# java compilation, the dependencies need to be found in the filesystem.
+ $1_ORIG_DEPS := $$($1_DEPENDENCIES)
ifeq ($$($1_DEPENDENCIES), )
# Add all source roots to the find cache since we are likely going to run find
# on these more than once. The cache will only be updated if necessary.
@@ -266,7 +267,8 @@
# Include all variables of significance in the vardeps file
$1_VARDEPS := $(JAR) $$($1_JAR_CREATE_OPTIONS) $$($1_MANIFEST) \
- $$($1_JARMAIN) $$($1_EXTRA_MANIFEST_ATTR)
+ $$($1_JARMAIN) $$($1_EXTRA_MANIFEST_ATTR) $$($1_ORIG_DEPS) $$($1_SRCS) \
+ $$($1_INCLUDES) $$($1_EXCLUDES) $$($1_EXCLUDE_FILES) $$($1_EXTRA_FILES)
$1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, $$(dir $$($1_JAR))_the.$$($1_JARNAME).vardeps)
# Here is the rule that creates/updates the jar file.
@@ -280,7 +282,7 @@
# potential changes.
$$(if $$(filter $$($1_VARDEPS_FILE) $$($1_MANIFEST), $$?), \
$$(if $$($1_MANIFEST), \
- $(CP) $$($1_MANIFEST) $$($1_MANIFEST_FILE) $$(NEWLINE) \
+ $(SED) -e '$(DOLLAR)$(DOLLAR)a\' $$($1_MANIFEST) > $$($1_MANIFEST_FILE) $$(NEWLINE) \
, \
$(RM) $$($1_MANIFEST_FILE) && $(TOUCH) $$($1_MANIFEST_FILE) $$(NEWLINE)) \
$$(if $$($1_JARMAIN), \
@@ -417,6 +419,7 @@
# HEADERS:=path to directory where all generated c-headers are written.
# DEPENDS:=Extra dependecy
# DISABLE_SJAVAC:=Explicitly disable the use of sjavac for this compilation unit.
+# KEEP_DUPS:=Do not remove duplicate file names from different source roots.
SetupJavaCompilation = $(NamedParamsMacroTemplate)
define SetupJavaCompilationBody
@@ -469,19 +472,27 @@
$1_SRCS := $$(filter-out $$($1_SRC_EXCLUDES),$$($1_SRCS))
endif
- # Remove duplicate source files by keeping the first found of each duplicate.
- # This allows for automatic overrides with custom or platform specific versions
- # source files.
- #
- # For the smart javac wrapper case, add each removed file to an extra exclude
- # file list to prevent sjavac from finding duplicate sources.
- $1_SRCS := $$(strip $$(foreach s, $$($1_SRCS), \
- $$(eval relative_src := $$(call remove-prefixes, $$($1_SRC), $$(s))) \
- $$(if $$($1_$$(relative_src)), \
- $$(eval $1_SJAVAC_EXCLUDE_FILES += $$(s)), \
- $$(eval $1_$$(relative_src) := 1) $$(s))))
+ ifneq ($$($1_KEEP_DUPS), true)
+ # Remove duplicate source files by keeping the first found of each duplicate.
+ # This allows for automatic overrides with custom or platform specific versions
+ # source files.
+ #
+ # For the smart javac wrapper case, add each removed file to an extra exclude
+ # file list to prevent sjavac from finding duplicate sources.
+ $1_SRCS := $$(strip $$(foreach s, $$($1_SRCS), \
+ $$(eval relative_src := $$(call remove-prefixes, $$($1_SRC), $$(s))) \
+ $$(if $$($1_$$(relative_src)), \
+ $$(eval $1_SJAVAC_EXCLUDE_FILES += $$(s)), \
+ $$(eval $1_$$(relative_src) := 1) $$(s))))
+ endif
- # Create the corresponding smart javac wrapper command line.
+ ifeq ($$(strip $$($1_SRCS)), )
+ $$(error No source files found for $1)
+ endif
+
+ $1_SAFE_NAME := $$(strip $$(subst /,_, $1))
+
+ # Create the corresponding smart javac wrapper command line.
$1_SJAVAC_ARGS:=$$(addprefix -x ,$$(addsuffix /*,$$($1_EXCLUDES))) \
$$(addprefix -i ,$$(addsuffix /*,$$($1_INCLUDES))) \
$$(addprefix -xf *,$$(strip $$($1_EXCLUDE_FILES) $$($1_SJAVAC_EXCLUDE_FILES))) \
@@ -560,14 +571,15 @@
$$(SPACE),%20,$$(subst $$(COMMA),%2C,$$(strip $$($1_SERVER_JVM) $$($1_SJAVAC))))
$1_VARDEPS := $$($1_JVM) $$($1_SJAVAC) $$($1_SJAVAC_ARGS) $$($1_FLAGS) \
- $$($1_HEADERS_ARG) $$($1_BIN)
+ $$($1_HEADERS_ARG) $$($1_BIN) $$($1_EXCLUDES) $$($1_INCLUDES) \
+ $$($1_EXCLUDE_FILES) $$($1_INCLUDE_FILES)
$1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, $$($1_BIN)/_the.$1.vardeps)
$$($1_BIN)/_the.$1_batch: $$($1_SRCS) $$($1_DEPENDS) $$($1_VARDEPS_FILE)
$(MKDIR) -p $$(@D) $$(dir $$($1_SJAVAC_PORTFILE))
$$(call ListPathsSafely,$1_SRCS,\n, >> $$($1_BIN)/_the.$1_batch.tmp)
$(ECHO) Compiling $1
- $(call LogFailures, $$($1_BIN)/_the.$1_batch.log, $1, \
+ $(call LogFailures, $$($1_BIN)/_the.$$($1_SAFE_NAME)_batch.log, $$($1_SAFE_NAME), \
$$($1_JVM) $$($1_SJAVAC) \
$$($1_REMOTE) \
-j 1 \
@@ -575,6 +587,7 @@
--permit-sources-without-package \
--compare-found-sources $$($1_BIN)/_the.$1_batch.tmp \
--log=$(LOG_LEVEL) \
+ --state-dir=$$($1_BIN) \
$$($1_SJAVAC_ARGS) \
$$($1_FLAGS) \
$$($1_HEADERS_ARG) \
@@ -615,7 +628,9 @@
$1_HEADER_TARGETS := $$($1_HEADERS)/_the.$1_headers
endif
- $1_VARDEPS := $$($1_JVM) $$($1_JAVAC) $$($1_FLAGS) $$($1_BIN) $$($1_HEADERS_ARG)
+ $1_VARDEPS := $$($1_JVM) $$($1_JAVAC) $$($1_FLAGS) $$($1_BIN) \
+ $$($1_HEADERS_ARG) $$($1_EXCLUDES) $$($1_INCLUDES) \
+ $$($1_EXCLUDE_FILES) $$($1_INCLUDE_FILES)
$1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, $$($1_BIN)/_the.$1.vardeps)
# When not using sjavac, pass along all sources to javac using an @file.
@@ -624,7 +639,7 @@
$(RM) $$($1_BIN)/_the.$1_batch $$($1_BIN)/_the.$1_batch.tmp
$$(call ListPathsSafely,$1_SRCS,\n, >> $$($1_BIN)/_the.$1_batch.tmp)
$(ECHO) Compiling `$(WC) $$($1_BIN)/_the.$1_batch.tmp | $(TR) -s ' ' | $(CUT) -f 2 -d ' '` files for $1
- $(call LogFailures, $$($1_BIN)/_the.$1_batch.log, $1, \
+ $(call LogFailures, $$($1_BIN)/_the.$$($1_SAFE_NAME)_batch.log, $$($1_SAFE_NAME), \
$$($1_JVM) $$($1_JAVAC) $$($1_FLAGS) \
-implicit:none \
-d $$($1_BIN) $$($1_HEADERS_ARG) @$$($1_BIN)/_the.$1_batch.tmp) && \
--- a/make/common/NativeCompilation.gmk Sat Sep 26 09:22:24 2015 -0700
+++ b/make/common/NativeCompilation.gmk Wed Jul 05 20:51:27 2017 +0200
@@ -204,18 +204,18 @@
ifeq ($(TOOLCHAIN_TYPE)$$(filter %.s,$2), solstudio)
# The Solaris studio compiler doesn't output the full path to the object file in the
# generated deps files. Fixing it with sed. If compiling assembly, don't try this.
- $(call LogFailures, $$($1_$2_OBJ).log, $1_$$(notdir $2), \
+ $(call LogFailures, $$($1_$2_OBJ).log, $$($1_SAFE_NAME)_$$(notdir $2), \
$$($1_$2_COMP) $$($1_$2_FLAGS) $$($1_$2_DEP_FLAG) $$($1_$2_DEP).tmp $(CC_OUT_OPTION)$$($1_$2_OBJ) $2)
$(SED) 's|^$$(@F):|$$@:|' $$($1_$2_DEP).tmp > $$($1_$2_DEP)
else
- $(call LogFailures, $$($1_$2_OBJ).log, $1_$$(notdir $2), \
+ $(call LogFailures, $$($1_$2_OBJ).log, $$($1_SAFE_NAME)_$$(notdir $2), \
$$($1_$2_COMP) $$($1_$2_FLAGS) $$($1_$2_DEP_FLAG) $$($1_$2_DEP) $(CC_OUT_OPTION)$$($1_$2_OBJ) $2)
endif
else
# The Visual Studio compiler lacks a feature for generating make dependencies, but by
# setting -showIncludes, all included files are printed. These are filtered out and
# parsed into make dependences.
- ($(call LogFailures, $$($1_$2_OBJ).log, $1_$$(notdir $2), \
+ ($(call LogFailures, $$($1_$2_OBJ).log, $$($1_SAFE_NAME)_$$(notdir $2), \
$$($1_$2_COMP) $$($1_$2_FLAGS) -showIncludes $$($1_$2_DEBUG_OUT_FLAGS) \
$(CC_OUT_OPTION)$$($1_$2_OBJ) $2) ; echo $$$$? > $$($1_$2_DEP).exitvalue) \
| $(TEE) $$($1_$2_DEP).raw | $(GREP) -v -e "^Note: including file:" \
@@ -353,6 +353,7 @@
$1_TARGET:=$$($1_OUTPUT_DIR)/$$($1_BASENAME)
$1_NOSUFFIX:=$$($1_PROGRAM)
endif
+ $1_SAFE_NAME := $$(strip $$(subst /,_, $1))
ifeq (,$$($1_TARGET))
$$(error Neither PROGRAM, LIBRARY nor STATIC_LIBRARY has been specified for SetupNativeCompilation)
@@ -414,6 +415,10 @@
$1_SRCS += $$($1_EXTRA_FILES)
+ ifeq (,$$($1_SRCS))
+ $$(error No sources found for $1 when looking inside the dirs $$($1_SRC))
+ endif
+
# Calculate the expected output from compiling the sources (sort to remove duplicates. Also provides
# a reproducable order on the input files to the linker).
$1_EXPECTED_OBJS_FILENAMES := $$(call replace_with_obj_extension, $$(notdir $$($1_SRCS)))
@@ -549,8 +554,8 @@
else
$(ECHO) $$(strip 'Updating $$($1_BASENAME)' \
$$(if $$(filter-out %.vardeps, $$?), \
- 'from $$(words $$(filter-out %.vardeps, $$?)) file(s)') \
- $$(if $$(filter %.vardeps, $$?), 'due to makefile changes'))
+ 'due to $$(words $$(filter-out %.vardeps, $$?)) file(s)', \
+ $$(if $$(filter %.vardeps, $$?), 'due to makefile changes')))
endif
$(TOUCH) $$@
@@ -674,7 +679,7 @@
$$($1_TARGET): $$($1_EXPECTED_OBJS) $$($1_RES) $$($1_REAL_MAPFILE) \
$$($1_VARDEPS_FILE)
$(ECHO) $(LOG_INFO) "Linking $$($1_BASENAME)"
- $(call LogFailures, $$($1_OBJECT_DIR)/$1_link.log, $1_link, \
+ $(call LogFailures, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_link.log, $$($1_SAFE_NAME)_link, \
$$($1_LD) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) $$($1_SYSROOT_LDFLAGS) \
$(LD_OUT_OPTION)$$@ \
$$($1_EXPECTED_OBJS) $$($1_RES) \
@@ -697,7 +702,7 @@
# Generating a static library, ie object file archive.
$$($1_TARGET): $$($1_EXPECTED_OBJS) $$($1_RES) $$($1_VARDEPS_FILE)
$(ECHO) $(LOG_INFO) "Archiving $$($1_STATIC_LIBRARY)"
- $(call LogFailures, $$($1_OBJECT_DIR)/$1_link.log, $1_link, \
+ $(call LogFailures, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_link.log, $$($1_SAFE_NAME)_link, \
$$($1_AR) $$($1_ARFLAGS) $(AR_OUT_OPTION)$$($1_TARGET) $$($1_EXPECTED_OBJS) \
$$($1_RES) $$($1_LDFLAGS_SUFFIX) $$($1_EXTRA_LDFLAGS_SUFFIX))
endif
@@ -715,7 +720,7 @@
$$($1_TARGET): $$($1_EXPECTED_OBJS) $$($1_RES) $$($1_MANIFEST) \
$$($1_VARDEPS_FILE)
$(ECHO) $(LOG_INFO) "Linking executable $$($1_BASENAME)"
- $(call LogFailures, $$($1_OBJECT_DIR)/$1_link.log, $1_link, \
+ $(call LogFailures, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_link.log, $$($1_SAFE_NAME)_link, \
$$($1_LD) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) $$($1_SYSROOT_LDFLAGS) \
$(EXE_OUT_OPTION)$$($1_TARGET) \
$$($1_EXPECTED_OBJS) $$($1_RES) \
--- a/nashorn/.hgtags Sat Sep 26 09:22:24 2015 -0700
+++ b/nashorn/.hgtags Wed Jul 05 20:51:27 2017 +0200
@@ -316,3 +316,4 @@
61b401b23fc28208930977d46b690423911173c6 jdk9-b80
42d8ed4651b62572b39e6fed3fafcb7ee93f9dc2 jdk9-b81
8bab0a9d8a638affdd680c5ec783373f71c19267 jdk9-b82
+21b86b980a5f0d27f1f758a3e4818d3331387172 jdk9-b83
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java Sat Sep 26 09:22:24 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java Wed Jul 05 20:51:27 2017 +0200
@@ -70,11 +70,10 @@
import jdk.nashorn.internal.ir.LexicalContext;
import jdk.nashorn.internal.ir.LexicalContextNode;
import jdk.nashorn.internal.ir.LiteralNode;
-import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
-import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit;
import jdk.nashorn.internal.ir.Node;
import jdk.nashorn.internal.ir.RuntimeNode;
import jdk.nashorn.internal.ir.RuntimeNode.Request;
+import jdk.nashorn.internal.ir.Splittable;
import jdk.nashorn.internal.ir.Statement;
import jdk.nashorn.internal.ir.SwitchNode;
import jdk.nashorn.internal.ir.Symbol;
@@ -984,7 +983,7 @@
boolean previousWasBlock = false;
for (final Iterator<LexicalContextNode> it = lc.getAllNodes(); it.hasNext();) {
final LexicalContextNode node = it.next();
- if (node instanceof FunctionNode || isSplitArray(node)) {
+ if (node instanceof FunctionNode || isSplitLiteral(node)) {
// We reached the function boundary or a splitting boundary without seeing a definition for the symbol.
// It needs to be in scope.
return true;
@@ -1010,12 +1009,8 @@
throw new AssertionError();
}
- private static boolean isSplitArray(final LexicalContextNode expr) {
- if(!(expr instanceof ArrayLiteralNode)) {
- return false;
- }
- final List<ArrayUnit> units = ((ArrayLiteralNode)expr).getUnits();
- return !(units == null || units.isEmpty());
+ private static boolean isSplitLiteral(final LexicalContextNode expr) {
+ return expr instanceof Splittable && ((Splittable) expr).getSplitRanges() != null;
}
private void throwUnprotectedSwitchError(final VarNode varNode) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java Sat Sep 26 09:22:24 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java Wed Jul 05 20:51:27 2017 +0200
@@ -105,7 +105,6 @@
import jdk.nashorn.internal.ir.LexicalContextNode;
import jdk.nashorn.internal.ir.LiteralNode;
import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
-import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit;
import jdk.nashorn.internal.ir.LiteralNode.PrimitiveLiteralNode;
import jdk.nashorn.internal.ir.LocalVariableConversion;
import jdk.nashorn.internal.ir.LoopNode;
@@ -118,6 +117,7 @@
import jdk.nashorn.internal.ir.RuntimeNode.Request;
import jdk.nashorn.internal.ir.SetSplitState;
import jdk.nashorn.internal.ir.SplitReturn;
+import jdk.nashorn.internal.ir.Splittable;
import jdk.nashorn.internal.ir.Statement;
import jdk.nashorn.internal.ir.SwitchNode;
import jdk.nashorn.internal.ir.Symbol;
@@ -242,7 +242,7 @@
private final DebugLogger log;
/** From what size should we use spill instead of fields for JavaScript objects? */
- private static final int OBJECT_SPILL_THRESHOLD = Options.getIntProperty("nashorn.spill.threshold", 256);
+ static final int OBJECT_SPILL_THRESHOLD = Options.getIntProperty("nashorn.spill.threshold", 256);
private final Set<String> emittedMethods = new HashSet<>();
@@ -1634,7 +1634,7 @@
@Override
void consumeStack() {
- dynamicCall(2 + argsCount, getCallSiteFlags(), origCallee.getName());
+ dynamicCall(2 + argsCount, getCallSiteFlags(), null);
}
}.emit();
return false;
@@ -2234,73 +2234,33 @@
*
* @param arrayLiteralNode the array of contents
* @param arrayType the type of the array, e.g. ARRAY_NUMBER or ARRAY_OBJECT
- *
- * @return the method generator that was used
*/
- private MethodEmitter loadArray(final ArrayLiteralNode arrayLiteralNode, final ArrayType arrayType) {
+ private void loadArray(final ArrayLiteralNode arrayLiteralNode, final ArrayType arrayType) {
assert arrayType == Type.INT_ARRAY || arrayType == Type.LONG_ARRAY || arrayType == Type.NUMBER_ARRAY || arrayType == Type.OBJECT_ARRAY;
- final Expression[] nodes = arrayLiteralNode.getValue();
- final Object presets = arrayLiteralNode.getPresets();
- final int[] postsets = arrayLiteralNode.getPostsets();
- final Class<?> type = arrayType.getTypeClass();
- final List<ArrayUnit> units = arrayLiteralNode.getUnits();
+ final Expression[] nodes = arrayLiteralNode.getValue();
+ final Object presets = arrayLiteralNode.getPresets();
+ final int[] postsets = arrayLiteralNode.getPostsets();
+ final List<Splittable.SplitRange> ranges = arrayLiteralNode.getSplitRanges();
loadConstant(presets);
final Type elementType = arrayType.getElementType();
- if (units != null) {
- final MethodEmitter savedMethod = method;
- final FunctionNode currentFunction = lc.getCurrentFunction();
-
- for (final ArrayUnit arrayUnit : units) {
- unit = lc.pushCompileUnit(arrayUnit.getCompileUnit());
-
- final String className = unit.getUnitClassName();
- assert unit != null;
- final String name = currentFunction.uniqueName(SPLIT_PREFIX.symbolName());
- final String signature = methodDescriptor(type, ScriptFunction.class, Object.class, ScriptObject.class, type);
-
- pushMethodEmitter(unit.getClassEmitter().method(EnumSet.of(Flag.PUBLIC, Flag.STATIC), name, signature));
-
- method.setFunctionNode(currentFunction);
- method.begin();
-
- defineCommonSplitMethodParameters();
- defineSplitMethodParameter(CompilerConstants.SPLIT_ARRAY_ARG.slot(), arrayType);
-
- // NOTE: when this is no longer needed, SplitIntoFunctions will no longer have to add IS_SPLIT
- // to synthetic functions, and FunctionNode.needsCallee() will no longer need to test for isSplit().
- final int arraySlot = fixScopeSlot(currentFunction, 3);
-
- lc.enterSplitNode();
-
- for (int i = arrayUnit.getLo(); i < arrayUnit.getHi(); i++) {
- method.load(arrayType, arraySlot);
- storeElement(nodes, elementType, postsets[i]);
+ if (ranges != null) {
+
+ loadSplitLiteral(new SplitLiteralCreator() {
+ @Override
+ public void populateRange(final MethodEmitter method, final Type type, final int slot, final int start, final int end) {
+ for (int i = start; i < end; i++) {
+ method.load(type, slot);
+ storeElement(nodes, elementType, postsets[i]);
+ }
+ method.load(type, slot);
}
-
- method.load(arrayType, arraySlot);
- method._return();
- lc.exitSplitNode();
- method.end();
- lc.releaseSlots();
- popMethodEmitter();
-
- assert method == savedMethod;
- method.loadCompilerConstant(CALLEE);
- method.swap();
- method.loadCompilerConstant(THIS);
- method.swap();
- method.loadCompilerConstant(SCOPE);
- method.swap();
- method.invokestatic(className, name, signature);
-
- unit = lc.popCompileUnit(unit);
- }
-
- return method;
+ }, ranges, arrayType);
+
+ return;
}
if(postsets.length > 0) {
@@ -2312,7 +2272,6 @@
}
method.load(arrayType, arraySlot);
}
- return method;
}
private void storeElement(final Expression[] nodes, final Type elementType, final int index) {
@@ -2537,6 +2496,7 @@
final List<MapTuple<Expression>> tuples = new ArrayList<>();
final List<PropertyNode> gettersSetters = new ArrayList<>();
final int ccp = getCurrentContinuationEntryPoint();
+ final List<Splittable.SplitRange> ranges = objectNode.getSplitRanges();
Expression protoNode = null;
boolean restOfProperty = false;
@@ -2583,7 +2543,13 @@
loadExpressionAsType(node, type);
}};
}
- oc.makeObject(method);
+
+ if (ranges != null) {
+ oc.createObject(method);
+ loadSplitLiteral(oc, ranges, Type.typeFor(oc.getAllocatorClass()));
+ } else {
+ oc.makeObject(method);
+ }
//if this is a rest of method and our continuation point was found as one of the values
//in the properties above, we need to reset the map to oc.getMap() in the continuation
@@ -2899,6 +2865,54 @@
method.onLocalStore(type, slot);
}
+ private void loadSplitLiteral(final SplitLiteralCreator creator, final List<Splittable.SplitRange> ranges, final Type literalType) {
+ assert ranges != null;
+
+ // final Type literalType = Type.typeFor(literalClass);
+ final MethodEmitter savedMethod = method;
+ final FunctionNode currentFunction = lc.getCurrentFunction();
+
+ for (final Splittable.SplitRange splitRange : ranges) {
+ unit = lc.pushCompileUnit(splitRange.getCompileUnit());
+
+ assert unit != null;
+ final String className = unit.getUnitClassName();
+ final String name = currentFunction.uniqueName(SPLIT_PREFIX.symbolName());
+ final Class<?> clazz = literalType.getTypeClass();
+ final String signature = methodDescriptor(clazz, ScriptFunction.class, Object.class, ScriptObject.class, clazz);
+
+ pushMethodEmitter(unit.getClassEmitter().method(EnumSet.of(Flag.PUBLIC, Flag.STATIC), name, signature));
+
+ method.setFunctionNode(currentFunction);
+ method.begin();
+
+ defineCommonSplitMethodParameters();
+ defineSplitMethodParameter(CompilerConstants.SPLIT_ARRAY_ARG.slot(), literalType);
+
+ // NOTE: when this is no longer needed, SplitIntoFunctions will no longer have to add IS_SPLIT
+ // to synthetic functions, and FunctionNode.needsCallee() will no longer need to test for isSplit().
+ final int literalSlot = fixScopeSlot(currentFunction, 3);
+
+ lc.enterSplitNode();
+
+ creator.populateRange(method, literalType, literalSlot, splitRange.getLow(), splitRange.getHigh());
+
+ method._return();
+ lc.exitSplitNode();
+ method.end();
+ lc.releaseSlots();
+ popMethodEmitter();
+
+ assert method == savedMethod;
+ method.loadCompilerConstant(CALLEE).swap();
+ method.loadCompilerConstant(THIS).swap();
+ method.loadCompilerConstant(SCOPE).swap();
+ method.invokestatic(className, name, signature);
+
+ unit = lc.popCompileUnit(unit);
+ }
+ }
+
private int fixScopeSlot(final FunctionNode functionNode, final int extraSlot) {
// TODO hack to move the scope to the expected slot (needed because split methods reuse the same slots as the root method)
final int actualScopeSlot = functionNode.compilerConstant(SCOPE).getSlot(SCOPE_TYPE);
@@ -5461,4 +5475,21 @@
method.uncheckedGoto(targetCatchLabel);
}
}
+
+ /**
+ * Interface implemented by object creators that support splitting over multiple methods.
+ */
+ interface SplitLiteralCreator {
+ /**
+ * Generate code to populate a range of the literal object. A reference to the object
+ * should be left on the stack when the method terminates.
+ *
+ * @param method the method emitter
+ * @param type the type of the literal object
+ * @param slot the local slot containing the literal object
+ * @param start the start index (inclusive)
+ * @param end the end index (exclusive)
+ */
+ void populateRange(MethodEmitter method, Type type, int slot, int start, int end);
+ }
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/FieldObjectCreator.java Sat Sep 26 09:22:24 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/FieldObjectCreator.java Wed Jul 05 20:51:27 2017 +0200
@@ -34,7 +34,6 @@
import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndex;
import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
-import java.util.Iterator;
import java.util.List;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.Symbol;
@@ -91,27 +90,20 @@
findClass();
}
- /**
- * Construct an object.
- *
- * @param method the method emitter
- */
@Override
- protected void makeObject(final MethodEmitter method) {
+ public void createObject(final MethodEmitter method) {
makeMap();
final String className = getClassName();
- try {
- // NOTE: we must load the actual structure class here, because the API operates with Nashorn Type objects,
- // and Type objects need a loaded class, for better or worse. We also have to be specific and use the type
- // of the actual structure class, we can't generalize it to e.g. Type.typeFor(ScriptObject.class) as the
- // exact type information is needed for generating continuations in rest-of methods. If we didn't do this,
- // object initializers like { x: arr[i] } would fail during deoptimizing compilation on arr[i], as the
- // values restored from the RewriteException would be cast to "ScriptObject" instead of to e.g. "JO4", and
- // subsequently the "PUTFIELD J04.L0" instruction in the continuation code would fail bytecode verification.
- method._new(Context.forStructureClass(className.replace('/', '.'))).dup();
- } catch (final ClassNotFoundException e) {
- throw new AssertionError(e);
- }
+ // NOTE: we must load the actual structure class here, because the API operates with Nashorn Type objects,
+ // and Type objects need a loaded class, for better or worse. We also have to be specific and use the type
+ // of the actual structure class, we can't generalize it to e.g. Type.typeFor(ScriptObject.class) as the
+ // exact type information is needed for generating continuations in rest-of methods. If we didn't do this,
+ // object initializers like { x: arr[i] } would fail during deoptimizing compilation on arr[i], as the
+ // values restored from the RewriteException would be cast to "ScriptObject" instead of to e.g. "JO4", and
+ // subsequently the "PUTFIELD J04.L0" instruction in the continuation code would fail bytecode verification.
+ assert fieldObjectClass != null;
+ method._new(fieldObjectClass).dup();
+
loadMap(method); //load the map
if (isScope()) {
@@ -126,14 +118,14 @@
} else {
method.invoke(constructorNoLookup(className, PropertyMap.class));
}
+ }
- helpOptimisticRecognizeDuplicateIdentity(method);
-
+ @Override
+ public void populateRange(final MethodEmitter method, final Type objectType, final int objectSlot, final int start, final int end) {
+ method.load(objectType, objectSlot);
// Set values.
- final Iterator<MapTuple<T>> iter = tuples.iterator();
-
- while (iter.hasNext()) {
- final MapTuple<T> tuple = iter.next();
+ for (int i = start; i < end; i++) {
+ final MapTuple<T> tuple = tuples.get(i);
//we only load when we have both symbols and values (which can be == the symbol)
//if we didn't load, we need an array property
if (tuple.symbol != null && tuple.value != null) {
@@ -212,6 +204,11 @@
}
}
+ @Override
+ protected Class<? extends ScriptObject> getAllocatorClass() {
+ return fieldObjectClass;
+ }
+
/**
* Get the class name for the object class,
* e.g. {@code com.nashorn.oracle.scripts.JO2P0}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/FindScopeDepths.java Sat Sep 26 09:22:24 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/FindScopeDepths.java Wed Jul 05 20:51:27 2017 +0200
@@ -275,15 +275,11 @@
final Set<Symbol> symbols = new HashSet<>();
block.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
@Override
- public final boolean enterDefault(final Node node) {
- if (!compiler.isOnDemandCompilation()) {
- if (node instanceof IdentNode) {
- final Symbol symbol = ((IdentNode)node).getSymbol();
- if (symbol != null && symbol.isScope()) {
- //if this is an internal symbol, skip it.
- symbols.add(symbol);
- }
- }
+ public boolean enterIdentNode(final IdentNode identNode) {
+ final Symbol symbol = identNode.getSymbol();
+ if (symbol != null && symbol.isScope()) {
+ //if this is an internal symbol, skip it.
+ symbols.add(symbol);
}
return true;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/FoldConstants.java Sat Sep 26 09:22:24 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/FoldConstants.java Wed Jul 05 20:51:27 2017 +0200
@@ -116,7 +116,7 @@
statements.addAll(executed.getStatements()); // Get statements form executed branch
}
if (dropped != null) {
- extractVarNodes(dropped, statements); // Get var-nodes from non-executed branch
+ extractVarNodesFromDeadCode(dropped, statements); // Get var-nodes from non-executed branch
}
if (statements.isEmpty()) {
return new EmptyNode(ifNode);
@@ -185,14 +185,27 @@
protected abstract LiteralNode<?> eval();
}
- private static void extractVarNodes(final Block block, final List<Statement> statements) {
- final LexicalContext lc = new LexicalContext();
- block.accept(lc, new NodeVisitor<LexicalContext>(lc) {
+ /**
+ * When we eliminate dead code, we must preserve var declarations as they are scoped to the whole
+ * function. This method gathers var nodes from code passed to it, removing their initializers.
+ *
+ * @param deadCodeRoot the root node of eliminated dead code
+ * @param statements a list that will be receiving the var nodes from the dead code, with their
+ * initializers removed.
+ */
+ static void extractVarNodesFromDeadCode(final Node deadCodeRoot, final List<Statement> statements) {
+ deadCodeRoot.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
@Override
public boolean enterVarNode(final VarNode varNode) {
statements.add(varNode.setInit(null));
return false;
}
+
+ @Override
+ public boolean enterFunctionNode(final FunctionNode functionNode) {
+ // Don't descend into nested functions
+ return false;
+ }
});
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Lower.java Sat Sep 26 09:22:24 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Lower.java Wed Jul 05 20:51:27 2017 +0200
@@ -121,13 +121,7 @@
terminated = true;
}
} else {
- statement.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
- @Override
- public boolean enterVarNode(final VarNode varNode) {
- newStatements.add(varNode.setInit(null));
- return false;
- }
- });
+ FoldConstants.extractVarNodesFromDeadCode(statement, newStatements);
}
}
return newStatements;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MethodEmitter.java Sat Sep 26 09:22:24 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MethodEmitter.java Wed Jul 05 20:51:27 2017 +0200
@@ -257,8 +257,7 @@
*/
private Type popType(final Type expected) {
final Type type = popType();
- assert type.isObject() && expected.isObject() ||
- type.isEquivalentTo(expected) : type + " is not compatible with " + expected;
+ assert type.isEquivalentTo(expected) : type + " is not compatible with " + expected;
return type;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ObjectCreator.java Sat Sep 26 09:22:24 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ObjectCreator.java Wed Jul 05 20:51:27 2017 +0200
@@ -36,7 +36,7 @@
* Base class for object creation code generation.
* @param <T> value type
*/
-public abstract class ObjectCreator<T> {
+public abstract class ObjectCreator<T> implements CodeGenerator.SplitLiteralCreator {
/** List of keys & symbols to initiate in this ObjectCreator */
final List<MapTuple<T>> tuples;
@@ -69,7 +69,23 @@
* Generate code for making the object.
* @param method Script method.
*/
- protected abstract void makeObject(final MethodEmitter method);
+ public void makeObject(final MethodEmitter method) {
+ createObject(method);
+ // We need to store the object in a temporary slot as populateRange expects to load the
+ // object from a slot (as it is also invoked within split methods). Note that this also
+ // helps optimistic continuations to handle the stack in case an optimistic assumption
+ // fails during initialization (see JDK-8079269).
+ final int objectSlot = method.getUsedSlotsWithLiveTemporaries();
+ final Type objectType = method.peekType();
+ method.storeTemp(objectType, objectSlot);
+ populateRange(method, objectType, objectSlot, 0, tuples.size());
+ }
+
+ /**
+ * Generate code for creating and initializing the object.
+ * @param method the method emitter
+ */
+ protected abstract void createObject(final MethodEmitter method);
/**
* Construct the property map appropriate for the object.
@@ -125,6 +141,12 @@
}
/**
+ * Get the class of objects created by this ObjectCreator
+ * @return class of created object
+ */
+ abstract protected Class<? extends ScriptObject> getAllocatorClass();
+
+ /**
* Technique for loading an initial value. Defined by anonymous subclasses in code gen.
*
* @param value Value to load.
@@ -145,29 +167,4 @@
MethodEmitter loadTuple(final MethodEmitter method, final MapTuple<T> tuple) {
return loadTuple(method, tuple, true);
}
-
- /**
- * If using optimistic typing, let the code generator realize that the newly created object on the stack
- * when DUP-ed will be the same value. Basically: {NEW, DUP, INVOKESPECIAL init, DUP} will leave a stack
- * load specification {unknown, unknown} on stack (that is "there's two values on the stack, but neither
- * comes from a known local load"). If there's an optimistic operation in the literal initializer,
- * OptimisticOperation.storeStack will allocate two temporary locals for it and store them as
- * {ASTORE 4, ASTORE 3}. If we instead do {NEW, DUP, INVOKESPECIAL init, ASTORE 3, ALOAD 3, DUP} we end up
- * with stack load specification {ALOAD 3, ALOAD 3} (as DUP can track that the value it duplicated came
- * from a local load), so if/when a continuation needs to be recreated from it, it'll be
- * able to emit ALOAD 3, ALOAD 3 to recreate the stack. If we didn't do this, deoptimization within an
- * object literal initialization could in rare cases cause an incompatible change in the shape of the
- * local variable table for the temporaries, e.g. in the following snippet where a variable is reassigned
- * to a wider type in an object initializer:
- * <code>var m = 1; var obj = {p0: m, p1: m = "foo", p2: m}</code>
- * @param method the current method emitter.
- */
- void helpOptimisticRecognizeDuplicateIdentity(final MethodEmitter method) {
- if (codegen.useOptimisticTypes()) {
- final Type objectType = method.peekType();
- final int tempSlot = method.defineTemporaryLocalVariable(objectType.getSlots());
- method.storeHidden(objectType, tempSlot);
- method.load(objectType, tempSlot);
- }
- }
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ReplaceCompileUnits.java Sat Sep 26 09:22:24 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ReplaceCompileUnits.java Wed Jul 05 20:51:27 2017 +0200
@@ -27,13 +27,15 @@
import java.util.ArrayList;
import java.util.List;
+
import jdk.nashorn.internal.ir.CompileUnitHolder;
import jdk.nashorn.internal.ir.FunctionNode;
import jdk.nashorn.internal.ir.LexicalContext;
import jdk.nashorn.internal.ir.LiteralNode;
import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
-import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit;
import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.ObjectNode;
+import jdk.nashorn.internal.ir.Splittable;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
/**
@@ -70,15 +72,28 @@
public Node leaveLiteralNode(final LiteralNode<?> node) {
if (node instanceof ArrayLiteralNode) {
final ArrayLiteralNode aln = (ArrayLiteralNode)node;
- if (aln.getUnits() == null) {
+ if (aln.getSplitRanges() == null) {
return node;
}
- final List<ArrayUnit> newArrayUnits = new ArrayList<>();
- for (final ArrayUnit au : aln.getUnits()) {
- newArrayUnits.add(new ArrayUnit(getExistingReplacement(au), au.getLo(), au.getHi()));
+ final List<Splittable.SplitRange> newArrayUnits = new ArrayList<>();
+ for (final Splittable.SplitRange au : aln.getSplitRanges()) {
+ newArrayUnits.add(new Splittable.SplitRange(getExistingReplacement(au), au.getLow(), au.getHigh()));
}
- return aln.setUnits(lc, newArrayUnits);
+ return aln.setSplitRanges(lc, newArrayUnits);
}
return node;
}
+
+ @Override
+ public Node leaveObjectNode(final ObjectNode objectNode) {
+ final List<Splittable.SplitRange> ranges = objectNode.getSplitRanges();
+ if (ranges != null) {
+ final List<Splittable.SplitRange> newRanges = new ArrayList<>();
+ for (final Splittable.SplitRange range : ranges) {
+ newRanges.add(new Splittable.SplitRange(getExistingReplacement(range), range.getLow(), range.getHigh()));
+ }
+ return objectNode.setSplitRanges(lc, newRanges);
+ }
+ return super.leaveObjectNode(objectNode);
+ }
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/SpillObjectCreator.java Sat Sep 26 09:22:24 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/SpillObjectCreator.java Wed Jul 05 20:51:27 2017 +0200
@@ -61,7 +61,7 @@
}
@Override
- protected void makeObject(final MethodEmitter method) {
+ public void createObject(final MethodEmitter method) {
assert !isScope() : "spill scope objects are not currently supported";
final int length = tuples.size();
@@ -69,9 +69,7 @@
final int spillLength = ScriptObject.spillAllocationLength(length);
final long[] jpresetValues = dualFields ? new long[spillLength] : null;
final Object[] opresetValues = new Object[spillLength];
- final Set<Integer> postsetValues = new LinkedHashSet<>();
- final int callSiteFlags = codegen.getCallSiteFlags();
- final Class<?> objectClass = dualFields ? JD.class : JO.class;
+ final Class<?> objectClass = getAllocatorClass();
ArrayData arrayData = ArrayData.allocate(ScriptRuntime.EMPTY_ARRAY);
// Compute constant property values
@@ -85,9 +83,7 @@
if (value != null) {
final Object constantValue = LiteralNode.objectAsConstant(value);
- if (constantValue == LiteralNode.POSTSET_MARKER) {
- postsetValues.add(pos);
- } else {
+ if (constantValue != LiteralNode.POSTSET_MARKER) {
final Property property = propertyMap.findProperty(key);
if (property != null) {
// normal property key
@@ -146,25 +142,34 @@
// instantiate the script object with spill objects
method.invoke(constructorNoLookup(objectClass, PropertyMap.class, long[].class, Object[].class));
- helpOptimisticRecognizeDuplicateIdentity(method);
-
// Set prefix array data if any
if (arrayData.length() > 0) {
method.dup();
codegen.loadConstant(arrayData);
method.invoke(virtualCallNoLookup(ScriptObject.class, "setArray", void.class, ArrayData.class));
}
+ }
+
+ @Override
+ public void populateRange(final MethodEmitter method, final Type objectType, final int objectSlot, final int start, final int end) {
+ final int callSiteFlags = codegen.getCallSiteFlags();
+ method.load(objectType, objectSlot);
// set postfix values
- for (final int i : postsetValues) {
+ for (int i = start; i < end; i++) {
final MapTuple<Expression> tuple = tuples.get(i);
+
+ if (LiteralNode.isConstant(tuple.value)) {
+ continue;
+ }
+
final Property property = propertyMap.findProperty(tuple.key);
+
if (property == null) {
final int index = ArrayIndex.getArrayIndex(tuple.key);
assert ArrayIndex.isValidArrayIndex(index);
method.dup();
method.load(ArrayIndex.toLongIndex(index));
- //method.println("putting " + tuple + " into arraydata");
loadTuple(method, tuple);
method.dynamicSetIndex(callSiteFlags);
} else {
@@ -178,8 +183,7 @@
@Override
protected PropertyMap makeMap() {
assert propertyMap == null : "property map already initialized";
- final boolean dualFields = codegen.useDualFields();
- final Class<? extends ScriptObject> clazz = dualFields ? JD.class : JO.class;
+ final Class<? extends ScriptObject> clazz = getAllocatorClass();
propertyMap = new MapCreator<>(clazz, tuples).makeSpillMap(false, codegen.useDualFields());
return propertyMap;
}
@@ -188,4 +192,9 @@
protected void loadValue(final Expression expr, final Type type) {
codegen.loadExpressionAsType(expr, type);
}
+
+ @Override
+ protected Class<? extends ScriptObject> getAllocatorClass() {
+ return codegen.useDualFields() ? JD.class : JO.class;
+ }
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Splitter.java Sat Sep 26 09:22:24 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Splitter.java Wed Jul 05 20:51:27 2017 +0200
@@ -36,9 +36,11 @@
import jdk.nashorn.internal.ir.LexicalContext;
import jdk.nashorn.internal.ir.LiteralNode;
import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
-import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit;
import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.ObjectNode;
+import jdk.nashorn.internal.ir.PropertyNode;
import jdk.nashorn.internal.ir.SplitNode;
+import jdk.nashorn.internal.ir.Splittable;
import jdk.nashorn.internal.ir.Statement;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
import jdk.nashorn.internal.runtime.Context;
@@ -295,7 +297,7 @@
final ArrayLiteralNode arrayLiteralNode = (ArrayLiteralNode) literal;
final Node[] value = arrayLiteralNode.getValue();
final int[] postsets = arrayLiteralNode.getPostsets();
- final List<ArrayUnit> units = new ArrayList<>();
+ final List<Splittable.SplitRange> ranges = new ArrayList<>();
long totalWeight = 0;
int lo = 0;
@@ -309,7 +311,7 @@
if (totalWeight >= SPLIT_THRESHOLD) {
final CompileUnit unit = compiler.findUnit(totalWeight - weight);
- units.add(new ArrayUnit(unit, lo, i));
+ ranges.add(new Splittable.SplitRange(unit, lo, i));
lo = i;
totalWeight = weight;
}
@@ -317,16 +319,59 @@
if (lo != postsets.length) {
final CompileUnit unit = compiler.findUnit(totalWeight);
- units.add(new ArrayUnit(unit, lo, postsets.length));
+ ranges.add(new Splittable.SplitRange(unit, lo, postsets.length));
}
- return arrayLiteralNode.setUnits(lc, units);
+ return arrayLiteralNode.setSplitRanges(lc, ranges);
}
return literal;
}
@Override
+ public Node leaveObjectNode(final ObjectNode objectNode) {
+ long weight = WeighNodes.weigh(objectNode);
+
+ if (weight < SPLIT_THRESHOLD) {
+ return objectNode;
+ }
+
+ final FunctionNode functionNode = lc.getCurrentFunction();
+ lc.setFlag(functionNode, FunctionNode.IS_SPLIT);
+
+ final List<Splittable.SplitRange> ranges = new ArrayList<>();
+ final List<PropertyNode> properties = objectNode.getElements();
+ final boolean isSpillObject = properties.size() > CodeGenerator.OBJECT_SPILL_THRESHOLD;
+ long totalWeight = 0;
+ int lo = 0;
+
+ for (int i = 0; i < properties.size(); i++) {
+
+ final PropertyNode property = properties.get(i);
+ final boolean isConstant = LiteralNode.isConstant(property.getValue());
+
+ if (!isConstant || !isSpillObject) {
+ weight = isConstant ? 0 : WeighNodes.weigh(property.getValue());
+ totalWeight += WeighNodes.AASTORE_WEIGHT + weight;
+
+ if (totalWeight >= SPLIT_THRESHOLD) {
+ final CompileUnit unit = compiler.findUnit(totalWeight - weight);
+ ranges.add(new Splittable.SplitRange(unit, lo, i));
+ lo = i;
+ totalWeight = weight;
+ }
+ }
+ }
+
+ if (lo != properties.size()) {
+ final CompileUnit unit = compiler.findUnit(totalWeight);
+ ranges.add(new Splittable.SplitRange(unit, lo, properties.size()));
+ }
+
+ return objectNode.setSplitRanges(lc, ranges);
+ }
+
+ @Override
public boolean enterFunctionNode(final FunctionNode node) {
//only go into the function node for this splitter. any subfunctions are rejected
return node == outermost;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/WeighNodes.java Sat Sep 26 09:22:24 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/WeighNodes.java Wed Jul 05 20:51:27 2017 +0200
@@ -44,12 +44,13 @@
import jdk.nashorn.internal.ir.LexicalContext;
import jdk.nashorn.internal.ir.LiteralNode;
import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
-import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit;
import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.ObjectNode;
import jdk.nashorn.internal.ir.PropertyNode;
import jdk.nashorn.internal.ir.ReturnNode;
import jdk.nashorn.internal.ir.RuntimeNode;
import jdk.nashorn.internal.ir.SplitNode;
+import jdk.nashorn.internal.ir.Splittable;
import jdk.nashorn.internal.ir.SwitchNode;
import jdk.nashorn.internal.ir.ThrowNode;
import jdk.nashorn.internal.ir.TryNode;
@@ -88,6 +89,8 @@
static final long THROW_WEIGHT = 2;
static final long VAR_WEIGHT = 40;
static final long WITH_WEIGHT = 8;
+ static final long OBJECT_WEIGHT = 16;
+ static final long SETPROP_WEIGHT = 5;
/** Accumulated weight. */
private long weight;
@@ -213,7 +216,7 @@
final ArrayLiteralNode arrayLiteralNode = (ArrayLiteralNode)literalNode;
final Node[] value = arrayLiteralNode.getValue();
final int[] postsets = arrayLiteralNode.getPostsets();
- final List<ArrayUnit> units = arrayLiteralNode.getUnits();
+ final List<Splittable.SplitRange> units = arrayLiteralNode.getSplitRanges();
if (units == null) {
for (final int postset : postsets) {
@@ -233,6 +236,27 @@
}
@Override
+ public boolean enterObjectNode(final ObjectNode objectNode) {
+ weight += OBJECT_WEIGHT;
+ final List<PropertyNode> properties = objectNode.getElements();
+ final boolean isSpillObject = properties.size() > CodeGenerator.OBJECT_SPILL_THRESHOLD;
+
+ for (final PropertyNode property : properties) {
+ if (!LiteralNode.isConstant(property.getValue())) {
+ weight += SETPROP_WEIGHT;
+ property.getValue().accept(this);
+ } else if (!isSpillObject) {
+ // constants in spill object are set via preset spill array,
+ // but fields objects need to set constants.
+ weight += SETPROP_WEIGHT;
+ }
+
+ }
+
+ return false;
+ }
+
+ @Override
public Node leavePropertyNode(final PropertyNode propertyNode) {
weight += LITERAL_WEIGHT;
return propertyNode;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/types/Type.java Sat Sep 26 09:22:24 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/types/Type.java Wed Jul 05 20:51:27 2017 +0200
@@ -65,6 +65,7 @@
import jdk.internal.org.objectweb.asm.Handle;
import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.nashorn.internal.codegen.CompilerConstants.Call;
+import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.Undefined;
import jdk.nashorn.internal.runtime.linker.Bootstrap;
@@ -256,6 +257,9 @@
case jdk.internal.org.objectweb.asm.Type.DOUBLE:
return NUMBER;
case jdk.internal.org.objectweb.asm.Type.OBJECT:
+ if (Context.isStructureClass(itype.getClassName())) {
+ return SCRIPT_OBJECT;
+ }
try {
return Type.typeFor(Class.forName(itype.getClassName()));
} catch(final ClassNotFoundException e) {
@@ -949,7 +953,7 @@
/**
* This is the singleton for integer arrays
*/
- public static final ArrayType INT_ARRAY = new ArrayType(int[].class) {
+ public static final ArrayType INT_ARRAY = putInCache(new ArrayType(int[].class) {
private static final long serialVersionUID = 1L;
@Override
@@ -973,12 +977,12 @@
public Type getElementType() {
return INT;
}
- };
+ });
/**
* This is the singleton for long arrays
*/
- public static final ArrayType LONG_ARRAY = new ArrayType(long[].class) {
+ public static final ArrayType LONG_ARRAY = putInCache(new ArrayType(long[].class) {
private static final long serialVersionUID = 1L;
@Override
@@ -1002,12 +1006,12 @@
public Type getElementType() {
return LONG;
}
- };
+ });
/**
* This is the singleton for numeric arrays
*/
- public static final ArrayType NUMBER_ARRAY = new ArrayType(double[].class) {
+ public static final ArrayType NUMBER_ARRAY = putInCache(new ArrayType(double[].class) {
private static final long serialVersionUID = 1L;
@Override
@@ -1031,13 +1035,7 @@
public Type getElementType() {
return NUMBER;
}
- };
-
- /** Singleton for method handle arrays used for properties etc. */
- public static final ArrayType METHODHANDLE_ARRAY = putInCache(new ArrayType(MethodHandle[].class));
-
- /** This is the singleton for string arrays */
- public static final ArrayType STRING_ARRAY = putInCache(new ArrayType(String[].class));
+ });
/** This is the singleton for object arrays */
public static final ArrayType OBJECT_ARRAY = putInCache(new ArrayType(Object[].class));
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LiteralNode.java Sat Sep 26 09:22:24 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LiteralNode.java Wed Jul 05 20:51:27 2017 +0200
@@ -25,11 +25,9 @@
package jdk.nashorn.internal.ir;
-import java.io.Serializable;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
-import jdk.nashorn.internal.codegen.CompileUnit;
import jdk.nashorn.internal.codegen.types.ArrayType;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.annotations.Immutable;
@@ -583,6 +581,15 @@
return POSTSET_MARKER;
}
+ /**
+ * Test whether {@code object} represents a constant value.
+ * @param object a node or value object
+ * @return true if object is a constant value
+ */
+ public static boolean isConstant(final Object object) {
+ return objectAsConstant(object) != POSTSET_MARKER;
+ }
+
private static final class NullLiteralNode extends PrimitiveLiteralNode<Object> {
private static final long serialVersionUID = 1L;
@@ -614,7 +621,7 @@
* Array literal node class.
*/
@Immutable
- public static final class ArrayLiteralNode extends LiteralNode<Expression[]> implements LexicalContextNode {
+ public static final class ArrayLiteralNode extends LiteralNode<Expression[]> implements LexicalContextNode, Splittable {
private static final long serialVersionUID = 1L;
/** Array element type. */
@@ -626,8 +633,8 @@
/** Indices of array elements requiring computed post sets. */
private final int[] postsets;
- /** Sub units with indexes ranges, in which to split up code generation, for large literals */
- private final List<ArrayUnit> units;
+ /** Ranges for splitting up large literals in code generation */
+ private final List<Splittable.SplitRange> splitRanges;
@Override
public boolean isArray() {
@@ -635,64 +642,13 @@
}
- /**
- * An ArrayUnit is a range in an ArrayLiteral. ArrayLiterals can
- * be split if they are too large, for bytecode generation reasons
- */
- public static final class ArrayUnit implements CompileUnitHolder, Serializable {
- private static final long serialVersionUID = 1L;
-
- /** Compile unit associated with the postsets range. */
- private final CompileUnit compileUnit;
-
- /** postsets range associated with the unit (hi not inclusive). */
- private final int lo, hi;
-
- /**
- * Constructor
- * @param compileUnit compile unit
- * @param lo lowest array index in unit
- * @param hi highest array index in unit + 1
- */
- public ArrayUnit(final CompileUnit compileUnit, final int lo, final int hi) {
- this.compileUnit = compileUnit;
- this.lo = lo;
- this.hi = hi;
- }
-
- /**
- * Get the high index position of the ArrayUnit (non inclusive)
- * @return high index position
- */
- public int getHi() {
- return hi;
- }
-
- /**
- * Get the low index position of the ArrayUnit (inclusive)
- * @return low index position
- */
- public int getLo() {
- return lo;
- }
-
- /**
- * The array compile unit
- * @return array compile unit
- */
- @Override
- public CompileUnit getCompileUnit() {
- return compileUnit;
- }
- }
-
private static final class ArrayLiteralInitializer {
static ArrayLiteralNode initialize(final ArrayLiteralNode node) {
final Type elementType = computeElementType(node.value);
final int[] postsets = computePostsets(node.value);
final Object presets = computePresets(node.value, elementType, postsets);
- return new ArrayLiteralNode(node, node.value, elementType, postsets, presets, node.units);
+ return new ArrayLiteralNode(node, node.value, elementType, postsets, presets, node.splitRanges);
}
private static Type computeElementType(final Expression[] value) {
@@ -725,7 +681,7 @@
for (int i = 0; i < value.length; i++) {
final Expression element = value[i];
- if (element == null || objectAsConstant(element) == POSTSET_MARKER) {
+ if (element == null || !isConstant(element)) {
computed[nComputed++] = i;
}
}
@@ -842,19 +798,19 @@
this.elementType = Type.UNKNOWN;
this.presets = null;
this.postsets = null;
- this.units = null;
+ this.splitRanges = null;
}
/**
* Copy constructor
* @param node source array literal node
*/
- private ArrayLiteralNode(final ArrayLiteralNode node, final Expression[] value, final Type elementType, final int[] postsets, final Object presets, final List<ArrayUnit> units) {
+ private ArrayLiteralNode(final ArrayLiteralNode node, final Expression[] value, final Type elementType, final int[] postsets, final Object presets, final List<Splittable.SplitRange> splitRanges) {
super(node, value);
this.elementType = elementType;
this.postsets = postsets;
this.presets = presets;
- this.units = units;
+ this.splitRanges = splitRanges;
}
/**
@@ -946,26 +902,27 @@
}
/**
- * Get the array units that make up this ArrayLiteral
- * @see ArrayUnit
- * @return list of array units
+ * Get the split ranges for this ArrayLiteral, or null if this array does not have to be split.
+ * @see Splittable.SplitRange
+ * @return list of split ranges
*/
- public List<ArrayUnit> getUnits() {
- return units == null ? null : Collections.unmodifiableList(units);
+ @Override
+ public List<Splittable.SplitRange> getSplitRanges() {
+ return splitRanges == null ? null : Collections.unmodifiableList(splitRanges);
}
/**
- * Set the ArrayUnits that make up this ArrayLiteral
+ * Set the SplitRanges that make up this ArrayLiteral
* @param lc lexical context
- * @see ArrayUnit
- * @param units list of array units
- * @return new or changed arrayliteralnode
+ * @see Splittable.SplitRange
+ * @param splitRanges list of split ranges
+ * @return new or changed node
*/
- public ArrayLiteralNode setUnits(final LexicalContext lc, final List<ArrayUnit> units) {
- if (this.units == units) {
+ public ArrayLiteralNode setSplitRanges(final LexicalContext lc, final List<Splittable.SplitRange> splitRanges) {
+ if (this.splitRanges == splitRanges) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new ArrayLiteralNode(this, value, elementType, postsets, presets, units));
+ return Node.replaceInLexicalContext(lc, this, new ArrayLiteralNode(this, value, elementType, postsets, presets, splitRanges));
}
@Override
@@ -987,7 +944,7 @@
if (this.value == value) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new ArrayLiteralNode(this, value, elementType, postsets, presets, units));
+ return Node.replaceInLexicalContext(lc, this, new ArrayLiteralNode(this, value, elementType, postsets, presets, splitRanges));
}
private ArrayLiteralNode setValue(final LexicalContext lc, final List<Expression> value) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ObjectNode.java Sat Sep 26 09:22:24 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ObjectNode.java Wed Jul 05 20:51:27 2017 +0200
@@ -27,6 +27,7 @@
import java.util.Collections;
import java.util.List;
+import java.util.RandomAccess;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.annotations.Immutable;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
@@ -35,12 +36,15 @@
* IR representation of an object literal.
*/
@Immutable
-public final class ObjectNode extends Expression {
+public final class ObjectNode extends Expression implements LexicalContextNode, Splittable {
private static final long serialVersionUID = 1L;
/** Literal elements. */
private final List<PropertyNode> elements;
+ /** Ranges for splitting large literals over multiple compile units in codegen. */
+ private final List<Splittable.SplitRange> splitRanges;
+
/**
* Constructor
*
@@ -51,19 +55,27 @@
public ObjectNode(final long token, final int finish, final List<PropertyNode> elements) {
super(token, finish);
this.elements = elements;
+ this.splitRanges = null;
+ assert elements instanceof RandomAccess : "Splitting requires random access lists";
}
- private ObjectNode(final ObjectNode objectNode, final List<PropertyNode> elements) {
+ private ObjectNode(final ObjectNode objectNode, final List<PropertyNode> elements,
+ final List<Splittable.SplitRange> splitRanges ) {
super(objectNode);
this.elements = elements;
+ this.splitRanges = splitRanges;
}
@Override
public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
+ return Acceptor.accept(this, visitor);
+ }
+
+ @Override
+ public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterObjectNode(this)) {
- return visitor.leaveObjectNode(setElements(Node.accept(visitor, elements)));
+ return visitor.leaveObjectNode(setElements(lc, Node.accept(visitor, elements)));
}
-
return this;
}
@@ -102,10 +114,35 @@
return Collections.unmodifiableList(elements);
}
- private ObjectNode setElements(final List<PropertyNode> elements) {
+ private ObjectNode setElements(final LexicalContext lc, final List<PropertyNode> elements) {
if (this.elements == elements) {
return this;
}
- return new ObjectNode(this, elements);
+ return Node.replaceInLexicalContext(lc, this, new ObjectNode(this, elements, this.splitRanges));
}
+
+ /**
+ * Set the split ranges for this ObjectNode
+ * @see Splittable.SplitRange
+ * @param lc the lexical context
+ * @param splitRanges list of split ranges
+ * @return new or changed object node
+ */
+ public ObjectNode setSplitRanges(final LexicalContext lc, final List<Splittable.SplitRange> splitRanges) {
+ if (this.splitRanges == splitRanges) {
+ return this;
+ }
+ return Node.replaceInLexicalContext(lc, this, new ObjectNode(this, elements, splitRanges));
+ }
+
+ /**
+ * Get the split ranges for this ObjectNode, or null if the object is not split.
+ * @see Splittable.SplitRange
+ * @return list of split ranges
+ */
+ @Override
+ public List<Splittable.SplitRange> getSplitRanges() {
+ return splitRanges == null ? null : Collections.unmodifiableList(splitRanges);
+ }
+
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Splittable.java Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,95 @@
+/*
+ * 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. 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.
+ */
+
+package jdk.nashorn.internal.ir;
+
+import java.io.Serializable;
+import java.util.List;
+import jdk.nashorn.internal.codegen.CompileUnit;
+
+/**
+ * An interface for splittable expressions.
+ */
+public interface Splittable {
+
+ /**
+ * Get a list of split ranges for this splittable expression, or null
+ * if the expression should not be split.
+ *
+ * @return a list of split ranges
+ */
+ List<SplitRange> getSplitRanges();
+
+ /**
+ * A SplitRange is a range in a splittable expression. It defines the
+ * boundaries of the split range and provides a compile unit for code generation.
+ */
+ final class SplitRange implements CompileUnitHolder, Serializable {
+ private static final long serialVersionUID = 1L;
+
+ /** Compile unit associated with the postsets range. */
+ private final CompileUnit compileUnit;
+
+ /** postsets range associated with the unit (hi not inclusive). */
+ private final int low, high;
+
+ /**
+ * Constructor
+ * @param compileUnit compile unit
+ * @param low lowest array index in unit
+ * @param high highest array index in unit + 1
+ */
+ public SplitRange(final CompileUnit compileUnit, final int low, final int high) {
+ this.compileUnit = compileUnit;
+ this.low = low;
+ this.high = high;
+ }
+
+ /**
+ * Get the high index position of the ArrayUnit (exclusive)
+ * @return high index position
+ */
+ public int getHigh() {
+ return high;
+ }
+
+ /**
+ * Get the low index position of the ArrayUnit (inclusive)
+ * @return low index position
+ */
+ public int getLow() {
+ return low;
+ }
+
+ /**
+ * The array compile unit
+ * @return array compile unit
+ */
+ @Override
+ public CompileUnit getCompileUnit() {
+ return compileUnit;
+ }
+ }
+}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java Sat Sep 26 09:22:24 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java Wed Jul 05 20:51:27 2017 +0200
@@ -64,7 +64,6 @@
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
-import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.LongAdder;
@@ -301,7 +300,47 @@
}
}
- private final Map<CodeSource, Reference<Class<?>>> anonymousHostClasses = new ConcurrentHashMap<>();
+ private final Map<CodeSource, HostClassReference> anonymousHostClasses = new HashMap<>();
+ private final ReferenceQueue<Class<?>> anonymousHostClassesRefQueue = new ReferenceQueue<>();
+
+ private static class HostClassReference extends WeakReference<Class<?>> {
+ final CodeSource codeSource;
+
+ HostClassReference(final CodeSource codeSource, final Class<?> clazz, final ReferenceQueue<Class<?>> refQueue) {
+ super(clazz, refQueue);
+ this.codeSource = codeSource;
+ }
+ }
+
+ private synchronized Class<?> getAnonymousHostClass(final CodeSource codeSource) {
+ // Remove cleared entries
+ for(;;) {
+ final HostClassReference clearedRef = (HostClassReference)anonymousHostClassesRefQueue.poll();
+ if (clearedRef == null) {
+ break;
+ }
+ anonymousHostClasses.remove(clearedRef.codeSource, clearedRef);
+ }
+
+ // Try to find an existing host class
+ final Reference<Class<?>> ref = anonymousHostClasses.get(codeSource);
+ if (ref != null) {
+ final Class<?> existingHostClass = ref.get();
+ if (existingHostClass != null) {
+ return existingHostClass;
+ }
+ }
+
+ // Define a new host class if existing is not found
+ final Class<?> newHostClass = createNewLoader().installClass(
+ // NOTE: we're defining these constants in AnonymousContextCodeInstaller so they are not
+ // initialized if we don't use AnonymousContextCodeInstaller. As this method is only ever
+ // invoked from AnonymousContextCodeInstaller, this is okay.
+ AnonymousContextCodeInstaller.ANONYMOUS_HOST_CLASS_NAME,
+ AnonymousContextCodeInstaller.ANONYMOUS_HOST_CLASS_BYTES, codeSource);
+ anonymousHostClasses.put(codeSource, new HostClassReference(codeSource, newHostClass, anonymousHostClassesRefQueue));
+ return newHostClass;
+ }
private static final class AnonymousContextCodeInstaller extends ContextCodeInstaller {
private static final Unsafe UNSAFE = getUnsafe();
@@ -310,9 +349,9 @@
private final Class<?> hostClass;
- private AnonymousContextCodeInstaller(final Context context, final CodeSource codeSource) {
+ private AnonymousContextCodeInstaller(final Context context, final CodeSource codeSource, final Class<?> hostClass) {
super(context, codeSource);
- hostClass = getAnonymousHostClass();
+ this.hostClass = hostClass;
}
@Override
@@ -335,19 +374,6 @@
return new NamedContextCodeInstaller(context, codeSource, context.createNewLoader());
}
- private Class<?> getAnonymousHostClass() {
- final Reference<Class<?>> ref = context.anonymousHostClasses.get(codeSource);
- if (ref != null) {
- final Class<?> existingHostClass = ref.get();
- if (existingHostClass != null) {
- return existingHostClass;
- }
- }
- final Class<?> newHostClass = context.createNewLoader().installClass(ANONYMOUS_HOST_CLASS_NAME, ANONYMOUS_HOST_CLASS_BYTES, codeSource);
- context.anonymousHostClasses.put(codeSource, new WeakReference<>(newHostClass));
- return newHostClass;
- }
-
private static final byte[] getAnonymousHostClassBytes() {
final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
cw.visit(V1_7, Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT, ANONYMOUS_HOST_CLASS_NAME.replace('.', '/'), null, "java/lang/Object", null);
@@ -1034,6 +1060,16 @@
}
/**
+ * Is {@code className} the name of a structure class?
+ *
+ * @param className a class name
+ * @return true if className is a structure class name
+ */
+ public static boolean isStructureClass(final String className) {
+ return StructureLoader.isStructureClass(className);
+ }
+
+ /**
* Checks that the given Class can be accessed from no permissions context.
*
* @param clazz Class object
@@ -1404,7 +1440,7 @@
final ScriptLoader loader = env._loader_per_compile ? createNewLoader() : scriptLoader;
installer = new NamedContextCodeInstaller(this, cs, loader);
} else {
- installer = new AnonymousContextCodeInstaller(this, cs);
+ installer = new AnonymousContextCodeInstaller(this, cs, getAnonymousHostClass(cs));
}
if (storedScript == null) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java Sat Sep 26 09:22:24 2015 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java Wed Jul 05 20:51:27 2017 +0200
@@ -203,6 +203,8 @@
// This is the superclass for our generated adapter.
private final Class<?> superClass;
+ // Interfaces implemented by our generated adapter.
+ private final List<Class<?>> interfaces;
// Class loader used as the parent for the class loader we'll create to load the generated class. It will be a class
// loader that has the visibility of all original types (class to extend and interfaces to implement) and of the
// Nashorn classes.
@@ -254,6 +256,7 @@
assert interfaces != null;
this.superClass = superClass;
+ this.interfaces = interfaces;
this.classOverride = classOverride;
this.commonLoader = commonLoader;
cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS) {
@@ -1031,6 +1034,24 @@
endMethod(mv);
}
+ // find the appropriate super type to use for invokespecial on the given interface
+ private Class<?> findInvokespecialOwnerFor(final Class<?> cl) {
+ assert Modifier.isInterface(cl.getModifiers()) : cl + " is not an interface";
+
+ if (cl.isAssignableFrom(superClass)) {
+ return superClass;
+ }
+
+ for (final Class<?> iface : interfaces) {
+ if (cl.isAssignableFrom(iface)) {
+ return iface;
+ }
+ }
+
+ // we better that interface that extends the given interface!
+ throw new AssertionError("can't find the class/interface that extends " + cl);
+ }
+
private void emitSuperCall(final InstructionAdapter mv, final Class<?> owner, final String name, final String methodDesc) {
mv.visitVarInsn(ALOAD, 0);
int nextParam = 1;
@@ -1042,7 +1063,9 @@
// default method - non-abstract, interface method
if (Modifier.isInterface(owner.getModifiers())) {
- mv.invokespecial(Type.getInternalName(owner), name, methodDesc, false);
+ // we should call default method on the immediate "super" type - not on (possibly)
+ // the indirectly inherited interface class!
+ mv.invokespecial(Type.getInternalName(findInvokespecialOwnerFor(owner)), name, methodDesc, false);
} else {
mv.invokespecial(superClassName, name, methodDesc, false);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8134488.js Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+/**
+ * JDK-8134488: var statement in if(false) block incorrectly evacuated into enclosing function
+ *
+ * @test
+ * @run
+ */
+
+var x = "string";
+print(x);
+
+(function f1() {
+ (function f2() {
+ // If it finds both 'print' and 'x', it'll print 'string'.
+ print(x);
+ })();
+
+ if (false) {
+ (function f3() {
+ var x;
+ })();
+ }
+
+})();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8134488.js.EXPECTED Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,2 @@
+string
+string
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8134490.js Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+/**
+ * JDK-8134490: Dead var statement evacuation incorrectly descends into nested functions
+ *
+ * @test
+ * @run
+ */
+
+var v1;
+
+function f1()
+{
+v1 = 1;
+return true;
+(function () { var v1; })();
+}
+
+f1();
+// If it executes without throwing an exception in code generator, it's working.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8135190.js Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+/**
+ * JDK-8135190: Method code too large in Babel browser.js script
+ *
+ * @test
+ * @run
+ */
+
+// Make sure huge object literals are parsed correctly and don't throw
+// (using buildObject -> JSON.stringify -> eval -> testObject)
+
+function buildObject(n, d) {
+ if (n < 2) {
+ return {name: "property", type: "identifier"};
+ }
+ var obj = {};
+ for (var i = 0; i < n; i++) {
+ obj["expr" + i] = buildObject(Math.floor(n / d), d);
+ }
+ return obj;
+}
+
+function testObject(obj, n, d) {
+ var keys = Object.keys(obj);
+ if (n < 2) {
+ Assert.assertTrue(keys.length === 2);
+ Assert.assertTrue(keys[0] === "name");
+ Assert.assertTrue(keys[1] === "type");
+ } else {
+ Assert.assertTrue(keys.length === n);
+ for (var i = 0; i < n; i++) {
+ Assert.assertTrue(keys[i] === "expr" + i);
+ }
+ }
+ if (n >= 2) {
+ for (var k in keys) {
+ testObject(obj[keys[k]], Math.floor(n / d), d)
+ }
+ }
+}
+
+var fieldObject = (eval("(" + JSON.stringify(buildObject(25, 2)) + ")"));
+testObject(fieldObject, 25, 2);
+var spillObject = (eval("(" + JSON.stringify(buildObject(1000, 100)) + ")"));
+testObject(spillObject, 1000, 100);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8137134.js Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+/**
+ * JDK-8137134: invokespecial on indirect super interface is generated by Java adapter generator
+ *
+ * @test
+ * @run
+ */
+
+var B = Java.type("jdk.nashorn.test.models.B");
+var b1 = new B() {}
+print(b1.a());
+print(b1.b());
+
+var b2 = new B() {
+ b: function() {
+ return "from B.b in script";
+ }
+};
+
+print(b2.a());
+print(b2.b());
+
+var b3 = new B() {
+ a: function() {
+ return "from A.a in script";
+ },
+ b: function() {
+ return "from B.b in script";
+ }
+};
+
+print(b3.a());
+print(b3.b());
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8137134.js.EXPECTED Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,6 @@
+from A.a
+from B.b
+from A.a
+from B.b in script
+from A.a in script
+from B.b in script
--- a/nashorn/test/script/currently-failing/gettersetter.js Sat Sep 26 09:22:24 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * 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
- * @option -Dnashorn.debug=true
- * @fork
- */
-
-load(__DIR__ + "maputil.js");
-
-function Foo() {
- return {
- get foo() { return 42; },
- set foo(x) {}
- }
-}
-
-var obj1 = Foo();
-var obj2 = Foo();
-
-assertSameMap(obj1, obj2, "Object literals before change");
-
-Object.defineProperty(obj2, "foo", { get: function() { return 'hello' } });
-assertSameMap(obj1, obj2);
-
-Object.defineProperty(obj2, "foo", { set: function(x) { print(x) } });
-assertSameMap(obj1, obj2);
--- a/nashorn/test/script/currently-failing/property_delete.js Sat Sep 26 09:22:24 2015 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * 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
- * @option -Dnashorn.debug=true
- * @fork
- */
-
-load(__DIR__ + "maputil.js");
-
-function Foo() {
- this.x = 33;
-}
-
-var obj1 = new Foo();
-var obj2 = new Foo();
-
-assertSameMap(obj1, obj2);
-
-// property deletion at same callsite
-function deleteX(obj) {
- delete obj.x;
-}
-deleteX(obj1);
-deleteX(obj2);
-
-assertSameMap(obj1, obj2);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/maptests/gettersetter.js Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,48 @@
+/*
+ * 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
+ * @option -Dnashorn.debug=true
+ * @fork
+ */
+
+load(__DIR__ + "maputil.js");
+
+function Foo() {
+ return {
+ get foo() { return 42; },
+ set foo(x) {}
+ }
+}
+
+var obj1 = Foo();
+var obj2 = Foo();
+
+assertSameMap(obj1, obj2, "Object literals before change");
+
+Object.defineProperty(obj2, "foo", { get: function() { return 'hello' } });
+assertSameMap(obj1, obj2);
+
+Object.defineProperty(obj2, "foo", { set: function(x) { print(x) } });
+assertSameMap(obj1, obj2);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/maptests/property_delete.js Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,48 @@
+/*
+ * 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
+ * @option -Dnashorn.debug=true
+ * @fork
+ */
+
+load(__DIR__ + "maputil.js");
+
+function Foo() {
+ this.x = 33;
+}
+
+var obj1 = new Foo();
+var obj2 = new Foo();
+
+assertSameMap(obj1, obj2);
+
+// property deletion at same callsite
+function deleteX(obj) {
+ delete obj.x;
+}
+deleteX(obj1);
+deleteX(obj2);
+
+assertEqualWithoutTypeMap(obj1, obj2);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/src/jdk/nashorn/test/models/A.java Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,32 @@
+/*
+ * 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. 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.
+ */
+
+package jdk.nashorn.test.models;
+
+public interface A {
+ default String a() {
+ return "from A.a";
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/src/jdk/nashorn/test/models/B.java Wed Jul 05 20:51:27 2017 +0200
@@ -0,0 +1,32 @@
+/*
+ * 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. 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.
+ */
+
+package jdk.nashorn.test.models;
+
+public interface B extends A {
+ default String b() {
+ return "from B.b";
+ }
+}