mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-11 22:19:43 +00:00
Merge
This commit is contained in:
commit
eb4655db3e
3
.hgtags
3
.hgtags
@ -309,3 +309,6 @@ e7dbbef69d12b6a74dfad331b7188e7f893e8d29 jdk9-b62
|
||||
8ffdeabc7c2b9a8280bf46cae026ac46b4d31c26 jdk9-b64
|
||||
4915246064b2f89d5f00c96e758686b7fdad36a6 jdk9-b65
|
||||
ff3fc75f3214ad7e03595be1b0d0f38d887b6f0e jdk9-b66
|
||||
56166ce66037952fa21e9f680b31bf8eb47312c0 jdk9-b67
|
||||
5b500c93ce4822d47061cd518ff3f72d9d8cb5b5 jdk9-b68
|
||||
d69c968463f0ae5d0b45de3fc14fe65171b23948 jdk9-b69
|
||||
|
||||
@ -309,3 +309,6 @@ ea38728b4f4bdd8fd0d7a89b18069f521cf05013 jdk9-b61
|
||||
82cf9aab9a83e41c8194ba01af9666afdb856cbe jdk9-b64
|
||||
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
|
||||
|
||||
@ -338,14 +338,16 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_OPTIMIZATION],
|
||||
# no adjustment
|
||||
;;
|
||||
slowdebug )
|
||||
# Add runtime stack smashing and undefined behavior checks
|
||||
CFLAGS_DEBUG_OPTIONS="-fstack-protector-all --param ssp-buffer-size=1"
|
||||
CXXFLAGS_DEBUG_OPTIONS="-fstack-protector-all --param ssp-buffer-size=1"
|
||||
# Add runtime stack smashing and undefined behavior checks.
|
||||
# Not all versions of gcc support -fstack-protector
|
||||
STACK_PROTECTOR_CFLAG="-fstack-protector-all"
|
||||
FLAGS_COMPILER_CHECK_ARGUMENTS([$STACK_PROTECTOR_CFLAG], [], [STACK_PROTECTOR_CFLAG=""])
|
||||
|
||||
CFLAGS_DEBUG_OPTIONS="$STACK_PROTECTOR_CFLAG --param ssp-buffer-size=1"
|
||||
CXXFLAGS_DEBUG_OPTIONS="$STACK_PROTECTOR_CFLAG --param ssp-buffer-size=1"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
AC_SUBST(CFLAGS_DEBUG_OPTIONS)
|
||||
AC_SUBST(CXXFLAGS_DEBUG_OPTIONS)
|
||||
|
||||
# Optimization levels
|
||||
if test "x$TOOLCHAIN_TYPE" = xsolstudio; then
|
||||
|
||||
@ -718,8 +718,6 @@ C_O_FLAG_DEBUG
|
||||
C_O_FLAG_NORM
|
||||
C_O_FLAG_HI
|
||||
C_O_FLAG_HIGHEST
|
||||
CXXFLAGS_DEBUG_OPTIONS
|
||||
CFLAGS_DEBUG_OPTIONS
|
||||
CXXFLAGS_DEBUG_SYMBOLS
|
||||
CFLAGS_DEBUG_SYMBOLS
|
||||
CXX_FLAG_DEPS
|
||||
@ -857,6 +855,7 @@ OS_VERSION_MINOR
|
||||
OS_VERSION_MAJOR
|
||||
PKG_CONFIG
|
||||
BASH_ARGS
|
||||
SETFILE
|
||||
CODESIGN
|
||||
XATTR
|
||||
DSYMUTIL
|
||||
@ -948,7 +947,6 @@ build_vendor
|
||||
build_cpu
|
||||
build
|
||||
CPIO
|
||||
SETFILE
|
||||
DF
|
||||
READLINK
|
||||
CYGPATH
|
||||
@ -1169,7 +1167,6 @@ SED
|
||||
CYGPATH
|
||||
READLINK
|
||||
DF
|
||||
SETFILE
|
||||
CPIO
|
||||
UNZIP
|
||||
ZIP
|
||||
@ -1182,6 +1179,7 @@ TIME
|
||||
DSYMUTIL
|
||||
XATTR
|
||||
CODESIGN
|
||||
SETFILE
|
||||
PKG_CONFIG
|
||||
JAVA
|
||||
JAVAC
|
||||
@ -2051,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
|
||||
@ -2064,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
|
||||
@ -4366,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=1432629750
|
||||
DATE_WHEN_GENERATED=1434614912
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
@ -13057,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.
|
||||
|
||||
|
||||
@ -15142,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.
|
||||
@ -19655,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
|
||||
|
||||
|
||||
@ -41837,14 +41843,80 @@ $as_echo "$ac_cv_c_bigendian" >&6; }
|
||||
# no adjustment
|
||||
;;
|
||||
slowdebug )
|
||||
# Add runtime stack smashing and undefined behavior checks
|
||||
CFLAGS_DEBUG_OPTIONS="-fstack-protector-all --param ssp-buffer-size=1"
|
||||
CXXFLAGS_DEBUG_OPTIONS="-fstack-protector-all --param ssp-buffer-size=1"
|
||||
;;
|
||||
esac
|
||||
# Add runtime stack smashing and undefined behavior checks.
|
||||
# Not all versions of gcc support -fstack-protector
|
||||
STACK_PROTECTOR_CFLAG="-fstack-protector-all"
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports \"$STACK_PROTECTOR_CFLAG\"" >&5
|
||||
$as_echo_n "checking if compiler supports \"$STACK_PROTECTOR_CFLAG\"... " >&6; }
|
||||
supports=yes
|
||||
|
||||
saved_cflags="$CFLAGS"
|
||||
CFLAGS="$CFLAGS $STACK_PROTECTOR_CFLAG"
|
||||
ac_ext=c
|
||||
ac_cpp='$CPP $CPPFLAGS'
|
||||
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
|
||||
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
|
||||
ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
int i;
|
||||
_ACEOF
|
||||
if ac_fn_c_try_compile "$LINENO"; then :
|
||||
|
||||
else
|
||||
supports=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
ac_ext=cpp
|
||||
ac_cpp='$CXXCPP $CPPFLAGS'
|
||||
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
|
||||
ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
|
||||
ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
|
||||
|
||||
CFLAGS="$saved_cflags"
|
||||
|
||||
saved_cxxflags="$CXXFLAGS"
|
||||
CXXFLAGS="$CXXFLAG $STACK_PROTECTOR_CFLAG"
|
||||
ac_ext=cpp
|
||||
ac_cpp='$CXXCPP $CPPFLAGS'
|
||||
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
|
||||
ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
|
||||
ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
|
||||
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
int i;
|
||||
_ACEOF
|
||||
if ac_fn_cxx_try_compile "$LINENO"; then :
|
||||
|
||||
else
|
||||
supports=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
ac_ext=cpp
|
||||
ac_cpp='$CXXCPP $CPPFLAGS'
|
||||
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
|
||||
ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
|
||||
ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
|
||||
|
||||
CXXFLAGS="$saved_cxxflags"
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $supports" >&5
|
||||
$as_echo "$supports" >&6; }
|
||||
if test "x$supports" = "xyes" ; then
|
||||
:
|
||||
else
|
||||
STACK_PROTECTOR_CFLAG=""
|
||||
fi
|
||||
|
||||
|
||||
CFLAGS_DEBUG_OPTIONS="$STACK_PROTECTOR_CFLAG --param ssp-buffer-size=1"
|
||||
CXXFLAGS_DEBUG_OPTIONS="$STACK_PROTECTOR_CFLAG --param ssp-buffer-size=1"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Optimization levels
|
||||
if test "x$TOOLCHAIN_TYPE" = xsolstudio; then
|
||||
|
||||
@ -309,3 +309,6 @@ d27f7e0a7aca129969de23e9934408a31b4abf4c jdk9-b62
|
||||
0a5e5a7c3539e8bde73d9fe55750e49a49cb8dac jdk9-b64
|
||||
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 ());
|
||||
}
|
||||
|
||||
}
|
||||
@ -469,3 +469,6 @@ ee878f3d6732856f7725c590312bfbe2ffa52cc7 jdk9-b58
|
||||
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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -466,6 +466,11 @@ class Address VALUE_OBJ_CLASS_SPEC {
|
||||
case base_plus_offset:
|
||||
{
|
||||
unsigned size = i->get(31, 30);
|
||||
if (i->get(26, 26) && i->get(23, 23)) {
|
||||
// SIMD Q Type - Size = 128 bits
|
||||
assert(size == 0, "bad size");
|
||||
size = 0b100;
|
||||
}
|
||||
unsigned mask = (1 << size) - 1;
|
||||
if (_offset < 0 || _offset & mask)
|
||||
{
|
||||
@ -1888,9 +1893,18 @@ public:
|
||||
};
|
||||
|
||||
enum SIMD_RegVariant {
|
||||
S32, D64, Q128
|
||||
B, H, S, D, Q
|
||||
};
|
||||
|
||||
#define INSN(NAME, op) \
|
||||
void NAME(FloatRegister Rt, SIMD_RegVariant T, const Address &adr) { \
|
||||
ld_st2((Register)Rt, adr, (int)T & 3, op + ((T==Q) ? 0b10:0b00), 1); \
|
||||
} \
|
||||
|
||||
INSN(ldr, 1);
|
||||
INSN(str, 0);
|
||||
|
||||
#undef INSN
|
||||
|
||||
private:
|
||||
|
||||
@ -1997,27 +2011,87 @@ public:
|
||||
rf(Vm, 16), f(0b000111, 15, 10), rf(Vn, 5), rf(Vd, 0); \
|
||||
}
|
||||
|
||||
INSN(eor, 0b101110001);
|
||||
INSN(orr, 0b001110101);
|
||||
INSN(eor, 0b101110001);
|
||||
INSN(orr, 0b001110101);
|
||||
INSN(andr, 0b001110001);
|
||||
INSN(bic, 0b001110011);
|
||||
INSN(bif, 0b101110111);
|
||||
INSN(bit, 0b101110101);
|
||||
INSN(bsl, 0b101110011);
|
||||
INSN(orn, 0b001110111);
|
||||
INSN(bic, 0b001110011);
|
||||
INSN(bif, 0b101110111);
|
||||
INSN(bit, 0b101110101);
|
||||
INSN(bsl, 0b101110011);
|
||||
INSN(orn, 0b001110111);
|
||||
|
||||
#undef INSN
|
||||
|
||||
#define INSN(NAME, opc) \
|
||||
#define INSN(NAME, opc, opc2) \
|
||||
void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm) { \
|
||||
starti; \
|
||||
f(0, 31), f((int)T & 1, 30), f(opc, 29), f(0b01110, 28, 24); \
|
||||
f((int)T >> 1, 23, 22), f(1, 21), rf(Vm, 16), f(0b100001, 15, 10); \
|
||||
f((int)T >> 1, 23, 22), f(1, 21), rf(Vm, 16), f(opc2, 15, 10); \
|
||||
rf(Vn, 5), rf(Vd, 0); \
|
||||
}
|
||||
|
||||
INSN(addv, 0);
|
||||
INSN(subv, 1);
|
||||
INSN(addv, 0, 0b100001);
|
||||
INSN(subv, 1, 0b100001);
|
||||
INSN(mulv, 0, 0b100111);
|
||||
INSN(sshl, 0, 0b010001);
|
||||
INSN(ushl, 1, 0b010001);
|
||||
|
||||
#undef INSN
|
||||
|
||||
#define INSN(NAME, opc, opc2) \
|
||||
void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn) { \
|
||||
starti; \
|
||||
f(0, 31), f((int)T & 1, 30), f(opc, 29), f(0b01110, 28, 24); \
|
||||
f((int)T >> 1, 23, 22), f(opc2, 21, 10); \
|
||||
rf(Vn, 5), rf(Vd, 0); \
|
||||
}
|
||||
|
||||
INSN(absr, 0, 0b100000101110);
|
||||
INSN(negr, 1, 0b100000101110);
|
||||
INSN(notr, 1, 0b100000010110);
|
||||
INSN(addv, 0, 0b110001101110);
|
||||
|
||||
#undef INSN
|
||||
|
||||
#define INSN(NAME, op0, cmode0) \
|
||||
void NAME(FloatRegister Vd, SIMD_Arrangement T, unsigned imm8, unsigned lsl = 0) { \
|
||||
unsigned cmode = cmode0; \
|
||||
unsigned op = op0; \
|
||||
starti; \
|
||||
assert(lsl == 0 || \
|
||||
((T == T4H || T == T8H) && lsl == 8) || \
|
||||
((T == T2S || T == T4S) && ((lsl >> 3) < 4)), "invalid shift"); \
|
||||
cmode |= lsl >> 2; \
|
||||
if (T == T4H || T == T8H) cmode |= 0b1000; \
|
||||
if (!(T == T4H || T == T8H || T == T2S || T == T4S)) { \
|
||||
assert(op == 0 && cmode0 == 0, "must be MOVI"); \
|
||||
cmode = 0b1110; \
|
||||
if (T == T1D || T == T2D) op = 1; \
|
||||
} \
|
||||
f(0, 31), f((int)T & 1, 30), f(op, 29), f(0b0111100000, 28, 19); \
|
||||
f(imm8 >> 5, 18, 16), f(cmode, 15, 12), f(0x01, 11, 10), f(imm8 & 0b11111, 9, 5); \
|
||||
rf(Vd, 0); \
|
||||
}
|
||||
|
||||
INSN(movi, 0, 0);
|
||||
INSN(orri, 0, 1);
|
||||
INSN(mvni, 1, 0);
|
||||
INSN(bici, 1, 1);
|
||||
|
||||
#undef INSN
|
||||
|
||||
#define INSN(NAME, op1, op2, op3) \
|
||||
void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm) { \
|
||||
starti; \
|
||||
assert(T == T2S || T == T4S || T == T2D, "invalid arrangement"); \
|
||||
f(0, 31), f((int)T & 1, 30), f(op1, 29), f(0b01110, 28, 24), f(op2, 23); \
|
||||
f(T==T2D ? 1:0, 22); f(1, 21), rf(Vm, 16), f(op3, 15, 10), rf(Vn, 5), rf(Vd, 0); \
|
||||
}
|
||||
|
||||
INSN(fadd, 0, 0, 0b110101);
|
||||
INSN(fdiv, 1, 0, 0b111111);
|
||||
INSN(fmul, 1, 0, 0b110111);
|
||||
INSN(fsub, 0, 1, 0b110101);
|
||||
|
||||
#undef INSN
|
||||
|
||||
@ -2064,19 +2138,40 @@ public:
|
||||
|
||||
#undef INSN
|
||||
|
||||
void shl(FloatRegister Vd, FloatRegister Vn, SIMD_Arrangement T, int shift){
|
||||
void ins(FloatRegister Vd, SIMD_RegVariant T, FloatRegister Vn, int didx, int sidx) {
|
||||
starti;
|
||||
/* The encodings for the immh:immb fields (bits 22:16) are
|
||||
* 0001 xxx 8B/16B, shift = xxx
|
||||
* 001x xxx 4H/8H, shift = xxxx
|
||||
* 01xx xxx 2S/4S, shift = xxxxx
|
||||
* 1xxx xxx 1D/2D, shift = xxxxxx (1D is RESERVED)
|
||||
*/
|
||||
assert((1 << ((T>>1)+3)) > shift, "Invalid Shift value");
|
||||
f(0, 31), f(T & 1, 30), f(0b0011110, 29, 23), f((1 << ((T>>1)+3))|shift, 22, 16);
|
||||
f(0b010101, 15, 10), rf(Vn, 5), rf(Vd, 0);
|
||||
assert(T != Q, "invalid register variant");
|
||||
f(0b01101110000, 31, 21), f(((didx<<1)|1)<<(int)T, 20, 16), f(0, 15);
|
||||
f(sidx<<(int)T, 14, 11), f(1, 10), rf(Vn, 5), rf(Vd, 0);
|
||||
}
|
||||
|
||||
void umov(Register Rd, FloatRegister Vn, SIMD_RegVariant T, int idx) {
|
||||
starti;
|
||||
f(0, 31), f(T==D ? 1:0, 30), f(0b001110000, 29, 21);
|
||||
f(((idx<<1)|1)<<(int)T, 20, 16), f(0b001111, 15, 10);
|
||||
rf(Vn, 5), rf(Rd, 0);
|
||||
}
|
||||
|
||||
#define INSN(NAME, opc, opc2) \
|
||||
void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, int shift){ \
|
||||
starti; \
|
||||
/* The encodings for the immh:immb fields (bits 22:16) are \
|
||||
* 0001 xxx 8B/16B, shift = xxx \
|
||||
* 001x xxx 4H/8H, shift = xxxx \
|
||||
* 01xx xxx 2S/4S, shift = xxxxx \
|
||||
* 1xxx xxx 1D/2D, shift = xxxxxx (1D is RESERVED) \
|
||||
*/ \
|
||||
assert((1 << ((T>>1)+3)) > shift, "Invalid Shift value"); \
|
||||
f(0, 31), f(T & 1, 30), f(opc, 29), f(0b011110, 28, 23), \
|
||||
f((1 << ((T>>1)+3))|shift, 22, 16); f(opc2, 15, 10), rf(Vn, 5), rf(Vd, 0); \
|
||||
}
|
||||
|
||||
INSN(shl, 0, 0b010101);
|
||||
INSN(sshr, 0, 0b000001);
|
||||
INSN(ushr, 1, 0b000001);
|
||||
|
||||
#undef INSN
|
||||
|
||||
void ushll(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, SIMD_Arrangement Tb, int shift) {
|
||||
starti;
|
||||
/* The encodings for the immh:immb fields (bits 22:16) are
|
||||
@ -2149,6 +2244,23 @@ public:
|
||||
rf(Vn, 5), rf(Vd, 0);
|
||||
}
|
||||
|
||||
void dup(FloatRegister Vd, SIMD_Arrangement T, Register Xs)
|
||||
{
|
||||
starti;
|
||||
assert(T != T1D, "reserved encoding");
|
||||
f(0,31), f((int)T & 1, 30), f(0b001110000, 29, 21);
|
||||
f((1 << (T >> 1)), 20, 16), f(0b000011, 15, 10), rf(Xs, 5), rf(Vd, 0);
|
||||
}
|
||||
|
||||
void dup(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, int index = 0)
|
||||
{
|
||||
starti;
|
||||
assert(T != T1D, "reserved encoding");
|
||||
f(0, 31), f((int)T & 1, 30), f(0b001110000, 29, 21);
|
||||
f(((1 << (T >> 1)) | (index << ((T >> 1) + 1))), 20, 16);
|
||||
f(0b000001, 15, 10), rf(Vn, 5), rf(Vd, 0);
|
||||
}
|
||||
|
||||
// CRC32 instructions
|
||||
#define INSN(NAME, sf, sz) \
|
||||
void NAME(Register Rd, Register Rn, Register Rm) { \
|
||||
|
||||
@ -64,7 +64,7 @@ define_pd_global(intx, StackShadowPages, 4 DEBUG_ONLY(+5));
|
||||
define_pd_global(intx, PreInflateSpin, 10);
|
||||
|
||||
define_pd_global(bool, RewriteBytecodes, true);
|
||||
define_pd_global(bool, RewriteFrequentPairs, false);
|
||||
define_pd_global(bool, RewriteFrequentPairs, true);
|
||||
|
||||
define_pd_global(bool, UseMembar, true);
|
||||
|
||||
|
||||
@ -2802,8 +2802,8 @@ void MacroAssembler::kernel_crc32(Register crc, Register buf, Register len,
|
||||
uzp2(v21, v20, v16, T2D);
|
||||
eor(v20, T16B, v17, v21);
|
||||
|
||||
shl(v16, v28, T2D, 1);
|
||||
shl(v17, v20, T2D, 1);
|
||||
shl(v16, T2D, v28, 1);
|
||||
shl(v17, T2D, v20, 1);
|
||||
|
||||
eor(v0, T16B, v0, v16);
|
||||
eor(v1, T16B, v1, v17);
|
||||
|
||||
@ -37,6 +37,7 @@ class MacroAssembler: public Assembler {
|
||||
friend class LIR_Assembler;
|
||||
|
||||
using Assembler::mov;
|
||||
using Assembler::movi;
|
||||
|
||||
protected:
|
||||
|
||||
@ -464,6 +465,45 @@ public:
|
||||
|
||||
void movptr(Register r, uintptr_t imm64);
|
||||
|
||||
// Macro to mov replicated immediate to vector register.
|
||||
// Where imm32 == hex abcdefgh, Vd will get the following values
|
||||
// for different arrangements in T
|
||||
// T8B: Vd = ghghghghghghghgh
|
||||
// T16B: Vd = ghghghghghghghghghghghghghghghgh
|
||||
// T4H: Vd = efghefghefghefgh
|
||||
// T8H: Vd = efghefghefghefghefghefghefghefgh
|
||||
// T2S: Vd = abcdefghabcdefgh
|
||||
// T4S: Vd = abcdefghabcdefghabcdefghabcdefgh
|
||||
// T1D/T2D: invalid
|
||||
void mov(FloatRegister Vd, SIMD_Arrangement T, u_int32_t imm32) {
|
||||
assert(T != T1D && T != T2D, "invalid arrangement");
|
||||
u_int32_t nimm32 = ~imm32;
|
||||
if (T == T8B || T == T16B) { imm32 &= 0xff; nimm32 &= 0xff; }
|
||||
if (T == T4H || T == T8H) { imm32 &= 0xffff; nimm32 &= 0xffff; }
|
||||
u_int32_t x = imm32;
|
||||
int movi_cnt = 0;
|
||||
int movn_cnt = 0;
|
||||
while (x) { if (x & 0xff) movi_cnt++; x >>= 8; }
|
||||
x = nimm32;
|
||||
while (x) { if (x & 0xff) movn_cnt++; x >>= 8; }
|
||||
if (movn_cnt < movi_cnt) imm32 = nimm32;
|
||||
unsigned lsl = 0;
|
||||
while (imm32 && (imm32 & 0xff) == 0) { lsl += 8; imm32 >>= 8; }
|
||||
if (movn_cnt < movi_cnt)
|
||||
mvni(Vd, T, imm32 & 0xff, lsl);
|
||||
else
|
||||
movi(Vd, T, imm32 & 0xff, lsl);
|
||||
imm32 >>= 8; lsl += 8;
|
||||
while (imm32) {
|
||||
while ((imm32 & 0xff) == 0) { lsl += 8; imm32 >>= 8; }
|
||||
if (movn_cnt < movi_cnt)
|
||||
bici(Vd, T, imm32 & 0xff, lsl);
|
||||
else
|
||||
orri(Vd, T, imm32 & 0xff, lsl);
|
||||
lsl += 8; imm32 >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
// macro instructions for accessing and updating floating point
|
||||
// status register
|
||||
//
|
||||
|
||||
@ -186,7 +186,7 @@ class ConcreteRegisterImpl : public AbstractRegisterImpl {
|
||||
// it's optoregs.
|
||||
|
||||
number_of_registers = (2 * RegisterImpl::number_of_registers +
|
||||
2 * FloatRegisterImpl::number_of_registers +
|
||||
4 * FloatRegisterImpl::number_of_registers +
|
||||
1) // flags
|
||||
};
|
||||
|
||||
|
||||
@ -513,23 +513,61 @@ void TemplateTable::nofast_iload() {
|
||||
void TemplateTable::iload_internal(RewriteControl rc) {
|
||||
transition(vtos, itos);
|
||||
if (RewriteFrequentPairs && rc == may_rewrite) {
|
||||
// TODO : check x86 code for what to do here
|
||||
__ call_Unimplemented();
|
||||
} else {
|
||||
locals_index(r1);
|
||||
__ ldr(r0, iaddress(r1));
|
||||
Label rewrite, done;
|
||||
Register bc = r4;
|
||||
|
||||
// get next bytecode
|
||||
__ load_unsigned_byte(r1, at_bcp(Bytecodes::length_for(Bytecodes::_iload)));
|
||||
|
||||
// if _iload, wait to rewrite to iload2. We only want to rewrite the
|
||||
// last two iloads in a pair. Comparing against fast_iload means that
|
||||
// the next bytecode is neither an iload or a caload, and therefore
|
||||
// an iload pair.
|
||||
__ cmpw(r1, Bytecodes::_iload);
|
||||
__ br(Assembler::EQ, done);
|
||||
|
||||
// if _fast_iload rewrite to _fast_iload2
|
||||
__ cmpw(r1, Bytecodes::_fast_iload);
|
||||
__ movw(bc, Bytecodes::_fast_iload2);
|
||||
__ br(Assembler::EQ, rewrite);
|
||||
|
||||
// if _caload rewrite to _fast_icaload
|
||||
__ cmpw(r1, Bytecodes::_caload);
|
||||
__ movw(bc, Bytecodes::_fast_icaload);
|
||||
__ br(Assembler::EQ, rewrite);
|
||||
|
||||
// else rewrite to _fast_iload
|
||||
__ movw(bc, Bytecodes::_fast_iload);
|
||||
|
||||
// rewrite
|
||||
// bc: new bytecode
|
||||
__ bind(rewrite);
|
||||
patch_bytecode(Bytecodes::_iload, bc, r1, false);
|
||||
__ bind(done);
|
||||
|
||||
}
|
||||
|
||||
// do iload, get the local value into tos
|
||||
locals_index(r1);
|
||||
__ ldr(r0, iaddress(r1));
|
||||
|
||||
}
|
||||
|
||||
void TemplateTable::fast_iload2()
|
||||
{
|
||||
__ call_Unimplemented();
|
||||
transition(vtos, itos);
|
||||
locals_index(r1);
|
||||
__ ldr(r0, iaddress(r1));
|
||||
__ push(itos);
|
||||
locals_index(r1, 3);
|
||||
__ ldr(r0, iaddress(r1));
|
||||
}
|
||||
|
||||
void TemplateTable::fast_iload()
|
||||
{
|
||||
__ call_Unimplemented();
|
||||
transition(vtos, itos);
|
||||
locals_index(r1);
|
||||
__ ldr(r0, iaddress(r1));
|
||||
}
|
||||
|
||||
void TemplateTable::lload()
|
||||
@ -721,7 +759,18 @@ void TemplateTable::caload()
|
||||
// iload followed by caload frequent pair
|
||||
void TemplateTable::fast_icaload()
|
||||
{
|
||||
__ call_Unimplemented();
|
||||
transition(vtos, itos);
|
||||
// load index out of locals
|
||||
locals_index(r2);
|
||||
__ ldr(r1, iaddress(r2));
|
||||
|
||||
__ pop_ptr(r0);
|
||||
|
||||
// r0: array
|
||||
// r1: index
|
||||
index_check(r0, r1); // leaves index in r1, kills rscratch1
|
||||
__ lea(r1, Address(r0, r1, Address::uxtw(1)));
|
||||
__ load_unsigned_short(r0, Address(r1, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
|
||||
}
|
||||
|
||||
void TemplateTable::saload()
|
||||
@ -797,7 +846,47 @@ void TemplateTable::aload_0_internal(RewriteControl rc) {
|
||||
// These bytecodes with a small amount of code are most profitable
|
||||
// to rewrite
|
||||
if (RewriteFrequentPairs && rc == may_rewrite) {
|
||||
__ call_Unimplemented();
|
||||
Label rewrite, done;
|
||||
const Register bc = r4;
|
||||
|
||||
// get next bytecode
|
||||
__ load_unsigned_byte(r1, at_bcp(Bytecodes::length_for(Bytecodes::_aload_0)));
|
||||
|
||||
// do actual aload_0
|
||||
aload(0);
|
||||
|
||||
// if _getfield then wait with rewrite
|
||||
__ cmpw(r1, Bytecodes::Bytecodes::_getfield);
|
||||
__ br(Assembler::EQ, done);
|
||||
|
||||
// if _igetfield then reqrite to _fast_iaccess_0
|
||||
assert(Bytecodes::java_code(Bytecodes::_fast_iaccess_0) == Bytecodes::_aload_0, "fix bytecode definition");
|
||||
__ cmpw(r1, Bytecodes::_fast_igetfield);
|
||||
__ movw(bc, Bytecodes::_fast_iaccess_0);
|
||||
__ br(Assembler::EQ, rewrite);
|
||||
|
||||
// if _agetfield then reqrite to _fast_aaccess_0
|
||||
assert(Bytecodes::java_code(Bytecodes::_fast_aaccess_0) == Bytecodes::_aload_0, "fix bytecode definition");
|
||||
__ cmpw(r1, Bytecodes::_fast_agetfield);
|
||||
__ movw(bc, Bytecodes::_fast_aaccess_0);
|
||||
__ br(Assembler::EQ, rewrite);
|
||||
|
||||
// if _fgetfield then reqrite to _fast_faccess_0
|
||||
assert(Bytecodes::java_code(Bytecodes::_fast_faccess_0) == Bytecodes::_aload_0, "fix bytecode definition");
|
||||
__ cmpw(r1, Bytecodes::_fast_fgetfield);
|
||||
__ movw(bc, Bytecodes::_fast_faccess_0);
|
||||
__ br(Assembler::EQ, rewrite);
|
||||
|
||||
// else rewrite to _fast_aload0
|
||||
assert(Bytecodes::java_code(Bytecodes::_fast_aload_0) == Bytecodes::_aload_0, "fix bytecode definition");
|
||||
__ movw(bc, Bytecodes::Bytecodes::_fast_aload_0);
|
||||
|
||||
// rewrite
|
||||
// bc: new bytecode
|
||||
__ bind(rewrite);
|
||||
patch_bytecode(Bytecodes::_aload_0, bc, r1, false);
|
||||
|
||||
__ bind(done);
|
||||
} else {
|
||||
aload(0);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
@ -3768,7 +3773,7 @@ HINSTANCE os::win32::load_Windows_dll(const char* name, char *ebuf,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define EXIT_TIMEOUT PRODUCT_ONLY(1000) NOT_PRODUCT(4000) /* 1 sec in product, 4 sec in debug */
|
||||
#define EXIT_TIMEOUT 300000 /* 5 minutes */
|
||||
|
||||
static BOOL CALLBACK init_crit_sect_call(PINIT_ONCE, PVOID pcrit_sect, PVOID*) {
|
||||
InitializeCriticalSection((CRITICAL_SECTION*)pcrit_sect);
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -1469,7 +1469,9 @@ void LIRGenerator::G1SATBCardTableModRef_pre_barrier(LIR_Opr addr_opr, LIR_Opr p
|
||||
} else {
|
||||
guarantee(in_bytes(PtrQueue::byte_width_of_active()) == 1,
|
||||
"Assumption");
|
||||
flag_type = T_BYTE;
|
||||
// Use unsigned type T_BOOLEAN here rather than signed T_BYTE since some platforms, eg. ARM,
|
||||
// need to use unsigned instructions to use the large offset to load the satb_mark_queue.
|
||||
flag_type = T_BOOLEAN;
|
||||
}
|
||||
LIR_Opr thrd = getThreadPointer();
|
||||
LIR_Address* mark_active_flag_addr =
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
#define SHARE_VM_GC_CMS_CMSOOPCLOSURES_HPP
|
||||
|
||||
#include "gc/shared/genOopClosures.hpp"
|
||||
#include "gc/shared/taskqueue.hpp"
|
||||
#include "memory/iterator.hpp"
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -641,6 +641,7 @@ void CompactibleFreeListSpace::set_end(HeapWord* value) {
|
||||
class FreeListSpace_DCTOC : public Filtering_DCTOC {
|
||||
CompactibleFreeListSpace* _cfls;
|
||||
CMSCollector* _collector;
|
||||
bool _parallel;
|
||||
protected:
|
||||
// Override.
|
||||
#define walk_mem_region_with_cl_DECL(ClosureType) \
|
||||
@ -661,9 +662,10 @@ public:
|
||||
CMSCollector* collector,
|
||||
ExtendedOopClosure* cl,
|
||||
CardTableModRefBS::PrecisionStyle precision,
|
||||
HeapWord* boundary) :
|
||||
HeapWord* boundary,
|
||||
bool parallel) :
|
||||
Filtering_DCTOC(sp, cl, precision, boundary),
|
||||
_cfls(sp), _collector(collector) {}
|
||||
_cfls(sp), _collector(collector), _parallel(parallel) {}
|
||||
};
|
||||
|
||||
// We de-virtualize the block-related calls below, since we know that our
|
||||
@ -674,10 +676,7 @@ void FreeListSpace_DCTOC::walk_mem_region_with_cl(MemRegion mr,
|
||||
HeapWord* bottom, \
|
||||
HeapWord* top, \
|
||||
ClosureType* cl) { \
|
||||
bool is_par = GenCollectedHeap::heap()->n_par_threads() > 0; \
|
||||
if (is_par) { \
|
||||
assert(GenCollectedHeap::heap()->n_par_threads() == \
|
||||
GenCollectedHeap::heap()->workers()->active_workers(), "Mismatch"); \
|
||||
if (_parallel) { \
|
||||
walk_mem_region_with_cl_par(mr, bottom, top, cl); \
|
||||
} else { \
|
||||
walk_mem_region_with_cl_nopar(mr, bottom, top, cl); \
|
||||
@ -747,8 +746,9 @@ FreeListSpace_DCTOC__walk_mem_region_with_cl_DEFN(FilteringClosure)
|
||||
DirtyCardToOopClosure*
|
||||
CompactibleFreeListSpace::new_dcto_cl(ExtendedOopClosure* cl,
|
||||
CardTableModRefBS::PrecisionStyle precision,
|
||||
HeapWord* boundary) {
|
||||
return new FreeListSpace_DCTOC(this, _collector, cl, precision, boundary);
|
||||
HeapWord* boundary,
|
||||
bool parallel) {
|
||||
return new FreeListSpace_DCTOC(this, _collector, cl, precision, boundary, parallel);
|
||||
}
|
||||
|
||||
|
||||
@ -1897,11 +1897,9 @@ CompactibleFreeListSpace::splitChunkAndReturnRemainder(FreeChunk* chunk,
|
||||
assert(chunk->is_free() && ffc->is_free(), "Error");
|
||||
_bt.split_block((HeapWord*)chunk, chunk->size(), new_size);
|
||||
if (rem_sz < SmallForDictionary) {
|
||||
bool is_par = (GenCollectedHeap::heap()->n_par_threads() > 0);
|
||||
// The freeList lock is held, but multiple GC task threads might be executing in parallel.
|
||||
bool is_par = Thread::current()->is_GC_task_thread();
|
||||
if (is_par) _indexedFreeListParLocks[rem_sz]->lock();
|
||||
assert(!is_par ||
|
||||
(GenCollectedHeap::heap()->n_par_threads() ==
|
||||
GenCollectedHeap::heap()->workers()->active_workers()), "Mismatch");
|
||||
returnChunkToFreeList(ffc);
|
||||
split(size, rem_sz);
|
||||
if (is_par) _indexedFreeListParLocks[rem_sz]->unlock();
|
||||
@ -1972,8 +1970,6 @@ void CompactibleFreeListSpace::save_marks() {
|
||||
|
||||
bool CompactibleFreeListSpace::no_allocs_since_save_marks() {
|
||||
assert(_promoInfo.tracking(), "No preceding save_marks?");
|
||||
assert(GenCollectedHeap::heap()->n_par_threads() == 0,
|
||||
"Shouldn't be called if using parallel gc.");
|
||||
return _promoInfo.noPromotions();
|
||||
}
|
||||
|
||||
@ -1981,8 +1977,6 @@ bool CompactibleFreeListSpace::no_allocs_since_save_marks() {
|
||||
\
|
||||
void CompactibleFreeListSpace:: \
|
||||
oop_since_save_marks_iterate##nv_suffix(OopClosureType* blk) { \
|
||||
assert(GenCollectedHeap::heap()->n_par_threads() == 0, \
|
||||
"Shouldn't be called (yet) during parallel part of gc."); \
|
||||
_promoInfo.promoted_oops_iterate##nv_suffix(blk); \
|
||||
/* \
|
||||
* This also restores any displaced headers and removes the elements from \
|
||||
|
||||
@ -438,7 +438,8 @@ class CompactibleFreeListSpace: public CompactibleSpace {
|
||||
// Override: provides a DCTO_CL specific to this kind of space.
|
||||
DirtyCardToOopClosure* new_dcto_cl(ExtendedOopClosure* cl,
|
||||
CardTableModRefBS::PrecisionStyle precision,
|
||||
HeapWord* boundary);
|
||||
HeapWord* boundary,
|
||||
bool parallel);
|
||||
|
||||
void blk_iterate(BlkClosure* cl);
|
||||
void blk_iterate_careful(BlkClosureCareful* cl);
|
||||
|
||||
@ -2428,14 +2428,18 @@ void CMSCollector::verify_after_remark_work_1() {
|
||||
MarkRefsIntoClosure notOlder(_span, verification_mark_bm());
|
||||
gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
|
||||
|
||||
gch->gen_process_roots(_cmsGen->level(),
|
||||
true, // younger gens are roots
|
||||
true, // activate StrongRootsScope
|
||||
GenCollectedHeap::ScanningOption(roots_scanning_options()),
|
||||
should_unload_classes(),
|
||||
¬Older,
|
||||
NULL,
|
||||
NULL); // SSS: Provide correct closure
|
||||
{
|
||||
StrongRootsScope srs(1);
|
||||
|
||||
gch->gen_process_roots(&srs,
|
||||
_cmsGen->level(),
|
||||
true, // younger gens are roots
|
||||
GenCollectedHeap::ScanningOption(roots_scanning_options()),
|
||||
should_unload_classes(),
|
||||
¬Older,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
// Now mark from the roots
|
||||
MarkFromRootsClosure markFromRootsClosure(this, _span,
|
||||
@ -2496,14 +2500,18 @@ void CMSCollector::verify_after_remark_work_2() {
|
||||
|
||||
gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
|
||||
|
||||
gch->gen_process_roots(_cmsGen->level(),
|
||||
true, // younger gens are roots
|
||||
true, // activate StrongRootsScope
|
||||
GenCollectedHeap::ScanningOption(roots_scanning_options()),
|
||||
should_unload_classes(),
|
||||
¬Older,
|
||||
NULL,
|
||||
&cld_closure);
|
||||
{
|
||||
StrongRootsScope srs(1);
|
||||
|
||||
gch->gen_process_roots(&srs,
|
||||
_cmsGen->level(),
|
||||
true, // younger gens are roots
|
||||
GenCollectedHeap::ScanningOption(roots_scanning_options()),
|
||||
should_unload_classes(),
|
||||
¬Older,
|
||||
NULL,
|
||||
&cld_closure);
|
||||
}
|
||||
|
||||
// Now mark from the roots
|
||||
MarkFromRootsVerifyClosure markFromRootsClosure(this, _span,
|
||||
@ -2913,10 +2921,11 @@ class CMSParMarkTask : public AbstractGangTask {
|
||||
|
||||
// Parallel initial mark task
|
||||
class CMSParInitialMarkTask: public CMSParMarkTask {
|
||||
StrongRootsScope* _strong_roots_scope;
|
||||
public:
|
||||
CMSParInitialMarkTask(CMSCollector* collector, uint n_workers) :
|
||||
CMSParMarkTask("Scan roots and young gen for initial mark in parallel",
|
||||
collector, n_workers) {}
|
||||
CMSParInitialMarkTask(CMSCollector* collector, StrongRootsScope* strong_roots_scope, uint n_workers) :
|
||||
CMSParMarkTask("Scan roots and young gen for initial mark in parallel", collector, n_workers),
|
||||
_strong_roots_scope(strong_roots_scope) {}
|
||||
void work(uint worker_id);
|
||||
};
|
||||
|
||||
@ -3004,24 +3013,26 @@ void CMSCollector::checkpointRootsInitialWork() {
|
||||
FlexibleWorkGang* workers = gch->workers();
|
||||
assert(workers != NULL, "Need parallel worker threads.");
|
||||
uint n_workers = workers->active_workers();
|
||||
CMSParInitialMarkTask tsk(this, n_workers);
|
||||
gch->set_par_threads(n_workers);
|
||||
|
||||
StrongRootsScope srs(n_workers);
|
||||
|
||||
CMSParInitialMarkTask tsk(this, &srs, n_workers);
|
||||
initialize_sequential_subtasks_for_young_gen_rescan(n_workers);
|
||||
if (n_workers > 1) {
|
||||
StrongRootsScope srs;
|
||||
workers->run_task(&tsk);
|
||||
} else {
|
||||
StrongRootsScope srs;
|
||||
tsk.work(0);
|
||||
}
|
||||
gch->set_par_threads(0);
|
||||
} else {
|
||||
// The serial version.
|
||||
CLDToOopClosure cld_closure(¬Older, true);
|
||||
gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
|
||||
gch->gen_process_roots(_cmsGen->level(),
|
||||
|
||||
StrongRootsScope srs(1);
|
||||
|
||||
gch->gen_process_roots(&srs,
|
||||
_cmsGen->level(),
|
||||
true, // younger gens are roots
|
||||
true, // activate StrongRootsScope
|
||||
GenCollectedHeap::ScanningOption(roots_scanning_options()),
|
||||
should_unload_classes(),
|
||||
¬Older,
|
||||
@ -4452,9 +4463,9 @@ void CMSParInitialMarkTask::work(uint worker_id) {
|
||||
|
||||
CLDToOopClosure cld_closure(&par_mri_cl, true);
|
||||
|
||||
gch->gen_process_roots(_collector->_cmsGen->level(),
|
||||
gch->gen_process_roots(_strong_roots_scope,
|
||||
_collector->_cmsGen->level(),
|
||||
false, // yg was scanned above
|
||||
false, // this is parallel code
|
||||
GenCollectedHeap::ScanningOption(_collector->CMSCollector::roots_scanning_options()),
|
||||
_collector->should_unload_classes(),
|
||||
&par_mri_cl,
|
||||
@ -4478,6 +4489,7 @@ class CMSParRemarkTask: public CMSParMarkTask {
|
||||
// The per-thread work queues, available here for stealing.
|
||||
OopTaskQueueSet* _task_queues;
|
||||
ParallelTaskTerminator _term;
|
||||
StrongRootsScope* _strong_roots_scope;
|
||||
|
||||
public:
|
||||
// A value of 0 passed to n_workers will cause the number of
|
||||
@ -4485,12 +4497,14 @@ class CMSParRemarkTask: public CMSParMarkTask {
|
||||
CMSParRemarkTask(CMSCollector* collector,
|
||||
CompactibleFreeListSpace* cms_space,
|
||||
uint n_workers, FlexibleWorkGang* workers,
|
||||
OopTaskQueueSet* task_queues):
|
||||
OopTaskQueueSet* task_queues,
|
||||
StrongRootsScope* strong_roots_scope):
|
||||
CMSParMarkTask("Rescan roots and grey objects in parallel",
|
||||
collector, n_workers),
|
||||
_cms_space(cms_space),
|
||||
_task_queues(task_queues),
|
||||
_term(n_workers, task_queues) { }
|
||||
_term(n_workers, task_queues),
|
||||
_strong_roots_scope(strong_roots_scope) { }
|
||||
|
||||
OopTaskQueueSet* task_queues() { return _task_queues; }
|
||||
|
||||
@ -4588,9 +4602,9 @@ void CMSParRemarkTask::work(uint worker_id) {
|
||||
// ---------- remaining roots --------------
|
||||
_timer.reset();
|
||||
_timer.start();
|
||||
gch->gen_process_roots(_collector->_cmsGen->level(),
|
||||
gch->gen_process_roots(_strong_roots_scope,
|
||||
_collector->_cmsGen->level(),
|
||||
false, // yg was scanned above
|
||||
false, // this is parallel code
|
||||
GenCollectedHeap::ScanningOption(_collector->CMSCollector::roots_scanning_options()),
|
||||
_collector->should_unload_classes(),
|
||||
&par_mrias_cl,
|
||||
@ -5058,22 +5072,15 @@ void CMSCollector::do_remark_parallel() {
|
||||
FlexibleWorkGang* workers = gch->workers();
|
||||
assert(workers != NULL, "Need parallel worker threads.");
|
||||
// Choose to use the number of GC workers most recently set
|
||||
// into "active_workers". If active_workers is not set, set it
|
||||
// to ParallelGCThreads.
|
||||
// into "active_workers".
|
||||
uint n_workers = workers->active_workers();
|
||||
if (n_workers == 0) {
|
||||
assert(n_workers > 0, "Should have been set during scavenge");
|
||||
n_workers = ParallelGCThreads;
|
||||
workers->set_active_workers(n_workers);
|
||||
}
|
||||
|
||||
CompactibleFreeListSpace* cms_space = _cmsGen->cmsSpace();
|
||||
|
||||
CMSParRemarkTask tsk(this,
|
||||
cms_space,
|
||||
n_workers, workers, task_queues());
|
||||
StrongRootsScope srs(n_workers);
|
||||
|
||||
CMSParRemarkTask tsk(this, cms_space, n_workers, workers, task_queues(), &srs);
|
||||
|
||||
// Set up for parallel process_roots work.
|
||||
gch->set_par_threads(n_workers);
|
||||
// We won't be iterating over the cards in the card table updating
|
||||
// the younger_gen cards, so we shouldn't call the following else
|
||||
// the verification code as well as subsequent younger_refs_iterate
|
||||
@ -5105,15 +5112,12 @@ void CMSCollector::do_remark_parallel() {
|
||||
// necessarily be so, since it's possible that we are doing
|
||||
// ST marking.
|
||||
ReferenceProcessorMTDiscoveryMutator mt(ref_processor(), true);
|
||||
StrongRootsScope srs;
|
||||
workers->run_task(&tsk);
|
||||
} else {
|
||||
ReferenceProcessorMTDiscoveryMutator mt(ref_processor(), false);
|
||||
StrongRootsScope srs;
|
||||
tsk.work(0);
|
||||
}
|
||||
|
||||
gch->set_par_threads(0); // 0 ==> non-parallel.
|
||||
// restore, single-threaded for now, any preserved marks
|
||||
// as a result of work_q overflow
|
||||
restore_preserved_marks_if_any();
|
||||
@ -5177,11 +5181,11 @@ void CMSCollector::do_remark_non_parallel() {
|
||||
verify_work_stacks_empty();
|
||||
|
||||
gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
|
||||
StrongRootsScope srs;
|
||||
StrongRootsScope srs(1);
|
||||
|
||||
gch->gen_process_roots(_cmsGen->level(),
|
||||
gch->gen_process_roots(&srs,
|
||||
_cmsGen->level(),
|
||||
true, // younger gens as roots
|
||||
false, // use the local StrongRootsScope
|
||||
GenCollectedHeap::ScanningOption(roots_scanning_options()),
|
||||
should_unload_classes(),
|
||||
&mrias_cl,
|
||||
@ -5254,18 +5258,14 @@ public:
|
||||
CMSBitMap* mark_bit_map,
|
||||
AbstractWorkGang* workers,
|
||||
OopTaskQueueSet* task_queues):
|
||||
// XXX Should superclass AGTWOQ also know about AWG since it knows
|
||||
// about the task_queues used by the AWG? Then it could initialize
|
||||
// the terminator() object. See 6984287. The set_for_termination()
|
||||
// below is a temporary band-aid for the regression in 6984287.
|
||||
AbstractGangTaskWOopQueues("Process referents by policy in parallel",
|
||||
task_queues),
|
||||
task_queues,
|
||||
workers->active_workers()),
|
||||
_task(task),
|
||||
_collector(collector), _span(span), _mark_bit_map(mark_bit_map)
|
||||
{
|
||||
assert(_collector->_span.equals(_span) && !_span.is_empty(),
|
||||
"Inconsistency in _span");
|
||||
set_for_termination(workers->active_workers());
|
||||
}
|
||||
|
||||
OopTaskQueueSet* task_queues() { return queues(); }
|
||||
|
||||
@ -39,16 +39,11 @@
|
||||
void CardTableModRefBS::non_clean_card_iterate_parallel_work(Space* sp, MemRegion mr,
|
||||
OopsInGenClosure* cl,
|
||||
CardTableRS* ct,
|
||||
int n_threads) {
|
||||
assert(n_threads > 0, "Error: expected n_threads > 0");
|
||||
assert((n_threads == 1 && ParallelGCThreads == 0) ||
|
||||
n_threads <= (int)ParallelGCThreads,
|
||||
"# worker threads != # requested!");
|
||||
assert(!Thread::current()->is_VM_thread() || (n_threads == 1), "There is only 1 VM thread");
|
||||
assert(UseDynamicNumberOfGCThreads ||
|
||||
!FLAG_IS_DEFAULT(ParallelGCThreads) ||
|
||||
n_threads == (int)ParallelGCThreads,
|
||||
"# worker threads != # requested!");
|
||||
uint n_threads) {
|
||||
assert(n_threads > 0, "expected n_threads > 0");
|
||||
assert(n_threads <= ParallelGCThreads,
|
||||
err_msg("n_threads: %u > ParallelGCThreads: " UINTX_FORMAT, n_threads, ParallelGCThreads));
|
||||
|
||||
// Make sure the LNC array is valid for the space.
|
||||
jbyte** lowest_non_clean;
|
||||
uintptr_t lowest_non_clean_base_chunk_index;
|
||||
@ -66,7 +61,8 @@ void CardTableModRefBS::non_clean_card_iterate_parallel_work(Space* sp, MemRegio
|
||||
|
||||
uint stride = 0;
|
||||
while (!pst->is_task_claimed(/* reference */ stride)) {
|
||||
process_stride(sp, mr, stride, n_strides, cl, ct,
|
||||
process_stride(sp, mr, stride, n_strides,
|
||||
cl, ct,
|
||||
lowest_non_clean,
|
||||
lowest_non_clean_base_chunk_index,
|
||||
lowest_non_clean_chunk_size);
|
||||
@ -132,9 +128,13 @@ process_stride(Space* sp,
|
||||
assert(chunk_mr.word_size() > 0, "[chunk_card_start > used_end)");
|
||||
assert(used.contains(chunk_mr), "chunk_mr should be subset of used");
|
||||
|
||||
// This function is used by the parallel card table iteration.
|
||||
const bool parallel = true;
|
||||
|
||||
DirtyCardToOopClosure* dcto_cl = sp->new_dcto_cl(cl, precision(),
|
||||
cl->gen_boundary());
|
||||
ClearNoncleanCardWrapper clear_cl(dcto_cl, ct);
|
||||
cl->gen_boundary(),
|
||||
parallel);
|
||||
ClearNoncleanCardWrapper clear_cl(dcto_cl, ct, parallel);
|
||||
|
||||
|
||||
// Process the chunk.
|
||||
|
||||
@ -567,23 +567,15 @@ void ParEvacuateFollowersClosure::do_void() {
|
||||
}
|
||||
|
||||
ParNewGenTask::ParNewGenTask(ParNewGeneration* gen, Generation* old_gen,
|
||||
HeapWord* young_old_boundary, ParScanThreadStateSet* state_set) :
|
||||
HeapWord* young_old_boundary, ParScanThreadStateSet* state_set,
|
||||
StrongRootsScope* strong_roots_scope) :
|
||||
AbstractGangTask("ParNewGeneration collection"),
|
||||
_gen(gen), _old_gen(old_gen),
|
||||
_young_old_boundary(young_old_boundary),
|
||||
_state_set(state_set)
|
||||
_state_set(state_set),
|
||||
_strong_roots_scope(strong_roots_scope)
|
||||
{}
|
||||
|
||||
// Reset the terminator for the given number of
|
||||
// active threads.
|
||||
void ParNewGenTask::set_for_termination(uint active_workers) {
|
||||
_state_set->reset(active_workers, _gen->promotion_failed());
|
||||
// Should the heap be passed in? There's only 1 for now so
|
||||
// grab it instead.
|
||||
GenCollectedHeap* gch = GenCollectedHeap::heap();
|
||||
gch->set_n_termination(active_workers);
|
||||
}
|
||||
|
||||
void ParNewGenTask::work(uint worker_id) {
|
||||
GenCollectedHeap* gch = GenCollectedHeap::heap();
|
||||
// Since this is being done in a separate thread, need new resource
|
||||
@ -603,10 +595,10 @@ void ParNewGenTask::work(uint worker_id) {
|
||||
false);
|
||||
|
||||
par_scan_state.start_strong_roots();
|
||||
gch->gen_process_roots(_gen->level(),
|
||||
gch->gen_process_roots(_strong_roots_scope,
|
||||
_gen->level(),
|
||||
true, // Process younger gens, if any,
|
||||
// as strong roots.
|
||||
false, // no scope; this is parallel code
|
||||
GenCollectedHeap::SO_ScavengeCodeCache,
|
||||
GenCollectedHeap::StrongAndWeakRoots,
|
||||
&par_scan_state.to_space_root_closure(),
|
||||
@ -759,9 +751,6 @@ public:
|
||||
|
||||
private:
|
||||
virtual void work(uint worker_id);
|
||||
virtual void set_for_termination(uint active_workers) {
|
||||
_state_set.terminator()->reset_for_reuse(active_workers);
|
||||
}
|
||||
private:
|
||||
ParNewGeneration& _gen;
|
||||
ProcessTask& _task;
|
||||
@ -838,7 +827,6 @@ void ParNewRefProcTaskExecutor::set_single_threaded_mode()
|
||||
{
|
||||
_state_set.flush();
|
||||
GenCollectedHeap* gch = GenCollectedHeap::heap();
|
||||
gch->set_par_threads(0); // 0 ==> non-parallel.
|
||||
gch->save_marks();
|
||||
}
|
||||
|
||||
@ -939,33 +927,35 @@ void ParNewGeneration::collect(bool full,
|
||||
to()->clear(SpaceDecorator::Mangle);
|
||||
|
||||
gch->save_marks();
|
||||
assert(workers != NULL, "Need parallel worker threads.");
|
||||
uint n_workers = active_workers;
|
||||
|
||||
// Set the correct parallelism (number of queues) in the reference processor
|
||||
ref_processor()->set_active_mt_degree(n_workers);
|
||||
ref_processor()->set_active_mt_degree(active_workers);
|
||||
|
||||
// Always set the terminator for the active number of workers
|
||||
// because only those workers go through the termination protocol.
|
||||
ParallelTaskTerminator _term(n_workers, task_queues());
|
||||
ParScanThreadStateSet thread_state_set(workers->active_workers(),
|
||||
ParallelTaskTerminator _term(active_workers, task_queues());
|
||||
ParScanThreadStateSet thread_state_set(active_workers,
|
||||
*to(), *this, *_old_gen, *task_queues(),
|
||||
_overflow_stacks, desired_plab_sz(), _term);
|
||||
|
||||
ParNewGenTask tsk(this, _old_gen, reserved().end(), &thread_state_set);
|
||||
gch->set_par_threads(n_workers);
|
||||
gch->rem_set()->prepare_for_younger_refs_iterate(true);
|
||||
// It turns out that even when we're using 1 thread, doing the work in a
|
||||
// separate thread causes wide variance in run times. We can't help this
|
||||
// in the multi-threaded case, but we special-case n=1 here to get
|
||||
// repeatable measurements of the 1-thread overhead of the parallel code.
|
||||
if (n_workers > 1) {
|
||||
StrongRootsScope srs;
|
||||
workers->run_task(&tsk);
|
||||
} else {
|
||||
StrongRootsScope srs;
|
||||
tsk.work(0);
|
||||
thread_state_set.reset(active_workers, promotion_failed());
|
||||
|
||||
{
|
||||
StrongRootsScope srs(active_workers);
|
||||
|
||||
ParNewGenTask tsk(this, _old_gen, reserved().end(), &thread_state_set, &srs);
|
||||
gch->rem_set()->prepare_for_younger_refs_iterate(true);
|
||||
// It turns out that even when we're using 1 thread, doing the work in a
|
||||
// separate thread causes wide variance in run times. We can't help this
|
||||
// in the multi-threaded case, but we special-case n=1 here to get
|
||||
// repeatable measurements of the 1-thread overhead of the parallel code.
|
||||
if (active_workers > 1) {
|
||||
workers->run_task(&tsk);
|
||||
} else {
|
||||
tsk.work(0);
|
||||
}
|
||||
}
|
||||
|
||||
thread_state_set.reset(0 /* Bad value in debug if not reset */,
|
||||
promotion_failed());
|
||||
|
||||
@ -995,7 +985,6 @@ void ParNewGeneration::collect(bool full,
|
||||
_gc_timer, _gc_tracer.gc_id());
|
||||
} else {
|
||||
thread_state_set.flush();
|
||||
gch->set_par_threads(0); // 0 ==> non-parallel.
|
||||
gch->save_marks();
|
||||
stats = rp->process_discovered_references(&is_alive, &keep_alive,
|
||||
&evacuate_followers, NULL,
|
||||
@ -1033,7 +1022,7 @@ void ParNewGeneration::collect(bool full,
|
||||
to()->set_concurrent_iteration_safe_limit(to()->top());
|
||||
|
||||
if (ResizePLAB) {
|
||||
plab_stats()->adjust_desired_plab_sz(n_workers);
|
||||
plab_stats()->adjust_desired_plab_sz(active_workers);
|
||||
}
|
||||
|
||||
if (PrintGC && !PrintGCDetails) {
|
||||
@ -1477,9 +1466,9 @@ void ParNewGeneration::ref_processor_init() {
|
||||
_ref_processor =
|
||||
new ReferenceProcessor(_reserved, // span
|
||||
ParallelRefProcEnabled && (ParallelGCThreads > 1), // mt processing
|
||||
(int) ParallelGCThreads, // mt processing degree
|
||||
(uint) ParallelGCThreads, // mt processing degree
|
||||
refs_discovery_is_mt(), // mt discovery
|
||||
(int) ParallelGCThreads, // mt discovery degree
|
||||
(uint) ParallelGCThreads, // mt discovery degree
|
||||
refs_discovery_is_atomic(), // atomic_discovery
|
||||
NULL); // is_alive_non_header
|
||||
}
|
||||
|
||||
@ -39,6 +39,7 @@ class ParScanWithBarrierClosure;
|
||||
class ParRootScanWithoutBarrierClosure;
|
||||
class ParRootScanWithBarrierTwoGensClosure;
|
||||
class ParEvacuateFollowersClosure;
|
||||
class StrongRootsScope;
|
||||
|
||||
// It would be better if these types could be kept local to the .cpp file,
|
||||
// but they must be here to allow ParScanClosure::do_oop_work to be defined
|
||||
@ -237,20 +238,18 @@ class ParNewGenTask: public AbstractGangTask {
|
||||
Generation* _old_gen;
|
||||
HeapWord* _young_old_boundary;
|
||||
class ParScanThreadStateSet* _state_set;
|
||||
StrongRootsScope* _strong_roots_scope;
|
||||
|
||||
public:
|
||||
ParNewGenTask(ParNewGeneration* gen,
|
||||
Generation* old_gen,
|
||||
HeapWord* young_old_boundary,
|
||||
ParScanThreadStateSet* state_set);
|
||||
ParScanThreadStateSet* state_set,
|
||||
StrongRootsScope* strong_roots_scope);
|
||||
|
||||
HeapWord* young_old_boundary() { return _young_old_boundary; }
|
||||
|
||||
void work(uint worker_id);
|
||||
|
||||
// Reset the terminator in ParScanThreadStateSet for
|
||||
// "active_workers" threads.
|
||||
virtual void set_for_termination(uint active_workers);
|
||||
};
|
||||
|
||||
class KeepAliveClosure: public DefNewGeneration::KeepAliveClosure {
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
#define SHARE_VM_GC_CMS_PAROOPCLOSURES_HPP
|
||||
|
||||
#include "gc/shared/genOopClosures.hpp"
|
||||
#include "gc/shared/taskqueue.hpp"
|
||||
#include "memory/padded.hpp"
|
||||
|
||||
// Closures for ParNewGeneration
|
||||
|
||||
@ -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
|
||||
|
||||
@ -147,6 +147,13 @@ public:
|
||||
bool completed() const { return _status == COMPLETED; }
|
||||
bool aborted() const { return _status == ABORTED; }
|
||||
bool active() const { return _status == ACTIVE; }
|
||||
|
||||
// This method configures the task for proper termination.
|
||||
// Some tasks do not have any requirements on termination
|
||||
// and may inherit this method that does nothing. Some
|
||||
// tasks do some coordination on termination and override
|
||||
// this method to implement that coordination.
|
||||
virtual void set_for_termination(uint active_workers) {}
|
||||
};
|
||||
// Class YieldingWorkGang: A subclass of WorkGang.
|
||||
// In particular, a YieldingWorkGang is made up of
|
||||
@ -169,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
|
||||
|
||||
@ -158,20 +158,10 @@ void CollectionSetChooser::add_region(HeapRegion* hr) {
|
||||
hr->calc_gc_efficiency();
|
||||
}
|
||||
|
||||
void CollectionSetChooser::prepare_for_par_region_addition(uint n_regions,
|
||||
void CollectionSetChooser::prepare_for_par_region_addition(uint n_threads,
|
||||
uint n_regions,
|
||||
uint chunk_size) {
|
||||
_first_par_unreserved_idx = 0;
|
||||
uint n_threads = (uint) ParallelGCThreads;
|
||||
if (UseDynamicNumberOfGCThreads) {
|
||||
assert(G1CollectedHeap::heap()->workers()->active_workers() > 0,
|
||||
"Should have been set earlier");
|
||||
// This is defensive code. As the assertion above says, the number
|
||||
// of active threads should be > 0, but in case there is some path
|
||||
// or some improperly initialized variable with leads to no
|
||||
// active threads, protect against that in a product build.
|
||||
n_threads = MAX2(G1CollectedHeap::heap()->workers()->active_workers(),
|
||||
1U);
|
||||
}
|
||||
uint max_waste = n_threads * chunk_size;
|
||||
// it should be aligned with respect to chunk_size
|
||||
uint aligned_n_regions = (n_regions + chunk_size - 1) / chunk_size * chunk_size;
|
||||
|
||||
@ -121,7 +121,7 @@ public:
|
||||
|
||||
// Must be called before calls to claim_array_chunk().
|
||||
// n_regions is the number of regions, chunk_size the chunk size.
|
||||
void prepare_for_par_region_addition(uint n_regions, uint chunk_size);
|
||||
void prepare_for_par_region_addition(uint n_threads, uint n_regions, uint chunk_size);
|
||||
// Returns the first index in a contiguous chunk of chunk_size indexes
|
||||
// that the calling thread has reserved. These must be set by the
|
||||
// calling thread using set_region() (to NULL if necessary).
|
||||
|
||||
@ -35,7 +35,7 @@ ConcurrentG1Refine::ConcurrentG1Refine(G1CollectedHeap* g1h, CardTableEntryClosu
|
||||
{
|
||||
// Ergonomically select initial concurrent refinement parameters
|
||||
if (FLAG_IS_DEFAULT(G1ConcRefinementGreenZone)) {
|
||||
FLAG_SET_DEFAULT(G1ConcRefinementGreenZone, MAX2<int>(ParallelGCThreads, 1));
|
||||
FLAG_SET_DEFAULT(G1ConcRefinementGreenZone, (intx)ParallelGCThreads);
|
||||
}
|
||||
set_green_zone(G1ConcRefinementGreenZone);
|
||||
|
||||
|
||||
@ -518,7 +518,7 @@ ConcurrentMark::ConcurrentMark(G1CollectedHeap* g1h, G1RegionToSpaceMapper* prev
|
||||
_markStack(this),
|
||||
// _finger set in set_non_marking_state
|
||||
|
||||
_max_worker_id(MAX2((uint)ParallelGCThreads, 1U)),
|
||||
_max_worker_id((uint)ParallelGCThreads),
|
||||
// _active_tasks set in set_non_marking_state
|
||||
// _tasks set inside the constructor
|
||||
_task_queues(new CMTaskQueueSet((int) _max_worker_id)),
|
||||
@ -1218,15 +1218,13 @@ void ConcurrentMark::markFromRoots() {
|
||||
"Maximum number of marking threads exceeded");
|
||||
|
||||
uint active_workers = MAX2(1U, parallel_marking_threads());
|
||||
assert(active_workers > 0, "Should have been set");
|
||||
|
||||
// Parallel task terminator is set in "set_concurrency_and_phase()"
|
||||
set_concurrency_and_phase(active_workers, true /* concurrent */);
|
||||
|
||||
CMConcurrentMarkingTask markingTask(this, cmThread());
|
||||
_parallel_workers->set_active_workers(active_workers);
|
||||
// Don't set _n_par_threads because it affects MT in process_roots()
|
||||
// and the decisions on that MT processing is made elsewhere.
|
||||
assert(_parallel_workers->active_workers() > 0, "Should have been set");
|
||||
_parallel_workers->run_task(&markingTask);
|
||||
print_stats();
|
||||
}
|
||||
@ -1761,28 +1759,20 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class G1ParNoteEndTask;
|
||||
|
||||
class G1NoteEndOfConcMarkClosure : public HeapRegionClosure {
|
||||
G1CollectedHeap* _g1;
|
||||
size_t _max_live_bytes;
|
||||
uint _regions_claimed;
|
||||
size_t _freed_bytes;
|
||||
FreeRegionList* _local_cleanup_list;
|
||||
HeapRegionSetCount _old_regions_removed;
|
||||
HeapRegionSetCount _humongous_regions_removed;
|
||||
HRRSCleanupTask* _hrrs_cleanup_task;
|
||||
double _claimed_region_time;
|
||||
double _max_region_time;
|
||||
|
||||
public:
|
||||
G1NoteEndOfConcMarkClosure(G1CollectedHeap* g1,
|
||||
FreeRegionList* local_cleanup_list,
|
||||
HRRSCleanupTask* hrrs_cleanup_task) :
|
||||
_g1(g1),
|
||||
_max_live_bytes(0), _regions_claimed(0),
|
||||
_freed_bytes(0),
|
||||
_claimed_region_time(0.0), _max_region_time(0.0),
|
||||
_local_cleanup_list(local_cleanup_list),
|
||||
_old_regions_removed(),
|
||||
_humongous_regions_removed(),
|
||||
@ -1799,10 +1789,7 @@ public:
|
||||
// We use a claim value of zero here because all regions
|
||||
// were claimed with value 1 in the FinalCount task.
|
||||
_g1->reset_gc_time_stamps(hr);
|
||||
double start = os::elapsedTime();
|
||||
_regions_claimed++;
|
||||
hr->note_end_of_marking();
|
||||
_max_live_bytes += hr->max_live_bytes();
|
||||
|
||||
if (hr->used() > 0 && hr->max_live_bytes() == 0 && !hr->is_young()) {
|
||||
_freed_bytes += hr->used();
|
||||
@ -1819,18 +1806,8 @@ public:
|
||||
hr->rem_set()->do_cleanup_work(_hrrs_cleanup_task);
|
||||
}
|
||||
|
||||
double region_time = (os::elapsedTime() - start);
|
||||
_claimed_region_time += region_time;
|
||||
if (region_time > _max_region_time) {
|
||||
_max_region_time = region_time;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t max_live_bytes() { return _max_live_bytes; }
|
||||
uint regions_claimed() { return _regions_claimed; }
|
||||
double claimed_region_time_sec() { return _claimed_region_time; }
|
||||
double max_region_time_sec() { return _max_region_time; }
|
||||
};
|
||||
|
||||
class G1ParNoteEndTask: public AbstractGangTask {
|
||||
@ -1838,14 +1815,12 @@ class G1ParNoteEndTask: public AbstractGangTask {
|
||||
|
||||
protected:
|
||||
G1CollectedHeap* _g1h;
|
||||
size_t _max_live_bytes;
|
||||
size_t _freed_bytes;
|
||||
FreeRegionList* _cleanup_list;
|
||||
HeapRegionClaimer _hrclaimer;
|
||||
|
||||
public:
|
||||
G1ParNoteEndTask(G1CollectedHeap* g1h, FreeRegionList* cleanup_list, uint n_workers) :
|
||||
AbstractGangTask("G1 note end"), _g1h(g1h), _max_live_bytes(0), _freed_bytes(0), _cleanup_list(cleanup_list), _hrclaimer(n_workers) {
|
||||
AbstractGangTask("G1 note end"), _g1h(g1h), _cleanup_list(cleanup_list), _hrclaimer(n_workers) {
|
||||
}
|
||||
|
||||
void work(uint worker_id) {
|
||||
@ -1861,8 +1836,6 @@ public:
|
||||
{
|
||||
MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag);
|
||||
_g1h->decrement_summary_bytes(g1_note_end.freed_bytes());
|
||||
_max_live_bytes += g1_note_end.max_live_bytes();
|
||||
_freed_bytes += g1_note_end.freed_bytes();
|
||||
|
||||
// If we iterate over the global cleanup list at the end of
|
||||
// cleanup to do this printing we will not guarantee to only
|
||||
@ -1887,8 +1860,6 @@ public:
|
||||
HeapRegionRemSet::finish_cleanup_task(&hrrs_cleanup_task);
|
||||
}
|
||||
}
|
||||
size_t max_live_bytes() { return _max_live_bytes; }
|
||||
size_t freed_bytes() { return _freed_bytes; }
|
||||
};
|
||||
|
||||
class G1ParScrubRemSetTask: public AbstractGangTask {
|
||||
@ -1938,18 +1909,10 @@ void ConcurrentMark::cleanup() {
|
||||
|
||||
HeapRegionRemSet::reset_for_cleanup_tasks();
|
||||
|
||||
uint n_workers;
|
||||
|
||||
// Do counting once more with the world stopped for good measure.
|
||||
G1ParFinalCountTask g1_par_count_task(g1h, &_region_bm, &_card_bm);
|
||||
|
||||
g1h->set_par_threads();
|
||||
n_workers = g1h->n_par_threads();
|
||||
assert(g1h->n_par_threads() == n_workers,
|
||||
"Should not have been reset");
|
||||
g1h->workers()->run_task(&g1_par_count_task);
|
||||
// Done with the parallel phase so reset to 0.
|
||||
g1h->set_par_threads(0);
|
||||
|
||||
if (VerifyDuringGC) {
|
||||
// Verify that the counting data accumulated during marking matches
|
||||
@ -1965,10 +1928,7 @@ void ConcurrentMark::cleanup() {
|
||||
&expected_region_bm,
|
||||
&expected_card_bm);
|
||||
|
||||
g1h->set_par_threads((int)n_workers);
|
||||
g1h->workers()->run_task(&g1_par_verify_task);
|
||||
// Done with the parallel phase so reset to 0.
|
||||
g1h->set_par_threads(0);
|
||||
|
||||
guarantee(g1_par_verify_task.failures() == 0, "Unexpected accounting failures");
|
||||
}
|
||||
@ -1990,11 +1950,11 @@ void ConcurrentMark::cleanup() {
|
||||
|
||||
g1h->reset_gc_time_stamp();
|
||||
|
||||
uint n_workers = _g1h->workers()->active_workers();
|
||||
|
||||
// Note end of marking in all heap regions.
|
||||
G1ParNoteEndTask g1_par_note_end_task(g1h, &_cleanup_list, n_workers);
|
||||
g1h->set_par_threads((int)n_workers);
|
||||
g1h->workers()->run_task(&g1_par_note_end_task);
|
||||
g1h->set_par_threads(0);
|
||||
g1h->check_gc_time_stamps();
|
||||
|
||||
if (!cleanup_list_is_empty()) {
|
||||
@ -2009,9 +1969,7 @@ void ConcurrentMark::cleanup() {
|
||||
if (G1ScrubRemSets) {
|
||||
double rs_scrub_start = os::elapsedTime();
|
||||
G1ParScrubRemSetTask g1_par_scrub_rs_task(g1h, &_region_bm, &_card_bm, n_workers);
|
||||
g1h->set_par_threads((int)n_workers);
|
||||
g1h->workers()->run_task(&g1_par_scrub_rs_task);
|
||||
g1h->set_par_threads(0);
|
||||
|
||||
double rs_scrub_end = os::elapsedTime();
|
||||
double this_rs_scrub_time = (rs_scrub_end - rs_scrub_start);
|
||||
@ -2020,7 +1978,7 @@ void ConcurrentMark::cleanup() {
|
||||
|
||||
// this will also free any regions totally full of garbage objects,
|
||||
// and sort the regions.
|
||||
g1h->g1_policy()->record_concurrent_mark_cleanup_end((int)n_workers);
|
||||
g1h->g1_policy()->record_concurrent_mark_cleanup_end();
|
||||
|
||||
// Statistics.
|
||||
double end = os::elapsedTime();
|
||||
@ -2312,9 +2270,7 @@ void G1CMRefProcTaskExecutor::execute(ProcessTask& proc_task) {
|
||||
// and overflow handling in CMTask::do_marking_step() knows
|
||||
// how many workers to wait for.
|
||||
_cm->set_concurrency(_active_workers);
|
||||
_g1h->set_par_threads(_active_workers);
|
||||
_workers->run_task(&proc_task_proxy);
|
||||
_g1h->set_par_threads(0);
|
||||
}
|
||||
|
||||
class G1CMRefEnqueueTaskProxy: public AbstractGangTask {
|
||||
@ -2344,9 +2300,7 @@ void G1CMRefProcTaskExecutor::execute(EnqueueTask& enq_task) {
|
||||
// and overflow handling in CMTask::do_marking_step() knows
|
||||
// how many workers to wait for.
|
||||
_cm->set_concurrency(_active_workers);
|
||||
_g1h->set_par_threads(_active_workers);
|
||||
_workers->run_task(&enq_task_proxy);
|
||||
_g1h->set_par_threads(0);
|
||||
}
|
||||
|
||||
void ConcurrentMark::weakRefsWorkParallelPart(BoolObjectClosure* is_alive, bool purged_classes) {
|
||||
@ -2608,27 +2562,23 @@ void ConcurrentMark::checkpointRootsFinalWork() {
|
||||
|
||||
g1h->ensure_parsability(false);
|
||||
|
||||
StrongRootsScope srs;
|
||||
// this is remark, so we'll use up all active threads
|
||||
uint active_workers = g1h->workers()->active_workers();
|
||||
if (active_workers == 0) {
|
||||
assert(active_workers > 0, "Should have been set earlier");
|
||||
active_workers = (uint) ParallelGCThreads;
|
||||
g1h->workers()->set_active_workers(active_workers);
|
||||
}
|
||||
set_concurrency_and_phase(active_workers, false /* concurrent */);
|
||||
// Leave _parallel_marking_threads at it's
|
||||
// value originally calculated in the ConcurrentMark
|
||||
// constructor and pass values of the active workers
|
||||
// through the gang in the task.
|
||||
|
||||
CMRemarkTask remarkTask(this, active_workers);
|
||||
// We will start all available threads, even if we decide that the
|
||||
// active_workers will be fewer. The extra ones will just bail out
|
||||
// immediately.
|
||||
g1h->set_par_threads(active_workers);
|
||||
g1h->workers()->run_task(&remarkTask);
|
||||
g1h->set_par_threads(0);
|
||||
{
|
||||
StrongRootsScope srs(active_workers);
|
||||
|
||||
CMRemarkTask remarkTask(this, active_workers);
|
||||
// We will start all available threads, even if we decide that the
|
||||
// active_workers will be fewer. The extra ones will just bail out
|
||||
// immediately.
|
||||
g1h->workers()->run_task(&remarkTask);
|
||||
}
|
||||
|
||||
SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();
|
||||
guarantee(has_overflown() ||
|
||||
@ -3001,9 +2951,7 @@ void ConcurrentMark::aggregate_count_data() {
|
||||
G1AggregateCountDataTask g1_par_agg_task(_g1h, this, &_card_bm,
|
||||
_max_worker_id, n_workers);
|
||||
|
||||
_g1h->set_par_threads(n_workers);
|
||||
_g1h->workers()->run_task(&g1_par_agg_task);
|
||||
_g1h->set_par_threads(0);
|
||||
}
|
||||
|
||||
// Clear the per-worker arrays used to store the per-region counting data
|
||||
|
||||
@ -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);
|
||||
|
||||
{
|
||||
@ -1326,27 +1326,10 @@ bool G1CollectedHeap::do_collection(bool explicit_gc,
|
||||
AdaptiveSizePolicy::calc_active_workers(workers()->total_workers(),
|
||||
workers()->active_workers(),
|
||||
Threads::number_of_non_daemon_threads());
|
||||
assert(UseDynamicNumberOfGCThreads ||
|
||||
n_workers == workers()->total_workers(),
|
||||
"If not dynamic should be using all the workers");
|
||||
workers()->set_active_workers(n_workers);
|
||||
// Set parallel threads in the heap (_n_par_threads) only
|
||||
// before a parallel phase and always reset it to 0 after
|
||||
// the phase so that the number of parallel threads does
|
||||
// no get carried forward to a serial phase where there
|
||||
// may be code that is "possibly_parallel".
|
||||
set_par_threads(n_workers);
|
||||
|
||||
ParRebuildRSTask rebuild_rs_task(this);
|
||||
assert(UseDynamicNumberOfGCThreads ||
|
||||
workers()->active_workers() == workers()->total_workers(),
|
||||
"Unless dynamic should use total workers");
|
||||
// Use the most recent number of active workers
|
||||
assert(workers()->active_workers() > 0,
|
||||
"Active workers not properly set");
|
||||
set_par_threads(workers()->active_workers());
|
||||
workers()->run_task(&rebuild_rs_task);
|
||||
set_par_threads(0);
|
||||
|
||||
// Rebuild the strong code root lists for each region
|
||||
rebuild_strong_code_roots();
|
||||
@ -1769,7 +1752,7 @@ G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* policy_) :
|
||||
_allocator = G1Allocator::create_allocator(this);
|
||||
_humongous_object_threshold_in_words = HeapRegion::GrainWords / 2;
|
||||
|
||||
int n_queues = MAX2((int)ParallelGCThreads, 1);
|
||||
int n_queues = (int)ParallelGCThreads;
|
||||
_task_queues = new RefToScanQueueSet(n_queues);
|
||||
|
||||
uint n_rem_sets = HeapRegionRemSet::num_par_rem_sets();
|
||||
@ -2081,11 +2064,11 @@ void G1CollectedHeap::ref_processing_init() {
|
||||
new ReferenceProcessor(mr, // span
|
||||
ParallelRefProcEnabled && (ParallelGCThreads > 1),
|
||||
// mt processing
|
||||
(int) ParallelGCThreads,
|
||||
(uint) ParallelGCThreads,
|
||||
// degree of mt processing
|
||||
(ParallelGCThreads > 1) || (ConcGCThreads > 1),
|
||||
// mt discovery
|
||||
(int) MAX2(ParallelGCThreads, ConcGCThreads),
|
||||
(uint) MAX2(ParallelGCThreads, ConcGCThreads),
|
||||
// degree of mt discovery
|
||||
false,
|
||||
// Reference discovery is not atomic
|
||||
@ -2098,11 +2081,11 @@ void G1CollectedHeap::ref_processing_init() {
|
||||
new ReferenceProcessor(mr, // span
|
||||
ParallelRefProcEnabled && (ParallelGCThreads > 1),
|
||||
// mt processing
|
||||
MAX2((int)ParallelGCThreads, 1),
|
||||
(uint) ParallelGCThreads,
|
||||
// degree of mt processing
|
||||
(ParallelGCThreads > 1),
|
||||
// mt discovery
|
||||
MAX2((int)ParallelGCThreads, 1),
|
||||
(uint) ParallelGCThreads,
|
||||
// degree of mt discovery
|
||||
true,
|
||||
// Reference discovery is atomic
|
||||
@ -2216,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;
|
||||
@ -2502,8 +2486,7 @@ void G1CollectedHeap::clear_cset_start_regions() {
|
||||
assert(_worker_cset_start_region != NULL, "sanity");
|
||||
assert(_worker_cset_start_region_time_stamp != NULL, "sanity");
|
||||
|
||||
int n_queues = MAX2((int)ParallelGCThreads, 1);
|
||||
for (int i = 0; i < n_queues; i++) {
|
||||
for (uint i = 0; i < ParallelGCThreads; i++) {
|
||||
_worker_cset_start_region[i] = NULL;
|
||||
_worker_cset_start_region_time_stamp[i] = 0;
|
||||
}
|
||||
@ -2541,9 +2524,6 @@ HeapRegion* G1CollectedHeap::start_cset_region_for_worker(uint worker_i) {
|
||||
result = g1_policy()->collection_set();
|
||||
uint cs_size = g1_policy()->cset_region_length();
|
||||
uint active_workers = workers()->active_workers();
|
||||
assert(UseDynamicNumberOfGCThreads ||
|
||||
active_workers == workers()->total_workers(),
|
||||
"Unless dynamic should use total workers");
|
||||
|
||||
uint end_ind = (cs_size * worker_i) / active_workers;
|
||||
uint start_ind = 0;
|
||||
@ -3021,7 +3001,7 @@ void G1CollectedHeap::verify(bool silent, VerifyOption vo) {
|
||||
G1VerifyCodeRootBlobClosure blobsCl(&codeRootsCl);
|
||||
|
||||
{
|
||||
G1RootProcessor root_processor(this);
|
||||
G1RootProcessor root_processor(this, 1);
|
||||
root_processor.process_all_roots(&rootsCl,
|
||||
&cldCl,
|
||||
&blobsCl);
|
||||
@ -3042,13 +3022,7 @@ void G1CollectedHeap::verify(bool silent, VerifyOption vo) {
|
||||
if (GCParallelVerificationEnabled && ParallelGCThreads > 1) {
|
||||
|
||||
G1ParVerifyTask task(this, vo);
|
||||
assert(UseDynamicNumberOfGCThreads ||
|
||||
workers()->active_workers() == workers()->total_workers(),
|
||||
"If not dynamic should be using all the workers");
|
||||
uint n_workers = workers()->active_workers();
|
||||
set_par_threads(n_workers);
|
||||
workers()->run_task(&task);
|
||||
set_par_threads(0);
|
||||
if (task.failures()) {
|
||||
failures = true;
|
||||
}
|
||||
@ -3572,6 +3546,10 @@ public:
|
||||
};
|
||||
#endif // ASSERT
|
||||
|
||||
uint G1CollectedHeap::num_task_queues() const {
|
||||
return _task_queues->size();
|
||||
}
|
||||
|
||||
#if TASKQUEUE_STATS
|
||||
void G1CollectedHeap::print_taskqueue_stats_hdr(outputStream* const st) {
|
||||
st->print_raw_cr("GC Task Stats");
|
||||
@ -3583,7 +3561,7 @@ void G1CollectedHeap::print_taskqueue_stats(outputStream* const st) const {
|
||||
print_taskqueue_stats_hdr(st);
|
||||
|
||||
TaskQueueStats totals;
|
||||
const uint n = workers()->total_workers();
|
||||
const uint n = num_task_queues();
|
||||
for (uint i = 0; i < n; ++i) {
|
||||
st->print("%3u ", i); task_queue(i)->stats.print(st); st->cr();
|
||||
totals += task_queue(i)->stats;
|
||||
@ -3594,7 +3572,7 @@ void G1CollectedHeap::print_taskqueue_stats(outputStream* const st) const {
|
||||
}
|
||||
|
||||
void G1CollectedHeap::reset_taskqueue_stats() {
|
||||
const uint n = workers()->total_workers();
|
||||
const uint n = num_task_queues();
|
||||
for (uint i = 0; i < n; ++i) {
|
||||
task_queue(i)->stats.reset();
|
||||
}
|
||||
@ -3696,9 +3674,6 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
|
||||
uint active_workers = AdaptiveSizePolicy::calc_active_workers(workers()->total_workers(),
|
||||
workers()->active_workers(),
|
||||
Threads::number_of_non_daemon_threads());
|
||||
assert(UseDynamicNumberOfGCThreads ||
|
||||
active_workers == workers()->total_workers(),
|
||||
"If not dynamic should be using all the workers");
|
||||
workers()->set_active_workers(active_workers);
|
||||
|
||||
double pause_start_sec = os::elapsedTime();
|
||||
@ -3873,8 +3848,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
|
||||
|
||||
if (evacuation_failed()) {
|
||||
_allocator->set_used(recalculate_used());
|
||||
uint n_queues = MAX2((int)ParallelGCThreads, 1);
|
||||
for (uint i = 0; i < n_queues; i++) {
|
||||
for (uint i = 0; i < ParallelGCThreads; i++) {
|
||||
if (_evacuation_failed_info_array[i].has_failed()) {
|
||||
_gc_tracer_stw->report_evacuation_failed(_evacuation_failed_info_array[i]);
|
||||
}
|
||||
@ -4041,10 +4015,8 @@ void G1CollectedHeap::finalize_for_evac_failure() {
|
||||
void G1CollectedHeap::remove_self_forwarding_pointers() {
|
||||
double remove_self_forwards_start = os::elapsedTime();
|
||||
|
||||
set_par_threads();
|
||||
G1ParRemoveSelfForwardPtrsTask rsfp_task(this);
|
||||
workers()->run_task(&rsfp_task);
|
||||
set_par_threads(0);
|
||||
|
||||
// Now restore saved marks, if any.
|
||||
assert(_objs_with_preserved_marks.size() ==
|
||||
@ -4308,12 +4280,13 @@ protected:
|
||||
Mutex* stats_lock() { return &_stats_lock; }
|
||||
|
||||
public:
|
||||
G1ParTask(G1CollectedHeap* g1h, RefToScanQueueSet *task_queues, G1RootProcessor* root_processor)
|
||||
G1ParTask(G1CollectedHeap* g1h, RefToScanQueueSet *task_queues, G1RootProcessor* root_processor, uint n_workers)
|
||||
: AbstractGangTask("G1 collection"),
|
||||
_g1h(g1h),
|
||||
_queues(task_queues),
|
||||
_root_processor(root_processor),
|
||||
_terminator(0, _queues),
|
||||
_terminator(n_workers, _queues),
|
||||
_n_workers(n_workers),
|
||||
_stats_lock(Mutex::leaf, "parallel G1 stats lock", true)
|
||||
{}
|
||||
|
||||
@ -4325,12 +4298,6 @@ public:
|
||||
|
||||
ParallelTaskTerminator* terminator() { return &_terminator; }
|
||||
|
||||
virtual void set_for_termination(uint active_workers) {
|
||||
_root_processor->set_num_workers(active_workers);
|
||||
terminator()->reset_for_reuse(active_workers);
|
||||
_n_workers = active_workers;
|
||||
}
|
||||
|
||||
// Helps out with CLD processing.
|
||||
//
|
||||
// During InitialMark we need to:
|
||||
@ -4811,19 +4778,14 @@ void G1CollectedHeap::parallel_cleaning(BoolObjectClosure* is_alive,
|
||||
|
||||
G1ParallelCleaningTask g1_unlink_task(is_alive, process_strings, process_symbols,
|
||||
n_workers, class_unloading_occurred);
|
||||
set_par_threads(n_workers);
|
||||
workers()->run_task(&g1_unlink_task);
|
||||
set_par_threads(0);
|
||||
}
|
||||
|
||||
void G1CollectedHeap::unlink_string_and_symbol_table(BoolObjectClosure* is_alive,
|
||||
bool process_strings, bool process_symbols) {
|
||||
{
|
||||
uint n_workers = workers()->active_workers();
|
||||
G1StringSymbolTableUnlinkTask g1_unlink_task(is_alive, process_strings, process_symbols);
|
||||
set_par_threads(n_workers);
|
||||
workers()->run_task(&g1_unlink_task);
|
||||
set_par_threads(0);
|
||||
}
|
||||
|
||||
if (G1StringDedup::is_enabled()) {
|
||||
@ -4851,13 +4813,9 @@ class G1RedirtyLoggedCardsTask : public AbstractGangTask {
|
||||
void G1CollectedHeap::redirty_logged_cards() {
|
||||
double redirty_logged_cards_start = os::elapsedTime();
|
||||
|
||||
uint n_workers = workers()->active_workers();
|
||||
|
||||
G1RedirtyLoggedCardsTask redirty_task(&dirty_card_queue_set());
|
||||
dirty_card_queue_set().reset_for_par_iteration();
|
||||
set_par_threads(n_workers);
|
||||
workers()->run_task(&redirty_task);
|
||||
set_par_threads(0);
|
||||
|
||||
DirtyCardQueueSet& dcq = JavaThread::dirty_card_queue_set();
|
||||
dcq.merge_bufferlists(&dirty_card_queue_set());
|
||||
@ -5093,9 +5051,7 @@ void G1STWRefProcTaskExecutor::execute(ProcessTask& proc_task) {
|
||||
ParallelTaskTerminator terminator(_active_workers, _queues);
|
||||
G1STWRefProcTaskProxy proc_task_proxy(proc_task, _g1h, _queues, &terminator);
|
||||
|
||||
_g1h->set_par_threads(_active_workers);
|
||||
_workers->run_task(&proc_task_proxy);
|
||||
_g1h->set_par_threads(0);
|
||||
}
|
||||
|
||||
// Gang task for parallel reference enqueueing.
|
||||
@ -5124,9 +5080,7 @@ void G1STWRefProcTaskExecutor::execute(EnqueueTask& enq_task) {
|
||||
|
||||
G1STWRefEnqueueTaskProxy enq_task_proxy(enq_task);
|
||||
|
||||
_g1h->set_par_threads(_active_workers);
|
||||
_workers->run_task(&enq_task_proxy);
|
||||
_g1h->set_par_threads(0);
|
||||
}
|
||||
|
||||
// End of weak reference support closures
|
||||
@ -5219,7 +5173,7 @@ public:
|
||||
};
|
||||
|
||||
// Weak Reference processing during an evacuation pause (part 1).
|
||||
void G1CollectedHeap::process_discovered_references(uint no_of_gc_workers) {
|
||||
void G1CollectedHeap::process_discovered_references() {
|
||||
double ref_proc_start = os::elapsedTime();
|
||||
|
||||
ReferenceProcessor* rp = _ref_processor_stw;
|
||||
@ -5246,17 +5200,14 @@ void G1CollectedHeap::process_discovered_references(uint no_of_gc_workers) {
|
||||
// referents points to another object which is also referenced by an
|
||||
// object discovered by the STW ref processor.
|
||||
|
||||
assert(no_of_gc_workers == workers()->active_workers(), "Need to reset active GC workers");
|
||||
uint no_of_gc_workers = workers()->active_workers();
|
||||
|
||||
set_par_threads(no_of_gc_workers);
|
||||
G1ParPreserveCMReferentsTask keep_cm_referents(this,
|
||||
no_of_gc_workers,
|
||||
_task_queues);
|
||||
|
||||
workers()->run_task(&keep_cm_referents);
|
||||
|
||||
set_par_threads(0);
|
||||
|
||||
// Closure to test whether a referent is alive.
|
||||
G1STWIsAliveClosure is_alive(this);
|
||||
|
||||
@ -5330,7 +5281,7 @@ void G1CollectedHeap::process_discovered_references(uint no_of_gc_workers) {
|
||||
}
|
||||
|
||||
// Weak Reference processing during an evacuation pause (part 2).
|
||||
void G1CollectedHeap::enqueue_discovered_references(uint no_of_gc_workers) {
|
||||
void G1CollectedHeap::enqueue_discovered_references() {
|
||||
double ref_enq_start = os::elapsedTime();
|
||||
|
||||
ReferenceProcessor* rp = _ref_processor_stw;
|
||||
@ -5344,12 +5295,12 @@ void G1CollectedHeap::enqueue_discovered_references(uint no_of_gc_workers) {
|
||||
} else {
|
||||
// Parallel reference enqueueing
|
||||
|
||||
assert(no_of_gc_workers == workers()->active_workers(),
|
||||
"Need to reset active workers");
|
||||
assert(rp->num_q() == no_of_gc_workers, "sanity");
|
||||
assert(no_of_gc_workers <= rp->max_num_q(), "sanity");
|
||||
uint n_workers = workers()->active_workers();
|
||||
|
||||
G1STWRefProcTaskExecutor par_task_executor(this, workers(), _task_queues, no_of_gc_workers);
|
||||
assert(rp->num_q() == n_workers, "sanity");
|
||||
assert(n_workers <= rp->max_num_q(), "sanity");
|
||||
|
||||
G1STWRefProcTaskExecutor par_task_executor(this, workers(), _task_queues, n_workers);
|
||||
rp->enqueue_discovered_references(&par_task_executor);
|
||||
}
|
||||
|
||||
@ -5380,11 +5331,6 @@ void G1CollectedHeap::evacuate_collection_set(EvacuationInfo& evacuation_info) {
|
||||
hot_card_cache->set_use_cache(false);
|
||||
|
||||
const uint n_workers = workers()->active_workers();
|
||||
assert(UseDynamicNumberOfGCThreads ||
|
||||
n_workers == workers()->total_workers(),
|
||||
"If not dynamic should be using all the workers");
|
||||
set_par_threads(n_workers);
|
||||
|
||||
|
||||
init_for_evac_failure(NULL);
|
||||
|
||||
@ -5393,19 +5339,16 @@ void G1CollectedHeap::evacuate_collection_set(EvacuationInfo& evacuation_info) {
|
||||
double end_par_time_sec;
|
||||
|
||||
{
|
||||
G1RootProcessor root_processor(this);
|
||||
G1ParTask g1_par_task(this, _task_queues, &root_processor);
|
||||
G1RootProcessor root_processor(this, n_workers);
|
||||
G1ParTask g1_par_task(this, _task_queues, &root_processor, n_workers);
|
||||
// InitialMark needs claim bits to keep track of the marked-through CLDs.
|
||||
if (g1_policy()->during_initial_mark_pause()) {
|
||||
ClassLoaderDataGraph::clear_claimed_marks();
|
||||
}
|
||||
|
||||
// The individual threads will set their evac-failure closures.
|
||||
if (PrintTerminationStats) G1ParScanThreadState::print_termination_stats_hdr();
|
||||
// These tasks use ShareHeap::_process_strong_tasks
|
||||
assert(UseDynamicNumberOfGCThreads ||
|
||||
workers()->active_workers() == workers()->total_workers(),
|
||||
"If not dynamic should be using all the workers");
|
||||
// The individual threads will set their evac-failure closures.
|
||||
if (PrintTerminationStats) G1ParScanThreadState::print_termination_stats_hdr();
|
||||
|
||||
workers()->run_task(&g1_par_task);
|
||||
end_par_time_sec = os::elapsedTime();
|
||||
|
||||
@ -5425,14 +5368,12 @@ void G1CollectedHeap::evacuate_collection_set(EvacuationInfo& evacuation_info) {
|
||||
(os::elapsedTime() - end_par_time_sec) * 1000.0;
|
||||
phase_times->record_code_root_fixup_time(code_root_fixup_time_ms);
|
||||
|
||||
set_par_threads(0);
|
||||
|
||||
// Process any discovered reference objects - we have
|
||||
// to do this _before_ we retire the GC alloc regions
|
||||
// as we may have to copy some 'reachable' referent
|
||||
// objects (and their reachable sub-graphs) that were
|
||||
// not copied during the pause.
|
||||
process_discovered_references(n_workers);
|
||||
process_discovered_references();
|
||||
|
||||
if (G1StringDedup::is_enabled()) {
|
||||
double fixup_start = os::elapsedTime();
|
||||
@ -5474,7 +5415,7 @@ void G1CollectedHeap::evacuate_collection_set(EvacuationInfo& evacuation_info) {
|
||||
// will log these updates (and dirty their associated
|
||||
// cards). We need these updates logged to update any
|
||||
// RSets.
|
||||
enqueue_discovered_references(n_workers);
|
||||
enqueue_discovered_references();
|
||||
|
||||
redirty_logged_cards();
|
||||
COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
|
||||
@ -5779,9 +5720,7 @@ void G1CollectedHeap::cleanUpCardTable() {
|
||||
// Iterate over the dirty cards region list.
|
||||
G1ParCleanupCTTask cleanup_task(ct_bs, this);
|
||||
|
||||
set_par_threads();
|
||||
workers()->run_task(&cleanup_task);
|
||||
set_par_threads(0);
|
||||
#ifndef PRODUCT
|
||||
if (G1VerifyCTCleanup || VerifyAfterGC) {
|
||||
G1VerifyCardTableCleanup cleanup_verifier(this, ct_bs);
|
||||
@ -6314,21 +6253,6 @@ void G1CollectedHeap::retire_mutator_alloc_region(HeapRegion* alloc_region,
|
||||
g1mm()->update_eden_size();
|
||||
}
|
||||
|
||||
void G1CollectedHeap::set_par_threads() {
|
||||
// Don't change the number of workers. Use the value previously set
|
||||
// in the workgroup.
|
||||
uint n_workers = workers()->active_workers();
|
||||
assert(UseDynamicNumberOfGCThreads ||
|
||||
n_workers == workers()->total_workers(),
|
||||
"Otherwise should be using the total number of workers");
|
||||
if (n_workers == 0) {
|
||||
assert(false, "Should have been set in prior evacuation pause.");
|
||||
n_workers = ParallelGCThreads;
|
||||
workers()->set_active_workers(n_workers);
|
||||
}
|
||||
set_par_threads(n_workers);
|
||||
}
|
||||
|
||||
// Methods for the GC alloc regions
|
||||
|
||||
HeapRegion* G1CollectedHeap::new_gc_alloc_region(size_t word_size,
|
||||
|
||||
@ -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
|
||||
@ -606,11 +607,11 @@ protected:
|
||||
|
||||
// Process any reference objects discovered during
|
||||
// an incremental evacuation pause.
|
||||
void process_discovered_references(uint no_of_gc_workers);
|
||||
void process_discovered_references();
|
||||
|
||||
// Enqueue any remaining discovered references
|
||||
// after processing.
|
||||
void enqueue_discovered_references(uint no_of_gc_workers);
|
||||
void enqueue_discovered_references();
|
||||
|
||||
public:
|
||||
FlexibleWorkGang* workers() const { return _workers; }
|
||||
@ -981,6 +982,8 @@ public:
|
||||
|
||||
RefToScanQueue *task_queue(uint i) const;
|
||||
|
||||
uint num_task_queues() const;
|
||||
|
||||
// A set of cards where updates happened during the GC
|
||||
DirtyCardQueueSet& dirty_card_queue_set() { return _dirty_card_queue_set; }
|
||||
|
||||
@ -1012,11 +1015,6 @@ public:
|
||||
// Initialize weak reference processing.
|
||||
void ref_processing_init();
|
||||
|
||||
// Explicitly import set_par_threads into this scope
|
||||
using CollectedHeap::set_par_threads;
|
||||
// Set _n_par_threads according to a policy TBD.
|
||||
void set_par_threads();
|
||||
|
||||
virtual Name kind() const {
|
||||
return CollectedHeap::G1CollectedHeap;
|
||||
}
|
||||
|
||||
@ -1587,14 +1587,17 @@ uint G1CollectorPolicy::calculate_parallel_work_chunk_size(uint n_workers, uint
|
||||
}
|
||||
|
||||
void
|
||||
G1CollectorPolicy::record_concurrent_mark_cleanup_end(uint n_workers) {
|
||||
G1CollectorPolicy::record_concurrent_mark_cleanup_end() {
|
||||
_collectionSetChooser->clear();
|
||||
|
||||
FlexibleWorkGang* workers = _g1->workers();
|
||||
uint n_workers = workers->active_workers();
|
||||
|
||||
uint n_regions = _g1->num_regions();
|
||||
uint chunk_size = calculate_parallel_work_chunk_size(n_workers, n_regions);
|
||||
_collectionSetChooser->prepare_for_par_region_addition(n_regions, chunk_size);
|
||||
_collectionSetChooser->prepare_for_par_region_addition(n_workers, n_regions, chunk_size);
|
||||
ParKnownGarbageTask par_known_garbage_task(_collectionSetChooser, chunk_size, n_workers);
|
||||
_g1->workers()->run_task(&par_known_garbage_task);
|
||||
workers->run_task(&par_known_garbage_task);
|
||||
|
||||
_collectionSetChooser->sort_regions();
|
||||
|
||||
|
||||
@ -692,7 +692,7 @@ public:
|
||||
|
||||
// Record start, end, and completion of cleanup.
|
||||
void record_concurrent_mark_cleanup_start();
|
||||
void record_concurrent_mark_cleanup_end(uint n_workers);
|
||||
void record_concurrent_mark_cleanup_end();
|
||||
void record_concurrent_mark_cleanup_completed();
|
||||
|
||||
// Records the information about the heap size for reporting in
|
||||
|
||||
@ -127,7 +127,7 @@ void G1MarkSweep::mark_sweep_phase1(bool& marked_for_unloading,
|
||||
|
||||
MarkingCodeBlobClosure follow_code_closure(&GenMarkSweep::follow_root_closure, !CodeBlobToOopClosure::FixRelocations);
|
||||
{
|
||||
G1RootProcessor root_processor(g1h);
|
||||
G1RootProcessor root_processor(g1h, 1);
|
||||
root_processor.process_strong_roots(&GenMarkSweep::follow_root_closure,
|
||||
&GenMarkSweep::follow_cld_closure,
|
||||
&follow_code_closure);
|
||||
@ -237,7 +237,7 @@ void G1MarkSweep::mark_sweep_phase3() {
|
||||
|
||||
CodeBlobToOopClosure adjust_code_closure(&GenMarkSweep::adjust_pointer_closure, CodeBlobToOopClosure::FixRelocations);
|
||||
{
|
||||
G1RootProcessor root_processor(g1h);
|
||||
G1RootProcessor root_processor(g1h, 1);
|
||||
root_processor.process_all_roots(&GenMarkSweep::adjust_pointer_closure,
|
||||
&GenMarkSweep::adjust_cld_closure,
|
||||
&adjust_code_closure);
|
||||
|
||||
@ -50,8 +50,8 @@ void G1ParClosureSuper::set_par_scan_thread_state(G1ParScanThreadState* par_scan
|
||||
_par_scan_state = par_scan_state;
|
||||
_worker_id = par_scan_state->queue_num();
|
||||
|
||||
assert(_worker_id < MAX2((uint)ParallelGCThreads, 1u),
|
||||
err_msg("The given worker id %u must be less than the number of threads %u", _worker_id, MAX2((uint)ParallelGCThreads, 1u)));
|
||||
assert(_worker_id < ParallelGCThreads,
|
||||
err_msg("The given worker id %u must be less than the number of threads " UINTX_FORMAT, _worker_id, ParallelGCThreads));
|
||||
}
|
||||
|
||||
// Generate G1 specialized oop_oop_iterate functions.
|
||||
|
||||
@ -90,11 +90,10 @@ public:
|
||||
|
||||
|
||||
void G1RootProcessor::worker_has_discovered_all_strong_classes() {
|
||||
uint n_workers = _g1h->n_par_threads();
|
||||
assert(ClassUnloadingWithConcurrentMark, "Currently only needed when doing G1 Class Unloading");
|
||||
|
||||
uint new_value = (uint)Atomic::add(1, &_n_workers_discovered_strong_classes);
|
||||
if (new_value == n_workers) {
|
||||
if (new_value == n_workers()) {
|
||||
// This thread is last. Notify the others.
|
||||
MonitorLockerEx ml(&_lock, Mutex::_no_safepoint_check_flag);
|
||||
_lock.notify_all();
|
||||
@ -102,21 +101,20 @@ void G1RootProcessor::worker_has_discovered_all_strong_classes() {
|
||||
}
|
||||
|
||||
void G1RootProcessor::wait_until_all_strong_classes_discovered() {
|
||||
uint n_workers = _g1h->n_par_threads();
|
||||
assert(ClassUnloadingWithConcurrentMark, "Currently only needed when doing G1 Class Unloading");
|
||||
|
||||
if ((uint)_n_workers_discovered_strong_classes != n_workers) {
|
||||
if ((uint)_n_workers_discovered_strong_classes != n_workers()) {
|
||||
MonitorLockerEx ml(&_lock, Mutex::_no_safepoint_check_flag);
|
||||
while ((uint)_n_workers_discovered_strong_classes != n_workers) {
|
||||
while ((uint)_n_workers_discovered_strong_classes != n_workers()) {
|
||||
_lock.wait(Mutex::_no_safepoint_check_flag, 0, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
G1RootProcessor::G1RootProcessor(G1CollectedHeap* g1h) :
|
||||
G1RootProcessor::G1RootProcessor(G1CollectedHeap* g1h, uint n_workers) :
|
||||
_g1h(g1h),
|
||||
_process_strong_tasks(new SubTasksDone(G1RP_PS_NumElements)),
|
||||
_srs(),
|
||||
_srs(n_workers),
|
||||
_lock(Mutex::leaf, "G1 Root Scanning barrier lock", false, Monitor::_safepoint_check_never),
|
||||
_n_workers_discovered_strong_classes(0) {}
|
||||
|
||||
@ -206,7 +204,7 @@ void G1RootProcessor::evacuate_roots(OopClosure* scan_non_heap_roots,
|
||||
}
|
||||
}
|
||||
|
||||
_process_strong_tasks->all_tasks_completed();
|
||||
_process_strong_tasks->all_tasks_completed(n_workers());
|
||||
}
|
||||
|
||||
void G1RootProcessor::process_strong_roots(OopClosure* oops,
|
||||
@ -216,7 +214,7 @@ void G1RootProcessor::process_strong_roots(OopClosure* oops,
|
||||
process_java_roots(oops, clds, clds, NULL, blobs, NULL, 0);
|
||||
process_vm_roots(oops, NULL, NULL, 0);
|
||||
|
||||
_process_strong_tasks->all_tasks_completed();
|
||||
_process_strong_tasks->all_tasks_completed(n_workers());
|
||||
}
|
||||
|
||||
void G1RootProcessor::process_all_roots(OopClosure* oops,
|
||||
@ -230,7 +228,7 @@ void G1RootProcessor::process_all_roots(OopClosure* oops,
|
||||
CodeCache::blobs_do(blobs);
|
||||
}
|
||||
|
||||
_process_strong_tasks->all_tasks_completed();
|
||||
_process_strong_tasks->all_tasks_completed(n_workers());
|
||||
}
|
||||
|
||||
void G1RootProcessor::process_java_roots(OopClosure* strong_roots,
|
||||
@ -253,7 +251,7 @@ void G1RootProcessor::process_java_roots(OopClosure* strong_roots,
|
||||
|
||||
{
|
||||
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::ThreadRoots, worker_i);
|
||||
bool is_par = _g1h->n_par_threads() > 0;
|
||||
bool is_par = n_workers() > 1;
|
||||
Threads::possibly_parallel_oops_do(is_par, strong_roots, thread_stack_clds, strong_code);
|
||||
}
|
||||
}
|
||||
@ -329,6 +327,6 @@ void G1RootProcessor::scan_remembered_sets(G1ParPushHeapRSClosure* scan_rs,
|
||||
_g1h->g1_rem_set()->oops_into_collection_set_do(scan_rs, &scavenge_cs_nmethods, worker_i);
|
||||
}
|
||||
|
||||
void G1RootProcessor::set_num_workers(uint active_workers) {
|
||||
_process_strong_tasks->set_n_threads(active_workers);
|
||||
uint G1RootProcessor::n_workers() const {
|
||||
return _srs.n_threads();
|
||||
}
|
||||
|
||||
@ -85,7 +85,7 @@ class G1RootProcessor : public StackObj {
|
||||
uint worker_i);
|
||||
|
||||
public:
|
||||
G1RootProcessor(G1CollectedHeap* g1h);
|
||||
G1RootProcessor(G1CollectedHeap* g1h, uint n_workers);
|
||||
|
||||
// Apply closures to the strongly and weakly reachable roots in the system
|
||||
// in a single pass.
|
||||
@ -114,8 +114,8 @@ public:
|
||||
OopClosure* scan_non_heap_weak_roots,
|
||||
uint worker_i);
|
||||
|
||||
// Inform the root processor about the number of worker threads
|
||||
void set_num_workers(uint active_workers);
|
||||
// Number of worker threads used by the root processor.
|
||||
uint n_workers() const;
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_GC_G1_G1ROOTPROCESSOR_HPP
|
||||
|
||||
@ -153,9 +153,7 @@ void G1StringDedup::unlink_or_oops_do(BoolObjectClosure* is_alive,
|
||||
|
||||
G1StringDedupUnlinkOrOopsDoTask task(is_alive, keep_alive, allow_resize_and_rehash, phase_times);
|
||||
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
||||
g1h->set_par_threads();
|
||||
g1h->workers()->run_task(&task);
|
||||
g1h->set_par_threads(0);
|
||||
}
|
||||
|
||||
void G1StringDedup::threads_do(ThreadClosure* tc) {
|
||||
|
||||
@ -42,7 +42,7 @@ G1StringDedupQueue::G1StringDedupQueue() :
|
||||
_cancel(false),
|
||||
_empty(true),
|
||||
_dropped(0) {
|
||||
_nqueues = MAX2(ParallelGCThreads, (size_t)1);
|
||||
_nqueues = ParallelGCThreads;
|
||||
_queues = NEW_C_HEAP_ARRAY(G1StringDedupWorkerQueue, _nqueues, mtGC);
|
||||
for (size_t i = 0; i < _nqueues; i++) {
|
||||
new (_queues + i) G1StringDedupWorkerQueue(G1StringDedupWorkerQueue::default_segment_size(), _max_cache_size, _max_size);
|
||||
|
||||
@ -112,7 +112,7 @@ public:
|
||||
};
|
||||
|
||||
G1StringDedupEntryCache::G1StringDedupEntryCache() {
|
||||
_nlists = MAX2(ParallelGCThreads, (size_t)1);
|
||||
_nlists = ParallelGCThreads;
|
||||
_lists = PaddedArray<G1StringDedupEntryFreeList, mtGC>::create_unfreeable((uint)_nlists);
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -832,9 +832,9 @@ void PSParallelCompact::post_initialize() {
|
||||
_ref_processor =
|
||||
new ReferenceProcessor(mr, // span
|
||||
ParallelRefProcEnabled && (ParallelGCThreads > 1), // mt processing
|
||||
(int) ParallelGCThreads, // mt processing degree
|
||||
(uint) ParallelGCThreads, // mt processing degree
|
||||
true, // mt discovery
|
||||
(int) ParallelGCThreads, // mt discovery degree
|
||||
(uint) ParallelGCThreads, // mt discovery degree
|
||||
true, // atomic_discovery
|
||||
&_is_alive_closure); // non-header is alive closure
|
||||
_counters = new CollectorCounters("PSParallelCompact", 1);
|
||||
@ -2029,7 +2029,6 @@ bool PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) {
|
||||
// Set the number of GC threads to be used in this collection
|
||||
gc_task_manager()->set_active_gang();
|
||||
gc_task_manager()->task_idle_workers();
|
||||
heap->set_par_threads(gc_task_manager()->active_workers());
|
||||
|
||||
TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
|
||||
GCTraceTime t1(GCCauseString("Full GC", gc_cause), PrintGC, !PrintGCDetails, NULL, _gc_tracer.gc_id());
|
||||
@ -2054,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"));
|
||||
@ -2090,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();
|
||||
@ -382,7 +382,6 @@ bool PSScavenge::invoke_no_policy() {
|
||||
// Get the active number of workers here and use that value
|
||||
// throughout the methods.
|
||||
uint active_workers = gc_task_manager()->active_workers();
|
||||
heap->set_par_threads(active_workers);
|
||||
|
||||
PSPromotionManager::pre_scavenge();
|
||||
|
||||
@ -846,9 +845,9 @@ void PSScavenge::initialize() {
|
||||
_ref_processor =
|
||||
new ReferenceProcessor(mr, // span
|
||||
ParallelRefProcEnabled && (ParallelGCThreads > 1), // mt processing
|
||||
(int) ParallelGCThreads, // mt processing degree
|
||||
(uint) ParallelGCThreads, // mt processing degree
|
||||
true, // mt discovery
|
||||
(int) ParallelGCThreads, // mt discovery degree
|
||||
(uint) ParallelGCThreads, // mt discovery degree
|
||||
true, // atomic_discovery
|
||||
NULL); // header provides liveness info
|
||||
|
||||
|
||||
@ -38,6 +38,7 @@
|
||||
#include "gc/shared/referencePolicy.hpp"
|
||||
#include "gc/shared/space.inline.hpp"
|
||||
#include "gc/shared/spaceDecorator.hpp"
|
||||
#include "gc/shared/strongRootsScope.hpp"
|
||||
#include "memory/iterator.hpp"
|
||||
#include "oops/instanceRefKlass.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
@ -454,7 +455,7 @@ void DefNewGeneration::compute_new_size() {
|
||||
}
|
||||
}
|
||||
|
||||
void DefNewGeneration::younger_refs_iterate(OopsInGenClosure* cl) {
|
||||
void DefNewGeneration::younger_refs_iterate(OopsInGenClosure* cl, uint n_threads) {
|
||||
assert(false, "NYI -- are you sure you want to call this?");
|
||||
}
|
||||
|
||||
@ -625,15 +626,22 @@ void DefNewGeneration::collect(bool full,
|
||||
assert(gch->no_allocs_since_save_marks(0),
|
||||
"save marks have not been newly set.");
|
||||
|
||||
gch->gen_process_roots(_level,
|
||||
true, // Process younger gens, if any,
|
||||
// as strong roots.
|
||||
true, // activate StrongRootsScope
|
||||
GenCollectedHeap::SO_ScavengeCodeCache,
|
||||
GenCollectedHeap::StrongAndWeakRoots,
|
||||
&fsc_with_no_gc_barrier,
|
||||
&fsc_with_gc_barrier,
|
||||
&cld_scan_closure);
|
||||
{
|
||||
// DefNew needs to run with n_threads == 0, to make sure the serial
|
||||
// version of the card table scanning code is used.
|
||||
// See: CardTableModRefBS::non_clean_card_iterate_possibly_parallel.
|
||||
StrongRootsScope srs(0);
|
||||
|
||||
gch->gen_process_roots(&srs,
|
||||
_level,
|
||||
true, // Process younger gens, if any,
|
||||
// as strong roots.
|
||||
GenCollectedHeap::SO_ScavengeCodeCache,
|
||||
GenCollectedHeap::StrongAndWeakRoots,
|
||||
&fsc_with_no_gc_barrier,
|
||||
&fsc_with_gc_barrier,
|
||||
&cld_scan_closure);
|
||||
}
|
||||
|
||||
// "evacuate followers".
|
||||
evacuate_followers.do_void();
|
||||
@ -952,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;
|
||||
|
||||
@ -255,7 +255,7 @@ protected:
|
||||
// Iteration
|
||||
void object_iterate(ObjectClosure* blk);
|
||||
|
||||
void younger_refs_iterate(OopsInGenClosure* cl);
|
||||
void younger_refs_iterate(OopsInGenClosure* cl, uint n_threads);
|
||||
|
||||
void space_iterate(SpaceClosure* blk, bool usedOnly = false);
|
||||
|
||||
|
||||
@ -40,6 +40,7 @@
|
||||
#include "gc/shared/modRefBarrierSet.hpp"
|
||||
#include "gc/shared/referencePolicy.hpp"
|
||||
#include "gc/shared/space.hpp"
|
||||
#include "gc/shared/strongRootsScope.hpp"
|
||||
#include "oops/instanceRefKlass.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
#include "prims/jvmtiExport.hpp"
|
||||
@ -200,14 +201,18 @@ void GenMarkSweep::mark_sweep_phase1(int level,
|
||||
// Need new claim bits before marking starts.
|
||||
ClassLoaderDataGraph::clear_claimed_marks();
|
||||
|
||||
gch->gen_process_roots(level,
|
||||
false, // Younger gens are not roots.
|
||||
true, // activate StrongRootsScope
|
||||
GenCollectedHeap::SO_None,
|
||||
GenCollectedHeap::StrongRootsOnly,
|
||||
&follow_root_closure,
|
||||
&follow_root_closure,
|
||||
&follow_cld_closure);
|
||||
{
|
||||
StrongRootsScope srs(1);
|
||||
|
||||
gch->gen_process_roots(&srs,
|
||||
level,
|
||||
false, // Younger gens are not roots.
|
||||
GenCollectedHeap::SO_None,
|
||||
GenCollectedHeap::StrongRootsOnly,
|
||||
&follow_root_closure,
|
||||
&follow_root_closure,
|
||||
&follow_cld_closure);
|
||||
}
|
||||
|
||||
// Process reference objects found during marking
|
||||
{
|
||||
@ -284,14 +289,18 @@ void GenMarkSweep::mark_sweep_phase3(int level) {
|
||||
assert(level == 1, "We don't use mark-sweep on young generations.");
|
||||
adjust_pointer_closure.set_orig_generation(gch->old_gen());
|
||||
|
||||
gch->gen_process_roots(level,
|
||||
false, // Younger gens are not roots.
|
||||
true, // activate StrongRootsScope
|
||||
GenCollectedHeap::SO_AllCodeCache,
|
||||
GenCollectedHeap::StrongAndWeakRoots,
|
||||
&adjust_pointer_closure,
|
||||
&adjust_pointer_closure,
|
||||
&adjust_cld_closure);
|
||||
{
|
||||
StrongRootsScope srs(1);
|
||||
|
||||
gch->gen_process_roots(&srs,
|
||||
level,
|
||||
false, // Younger gens are not roots.
|
||||
GenCollectedHeap::SO_AllCodeCache,
|
||||
GenCollectedHeap::StrongAndWeakRoots,
|
||||
&adjust_pointer_closure,
|
||||
&adjust_pointer_closure,
|
||||
&adjust_cld_closure);
|
||||
}
|
||||
|
||||
gch->gen_process_weak_roots(&adjust_pointer_closure);
|
||||
|
||||
|
||||
@ -161,7 +161,7 @@ uint AdaptiveSizePolicy::calc_default_active_workers(uintx total_workers,
|
||||
}
|
||||
_debug_perturbation = !_debug_perturbation;
|
||||
}
|
||||
assert((new_active_workers <= (uintx) ParallelGCThreads) &&
|
||||
assert((new_active_workers <= ParallelGCThreads) &&
|
||||
(new_active_workers >= min_workers),
|
||||
"Jiggled active workers too much");
|
||||
}
|
||||
@ -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;
|
||||
|
||||
@ -353,8 +353,8 @@ void CardGeneration::space_iterate(SpaceClosure* blk,
|
||||
blk->do_space(space());
|
||||
}
|
||||
|
||||
void CardGeneration::younger_refs_iterate(OopsInGenClosure* blk) {
|
||||
void CardGeneration::younger_refs_iterate(OopsInGenClosure* blk, uint n_threads) {
|
||||
blk->set_generation(this);
|
||||
younger_refs_in_space_iterate(space(), blk);
|
||||
younger_refs_in_space_iterate(space(), blk, n_threads);
|
||||
blk->reset_generation();
|
||||
}
|
||||
|
||||
@ -89,7 +89,7 @@ class CardGeneration: public Generation {
|
||||
|
||||
void space_iterate(SpaceClosure* blk, bool usedOnly = false);
|
||||
|
||||
void younger_refs_iterate(OopsInGenClosure* blk);
|
||||
void younger_refs_iterate(OopsInGenClosure* blk, uint n_threads);
|
||||
|
||||
bool is_in(const void* p) const;
|
||||
|
||||
|
||||
@ -440,31 +440,11 @@ void CardTableModRefBS::write_ref_field_work(void* field, oop newVal, bool relea
|
||||
void CardTableModRefBS::non_clean_card_iterate_possibly_parallel(Space* sp,
|
||||
MemRegion mr,
|
||||
OopsInGenClosure* cl,
|
||||
CardTableRS* ct) {
|
||||
CardTableRS* ct,
|
||||
uint n_threads) {
|
||||
if (!mr.is_empty()) {
|
||||
// Caller (process_roots()) claims that all GC threads
|
||||
// execute this call. With UseDynamicNumberOfGCThreads now all
|
||||
// active GC threads execute this call. The number of active GC
|
||||
// threads needs to be passed to par_non_clean_card_iterate_work()
|
||||
// to get proper partitioning and termination.
|
||||
//
|
||||
// This is an example of where n_par_threads() is used instead
|
||||
// of workers()->active_workers(). n_par_threads can be set to 0 to
|
||||
// turn off parallelism. For example when this code is called as
|
||||
// part of verification during root processing then n_par_threads()
|
||||
// may have been set to 0. active_workers is not overloaded with
|
||||
// the meaning that it is a switch to disable parallelism and so keeps
|
||||
// the meaning of the number of active gc workers. If parallelism has
|
||||
// not been shut off by setting n_par_threads to 0, then n_par_threads
|
||||
// should be equal to active_workers. When a different mechanism for
|
||||
// shutting off parallelism is used, then active_workers can be used in
|
||||
// place of n_par_threads.
|
||||
int n_threads = GenCollectedHeap::heap()->n_par_threads();
|
||||
bool is_par = n_threads > 0;
|
||||
if (is_par) {
|
||||
if (n_threads > 0) {
|
||||
#if INCLUDE_ALL_GCS
|
||||
assert(GenCollectedHeap::heap()->n_par_threads() ==
|
||||
GenCollectedHeap::heap()->workers()->active_workers(), "Mismatch");
|
||||
non_clean_card_iterate_parallel_work(sp, mr, cl, ct, n_threads);
|
||||
#else // INCLUDE_ALL_GCS
|
||||
fatal("Parallel gc not supported here.");
|
||||
@ -472,8 +452,11 @@ void CardTableModRefBS::non_clean_card_iterate_possibly_parallel(Space* sp,
|
||||
} else {
|
||||
// clear_cl finds contiguous dirty ranges of cards to process and clear.
|
||||
|
||||
DirtyCardToOopClosure* dcto_cl = sp->new_dcto_cl(cl, precision(), cl->gen_boundary());
|
||||
ClearNoncleanCardWrapper clear_cl(dcto_cl, ct);
|
||||
// This is the single-threaded version used by DefNew.
|
||||
const bool parallel = false;
|
||||
|
||||
DirtyCardToOopClosure* dcto_cl = sp->new_dcto_cl(cl, precision(), cl->gen_boundary(), parallel);
|
||||
ClearNoncleanCardWrapper clear_cl(dcto_cl, ct, parallel);
|
||||
|
||||
clear_cl.do_MemRegion(mr);
|
||||
}
|
||||
|
||||
@ -178,14 +178,15 @@ class CardTableModRefBS: public ModRefBarrierSet {
|
||||
// region mr in the given space and apply cl to any dirty sub-regions
|
||||
// of mr. Clears the dirty cards as they are processed.
|
||||
void non_clean_card_iterate_possibly_parallel(Space* sp, MemRegion mr,
|
||||
OopsInGenClosure* cl, CardTableRS* ct);
|
||||
OopsInGenClosure* cl, CardTableRS* ct,
|
||||
uint n_threads);
|
||||
|
||||
private:
|
||||
// Work method used to implement non_clean_card_iterate_possibly_parallel()
|
||||
// above in the parallel case.
|
||||
void non_clean_card_iterate_parallel_work(Space* sp, MemRegion mr,
|
||||
OopsInGenClosure* cl, CardTableRS* ct,
|
||||
int n_threads);
|
||||
uint n_threads);
|
||||
|
||||
protected:
|
||||
// Dirty the bytes corresponding to "mr" (not all of which must be
|
||||
|
||||
@ -102,9 +102,10 @@ void CardTableRS::prepare_for_younger_refs_iterate(bool parallel) {
|
||||
}
|
||||
|
||||
void CardTableRS::younger_refs_iterate(Generation* g,
|
||||
OopsInGenClosure* blk) {
|
||||
OopsInGenClosure* blk,
|
||||
uint n_threads) {
|
||||
_last_cur_val_in_gen[g->level()+1] = cur_youngergen_card_val();
|
||||
g->younger_refs_iterate(blk);
|
||||
g->younger_refs_iterate(blk, n_threads);
|
||||
}
|
||||
|
||||
inline bool ClearNoncleanCardWrapper::clear_card(jbyte* entry) {
|
||||
@ -164,15 +165,8 @@ inline bool ClearNoncleanCardWrapper::clear_card_serial(jbyte* entry) {
|
||||
}
|
||||
|
||||
ClearNoncleanCardWrapper::ClearNoncleanCardWrapper(
|
||||
DirtyCardToOopClosure* dirty_card_closure, CardTableRS* ct) :
|
||||
_dirty_card_closure(dirty_card_closure), _ct(ct) {
|
||||
// Cannot yet substitute active_workers for n_par_threads
|
||||
// in the case where parallelism is being turned off by
|
||||
// setting n_par_threads to 0.
|
||||
_is_par = (GenCollectedHeap::heap()->n_par_threads() > 0);
|
||||
assert(!_is_par ||
|
||||
(GenCollectedHeap::heap()->n_par_threads() ==
|
||||
GenCollectedHeap::heap()->workers()->active_workers()), "Mismatch");
|
||||
DirtyCardToOopClosure* dirty_card_closure, CardTableRS* ct, bool is_par) :
|
||||
_dirty_card_closure(dirty_card_closure), _ct(ct), _is_par(is_par) {
|
||||
}
|
||||
|
||||
bool ClearNoncleanCardWrapper::is_word_aligned(jbyte* entry) {
|
||||
@ -272,7 +266,8 @@ void CardTableRS::write_ref_field_gc_par(void* field, oop new_val) {
|
||||
}
|
||||
|
||||
void CardTableRS::younger_refs_in_space_iterate(Space* sp,
|
||||
OopsInGenClosure* cl) {
|
||||
OopsInGenClosure* cl,
|
||||
uint n_threads) {
|
||||
const MemRegion urasm = sp->used_region_at_save_marks();
|
||||
#ifdef ASSERT
|
||||
// Convert the assertion check to a warning if we are running
|
||||
@ -301,7 +296,7 @@ void CardTableRS::younger_refs_in_space_iterate(Space* sp,
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
#endif
|
||||
_ct_bs->non_clean_card_iterate_possibly_parallel(sp, urasm, cl, this);
|
||||
_ct_bs->non_clean_card_iterate_possibly_parallel(sp, urasm, cl, this, n_threads);
|
||||
}
|
||||
|
||||
void CardTableRS::clear_into_younger(Generation* old_gen) {
|
||||
|
||||
@ -56,7 +56,7 @@ class CardTableRS: public GenRemSet {
|
||||
|
||||
CardTableModRefBSForCTRS* _ct_bs;
|
||||
|
||||
virtual void younger_refs_in_space_iterate(Space* sp, OopsInGenClosure* cl);
|
||||
virtual void younger_refs_in_space_iterate(Space* sp, OopsInGenClosure* cl, uint n_threads);
|
||||
|
||||
void verify_space(Space* s, HeapWord* gen_start);
|
||||
|
||||
@ -116,7 +116,7 @@ public:
|
||||
// Card table entries are cleared before application; "blk" is
|
||||
// responsible for dirtying if the oop is still older-to-younger after
|
||||
// closure application.
|
||||
void younger_refs_iterate(Generation* g, OopsInGenClosure* blk);
|
||||
void younger_refs_iterate(Generation* g, OopsInGenClosure* blk, uint n_threads);
|
||||
|
||||
void inline_write_ref_field_gc(void* field, oop new_val) {
|
||||
jbyte* byte = _ct_bs->byte_for(field);
|
||||
@ -183,7 +183,7 @@ private:
|
||||
bool is_word_aligned(jbyte* entry);
|
||||
|
||||
public:
|
||||
ClearNoncleanCardWrapper(DirtyCardToOopClosure* dirty_card_closure, CardTableRS* ct);
|
||||
ClearNoncleanCardWrapper(DirtyCardToOopClosure* dirty_card_closure, CardTableRS* ct, bool is_par);
|
||||
void do_MemRegion(MemRegion mr);
|
||||
};
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user