Merge
This commit is contained in:
commit
94f4ff3fb2
2
.hgtags
2
.hgtags
@ -310,3 +310,5 @@ e7dbbef69d12b6a74dfad331b7188e7f893e8d29 jdk9-b62
|
||||
4915246064b2f89d5f00c96e758686b7fdad36a6 jdk9-b65
|
||||
ff3fc75f3214ad7e03595be1b0d0f38d887b6f0e jdk9-b66
|
||||
56166ce66037952fa21e9f680b31bf8eb47312c0 jdk9-b67
|
||||
5b500c93ce4822d47061cd518ff3f72d9d8cb5b5 jdk9-b68
|
||||
d69c968463f0ae5d0b45de3fc14fe65171b23948 jdk9-b69
|
||||
|
@ -310,3 +310,5 @@ ea38728b4f4bdd8fd0d7a89b18069f521cf05013 jdk9-b61
|
||||
7c31f9d7b932f7924f1258d52885b1c7c3e078c2 jdk9-b65
|
||||
dc6e8336f51bb6b67b7245766179eab5ca7720b4 jdk9-b66
|
||||
f546760134eb861fcfecd4ce611b0040b0d25a6a jdk9-b67
|
||||
70e4272790b6199e9ca89df2758ff9cb58ec4125 jdk9-b68
|
||||
1bcfd6b8726582cff5a42dbfc75903e36f9dd4fe jdk9-b69
|
||||
|
@ -436,7 +436,6 @@ AC_DEFUN_ONCE([BASIC_SETUP_FUNDAMENTAL_TOOLS],
|
||||
BASIC_PATH_PROGS(CYGPATH, cygpath)
|
||||
BASIC_PATH_PROGS(READLINK, [greadlink readlink])
|
||||
BASIC_PATH_PROGS(DF, df)
|
||||
BASIC_PATH_PROGS(SETFILE, SetFile)
|
||||
BASIC_PATH_PROGS(CPIO, [cpio bsdcpio])
|
||||
])
|
||||
|
||||
@ -574,10 +573,11 @@ AC_DEFUN_ONCE([BASIC_SETUP_DEVKIT],
|
||||
)
|
||||
|
||||
if test "x$OPENJDK_BUILD_OS" = "xmacosx"; then
|
||||
# detect if Xcode is installed by running xcodebuild -version
|
||||
# If a devkit has been supplied, find xcodebuild in the toolchain_path.
|
||||
# If not, detect if Xcode is installed by running xcodebuild -version
|
||||
# if no Xcode installed, xcodebuild exits with 1
|
||||
# if Xcode is installed, even if xcode-select is misconfigured, then it exits with 0
|
||||
if /usr/bin/xcodebuild -version >/dev/null 2>&1; then
|
||||
if test "x$DEVKIT_ROOT" != x || /usr/bin/xcodebuild -version >/dev/null 2>&1; then
|
||||
# We need to use xcodebuild in the toolchain dir provided by the user, this will
|
||||
# fall back on the stub binary in /usr/bin/xcodebuild
|
||||
AC_PATH_PROG([XCODEBUILD], [xcodebuild], [/usr/bin/xcodebuild], [$TOOLCHAIN_PATH])
|
||||
@ -961,6 +961,7 @@ AC_DEFUN_ONCE([BASIC_SETUP_COMPLEX_TOOLS],
|
||||
AC_MSG_RESULT([yes])
|
||||
fi
|
||||
fi
|
||||
BASIC_REQUIRE_PROGS(SETFILE, SetFile)
|
||||
fi
|
||||
])
|
||||
|
||||
|
7
common/autoconf/build-aux/config.guess
vendored
7
common/autoconf/build-aux/config.guess
vendored
@ -86,4 +86,11 @@ if [ "x$OUT" = x ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# Test and fix cpu on Macosx when C preprocessor is not on the path
|
||||
echo $OUT | grep i386-apple-darwin > /dev/null 2> /dev/null
|
||||
if test $? = 0; then
|
||||
REAL_CPU=`uname -m`
|
||||
OUT=$REAL_CPU`echo $OUT | sed -e 's/[^-]*//'`
|
||||
fi
|
||||
|
||||
echo $OUT
|
||||
|
@ -855,6 +855,7 @@ OS_VERSION_MINOR
|
||||
OS_VERSION_MAJOR
|
||||
PKG_CONFIG
|
||||
BASH_ARGS
|
||||
SETFILE
|
||||
CODESIGN
|
||||
XATTR
|
||||
DSYMUTIL
|
||||
@ -946,7 +947,6 @@ build_vendor
|
||||
build_cpu
|
||||
build
|
||||
CPIO
|
||||
SETFILE
|
||||
DF
|
||||
READLINK
|
||||
CYGPATH
|
||||
@ -1167,7 +1167,6 @@ SED
|
||||
CYGPATH
|
||||
READLINK
|
||||
DF
|
||||
SETFILE
|
||||
CPIO
|
||||
UNZIP
|
||||
ZIP
|
||||
@ -1180,6 +1179,7 @@ TIME
|
||||
DSYMUTIL
|
||||
XATTR
|
||||
CODESIGN
|
||||
SETFILE
|
||||
PKG_CONFIG
|
||||
JAVA
|
||||
JAVAC
|
||||
@ -2049,7 +2049,6 @@ Some influential environment variables:
|
||||
CYGPATH Override default value for CYGPATH
|
||||
READLINK Override default value for READLINK
|
||||
DF Override default value for DF
|
||||
SETFILE Override default value for SETFILE
|
||||
CPIO Override default value for CPIO
|
||||
UNZIP Override default value for UNZIP
|
||||
ZIP Override default value for ZIP
|
||||
@ -2062,6 +2061,7 @@ Some influential environment variables:
|
||||
DSYMUTIL Override default value for DSYMUTIL
|
||||
XATTR Override default value for XATTR
|
||||
CODESIGN Override default value for CODESIGN
|
||||
SETFILE Override default value for SETFILE
|
||||
PKG_CONFIG path to pkg-config utility
|
||||
JAVA Override default value for JAVA
|
||||
JAVAC Override default value for JAVAC
|
||||
@ -4364,7 +4364,7 @@ VS_SDK_PLATFORM_NAME_2013=
|
||||
#CUSTOM_AUTOCONF_INCLUDE
|
||||
|
||||
# Do not change or remove the following line, it is needed for consistency checks:
|
||||
DATE_WHEN_GENERATED=1433337614
|
||||
DATE_WHEN_GENERATED=1434614912
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
@ -13055,192 +13055,6 @@ $as_echo "$tool_specified" >&6; }
|
||||
|
||||
|
||||
|
||||
# Publish this variable in the help.
|
||||
|
||||
|
||||
if test "x$SETFILE" = x; then
|
||||
# The variable is not set by user, try to locate tool using the code snippet
|
||||
for ac_prog in SetFile
|
||||
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_SETFILE+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
case $SETFILE in
|
||||
[\\/]* | ?:[\\/]*)
|
||||
ac_cv_path_SETFILE="$SETFILE" # 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_SETFILE="$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
|
||||
SETFILE=$ac_cv_path_SETFILE
|
||||
if test -n "$SETFILE"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $SETFILE" >&5
|
||||
$as_echo "$SETFILE" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
test -n "$SETFILE" && break
|
||||
done
|
||||
|
||||
else
|
||||
# The variable is set, but is it from the command line or the environment?
|
||||
|
||||
# Try to remove the string !SETFILE! from our list.
|
||||
try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!SETFILE!/}
|
||||
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 "xSETFILE" != xBASH; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of SETFILE from the environment. Use command line variables instead." >&5
|
||||
$as_echo "$as_me: WARNING: Ignoring value of SETFILE from the environment. Use command line variables instead." >&2;}
|
||||
fi
|
||||
# Try to locate tool using the code snippet
|
||||
for ac_prog in SetFile
|
||||
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_SETFILE+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
case $SETFILE in
|
||||
[\\/]* | ?:[\\/]*)
|
||||
ac_cv_path_SETFILE="$SETFILE" # 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_SETFILE="$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
|
||||
SETFILE=$ac_cv_path_SETFILE
|
||||
if test -n "$SETFILE"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $SETFILE" >&5
|
||||
$as_echo "$SETFILE" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
test -n "$SETFILE" && 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="$SETFILE"
|
||||
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 SETFILE=$tool_basename" >&5
|
||||
$as_echo "$as_me: Will search for user supplied tool SETFILE=$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_SETFILE+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
case $SETFILE in
|
||||
[\\/]* | ?:[\\/]*)
|
||||
ac_cv_path_SETFILE="$SETFILE" # 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_SETFILE="$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
|
||||
SETFILE=$ac_cv_path_SETFILE
|
||||
if test -n "$SETFILE"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $SETFILE" >&5
|
||||
$as_echo "$SETFILE" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
if test "x$SETFILE" = 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 SETFILE=$tool_specified" >&5
|
||||
$as_echo "$as_me: Will use user supplied tool SETFILE=$tool_specified" >&6;}
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SETFILE" >&5
|
||||
$as_echo_n "checking for SETFILE... " >&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 SETFILE=$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
|
||||
|
||||
|
||||
|
||||
|
||||
# Publish this variable in the help.
|
||||
|
||||
|
||||
@ -15140,10 +14954,11 @@ fi
|
||||
|
||||
|
||||
if test "x$OPENJDK_BUILD_OS" = "xmacosx"; then
|
||||
# detect if Xcode is installed by running xcodebuild -version
|
||||
# If a devkit has been supplied, find xcodebuild in the toolchain_path.
|
||||
# If not, detect if Xcode is installed by running xcodebuild -version
|
||||
# if no Xcode installed, xcodebuild exits with 1
|
||||
# if Xcode is installed, even if xcode-select is misconfigured, then it exits with 0
|
||||
if /usr/bin/xcodebuild -version >/dev/null 2>&1; then
|
||||
if test "x$DEVKIT_ROOT" != x || /usr/bin/xcodebuild -version >/dev/null 2>&1; then
|
||||
# We need to use xcodebuild in the toolchain dir provided by the user, this will
|
||||
# fall back on the stub binary in /usr/bin/xcodebuild
|
||||
# Extract the first word of "xcodebuild", so it can be a program name with args.
|
||||
@ -19653,6 +19468,199 @@ $as_echo "no" >&6; }
|
||||
$as_echo "yes" >&6; }
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# Publish this variable in the help.
|
||||
|
||||
|
||||
if test "x$SETFILE" = x; then
|
||||
# The variable is not set by user, try to locate tool using the code snippet
|
||||
for ac_prog in SetFile
|
||||
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_SETFILE+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
case $SETFILE in
|
||||
[\\/]* | ?:[\\/]*)
|
||||
ac_cv_path_SETFILE="$SETFILE" # 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_SETFILE="$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
|
||||
SETFILE=$ac_cv_path_SETFILE
|
||||
if test -n "$SETFILE"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $SETFILE" >&5
|
||||
$as_echo "$SETFILE" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
test -n "$SETFILE" && break
|
||||
done
|
||||
|
||||
else
|
||||
# The variable is set, but is it from the command line or the environment?
|
||||
|
||||
# Try to remove the string !SETFILE! from our list.
|
||||
try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!SETFILE!/}
|
||||
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 "xSETFILE" != xBASH; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of SETFILE from the environment. Use command line variables instead." >&5
|
||||
$as_echo "$as_me: WARNING: Ignoring value of SETFILE from the environment. Use command line variables instead." >&2;}
|
||||
fi
|
||||
# Try to locate tool using the code snippet
|
||||
for ac_prog in SetFile
|
||||
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_SETFILE+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
case $SETFILE in
|
||||
[\\/]* | ?:[\\/]*)
|
||||
ac_cv_path_SETFILE="$SETFILE" # 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_SETFILE="$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
|
||||
SETFILE=$ac_cv_path_SETFILE
|
||||
if test -n "$SETFILE"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $SETFILE" >&5
|
||||
$as_echo "$SETFILE" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
test -n "$SETFILE" && 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="$SETFILE"
|
||||
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 SETFILE=$tool_basename" >&5
|
||||
$as_echo "$as_me: Will search for user supplied tool SETFILE=$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_SETFILE+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
case $SETFILE in
|
||||
[\\/]* | ?:[\\/]*)
|
||||
ac_cv_path_SETFILE="$SETFILE" # 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_SETFILE="$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
|
||||
SETFILE=$ac_cv_path_SETFILE
|
||||
if test -n "$SETFILE"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $SETFILE" >&5
|
||||
$as_echo "$SETFILE" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
if test "x$SETFILE" = 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 SETFILE=$tool_specified" >&5
|
||||
$as_echo "$as_me: Will use user supplied tool SETFILE=$tool_specified" >&6;}
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SETFILE" >&5
|
||||
$as_echo_n "checking for SETFILE... " >&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 SETFILE=$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
|
||||
|
||||
|
||||
|
||||
if test "x$SETFILE" = x; then
|
||||
as_fn_error $? "Could not find required tool for SETFILE" "$LINENO" 5
|
||||
fi
|
||||
|
||||
|
||||
fi
|
||||
|
||||
|
||||
|
@ -310,3 +310,5 @@ d27f7e0a7aca129969de23e9934408a31b4abf4c jdk9-b62
|
||||
afc1e295c4bf83f9a5dd539c29914edd4a754a3f jdk9-b65
|
||||
44ee68f7dbacab24a45115fd6a8ccdc7eb6e8f0b jdk9-b66
|
||||
4418697e56f1f43597f55c7cb6573549c6117868 jdk9-b67
|
||||
8efad64f40eb8cd4df376c0a5275892eeb396bbd jdk9-b68
|
||||
de8acedcb5b5870f1dc54cba575aaa5d33897ea2 jdk9-b69
|
||||
|
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* 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. 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 org.omg.CORBA;
|
||||
|
||||
|
||||
/**
|
||||
* This Helper class is used to facilitate the marshalling of <tt>Bounds</tt>.
|
||||
* For more information on Helper files, see
|
||||
* <a href="doc-files/generatedfiles.html#helper">
|
||||
* "Generated Files: Helper Files"</a>.<P>
|
||||
*/
|
||||
|
||||
abstract public class BoundsHelper
|
||||
{
|
||||
private static String _id = "IDL:omg.org/CORBA/Bounds:1.0";
|
||||
|
||||
public static void insert (org.omg.CORBA.Any a, org.omg.CORBA.Bounds that)
|
||||
{
|
||||
org.omg.CORBA.portable.OutputStream out = a.create_output_stream ();
|
||||
a.type (type ());
|
||||
write (out, that);
|
||||
a.read_value (out.create_input_stream (), type ());
|
||||
}
|
||||
|
||||
public static org.omg.CORBA.Bounds extract (org.omg.CORBA.Any a)
|
||||
{
|
||||
return read (a.create_input_stream ());
|
||||
}
|
||||
|
||||
private static org.omg.CORBA.TypeCode __typeCode = null;
|
||||
private static boolean __active = false;
|
||||
synchronized public static org.omg.CORBA.TypeCode type ()
|
||||
{
|
||||
if (__typeCode == null)
|
||||
{
|
||||
synchronized (org.omg.CORBA.TypeCode.class)
|
||||
{
|
||||
if (__typeCode == null)
|
||||
{
|
||||
if (__active)
|
||||
{
|
||||
return org.omg.CORBA.ORB.init().create_recursive_tc ( _id );
|
||||
}
|
||||
__active = true;
|
||||
org.omg.CORBA.StructMember[] _members0 = new org.omg.CORBA.StructMember [0];
|
||||
org.omg.CORBA.TypeCode _tcOf_members0 = null;
|
||||
__typeCode = org.omg.CORBA.ORB.init ().create_exception_tc (org.omg.CORBA.BoundsHelper.id (), "Bounds", _members0);
|
||||
__active = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return __typeCode;
|
||||
}
|
||||
|
||||
public static String id ()
|
||||
{
|
||||
return _id;
|
||||
}
|
||||
|
||||
public static org.omg.CORBA.Bounds read (org.omg.CORBA.portable.InputStream istream)
|
||||
{
|
||||
org.omg.CORBA.Bounds value = new org.omg.CORBA.Bounds ();
|
||||
// read and discard the repository ID
|
||||
istream.read_string ();
|
||||
return value;
|
||||
}
|
||||
|
||||
public static void write (org.omg.CORBA.portable.OutputStream ostream, org.omg.CORBA.Bounds value)
|
||||
{
|
||||
// write the repository ID
|
||||
ostream.write_string (id ());
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2004, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 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
|
||||
@ -52,8 +52,8 @@ public interface DynAny extends org.omg.CORBA.Object
|
||||
*
|
||||
* @param dyn_any the <code>DynAny</code> object whose contents
|
||||
* are assigned to this <code>DynAny</code>.
|
||||
* @throws Invalid if the source <code>DynAny</code> is
|
||||
* invalid
|
||||
* @throws org.omg.CORBA.DynAnyPackage.Invalid if the source
|
||||
* <code>DynAny</code> is invalid
|
||||
*/
|
||||
public void assign(org.omg.CORBA.DynAny dyn_any)
|
||||
throws org.omg.CORBA.DynAnyPackage.Invalid;
|
||||
@ -63,8 +63,8 @@ public interface DynAny extends org.omg.CORBA.Object
|
||||
* object.
|
||||
*
|
||||
* @param value the <code>Any</code> object.
|
||||
* @throws Invalid if the source <code>Any</code> object is
|
||||
* empty or bad
|
||||
* @throws org.omg.CORBA.DynAnyPackage.Invalid if the source
|
||||
* <code>Any</code> object is empty or bad
|
||||
*/
|
||||
public void from_any(org.omg.CORBA.Any value)
|
||||
throws org.omg.CORBA.DynAnyPackage.Invalid;
|
||||
@ -74,8 +74,8 @@ public interface DynAny extends org.omg.CORBA.Object
|
||||
* object.
|
||||
*
|
||||
* @return the <code>Any</code> object.
|
||||
* @throws Invalid if this <code>DynAny</code> is empty or
|
||||
* bad.
|
||||
* @throws org.omg.CORBA.DynAnyPackage.Invalid if this
|
||||
* <code>DynAny</code> is empty or bad.
|
||||
* created or does not contain a meaningful value
|
||||
*/
|
||||
public org.omg.CORBA.Any to_any()
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2004, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 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
|
||||
@ -48,7 +48,8 @@ public interface DynArray extends org.omg.CORBA.Object, org.omg.CORBA.DynAny
|
||||
* <code>DynArray</code> object to the given array.
|
||||
*
|
||||
* @param value the array of <code>Any</code> objects
|
||||
* @exception InvalidSeq if the sequence is bad
|
||||
* @exception org.omg.CORBA.DynAnyPackage.InvalidSeq if the
|
||||
* sequence is bad
|
||||
* @see #get_elements
|
||||
*/
|
||||
public void set_elements(org.omg.CORBA.Any[] value)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2004, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 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
|
||||
@ -65,7 +65,8 @@ public interface DynSequence extends org.omg.CORBA.Object, org.omg.CORBA.DynAny
|
||||
* array.
|
||||
*
|
||||
* @param value the array of <code>Any</code> objects to be set
|
||||
* @exception InvalidSeq if the array of values is bad
|
||||
* @exception org.omg.CORBA.DynAnyPackage.InvalidSeq if the array
|
||||
* of values is bad
|
||||
* @see #get_elements
|
||||
*/
|
||||
public void set_elements(org.omg.CORBA.Any[] value)
|
||||
|
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* 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. 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 org.omg.CORBA.ORBPackage;
|
||||
|
||||
|
||||
/**
|
||||
* This Helper class is used to facilitate the marshalling of
|
||||
* <tt>ORBPackage/InvalidName</tt>.
|
||||
* For more information on Helper files, see
|
||||
* <a href="doc-files/generatedfiles.html#helper">
|
||||
* "Generated Files: Helper Files"</a>.<P>
|
||||
*/
|
||||
|
||||
abstract public class InvalidNameHelper
|
||||
{
|
||||
private static String _id = "IDL:omg.org.CORBA/ORB/InvalidName:1.0";
|
||||
|
||||
public static void insert (org.omg.CORBA.Any a, org.omg.CORBA.ORBPackage.InvalidName that)
|
||||
{
|
||||
org.omg.CORBA.portable.OutputStream out = a.create_output_stream ();
|
||||
a.type (type ());
|
||||
write (out, that);
|
||||
a.read_value (out.create_input_stream (), type ());
|
||||
}
|
||||
|
||||
public static org.omg.CORBA.ORBPackage.InvalidName extract (org.omg.CORBA.Any a)
|
||||
{
|
||||
return read (a.create_input_stream ());
|
||||
}
|
||||
|
||||
private static org.omg.CORBA.TypeCode __typeCode = null;
|
||||
private static boolean __active = false;
|
||||
synchronized public static org.omg.CORBA.TypeCode type ()
|
||||
{
|
||||
if (__typeCode == null)
|
||||
{
|
||||
synchronized (org.omg.CORBA.TypeCode.class)
|
||||
{
|
||||
if (__typeCode == null)
|
||||
{
|
||||
if (__active)
|
||||
{
|
||||
return org.omg.CORBA.ORB.init().create_recursive_tc ( _id );
|
||||
}
|
||||
__active = true;
|
||||
org.omg.CORBA.StructMember[] _members0 = new org.omg.CORBA.StructMember [0];
|
||||
org.omg.CORBA.TypeCode _tcOf_members0 = null;
|
||||
__typeCode = org.omg.CORBA.ORB.init ().create_exception_tc (org.omg.CORBA.ORBPackage.InvalidNameHelper.id (), "InvalidName", _members0);
|
||||
__active = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return __typeCode;
|
||||
}
|
||||
|
||||
public static String id ()
|
||||
{
|
||||
return _id;
|
||||
}
|
||||
|
||||
public static org.omg.CORBA.ORBPackage.InvalidName read (org.omg.CORBA.portable.InputStream istream)
|
||||
{
|
||||
org.omg.CORBA.ORBPackage.InvalidName value = new org.omg.CORBA.ORBPackage.InvalidName ();
|
||||
// read and discard the repository ID
|
||||
istream.read_string ();
|
||||
return value;
|
||||
}
|
||||
|
||||
public static void write (org.omg.CORBA.portable.OutputStream ostream, org.omg.CORBA.ORBPackage.InvalidName value)
|
||||
{
|
||||
// write the repository ID
|
||||
ostream.write_string (id ());
|
||||
}
|
||||
|
||||
}
|
@ -248,7 +248,7 @@ public abstract class ServerRequest {
|
||||
* contain an exception will result in a BAD_PARAM system exception. Passing
|
||||
* in an unlisted user exception will result in either the DIR receiving a
|
||||
* BAD_PARAM system exception or in the client receiving an
|
||||
* UNKNOWN_EXCEPTION system exception.
|
||||
* UNKNOWN system exception.
|
||||
*
|
||||
* @param any the <code>Any</code> object containing the exception
|
||||
* @deprecated use set_exception()
|
||||
@ -272,13 +272,13 @@ public abstract class ServerRequest {
|
||||
* will cause a BAD_PARAM system exception to be thrown. Passing
|
||||
* in an unlisted user exception will result in either the DIR receiving a
|
||||
* BAD_PARAM system exception or in the client receiving an
|
||||
* UNKNOWN_EXCEPTION system exception.
|
||||
* UNKNOWN system exception.
|
||||
*
|
||||
* @param any the <code>Any</code> object containing the exception
|
||||
* @exception BAD_PARAM if the given <code>Any</code> object does not
|
||||
* contain an exception or the exception is an
|
||||
* unlisted user exception
|
||||
* @exception UNKNOWN_EXCEPTION if the given exception is an unlisted
|
||||
* @exception UNKNOWN if the given exception is an unlisted
|
||||
* user exception and the DIR did not
|
||||
* receive a BAD_PARAM exception
|
||||
* @see <a href="package-summary.html#unimpl"><code>CORBA</code>
|
||||
|
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* 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. 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 org.omg.CORBA.TypeCodePackage;
|
||||
|
||||
|
||||
/**
|
||||
* This Helper class is used to facilitate the marshalling of
|
||||
* <tt>TypeCodePackage/BadKind</tt>.
|
||||
* For more information on Helper files, see
|
||||
* <a href="doc-files/generatedfiles.html#helper">
|
||||
* "Generated Files: Helper Files"</a>.<P>
|
||||
*/
|
||||
|
||||
abstract public class BadKindHelper
|
||||
{
|
||||
private static String _id = "IDL:omg.org.CORBA/TypeCode/BadKind:1.0";
|
||||
|
||||
public static void insert (org.omg.CORBA.Any a, org.omg.CORBA.TypeCodePackage.BadKind that)
|
||||
{
|
||||
org.omg.CORBA.portable.OutputStream out = a.create_output_stream ();
|
||||
a.type (type ());
|
||||
write (out, that);
|
||||
a.read_value (out.create_input_stream (), type ());
|
||||
}
|
||||
|
||||
public static org.omg.CORBA.TypeCodePackage.BadKind extract (org.omg.CORBA.Any a)
|
||||
{
|
||||
return read (a.create_input_stream ());
|
||||
}
|
||||
|
||||
private static org.omg.CORBA.TypeCode __typeCode = null;
|
||||
private static boolean __active = false;
|
||||
synchronized public static org.omg.CORBA.TypeCode type ()
|
||||
{
|
||||
if (__typeCode == null)
|
||||
{
|
||||
synchronized (org.omg.CORBA.TypeCode.class)
|
||||
{
|
||||
if (__typeCode == null)
|
||||
{
|
||||
if (__active)
|
||||
{
|
||||
return org.omg.CORBA.ORB.init().create_recursive_tc ( _id );
|
||||
}
|
||||
__active = true;
|
||||
org.omg.CORBA.StructMember[] _members0 = new org.omg.CORBA.StructMember [0];
|
||||
org.omg.CORBA.TypeCode _tcOf_members0 = null;
|
||||
__typeCode = org.omg.CORBA.ORB.init ().create_exception_tc (org.omg.CORBA.TypeCodePackage.BadKindHelper.id (), "BadKind", _members0);
|
||||
__active = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return __typeCode;
|
||||
}
|
||||
|
||||
public static String id ()
|
||||
{
|
||||
return _id;
|
||||
}
|
||||
|
||||
public static org.omg.CORBA.TypeCodePackage.BadKind read (org.omg.CORBA.portable.InputStream istream)
|
||||
{
|
||||
org.omg.CORBA.TypeCodePackage.BadKind value = new org.omg.CORBA.TypeCodePackage.BadKind ();
|
||||
// read and discard the repository ID
|
||||
istream.read_string ();
|
||||
return value;
|
||||
}
|
||||
|
||||
public static void write (org.omg.CORBA.portable.OutputStream ostream, org.omg.CORBA.TypeCodePackage.BadKind value)
|
||||
{
|
||||
// write the repository ID
|
||||
ostream.write_string (id ());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* 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. 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 org.omg.CORBA.TypeCodePackage;
|
||||
|
||||
|
||||
/**
|
||||
* This Helper class is used to facilitate the marshalling of
|
||||
* <tt>TypeCodePackage/Bounds</tt>.
|
||||
* For more information on Helper files, see
|
||||
* <a href="doc-files/generatedfiles.html#helper">
|
||||
* "Generated Files: Helper Files"</a>.<P>
|
||||
*/
|
||||
|
||||
abstract public class BoundsHelper
|
||||
{
|
||||
private static String _id = "IDL:omg.org.CORBA/TypeCode/Bounds:1.0";
|
||||
|
||||
public static void insert (org.omg.CORBA.Any a, org.omg.CORBA.TypeCodePackage.Bounds that)
|
||||
{
|
||||
org.omg.CORBA.portable.OutputStream out = a.create_output_stream ();
|
||||
a.type (type ());
|
||||
write (out, that);
|
||||
a.read_value (out.create_input_stream (), type ());
|
||||
}
|
||||
|
||||
public static org.omg.CORBA.TypeCodePackage.Bounds extract (org.omg.CORBA.Any a)
|
||||
{
|
||||
return read (a.create_input_stream ());
|
||||
}
|
||||
|
||||
private static org.omg.CORBA.TypeCode __typeCode = null;
|
||||
private static boolean __active = false;
|
||||
synchronized public static org.omg.CORBA.TypeCode type ()
|
||||
{
|
||||
if (__typeCode == null)
|
||||
{
|
||||
synchronized (org.omg.CORBA.TypeCode.class)
|
||||
{
|
||||
if (__typeCode == null)
|
||||
{
|
||||
if (__active)
|
||||
{
|
||||
return org.omg.CORBA.ORB.init().create_recursive_tc ( _id );
|
||||
}
|
||||
__active = true;
|
||||
org.omg.CORBA.StructMember[] _members0 = new org.omg.CORBA.StructMember [0];
|
||||
org.omg.CORBA.TypeCode _tcOf_members0 = null;
|
||||
__typeCode = org.omg.CORBA.ORB.init ().create_exception_tc (org.omg.CORBA.TypeCodePackage.BoundsHelper.id (), "Bounds", _members0);
|
||||
__active = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return __typeCode;
|
||||
}
|
||||
|
||||
public static String id ()
|
||||
{
|
||||
return _id;
|
||||
}
|
||||
|
||||
public static org.omg.CORBA.TypeCodePackage.Bounds read (org.omg.CORBA.portable.InputStream istream)
|
||||
{
|
||||
org.omg.CORBA.TypeCodePackage.Bounds value = new org.omg.CORBA.TypeCodePackage.Bounds ();
|
||||
// read and discard the repository ID
|
||||
istream.read_string ();
|
||||
return value;
|
||||
}
|
||||
|
||||
public static void write (org.omg.CORBA.portable.OutputStream ostream, org.omg.CORBA.TypeCodePackage.Bounds value)
|
||||
{
|
||||
// write the repository ID
|
||||
ostream.write_string (id ());
|
||||
}
|
||||
|
||||
}
|
@ -470,3 +470,5 @@ bf92b8db249cdfa5651ef954b6c0743a7e0ea4cd jdk9-b64
|
||||
e7ae94c4f35e940ea423fc1dd260435df34a77c0 jdk9-b65
|
||||
197e94e0dacddd16816f101d24fc0442ab518326 jdk9-b66
|
||||
d47dfabd16d48eb96a451edd1b61194a39ee0eb5 jdk9-b67
|
||||
11af3990d56c97b40318bc1f20608e86f051a3f7 jdk9-b68
|
||||
ff0929a59ced0e144201aa05819ae2e47d6f2c61 jdk9-b69
|
||||
|
@ -31,8 +31,8 @@ ifndef OPENJDK
|
||||
REASON = "This JDK does not support SDT probes"
|
||||
else
|
||||
|
||||
# We need a recent GCC for the default
|
||||
ifeq "$(shell expr \( $(CC_VER_MAJOR) \>= 4 \) \& \( $(CC_VER_MINOR) \>= 4 \) )" "0"
|
||||
# We need a recent GCC for the default (4.4 or later)
|
||||
ifeq "$(shell expr \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 4 \) \) \| \( $(CC_VER_MAJOR) \>= 5 \) )" "0"
|
||||
REASON = "gcc version is too old"
|
||||
else
|
||||
|
||||
|
@ -44,6 +44,7 @@ BUILD_HOTSPOT_JTREG_NATIVE_SRC := \
|
||||
$(HOTSPOT_TOPDIR)/test/native_sanity \
|
||||
$(HOTSPOT_TOPDIR)/test/runtime/jni/8025979 \
|
||||
$(HOTSPOT_TOPDIR)/test/runtime/jni/8033445 \
|
||||
$(HOTSPOT_TOPDIR)/test/runtime/jni/ToStringInInterfaceTest \
|
||||
#
|
||||
|
||||
BUILD_HOTSPOT_JTREG_OUTPUT_DIR := $(BUILD_OUTPUT)/support/test/hotspot/jtreg/native
|
||||
|
@ -3372,6 +3372,25 @@ operand immI() %{
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate: 0-bit
|
||||
operand immI0() %{
|
||||
predicate(n->get_int() == 0);
|
||||
match(ConI);
|
||||
op_cost(0);
|
||||
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate: 5-bit
|
||||
operand immI5() %{
|
||||
predicate(Assembler::is_simm5(n->get_int()));
|
||||
match(ConI);
|
||||
op_cost(0);
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate: 8-bit
|
||||
operand immI8() %{
|
||||
predicate(Assembler::is_simm8(n->get_int()));
|
||||
@ -3381,6 +3400,25 @@ operand immI8() %{
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate: the value 10
|
||||
operand immI10() %{
|
||||
predicate(n->get_int() == 10);
|
||||
match(ConI);
|
||||
op_cost(0);
|
||||
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate: 11-bit
|
||||
operand immI11() %{
|
||||
predicate(Assembler::is_simm11(n->get_int()));
|
||||
match(ConI);
|
||||
op_cost(0);
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate: 13-bit
|
||||
operand immI13() %{
|
||||
predicate(Assembler::is_simm13(n->get_int()));
|
||||
@ -3410,84 +3448,6 @@ operand immI16() %{
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Unsigned Integer Immediate: 12-bit (non-negative that fits in simm13)
|
||||
operand immU12() %{
|
||||
predicate((0 <= n->get_int()) && Assembler::is_simm13(n->get_int()));
|
||||
match(ConI);
|
||||
op_cost(0);
|
||||
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate: 6-bit
|
||||
operand immU6() %{
|
||||
predicate(n->get_int() >= 0 && n->get_int() <= 63);
|
||||
match(ConI);
|
||||
op_cost(0);
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate: 11-bit
|
||||
operand immI11() %{
|
||||
predicate(Assembler::is_simm11(n->get_int()));
|
||||
match(ConI);
|
||||
op_cost(0);
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate: 5-bit
|
||||
operand immI5() %{
|
||||
predicate(Assembler::is_simm5(n->get_int()));
|
||||
match(ConI);
|
||||
op_cost(0);
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Int Immediate non-negative
|
||||
operand immU31()
|
||||
%{
|
||||
predicate(n->get_int() >= 0);
|
||||
match(ConI);
|
||||
|
||||
op_cost(0);
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate: 0-bit
|
||||
operand immI0() %{
|
||||
predicate(n->get_int() == 0);
|
||||
match(ConI);
|
||||
op_cost(0);
|
||||
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate: the value 10
|
||||
operand immI10() %{
|
||||
predicate(n->get_int() == 10);
|
||||
match(ConI);
|
||||
op_cost(0);
|
||||
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate: the values 0-31
|
||||
operand immU5() %{
|
||||
predicate(n->get_int() >= 0 && n->get_int() <= 31);
|
||||
match(ConI);
|
||||
op_cost(0);
|
||||
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate: the values 1-31
|
||||
operand immI_1_31() %{
|
||||
predicate(n->get_int() >= 1 && n->get_int() <= 31);
|
||||
@ -3529,7 +3489,6 @@ operand immI_24() %{
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate: the value 255
|
||||
operand immI_255() %{
|
||||
predicate( n->get_int() == 255 );
|
||||
@ -3550,6 +3509,46 @@ operand immI_65535() %{
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate: the values 0-31
|
||||
operand immU5() %{
|
||||
predicate(n->get_int() >= 0 && n->get_int() <= 31);
|
||||
match(ConI);
|
||||
op_cost(0);
|
||||
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate: 6-bit
|
||||
operand immU6() %{
|
||||
predicate(n->get_int() >= 0 && n->get_int() <= 63);
|
||||
match(ConI);
|
||||
op_cost(0);
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Unsigned Integer Immediate: 12-bit (non-negative that fits in simm13)
|
||||
operand immU12() %{
|
||||
predicate((0 <= n->get_int()) && Assembler::is_simm13(n->get_int()));
|
||||
match(ConI);
|
||||
op_cost(0);
|
||||
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate non-negative
|
||||
operand immU31()
|
||||
%{
|
||||
predicate(n->get_int() >= 0);
|
||||
match(ConI);
|
||||
|
||||
op_cost(0);
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Long Immediate: the value FF
|
||||
operand immL_FF() %{
|
||||
predicate( n->get_long() == 0xFFL );
|
||||
@ -5653,17 +5652,17 @@ instruct loadUB2L(iRegL dst, memory mem) %{
|
||||
ins_pipe(iload_mem);
|
||||
%}
|
||||
|
||||
// Load Unsigned Byte (8 bit UNsigned) with 8-bit mask into Long Register
|
||||
instruct loadUB2L_immI8(iRegL dst, memory mem, immI8 mask) %{
|
||||
// Load Unsigned Byte (8 bit UNsigned) with 32-bit mask into Long Register
|
||||
instruct loadUB2L_immI(iRegL dst, memory mem, immI mask) %{
|
||||
match(Set dst (ConvI2L (AndI (LoadUB mem) mask)));
|
||||
ins_cost(MEMORY_REF_COST + DEFAULT_COST);
|
||||
|
||||
size(2*4);
|
||||
format %{ "LDUB $mem,$dst\t# ubyte & 8-bit mask -> long\n\t"
|
||||
"AND $dst,$mask,$dst" %}
|
||||
format %{ "LDUB $mem,$dst\t# ubyte & 32-bit mask -> long\n\t"
|
||||
"AND $dst,right_n_bits($mask, 8),$dst" %}
|
||||
ins_encode %{
|
||||
__ ldub($mem$$Address, $dst$$Register);
|
||||
__ and3($dst$$Register, $mask$$constant, $dst$$Register);
|
||||
__ and3($dst$$Register, $mask$$constant & right_n_bits(8), $dst$$Register);
|
||||
%}
|
||||
ins_pipe(iload_mem);
|
||||
%}
|
||||
@ -5776,20 +5775,20 @@ instruct loadUS2L_immI13(iRegL dst, memory mem, immI13 mask) %{
|
||||
ins_pipe(iload_mem);
|
||||
%}
|
||||
|
||||
// Load Unsigned Short/Char (16bit UNsigned) with a 16-bit mask into a Long Register
|
||||
instruct loadUS2L_immI16(iRegL dst, memory mem, immI16 mask, iRegL tmp) %{
|
||||
// Load Unsigned Short/Char (16bit UNsigned) with a 32-bit mask into a Long Register
|
||||
instruct loadUS2L_immI(iRegL dst, memory mem, immI mask, iRegL tmp) %{
|
||||
match(Set dst (ConvI2L (AndI (LoadUS mem) mask)));
|
||||
effect(TEMP dst, TEMP tmp);
|
||||
ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST);
|
||||
|
||||
format %{ "LDUH $mem,$dst\t! ushort/char & 16-bit mask -> long\n\t"
|
||||
"SET $mask,$tmp\n\t"
|
||||
format %{ "LDUH $mem,$dst\t! ushort/char & 32-bit mask -> long\n\t"
|
||||
"SET right_n_bits($mask, 16),$tmp\n\t"
|
||||
"AND $dst,$tmp,$dst" %}
|
||||
ins_encode %{
|
||||
Register Rdst = $dst$$Register;
|
||||
Register Rtmp = $tmp$$Register;
|
||||
__ lduh($mem$$Address, Rdst);
|
||||
__ set($mask$$constant, Rtmp);
|
||||
__ set($mask$$constant & right_n_bits(16), Rtmp);
|
||||
__ and3(Rdst, Rtmp, Rdst);
|
||||
%}
|
||||
ins_pipe(iload_mem);
|
||||
|
@ -2813,6 +2813,13 @@ void Assembler::orl(Register dst, Register src) {
|
||||
emit_arith(0x0B, 0xC0, dst, src);
|
||||
}
|
||||
|
||||
void Assembler::orl(Address dst, Register src) {
|
||||
InstructionMark im(this);
|
||||
prefix(dst, src);
|
||||
emit_int8(0x09);
|
||||
emit_operand(src, dst);
|
||||
}
|
||||
|
||||
void Assembler::packuswb(XMMRegister dst, Address src) {
|
||||
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
|
||||
assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes");
|
||||
@ -6907,6 +6914,19 @@ void Assembler::rclq(Register dst, int imm8) {
|
||||
}
|
||||
}
|
||||
|
||||
void Assembler::rcrq(Register dst, int imm8) {
|
||||
assert(isShiftCount(imm8 >> 1), "illegal shift count");
|
||||
int encode = prefixq_and_encode(dst->encoding());
|
||||
if (imm8 == 1) {
|
||||
emit_int8((unsigned char)0xD1);
|
||||
emit_int8((unsigned char)(0xD8 | encode));
|
||||
} else {
|
||||
emit_int8((unsigned char)0xC1);
|
||||
emit_int8((unsigned char)(0xD8 | encode));
|
||||
emit_int8(imm8);
|
||||
}
|
||||
}
|
||||
|
||||
void Assembler::rorq(Register dst, int imm8) {
|
||||
assert(isShiftCount(imm8 >> 1), "illegal shift count");
|
||||
int encode = prefixq_and_encode(dst->encoding());
|
||||
|
@ -1594,6 +1594,7 @@ private:
|
||||
void orl(Register dst, int32_t imm32);
|
||||
void orl(Register dst, Address src);
|
||||
void orl(Register dst, Register src);
|
||||
void orl(Address dst, Register src);
|
||||
|
||||
void orq(Address dst, int32_t imm32);
|
||||
void orq(Register dst, int32_t imm32);
|
||||
@ -1694,6 +1695,8 @@ private:
|
||||
|
||||
void rclq(Register dst, int imm8);
|
||||
|
||||
void rcrq(Register dst, int imm8);
|
||||
|
||||
void rdtsc();
|
||||
|
||||
void ret(int imm16);
|
||||
|
@ -7750,6 +7750,503 @@ void MacroAssembler::multiply_to_len(Register x, Register xlen, Register y, Regi
|
||||
pop(tmp2);
|
||||
pop(tmp1);
|
||||
}
|
||||
|
||||
//Helper functions for square_to_len()
|
||||
|
||||
/**
|
||||
* Store the squares of x[], right shifted one bit (divided by 2) into z[]
|
||||
* Preserves x and z and modifies rest of the registers.
|
||||
*/
|
||||
|
||||
void MacroAssembler::square_rshift(Register x, Register xlen, Register z, Register tmp1, Register tmp3, Register tmp4, Register tmp5, Register rdxReg, Register raxReg) {
|
||||
// Perform square and right shift by 1
|
||||
// Handle odd xlen case first, then for even xlen do the following
|
||||
// jlong carry = 0;
|
||||
// for (int j=0, i=0; j < xlen; j+=2, i+=4) {
|
||||
// huge_128 product = x[j:j+1] * x[j:j+1];
|
||||
// z[i:i+1] = (carry << 63) | (jlong)(product >>> 65);
|
||||
// z[i+2:i+3] = (jlong)(product >>> 1);
|
||||
// carry = (jlong)product;
|
||||
// }
|
||||
|
||||
xorq(tmp5, tmp5); // carry
|
||||
xorq(rdxReg, rdxReg);
|
||||
xorl(tmp1, tmp1); // index for x
|
||||
xorl(tmp4, tmp4); // index for z
|
||||
|
||||
Label L_first_loop, L_first_loop_exit;
|
||||
|
||||
testl(xlen, 1);
|
||||
jccb(Assembler::zero, L_first_loop); //jump if xlen is even
|
||||
|
||||
// Square and right shift by 1 the odd element using 32 bit multiply
|
||||
movl(raxReg, Address(x, tmp1, Address::times_4, 0));
|
||||
imulq(raxReg, raxReg);
|
||||
shrq(raxReg, 1);
|
||||
adcq(tmp5, 0);
|
||||
movq(Address(z, tmp4, Address::times_4, 0), raxReg);
|
||||
incrementl(tmp1);
|
||||
addl(tmp4, 2);
|
||||
|
||||
// Square and right shift by 1 the rest using 64 bit multiply
|
||||
bind(L_first_loop);
|
||||
cmpptr(tmp1, xlen);
|
||||
jccb(Assembler::equal, L_first_loop_exit);
|
||||
|
||||
// Square
|
||||
movq(raxReg, Address(x, tmp1, Address::times_4, 0));
|
||||
rorq(raxReg, 32); // convert big-endian to little-endian
|
||||
mulq(raxReg); // 64-bit multiply rax * rax -> rdx:rax
|
||||
|
||||
// Right shift by 1 and save carry
|
||||
shrq(tmp5, 1); // rdx:rax:tmp5 = (tmp5:rdx:rax) >>> 1
|
||||
rcrq(rdxReg, 1);
|
||||
rcrq(raxReg, 1);
|
||||
adcq(tmp5, 0);
|
||||
|
||||
// Store result in z
|
||||
movq(Address(z, tmp4, Address::times_4, 0), rdxReg);
|
||||
movq(Address(z, tmp4, Address::times_4, 8), raxReg);
|
||||
|
||||
// Update indices for x and z
|
||||
addl(tmp1, 2);
|
||||
addl(tmp4, 4);
|
||||
jmp(L_first_loop);
|
||||
|
||||
bind(L_first_loop_exit);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Perform the following multiply add operation using BMI2 instructions
|
||||
* carry:sum = sum + op1*op2 + carry
|
||||
* op2 should be in rdx
|
||||
* op2 is preserved, all other registers are modified
|
||||
*/
|
||||
void MacroAssembler::multiply_add_64_bmi2(Register sum, Register op1, Register op2, Register carry, Register tmp2) {
|
||||
// assert op2 is rdx
|
||||
mulxq(tmp2, op1, op1); // op1 * op2 -> tmp2:op1
|
||||
addq(sum, carry);
|
||||
adcq(tmp2, 0);
|
||||
addq(sum, op1);
|
||||
adcq(tmp2, 0);
|
||||
movq(carry, tmp2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the following multiply add operation:
|
||||
* carry:sum = sum + op1*op2 + carry
|
||||
* Preserves op1, op2 and modifies rest of registers
|
||||
*/
|
||||
void MacroAssembler::multiply_add_64(Register sum, Register op1, Register op2, Register carry, Register rdxReg, Register raxReg) {
|
||||
// rdx:rax = op1 * op2
|
||||
movq(raxReg, op2);
|
||||
mulq(op1);
|
||||
|
||||
// rdx:rax = sum + carry + rdx:rax
|
||||
addq(sum, carry);
|
||||
adcq(rdxReg, 0);
|
||||
addq(sum, raxReg);
|
||||
adcq(rdxReg, 0);
|
||||
|
||||
// carry:sum = rdx:sum
|
||||
movq(carry, rdxReg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add 64 bit long carry into z[] with carry propogation.
|
||||
* Preserves z and carry register values and modifies rest of registers.
|
||||
*
|
||||
*/
|
||||
void MacroAssembler::add_one_64(Register z, Register zlen, Register carry, Register tmp1) {
|
||||
Label L_fourth_loop, L_fourth_loop_exit;
|
||||
|
||||
movl(tmp1, 1);
|
||||
subl(zlen, 2);
|
||||
addq(Address(z, zlen, Address::times_4, 0), carry);
|
||||
|
||||
bind(L_fourth_loop);
|
||||
jccb(Assembler::carryClear, L_fourth_loop_exit);
|
||||
subl(zlen, 2);
|
||||
jccb(Assembler::negative, L_fourth_loop_exit);
|
||||
addq(Address(z, zlen, Address::times_4, 0), tmp1);
|
||||
jmp(L_fourth_loop);
|
||||
bind(L_fourth_loop_exit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shift z[] left by 1 bit.
|
||||
* Preserves x, len, z and zlen registers and modifies rest of the registers.
|
||||
*
|
||||
*/
|
||||
void MacroAssembler::lshift_by_1(Register x, Register len, Register z, Register zlen, Register tmp1, Register tmp2, Register tmp3, Register tmp4) {
|
||||
|
||||
Label L_fifth_loop, L_fifth_loop_exit;
|
||||
|
||||
// Fifth loop
|
||||
// Perform primitiveLeftShift(z, zlen, 1)
|
||||
|
||||
const Register prev_carry = tmp1;
|
||||
const Register new_carry = tmp4;
|
||||
const Register value = tmp2;
|
||||
const Register zidx = tmp3;
|
||||
|
||||
// int zidx, carry;
|
||||
// long value;
|
||||
// carry = 0;
|
||||
// for (zidx = zlen-2; zidx >=0; zidx -= 2) {
|
||||
// (carry:value) = (z[i] << 1) | carry ;
|
||||
// z[i] = value;
|
||||
// }
|
||||
|
||||
movl(zidx, zlen);
|
||||
xorl(prev_carry, prev_carry); // clear carry flag and prev_carry register
|
||||
|
||||
bind(L_fifth_loop);
|
||||
decl(zidx); // Use decl to preserve carry flag
|
||||
decl(zidx);
|
||||
jccb(Assembler::negative, L_fifth_loop_exit);
|
||||
|
||||
if (UseBMI2Instructions) {
|
||||
movq(value, Address(z, zidx, Address::times_4, 0));
|
||||
rclq(value, 1);
|
||||
rorxq(value, value, 32);
|
||||
movq(Address(z, zidx, Address::times_4, 0), value); // Store back in big endian form
|
||||
}
|
||||
else {
|
||||
// clear new_carry
|
||||
xorl(new_carry, new_carry);
|
||||
|
||||
// Shift z[i] by 1, or in previous carry and save new carry
|
||||
movq(value, Address(z, zidx, Address::times_4, 0));
|
||||
shlq(value, 1);
|
||||
adcl(new_carry, 0);
|
||||
|
||||
orq(value, prev_carry);
|
||||
rorq(value, 0x20);
|
||||
movq(Address(z, zidx, Address::times_4, 0), value); // Store back in big endian form
|
||||
|
||||
// Set previous carry = new carry
|
||||
movl(prev_carry, new_carry);
|
||||
}
|
||||
jmp(L_fifth_loop);
|
||||
|
||||
bind(L_fifth_loop_exit);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Code for BigInteger::squareToLen() intrinsic
|
||||
*
|
||||
* rdi: x
|
||||
* rsi: len
|
||||
* r8: z
|
||||
* rcx: zlen
|
||||
* r12: tmp1
|
||||
* r13: tmp2
|
||||
* r14: tmp3
|
||||
* r15: tmp4
|
||||
* rbx: tmp5
|
||||
*
|
||||
*/
|
||||
void MacroAssembler::square_to_len(Register x, Register len, Register z, Register zlen, Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5, Register rdxReg, Register raxReg) {
|
||||
|
||||
Label L_second_loop, L_second_loop_exit, L_third_loop, L_third_loop_exit, fifth_loop, fifth_loop_exit, L_last_x, L_multiply;
|
||||
push(tmp1);
|
||||
push(tmp2);
|
||||
push(tmp3);
|
||||
push(tmp4);
|
||||
push(tmp5);
|
||||
|
||||
// First loop
|
||||
// Store the squares, right shifted one bit (i.e., divided by 2).
|
||||
square_rshift(x, len, z, tmp1, tmp3, tmp4, tmp5, rdxReg, raxReg);
|
||||
|
||||
// Add in off-diagonal sums.
|
||||
//
|
||||
// Second, third (nested) and fourth loops.
|
||||
// zlen +=2;
|
||||
// for (int xidx=len-2,zidx=zlen-4; xidx > 0; xidx-=2,zidx-=4) {
|
||||
// carry = 0;
|
||||
// long op2 = x[xidx:xidx+1];
|
||||
// for (int j=xidx-2,k=zidx; j >= 0; j-=2) {
|
||||
// k -= 2;
|
||||
// long op1 = x[j:j+1];
|
||||
// long sum = z[k:k+1];
|
||||
// carry:sum = multiply_add_64(sum, op1, op2, carry, tmp_regs);
|
||||
// z[k:k+1] = sum;
|
||||
// }
|
||||
// add_one_64(z, k, carry, tmp_regs);
|
||||
// }
|
||||
|
||||
const Register carry = tmp5;
|
||||
const Register sum = tmp3;
|
||||
const Register op1 = tmp4;
|
||||
Register op2 = tmp2;
|
||||
|
||||
push(zlen);
|
||||
push(len);
|
||||
addl(zlen,2);
|
||||
bind(L_second_loop);
|
||||
xorq(carry, carry);
|
||||
subl(zlen, 4);
|
||||
subl(len, 2);
|
||||
push(zlen);
|
||||
push(len);
|
||||
cmpl(len, 0);
|
||||
jccb(Assembler::lessEqual, L_second_loop_exit);
|
||||
|
||||
// Multiply an array by one 64 bit long.
|
||||
if (UseBMI2Instructions) {
|
||||
op2 = rdxReg;
|
||||
movq(op2, Address(x, len, Address::times_4, 0));
|
||||
rorxq(op2, op2, 32);
|
||||
}
|
||||
else {
|
||||
movq(op2, Address(x, len, Address::times_4, 0));
|
||||
rorq(op2, 32);
|
||||
}
|
||||
|
||||
bind(L_third_loop);
|
||||
decrementl(len);
|
||||
jccb(Assembler::negative, L_third_loop_exit);
|
||||
decrementl(len);
|
||||
jccb(Assembler::negative, L_last_x);
|
||||
|
||||
movq(op1, Address(x, len, Address::times_4, 0));
|
||||
rorq(op1, 32);
|
||||
|
||||
bind(L_multiply);
|
||||
subl(zlen, 2);
|
||||
movq(sum, Address(z, zlen, Address::times_4, 0));
|
||||
|
||||
// Multiply 64 bit by 64 bit and add 64 bits lower half and upper 64 bits as carry.
|
||||
if (UseBMI2Instructions) {
|
||||
multiply_add_64_bmi2(sum, op1, op2, carry, tmp2);
|
||||
}
|
||||
else {
|
||||
multiply_add_64(sum, op1, op2, carry, rdxReg, raxReg);
|
||||
}
|
||||
|
||||
movq(Address(z, zlen, Address::times_4, 0), sum);
|
||||
|
||||
jmp(L_third_loop);
|
||||
bind(L_third_loop_exit);
|
||||
|
||||
// Fourth loop
|
||||
// Add 64 bit long carry into z with carry propogation.
|
||||
// Uses offsetted zlen.
|
||||
add_one_64(z, zlen, carry, tmp1);
|
||||
|
||||
pop(len);
|
||||
pop(zlen);
|
||||
jmp(L_second_loop);
|
||||
|
||||
// Next infrequent code is moved outside loops.
|
||||
bind(L_last_x);
|
||||
movl(op1, Address(x, 0));
|
||||
jmp(L_multiply);
|
||||
|
||||
bind(L_second_loop_exit);
|
||||
pop(len);
|
||||
pop(zlen);
|
||||
pop(len);
|
||||
pop(zlen);
|
||||
|
||||
// Fifth loop
|
||||
// Shift z left 1 bit.
|
||||
lshift_by_1(x, len, z, zlen, tmp1, tmp2, tmp3, tmp4);
|
||||
|
||||
// z[zlen-1] |= x[len-1] & 1;
|
||||
movl(tmp3, Address(x, len, Address::times_4, -4));
|
||||
andl(tmp3, 1);
|
||||
orl(Address(z, zlen, Address::times_4, -4), tmp3);
|
||||
|
||||
pop(tmp5);
|
||||
pop(tmp4);
|
||||
pop(tmp3);
|
||||
pop(tmp2);
|
||||
pop(tmp1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for mul_add()
|
||||
* Multiply the in[] by int k and add to out[] starting at offset offs using
|
||||
* 128 bit by 32 bit multiply and return the carry in tmp5.
|
||||
* Only quad int aligned length of in[] is operated on in this function.
|
||||
* k is in rdxReg for BMI2Instructions, for others it is in tmp2.
|
||||
* This function preserves out, in and k registers.
|
||||
* len and offset point to the appropriate index in "in" & "out" correspondingly
|
||||
* tmp5 has the carry.
|
||||
* other registers are temporary and are modified.
|
||||
*
|
||||
*/
|
||||
void MacroAssembler::mul_add_128_x_32_loop(Register out, Register in,
|
||||
Register offset, Register len, Register tmp1, Register tmp2, Register tmp3,
|
||||
Register tmp4, Register tmp5, Register rdxReg, Register raxReg) {
|
||||
|
||||
Label L_first_loop, L_first_loop_exit;
|
||||
|
||||
movl(tmp1, len);
|
||||
shrl(tmp1, 2);
|
||||
|
||||
bind(L_first_loop);
|
||||
subl(tmp1, 1);
|
||||
jccb(Assembler::negative, L_first_loop_exit);
|
||||
|
||||
subl(len, 4);
|
||||
subl(offset, 4);
|
||||
|
||||
Register op2 = tmp2;
|
||||
const Register sum = tmp3;
|
||||
const Register op1 = tmp4;
|
||||
const Register carry = tmp5;
|
||||
|
||||
if (UseBMI2Instructions) {
|
||||
op2 = rdxReg;
|
||||
}
|
||||
|
||||
movq(op1, Address(in, len, Address::times_4, 8));
|
||||
rorq(op1, 32);
|
||||
movq(sum, Address(out, offset, Address::times_4, 8));
|
||||
rorq(sum, 32);
|
||||
if (UseBMI2Instructions) {
|
||||
multiply_add_64_bmi2(sum, op1, op2, carry, raxReg);
|
||||
}
|
||||
else {
|
||||
multiply_add_64(sum, op1, op2, carry, rdxReg, raxReg);
|
||||
}
|
||||
// Store back in big endian from little endian
|
||||
rorq(sum, 0x20);
|
||||
movq(Address(out, offset, Address::times_4, 8), sum);
|
||||
|
||||
movq(op1, Address(in, len, Address::times_4, 0));
|
||||
rorq(op1, 32);
|
||||
movq(sum, Address(out, offset, Address::times_4, 0));
|
||||
rorq(sum, 32);
|
||||
if (UseBMI2Instructions) {
|
||||
multiply_add_64_bmi2(sum, op1, op2, carry, raxReg);
|
||||
}
|
||||
else {
|
||||
multiply_add_64(sum, op1, op2, carry, rdxReg, raxReg);
|
||||
}
|
||||
// Store back in big endian from little endian
|
||||
rorq(sum, 0x20);
|
||||
movq(Address(out, offset, Address::times_4, 0), sum);
|
||||
|
||||
jmp(L_first_loop);
|
||||
bind(L_first_loop_exit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Code for BigInteger::mulAdd() intrinsic
|
||||
*
|
||||
* rdi: out
|
||||
* rsi: in
|
||||
* r11: offs (out.length - offset)
|
||||
* rcx: len
|
||||
* r8: k
|
||||
* r12: tmp1
|
||||
* r13: tmp2
|
||||
* r14: tmp3
|
||||
* r15: tmp4
|
||||
* rbx: tmp5
|
||||
* Multiply the in[] by word k and add to out[], return the carry in rax
|
||||
*/
|
||||
void MacroAssembler::mul_add(Register out, Register in, Register offs,
|
||||
Register len, Register k, Register tmp1, Register tmp2, Register tmp3,
|
||||
Register tmp4, Register tmp5, Register rdxReg, Register raxReg) {
|
||||
|
||||
Label L_carry, L_last_in, L_done;
|
||||
|
||||
// carry = 0;
|
||||
// for (int j=len-1; j >= 0; j--) {
|
||||
// long product = (in[j] & LONG_MASK) * kLong +
|
||||
// (out[offs] & LONG_MASK) + carry;
|
||||
// out[offs--] = (int)product;
|
||||
// carry = product >>> 32;
|
||||
// }
|
||||
//
|
||||
push(tmp1);
|
||||
push(tmp2);
|
||||
push(tmp3);
|
||||
push(tmp4);
|
||||
push(tmp5);
|
||||
|
||||
Register op2 = tmp2;
|
||||
const Register sum = tmp3;
|
||||
const Register op1 = tmp4;
|
||||
const Register carry = tmp5;
|
||||
|
||||
if (UseBMI2Instructions) {
|
||||
op2 = rdxReg;
|
||||
movl(op2, k);
|
||||
}
|
||||
else {
|
||||
movl(op2, k);
|
||||
}
|
||||
|
||||
xorq(carry, carry);
|
||||
|
||||
//First loop
|
||||
|
||||
//Multiply in[] by k in a 4 way unrolled loop using 128 bit by 32 bit multiply
|
||||
//The carry is in tmp5
|
||||
mul_add_128_x_32_loop(out, in, offs, len, tmp1, tmp2, tmp3, tmp4, tmp5, rdxReg, raxReg);
|
||||
|
||||
//Multiply the trailing in[] entry using 64 bit by 32 bit, if any
|
||||
decrementl(len);
|
||||
jccb(Assembler::negative, L_carry);
|
||||
decrementl(len);
|
||||
jccb(Assembler::negative, L_last_in);
|
||||
|
||||
movq(op1, Address(in, len, Address::times_4, 0));
|
||||
rorq(op1, 32);
|
||||
|
||||
subl(offs, 2);
|
||||
movq(sum, Address(out, offs, Address::times_4, 0));
|
||||
rorq(sum, 32);
|
||||
|
||||
if (UseBMI2Instructions) {
|
||||
multiply_add_64_bmi2(sum, op1, op2, carry, raxReg);
|
||||
}
|
||||
else {
|
||||
multiply_add_64(sum, op1, op2, carry, rdxReg, raxReg);
|
||||
}
|
||||
|
||||
// Store back in big endian from little endian
|
||||
rorq(sum, 0x20);
|
||||
movq(Address(out, offs, Address::times_4, 0), sum);
|
||||
|
||||
testl(len, len);
|
||||
jccb(Assembler::zero, L_carry);
|
||||
|
||||
//Multiply the last in[] entry, if any
|
||||
bind(L_last_in);
|
||||
movl(op1, Address(in, 0));
|
||||
movl(sum, Address(out, offs, Address::times_4, -4));
|
||||
|
||||
movl(raxReg, k);
|
||||
mull(op1); //tmp4 * eax -> edx:eax
|
||||
addl(sum, carry);
|
||||
adcl(rdxReg, 0);
|
||||
addl(sum, raxReg);
|
||||
adcl(rdxReg, 0);
|
||||
movl(carry, rdxReg);
|
||||
|
||||
movl(Address(out, offs, Address::times_4, -4), sum);
|
||||
|
||||
bind(L_carry);
|
||||
//return tmp5/carry as carry in rax
|
||||
movl(rax, carry);
|
||||
|
||||
bind(L_done);
|
||||
pop(tmp5);
|
||||
pop(tmp4);
|
||||
pop(tmp3);
|
||||
pop(tmp2);
|
||||
pop(tmp1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
@ -1241,6 +1241,25 @@ public:
|
||||
Register carry2);
|
||||
void multiply_to_len(Register x, Register xlen, Register y, Register ylen, Register z, Register zlen,
|
||||
Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5);
|
||||
|
||||
void square_rshift(Register x, Register len, Register z, Register tmp1, Register tmp3,
|
||||
Register tmp4, Register tmp5, Register rdxReg, Register raxReg);
|
||||
void multiply_add_64_bmi2(Register sum, Register op1, Register op2, Register carry,
|
||||
Register tmp2);
|
||||
void multiply_add_64(Register sum, Register op1, Register op2, Register carry,
|
||||
Register rdxReg, Register raxReg);
|
||||
void add_one_64(Register z, Register zlen, Register carry, Register tmp1);
|
||||
void lshift_by_1(Register x, Register len, Register z, Register zlen, Register tmp1, Register tmp2,
|
||||
Register tmp3, Register tmp4);
|
||||
void square_to_len(Register x, Register len, Register z, Register zlen, Register tmp1, Register tmp2,
|
||||
Register tmp3, Register tmp4, Register tmp5, Register rdxReg, Register raxReg);
|
||||
|
||||
void mul_add_128_x_32_loop(Register out, Register in, Register offset, Register len, Register tmp1,
|
||||
Register tmp2, Register tmp3, Register tmp4, Register tmp5, Register rdxReg,
|
||||
Register raxReg);
|
||||
void mul_add(Register out, Register in, Register offset, Register len, Register k, Register tmp1,
|
||||
Register tmp2, Register tmp3, Register tmp4, Register tmp5, Register rdxReg,
|
||||
Register raxReg);
|
||||
#endif
|
||||
|
||||
// CRC32 code for java.util.zip.CRC32::updateBytes() instrinsic.
|
||||
|
@ -3785,6 +3785,107 @@ class StubGenerator: public StubCodeGenerator {
|
||||
return start;
|
||||
}
|
||||
|
||||
/**
|
||||
* Arguments:
|
||||
*
|
||||
// Input:
|
||||
// c_rarg0 - x address
|
||||
// c_rarg1 - x length
|
||||
// c_rarg2 - z address
|
||||
// c_rarg3 - z lenth
|
||||
*
|
||||
*/
|
||||
address generate_squareToLen() {
|
||||
|
||||
__ align(CodeEntryAlignment);
|
||||
StubCodeMark mark(this, "StubRoutines", "squareToLen");
|
||||
|
||||
address start = __ pc();
|
||||
// Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...)
|
||||
// Unix: rdi, rsi, rdx, rcx (c_rarg0, c_rarg1, ...)
|
||||
const Register x = rdi;
|
||||
const Register len = rsi;
|
||||
const Register z = r8;
|
||||
const Register zlen = rcx;
|
||||
|
||||
const Register tmp1 = r12;
|
||||
const Register tmp2 = r13;
|
||||
const Register tmp3 = r14;
|
||||
const Register tmp4 = r15;
|
||||
const Register tmp5 = rbx;
|
||||
|
||||
BLOCK_COMMENT("Entry:");
|
||||
__ enter(); // required for proper stackwalking of RuntimeStub frame
|
||||
|
||||
setup_arg_regs(4); // x => rdi, len => rsi, z => rdx
|
||||
// zlen => rcx
|
||||
// r9 and r10 may be used to save non-volatile registers
|
||||
__ movptr(r8, rdx);
|
||||
__ square_to_len(x, len, z, zlen, tmp1, tmp2, tmp3, tmp4, tmp5, rdx, rax);
|
||||
|
||||
restore_arg_regs();
|
||||
|
||||
__ leave(); // required for proper stackwalking of RuntimeStub frame
|
||||
__ ret(0);
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
/**
|
||||
* Arguments:
|
||||
*
|
||||
* Input:
|
||||
* c_rarg0 - out address
|
||||
* c_rarg1 - in address
|
||||
* c_rarg2 - offset
|
||||
* c_rarg3 - len
|
||||
* not Win64
|
||||
* c_rarg4 - k
|
||||
* Win64
|
||||
* rsp+40 - k
|
||||
*/
|
||||
address generate_mulAdd() {
|
||||
__ align(CodeEntryAlignment);
|
||||
StubCodeMark mark(this, "StubRoutines", "mulAdd");
|
||||
|
||||
address start = __ pc();
|
||||
// Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...)
|
||||
// Unix: rdi, rsi, rdx, rcx, r8, r9 (c_rarg0, c_rarg1, ...)
|
||||
const Register out = rdi;
|
||||
const Register in = rsi;
|
||||
const Register offset = r11;
|
||||
const Register len = rcx;
|
||||
const Register k = r8;
|
||||
|
||||
// Next registers will be saved on stack in mul_add().
|
||||
const Register tmp1 = r12;
|
||||
const Register tmp2 = r13;
|
||||
const Register tmp3 = r14;
|
||||
const Register tmp4 = r15;
|
||||
const Register tmp5 = rbx;
|
||||
|
||||
BLOCK_COMMENT("Entry:");
|
||||
__ enter(); // required for proper stackwalking of RuntimeStub frame
|
||||
|
||||
setup_arg_regs(4); // out => rdi, in => rsi, offset => rdx
|
||||
// len => rcx, k => r8
|
||||
// r9 and r10 may be used to save non-volatile registers
|
||||
#ifdef _WIN64
|
||||
// last argument is on stack on Win64
|
||||
__ movl(k, Address(rsp, 6 * wordSize));
|
||||
#endif
|
||||
__ movptr(r11, rdx); // move offset in rdx to offset(r11)
|
||||
__ mul_add(out, in, offset, len, k, tmp1, tmp2, tmp3, tmp4, tmp5, rdx, rax);
|
||||
|
||||
restore_arg_regs();
|
||||
|
||||
__ leave(); // required for proper stackwalking of RuntimeStub frame
|
||||
__ ret(0);
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
|
||||
#undef __
|
||||
#define __ masm->
|
||||
|
||||
@ -4030,6 +4131,12 @@ class StubGenerator: public StubCodeGenerator {
|
||||
if (UseMultiplyToLenIntrinsic) {
|
||||
StubRoutines::_multiplyToLen = generate_multiplyToLen();
|
||||
}
|
||||
if (UseSquareToLenIntrinsic) {
|
||||
StubRoutines::_squareToLen = generate_squareToLen();
|
||||
}
|
||||
if (UseMulAddIntrinsic) {
|
||||
StubRoutines::_mulAdd = generate_mulAdd();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@ static bool returns_to_call_stub(address return_pc) { return return_pc == _
|
||||
|
||||
enum platform_dependent_constants {
|
||||
code_size1 = 19000, // simply increase if too small (assembler will crash if too small)
|
||||
code_size2 = 22000 // simply increase if too small (assembler will crash if too small)
|
||||
code_size2 = 23000 // simply increase if too small (assembler will crash if too small)
|
||||
};
|
||||
|
||||
class x86 {
|
||||
|
@ -790,6 +790,12 @@ void VM_Version::get_processor_features() {
|
||||
if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) {
|
||||
UseMultiplyToLenIntrinsic = true;
|
||||
}
|
||||
if (FLAG_IS_DEFAULT(UseSquareToLenIntrinsic)) {
|
||||
UseSquareToLenIntrinsic = true;
|
||||
}
|
||||
if (FLAG_IS_DEFAULT(UseMulAddIntrinsic)) {
|
||||
UseMulAddIntrinsic = true;
|
||||
}
|
||||
#else
|
||||
if (UseMultiplyToLenIntrinsic) {
|
||||
if (!FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) {
|
||||
@ -797,6 +803,18 @@ void VM_Version::get_processor_features() {
|
||||
}
|
||||
FLAG_SET_DEFAULT(UseMultiplyToLenIntrinsic, false);
|
||||
}
|
||||
if (UseSquareToLenIntrinsic) {
|
||||
if (!FLAG_IS_DEFAULT(UseSquareToLenIntrinsic)) {
|
||||
warning("squareToLen intrinsic is not available in 32-bit VM");
|
||||
}
|
||||
FLAG_SET_DEFAULT(UseSquareToLenIntrinsic, false);
|
||||
}
|
||||
if (UseMulAddIntrinsic) {
|
||||
if (!FLAG_IS_DEFAULT(UseMulAddIntrinsic)) {
|
||||
warning("mulAdd intrinsic is not available in 32-bit VM");
|
||||
}
|
||||
FLAG_SET_DEFAULT(UseMulAddIntrinsic, false);
|
||||
}
|
||||
#endif
|
||||
#endif // COMPILER2
|
||||
|
||||
|
@ -5431,18 +5431,18 @@ instruct loadUB2L(eRegL dst, memory mem, eFlagsReg cr) %{
|
||||
%}
|
||||
|
||||
// Load Unsigned Byte (8 bit UNsigned) with mask into Long Register
|
||||
instruct loadUB2L_immI8(eRegL dst, memory mem, immI8 mask, eFlagsReg cr) %{
|
||||
instruct loadUB2L_immI(eRegL dst, memory mem, immI mask, eFlagsReg cr) %{
|
||||
match(Set dst (ConvI2L (AndI (LoadUB mem) mask)));
|
||||
effect(KILL cr);
|
||||
|
||||
format %{ "MOVZX8 $dst.lo,$mem\t# ubyte & 8-bit mask -> long\n\t"
|
||||
format %{ "MOVZX8 $dst.lo,$mem\t# ubyte & 32-bit mask -> long\n\t"
|
||||
"XOR $dst.hi,$dst.hi\n\t"
|
||||
"AND $dst.lo,$mask" %}
|
||||
"AND $dst.lo,right_n_bits($mask, 8)" %}
|
||||
ins_encode %{
|
||||
Register Rdst = $dst$$Register;
|
||||
__ movzbl(Rdst, $mem$$Address);
|
||||
__ xorl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rdst));
|
||||
__ andl(Rdst, $mask$$constant);
|
||||
__ andl(Rdst, $mask$$constant & right_n_bits(8));
|
||||
%}
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
@ -5550,19 +5550,19 @@ instruct loadUS2L_immI_255(eRegL dst, memory mem, immI_255 mask, eFlagsReg cr) %
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Unsigned Short/Char (16 bit UNsigned) with a 16-bit mask into Long Register
|
||||
instruct loadUS2L_immI16(eRegL dst, memory mem, immI16 mask, eFlagsReg cr) %{
|
||||
// Load Unsigned Short/Char (16 bit UNsigned) with a 32-bit mask into Long Register
|
||||
instruct loadUS2L_immI(eRegL dst, memory mem, immI mask, eFlagsReg cr) %{
|
||||
match(Set dst (ConvI2L (AndI (LoadUS mem) mask)));
|
||||
effect(KILL cr);
|
||||
|
||||
format %{ "MOVZX $dst.lo, $mem\t# ushort/char & 16-bit mask -> long\n\t"
|
||||
format %{ "MOVZX $dst.lo, $mem\t# ushort/char & 32-bit mask -> long\n\t"
|
||||
"XOR $dst.hi,$dst.hi\n\t"
|
||||
"AND $dst.lo,$mask" %}
|
||||
"AND $dst.lo,right_n_bits($mask, 16)" %}
|
||||
ins_encode %{
|
||||
Register Rdst = $dst$$Register;
|
||||
__ movzwl(Rdst, $mem$$Address);
|
||||
__ xorl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rdst));
|
||||
__ andl(Rdst, $mask$$constant);
|
||||
__ andl(Rdst, $mask$$constant & right_n_bits(16));
|
||||
%}
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
@ -4753,17 +4753,17 @@ instruct loadUB2L(rRegL dst, memory mem)
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Unsigned Byte (8 bit UNsigned) with a 8-bit mask into Long Register
|
||||
instruct loadUB2L_immI8(rRegL dst, memory mem, immI8 mask, rFlagsReg cr) %{
|
||||
// Load Unsigned Byte (8 bit UNsigned) with 32-bit mask into Long Register
|
||||
instruct loadUB2L_immI(rRegL dst, memory mem, immI mask, rFlagsReg cr) %{
|
||||
match(Set dst (ConvI2L (AndI (LoadUB mem) mask)));
|
||||
effect(KILL cr);
|
||||
|
||||
format %{ "movzbq $dst, $mem\t# ubyte & 8-bit mask -> long\n\t"
|
||||
"andl $dst, $mask" %}
|
||||
format %{ "movzbq $dst, $mem\t# ubyte & 32-bit mask -> long\n\t"
|
||||
"andl $dst, right_n_bits($mask, 8)" %}
|
||||
ins_encode %{
|
||||
Register Rdst = $dst$$Register;
|
||||
__ movzbq(Rdst, $mem$$Address);
|
||||
__ andl(Rdst, $mask$$constant);
|
||||
__ andl(Rdst, $mask$$constant & right_n_bits(8));
|
||||
%}
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
@ -4863,17 +4863,17 @@ instruct loadUS2L_immI_255(rRegL dst, memory mem, immI_255 mask) %{
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Unsigned Short/Char (16 bit UNsigned) with mask into Long Register
|
||||
instruct loadUS2L_immI16(rRegL dst, memory mem, immI16 mask, rFlagsReg cr) %{
|
||||
// Load Unsigned Short/Char (16 bit UNsigned) with 32-bit mask into Long Register
|
||||
instruct loadUS2L_immI(rRegL dst, memory mem, immI mask, rFlagsReg cr) %{
|
||||
match(Set dst (ConvI2L (AndI (LoadUS mem) mask)));
|
||||
effect(KILL cr);
|
||||
|
||||
format %{ "movzwq $dst, $mem\t# ushort/char & 16-bit mask -> long\n\t"
|
||||
"andl $dst, $mask" %}
|
||||
format %{ "movzwq $dst, $mem\t# ushort/char & 32-bit mask -> long\n\t"
|
||||
"andl $dst, right_n_bits($mask, 16)" %}
|
||||
ins_encode %{
|
||||
Register Rdst = $dst$$Register;
|
||||
__ movzwq(Rdst, $mem$$Address);
|
||||
__ andl(Rdst, $mask$$constant);
|
||||
__ andl(Rdst, $mask$$constant & right_n_bits(16));
|
||||
%}
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
@ -1267,10 +1267,6 @@ void os::shutdown() {
|
||||
// Note: os::abort() might be called very early during initialization, or
|
||||
// called from signal handler. Before adding something to os::abort(), make
|
||||
// sure it is async-safe and can handle partially initialized VM.
|
||||
void os::abort(bool dump_core) {
|
||||
abort(dump_core, NULL, NULL);
|
||||
}
|
||||
|
||||
void os::abort(bool dump_core, void* siginfo, void* context) {
|
||||
os::shutdown();
|
||||
if (dump_core) {
|
||||
|
@ -1131,10 +1131,6 @@ void os::shutdown() {
|
||||
// Note: os::abort() might be called very early during initialization, or
|
||||
// called from signal handler. Before adding something to os::abort(), make
|
||||
// sure it is async-safe and can handle partially initialized VM.
|
||||
void os::abort(bool dump_core) {
|
||||
abort(dump_core, NULL, NULL);
|
||||
}
|
||||
|
||||
void os::abort(bool dump_core, void* siginfo, void* context) {
|
||||
os::shutdown();
|
||||
if (dump_core) {
|
||||
|
@ -1478,10 +1478,6 @@ void os::shutdown() {
|
||||
// Note: os::abort() might be called very early during initialization, or
|
||||
// called from signal handler. Before adding something to os::abort(), make
|
||||
// sure it is async-safe and can handle partially initialized VM.
|
||||
void os::abort(bool dump_core) {
|
||||
abort(dump_core, NULL, NULL);
|
||||
}
|
||||
|
||||
void os::abort(bool dump_core, void* siginfo, void* context) {
|
||||
os::shutdown();
|
||||
if (dump_core) {
|
||||
|
@ -1520,10 +1520,6 @@ void os::shutdown() {
|
||||
// Note: os::abort() might be called very early during initialization, or
|
||||
// called from signal handler. Before adding something to os::abort(), make
|
||||
// sure it is async-safe and can handle partially initialized VM.
|
||||
void os::abort(bool dump_core) {
|
||||
abort(dump_core, NULL, NULL);
|
||||
}
|
||||
|
||||
void os::abort(bool dump_core, void* siginfo, void* context) {
|
||||
os::shutdown();
|
||||
if (dump_core) {
|
||||
|
@ -997,7 +997,16 @@ void os::check_dump_limit(char* buffer, size_t buffsz) {
|
||||
if (!FLAG_IS_DEFAULT(CreateCoredumpOnCrash) && !CreateCoredumpOnCrash) {
|
||||
jio_snprintf(buffer, buffsz, "CreateCoredumpOnCrash is disabled from command line");
|
||||
status = false;
|
||||
} else {
|
||||
}
|
||||
|
||||
#ifndef ASSERT
|
||||
if (!os::win32::is_windows_server() && FLAG_IS_DEFAULT(CreateCoredumpOnCrash)) {
|
||||
jio_snprintf(buffer, buffsz, "Minidumps are not enabled by default on client versions of Windows");
|
||||
status = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (status) {
|
||||
const char* cwd = get_current_directory(NULL, 0);
|
||||
int pid = current_process_id();
|
||||
if (cwd != NULL) {
|
||||
@ -1086,10 +1095,6 @@ void os::abort(bool dump_core, void* siginfo, void* context) {
|
||||
win32::exit_process_or_thread(win32::EPT_PROCESS, 1);
|
||||
}
|
||||
|
||||
void os::abort(bool dump_core) {
|
||||
abort(dump_core, NULL, NULL);
|
||||
}
|
||||
|
||||
// Die immediately, no exit hook, no abort hook, no cleanup.
|
||||
void os::die() {
|
||||
win32::exit_process_or_thread(win32::EPT_PROCESS_DIE, -1);
|
||||
|
@ -59,8 +59,8 @@
|
||||
extern sigjmp_buf* get_jmp_buf_for_continuation();
|
||||
|
||||
address os::current_stack_pointer() {
|
||||
address dummy = (address) &dummy;
|
||||
return dummy;
|
||||
// return the address of the current function
|
||||
return (address)__builtin_frame_address(0);
|
||||
}
|
||||
|
||||
frame os::get_sender_for_C_frame(frame* fr) {
|
||||
|
@ -49,25 +49,6 @@ ciMethodHandle* ciCallSite::get_target() const {
|
||||
return CURRENT_ENV->get_object(method_handle_oop)->as_method_handle();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciCallSite::get_context
|
||||
//
|
||||
// Return the target MethodHandle of this CallSite.
|
||||
ciKlass* ciCallSite::get_context() {
|
||||
assert(!is_constant_call_site(), "");
|
||||
|
||||
VM_ENTRY_MARK;
|
||||
oop call_site_oop = get_oop();
|
||||
InstanceKlass* ctxk = MethodHandles::get_call_site_context(call_site_oop);
|
||||
if (ctxk == NULL) {
|
||||
// The call site doesn't have a context associated. Set it to the default context.
|
||||
oop def_context_oop = java_lang_invoke_CallSite::default_context();
|
||||
java_lang_invoke_CallSite::set_context_cas(call_site_oop, def_context_oop, /*expected=*/NULL);
|
||||
ctxk = MethodHandles::get_call_site_context(call_site_oop);
|
||||
}
|
||||
return (CURRENT_ENV->get_metadata(ctxk))->as_klass();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciCallSite::print
|
||||
//
|
||||
|
@ -43,7 +43,6 @@ public:
|
||||
|
||||
// Return the target MethodHandle of this CallSite.
|
||||
ciMethodHandle* get_target() const;
|
||||
ciKlass* get_context();
|
||||
|
||||
void print();
|
||||
};
|
||||
|
@ -709,24 +709,23 @@ Method* ciEnv::lookup_method(InstanceKlass* accessor,
|
||||
KlassHandle h_holder(THREAD, holder);
|
||||
LinkResolver::check_klass_accessability(h_accessor, h_holder, KILL_COMPILE_ON_FATAL_(NULL));
|
||||
methodHandle dest_method;
|
||||
LinkInfo link_info(h_holder, name, sig, h_accessor, /*check_access*/true);
|
||||
switch (bc) {
|
||||
case Bytecodes::_invokestatic:
|
||||
dest_method =
|
||||
LinkResolver::resolve_static_call_or_null(h_holder, name, sig, h_accessor);
|
||||
LinkResolver::resolve_static_call_or_null(link_info);
|
||||
break;
|
||||
case Bytecodes::_invokespecial:
|
||||
dest_method =
|
||||
LinkResolver::resolve_special_call_or_null(h_holder, name, sig, h_accessor);
|
||||
LinkResolver::resolve_special_call_or_null(link_info);
|
||||
break;
|
||||
case Bytecodes::_invokeinterface:
|
||||
dest_method =
|
||||
LinkResolver::linktime_resolve_interface_method_or_null(h_holder, name, sig,
|
||||
h_accessor, true);
|
||||
LinkResolver::linktime_resolve_interface_method_or_null(link_info);
|
||||
break;
|
||||
case Bytecodes::_invokevirtual:
|
||||
dest_method =
|
||||
LinkResolver::linktime_resolve_virtual_method_or_null(h_holder, name, sig,
|
||||
h_accessor, true);
|
||||
LinkResolver::linktime_resolve_virtual_method_or_null(link_info);
|
||||
break;
|
||||
default: ShouldNotReachHere();
|
||||
}
|
||||
|
@ -352,11 +352,11 @@ bool ciField::will_link(ciInstanceKlass* accessing_klass,
|
||||
}
|
||||
}
|
||||
|
||||
LinkInfo link_info(_holder->get_instanceKlass(),
|
||||
_name->get_symbol(), _signature->get_symbol(),
|
||||
accessing_klass->get_Klass());
|
||||
fieldDescriptor result;
|
||||
LinkResolver::resolve_field(result, _holder->get_instanceKlass(),
|
||||
_name->get_symbol(), _signature->get_symbol(),
|
||||
accessing_klass->get_Klass(), bc, true, false,
|
||||
KILL_COMPILE_ON_FATAL_(false));
|
||||
LinkResolver::resolve_field(result, link_info, bc, false, KILL_COMPILE_ON_FATAL_(false));
|
||||
|
||||
// update the hit-cache, unless there is a problem with memory scoping:
|
||||
if (accessing_klass->is_shared() || !is_shared()) {
|
||||
|
@ -453,8 +453,12 @@ int ciInstanceKlass::compute_nonstatic_fields() {
|
||||
|
||||
if (fields == NULL) {
|
||||
// This can happen if this class (java.lang.Class) has invisible fields.
|
||||
_nonstatic_fields = super_fields;
|
||||
return super_fields->length();
|
||||
if (super_fields != NULL) {
|
||||
_nonstatic_fields = super_fields;
|
||||
return super_fields->length();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int flen = fields->length();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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
|
||||
@ -786,6 +786,7 @@ ciMethod* ciMethod::resolve_invoke(ciKlass* caller, ciKlass* exact_receiver, boo
|
||||
Symbol* h_name = name()->get_symbol();
|
||||
Symbol* h_signature = signature()->get_symbol();
|
||||
|
||||
LinkInfo link_info(h_resolved, h_name, h_signature, caller_klass, check_access);
|
||||
methodHandle m;
|
||||
// Only do exact lookup if receiver klass has been linked. Otherwise,
|
||||
// the vtable has not been setup, and the LinkResolver will fail.
|
||||
@ -793,9 +794,9 @@ ciMethod* ciMethod::resolve_invoke(ciKlass* caller, ciKlass* exact_receiver, boo
|
||||
||
|
||||
InstanceKlass::cast(h_recv())->is_linked() && !exact_receiver->is_interface()) {
|
||||
if (holder()->is_interface()) {
|
||||
m = LinkResolver::resolve_interface_call_or_null(h_recv, h_resolved, h_name, h_signature, caller_klass, check_access);
|
||||
m = LinkResolver::resolve_interface_call_or_null(h_recv, link_info);
|
||||
} else {
|
||||
m = LinkResolver::resolve_virtual_call_or_null(h_recv, h_resolved, h_name, h_signature, caller_klass, check_access);
|
||||
m = LinkResolver::resolve_virtual_call_or_null(h_recv, link_info);
|
||||
}
|
||||
}
|
||||
|
||||
@ -839,7 +840,8 @@ int ciMethod::resolve_vtable_index(ciKlass* caller, ciKlass* receiver) {
|
||||
Symbol* h_name = name()->get_symbol();
|
||||
Symbol* h_signature = signature()->get_symbol();
|
||||
|
||||
vtable_index = LinkResolver::resolve_virtual_vtable_index(h_recv, h_recv, h_name, h_signature, caller_klass);
|
||||
LinkInfo link_info(h_recv, h_name, h_signature, caller_klass);
|
||||
vtable_index = LinkResolver::resolve_virtual_vtable_index(h_recv, link_info);
|
||||
if (vtable_index == Method::nonvirtual_vtable_index) {
|
||||
// A statically bound method. Return "no such index".
|
||||
vtable_index = Method::invalid_vtable_index;
|
||||
@ -1285,10 +1287,8 @@ bool ciMethod::check_call(int refinfo_index, bool is_static) const {
|
||||
EXCEPTION_MARK;
|
||||
HandleMark hm(THREAD);
|
||||
constantPoolHandle pool (THREAD, get_Method()->constants());
|
||||
methodHandle spec_method;
|
||||
KlassHandle spec_klass;
|
||||
Bytecodes::Code code = (is_static ? Bytecodes::_invokestatic : Bytecodes::_invokevirtual);
|
||||
LinkResolver::resolve_method_statically(spec_method, spec_klass, code, pool, refinfo_index, THREAD);
|
||||
methodHandle spec_method = LinkResolver::resolve_method_statically(code, pool, refinfo_index, THREAD);
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
return false;
|
||||
|
@ -2967,47 +2967,42 @@ int java_lang_invoke_MethodType::rtype_slot_count(oop mt) {
|
||||
|
||||
int java_lang_invoke_CallSite::_target_offset;
|
||||
int java_lang_invoke_CallSite::_context_offset;
|
||||
int java_lang_invoke_CallSite::_default_context_offset;
|
||||
|
||||
void java_lang_invoke_CallSite::compute_offsets() {
|
||||
Klass* k = SystemDictionary::CallSite_klass();
|
||||
if (k != NULL) {
|
||||
compute_offset(_target_offset, k, vmSymbols::target_name(), vmSymbols::java_lang_invoke_MethodHandle_signature());
|
||||
compute_offset(_context_offset, k, vmSymbols::context_name(), vmSymbols::sun_misc_Cleaner_signature());
|
||||
compute_offset(_default_context_offset, k,
|
||||
vmSymbols::DEFAULT_CONTEXT_name(), vmSymbols::sun_misc_Cleaner_signature(),
|
||||
/*is_static=*/true, /*allow_super=*/false);
|
||||
compute_offset(_context_offset, k, vmSymbols::context_name(),
|
||||
vmSymbols::java_lang_invoke_MethodHandleNatives_CallSiteContext_signature());
|
||||
}
|
||||
}
|
||||
|
||||
oop java_lang_invoke_CallSite::context_volatile(oop call_site) {
|
||||
oop java_lang_invoke_CallSite::context(oop call_site) {
|
||||
assert(java_lang_invoke_CallSite::is_instance(call_site), "");
|
||||
|
||||
oop dep_oop = call_site->obj_field_volatile(_context_offset);
|
||||
oop dep_oop = call_site->obj_field(_context_offset);
|
||||
return dep_oop;
|
||||
}
|
||||
|
||||
void java_lang_invoke_CallSite::set_context_volatile(oop call_site, oop context) {
|
||||
assert(java_lang_invoke_CallSite::is_instance(call_site), "");
|
||||
call_site->obj_field_put_volatile(_context_offset, context);
|
||||
}
|
||||
// Support for java_lang_invoke_MethodHandleNatives_CallSiteContext
|
||||
|
||||
bool java_lang_invoke_CallSite::set_context_cas(oop call_site, oop context, oop expected) {
|
||||
assert(java_lang_invoke_CallSite::is_instance(call_site), "");
|
||||
HeapWord* context_addr = call_site->obj_field_addr<HeapWord>(_context_offset);
|
||||
oop res = oopDesc::atomic_compare_exchange_oop(context, context_addr, expected, true);
|
||||
bool success = (res == expected);
|
||||
if (success) {
|
||||
update_barrier_set((void*)context_addr, context);
|
||||
int java_lang_invoke_MethodHandleNatives_CallSiteContext::_vmdependencies_offset;
|
||||
|
||||
void java_lang_invoke_MethodHandleNatives_CallSiteContext::compute_offsets() {
|
||||
Klass* k = SystemDictionary::Context_klass();
|
||||
if (k != NULL) {
|
||||
CALLSITECONTEXT_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
oop java_lang_invoke_CallSite::default_context() {
|
||||
InstanceKlass* ik = InstanceKlass::cast(SystemDictionary::CallSite_klass());
|
||||
oop def_context_oop = ik->java_mirror()->obj_field(_default_context_offset);
|
||||
assert(!oopDesc::is_null(def_context_oop), "");
|
||||
return def_context_oop;
|
||||
nmethodBucket* java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(oop call_site) {
|
||||
assert(java_lang_invoke_MethodHandleNatives_CallSiteContext::is_instance(call_site), "");
|
||||
return (nmethodBucket*) (address) call_site->long_field(_vmdependencies_offset);
|
||||
}
|
||||
|
||||
void java_lang_invoke_MethodHandleNatives_CallSiteContext::set_vmdependencies(oop call_site, nmethodBucket* context) {
|
||||
assert(java_lang_invoke_MethodHandleNatives_CallSiteContext::is_instance(call_site), "");
|
||||
call_site->long_field_put(_vmdependencies_offset, (jlong) (address) context);
|
||||
}
|
||||
|
||||
// Support for java_security_AccessControlContext
|
||||
@ -3403,6 +3398,7 @@ void JavaClasses::compute_offsets() {
|
||||
java_lang_invoke_LambdaForm::compute_offsets();
|
||||
java_lang_invoke_MethodType::compute_offsets();
|
||||
java_lang_invoke_CallSite::compute_offsets();
|
||||
java_lang_invoke_MethodHandleNatives_CallSiteContext::compute_offsets();
|
||||
java_security_AccessControlContext::compute_offsets();
|
||||
// Initialize reflection classes. The layouts of these classes
|
||||
// changed with the new reflection implementation in JDK 1.4, and
|
||||
|
@ -1170,8 +1170,6 @@ class java_lang_invoke_CallSite: AllStatic {
|
||||
private:
|
||||
static int _target_offset;
|
||||
static int _context_offset;
|
||||
static int _default_context_offset;
|
||||
|
||||
|
||||
static void compute_offsets();
|
||||
|
||||
@ -1181,11 +1179,7 @@ public:
|
||||
static void set_target( oop site, oop target);
|
||||
static void set_target_volatile( oop site, oop target);
|
||||
|
||||
static oop context_volatile(oop site);
|
||||
static void set_context_volatile(oop site, oop context);
|
||||
static bool set_context_cas (oop site, oop context, oop expected);
|
||||
|
||||
static oop default_context();
|
||||
static oop context(oop site);
|
||||
|
||||
// Testers
|
||||
static bool is_subclass(Klass* klass) {
|
||||
@ -1197,6 +1191,31 @@ public:
|
||||
static int target_offset_in_bytes() { return _target_offset; }
|
||||
};
|
||||
|
||||
// Interface to java.lang.invoke.MethodHandleNatives$CallSiteContext objects
|
||||
|
||||
#define CALLSITECONTEXT_INJECTED_FIELDS(macro) \
|
||||
macro(java_lang_invoke_MethodHandleNatives_CallSiteContext, vmdependencies, intptr_signature, false)
|
||||
|
||||
class java_lang_invoke_MethodHandleNatives_CallSiteContext : AllStatic {
|
||||
friend class JavaClasses;
|
||||
|
||||
private:
|
||||
static int _vmdependencies_offset;
|
||||
|
||||
static void compute_offsets();
|
||||
|
||||
public:
|
||||
// Accessors
|
||||
static nmethodBucket* vmdependencies(oop context);
|
||||
static void set_vmdependencies(oop context, nmethodBucket* bucket);
|
||||
|
||||
// Testers
|
||||
static bool is_subclass(Klass* klass) {
|
||||
return klass->is_subclass_of(SystemDictionary::Context_klass());
|
||||
}
|
||||
static bool is_instance(oop obj);
|
||||
};
|
||||
|
||||
// Interface to java.security.AccessControlContext objects
|
||||
|
||||
class java_security_AccessControlContext: AllStatic {
|
||||
@ -1406,7 +1425,8 @@ class InjectedField {
|
||||
#define ALL_INJECTED_FIELDS(macro) \
|
||||
CLASS_INJECTED_FIELDS(macro) \
|
||||
CLASSLOADER_INJECTED_FIELDS(macro) \
|
||||
MEMBERNAME_INJECTED_FIELDS(macro)
|
||||
MEMBERNAME_INJECTED_FIELDS(macro) \
|
||||
CALLSITECONTEXT_INJECTED_FIELDS(macro)
|
||||
|
||||
// Interface to hard-coded offset checking
|
||||
|
||||
|
@ -49,6 +49,10 @@ inline bool java_lang_invoke_CallSite::is_instance(oop obj) {
|
||||
return obj != NULL && is_subclass(obj->klass());
|
||||
}
|
||||
|
||||
inline bool java_lang_invoke_MethodHandleNatives_CallSiteContext::is_instance(oop obj) {
|
||||
return obj != NULL && is_subclass(obj->klass());
|
||||
}
|
||||
|
||||
inline bool java_lang_invoke_MemberName::is_instance(oop obj) {
|
||||
return obj != NULL && is_subclass(obj->klass());
|
||||
}
|
||||
|
@ -159,6 +159,7 @@ class Ticks;
|
||||
do_klass(MethodType_klass, java_lang_invoke_MethodType, Pre ) \
|
||||
do_klass(BootstrapMethodError_klass, java_lang_BootstrapMethodError, Pre ) \
|
||||
do_klass(CallSite_klass, java_lang_invoke_CallSite, Pre ) \
|
||||
do_klass(Context_klass, java_lang_invoke_MethodHandleNatives_CallSiteContext, Pre ) \
|
||||
do_klass(ConstantCallSite_klass, java_lang_invoke_ConstantCallSite, Pre ) \
|
||||
do_klass(MutableCallSite_klass, java_lang_invoke_MutableCallSite, Pre ) \
|
||||
do_klass(VolatileCallSite_klass, java_lang_invoke_VolatileCallSite, Pre ) \
|
||||
|
@ -45,6 +45,8 @@
|
||||
#include "runtime/javaCalls.hpp"
|
||||
#include "runtime/orderAccess.inline.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
#include "runtime/thread.hpp"
|
||||
#include "services/threadService.hpp"
|
||||
#include "utilities/bytes.hpp"
|
||||
|
||||
#define NOFAILOVER_MAJOR_VERSION 51
|
||||
@ -130,6 +132,16 @@ bool Verifier::verify(instanceKlassHandle klass, Verifier::Mode mode, bool shoul
|
||||
return true;
|
||||
}
|
||||
|
||||
// Timer includes any side effects of class verification (resolution,
|
||||
// etc), but not recursive calls to Verifier::verify().
|
||||
JavaThread* jt = (JavaThread*)THREAD;
|
||||
PerfClassTraceTime timer(ClassLoader::perf_class_verify_time(),
|
||||
ClassLoader::perf_class_verify_selftime(),
|
||||
ClassLoader::perf_classes_verified(),
|
||||
jt->get_thread_stat()->perf_recursion_counts_addr(),
|
||||
jt->get_thread_stat()->perf_timers_addr(),
|
||||
PerfClassTraceTime::CLASS_VERIFY);
|
||||
|
||||
// If the class should be verified, first see if we can use the split
|
||||
// verifier. If not, or if verification fails and FailOverToOldVerifier
|
||||
// is set, then call the inference verifier.
|
||||
|
@ -274,12 +274,14 @@
|
||||
/* internal classes known only to the JVM: */ \
|
||||
template(java_lang_invoke_MemberName, "java/lang/invoke/MemberName") \
|
||||
template(java_lang_invoke_MethodHandleNatives, "java/lang/invoke/MethodHandleNatives") \
|
||||
template(java_lang_invoke_MethodHandleNatives_CallSiteContext, "java/lang/invoke/MethodHandleNatives$CallSiteContext") \
|
||||
template(java_lang_invoke_LambdaForm, "java/lang/invoke/LambdaForm") \
|
||||
template(java_lang_invoke_ForceInline_signature, "Ljava/lang/invoke/ForceInline;") \
|
||||
template(java_lang_invoke_DontInline_signature, "Ljava/lang/invoke/DontInline;") \
|
||||
template(java_lang_invoke_Stable_signature, "Ljava/lang/invoke/Stable;") \
|
||||
template(java_lang_invoke_LambdaForm_Compiled_signature, "Ljava/lang/invoke/LambdaForm$Compiled;") \
|
||||
template(java_lang_invoke_LambdaForm_Hidden_signature, "Ljava/lang/invoke/LambdaForm$Hidden;") \
|
||||
template(java_lang_invoke_MethodHandleNatives_CallSiteContext_signature, "Ljava/lang/invoke/MethodHandleNatives$CallSiteContext;") \
|
||||
/* internal up-calls made only by the JVM, via class sun.invoke.MethodHandleNatives: */ \
|
||||
template(findMethodHandleType_name, "findMethodHandleType") \
|
||||
template(findMethodHandleType_signature, "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/invoke/MethodType;") \
|
||||
@ -401,7 +403,7 @@
|
||||
template(protection_domain_name, "protection_domain") \
|
||||
template(signers_name, "signers_name") \
|
||||
template(loader_data_name, "loader_data") \
|
||||
template(dependencies_name, "dependencies") \
|
||||
template(vmdependencies_name, "vmdependencies") \
|
||||
template(input_stream_void_signature, "(Ljava/io/InputStream;)V") \
|
||||
template(getFileURL_name, "getFileURL") \
|
||||
template(getFileURL_signature, "(Ljava/io/File;)Ljava/net/URL;") \
|
||||
@ -797,6 +799,14 @@
|
||||
do_name( multiplyToLen_name, "multiplyToLen") \
|
||||
do_signature(multiplyToLen_signature, "([II[II[I)[I") \
|
||||
\
|
||||
do_intrinsic(_squareToLen, java_math_BigInteger, squareToLen_name, squareToLen_signature, F_S) \
|
||||
do_name( squareToLen_name, "implSquareToLen") \
|
||||
do_signature(squareToLen_signature, "([II[II)[I") \
|
||||
\
|
||||
do_intrinsic(_mulAdd, java_math_BigInteger, mulAdd_name, mulAdd_signature, F_S) \
|
||||
do_name( mulAdd_name, "implMulAdd") \
|
||||
do_signature(mulAdd_signature, "([I[IIII)I") \
|
||||
\
|
||||
/* java/lang/ref/Reference */ \
|
||||
do_intrinsic(_Reference_get, java_lang_ref_Reference, get_name, void_object_signature, F_R) \
|
||||
\
|
||||
|
@ -1047,40 +1047,6 @@ void CodeCache::flush_dependents_on(instanceKlassHandle dependee) {
|
||||
}
|
||||
}
|
||||
|
||||
// Flushes compiled methods dependent on a particular CallSite
|
||||
// instance when its target is different than the given MethodHandle.
|
||||
void CodeCache::flush_dependents_on(Handle call_site, Handle method_handle) {
|
||||
assert_lock_strong(Compile_lock);
|
||||
|
||||
if (number_of_nmethods_with_dependencies() == 0) return;
|
||||
|
||||
// CodeCache can only be updated by a thread_in_VM and they will all be
|
||||
// stopped during the safepoint so CodeCache will be safe to update without
|
||||
// holding the CodeCache_lock.
|
||||
|
||||
CallSiteDepChange changes(call_site(), method_handle());
|
||||
|
||||
// Compute the dependent nmethods that have a reference to a
|
||||
// CallSite object. We use InstanceKlass::mark_dependent_nmethod
|
||||
// directly instead of CodeCache::mark_for_deoptimization because we
|
||||
// want dependents on the call site class only not all classes in
|
||||
// the ContextStream.
|
||||
int marked = 0;
|
||||
{
|
||||
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
|
||||
InstanceKlass* ctxk = MethodHandles::get_call_site_context(call_site());
|
||||
if (ctxk == NULL) {
|
||||
return; // No dependencies to invalidate yet.
|
||||
}
|
||||
marked = ctxk->mark_dependent_nmethods(changes);
|
||||
}
|
||||
if (marked > 0) {
|
||||
// At least one nmethod has been marked for deoptimization
|
||||
VM_Deoptimize op;
|
||||
VMThread::execute(&op);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HOTSWAP
|
||||
// Flushes compiled methods dependent on dependee in the evolutionary sense
|
||||
void CodeCache::flush_evol_dependents_on(instanceKlassHandle ev_k_h) {
|
||||
|
@ -224,7 +224,6 @@ class CodeCache : AllStatic {
|
||||
|
||||
// Flushing and deoptimization
|
||||
static void flush_dependents_on(instanceKlassHandle dependee);
|
||||
static void flush_dependents_on(Handle call_site, Handle method_handle);
|
||||
#ifdef HOTSWAP
|
||||
// Flushing and deoptimization in case of evolution
|
||||
static void flush_evol_dependents_on(instanceKlassHandle dependee);
|
||||
|
@ -117,9 +117,7 @@ void Dependencies::assert_has_no_finalizable_subclasses(ciKlass* ctxk) {
|
||||
}
|
||||
|
||||
void Dependencies::assert_call_site_target_value(ciCallSite* call_site, ciMethodHandle* method_handle) {
|
||||
ciKlass* ctxk = call_site->get_context();
|
||||
check_ctxk(ctxk);
|
||||
assert_common_3(call_site_target_value, ctxk, call_site, method_handle);
|
||||
assert_common_2(call_site_target_value, call_site, method_handle);
|
||||
}
|
||||
|
||||
// Helper function. If we are adding a new dep. under ctxk2,
|
||||
@ -175,7 +173,6 @@ void Dependencies::assert_common_2(DepType dept,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
assert(dep_implicit_context_arg(dept) == 0, "sanity");
|
||||
if (note_dep_seen(dept, x0) && note_dep_seen(dept, x1)) {
|
||||
// look in this bucket for redundant assertions
|
||||
const int stride = 2;
|
||||
@ -389,7 +386,7 @@ int Dependencies::_dep_args[TYPE_LIMIT] = {
|
||||
3, // unique_concrete_subtypes_2 ctxk, k1, k2
|
||||
3, // unique_concrete_methods_2 ctxk, m1, m2
|
||||
1, // no_finalizable_subclasses ctxk
|
||||
3 // call_site_target_value ctxk, call_site, method_handle
|
||||
2 // call_site_target_value call_site, method_handle
|
||||
};
|
||||
|
||||
const char* Dependencies::dep_name(Dependencies::DepType dept) {
|
||||
@ -1515,16 +1512,11 @@ Klass* Dependencies::check_has_no_finalizable_subclasses(Klass* ctxk, KlassDepCh
|
||||
return find_finalizable_subclass(search_at);
|
||||
}
|
||||
|
||||
Klass* Dependencies::check_call_site_target_value(Klass* recorded_ctxk, oop call_site, oop method_handle, CallSiteDepChange* changes) {
|
||||
assert(call_site->is_a(SystemDictionary::CallSite_klass()), "sanity");
|
||||
Klass* Dependencies::check_call_site_target_value(oop call_site, oop method_handle, CallSiteDepChange* changes) {
|
||||
assert(!oopDesc::is_null(call_site), "sanity");
|
||||
assert(!oopDesc::is_null(method_handle), "sanity");
|
||||
assert(call_site->is_a(SystemDictionary::CallSite_klass()), "sanity");
|
||||
|
||||
Klass* call_site_ctxk = MethodHandles::get_call_site_context(call_site);
|
||||
assert(!Klass::is_null(call_site_ctxk), "call site context should be initialized already");
|
||||
if (recorded_ctxk != call_site_ctxk) {
|
||||
// Stale context
|
||||
return recorded_ctxk;
|
||||
}
|
||||
if (changes == NULL) {
|
||||
// Validate all CallSites
|
||||
if (java_lang_invoke_CallSite::target(call_site) != method_handle)
|
||||
@ -1599,7 +1591,7 @@ Klass* Dependencies::DepStream::check_call_site_dependency(CallSiteDepChange* ch
|
||||
Klass* witness = NULL;
|
||||
switch (type()) {
|
||||
case call_site_target_value:
|
||||
witness = check_call_site_target_value(context_type(), argument_oop(1), argument_oop(2), changes);
|
||||
witness = check_call_site_target_value(argument_oop(0), argument_oop(1), changes);
|
||||
break;
|
||||
default:
|
||||
witness = NULL;
|
||||
|
@ -173,7 +173,7 @@ class Dependencies: public ResourceObj {
|
||||
non_klass_types = (1 << call_site_target_value),
|
||||
klass_types = all_types & ~non_klass_types,
|
||||
|
||||
non_ctxk_types = (1 << evol_method),
|
||||
non_ctxk_types = (1 << evol_method) | (1 << call_site_target_value),
|
||||
implicit_ctxk_types = 0,
|
||||
explicit_ctxk_types = all_types & ~(non_ctxk_types | implicit_ctxk_types),
|
||||
|
||||
@ -330,7 +330,7 @@ class Dependencies: public ResourceObj {
|
||||
static Klass* check_exclusive_concrete_methods(Klass* ctxk, Method* m1, Method* m2,
|
||||
KlassDepChange* changes = NULL);
|
||||
static Klass* check_has_no_finalizable_subclasses(Klass* ctxk, KlassDepChange* changes = NULL);
|
||||
static Klass* check_call_site_target_value(Klass* recorded_ctxk, oop call_site, oop method_handle, CallSiteDepChange* changes = NULL);
|
||||
static Klass* check_call_site_target_value(oop call_site, oop method_handle, CallSiteDepChange* changes = NULL);
|
||||
// A returned Klass* is NULL if the dependency assertion is still
|
||||
// valid. A non-NULL Klass* is a 'witness' to the assertion
|
||||
// failure, a point in the class hierarchy where the assertion has
|
||||
@ -496,7 +496,7 @@ class Dependencies: public ResourceObj {
|
||||
bool next();
|
||||
|
||||
DepType type() { return _type; }
|
||||
bool is_oop_argument(int i) { return type() == call_site_target_value && i > 0; }
|
||||
bool is_oop_argument(int i) { return type() == call_site_target_value; }
|
||||
uintptr_t get_identifier(int i);
|
||||
|
||||
int argument_count() { return dep_args(type()); }
|
||||
|
@ -565,13 +565,18 @@ nmethod* nmethod::new_nmethod(methodHandle method,
|
||||
// the number of methods compiled. For applications with a lot
|
||||
// classes the slow way is too slow.
|
||||
for (Dependencies::DepStream deps(nm); deps.next(); ) {
|
||||
Klass* klass = deps.context_type();
|
||||
if (klass == NULL) {
|
||||
continue; // ignore things like evol_method
|
||||
if (deps.type() == Dependencies::call_site_target_value) {
|
||||
// CallSite dependencies are managed on per-CallSite instance basis.
|
||||
oop call_site = deps.argument_oop(0);
|
||||
MethodHandles::add_dependent_nmethod(call_site, nm);
|
||||
} else {
|
||||
Klass* klass = deps.context_type();
|
||||
if (klass == NULL) {
|
||||
continue; // ignore things like evol_method
|
||||
}
|
||||
// record this nmethod as dependent on this klass
|
||||
InstanceKlass::cast(klass)->add_dependent_nmethod(nm);
|
||||
}
|
||||
|
||||
// record this nmethod as dependent on this klass
|
||||
InstanceKlass::cast(klass)->add_dependent_nmethod(nm);
|
||||
}
|
||||
NOT_PRODUCT(nmethod_stats.note_nmethod(nm));
|
||||
if (PrintAssembly || CompilerOracle::has_option_string(method, "PrintAssembly")) {
|
||||
@ -1464,13 +1469,20 @@ void nmethod::flush_dependencies(BoolObjectClosure* is_alive) {
|
||||
if (!has_flushed_dependencies()) {
|
||||
set_has_flushed_dependencies();
|
||||
for (Dependencies::DepStream deps(this); deps.next(); ) {
|
||||
Klass* klass = deps.context_type();
|
||||
if (klass == NULL) continue; // ignore things like evol_method
|
||||
|
||||
// During GC the is_alive closure is non-NULL, and is used to
|
||||
// determine liveness of dependees that need to be updated.
|
||||
if (is_alive == NULL || klass->is_loader_alive(is_alive)) {
|
||||
InstanceKlass::cast(klass)->remove_dependent_nmethod(this);
|
||||
if (deps.type() == Dependencies::call_site_target_value) {
|
||||
// CallSite dependencies are managed on per-CallSite instance basis.
|
||||
oop call_site = deps.argument_oop(0);
|
||||
MethodHandles::remove_dependent_nmethod(call_site, this);
|
||||
} else {
|
||||
Klass* klass = deps.context_type();
|
||||
if (klass == NULL) {
|
||||
continue; // ignore things like evol_method
|
||||
}
|
||||
// During GC the is_alive closure is non-NULL, and is used to
|
||||
// determine liveness of dependees that need to be updated.
|
||||
if (is_alive == NULL || klass->is_loader_alive(is_alive)) {
|
||||
InstanceKlass::cast(klass)->remove_dependent_nmethod(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -254,9 +254,9 @@ void VM_GenCollectFullConcurrent::doit_epilogue() {
|
||||
if (_gc_cause != GCCause::_gc_locker &&
|
||||
gch->total_full_collections_completed() <= _full_gc_count_before) {
|
||||
// maybe we should change the condition to test _gc_cause ==
|
||||
// GCCause::_java_lang_system_gc, instead of
|
||||
// _gc_cause != GCCause::_gc_locker
|
||||
assert(_gc_cause == GCCause::_java_lang_system_gc,
|
||||
// GCCause::_java_lang_system_gc or GCCause::_dcmd_gc_run,
|
||||
// instead of _gc_cause != GCCause::_gc_locker
|
||||
assert(GCCause::is_user_requested_gc(_gc_cause),
|
||||
"the only way to get here if this was a System.gc()-induced GC");
|
||||
assert(ExplicitGCInvokesConcurrent, "Error");
|
||||
// Now, wait for witnessing concurrent gc cycle to complete,
|
||||
|
@ -43,7 +43,7 @@ GangWorker* YieldingFlexibleWorkGang::allocate_worker(uint which) {
|
||||
}
|
||||
|
||||
// Run a task; returns when the task is done, or the workers yield,
|
||||
// or the task is aborted, or the work gang is terminated via stop().
|
||||
// or the task is aborted.
|
||||
// A task that has been yielded can be continued via this interface
|
||||
// by using the same task repeatedly as the argument to the call.
|
||||
// It is expected that the YieldingFlexibleGangTask carries the appropriate
|
||||
@ -297,16 +297,9 @@ void YieldingFlexibleGangWorker::loop() {
|
||||
WorkData data;
|
||||
int id;
|
||||
while (true) {
|
||||
// Check if there is work to do or if we have been asked
|
||||
// to terminate
|
||||
// Check if there is work to do.
|
||||
gang()->internal_worker_poll(&data);
|
||||
if (data.terminate()) {
|
||||
// We have been asked to terminate.
|
||||
assert(gang()->task() == NULL, "No task binding");
|
||||
// set_status(TERMINATED);
|
||||
return;
|
||||
} else if (data.task() != NULL &&
|
||||
data.sequence_number() != previous_sequence_number) {
|
||||
if (data.task() != NULL && data.sequence_number() != previous_sequence_number) {
|
||||
// There is work to be done.
|
||||
// First check if we need to become active or if there
|
||||
// are already the requisite number of workers
|
||||
|
@ -176,7 +176,7 @@ public:
|
||||
GangWorker* allocate_worker(uint which);
|
||||
|
||||
// Run a task; returns when the task is done, or the workers yield,
|
||||
// or the task is aborted, or the work gang is terminated via stop().
|
||||
// or the task is aborted.
|
||||
// A task that has been yielded can be continued via this same interface
|
||||
// by using the same task repeatedly as the argument to the call.
|
||||
// It is expected that the YieldingFlexibleGangTask carries the appropriate
|
||||
|
@ -1183,7 +1183,7 @@ bool G1CollectedHeap::do_collection(bool explicit_gc,
|
||||
IsGCActiveMark x;
|
||||
|
||||
// Timing
|
||||
assert(gc_cause() != GCCause::_java_lang_system_gc || explicit_gc, "invariant");
|
||||
assert(!GCCause::is_user_requested_gc(gc_cause()) || explicit_gc, "invariant");
|
||||
TraceCPUTime tcpu(G1Log::finer(), true, gclog_or_tty);
|
||||
|
||||
{
|
||||
@ -2199,6 +2199,7 @@ bool G1CollectedHeap::should_do_concurrent_full_gc(GCCause::Cause cause) {
|
||||
switch (cause) {
|
||||
case GCCause::_gc_locker: return GCLockerInvokesConcurrent;
|
||||
case GCCause::_java_lang_system_gc: return ExplicitGCInvokesConcurrent;
|
||||
case GCCause::_dcmd_gc_run: return ExplicitGCInvokesConcurrent;
|
||||
case GCCause::_g1_humongous_allocation: return true;
|
||||
case GCCause::_update_allocation_context_stats_inc: return true;
|
||||
case GCCause::_wb_conc_mark: return true;
|
||||
|
@ -324,7 +324,8 @@ private:
|
||||
// explicitly started if:
|
||||
// (a) cause == _gc_locker and +GCLockerInvokesConcurrent, or
|
||||
// (b) cause == _java_lang_system_gc and +ExplicitGCInvokesConcurrent.
|
||||
// (c) cause == _g1_humongous_allocation
|
||||
// (c) cause == _dcmd_gc_run and +ExplicitGCInvokesConcurrent.
|
||||
// (d) cause == _g1_humongous_allocation
|
||||
bool should_do_concurrent_full_gc(GCCause::Cause cause);
|
||||
|
||||
// Keeps track of how many "old marking cycles" (i.e., Full GCs or
|
||||
|
@ -168,7 +168,7 @@ void VM_G1IncCollectionPause::doit_epilogue() {
|
||||
// +ExplicitGCInvokesConcurrent, we have to wait here for the cycle
|
||||
// that just started (or maybe one that was already in progress) to
|
||||
// finish.
|
||||
if (_gc_cause == GCCause::_java_lang_system_gc &&
|
||||
if (GCCause::is_user_requested_gc(_gc_cause) &&
|
||||
_should_initiate_conc_mark) {
|
||||
assert(ExplicitGCInvokesConcurrent,
|
||||
"the only way to be here is if ExplicitGCInvokesConcurrent is set");
|
||||
|
@ -130,7 +130,7 @@ void PSAdaptiveSizePolicy::major_collection_end(size_t amount_live,
|
||||
// Update the pause time.
|
||||
_major_timer.stop();
|
||||
|
||||
if (gc_cause != GCCause::_java_lang_system_gc ||
|
||||
if (!GCCause::is_user_requested_gc(gc_cause) ||
|
||||
UseAdaptiveSizePolicyWithSystemGC) {
|
||||
double major_pause_in_seconds = _major_timer.seconds();
|
||||
double major_pause_in_ms = major_pause_in_seconds * MILLIUNITS;
|
||||
|
@ -272,7 +272,7 @@ bool PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) {
|
||||
// Don't check if the size_policy is ready here. Let
|
||||
// the size_policy check that internally.
|
||||
if (UseAdaptiveGenerationSizePolicyAtMajorCollection &&
|
||||
((gc_cause != GCCause::_java_lang_system_gc) ||
|
||||
(!GCCause::is_user_requested_gc(gc_cause) ||
|
||||
UseAdaptiveSizePolicyWithSystemGC)) {
|
||||
// Swap the survivor spaces if from_space is empty. The
|
||||
// resize_young_gen() called below is normally used after
|
||||
|
@ -2053,7 +2053,7 @@ bool PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) {
|
||||
marking_phase(vmthread_cm, maximum_heap_compaction, &_gc_tracer);
|
||||
|
||||
bool max_on_system_gc = UseMaximumCompactionOnSystemGC
|
||||
&& gc_cause == GCCause::_java_lang_system_gc;
|
||||
&& GCCause::is_user_requested_gc(gc_cause);
|
||||
summary_phase(vmthread_cm, maximum_heap_compaction || max_on_system_gc);
|
||||
|
||||
COMPILER2_PRESENT(assert(DerivedPointerTable::is_active(), "Sanity"));
|
||||
@ -2089,7 +2089,7 @@ bool PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) {
|
||||
// Don't check if the size_policy is ready here. Let
|
||||
// the size_policy check that internally.
|
||||
if (UseAdaptiveGenerationSizePolicyAtMajorCollection &&
|
||||
((gc_cause != GCCause::_java_lang_system_gc) ||
|
||||
(!GCCause::is_user_requested_gc(gc_cause) ||
|
||||
UseAdaptiveSizePolicyWithSystemGC)) {
|
||||
// Swap the survivor spaces if from_space is empty. The
|
||||
// resize_young_gen() called below is normally used after
|
||||
|
@ -290,7 +290,7 @@ bool PSScavenge::invoke_no_policy() {
|
||||
|
||||
AdaptiveSizePolicyOutput(size_policy, heap->total_collections());
|
||||
|
||||
if ((gc_cause != GCCause::_java_lang_system_gc) ||
|
||||
if (!GCCause::is_user_requested_gc(gc_cause) ||
|
||||
UseAdaptiveSizePolicyWithSystemGC) {
|
||||
// Gather the feedback data for eden occupancy.
|
||||
young_gen->eden_space()->accumulate_statistics();
|
||||
|
@ -960,7 +960,7 @@ void DefNewGeneration::gc_epilogue(bool full) {
|
||||
GCCause::to_string(gch->gc_cause()));
|
||||
}
|
||||
assert(gch->gc_cause() == GCCause::_scavenge_alot ||
|
||||
(gch->gc_cause() == GCCause::_java_lang_system_gc && UseConcMarkSweepGC && ExplicitGCInvokesConcurrent) ||
|
||||
(GCCause::is_user_requested_gc(gch->gc_cause()) && UseConcMarkSweepGC && ExplicitGCInvokesConcurrent) ||
|
||||
!gch->incremental_collection_failed(),
|
||||
"Twice in a row");
|
||||
seen_incremental_collection_failed = false;
|
||||
|
@ -244,7 +244,7 @@ void AdaptiveSizePolicy::minor_collection_end(GCCause::Cause gc_cause) {
|
||||
// Update the pause time.
|
||||
_minor_timer.stop();
|
||||
|
||||
if (gc_cause != GCCause::_java_lang_system_gc ||
|
||||
if (!GCCause::is_user_requested_gc(gc_cause) ||
|
||||
UseAdaptiveSizePolicyWithSystemGC) {
|
||||
double minor_pause_in_seconds = _minor_timer.seconds();
|
||||
double minor_pause_in_ms = minor_pause_in_seconds * MILLIUNITS;
|
||||
|
@ -103,6 +103,9 @@ const char* GCCause::to_string(GCCause::Cause cause) {
|
||||
case _last_ditch_collection:
|
||||
return "Last ditch collection";
|
||||
|
||||
case _dcmd_gc_run:
|
||||
return "Diagnostic Command";
|
||||
|
||||
case _last_gc_cause:
|
||||
return "ILLEGAL VALUE - last gc cause - ILLEGAL VALUE";
|
||||
|
||||
|
@ -74,12 +74,15 @@ class GCCause : public AllStatic {
|
||||
_g1_humongous_allocation,
|
||||
|
||||
_last_ditch_collection,
|
||||
|
||||
_dcmd_gc_run,
|
||||
|
||||
_last_gc_cause
|
||||
};
|
||||
|
||||
inline static bool is_user_requested_gc(GCCause::Cause cause) {
|
||||
return (cause == GCCause::_java_lang_system_gc ||
|
||||
cause == GCCause::_jvmti_force_gc);
|
||||
cause == GCCause::_dcmd_gc_run);
|
||||
}
|
||||
|
||||
inline static bool is_serviceability_requested_gc(GCCause::Cause
|
||||
|
@ -304,9 +304,16 @@ bool GenCollectedHeap::must_clear_all_soft_refs() {
|
||||
}
|
||||
|
||||
bool GenCollectedHeap::should_do_concurrent_full_gc(GCCause::Cause cause) {
|
||||
return UseConcMarkSweepGC &&
|
||||
((cause == GCCause::_gc_locker && GCLockerInvokesConcurrent) ||
|
||||
(cause == GCCause::_java_lang_system_gc && ExplicitGCInvokesConcurrent));
|
||||
if (!UseConcMarkSweepGC) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (cause) {
|
||||
case GCCause::_gc_locker: return GCLockerInvokesConcurrent;
|
||||
case GCCause::_java_lang_system_gc:
|
||||
case GCCause::_dcmd_gc_run: return ExplicitGCInvokesConcurrent;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
void GenCollectedHeap::collect_generation(Generation* gen, bool full, size_t size,
|
||||
|
@ -47,7 +47,6 @@ AbstractWorkGang::AbstractWorkGang(const char* name,
|
||||
/* allow_vm_block */ are_GC_task_threads,
|
||||
Monitor::_safepoint_check_sometimes);
|
||||
assert(monitor() != NULL, "Failed to allocate monitor");
|
||||
_terminate = false;
|
||||
_task = NULL;
|
||||
_sequence_number = 0;
|
||||
_started_workers = 0;
|
||||
@ -106,18 +105,6 @@ bool WorkGang::initialize_workers() {
|
||||
return true;
|
||||
}
|
||||
|
||||
AbstractWorkGang::~AbstractWorkGang() {
|
||||
if (TraceWorkGang) {
|
||||
tty->print_cr("Destructing work gang %s", name());
|
||||
}
|
||||
stop(); // stop all the workers
|
||||
for (uint worker = 0; worker < total_workers(); worker += 1) {
|
||||
delete gang_worker(worker);
|
||||
}
|
||||
delete gang_workers();
|
||||
delete monitor();
|
||||
}
|
||||
|
||||
GangWorker* AbstractWorkGang::gang_worker(uint i) const {
|
||||
// Array index bounds checking.
|
||||
GangWorker* result = NULL;
|
||||
@ -175,28 +162,9 @@ void FlexibleWorkGang::run_task(AbstractGangTask* task) {
|
||||
WorkGang::run_task(task, (uint) active_workers());
|
||||
}
|
||||
|
||||
void AbstractWorkGang::stop() {
|
||||
// Tell all workers to terminate, then wait for them to become inactive.
|
||||
MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
|
||||
if (TraceWorkGang) {
|
||||
tty->print_cr("Stopping work gang %s task %s", name(), task()->name());
|
||||
}
|
||||
_task = NULL;
|
||||
_terminate = true;
|
||||
monitor()->notify_all();
|
||||
while (finished_workers() < active_workers()) {
|
||||
if (TraceWorkGang) {
|
||||
tty->print_cr("Waiting in work gang %s: %u/%u finished",
|
||||
name(), finished_workers(), active_workers());
|
||||
}
|
||||
monitor()->wait(/* no_safepoint_check */ true);
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractWorkGang::internal_worker_poll(WorkData* data) const {
|
||||
assert(monitor()->owned_by_self(), "worker_poll is an internal method");
|
||||
assert(data != NULL, "worker data is null");
|
||||
data->set_terminate(terminate());
|
||||
data->set_task(task());
|
||||
data->set_sequence_number(sequence_number());
|
||||
}
|
||||
@ -259,7 +227,7 @@ void GangWorker::initialize() {
|
||||
void GangWorker::loop() {
|
||||
int previous_sequence_number = 0;
|
||||
Monitor* gang_monitor = gang()->monitor();
|
||||
for ( ; /* !terminate() */; ) {
|
||||
for ( ; ; ) {
|
||||
WorkData data;
|
||||
int part; // Initialized below.
|
||||
{
|
||||
@ -272,8 +240,6 @@ void GangWorker::loop() {
|
||||
if (TraceWorkGang) {
|
||||
tty->print("Polled outside for work in gang %s worker %u",
|
||||
gang()->name(), id());
|
||||
tty->print(" terminate: %s",
|
||||
data.terminate() ? "true" : "false");
|
||||
tty->print(" sequence: %d (prev: %d)",
|
||||
data.sequence_number(), previous_sequence_number);
|
||||
if (data.task() != NULL) {
|
||||
@ -283,13 +249,7 @@ void GangWorker::loop() {
|
||||
}
|
||||
tty->cr();
|
||||
}
|
||||
for ( ; /* break or return */; ) {
|
||||
// Terminate if requested.
|
||||
if (data.terminate()) {
|
||||
gang()->internal_note_finish();
|
||||
gang_monitor->notify_all();
|
||||
return;
|
||||
}
|
||||
for ( ; /* break */; ) {
|
||||
// Check for new work.
|
||||
if ((data.task() != NULL) &&
|
||||
(data.sequence_number() != previous_sequence_number)) {
|
||||
@ -306,8 +266,6 @@ void GangWorker::loop() {
|
||||
if (TraceWorkGang) {
|
||||
tty->print("Polled inside for work in gang %s worker %u",
|
||||
gang()->name(), id());
|
||||
tty->print(" terminate: %s",
|
||||
data.terminate() ? "true" : "false");
|
||||
tty->print(" sequence: %d (prev: %d)",
|
||||
data.sequence_number(), previous_sequence_number);
|
||||
if (data.task() != NULL) {
|
||||
|
@ -103,16 +103,15 @@ class AbstractGangTaskWOopQueues : public AbstractGangTask {
|
||||
// An abstract class representing a gang of workers.
|
||||
// You subclass this to supply an implementation of run_task().
|
||||
class AbstractWorkGang: public CHeapObj<mtInternal> {
|
||||
// Here's the public interface to this class.
|
||||
protected:
|
||||
// Work gangs are never deleted, so no need to cleanup.
|
||||
~AbstractWorkGang() { ShouldNotReachHere(); }
|
||||
public:
|
||||
// Constructor and destructor.
|
||||
// Constructor.
|
||||
AbstractWorkGang(const char* name, bool are_GC_task_threads,
|
||||
bool are_ConcurrentGC_threads);
|
||||
~AbstractWorkGang();
|
||||
// Run a task, returns when the task is done (or terminated).
|
||||
virtual void run_task(AbstractGangTask* task) = 0;
|
||||
// Stop and terminate all workers.
|
||||
virtual void stop();
|
||||
// Return true if more workers should be applied to the task.
|
||||
virtual bool needs_more_workers() const { return true; }
|
||||
public:
|
||||
@ -129,8 +128,6 @@ protected:
|
||||
Monitor* _monitor;
|
||||
// The count of the number of workers in the gang.
|
||||
uint _total_workers;
|
||||
// Whether the workers should terminate.
|
||||
bool _terminate;
|
||||
// The array of worker threads for this gang.
|
||||
// This is only needed for cleaning up.
|
||||
GangWorker** _gang_workers;
|
||||
@ -153,9 +150,6 @@ public:
|
||||
virtual uint active_workers() const {
|
||||
return _total_workers;
|
||||
}
|
||||
bool terminate() const {
|
||||
return _terminate;
|
||||
}
|
||||
GangWorker** gang_workers() const {
|
||||
return _gang_workers;
|
||||
}
|
||||
@ -205,21 +199,16 @@ protected:
|
||||
class WorkData: public StackObj {
|
||||
// This would be a struct, but I want accessor methods.
|
||||
private:
|
||||
bool _terminate;
|
||||
AbstractGangTask* _task;
|
||||
int _sequence_number;
|
||||
public:
|
||||
// Constructor and destructor
|
||||
WorkData() {
|
||||
_terminate = false;
|
||||
_task = NULL;
|
||||
_sequence_number = 0;
|
||||
}
|
||||
~WorkData() {
|
||||
}
|
||||
// Accessors and modifiers
|
||||
bool terminate() const { return _terminate; }
|
||||
void set_terminate(bool value) { _terminate = value; }
|
||||
AbstractGangTask* task() const { return _task; }
|
||||
void set_task(AbstractGangTask* value) { _task = value; }
|
||||
int sequence_number() const { return _sequence_number; }
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 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
|
||||
@ -147,13 +147,10 @@ BasicType Bytecode_member_ref::result_type() const {
|
||||
|
||||
|
||||
methodHandle Bytecode_invoke::static_target(TRAPS) {
|
||||
methodHandle m;
|
||||
KlassHandle resolved_klass;
|
||||
constantPoolHandle constants(THREAD, this->constants());
|
||||
|
||||
Bytecodes::Code bc = invoke_code();
|
||||
LinkResolver::resolve_method_statically(m, resolved_klass, bc, constants, index(), CHECK_(methodHandle()));
|
||||
return m;
|
||||
return LinkResolver::resolve_method_statically(bc, constants, index(), THREAD);
|
||||
}
|
||||
|
||||
Handle Bytecode_invoke::appendix(TRAPS) {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 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
|
||||
@ -36,7 +36,7 @@
|
||||
// that method. If the info is invalid, the link has not been resolved
|
||||
// successfully.
|
||||
|
||||
class CallInfo VALUE_OBJ_CLASS_SPEC {
|
||||
class CallInfo : public StackObj {
|
||||
public:
|
||||
// Ways that a method call might be selected (or not) based on receiver type.
|
||||
// Note that an invokevirtual instruction might be linked with no_dispatch,
|
||||
@ -58,11 +58,22 @@ class CallInfo VALUE_OBJ_CLASS_SPEC {
|
||||
Handle _resolved_appendix; // extra argument in constant pool (if CPCE::has_appendix)
|
||||
Handle _resolved_method_type; // MethodType (for invokedynamic and invokehandle call sites)
|
||||
|
||||
void set_static( KlassHandle resolved_klass, methodHandle resolved_method , TRAPS);
|
||||
void set_interface(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int itable_index , TRAPS);
|
||||
void set_virtual( KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index , TRAPS);
|
||||
void set_handle( methodHandle resolved_method, Handle resolved_appendix, Handle resolved_method_type, TRAPS);
|
||||
void set_common( KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, CallKind kind, int index, TRAPS);
|
||||
void set_static(KlassHandle resolved_klass, const methodHandle& resolved_method, TRAPS);
|
||||
void set_interface(KlassHandle resolved_klass, KlassHandle selected_klass,
|
||||
const methodHandle& resolved_method,
|
||||
const methodHandle& selected_method,
|
||||
int itable_index, TRAPS);
|
||||
void set_virtual(KlassHandle resolved_klass, KlassHandle selected_klass,
|
||||
const methodHandle& resolved_method,
|
||||
const methodHandle& selected_method,
|
||||
int vtable_index, TRAPS);
|
||||
void set_handle(const methodHandle& resolved_method,
|
||||
Handle resolved_appendix, Handle resolved_method_type, TRAPS);
|
||||
void set_common(KlassHandle resolved_klass, KlassHandle selected_klass,
|
||||
const methodHandle& resolved_method,
|
||||
const methodHandle& selected_method,
|
||||
CallKind kind,
|
||||
int index, TRAPS);
|
||||
|
||||
friend class LinkResolver;
|
||||
|
||||
@ -113,6 +124,37 @@ class CallInfo VALUE_OBJ_CLASS_SPEC {
|
||||
void print() PRODUCT_RETURN;
|
||||
};
|
||||
|
||||
|
||||
// Condensed information from constant pool to use to resolve the method or field.
|
||||
// resolved_klass = specified class (i.e., static receiver class)
|
||||
// current_klass = sending method holder (i.e., class containing the method
|
||||
// containing the call being resolved)
|
||||
class LinkInfo : public StackObj {
|
||||
Symbol* _name; // extracted from JVM_CONSTANT_NameAndType
|
||||
Symbol* _signature;
|
||||
KlassHandle _resolved_klass; // class that the constant pool entry points to
|
||||
KlassHandle _current_klass; // class that owns the constant pool
|
||||
bool _check_access;
|
||||
public:
|
||||
LinkInfo(constantPoolHandle pool, int index, TRAPS);
|
||||
// Condensed information from other call sites within the vm.
|
||||
LinkInfo(KlassHandle resolved_klass, Symbol* name, Symbol* signature,
|
||||
KlassHandle current_klass, bool check_access = true) :
|
||||
_resolved_klass(resolved_klass),
|
||||
_name(name), _signature(signature), _current_klass(current_klass),
|
||||
_check_access(check_access) {}
|
||||
|
||||
// accessors
|
||||
Symbol* name() const { return _name; }
|
||||
Symbol* signature() const { return _signature; }
|
||||
KlassHandle resolved_klass() const { return _resolved_klass; }
|
||||
KlassHandle current_klass() const { return _current_klass; }
|
||||
bool check_access() const { return _check_access; }
|
||||
char* method_string() const;
|
||||
|
||||
void print() PRODUCT_RETURN;
|
||||
};
|
||||
|
||||
// Link information for getfield/putfield & getstatic/putstatic bytecodes
|
||||
// is represented using a fieldDescriptor.
|
||||
|
||||
@ -124,85 +166,136 @@ class LinkResolver: AllStatic {
|
||||
friend class klassItable;
|
||||
|
||||
private:
|
||||
static void lookup_method_in_klasses (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, bool checkpolymorphism, bool in_imethod_resolve, TRAPS);
|
||||
static void lookup_instance_method_in_klasses (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS);
|
||||
static void lookup_method_in_interfaces (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS);
|
||||
static void lookup_polymorphic_method (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature,
|
||||
KlassHandle current_klass, Handle *appendix_result_or_null, Handle *method_type_result, TRAPS);
|
||||
|
||||
static void resolve_klass (KlassHandle& result, constantPoolHandle pool, int index, TRAPS);
|
||||
static methodHandle lookup_method_in_klasses(const LinkInfo& link_info,
|
||||
bool checkpolymorphism,
|
||||
bool in_imethod_resolve, TRAPS);
|
||||
static methodHandle lookup_method_in_interfaces(const LinkInfo& link_info, TRAPS);
|
||||
static methodHandle lookup_polymorphic_method(const LinkInfo& link_info,
|
||||
Handle *appendix_result_or_null,
|
||||
Handle *method_type_result, TRAPS);
|
||||
// Not Linktime so doesn't take LinkInfo
|
||||
static methodHandle lookup_instance_method_in_klasses (
|
||||
KlassHandle klass, Symbol* name, Symbol* signature, TRAPS);
|
||||
|
||||
static void resolve_pool (KlassHandle& resolved_klass, Symbol*& method_name, Symbol*& method_signature, KlassHandle& current_klass, constantPoolHandle pool, int index, TRAPS);
|
||||
// Similar loader constraint checking functions that throw
|
||||
// LinkageError with descriptive message.
|
||||
static void check_method_loader_constraints(const LinkInfo& link_info,
|
||||
const methodHandle& resolved_method,
|
||||
const char* method_type, TRAPS);
|
||||
static void check_field_loader_constraints(Symbol* field, Symbol* sig,
|
||||
KlassHandle current_klass,
|
||||
KlassHandle sel_klass, TRAPS);
|
||||
|
||||
static void resolve_interface_method(methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool nostatics, TRAPS);
|
||||
static void resolve_method (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool require_methodref, TRAPS);
|
||||
static methodHandle resolve_interface_method(const LinkInfo& link_info, bool nostatics, TRAPS);
|
||||
static methodHandle resolve_method (const LinkInfo& link_info, bool require_methodref, TRAPS);
|
||||
|
||||
static void linktime_resolve_static_method (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS);
|
||||
static void linktime_resolve_special_method (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS);
|
||||
static void linktime_resolve_virtual_method (methodHandle &resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature,KlassHandle current_klass, bool check_access, TRAPS);
|
||||
static void linktime_resolve_interface_method (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS);
|
||||
static methodHandle linktime_resolve_static_method (const LinkInfo& link_info, TRAPS);
|
||||
static methodHandle linktime_resolve_special_method (const LinkInfo& link_info, TRAPS);
|
||||
static methodHandle linktime_resolve_virtual_method (const LinkInfo& link_info, TRAPS);
|
||||
static methodHandle linktime_resolve_interface_method (const LinkInfo& link_info, TRAPS);
|
||||
|
||||
static void runtime_resolve_special_method (CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass, KlassHandle current_klass, bool check_access, TRAPS);
|
||||
static void runtime_resolve_virtual_method (CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass, Handle recv, KlassHandle recv_klass, bool check_null_and_abstract, TRAPS);
|
||||
static void runtime_resolve_interface_method (CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass, Handle recv, KlassHandle recv_klass, bool check_null_and_abstract, TRAPS);
|
||||
static void runtime_resolve_special_method (CallInfo& result,
|
||||
const methodHandle& resolved_method,
|
||||
KlassHandle resolved_klass,
|
||||
KlassHandle current_klass,
|
||||
bool check_access, TRAPS);
|
||||
static void runtime_resolve_virtual_method (CallInfo& result,
|
||||
const methodHandle& resolved_method,
|
||||
KlassHandle resolved_klass,
|
||||
Handle recv,
|
||||
KlassHandle recv_klass,
|
||||
bool check_null_and_abstract, TRAPS);
|
||||
static void runtime_resolve_interface_method (CallInfo& result,
|
||||
const methodHandle& resolved_method,
|
||||
KlassHandle resolved_klass,
|
||||
Handle recv,
|
||||
KlassHandle recv_klass,
|
||||
bool check_null_and_abstract, TRAPS);
|
||||
|
||||
static void check_field_accessability (KlassHandle ref_klass, KlassHandle resolved_klass, KlassHandle sel_klass, fieldDescriptor& fd, TRAPS);
|
||||
static void check_method_accessability (KlassHandle ref_klass, KlassHandle resolved_klass, KlassHandle sel_klass, methodHandle sel_method, TRAPS);
|
||||
static void check_field_accessability(KlassHandle ref_klass,
|
||||
KlassHandle resolved_klass,
|
||||
KlassHandle sel_klass,
|
||||
const fieldDescriptor& fd, TRAPS);
|
||||
static void check_method_accessability(KlassHandle ref_klass,
|
||||
KlassHandle resolved_klass,
|
||||
KlassHandle sel_klass,
|
||||
const methodHandle& sel_method, TRAPS);
|
||||
|
||||
// runtime resolving from constant pool
|
||||
static void resolve_invokestatic (CallInfo& result,
|
||||
constantPoolHandle pool, int index, TRAPS);
|
||||
static void resolve_invokespecial (CallInfo& result,
|
||||
constantPoolHandle pool, int index, TRAPS);
|
||||
static void resolve_invokevirtual (CallInfo& result, Handle recv,
|
||||
constantPoolHandle pool, int index, TRAPS);
|
||||
static void resolve_invokeinterface(CallInfo& result, Handle recv,
|
||||
constantPoolHandle pool, int index, TRAPS);
|
||||
static void resolve_invokedynamic (CallInfo& result,
|
||||
constantPoolHandle pool, int index, TRAPS);
|
||||
static void resolve_invokehandle (CallInfo& result,
|
||||
constantPoolHandle pool, int index, TRAPS);
|
||||
public:
|
||||
// constant pool resolving
|
||||
static void check_klass_accessability(KlassHandle ref_klass, KlassHandle sel_klass, TRAPS);
|
||||
|
||||
// static resolving calls (will not run any Java code); used only from Bytecode_invoke::static_target
|
||||
static void resolve_method_statically(methodHandle& method_result, KlassHandle& klass_result,
|
||||
Bytecodes::Code code, constantPoolHandle pool, int index, TRAPS);
|
||||
// static resolving calls (will not run any Java code);
|
||||
// used only from Bytecode_invoke::static_target
|
||||
static methodHandle resolve_method_statically(Bytecodes::Code code,
|
||||
constantPoolHandle pool,
|
||||
int index, TRAPS);
|
||||
|
||||
// runtime/static resolving for fields
|
||||
static void resolve_field_access(fieldDescriptor& result, constantPoolHandle pool, int index, Bytecodes::Code byte, TRAPS);
|
||||
static void resolve_field(fieldDescriptor& result, KlassHandle resolved_klass, Symbol* field_name, Symbol* field_signature,
|
||||
KlassHandle current_klass, Bytecodes::Code access_kind, bool check_access, bool initialize_class, TRAPS);
|
||||
static void resolve_field_access(fieldDescriptor& result,
|
||||
constantPoolHandle pool,
|
||||
int index, Bytecodes::Code byte, TRAPS);
|
||||
static void resolve_field(fieldDescriptor& result, const LinkInfo& link_info,
|
||||
Bytecodes::Code access_kind,
|
||||
bool initialize_class, TRAPS);
|
||||
|
||||
// source of access_kind codes:
|
||||
static Bytecodes::Code field_access_kind(bool is_static, bool is_put) {
|
||||
return (is_static
|
||||
? (is_put ? Bytecodes::_putstatic : Bytecodes::_getstatic)
|
||||
: (is_put ? Bytecodes::_putfield : Bytecodes::_getfield ));
|
||||
}
|
||||
static void resolve_static_call (CallInfo& result,
|
||||
const LinkInfo& link_info,
|
||||
bool initialize_klass, TRAPS);
|
||||
static void resolve_special_call (CallInfo& result,
|
||||
const LinkInfo& link_info,
|
||||
TRAPS);
|
||||
static void resolve_virtual_call (CallInfo& result, Handle recv, KlassHandle recv_klass,
|
||||
const LinkInfo& link_info,
|
||||
bool check_null_and_abstract, TRAPS);
|
||||
static void resolve_interface_call(CallInfo& result, Handle recv, KlassHandle recv_klass,
|
||||
const LinkInfo& link_info,
|
||||
bool check_null_and_abstract, TRAPS);
|
||||
static void resolve_handle_call (CallInfo& result,
|
||||
const LinkInfo& link_info, TRAPS);
|
||||
static void resolve_dynamic_call (CallInfo& result, Handle bootstrap_specifier,
|
||||
Symbol* method_name, Symbol* method_signature,
|
||||
KlassHandle current_klass, TRAPS);
|
||||
|
||||
// runtime resolving:
|
||||
// resolved_klass = specified class (i.e., static receiver class)
|
||||
// current_klass = sending method holder (i.e., class containing the method containing the call being resolved)
|
||||
static void resolve_static_call (CallInfo& result, KlassHandle& resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool initialize_klass, TRAPS);
|
||||
static void resolve_special_call (CallInfo& result, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS);
|
||||
static void resolve_virtual_call (CallInfo& result, Handle recv, KlassHandle recv_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool check_null_and_abstract, TRAPS);
|
||||
static void resolve_interface_call(CallInfo& result, Handle recv, KlassHandle recv_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool check_null_and_abstract, TRAPS);
|
||||
static void resolve_handle_call (CallInfo& result, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, TRAPS);
|
||||
static void resolve_dynamic_call (CallInfo& result, Handle bootstrap_specifier, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, TRAPS);
|
||||
// same as above for compile-time resolution; but returns null handle instead of throwing
|
||||
// an exception on error also, does not initialize klass (i.e., no side effects)
|
||||
static methodHandle resolve_virtual_call_or_null (KlassHandle receiver_klass,
|
||||
const LinkInfo& link_info);
|
||||
static methodHandle resolve_interface_call_or_null(KlassHandle receiver_klass,
|
||||
const LinkInfo& link_info);
|
||||
static methodHandle resolve_static_call_or_null (const LinkInfo& link_info);
|
||||
static methodHandle resolve_special_call_or_null (const LinkInfo& link_info);
|
||||
|
||||
// same as above for compile-time resolution; but returns null handle instead of throwing an exception on error
|
||||
// also, does not initialize klass (i.e., no side effects)
|
||||
static methodHandle resolve_virtual_call_or_null (KlassHandle receiver_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access = true);
|
||||
static methodHandle resolve_interface_call_or_null(KlassHandle receiver_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access = true);
|
||||
static methodHandle resolve_static_call_or_null (KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access = true);
|
||||
static methodHandle resolve_special_call_or_null (KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access = true);
|
||||
static int vtable_index_of_interface_method(KlassHandle klass, methodHandle resolved_method);
|
||||
static int vtable_index_of_interface_method(KlassHandle klass, const methodHandle& resolved_method);
|
||||
|
||||
// same as above for compile-time resolution; returns vtable_index if current_klass if linked
|
||||
static int resolve_virtual_vtable_index (KlassHandle receiver_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass);
|
||||
static int resolve_virtual_vtable_index (KlassHandle receiver_klass,
|
||||
const LinkInfo& link_info);
|
||||
|
||||
// static resolving for compiler (does not throw exceptions, returns null handle if unsuccessful)
|
||||
static methodHandle linktime_resolve_virtual_method_or_null (KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access);
|
||||
static methodHandle linktime_resolve_interface_method_or_null(KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access);
|
||||
static methodHandle linktime_resolve_virtual_method_or_null (const LinkInfo& link_info);
|
||||
static methodHandle linktime_resolve_interface_method_or_null(const LinkInfo& link_info);
|
||||
|
||||
// runtime resolving from constant pool
|
||||
static void resolve_invokestatic (CallInfo& result, constantPoolHandle pool, int index, TRAPS);
|
||||
static void resolve_invokespecial (CallInfo& result, constantPoolHandle pool, int index, TRAPS);
|
||||
static void resolve_invokevirtual (CallInfo& result, Handle recv, constantPoolHandle pool, int index, TRAPS);
|
||||
static void resolve_invokeinterface(CallInfo& result, Handle recv, constantPoolHandle pool, int index, TRAPS);
|
||||
static void resolve_invokedynamic (CallInfo& result, constantPoolHandle pool, int index, TRAPS);
|
||||
static void resolve_invokehandle (CallInfo& result, constantPoolHandle pool, int index, TRAPS);
|
||||
|
||||
static void resolve_invoke (CallInfo& result, Handle recv, constantPoolHandle pool, int index, Bytecodes::Code byte, TRAPS);
|
||||
static void resolve_invoke(CallInfo& result, Handle recv,
|
||||
constantPoolHandle pool, int index,
|
||||
Bytecodes::Code byte, TRAPS);
|
||||
private:
|
||||
static void trace_method_resolution(const char* prefix, KlassHandle klass,
|
||||
KlassHandle resolved_klass,
|
||||
const methodHandle& method) PRODUCT_RETURN;
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_INTERPRETER_LINKRESOLVER_HPP
|
||||
|
@ -614,8 +614,7 @@ class SpaceManager : public CHeapObj<mtClass> {
|
||||
Metachunk* _chunks_in_use[NumberOfInUseLists];
|
||||
Metachunk* _current_chunk;
|
||||
|
||||
// Number of small chunks to allocate to a manager
|
||||
// If class space manager, small chunks are unlimited
|
||||
// Maximum number of small chunks to allocate to a SpaceManager
|
||||
static uint const _small_chunk_limit;
|
||||
|
||||
// Sum of all space in allocated chunks
|
||||
@ -730,6 +729,8 @@ class SpaceManager : public CHeapObj<mtClass> {
|
||||
// Block allocation and deallocation.
|
||||
// Allocates a block from the current chunk
|
||||
MetaWord* allocate(size_t word_size);
|
||||
// Allocates a block from a small chunk
|
||||
MetaWord* get_small_chunk_and_allocate(size_t word_size);
|
||||
|
||||
// Helper for allocations
|
||||
MetaWord* allocate_work(size_t word_size);
|
||||
@ -2011,9 +2012,8 @@ void SpaceManager::locked_print_chunks_in_use_on(outputStream* st) const {
|
||||
size_t SpaceManager::calc_chunk_size(size_t word_size) {
|
||||
|
||||
// Decide between a small chunk and a medium chunk. Up to
|
||||
// _small_chunk_limit small chunks can be allocated but
|
||||
// once a medium chunk has been allocated, no more small
|
||||
// chunks will be allocated.
|
||||
// _small_chunk_limit small chunks can be allocated.
|
||||
// After that a medium chunk is preferred.
|
||||
size_t chunk_word_size;
|
||||
if (chunks_in_use(MediumIndex) == NULL &&
|
||||
sum_count_in_chunks_in_use(SmallIndex) < _small_chunk_limit) {
|
||||
@ -2081,7 +2081,7 @@ MetaWord* SpaceManager::grow_and_allocate(size_t word_size) {
|
||||
word_size, words_used, words_left);
|
||||
}
|
||||
|
||||
// Get another chunk out of the virtual space
|
||||
// Get another chunk
|
||||
size_t grow_chunks_by_words = calc_chunk_size(word_size);
|
||||
Metachunk* next = get_new_chunk(word_size, grow_chunks_by_words);
|
||||
|
||||
@ -2412,6 +2412,43 @@ Metachunk* SpaceManager::get_new_chunk(size_t word_size,
|
||||
return next;
|
||||
}
|
||||
|
||||
/*
|
||||
* The policy is to allocate up to _small_chunk_limit small chunks
|
||||
* after which only medium chunks are allocated. This is done to
|
||||
* reduce fragmentation. In some cases, this can result in a lot
|
||||
* of small chunks being allocated to the point where it's not
|
||||
* possible to expand. If this happens, there may be no medium chunks
|
||||
* available and OOME would be thrown. Instead of doing that,
|
||||
* if the allocation request size fits in a small chunk, an attempt
|
||||
* will be made to allocate a small chunk.
|
||||
*/
|
||||
MetaWord* SpaceManager::get_small_chunk_and_allocate(size_t word_size) {
|
||||
if (word_size + Metachunk::overhead() > small_chunk_size()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag);
|
||||
MutexLockerEx cl1(expand_lock(), Mutex::_no_safepoint_check_flag);
|
||||
|
||||
Metachunk* chunk = chunk_manager()->chunk_freelist_allocate(small_chunk_size());
|
||||
|
||||
MetaWord* mem = NULL;
|
||||
|
||||
if (chunk != NULL) {
|
||||
// Add chunk to the in-use chunk list and do an allocation from it.
|
||||
// Add to this manager's list of chunks in use.
|
||||
add_chunk(chunk, false);
|
||||
mem = chunk->allocate(word_size);
|
||||
|
||||
inc_used_metrics(word_size);
|
||||
|
||||
// Track metaspace memory usage statistic.
|
||||
track_metaspace_memory_usage();
|
||||
}
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
MetaWord* SpaceManager::allocate(size_t word_size) {
|
||||
MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag);
|
||||
|
||||
@ -3560,7 +3597,18 @@ MetaWord* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size,
|
||||
}
|
||||
|
||||
if (result == NULL) {
|
||||
report_metadata_oome(loader_data, word_size, type, mdtype, CHECK_NULL);
|
||||
SpaceManager* sm;
|
||||
if (is_class_space_allocation(mdtype)) {
|
||||
sm = loader_data->metaspace_non_null()->class_vsm();
|
||||
} else {
|
||||
sm = loader_data->metaspace_non_null()->vsm();
|
||||
}
|
||||
|
||||
result = sm->get_small_chunk_and_allocate(word_size);
|
||||
|
||||
if (result == NULL) {
|
||||
report_metadata_oome(loader_data, word_size, type, mdtype, CHECK_NULL);
|
||||
}
|
||||
}
|
||||
|
||||
// Zero initialize.
|
||||
|
@ -622,14 +622,6 @@ bool InstanceKlass::link_class_impl(
|
||||
if (!this_k->is_linked()) {
|
||||
if (!this_k->is_rewritten()) {
|
||||
{
|
||||
// Timer includes any side effects of class verification (resolution,
|
||||
// etc), but not recursive entry into verify_code().
|
||||
PerfClassTraceTime timer(ClassLoader::perf_class_verify_time(),
|
||||
ClassLoader::perf_class_verify_selftime(),
|
||||
ClassLoader::perf_classes_verified(),
|
||||
jt->get_thread_stat()->perf_recursion_counts_addr(),
|
||||
jt->get_thread_stat()->perf_timers_addr(),
|
||||
PerfClassTraceTime::CLASS_VERIFY);
|
||||
bool verify_ok = verify_code(this_k, throw_verifyerror, THREAD);
|
||||
if (!verify_ok) {
|
||||
return false;
|
||||
@ -1830,11 +1822,10 @@ int nmethodBucket::decrement() {
|
||||
// are dependent on the changes that were passed in and mark them for
|
||||
// deoptimization. Returns the number of nmethods found.
|
||||
//
|
||||
int InstanceKlass::mark_dependent_nmethods(DepChange& changes) {
|
||||
int nmethodBucket::mark_dependent_nmethods(nmethodBucket* deps, DepChange& changes) {
|
||||
assert_locked_or_safepoint(CodeCache_lock);
|
||||
int found = 0;
|
||||
nmethodBucket* b = _dependencies;
|
||||
while (b != NULL) {
|
||||
for (nmethodBucket* b = deps; b != NULL; b = b->next()) {
|
||||
nmethod* nm = b->get_nmethod();
|
||||
// since dependencies aren't removed until an nmethod becomes a zombie,
|
||||
// the dependency list may contain nmethods which aren't alive.
|
||||
@ -1842,7 +1833,6 @@ int InstanceKlass::mark_dependent_nmethods(DepChange& changes) {
|
||||
if (TraceDependencies) {
|
||||
ResourceMark rm;
|
||||
tty->print_cr("Marked for deoptimization");
|
||||
tty->print_cr(" context = %s", this->external_name());
|
||||
changes.print();
|
||||
nm->print();
|
||||
nm->print_dependencies();
|
||||
@ -1850,36 +1840,119 @@ int InstanceKlass::mark_dependent_nmethods(DepChange& changes) {
|
||||
nm->mark_for_deoptimization();
|
||||
found++;
|
||||
}
|
||||
b = b->next();
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
//
|
||||
// Add an nmethodBucket to the list of dependencies for this nmethod.
|
||||
// It's possible that an nmethod has multiple dependencies on this klass
|
||||
// so a count is kept for each bucket to guarantee that creation and
|
||||
// deletion of dependencies is consistent. Returns new head of the list.
|
||||
//
|
||||
nmethodBucket* nmethodBucket::add_dependent_nmethod(nmethodBucket* deps, nmethod* nm) {
|
||||
assert_locked_or_safepoint(CodeCache_lock);
|
||||
for (nmethodBucket* b = deps; b != NULL; b = b->next()) {
|
||||
if (nm == b->get_nmethod()) {
|
||||
b->increment();
|
||||
return deps;
|
||||
}
|
||||
}
|
||||
return new nmethodBucket(nm, deps);
|
||||
}
|
||||
|
||||
//
|
||||
// Decrement count of the nmethod in the dependency list and remove
|
||||
// the bucket completely when the count goes to 0. This method must
|
||||
// find a corresponding bucket otherwise there's a bug in the
|
||||
// recording of dependencies. Returns true if the bucket is ready for reclamation.
|
||||
//
|
||||
bool nmethodBucket::remove_dependent_nmethod(nmethodBucket* deps, nmethod* nm) {
|
||||
assert_locked_or_safepoint(CodeCache_lock);
|
||||
|
||||
for (nmethodBucket* b = deps; b != NULL; b = b->next()) {
|
||||
if (nm == b->get_nmethod()) {
|
||||
int val = b->decrement();
|
||||
guarantee(val >= 0, err_msg("Underflow: %d", val));
|
||||
return (val == 0);
|
||||
}
|
||||
}
|
||||
#ifdef ASSERT
|
||||
tty->print_raw_cr("### can't find dependent nmethod");
|
||||
nm->print();
|
||||
#endif // ASSERT
|
||||
ShouldNotReachHere();
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Reclaim all unused buckets. Returns new head of the list.
|
||||
//
|
||||
nmethodBucket* nmethodBucket::clean_dependent_nmethods(nmethodBucket* deps) {
|
||||
nmethodBucket* first = deps;
|
||||
nmethodBucket* last = NULL;
|
||||
nmethodBucket* b = first;
|
||||
|
||||
while (b != NULL) {
|
||||
assert(b->count() >= 0, err_msg("bucket count: %d", b->count()));
|
||||
nmethodBucket* next = b->next();
|
||||
if (b->count() == 0) {
|
||||
if (last == NULL) {
|
||||
first = next;
|
||||
} else {
|
||||
last->set_next(next);
|
||||
}
|
||||
delete b;
|
||||
// last stays the same.
|
||||
} else {
|
||||
last = b;
|
||||
}
|
||||
b = next;
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
void nmethodBucket::print_dependent_nmethods(nmethodBucket* deps, bool verbose) {
|
||||
int idx = 0;
|
||||
for (nmethodBucket* b = deps; b != NULL; b = b->next()) {
|
||||
nmethod* nm = b->get_nmethod();
|
||||
tty->print("[%d] count=%d { ", idx++, b->count());
|
||||
if (!verbose) {
|
||||
nm->print_on(tty, "nmethod");
|
||||
tty->print_cr(" } ");
|
||||
} else {
|
||||
nm->print();
|
||||
nm->print_dependencies();
|
||||
tty->print_cr("--- } ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool nmethodBucket::is_dependent_nmethod(nmethodBucket* deps, nmethod* nm) {
|
||||
for (nmethodBucket* b = deps; b != NULL; b = b->next()) {
|
||||
if (nm == b->get_nmethod()) {
|
||||
#ifdef ASSERT
|
||||
int count = b->count();
|
||||
assert(count >= 0, err_msg("count shouldn't be negative: %d", count));
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif //PRODUCT
|
||||
|
||||
int InstanceKlass::mark_dependent_nmethods(DepChange& changes) {
|
||||
assert_locked_or_safepoint(CodeCache_lock);
|
||||
return nmethodBucket::mark_dependent_nmethods(_dependencies, changes);
|
||||
}
|
||||
|
||||
void InstanceKlass::clean_dependent_nmethods() {
|
||||
assert_locked_or_safepoint(CodeCache_lock);
|
||||
|
||||
if (has_unloaded_dependent()) {
|
||||
nmethodBucket* b = _dependencies;
|
||||
nmethodBucket* last = NULL;
|
||||
while (b != NULL) {
|
||||
assert(b->count() >= 0, err_msg("bucket count: %d", b->count()));
|
||||
|
||||
nmethodBucket* next = b->next();
|
||||
|
||||
if (b->count() == 0) {
|
||||
if (last == NULL) {
|
||||
_dependencies = next;
|
||||
} else {
|
||||
last->set_next(next);
|
||||
}
|
||||
delete b;
|
||||
// last stays the same.
|
||||
} else {
|
||||
last = b;
|
||||
}
|
||||
|
||||
b = next;
|
||||
}
|
||||
_dependencies = nmethodBucket::clean_dependent_nmethods(_dependencies);
|
||||
set_has_unloaded_dependent(false);
|
||||
}
|
||||
#ifdef ASSERT
|
||||
@ -1893,90 +1966,26 @@ void InstanceKlass::clean_dependent_nmethods() {
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
// Add an nmethodBucket to the list of dependencies for this nmethod.
|
||||
// It's possible that an nmethod has multiple dependencies on this klass
|
||||
// so a count is kept for each bucket to guarantee that creation and
|
||||
// deletion of dependencies is consistent.
|
||||
//
|
||||
void InstanceKlass::add_dependent_nmethod(nmethod* nm) {
|
||||
assert_locked_or_safepoint(CodeCache_lock);
|
||||
nmethodBucket* b = _dependencies;
|
||||
nmethodBucket* last = NULL;
|
||||
while (b != NULL) {
|
||||
if (nm == b->get_nmethod()) {
|
||||
b->increment();
|
||||
return;
|
||||
}
|
||||
b = b->next();
|
||||
}
|
||||
_dependencies = new nmethodBucket(nm, _dependencies);
|
||||
_dependencies = nmethodBucket::add_dependent_nmethod(_dependencies, nm);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Decrement count of the nmethod in the dependency list and remove
|
||||
// the bucket competely when the count goes to 0. This method must
|
||||
// find a corresponding bucket otherwise there's a bug in the
|
||||
// recording of dependecies.
|
||||
//
|
||||
void InstanceKlass::remove_dependent_nmethod(nmethod* nm) {
|
||||
assert_locked_or_safepoint(CodeCache_lock);
|
||||
nmethodBucket* b = _dependencies;
|
||||
nmethodBucket* last = NULL;
|
||||
while (b != NULL) {
|
||||
if (nm == b->get_nmethod()) {
|
||||
int val = b->decrement();
|
||||
guarantee(val >= 0, err_msg("Underflow: %d", val));
|
||||
if (val == 0) {
|
||||
set_has_unloaded_dependent(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
last = b;
|
||||
b = b->next();
|
||||
}
|
||||
#ifdef ASSERT
|
||||
tty->print_cr("### %s can't find dependent nmethod:", this->external_name());
|
||||
nm->print();
|
||||
#endif // ASSERT
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
|
||||
if (nmethodBucket::remove_dependent_nmethod(_dependencies, nm)) {
|
||||
set_has_unloaded_dependent(true);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
void InstanceKlass::print_dependent_nmethods(bool verbose) {
|
||||
nmethodBucket* b = _dependencies;
|
||||
int idx = 0;
|
||||
while (b != NULL) {
|
||||
nmethod* nm = b->get_nmethod();
|
||||
tty->print("[%d] count=%d { ", idx++, b->count());
|
||||
if (!verbose) {
|
||||
nm->print_on(tty, "nmethod");
|
||||
tty->print_cr(" } ");
|
||||
} else {
|
||||
nm->print();
|
||||
nm->print_dependencies();
|
||||
tty->print_cr("--- } ");
|
||||
}
|
||||
b = b->next();
|
||||
}
|
||||
nmethodBucket::print_dependent_nmethods(_dependencies, verbose);
|
||||
}
|
||||
|
||||
|
||||
bool InstanceKlass::is_dependent_nmethod(nmethod* nm) {
|
||||
nmethodBucket* b = _dependencies;
|
||||
while (b != NULL) {
|
||||
if (nm == b->get_nmethod()) {
|
||||
#ifdef ASSERT
|
||||
int count = b->count();
|
||||
assert(count >= 0, err_msg("count shouldn't be negative: %d", count));
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
b = b->next();
|
||||
}
|
||||
return false;
|
||||
return nmethodBucket::is_dependent_nmethod(_dependencies, nm);
|
||||
}
|
||||
#endif //PRODUCT
|
||||
|
||||
|
@ -1290,6 +1290,15 @@ class nmethodBucket: public CHeapObj<mtClass> {
|
||||
nmethodBucket* next() { return _next; }
|
||||
void set_next(nmethodBucket* b) { _next = b; }
|
||||
nmethod* get_nmethod() { return _nmethod; }
|
||||
|
||||
static int mark_dependent_nmethods(nmethodBucket* deps, DepChange& changes);
|
||||
static nmethodBucket* add_dependent_nmethod(nmethodBucket* deps, nmethod* nm);
|
||||
static bool remove_dependent_nmethod(nmethodBucket* deps, nmethod* nm);
|
||||
static nmethodBucket* clean_dependent_nmethods(nmethodBucket* deps);
|
||||
#ifndef PRODUCT
|
||||
static void print_dependent_nmethods(nmethodBucket* deps, bool verbose);
|
||||
static bool is_dependent_nmethod(nmethodBucket* deps, nmethod* nm);
|
||||
#endif //PRODUCT
|
||||
};
|
||||
|
||||
// An iterator that's used to access the inner classes indices in the
|
||||
|
@ -1136,7 +1136,7 @@ void klassItable::initialize_itable_for_interface(int method_table_offset, Klass
|
||||
if (m->has_itable_index()) {
|
||||
// This search must match the runtime resolution, i.e. selection search for invokeinterface
|
||||
// to correctly enforce loader constraints for interface method inheritance
|
||||
LinkResolver::lookup_instance_method_in_klasses(target, _klass, m->name(), m->signature(), CHECK);
|
||||
target = LinkResolver::lookup_instance_method_in_klasses(_klass, m->name(), m->signature(), CHECK);
|
||||
}
|
||||
if (target == NULL || !target->is_public() || target->is_abstract()) {
|
||||
// Entry does not resolve. Leave it empty for AbstractMethodError.
|
||||
|
@ -599,10 +599,14 @@ Node *ArrayCopyNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
}
|
||||
|
||||
bool ArrayCopyNode::may_modify(const TypeOopPtr *t_oop, PhaseTransform *phase) {
|
||||
const TypeOopPtr* dest_t = phase->type(in(ArrayCopyNode::Dest))->is_oopptr();
|
||||
Node* dest = in(ArrayCopyNode::Dest);
|
||||
if (dest->is_top()) {
|
||||
return false;
|
||||
}
|
||||
const TypeOopPtr* dest_t = phase->type(dest)->is_oopptr();
|
||||
assert(!dest_t->is_known_instance() || _dest_type->is_known_instance(), "result of EA not recorded");
|
||||
const TypeOopPtr* src_t = phase->type(in(ArrayCopyNode::Src))->is_oopptr();
|
||||
assert(!src_t->is_known_instance() || _src_type->is_known_instance(), "result of EA not recorded");
|
||||
assert(in(ArrayCopyNode::Src)->is_top() || !phase->type(in(ArrayCopyNode::Src))->is_oopptr()->is_known_instance() ||
|
||||
_src_type->is_known_instance(), "result of EA not recorded");
|
||||
|
||||
if (_dest_type != TypeOopPtr::BOTTOM || t_oop->is_known_instance()) {
|
||||
assert(_dest_type == TypeOopPtr::BOTTOM || _dest_type->is_known_instance(), "result of EA is known instance");
|
||||
|
@ -665,6 +665,12 @@
|
||||
product(bool, UseMultiplyToLenIntrinsic, false, \
|
||||
"Enables intrinsification of BigInteger.multiplyToLen()") \
|
||||
\
|
||||
product(bool, UseSquareToLenIntrinsic, false, \
|
||||
"Enables intrinsification of BigInteger.squareToLen()") \
|
||||
\
|
||||
product(bool, UseMulAddIntrinsic, false, \
|
||||
"Enables intrinsification of BigInteger.mulAdd()") \
|
||||
\
|
||||
product(bool, UseTypeSpeculation, true, \
|
||||
"Speculatively propagate types from profiles") \
|
||||
\
|
||||
|
@ -1946,7 +1946,7 @@ bool CallLeafNode::may_modify(const TypeOopPtr *t_oop, PhaseTransform *phase) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (may_modify_arraycopy_helper(phase->type(dest)->is_oopptr(), t_oop, phase)) {
|
||||
if (!dest->is_top() && may_modify_arraycopy_helper(phase->type(dest)->is_oopptr(), t_oop, phase)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -972,7 +972,9 @@ void ConnectionGraph::process_call_arguments(CallNode *call) {
|
||||
strcmp(call->as_CallLeaf()->_name, "sha256_implCompressMB") == 0 ||
|
||||
strcmp(call->as_CallLeaf()->_name, "sha512_implCompress") == 0 ||
|
||||
strcmp(call->as_CallLeaf()->_name, "sha512_implCompressMB") == 0 ||
|
||||
strcmp(call->as_CallLeaf()->_name, "multiplyToLen") == 0)
|
||||
strcmp(call->as_CallLeaf()->_name, "multiplyToLen") == 0 ||
|
||||
strcmp(call->as_CallLeaf()->_name, "squareToLen") == 0 ||
|
||||
strcmp(call->as_CallLeaf()->_name, "mulAdd") == 0)
|
||||
))) {
|
||||
call->dump();
|
||||
fatal(err_msg_res("EA unexpected CallLeaf %s", call->as_CallLeaf()->_name));
|
||||
|
@ -1457,18 +1457,18 @@ void GraphKit::set_all_memory_call(Node* call, bool separate_io_proj) {
|
||||
// factory methods in "int adr_idx"
|
||||
Node* GraphKit::make_load(Node* ctl, Node* adr, const Type* t, BasicType bt,
|
||||
int adr_idx,
|
||||
MemNode::MemOrd mo, bool require_atomic_access) {
|
||||
MemNode::MemOrd mo, LoadNode::ControlDependency control_dependency, bool require_atomic_access) {
|
||||
assert(adr_idx != Compile::AliasIdxTop, "use other make_load factory" );
|
||||
const TypePtr* adr_type = NULL; // debug-mode-only argument
|
||||
debug_only(adr_type = C->get_adr_type(adr_idx));
|
||||
Node* mem = memory(adr_idx);
|
||||
Node* ld;
|
||||
if (require_atomic_access && bt == T_LONG) {
|
||||
ld = LoadLNode::make_atomic(ctl, mem, adr, adr_type, t, mo);
|
||||
ld = LoadLNode::make_atomic(ctl, mem, adr, adr_type, t, mo, control_dependency);
|
||||
} else if (require_atomic_access && bt == T_DOUBLE) {
|
||||
ld = LoadDNode::make_atomic(ctl, mem, adr, adr_type, t, mo);
|
||||
ld = LoadDNode::make_atomic(ctl, mem, adr, adr_type, t, mo, control_dependency);
|
||||
} else {
|
||||
ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt, mo);
|
||||
ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt, mo, control_dependency);
|
||||
}
|
||||
ld = _gvn.transform(ld);
|
||||
if ((bt == T_OBJECT) && C->do_escape_analysis() || C->eliminate_boxing()) {
|
||||
|
@ -512,21 +512,24 @@ class GraphKit : public Phase {
|
||||
// adapted the `do_put_xxx' and `do_get_xxx' procedures for the case
|
||||
// of volatile fields.
|
||||
Node* make_load(Node* ctl, Node* adr, const Type* t, BasicType bt,
|
||||
MemNode::MemOrd mo, bool require_atomic_access = false) {
|
||||
MemNode::MemOrd mo, LoadNode::ControlDependency control_dependency = LoadNode::DependsOnlyOnTest,
|
||||
bool require_atomic_access = false) {
|
||||
// This version computes alias_index from bottom_type
|
||||
return make_load(ctl, adr, t, bt, adr->bottom_type()->is_ptr(),
|
||||
mo, require_atomic_access);
|
||||
mo, control_dependency, require_atomic_access);
|
||||
}
|
||||
Node* make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, const TypePtr* adr_type,
|
||||
MemNode::MemOrd mo, bool require_atomic_access = false) {
|
||||
MemNode::MemOrd mo, LoadNode::ControlDependency control_dependency = LoadNode::DependsOnlyOnTest,
|
||||
bool require_atomic_access = false) {
|
||||
// This version computes alias_index from an address type
|
||||
assert(adr_type != NULL, "use other make_load factory");
|
||||
return make_load(ctl, adr, t, bt, C->get_alias_index(adr_type),
|
||||
mo, require_atomic_access);
|
||||
mo, control_dependency, require_atomic_access);
|
||||
}
|
||||
// This is the base version which is given an alias index.
|
||||
Node* make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, int adr_idx,
|
||||
MemNode::MemOrd mo, bool require_atomic_access = false);
|
||||
MemNode::MemOrd mo, LoadNode::ControlDependency control_dependency = LoadNode::DependsOnlyOnTest,
|
||||
bool require_atomic_access = false);
|
||||
|
||||
// Create & transform a StoreNode and store the effect into the
|
||||
// parser's memory state.
|
||||
|
@ -817,19 +817,78 @@ bool IfNode::fold_compares_helper(ProjNode* proj, ProjNode* success, ProjNode* f
|
||||
BoolTest::mask hi_test = this_bool->_test._test;
|
||||
BoolTest::mask cond = hi_test;
|
||||
|
||||
// convert:
|
||||
//
|
||||
// dom_bool = x {<,<=,>,>=} a
|
||||
// / \
|
||||
// proj = {True,False} / \ otherproj = {False,True}
|
||||
// /
|
||||
// this_bool = x {<,<=} b
|
||||
// / \
|
||||
// fail = {True,False} / \ success = {False,True}
|
||||
// /
|
||||
//
|
||||
// (Second test guaranteed canonicalized, first one may not have
|
||||
// been canonicalized yet)
|
||||
//
|
||||
// into:
|
||||
//
|
||||
// cond = (x - lo) {<u,<=u,>u,>=u} adjusted_lim
|
||||
// / \
|
||||
// fail / \ success
|
||||
// /
|
||||
//
|
||||
|
||||
// Figure out which of the two tests sets the upper bound and which
|
||||
// sets the lower bound if any.
|
||||
Node* adjusted_lim = NULL;
|
||||
if (hi_type->_lo > lo_type->_hi && hi_type->_hi == max_jint && lo_type->_lo == min_jint) {
|
||||
|
||||
assert((dom_bool->_test.is_less() && !proj->_con) ||
|
||||
(dom_bool->_test.is_greater() && proj->_con), "incorrect test");
|
||||
// this test was canonicalized
|
||||
assert(this_bool->_test.is_less() && fail->_con, "incorrect test");
|
||||
|
||||
// this_bool = <
|
||||
// dom_bool = >= (proj = True) or dom_bool = < (proj = False)
|
||||
// x in [a, b[ on the fail (= True) projection, b > a-1 (because of hi_type->_lo > lo_type->_hi test above):
|
||||
// lo = a, hi = b, adjusted_lim = b-a, cond = <u
|
||||
// dom_bool = > (proj = True) or dom_bool = <= (proj = False)
|
||||
// x in ]a, b[ on the fail (= True) projection, b > a:
|
||||
// lo = a+1, hi = b, adjusted_lim = b-a-1, cond = <u
|
||||
// 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
|
||||
// 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
|
||||
|
||||
if (lo_test == BoolTest::gt || lo_test == BoolTest::le) {
|
||||
if (hi_test == BoolTest::le) {
|
||||
adjusted_lim = igvn->transform(new SubINode(hi, lo));
|
||||
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) {
|
||||
|
||||
// this_bool = <
|
||||
// dom_bool = < (proj = True) or dom_bool = >= (proj = False)
|
||||
// x in [b, a[ on the fail (= False) projection, a > b-1 (because of lo_type->_lo > hi_type->_hi above):
|
||||
// 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
|
||||
// this_bool = <=
|
||||
// dom_bool = < (proj = True) or dom_bool = >= (proj = False)
|
||||
// x in ]b, a[ on the fail (= False) projection, a > b:
|
||||
// lo = b+1, hi = a, adjusted_lim = a-b-1, cond = >=u
|
||||
// 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
|
||||
|
||||
swap(lo, hi);
|
||||
swap(lo_type, hi_type);
|
||||
swap(lo_test, hi_test);
|
||||
@ -842,6 +901,10 @@ bool IfNode::fold_compares_helper(ProjNode* proj, ProjNode* success, ProjNode* f
|
||||
cond = (hi_test == BoolTest::le || hi_test == BoolTest::gt) ? BoolTest::gt : BoolTest::ge;
|
||||
|
||||
if (lo_test == BoolTest::le) {
|
||||
if (cond == BoolTest::gt) {
|
||||
adjusted_lim = igvn->transform(new SubINode(hi, lo));
|
||||
cond = BoolTest::ge;
|
||||
}
|
||||
lo = igvn->transform(new AddINode(lo, igvn->intcon(1)));
|
||||
}
|
||||
|
||||
@ -860,7 +923,6 @@ bool IfNode::fold_compares_helper(ProjNode* proj, ProjNode* success, ProjNode* f
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lo = NULL;
|
||||
hi = NULL;
|
||||
}
|
||||
@ -868,12 +930,13 @@ bool IfNode::fold_compares_helper(ProjNode* proj, ProjNode* success, ProjNode* f
|
||||
if (lo && hi) {
|
||||
// Merge the two compares into a single unsigned compare by building (CmpU (n - lo) (hi - lo))
|
||||
Node* adjusted_val = igvn->transform(new SubINode(n, lo));
|
||||
Node* adjusted_lim = igvn->transform(new SubINode(hi, lo));
|
||||
if (adjusted_lim == NULL) {
|
||||
adjusted_lim = igvn->transform(new SubINode(hi, lo));
|
||||
}
|
||||
Node* newcmp = igvn->transform(new CmpUNode(adjusted_val, adjusted_lim));
|
||||
Node* newbool = igvn->transform(new BoolNode(newcmp, cond));
|
||||
|
||||
igvn->is_IterGVN()->replace_input_of(dom_iff, 1, igvn->intcon(proj->_con));
|
||||
igvn->hash_delete(this);
|
||||
igvn->replace_input_of(dom_iff, 1, igvn->intcon(proj->_con));
|
||||
set_req(1, newbool);
|
||||
|
||||
return true;
|
||||
|
@ -291,6 +291,8 @@ class LibraryCallKit : public GraphKit {
|
||||
bool inline_updateBytesCRC32();
|
||||
bool inline_updateByteBufferCRC32();
|
||||
bool inline_multiplyToLen();
|
||||
bool inline_squareToLen();
|
||||
bool inline_mulAdd();
|
||||
|
||||
bool inline_profileBoolean();
|
||||
bool inline_isCompileConstant();
|
||||
@ -494,6 +496,14 @@ CallGenerator* Compile::make_vm_intrinsic(ciMethod* m, bool is_virtual) {
|
||||
if (!UseMultiplyToLenIntrinsic) return NULL;
|
||||
break;
|
||||
|
||||
case vmIntrinsics::_squareToLen:
|
||||
if (!UseSquareToLenIntrinsic) return NULL;
|
||||
break;
|
||||
|
||||
case vmIntrinsics::_mulAdd:
|
||||
if (!UseMulAddIntrinsic) return NULL;
|
||||
break;
|
||||
|
||||
case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt:
|
||||
case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt:
|
||||
if (!UseAESIntrinsics) return NULL;
|
||||
@ -913,6 +923,12 @@ bool LibraryCallKit::try_to_inline(int predicate) {
|
||||
case vmIntrinsics::_multiplyToLen:
|
||||
return inline_multiplyToLen();
|
||||
|
||||
case vmIntrinsics::_squareToLen:
|
||||
return inline_squareToLen();
|
||||
|
||||
case vmIntrinsics::_mulAdd:
|
||||
return inline_mulAdd();
|
||||
|
||||
case vmIntrinsics::_encodeISOArray:
|
||||
return inline_encodeISOArray();
|
||||
|
||||
@ -2631,7 +2647,9 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas
|
||||
|
||||
if (!is_store) {
|
||||
MemNode::MemOrd mo = is_volatile ? MemNode::acquire : MemNode::unordered;
|
||||
Node* p = make_load(control(), adr, value_type, type, adr_type, mo, is_volatile);
|
||||
// To be valid, unsafe loads may depend on other conditions than
|
||||
// the one that guards them: pin the Load node
|
||||
Node* p = make_load(control(), adr, value_type, type, adr_type, mo, LoadNode::Pinned, is_volatile);
|
||||
// load value
|
||||
switch (type) {
|
||||
case T_BOOLEAN:
|
||||
@ -5304,6 +5322,100 @@ bool LibraryCallKit::inline_multiplyToLen() {
|
||||
return true;
|
||||
}
|
||||
|
||||
//-------------inline_squareToLen------------------------------------
|
||||
bool LibraryCallKit::inline_squareToLen() {
|
||||
assert(UseSquareToLenIntrinsic, "not implementated on this platform");
|
||||
|
||||
address stubAddr = StubRoutines::squareToLen();
|
||||
if (stubAddr == NULL) {
|
||||
return false; // Intrinsic's stub is not implemented on this platform
|
||||
}
|
||||
const char* stubName = "squareToLen";
|
||||
|
||||
assert(callee()->signature()->size() == 4, "implSquareToLen has 4 parameters");
|
||||
|
||||
Node* x = argument(0);
|
||||
Node* len = argument(1);
|
||||
Node* z = argument(2);
|
||||
Node* zlen = argument(3);
|
||||
|
||||
const Type* x_type = x->Value(&_gvn);
|
||||
const Type* z_type = z->Value(&_gvn);
|
||||
const TypeAryPtr* top_x = x_type->isa_aryptr();
|
||||
const TypeAryPtr* top_z = z_type->isa_aryptr();
|
||||
if (top_x == NULL || top_x->klass() == NULL ||
|
||||
top_z == NULL || top_z->klass() == NULL) {
|
||||
// failed array check
|
||||
return false;
|
||||
}
|
||||
|
||||
BasicType x_elem = x_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
|
||||
BasicType z_elem = z_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
|
||||
if (x_elem != T_INT || z_elem != T_INT) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Node* x_start = array_element_address(x, intcon(0), x_elem);
|
||||
Node* z_start = array_element_address(z, intcon(0), z_elem);
|
||||
|
||||
Node* call = make_runtime_call(RC_LEAF|RC_NO_FP,
|
||||
OptoRuntime::squareToLen_Type(),
|
||||
stubAddr, stubName, TypePtr::BOTTOM,
|
||||
x_start, len, z_start, zlen);
|
||||
|
||||
set_result(z);
|
||||
return true;
|
||||
}
|
||||
|
||||
//-------------inline_mulAdd------------------------------------------
|
||||
bool LibraryCallKit::inline_mulAdd() {
|
||||
assert(UseMulAddIntrinsic, "not implementated on this platform");
|
||||
|
||||
address stubAddr = StubRoutines::mulAdd();
|
||||
if (stubAddr == NULL) {
|
||||
return false; // Intrinsic's stub is not implemented on this platform
|
||||
}
|
||||
const char* stubName = "mulAdd";
|
||||
|
||||
assert(callee()->signature()->size() == 5, "mulAdd has 5 parameters");
|
||||
|
||||
Node* out = argument(0);
|
||||
Node* in = argument(1);
|
||||
Node* offset = argument(2);
|
||||
Node* len = argument(3);
|
||||
Node* k = argument(4);
|
||||
|
||||
const Type* out_type = out->Value(&_gvn);
|
||||
const Type* in_type = in->Value(&_gvn);
|
||||
const TypeAryPtr* top_out = out_type->isa_aryptr();
|
||||
const TypeAryPtr* top_in = in_type->isa_aryptr();
|
||||
if (top_out == NULL || top_out->klass() == NULL ||
|
||||
top_in == NULL || top_in->klass() == NULL) {
|
||||
// failed array check
|
||||
return false;
|
||||
}
|
||||
|
||||
BasicType out_elem = out_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
|
||||
BasicType in_elem = in_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
|
||||
if (out_elem != T_INT || in_elem != T_INT) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Node* outlen = load_array_length(out);
|
||||
Node* new_offset = _gvn.transform(new SubINode(outlen, offset));
|
||||
Node* out_start = array_element_address(out, intcon(0), out_elem);
|
||||
Node* in_start = array_element_address(in, intcon(0), in_elem);
|
||||
|
||||
Node* call = make_runtime_call(RC_LEAF|RC_NO_FP,
|
||||
OptoRuntime::mulAdd_Type(),
|
||||
stubAddr, stubName, TypePtr::BOTTOM,
|
||||
out_start,in_start, new_offset, len, k);
|
||||
Node* result = _gvn.transform(new ProjNode(call, TypeFunc::Parms));
|
||||
set_result(result);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculate CRC32 for byte.
|
||||
@ -5488,7 +5600,7 @@ Node * LibraryCallKit::load_field_from_object(Node * fromObj, const char * field
|
||||
}
|
||||
// Build the load.
|
||||
MemNode::MemOrd mo = is_vol ? MemNode::acquire : MemNode::unordered;
|
||||
Node* loadedField = make_load(NULL, adr, type, bt, adr_type, mo, is_vol);
|
||||
Node* loadedField = make_load(NULL, adr, type, bt, adr_type, mo, LoadNode::DependsOnlyOnTest, is_vol);
|
||||
// If reference is volatile, prevent following memory ops from
|
||||
// floating up past the volatile read. Also prevents commoning
|
||||
// another volatile read.
|
||||
|
@ -437,7 +437,13 @@ class Invariance : public StackObj {
|
||||
}
|
||||
}
|
||||
if (all_inputs_invariant) {
|
||||
_invariant.set(n->_idx); // I am a invariant too
|
||||
// If n's control is a predicate that was moved out of the
|
||||
// loop, it was marked invariant but n is only invariant if
|
||||
// it depends only on that test. Otherwise, unless that test
|
||||
// is out of the loop, it's not invariant.
|
||||
if (n->is_CFG() || n->depends_only_on_test() || n->in(0) == NULL || !_phase->is_member(_lpt, n->in(0))) {
|
||||
_invariant.set(n->_idx); // I am a invariant too
|
||||
}
|
||||
}
|
||||
} else { // process next input
|
||||
_stack.set_index(idx + 1);
|
||||
|
@ -475,7 +475,7 @@ void PhaseIdealLoop::do_peeling( IdealLoopTree *loop, Node_List &old_new ) {
|
||||
|
||||
C->set_major_progress();
|
||||
// Peeling a 'main' loop in a pre/main/post situation obfuscates the
|
||||
// 'pre' loop from the main and the 'pre' can no longer have it's
|
||||
// 'pre' loop from the main and the 'pre' can no longer have its
|
||||
// iterations adjusted. Therefore, we need to declare this loop as
|
||||
// no longer a 'main' loop; it will need new pre and post loops before
|
||||
// we can do further RCE.
|
||||
@ -1582,13 +1582,36 @@ void PhaseIdealLoop::mark_reductions(IdealLoopTree *loop) {
|
||||
if (opc != ReductionNode::opcode(opc, def_node->bottom_type()->basic_type())) {
|
||||
if (!def_node->is_reduction()) { // Not marked yet
|
||||
// To be a reduction, the arithmetic node must have the phi as input and provide a def to it
|
||||
bool ok = false;
|
||||
for (unsigned j = 1; j < def_node->req(); j++) {
|
||||
Node* in = def_node->in(j);
|
||||
if (in == phi) {
|
||||
def_node->add_flag(Node::Flag_is_reduction);
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// do nothing if we did not match the initial criteria
|
||||
if (ok == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// The result of the reduction must not be used in the loop
|
||||
for (DUIterator_Fast imax, i = def_node->fast_outs(imax); i < imax && ok; i++) {
|
||||
Node* u = def_node->fast_out(i);
|
||||
if (has_ctrl(u) && !loop->is_member(get_loop(get_ctrl(u)))) {
|
||||
continue;
|
||||
}
|
||||
if (u == phi) {
|
||||
continue;
|
||||
}
|
||||
ok = false;
|
||||
}
|
||||
|
||||
// iff the uses conform
|
||||
if (ok) {
|
||||
def_node->add_flag(Node::Flag_is_reduction);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1888,10 +1911,13 @@ void PhaseIdealLoop::do_range_check( IdealLoopTree *loop, Node_List &old_new ) {
|
||||
return;
|
||||
assert(opqzm->in(1) == main_limit, "do not understand situation");
|
||||
|
||||
// Find the pre-loop limit; we will expand it's iterations to
|
||||
// Find the pre-loop limit; we will expand its iterations to
|
||||
// not ever trip low tests.
|
||||
Node *p_f = iffm->in(0);
|
||||
assert(p_f->Opcode() == Op_IfFalse, "");
|
||||
// pre loop may have been optimized out
|
||||
if (p_f->Opcode() != Op_IfFalse) {
|
||||
return;
|
||||
}
|
||||
CountedLoopEndNode *pre_end = p_f->in(0)->as_CountedLoopEnd();
|
||||
assert(pre_end->loopnode()->is_pre_loop(), "");
|
||||
Node *pre_opaq1 = pre_end->limit();
|
||||
@ -2192,6 +2218,56 @@ void IdealLoopTree::adjust_loop_exit_prob( PhaseIdealLoop *phase ) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
static CountedLoopNode* locate_pre_from_main(CountedLoopNode *cl) {
|
||||
Node *ctrl = cl->in(LoopNode::EntryControl);
|
||||
assert(ctrl->Opcode() == Op_IfTrue || ctrl->Opcode() == Op_IfFalse, "");
|
||||
Node *iffm = ctrl->in(0);
|
||||
assert(iffm->Opcode() == Op_If, "");
|
||||
Node *p_f = iffm->in(0);
|
||||
assert(p_f->Opcode() == Op_IfFalse, "");
|
||||
CountedLoopEndNode *pre_end = p_f->in(0)->as_CountedLoopEnd();
|
||||
assert(pre_end->loopnode()->is_pre_loop(), "");
|
||||
return pre_end->loopnode();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Remove the main and post loops and make the pre loop execute all
|
||||
// iterations. Useful when the pre loop is found empty.
|
||||
void IdealLoopTree::remove_main_post_loops(CountedLoopNode *cl, PhaseIdealLoop *phase) {
|
||||
CountedLoopEndNode* pre_end = cl->loopexit();
|
||||
Node* pre_cmp = pre_end->cmp_node();
|
||||
if (pre_cmp->in(2)->Opcode() != Op_Opaque1) {
|
||||
// Only safe to remove the main loop if the compiler optimized it
|
||||
// out based on an unknown number of iterations
|
||||
return;
|
||||
}
|
||||
|
||||
// Can we find the main loop?
|
||||
if (_next == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
Node* next_head = _next->_head;
|
||||
if (!next_head->is_CountedLoop()) {
|
||||
return;
|
||||
}
|
||||
|
||||
CountedLoopNode* main_head = next_head->as_CountedLoop();
|
||||
if (!main_head->is_main_loop()) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(locate_pre_from_main(main_head) == cl, "bad main loop");
|
||||
Node* main_iff = main_head->in(LoopNode::EntryControl)->in(0);
|
||||
|
||||
// Remove the Opaque1Node of the pre loop and make it execute all iterations
|
||||
phase->_igvn.replace_input_of(pre_cmp, 2, pre_cmp->in(2)->in(2));
|
||||
// Remove the Opaque1Node of the main loop so it can be optimized out
|
||||
Node* main_cmp = main_iff->in(1)->in(1);
|
||||
assert(main_cmp->in(2)->Opcode() == Op_Opaque1, "main loop has no opaque node?");
|
||||
phase->_igvn.replace_input_of(main_cmp, 2, main_cmp->in(2)->in(1));
|
||||
}
|
||||
|
||||
//------------------------------policy_do_remove_empty_loop--------------------
|
||||
// Micro-benchmark spamming. Policy is to always remove empty loops.
|
||||
@ -2210,6 +2286,12 @@ bool IdealLoopTree::policy_do_remove_empty_loop( PhaseIdealLoop *phase ) {
|
||||
if (!phase->is_member(this, phase->get_ctrl(cl->loopexit()->in(CountedLoopEndNode::TestValue))))
|
||||
return false; // Infinite loop
|
||||
|
||||
if (cl->is_pre_loop()) {
|
||||
// If the loop we are removing is a pre-loop then the main and
|
||||
// post loop can be removed as well
|
||||
remove_main_post_loops(cl, phase);
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
// Ensure only one phi which is the iv.
|
||||
Node* iv = NULL;
|
||||
|
@ -485,6 +485,8 @@ public:
|
||||
bool is_inner() { return is_loop() && _child == NULL; }
|
||||
bool is_counted() { return is_loop() && _head != NULL && _head->is_CountedLoop(); }
|
||||
|
||||
void remove_main_post_loops(CountedLoopNode *cl, PhaseIdealLoop *phase);
|
||||
|
||||
#ifndef PRODUCT
|
||||
void dump_head( ) const; // Dump loop head only
|
||||
void dump() const; // Dump this loop recursively
|
||||
|
@ -718,7 +718,7 @@ Node *PhaseIdealLoop::split_if_with_blocks_pre( Node *n ) {
|
||||
}
|
||||
|
||||
// Use same limit as split_if_with_blocks_post
|
||||
if( C->unique() > 35000 ) return n; // Method too big
|
||||
if( C->live_nodes() > 35000 ) return n; // Method too big
|
||||
|
||||
// Split 'n' through the merge point if it is profitable
|
||||
Node *phi = split_thru_phi( n, n_blk, policy );
|
||||
@ -802,7 +802,7 @@ void PhaseIdealLoop::split_if_with_blocks_post( Node *n ) {
|
||||
// Cloning Cmp through Phi's involves the split-if transform.
|
||||
// FastLock is not used by an If
|
||||
if( n->is_Cmp() && !n->is_FastLock() ) {
|
||||
if( C->unique() > 35000 ) return; // Method too big
|
||||
if( C->live_nodes() > 35000 ) return; // Method too big
|
||||
|
||||
// Do not do 'split-if' if irreducible loops are present.
|
||||
if( _has_irreducible_loops )
|
||||
|
@ -844,7 +844,7 @@ void Matcher::init_spill_mask( Node *ret ) {
|
||||
MachNode *spillCP = match_tree(new LoadNNode(NULL,mem,fp,atp,TypeInstPtr::BOTTOM,MemNode::unordered));
|
||||
#endif
|
||||
MachNode *spillI = match_tree(new LoadINode(NULL,mem,fp,atp,TypeInt::INT,MemNode::unordered));
|
||||
MachNode *spillL = match_tree(new LoadLNode(NULL,mem,fp,atp,TypeLong::LONG,MemNode::unordered,false));
|
||||
MachNode *spillL = match_tree(new LoadLNode(NULL,mem,fp,atp,TypeLong::LONG,MemNode::unordered, LoadNode::DependsOnlyOnTest, false));
|
||||
MachNode *spillF = match_tree(new LoadFNode(NULL,mem,fp,atp,Type::FLOAT,MemNode::unordered));
|
||||
MachNode *spillD = match_tree(new LoadDNode(NULL,mem,fp,atp,Type::DOUBLE,MemNode::unordered));
|
||||
MachNode *spillP = match_tree(new LoadPNode(NULL,mem,fp,atp,TypeInstPtr::BOTTOM,MemNode::unordered));
|
||||
|
@ -784,6 +784,9 @@ void LoadNode::dump_spec(outputStream *st) const {
|
||||
// standard dump does this in Verbose and WizardMode
|
||||
st->print(" #"); _type->dump_on(st);
|
||||
}
|
||||
if (!_depends_only_on_test) {
|
||||
st->print(" (does not depend only on test)");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -800,7 +803,7 @@ bool LoadNode::is_immutable_value(Node* adr) {
|
||||
|
||||
//----------------------------LoadNode::make-----------------------------------
|
||||
// Polymorphic factory method:
|
||||
Node *LoadNode::make(PhaseGVN& gvn, Node *ctl, Node *mem, Node *adr, const TypePtr* adr_type, const Type *rt, BasicType bt, MemOrd mo) {
|
||||
Node *LoadNode::make(PhaseGVN& gvn, Node *ctl, Node *mem, Node *adr, const TypePtr* adr_type, const Type *rt, BasicType bt, MemOrd mo, ControlDependency control_dependency) {
|
||||
Compile* C = gvn.C;
|
||||
|
||||
// sanity check the alias category against the created node type
|
||||
@ -816,39 +819,39 @@ Node *LoadNode::make(PhaseGVN& gvn, Node *ctl, Node *mem, Node *adr, const TypeP
|
||||
rt->isa_oopptr() || is_immutable_value(adr),
|
||||
"raw memory operations should have control edge");
|
||||
switch (bt) {
|
||||
case T_BOOLEAN: return new LoadUBNode(ctl, mem, adr, adr_type, rt->is_int(), mo);
|
||||
case T_BYTE: return new LoadBNode (ctl, mem, adr, adr_type, rt->is_int(), mo);
|
||||
case T_INT: return new LoadINode (ctl, mem, adr, adr_type, rt->is_int(), mo);
|
||||
case T_CHAR: return new LoadUSNode(ctl, mem, adr, adr_type, rt->is_int(), mo);
|
||||
case T_SHORT: return new LoadSNode (ctl, mem, adr, adr_type, rt->is_int(), mo);
|
||||
case T_LONG: return new LoadLNode (ctl, mem, adr, adr_type, rt->is_long(), mo);
|
||||
case T_FLOAT: return new LoadFNode (ctl, mem, adr, adr_type, rt, mo);
|
||||
case T_DOUBLE: return new LoadDNode (ctl, mem, adr, adr_type, rt, mo);
|
||||
case T_ADDRESS: return new LoadPNode (ctl, mem, adr, adr_type, rt->is_ptr(), mo);
|
||||
case T_BOOLEAN: return new LoadUBNode(ctl, mem, adr, adr_type, rt->is_int(), mo, control_dependency);
|
||||
case T_BYTE: return new LoadBNode (ctl, mem, adr, adr_type, rt->is_int(), mo, control_dependency);
|
||||
case T_INT: return new LoadINode (ctl, mem, adr, adr_type, rt->is_int(), mo, control_dependency);
|
||||
case T_CHAR: return new LoadUSNode(ctl, mem, adr, adr_type, rt->is_int(), mo, control_dependency);
|
||||
case T_SHORT: return new LoadSNode (ctl, mem, adr, adr_type, rt->is_int(), mo, control_dependency);
|
||||
case T_LONG: return new LoadLNode (ctl, mem, adr, adr_type, rt->is_long(), mo, control_dependency);
|
||||
case T_FLOAT: return new LoadFNode (ctl, mem, adr, adr_type, rt, mo, control_dependency);
|
||||
case T_DOUBLE: return new LoadDNode (ctl, mem, adr, adr_type, rt, mo, control_dependency);
|
||||
case T_ADDRESS: return new LoadPNode (ctl, mem, adr, adr_type, rt->is_ptr(), mo, control_dependency);
|
||||
case T_OBJECT:
|
||||
#ifdef _LP64
|
||||
if (adr->bottom_type()->is_ptr_to_narrowoop()) {
|
||||
Node* load = gvn.transform(new LoadNNode(ctl, mem, adr, adr_type, rt->make_narrowoop(), mo));
|
||||
Node* load = gvn.transform(new LoadNNode(ctl, mem, adr, adr_type, rt->make_narrowoop(), mo, control_dependency));
|
||||
return new DecodeNNode(load, load->bottom_type()->make_ptr());
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
assert(!adr->bottom_type()->is_ptr_to_narrowoop() && !adr->bottom_type()->is_ptr_to_narrowklass(), "should have got back a narrow oop");
|
||||
return new LoadPNode(ctl, mem, adr, adr_type, rt->is_oopptr(), mo);
|
||||
return new LoadPNode(ctl, mem, adr, adr_type, rt->is_oopptr(), mo, control_dependency);
|
||||
}
|
||||
}
|
||||
ShouldNotReachHere();
|
||||
return (LoadNode*)NULL;
|
||||
}
|
||||
|
||||
LoadLNode* LoadLNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo) {
|
||||
LoadLNode* LoadLNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo, ControlDependency control_dependency) {
|
||||
bool require_atomic = true;
|
||||
return new LoadLNode(ctl, mem, adr, adr_type, rt->is_long(), mo, require_atomic);
|
||||
return new LoadLNode(ctl, mem, adr, adr_type, rt->is_long(), mo, control_dependency, require_atomic);
|
||||
}
|
||||
|
||||
LoadDNode* LoadDNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo) {
|
||||
LoadDNode* LoadDNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo, ControlDependency control_dependency) {
|
||||
bool require_atomic = true;
|
||||
return new LoadDNode(ctl, mem, adr, adr_type, rt, mo, require_atomic);
|
||||
return new LoadDNode(ctl, mem, adr, adr_type, rt, mo, control_dependency, require_atomic);
|
||||
}
|
||||
|
||||
|
||||
|
@ -137,7 +137,33 @@ public:
|
||||
//------------------------------LoadNode---------------------------------------
|
||||
// Load value; requires Memory and Address
|
||||
class LoadNode : public MemNode {
|
||||
public:
|
||||
// Some loads (from unsafe) should be pinned: they don't depend only
|
||||
// on the dominating test. The boolean field _depends_only_on_test
|
||||
// below records whether that node depends only on the dominating
|
||||
// test.
|
||||
// Methods used to build LoadNodes pass an argument of type enum
|
||||
// ControlDependency instead of a boolean because those methods
|
||||
// typically have multiple boolean parameters with default values:
|
||||
// passing the wrong boolean to one of these parameters by mistake
|
||||
// goes easily unnoticed. Using an enum, the compiler can check that
|
||||
// the type of a value and the type of the parameter match.
|
||||
enum ControlDependency {
|
||||
Pinned,
|
||||
DependsOnlyOnTest
|
||||
};
|
||||
private:
|
||||
// LoadNode::hash() doesn't take the _depends_only_on_test field
|
||||
// into account: If the graph already has a non-pinned LoadNode and
|
||||
// we add a pinned LoadNode with the same inputs, it's safe for GVN
|
||||
// to replace the pinned LoadNode with the non-pinned LoadNode,
|
||||
// otherwise it wouldn't be safe to have a non pinned LoadNode with
|
||||
// those inputs in the first place. If the graph already has a
|
||||
// pinned LoadNode and we add a non pinned LoadNode with the same
|
||||
// inputs, it's safe (but suboptimal) for GVN to replace the
|
||||
// non-pinned LoadNode by the pinned LoadNode.
|
||||
bool _depends_only_on_test;
|
||||
|
||||
// On platforms with weak memory ordering (e.g., PPC, Ia64) we distinguish
|
||||
// loads that can be reordered, and such requiring acquire semantics to
|
||||
// adhere to the Java specification. The required behaviour is stored in
|
||||
@ -154,8 +180,8 @@ protected:
|
||||
virtual Node* find_previous_arraycopy(PhaseTransform* phase, Node* ld_alloc, Node*& mem, bool can_see_stored_value) const;
|
||||
public:
|
||||
|
||||
LoadNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *rt, MemOrd mo)
|
||||
: MemNode(c,mem,adr,at), _type(rt), _mo(mo) {
|
||||
LoadNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *rt, MemOrd mo, ControlDependency control_dependency)
|
||||
: MemNode(c,mem,adr,at), _type(rt), _mo(mo), _depends_only_on_test(control_dependency == DependsOnlyOnTest) {
|
||||
init_class_id(Class_Load);
|
||||
}
|
||||
inline bool is_unordered() const { return !is_acquire(); }
|
||||
@ -166,7 +192,8 @@ public:
|
||||
|
||||
// Polymorphic factory method:
|
||||
static Node* make(PhaseGVN& gvn, Node *c, Node *mem, Node *adr,
|
||||
const TypePtr* at, const Type *rt, BasicType bt, MemOrd mo);
|
||||
const TypePtr* at, const Type *rt, BasicType bt,
|
||||
MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest);
|
||||
|
||||
virtual uint hash() const; // Check the type
|
||||
|
||||
@ -234,16 +261,15 @@ protected:
|
||||
// which produce results (new raw memory state) inside of loops preventing all
|
||||
// manner of other optimizations). Basically, it's ugly but so is the alternative.
|
||||
// See comment in macro.cpp, around line 125 expand_allocate_common().
|
||||
virtual bool depends_only_on_test() const { return adr_type() != TypeRawPtr::BOTTOM; }
|
||||
|
||||
virtual bool depends_only_on_test() const { return adr_type() != TypeRawPtr::BOTTOM && _depends_only_on_test; }
|
||||
};
|
||||
|
||||
//------------------------------LoadBNode--------------------------------------
|
||||
// Load a byte (8bits signed) from memory
|
||||
class LoadBNode : public LoadNode {
|
||||
public:
|
||||
LoadBNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo)
|
||||
: LoadNode(c, mem, adr, at, ti, mo) {}
|
||||
LoadBNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
|
||||
: LoadNode(c, mem, adr, at, ti, mo, control_dependency) {}
|
||||
virtual int Opcode() const;
|
||||
virtual uint ideal_reg() const { return Op_RegI; }
|
||||
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
|
||||
@ -256,8 +282,8 @@ public:
|
||||
// Load a unsigned byte (8bits unsigned) from memory
|
||||
class LoadUBNode : public LoadNode {
|
||||
public:
|
||||
LoadUBNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeInt* ti, MemOrd mo)
|
||||
: LoadNode(c, mem, adr, at, ti, mo) {}
|
||||
LoadUBNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeInt* ti, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
|
||||
: LoadNode(c, mem, adr, at, ti, mo, control_dependency) {}
|
||||
virtual int Opcode() const;
|
||||
virtual uint ideal_reg() const { return Op_RegI; }
|
||||
virtual Node* Ideal(PhaseGVN *phase, bool can_reshape);
|
||||
@ -270,8 +296,8 @@ public:
|
||||
// Load an unsigned short/char (16bits unsigned) from memory
|
||||
class LoadUSNode : public LoadNode {
|
||||
public:
|
||||
LoadUSNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo)
|
||||
: LoadNode(c, mem, adr, at, ti, mo) {}
|
||||
LoadUSNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
|
||||
: LoadNode(c, mem, adr, at, ti, mo, control_dependency) {}
|
||||
virtual int Opcode() const;
|
||||
virtual uint ideal_reg() const { return Op_RegI; }
|
||||
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
|
||||
@ -284,8 +310,8 @@ public:
|
||||
// Load a short (16bits signed) from memory
|
||||
class LoadSNode : public LoadNode {
|
||||
public:
|
||||
LoadSNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo)
|
||||
: LoadNode(c, mem, adr, at, ti, mo) {}
|
||||
LoadSNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
|
||||
: LoadNode(c, mem, adr, at, ti, mo, control_dependency) {}
|
||||
virtual int Opcode() const;
|
||||
virtual uint ideal_reg() const { return Op_RegI; }
|
||||
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
|
||||
@ -298,8 +324,8 @@ public:
|
||||
// Load an integer from memory
|
||||
class LoadINode : public LoadNode {
|
||||
public:
|
||||
LoadINode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo)
|
||||
: LoadNode(c, mem, adr, at, ti, mo) {}
|
||||
LoadINode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
|
||||
: LoadNode(c, mem, adr, at, ti, mo, control_dependency) {}
|
||||
virtual int Opcode() const;
|
||||
virtual uint ideal_reg() const { return Op_RegI; }
|
||||
virtual int store_Opcode() const { return Op_StoreI; }
|
||||
@ -331,15 +357,15 @@ class LoadLNode : public LoadNode {
|
||||
|
||||
public:
|
||||
LoadLNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeLong *tl,
|
||||
MemOrd mo, bool require_atomic_access = false)
|
||||
: LoadNode(c, mem, adr, at, tl, mo), _require_atomic_access(require_atomic_access) {}
|
||||
MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest, bool require_atomic_access = false)
|
||||
: LoadNode(c, mem, adr, at, tl, mo, control_dependency), _require_atomic_access(require_atomic_access) {}
|
||||
virtual int Opcode() const;
|
||||
virtual uint ideal_reg() const { return Op_RegL; }
|
||||
virtual int store_Opcode() const { return Op_StoreL; }
|
||||
virtual BasicType memory_type() const { return T_LONG; }
|
||||
bool require_atomic_access() const { return _require_atomic_access; }
|
||||
static LoadLNode* make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type,
|
||||
const Type* rt, MemOrd mo);
|
||||
const Type* rt, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest);
|
||||
#ifndef PRODUCT
|
||||
virtual void dump_spec(outputStream *st) const {
|
||||
LoadNode::dump_spec(st);
|
||||
@ -352,8 +378,8 @@ public:
|
||||
// Load a long from unaligned memory
|
||||
class LoadL_unalignedNode : public LoadLNode {
|
||||
public:
|
||||
LoadL_unalignedNode(Node *c, Node *mem, Node *adr, const TypePtr* at, MemOrd mo)
|
||||
: LoadLNode(c, mem, adr, at, TypeLong::LONG, mo) {}
|
||||
LoadL_unalignedNode(Node *c, Node *mem, Node *adr, const TypePtr* at, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
|
||||
: LoadLNode(c, mem, adr, at, TypeLong::LONG, mo, control_dependency) {}
|
||||
virtual int Opcode() const;
|
||||
};
|
||||
|
||||
@ -361,8 +387,8 @@ public:
|
||||
// Load a float (64 bits) from memory
|
||||
class LoadFNode : public LoadNode {
|
||||
public:
|
||||
LoadFNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *t, MemOrd mo)
|
||||
: LoadNode(c, mem, adr, at, t, mo) {}
|
||||
LoadFNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *t, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
|
||||
: LoadNode(c, mem, adr, at, t, mo, control_dependency) {}
|
||||
virtual int Opcode() const;
|
||||
virtual uint ideal_reg() const { return Op_RegF; }
|
||||
virtual int store_Opcode() const { return Op_StoreF; }
|
||||
@ -382,15 +408,15 @@ class LoadDNode : public LoadNode {
|
||||
|
||||
public:
|
||||
LoadDNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *t,
|
||||
MemOrd mo, bool require_atomic_access = false)
|
||||
: LoadNode(c, mem, adr, at, t, mo), _require_atomic_access(require_atomic_access) {}
|
||||
MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest, bool require_atomic_access = false)
|
||||
: LoadNode(c, mem, adr, at, t, mo, control_dependency), _require_atomic_access(require_atomic_access) {}
|
||||
virtual int Opcode() const;
|
||||
virtual uint ideal_reg() const { return Op_RegD; }
|
||||
virtual int store_Opcode() const { return Op_StoreD; }
|
||||
virtual BasicType memory_type() const { return T_DOUBLE; }
|
||||
bool require_atomic_access() const { return _require_atomic_access; }
|
||||
static LoadDNode* make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type,
|
||||
const Type* rt, MemOrd mo);
|
||||
const Type* rt, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest);
|
||||
#ifndef PRODUCT
|
||||
virtual void dump_spec(outputStream *st) const {
|
||||
LoadNode::dump_spec(st);
|
||||
@ -403,8 +429,8 @@ public:
|
||||
// Load a double from unaligned memory
|
||||
class LoadD_unalignedNode : public LoadDNode {
|
||||
public:
|
||||
LoadD_unalignedNode(Node *c, Node *mem, Node *adr, const TypePtr* at, MemOrd mo)
|
||||
: LoadDNode(c, mem, adr, at, Type::DOUBLE, mo) {}
|
||||
LoadD_unalignedNode(Node *c, Node *mem, Node *adr, const TypePtr* at, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
|
||||
: LoadDNode(c, mem, adr, at, Type::DOUBLE, mo, control_dependency) {}
|
||||
virtual int Opcode() const;
|
||||
};
|
||||
|
||||
@ -412,8 +438,8 @@ public:
|
||||
// Load a pointer from memory (either object or array)
|
||||
class LoadPNode : public LoadNode {
|
||||
public:
|
||||
LoadPNode(Node *c, Node *mem, Node *adr, const TypePtr *at, const TypePtr* t, MemOrd mo)
|
||||
: LoadNode(c, mem, adr, at, t, mo) {}
|
||||
LoadPNode(Node *c, Node *mem, Node *adr, const TypePtr *at, const TypePtr* t, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
|
||||
: LoadNode(c, mem, adr, at, t, mo, control_dependency) {}
|
||||
virtual int Opcode() const;
|
||||
virtual uint ideal_reg() const { return Op_RegP; }
|
||||
virtual int store_Opcode() const { return Op_StoreP; }
|
||||
@ -425,8 +451,8 @@ public:
|
||||
// Load a narrow oop from memory (either object or array)
|
||||
class LoadNNode : public LoadNode {
|
||||
public:
|
||||
LoadNNode(Node *c, Node *mem, Node *adr, const TypePtr *at, const Type* t, MemOrd mo)
|
||||
: LoadNode(c, mem, adr, at, t, mo) {}
|
||||
LoadNNode(Node *c, Node *mem, Node *adr, const TypePtr *at, const Type* t, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
|
||||
: LoadNode(c, mem, adr, at, t, mo, control_dependency) {}
|
||||
virtual int Opcode() const;
|
||||
virtual uint ideal_reg() const { return Op_RegN; }
|
||||
virtual int store_Opcode() const { return Op_StoreN; }
|
||||
|
@ -235,7 +235,7 @@ void Parse::do_get_xxx(Node* obj, ciField* field, bool is_field) {
|
||||
//
|
||||
MemNode::MemOrd mo = is_vol ? MemNode::acquire : MemNode::unordered;
|
||||
bool needs_atomic_access = is_vol || AlwaysAtomicAccesses;
|
||||
Node* ld = make_load(NULL, adr, type, bt, adr_type, mo, needs_atomic_access);
|
||||
Node* ld = make_load(NULL, adr, type, bt, adr_type, mo, LoadNode::DependsOnlyOnTest, needs_atomic_access);
|
||||
|
||||
// Adjust Java stack
|
||||
if (type2size[bt] == 1)
|
||||
|
@ -1573,11 +1573,12 @@ void PhaseCCP::analyze() {
|
||||
set_type(n, t);
|
||||
for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
|
||||
Node* m = n->fast_out(i); // Get user
|
||||
if( m->is_Region() ) { // New path to Region? Must recheck Phis too
|
||||
if (m->is_Region()) { // New path to Region? Must recheck Phis too
|
||||
for (DUIterator_Fast i2max, i2 = m->fast_outs(i2max); i2 < i2max; i2++) {
|
||||
Node* p = m->fast_out(i2); // Propagate changes to uses
|
||||
if( p->bottom_type() != type(p) ) // If not already bottomed out
|
||||
if (p->bottom_type() != type(p)) { // If not already bottomed out
|
||||
worklist.push(p); // Propagate change to user
|
||||
}
|
||||
}
|
||||
}
|
||||
// If we changed the receiver type to a call, we need to revisit
|
||||
@ -1587,12 +1588,31 @@ void PhaseCCP::analyze() {
|
||||
if (m->is_Call()) {
|
||||
for (DUIterator_Fast i2max, i2 = m->fast_outs(i2max); i2 < i2max; i2++) {
|
||||
Node* p = m->fast_out(i2); // Propagate changes to uses
|
||||
if (p->is_Proj() && p->as_Proj()->_con == TypeFunc::Control && p->outcnt() == 1)
|
||||
if (p->is_Proj() && p->as_Proj()->_con == TypeFunc::Control && p->outcnt() == 1) {
|
||||
worklist.push(p->unique_out());
|
||||
}
|
||||
}
|
||||
}
|
||||
if( m->bottom_type() != type(m) ) // If not already bottomed out
|
||||
if (m->bottom_type() != type(m)) { // If not already bottomed out
|
||||
worklist.push(m); // Propagate change to user
|
||||
}
|
||||
|
||||
// CmpU nodes can get their type information from two nodes up in the
|
||||
// graph (instead of from the nodes immediately above). Make sure they
|
||||
// are added to the worklist if nodes they depend on are updated, since
|
||||
// they could be missed and get wrong types otherwise.
|
||||
uint m_op = m->Opcode();
|
||||
if (m_op == Op_AddI || m_op == Op_SubI) {
|
||||
for (DUIterator_Fast i2max, i2 = m->fast_outs(i2max); i2 < i2max; i2++) {
|
||||
Node* p = m->fast_out(i2); // Propagate changes to uses
|
||||
if (p->Opcode() == Op_CmpU) {
|
||||
// Got a CmpU which might need the new type information from node n.
|
||||
if(p->bottom_type() != type(p)) { // If not already bottomed out
|
||||
worklist.push(p); // Propagate change to user
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -945,6 +945,48 @@ const TypeFunc* OptoRuntime::multiplyToLen_Type() {
|
||||
return TypeFunc::make(domain, range);
|
||||
}
|
||||
|
||||
const TypeFunc* OptoRuntime::squareToLen_Type() {
|
||||
// create input type (domain)
|
||||
int num_args = 4;
|
||||
int argcnt = num_args;
|
||||
const Type** fields = TypeTuple::fields(argcnt);
|
||||
int argp = TypeFunc::Parms;
|
||||
fields[argp++] = TypePtr::NOTNULL; // x
|
||||
fields[argp++] = TypeInt::INT; // len
|
||||
fields[argp++] = TypePtr::NOTNULL; // z
|
||||
fields[argp++] = TypeInt::INT; // zlen
|
||||
assert(argp == TypeFunc::Parms+argcnt, "correct decoding");
|
||||
const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields);
|
||||
|
||||
// no result type needed
|
||||
fields = TypeTuple::fields(1);
|
||||
fields[TypeFunc::Parms+0] = NULL;
|
||||
const TypeTuple* range = TypeTuple::make(TypeFunc::Parms, fields);
|
||||
return TypeFunc::make(domain, range);
|
||||
}
|
||||
|
||||
// for mulAdd calls, 2 pointers and 3 ints, returning int
|
||||
const TypeFunc* OptoRuntime::mulAdd_Type() {
|
||||
// create input type (domain)
|
||||
int num_args = 5;
|
||||
int argcnt = num_args;
|
||||
const Type** fields = TypeTuple::fields(argcnt);
|
||||
int argp = TypeFunc::Parms;
|
||||
fields[argp++] = TypePtr::NOTNULL; // out
|
||||
fields[argp++] = TypePtr::NOTNULL; // in
|
||||
fields[argp++] = TypeInt::INT; // offset
|
||||
fields[argp++] = TypeInt::INT; // len
|
||||
fields[argp++] = TypeInt::INT; // k
|
||||
assert(argp == TypeFunc::Parms+argcnt, "correct decoding");
|
||||
const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields);
|
||||
|
||||
// returning carry (int)
|
||||
fields = TypeTuple::fields(1);
|
||||
fields[TypeFunc::Parms+0] = TypeInt::INT;
|
||||
const TypeTuple* range = TypeTuple::make(TypeFunc::Parms+1, fields);
|
||||
return TypeFunc::make(domain, range);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------- Interpreter state access for on stack replacement
|
||||
|
@ -312,6 +312,10 @@ private:
|
||||
|
||||
static const TypeFunc* multiplyToLen_Type();
|
||||
|
||||
static const TypeFunc* squareToLen_Type();
|
||||
|
||||
static const TypeFunc* mulAdd_Type();
|
||||
|
||||
static const TypeFunc* updateBytesCRC32_Type();
|
||||
|
||||
// leaf on stack replacement interpreter accessor types
|
||||
|
@ -1631,7 +1631,7 @@ void SuperWord::output() {
|
||||
}
|
||||
Node* adr = low_adr->in(MemNode::Address);
|
||||
const TypePtr* atyp = n->adr_type();
|
||||
vn = LoadVectorNode::make(opc, ctl, mem, adr, atyp, vlen, velt_basic_type(n));
|
||||
vn = LoadVectorNode::make(opc, ctl, mem, adr, atyp, vlen, velt_basic_type(n), control_dependency(p));
|
||||
vlen_in_bytes = vn->as_LoadVector()->memory_size();
|
||||
} else if (n->is_Store()) {
|
||||
// Promote value to be stored to vector
|
||||
@ -2280,6 +2280,19 @@ Node* SuperWord::executed_last(Node_List* p) {
|
||||
return n;
|
||||
}
|
||||
|
||||
LoadNode::ControlDependency SuperWord::control_dependency(Node_List* p) {
|
||||
LoadNode::ControlDependency dep = LoadNode::DependsOnlyOnTest;
|
||||
for (uint i = 0; i < p->size(); i++) {
|
||||
Node* n = p->at(i);
|
||||
assert(n->is_Load(), "only meaningful for loads");
|
||||
if (!n->depends_only_on_test()) {
|
||||
dep = LoadNode::Pinned;
|
||||
}
|
||||
}
|
||||
return dep;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------align_initial_loop_index---------------------------
|
||||
// Adjust pre-loop limit so that in main loop, a load/store reference
|
||||
// to align_to_ref will be a position zero in the vector.
|
||||
|
@ -428,6 +428,7 @@ class SuperWord : public ResourceObj {
|
||||
Node* executed_first(Node_List* p);
|
||||
// Return the node executed last in pack p.
|
||||
Node* executed_last(Node_List* p);
|
||||
static LoadNode::ControlDependency control_dependency(Node_List* p);
|
||||
// Alignment within a vector memory reference
|
||||
int memory_alignment(MemNode* s, int iv_adjust);
|
||||
// (Start, end] half-open range defining which operands are vector
|
||||
|
@ -406,9 +406,11 @@ PackNode* PackNode::binary_tree_pack(int lo, int hi) {
|
||||
|
||||
// Return the vector version of a scalar load node.
|
||||
LoadVectorNode* LoadVectorNode::make(int opc, Node* ctl, Node* mem,
|
||||
Node* adr, const TypePtr* atyp, uint vlen, BasicType bt) {
|
||||
Node* adr, const TypePtr* atyp,
|
||||
uint vlen, BasicType bt,
|
||||
ControlDependency control_dependency) {
|
||||
const TypeVect* vt = TypeVect::make(bt, vlen);
|
||||
return new LoadVectorNode(ctl, mem, adr, atyp, vt);
|
||||
return new LoadVectorNode(ctl, mem, adr, atyp, vt, control_dependency);
|
||||
}
|
||||
|
||||
// Return the vector version of a scalar store node.
|
||||
|
@ -454,8 +454,8 @@ class XorVNode : public VectorNode {
|
||||
// Load Vector from memory
|
||||
class LoadVectorNode : public LoadNode {
|
||||
public:
|
||||
LoadVectorNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeVect* vt)
|
||||
: LoadNode(c, mem, adr, at, vt, MemNode::unordered) {
|
||||
LoadVectorNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeVect* vt, ControlDependency control_dependency = LoadNode::DependsOnlyOnTest)
|
||||
: LoadNode(c, mem, adr, at, vt, MemNode::unordered, control_dependency) {
|
||||
init_class_id(Class_LoadVector);
|
||||
}
|
||||
|
||||
@ -471,7 +471,9 @@ class LoadVectorNode : public LoadNode {
|
||||
virtual int store_Opcode() const { return Op_StoreVector; }
|
||||
|
||||
static LoadVectorNode* make(int opc, Node* ctl, Node* mem,
|
||||
Node* adr, const TypePtr* atyp, uint vlen, BasicType bt);
|
||||
Node* adr, const TypePtr* atyp,
|
||||
uint vlen, BasicType bt,
|
||||
ControlDependency control_dependency = LoadNode::DependsOnlyOnTest);
|
||||
};
|
||||
|
||||
//------------------------------StoreVectorNode--------------------------------
|
||||
|
@ -1126,39 +1126,32 @@ static void jni_invoke_nonstatic(JNIEnv *env, JavaValue* result, jobject receive
|
||||
Method* m = Method::resolve_jmethod_id(method_id);
|
||||
number_of_parameters = m->size_of_parameters();
|
||||
Klass* holder = m->method_holder();
|
||||
if (!(holder)->is_interface()) {
|
||||
if (call_type != JNI_VIRTUAL) {
|
||||
selected_method = m;
|
||||
} else if (!m->has_itable_index()) {
|
||||
// non-interface call -- for that little speed boost, don't handlize
|
||||
debug_only(No_Safepoint_Verifier nosafepoint;)
|
||||
if (call_type == JNI_VIRTUAL) {
|
||||
// jni_GetMethodID makes sure class is linked and initialized
|
||||
// so m should have a valid vtable index.
|
||||
assert(!m->has_itable_index(), "");
|
||||
int vtbl_index = m->vtable_index();
|
||||
if (vtbl_index != Method::nonvirtual_vtable_index) {
|
||||
Klass* k = h_recv->klass();
|
||||
// k might be an arrayKlassOop but all vtables start at
|
||||
// the same place. The cast is to avoid virtual call and assertion.
|
||||
InstanceKlass *ik = (InstanceKlass*)k;
|
||||
selected_method = ik->method_at_vtable(vtbl_index);
|
||||
} else {
|
||||
// final method
|
||||
selected_method = m;
|
||||
}
|
||||
// jni_GetMethodID makes sure class is linked and initialized
|
||||
// so m should have a valid vtable index.
|
||||
assert(m->valid_vtable_index(), "no valid vtable index");
|
||||
int vtbl_index = m->vtable_index();
|
||||
if (vtbl_index != Method::nonvirtual_vtable_index) {
|
||||
Klass* k = h_recv->klass();
|
||||
// k might be an arrayKlassOop but all vtables start at
|
||||
// the same place. The cast is to avoid virtual call and assertion.
|
||||
InstanceKlass *ik = (InstanceKlass*)k;
|
||||
selected_method = ik->method_at_vtable(vtbl_index);
|
||||
} else {
|
||||
// JNI_NONVIRTUAL call
|
||||
// final method
|
||||
selected_method = m;
|
||||
}
|
||||
} else {
|
||||
// interface call
|
||||
KlassHandle h_holder(THREAD, holder);
|
||||
|
||||
if (call_type == JNI_VIRTUAL) {
|
||||
int itbl_index = m->itable_index();
|
||||
Klass* k = h_recv->klass();
|
||||
selected_method = InstanceKlass::cast(k)->method_at_itable(h_holder(), itbl_index, CHECK);
|
||||
} else {
|
||||
selected_method = m;
|
||||
}
|
||||
int itbl_index = m->itable_index();
|
||||
Klass* k = h_recv->klass();
|
||||
selected_method = InstanceKlass::cast(k)->method_at_itable(h_holder(), itbl_index, CHECK);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -842,7 +842,7 @@ JvmtiEnvBase::get_stack_trace(JavaThread *java_thread,
|
||||
// optimize to limit the number of times that java_sender() is called
|
||||
javaVFrame *jvf_cursor = jvf;
|
||||
javaVFrame *jvf_prev = NULL;
|
||||
javaVFrame *jvf_prev_prev;
|
||||
javaVFrame *jvf_prev_prev = NULL;
|
||||
int j = 0;
|
||||
while (jvf_cursor != NULL) {
|
||||
jvf_prev_prev = jvf_prev;
|
||||
|
@ -677,24 +677,24 @@ Handle MethodHandles::resolve_MemberName(Handle mname, KlassHandle caller, TRAPS
|
||||
case IS_METHOD:
|
||||
{
|
||||
CallInfo result;
|
||||
LinkInfo link_info(defc, name, type, caller, caller.not_null());
|
||||
{
|
||||
assert(!HAS_PENDING_EXCEPTION, "");
|
||||
if (ref_kind == JVM_REF_invokeStatic) {
|
||||
LinkResolver::resolve_static_call(result,
|
||||
defc, name, type, caller, caller.not_null(), false, THREAD);
|
||||
link_info, false, THREAD);
|
||||
} else if (ref_kind == JVM_REF_invokeInterface) {
|
||||
LinkResolver::resolve_interface_call(result, Handle(), defc,
|
||||
defc, name, type, caller, caller.not_null(), false, THREAD);
|
||||
link_info, false, THREAD);
|
||||
} else if (mh_invoke_id != vmIntrinsics::_none) {
|
||||
assert(!is_signature_polymorphic_static(mh_invoke_id), "");
|
||||
LinkResolver::resolve_handle_call(result,
|
||||
defc, name, type, caller, THREAD);
|
||||
LinkResolver::resolve_handle_call(result, link_info, THREAD);
|
||||
} else if (ref_kind == JVM_REF_invokeSpecial) {
|
||||
LinkResolver::resolve_special_call(result,
|
||||
defc, name, type, caller, caller.not_null(), THREAD);
|
||||
link_info, THREAD);
|
||||
} else if (ref_kind == JVM_REF_invokeVirtual) {
|
||||
LinkResolver::resolve_virtual_call(result, Handle(), defc,
|
||||
defc, name, type, caller, caller.not_null(), false, THREAD);
|
||||
link_info, false, THREAD);
|
||||
} else {
|
||||
assert(false, err_msg("ref_kind=%d", ref_kind));
|
||||
}
|
||||
@ -714,11 +714,11 @@ Handle MethodHandles::resolve_MemberName(Handle mname, KlassHandle caller, TRAPS
|
||||
case IS_CONSTRUCTOR:
|
||||
{
|
||||
CallInfo result;
|
||||
LinkInfo link_info(defc, name, type, caller, caller.not_null());
|
||||
{
|
||||
assert(!HAS_PENDING_EXCEPTION, "");
|
||||
if (name == vmSymbols::object_initializer_name()) {
|
||||
LinkResolver::resolve_special_call(result,
|
||||
defc, name, type, caller, caller.not_null(), THREAD);
|
||||
LinkResolver::resolve_special_call(result, link_info, THREAD);
|
||||
} else {
|
||||
break; // will throw after end of switch
|
||||
}
|
||||
@ -735,7 +735,8 @@ Handle MethodHandles::resolve_MemberName(Handle mname, KlassHandle caller, TRAPS
|
||||
fieldDescriptor result; // find_field initializes fd if found
|
||||
{
|
||||
assert(!HAS_PENDING_EXCEPTION, "");
|
||||
LinkResolver::resolve_field(result, defc, name, type, caller, Bytecodes::_nop, false, false, THREAD);
|
||||
LinkInfo link_info(defc, name, type, caller, /*check_access*/false);
|
||||
LinkResolver::resolve_field(result, link_info, Bytecodes::_nop, false, THREAD);
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
return empty;
|
||||
}
|
||||
@ -942,22 +943,56 @@ int MethodHandles::find_MemberNames(KlassHandle k,
|
||||
return rfill + overflow;
|
||||
}
|
||||
|
||||
// Get context class for a CallSite instance: either extract existing context or use default one.
|
||||
InstanceKlass* MethodHandles::get_call_site_context(oop call_site) {
|
||||
// In order to extract a context the following traversal is performed:
|
||||
// CallSite.context => Cleaner.referent => Class._klass => Klass
|
||||
assert(java_lang_invoke_CallSite::is_instance(call_site), "");
|
||||
oop context_oop = java_lang_invoke_CallSite::context_volatile(call_site);
|
||||
if (oopDesc::is_null(context_oop)) {
|
||||
return NULL; // The context hasn't been initialized yet.
|
||||
void MethodHandles::add_dependent_nmethod(oop call_site, nmethod* nm) {
|
||||
assert_locked_or_safepoint(CodeCache_lock);
|
||||
|
||||
oop context = java_lang_invoke_CallSite::context(call_site);
|
||||
nmethodBucket* deps = java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(context);
|
||||
|
||||
nmethodBucket* new_deps = nmethodBucket::add_dependent_nmethod(deps, nm);
|
||||
if (deps != new_deps) {
|
||||
java_lang_invoke_MethodHandleNatives_CallSiteContext::set_vmdependencies(context, new_deps);
|
||||
}
|
||||
oop context_class_oop = java_lang_ref_Reference::referent(context_oop);
|
||||
if (oopDesc::is_null(context_class_oop)) {
|
||||
// The context reference was cleared by GC, so current dependency context
|
||||
// isn't usable anymore. Context should be fetched from CallSite again.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void MethodHandles::remove_dependent_nmethod(oop call_site, nmethod* nm) {
|
||||
assert_locked_or_safepoint(CodeCache_lock);
|
||||
|
||||
oop context = java_lang_invoke_CallSite::context(call_site);
|
||||
nmethodBucket* deps = java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(context);
|
||||
|
||||
if (nmethodBucket::remove_dependent_nmethod(deps, nm)) {
|
||||
nmethodBucket* new_deps = nmethodBucket::clean_dependent_nmethods(deps);
|
||||
if (deps != new_deps) {
|
||||
java_lang_invoke_MethodHandleNatives_CallSiteContext::set_vmdependencies(context, new_deps);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MethodHandles::flush_dependent_nmethods(Handle call_site, Handle target) {
|
||||
assert_lock_strong(Compile_lock);
|
||||
|
||||
int marked = 0;
|
||||
CallSiteDepChange changes(call_site(), target());
|
||||
{
|
||||
MutexLockerEx mu2(CodeCache_lock, Mutex::_no_safepoint_check_flag);
|
||||
|
||||
oop context = java_lang_invoke_CallSite::context(call_site());
|
||||
nmethodBucket* deps = java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(context);
|
||||
|
||||
marked = nmethodBucket::mark_dependent_nmethods(deps, changes);
|
||||
if (marked > 0) {
|
||||
nmethodBucket* new_deps = nmethodBucket::clean_dependent_nmethods(deps);
|
||||
if (deps != new_deps) {
|
||||
java_lang_invoke_MethodHandleNatives_CallSiteContext::set_vmdependencies(context, new_deps);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (marked > 0) {
|
||||
// At least one nmethod has been marked for deoptimization
|
||||
VM_Deoptimize op;
|
||||
VMThread::execute(&op);
|
||||
}
|
||||
return InstanceKlass::cast(java_lang_Class::as_Klass(context_class_oop));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -1276,7 +1311,7 @@ JVM_ENTRY(void, MHN_setCallSiteTargetNormal(JNIEnv* env, jobject igcls, jobject
|
||||
{
|
||||
// Walk all nmethods depending on this call site.
|
||||
MutexLocker mu(Compile_lock, thread);
|
||||
CodeCache::flush_dependents_on(call_site, target);
|
||||
MethodHandles::flush_dependent_nmethods(call_site, target);
|
||||
java_lang_invoke_CallSite::set_target(call_site(), target());
|
||||
}
|
||||
}
|
||||
@ -1288,30 +1323,34 @@ JVM_ENTRY(void, MHN_setCallSiteTargetVolatile(JNIEnv* env, jobject igcls, jobjec
|
||||
{
|
||||
// Walk all nmethods depending on this call site.
|
||||
MutexLocker mu(Compile_lock, thread);
|
||||
CodeCache::flush_dependents_on(call_site, target);
|
||||
MethodHandles::flush_dependent_nmethods(call_site, target);
|
||||
java_lang_invoke_CallSite::set_target_volatile(call_site(), target());
|
||||
}
|
||||
}
|
||||
JVM_END
|
||||
|
||||
JVM_ENTRY(void, MHN_invalidateDependentNMethods(JNIEnv* env, jobject igcls, jobject call_site_jh)) {
|
||||
Handle call_site(THREAD, JNIHandles::resolve_non_null(call_site_jh));
|
||||
JVM_ENTRY(void, MHN_clearCallSiteContext(JNIEnv* env, jobject igcls, jobject context_jh)) {
|
||||
Handle context(THREAD, JNIHandles::resolve_non_null(context_jh));
|
||||
{
|
||||
// Walk all nmethods depending on this call site.
|
||||
MutexLocker mu1(Compile_lock, thread);
|
||||
|
||||
CallSiteDepChange changes(call_site(), Handle());
|
||||
|
||||
InstanceKlass* ctxk = MethodHandles::get_call_site_context(call_site());
|
||||
if (ctxk == NULL) {
|
||||
return; // No dependencies to invalidate yet.
|
||||
}
|
||||
int marked = 0;
|
||||
{
|
||||
MutexLockerEx mu2(CodeCache_lock, Mutex::_no_safepoint_check_flag);
|
||||
marked = ctxk->mark_dependent_nmethods(changes);
|
||||
nmethodBucket* b = java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(context());
|
||||
while(b != NULL) {
|
||||
nmethod* nm = b->get_nmethod();
|
||||
if (b->count() > 0 && nm->is_alive() && !nm->is_marked_for_deoptimization()) {
|
||||
nm->mark_for_deoptimization();
|
||||
marked++;
|
||||
}
|
||||
nmethodBucket* next = b->next();
|
||||
delete b;
|
||||
b = next;
|
||||
}
|
||||
java_lang_invoke_MethodHandleNatives_CallSiteContext::set_vmdependencies(context(), NULL); // reset context
|
||||
}
|
||||
java_lang_invoke_CallSite::set_context_volatile(call_site(), NULL); // Reset call site to initial state
|
||||
if (marked > 0) {
|
||||
// At least one nmethod has been marked for deoptimization
|
||||
VM_Deoptimize op;
|
||||
@ -1357,6 +1396,7 @@ JVM_END
|
||||
#define MT JLINV"MethodType;"
|
||||
#define MH JLINV"MethodHandle;"
|
||||
#define MEM JLINV"MemberName;"
|
||||
#define CTX JLINV"MethodHandleNatives$CallSiteContext;"
|
||||
|
||||
#define CC (char*) /*cast a literal from (const char*)*/
|
||||
#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
|
||||
@ -1374,7 +1414,7 @@ static JNINativeMethod MHN_methods[] = {
|
||||
{CC"objectFieldOffset", CC"("MEM")J", FN_PTR(MHN_objectFieldOffset)},
|
||||
{CC"setCallSiteTargetNormal", CC"("CS""MH")V", FN_PTR(MHN_setCallSiteTargetNormal)},
|
||||
{CC"setCallSiteTargetVolatile", CC"("CS""MH")V", FN_PTR(MHN_setCallSiteTargetVolatile)},
|
||||
{CC"invalidateDependentNMethods", CC"("CS")V", FN_PTR(MHN_invalidateDependentNMethods)},
|
||||
{CC"clearCallSiteContext", CC"("CTX")V", FN_PTR(MHN_clearCallSiteContext)},
|
||||
{CC"staticFieldOffset", CC"("MEM")J", FN_PTR(MHN_staticFieldOffset)},
|
||||
{CC"staticFieldBase", CC"("MEM")"OBJ, FN_PTR(MHN_staticFieldBase)},
|
||||
{CC"getMemberVMInfo", CC"("MEM")"OBJ, FN_PTR(MHN_getMemberVMInfo)}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user