# HG changeset patch # User lana # Date 1409338723 25200 # Node ID 317aad3480c816ecf87c989f3e3bd9ce0b30dd2a # Parent aa7ada31eb77453e6035f22cb55a6f60448f4508# Parent 291708c85e7629a76f415764fae62cc6ab8041ce Merge diff -r aa7ada31eb77 -r 317aad3480c8 .hgtags --- a/.hgtags Fri Aug 29 10:47:32 2014 -0700 +++ b/.hgtags Fri Aug 29 11:58:43 2014 -0700 @@ -269,3 +269,4 @@ d9ce05f36ffec3e5e8af62a92455c1c66a63c320 jdk9-b24 13a5c76976fe48e55c9727c25fae2d2ce7c05da0 jdk9-b25 cd6f4557e7fea5799ff3762ed7a80a743e75d5fd jdk9-b26 +d06a6d3c66c08293b2a9650f3cc01fd55c620e65 jdk9-b27 diff -r aa7ada31eb77 -r 317aad3480c8 .hgtags-top-repo --- a/.hgtags-top-repo Fri Aug 29 10:47:32 2014 -0700 +++ b/.hgtags-top-repo Fri Aug 29 11:58:43 2014 -0700 @@ -269,3 +269,4 @@ 1d4a293fbec19dc2d5790bbb2c7dd0ed8f265484 jdk9-b24 aefd8899a8d6615fb34ba99b2e38996a7145baa8 jdk9-b25 d3ec8d048e6c3c46b6e0ee011cc551ad386dfba5 jdk9-b26 +ba5645f2735b41ed085d07ba20fa7b322afff318 jdk9-b27 diff -r aa7ada31eb77 -r 317aad3480c8 common/autoconf/basics.m4 --- a/common/autoconf/basics.m4 Fri Aug 29 10:47:32 2014 -0700 +++ b/common/autoconf/basics.m4 Fri Aug 29 11:58:43 2014 -0700 @@ -377,7 +377,6 @@ BASIC_REQUIRE_PROGS(CMP, cmp) BASIC_REQUIRE_PROGS(COMM, comm) BASIC_REQUIRE_PROGS(CP, cp) - BASIC_REQUIRE_PROGS(CPIO, cpio) BASIC_REQUIRE_PROGS(CUT, cut) BASIC_REQUIRE_PROGS(DATE, date) BASIC_REQUIRE_PROGS(DIFF, [gdiff diff]) @@ -427,6 +426,7 @@ BASIC_PATH_PROGS(READLINK, [greadlink readlink]) BASIC_PATH_PROGS(DF, df) BASIC_PATH_PROGS(SETFILE, SetFile) + BASIC_PATH_PROGS(CPIO, [cpio bsdcpio]) ]) # Setup basic configuration paths, and platform-specific stuff related to PATHs. @@ -954,7 +954,7 @@ # not be the case in cygwin in certain conditions. AC_DEFUN_ONCE([BASIC_CHECK_SRC_PERMS], [ - if test x"$OPENJDK_BUILD_OS" = xwindows; then + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then file_to_test="$SRC_ROOT/LICENSE" if test `$STAT -c '%a' "$file_to_test"` -lt 400; then AC_MSG_ERROR([Bad file permissions on src files. This is usually caused by cloning the repositories with a non cygwin hg in a directory not created in cygwin.]) diff -r aa7ada31eb77 -r 317aad3480c8 common/autoconf/basics_windows.m4 --- a/common/autoconf/basics_windows.m4 Fri Aug 29 10:47:32 2014 -0700 +++ b/common/autoconf/basics_windows.m4 Fri Aug 29 11:58:43 2014 -0700 @@ -266,6 +266,14 @@ BASIC_WINDOWS_REWRITE_AS_UNIX_PATH(new_path) new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + BASIC_WINDOWS_REWRITE_AS_UNIX_PATH(new_path) + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. diff -r aa7ada31eb77 -r 317aad3480c8 common/autoconf/flags.m4 --- a/common/autoconf/flags.m4 Fri Aug 29 10:47:32 2014 -0700 +++ b/common/autoconf/flags.m4 Fri Aug 29 11:58:43 2014 -0700 @@ -900,7 +900,7 @@ case "${TOOLCHAIN_TYPE}" in microsoft) - CFLAGS_WARNINGS_ARE_ERRORS="/WX" + CFLAGS_WARNINGS_ARE_ERRORS="-WX" ;; solstudio) CFLAGS_WARNINGS_ARE_ERRORS="-errtags -errwarn=%all" diff -r aa7ada31eb77 -r 317aad3480c8 common/autoconf/generated-configure.sh --- a/common/autoconf/generated-configure.sh Fri Aug 29 10:47:32 2014 -0700 +++ b/common/autoconf/generated-configure.sh Fri Aug 29 11:58:43 2014 -0700 @@ -920,12 +920,14 @@ OPENJDK_TARGET_CPU_BITS OPENJDK_TARGET_CPU_ARCH OPENJDK_TARGET_CPU +OPENJDK_TARGET_OS_ENV OPENJDK_TARGET_OS_API OPENJDK_TARGET_OS OPENJDK_BUILD_CPU_ENDIAN OPENJDK_BUILD_CPU_BITS OPENJDK_BUILD_CPU_ARCH OPENJDK_BUILD_CPU +OPENJDK_BUILD_OS_ENV OPENJDK_BUILD_OS_API OPENJDK_BUILD_OS OPENJDK_BUILD_AUTOCONF_NAME @@ -942,6 +944,7 @@ build_vendor build_cpu build +CPIO SETFILE DF READLINK @@ -980,7 +983,6 @@ DIFF DATE CUT -CPIO CP COMM CMP @@ -1120,7 +1122,6 @@ CMP COMM CP -CPIO CUT DATE DIFF @@ -1159,6 +1160,7 @@ READLINK DF SETFILE +CPIO UNZIP ZIP LDD @@ -1990,7 +1992,6 @@ CMP Override default value for CMP COMM Override default value for COMM CP Override default value for CP - CPIO Override default value for CPIO CUT Override default value for CUT DATE Override default value for DATE DIFF Override default value for DIFF @@ -2029,6 +2030,7 @@ 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 LDD Override default value for LDD @@ -4319,7 +4321,7 @@ #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1407143049 +DATE_WHEN_GENERATED=1408448519 ############################################################################### # @@ -5724,199 +5726,6 @@ # Publish this variable in the help. - if test "x$CPIO" = x; then - # The variable is not set by user, try to locate tool using the code snippet - for ac_prog in cpio -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_CPIO+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $CPIO in - [\\/]* | ?:[\\/]*) - ac_cv_path_CPIO="$CPIO" # 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_CPIO="$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 -CPIO=$ac_cv_path_CPIO -if test -n "$CPIO"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPIO" >&5 -$as_echo "$CPIO" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$CPIO" && break -done - - else - # The variable is set, but is it from the command line or the environment? - - # Try to remove the string !CPIO! from our list. - try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!CPIO!/} - 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 "xCPIO" != xBASH; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of CPIO from the environment. Use command line variables instead." >&5 -$as_echo "$as_me: WARNING: Ignoring value of CPIO from the environment. Use command line variables instead." >&2;} - fi - # Try to locate tool using the code snippet - for ac_prog in cpio -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_CPIO+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $CPIO in - [\\/]* | ?:[\\/]*) - ac_cv_path_CPIO="$CPIO" # 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_CPIO="$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 -CPIO=$ac_cv_path_CPIO -if test -n "$CPIO"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPIO" >&5 -$as_echo "$CPIO" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$CPIO" && 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="$CPIO" - 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 CPIO=$tool_basename" >&5 -$as_echo "$as_me: Will search for user supplied tool CPIO=$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_CPIO+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $CPIO in - [\\/]* | ?:[\\/]*) - ac_cv_path_CPIO="$CPIO" # 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_CPIO="$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 -CPIO=$ac_cv_path_CPIO -if test -n "$CPIO"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPIO" >&5 -$as_echo "$CPIO" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - if test "x$CPIO" = 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 CPIO=$tool_specified" >&5 -$as_echo "$as_me: Will use user supplied tool CPIO=$tool_specified" >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CPIO" >&5 -$as_echo_n "checking for CPIO... " >&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 CPIO=$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$CPIO" = x; then - as_fn_error $? "Could not find required tool for CPIO" "$LINENO" 5 - fi - - - - - - # Publish this variable in the help. - - if test "x$CUT" = x; then # The variable is not set by user, try to locate tool using the code snippet for ac_prog in cut @@ -13386,6 +13195,192 @@ + # Publish this variable in the help. + + + if test "x$CPIO" = x; then + # The variable is not set by user, try to locate tool using the code snippet + for ac_prog in cpio bsdcpio +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_CPIO+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $CPIO in + [\\/]* | ?:[\\/]*) + ac_cv_path_CPIO="$CPIO" # 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_CPIO="$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 +CPIO=$ac_cv_path_CPIO +if test -n "$CPIO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPIO" >&5 +$as_echo "$CPIO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CPIO" && break +done + + else + # The variable is set, but is it from the command line or the environment? + + # Try to remove the string !CPIO! from our list. + try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!CPIO!/} + 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 "xCPIO" != xBASH; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of CPIO from the environment. Use command line variables instead." >&5 +$as_echo "$as_me: WARNING: Ignoring value of CPIO from the environment. Use command line variables instead." >&2;} + fi + # Try to locate tool using the code snippet + for ac_prog in cpio bsdcpio +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_CPIO+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $CPIO in + [\\/]* | ?:[\\/]*) + ac_cv_path_CPIO="$CPIO" # 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_CPIO="$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 +CPIO=$ac_cv_path_CPIO +if test -n "$CPIO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPIO" >&5 +$as_echo "$CPIO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CPIO" && 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="$CPIO" + 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 CPIO=$tool_basename" >&5 +$as_echo "$as_me: Will search for user supplied tool CPIO=$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_CPIO+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $CPIO in + [\\/]* | ?:[\\/]*) + ac_cv_path_CPIO="$CPIO" # 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_CPIO="$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 +CPIO=$ac_cv_path_CPIO +if test -n "$CPIO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPIO" >&5 +$as_echo "$CPIO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "x$CPIO" = 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 CPIO=$tool_specified" >&5 +$as_echo "$as_me: Will use user supplied tool CPIO=$tool_specified" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CPIO" >&5 +$as_echo_n "checking for CPIO... " >&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 CPIO=$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 + + + + # Now we can determine OpenJDK build and target platforms. This is required to # have early on. # Make sure we can run config.sub. @@ -13644,6 +13639,7 @@ + { $as_echo "$as_me:${as_lineno-$LINENO}: checking openjdk-build os-cpu" >&5 $as_echo_n "checking openjdk-build os-cpu... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OPENJDK_BUILD_OS-$OPENJDK_BUILD_CPU" >&5 @@ -13775,6 +13771,7 @@ + { $as_echo "$as_me:${as_lineno-$LINENO}: checking openjdk-target os-cpu" >&5 $as_echo_n "checking openjdk-target os-cpu... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OPENJDK_TARGET_OS-$OPENJDK_TARGET_CPU" >&5 @@ -15611,6 +15608,23 @@ new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -15967,6 +15981,23 @@ new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -16320,6 +16351,23 @@ new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -16678,6 +16726,23 @@ new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -17030,6 +17095,23 @@ new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -27493,6 +27575,23 @@ new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -28136,6 +28235,23 @@ new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -28576,6 +28692,23 @@ new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -29842,6 +29975,23 @@ new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -30282,6 +30432,23 @@ new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -31127,6 +31294,23 @@ new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -31525,6 +31709,23 @@ new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -31852,6 +32053,23 @@ new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -32330,6 +32548,23 @@ new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -32941,6 +33176,23 @@ new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -33460,6 +33712,23 @@ new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -33911,6 +34180,23 @@ new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -34235,6 +34521,23 @@ new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -34555,6 +34858,23 @@ new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -34857,6 +35177,23 @@ new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -35311,6 +35648,23 @@ new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -35762,6 +36116,23 @@ new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -36213,6 +36584,23 @@ new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -36665,6 +37053,23 @@ new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -37228,6 +37633,23 @@ new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -37789,6 +38211,23 @@ new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -38359,6 +38798,23 @@ new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -38926,6 +39382,23 @@ new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -39402,6 +39875,23 @@ new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -39853,6 +40343,23 @@ new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -40304,6 +40811,23 @@ new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -42629,7 +43153,7 @@ case "${TOOLCHAIN_TYPE}" in microsoft) - CFLAGS_WARNINGS_ARE_ERRORS="/WX" + CFLAGS_WARNINGS_ARE_ERRORS="-WX" ;; solstudio) CFLAGS_WARNINGS_ARE_ERRORS="-errtags -errwarn=%all" @@ -48711,12 +49235,22 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: checking found msvcr100.dll architecture" >&5 $as_echo_n "checking found msvcr100.dll architecture... " >&6; } MSVCR_DLL_FILETYPE=`$FILE -b "$POSSIBLE_MSVCR_DLL"` - if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then - CORRECT_MSVCR_ARCH=386 - else - CORRECT_MSVCR_ARCH=x86-64 - fi - if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP $CORRECT_MSVCR_ARCH 2>&1 > /dev/null; then + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + # The MSYS 'file' command returns "PE32 executable for MS Windows (DLL) (GUI) Intel 80386 32-bit" + # on x32 and "PE32+ executable for MS Windows (DLL) (GUI) Mono/.Net assembly" on x64 systems. + if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then + CORRECT_MSVCR_ARCH="PE32 executable" + else + CORRECT_MSVCR_ARCH="PE32+ executable" + fi + else + if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then + CORRECT_MSVCR_ARCH=386 + else + CORRECT_MSVCR_ARCH=x86-64 + fi + fi + if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP "$CORRECT_MSVCR_ARCH" 2>&1 > /dev/null; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } MSVCR_DLL="$POSSIBLE_MSVCR_DLL" @@ -48767,12 +49301,22 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: checking found msvcr100.dll architecture" >&5 $as_echo_n "checking found msvcr100.dll architecture... " >&6; } MSVCR_DLL_FILETYPE=`$FILE -b "$POSSIBLE_MSVCR_DLL"` - if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then - CORRECT_MSVCR_ARCH=386 - else - CORRECT_MSVCR_ARCH=x86-64 - fi - if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP $CORRECT_MSVCR_ARCH 2>&1 > /dev/null; then + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + # The MSYS 'file' command returns "PE32 executable for MS Windows (DLL) (GUI) Intel 80386 32-bit" + # on x32 and "PE32+ executable for MS Windows (DLL) (GUI) Mono/.Net assembly" on x64 systems. + if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then + CORRECT_MSVCR_ARCH="PE32 executable" + else + CORRECT_MSVCR_ARCH="PE32+ executable" + fi + else + if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then + CORRECT_MSVCR_ARCH=386 + else + CORRECT_MSVCR_ARCH=x86-64 + fi + fi + if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP "$CORRECT_MSVCR_ARCH" 2>&1 > /dev/null; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } MSVCR_DLL="$POSSIBLE_MSVCR_DLL" @@ -48805,12 +49349,22 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: checking found msvcr100.dll architecture" >&5 $as_echo_n "checking found msvcr100.dll architecture... " >&6; } MSVCR_DLL_FILETYPE=`$FILE -b "$POSSIBLE_MSVCR_DLL"` - if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then - CORRECT_MSVCR_ARCH=386 - else - CORRECT_MSVCR_ARCH=x86-64 - fi - if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP $CORRECT_MSVCR_ARCH 2>&1 > /dev/null; then + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + # The MSYS 'file' command returns "PE32 executable for MS Windows (DLL) (GUI) Intel 80386 32-bit" + # on x32 and "PE32+ executable for MS Windows (DLL) (GUI) Mono/.Net assembly" on x64 systems. + if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then + CORRECT_MSVCR_ARCH="PE32 executable" + else + CORRECT_MSVCR_ARCH="PE32+ executable" + fi + else + if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then + CORRECT_MSVCR_ARCH=386 + else + CORRECT_MSVCR_ARCH=x86-64 + fi + fi + if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP "$CORRECT_MSVCR_ARCH" 2>&1 > /dev/null; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } MSVCR_DLL="$POSSIBLE_MSVCR_DLL" @@ -48853,12 +49407,22 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: checking found msvcr100.dll architecture" >&5 $as_echo_n "checking found msvcr100.dll architecture... " >&6; } MSVCR_DLL_FILETYPE=`$FILE -b "$POSSIBLE_MSVCR_DLL"` - if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then - CORRECT_MSVCR_ARCH=386 - else - CORRECT_MSVCR_ARCH=x86-64 - fi - if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP $CORRECT_MSVCR_ARCH 2>&1 > /dev/null; then + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + # The MSYS 'file' command returns "PE32 executable for MS Windows (DLL) (GUI) Intel 80386 32-bit" + # on x32 and "PE32+ executable for MS Windows (DLL) (GUI) Mono/.Net assembly" on x64 systems. + if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then + CORRECT_MSVCR_ARCH="PE32 executable" + else + CORRECT_MSVCR_ARCH="PE32+ executable" + fi + else + if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then + CORRECT_MSVCR_ARCH=386 + else + CORRECT_MSVCR_ARCH=x86-64 + fi + fi + if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP "$CORRECT_MSVCR_ARCH" 2>&1 > /dev/null; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } MSVCR_DLL="$POSSIBLE_MSVCR_DLL" @@ -48906,12 +49470,22 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: checking found msvcr100.dll architecture" >&5 $as_echo_n "checking found msvcr100.dll architecture... " >&6; } MSVCR_DLL_FILETYPE=`$FILE -b "$POSSIBLE_MSVCR_DLL"` - if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then - CORRECT_MSVCR_ARCH=386 - else - CORRECT_MSVCR_ARCH=x86-64 - fi - if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP $CORRECT_MSVCR_ARCH 2>&1 > /dev/null; then + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + # The MSYS 'file' command returns "PE32 executable for MS Windows (DLL) (GUI) Intel 80386 32-bit" + # on x32 and "PE32+ executable for MS Windows (DLL) (GUI) Mono/.Net assembly" on x64 systems. + if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then + CORRECT_MSVCR_ARCH="PE32 executable" + else + CORRECT_MSVCR_ARCH="PE32+ executable" + fi + else + if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then + CORRECT_MSVCR_ARCH=386 + else + CORRECT_MSVCR_ARCH=x86-64 + fi + fi + if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP "$CORRECT_MSVCR_ARCH" 2>&1 > /dev/null; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } MSVCR_DLL="$POSSIBLE_MSVCR_DLL" @@ -48955,12 +49529,22 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: checking found msvcr100.dll architecture" >&5 $as_echo_n "checking found msvcr100.dll architecture... " >&6; } MSVCR_DLL_FILETYPE=`$FILE -b "$POSSIBLE_MSVCR_DLL"` - if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then - CORRECT_MSVCR_ARCH=386 - else - CORRECT_MSVCR_ARCH=x86-64 - fi - if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP $CORRECT_MSVCR_ARCH 2>&1 > /dev/null; then + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + # The MSYS 'file' command returns "PE32 executable for MS Windows (DLL) (GUI) Intel 80386 32-bit" + # on x32 and "PE32+ executable for MS Windows (DLL) (GUI) Mono/.Net assembly" on x64 systems. + if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then + CORRECT_MSVCR_ARCH="PE32 executable" + else + CORRECT_MSVCR_ARCH="PE32+ executable" + fi + else + if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then + CORRECT_MSVCR_ARCH=386 + else + CORRECT_MSVCR_ARCH=x86-64 + fi + fi + if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP "$CORRECT_MSVCR_ARCH" 2>&1 > /dev/null; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } MSVCR_DLL="$POSSIBLE_MSVCR_DLL" @@ -49903,7 +50487,7 @@ # Check for some common pitfalls - if test x"$OPENJDK_BUILD_OS" = xwindows; then + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then file_to_test="$SRC_ROOT/LICENSE" if test `$STAT -c '%a' "$file_to_test"` -lt 400; then as_fn_error $? "Bad file permissions on src files. This is usually caused by cloning the repositories with a non cygwin hg in a directory not created in cygwin." "$LINENO" 5 diff -r aa7ada31eb77 -r 317aad3480c8 common/autoconf/platform.m4 --- a/common/autoconf/platform.m4 Fri Aug 29 10:47:32 2014 -0700 +++ b/common/autoconf/platform.m4 Fri Aug 29 11:58:43 2014 -0700 @@ -173,6 +173,7 @@ OPENJDK_BUILD_CPU_ENDIAN="$VAR_CPU_ENDIAN" AC_SUBST(OPENJDK_BUILD_OS) AC_SUBST(OPENJDK_BUILD_OS_API) + AC_SUBST(OPENJDK_BUILD_OS_ENV) AC_SUBST(OPENJDK_BUILD_CPU) AC_SUBST(OPENJDK_BUILD_CPU_ARCH) AC_SUBST(OPENJDK_BUILD_CPU_BITS) @@ -194,6 +195,7 @@ OPENJDK_TARGET_CPU_ENDIAN="$VAR_CPU_ENDIAN" AC_SUBST(OPENJDK_TARGET_OS) AC_SUBST(OPENJDK_TARGET_OS_API) + AC_SUBST(OPENJDK_TARGET_OS_ENV) AC_SUBST(OPENJDK_TARGET_CPU) AC_SUBST(OPENJDK_TARGET_CPU_ARCH) AC_SUBST(OPENJDK_TARGET_CPU_BITS) diff -r aa7ada31eb77 -r 317aad3480c8 common/autoconf/spec.gmk.in --- a/common/autoconf/spec.gmk.in Fri Aug 29 10:47:32 2014 -0700 +++ b/common/autoconf/spec.gmk.in Fri Aug 29 11:58:43 2014 -0700 @@ -106,6 +106,7 @@ # When not cross-compiling, it is the same as the target. OPENJDK_BUILD_OS:=@OPENJDK_BUILD_OS@ OPENJDK_BUILD_OS_API:=@OPENJDK_BUILD_OS_API@ +OPENJDK_BUILD_OS_ENV:=@OPENJDK_BUILD_OS_ENV@ OPENJDK_BUILD_CPU:=@OPENJDK_BUILD_CPU@ OPENJDK_BUILD_CPU_ARCH:=@OPENJDK_BUILD_CPU_ARCH@ diff -r aa7ada31eb77 -r 317aad3480c8 common/autoconf/toolchain_windows.m4 --- a/common/autoconf/toolchain_windows.m4 Fri Aug 29 10:47:32 2014 -0700 +++ b/common/autoconf/toolchain_windows.m4 Fri Aug 29 11:58:43 2014 -0700 @@ -244,12 +244,22 @@ # Need to check if the found msvcr is correct architecture AC_MSG_CHECKING([found msvcr100.dll architecture]) MSVCR_DLL_FILETYPE=`$FILE -b "$POSSIBLE_MSVCR_DLL"` - if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then - CORRECT_MSVCR_ARCH=386 + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + # The MSYS 'file' command returns "PE32 executable for MS Windows (DLL) (GUI) Intel 80386 32-bit" + # on x32 and "PE32+ executable for MS Windows (DLL) (GUI) Mono/.Net assembly" on x64 systems. + if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then + CORRECT_MSVCR_ARCH="PE32 executable" + else + CORRECT_MSVCR_ARCH="PE32+ executable" + fi else - CORRECT_MSVCR_ARCH=x86-64 + if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then + CORRECT_MSVCR_ARCH=386 + else + CORRECT_MSVCR_ARCH=x86-64 + fi fi - if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP $CORRECT_MSVCR_ARCH 2>&1 > /dev/null; then + if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP "$CORRECT_MSVCR_ARCH" 2>&1 > /dev/null; then AC_MSG_RESULT([ok]) MSVCR_DLL="$POSSIBLE_MSVCR_DLL" AC_MSG_CHECKING([for msvcr100.dll]) diff -r aa7ada31eb77 -r 317aad3480c8 corba/.hgtags --- a/corba/.hgtags Fri Aug 29 10:47:32 2014 -0700 +++ b/corba/.hgtags Fri Aug 29 11:58:43 2014 -0700 @@ -269,3 +269,4 @@ 8a44142bb7fc8118f70f91a1b97c12dfc50563ee jdk9-b24 da08cca6b97f41b7081a3e176dcb400af6e4bb26 jdk9-b25 6c777df597bbf5abba3488d44c401edfe73c74af jdk9-b26 +7e06bf1dcb0907b80ddf59315426ce9ce775e56d jdk9-b27 diff -r aa7ada31eb77 -r 317aad3480c8 corba/src/java.corba/share/classes/org/omg/CORBA/FloatSeqHelper.java --- a/corba/src/java.corba/share/classes/org/omg/CORBA/FloatSeqHelper.java Fri Aug 29 10:47:32 2014 -0700 +++ b/corba/src/java.corba/share/classes/org/omg/CORBA/FloatSeqHelper.java Fri Aug 29 11:58:43 2014 -0700 @@ -38,11 +38,11 @@ * OMG specifications : * */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/.hgtags --- a/hotspot/.hgtags Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/.hgtags Fri Aug 29 11:58:43 2014 -0700 @@ -429,3 +429,4 @@ dde2d03b0ea46a27650839e3a1d212c7c1f7b4c8 jdk9-b24 6de94e8693240cec8aae11f6b42f43433456a733 jdk9-b25 48b95a073d752d6891cc0d1d2836b321ecf3ce0c jdk9-b26 +f95347244306affc32ce3056f27ceff7b2100810 jdk9-b27 diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/agent/src/os/solaris/proc/saproc.cpp --- a/hotspot/agent/src/os/solaris/proc/saproc.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/agent/src/os/solaris/proc/saproc.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -314,7 +314,7 @@ handle = dlopen(name, mode); } if (_libsaproc_debug) { - printf("libsaproc DEBUG: pathmap_dlopen %s return 0x%x\n", name, handle); + printf("libsaproc DEBUG: pathmap_dlopen %s return 0x%lx\n", name, (unsigned long) handle); } return handle; } @@ -661,30 +661,30 @@ // read FileMapHeader size_t n = read(fd, pheader, sizeof(struct FileMapHeader)); if (n != sizeof(struct FileMapHeader)) { - free(pheader); - close(fd); char errMsg[ERR_MSG_SIZE]; sprintf(errMsg, "unable to read shared archive file map header from %s", classes_jsa); + close(fd); + free(pheader); THROW_NEW_DEBUGGER_EXCEPTION_(errMsg, 1); } // check file magic if (pheader->_magic != 0xf00baba2) { - free(pheader); - close(fd); char errMsg[ERR_MSG_SIZE]; sprintf(errMsg, "%s has bad shared archive magic 0x%x, expecting 0xf00baba2", classes_jsa, pheader->_magic); + close(fd); + free(pheader); THROW_NEW_DEBUGGER_EXCEPTION_(errMsg, 1); } // check version if (pheader->_version != CURRENT_ARCHIVE_VERSION) { - free(pheader); - close(fd); char errMsg[ERR_MSG_SIZE]; sprintf(errMsg, "%s has wrong shared archive version %d, expecting %d", classes_jsa, pheader->_version, CURRENT_ARCHIVE_VERSION); + close(fd); + free(pheader); THROW_NEW_DEBUGGER_EXCEPTION_(errMsg, 1); } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/make/excludeSrc.make --- a/hotspot/make/excludeSrc.make Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/make/excludeSrc.make Fri Aug 29 11:58:43 2014 -0700 @@ -119,8 +119,8 @@ CFLAGS += -DINCLUDE_NMT=0 Src_Files_EXCLUDE += \ - memBaseline.cpp memPtr.cpp memRecorder.cpp memReporter.cpp memSnapshot.cpp memTrackWorker.cpp \ - memTracker.cpp nmtDCmd.cpp + memBaseline.cpp memReporter.cpp mallocTracker.cpp virtualMemoryTracker.cpp nmtCommon.cpp \ + memTracker.cpp nmtDCmd.cpp mallocSiteTable.cpp endif -include $(HS_ALT_MAKE)/excludeSrc.make diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/make/jprt.properties --- a/hotspot/make/jprt.properties Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/make/jprt.properties Fri Aug 29 11:58:43 2014 -0700 @@ -356,14 +356,15 @@ ${jprt.my.windows.x64}-fastdebug-c2-internalvmtests jprt.make.rule.test.targets.standard.reg.group = \ - ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GROUP, \ - ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GROUP, \ - ${jprt.my.linux.i586}-{product|fastdebug}-c2-GROUP, \ - ${jprt.my.linux.x64}-{product|fastdebug}-c2-GROUP, \ - ${jprt.my.windows.i586}-{product|fastdebug}-c2-GROUP, \ - ${jprt.my.windows.x64}-{product|fastdebug}-c2-GROUP, \ - ${jprt.my.linux.i586}-{product|fastdebug}-c1-GROUP, \ - ${jprt.my.windows.i586}-{product|fastdebug}-c1-GROUP + ${jprt.my.solaris.sparcv9}-fastdebug-c2-GROUP, \ + ${jprt.my.solaris.x64}-fastdebug-c2-GROUP, \ + ${jprt.my.linux.i586}-fastdebug-c2-GROUP, \ + ${jprt.my.linux.x64}-fastdebug-c2-GROUP, \ + ${jprt.my.macosx.x64}-fastdebug-c2-GROUP, \ + ${jprt.my.windows.i586}-fastdebug-c2-GROUP, \ + ${jprt.my.windows.x64}-fastdebug-c2-GROUP, \ + ${jprt.my.linux.i586}-fastdebug-c1-GROUP, \ + ${jprt.my.windows.i586}-fastdebug-c1-GROUP jprt.make.rule.test.targets.standard = \ ${jprt.make.rule.test.targets.standard.client}, \ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/make/solaris/makefiles/dtrace.make --- a/hotspot/make/solaris/makefiles/dtrace.make Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/make/solaris/makefiles/dtrace.make Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 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 @@ -58,6 +58,8 @@ DTRACE_COMMON_SRCDIR = $(GAMMADIR)/src/os/posix/dtrace DTRACE = dtrace DTRACE.o = $(DTRACE).o +DTRACE_JHELPER = dtrace_jhelper +DTRACE_JHELPER.o = $(DTRACE_JHELPER).o # to remove '-g' option which causes link problems # also '-z nodefs' is used as workaround @@ -255,7 +257,10 @@ endif $(DTRACE).d: $(DTRACE_COMMON_SRCDIR)/hotspot.d $(DTRACE_COMMON_SRCDIR)/hotspot_jni.d \ - $(DTRACE_COMMON_SRCDIR)/hs_private.d $(DTRACE_SRCDIR)/jhelper.d + $(DTRACE_COMMON_SRCDIR)/hs_private.d + $(QUIETLY) cat $^ > $@ + +$(DTRACE_JHELPER).d: $(DTRACE_SRCDIR)/jhelper.d $(QUIETLY) cat $^ > $@ DTraced_Files = ciEnv.o \ @@ -280,7 +285,7 @@ vmGCOperations.o \ # Dtrace is available, so we build $(DTRACE.o) -$(DTRACE.o): $(DTRACE).d $(JVMOFFS).h $(JVMOFFS)Index.h $(DTraced_Files) +$(DTRACE.o): $(DTRACE).d $(DTraced_Files) @echo Compiling $(DTRACE).d $(QUIETLY) $(DTRACE_PROG) $(DTRACE_OPTS) -C -I. -G -xlazyload -o $@ -s $(DTRACE).d \ @@ -344,6 +349,11 @@ dtrace_gen_headers: $(DtraceOutDir)/hotspot.h $(DtraceOutDir)/hotspot_jni.h $(DtraceOutDir)/hs_private.h +# The jhelper.d and hotspot probes are separated into two different SUNW_dof sections. +# Now the jhelper.d is built without the -Xlazyload flag. +$(DTRACE_JHELPER.o) : $(DTRACE_JHELPER).d $(JVMOFFS).h $(JVMOFFS)Index.h + @echo Compiling $(DTRACE_JHELPER).d + $(QUIETLY) $(DTRACE_PROG) $(DTRACE_OPTS) -C -I. -G -o $@ -s $(DTRACE_JHELPER).d .PHONY: dtraceCheck @@ -372,7 +382,7 @@ ifneq ("${DTRACE_PROG}", "") ifeq ("${HOTSPOT_DISABLE_DTRACE_PROBES}", "") -DTRACE_OBJS = $(DTRACE.o) $(JVMOFFS.o) +DTRACE_OBJS = $(DTRACE.o) $(JVMOFFS.o) $(DTRACE_JHELPER.o) CFLAGS += $(DTRACE_INCL) -DDTRACE_ENABLED MAPFILE_DTRACE_OPT = $(MAPFILE_DTRACE) diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/cpu/ppc/vm/assembler_ppc.hpp --- a/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -298,6 +298,7 @@ LWZ_OPCODE = (32u << OPCODE_SHIFT), LWZX_OPCODE = (31u << OPCODE_SHIFT | 23u << 1), LWZU_OPCODE = (33u << OPCODE_SHIFT), + LWBRX_OPCODE = (31u << OPCODE_SHIFT | 534 << 1), LHA_OPCODE = (42u << OPCODE_SHIFT), LHAX_OPCODE = (31u << OPCODE_SHIFT | 343u << 1), @@ -306,6 +307,7 @@ LHZ_OPCODE = (40u << OPCODE_SHIFT), LHZX_OPCODE = (31u << OPCODE_SHIFT | 279u << 1), LHZU_OPCODE = (41u << OPCODE_SHIFT), + LHBRX_OPCODE = (31u << OPCODE_SHIFT | 790 << 1), LBZ_OPCODE = (34u << OPCODE_SHIFT), LBZX_OPCODE = (31u << OPCODE_SHIFT | 87u << 1), @@ -1364,11 +1366,17 @@ inline void lwax( Register d, Register s1, Register s2); inline void lwa( Register d, int si16, Register s1); + // 4 bytes reversed + inline void lwbrx( Register d, Register s1, Register s2); + // 2 bytes inline void lhzx( Register d, Register s1, Register s2); inline void lhz( Register d, int si16, Register s1); inline void lhzu( Register d, int si16, Register s1); + // 2 bytes reversed + inline void lhbrx( Register d, Register s1, Register s2); + // 2 bytes inline void lhax( Register d, Register s1, Register s2); inline void lha( Register d, int si16, Register s1); @@ -1858,10 +1866,12 @@ inline void lwz( Register d, int si16); inline void lwax( Register d, Register s2); inline void lwa( Register d, int si16); + inline void lwbrx(Register d, Register s2); inline void lhzx( Register d, Register s2); inline void lhz( Register d, int si16); inline void lhax( Register d, Register s2); inline void lha( Register d, int si16); + inline void lhbrx(Register d, Register s2); inline void lbzx( Register d, Register s2); inline void lbz( Register d, int si16); inline void ldx( Register d, Register s2); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp --- a/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -263,10 +263,14 @@ inline void Assembler::lwax( Register d, Register s1, Register s2) { emit_int32(LWAX_OPCODE | rt(d) | ra0mem(s1) | rb(s2));} inline void Assembler::lwa( Register d, int si16, Register s1) { emit_int32(LWA_OPCODE | rt(d) | ds(si16) | ra0mem(s1));} +inline void Assembler::lwbrx( Register d, Register s1, Register s2) { emit_int32(LWBRX_OPCODE | rt(d) | ra0mem(s1) | rb(s2));} + inline void Assembler::lhzx( Register d, Register s1, Register s2) { emit_int32(LHZX_OPCODE | rt(d) | ra0mem(s1) | rb(s2));} inline void Assembler::lhz( Register d, int si16, Register s1) { emit_int32(LHZ_OPCODE | rt(d) | d1(si16) | ra0mem(s1));} inline void Assembler::lhzu( Register d, int si16, Register s1) { assert(d != s1, "according to ibm manual"); emit_int32(LHZU_OPCODE | rt(d) | d1(si16) | rta0mem(s1));} +inline void Assembler::lhbrx( Register d, Register s1, Register s2) { emit_int32(LHBRX_OPCODE | rt(d) | ra0mem(s1) | rb(s2));} + inline void Assembler::lhax( Register d, Register s1, Register s2) { emit_int32(LHAX_OPCODE | rt(d) | ra0mem(s1) | rb(s2));} inline void Assembler::lha( Register d, int si16, Register s1) { emit_int32(LHA_OPCODE | rt(d) | d1(si16) | ra0mem(s1));} inline void Assembler::lhau( Register d, int si16, Register s1) { assert(d != s1, "according to ibm manual"); emit_int32(LHAU_OPCODE | rt(d) | d1(si16) | rta0mem(s1));} @@ -736,10 +740,12 @@ inline void Assembler::lwz( Register d, int si16 ) { emit_int32( LWZ_OPCODE | rt(d) | d1(si16));} inline void Assembler::lwax( Register d, Register s2) { emit_int32( LWAX_OPCODE | rt(d) | rb(s2));} inline void Assembler::lwa( Register d, int si16 ) { emit_int32( LWA_OPCODE | rt(d) | ds(si16));} +inline void Assembler::lwbrx(Register d, Register s2) { emit_int32( LWBRX_OPCODE| rt(d) | rb(s2));} inline void Assembler::lhzx( Register d, Register s2) { emit_int32( LHZX_OPCODE | rt(d) | rb(s2));} inline void Assembler::lhz( Register d, int si16 ) { emit_int32( LHZ_OPCODE | rt(d) | d1(si16));} inline void Assembler::lhax( Register d, Register s2) { emit_int32( LHAX_OPCODE | rt(d) | rb(s2));} inline void Assembler::lha( Register d, int si16 ) { emit_int32( LHA_OPCODE | rt(d) | d1(si16));} +inline void Assembler::lhbrx(Register d, Register s2) { emit_int32( LHBRX_OPCODE| rt(d) | rb(s2));} inline void Assembler::lbzx( Register d, Register s2) { emit_int32( LBZX_OPCODE | rt(d) | rb(s2));} inline void Assembler::lbz( Register d, int si16 ) { emit_int32( LBZ_OPCODE | rt(d) | d1(si16));} inline void Assembler::ld( Register d, int si16 ) { emit_int32( LD_OPCODE | rt(d) | ds(si16));} diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/cpu/ppc/vm/cppInterpreterGenerator_ppc.hpp --- a/hotspot/src/cpu/ppc/vm/cppInterpreterGenerator_ppc.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/cpu/ppc/vm/cppInterpreterGenerator_ppc.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright 2012, 2013 SAP AG. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -26,8 +26,9 @@ #ifndef CPU_PPC_VM_CPPINTERPRETERGENERATOR_PPC_HPP #define CPU_PPC_VM_CPPINTERPRETERGENERATOR_PPC_HPP - address generate_normal_entry(void); - address generate_native_entry(void); + address generate_normal_entry(bool synchronized); + address generate_native_entry(bool synchronized); + address generate_math_entry(AbstractInterpreter::MethodKind kind) { return NULL; } void lock_method(void); void unlock_method(void); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/cpu/ppc/vm/cppInterpreter_ppc.cpp --- a/hotspot/src/cpu/ppc/vm/cppInterpreter_ppc.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/cpu/ppc/vm/cppInterpreter_ppc.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -938,8 +938,9 @@ // Interpreter stub for calling a native method. (C++ interpreter) // This sets up a somewhat different looking stack for calling the native method // than the typical interpreter frame setup. +// The synchronized parameter is ignored. // -address CppInterpreterGenerator::generate_native_entry(void) { +address CppInterpreterGenerator::generate_native_entry(bool synchronized) { if (native_entry != NULL) return native_entry; address entry = __ pc(); @@ -1729,7 +1730,8 @@ __ std(R0, BasicObjectLock::obj_offset_in_bytes(), stack_base); // Mark lock as unused } -address CppInterpreterGenerator::generate_normal_entry(void) { +// The synchronized parameter is ignored +address CppInterpreterGenerator::generate_normal_entry(bool synchronized) { if (interpreter_frame_manager != NULL) return interpreter_frame_manager; address entry = __ pc(); @@ -2789,38 +2791,6 @@ return interpreter_frame_manager; } -// Generate code for various sorts of method entries -// -address AbstractInterpreterGenerator::generate_method_entry(AbstractInterpreter::MethodKind kind) { - address entry_point = NULL; - - switch (kind) { - case Interpreter::zerolocals : break; - case Interpreter::zerolocals_synchronized : break; - case Interpreter::native : // Fall thru - case Interpreter::native_synchronized : entry_point = ((CppInterpreterGenerator*)this)->generate_native_entry(); break; - case Interpreter::empty : break; - case Interpreter::accessor : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry(); break; - case Interpreter::abstract : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry(); break; - // These are special interpreter intrinsics which we don't support so far. - case Interpreter::java_lang_math_sin : break; - case Interpreter::java_lang_math_cos : break; - case Interpreter::java_lang_math_tan : break; - case Interpreter::java_lang_math_abs : break; - case Interpreter::java_lang_math_log : break; - case Interpreter::java_lang_math_log10 : break; - case Interpreter::java_lang_math_sqrt : break; - case Interpreter::java_lang_math_pow : break; - case Interpreter::java_lang_math_exp : break; - case Interpreter::java_lang_ref_reference_get: entry_point = ((InterpreterGenerator*)this)->generate_Reference_get_entry(); break; - default : ShouldNotReachHere(); break; - } - - if (entry_point) { - return entry_point; - } - return ((InterpreterGenerator*)this)->generate_normal_entry(); -} InterpreterGenerator::InterpreterGenerator(StubQueue* code) : CppInterpreterGenerator(code) { diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp --- a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -119,9 +119,15 @@ // Call the Interpreter::remove_activation_preserving_args_entry() // func to get the address of the same-named entrypoint in the // generated interpreter code. +#if defined(ABI_ELFv2) + call_c(CAST_FROM_FN_PTR(address, + Interpreter::remove_activation_preserving_args_entry), + relocInfo::none); +#else call_c(CAST_FROM_FN_PTR(FunctionDescriptor*, Interpreter::remove_activation_preserving_args_entry), relocInfo::none); +#endif // Jump to Interpreter::_remove_activation_preserving_args_entry. mtctr(R3_RET); @@ -331,29 +337,40 @@ void InterpreterMacroAssembler::get_2_byte_integer_at_bcp(int bcp_offset, Register Rdst, signedOrNot is_signed) { +#if defined(VM_LITTLE_ENDIAN) + if (bcp_offset) { + load_const_optimized(Rdst, bcp_offset); + lhbrx(Rdst, R14_bcp, Rdst); + } else { + lhbrx(Rdst, R14_bcp); + } + if (is_signed == Signed) { + extsh(Rdst, Rdst); + } +#else // Read Java big endian format. if (is_signed == Signed) { lha(Rdst, bcp_offset, R14_bcp); } else { lhz(Rdst, bcp_offset, R14_bcp); } -#if 0 - assert(Rtmp != Rdst, "need separate temp register"); - Register Rfirst = Rtmp; - lbz(Rfirst, bcp_offset, R14_bcp); // first byte - lbz(Rdst, bcp_offset+1, R14_bcp); // second byte - - // Rdst = ((Rfirst<<8) & 0xFF00) | (Rdst &~ 0xFF00) - rldimi(/*RA=*/Rdst, /*RS=*/Rfirst, /*sh=*/8, /*mb=*/48); - if (is_signed == Signed) { - extsh(Rdst, Rdst); - } #endif } void InterpreterMacroAssembler::get_4_byte_integer_at_bcp(int bcp_offset, Register Rdst, signedOrNot is_signed) { +#if defined(VM_LITTLE_ENDIAN) + if (bcp_offset) { + load_const_optimized(Rdst, bcp_offset); + lwbrx(Rdst, R14_bcp, Rdst); + } else { + lwbrx(Rdst, R14_bcp); + } + if (is_signed == Signed) { + extsw(Rdst, Rdst); + } +#else // Read Java big endian format. if (bcp_offset & 3) { // Offset unaligned? load_const_optimized(Rdst, bcp_offset); @@ -369,18 +386,26 @@ lwz(Rdst, bcp_offset, R14_bcp); } } +#endif } + // Load the constant pool cache index from the bytecode stream. // // Kills / writes: // - Rdst, Rscratch void InterpreterMacroAssembler::get_cache_index_at_bcp(Register Rdst, int bcp_offset, size_t index_size) { assert(bcp_offset > 0, "bcp is still pointing to start of bytecode"); + // Cache index is always in the native format, courtesy of Rewriter. if (index_size == sizeof(u2)) { - get_2_byte_integer_at_bcp(bcp_offset, Rdst, Unsigned); + lhz(Rdst, bcp_offset, R14_bcp); } else if (index_size == sizeof(u4)) { - get_4_byte_integer_at_bcp(bcp_offset, Rdst, Signed); + if (bcp_offset & 3) { + load_const_optimized(Rdst, bcp_offset); + lwax(Rdst, R14_bcp, Rdst); + } else { + lwa(Rdst, bcp_offset, R14_bcp); + } assert(ConstantPool::decode_invokedynamic_index(~123) == 123, "else change next line"); nand(Rdst, Rdst, Rdst); // convert to plain index } else if (index_size == sizeof(u1)) { @@ -397,6 +422,29 @@ add(cache, R27_constPoolCache, cache); } +// Load 4-byte signed or unsigned integer in Java format (that is, big-endian format) +// from (Rsrc)+offset. +void InterpreterMacroAssembler::get_u4(Register Rdst, Register Rsrc, int offset, + signedOrNot is_signed) { +#if defined(VM_LITTLE_ENDIAN) + if (offset) { + load_const_optimized(Rdst, offset); + lwbrx(Rdst, Rdst, Rsrc); + } else { + lwbrx(Rdst, Rsrc); + } + if (is_signed == Signed) { + extsw(Rdst, Rdst); + } +#else + if (is_signed == Signed) { + lwa(Rdst, offset, Rsrc); + } else { + lwz(Rdst, offset, Rsrc); + } +#endif +} + // Load object from cpool->resolved_references(index). void InterpreterMacroAssembler::load_resolved_reference_at_index(Register result, Register index) { assert_different_registers(result, index); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp --- a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -130,6 +130,7 @@ void get_cache_and_index_at_bcp(Register cache, int bcp_offset, size_t index_size = sizeof(u2)); + void get_u4(Register Rdst, Register Rsrc, int offset, signedOrNot is_signed); // common code diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/cpu/ppc/vm/interpreterGenerator_ppc.hpp --- a/hotspot/src/cpu/ppc/vm/interpreterGenerator_ppc.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/cpu/ppc/vm/interpreterGenerator_ppc.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright 2012, 2013 SAP AG. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -31,7 +31,12 @@ private: address generate_abstract_entry(void); - address generate_accessor_entry(void); + address generate_jump_to_normal_entry(void); + address generate_accessor_entry(void) { return generate_jump_to_normal_entry(); } + address generate_empty_entry(void) { return generate_jump_to_normal_entry(); } address generate_Reference_get_entry(void); + // Not supported + address generate_CRC32_update_entry() { return NULL; } + address generate_CRC32_updateBytes_entry(AbstractInterpreter::MethodKind kind) { return NULL; } #endif // CPU_PPC_VM_INTERPRETERGENERATOR_PPC_HPP diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/cpu/ppc/vm/interpreter_ppc.cpp --- a/hotspot/src/cpu/ppc/vm/interpreter_ppc.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/cpu/ppc/vm/interpreter_ppc.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -428,6 +428,19 @@ return entry; } + +// Call an accessor method (assuming it is resolved, otherwise drop into +// vanilla (slow path) entry. +address InterpreterGenerator::generate_jump_to_normal_entry(void) { + address entry = __ pc(); + address normal_entry = Interpreter::entry_for_kind(Interpreter::zerolocals); + assert(normal_entry != NULL, "should already be generated."); + __ branch_to_entry(normal_entry, R11_scratch1); + __ flush(); + + return entry; +} + // Abstract method entry. // address InterpreterGenerator::generate_abstract_entry(void) { @@ -485,203 +498,6 @@ return entry; } -// Call an accessor method (assuming it is resolved, otherwise drop into -// vanilla (slow path) entry. -address InterpreterGenerator::generate_accessor_entry(void) { - if (!UseFastAccessorMethods && (!FLAG_IS_ERGO(UseFastAccessorMethods))) { - return NULL; - } - - Label Lslow_path, Lacquire; - - const Register - Rclass_or_obj = R3_ARG1, - Rconst_method = R4_ARG2, - Rcodes = Rconst_method, - Rcpool_cache = R5_ARG3, - Rscratch = R11_scratch1, - Rjvmti_mode = Rscratch, - Roffset = R12_scratch2, - Rflags = R6_ARG4, - Rbtable = R7_ARG5; - - static address branch_table[number_of_states]; - - address entry = __ pc(); - - // Check for safepoint: - // Ditch this, real man don't need safepoint checks. - - // Also check for JVMTI mode - // Check for null obj, take slow path if so. - __ ld(Rclass_or_obj, Interpreter::stackElementSize, CC_INTERP_ONLY(R17_tos) NOT_CC_INTERP(R15_esp)); - __ lwz(Rjvmti_mode, thread_(interp_only_mode)); - __ cmpdi(CCR1, Rclass_or_obj, 0); - __ cmpwi(CCR0, Rjvmti_mode, 0); - __ crorc(/*CCR0 eq*/2, /*CCR1 eq*/4+2, /*CCR0 eq*/2); - __ beq(CCR0, Lslow_path); // this==null or jvmti_mode!=0 - - // Do 2 things in parallel: - // 1. Load the index out of the first instruction word, which looks like this: - // <0x2a><0xb4>. - // 2. Load constant pool cache base. - __ ld(Rconst_method, in_bytes(Method::const_offset()), R19_method); - __ ld(Rcpool_cache, in_bytes(ConstMethod::constants_offset()), Rconst_method); - - __ lhz(Rcodes, in_bytes(ConstMethod::codes_offset()) + 2, Rconst_method); // Lower half of 32 bit field. - __ ld(Rcpool_cache, ConstantPool::cache_offset_in_bytes(), Rcpool_cache); - - // Get the const pool entry by means of . - const int codes_shift = exact_log2(in_words(ConstantPoolCacheEntry::size()) * BytesPerWord); - __ slwi(Rscratch, Rcodes, codes_shift); // (codes&0xFFFF)<print_cr("accessor_entry: branch_table[%d] = 0x%llx (opcode 0x%llx)", i, branch_table[i], *((unsigned int*)branch_table[i])); - } -#endif - - __ bind(Lslow_path); - __ branch_to_entry(Interpreter::entry_for_kind(Interpreter::zerolocals), Rscratch); - __ flush(); - - return entry; -} - // Interpreter intrinsic for WeakReference.get(). // 1. Don't push a full blown frame and go on dispatching, but fetch the value // into R8 and return quickly @@ -713,7 +529,6 @@ // and so we don't need to call the G1 pre-barrier. Thus we can use the // regular method entry code to generate the NPE. // - // This code is based on generate_accessor_enty. address entry = __ pc(); @@ -768,7 +583,7 @@ return entry; } else { - return generate_accessor_entry(); + return generate_jump_to_normal_entry(); } } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/cpu/ppc/vm/ppc.ad --- a/hotspot/src/cpu/ppc/vm/ppc.ad Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/cpu/ppc/vm/ppc.ad Fri Aug 29 11:58:43 2014 -0700 @@ -1283,8 +1283,6 @@ bool MachConstantBaseNode::requires_postalloc_expand() const { return true; } void MachConstantBaseNode::postalloc_expand(GrowableArray *nodes, PhaseRegAlloc *ra_) { - Compile *C = ra_->C; - iRegPdstOper *op_dst = new iRegPdstOper(); MachNode *m1 = new loadToc_hiNode(); MachNode *m2 = new loadToc_loNode(); @@ -2229,7 +2227,7 @@ } /* TODO: PPC port // Make a new machine dependent decode node (with its operands). -MachTypeNode *Matcher::make_decode_node(Compile *C) { +MachTypeNode *Matcher::make_decode_node() { assert(Universe::narrow_oop_base() == NULL && Universe::narrow_oop_shift() == 0, "This method is only implemented for unscaled cOops mode so far"); MachTypeNode *decode = new decodeN_unscaledNode(); @@ -2593,7 +2591,7 @@ MachNode *_last; } loadConLNodesTuple; -loadConLNodesTuple loadConLNodesTuple_create(Compile *C, PhaseRegAlloc *ra_, Node *toc, immLOper *immSrc, +loadConLNodesTuple loadConLNodesTuple_create(PhaseRegAlloc *ra_, Node *toc, immLOper *immSrc, OptoReg::Name reg_second, OptoReg::Name reg_first) { loadConLNodesTuple nodes; @@ -2669,7 +2667,7 @@ enc_class postalloc_expand_load_long_constant(iRegLdst dst, immL src, iRegLdst toc) %{ // Create new nodes. loadConLNodesTuple loadConLNodes = - loadConLNodesTuple_create(C, ra_, n_toc, op_src, + loadConLNodesTuple_create(ra_, n_toc, op_src, ra_->get_reg_second(this), ra_->get_reg_first(this)); // Push new nodes. @@ -3391,7 +3389,7 @@ immLOper *op_repl = new immLOper((jlong)replicate_immF(op_src->constantF())); loadConLNodesTuple loadConLNodes = - loadConLNodesTuple_create(C, ra_, n_toc, op_repl, + loadConLNodesTuple_create(ra_, n_toc, op_repl, ra_->get_reg_second(this), ra_->get_reg_first(this)); // Push new nodes. @@ -3611,7 +3609,7 @@ // Create the nodes for loading the IC from the TOC. loadConLNodesTuple loadConLNodes_IC = - loadConLNodesTuple_create(C, ra_, n_toc, new immLOper((jlong)Universe::non_oop_word()), + loadConLNodesTuple_create(ra_, n_toc, new immLOper((jlong)Universe::non_oop_word()), OptoReg::Name(R19_H_num), OptoReg::Name(R19_num)); // Create the call node. @@ -3765,7 +3763,7 @@ #if defined(ABI_ELFv2) jlong entry_address = (jlong) this->entry_point(); assert(entry_address, "need address here"); - loadConLNodes_Entry = loadConLNodesTuple_create(C, ra_, n_toc, new immLOper(entry_address), + loadConLNodes_Entry = loadConLNodesTuple_create(ra_, n_toc, new immLOper(entry_address), OptoReg::Name(R12_H_num), OptoReg::Name(R12_num)); #else // Get the struct that describes the function we are about to call. @@ -3777,13 +3775,13 @@ loadConLNodesTuple loadConLNodes_Toc; // Create nodes and operands for loading the entry point. - loadConLNodes_Entry = loadConLNodesTuple_create(C, ra_, n_toc, new immLOper(entry_address), + loadConLNodes_Entry = loadConLNodesTuple_create(ra_, n_toc, new immLOper(entry_address), OptoReg::Name(R12_H_num), OptoReg::Name(R12_num)); // Create nodes and operands for loading the env pointer. if (fd->env() != NULL) { - loadConLNodes_Env = loadConLNodesTuple_create(C, ra_, n_toc, new immLOper((jlong) fd->env()), + loadConLNodes_Env = loadConLNodesTuple_create(ra_, n_toc, new immLOper((jlong) fd->env()), OptoReg::Name(R11_H_num), OptoReg::Name(R11_num)); } else { loadConLNodes_Env._large_hi = NULL; @@ -3796,7 +3794,7 @@ } // Create nodes and operands for loading the Toc point. - loadConLNodes_Toc = loadConLNodesTuple_create(C, ra_, n_toc, new immLOper((jlong) fd->toc()), + loadConLNodes_Toc = loadConLNodesTuple_create(ra_, n_toc, new immLOper((jlong) fd->toc()), OptoReg::Name(R2_H_num), OptoReg::Name(R2_num)); #endif // ABI_ELFv2 // mtctr node diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.hpp --- a/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -30,7 +30,6 @@ address generate_normal_entry(bool synchronized); address generate_native_entry(bool synchronized); address generate_math_entry(AbstractInterpreter::MethodKind kind); - address generate_empty_entry(void); void lock_method(Register Rflags, Register Rscratch1, Register Rscratch2, bool flags_preloaded=false); void unlock_method(bool check_exceptions = true); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/cpu/ppc/vm/templateInterpreter_ppc.cpp --- a/hotspot/src/cpu/ppc/vm/templateInterpreter_ppc.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/cpu/ppc/vm/templateInterpreter_ppc.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -176,8 +176,12 @@ const Register size = R12_scratch2; __ get_cache_and_index_at_bcp(cache, 1, index_size); - // Big Endian (get least significant byte of 64 bit value): + // Get least significant byte of 64 bit value: +#if defined(VM_LITTLE_ENDIAN) + __ lbz(size, in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::flags_offset()), cache); +#else __ lbz(size, in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::flags_offset()) + 7, cache); +#endif __ sldi(size, size, Interpreter::logStackElementSize); __ add(R15_esp, R15_esp, size); __ dispatch_next(state, step); @@ -598,48 +602,6 @@ // End of helpers -// ============================================================================ -// Various method entries -// - -// Empty method, generate a very fast return. We must skip this entry if -// someone's debugging, indicated by the flag -// "interp_mode" in the Thread obj. -// Note: empty methods are generated mostly methods that do assertions, which are -// disabled in the "java opt build". -address TemplateInterpreterGenerator::generate_empty_entry(void) { - if (!UseFastEmptyMethods) { - NOT_PRODUCT(__ should_not_reach_here();) - return Interpreter::entry_for_kind(Interpreter::zerolocals); - } - - Label Lslow_path; - const Register Rjvmti_mode = R11_scratch1; - address entry = __ pc(); - - __ lwz(Rjvmti_mode, thread_(interp_only_mode)); - __ cmpwi(CCR0, Rjvmti_mode, 0); - __ bne(CCR0, Lslow_path); // jvmti_mode!=0 - - // Noone's debuggin: Simply return. - // Pop c2i arguments (if any) off when we return. -#ifdef ASSERT - __ ld(R9_ARG7, 0, R1_SP); - __ ld(R10_ARG8, 0, R21_sender_SP); - __ cmpd(CCR0, R9_ARG7, R10_ARG8); - __ asm_assert_eq("backlink", 0x545); -#endif // ASSERT - __ mr(R1_SP, R21_sender_SP); // Cut the stack back to where the caller started. - - // And we're done. - __ blr(); - - __ bind(Lslow_path); - __ branch_to_entry(Interpreter::entry_for_kind(Interpreter::zerolocals), R11_scratch1); - __ flush(); - - return entry; -} // Support abs and sqrt like in compiler. // For others we can use a normal (native) entry. @@ -858,7 +820,9 @@ // Our signature handlers copy required arguments to the C stack // (outgoing C args), R3_ARG1 to R10_ARG8, and FARG1 to FARG13. __ mr(R3_ARG1, R18_locals); +#if !defined(ABI_ELFv2) __ ld(signature_handler_fd, 0, signature_handler_fd); +#endif __ call_stub(signature_handler_fd); @@ -1020,8 +984,13 @@ // native result across the call. No oop is present. __ mr(R3_ARG1, R16_thread); +#if defined(ABI_ELFv2) + __ call_c(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans), + relocInfo::none); +#else __ call_c(CAST_FROM_FN_PTR(FunctionDescriptor*, JavaThread::check_special_condition_for_native_trans), relocInfo::none); +#endif __ bind(sync_check_done); @@ -1278,45 +1247,6 @@ return entry; } -// ============================================================================= -// Entry points - -address AbstractInterpreterGenerator::generate_method_entry( - AbstractInterpreter::MethodKind kind) { - // Determine code generation flags. - bool synchronized = false; - address entry_point = NULL; - - switch (kind) { - case Interpreter::zerolocals : break; - case Interpreter::zerolocals_synchronized: synchronized = true; break; - case Interpreter::native : entry_point = ((InterpreterGenerator*) this)->generate_native_entry(false); break; - case Interpreter::native_synchronized : entry_point = ((InterpreterGenerator*) this)->generate_native_entry(true); break; - case Interpreter::empty : entry_point = ((InterpreterGenerator*) this)->generate_empty_entry(); break; - case Interpreter::accessor : entry_point = ((InterpreterGenerator*) this)->generate_accessor_entry(); break; - case Interpreter::abstract : entry_point = ((InterpreterGenerator*) this)->generate_abstract_entry(); break; - - case Interpreter::java_lang_math_sin : // fall thru - case Interpreter::java_lang_math_cos : // fall thru - case Interpreter::java_lang_math_tan : // fall thru - case Interpreter::java_lang_math_abs : // fall thru - case Interpreter::java_lang_math_log : // fall thru - case Interpreter::java_lang_math_log10 : // fall thru - case Interpreter::java_lang_math_sqrt : // fall thru - case Interpreter::java_lang_math_pow : // fall thru - case Interpreter::java_lang_math_exp : entry_point = ((InterpreterGenerator*) this)->generate_math_entry(kind); break; - case Interpreter::java_lang_ref_reference_get - : entry_point = ((InterpreterGenerator*)this)->generate_Reference_get_entry(); break; - default : ShouldNotReachHere(); break; - } - - if (entry_point) { - return entry_point; - } - - return ((InterpreterGenerator*) this)->generate_normal_entry(synchronized); -} - // These should never be compiled since the interpreter will prefer // the compiled version to the intrinsic version. bool AbstractInterpreter::can_be_compiled(methodHandle m) { @@ -1344,7 +1274,7 @@ int callee_locals, bool is_top_frame) { // Note: This calculation must exactly parallel the frame setup - // in AbstractInterpreterGenerator::generate_method_entry. + // in InterpreterGenerator::generate_fixed_frame. assert(Interpreter::stackElementWords == 1, "sanity"); const int max_alignment_space = StackAlignmentInBytes / Interpreter::stackElementSize; const int abi_scratch = is_top_frame ? (frame::abi_reg_args_size / Interpreter::stackElementSize) : diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp --- a/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -189,8 +189,12 @@ assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range"); assert(load_bc_into_bc_reg, "we use bc_reg as temp"); __ get_cache_and_index_at_bcp(Rtemp /* dst = cache */, 1); - // Big Endian: ((*(cache+indices))>>((1+byte_no)*8))&0xFF + // ((*(cache+indices))>>((1+byte_no)*8))&0xFF: +#if defined(VM_LITTLE_ENDIAN) + __ lbz(Rnew_bc, in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::indices_offset()) + 1 + byte_no, Rtemp); +#else __ lbz(Rnew_bc, in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::indices_offset()) + 7 - (1 + byte_no), Rtemp); +#endif __ cmpwi(CCR0, Rnew_bc, 0); __ li(Rnew_bc, (unsigned int)(unsigned char)new_bc); __ beq(CCR0, L_patch_done); @@ -1839,8 +1843,8 @@ __ clrrdi(Rdef_offset_addr, Rdef_offset_addr, log2_long((jlong)BytesPerInt)); // Load lo & hi. - __ lwz(Rlow_byte, BytesPerInt, Rdef_offset_addr); - __ lwz(Rhigh_byte, BytesPerInt * 2, Rdef_offset_addr); + __ get_u4(Rlow_byte, Rdef_offset_addr, BytesPerInt, InterpreterMacroAssembler::Unsigned); + __ get_u4(Rhigh_byte, Rdef_offset_addr, 2 *BytesPerInt, InterpreterMacroAssembler::Unsigned); // Check for default case (=index outside [low,high]). __ cmpw(CCR0, R17_tos, Rlow_byte); @@ -1854,12 +1858,17 @@ __ profile_switch_case(Rindex, Rhigh_byte /* scratch */, Rscratch1, Rscratch2); __ sldi(Rindex, Rindex, LogBytesPerInt); __ addi(Rindex, Rindex, 3 * BytesPerInt); +#if defined(VM_LITTLE_ENDIAN) + __ lwbrx(Roffset, Rdef_offset_addr, Rindex); + __ extsw(Roffset, Roffset); +#else __ lwax(Roffset, Rdef_offset_addr, Rindex); +#endif __ b(Ldispatch); __ bind(Ldefault_case); __ profile_switch_default(Rhigh_byte, Rscratch1); - __ lwa(Roffset, 0, Rdef_offset_addr); + __ get_u4(Roffset, Rdef_offset_addr, 0, InterpreterMacroAssembler::Signed); __ bind(Ldispatch); @@ -1875,12 +1884,11 @@ // Table switch using linear search through cases. // Bytecode stream format: // Bytecode (1) | 4-byte padding | default offset (4) | count (4) | value/offset pair1 (8) | value/offset pair2 (8) | ... -// Note: Everything is big-endian format here. So on little endian machines, we have to revers offset and count and cmp value. +// Note: Everything is big-endian format here. void TemplateTable::fast_linearswitch() { transition(itos, vtos); - Label Lloop_entry, Lsearch_loop, Lfound, Lcontinue_execution, Ldefault_case; - + Label Lloop_entry, Lsearch_loop, Lcontinue_execution, Ldefault_case; Register Rcount = R3_ARG1, Rcurrent_pair = R4_ARG2, Rdef_offset_addr = R5_ARG3, // Is going to contain address of default offset. @@ -1894,47 +1902,40 @@ __ clrrdi(Rdef_offset_addr, Rdef_offset_addr, log2_long((jlong)BytesPerInt)); // Setup loop counter and limit. - __ lwz(Rcount, BytesPerInt, Rdef_offset_addr); // Load count. + __ get_u4(Rcount, Rdef_offset_addr, BytesPerInt, InterpreterMacroAssembler::Unsigned); __ addi(Rcurrent_pair, Rdef_offset_addr, 2 * BytesPerInt); // Rcurrent_pair now points to first pair. - // Set up search loop. - __ cmpwi(CCR0, Rcount, 0); - __ beq(CCR0, Ldefault_case); - __ mtctr(Rcount); - - // linear table search - __ bind(Lsearch_loop); - - __ lwz(Rvalue, 0, Rcurrent_pair); - __ lwa(Roffset, 1 * BytesPerInt, Rcurrent_pair); - - __ cmpw(CCR0, Rvalue, Rcmp_value); - __ beq(CCR0, Lfound); - - __ addi(Rcurrent_pair, Rcurrent_pair, 2 * BytesPerInt); - __ bdnz(Lsearch_loop); - - // default case + __ cmpwi(CCR0, Rcount, 0); + __ bne(CCR0, Lloop_entry); + + // Default case __ bind(Ldefault_case); - - __ lwa(Roffset, 0, Rdef_offset_addr); + __ get_u4(Roffset, Rdef_offset_addr, 0, InterpreterMacroAssembler::Signed); if (ProfileInterpreter) { __ profile_switch_default(Rdef_offset_addr, Rcount/* scratch */); - __ b(Lcontinue_execution); } - - // Entry found, skip Roffset bytecodes and continue. - __ bind(Lfound); + __ b(Lcontinue_execution); + + // Next iteration + __ bind(Lsearch_loop); + __ bdz(Ldefault_case); + __ addi(Rcurrent_pair, Rcurrent_pair, 2 * BytesPerInt); + __ bind(Lloop_entry); + __ get_u4(Rvalue, Rcurrent_pair, 0, InterpreterMacroAssembler::Unsigned); + __ cmpw(CCR0, Rvalue, Rcmp_value); + __ bne(CCR0, Lsearch_loop); + + // Found, load offset. + __ get_u4(Roffset, Rcurrent_pair, BytesPerInt, InterpreterMacroAssembler::Signed); + // Calculate case index and profile + __ mfctr(Rcurrent_pair); if (ProfileInterpreter) { - // Calc the num of the pair we hit. Careful, Rcurrent_pair points 2 ints - // beyond the actual current pair due to the auto update load above! - __ sub(Rcurrent_pair, Rcurrent_pair, Rdef_offset_addr); - __ addi(Rcurrent_pair, Rcurrent_pair, - 2 * BytesPerInt); - __ srdi(Rcurrent_pair, Rcurrent_pair, LogBytesPerInt + 1); + __ sub(Rcurrent_pair, Rcount, Rcurrent_pair); __ profile_switch_case(Rcurrent_pair, Rcount /*scratch*/, Rdef_offset_addr/*scratch*/, Rscratch); - __ bind(Lcontinue_execution); } + + __ bind(Lcontinue_execution); __ add(R14_bcp, Roffset, R14_bcp); __ dispatch_next(vtos); } @@ -1990,7 +1991,7 @@ // initialize i & j __ li(Ri,0); - __ lwz(Rj, -BytesPerInt, Rarray); + __ get_u4(Rj, Rarray, -BytesPerInt, InterpreterMacroAssembler::Unsigned); // and start. Label entry; @@ -2007,7 +2008,11 @@ // i = h; // } __ sldi(Rscratch, Rh, log_entry_size); +#if defined(VM_LITTLE_ENDIAN) + __ lwbrx(Rscratch, Rscratch, Rarray); +#else __ lwzx(Rscratch, Rscratch, Rarray); +#endif // if (key < current value) // Rh = Rj @@ -2039,20 +2044,20 @@ // Ri = value offset __ sldi(Ri, Ri, log_entry_size); __ add(Ri, Ri, Rarray); - __ lwz(Rscratch, 0, Ri); + __ get_u4(Rscratch, Ri, 0, InterpreterMacroAssembler::Unsigned); Label not_found; // Ri = offset offset __ cmpw(CCR0, Rkey, Rscratch); __ beq(CCR0, not_found); // entry not found -> j = default offset - __ lwz(Rj, -2 * BytesPerInt, Rarray); + __ get_u4(Rj, Rarray, -2 * BytesPerInt, InterpreterMacroAssembler::Unsigned); __ b(default_case); __ bind(not_found); // entry found -> j = offset __ profile_switch_case(Rh, Rj, Rscratch, Rkey); - __ lwz(Rj, BytesPerInt, Ri); + __ get_u4(Rj, Ri, BytesPerInt, InterpreterMacroAssembler::Unsigned); if (ProfileInterpreter) { __ b(continue_execution); @@ -2147,8 +2152,11 @@ assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range"); // We are resolved if the indices offset contains the current bytecode. - // Big Endian: +#if defined(VM_LITTLE_ENDIAN) + __ lbz(Rscratch, in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::indices_offset()) + byte_no + 1, Rcache); +#else __ lbz(Rscratch, in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::indices_offset()) + 7 - (byte_no + 1), Rcache); +#endif // Acquire by cmp-br-isync (see below). __ cmpdi(CCR0, Rscratch, (int)bytecode()); __ beq(CCR0, Lresolved); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp --- a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -29,6 +29,7 @@ #include "compiler/disassembler.hpp" #include "memory/resourceArea.hpp" #include "runtime/java.hpp" +#include "runtime/os.hpp" #include "runtime/stubCodeGenerator.hpp" #include "utilities/defaultStream.hpp" #include "vm_version_ppc.hpp" @@ -108,7 +109,7 @@ (has_vand() ? " vand" : "") // Make sure number of %s matches num_features! ); - _features_str = strdup(buf); + _features_str = os::strdup(buf); NOT_PRODUCT(if (Verbose) print_features();); // PPC64 supports 8-byte compare-exchange operations (see diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -29,6 +29,7 @@ #include "interpreter/interpreter.hpp" #include "interpreter/interpreterGenerator.hpp" #include "interpreter/interpreterRuntime.hpp" +#include "interpreter/interp_masm.hpp" #include "oops/arrayOop.hpp" #include "oops/methodData.hpp" #include "oops/method.hpp" @@ -68,9 +69,7 @@ #define STATE(field_name) Lstate, in_bytes(byte_offset_of(BytecodeInterpreter, field_name)) #define __ _masm-> -Label frame_manager_entry; -Label fast_accessor_slow_entry_path; // fast accessor methods need to be able to jmp to unsynchronized - // c++ interpreter entry point this holds that entry point label. +Label frame_manager_entry; // c++ interpreter entry point this holds that entry point label. static address unctrap_frame_manager_entry = NULL; @@ -452,110 +451,6 @@ return NULL; } -// Call an accessor method (assuming it is resolved, otherwise drop into -// vanilla (slow path) entry - -// Generates code to elide accessor methods -// Uses G3_scratch and G1_scratch as scratch -address InterpreterGenerator::generate_accessor_entry(void) { - - // Code: _aload_0, _(i|a)getfield, _(i|a)return or any rewrites thereof; - // parameter size = 1 - // Note: We can only use this code if the getfield has been resolved - // and if we don't have a null-pointer exception => check for - // these conditions first and use slow path if necessary. - address entry = __ pc(); - Label slow_path; - - if ( UseFastAccessorMethods) { - // Check if we need to reach a safepoint and generate full interpreter - // frame if so. - AddressLiteral sync_state(SafepointSynchronize::address_of_state()); - __ load_contents(sync_state, G3_scratch); - __ cmp(G3_scratch, SafepointSynchronize::_not_synchronized); - __ br(Assembler::notEqual, false, Assembler::pn, slow_path); - __ delayed()->nop(); - - // Check if local 0 != NULL - __ ld_ptr(Gargs, G0, Otos_i ); // get local 0 - __ tst(Otos_i); // check if local 0 == NULL and go the slow path - __ brx(Assembler::zero, false, Assembler::pn, slow_path); - __ delayed()->nop(); - - - // read first instruction word and extract bytecode @ 1 and index @ 2 - // get first 4 bytes of the bytecodes (big endian!) - __ ld_ptr(Address(G5_method, in_bytes(Method::const_offset())), G1_scratch); - __ ld(Address(G1_scratch, in_bytes(ConstMethod::codes_offset())), G1_scratch); - - // move index @ 2 far left then to the right most two bytes. - __ sll(G1_scratch, 2*BitsPerByte, G1_scratch); - __ srl(G1_scratch, 2*BitsPerByte - exact_log2(in_words( - ConstantPoolCacheEntry::size()) * BytesPerWord), G1_scratch); - - // get constant pool cache - __ ld_ptr(G5_method, in_bytes(Method::const_offset()), G3_scratch); - __ ld_ptr(G3_scratch, in_bytes(ConstMethod::constants_offset()), G3_scratch); - __ ld_ptr(G3_scratch, ConstantPool::cache_offset_in_bytes(), G3_scratch); - - // get specific constant pool cache entry - __ add(G3_scratch, G1_scratch, G3_scratch); - - // Check the constant Pool cache entry to see if it has been resolved. - // If not, need the slow path. - ByteSize cp_base_offset = ConstantPoolCache::base_offset(); - __ ld_ptr(G3_scratch, in_bytes(cp_base_offset + ConstantPoolCacheEntry::indices_offset()), G1_scratch); - __ srl(G1_scratch, 2*BitsPerByte, G1_scratch); - __ and3(G1_scratch, 0xFF, G1_scratch); - __ cmp(G1_scratch, Bytecodes::_getfield); - __ br(Assembler::notEqual, false, Assembler::pn, slow_path); - __ delayed()->nop(); - - // Get the type and return field offset from the constant pool cache - __ ld_ptr(G3_scratch, in_bytes(cp_base_offset + ConstantPoolCacheEntry::flags_offset()), G1_scratch); - __ ld_ptr(G3_scratch, in_bytes(cp_base_offset + ConstantPoolCacheEntry::f2_offset()), G3_scratch); - - Label xreturn_path; - // Need to differentiate between igetfield, agetfield, bgetfield etc. - // because they are different sizes. - // Get the type from the constant pool cache - __ srl(G1_scratch, ConstantPoolCacheEntry::tos_state_shift, G1_scratch); - // Make sure we don't need to mask G1_scratch after the above shift - ConstantPoolCacheEntry::verify_tos_state_shift(); - __ cmp(G1_scratch, atos ); - __ br(Assembler::equal, true, Assembler::pt, xreturn_path); - __ delayed()->ld_ptr(Otos_i, G3_scratch, Otos_i); - __ cmp(G1_scratch, itos); - __ br(Assembler::equal, true, Assembler::pt, xreturn_path); - __ delayed()->ld(Otos_i, G3_scratch, Otos_i); - __ cmp(G1_scratch, stos); - __ br(Assembler::equal, true, Assembler::pt, xreturn_path); - __ delayed()->ldsh(Otos_i, G3_scratch, Otos_i); - __ cmp(G1_scratch, ctos); - __ br(Assembler::equal, true, Assembler::pt, xreturn_path); - __ delayed()->lduh(Otos_i, G3_scratch, Otos_i); -#ifdef ASSERT - __ cmp(G1_scratch, btos); - __ br(Assembler::equal, true, Assembler::pt, xreturn_path); - __ delayed()->ldsb(Otos_i, G3_scratch, Otos_i); - __ should_not_reach_here(); -#endif - __ ldsb(Otos_i, G3_scratch, Otos_i); - __ bind(xreturn_path); - - // _ireturn/_areturn - __ retl(); // return from leaf routine - __ delayed()->mov(O5_savedSP, SP); - - // Generate regular method entry - __ bind(slow_path); - __ ba(fast_accessor_slow_entry_path); - __ delayed()->nop(); - return entry; - } - return NULL; -} - address InterpreterGenerator::generate_Reference_get_entry(void) { #if INCLUDE_ALL_GCS if (UseG1GC) { @@ -573,7 +468,7 @@ // If G1 is not enabled then attempt to go through the accessor entry point // Reference.get is an accessor - return generate_accessor_entry(); + return generate_jump_to_normal_entry(); } // @@ -1870,23 +1765,6 @@ __ ba(call_interpreter_2); __ delayed()->st_ptr(O1, STATE(_stack)); - - // Fast accessor methods share this entry point. - // This works because frame manager is in the same codelet - // This can either be an entry via call_stub/c1/c2 or a recursive interpreter call - // we need to do a little register fixup here once we distinguish the two of them - if (UseFastAccessorMethods && !synchronized) { - // Call stub_return address still in O7 - __ bind(fast_accessor_slow_entry_path); - __ set((intptr_t)return_from_native_method - 8, Gtmp1); - __ cmp(Gtmp1, O7); // returning to interpreter? - __ brx(Assembler::equal, true, Assembler::pt, re_dispatch); // yep - __ delayed()->nop(); - __ ba(re_dispatch); - __ delayed()->mov(G0, prevState); // initial entry - - } - // interpreter returning to native code (call_stub/c1/c2) // convert result and unwind initial activation // L2_scratch - scaled result type index diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/cpu/sparc/vm/interpreterGenerator_sparc.hpp --- a/hotspot/src/cpu/sparc/vm/interpreterGenerator_sparc.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/cpu/sparc/vm/interpreterGenerator_sparc.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -32,9 +32,11 @@ address generate_normal_entry(bool synchronized); address generate_native_entry(bool synchronized); address generate_abstract_entry(void); - address generate_math_entry(AbstractInterpreter::MethodKind kind); - address generate_empty_entry(void); - address generate_accessor_entry(void); + // there are no math intrinsics on sparc + address generate_math_entry(AbstractInterpreter::MethodKind kind) { return NULL; } + address generate_jump_to_normal_entry(void); + address generate_accessor_entry(void) { return generate_jump_to_normal_entry(); } + address generate_empty_entry(void) { return generate_jump_to_normal_entry(); } address generate_Reference_get_entry(void); void lock_method(void); void save_native_result(void); @@ -43,4 +45,7 @@ void generate_counter_incr(Label* overflow, Label* profile_method, Label* profile_method_continue); void generate_counter_overflow(Label& Lcontinue); + // Not supported + address generate_CRC32_update_entry() { return NULL; } + address generate_CRC32_updateBytes_entry(AbstractInterpreter::MethodKind kind) { return NULL; } #endif // CPU_SPARC_VM_INTERPRETERGENERATOR_SPARC_HPP diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/cpu/sparc/vm/interpreter_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/interpreter_sparc.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/cpu/sparc/vm/interpreter_sparc.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -241,6 +241,15 @@ // Various method entries +address InterpreterGenerator::generate_jump_to_normal_entry(void) { + address entry = __ pc(); + assert(Interpreter::entry_for_kind(Interpreter::zerolocals) != NULL, "should already be generated"); + AddressLiteral al(Interpreter::entry_for_kind(Interpreter::zerolocals)); + __ jump_to(al, G3_scratch); + __ delayed()->nop(); + return entry; +} + // Abstract method entry // Attempt to execute abstract method. Throw exception // @@ -255,159 +264,6 @@ } - -//---------------------------------------------------------------------------------------------------- -// Entry points & stack frame layout -// -// Here we generate the various kind of entries into the interpreter. -// The two main entry type are generic bytecode methods and native call method. -// These both come in synchronized and non-synchronized versions but the -// frame layout they create is very similar. The other method entry -// types are really just special purpose entries that are really entry -// and interpretation all in one. These are for trivial methods like -// accessor, empty, or special math methods. -// -// When control flow reaches any of the entry types for the interpreter -// the following holds -> -// -// C2 Calling Conventions: -// -// The entry code below assumes that the following registers are set -// when coming in: -// G5_method: holds the Method* of the method to call -// Lesp: points to the TOS of the callers expression stack -// after having pushed all the parameters -// -// The entry code does the following to setup an interpreter frame -// pop parameters from the callers stack by adjusting Lesp -// set O0 to Lesp -// compute X = (max_locals - num_parameters) -// bump SP up by X to accomadate the extra locals -// compute X = max_expression_stack -// + vm_local_words -// + 16 words of register save area -// save frame doing a save sp, -X, sp growing towards lower addresses -// set Lbcp, Lmethod, LcpoolCache -// set Llocals to i0 -// set Lmonitors to FP - rounded_vm_local_words -// set Lesp to Lmonitors - 4 -// -// The frame has now been setup to do the rest of the entry code - -// Try this optimization: Most method entries could live in a -// "one size fits all" stack frame without all the dynamic size -// calculations. It might be profitable to do all this calculation -// statically and approximately for "small enough" methods. - -//----------------------------------------------------------------------------------------------- - -// C1 Calling conventions -// -// Upon method entry, the following registers are setup: -// -// g2 G2_thread: current thread -// g5 G5_method: method to activate -// g4 Gargs : pointer to last argument -// -// -// Stack: -// -// +---------------+ <--- sp -// | | -// : reg save area : -// | | -// +---------------+ <--- sp + 0x40 -// | | -// : extra 7 slots : note: these slots are not really needed for the interpreter (fix later) -// | | -// +---------------+ <--- sp + 0x5c -// | | -// : free : -// | | -// +---------------+ <--- Gargs -// | | -// : arguments : -// | | -// +---------------+ -// | | -// -// -// -// AFTER FRAME HAS BEEN SETUP for method interpretation the stack looks like: -// -// +---------------+ <--- sp -// | | -// : reg save area : -// | | -// +---------------+ <--- sp + 0x40 -// | | -// : extra 7 slots : note: these slots are not really needed for the interpreter (fix later) -// | | -// +---------------+ <--- sp + 0x5c -// | | -// : : -// | | <--- Lesp -// +---------------+ <--- Lmonitors (fp - 0x18) -// | VM locals | -// +---------------+ <--- fp -// | | -// : reg save area : -// | | -// +---------------+ <--- fp + 0x40 -// | | -// : extra 7 slots : note: these slots are not really needed for the interpreter (fix later) -// | | -// +---------------+ <--- fp + 0x5c -// | | -// : free : -// | | -// +---------------+ -// | | -// : nonarg locals : -// | | -// +---------------+ -// | | -// : arguments : -// | | <--- Llocals -// +---------------+ <--- Gargs -// | | - -address AbstractInterpreterGenerator::generate_method_entry(AbstractInterpreter::MethodKind kind) { - // determine code generation flags - bool synchronized = false; - address entry_point = NULL; - - switch (kind) { - case Interpreter::zerolocals : break; - case Interpreter::zerolocals_synchronized: synchronized = true; break; - case Interpreter::native : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(false); break; - case Interpreter::native_synchronized : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(true); break; - case Interpreter::empty : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry(); break; - case Interpreter::accessor : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry(); break; - case Interpreter::abstract : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry(); break; - - case Interpreter::java_lang_math_sin : break; - case Interpreter::java_lang_math_cos : break; - case Interpreter::java_lang_math_tan : break; - case Interpreter::java_lang_math_sqrt : break; - case Interpreter::java_lang_math_abs : break; - case Interpreter::java_lang_math_log : break; - case Interpreter::java_lang_math_log10 : break; - case Interpreter::java_lang_math_pow : break; - case Interpreter::java_lang_math_exp : break; - case Interpreter::java_lang_ref_reference_get - : entry_point = ((InterpreterGenerator*)this)->generate_Reference_get_entry(); break; - default: - fatal(err_msg("unexpected method kind: %d", kind)); - break; - } - - if (entry_point) return entry_point; - - return ((InterpreterGenerator*)this)->generate_normal_entry(synchronized); -} - - bool AbstractInterpreter::can_be_compiled(methodHandle m) { // No special entry points that preclude compilation return true; diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/cpu/sparc/vm/sparc.ad --- a/hotspot/src/cpu/sparc/vm/sparc.ad Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/cpu/sparc/vm/sparc.ad Fri Aug 29 11:58:43 2014 -0700 @@ -6184,7 +6184,11 @@ ins_cost(DEFAULT_COST * 3/2); format %{ "SET $con,$dst\t! non-oop ptr" %} ins_encode %{ - __ set($con$$constant, $dst$$Register); + if (_opnds[1]->constant_reloc() == relocInfo::metadata_type) { + __ set_metadata_constant((Metadata*)$con$$constant, $dst$$Register); + } else { + __ set($con$$constant, $dst$$Register); + } %} ins_pipe(loadConP); %} diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -456,6 +456,115 @@ // Generate a fixed interpreter frame. This is identical setup for interpreted // methods and for native methods hence the shared code. + +//---------------------------------------------------------------------------------------------------- +// Stack frame layout +// +// When control flow reaches any of the entry types for the interpreter +// the following holds -> +// +// C2 Calling Conventions: +// +// The entry code below assumes that the following registers are set +// when coming in: +// G5_method: holds the Method* of the method to call +// Lesp: points to the TOS of the callers expression stack +// after having pushed all the parameters +// +// The entry code does the following to setup an interpreter frame +// pop parameters from the callers stack by adjusting Lesp +// set O0 to Lesp +// compute X = (max_locals - num_parameters) +// bump SP up by X to accomadate the extra locals +// compute X = max_expression_stack +// + vm_local_words +// + 16 words of register save area +// save frame doing a save sp, -X, sp growing towards lower addresses +// set Lbcp, Lmethod, LcpoolCache +// set Llocals to i0 +// set Lmonitors to FP - rounded_vm_local_words +// set Lesp to Lmonitors - 4 +// +// The frame has now been setup to do the rest of the entry code + +// Try this optimization: Most method entries could live in a +// "one size fits all" stack frame without all the dynamic size +// calculations. It might be profitable to do all this calculation +// statically and approximately for "small enough" methods. + +//----------------------------------------------------------------------------------------------- + +// C1 Calling conventions +// +// Upon method entry, the following registers are setup: +// +// g2 G2_thread: current thread +// g5 G5_method: method to activate +// g4 Gargs : pointer to last argument +// +// +// Stack: +// +// +---------------+ <--- sp +// | | +// : reg save area : +// | | +// +---------------+ <--- sp + 0x40 +// | | +// : extra 7 slots : note: these slots are not really needed for the interpreter (fix later) +// | | +// +---------------+ <--- sp + 0x5c +// | | +// : free : +// | | +// +---------------+ <--- Gargs +// | | +// : arguments : +// | | +// +---------------+ +// | | +// +// +// +// AFTER FRAME HAS BEEN SETUP for method interpretation the stack looks like: +// +// +---------------+ <--- sp +// | | +// : reg save area : +// | | +// +---------------+ <--- sp + 0x40 +// | | +// : extra 7 slots : note: these slots are not really needed for the interpreter (fix later) +// | | +// +---------------+ <--- sp + 0x5c +// | | +// : : +// | | <--- Lesp +// +---------------+ <--- Lmonitors (fp - 0x18) +// | VM locals | +// +---------------+ <--- fp +// | | +// : reg save area : +// | | +// +---------------+ <--- fp + 0x40 +// | | +// : extra 7 slots : note: these slots are not really needed for the interpreter (fix later) +// | | +// +---------------+ <--- fp + 0x5c +// | | +// : free : +// | | +// +---------------+ +// | | +// : nonarg locals : +// | | +// +---------------+ +// | | +// : arguments : +// | | <--- Llocals +// +---------------+ <--- Gargs +// | | + void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) { // // @@ -599,136 +708,6 @@ } -// Empty method, generate a very fast return. - -address InterpreterGenerator::generate_empty_entry(void) { - - // A method that does nother but return... - - address entry = __ pc(); - Label slow_path; - - // do nothing for empty methods (do not even increment invocation counter) - if ( UseFastEmptyMethods) { - // If we need a safepoint check, generate full interpreter entry. - AddressLiteral sync_state(SafepointSynchronize::address_of_state()); - __ set(sync_state, G3_scratch); - __ cmp_and_br_short(G3_scratch, SafepointSynchronize::_not_synchronized, Assembler::notEqual, Assembler::pn, slow_path); - - // Code: _return - __ retl(); - __ delayed()->mov(O5_savedSP, SP); - - __ bind(slow_path); - (void) generate_normal_entry(false); - - return entry; - } - return NULL; -} - -// Call an accessor method (assuming it is resolved, otherwise drop into -// vanilla (slow path) entry - -// Generates code to elide accessor methods -// Uses G3_scratch and G1_scratch as scratch -address InterpreterGenerator::generate_accessor_entry(void) { - - // Code: _aload_0, _(i|a)getfield, _(i|a)return or any rewrites thereof; - // parameter size = 1 - // Note: We can only use this code if the getfield has been resolved - // and if we don't have a null-pointer exception => check for - // these conditions first and use slow path if necessary. - address entry = __ pc(); - Label slow_path; - - - // XXX: for compressed oops pointer loading and decoding doesn't fit in - // delay slot and damages G1 - if ( UseFastAccessorMethods && !UseCompressedOops ) { - // Check if we need to reach a safepoint and generate full interpreter - // frame if so. - AddressLiteral sync_state(SafepointSynchronize::address_of_state()); - __ load_contents(sync_state, G3_scratch); - __ cmp(G3_scratch, SafepointSynchronize::_not_synchronized); - __ cmp_and_br_short(G3_scratch, SafepointSynchronize::_not_synchronized, Assembler::notEqual, Assembler::pn, slow_path); - - // Check if local 0 != NULL - __ ld_ptr(Gargs, G0, Otos_i ); // get local 0 - // check if local 0 == NULL and go the slow path - __ br_null_short(Otos_i, Assembler::pn, slow_path); - - - // read first instruction word and extract bytecode @ 1 and index @ 2 - // get first 4 bytes of the bytecodes (big endian!) - __ ld_ptr(G5_method, Method::const_offset(), G1_scratch); - __ ld(G1_scratch, ConstMethod::codes_offset(), G1_scratch); - - // move index @ 2 far left then to the right most two bytes. - __ sll(G1_scratch, 2*BitsPerByte, G1_scratch); - __ srl(G1_scratch, 2*BitsPerByte - exact_log2(in_words( - ConstantPoolCacheEntry::size()) * BytesPerWord), G1_scratch); - - // get constant pool cache - __ ld_ptr(G5_method, Method::const_offset(), G3_scratch); - __ ld_ptr(G3_scratch, ConstMethod::constants_offset(), G3_scratch); - __ ld_ptr(G3_scratch, ConstantPool::cache_offset_in_bytes(), G3_scratch); - - // get specific constant pool cache entry - __ add(G3_scratch, G1_scratch, G3_scratch); - - // Check the constant Pool cache entry to see if it has been resolved. - // If not, need the slow path. - ByteSize cp_base_offset = ConstantPoolCache::base_offset(); - __ ld_ptr(G3_scratch, cp_base_offset + ConstantPoolCacheEntry::indices_offset(), G1_scratch); - __ srl(G1_scratch, 2*BitsPerByte, G1_scratch); - __ and3(G1_scratch, 0xFF, G1_scratch); - __ cmp_and_br_short(G1_scratch, Bytecodes::_getfield, Assembler::notEqual, Assembler::pn, slow_path); - - // Get the type and return field offset from the constant pool cache - __ ld_ptr(G3_scratch, cp_base_offset + ConstantPoolCacheEntry::flags_offset(), G1_scratch); - __ ld_ptr(G3_scratch, cp_base_offset + ConstantPoolCacheEntry::f2_offset(), G3_scratch); - - Label xreturn_path; - // Need to differentiate between igetfield, agetfield, bgetfield etc. - // because they are different sizes. - // Get the type from the constant pool cache - __ srl(G1_scratch, ConstantPoolCacheEntry::tos_state_shift, G1_scratch); - // Make sure we don't need to mask G1_scratch after the above shift - ConstantPoolCacheEntry::verify_tos_state_shift(); - __ cmp(G1_scratch, atos ); - __ br(Assembler::equal, true, Assembler::pt, xreturn_path); - __ delayed()->ld_ptr(Otos_i, G3_scratch, Otos_i); - __ cmp(G1_scratch, itos); - __ br(Assembler::equal, true, Assembler::pt, xreturn_path); - __ delayed()->ld(Otos_i, G3_scratch, Otos_i); - __ cmp(G1_scratch, stos); - __ br(Assembler::equal, true, Assembler::pt, xreturn_path); - __ delayed()->ldsh(Otos_i, G3_scratch, Otos_i); - __ cmp(G1_scratch, ctos); - __ br(Assembler::equal, true, Assembler::pt, xreturn_path); - __ delayed()->lduh(Otos_i, G3_scratch, Otos_i); -#ifdef ASSERT - __ cmp(G1_scratch, btos); - __ br(Assembler::equal, true, Assembler::pt, xreturn_path); - __ delayed()->ldsb(Otos_i, G3_scratch, Otos_i); - __ should_not_reach_here(); -#endif - __ ldsb(Otos_i, G3_scratch, Otos_i); - __ bind(xreturn_path); - - // _ireturn/_areturn - __ retl(); // return from leaf routine - __ delayed()->mov(O5_savedSP, SP); - - // Generate regular method entry - __ bind(slow_path); - (void) generate_normal_entry(false); - return entry; - } - return NULL; -} - // Method entry for java.lang.ref.Reference.get. address InterpreterGenerator::generate_Reference_get_entry(void) { #if INCLUDE_ALL_GCS @@ -806,7 +785,7 @@ // If G1 is not enabled then attempt to go through the accessor entry point // Reference.get is an accessor - return generate_accessor_entry(); + return generate_jump_to_normal_entry(); } // @@ -1242,8 +1221,6 @@ // Generic method entry to (asm) interpreter -//------------------------------------------------------------------------------------------------------------------------ -// address InterpreterGenerator::generate_normal_entry(bool synchronized) { address entry = __ pc(); @@ -1410,123 +1387,6 @@ return entry; } - -//---------------------------------------------------------------------------------------------------- -// Entry points & stack frame layout -// -// Here we generate the various kind of entries into the interpreter. -// The two main entry type are generic bytecode methods and native call method. -// These both come in synchronized and non-synchronized versions but the -// frame layout they create is very similar. The other method entry -// types are really just special purpose entries that are really entry -// and interpretation all in one. These are for trivial methods like -// accessor, empty, or special math methods. -// -// When control flow reaches any of the entry types for the interpreter -// the following holds -> -// -// C2 Calling Conventions: -// -// The entry code below assumes that the following registers are set -// when coming in: -// G5_method: holds the Method* of the method to call -// Lesp: points to the TOS of the callers expression stack -// after having pushed all the parameters -// -// The entry code does the following to setup an interpreter frame -// pop parameters from the callers stack by adjusting Lesp -// set O0 to Lesp -// compute X = (max_locals - num_parameters) -// bump SP up by X to accomadate the extra locals -// compute X = max_expression_stack -// + vm_local_words -// + 16 words of register save area -// save frame doing a save sp, -X, sp growing towards lower addresses -// set Lbcp, Lmethod, LcpoolCache -// set Llocals to i0 -// set Lmonitors to FP - rounded_vm_local_words -// set Lesp to Lmonitors - 4 -// -// The frame has now been setup to do the rest of the entry code - -// Try this optimization: Most method entries could live in a -// "one size fits all" stack frame without all the dynamic size -// calculations. It might be profitable to do all this calculation -// statically and approximately for "small enough" methods. - -//----------------------------------------------------------------------------------------------- - -// C1 Calling conventions -// -// Upon method entry, the following registers are setup: -// -// g2 G2_thread: current thread -// g5 G5_method: method to activate -// g4 Gargs : pointer to last argument -// -// -// Stack: -// -// +---------------+ <--- sp -// | | -// : reg save area : -// | | -// +---------------+ <--- sp + 0x40 -// | | -// : extra 7 slots : note: these slots are not really needed for the interpreter (fix later) -// | | -// +---------------+ <--- sp + 0x5c -// | | -// : free : -// | | -// +---------------+ <--- Gargs -// | | -// : arguments : -// | | -// +---------------+ -// | | -// -// -// -// AFTER FRAME HAS BEEN SETUP for method interpretation the stack looks like: -// -// +---------------+ <--- sp -// | | -// : reg save area : -// | | -// +---------------+ <--- sp + 0x40 -// | | -// : extra 7 slots : note: these slots are not really needed for the interpreter (fix later) -// | | -// +---------------+ <--- sp + 0x5c -// | | -// : : -// | | <--- Lesp -// +---------------+ <--- Lmonitors (fp - 0x18) -// | VM locals | -// +---------------+ <--- fp -// | | -// : reg save area : -// | | -// +---------------+ <--- fp + 0x40 -// | | -// : extra 7 slots : note: these slots are not really needed for the interpreter (fix later) -// | | -// +---------------+ <--- fp + 0x5c -// | | -// : free : -// | | -// +---------------+ -// | | -// : nonarg locals : -// | | -// +---------------+ -// | | -// : arguments : -// | | <--- Llocals -// +---------------+ <--- Gargs -// | | - static int size_activation_helper(int callee_extra_locals, int max_stack, int monitor_size) { // Figure out the size of an interpreter frame (in words) given that we have a fully allocated diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -26,6 +26,7 @@ #include "asm/macroAssembler.inline.hpp" #include "memory/resourceArea.hpp" #include "runtime/java.hpp" +#include "runtime/os.hpp" #include "runtime/stubCodeGenerator.hpp" #include "vm_version_sparc.hpp" @@ -249,7 +250,7 @@ (!has_hardware_fsmuld() ? ", no-fsmuld" : "")); // buf is started with ", " or is empty - _features_str = strdup(strlen(buf) > 2 ? buf + 2 : buf); + _features_str = os::strdup(strlen(buf) > 2 ? buf + 2 : buf); // There are three 64-bit SPARC families that do not overlap, e.g., // both is_ultra3() and is_sparc64() cannot be true at the same time. diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/cpu/x86/vm/assembler_x86.cpp --- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -3854,6 +3854,15 @@ } // Carry-Less Multiplication Quadword +void Assembler::pclmulqdq(XMMRegister dst, XMMRegister src, int mask) { + assert(VM_Version::supports_clmul(), ""); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, VEX_OPCODE_0F_3A); + emit_int8(0x44); + emit_int8((unsigned char)(0xC0 | encode)); + emit_int8((unsigned char)mask); +} + +// Carry-Less Multiplication Quadword void Assembler::vpclmulqdq(XMMRegister dst, XMMRegister nds, XMMRegister src, int mask) { assert(VM_Version::supports_avx() && VM_Version::supports_clmul(), ""); bool vector256 = false; diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/cpu/x86/vm/assembler_x86.hpp --- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -1837,6 +1837,7 @@ void vpbroadcastd(XMMRegister dst, XMMRegister src); // Carry-Less Multiplication Quadword + void pclmulqdq(XMMRegister dst, XMMRegister src, int mask); void vpclmulqdq(XMMRegister dst, XMMRegister nds, XMMRegister src, int mask); // AVX instruction which is used to clear upper 128 bits of YMM registers and diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/cpu/x86/vm/cppInterpreterGenerator_x86.hpp --- a/hotspot/src/cpu/x86/vm/cppInterpreterGenerator_x86.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/cpu/x86/vm/cppInterpreterGenerator_x86.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -27,21 +27,6 @@ protected: -#if 0 - address generate_asm_interpreter_entry(bool synchronized); - address generate_native_entry(bool synchronized); - address generate_abstract_entry(void); - address generate_math_entry(AbstractInterpreter::MethodKind kind); - address generate_empty_entry(void); - address generate_accessor_entry(void); - address generate_Reference_get_entry(void); - void lock_method(void); - void generate_stack_overflow_check(void); - - void generate_counter_incr(Label* overflow, Label* profile_method, Label* profile_method_continue); - void generate_counter_overflow(Label* do_continue); -#endif - void generate_more_monitors(); void generate_deopt_handling(); address generate_interpreter_frame_manager(bool synchronized); // C++ interpreter only diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp --- a/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -66,9 +66,6 @@ #define __ _masm-> #define STATE(field_name) (Address(state, byte_offset_of(BytecodeInterpreter, field_name))) -Label fast_accessor_slow_entry_path; // fast accessor methods need to be able to jmp to unsynchronized - // c++ interpreter entry point this holds that entry point label. - // default registers for state and sender_sp // state and sender_sp are the same on 32bit because we have no choice. // state could be rsi on 64bit but it is an arg reg and not callee save @@ -660,7 +657,6 @@ // generate_method_entry) so the guard should work for them too. // - // monitor entry size: see picture of stack set (generate_method_entry) and frame_i486.hpp const int entry_size = frame::interpreter_frame_monitor_size() * wordSize; // total overhead size: entry_size + (saved rbp, thru expr stack bottom). @@ -794,156 +790,6 @@ __ lock_object(monitor); } -// Call an accessor method (assuming it is resolved, otherwise drop into vanilla (slow path) entry - -address InterpreterGenerator::generate_accessor_entry(void) { - - // rbx: Method* - - // rsi/r13: senderSP must preserved for slow path, set SP to it on fast path - - Label xreturn_path; - - // do fastpath for resolved accessor methods - if (UseFastAccessorMethods) { - - address entry_point = __ pc(); - - Label slow_path; - // If we need a safepoint check, generate full interpreter entry. - ExternalAddress state(SafepointSynchronize::address_of_state()); - __ cmp32(ExternalAddress(SafepointSynchronize::address_of_state()), - SafepointSynchronize::_not_synchronized); - - __ jcc(Assembler::notEqual, slow_path); - // ASM/C++ Interpreter - // Code: _aload_0, _(i|a)getfield, _(i|a)return or any rewrites thereof; parameter size = 1 - // Note: We can only use this code if the getfield has been resolved - // and if we don't have a null-pointer exception => check for - // these conditions first and use slow path if necessary. - // rbx,: method - // rcx: receiver - __ movptr(rax, Address(rsp, wordSize)); - - // check if local 0 != NULL and read field - __ testptr(rax, rax); - __ jcc(Assembler::zero, slow_path); - - // read first instruction word and extract bytecode @ 1 and index @ 2 - __ movptr(rdx, Address(rbx, Method::const_offset())); - __ movptr(rdi, Address(rdx, ConstMethod::constants_offset())); - __ movl(rdx, Address(rdx, ConstMethod::codes_offset())); - // Shift codes right to get the index on the right. - // The bytecode fetched looks like <0xb4><0x2a> - __ shrl(rdx, 2*BitsPerByte); - __ shll(rdx, exact_log2(in_words(ConstantPoolCacheEntry::size()))); - __ movptr(rdi, Address(rdi, ConstantPool::cache_offset_in_bytes())); - - // rax,: local 0 - // rbx,: method - // rcx: receiver - do not destroy since it is needed for slow path! - // rcx: scratch - // rdx: constant pool cache index - // rdi: constant pool cache - // rsi/r13: sender sp - - // check if getfield has been resolved and read constant pool cache entry - // check the validity of the cache entry by testing whether _indices field - // contains Bytecode::_getfield in b1 byte. - assert(in_words(ConstantPoolCacheEntry::size()) == 4, "adjust shift below"); - __ movl(rcx, - Address(rdi, - rdx, - Address::times_ptr, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::indices_offset())); - __ shrl(rcx, 2*BitsPerByte); - __ andl(rcx, 0xFF); - __ cmpl(rcx, Bytecodes::_getfield); - __ jcc(Assembler::notEqual, slow_path); - - // Note: constant pool entry is not valid before bytecode is resolved - __ movptr(rcx, - Address(rdi, - rdx, - Address::times_ptr, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::f2_offset())); - __ movl(rdx, - Address(rdi, - rdx, - Address::times_ptr, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::flags_offset())); - - Label notByte, notShort, notChar; - const Address field_address (rax, rcx, Address::times_1); - - // Need to differentiate between igetfield, agetfield, bgetfield etc. - // because they are different sizes. - // Use the type from the constant pool cache - __ shrl(rdx, ConstantPoolCacheEntry::tos_state_shift); - // Make sure we don't need to mask rdx after the above shift - ConstantPoolCacheEntry::verify_tos_state_shift(); -#ifdef _LP64 - Label notObj; - __ cmpl(rdx, atos); - __ jcc(Assembler::notEqual, notObj); - // atos - __ movptr(rax, field_address); - __ jmp(xreturn_path); - - __ bind(notObj); -#endif // _LP64 - __ cmpl(rdx, btos); - __ jcc(Assembler::notEqual, notByte); - __ load_signed_byte(rax, field_address); - __ jmp(xreturn_path); - - __ bind(notByte); - __ cmpl(rdx, stos); - __ jcc(Assembler::notEqual, notShort); - __ load_signed_short(rax, field_address); - __ jmp(xreturn_path); - - __ bind(notShort); - __ cmpl(rdx, ctos); - __ jcc(Assembler::notEqual, notChar); - __ load_unsigned_short(rax, field_address); - __ jmp(xreturn_path); - - __ bind(notChar); -#ifdef ASSERT - Label okay; -#ifndef _LP64 - __ cmpl(rdx, atos); - __ jcc(Assembler::equal, okay); -#endif // _LP64 - __ cmpl(rdx, itos); - __ jcc(Assembler::equal, okay); - __ stop("what type is this?"); - __ bind(okay); -#endif // ASSERT - // All the rest are a 32 bit wordsize - __ movl(rax, field_address); - - __ bind(xreturn_path); - - // _ireturn/_areturn - __ pop(rdi); // get return address - __ mov(rsp, sender_sp_on_entry); // set sp to sender sp - __ jmp(rdi); - - // generate a vanilla interpreter entry as the slow path - __ bind(slow_path); - // We will enter c++ interpreter looking like it was - // called by the call_stub this will cause it to return - // a tosca result to the invoker which might have been - // the c++ interpreter itself. - - __ jmp(fast_accessor_slow_entry_path); - return entry_point; - - } else { - return NULL; - } - -} - address InterpreterGenerator::generate_Reference_get_entry(void) { #if INCLUDE_ALL_GCS if (UseG1GC) { @@ -961,7 +807,7 @@ // If G1 is not enabled then attempt to go through the accessor entry point // Reference.get is an accessor - return generate_accessor_entry(); + return generate_jump_to_normal_entry(); } // @@ -1670,10 +1516,6 @@ address entry_point = __ pc(); - // Fast accessor methods share this entry point. - // This works because frame manager is in the same codelet - if (UseFastAccessorMethods && !synchronized) __ bind(fast_accessor_slow_entry_path); - Label dispatch_entry_2; __ movptr(rcx, sender_sp_on_entry); __ movptr(state, (int32_t)NULL_WORD); // no current activation @@ -2212,40 +2054,6 @@ return entry_point; } -address AbstractInterpreterGenerator::generate_method_entry(AbstractInterpreter::MethodKind kind) { - // determine code generation flags - bool synchronized = false; - address entry_point = NULL; - - switch (kind) { - case Interpreter::zerolocals : break; - case Interpreter::zerolocals_synchronized: synchronized = true; break; - case Interpreter::native : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(false); break; - case Interpreter::native_synchronized : entry_point = ((InterpreterGenerator*)this)->generate_native_entry(true); break; - case Interpreter::empty : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry(); break; - case Interpreter::accessor : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry(); break; - case Interpreter::abstract : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry(); break; - - case Interpreter::java_lang_math_sin : // fall thru - case Interpreter::java_lang_math_cos : // fall thru - case Interpreter::java_lang_math_tan : // fall thru - case Interpreter::java_lang_math_abs : // fall thru - case Interpreter::java_lang_math_log : // fall thru - case Interpreter::java_lang_math_log10 : // fall thru - case Interpreter::java_lang_math_sqrt : // fall thru - case Interpreter::java_lang_math_pow : // fall thru - case Interpreter::java_lang_math_exp : // fall thru - entry_point = ((InterpreterGenerator*)this)->generate_math_entry(kind); break; - case Interpreter::java_lang_ref_reference_get - : entry_point = ((InterpreterGenerator*)this)->generate_Reference_get_entry(); break; - default : ShouldNotReachHere(); break; - } - - if (entry_point) return entry_point; - - return ((InterpreterGenerator*)this)->generate_normal_entry(synchronized); - -} InterpreterGenerator::InterpreterGenerator(StubQueue* code) : CppInterpreterGenerator(code) { diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/cpu/x86/vm/interpreterGenerator_x86.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/cpu/x86/vm/interpreterGenerator_x86.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "asm/macroAssembler.hpp" +#include "interpreter/interpreter.hpp" +#include "interpreter/interpreterGenerator.hpp" +#include "interpreter/interpreterRuntime.hpp" +#include "interpreter/interp_masm.hpp" + +#define __ _masm-> + +// Jump into normal path for accessor and empty entry to jump to normal entry +// The "fast" optimization don't update compilation count therefore can disable inlining +// for these functions that should be inlined. +address InterpreterGenerator::generate_jump_to_normal_entry(void) { + address entry_point = __ pc(); + + assert(Interpreter::entry_for_kind(Interpreter::zerolocals) != NULL, "should already be generated"); + __ jump(RuntimeAddress(Interpreter::entry_for_kind(Interpreter::zerolocals))); + return entry_point; +} + +// Abstract method entry +// Attempt to execute abstract method. Throw exception +address InterpreterGenerator::generate_abstract_entry(void) { + + address entry_point = __ pc(); + + // abstract method entry + +#ifndef CC_INTERP + // pop return address, reset last_sp to NULL + __ empty_expression_stack(); + __ restore_bcp(); // rsi must be correct for exception handler (was destroyed) + __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) +#endif + + // throw exception + __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError)); + // the call_VM checks for exception, so we should never return here. + __ should_not_reach_here(); + + return entry_point; +} diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/cpu/x86/vm/interpreterGenerator_x86.hpp --- a/hotspot/src/cpu/x86/vm/interpreterGenerator_x86.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/cpu/x86/vm/interpreterGenerator_x86.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -36,8 +36,9 @@ address generate_native_entry(bool synchronized); address generate_abstract_entry(void); address generate_math_entry(AbstractInterpreter::MethodKind kind); - address generate_empty_entry(void); - address generate_accessor_entry(void); + address generate_jump_to_normal_entry(void); + address generate_accessor_entry(void) { return generate_jump_to_normal_entry(); } + address generate_empty_entry(void) { return generate_jump_to_normal_entry(); } address generate_Reference_get_entry(); address generate_CRC32_update_entry(); address generate_CRC32_updateBytes_entry(AbstractInterpreter::MethodKind kind); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/cpu/x86/vm/interpreter_x86_32.cpp --- a/hotspot/src/cpu/x86/vm/interpreter_x86_32.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/cpu/x86/vm/interpreter_x86_32.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -67,45 +67,6 @@ } -// -// Various method entries (that c++ and asm interpreter agree upon) -//------------------------------------------------------------------------------------------------------------------------ -// -// - -// Empty method, generate a very fast return. - -address InterpreterGenerator::generate_empty_entry(void) { - - // rbx,: Method* - // rcx: receiver (unused) - // rsi: previous interpreter state (C++ interpreter) must preserve - // rsi: sender sp must set sp to this value on return - - if (!UseFastEmptyMethods) return NULL; - - address entry_point = __ pc(); - - // If we need a safepoint check, generate full interpreter entry. - Label slow_path; - ExternalAddress state(SafepointSynchronize::address_of_state()); - __ cmp32(ExternalAddress(SafepointSynchronize::address_of_state()), - SafepointSynchronize::_not_synchronized); - __ jcc(Assembler::notEqual, slow_path); - - // do nothing for empty methods (do not even increment invocation counter) - // Code: _return - // _return - // return w/o popping parameters - __ pop(rax); - __ mov(rsp, rsi); - __ jmp(rax); - - __ bind(slow_path); - (void) generate_normal_entry(false); - return entry_point; -} - address InterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKind kind) { // rbx,: Method* @@ -216,36 +177,6 @@ } -// Abstract method entry -// Attempt to execute abstract method. Throw exception -address InterpreterGenerator::generate_abstract_entry(void) { - - // rbx,: Method* - // rcx: receiver (unused) - // rsi: previous interpreter state (C++ interpreter) must preserve - - // rsi: sender SP - - address entry_point = __ pc(); - - // abstract method entry - -#ifndef CC_INTERP - // pop return address, reset last_sp to NULL - __ empty_expression_stack(); - __ restore_bcp(); // rsi must be correct for exception handler (was destroyed) - __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) -#endif - - // throw exception - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError)); - // the call_VM checks for exception, so we should never return here. - __ should_not_reach_here(); - - return entry_point; -} - - void Deoptimization::unwind_callee_save_values(frame* f, vframeArray* vframe_array) { // This code is sort of the equivalent of C2IAdapter::setup_stack_frame back in diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/cpu/x86/vm/interpreter_x86_64.cpp --- a/hotspot/src/cpu/x86/vm/interpreter_x86_64.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/cpu/x86/vm/interpreter_x86_64.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -301,66 +301,6 @@ return entry_point; } - -// Abstract method entry -// Attempt to execute abstract method. Throw exception -address InterpreterGenerator::generate_abstract_entry(void) { - // rbx: Method* - // r13: sender SP - - address entry_point = __ pc(); - - // abstract method entry - -#ifndef CC_INTERP - // pop return address, reset last_sp to NULL - __ empty_expression_stack(); - __ restore_bcp(); // rsi must be correct for exception handler (was destroyed) - __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) -#endif - - // throw exception - __ call_VM(noreg, CAST_FROM_FN_PTR(address, - InterpreterRuntime::throw_AbstractMethodError)); - // the call_VM checks for exception, so we should never return here. - __ should_not_reach_here(); - - return entry_point; -} - - -// Empty method, generate a very fast return. - -address InterpreterGenerator::generate_empty_entry(void) { - // rbx: Method* - // r13: sender sp must set sp to this value on return - - if (!UseFastEmptyMethods) { - return NULL; - } - - address entry_point = __ pc(); - - // If we need a safepoint check, generate full interpreter entry. - Label slow_path; - __ cmp32(ExternalAddress(SafepointSynchronize::address_of_state()), - SafepointSynchronize::_not_synchronized); - __ jcc(Assembler::notEqual, slow_path); - - // do nothing for empty methods (do not even increment invocation counter) - // Code: _return - // _return - // return w/o popping parameters - __ pop(rax); - __ mov(rsp, r13); - __ jmp(rax); - - __ bind(slow_path); - (void) generate_normal_entry(false); - return entry_point; - -} - void Deoptimization::unwind_callee_save_values(frame* f, vframeArray* vframe_array) { // This code is sort of the equivalent of C2IAdapter::setup_stack_frame back in diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -7316,17 +7316,34 @@ * Fold 128-bit data chunk */ void MacroAssembler::fold_128bit_crc32(XMMRegister xcrc, XMMRegister xK, XMMRegister xtmp, Register buf, int offset) { - vpclmulhdq(xtmp, xK, xcrc); // [123:64] - vpclmulldq(xcrc, xK, xcrc); // [63:0] - vpxor(xcrc, xcrc, Address(buf, offset), false /* vector256 */); - pxor(xcrc, xtmp); + if (UseAVX > 0) { + vpclmulhdq(xtmp, xK, xcrc); // [123:64] + vpclmulldq(xcrc, xK, xcrc); // [63:0] + vpxor(xcrc, xcrc, Address(buf, offset), false /* vector256 */); + pxor(xcrc, xtmp); + } else { + movdqa(xtmp, xcrc); + pclmulhdq(xtmp, xK); // [123:64] + pclmulldq(xcrc, xK); // [63:0] + pxor(xcrc, xtmp); + movdqu(xtmp, Address(buf, offset)); + pxor(xcrc, xtmp); + } } void MacroAssembler::fold_128bit_crc32(XMMRegister xcrc, XMMRegister xK, XMMRegister xtmp, XMMRegister xbuf) { - vpclmulhdq(xtmp, xK, xcrc); - vpclmulldq(xcrc, xK, xcrc); - pxor(xcrc, xbuf); - pxor(xcrc, xtmp); + if (UseAVX > 0) { + vpclmulhdq(xtmp, xK, xcrc); + vpclmulldq(xcrc, xK, xcrc); + pxor(xcrc, xbuf); + pxor(xcrc, xtmp); + } else { + movdqa(xtmp, xcrc); + pclmulhdq(xtmp, xK); + pclmulldq(xcrc, xK); + pxor(xcrc, xbuf); + pxor(xcrc, xtmp); + } } /** @@ -7444,9 +7461,17 @@ // Fold 128 bits in xmm1 down into 32 bits in crc register. BIND(L_fold_128b); movdqu(xmm0, ExternalAddress(StubRoutines::x86::crc_by128_masks_addr())); - vpclmulqdq(xmm2, xmm0, xmm1, 0x1); - vpand(xmm3, xmm0, xmm2, false /* vector256 */); - vpclmulqdq(xmm0, xmm0, xmm3, 0x1); + if (UseAVX > 0) { + vpclmulqdq(xmm2, xmm0, xmm1, 0x1); + vpand(xmm3, xmm0, xmm2, false /* vector256 */); + vpclmulqdq(xmm0, xmm0, xmm3, 0x1); + } else { + movdqa(xmm2, xmm0); + pclmulqdq(xmm2, xmm1, 0x1); + movdqa(xmm3, xmm0); + pand(xmm3, xmm2); + pclmulqdq(xmm0, xmm3, 0x1); + } psrldq(xmm1, 8); psrldq(xmm2, 4); pxor(xmm0, xmm1); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -966,6 +966,16 @@ void mulss(XMMRegister dst, Address src) { Assembler::mulss(dst, src); } void mulss(XMMRegister dst, AddressLiteral src); + // Carry-Less Multiplication Quadword + void pclmulldq(XMMRegister dst, XMMRegister src) { + // 0x00 - multiply lower 64 bits [0:63] + Assembler::pclmulqdq(dst, src, 0x00); + } + void pclmulhdq(XMMRegister dst, XMMRegister src) { + // 0x11 - multiply upper 64 bits [64:127] + Assembler::pclmulqdq(dst, src, 0x11); + } + void sqrtsd(XMMRegister dst, XMMRegister src) { Assembler::sqrtsd(dst, src); } void sqrtsd(XMMRegister dst, Address src) { Assembler::sqrtsd(dst, src); } void sqrtsd(XMMRegister dst, AddressLiteral src); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/cpu/x86/vm/templateInterpreter_x86.cpp --- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -38,7 +38,7 @@ int callee_locals, bool is_top_frame) { // Note: This calculation must exactly parallel the frame setup - // in AbstractInterpreterGenerator::generate_method_entry. + // in InterpreterGenerator::generate_fixed_frame. // fixed size of an interpreter frame: int overhead = frame::sender_sp_offset - diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp --- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -468,10 +468,10 @@ // rax, // NOTE: since the additional locals are also always pushed (wasn't obvious in - // generate_method_entry) so the guard should work for them too. + // generate_fixed_frame) so the guard should work for them too. // - // monitor entry size: see picture of stack set (generate_method_entry) and frame_x86.hpp + // monitor entry size: see picture of stack in frame_x86.hpp const int entry_size = frame::interpreter_frame_monitor_size() * wordSize; // total overhead size: entry_size + (saved rbp, thru expr stack bottom). @@ -633,145 +633,6 @@ __ movptr(Address(rsp, 0), rsp); // set expression stack bottom } -// End of helpers - -// -// Various method entries -//------------------------------------------------------------------------------------------------------------------------ -// -// - -// Call an accessor method (assuming it is resolved, otherwise drop into vanilla (slow path) entry - -address InterpreterGenerator::generate_accessor_entry(void) { - - // rbx,: Method* - // rcx: receiver (preserve for slow entry into asm interpreter) - - // rsi: senderSP must preserved for slow path, set SP to it on fast path - - address entry_point = __ pc(); - Label xreturn_path; - - // do fastpath for resolved accessor methods - if (UseFastAccessorMethods) { - Label slow_path; - // If we need a safepoint check, generate full interpreter entry. - ExternalAddress state(SafepointSynchronize::address_of_state()); - __ cmp32(ExternalAddress(SafepointSynchronize::address_of_state()), - SafepointSynchronize::_not_synchronized); - - __ jcc(Assembler::notEqual, slow_path); - // ASM/C++ Interpreter - // Code: _aload_0, _(i|a)getfield, _(i|a)return or any rewrites thereof; parameter size = 1 - // Note: We can only use this code if the getfield has been resolved - // and if we don't have a null-pointer exception => check for - // these conditions first and use slow path if necessary. - // rbx,: method - // rcx: receiver - __ movptr(rax, Address(rsp, wordSize)); - - // check if local 0 != NULL and read field - __ testptr(rax, rax); - __ jcc(Assembler::zero, slow_path); - - // read first instruction word and extract bytecode @ 1 and index @ 2 - __ movptr(rdx, Address(rbx, Method::const_offset())); - __ movptr(rdi, Address(rdx, ConstMethod::constants_offset())); - __ movl(rdx, Address(rdx, ConstMethod::codes_offset())); - // Shift codes right to get the index on the right. - // The bytecode fetched looks like <0xb4><0x2a> - __ shrl(rdx, 2*BitsPerByte); - __ shll(rdx, exact_log2(in_words(ConstantPoolCacheEntry::size()))); - __ movptr(rdi, Address(rdi, ConstantPool::cache_offset_in_bytes())); - - // rax,: local 0 - // rbx,: method - // rcx: receiver - do not destroy since it is needed for slow path! - // rcx: scratch - // rdx: constant pool cache index - // rdi: constant pool cache - // rsi: sender sp - - // check if getfield has been resolved and read constant pool cache entry - // check the validity of the cache entry by testing whether _indices field - // contains Bytecode::_getfield in b1 byte. - assert(in_words(ConstantPoolCacheEntry::size()) == 4, "adjust shift below"); - __ movl(rcx, - Address(rdi, - rdx, - Address::times_ptr, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::indices_offset())); - __ shrl(rcx, 2*BitsPerByte); - __ andl(rcx, 0xFF); - __ cmpl(rcx, Bytecodes::_getfield); - __ jcc(Assembler::notEqual, slow_path); - - // Note: constant pool entry is not valid before bytecode is resolved - __ movptr(rcx, - Address(rdi, - rdx, - Address::times_ptr, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::f2_offset())); - __ movl(rdx, - Address(rdi, - rdx, - Address::times_ptr, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::flags_offset())); - - Label notByte, notShort, notChar; - const Address field_address (rax, rcx, Address::times_1); - - // Need to differentiate between igetfield, agetfield, bgetfield etc. - // because they are different sizes. - // Use the type from the constant pool cache - __ shrl(rdx, ConstantPoolCacheEntry::tos_state_shift); - // Make sure we don't need to mask rdx after the above shift - ConstantPoolCacheEntry::verify_tos_state_shift(); - __ cmpl(rdx, btos); - __ jcc(Assembler::notEqual, notByte); - __ load_signed_byte(rax, field_address); - __ jmp(xreturn_path); - - __ bind(notByte); - __ cmpl(rdx, stos); - __ jcc(Assembler::notEqual, notShort); - __ load_signed_short(rax, field_address); - __ jmp(xreturn_path); - - __ bind(notShort); - __ cmpl(rdx, ctos); - __ jcc(Assembler::notEqual, notChar); - __ load_unsigned_short(rax, field_address); - __ jmp(xreturn_path); - - __ bind(notChar); -#ifdef ASSERT - Label okay; - __ cmpl(rdx, atos); - __ jcc(Assembler::equal, okay); - __ cmpl(rdx, itos); - __ jcc(Assembler::equal, okay); - __ stop("what type is this?"); - __ bind(okay); -#endif // ASSERT - // All the rest are a 32 bit wordsize - // This is ok for now. Since fast accessors should be going away - __ movptr(rax, field_address); - - __ bind(xreturn_path); - - // _ireturn/_areturn - __ pop(rdi); // get return address - __ mov(rsp, rsi); // set sp to sender sp - __ jmp(rdi); - - // generate a vanilla interpreter entry as the slow path - __ bind(slow_path); - - (void) generate_normal_entry(false); - return entry_point; - } - return NULL; - -} // Method entry for java.lang.ref.Reference.get. address InterpreterGenerator::generate_Reference_get_entry(void) { @@ -862,7 +723,7 @@ // If G1 is not enabled then attempt to go through the accessor entry point // Reference.get is an accessor - return generate_accessor_entry(); + return generate_jump_to_normal_entry(); } /** @@ -1557,100 +1418,6 @@ return entry_point; } -//------------------------------------------------------------------------------------------------------------------------ -// Entry points -// -// Here we generate the various kind of entries into the interpreter. -// The two main entry type are generic bytecode methods and native call method. -// These both come in synchronized and non-synchronized versions but the -// frame layout they create is very similar. The other method entry -// types are really just special purpose entries that are really entry -// and interpretation all in one. These are for trivial methods like -// accessor, empty, or special math methods. -// -// When control flow reaches any of the entry types for the interpreter -// the following holds -> -// -// Arguments: -// -// rbx,: Method* -// rcx: receiver -// -// -// Stack layout immediately at entry -// -// [ return address ] <--- rsp -// [ parameter n ] -// ... -// [ parameter 1 ] -// [ expression stack ] (caller's java expression stack) - -// Assuming that we don't go to one of the trivial specialized -// entries the stack will look like below when we are ready to execute -// the first bytecode (or call the native routine). The register usage -// will be as the template based interpreter expects (see interpreter_x86.hpp). -// -// local variables follow incoming parameters immediately; i.e. -// the return address is moved to the end of the locals). -// -// [ monitor entry ] <--- rsp -// ... -// [ monitor entry ] -// [ expr. stack bottom ] -// [ saved rsi ] -// [ current rdi ] -// [ Method* ] -// [ saved rbp, ] <--- rbp, -// [ return address ] -// [ local variable m ] -// ... -// [ local variable 1 ] -// [ parameter n ] -// ... -// [ parameter 1 ] <--- rdi - -address AbstractInterpreterGenerator::generate_method_entry(AbstractInterpreter::MethodKind kind) { - // determine code generation flags - bool synchronized = false; - address entry_point = NULL; - InterpreterGenerator* ig_this = (InterpreterGenerator*)this; - - switch (kind) { - case Interpreter::zerolocals : break; - case Interpreter::zerolocals_synchronized: synchronized = true; break; - case Interpreter::native : entry_point = ig_this->generate_native_entry(false); break; - case Interpreter::native_synchronized : entry_point = ig_this->generate_native_entry(true); break; - case Interpreter::empty : entry_point = ig_this->generate_empty_entry(); break; - case Interpreter::accessor : entry_point = ig_this->generate_accessor_entry(); break; - case Interpreter::abstract : entry_point = ig_this->generate_abstract_entry(); break; - - case Interpreter::java_lang_math_sin : // fall thru - case Interpreter::java_lang_math_cos : // fall thru - case Interpreter::java_lang_math_tan : // fall thru - case Interpreter::java_lang_math_abs : // fall thru - case Interpreter::java_lang_math_log : // fall thru - case Interpreter::java_lang_math_log10 : // fall thru - case Interpreter::java_lang_math_sqrt : // fall thru - case Interpreter::java_lang_math_pow : // fall thru - case Interpreter::java_lang_math_exp : entry_point = ig_this->generate_math_entry(kind); break; - case Interpreter::java_lang_ref_reference_get - : entry_point = ig_this->generate_Reference_get_entry(); break; - case Interpreter::java_util_zip_CRC32_update - : entry_point = ig_this->generate_CRC32_update_entry(); break; - case Interpreter::java_util_zip_CRC32_updateBytes - : // fall thru - case Interpreter::java_util_zip_CRC32_updateByteBuffer - : entry_point = ig_this->generate_CRC32_updateBytes_entry(kind); break; - default: - fatal(err_msg("unexpected method kind: %d", kind)); - break; - } - - if (entry_point) return entry_point; - - return ig_this->generate_normal_entry(synchronized); - -} // These should never be compiled since the interpreter will prefer // the compiled version to the intrinsic version. diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp --- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -400,7 +400,7 @@ // page mechanism will work for that. // // NOTE: Since the additional locals are also always pushed (wasn't -// obvious in generate_method_entry) so the guard should work for them +// obvious in generate_fixed_frame) so the guard should work for them // too. // // Args: @@ -411,8 +411,7 @@ // rax void InterpreterGenerator::generate_stack_overflow_check(void) { - // monitor entry size: see picture of stack set - // (generate_method_entry) and frame_amd64.hpp + // monitor entry size: see picture of stack in frame_x86.hpp const int entry_size = frame::interpreter_frame_monitor_size() * wordSize; // total overhead size: entry_size + (saved rbp through expr stack @@ -600,153 +599,6 @@ // End of helpers -// Various method entries -//------------------------------------------------------------------------------------------------------------------------ -// -// - -// Call an accessor method (assuming it is resolved, otherwise drop -// into vanilla (slow path) entry -address InterpreterGenerator::generate_accessor_entry(void) { - // rbx: Method* - - // r13: senderSP must preserver for slow path, set SP to it on fast path - - address entry_point = __ pc(); - Label xreturn_path; - - // do fastpath for resolved accessor methods - if (UseFastAccessorMethods) { - // Code: _aload_0, _(i|a)getfield, _(i|a)return or any rewrites - // thereof; parameter size = 1 - // Note: We can only use this code if the getfield has been resolved - // and if we don't have a null-pointer exception => check for - // these conditions first and use slow path if necessary. - Label slow_path; - // If we need a safepoint check, generate full interpreter entry. - __ cmp32(ExternalAddress(SafepointSynchronize::address_of_state()), - SafepointSynchronize::_not_synchronized); - - __ jcc(Assembler::notEqual, slow_path); - // rbx: method - __ movptr(rax, Address(rsp, wordSize)); - - // check if local 0 != NULL and read field - __ testptr(rax, rax); - __ jcc(Assembler::zero, slow_path); - - // read first instruction word and extract bytecode @ 1 and index @ 2 - __ movptr(rdx, Address(rbx, Method::const_offset())); - __ movptr(rdi, Address(rdx, ConstMethod::constants_offset())); - __ movl(rdx, Address(rdx, ConstMethod::codes_offset())); - // Shift codes right to get the index on the right. - // The bytecode fetched looks like <0xb4><0x2a> - __ shrl(rdx, 2 * BitsPerByte); - __ shll(rdx, exact_log2(in_words(ConstantPoolCacheEntry::size()))); - __ movptr(rdi, Address(rdi, ConstantPool::cache_offset_in_bytes())); - - // rax: local 0 - // rbx: method - // rdx: constant pool cache index - // rdi: constant pool cache - - // check if getfield has been resolved and read constant pool cache entry - // check the validity of the cache entry by testing whether _indices field - // contains Bytecode::_getfield in b1 byte. - assert(in_words(ConstantPoolCacheEntry::size()) == 4, - "adjust shift below"); - __ movl(rcx, - Address(rdi, - rdx, - Address::times_8, - ConstantPoolCache::base_offset() + - ConstantPoolCacheEntry::indices_offset())); - __ shrl(rcx, 2 * BitsPerByte); - __ andl(rcx, 0xFF); - __ cmpl(rcx, Bytecodes::_getfield); - __ jcc(Assembler::notEqual, slow_path); - - // Note: constant pool entry is not valid before bytecode is resolved - __ movptr(rcx, - Address(rdi, - rdx, - Address::times_8, - ConstantPoolCache::base_offset() + - ConstantPoolCacheEntry::f2_offset())); - // edx: flags - __ movl(rdx, - Address(rdi, - rdx, - Address::times_8, - ConstantPoolCache::base_offset() + - ConstantPoolCacheEntry::flags_offset())); - - Label notObj, notInt, notByte, notShort; - const Address field_address(rax, rcx, Address::times_1); - - // Need to differentiate between igetfield, agetfield, bgetfield etc. - // because they are different sizes. - // Use the type from the constant pool cache - __ shrl(rdx, ConstantPoolCacheEntry::tos_state_shift); - // Make sure we don't need to mask edx after the above shift - ConstantPoolCacheEntry::verify_tos_state_shift(); - - __ cmpl(rdx, atos); - __ jcc(Assembler::notEqual, notObj); - // atos - __ load_heap_oop(rax, field_address); - __ jmp(xreturn_path); - - __ bind(notObj); - __ cmpl(rdx, itos); - __ jcc(Assembler::notEqual, notInt); - // itos - __ movl(rax, field_address); - __ jmp(xreturn_path); - - __ bind(notInt); - __ cmpl(rdx, btos); - __ jcc(Assembler::notEqual, notByte); - // btos - __ load_signed_byte(rax, field_address); - __ jmp(xreturn_path); - - __ bind(notByte); - __ cmpl(rdx, stos); - __ jcc(Assembler::notEqual, notShort); - // stos - __ load_signed_short(rax, field_address); - __ jmp(xreturn_path); - - __ bind(notShort); -#ifdef ASSERT - Label okay; - __ cmpl(rdx, ctos); - __ jcc(Assembler::equal, okay); - __ stop("what type is this?"); - __ bind(okay); -#endif - // ctos - __ load_unsigned_short(rax, field_address); - - __ bind(xreturn_path); - - // _ireturn/_areturn - __ pop(rdi); - __ mov(rsp, r13); - __ jmp(rdi); - __ ret(0); - - // generate a vanilla interpreter entry as the slow path - __ bind(slow_path); - (void) generate_normal_entry(false); - } else { - (void) generate_normal_entry(false); - } - - return entry_point; -} - // Method entry for java.lang.ref.Reference.get. address InterpreterGenerator::generate_Reference_get_entry(void) { #if INCLUDE_ALL_GCS @@ -773,8 +625,6 @@ // and so we don't need to call the G1 pre-barrier. Thus we can use the // regular method entry code to generate the NPE. // - // This code is based on generate_accessor_enty. - // // rbx: Method* // r13: senderSP must preserve for slow path, set SP to it on fast path @@ -832,7 +682,7 @@ // If G1 is not enabled then attempt to go through the accessor entry point // Reference.get is an accessor - return generate_accessor_entry(); + return generate_jump_to_normal_entry(); } /** @@ -1566,100 +1416,6 @@ return entry_point; } -// Entry points -// -// Here we generate the various kind of entries into the interpreter. -// The two main entry type are generic bytecode methods and native -// call method. These both come in synchronized and non-synchronized -// versions but the frame layout they create is very similar. The -// other method entry types are really just special purpose entries -// that are really entry and interpretation all in one. These are for -// trivial methods like accessor, empty, or special math methods. -// -// When control flow reaches any of the entry types for the interpreter -// the following holds -> -// -// Arguments: -// -// rbx: Method* -// -// Stack layout immediately at entry -// -// [ return address ] <--- rsp -// [ parameter n ] -// ... -// [ parameter 1 ] -// [ expression stack ] (caller's java expression stack) - -// Assuming that we don't go to one of the trivial specialized entries -// the stack will look like below when we are ready to execute the -// first bytecode (or call the native routine). The register usage -// will be as the template based interpreter expects (see -// interpreter_amd64.hpp). -// -// local variables follow incoming parameters immediately; i.e. -// the return address is moved to the end of the locals). -// -// [ monitor entry ] <--- rsp -// ... -// [ monitor entry ] -// [ expr. stack bottom ] -// [ saved r13 ] -// [ current r14 ] -// [ Method* ] -// [ saved ebp ] <--- rbp -// [ return address ] -// [ local variable m ] -// ... -// [ local variable 1 ] -// [ parameter n ] -// ... -// [ parameter 1 ] <--- r14 - -address AbstractInterpreterGenerator::generate_method_entry( - AbstractInterpreter::MethodKind kind) { - // determine code generation flags - bool synchronized = false; - address entry_point = NULL; - InterpreterGenerator* ig_this = (InterpreterGenerator*)this; - - switch (kind) { - case Interpreter::zerolocals : break; - case Interpreter::zerolocals_synchronized: synchronized = true; break; - case Interpreter::native : entry_point = ig_this->generate_native_entry(false); break; - case Interpreter::native_synchronized : entry_point = ig_this->generate_native_entry(true); break; - case Interpreter::empty : entry_point = ig_this->generate_empty_entry(); break; - case Interpreter::accessor : entry_point = ig_this->generate_accessor_entry(); break; - case Interpreter::abstract : entry_point = ig_this->generate_abstract_entry(); break; - - case Interpreter::java_lang_math_sin : // fall thru - case Interpreter::java_lang_math_cos : // fall thru - case Interpreter::java_lang_math_tan : // fall thru - case Interpreter::java_lang_math_abs : // fall thru - case Interpreter::java_lang_math_log : // fall thru - case Interpreter::java_lang_math_log10 : // fall thru - case Interpreter::java_lang_math_sqrt : // fall thru - case Interpreter::java_lang_math_pow : // fall thru - case Interpreter::java_lang_math_exp : entry_point = ig_this->generate_math_entry(kind); break; - case Interpreter::java_lang_ref_reference_get - : entry_point = ig_this->generate_Reference_get_entry(); break; - case Interpreter::java_util_zip_CRC32_update - : entry_point = ig_this->generate_CRC32_update_entry(); break; - case Interpreter::java_util_zip_CRC32_updateBytes - : // fall thru - case Interpreter::java_util_zip_CRC32_updateByteBuffer - : entry_point = ig_this->generate_CRC32_updateBytes_entry(kind); break; - default: - fatal(err_msg("unexpected method kind: %d", kind)); - break; - } - - if (entry_point) { - return entry_point; - } - - return ig_this->generate_normal_entry(synchronized); -} // These should never be compiled since the interpreter will prefer // the compiled version to the intrinsic version. diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/cpu/x86/vm/vm_version_x86.cpp --- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -27,6 +27,7 @@ #include "asm/macroAssembler.inline.hpp" #include "memory/resourceArea.hpp" #include "runtime/java.hpp" +#include "runtime/os.hpp" #include "runtime/stubCodeGenerator.hpp" #include "vm_version_x86.hpp" @@ -514,7 +515,7 @@ (supports_tscinv() ? ", tscinv": ""), (supports_bmi1() ? ", bmi1" : ""), (supports_bmi2() ? ", bmi2" : "")); - _features_str = strdup(buf); + _features_str = os::strdup(buf); // UseSSE is set to the smaller of what hardware supports and what // the command line requires. I.e., you cannot set UseSSE to 2 on @@ -559,7 +560,7 @@ FLAG_SET_DEFAULT(UseCLMUL, false); } - if (UseCLMUL && (UseAVX > 0) && (UseSSE > 2)) { + if (UseCLMUL && (UseSSE > 2)) { if (FLAG_IS_DEFAULT(UseCRC32Intrinsics)) { UseCRC32Intrinsics = true; } @@ -805,6 +806,21 @@ } } } + if ((cpu_family() == 0x06) && + ((extended_cpu_model() == 0x36) || // Centerton + (extended_cpu_model() == 0x37) || // Silvermont + (extended_cpu_model() == 0x4D))) { +#ifdef COMPILER2 + if (FLAG_IS_DEFAULT(OptoScheduling)) { + OptoScheduling = true; + } +#endif + if (supports_sse4_2()) { // Silvermont + if (FLAG_IS_DEFAULT(UseUnalignedLoadStores)) { + UseUnalignedLoadStores = true; // use movdqu on newest Intel cpus + } + } + } } // Use count leading zeros count instruction if available. @@ -892,23 +908,25 @@ AllocatePrefetchDistance = allocate_prefetch_distance(); AllocatePrefetchStyle = allocate_prefetch_style(); - if( is_intel() && cpu_family() == 6 && supports_sse3() ) { - if( AllocatePrefetchStyle == 2 ) { // watermark prefetching on Core + if (is_intel() && cpu_family() == 6 && supports_sse3()) { + if (AllocatePrefetchStyle == 2) { // watermark prefetching on Core #ifdef _LP64 AllocatePrefetchDistance = 384; #else AllocatePrefetchDistance = 320; #endif } - if( supports_sse4_2() && supports_ht() ) { // Nehalem based cpus + if (supports_sse4_2() && supports_ht()) { // Nehalem based cpus AllocatePrefetchDistance = 192; AllocatePrefetchLines = 4; + } #ifdef COMPILER2 - if (AggressiveOpts && FLAG_IS_DEFAULT(UseFPUForSpilling)) { + if (supports_sse4_2()) { + if (FLAG_IS_DEFAULT(UseFPUForSpilling)) { FLAG_SET_DEFAULT(UseFPUForSpilling, true); } + } #endif - } } assert(AllocatePrefetchDistance % AllocatePrefetchStepSize == 0, "invalid value"); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp --- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2009, 2010, 2011 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -831,60 +831,6 @@ return generate_entry((address) CppInterpreter::normal_entry); } -address AbstractInterpreterGenerator::generate_method_entry( - AbstractInterpreter::MethodKind kind) { - address entry_point = NULL; - - switch (kind) { - case Interpreter::zerolocals: - case Interpreter::zerolocals_synchronized: - break; - - case Interpreter::native: - entry_point = ((InterpreterGenerator*) this)->generate_native_entry(false); - break; - - case Interpreter::native_synchronized: - entry_point = ((InterpreterGenerator*) this)->generate_native_entry(false); - break; - - case Interpreter::empty: - entry_point = ((InterpreterGenerator*) this)->generate_empty_entry(); - break; - - case Interpreter::accessor: - entry_point = ((InterpreterGenerator*) this)->generate_accessor_entry(); - break; - - case Interpreter::abstract: - entry_point = ((InterpreterGenerator*) this)->generate_abstract_entry(); - break; - - case Interpreter::java_lang_math_sin: - case Interpreter::java_lang_math_cos: - case Interpreter::java_lang_math_tan: - case Interpreter::java_lang_math_abs: - case Interpreter::java_lang_math_log: - case Interpreter::java_lang_math_log10: - case Interpreter::java_lang_math_sqrt: - case Interpreter::java_lang_math_pow: - case Interpreter::java_lang_math_exp: - entry_point = ((InterpreterGenerator*) this)->generate_math_entry(kind); - break; - - case Interpreter::java_lang_ref_reference_get: - entry_point = ((InterpreterGenerator*)this)->generate_Reference_get_entry(); - break; - - default: - ShouldNotReachHere(); - } - - if (entry_point == NULL) - entry_point = ((InterpreterGenerator*) this)->generate_normal_entry(false); - - return entry_point; -} InterpreterGenerator::InterpreterGenerator(StubQueue* code) : CppInterpreterGenerator(code) { diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/cpu/zero/vm/globals_zero.hpp --- a/hotspot/src/cpu/zero/vm/globals_zero.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/cpu/zero/vm/globals_zero.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2009, 2010, 2011 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -61,6 +61,12 @@ define_pd_global(uintx, TypeProfileLevel, 0); -#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct) +#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct) \ + product(bool, UseFastEmptyMethods, true, \ + "Use fast method entry code for empty methods") \ + \ + product(bool, UseFastAccessorMethods, true, \ + "Use fast method entry code for accessor methods") \ + \ #endif // CPU_ZERO_VM_GLOBALS_ZERO_HPP diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/cpu/zero/vm/interpreterGenerator_zero.hpp --- a/hotspot/src/cpu/zero/vm/interpreterGenerator_zero.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/cpu/zero/vm/interpreterGenerator_zero.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright 2007 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -39,4 +39,7 @@ address generate_accessor_entry(); address generate_Reference_get_entry(); + // Not supported + address generate_CRC32_update_entry() { return NULL; } + address generate_CRC32_updateBytes_entry(AbstractInterpreter::MethodKind kind) { return NULL; } #endif // CPU_ZERO_VM_INTERPRETERGENERATOR_ZERO_HPP diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/os/aix/vm/os_aix.cpp --- a/hotspot/src/os/aix/vm/os_aix.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/os/aix/vm/os_aix.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -58,6 +58,7 @@ #include "runtime/mutexLocker.hpp" #include "runtime/objectMonitor.hpp" #include "runtime/orderAccess.inline.hpp" +#include "runtime/os.hpp" #include "runtime/osThread.hpp" #include "runtime/perfMemory.hpp" #include "runtime/sharedRuntime.hpp" @@ -378,10 +379,10 @@ // default should be 4K. size_t data_page_size = SIZE_4K; { - void* p = ::malloc(SIZE_16M); + void* p = os::malloc(SIZE_16M, mtInternal); guarantee(p != NULL, "malloc failed"); data_page_size = os::Aix::query_pagesize(p); - ::free(p); + os::free(p); } // query default shm page size (LDR_CNTRL SHMPSIZE) diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/os/aix/vm/porting_aix.cpp --- a/hotspot/src/os/aix/vm/porting_aix.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/os/aix/vm/porting_aix.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -24,6 +24,8 @@ #include "asm/assembler.hpp" #include "memory/allocation.hpp" +#include "memory/allocation.inline.hpp" +#include "runtime/os.hpp" #include "loadlib_aix.hpp" #include "porting_aix.hpp" #include "utilities/debug.hpp" @@ -83,7 +85,7 @@ while (n) { node* p = n; n = n->next; - free(p->v); + os::free(p->v); delete p; } } @@ -95,7 +97,7 @@ } } node* p = new node; - p->v = strdup(s); + p->v = os::strdup_check_oom(s); p->next = first; first = p; return p->v; diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/os/bsd/vm/os_bsd.cpp --- a/hotspot/src/os/bsd/vm/os_bsd.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/os/bsd/vm/os_bsd.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -2439,23 +2439,25 @@ } // The memory is committed - MemTracker::record_virtual_memory_reserve_and_commit((address)addr, bytes, mtNone, CALLER_PC); + MemTracker::record_virtual_memory_reserve_and_commit((address)addr, bytes, CALLER_PC); return addr; } bool os::release_memory_special(char* base, size_t bytes) { - MemTracker::Tracker tkr = MemTracker::get_virtual_memory_release_tracker(); - // detaching the SHM segment will also delete it, see reserve_memory_special() - int rslt = shmdt(base); - if (rslt == 0) { - tkr.record((address)base, bytes); - return true; + if (MemTracker::tracking_level() > NMT_minimal) { + Tracker tkr = MemTracker::get_virtual_memory_release_tracker(); + // detaching the SHM segment will also delete it, see reserve_memory_special() + int rslt = shmdt(base); + if (rslt == 0) { + tkr.record((address)base, bytes); + return true; + } else { + return false; + } } else { - tkr.discard(); - return false; + return shmdt(base) == 0; } - } size_t os::large_page_size() { diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/os/bsd/vm/perfMemory_bsd.cpp --- a/hotspot/src/os/bsd/vm/perfMemory_bsd.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/os/bsd/vm/perfMemory_bsd.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -753,7 +753,7 @@ (void)::memset((void*) mapAddress, 0, size); // it does not go through os api, the operation has to record from here - MemTracker::record_virtual_memory_reserve((address)mapAddress, size, mtInternal, CURRENT_PC); + MemTracker::record_virtual_memory_reserve_and_commit((address)mapAddress, size, CURRENT_PC, mtInternal); return mapAddress; } @@ -918,7 +918,7 @@ } // it does not go through os api, the operation has to record from here - MemTracker::record_virtual_memory_reserve((address)mapAddress, size, mtInternal, CURRENT_PC); + MemTracker::record_virtual_memory_reserve_and_commit((address)mapAddress, size, CURRENT_PC, mtInternal); *addr = mapAddress; *sizep = size; diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/os/linux/vm/os_linux.cpp --- a/hotspot/src/os/linux/vm/os_linux.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/os/linux/vm/os_linux.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -3504,9 +3504,12 @@ assert(is_ptr_aligned(start, alignment), "Must be"); - // os::reserve_memory_special will record this memory area. - // Need to release it here to prevent overlapping reservations. - MemTracker::record_virtual_memory_release((address)start, bytes); + if (MemTracker::tracking_level() > NMT_minimal) { + // os::reserve_memory_special will record this memory area. + // Need to release it here to prevent overlapping reservations. + Tracker tkr = MemTracker::get_virtual_memory_release_tracker(); + tkr.record((address)start, bytes); + } char* end = start + bytes; @@ -3601,7 +3604,7 @@ } // The memory is committed - MemTracker::record_virtual_memory_reserve_and_commit((address)addr, bytes, mtNone, CALLER_PC); + MemTracker::record_virtual_memory_reserve_and_commit((address)addr, bytes, CALLER_PC); } return addr; @@ -3617,24 +3620,30 @@ } bool os::release_memory_special(char* base, size_t bytes) { + bool res; + if (MemTracker::tracking_level() > NMT_minimal) { + Tracker tkr = MemTracker::get_virtual_memory_release_tracker(); + res = os::Linux::release_memory_special_impl(base, bytes); + if (res) { + tkr.record((address)base, bytes); + } + + } else { + res = os::Linux::release_memory_special_impl(base, bytes); + } + return res; +} + +bool os::Linux::release_memory_special_impl(char* base, size_t bytes) { assert(UseLargePages, "only for large pages"); - - MemTracker::Tracker tkr = MemTracker::get_virtual_memory_release_tracker(); - bool res; + if (UseSHM) { res = os::Linux::release_memory_special_shm(base, bytes); } else { assert(UseHugeTLBFS, "must be"); res = os::Linux::release_memory_special_huge_tlbfs(base, bytes); } - - if (res) { - tkr.record((address)base, bytes); - } else { - tkr.discard(); - } - return res; } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/os/linux/vm/os_linux.hpp --- a/hotspot/src/os/linux/vm/os_linux.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/os/linux/vm/os_linux.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -108,6 +108,7 @@ static char* reserve_memory_special_huge_tlbfs_only(size_t bytes, char* req_addr, bool exec); static char* reserve_memory_special_huge_tlbfs_mixed(size_t bytes, size_t alignment, char* req_addr, bool exec); + static bool release_memory_special_impl(char* base, size_t bytes); static bool release_memory_special_shm(char* base, size_t bytes); static bool release_memory_special_huge_tlbfs(char* base, size_t bytes); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/os/linux/vm/perfMemory_linux.cpp --- a/hotspot/src/os/linux/vm/perfMemory_linux.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/os/linux/vm/perfMemory_linux.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -753,7 +753,7 @@ (void)::memset((void*) mapAddress, 0, size); // it does not go through os api, the operation has to record from here - MemTracker::record_virtual_memory_reserve((address)mapAddress, size, mtInternal, CURRENT_PC); + MemTracker::record_virtual_memory_reserve_and_commit((address)mapAddress, size, CURRENT_PC, mtInternal); return mapAddress; } @@ -924,7 +924,7 @@ } // it does not go through os api, the operation has to record from here - MemTracker::record_virtual_memory_reserve((address)mapAddress, size, mtInternal, CURRENT_PC); + MemTracker::record_virtual_memory_reserve_and_commit((address)mapAddress, size, CURRENT_PC, mtInternal); *addr = mapAddress; *sizep = size; diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/os/posix/vm/os_posix.cpp --- a/hotspot/src/os/posix/vm/os_posix.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/os/posix/vm/os_posix.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -75,21 +75,41 @@ VMError::report_coredump_status(buffer, success); } -address os::get_caller_pc(int n) { +int os::get_native_stack(address* stack, int frames, int toSkip) { #ifdef _NMT_NOINLINE_ - n ++; + toSkip++; #endif + + int frame_idx = 0; + int num_of_frames; // number of frames captured frame fr = os::current_frame(); - while (n > 0 && fr.pc() && - !os::is_first_C_frame(&fr) && fr.sender_pc()) { - fr = os::get_sender_for_C_frame(&fr); - n --; + while (fr.pc() && frame_idx < frames) { + if (toSkip > 0) { + toSkip --; + } else { + stack[frame_idx ++] = fr.pc(); + } + if (fr.fp() == NULL || os::is_first_C_frame(&fr) + ||fr.sender_pc() == NULL || fr.cb() != NULL) break; + + if (fr.sender_pc() && !os::is_first_C_frame(&fr)) { + fr = os::get_sender_for_C_frame(&fr); + } else { + break; + } } - if (n == 0) { - return fr.pc(); - } else { - return NULL; + num_of_frames = frame_idx; + for (; frame_idx < frames; frame_idx ++) { + stack[frame_idx] = NULL; } + + return num_of_frames; +} + + +bool os::unsetenv(const char* name) { + assert(name != NULL, "Null pointer"); + return (::unsetenv(name) == 0); } int os::get_last_error() { diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/os/solaris/vm/attachListener_solaris.cpp --- a/hotspot/src/os/solaris/vm/attachListener_solaris.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/os/solaris/vm/attachListener_solaris.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -199,23 +199,29 @@ // Calls from the door function to check that the client credentials // match this process. Returns 0 if credentials okay, otherwise -1. static int check_credentials() { - door_cred_t cred_info; + ucred_t *cred_info = NULL; + int ret = -1; // deny by default // get client credentials - if (door_cred(&cred_info) == -1) { - return -1; // unable to get them + if (door_ucred(&cred_info) == -1) { + return -1; // unable to get them, deny } // get our euid/eguid (probably could cache these) uid_t euid = geteuid(); gid_t egid = getegid(); - // check that the effective uid/gid matches - discuss this with Jeff. - if (cred_info.dc_euid == euid && cred_info.dc_egid == egid) { - return 0; // okay - } else { - return -1; // denied + // get euid/egid from ucred_free + uid_t ucred_euid = ucred_geteuid(cred_info); + gid_t ucred_egid = ucred_getegid(cred_info); + + // check that the effective uid/gid matches + if (ucred_euid == euid && ucred_egid == egid) { + ret = 0; // allow } + + ucred_free(cred_info); + return ret; } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/os/solaris/vm/perfMemory_solaris.cpp --- a/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -770,7 +770,8 @@ (void)::memset((void*) mapAddress, 0, size); // it does not go through os api, the operation has to record from here - MemTracker::record_virtual_memory_reserve((address)mapAddress, size, mtInternal, CURRENT_PC); + MemTracker::record_virtual_memory_reserve_and_commit((address)mapAddress, + size, CURRENT_PC, mtInternal); return mapAddress; } @@ -941,7 +942,8 @@ } // it does not go through os api, the operation has to record from here - MemTracker::record_virtual_memory_reserve((address)mapAddress, size, mtInternal, CURRENT_PC); + MemTracker::record_virtual_memory_reserve_and_commit((address)mapAddress, + size, CURRENT_PC, mtInternal); *addr = mapAddress; *sizep = size; diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/os/windows/vm/os_windows.cpp --- a/hotspot/src/os/windows/vm/os_windows.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/os/windows/vm/os_windows.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -138,9 +138,8 @@ // Workaround for issue when a custom launcher doesn't call // DestroyJavaVM and NMT is trying to track memory when free is // called from a static destructor - if (MemTracker::is_on()) { - MemTracker::shutdown(MemTracker::NMT_normal); - } + MemTracker::shutdown(); + break; default: break; @@ -163,6 +162,10 @@ return result > 0 && result < len; } +bool os::unsetenv(const char* name) { + assert(name != NULL, "Null pointer"); + return (SetEnvironmentVariable(name, NULL) == TRUE); +} // No setuid programs under Windows. bool os::have_special_privileges() { @@ -319,15 +322,16 @@ * So far, this method is only used by Native Memory Tracking, which is * only supported on Windows XP or later. */ -address os::get_caller_pc(int n) { +int os::get_native_stack(address* stack, int frames, int toSkip) { #ifdef _NMT_NOINLINE_ - n++; + toSkip ++; #endif - address pc; - if (os::Kernel32Dll::RtlCaptureStackBackTrace(n + 1, 1, (PVOID*)&pc, NULL) == 1) { - return pc; - } - return NULL; + int captured = Kernel32Dll::RtlCaptureStackBackTrace(toSkip + 1, frames, + (PVOID*)stack, NULL); + for (int index = captured; index < frames; index ++) { + stack[index] = NULL; + } + return captured; } @@ -2901,7 +2905,7 @@ PAGE_READWRITE); // If reservation failed, return NULL if (p_buf == NULL) return NULL; - MemTracker::record_virtual_memory_reserve((address)p_buf, size_of_reserve, mtNone, CALLER_PC); + MemTracker::record_virtual_memory_reserve((address)p_buf, size_of_reserve, CALLER_PC); os::release_memory(p_buf, bytes + chunk_size); // we still need to round up to a page boundary (in case we are using large pages) @@ -2967,7 +2971,7 @@ // need to create a dummy 'reserve' record to match // the release. MemTracker::record_virtual_memory_reserve((address)p_buf, - bytes_to_release, mtNone, CALLER_PC); + bytes_to_release, CALLER_PC); os::release_memory(p_buf, bytes_to_release); } #ifdef ASSERT @@ -2986,11 +2990,10 @@ } // Although the memory is allocated individually, it is returned as one. // NMT records it as one block. - address pc = CALLER_PC; if ((flags & MEM_COMMIT) != 0) { - MemTracker::record_virtual_memory_reserve_and_commit((address)p_buf, bytes, mtNone, pc); + MemTracker::record_virtual_memory_reserve_and_commit((address)p_buf, bytes, CALLER_PC); } else { - MemTracker::record_virtual_memory_reserve((address)p_buf, bytes, mtNone, pc); + MemTracker::record_virtual_memory_reserve((address)p_buf, bytes, CALLER_PC); } // made it this far, success @@ -3188,8 +3191,7 @@ DWORD flag = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES; char * res = (char *)VirtualAlloc(addr, bytes, flag, prot); if (res != NULL) { - address pc = CALLER_PC; - MemTracker::record_virtual_memory_reserve_and_commit((address)res, bytes, mtNone, pc); + MemTracker::record_virtual_memory_reserve_and_commit((address)res, bytes, CALLER_PC); } return res; diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/os/windows/vm/perfMemory_windows.cpp --- a/hotspot/src/os/windows/vm/perfMemory_windows.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/os/windows/vm/perfMemory_windows.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -29,6 +29,7 @@ #include "oops/oop.inline.hpp" #include "os_windows.inline.hpp" #include "runtime/handles.inline.hpp" +#include "runtime/os.hpp" #include "runtime/perfMemory.hpp" #include "services/memTracker.hpp" #include "utilities/exceptions.hpp" @@ -1388,7 +1389,7 @@ // the file has been successfully created and the file mapping // object has been created. sharedmem_fileHandle = fh; - sharedmem_fileName = strdup(filename); + sharedmem_fileName = os::strdup(filename); return fmh; } @@ -1498,7 +1499,8 @@ (void)memset(mapAddress, '\0', size); // it does not go through os api, the operation has to record from here - MemTracker::record_virtual_memory_reserve((address)mapAddress, size, mtInternal, CURRENT_PC); + MemTracker::record_virtual_memory_reserve_and_commit((address)mapAddress, + size, CURRENT_PC, mtInternal); return (char*) mapAddress; } @@ -1680,7 +1682,8 @@ } // it does not go through os api, the operation has to record from here - MemTracker::record_virtual_memory_reserve((address)mapAddress, size, mtInternal, CURRENT_PC); + MemTracker::record_virtual_memory_reserve_and_commit((address)mapAddress, size, + CURRENT_PC, mtInternal); *addrp = (char*)mapAddress; @@ -1834,10 +1837,14 @@ return; } - MemTracker::Tracker tkr = MemTracker::get_virtual_memory_release_tracker(); - remove_file_mapping(addr); - // it does not go through os api, the operation has to record from here - tkr.record((address)addr, bytes); + if (MemTracker::tracking_level() > NMT_minimal) { + // it does not go through os api, the operation has to record from here + Tracker tkr = MemTracker::get_virtual_memory_release_tracker(); + remove_file_mapping(addr); + tkr.record((address)addr, bytes); + } else { + remove_file_mapping(addr); + } } char* PerfMemory::backing_store_filename() { diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp --- a/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -23,6 +23,8 @@ */ #include "precompiled.hpp" +#include "memory/allocation.hpp" +#include "memory/allocation.inline.hpp" #include "runtime/os.hpp" #include "vm_version_sparc.hpp" @@ -48,7 +50,7 @@ // All SI defines used below must be supported. guarantee(bufsize != -1, "must be supported"); - char* buf = (char*) malloc(bufsize); + char* buf = (char*) os::malloc(bufsize, mtInternal); if (buf == NULL) return; @@ -60,7 +62,7 @@ } } - free(buf); + os::free(buf); } int VM_Version::platform_features(int features) { @@ -161,7 +163,7 @@ char tmp; size_t bufsize = sysinfo(SI_ISALIST, &tmp, 1); - char* buf = (char*) malloc(bufsize); + char* buf = (char*) os::malloc(bufsize, mtInternal); if (buf != NULL) { if (sysinfo(SI_ISALIST, buf, bufsize) == bufsize) { @@ -184,7 +186,7 @@ if (vis[3] == '2') features |= vis2_instructions_m; } } - free(buf); + os::free(buf); } } @@ -228,7 +230,7 @@ } #endif // Convert to UPPER case before compare. - char* impl = strdup(implementation); + char* impl = os::strdup_check_oom(implementation); for (int i = 0; impl[i] != 0; i++) impl[i] = (char)toupper((uint)impl[i]); @@ -252,7 +254,7 @@ implementation = "SPARC"; } } - free((void*)impl); + os::free((void*)impl); break; } } // for( diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/adlc/output_c.cpp --- a/hotspot/src/share/vm/adlc/output_c.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/adlc/output_c.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -997,7 +997,7 @@ int nopcnt = 0; for ( _pipeline->_noplist.reset(); (nop = _pipeline->_noplist.iter()) != NULL; nopcnt++ ); - fprintf(fp_cpp, "void Bundle::initialize_nops(MachNode * nop_list[%d], Compile *C) {\n", nopcnt); + fprintf(fp_cpp, "void Bundle::initialize_nops(MachNode * nop_list[%d]) {\n", nopcnt); int i = 0; for ( _pipeline->_noplist.reset(); (nop = _pipeline->_noplist.iter()) != NULL; i++ ) { fprintf(fp_cpp, " nop_list[%d] = (MachNode *) new %sNode();\n", i, nop); @@ -1369,7 +1369,7 @@ fprintf(fp, " ra_->add_reference(root, inst%d);\n", inst_num); fprintf(fp, " ra_->set_oop (root, ra_->is_oop(inst%d));\n", inst_num); fprintf(fp, " ra_->set_pair(root->_idx, ra_->get_reg_second(inst%d), ra_->get_reg_first(inst%d));\n", inst_num, inst_num); - fprintf(fp, " root->_opnds[0] = inst%d->_opnds[0]->clone(C); // result\n", inst_num); + fprintf(fp, " root->_opnds[0] = inst%d->_opnds[0]->clone(); // result\n", inst_num); fprintf(fp, " // ----- Done with initial setup -----\n"); } else { if( (op_form == NULL) || (op_form->is_base_constant(globals) == Form::none) ) { @@ -1382,7 +1382,7 @@ } else { fprintf(fp, " // no ideal edge for constants after matching\n"); } - fprintf(fp, " root->_opnds[%d] = inst%d->_opnds[%d]->clone(C);\n", + fprintf(fp, " root->_opnds[%d] = inst%d->_opnds[%d]->clone();\n", opnds_index, inst_num, inst_op_num ); } ++opnds_index; @@ -1402,7 +1402,7 @@ // Define the Peephole method for an instruction node void ArchDesc::definePeephole(FILE *fp, InstructForm *node) { // Generate Peephole function header - fprintf(fp, "MachNode *%sNode::peephole( Block *block, int block_index, PhaseRegAlloc *ra_, int &deleted, Compile* C ) {\n", node->_ident); + fprintf(fp, "MachNode *%sNode::peephole(Block *block, int block_index, PhaseRegAlloc *ra_, int &deleted) {\n", node->_ident); fprintf(fp, " bool matches = true;\n"); // Identify the maximum instruction position, @@ -1593,7 +1593,7 @@ } const char *resultOper = new_inst->reduce_result(); - fprintf(fp," n%d->set_opnd_array(0, state->MachOperGenerator( %s, C ));\n", + fprintf(fp," n%d->set_opnd_array(0, state->MachOperGenerator(%s));\n", cnt, machOperEnum(resultOper)); // get the formal operand NameList @@ -1634,7 +1634,7 @@ // If there is no use of the created operand, just skip it if (new_pos != NameList::Not_in_list) { //Copy the operand from the original made above - fprintf(fp," n%d->set_opnd_array(%d, op%d->clone(C)); // %s\n", + fprintf(fp," n%d->set_opnd_array(%d, op%d->clone()); // %s\n", cnt, new_pos, exp_pos-node->num_opnds(), opid); // Check for who defines this operand & add edge if needed fprintf(fp," if(tmp%d != NULL)\n", exp_pos); @@ -1662,7 +1662,7 @@ new_pos = new_inst->operand_position(parameter,Component::USE); if (new_pos != -1) { // Copy the operand from the ExpandNode to the new node - fprintf(fp," n%d->set_opnd_array(%d, opnd_array(%d)->clone(C)); // %s\n", + fprintf(fp," n%d->set_opnd_array(%d, opnd_array(%d)->clone()); // %s\n", cnt, new_pos, exp_pos, opid); // For each operand add appropriate input edges by looking at tmp's fprintf(fp," if(tmp%d == this) {\n", exp_pos); @@ -1729,14 +1729,14 @@ declared_def = true; } if (op && op->_interface && op->_interface->is_RegInterface()) { - fprintf(fp," def = new MachTempNode(state->MachOperGenerator( %s, C ));\n", + fprintf(fp," def = new MachTempNode(state->MachOperGenerator(%s));\n", machOperEnum(op->_ident)); fprintf(fp," add_req(def);\n"); // The operand for TEMP is already constructed during // this mach node construction, see buildMachNode(). // // int idx = node->operand_position_format(comp->_name); - // fprintf(fp," set_opnd_array(%d, state->MachOperGenerator( %s, C ));\n", + // fprintf(fp," set_opnd_array(%d, state->MachOperGenerator(%s));\n", // idx, machOperEnum(op->_ident)); } else { assert(false, "can't have temps which aren't registers"); @@ -1802,7 +1802,7 @@ uint j = node->unique_opnds_idx(i); // unique_opnds_idx(i) is unique if unique_opnds_idx(j) is not unique. if( j != node->unique_opnds_idx(j) ) { - fprintf(fp," set_opnd_array(%d, opnd_array(%d)->clone(C)); // %s\n", + fprintf(fp," set_opnd_array(%d, opnd_array(%d)->clone()); // %s\n", new_num_opnds, i, comp->_name); // delete not unique edges here fprintf(fp," for(unsigned i = 0; i < num%d; i++) {\n", i); @@ -2839,12 +2839,12 @@ // generate code to create a clone for a class derived from MachOper // -// (0) MachOper *MachOperXOper::clone(Compile* C) const { +// (0) MachOper *MachOperXOper::clone() const { // (1) return new MachXOper( _ccode, _c0, _c1, ..., _cn); // (2) } // static void defineClone(FILE *fp, FormDict &globalNames, OperandForm &oper) { - fprintf(fp,"MachOper *%sOper::clone(Compile* C) const {\n", oper._ident); + fprintf(fp,"MachOper *%sOper::clone() const {\n", oper._ident); // Check for constants that need to be copied over const int num_consts = oper.num_consts(globalNames); const bool is_ideal_bool = oper.is_ideal_bool(); @@ -3043,7 +3043,7 @@ static void define_fill_new_machnode(bool used, FILE *fp_cpp) { fprintf(fp_cpp, "\n"); fprintf(fp_cpp, "// Copy _idx, inputs and operands to new node\n"); - fprintf(fp_cpp, "void MachNode::fill_new_machnode( MachNode* node, Compile* C) const {\n"); + fprintf(fp_cpp, "void MachNode::fill_new_machnode(MachNode* node) const {\n"); if( !used ) { fprintf(fp_cpp, " // This architecture does not have cisc or short branch instructions\n"); fprintf(fp_cpp, " ShouldNotCallThis();\n"); @@ -3064,7 +3064,7 @@ fprintf(fp_cpp, " MachOper **to = node->_opnds;\n"); fprintf(fp_cpp, " for( int i = 0; i < nopnds; i++ ) {\n"); fprintf(fp_cpp, " if( i != cisc_operand() ) \n"); - fprintf(fp_cpp, " to[i] = _opnds[i]->clone(C);\n"); + fprintf(fp_cpp, " to[i] = _opnds[i]->clone();\n"); fprintf(fp_cpp, " }\n"); fprintf(fp_cpp, "}\n"); } @@ -3105,7 +3105,7 @@ if ( strcmp(oper->_ident,"label") == 0 ) { defineIn_RegMask(_CPP_MISC_file._fp, _globalNames, *oper); - fprintf(fp,"MachOper *%sOper::clone(Compile* C) const {\n", oper->_ident); + fprintf(fp,"MachOper *%sOper::clone() const {\n", oper->_ident); fprintf(fp," return new %sOper(_label, _block_num);\n", oper->_ident); fprintf(fp,"}\n"); @@ -3124,7 +3124,7 @@ if ( strcmp(oper->_ident,"method") == 0 ) { defineIn_RegMask(_CPP_MISC_file._fp, _globalNames, *oper); - fprintf(fp,"MachOper *%sOper::clone(Compile* C) const {\n", oper->_ident); + fprintf(fp,"MachOper *%sOper::clone() const {\n", oper->_ident); fprintf(fp," return new %sOper(_method);\n", oper->_ident); fprintf(fp,"}\n"); @@ -3845,7 +3845,7 @@ "// that invokes 'new' on the corresponding class constructor.\n"); fprintf(fp_cpp, "\n"); fprintf(fp_cpp, "MachOper *State::MachOperGenerator"); - fprintf(fp_cpp, "(int opcode, Compile* C)"); + fprintf(fp_cpp, "(int opcode)"); fprintf(fp_cpp, "{\n"); fprintf(fp_cpp, "\n"); fprintf(fp_cpp, " switch(opcode) {\n"); @@ -3921,7 +3921,7 @@ int index = clist.operand_position(comp->_name, comp->_usedef, inst); const char *opcode = machOperEnum(comp->_type); fprintf(fp_cpp, "%s node->set_opnd_array(%d, ", indent, index); - fprintf(fp_cpp, "MachOperGenerator(%s, C));\n", opcode); + fprintf(fp_cpp, "MachOperGenerator(%s));\n", opcode); } } else if ( inst->is_chain_of_constant(_globalNames, opType) ) { @@ -3978,7 +3978,7 @@ InstructForm *inst_cisc = cisc_spill_alternate(); if (inst_cisc != NULL) { fprintf(fp_hpp, " virtual int cisc_operand() const { return %d; }\n", cisc_spill_operand()); - fprintf(fp_hpp, " virtual MachNode *cisc_version(int offset, Compile* C);\n"); + fprintf(fp_hpp, " virtual MachNode *cisc_version(int offset);\n"); fprintf(fp_hpp, " virtual void use_cisc_RegMask();\n"); fprintf(fp_hpp, " virtual const RegMask *cisc_RegMask() const { return _cisc_RegMask; }\n"); } @@ -4008,7 +4008,7 @@ // Construct CISC version of this instruction fprintf(fp_cpp, "\n"); fprintf(fp_cpp, "// Build CISC version of this instruction\n"); - fprintf(fp_cpp, "MachNode *%sNode::cisc_version( int offset, Compile* C ) {\n", this->_ident); + fprintf(fp_cpp, "MachNode *%sNode::cisc_version(int offset) {\n", this->_ident); // Create the MachNode object fprintf(fp_cpp, " %sNode *node = new %sNode();\n", name, name); // Fill in the bottom_type where requested @@ -4023,7 +4023,7 @@ fprintf(fp_cpp, "\n"); fprintf(fp_cpp, " // Copy _idx, inputs and operands to new node\n"); - fprintf(fp_cpp, " fill_new_machnode(node, C);\n"); + fprintf(fp_cpp, " fill_new_machnode(node);\n"); // Construct operand to access [stack_pointer + offset] fprintf(fp_cpp, " // Construct operand to access [stack_pointer + offset]\n"); fprintf(fp_cpp, " node->set_opnd_array(cisc_operand(), new %sOper(offset));\n", cisc_oper_name); @@ -4042,7 +4042,7 @@ // Build prototypes for short branch methods void InstructForm::declare_short_branch_methods(FILE *fp_hpp) { if (has_short_branch_form()) { - fprintf(fp_hpp, " virtual MachNode *short_branch_version(Compile* C);\n"); + fprintf(fp_hpp, " virtual MachNode *short_branch_version();\n"); } } @@ -4055,7 +4055,7 @@ // Construct short_branch_version() method. fprintf(fp_cpp, "// Build short branch version of this instruction\n"); - fprintf(fp_cpp, "MachNode *%sNode::short_branch_version(Compile* C) {\n", this->_ident); + fprintf(fp_cpp, "MachNode *%sNode::short_branch_version() {\n", this->_ident); // Create the MachNode object fprintf(fp_cpp, " %sNode *node = new %sNode();\n", name, name); if( is_ideal_if() ) { @@ -4071,7 +4071,7 @@ // Short branch version must use same node index for access // through allocator's tables fprintf(fp_cpp, " // Copy _idx, inputs and operands to new node\n"); - fprintf(fp_cpp, " fill_new_machnode(node, C);\n"); + fprintf(fp_cpp, " fill_new_machnode(node);\n"); // Return result and exit scope fprintf(fp_cpp, " return node;\n"); @@ -4097,7 +4097,7 @@ "// that invokes 'new' on the corresponding class constructor.\n"); fprintf(fp_cpp, "\n"); fprintf(fp_cpp, "MachNode *State::MachNodeGenerator"); - fprintf(fp_cpp, "(int opcode, Compile* C)"); + fprintf(fp_cpp, "(int opcode)"); fprintf(fp_cpp, "{\n"); fprintf(fp_cpp, " switch(opcode) {\n"); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/adlc/output_h.cpp --- a/hotspot/src/share/vm/adlc/output_h.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/adlc/output_h.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -1119,7 +1119,7 @@ fprintf(fp_hpp, " _nop_count = %d\n", _pipeline->_nopcnt); fprintf(fp_hpp, " };\n\n"); - fprintf(fp_hpp, " static void initialize_nops(MachNode *nop_list[%d], Compile* C);\n\n", + fprintf(fp_hpp, " static void initialize_nops(MachNode *nop_list[%d]);\n\n", _pipeline->_nopcnt); fprintf(fp_hpp, "#ifndef PRODUCT\n"); fprintf(fp_hpp, " void dump(outputStream *st = tty) const;\n"); @@ -1240,7 +1240,7 @@ constant_type, _globalNames); // Clone function - fprintf(fp," virtual MachOper *clone(Compile* C) const;\n"); + fprintf(fp," virtual MachOper *clone() const;\n"); // Support setting a spill offset into a constant operand. // We only support setting an 'int' offset, while in the @@ -1718,7 +1718,7 @@ // If there is an explicit peephole rule, build it if ( instr->peepholes() != NULL ) { - fprintf(fp," virtual MachNode *peephole(Block *block, int block_index, PhaseRegAlloc *ra_, int &deleted, Compile *C);\n"); + fprintf(fp," virtual MachNode *peephole(Block *block, int block_index, PhaseRegAlloc *ra_, int &deleted);\n"); } // Output the declaration for number of relocation entries @@ -1863,7 +1863,7 @@ } if ( instr->num_post_match_opnds() != 0 || instr->is_chain_of_constant(_globalNames) ) { - fprintf(fp," friend MachNode *State::MachNodeGenerator(int opcode, Compile* C);\n"); + fprintf(fp," friend MachNode *State::MachNodeGenerator(int opcode);\n"); } if ( instr->rematerialize(_globalNames, get_registers()) ) { fprintf(fp," // Rematerialize %s\n", instr->_ident); @@ -2071,8 +2071,8 @@ fprintf(fp," DEBUG_ONLY( ~State(void); ) // Destructor\n"); fprintf(fp,"\n"); fprintf(fp," // Methods created by ADLC and invoked by Reduce\n"); - fprintf(fp," MachOper *MachOperGenerator( int opcode, Compile* C );\n"); - fprintf(fp," MachNode *MachNodeGenerator( int opcode, Compile* C );\n"); + fprintf(fp," MachOper *MachOperGenerator(int opcode);\n"); + fprintf(fp," MachNode *MachNodeGenerator(int opcode);\n"); fprintf(fp,"\n"); fprintf(fp," // Assign a state to a node, definition of method produced by ADLC\n"); fprintf(fp," bool DFA( int opcode, const Node *ideal );\n"); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/asm/codeBuffer.cpp --- a/hotspot/src/share/vm/asm/codeBuffer.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/asm/codeBuffer.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -269,7 +269,7 @@ GrowableArray* CodeBuffer::create_patch_overflow() { if (_overflow_arena == NULL) { - _overflow_arena = new (mtCode) Arena(); + _overflow_arena = new (mtCode) Arena(mtCode); } return new (_overflow_arena) GrowableArray(_overflow_arena, 8, 0, 0); } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/c1/c1_Compiler.cpp --- a/hotspot/src/share/vm/c1/c1_Compiler.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/c1/c1_Compiler.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -48,7 +48,7 @@ void Compiler::init_c1_runtime() { BufferBlob* buffer_blob = CompilerThread::current()->get_buffer_blob(); - Arena* arena = new (mtCompiler) Arena(); + Arena* arena = new (mtCompiler) Arena(mtCompiler); Runtime1::initialize(buffer_blob); FrameMap::initialize(); // initialize data structures diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/c1/c1_LIRAssembler.cpp --- a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ #include "c1/c1_MacroAssembler.hpp" #include "c1/c1_ValueStack.hpp" #include "ci/ciInstance.hpp" +#include "runtime/os.hpp" void LIR_Assembler::patching_epilog(PatchingStub* patch, LIR_PatchCode patch_code, Register obj, CodeEmitInfo* info) { // we must have enough patching space so that call can be inserted @@ -848,7 +849,7 @@ stringStream st; st.print("bad oop %s at %d", r->as_Register()->name(), _masm->offset()); #ifdef SPARC - _masm->_verify_oop(r->as_Register(), strdup(st.as_string()), __FILE__, __LINE__); + _masm->_verify_oop(r->as_Register(), os::strdup(st.as_string(), mtCompiler), __FILE__, __LINE__); #else _masm->verify_oop(r->as_Register()); #endif diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/c1/c1_LinearScan.cpp --- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -1613,25 +1613,22 @@ Interval* precolored_cpu_intervals, *not_precolored_cpu_intervals; Interval* precolored_fpu_intervals, *not_precolored_fpu_intervals; - create_unhandled_lists(&precolored_cpu_intervals, ¬_precolored_cpu_intervals, is_precolored_cpu_interval, is_virtual_cpu_interval); - if (has_fpu_registers()) { - create_unhandled_lists(&precolored_fpu_intervals, ¬_precolored_fpu_intervals, is_precolored_fpu_interval, is_virtual_fpu_interval); -#ifdef ASSERT - } else { - // fpu register allocation is omitted because no virtual fpu registers are present - // just check this again... - create_unhandled_lists(&precolored_fpu_intervals, ¬_precolored_fpu_intervals, is_precolored_fpu_interval, is_virtual_fpu_interval); - assert(not_precolored_fpu_intervals == Interval::end(), "missed an uncolored fpu interval"); -#endif - } - // allocate cpu registers + create_unhandled_lists(&precolored_cpu_intervals, ¬_precolored_cpu_intervals, + is_precolored_cpu_interval, is_virtual_cpu_interval); + + // allocate fpu registers + create_unhandled_lists(&precolored_fpu_intervals, ¬_precolored_fpu_intervals, + is_precolored_fpu_interval, is_virtual_fpu_interval); + + // the fpu interval allocation cannot be moved down below with the fpu section as + // the cpu_lsw.walk() changes interval positions. + LinearScanWalker cpu_lsw(this, precolored_cpu_intervals, not_precolored_cpu_intervals); cpu_lsw.walk(); cpu_lsw.finish_allocation(); if (has_fpu_registers()) { - // allocate fpu registers LinearScanWalker fpu_lsw(this, precolored_fpu_intervals, not_precolored_fpu_intervals); fpu_lsw.walk(); fpu_lsw.finish_allocation(); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/ci/ciEnv.cpp --- a/hotspot/src/share/vm/ci/ciEnv.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/ci/ciEnv.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -86,7 +86,8 @@ // ------------------------------------------------------------------ // ciEnv::ciEnv -ciEnv::ciEnv(CompileTask* task, int system_dictionary_modification_counter) { +ciEnv::ciEnv(CompileTask* task, int system_dictionary_modification_counter) + : _ciEnv_arena(mtCompiler) { VM_ENTRY_MARK; // Set up ciEnv::current immediately, for the sake of ciObjectFactory, etc. @@ -144,7 +145,7 @@ _jvmti_can_pop_frame = false; } -ciEnv::ciEnv(Arena* arena) { +ciEnv::ciEnv(Arena* arena) : _ciEnv_arena(mtCompiler) { ASSERT_IN_VM; // Set up ciEnv::current immediately, for the sake of ciObjectFactory, etc. diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/ci/ciObjectFactory.cpp --- a/hotspot/src/share/vm/ci/ciObjectFactory.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/ci/ciObjectFactory.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -112,7 +112,7 @@ // This Arena is long lived and exists in the resource mark of the // compiler thread that initializes the initial ciObjectFactory which // creates the shared ciObjects that all later ciObjectFactories use. - Arena* arena = new (mtCompiler) Arena(); + Arena* arena = new (mtCompiler) Arena(mtCompiler); ciEnv initial(arena); ciEnv* env = ciEnv::current(); env->_factory->init_shared_objects(); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/classfile/classLoader.cpp --- a/hotspot/src/share/vm/classfile/classLoader.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/classfile/classLoader.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -273,13 +273,17 @@ } LazyClassPathEntry::LazyClassPathEntry(char* path, const struct stat* st) : ClassPathEntry() { - _path = strdup(path); + _path = os::strdup_check_oom(path); _st = *st; _meta_index = NULL; _resolved_entry = NULL; _has_error = false; } +LazyClassPathEntry::~LazyClassPathEntry() { + os::free(_path); +} + bool LazyClassPathEntry::is_jar_file() { return ((_st.st_mode & S_IFREG) == S_IFREG); } @@ -416,7 +420,7 @@ default: { if (!skipCurrentJar && cur_entry != NULL) { - char* new_name = strdup(package_name); + char* new_name = os::strdup_check_oom(package_name); boot_class_path_packages.append(new_name); } } @@ -438,7 +442,7 @@ void ClassLoader::setup_bootstrap_search_path() { assert(_first_entry == NULL, "should not setup bootstrap class search path twice"); - char* sys_class_path = os::strdup(Arguments::get_sysclasspath()); + char* sys_class_path = os::strdup_check_oom(Arguments::get_sysclasspath()); if (TraceClassLoading && Verbose) { tty->print_cr("[Bootstrap loader class path=%s]", sys_class_path); } @@ -460,6 +464,7 @@ end++; } } + os::free(sys_class_path); } ClassPathEntry* ClassLoader::create_class_path_entry(char *path, const struct stat* st, bool lazy, TRAPS) { diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/classfile/classLoader.hpp --- a/hotspot/src/share/vm/classfile/classLoader.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/classfile/classLoader.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -128,6 +128,8 @@ bool is_jar_file(); const char* name() { return _path; } LazyClassPathEntry(char* path, const struct stat* st); + virtual ~LazyClassPathEntry(); + ClassFileStream* open_stream(const char* name, TRAPS); void set_meta_index(MetaIndex* meta_index) { _meta_index = meta_index; } virtual bool is_lazy(); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/classfile/stackMapFrame.cpp --- a/hotspot/src/share/vm/classfile/stackMapFrame.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/classfile/stackMapFrame.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -54,21 +54,6 @@ return frame; } -bool StackMapFrame::has_new_object() const { - int32_t i; - for (i = 0; i < _max_locals; i++) { - if (_locals[i].is_uninitialized()) { - return true; - } - } - for (i = 0; i < _stack_size; i++) { - if (_stack[i].is_uninitialized()) { - return true; - } - } - return false; -} - void StackMapFrame::initialize_object( VerificationType old_object, VerificationType new_object) { int32_t i; diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/classfile/stackMapFrame.hpp --- a/hotspot/src/share/vm/classfile/stackMapFrame.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/classfile/stackMapFrame.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -155,10 +155,6 @@ const methodHandle m, VerificationType thisKlass, TRAPS); // Search local variable type array and stack type array. - // Return true if an uninitialized object is found. - bool has_new_object() const; - - // Search local variable type array and stack type array. // Set every element with type of old_object to new_object. void initialize_object( VerificationType old_object, VerificationType new_object); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/classfile/stackMapTable.cpp --- a/hotspot/src/share/vm/classfile/stackMapTable.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/classfile/stackMapTable.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -70,24 +70,26 @@ bool StackMapTable::match_stackmap( StackMapFrame* frame, int32_t target, - bool match, bool update, ErrorContext* ctx, TRAPS) const { + bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const { int index = get_index_from_offset(target); - return match_stackmap(frame, target, index, match, update, ctx, THREAD); + return match_stackmap(frame, target, index, match, update, handler, ctx, THREAD); } // Match and/or update current_frame to the frame in stackmap table with // specified offset and frame index. Return true if the two frames match. +// handler is true if the frame in stackmap_table is for an exception handler. // -// The values of match and update are: _match__update_ +// The values of match and update are: _match__update__handler // -// checking a branch target/exception handler: true false +// checking a branch target: true false false +// checking an exception handler: true false true // linear bytecode verification following an -// unconditional branch: false true +// unconditional branch: false true false // linear bytecode verification not following an -// unconditional branch: true true +// unconditional branch: true true false bool StackMapTable::match_stackmap( StackMapFrame* frame, int32_t target, int32_t frame_index, - bool match, bool update, ErrorContext* ctx, TRAPS) const { + bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const { if (frame_index < 0 || frame_index >= _frame_count) { *ctx = ErrorContext::missing_stackmap(frame->offset()); frame->verifier()->verify_error( @@ -98,11 +100,9 @@ StackMapFrame *stackmap_frame = _frame_array[frame_index]; bool result = true; if (match) { - // when checking handler target, match == true && update == false - bool is_exception_handler = !update; // Has direct control flow from last instruction, need to match the two // frames. - result = frame->is_assignable_to(stackmap_frame, is_exception_handler, + result = frame->is_assignable_to(stackmap_frame, handler, ctx, CHECK_VERIFY_(frame->verifier(), result)); } if (update) { @@ -126,24 +126,10 @@ StackMapFrame* frame, int32_t target, TRAPS) const { ErrorContext ctx; bool match = match_stackmap( - frame, target, true, false, &ctx, CHECK_VERIFY(frame->verifier())); + frame, target, true, false, false, &ctx, CHECK_VERIFY(frame->verifier())); if (!match || (target < 0 || target >= _code_length)) { frame->verifier()->verify_error(ctx, "Inconsistent stackmap frames at branch target %d", target); - return; - } - // check if uninitialized objects exist on backward branches - check_new_object(frame, target, CHECK_VERIFY(frame->verifier())); - frame->verifier()->update_furthest_jump(target); -} - -void StackMapTable::check_new_object( - const StackMapFrame* frame, int32_t target, TRAPS) const { - if (frame->offset() > target && frame->has_new_object()) { - frame->verifier()->verify_error( - ErrorContext::bad_code(frame->offset()), - "Uninitialized object exists on backward branch %d", target); - return; } } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/classfile/stackMapTable.hpp --- a/hotspot/src/share/vm/classfile/stackMapTable.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/classfile/stackMapTable.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -60,12 +60,12 @@ // specified offset. Return true if the two frames match. bool match_stackmap( StackMapFrame* current_frame, int32_t offset, - bool match, bool update, ErrorContext* ctx, TRAPS) const; + bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const; // Match and/or update current_frame to the frame in stackmap table with // specified offset and frame index. Return true if the two frames match. bool match_stackmap( StackMapFrame* current_frame, int32_t offset, int32_t frame_index, - bool match, bool update, ErrorContext* ctx, TRAPS) const; + bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const; // Check jump instructions. Make sure there are no uninitialized // instances on backward branch. @@ -76,10 +76,6 @@ // Returns the frame array index where the frame with offset is stored. int get_index_from_offset(int32_t offset) const; - // Make sure that there's no uninitialized object exist on backward branch. - void check_new_object( - const StackMapFrame* frame, int32_t target, TRAPS) const; - void print_on(outputStream* str) const; }; diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/classfile/symbolTable.cpp --- a/hotspot/src/share/vm/classfile/symbolTable.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/classfile/symbolTable.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -70,9 +70,9 @@ void SymbolTable::initialize_symbols(int arena_alloc_size) { // Initialize the arena for global symbols, size passed in depends on CDS. if (arena_alloc_size == 0) { - _arena = new (mtSymbol) Arena(); + _arena = new (mtSymbol) Arena(mtSymbol); } else { - _arena = new (mtSymbol) Arena(arena_alloc_size); + _arena = new (mtSymbol) Arena(mtSymbol, arena_alloc_size); } } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/classfile/verifier.cpp --- a/hotspot/src/share/vm/classfile/verifier.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/classfile/verifier.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -620,8 +620,6 @@ // flow from current instruction to the next // instruction in sequence - set_furthest_jump(0); - Bytecodes::Code opcode; while (!bcs.is_last_bytecode()) { // Check for recursive re-verification before each bytecode. @@ -1780,7 +1778,7 @@ // If matched, current_frame will be updated by this method. bool matches = stackmap_table->match_stackmap( current_frame, this_offset, stackmap_index, - !no_control_flow, true, &ctx, CHECK_VERIFY_(this, 0)); + !no_control_flow, true, false, &ctx, CHECK_VERIFY_(this, 0)); if (!matches) { // report type error verify_error(ctx, "Instruction type does not match stack map"); @@ -1827,7 +1825,7 @@ } ErrorContext ctx; bool matches = stackmap_table->match_stackmap( - new_frame, handler_pc, true, false, &ctx, CHECK_VERIFY(this)); + new_frame, handler_pc, true, false, true, &ctx, CHECK_VERIFY(this)); if (!matches) { verify_error(ctx, "Stack map does not match the one at " "exception handler %d", handler_pc); @@ -2219,6 +2217,181 @@ } } +// Look at the method's handlers. If the bci is in the handler's try block +// then check if the handler_pc is already on the stack. If not, push it. +void ClassVerifier::push_handlers(ExceptionTable* exhandlers, + GrowableArray* handler_stack, + u4 bci) { + int exlength = exhandlers->length(); + for(int x = 0; x < exlength; x++) { + if (bci >= exhandlers->start_pc(x) && bci < exhandlers->end_pc(x)) { + handler_stack->append_if_missing(exhandlers->handler_pc(x)); + } + } +} + +// Return TRUE if all code paths starting with start_bc_offset end in +// bytecode athrow or loop. +bool ClassVerifier::ends_in_athrow(u4 start_bc_offset) { + ResourceMark rm; + // Create bytecode stream. + RawBytecodeStream bcs(method()); + u4 code_length = method()->code_size(); + bcs.set_start(start_bc_offset); + u4 target; + // Create stack for storing bytecode start offsets for if* and *switch. + GrowableArray* bci_stack = new GrowableArray(30); + // Create stack for handlers for try blocks containing this handler. + GrowableArray* handler_stack = new GrowableArray(30); + // Create list of visited branch opcodes (goto* and if*). + GrowableArray* visited_branches = new GrowableArray(30); + ExceptionTable exhandlers(_method()); + + while (true) { + if (bcs.is_last_bytecode()) { + // if no more starting offsets to parse or if at the end of the + // method then return false. + if ((bci_stack->is_empty()) || ((u4)bcs.end_bci() == code_length)) + return false; + // Pop a bytecode starting offset and scan from there. + bcs.set_start(bci_stack->pop()); + } + Bytecodes::Code opcode = bcs.raw_next(); + u4 bci = bcs.bci(); + + // If the bytecode is in a TRY block, push its handlers so they + // will get parsed. + push_handlers(&exhandlers, handler_stack, bci); + + switch (opcode) { + case Bytecodes::_if_icmpeq: + case Bytecodes::_if_icmpne: + case Bytecodes::_if_icmplt: + case Bytecodes::_if_icmpge: + case Bytecodes::_if_icmpgt: + case Bytecodes::_if_icmple: + case Bytecodes::_ifeq: + case Bytecodes::_ifne: + case Bytecodes::_iflt: + case Bytecodes::_ifge: + case Bytecodes::_ifgt: + case Bytecodes::_ifle: + case Bytecodes::_if_acmpeq: + case Bytecodes::_if_acmpne: + case Bytecodes::_ifnull: + case Bytecodes::_ifnonnull: + target = bcs.dest(); + if (visited_branches->contains(bci)) { + if (bci_stack->is_empty()) return true; + // Pop a bytecode starting offset and scan from there. + bcs.set_start(bci_stack->pop()); + } else { + if (target > bci) { // forward branch + if (target >= code_length) return false; + // Push the branch target onto the stack. + bci_stack->push(target); + // then, scan bytecodes starting with next. + bcs.set_start(bcs.next_bci()); + } else { // backward branch + // Push bytecode offset following backward branch onto the stack. + bci_stack->push(bcs.next_bci()); + // Check bytecodes starting with branch target. + bcs.set_start(target); + } + // Record target so we don't branch here again. + visited_branches->append(bci); + } + break; + + case Bytecodes::_goto: + case Bytecodes::_goto_w: + target = (opcode == Bytecodes::_goto ? bcs.dest() : bcs.dest_w()); + if (visited_branches->contains(bci)) { + if (bci_stack->is_empty()) return true; + // Been here before, pop new starting offset from stack. + bcs.set_start(bci_stack->pop()); + } else { + if (target >= code_length) return false; + // Continue scanning from the target onward. + bcs.set_start(target); + // Record target so we don't branch here again. + visited_branches->append(bci); + } + break; + + // Check that all switch alternatives end in 'athrow' bytecodes. Since it + // is difficult to determine where each switch alternative ends, parse + // each switch alternative until either hit a 'return', 'athrow', or reach + // the end of the method's bytecodes. This is gross but should be okay + // because: + // 1. tableswitch and lookupswitch byte codes in handlers for ctor explicit + // constructor invocations should be rare. + // 2. if each switch alternative ends in an athrow then the parsing should be + // short. If there is no athrow then it is bogus code, anyway. + case Bytecodes::_lookupswitch: + case Bytecodes::_tableswitch: + { + address aligned_bcp = (address) round_to((intptr_t)(bcs.bcp() + 1), jintSize); + u4 default_offset = Bytes::get_Java_u4(aligned_bcp) + bci; + int keys, delta; + if (opcode == Bytecodes::_tableswitch) { + jint low = (jint)Bytes::get_Java_u4(aligned_bcp + jintSize); + jint high = (jint)Bytes::get_Java_u4(aligned_bcp + 2*jintSize); + // This is invalid, but let the regular bytecode verifier + // report this because the user will get a better error message. + if (low > high) return true; + keys = high - low + 1; + delta = 1; + } else { + keys = (int)Bytes::get_Java_u4(aligned_bcp + jintSize); + delta = 2; + } + // Invalid, let the regular bytecode verifier deal with it. + if (keys < 0) return true; + + // Push the offset of the next bytecode onto the stack. + bci_stack->push(bcs.next_bci()); + + // Push the switch alternatives onto the stack. + for (int i = 0; i < keys; i++) { + u4 target = bci + (jint)Bytes::get_Java_u4(aligned_bcp+(3+i*delta)*jintSize); + if (target > code_length) return false; + bci_stack->push(target); + } + + // Start bytecode parsing for the switch at the default alternative. + if (default_offset > code_length) return false; + bcs.set_start(default_offset); + break; + } + + case Bytecodes::_return: + return false; + + case Bytecodes::_athrow: + { + if (bci_stack->is_empty()) { + if (handler_stack->is_empty()) { + return true; + } else { + // Parse the catch handlers for try blocks containing athrow. + bcs.set_start(handler_stack->pop()); + } + } else { + // Pop a bytecode offset and starting scanning from there. + bcs.set_start(bci_stack->pop()); + } + } + break; + + default: + ; + } // end switch + } // end while loop + + return false; +} + void ClassVerifier::verify_invoke_init( RawBytecodeStream* bcs, u2 ref_class_index, VerificationType ref_class_type, StackMapFrame* current_frame, u4 code_length, bool *this_uninit, @@ -2238,25 +2411,26 @@ return; } - // Make sure that this call is not jumped over. - if (bci < furthest_jump()) { - verify_error(ErrorContext::bad_code(bci), - "Bad method call from inside of a branch"); - return; - } - - // Make sure that this call is not done from within a TRY block because - // that can result in returning an incomplete object. Simply checking - // (bci >= start_pc) also ensures that this call is not done after a TRY - // block. That is also illegal because this call must be the first Java - // statement in the constructor. + // Check if this call is done from inside of a TRY block. If so, make + // sure that all catch clause paths end in a throw. Otherwise, this + // can result in returning an incomplete object. ExceptionTable exhandlers(_method()); int exlength = exhandlers.length(); for(int i = 0; i < exlength; i++) { - if (bci >= exhandlers.start_pc(i)) { - verify_error(ErrorContext::bad_code(bci), - "Bad method call from after the start of a try block"); - return; + u2 start_pc = exhandlers.start_pc(i); + u2 end_pc = exhandlers.end_pc(i); + + if (bci >= start_pc && bci < end_pc) { + if (!ends_in_athrow(exhandlers.handler_pc(i))) { + verify_error(ErrorContext::bad_code(bci), + "Bad method call from after the start of a try block"); + return; + } else if (VerboseVerification) { + ResourceMark rm; + tty->print_cr( + "Survived call to ends_in_athrow(): %s", + current_class()->name()->as_C_string()); + } } } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/classfile/verifier.hpp --- a/hotspot/src/share/vm/classfile/verifier.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/classfile/verifier.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ #include "oops/klass.hpp" #include "oops/method.hpp" #include "runtime/handles.hpp" +#include "utilities/growableArray.hpp" #include "utilities/exceptions.hpp" // The verifier class @@ -258,9 +259,6 @@ ErrorContext _error_context; // contains information about an error - // Used to detect illegal jumps over calls to super() nd this() in ctors. - int32_t _furthest_jump; - void verify_method(methodHandle method, TRAPS); char* generate_code_data(methodHandle m, u4 code_length, TRAPS); void verify_exception_handler_table(u4 code_length, char* code_data, @@ -306,6 +304,16 @@ StackMapFrame* current_frame, u4 code_length, bool* this_uninit, constantPoolHandle cp, TRAPS); + // Used by ends_in_athrow() to push all handlers that contain bci onto + // the handler_stack, if the handler is not already on the stack. + void push_handlers(ExceptionTable* exhandlers, + GrowableArray* handler_stack, + u4 bci); + + // Returns true if all paths starting with start_bc_offset end in athrow + // bytecode or loop. + bool ends_in_athrow(u4 start_bc_offset); + void verify_invoke_instructions( RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame, bool* this_uninit, VerificationType return_type, @@ -407,19 +415,6 @@ TypeOrigin ref_ctx(const char* str, TRAPS); - // Keep track of the furthest branch done in a method to make sure that - // there are no branches over calls to super() or this() from inside of - // a constructor. - int32_t furthest_jump() { return _furthest_jump; } - - void set_furthest_jump(int32_t target) { - _furthest_jump = target; - } - - void update_furthest_jump(int32_t target) { - if (target > _furthest_jump) _furthest_jump = target; - } - }; inline int ClassVerifier::change_sig_to_verificationType( diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/code/dependencies.cpp --- a/hotspot/src/share/vm/code/dependencies.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/code/dependencies.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -407,56 +407,66 @@ // for the sake of the compiler log, print out current dependencies: void Dependencies::log_all_dependencies() { if (log() == NULL) return; - ciBaseObject* args[max_arg_count]; + ResourceMark rm; for (int deptv = (int)FIRST_TYPE; deptv < (int)TYPE_LIMIT; deptv++) { DepType dept = (DepType)deptv; GrowableArray* deps = _deps[dept]; - if (deps->length() == 0) continue; + int deplen = deps->length(); + if (deplen == 0) { + continue; + } int stride = dep_args(dept); + GrowableArray* ciargs = new GrowableArray(stride); for (int i = 0; i < deps->length(); i += stride) { for (int j = 0; j < stride; j++) { // flush out the identities before printing - args[j] = deps->at(i+j); + ciargs->push(deps->at(i+j)); } - write_dependency_to(log(), dept, stride, args); + write_dependency_to(log(), dept, ciargs); + ciargs->clear(); } + guarantee(deplen == deps->length(), "deps array cannot grow inside nested ResoureMark scope"); } } void Dependencies::write_dependency_to(CompileLog* log, DepType dept, - int nargs, DepArgument args[], + GrowableArray* args, Klass* witness) { if (log == NULL) { return; } + ResourceMark rm; ciEnv* env = ciEnv::current(); - ciBaseObject* ciargs[max_arg_count]; - assert(nargs <= max_arg_count, "oob"); - for (int j = 0; j < nargs; j++) { - if (args[j].is_oop()) { - ciargs[j] = env->get_object(args[j].oop_value()); + GrowableArray* ciargs = new GrowableArray(args->length()); + for (GrowableArrayIterator it = args->begin(); it != args->end(); ++it) { + DepArgument arg = *it; + if (arg.is_oop()) { + ciargs->push(env->get_object(arg.oop_value())); } else { - ciargs[j] = env->get_metadata(args[j].metadata_value()); + ciargs->push(env->get_metadata(arg.metadata_value())); } } - Dependencies::write_dependency_to(log, dept, nargs, ciargs, witness); + int argslen = ciargs->length(); + Dependencies::write_dependency_to(log, dept, ciargs, witness); + guarantee(argslen == ciargs->length(), "ciargs array cannot grow inside nested ResoureMark scope"); } void Dependencies::write_dependency_to(CompileLog* log, DepType dept, - int nargs, ciBaseObject* args[], + GrowableArray* args, Klass* witness) { - if (log == NULL) return; - assert(nargs <= max_arg_count, "oob"); - int argids[max_arg_count]; - int ctxkj = dep_context_arg(dept); // -1 if no context arg - int j; - for (j = 0; j < nargs; j++) { - if (args[j]->is_object()) { - argids[j] = log->identify(args[j]->as_object()); + if (log == NULL) { + return; + } + ResourceMark rm; + GrowableArray* argids = new GrowableArray(args->length()); + for (GrowableArrayIterator it = args->begin(); it != args->end(); ++it) { + ciBaseObject* obj = *it; + if (obj->is_object()) { + argids->push(log->identify(obj->as_object())); } else { - argids[j] = log->identify(args[j]->as_metadata()); + argids->push(log->identify(obj->as_metadata())); } } if (witness != NULL) { @@ -465,16 +475,17 @@ log->begin_elem("dependency"); } log->print(" type='%s'", dep_name(dept)); - if (ctxkj >= 0) { - log->print(" ctxk='%d'", argids[ctxkj]); + const int ctxkj = dep_context_arg(dept); // -1 if no context arg + if (ctxkj >= 0 && ctxkj < argids->length()) { + log->print(" ctxk='%d'", argids->at(ctxkj)); } // write remaining arguments, if any. - for (j = 0; j < nargs; j++) { + for (int j = 0; j < argids->length(); j++) { if (j == ctxkj) continue; // already logged if (j == 1) { - log->print( " x='%d'", argids[j]); + log->print( " x='%d'", argids->at(j)); } else { - log->print(" x%d='%d'", j, argids[j]); + log->print(" x%d='%d'", j, argids->at(j)); } } if (witness != NULL) { @@ -486,9 +497,12 @@ void Dependencies::write_dependency_to(xmlStream* xtty, DepType dept, - int nargs, DepArgument args[], + GrowableArray* args, Klass* witness) { - if (xtty == NULL) return; + if (xtty == NULL) { + return; + } + ResourceMark rm; ttyLocker ttyl; int ctxkj = dep_context_arg(dept); // -1 if no context arg if (witness != NULL) { @@ -498,23 +512,24 @@ } xtty->print(" type='%s'", dep_name(dept)); if (ctxkj >= 0) { - xtty->object("ctxk", args[ctxkj].metadata_value()); + xtty->object("ctxk", args->at(ctxkj).metadata_value()); } // write remaining arguments, if any. - for (int j = 0; j < nargs; j++) { + for (int j = 0; j < args->length(); j++) { if (j == ctxkj) continue; // already logged + DepArgument arg = args->at(j); if (j == 1) { - if (args[j].is_oop()) { - xtty->object("x", args[j].oop_value()); + if (arg.is_oop()) { + xtty->object("x", arg.oop_value()); } else { - xtty->object("x", args[j].metadata_value()); + xtty->object("x", arg.metadata_value()); } } else { char xn[10]; sprintf(xn, "x%d", j); - if (args[j].is_oop()) { - xtty->object(xn, args[j].oop_value()); + if (arg.is_oop()) { + xtty->object(xn, arg.oop_value()); } else { - xtty->object(xn, args[j].metadata_value()); + xtty->object(xn, arg.metadata_value()); } } } @@ -525,7 +540,7 @@ xtty->end_elem(); } -void Dependencies::print_dependency(DepType dept, int nargs, DepArgument args[], +void Dependencies::print_dependency(DepType dept, GrowableArray* args, Klass* witness) { ResourceMark rm; ttyLocker ttyl; // keep the following output all in one block @@ -534,8 +549,8 @@ dep_name(dept)); // print arguments int ctxkj = dep_context_arg(dept); // -1 if no context arg - for (int j = 0; j < nargs; j++) { - DepArgument arg = args[j]; + for (int j = 0; j < args->length(); j++) { + DepArgument arg = args->at(j); bool put_star = false; if (arg.is_null()) continue; const char* what; @@ -571,31 +586,33 @@ void Dependencies::DepStream::log_dependency(Klass* witness) { if (_deps == NULL && xtty == NULL) return; // fast cutout for runtime ResourceMark rm; - int nargs = argument_count(); - DepArgument args[max_arg_count]; + const int nargs = argument_count(); + GrowableArray* args = new GrowableArray(nargs); for (int j = 0; j < nargs; j++) { if (type() == call_site_target_value) { - args[j] = argument_oop(j); + args->push(argument_oop(j)); } else { - args[j] = argument(j); + args->push(argument(j)); } } + int argslen = args->length(); if (_deps != NULL && _deps->log() != NULL) { - Dependencies::write_dependency_to(_deps->log(), - type(), nargs, args, witness); + Dependencies::write_dependency_to(_deps->log(), type(), args, witness); } else { - Dependencies::write_dependency_to(xtty, - type(), nargs, args, witness); + Dependencies::write_dependency_to(xtty, type(), args, witness); } + guarantee(argslen == args->length(), "args array cannot grow inside nested ResoureMark scope"); } void Dependencies::DepStream::print_dependency(Klass* witness, bool verbose) { + ResourceMark rm; int nargs = argument_count(); - DepArgument args[max_arg_count]; + GrowableArray* args = new GrowableArray(nargs); for (int j = 0; j < nargs; j++) { - args[j] = argument(j); + args->push(argument(j)); } - Dependencies::print_dependency(type(), nargs, args, witness); + int argslen = args->length(); + Dependencies::print_dependency(type(), args, witness); if (verbose) { if (_code != NULL) { tty->print(" code: "); @@ -603,6 +620,7 @@ tty->cr(); } } + guarantee(argslen == args->length(), "args array cannot grow inside nested ResoureMark scope"); } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/code/dependencies.hpp --- a/hotspot/src/share/vm/code/dependencies.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/code/dependencies.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -369,20 +369,36 @@ void copy_to(nmethod* nm); void log_all_dependencies(); - void log_dependency(DepType dept, int nargs, ciBaseObject* args[]) { - write_dependency_to(log(), dept, nargs, args); + + void log_dependency(DepType dept, GrowableArray* args) { + ResourceMark rm; + int argslen = args->length(); + write_dependency_to(log(), dept, args); + guarantee(argslen == args->length(), + "args array cannot grow inside nested ResoureMark scope"); } + void log_dependency(DepType dept, ciBaseObject* x0, ciBaseObject* x1 = NULL, ciBaseObject* x2 = NULL) { - if (log() == NULL) return; - ciBaseObject* args[max_arg_count]; - args[0] = x0; - args[1] = x1; - args[2] = x2; - assert(2 < max_arg_count, ""); - log_dependency(dept, dep_args(dept), args); + if (log() == NULL) { + return; + } + ResourceMark rm; + GrowableArray* ciargs = + new GrowableArray(dep_args(dept)); + assert (x0 != NULL, "no log x0"); + ciargs->push(x0); + + if (x1 != NULL) { + ciargs->push(x1); + } + if (x2 != NULL) { + ciargs->push(x2); + } + assert(ciargs->length() == dep_args(dept), ""); + log_dependency(dept, ciargs); } class DepArgument : public ResourceObj { @@ -405,20 +421,8 @@ Metadata* metadata_value() const { assert(!_is_oop && _valid, "must be"); return (Metadata*) _value; } }; - static void write_dependency_to(CompileLog* log, - DepType dept, - int nargs, ciBaseObject* args[], - Klass* witness = NULL); - static void write_dependency_to(CompileLog* log, - DepType dept, - int nargs, DepArgument args[], - Klass* witness = NULL); - static void write_dependency_to(xmlStream* xtty, - DepType dept, - int nargs, DepArgument args[], - Klass* witness = NULL); static void print_dependency(DepType dept, - int nargs, DepArgument args[], + GrowableArray* args, Klass* witness = NULL); private: @@ -427,6 +431,18 @@ static Klass* ctxk_encoded_as_null(DepType dept, Metadata* x); + static void write_dependency_to(CompileLog* log, + DepType dept, + GrowableArray* args, + Klass* witness = NULL); + static void write_dependency_to(CompileLog* log, + DepType dept, + GrowableArray* args, + Klass* witness = NULL); + static void write_dependency_to(xmlStream* xtty, + DepType dept, + GrowableArray* args, + Klass* witness = NULL); public: // Use this to iterate over an nmethod's dependency set. // Works on new and old dependency sets. diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/compiler/compilerOracle.cpp --- a/hotspot/src/share/vm/compiler/compilerOracle.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/compiler/compilerOracle.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -33,6 +33,7 @@ #include "oops/symbol.hpp" #include "runtime/handles.inline.hpp" #include "runtime/jniHandles.hpp" +#include "runtime/os.hpp" class MethodMatcher : public CHeapObj { public: @@ -175,7 +176,11 @@ Symbol* method_name, Mode method_mode, Symbol* signature, const char * opt, MethodMatcher* next): MethodMatcher(class_name, class_mode, method_name, method_mode, signature, next) { - option = opt; + option = os::strdup_check_oom(opt); + } + + virtual ~MethodOptionMatcher() { + os::free((void*)option); } bool match(methodHandle method, const char* opt) { @@ -498,7 +503,7 @@ tty->print("CompilerOracle: %s ", command_names[command]); match->print(); } - match = add_option_string(c_name, c_match, m_name, m_match, signature, strdup(option)); + match = add_option_string(c_name, c_match, m_name, m_match, signature, option); line += bytes_read; } } else { diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.cpp --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -52,7 +52,8 @@ } void ConcurrentMarkSweepPolicy::initialize_generations() { - _generations = NEW_C_HEAP_ARRAY3(GenerationSpecPtr, number_of_generations(), mtGC, 0, AllocFailStrategy::RETURN_NULL); + _generations = NEW_C_HEAP_ARRAY3(GenerationSpecPtr, number_of_generations(), mtGC, + CURRENT_PC, AllocFailStrategy::RETURN_NULL); if (_generations == NULL) vm_exit_during_initialization("Unable to allocate gen spec"); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -5987,6 +5987,8 @@ }; void CMSRefProcTaskProxy::work(uint worker_id) { + ResourceMark rm; + HandleMark hm; assert(_collector->_span.equals(_span), "Inconsistency in _span"); CMSParKeepAliveClosure par_keep_alive(_collector, _span, _mark_bit_map, diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -2167,7 +2167,9 @@ g1h->increment_total_collections(); // Clean out dead classes and update Metaspace sizes. - ClassLoaderDataGraph::purge(); + if (ClassUnloadingWithConcurrentMark) { + ClassLoaderDataGraph::purge(); + } MetaspaceGC::compute_new_size(); // We reclaimed old regions so we should calculate the sizes to make @@ -2403,6 +2405,8 @@ } virtual void work(uint worker_id) { + ResourceMark rm; + HandleMark hm; CMTask* task = _cm->task(worker_id); G1CMIsAliveClosure g1_is_alive(_g1h); G1CMKeepAliveAndDrainClosure g1_par_keep_alive(_cm, task, false /* is_serial */); @@ -2595,24 +2599,27 @@ assert(_markStack.isEmpty(), "Marking should have completed"); // Unload Klasses, String, Symbols, Code Cache, etc. - - G1RemarkGCTraceTime trace("Unloading", G1Log::finer()); - - bool purged_classes; - { - G1RemarkGCTraceTime trace("System Dictionary Unloading", G1Log::finest()); - purged_classes = SystemDictionary::do_unloading(&g1_is_alive); - } - - { - G1RemarkGCTraceTime trace("Parallel Unloading", G1Log::finest()); - weakRefsWorkParallelPart(&g1_is_alive, purged_classes); - } - - if (G1StringDedup::is_enabled()) { - G1RemarkGCTraceTime trace("String Deduplication Unlink", G1Log::finest()); - G1StringDedup::unlink(&g1_is_alive); + G1RemarkGCTraceTime trace("Unloading", G1Log::finer()); + + if (ClassUnloadingWithConcurrentMark) { + bool purged_classes; + + { + G1RemarkGCTraceTime trace("System Dictionary Unloading", G1Log::finest()); + purged_classes = SystemDictionary::do_unloading(&g1_is_alive); + } + + { + G1RemarkGCTraceTime trace("Parallel Unloading", G1Log::finest()); + weakRefsWorkParallelPart(&g1_is_alive, purged_classes); + } + } + + if (G1StringDedup::is_enabled()) { + G1RemarkGCTraceTime trace("String Deduplication Unlink", G1Log::finest()); + G1StringDedup::unlink(&g1_is_alive); + } } } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -1926,6 +1926,8 @@ _secondary_free_list("Secondary Free List", new SecondaryFreeRegionListMtSafeChecker()), _old_set("Old Set", false /* humongous */, new OldRegionSetMtSafeChecker()), _humongous_set("Master Humongous Set", true /* humongous */, new HumongousRegionSetMtSafeChecker()), + _humongous_is_live(), + _has_humongous_reclaim_candidates(false), _free_regions_coming(false), _young_list(new YoungList(this)), _gc_time_stamp(0), @@ -2082,6 +2084,7 @@ _g1h = this; _in_cset_fast_test.initialize(_g1_reserved.start(), _g1_reserved.end(), HeapRegion::GrainBytes); + _humongous_is_live.initialize(_g1_reserved.start(), _g1_reserved.end(), HeapRegion::GrainBytes); // Create the ConcurrentMark data structure and thread. // (Must do this late, so that "max_regions" is defined.) @@ -2177,6 +2180,11 @@ } } +void G1CollectedHeap::clear_humongous_is_live_table() { + guarantee(G1ReclaimDeadHumongousObjectsAtYoungGC, "Should only be called if true"); + _humongous_is_live.clear(); +} + size_t G1CollectedHeap::conservative_max_heap_alignment() { return HeapRegion::max_region_size(); } @@ -2574,15 +2582,12 @@ // Iteration functions. -// Iterates an OopClosure over all ref-containing fields of objects -// within a HeapRegion. +// Applies an ExtendedOopClosure onto all references of objects within a HeapRegion. class IterateOopClosureRegionClosure: public HeapRegionClosure { - MemRegion _mr; ExtendedOopClosure* _cl; public: - IterateOopClosureRegionClosure(MemRegion mr, ExtendedOopClosure* cl) - : _mr(mr), _cl(cl) {} + IterateOopClosureRegionClosure(ExtendedOopClosure* cl) : _cl(cl) {} bool doHeapRegion(HeapRegion* r) { if (!r->continuesHumongous()) { r->oop_iterate(_cl); @@ -2592,12 +2597,7 @@ }; void G1CollectedHeap::oop_iterate(ExtendedOopClosure* cl) { - IterateOopClosureRegionClosure blk(_g1_committed, cl); - heap_region_iterate(&blk); -} - -void G1CollectedHeap::oop_iterate(MemRegion mr, ExtendedOopClosure* cl) { - IterateOopClosureRegionClosure blk(mr, cl); + IterateOopClosureRegionClosure blk(cl); heap_region_iterate(&blk); } @@ -3771,6 +3771,61 @@ return g1_rem_set()->cardsScanned(); } +bool G1CollectedHeap::humongous_region_is_always_live(uint index) { + HeapRegion* region = region_at(index); + assert(region->startsHumongous(), "Must start a humongous object"); + return oop(region->bottom())->is_objArray() || !region->rem_set()->is_empty(); +} + +class RegisterHumongousWithInCSetFastTestClosure : public HeapRegionClosure { + private: + size_t _total_humongous; + size_t _candidate_humongous; + public: + RegisterHumongousWithInCSetFastTestClosure() : _total_humongous(0), _candidate_humongous(0) { + } + + virtual bool doHeapRegion(HeapRegion* r) { + if (!r->startsHumongous()) { + return false; + } + G1CollectedHeap* g1h = G1CollectedHeap::heap(); + + uint region_idx = r->hrs_index(); + bool is_candidate = !g1h->humongous_region_is_always_live(region_idx); + // Is_candidate already filters out humongous regions with some remembered set. + // This will not lead to humongous object that we mistakenly keep alive because + // during young collection the remembered sets will only be added to. + if (is_candidate) { + g1h->register_humongous_region_with_in_cset_fast_test(region_idx); + _candidate_humongous++; + } + _total_humongous++; + + return false; + } + + size_t total_humongous() const { return _total_humongous; } + size_t candidate_humongous() const { return _candidate_humongous; } +}; + +void G1CollectedHeap::register_humongous_regions_with_in_cset_fast_test() { + if (!G1ReclaimDeadHumongousObjectsAtYoungGC) { + g1_policy()->phase_times()->record_fast_reclaim_humongous_stats(0, 0); + return; + } + + RegisterHumongousWithInCSetFastTestClosure cl; + heap_region_iterate(&cl); + g1_policy()->phase_times()->record_fast_reclaim_humongous_stats(cl.total_humongous(), + cl.candidate_humongous()); + _has_humongous_reclaim_candidates = cl.candidate_humongous() > 0; + + if (_has_humongous_reclaim_candidates) { + clear_humongous_is_live_table(); + } +} + void G1CollectedHeap::setup_surviving_young_words() { assert(_surviving_young_words == NULL, "pre-condition"); @@ -4058,6 +4113,8 @@ g1_policy()->finalize_cset(target_pause_time_ms, evacuation_info); + register_humongous_regions_with_in_cset_fast_test(); + _cm->note_start_of_gc(); // We should not verify the per-thread SATB buffers given that // we have not filtered them yet (we'll do so during the @@ -4108,6 +4165,9 @@ true /* verify_fingers */); free_collection_set(g1_policy()->collection_set(), evacuation_info); + + eagerly_reclaim_humongous_regions(); + g1_policy()->clear_collection_set(); cleanup_surviving_young_words(); @@ -4608,7 +4668,9 @@ assert(_worker_id == _par_scan_state->queue_num(), "sanity"); - if (_g1->in_cset_fast_test(obj)) { + G1CollectedHeap::in_cset_state_t state = _g1->in_cset_state(obj); + + if (state == G1CollectedHeap::InCSet) { oop forwardee; if (obj->is_forwarded()) { forwardee = obj->forwardee(); @@ -4627,6 +4689,9 @@ do_klass_barrier(p, forwardee); } } else { + if (state == G1CollectedHeap::IsHumongous) { + _g1->set_humongous_is_live(obj); + } // The object is not in collection set. If we're a root scanning // closure during an initial mark pause then attempt to mark the object. if (do_mark_object == G1MarkFromRoot) { @@ -4719,11 +4784,6 @@ Mutex _stats_lock; Mutex* stats_lock() { return &_stats_lock; } - size_t getNCards() { - return (_g1h->capacity() + G1BlockOffsetSharedArray::N_bytes - 1) - / G1BlockOffsetSharedArray::N_bytes; - } - public: G1ParTask(G1CollectedHeap* g1h, RefToScanQueueSet *task_queues) : AbstractGangTask("G1 collection"), @@ -4847,10 +4907,15 @@ if (_g1h->g1_policy()->during_initial_mark_pause()) { // We also need to mark copied objects. strong_root_cl = &scan_mark_root_cl; - weak_root_cl = &scan_mark_weak_root_cl; strong_cld_cl = &scan_mark_cld_cl; - weak_cld_cl = &scan_mark_weak_cld_cl; strong_code_cl = &scan_mark_code_cl; + if (ClassUnloadingWithConcurrentMark) { + weak_root_cl = &scan_mark_weak_root_cl; + weak_cld_cl = &scan_mark_weak_cld_cl; + } else { + weak_root_cl = &scan_mark_root_cl; + weak_cld_cl = &scan_mark_cld_cl; + } } else { strong_root_cl = &scan_only_root_cl; weak_root_cl = &scan_only_root_cl; @@ -4921,6 +4986,7 @@ double closure_app_time_sec = 0.0; bool during_im = _g1h->g1_policy()->during_initial_mark_pause(); + bool trace_metadata = during_im && ClassUnloadingWithConcurrentMark; BufferingOopClosure buf_scan_non_heap_roots(scan_non_heap_roots); BufferingOopClosure buf_scan_non_heap_weak_roots(scan_non_heap_weak_roots); @@ -4930,8 +4996,8 @@ &buf_scan_non_heap_roots, &buf_scan_non_heap_weak_roots, scan_strong_clds, - // Initial Mark handles the weak CLDs separately. - (during_im ? NULL : scan_weak_clds), + // Unloading Initial Marks handle the weak CLDs separately. + (trace_metadata ? NULL : scan_weak_clds), scan_strong_code); // Now the CM ref_processor roots. @@ -4943,7 +5009,7 @@ ref_processor_cm()->weak_oops_do(&buf_scan_non_heap_roots); } - if (during_im) { + if (trace_metadata) { // Barrier to make sure all workers passed // the strong CLD and strong nmethods phases. active_strong_roots_scope()->wait_until_all_workers_done_with_threads(n_par_threads()); @@ -5450,12 +5516,21 @@ public: G1KeepAliveClosure(G1CollectedHeap* g1) : _g1(g1) {} void do_oop(narrowOop* p) { guarantee(false, "Not needed"); } - void do_oop( oop* p) { + void do_oop(oop* p) { oop obj = *p; - if (_g1->obj_in_cs(obj)) { + G1CollectedHeap::in_cset_state_t cset_state = _g1->in_cset_state(obj); + if (obj == NULL || cset_state == G1CollectedHeap::InNeither) { + return; + } + if (cset_state == G1CollectedHeap::InCSet) { assert( obj->is_forwarded(), "invariant" ); *p = obj->forwardee(); + } else { + assert(!obj->is_forwarded(), "invariant" ); + assert(cset_state == G1CollectedHeap::IsHumongous, + err_msg("Only allowed InCSet state is IsHumongous, but is %d", cset_state)); + _g1->set_humongous_is_live(obj); } } }; @@ -5485,7 +5560,7 @@ template void do_oop_work(T* p) { oop obj = oopDesc::load_decode_heap_oop(p); - if (_g1h->obj_in_cs(obj)) { + if (_g1h->is_in_cset_or_humongous(obj)) { // If the referent object has been forwarded (either copied // to a new location or to itself in the event of an // evacuation failure) then we need to update the reference @@ -5510,10 +5585,10 @@ assert(!Metaspace::contains((const void*)p), err_msg("Unexpectedly found a pointer from metadata: " PTR_FORMAT, p)); - _copy_non_heap_obj_cl->do_oop(p); - } + _copy_non_heap_obj_cl->do_oop(p); } } + } }; // Serial drain queue closure. Called as the 'complete_gc' @@ -6435,6 +6510,154 @@ policy->phase_times()->record_non_young_free_cset_time_ms(non_young_time_ms); } +class G1FreeHumongousRegionClosure : public HeapRegionClosure { + private: + FreeRegionList* _free_region_list; + HeapRegionSet* _proxy_set; + HeapRegionSetCount _humongous_regions_removed; + size_t _freed_bytes; + public: + + G1FreeHumongousRegionClosure(FreeRegionList* free_region_list) : + _free_region_list(free_region_list), _humongous_regions_removed(), _freed_bytes(0) { + } + + virtual bool doHeapRegion(HeapRegion* r) { + if (!r->startsHumongous()) { + return false; + } + + G1CollectedHeap* g1h = G1CollectedHeap::heap(); + + oop obj = (oop)r->bottom(); + CMBitMap* next_bitmap = g1h->concurrent_mark()->nextMarkBitMap(); + + // The following checks whether the humongous object is live are sufficient. + // The main additional check (in addition to having a reference from the roots + // or the young gen) is whether the humongous object has a remembered set entry. + // + // A humongous object cannot be live if there is no remembered set for it + // because: + // - there can be no references from within humongous starts regions referencing + // the object because we never allocate other objects into them. + // (I.e. there are no intra-region references that may be missed by the + // remembered set) + // - as soon there is a remembered set entry to the humongous starts region + // (i.e. it has "escaped" to an old object) this remembered set entry will stay + // until the end of a concurrent mark. + // + // It is not required to check whether the object has been found dead by marking + // or not, in fact it would prevent reclamation within a concurrent cycle, as + // all objects allocated during that time are considered live. + // SATB marking is even more conservative than the remembered set. + // So if at this point in the collection there is no remembered set entry, + // nobody has a reference to it. + // At the start of collection we flush all refinement logs, and remembered sets + // are completely up-to-date wrt to references to the humongous object. + // + // Other implementation considerations: + // - never consider object arrays: while they are a valid target, they have not + // been observed to be used as temporary objects. + // - they would also pose considerable effort for cleaning up the the remembered + // sets. + // While this cleanup is not strictly necessary to be done (or done instantly), + // given that their occurrence is very low, this saves us this additional + // complexity. + uint region_idx = r->hrs_index(); + if (g1h->humongous_is_live(region_idx) || + g1h->humongous_region_is_always_live(region_idx)) { + + if (G1TraceReclaimDeadHumongousObjectsAtYoungGC) { + gclog_or_tty->print_cr("Live humongous %d region %d with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d live-other %d obj array %d", + r->isHumongous(), + region_idx, + r->rem_set()->occupied(), + r->rem_set()->strong_code_roots_list_length(), + next_bitmap->isMarked(r->bottom()), + g1h->humongous_is_live(region_idx), + obj->is_objArray() + ); + } + + return false; + } + + guarantee(!obj->is_objArray(), + err_msg("Eagerly reclaiming object arrays is not supported, but the object "PTR_FORMAT" is.", + r->bottom())); + + if (G1TraceReclaimDeadHumongousObjectsAtYoungGC) { + gclog_or_tty->print_cr("Reclaim humongous region %d start "PTR_FORMAT" region %d length "UINT32_FORMAT" with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d live-other %d obj array %d", + r->isHumongous(), + r->bottom(), + region_idx, + r->region_num(), + r->rem_set()->occupied(), + r->rem_set()->strong_code_roots_list_length(), + next_bitmap->isMarked(r->bottom()), + g1h->humongous_is_live(region_idx), + obj->is_objArray() + ); + } + // Need to clear mark bit of the humongous object if already set. + if (next_bitmap->isMarked(r->bottom())) { + next_bitmap->clear(r->bottom()); + } + _freed_bytes += r->used(); + r->set_containing_set(NULL); + _humongous_regions_removed.increment(1u, r->capacity()); + g1h->free_humongous_region(r, _free_region_list, false); + + return false; + } + + HeapRegionSetCount& humongous_free_count() { + return _humongous_regions_removed; + } + + size_t bytes_freed() const { + return _freed_bytes; + } + + size_t humongous_reclaimed() const { + return _humongous_regions_removed.length(); + } +}; + +void G1CollectedHeap::eagerly_reclaim_humongous_regions() { + assert_at_safepoint(true); + + if (!G1ReclaimDeadHumongousObjectsAtYoungGC || !_has_humongous_reclaim_candidates) { + g1_policy()->phase_times()->record_fast_reclaim_humongous_time_ms(0.0, 0); + return; + } + + double start_time = os::elapsedTime(); + + FreeRegionList local_cleanup_list("Local Humongous Cleanup List"); + + G1FreeHumongousRegionClosure cl(&local_cleanup_list); + heap_region_iterate(&cl); + + HeapRegionSetCount empty_set; + remove_from_old_sets(empty_set, cl.humongous_free_count()); + + G1HRPrinter* hr_printer = _g1h->hr_printer(); + if (hr_printer->is_active()) { + FreeRegionListIterator iter(&local_cleanup_list); + while (iter.more_available()) { + HeapRegion* hr = iter.get_next(); + hr_printer->cleanup(hr); + } + } + + prepend_to_freelist(&local_cleanup_list); + decrement_summary_bytes(cl.bytes_freed()); + + g1_policy()->phase_times()->record_fast_reclaim_humongous_time_ms((os::elapsedTime() - start_time) * 1000.0, + cl.humongous_reclaimed()); +} + // This routine is similar to the above but does not record // any policy statistics or update free lists; we are abandoning // the current incremental collection set in preparation of a diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -197,16 +197,6 @@ bool do_object_b(oop p); }; -// Instances of this class are used for quick tests on whether a reference points -// into the collection set. Each of the array's elements denotes whether the -// corresponding region is in the collection set. -class G1FastCSetBiasedMappedArray : public G1BiasedMappedArray { - protected: - bool default_value() const { return false; } - public: - void clear() { G1BiasedMappedArray::clear(); } -}; - class RefineCardTableEntryClosure; class G1CollectedHeap : public SharedHeap { @@ -237,6 +227,7 @@ friend class EvacPopObjClosure; friend class G1ParCleanupCTTask; + friend class G1FreeHumongousRegionClosure; // Other related classes. friend class G1MarkSweep; @@ -267,6 +258,9 @@ // It keeps track of the humongous regions. HeapRegionSet _humongous_set; + void clear_humongous_is_live_table(); + void eagerly_reclaim_humongous_regions(); + // The number of regions we could create by expansion. uint _expansion_regions; @@ -367,10 +361,25 @@ // than the current allocation region. size_t _summary_bytes_used; - // This array is used for a quick test on whether a reference points into - // the collection set or not. Each of the array's elements denotes whether the - // corresponding region is in the collection set or not. - G1FastCSetBiasedMappedArray _in_cset_fast_test; + // Records whether the region at the given index is kept live by roots or + // references from the young generation. + class HumongousIsLiveBiasedMappedArray : public G1BiasedMappedArray { + protected: + bool default_value() const { return false; } + public: + void clear() { G1BiasedMappedArray::clear(); } + void set_live(uint region) { + set_by_index(region, true); + } + bool is_live(uint region) { + return get_by_index(region); + } + }; + + HumongousIsLiveBiasedMappedArray _humongous_is_live; + // Stores whether during humongous object registration we found candidate regions. + // If not, we can skip a few steps. + bool _has_humongous_reclaim_candidates; volatile unsigned _gc_time_stamp; @@ -690,10 +699,24 @@ virtual void gc_prologue(bool full); virtual void gc_epilogue(bool full); + inline void set_humongous_is_live(oop obj); + + bool humongous_is_live(uint region) { + return _humongous_is_live.is_live(region); + } + + // Returns whether the given region (which must be a humongous (start) region) + // is to be considered conservatively live regardless of any other conditions. + bool humongous_region_is_always_live(uint index); + // Register the given region to be part of the collection set. + inline void register_humongous_region_with_in_cset_fast_test(uint index); + // Register regions with humongous objects (actually on the start region) in + // the in_cset_fast_test table. + void register_humongous_regions_with_in_cset_fast_test(); // We register a region with the fast "in collection set" test. We // simply set to true the array slot corresponding to this region. void register_region_with_in_cset_fast_test(HeapRegion* r) { - _in_cset_fast_test.set_by_index(r->hrs_index(), true); + _in_cset_fast_test.set_in_cset(r->hrs_index()); } // This is a fast test on whether a reference points into the @@ -1283,9 +1306,61 @@ virtual bool is_in(const void* p) const; // Return "TRUE" iff the given object address is within the collection - // set. + // set. Slow implementation. inline bool obj_in_cs(oop obj); + inline bool is_in_cset(oop obj); + + inline bool is_in_cset_or_humongous(const oop obj); + + enum in_cset_state_t { + InNeither, // neither in collection set nor humongous + InCSet, // region is in collection set only + IsHumongous // region is a humongous start region + }; + private: + // Instances of this class are used for quick tests on whether a reference points + // into the collection set or is a humongous object (points into a humongous + // object). + // Each of the array's elements denotes whether the corresponding region is in + // the collection set or a humongous region. + // We use this to quickly reclaim humongous objects: by making a humongous region + // succeed this test, we sort-of add it to the collection set. During the reference + // iteration closures, when we see a humongous region, we simply mark it as + // referenced, i.e. live. + class G1FastCSetBiasedMappedArray : public G1BiasedMappedArray { + protected: + char default_value() const { return G1CollectedHeap::InNeither; } + public: + void set_humongous(uintptr_t index) { + assert(get_by_index(index) != InCSet, "Should not overwrite InCSet values"); + set_by_index(index, G1CollectedHeap::IsHumongous); + } + + void clear_humongous(uintptr_t index) { + set_by_index(index, G1CollectedHeap::InNeither); + } + + void set_in_cset(uintptr_t index) { + assert(get_by_index(index) != G1CollectedHeap::IsHumongous, "Should not overwrite IsHumongous value"); + set_by_index(index, G1CollectedHeap::InCSet); + } + + bool is_in_cset_or_humongous(HeapWord* addr) const { return get_by_address(addr) != G1CollectedHeap::InNeither; } + bool is_in_cset(HeapWord* addr) const { return get_by_address(addr) == G1CollectedHeap::InCSet; } + G1CollectedHeap::in_cset_state_t at(HeapWord* addr) const { return (G1CollectedHeap::in_cset_state_t)get_by_address(addr); } + void clear() { G1BiasedMappedArray::clear(); } + }; + + // This array is used for a quick test on whether a reference points into + // the collection set or not. Each of the array's elements denotes whether the + // corresponding region is in the collection set or not. + G1FastCSetBiasedMappedArray _in_cset_fast_test; + + public: + + inline in_cset_state_t in_cset_state(const oop obj); + // Return "TRUE" iff the given object address is in the reserved // region of g1. bool is_in_g1_reserved(const void* p) const { @@ -1320,9 +1395,6 @@ // "cl.do_oop" on each. virtual void oop_iterate(ExtendedOopClosure* cl); - // Same as above, restricted to a memory region. - void oop_iterate(MemRegion mr, ExtendedOopClosure* cl); - // Iterate over all objects, calling "cl.do_object" on each. virtual void object_iterate(ObjectClosure* cl); @@ -1340,6 +1412,10 @@ // Return the region with the given index. It assumes the index is valid. inline HeapRegion* region_at(uint index) const; + // Calculate the region index of the given address. Given address must be + // within the heap. + inline uint addr_to_region(HeapWord* addr) const; + // Divide the heap region sequence into "chunks" of some size (the number // of regions divided by the number of parallel threads times some // overpartition factor, currently 4). Assumes that this will be called diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -40,6 +40,13 @@ // Return the region with the given index. It assumes the index is valid. inline HeapRegion* G1CollectedHeap::region_at(uint index) const { return _hrs.at(index); } +inline uint G1CollectedHeap::addr_to_region(HeapWord* addr) const { + assert(is_in_reserved(addr), + err_msg("Cannot calculate region index for address "PTR_FORMAT" that is outside of the heap ["PTR_FORMAT", "PTR_FORMAT")", + p2i(addr), p2i(_reserved.start()), p2i(_reserved.end()))); + return (uint)(pointer_delta(addr, _reserved.start(), sizeof(uint8_t)) >> HeapRegion::LogOfHRGrainBytes); +} + template inline HeapRegion* G1CollectedHeap::heap_region_containing_raw(const T addr) const { @@ -172,12 +179,11 @@ return _cm->nextMarkBitMap()->isMarked((HeapWord *)obj); } - // This is a fast test on whether a reference points into the // collection set or not. Assume that the reference // points into the heap. -inline bool G1CollectedHeap::in_cset_fast_test(oop obj) { - bool ret = _in_cset_fast_test.get_by_address((HeapWord*)obj); +inline bool G1CollectedHeap::is_in_cset(oop obj) { + bool ret = _in_cset_fast_test.is_in_cset((HeapWord*)obj); // let's make sure the result is consistent with what the slower // test returns assert( ret || !obj_in_cs(obj), "sanity"); @@ -185,6 +191,18 @@ return ret; } +bool G1CollectedHeap::is_in_cset_or_humongous(const oop obj) { + return _in_cset_fast_test.is_in_cset_or_humongous((HeapWord*)obj); +} + +G1CollectedHeap::in_cset_state_t G1CollectedHeap::in_cset_state(const oop obj) { + return _in_cset_fast_test.at((HeapWord*)obj); +} + +void G1CollectedHeap::register_humongous_region_with_in_cset_fast_test(uint index) { + _in_cset_fast_test.set_humongous(index); +} + #ifndef PRODUCT // Support for G1EvacuationFailureALot @@ -288,4 +306,22 @@ return is_obj_ill(obj, heap_region_containing(obj)); } +inline void G1CollectedHeap::set_humongous_is_live(oop obj) { + uint region = addr_to_region((HeapWord*)obj); + // We not only set the "live" flag in the humongous_is_live table, but also + // reset the entry in the _in_cset_fast_test table so that subsequent references + // to the same humongous object do not go into the slow path again. + // This is racy, as multiple threads may at the same time enter here, but this + // is benign. + // During collection we only ever set the "live" flag, and only ever clear the + // entry in the in_cset_fast_table. + // We only ever evaluate the contents of these tables (in the VM thread) after + // having synchronized the worker threads with the VM thread, or in the same + // thread (i.e. within the VM thread). + if (!_humongous_is_live.is_live(region)) { + _humongous_is_live.set_live(region); + _in_cset_fast_test.clear_humongous(region); + } +} + #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1COLLECTEDHEAP_INLINE_HPP diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -237,8 +237,10 @@ _last_gc_worker_times_ms.verify(); _last_gc_worker_other_times_ms.verify(); - _last_redirty_logged_cards_time_ms.verify(); - _last_redirty_logged_cards_processed_cards.verify(); + if (G1DeferredRSUpdate) { + _last_redirty_logged_cards_time_ms.verify(); + _last_redirty_logged_cards_processed_cards.verify(); + } } void G1GCPhaseTimes::note_string_dedup_fixup_start() { @@ -255,6 +257,10 @@ LineBuffer(level).append_and_print_cr("[%s: %.1lf ms]", str, value); } +void G1GCPhaseTimes::print_stats(int level, const char* str, size_t value) { + LineBuffer(level).append_and_print_cr("[%s: "SIZE_FORMAT"]", str, value); +} + void G1GCPhaseTimes::print_stats(int level, const char* str, double value, uint workers) { LineBuffer(level).append_and_print_cr("[%s: %.1lf ms, GC Workers: %u]", str, value, workers); } @@ -357,6 +363,14 @@ _last_redirty_logged_cards_processed_cards.print(3, "Redirtied Cards"); } } + if (G1ReclaimDeadHumongousObjectsAtYoungGC) { + print_stats(2, "Humongous Reclaim", _cur_fast_reclaim_humongous_time_ms); + if (G1Log::finest()) { + print_stats(3, "Humongous Total", _cur_fast_reclaim_humongous_total); + print_stats(3, "Humongous Candidate", _cur_fast_reclaim_humongous_candidates); + print_stats(3, "Humongous Reclaimed", _cur_fast_reclaim_humongous_reclaimed); + } + } print_stats(2, "Free CSet", (_recorded_young_free_cset_time_ms + _recorded_non_young_free_cset_time_ms)); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -157,11 +157,17 @@ double _recorded_young_free_cset_time_ms; double _recorded_non_young_free_cset_time_ms; + double _cur_fast_reclaim_humongous_time_ms; + size_t _cur_fast_reclaim_humongous_total; + size_t _cur_fast_reclaim_humongous_candidates; + size_t _cur_fast_reclaim_humongous_reclaimed; + double _cur_verify_before_time_ms; double _cur_verify_after_time_ms; // Helper methods for detailed logging void print_stats(int level, const char* str, double value); + void print_stats(int level, const char* str, size_t value); void print_stats(int level, const char* str, double value, uint workers); public: @@ -282,6 +288,16 @@ _recorded_non_young_free_cset_time_ms = time_ms; } + void record_fast_reclaim_humongous_stats(size_t total, size_t candidates) { + _cur_fast_reclaim_humongous_total = total; + _cur_fast_reclaim_humongous_candidates = candidates; + } + + void record_fast_reclaim_humongous_time_ms(double value, size_t reclaimed) { + _cur_fast_reclaim_humongous_time_ms = value; + _cur_fast_reclaim_humongous_reclaimed = reclaimed; + } + void record_young_cset_choice_time_ms(double time_ms) { _recorded_young_cset_choice_time_ms = time_ms; } @@ -348,6 +364,10 @@ return _recorded_non_young_free_cset_time_ms; } + double fast_reclaim_humongous_time_ms() { + return _cur_fast_reclaim_humongous_time_ms; + } + double average_last_update_rs_time() { return _last_update_rs_times_ms.average(); } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -44,7 +44,7 @@ inline void FilterIntoCSClosure::do_oop_nv(T* p) { T heap_oop = oopDesc::load_heap_oop(p); if (!oopDesc::is_null(heap_oop) && - _g1->obj_in_cs(oopDesc::decode_heap_oop_not_null(heap_oop))) { + _g1->is_in_cset_or_humongous(oopDesc::decode_heap_oop_not_null(heap_oop))) { _oc->do_oop(p); } } @@ -67,7 +67,8 @@ if (!oopDesc::is_null(heap_oop)) { oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); - if (_g1->in_cset_fast_test(obj)) { + G1CollectedHeap::in_cset_state_t state = _g1->in_cset_state(obj); + if (state == G1CollectedHeap::InCSet) { // We're not going to even bother checking whether the object is // already forwarded or not, as this usually causes an immediate // stall. We'll try to prefetch the object (for write, given that @@ -86,6 +87,9 @@ _par_scan_state->push_on_queue(p); } else { + if (state == G1CollectedHeap::IsHumongous) { + _g1->set_humongous_is_live(obj); + } _par_scan_state->update_rs(_from, p, _worker_id); } } @@ -97,12 +101,14 @@ if (!oopDesc::is_null(heap_oop)) { oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); - if (_g1->in_cset_fast_test(obj)) { + if (_g1->is_in_cset_or_humongous(obj)) { Prefetch::write(obj->mark_addr(), 0); Prefetch::read(obj->mark_addr(), (HeapWordSize*2)); // Place on the references queue _par_scan_state->push_on_queue(p); + } else { + assert(!_g1->obj_in_cs(obj), "checking"); } } } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -288,7 +288,12 @@ } HeapWord* G1ParScanThreadState::allocate(GCAllocPurpose purpose, size_t word_sz) { - HeapWord* obj = alloc_buffer(purpose)->allocate(word_sz); + HeapWord* obj = NULL; + if (purpose == GCAllocForSurvived) { + obj = alloc_buffer(GCAllocForSurvived)->allocate_aligned(word_sz, SurvivorAlignmentInBytes); + } else { + obj = alloc_buffer(GCAllocForTenured)->allocate(word_sz); + } if (obj != NULL) { return obj; } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.inline.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.inline.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.inline.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -52,15 +52,20 @@ // set, due to (benign) races in the claim mechanism during RSet scanning more // than one thread might claim the same card. So the same card may be // processed multiple times. So redo this check. - if (_g1h->in_cset_fast_test(obj)) { + G1CollectedHeap::in_cset_state_t in_cset_state = _g1h->in_cset_state(obj); + if (in_cset_state == G1CollectedHeap::InCSet) { oop forwardee; if (obj->is_forwarded()) { forwardee = obj->forwardee(); } else { forwardee = copy_to_survivor_space(obj); } - assert(forwardee != NULL, "forwardee should not be NULL"); oopDesc::encode_store_heap_oop(p, forwardee); + } else if (in_cset_state == G1CollectedHeap::IsHumongous) { + _g1h->set_humongous_is_live(obj); + } else { + assert(in_cset_state == G1CollectedHeap::InNeither, + err_msg("In_cset_state must be InNeither here, but is %d", in_cset_state)); } assert(obj != NULL, "Must be"); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -349,23 +349,8 @@ assert((ParallelGCThreads > 0) || worker_i == 0, "invariant"); - // The two flags below were introduced temporarily to serialize - // the updating and scanning of remembered sets. There are some - // race conditions when these two operations are done in parallel - // and they are causing failures. When we resolve said race - // conditions, we'll revert back to parallel remembered set - // updating and scanning. See CRs 6677707 and 6677708. - if (G1UseParallelRSetUpdating || (worker_i == 0)) { - updateRS(&into_cset_dcq, worker_i); - } else { - _g1p->phase_times()->record_update_rs_processed_buffers(worker_i, 0); - _g1p->phase_times()->record_update_rs_time(worker_i, 0.0); - } - if (G1UseParallelRSetScanning || (worker_i == 0)) { - scanRS(oc, code_root_cl, worker_i); - } else { - _g1p->phase_times()->record_scan_rs_time(worker_i, 0.0); - } + updateRS(&into_cset_dcq, worker_i); + scanRS(oc, code_root_cl, worker_i); // We now clear the cached values of _cset_rs_update_cl for this worker _cset_rs_update_cl[worker_i] = NULL; diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -220,14 +220,6 @@ product(uintx, G1HeapRegionSize, 0, \ "Size of the G1 regions.") \ \ - experimental(bool, G1UseParallelRSetUpdating, true, \ - "Enables the parallelization of remembered set updating " \ - "during evacuation pauses") \ - \ - experimental(bool, G1UseParallelRSetScanning, true, \ - "Enables the parallelization of remembered set scanning " \ - "during evacuation pauses") \ - \ product(uintx, G1ConcRefinementThreads, 0, \ "If non-0 is the number of parallel rem set update threads, " \ "otherwise the value is determined ergonomically.") \ @@ -289,6 +281,13 @@ "The amount of code root chunks that should be kept at most " \ "as percentage of already allocated.") \ \ + experimental(bool, G1ReclaimDeadHumongousObjectsAtYoungGC, true, \ + "Try to reclaim dead large objects at every young GC.") \ + \ + experimental(bool, G1TraceReclaimDeadHumongousObjectsAtYoungGC, false, \ + "Print some information about large object liveness " \ + "at every young GC.") \ + \ experimental(uintx, G1OldCSetRegionThresholdPercent, 10, \ "An upper bound for the number of old CSet regions expressed " \ "as a percentage of the heap size.") \ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/gc_implementation/g1/heapRegion.inline.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.inline.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.inline.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -94,26 +94,37 @@ inline bool HeapRegion::block_is_obj(const HeapWord* p) const { G1CollectedHeap* g1h = G1CollectedHeap::heap(); - return !g1h->is_obj_dead(oop(p), this); + if (ClassUnloadingWithConcurrentMark) { + return !g1h->is_obj_dead(oop(p), this); + } + return p < top(); } inline size_t HeapRegion::block_size(const HeapWord *addr) const { + if (addr == top()) { + return pointer_delta(end(), addr); + } + + if (block_is_obj(addr)) { + return oop(addr)->size(); + } + + assert(ClassUnloadingWithConcurrentMark, + err_msg("All blocks should be objects if G1 Class Unloading isn't used. " + "HR: ["PTR_FORMAT", "PTR_FORMAT", "PTR_FORMAT") " + "addr: " PTR_FORMAT, + p2i(bottom()), p2i(top()), p2i(end()), p2i(addr))); + // Old regions' dead objects may have dead classes // We need to find the next live object in some other // manner than getting the oop size G1CollectedHeap* g1h = G1CollectedHeap::heap(); - if (g1h->is_obj_dead(oop(addr), this)) { - HeapWord* next = g1h->concurrent_mark()->prevMarkBitMap()-> - getNextMarkedWordAddress(addr, prev_top_at_mark_start()); - - assert(next > addr, "must get the next live object"); + HeapWord* next = g1h->concurrent_mark()->prevMarkBitMap()-> + getNextMarkedWordAddress(addr, prev_top_at_mark_start()); - return pointer_delta(next, addr); - } else if (addr == top()) { - return pointer_delta(end(), addr); - } - return oop(addr)->size(); + assert(next > addr, "must get the next live object"); + return pointer_delta(next, addr); } inline HeapWord* HeapRegion::par_allocate_no_bot_updates(size_t word_size) { diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -289,7 +289,7 @@ } _fine_grain_regions = NEW_C_HEAP_ARRAY3(PerRegionTablePtr, _max_fine_entries, - mtGC, 0, AllocFailStrategy::RETURN_NULL); + mtGC, CURRENT_PC, AllocFailStrategy::RETURN_NULL); if (_fine_grain_regions == NULL) { vm_exit_out_of_memory(sizeof(void*)*_max_fine_entries, OOM_MALLOC_ERROR, @@ -695,6 +695,9 @@ clear_fcc(); } +bool OtherRegionsTable::is_empty() const { + return occ_sparse() == 0 && occ_coarse() == 0 && _first_all_fine_prts == NULL; +} size_t OtherRegionsTable::occupied() const { size_t sum = occ_fine(); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -185,6 +185,9 @@ // objects. void scrub(CardTableModRefBS* ctbs, BitMap* region_bm, BitMap* card_bm); + // Returns whether this remembered set (and all sub-sets) contain no entries. + bool is_empty() const; + size_t occupied() const; size_t occ_fine() const; size_t occ_coarse() const; @@ -269,6 +272,10 @@ return _other_regions.hr(); } + bool is_empty() const { + return (strong_code_roots_list_length() == 0) && _other_regions.is_empty(); + } + size_t occupied() { MutexLockerEx x(&_m, Mutex::_no_safepoint_check_flag); return occupied_locked(); @@ -371,7 +378,7 @@ void strong_code_roots_do(CodeBlobClosure* blk) const; // Returns the number of elements in the strong code roots list - size_t strong_code_roots_list_length() { + size_t strong_code_roots_list_length() const { return _code_roots.length(); } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp --- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -28,12 +28,12 @@ #include "gc_implementation/parNew/parOopClosures.inline.hpp" #include "gc_implementation/shared/adaptiveSizePolicy.hpp" #include "gc_implementation/shared/ageTable.hpp" -#include "gc_implementation/shared/parGCAllocBuffer.hpp" +#include "gc_implementation/shared/copyFailedInfo.hpp" #include "gc_implementation/shared/gcHeapSummary.hpp" #include "gc_implementation/shared/gcTimer.hpp" #include "gc_implementation/shared/gcTrace.hpp" #include "gc_implementation/shared/gcTraceTime.hpp" -#include "gc_implementation/shared/copyFailedInfo.hpp" +#include "gc_implementation/shared/parGCAllocBuffer.inline.hpp" #include "gc_implementation/shared/spaceDecorator.hpp" #include "memory/defNewGeneration.inline.hpp" #include "memory/genCollectedHeap.hpp" @@ -252,7 +252,7 @@ plab->set_word_size(buf_size); plab->set_buf(buf_space); record_survivor_plab(buf_space, buf_size); - obj = plab->allocate(word_sz); + obj = plab->allocate_aligned(word_sz, SurvivorAlignmentInBytes); // Note that we cannot compare buf_size < word_sz below // because of AlignmentReserve (see ParGCAllocBuffer::allocate()). assert(obj != NULL || plab->words_remaining() < word_sz, diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp --- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -168,7 +168,7 @@ HeapWord* alloc_in_to_space_slow(size_t word_sz); HeapWord* alloc_in_to_space(size_t word_sz) { - HeapWord* obj = to_space_alloc_buffer()->allocate(word_sz); + HeapWord* obj = to_space_alloc_buffer()->allocate_aligned(word_sz, SurvivorAlignmentInBytes); if (obj != NULL) return obj; else return alloc_in_to_space_slow(word_sz); } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.hpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -26,6 +26,7 @@ #define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSPROMOTIONLAB_HPP #include "gc_implementation/parallelScavenge/objectStartArray.hpp" +#include "gc_interface/collectedHeap.inline.hpp" #include "memory/allocation.hpp" // @@ -94,23 +95,9 @@ PSYoungPromotionLAB() { } // Not MT safe - HeapWord* allocate(size_t size) { - // Can't assert this, when young fills, we keep the LAB around, but flushed. - // assert(_state != flushed, "Sanity"); - HeapWord* obj = top(); - HeapWord* new_top = obj + size; - // The 'new_top>obj' check is needed to detect overflow of obj+size. - if (new_top > obj && new_top <= end()) { - set_top(new_top); - assert(is_object_aligned((intptr_t)obj) && is_object_aligned((intptr_t)new_top), - "checking alignment"); - return obj; - } + inline HeapWord* allocate(size_t size); - return NULL; - } - - debug_only(virtual bool lab_is_valid(MemRegion lab)); + debug_only(virtual bool lab_is_valid(MemRegion lab);) }; class PSOldPromotionLAB : public PSPromotionLAB { diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.inline.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.inline.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSPROMOTIONLAB_INLINE_HPP +#define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSPROMOTIONLAB_INLINE_HPP + +#include "gc_implementation/parallelScavenge/psPromotionLAB.hpp" +#include "gc_interface/collectedHeap.inline.hpp" + +HeapWord* PSYoungPromotionLAB::allocate(size_t size) { + // Can't assert this, when young fills, we keep the LAB around, but flushed. + // assert(_state != flushed, "Sanity"); + HeapWord* obj = CollectedHeap::align_allocation_or_fail(top(), end(), SurvivorAlignmentInBytes); + if (obj == NULL) { + return NULL; + } + + HeapWord* new_top = obj + size; + // The 'new_top>obj' check is needed to detect overflow of obj+size. + if (new_top > obj && new_top <= end()) { + set_top(new_top); + assert(is_ptr_aligned(obj, SurvivorAlignmentInBytes) && is_object_aligned((intptr_t)new_top), + "checking alignment"); + return obj; + } else { + set_top(obj); + return NULL; + } +} + +#endif // SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSPROMOTIONLAB_INLINE_HPP diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -27,6 +27,7 @@ #include "gc_implementation/parallelScavenge/psOldGen.hpp" #include "gc_implementation/parallelScavenge/psPromotionManager.hpp" +#include "gc_implementation/parallelScavenge/psPromotionLAB.inline.hpp" #include "gc_implementation/parallelScavenge/psScavenge.hpp" #include "oops/oop.psgc.inline.hpp" diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp --- a/hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -24,7 +24,7 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_PARNEW_PARGCALLOCBUFFER_HPP #define SHARE_VM_GC_IMPLEMENTATION_PARNEW_PARGCALLOCBUFFER_HPP - +#include "gc_interface/collectedHeap.hpp" #include "memory/allocation.hpp" #include "memory/blockOffsetTable.hpp" #include "memory/threadLocalAllocBuffer.hpp" @@ -84,6 +84,9 @@ } } + // Allocate the object aligned to "alignment_in_bytes". + HeapWord* allocate_aligned(size_t word_sz, unsigned short alignment_in_bytes); + // Undo the last allocation in the buffer, which is required to be of the // "obj" of the given "word_sz". void undo_allocation(HeapWord* obj, size_t word_sz) { diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.inline.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.inline.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_PARGCALLOCBUFFER_INLINE_HPP +#define SHARE_VM_GC_IMPLEMENTATION_SHARED_PARGCALLOCBUFFER_INLINE_HPP + +#include "gc_implementation/shared/parGCAllocBuffer.hpp" +#include "gc_interface/collectedHeap.inline.hpp" + +HeapWord* ParGCAllocBuffer::allocate_aligned(size_t word_sz, unsigned short alignment_in_bytes) { + + HeapWord* res = CollectedHeap::align_allocation_or_fail(_top, _end, alignment_in_bytes); + if (res == NULL) { + return NULL; + } + + // Set _top so that allocate(), which expects _top to be correctly set, + // can be used below. + _top = res; + return allocate(word_sz); +} + +#endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_PARGCALLOCBUFFER_INLINE_HPP diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp --- a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -195,6 +195,7 @@ gch->do_full_collection(gch->must_clear_all_soft_refs(), _max_level); } +// Returns true iff concurrent GCs unloads metadata. bool VM_CollectForMetadataAllocation::initiate_concurrent_GC() { #if INCLUDE_ALL_GCS if (UseConcMarkSweepGC && CMSClassUnloadingEnabled) { @@ -202,7 +203,7 @@ return true; } - if (UseG1GC) { + if (UseG1GC && ClassUnloadingWithConcurrentMark) { G1CollectedHeap* g1h = G1CollectedHeap::heap(); g1h->g1_policy()->set_initiate_conc_mark_if_possible(); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/gc_interface/collectedHeap.hpp --- a/hotspot/src/share/vm/gc_interface/collectedHeap.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/gc_interface/collectedHeap.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -351,6 +351,12 @@ fill_with_object(start, pointer_delta(end, start), zap); } + // Return the address "addr" aligned by "alignment_in_bytes" if such + // an address is below "end". Return NULL otherwise. + inline static HeapWord* align_allocation_or_fail(HeapWord* addr, + HeapWord* end, + unsigned short alignment_in_bytes); + // Some heaps may offer a contiguous region for shared non-blocking // allocation, via inlined code (by exporting the address of the top and // end fields defining the extent of the contiguous allocation region.) diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/gc_interface/collectedHeap.inline.hpp --- a/hotspot/src/share/vm/gc_interface/collectedHeap.inline.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/gc_interface/collectedHeap.inline.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -241,6 +241,44 @@ oop_iterate(&no_header_cl); } + +inline HeapWord* CollectedHeap::align_allocation_or_fail(HeapWord* addr, + HeapWord* end, + unsigned short alignment_in_bytes) { + if (alignment_in_bytes <= ObjectAlignmentInBytes) { + return addr; + } + + assert(is_ptr_aligned(addr, HeapWordSize), + err_msg("Address " PTR_FORMAT " is not properly aligned.", p2i(addr))); + assert(is_size_aligned(alignment_in_bytes, HeapWordSize), + err_msg("Alignment size %u is incorrect.", alignment_in_bytes)); + + HeapWord* new_addr = (HeapWord*) align_pointer_up(addr, alignment_in_bytes); + size_t padding = pointer_delta(new_addr, addr); + + if (padding == 0) { + return addr; + } + + if (padding < CollectedHeap::min_fill_size()) { + padding += alignment_in_bytes / HeapWordSize; + assert(padding >= CollectedHeap::min_fill_size(), + err_msg("alignment_in_bytes %u is expect to be larger " + "than the minimum object size", alignment_in_bytes)); + new_addr = addr + padding; + } + + assert(new_addr > addr, err_msg("Unexpected arithmetic overflow " + PTR_FORMAT " not greater than " PTR_FORMAT, p2i(new_addr), p2i(addr))); + if(new_addr < end) { + CollectedHeap::fill_with_object(addr, padding); + return new_addr; + } else { + return NULL; + } +} + #ifndef PRODUCT inline bool diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/interpreter/abstractInterpreter.hpp --- a/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -280,9 +280,6 @@ address generate_result_handler_for(BasicType type); address generate_slow_signature_handler(); - // entry point generator - address generate_method_entry(AbstractInterpreter::MethodKind kind); - void bang_stack_shadow_pages(bool native_call); void generate_all(); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/interpreter/cppInterpreter.cpp --- a/hotspot/src/share/vm/interpreter/cppInterpreter.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/interpreter/cppInterpreter.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -108,7 +108,7 @@ } -#define method_entry(kind) Interpreter::_entry_table[Interpreter::kind] = generate_method_entry(Interpreter::kind) +#define method_entry(kind) Interpreter::_entry_table[Interpreter::kind] = ((InterpreterGenerator*)this)->generate_method_entry(Interpreter::kind) { CodeletMark cm(_masm, "(kind = frame_manager)"); // all non-native method kinds diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/interpreter/interpreter.cpp --- a/hotspot/src/share/vm/interpreter/interpreter.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/interpreter/interpreter.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -29,6 +29,7 @@ #include "interpreter/bytecodeHistogram.hpp" #include "interpreter/bytecodeInterpreter.hpp" #include "interpreter/interpreter.hpp" +#include "interpreter/interpreterGenerator.hpp" #include "interpreter/interpreterRuntime.hpp" #include "interpreter/interp_masm.hpp" #include "interpreter/templateTable.hpp" @@ -261,7 +262,7 @@ // Special intrinsic method? // Note: This test must come _after_ the test for native methods, // otherwise we will run into problems with JDK 1.2, see also - // AbstractInterpreterGenerator::generate_method_entry() for + // InterpreterGenerator::generate_method_entry() for // for details. switch (m->intrinsic_id()) { case vmIntrinsics::_dsin : return java_lang_math_sin ; @@ -521,3 +522,50 @@ Interpreter::_entry_table[kind] = Interpreter::_entry_table[Interpreter::abstract]; } } + +// Generate method entries +address InterpreterGenerator::generate_method_entry( + AbstractInterpreter::MethodKind kind) { + // determine code generation flags + bool synchronized = false; + address entry_point = NULL; + + switch (kind) { + case Interpreter::zerolocals : break; + case Interpreter::zerolocals_synchronized: synchronized = true; break; + case Interpreter::native : entry_point = generate_native_entry(false); break; + case Interpreter::native_synchronized : entry_point = generate_native_entry(true); break; + case Interpreter::empty : entry_point = generate_empty_entry(); break; + case Interpreter::accessor : entry_point = generate_accessor_entry(); break; + case Interpreter::abstract : entry_point = generate_abstract_entry(); break; + + case Interpreter::java_lang_math_sin : // fall thru + case Interpreter::java_lang_math_cos : // fall thru + case Interpreter::java_lang_math_tan : // fall thru + case Interpreter::java_lang_math_abs : // fall thru + case Interpreter::java_lang_math_log : // fall thru + case Interpreter::java_lang_math_log10 : // fall thru + case Interpreter::java_lang_math_sqrt : // fall thru + case Interpreter::java_lang_math_pow : // fall thru + case Interpreter::java_lang_math_exp : entry_point = generate_math_entry(kind); break; + case Interpreter::java_lang_ref_reference_get + : entry_point = generate_Reference_get_entry(); break; +#ifndef CC_INTERP + case Interpreter::java_util_zip_CRC32_update + : entry_point = generate_CRC32_update_entry(); break; + case Interpreter::java_util_zip_CRC32_updateBytes + : // fall thru + case Interpreter::java_util_zip_CRC32_updateByteBuffer + : entry_point = generate_CRC32_updateBytes_entry(kind); break; +#endif // CC_INTERP + default: + fatal(err_msg("unexpected method kind: %d", kind)); + break; + } + + if (entry_point) { + return entry_point; + } + + return generate_normal_entry(synchronized); +} diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/interpreter/interpreterGenerator.hpp --- a/hotspot/src/share/vm/interpreter/interpreterGenerator.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/interpreter/interpreterGenerator.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -37,9 +37,11 @@ class InterpreterGenerator: public CC_INTERP_ONLY(CppInterpreterGenerator) NOT_CC_INTERP(TemplateInterpreterGenerator) { -public: + public: -InterpreterGenerator(StubQueue* _code); + InterpreterGenerator(StubQueue* _code); + // entry point generator + address generate_method_entry(AbstractInterpreter::MethodKind kind); #ifdef TARGET_ARCH_x86 # include "interpreterGenerator_x86.hpp" diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/interpreter/interpreterRuntime.cpp --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -987,17 +987,6 @@ int index = cp_entry->field_index(); if ((ik->field_access_flags(index) & JVM_ACC_FIELD_ACCESS_WATCHED) == 0) return; - switch(cp_entry->flag_state()) { - case btos: // fall through - case ctos: // fall through - case stos: // fall through - case itos: // fall through - case ftos: // fall through - case ltos: // fall through - case dtos: // fall through - case atos: break; - default: ShouldNotReachHere(); return; - } bool is_static = (obj == NULL); HandleMark hm(thread); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/interpreter/templateInterpreter.cpp --- a/hotspot/src/share/vm/interpreter/templateInterpreter.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/interpreter/templateInterpreter.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -364,7 +364,7 @@ #define method_entry(kind) \ { CodeletMark cm(_masm, "method entry point (kind = " #kind ")"); \ - Interpreter::_entry_table[Interpreter::kind] = generate_method_entry(Interpreter::kind); \ + Interpreter::_entry_table[Interpreter::kind] = ((InterpreterGenerator*)this)->generate_method_entry(Interpreter::kind); \ } // all non-native method kinds diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/interpreter/templateInterpreterGenerator.hpp --- a/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -59,9 +59,6 @@ address generate_safept_entry_for(TosState state, address runtime_entry); void generate_throw_exception(); - // entry point generator -// address generate_method_entry(AbstractInterpreter::MethodKind kind); - // Instruction generation void generate_and_dispatch (Template* t, TosState tos_out = ilgl); void set_vtos_entry_points (Template* t, address& bep, address& cep, address& sep, address& aep, address& iep, address& lep, address& fep, address& dep, address& vep); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/memory/allocation.cpp --- a/hotspot/src/share/vm/memory/allocation.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/memory/allocation.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -422,26 +422,23 @@ } //------------------------------Arena------------------------------------------ -NOT_PRODUCT(volatile jint Arena::_instance_count = 0;) -Arena::Arena(size_t init_size) { +Arena::Arena(MEMFLAGS flag, size_t init_size) : _flags(flag), _size_in_bytes(0) { size_t round_size = (sizeof (char *)) - 1; init_size = (init_size+round_size) & ~round_size; _first = _chunk = new (AllocFailStrategy::EXIT_OOM, init_size) Chunk(init_size); _hwm = _chunk->bottom(); // Save the cached hwm, max _max = _chunk->top(); - _size_in_bytes = 0; + MemTracker::record_new_arena(flag); set_size_in_bytes(init_size); - NOT_PRODUCT(Atomic::inc(&_instance_count);) } -Arena::Arena() { +Arena::Arena(MEMFLAGS flag) : _flags(flag), _size_in_bytes(0) { _first = _chunk = new (AllocFailStrategy::EXIT_OOM, Chunk::init_size) Chunk(Chunk::init_size); _hwm = _chunk->bottom(); // Save the cached hwm, max _max = _chunk->top(); - _size_in_bytes = 0; + MemTracker::record_new_arena(flag); set_size_in_bytes(Chunk::init_size); - NOT_PRODUCT(Atomic::inc(&_instance_count);) } Arena *Arena::move_contents(Arena *copy) { @@ -463,7 +460,7 @@ Arena::~Arena() { destruct_contents(); - NOT_PRODUCT(Atomic::dec(&_instance_count);) + MemTracker::record_arena_free(_flags); } void* Arena::operator new(size_t size) throw() { @@ -479,21 +476,21 @@ // dynamic memory type binding void* Arena::operator new(size_t size, MEMFLAGS flags) throw() { #ifdef ASSERT - void* p = (void*)AllocateHeap(size, flags|otArena, CALLER_PC); + void* p = (void*)AllocateHeap(size, flags, CALLER_PC); if (PrintMallocFree) trace_heap_malloc(size, "Arena-new", p); return p; #else - return (void *) AllocateHeap(size, flags|otArena, CALLER_PC); + return (void *) AllocateHeap(size, flags, CALLER_PC); #endif } void* Arena::operator new(size_t size, const std::nothrow_t& nothrow_constant, MEMFLAGS flags) throw() { #ifdef ASSERT - void* p = os::malloc(size, flags|otArena, CALLER_PC); + void* p = os::malloc(size, flags, CALLER_PC); if (PrintMallocFree) trace_heap_malloc(size, "Arena-new", p); return p; #else - return os::malloc(size, flags|otArena, CALLER_PC); + return os::malloc(size, flags, CALLER_PC); #endif } @@ -518,8 +515,9 @@ // change the size void Arena::set_size_in_bytes(size_t size) { if (_size_in_bytes != size) { + long delta = (long)(size - size_in_bytes()); _size_in_bytes = size; - MemTracker::record_arena_size((address)this, size); + MemTracker::record_arena_size_change(delta, _flags); } } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/memory/allocation.hpp --- a/hotspot/src/share/vm/memory/allocation.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/memory/allocation.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -133,51 +133,34 @@ /* - * MemoryType bitmap layout: - * | 16 15 14 13 12 11 10 09 | 08 07 06 05 | 04 03 02 01 | - * | memory type | object | reserved | - * | | type | | + * Memory types */ enum MemoryType { // Memory type by sub systems. It occupies lower byte. - mtNone = 0x0000, // undefined - mtClass = 0x0100, // memory class for Java classes - mtThread = 0x0200, // memory for thread objects - mtThreadStack = 0x0300, - mtCode = 0x0400, // memory for generated code - mtGC = 0x0500, // memory for GC - mtCompiler = 0x0600, // memory for compiler - mtInternal = 0x0700, // memory used by VM, but does not belong to + mtJavaHeap = 0x00, // Java heap + mtClass = 0x01, // memory class for Java classes + mtThread = 0x02, // memory for thread objects + mtThreadStack = 0x03, + mtCode = 0x04, // memory for generated code + mtGC = 0x05, // memory for GC + mtCompiler = 0x06, // memory for compiler + mtInternal = 0x07, // memory used by VM, but does not belong to // any of above categories, and not used for // native memory tracking - mtOther = 0x0800, // memory not used by VM - mtSymbol = 0x0900, // symbol - mtNMT = 0x0A00, // memory used by native memory tracking - mtChunk = 0x0B00, // chunk that holds content of arenas - mtJavaHeap = 0x0C00, // Java heap - mtClassShared = 0x0D00, // class data sharing - mtTest = 0x0E00, // Test type for verifying NMT - mtTracing = 0x0F00, // memory used for Tracing - mt_number_of_types = 0x000F, // number of memory types (mtDontTrack + mtOther = 0x08, // memory not used by VM + mtSymbol = 0x09, // symbol + mtNMT = 0x0A, // memory used by native memory tracking + mtClassShared = 0x0B, // class data sharing + mtChunk = 0x0C, // chunk that holds content of arenas + mtTest = 0x0D, // Test type for verifying NMT + mtTracing = 0x0E, // memory used for Tracing + mtNone = 0x0F, // undefined + mt_number_of_types = 0x10 // number of memory types (mtDontTrack // is not included as validate type) - mtDontTrack = 0x0F00, // memory we do not or cannot track - mt_masks = 0x7F00, - - // object type mask - otArena = 0x0010, // an arena object - otNMTRecorder = 0x0020, // memory recorder object - ot_masks = 0x00F0 }; -#define IS_MEMORY_TYPE(flags, type) ((flags & mt_masks) == type) -#define HAS_VALID_MEMORY_TYPE(flags)((flags & mt_masks) != mtNone) -#define FLAGS_TO_MEMORY_TYPE(flags) (flags & mt_masks) +typedef MemoryType MEMFLAGS; -#define IS_ARENA_OBJ(flags) ((flags & ot_masks) == otArena) -#define IS_NMT_RECORDER(flags) ((flags & ot_masks) == otNMTRecorder) -#define NMT_CAN_TRACK(flags) (!IS_NMT_RECORDER(flags) && !(IS_MEMORY_TYPE(flags, mtDontTrack))) - -typedef unsigned short MEMFLAGS; #if INCLUDE_NMT @@ -189,27 +172,23 @@ #endif // INCLUDE_NMT -// debug build does not inline -#if defined(_NMT_NOINLINE_) - #define CURRENT_PC (NMT_track_callsite ? os::get_caller_pc(1) : 0) - #define CALLER_PC (NMT_track_callsite ? os::get_caller_pc(2) : 0) - #define CALLER_CALLER_PC (NMT_track_callsite ? os::get_caller_pc(3) : 0) -#else - #define CURRENT_PC (NMT_track_callsite? os::get_caller_pc(0) : 0) - #define CALLER_PC (NMT_track_callsite ? os::get_caller_pc(1) : 0) - #define CALLER_CALLER_PC (NMT_track_callsite ? os::get_caller_pc(2) : 0) -#endif - +class NativeCallStack; template class CHeapObj ALLOCATION_SUPER_CLASS_SPEC { public: - _NOINLINE_ void* operator new(size_t size, address caller_pc = 0) throw(); + _NOINLINE_ void* operator new(size_t size, const NativeCallStack& stack) throw(); + _NOINLINE_ void* operator new(size_t size) throw(); _NOINLINE_ void* operator new (size_t size, const std::nothrow_t& nothrow_constant, - address caller_pc = 0) throw(); - _NOINLINE_ void* operator new [](size_t size, address caller_pc = 0) throw(); + const NativeCallStack& stack) throw(); + _NOINLINE_ void* operator new (size_t size, const std::nothrow_t& nothrow_constant) + throw(); + _NOINLINE_ void* operator new [](size_t size, const NativeCallStack& stack) throw(); + _NOINLINE_ void* operator new [](size_t size) throw(); _NOINLINE_ void* operator new [](size_t size, const std::nothrow_t& nothrow_constant, - address caller_pc = 0) throw(); + const NativeCallStack& stack) throw(); + _NOINLINE_ void* operator new [](size_t size, const std::nothrow_t& nothrow_constant) + throw(); void operator delete(void* p); void operator delete [] (void* p); }; @@ -384,13 +363,15 @@ //------------------------------Arena------------------------------------------ // Fast allocation of memory -class Arena : public CHeapObj { +class Arena : public CHeapObj { protected: friend class ResourceMark; friend class HandleMark; friend class NoHandleMark; friend class VMStructs; + MEMFLAGS _flags; // Memory tracking flags + Chunk *_first; // First chunk Chunk *_chunk; // current chunk char *_hwm, *_max; // High water mark and max in current chunk @@ -418,8 +399,8 @@ } public: - Arena(); - Arena(size_t init_size); + Arena(MEMFLAGS memflag); + Arena(MEMFLAGS memflag, size_t init_size); ~Arena(); void destruct_contents(); char* hwm() const { return _hwm; } @@ -518,8 +499,6 @@ static void free_malloced_objects(Chunk* chunk, char* hwm, char* max, char* hwm2) PRODUCT_RETURN; static void free_all(char** start, char** end) PRODUCT_RETURN; - // how many arena instances - NOT_PRODUCT(static volatile jint _instance_count;) private: // Reset this Arena to empty, access will trigger grow if necessary void reset(void) { @@ -681,7 +660,7 @@ NEW_C_HEAP_ARRAY3(type, (size), memflags, pc, AllocFailStrategy::RETURN_NULL) #define NEW_C_HEAP_ARRAY_RETURN_NULL(type, size, memflags)\ - NEW_C_HEAP_ARRAY3(type, (size), memflags, (address)0, AllocFailStrategy::RETURN_NULL) + NEW_C_HEAP_ARRAY3(type, (size), memflags, CURRENT_PC, AllocFailStrategy::RETURN_NULL) #define REALLOC_C_HEAP_ARRAY(type, old, size, memflags)\ (type*) (ReallocateHeap((char*)(old), (size) * sizeof(type), memflags)) diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/memory/allocation.inline.hpp --- a/hotspot/src/share/vm/memory/allocation.inline.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/memory/allocation.inline.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -27,6 +27,7 @@ #include "runtime/atomic.inline.hpp" #include "runtime/os.hpp" +#include "services/memTracker.hpp" // Explicit C-heap memory management @@ -49,12 +50,10 @@ #endif // allocate using malloc; will fail if no memory available -inline char* AllocateHeap(size_t size, MEMFLAGS flags, address pc = 0, +inline char* AllocateHeap(size_t size, MEMFLAGS flags, + const NativeCallStack& stack, AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM) { - if (pc == 0) { - pc = CURRENT_PC; - } - char* p = (char*) os::malloc(size, flags, pc); + char* p = (char*) os::malloc(size, flags, stack); #ifdef ASSERT if (PrintMallocFree) trace_heap_malloc(size, "AllocateHeap", p); #endif @@ -63,10 +62,14 @@ } return p; } +inline char* AllocateHeap(size_t size, MEMFLAGS flags, + AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM) { + return AllocateHeap(size, flags, CURRENT_PC, alloc_failmode); +} -inline char* ReallocateHeap(char *old, size_t size, MEMFLAGS flags, +inline char* ReallocateHeap(char *old, size_t size, MEMFLAGS flag, AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM) { - char* p = (char*) os::realloc(old, size, flags, CURRENT_PC); + char* p = (char*) os::realloc(old, size, flag, CURRENT_PC); #ifdef ASSERT if (PrintMallocFree) trace_heap_malloc(size, "ReallocateHeap", p); #endif @@ -85,8 +88,22 @@ template void* CHeapObj::operator new(size_t size, - address caller_pc) throw() { - void* p = (void*)AllocateHeap(size, F, (caller_pc != 0 ? caller_pc : CALLER_PC)); + const NativeCallStack& stack) throw() { + void* p = (void*)AllocateHeap(size, F, stack); +#ifdef ASSERT + if (PrintMallocFree) trace_heap_malloc(size, "CHeapObj-new", p); +#endif + return p; +} + +template void* CHeapObj::operator new(size_t size) throw() { + return CHeapObj::operator new(size, CALLER_PC); +} + +template void* CHeapObj::operator new (size_t size, + const std::nothrow_t& nothrow_constant, const NativeCallStack& stack) throw() { + void* p = (void*)AllocateHeap(size, F, stack, + AllocFailStrategy::RETURN_NULL); #ifdef ASSERT if (PrintMallocFree) trace_heap_malloc(size, "CHeapObj-new", p); #endif @@ -94,23 +111,28 @@ } template void* CHeapObj::operator new (size_t size, - const std::nothrow_t& nothrow_constant, address caller_pc) throw() { - void* p = (void*)AllocateHeap(size, F, (caller_pc != 0 ? caller_pc : CALLER_PC), - AllocFailStrategy::RETURN_NULL); -#ifdef ASSERT - if (PrintMallocFree) trace_heap_malloc(size, "CHeapObj-new", p); -#endif - return p; + const std::nothrow_t& nothrow_constant) throw() { + return CHeapObj::operator new(size, nothrow_constant, CALLER_PC); } template void* CHeapObj::operator new [](size_t size, - address caller_pc) throw() { - return CHeapObj::operator new(size, caller_pc); + const NativeCallStack& stack) throw() { + return CHeapObj::operator new(size, stack); +} + +template void* CHeapObj::operator new [](size_t size) + throw() { + return CHeapObj::operator new(size, CALLER_PC); } template void* CHeapObj::operator new [](size_t size, - const std::nothrow_t& nothrow_constant, address caller_pc) throw() { - return CHeapObj::operator new(size, nothrow_constant, caller_pc); + const std::nothrow_t& nothrow_constant, const NativeCallStack& stack) throw() { + return CHeapObj::operator new(size, nothrow_constant, stack); +} + +template void* CHeapObj::operator new [](size_t size, + const std::nothrow_t& nothrow_constant) throw() { + return CHeapObj::operator new(size, nothrow_constant, CALLER_PC); } template void CHeapObj::operator delete(void* p){ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/memory/cardTableRS.cpp --- a/hotspot/src/share/vm/memory/cardTableRS.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/memory/cardTableRS.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -56,7 +56,7 @@ #endif set_bs(_ct_bs); _last_cur_val_in_gen = NEW_C_HEAP_ARRAY3(jbyte, GenCollectedHeap::max_gens + 1, - mtGC, 0, AllocFailStrategy::RETURN_NULL); + mtGC, CURRENT_PC, AllocFailStrategy::RETURN_NULL); if (_last_cur_val_in_gen == NULL) { vm_exit_during_initialization("Could not create last_cur_val_in_gen array."); } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/memory/collectorPolicy.cpp --- a/hotspot/src/share/vm/memory/collectorPolicy.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/memory/collectorPolicy.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -176,13 +176,9 @@ size_t alignment = GenRemSet::max_alignment_constraint(); - // Parallel GC does its own alignment of the generations to avoid requiring a - // large page (256M on some platforms) for the permanent generation. The - // other collectors should also be updated to do their own alignment and then - // this use of lcm() should be removed. - if (UseLargePages && !UseParallelGC) { + if (UseLargePages) { // In presence of large pages we have to make sure that our - // alignment is large page aware + // alignment is large page aware. alignment = lcm(os::large_page_size(), alignment); } @@ -909,7 +905,8 @@ } void MarkSweepPolicy::initialize_generations() { - _generations = NEW_C_HEAP_ARRAY3(GenerationSpecPtr, number_of_generations(), mtGC, 0, AllocFailStrategy::RETURN_NULL); + _generations = NEW_C_HEAP_ARRAY3(GenerationSpecPtr, number_of_generations(), mtGC, CURRENT_PC, + AllocFailStrategy::RETURN_NULL); if (_generations == NULL) { vm_exit_during_initialization("Unable to allocate gen spec"); } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/memory/defNewGeneration.cpp --- a/hotspot/src/share/vm/memory/defNewGeneration.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/memory/defNewGeneration.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -790,7 +790,7 @@ // Try allocating obj in to-space (unless too old) if (old->age() < tenuring_threshold()) { - obj = (oop) to()->allocate(s); + obj = (oop) to()->allocate_aligned(s); } // Otherwise try allocating obj tenured diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/memory/heapInspection.cpp --- a/hotspot/src/share/vm/memory/heapInspection.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/memory/heapInspection.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -135,7 +135,7 @@ _ref = (HeapWord*) Universe::boolArrayKlassObj(); _buckets = (KlassInfoBucket*) AllocateHeap(sizeof(KlassInfoBucket) * _num_buckets, - mtInternal, 0, AllocFailStrategy::RETURN_NULL); + mtInternal, CURRENT_PC, AllocFailStrategy::RETURN_NULL); if (_buckets != NULL) { _size = _num_buckets; for (int index = 0; index < _size; index++) { diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/memory/memRegion.cpp --- a/hotspot/src/share/vm/memory/memRegion.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/memory/memRegion.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -103,11 +103,13 @@ } void* MemRegion::operator new(size_t size) throw() { - return (address)AllocateHeap(size, mtGC, 0, AllocFailStrategy::RETURN_NULL); + return (address)AllocateHeap(size, mtGC, CURRENT_PC, + AllocFailStrategy::RETURN_NULL); } void* MemRegion::operator new [](size_t size) throw() { - return (address)AllocateHeap(size, mtGC, 0, AllocFailStrategy::RETURN_NULL); + return (address)AllocateHeap(size, mtGC, CURRENT_PC, + AllocFailStrategy::RETURN_NULL); } void MemRegion::operator delete(void* p) { FreeHeap(p, mtGC); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/memory/resourceArea.hpp --- a/hotspot/src/share/vm/memory/resourceArea.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/memory/resourceArea.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -49,11 +49,11 @@ debug_only(static int _warned;) // to suppress multiple warnings public: - ResourceArea() { + ResourceArea() : Arena(mtThread) { debug_only(_nesting = 0;) } - ResourceArea(size_t init_size) : Arena(init_size) { + ResourceArea(size_t init_size) : Arena(mtThread, init_size) { debug_only(_nesting = 0;); } @@ -64,7 +64,7 @@ if (UseMallocOnly) { // use malloc, but save pointer in res. area for later freeing char** save = (char**)internal_malloc_4(sizeof(char*)); - return (*save = (char*)os::malloc(size, mtThread)); + return (*save = (char*)os::malloc(size, mtThread, CURRENT_PC)); } #endif return (char*)Amalloc(size, alloc_failmode); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/memory/sharedHeap.cpp --- a/hotspot/src/share/vm/memory/sharedHeap.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/memory/sharedHeap.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -159,9 +159,9 @@ Monitor* SharedHeap::StrongRootsScope::_lock = new Monitor(Mutex::leaf, "StrongRootsScope lock", false); void SharedHeap::StrongRootsScope::mark_worker_done_with_threads(uint n_workers) { - // The Thread work barrier is only needed by G1. + // The Thread work barrier is only needed by G1 Class Unloading. // No need to use the barrier if this is single-threaded code. - if (UseG1GC && n_workers > 0) { + if (UseG1GC && ClassUnloadingWithConcurrentMark && n_workers > 0) { uint new_value = (uint)Atomic::add(1, &_n_workers_done_with_threads); if (new_value == n_workers) { // This thread is last. Notify the others. @@ -172,6 +172,9 @@ } void SharedHeap::StrongRootsScope::wait_until_all_workers_done_with_threads(uint n_workers) { + assert(UseG1GC, "Currently only used by G1"); + assert(ClassUnloadingWithConcurrentMark, "Currently only needed when doing G1 Class Unloading"); + // No need to use the barrier if this is single-threaded code. if (n_workers > 0 && (uint)_n_workers_done_with_threads != n_workers) { MonitorLockerEx ml(_lock, Mutex::_no_safepoint_check_flag); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/memory/space.cpp --- a/hotspot/src/share/vm/memory/space.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/memory/space.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -28,6 +28,7 @@ #include "gc_implementation/shared/liveRange.hpp" #include "gc_implementation/shared/markSweep.hpp" #include "gc_implementation/shared/spaceDecorator.hpp" +#include "gc_interface/collectedHeap.inline.hpp" #include "memory/blockOffsetTable.inline.hpp" #include "memory/defNewGeneration.hpp" #include "memory/genCollectedHeap.hpp" @@ -720,6 +721,27 @@ } while (true); } +HeapWord* ContiguousSpace::allocate_aligned(size_t size) { + assert(Heap_lock->owned_by_self() || (SafepointSynchronize::is_at_safepoint() && Thread::current()->is_VM_thread()), "not locked"); + HeapWord* end_value = end(); + + HeapWord* obj = CollectedHeap::align_allocation_or_fail(top(), end_value, SurvivorAlignmentInBytes); + if (obj == NULL) { + return NULL; + } + + if (pointer_delta(end_value, obj) >= size) { + HeapWord* new_top = obj + size; + set_top(new_top); + assert(is_ptr_aligned(obj, SurvivorAlignmentInBytes) && is_aligned(new_top), + "checking alignment"); + return obj; + } else { + set_top(obj); + return NULL; + } +} + // Requires locking. HeapWord* ContiguousSpace::allocate(size_t size) { return allocate_impl(size, end()); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/memory/space.hpp --- a/hotspot/src/share/vm/memory/space.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/memory/space.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -526,6 +526,7 @@ // Allocation (return NULL if full) virtual HeapWord* allocate(size_t word_size); virtual HeapWord* par_allocate(size_t word_size); + HeapWord* allocate_aligned(size_t word_size); // Iteration void oop_iterate(ExtendedOopClosure* cl); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/oops/method.cpp --- a/hotspot/src/share/vm/oops/method.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/oops/method.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -283,6 +283,13 @@ return bcp; } +address Method::bcp_from(address bcp) const { + if (is_native() && bcp == NULL) { + return code_base(); + } else { + return bcp; + } +} int Method::size(bool is_native) { // If native, then include pointers for native_function and signature_handler diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/oops/method.hpp --- a/hotspot/src/share/vm/oops/method.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/oops/method.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -648,7 +648,8 @@ // Returns the byte code index from the byte code pointer int bci_from(address bcp) const; - address bcp_from(int bci) const; + address bcp_from(int bci) const; + address bcp_from(address bcp) const; int validate_bci_from_bcp(address bcp) const; int validate_bci(int bci) const; diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/oops/oop.pcgc.inline.hpp --- a/hotspot/src/share/vm/oops/oop.pcgc.inline.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/oops/oop.pcgc.inline.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -55,8 +55,6 @@ klass()->oop_follow_contents(cm, this); } -// Used by parallel old GC. - inline oop oopDesc::forward_to_atomic(oop p) { assert(ParNewGeneration::is_legal_forward_ptr(p), "illegal forwarding pointer value."); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/callGenerator.cpp --- a/hotspot/src/share/vm/opto/callGenerator.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/callGenerator.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -357,7 +357,7 @@ // Make sure the state is a MergeMem for parsing. if (!map->in(TypeFunc::Memory)->is_MergeMem()) { - Node* mem = MergeMemNode::make(C, map->in(TypeFunc::Memory)); + Node* mem = MergeMemNode::make(map->in(TypeFunc::Memory)); C->initial_gvn()->set_type_bottom(mem); map->set_req(TypeFunc::Memory, mem); } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/callnode.cpp --- a/hotspot/src/share/vm/opto/callnode.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/callnode.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -688,7 +688,7 @@ return new MachProjNode(this,proj->_con,RegMask::Empty,MachProjNode::unmatched_proj); case TypeFunc::Parms+1: // For LONG & DOUBLE returns - assert(tf()->_range->field_at(TypeFunc::Parms+1) == Type::HALF, ""); + assert(tf()->range()->field_at(TypeFunc::Parms+1) == Type::HALF, ""); // 2nd half of doubles and longs return new MachProjNode(this,proj->_con, RegMask::Empty, (uint)OptoReg::Bad); @@ -778,7 +778,7 @@ } // Returns the unique CheckCastPP of a call -// or 'this' if there are several CheckCastPP +// or 'this' if there are several CheckCastPP or unexpected uses // or returns NULL if there is no one. Node *CallNode::result_cast() { Node *cast = NULL; @@ -794,6 +794,13 @@ return this; // more than 1 CheckCastPP } cast = use; + } else if (!use->is_Initialize() && + !use->is_AddP()) { + // Expected uses are restricted to a CheckCastPP, an Initialize + // node, and AddP nodes. If we encounter any other use (a Phi + // node can be seen in rare cases) return this to prevent + // incorrect optimizations. + return this; } } return cast; diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/cfgnode.cpp --- a/hotspot/src/share/vm/opto/cfgnode.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/cfgnode.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -108,6 +108,7 @@ rreq++; // One more input to Region } // Found a region to merge into Region + igvn->_worklist.push(r); // Clobber pointer to the now dead 'r' region->set_req(i, phase->C->top()); } @@ -449,6 +450,7 @@ // Remove TOP or NULL input paths. If only 1 input path remains, this Region // degrades to a copy. bool add_to_worklist = false; + bool modified = false; int cnt = 0; // Count of values merging DEBUG_ONLY( int cnt_orig = req(); ) // Save original inputs count int del_it = 0; // The last input path we delete @@ -459,6 +461,7 @@ // Remove useless control copy inputs if( n->is_Region() && n->as_Region()->is_copy() ) { set_req(i, n->nonnull_req()); + modified = true; i--; continue; } @@ -466,12 +469,14 @@ Node *call = n->in(0); if (call->is_Call() && call->as_Call()->entry_point() == OptoRuntime::rethrow_stub()) { set_req(i, call->in(0)); + modified = true; i--; continue; } } if( phase->type(n) == Type::TOP ) { set_req(i, NULL); // Ignore TOP inputs + modified = true; i--; continue; } @@ -691,7 +696,7 @@ } } - return NULL; + return modified ? this : NULL; } @@ -1871,7 +1876,7 @@ igvn->register_new_node_with_optimizer(new_base); hook->add_req(new_base); } - MergeMemNode* result = MergeMemNode::make(phase->C, new_base); + MergeMemNode* result = MergeMemNode::make(new_base); for (uint i = 1; i < req(); ++i) { Node *ii = in(i); if (ii->is_MergeMem()) { diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/chaitin.cpp --- a/hotspot/src/share/vm/opto/chaitin.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/chaitin.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -1620,7 +1620,7 @@ C->check_node_count(0, "out of nodes fixing spills"); if (C->failing()) return; // Transform node - MachNode *cisc = mach->cisc_version(stk_offset, C)->as_Mach(); + MachNode *cisc = mach->cisc_version(stk_offset)->as_Mach(); cisc->set_req(inp,fp); // Base register is frame pointer if( cisc->oper_input_base() > 1 && mach->oper_input_base() <= 1 ) { assert( cisc->oper_input_base() == 2, "Only adding one edge"); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/compile.cpp --- a/hotspot/src/share/vm/opto/compile.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/compile.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -647,6 +647,10 @@ _printer(IdealGraphPrinter::printer()), #endif _congraph(NULL), + _comp_arena(mtCompiler), + _node_arena(mtCompiler), + _old_arena(mtCompiler), + _Compile_types(mtCompiler), _replay_inline_data(NULL), _late_inlines(comp_arena(), 2, 0, NULL), _string_late_inlines(comp_arena(), 2, 0, NULL), @@ -954,6 +958,10 @@ _in_dump_cnt(0), _printer(NULL), #endif + _comp_arena(mtCompiler), + _node_arena(mtCompiler), + _old_arena(mtCompiler), + _Compile_types(mtCompiler), _dead_node_list(comp_arena()), _dead_node_count(0), _congraph(NULL), @@ -1039,6 +1047,7 @@ _node_note_array = NULL; _default_node_notes = NULL; + DEBUG_ONLY( _modified_nodes = NULL; ) // Used in Optimize() _immutable_memory = NULL; // filled in at first inquiry @@ -1247,6 +1256,18 @@ } } } +void Compile::record_modified_node(Node* n) { + if (_modified_nodes != NULL && !_inlining_incrementally && + n->outcnt() != 0 && !n->is_Con()) { + _modified_nodes->push(n); + } +} + +void Compile::remove_modified_node(Node* n) { + if (_modified_nodes != NULL) { + _modified_nodes->remove(n); + } +} #endif #ifndef PRODUCT @@ -2035,6 +2056,9 @@ // Iterative Global Value Numbering, including ideal transforms // Initialize IterGVN with types and values from parse-time GVN PhaseIterGVN igvn(initial_gvn()); +#ifdef ASSERT + _modified_nodes = new (comp_arena()) Unique_Node_List(comp_arena()); +#endif { NOT_PRODUCT( TracePhase t2("iterGVN", &_t_iterGVN, TimeCompiler); ) igvn.optimize(); @@ -2197,6 +2221,7 @@ } } + DEBUG_ONLY( _modified_nodes = NULL; ) } // (End scope of igvn; run destructor if necessary for asserts.) process_print_inlining(); @@ -2825,7 +2850,7 @@ // oops implicit null check is not generated. // This will allow to generate normal oop implicit null check. if (Matcher::gen_narrow_oop_implicit_null_checks()) - new_in2 = ConNode::make(this, TypeNarrowOop::NULL_PTR); + new_in2 = ConNode::make(TypeNarrowOop::NULL_PTR); // // This transformation together with CastPP transformation above // will generated code for implicit NULL checks for compressed oops. @@ -2864,9 +2889,9 @@ // NullCheck base_reg // } else if (t->isa_oopptr()) { - new_in2 = ConNode::make(this, t->make_narrowoop()); + new_in2 = ConNode::make(t->make_narrowoop()); } else if (t->isa_klassptr()) { - new_in2 = ConNode::make(this, t->make_narrowklass()); + new_in2 = ConNode::make(t->make_narrowklass()); } } if (new_in2 != NULL) { @@ -2899,11 +2924,11 @@ const Type* t = in1->bottom_type(); if (t == TypePtr::NULL_PTR) { assert(t->isa_oopptr(), "null klass?"); - n->subsume_by(ConNode::make(this, TypeNarrowOop::NULL_PTR), this); + n->subsume_by(ConNode::make(TypeNarrowOop::NULL_PTR), this); } else if (t->isa_oopptr()) { - n->subsume_by(ConNode::make(this, t->make_narrowoop()), this); + n->subsume_by(ConNode::make(t->make_narrowoop()), this); } else if (t->isa_klassptr()) { - n->subsume_by(ConNode::make(this, t->make_narrowklass()), this); + n->subsume_by(ConNode::make(t->make_narrowklass()), this); } } if (in1->outcnt() == 0) { @@ -2964,7 +2989,7 @@ if (d) { // Replace them with a fused divmod if supported if (Matcher::has_match_rule(Op_DivModI)) { - DivModINode* divmod = DivModINode::make(this, n); + DivModINode* divmod = DivModINode::make(n); d->subsume_by(divmod->div_proj(), this); n->subsume_by(divmod->mod_proj(), this); } else { @@ -2984,7 +3009,7 @@ if (d) { // Replace them with a fused divmod if supported if (Matcher::has_match_rule(Op_DivModL)) { - DivModLNode* divmod = DivModLNode::make(this, n); + DivModLNode* divmod = DivModLNode::make(n); d->subsume_by(divmod->div_proj(), this); n->subsume_by(divmod->mod_proj(), this); } else { @@ -3010,7 +3035,7 @@ if (n->req()-1 > 2) { // Replace many operand PackNodes with a binary tree for matching PackNode* p = (PackNode*) n; - Node* btp = p->binary_tree_pack(this, 1, n->req()); + Node* btp = p->binary_tree_pack(1, n->req()); n->subsume_by(btp, this); } break; @@ -3035,11 +3060,11 @@ if (t != NULL && t->is_con()) { juint shift = t->get_con(); if (shift > mask) { // Unsigned cmp - n->set_req(2, ConNode::make(this, TypeInt::make(shift & mask))); + n->set_req(2, ConNode::make(TypeInt::make(shift & mask))); } } else { if (t == NULL || t->_lo < 0 || t->_hi > (int)mask) { - Node* shift = new AndINode(in2, ConNode::make(this, TypeInt::make(mask))); + Node* shift = new AndINode(in2, ConNode::make(TypeInt::make(mask))); n->set_req(2, shift); } } @@ -4031,6 +4056,7 @@ int j = 0; int identical = 0; int i = 0; + bool modified = false; for (; i < _expensive_nodes->length()-1; i++) { assert(j <= i, "can't write beyond current index"); if (_expensive_nodes->at(i)->Opcode() == _expensive_nodes->at(i+1)->Opcode()) { @@ -4043,20 +4069,23 @@ identical = 0; } else { Node* n = _expensive_nodes->at(i); - igvn.hash_delete(n); - n->set_req(0, NULL); + igvn.replace_input_of(n, 0, NULL); igvn.hash_insert(n); + modified = true; } } if (identical > 0) { _expensive_nodes->at_put(j++, _expensive_nodes->at(i)); } else if (_expensive_nodes->length() >= 1) { Node* n = _expensive_nodes->at(i); - igvn.hash_delete(n); - n->set_req(0, NULL); + igvn.replace_input_of(n, 0, NULL); igvn.hash_insert(n); + modified = true; } _expensive_nodes->trunc_to(j); + if (modified) { + igvn.optimize(); + } } void Compile::add_expensive_node(Node * n) { diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/compile.hpp --- a/hotspot/src/share/vm/opto/compile.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/compile.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -344,6 +344,8 @@ VectorSet _dead_node_list; // Set of dead nodes uint _dead_node_count; // Number of dead nodes; VectorSet::Size() is O(N). // So use this to keep count and make the call O(1). + DEBUG_ONLY( Unique_Node_List* _modified_nodes; ) // List of nodes which inputs were modified + debug_only(static int _debug_idx;) // Monotonic counter (not reset), use -XX:BreakAtNode= Arena _node_arena; // Arena for new-space Nodes Arena _old_arena; // Arena for old-space Nodes, lifetime during xform @@ -766,6 +768,11 @@ void print_missing_nodes(); #endif + // Record modified nodes to check that they are put on IGVN worklist + void record_modified_node(Node* n) NOT_DEBUG_RETURN; + void remove_modified_node(Node* n) NOT_DEBUG_RETURN; + DEBUG_ONLY( Unique_Node_List* modified_nodes() const { return _modified_nodes; } ) + // Constant table ConstantTable& constant_table() { return _constant_table; } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/connode.cpp --- a/hotspot/src/share/vm/opto/connode.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/connode.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -43,7 +43,7 @@ } //------------------------------make------------------------------------------- -ConNode *ConNode::make( Compile* C, const Type *t ) { +ConNode *ConNode::make(const Type *t) { switch( t->basic_type() ) { case T_INT: return new ConINode( t->is_int() ); case T_LONG: return new ConLNode( t->is_long() ); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/connode.hpp --- a/hotspot/src/share/vm/opto/connode.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/connode.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -46,7 +46,7 @@ virtual const RegMask &in_RegMask(uint) const { return RegMask::Empty; } // Polymorphic factory method: - static ConNode* make( Compile* C, const Type *t ); + static ConNode* make(const Type *t); }; //------------------------------ConINode--------------------------------------- @@ -57,7 +57,7 @@ virtual int Opcode() const; // Factory method: - static ConINode* make( Compile* C, int con ) { + static ConINode* make(int con) { return new ConINode( TypeInt::make(con) ); } @@ -71,7 +71,7 @@ virtual int Opcode() const; // Factory methods: - static ConPNode* make( Compile *C ,address con ) { + static ConPNode* make(address con) { if (con == NULL) return new ConPNode( TypePtr::NULL_PTR ) ; else @@ -105,7 +105,7 @@ virtual int Opcode() const; // Factory method: - static ConLNode* make( Compile *C ,jlong con ) { + static ConLNode* make(jlong con) { return new ConLNode( TypeLong::make(con) ); } @@ -119,7 +119,7 @@ virtual int Opcode() const; // Factory method: - static ConFNode* make( Compile *C, float con ) { + static ConFNode* make(float con) { return new ConFNode( TypeF::make(con) ); } @@ -133,7 +133,7 @@ virtual int Opcode() const; // Factory method: - static ConDNode* make( Compile *C, double con ) { + static ConDNode* make(double con) { return new ConDNode( TypeD::make(con) ); } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/divnode.cpp --- a/hotspot/src/share/vm/opto/divnode.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/divnode.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -479,7 +479,10 @@ if (i == 0) return NULL; // Dividing by zero constant does not idealize - set_req(0,NULL); // Dividing by a not-zero constant; no faulting + if (in(0) != NULL) { + phase->igvn_rehash_node_delayed(this); + set_req(0, NULL); // Dividing by a not-zero constant; no faulting + } // Dividing by MININT does not optimize as a power-of-2 shift. if( i == min_jint ) return NULL; @@ -578,7 +581,10 @@ if (l == 0) return NULL; // Dividing by zero constant does not idealize - set_req(0,NULL); // Dividing by a not-zero constant; no faulting + if (in(0) != NULL) { + phase->igvn_rehash_node_delayed(this); + set_req(0, NULL); // Dividing by a not-zero constant; no faulting + } // Dividing by MINLONG does not optimize as a power-of-2 shift. if( l == min_jlong ) return NULL; @@ -1274,7 +1280,7 @@ } //------------------------------make------------------------------------------ -DivModINode* DivModINode::make(Compile* C, Node* div_or_mod) { +DivModINode* DivModINode::make(Node* div_or_mod) { Node* n = div_or_mod; assert(n->Opcode() == Op_DivI || n->Opcode() == Op_ModI, "only div or mod input pattern accepted"); @@ -1286,7 +1292,7 @@ } //------------------------------make------------------------------------------ -DivModLNode* DivModLNode::make(Compile* C, Node* div_or_mod) { +DivModLNode* DivModLNode::make(Node* div_or_mod) { Node* n = div_or_mod; assert(n->Opcode() == Op_DivL || n->Opcode() == Op_ModL, "only div or mod input pattern accepted"); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/divnode.hpp --- a/hotspot/src/share/vm/opto/divnode.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/divnode.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -168,7 +168,7 @@ virtual Node *match( const ProjNode *proj, const Matcher *m ); // Make a divmod and associated projections from a div or mod. - static DivModINode* make(Compile* C, Node* div_or_mod); + static DivModINode* make(Node* div_or_mod); }; //------------------------------DivModLNode--------------------------------------- @@ -181,7 +181,7 @@ virtual Node *match( const ProjNode *proj, const Matcher *m ); // Make a divmod and associated projections from a div or mod. - static DivModLNode* make(Compile* C, Node* div_or_mod); + static DivModLNode* make(Node* div_or_mod); }; #endif // SHARE_VM_OPTO_DIVNODE_HPP diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/escape.cpp --- a/hotspot/src/share/vm/opto/escape.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/escape.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -1452,7 +1452,6 @@ return 0; InitializeNode* ini = alloc->as_Allocate()->initialization(); - Compile* C = _compile; bool visited_bottom_offset = false; GrowableArray offsets_worklist; diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/graphKit.cpp --- a/hotspot/src/share/vm/opto/graphKit.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/graphKit.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -591,7 +591,7 @@ C->log()->elem("hot_throw preallocated='1' reason='%s'", Deoptimization::trap_reason_name(reason)); const TypeInstPtr* ex_con = TypeInstPtr::make(ex_obj); - Node* ex_node = _gvn.transform( ConNode::make(C, ex_con) ); + Node* ex_node = _gvn.transform(ConNode::make(ex_con)); // Clear the detail message of the preallocated exception object. // Weblogic sometimes mutates the detail message of exceptions @@ -706,7 +706,7 @@ if (map() == NULL) return NULL; // Clone the memory edge first - Node* mem = MergeMemNode::make(C, map()->memory()); + Node* mem = MergeMemNode::make(map()->memory()); gvn().set_type_bottom(mem); SafePointNode *clonemap = (SafePointNode*)map()->clone(); @@ -1135,7 +1135,7 @@ return longcon((julong) offset_con); } Node* conv = _gvn.transform( new ConvI2LNode(offset)); - Node* mask = _gvn.transform( ConLNode::make(C, (julong) max_juint) ); + Node* mask = _gvn.transform(ConLNode::make((julong) max_juint)); return _gvn.transform( new AndLNode(conv, mask) ); } @@ -1435,7 +1435,7 @@ //------------------------------set_all_memory--------------------------------- void GraphKit::set_all_memory(Node* newmem) { - Node* mergemem = MergeMemNode::make(C, newmem); + Node* mergemem = MergeMemNode::make(newmem); gvn().set_type_bottom(mergemem); map()->set_memory(mergemem); } @@ -1464,9 +1464,9 @@ Node* mem = memory(adr_idx); Node* ld; if (require_atomic_access && bt == T_LONG) { - ld = LoadLNode::make_atomic(C, ctl, mem, adr, adr_type, t, mo); + ld = LoadLNode::make_atomic(ctl, mem, adr, adr_type, t, mo); } else if (require_atomic_access && bt == T_DOUBLE) { - ld = LoadDNode::make_atomic(C, ctl, mem, adr, adr_type, t, mo); + ld = LoadDNode::make_atomic(ctl, mem, adr, adr_type, t, mo); } else { ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt, mo); } @@ -1488,9 +1488,9 @@ Node *mem = memory(adr_idx); Node* st; if (require_atomic_access && bt == T_LONG) { - st = StoreLNode::make_atomic(C, ctl, mem, adr, adr_type, val, mo); + st = StoreLNode::make_atomic(ctl, mem, adr, adr_type, val, mo); } else if (require_atomic_access && bt == T_DOUBLE) { - st = StoreDNode::make_atomic(C, ctl, mem, adr, adr_type, val, mo); + st = StoreDNode::make_atomic(ctl, mem, adr, adr_type, val, mo); } else { st = StoreNode::make(_gvn, ctl, mem, adr, adr_type, val, bt, mo); } @@ -2084,9 +2084,9 @@ void GraphKit::round_double_arguments(ciMethod* dest_method) { // (Note: TypeFunc::make has a cache that makes this fast.) const TypeFunc* tf = TypeFunc::make(dest_method); - int nargs = tf->_domain->_cnt - TypeFunc::Parms; + int nargs = tf->domain()->cnt() - TypeFunc::Parms; for (int j = 0; j < nargs; j++) { - const Type *targ = tf->_domain->field_at(j + TypeFunc::Parms); + const Type *targ = tf->domain()->field_at(j + TypeFunc::Parms); if( targ->basic_type() == T_DOUBLE ) { // If any parameters are doubles, they must be rounded before // the call, dstore_rounding does gvn.transform @@ -2188,10 +2188,10 @@ return; } const TypeFunc* tf = TypeFunc::make(dest_method); - int nargs = tf->_domain->_cnt - TypeFunc::Parms; + int nargs = tf->domain()->cnt() - TypeFunc::Parms; int skip = Bytecodes::has_receiver(bc) ? 1 : 0; for (int j = skip, i = 0; j < nargs && i < TypeProfileArgsLimit; j++) { - const Type *targ = tf->_domain->field_at(j + TypeFunc::Parms); + const Type *targ = tf->domain()->field_at(j + TypeFunc::Parms); if (targ->basic_type() == T_OBJECT || targ->basic_type() == T_ARRAY) { bool maybe_null = true; ciKlass* better_type = NULL; @@ -3364,7 +3364,7 @@ // This will allow us to observe initializations when they occur, // and link them properly (as a group) to the InitializeNode. assert(init->in(InitializeNode::Memory) == malloc, ""); - MergeMemNode* minit_in = MergeMemNode::make(C, malloc); + MergeMemNode* minit_in = MergeMemNode::make(malloc); init->set_req(InitializeNode::Memory, minit_in); record_for_igvn(minit_in); // fold it up later, if possible Node* minit_out = memory(rawidx); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/idealKit.cpp --- a/hotspot/src/share/vm/opto/idealKit.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/idealKit.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -320,7 +320,7 @@ Node* ns = new_cvstate(); for (uint i = 0; i < ns->req(); i++) ns->init_req(i, _cvstate->in(i)); // We must clone memory since it will be updated as we do stores. - ns->set_req(TypeFunc::Memory, MergeMemNode::make(C, ns->in(TypeFunc::Memory))); + ns->set_req(TypeFunc::Memory, MergeMemNode::make(ns->in(TypeFunc::Memory))); return ns; } @@ -359,7 +359,7 @@ Node* mem = memory(adr_idx); Node* ld; if (require_atomic_access && bt == T_LONG) { - ld = LoadLNode::make_atomic(C, ctl, mem, adr, adr_type, t, MemNode::unordered); + ld = LoadLNode::make_atomic(ctl, mem, adr, adr_type, t, MemNode::unordered); } else { ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt, MemNode::unordered); } @@ -375,7 +375,7 @@ Node *mem = memory(adr_idx); Node* st; if (require_atomic_access && bt == T_LONG) { - st = StoreLNode::make_atomic(C, ctl, mem, adr, adr_type, val, mo); + st = StoreLNode::make_atomic(ctl, mem, adr, adr_type, val, mo); } else { st = StoreNode::make(_gvn, ctl, mem, adr, adr_type, val, bt, mo); } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/lcm.cpp --- a/hotspot/src/share/vm/opto/lcm.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/lcm.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -464,7 +464,9 @@ iop == Op_CreateEx || // Create-exception must start block iop == Op_CheckCastPP ) { - worklist.map(i,worklist.pop()); + // select the node n + // remove n from worklist and retain the order of remaining nodes + worklist.remove((uint)i); return n; } @@ -550,7 +552,9 @@ assert(idx >= 0, "index should be set"); Node *n = worklist[(uint)idx]; // Get the winner - worklist.map((uint)idx, worklist.pop()); // Compress worklist + // select the node n + // remove n from worklist and retain the order of remaining nodes + worklist.remove((uint)idx); return n; } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/library_call.cpp --- a/hotspot/src/share/vm/opto/library_call.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/library_call.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -1905,7 +1905,7 @@ Node *bolyplus1 = _gvn.transform(new BoolNode( cmpyplus1, BoolTest::eq )); Node* correctedsign = NULL; if (ConditionalMoveLimit != 0) { - correctedsign = _gvn.transform( CMoveNode::make(C, NULL, bolyplus1, signnode, longcon(0), TypeLong::LONG)); + correctedsign = _gvn.transform(CMoveNode::make(NULL, bolyplus1, signnode, longcon(0), TypeLong::LONG)); } else { IfNode *ifyplus1 = create_and_xform_if(ylong_path,bolyplus1, PROB_FAIR, COUNT_UNKNOWN); RegionNode *r = new RegionNode(3); @@ -1934,7 +1934,7 @@ // (1&(long)y)==1?-DPow(abs(x), y):DPow(abs(x), y) Node *signresult = NULL; if (ConditionalMoveLimit != 0) { - signresult = _gvn.transform( CMoveNode::make(C, NULL, bol3, absxpowy, negabsxpowy, Type::DOUBLE)); + signresult = _gvn.transform(CMoveNode::make(NULL, bol3, absxpowy, negabsxpowy, Type::DOUBLE)); } else { IfNode *ifyeven = create_and_xform_if(ylong_path,bol3, PROB_FAIR, COUNT_UNKNOWN); RegionNode *r = new RegionNode(3); @@ -2268,7 +2268,7 @@ // which could hinder other optimizations. // Since Math.min/max is often used with arraycopy, we want // tightly_coupled_allocation to be able to see beyond min/max expressions. - Node* cmov = CMoveNode::make(C, NULL, best_bol, + Node* cmov = CMoveNode::make(NULL, best_bol, answer_if_false, answer_if_true, TypeInt::make(lo, hi, widen)); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/loopPredicate.cpp --- a/hotspot/src/share/vm/opto/loopPredicate.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/loopPredicate.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -107,8 +107,7 @@ rgn = new RegionNode(1); rgn->add_req(uncommon_proj); register_control(rgn, loop, uncommon_proj); - _igvn.hash_delete(call); - call->set_req(0, rgn); + _igvn.replace_input_of(call, 0, rgn); // When called from beautify_loops() idom is not constructed yet. if (_idom != NULL) { set_idom(call, rgn, dom_depth(rgn)); @@ -166,8 +165,7 @@ if (new_entry == NULL) { // Attach if_cont to iff - _igvn.hash_delete(iff); - iff->set_req(0, if_cont); + _igvn.replace_input_of(iff, 0, if_cont); if (_idom != NULL) { set_idom(iff, if_cont, dom_depth(iff)); } @@ -194,8 +192,7 @@ rgn = new RegionNode(1); register_new_node_with_optimizer(rgn); rgn->add_req(uncommon_proj); - hash_delete(call); - call->set_req(0, rgn); + replace_input_of(call, 0, rgn); } else { // Find region's edge corresponding to uncommon_proj for (; proj_index < rgn->req(); proj_index++) diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/loopTransform.cpp --- a/hotspot/src/share/vm/opto/loopTransform.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/loopTransform.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -924,15 +924,13 @@ if( bol->outcnt() != 1 ) { bol = bol->clone(); register_new_node(bol,main_end->in(CountedLoopEndNode::TestControl)); - _igvn.hash_delete(main_end); - main_end->set_req(CountedLoopEndNode::TestValue, bol); + _igvn.replace_input_of(main_end, CountedLoopEndNode::TestValue, bol); } // Need only 1 user of 'cmp' because I will be hacking the loop bounds. if( cmp->outcnt() != 1 ) { cmp = cmp->clone(); register_new_node(cmp,main_end->in(CountedLoopEndNode::TestControl)); - _igvn.hash_delete(bol); - bol->set_req(1, cmp); + _igvn.replace_input_of(bol, 1, cmp); } //------------------------------ @@ -1118,8 +1116,7 @@ Node* pre_bol = pre_end->in(CountedLoopEndNode::TestValue)->as_Bool(); BoolNode* new_bol0 = new BoolNode(pre_bol->in(1), new_test); register_new_node( new_bol0, pre_head->in(0) ); - _igvn.hash_delete(pre_end); - pre_end->set_req(CountedLoopEndNode::TestValue, new_bol0); + _igvn.replace_input_of(pre_end, CountedLoopEndNode::TestValue, new_bol0); // Modify main loop guard condition assert(min_iff->in(CountedLoopEndNode::TestValue) == min_bol, "guard okay"); BoolNode* new_bol1 = new BoolNode(min_bol->in(1), new_test); @@ -1130,8 +1127,7 @@ BoolNode* main_bol = main_end->in(CountedLoopEndNode::TestValue)->as_Bool(); BoolNode* new_bol2 = new BoolNode(main_bol->in(1), new_test); register_new_node( new_bol2, main_end->in(CountedLoopEndNode::TestControl) ); - _igvn.hash_delete(main_end); - main_end->set_req(CountedLoopEndNode::TestValue, new_bol2); + _igvn.replace_input_of(main_end, CountedLoopEndNode::TestValue, new_bol2); } // Flag main loop @@ -1346,8 +1342,7 @@ Node* bol2 = loop_end->in(1)->clone(); bol2->set_req(1, cmp2); register_new_node(bol2, ctrl2); - _igvn.hash_delete(loop_end); - loop_end->set_req(1, bol2); + _igvn.replace_input_of(loop_end, 1, bol2); } // Step 3: Find the min-trip test guaranteed before a 'main' loop. // Make it a 1-trip test (means at least 2 trips). @@ -1356,8 +1351,7 @@ // can edit it's inputs directly. Hammer in the new limit for the // minimum-trip guard. assert(opaq->outcnt() == 1, ""); - _igvn.hash_delete(opaq); - opaq->set_req(1, new_limit); + _igvn.replace_input_of(opaq, 1, new_limit); } // Adjust max trip count. The trip count is intentionally rounded @@ -1407,8 +1401,7 @@ register_new_node( cmp2, ctrl2 ); Node *bol2 = new BoolNode( cmp2, loop_end->test_trip() ); register_new_node( bol2, ctrl2 ); - _igvn.hash_delete(loop_end); - loop_end->set_req(CountedLoopEndNode::TestValue, bol2); + _igvn.replace_input_of(loop_end, CountedLoopEndNode::TestValue, bol2); // Step 3: Find the min-trip test guaranteed before a 'main' loop. // Make it a 1-trip test (means at least 2 trips). @@ -1997,8 +1990,7 @@ : (Node*)new MaxINode(pre_limit, orig_limit); register_new_node(pre_limit, pre_ctrl); } - _igvn.hash_delete(pre_opaq); - pre_opaq->set_req(1, pre_limit); + _igvn.replace_input_of(pre_opaq, 1, pre_limit); // Note:: we are making the main loop limit no longer precise; // need to round up based on stride. @@ -2027,10 +2019,9 @@ Node *main_bol = main_cle->in(1); // Hacking loop bounds; need private copies of exit test if( main_bol->outcnt() > 1 ) {// BoolNode shared? - _igvn.hash_delete(main_cle); main_bol = main_bol->clone();// Clone a private BoolNode register_new_node( main_bol, main_cle->in(0) ); - main_cle->set_req(1,main_bol); + _igvn.replace_input_of(main_cle, 1, main_bol); } Node *main_cmp = main_bol->in(1); if( main_cmp->outcnt() > 1 ) { // CmpNode shared? diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/loopnode.cpp --- a/hotspot/src/share/vm/opto/loopnode.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/loopnode.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -133,7 +133,7 @@ // Return earliest legal location assert(early == find_non_split_ctrl(early), "unexpected early control"); - if (n->is_expensive()) { + if (n->is_expensive() && !_verify_only && !_verify_me) { assert(n->in(0), "should have control input"); early = get_early_ctrl_for_expensive(n, early); } @@ -226,8 +226,7 @@ } if (ctl != n->in(0)) { - _igvn.hash_delete(n); - n->set_req(0, ctl); + _igvn.replace_input_of(n, 0, ctl); _igvn.hash_insert(n); } @@ -521,8 +520,7 @@ assert(check_iff->in(1)->Opcode() == Op_Conv2B && check_iff->in(1)->in(1)->Opcode() == Op_Opaque1, ""); Node* opq = check_iff->in(1)->in(1); - _igvn.hash_delete(opq); - opq->set_req(1, bol); + _igvn.replace_input_of(opq, 1, bol); // Update ctrl. set_ctrl(opq, check_iff->in(0)); set_ctrl(check_iff->in(1), check_iff->in(0)); @@ -690,7 +688,7 @@ incr->set_req(2,stride); incr = _igvn.register_new_node_with_optimizer(incr); set_early_ctrl( incr ); - _igvn.hash_delete(phi); + _igvn.rehash_node_delayed(phi); phi->set_req_X( LoopNode::LoopBackControl, incr, &_igvn ); // If phi type is more restrictive than Int, raise to @@ -743,8 +741,8 @@ iffalse = iff2; iftrue = ift2; } else { - _igvn.hash_delete(iffalse); - _igvn.hash_delete(iftrue); + _igvn.rehash_node_delayed(iffalse); + _igvn.rehash_node_delayed(iftrue); iffalse->set_req_X( 0, le, &_igvn ); iftrue ->set_req_X( 0, le, &_igvn ); } @@ -1257,6 +1255,7 @@ _head->del_req(i); } } + igvn.rehash_node_delayed(_head); // Transform landing pad igvn.register_new_node_with_optimizer(landing_pad, _head); // Insert landing pad into the header @@ -1397,7 +1396,7 @@ igvn.register_new_node_with_optimizer(r, _head); // Plug region into end of loop _head, followed by hot_tail while( _head->req() > 3 ) _head->del_req( _head->req()-1 ); - _head->set_req(2, r); + igvn.replace_input_of(_head, 2, r); if( hot_idx ) _head->add_req(hot_tail); // Split all the Phis up between '_head' loop and the Region 'r' @@ -1419,7 +1418,7 @@ igvn.register_new_node_with_optimizer(phi, n); // Add the merge phi to the old Phi while( n->req() > 3 ) n->del_req( n->req()-1 ); - n->set_req(2, phi); + igvn.replace_input_of(n, 2, phi); if( hot_idx ) n->add_req(hot_phi); } } @@ -1495,13 +1494,14 @@ if( fall_in_cnt > 1 ) { // Since I am just swapping inputs I do not need to update def-use info Node *tmp = _head->in(1); + igvn.rehash_node_delayed(_head); _head->set_req( 1, _head->in(fall_in_cnt) ); _head->set_req( fall_in_cnt, tmp ); // Swap also all Phis for (DUIterator_Fast imax, i = _head->fast_outs(imax); i < imax; i++) { Node* phi = _head->fast_out(i); if( phi->is_Phi() ) { - igvn.hash_delete(phi); // Yank from hash before hacking edges + igvn.rehash_node_delayed(phi); // Yank from hash before hacking edges tmp = phi->in(1); phi->set_req( 1, phi->in(fall_in_cnt) ); phi->set_req( fall_in_cnt, tmp ); @@ -2905,6 +2905,7 @@ uint k = 0; // Probably cfg->in(0) while( cfg->in(k) != m ) k++; // But check incase cfg is a Region cfg->set_req( k, if_t ); // Now point to NeverBranch + _igvn._worklist.push(cfg); // Now create the never-taken loop exit Node *if_f = new CProjNode( iff, 1 ); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/loopopts.cpp --- a/hotspot/src/share/vm/opto/loopopts.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/loopopts.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -625,7 +625,7 @@ set_ctrl(inp, cmov_ctrl); } } - Node *cmov = CMoveNode::make( C, cmov_ctrl, iff->in(1), phi->in(1+flip), phi->in(2-flip), _igvn.type(phi) ); + Node *cmov = CMoveNode::make(cmov_ctrl, iff->in(1), phi->in(1+flip), phi->in(2-flip), _igvn.type(phi)); register_new_node( cmov, cmov_ctrl ); _igvn.replace_node( phi, cmov ); #ifndef PRODUCT @@ -2574,7 +2574,7 @@ new_head->set_unswitch_count(head->unswitch_count()); // Preserve _igvn.register_new_node_with_optimizer(new_head); assert(first_not_peeled->in(0) == last_peel, "last_peel <- first_not_peeled"); - first_not_peeled->set_req(0, new_head); + _igvn.replace_input_of(first_not_peeled, 0, new_head); set_loop(new_head, loop); loop->_body.push(new_head); not_peel.set(new_head->_idx); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/machnode.cpp --- a/hotspot/src/share/vm/opto/machnode.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/machnode.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -178,7 +178,7 @@ } // Return an equivalent instruction using memory for cisc_operand position -MachNode *MachNode::cisc_version(int offset, Compile* C) { +MachNode *MachNode::cisc_version(int offset) { ShouldNotCallThis(); return NULL; } @@ -411,7 +411,7 @@ //------------------------------peephole--------------------------------------- // Apply peephole rule(s) to this instruction -MachNode *MachNode::peephole( Block *block, int block_index, PhaseRegAlloc *ra_, int &deleted, Compile* C ) { +MachNode *MachNode::peephole(Block *block, int block_index, PhaseRegAlloc *ra_, int &deleted) { return NULL; } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/machnode.hpp --- a/hotspot/src/share/vm/opto/machnode.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/machnode.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -152,7 +152,7 @@ virtual uint cmp( const MachOper &oper ) const; // Virtual clone, since I do not know how big the MachOper is. - virtual MachOper *clone(Compile* C) const = 0; + virtual MachOper *clone() const = 0; // Return ideal Type from simple operands. Fail for complex operands. virtual const Type *type() const; @@ -202,10 +202,10 @@ // Copy inputs and operands to new node of instruction. // Called from cisc_version() and short_branch_version(). // !!!! The method's body is defined in ad_.cpp file. - void fill_new_machnode(MachNode *n, Compile* C) const; + void fill_new_machnode(MachNode *n) const; // Return an equivalent instruction using memory for cisc_operand position - virtual MachNode *cisc_version(int offset, Compile* C); + virtual MachNode *cisc_version(int offset); // Modify this instruction's register mask to use stack version for cisc_operand virtual void use_cisc_RegMask(); @@ -317,7 +317,7 @@ virtual const class TypePtr *adr_type() const; // Apply peephole rule(s) to this instruction - virtual MachNode *peephole( Block *block, int block_index, PhaseRegAlloc *ra_, int &deleted, Compile* C ); + virtual MachNode *peephole(Block *block, int block_index, PhaseRegAlloc *ra_, int &deleted); // Top-level ideal Opcode matched virtual int ideal_Opcode() const { return Op_Node; } @@ -627,7 +627,7 @@ virtual void save_label(Label** label, uint* block_num) = 0; // Support for short branches - virtual MachNode *short_branch_version(Compile* C) { return NULL; } + virtual MachNode *short_branch_version() { return NULL; } virtual bool pinned() const { return true; }; }; @@ -985,7 +985,7 @@ labelOper(labelOper* l) : _label(l->_label) , _block_num(l->_block_num) {} - virtual MachOper *clone(Compile* C) const; + virtual MachOper *clone() const; virtual Label *label() const { assert(_label != NULL, "need Label"); return _label; } @@ -1012,7 +1012,7 @@ methodOper() : _method(0) {} methodOper(intptr_t method) : _method(method) {} - virtual MachOper *clone(Compile* C) const; + virtual MachOper *clone() const; virtual intptr_t method() const { return _method; } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/macro.cpp --- a/hotspot/src/share/vm/opto/macro.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/macro.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -702,6 +702,7 @@ ciType* elem_type; Node* res = alloc->result_cast(); + assert(res == NULL || res->is_CheckCastPP(), "unexpected AllocateNode result"); const TypeOopPtr* res_type = NULL; if (res != NULL) { // Could be NULL when there are no users res_type = _igvn.type(res)->isa_oopptr(); @@ -791,6 +792,7 @@ for (int k = 0; k < j; k++) { sfpt->del_req(last--); } + _igvn._worklist.push(sfpt); // rollback processed safepoints while (safepoints_done.length() > 0) { SafePointNode* sfpt_done = safepoints_done.pop(); @@ -815,6 +817,7 @@ } } } + _igvn._worklist.push(sfpt_done); } #ifndef PRODUCT if (PrintEliminateAllocations) { @@ -855,6 +858,7 @@ int start = jvms->debug_start(); int end = jvms->debug_end(); sfpt->replace_edges_in_range(res, sobj, start, end); + _igvn._worklist.push(sfpt); safepoints_done.append_if_missing(sfpt); // keep it for rollback } return true; @@ -1034,6 +1038,8 @@ return false; } + assert(boxing->result_cast() == NULL, "unexpected boxing node result"); + extract_call_projections(boxing); const TypeTuple* r = boxing->tf()->range(); @@ -1775,6 +1781,7 @@ Node *pf_region = new RegionNode(3); Node *pf_phi_rawmem = new PhiNode( pf_region, Type::MEMORY, TypeRawPtr::BOTTOM ); + transform_later(pf_region); // Generate several prefetch instructions. uint lines = (length != NULL) ? AllocatePrefetchLines : AllocateInstancePrefetchLines; diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/matcher.cpp --- a/hotspot/src/share/vm/opto/matcher.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/matcher.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -305,7 +305,7 @@ // to avoid false sharing if the corresponding mach node is not used. // The corresponding mach node is only used in rare cases for derived // pointers. - Node* new_ideal_null = ConNode::make(C, TypePtr::NULL_PTR); + Node* new_ideal_null = ConNode::make(TypePtr::NULL_PTR); // Swap out to old-space; emptying new-space Arena *old = C->node_arena()->move_contents(C->old_arena()); @@ -1643,8 +1643,8 @@ } // Build the object to represent this state & prepare for recursive calls - MachNode *mach = s->MachNodeGenerator( rule, C ); - mach->_opnds[0] = s->MachOperGenerator( _reduceOp[rule], C ); + MachNode *mach = s->MachNodeGenerator(rule); + mach->_opnds[0] = s->MachOperGenerator(_reduceOp[rule]); assert( mach->_opnds[0] != NULL, "Missing result operand" ); Node *leaf = s->_leaf; // Check for instruction or instruction chain rule @@ -1756,13 +1756,13 @@ assert( 0 <= opnd_class_instance && opnd_class_instance < NUM_OPERANDS, "Bad AD file: Instruction chain rule must chain from operand"); // Insert operand into array of operands for this instruction - mach->_opnds[1] = s->MachOperGenerator( opnd_class_instance, C ); + mach->_opnds[1] = s->MachOperGenerator(opnd_class_instance); ReduceOper( s, newrule, mem, mach ); } else { // Chain from the result of an instruction assert( newrule >= _LAST_MACH_OPER, "Do NOT chain from internal operand"); - mach->_opnds[1] = s->MachOperGenerator( _reduceOp[catch_op], C ); + mach->_opnds[1] = s->MachOperGenerator(_reduceOp[catch_op]); Node *mem1 = (Node*)1; debug_only(Node *save_mem_node = _mem_node;) mach->add_req( ReduceInst(s, newrule, mem1) ); @@ -1807,7 +1807,7 @@ if( newrule < NUM_OPERANDS ) { // Operand/operandClass or internalOp/instruction? // Operand/operandClass // Insert operand into array of operands for this instruction - mach->_opnds[num_opnds++] = newstate->MachOperGenerator( opnd_class_instance, C ); + mach->_opnds[num_opnds++] = newstate->MachOperGenerator(opnd_class_instance); ReduceOper( newstate, newrule, mem, mach ); } else { // Child is internal operand or new instruction @@ -1818,7 +1818,7 @@ } else { // instruction --> call build operand( ) to catch result // --> ReduceInst( newrule ) - mach->_opnds[num_opnds++] = s->MachOperGenerator( _reduceOp[catch_op], C ); + mach->_opnds[num_opnds++] = s->MachOperGenerator(_reduceOp[catch_op]); Node *mem1 = (Node*)1; debug_only(Node *save_mem_node = _mem_node;) mach->add_req( ReduceInst( newstate, newrule, mem1 ) ); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/mathexactnode.cpp --- a/hotspot/src/share/vm/opto/mathexactnode.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/mathexactnode.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -191,7 +191,7 @@ NativeType val1 = TypeClass::as_self(type1)->get_con(); NativeType val2 = TypeClass::as_self(type2)->get_con(); if (node->will_overflow(val1, val2) == false) { - Node* con_result = ConINode::make(phase->C, 0); + Node* con_result = ConINode::make(0); return con_result; } return NULL; diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/memnode.cpp --- a/hotspot/src/share/vm/opto/memnode.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/memnode.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -933,12 +933,12 @@ return (LoadNode*)NULL; } -LoadLNode* LoadLNode::make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo) { +LoadLNode* LoadLNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo) { bool require_atomic = true; return new LoadLNode(ctl, mem, adr, adr_type, rt->is_long(), mo, require_atomic); } -LoadDNode* LoadDNode::make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo) { +LoadDNode* LoadDNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo) { bool require_atomic = true; return new LoadDNode(ctl, mem, adr, adr_type, rt, mo, require_atomic); } @@ -1471,6 +1471,7 @@ Node* ctrl = in(MemNode::Control); Node* address = in(MemNode::Address); + bool progress = false; // Skip up past a SafePoint control. Cannot do this for Stores because // pointer stores & cardmarks must stay on the same side of a SafePoint. @@ -1478,6 +1479,7 @@ phase->C->get_alias_index(phase->type(address)->is_ptr()) != Compile::AliasIdxRaw ) { ctrl = ctrl->in(0); set_req(MemNode::Control,ctrl); + progress = true; } intptr_t ignore = 0; @@ -1490,6 +1492,7 @@ && all_controls_dominate(base, phase->C->start())) { // A method-invariant, non-null address (constant or 'this' argument). set_req(MemNode::Control, NULL); + progress = true; } } @@ -1550,7 +1553,7 @@ } } - return NULL; // No further progress + return progress ? this : NULL; } // Helper to recognize certain Klass fields which are invariant across @@ -2014,7 +2017,6 @@ //----------------------------LoadKlassNode::make------------------------------ // Polymorphic factory method: Node *LoadKlassNode::make( PhaseGVN& gvn, Node *mem, Node *adr, const TypePtr* at, const TypeKlassPtr *tk ) { - Compile* C = gvn.C; Node *ctl = NULL; // sanity check the alias category against the created node type const TypePtr *adr_type = adr->bottom_type()->isa_ptr(); @@ -2379,12 +2381,12 @@ return (StoreNode*)NULL; } -StoreLNode* StoreLNode::make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, MemOrd mo) { +StoreLNode* StoreLNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, MemOrd mo) { bool require_atomic = true; return new StoreLNode(ctl, mem, adr, adr_type, val, mo, require_atomic); } -StoreDNode* StoreDNode::make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, MemOrd mo) { +StoreDNode* StoreDNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, MemOrd mo) { bool require_atomic = true; return new StoreDNode(ctl, mem, adr, adr_type, val, mo, require_atomic); } @@ -2460,7 +2462,7 @@ // and I need to disappear. if (moved != NULL) { // %%% hack to ensure that Ideal returns a new node: - mem = MergeMemNode::make(phase->C, mem); + mem = MergeMemNode::make(mem); return mem; // fold me away } } @@ -2820,7 +2822,6 @@ intptr_t start_offset, Node* end_offset, PhaseGVN* phase) { - Compile* C = phase->C; intptr_t offset = start_offset; int unit = BytesPerLong; @@ -2847,7 +2848,6 @@ return mem; } - Compile* C = phase->C; int unit = BytesPerLong; Node* zbase = start_offset; Node* zend = end_offset; @@ -2875,7 +2875,6 @@ return mem; } - Compile* C = phase->C; assert((end_offset % BytesPerInt) == 0, "odd end offset"); intptr_t done_offset = end_offset; if ((done_offset % BytesPerLong) != 0) { @@ -2944,6 +2943,7 @@ return NULL; } + bool progress = false; // Eliminate volatile MemBars for scalar replaced objects. if (can_reshape && req() == (Precedent+1)) { bool eliminate = false; @@ -2966,6 +2966,7 @@ phase->is_IterGVN()->_worklist.push(my_mem); // remove dead node later my_mem = NULL; } + progress = true; } if (my_mem != NULL && my_mem->is_Mem()) { const TypeOopPtr* t_oop = my_mem->in(MemNode::Address)->bottom_type()->isa_oopptr(); @@ -2995,7 +2996,7 @@ return new ConINode(TypeInt::ZERO); } } - return NULL; + return progress ? this : NULL; } //------------------------------Value------------------------------------------ @@ -3497,6 +3498,7 @@ // if it redundantly stored the same value (or zero to fresh memory). // In any case, wire it in: + phase->igvn_rehash_node_delayed(this); set_req(i, new_st); // The caller may now kill the old guy. @@ -4126,7 +4128,7 @@ // Make a new, untransformed MergeMem with the same base as 'mem'. // If mem is itself a MergeMem, populate the result with the same edges. -MergeMemNode* MergeMemNode::make(Compile* C, Node* mem) { +MergeMemNode* MergeMemNode::make(Node* mem) { return new MergeMemNode(mem); } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/memnode.hpp --- a/hotspot/src/share/vm/opto/memnode.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/memnode.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -333,7 +333,7 @@ virtual int store_Opcode() const { return Op_StoreL; } virtual BasicType memory_type() const { return T_LONG; } bool require_atomic_access() const { return _require_atomic_access; } - static LoadLNode* make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, + static LoadLNode* make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo); #ifndef PRODUCT virtual void dump_spec(outputStream *st) const { @@ -384,7 +384,7 @@ virtual int store_Opcode() const { return Op_StoreD; } virtual BasicType memory_type() const { return T_DOUBLE; } bool require_atomic_access() const { return _require_atomic_access; } - static LoadDNode* make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, + static LoadDNode* make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo); #ifndef PRODUCT virtual void dump_spec(outputStream *st) const { @@ -593,7 +593,7 @@ virtual int Opcode() const; virtual BasicType memory_type() const { return T_LONG; } bool require_atomic_access() const { return _require_atomic_access; } - static StoreLNode* make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, MemOrd mo); + static StoreLNode* make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, MemOrd mo); #ifndef PRODUCT virtual void dump_spec(outputStream *st) const { StoreNode::dump_spec(st); @@ -629,7 +629,7 @@ virtual int Opcode() const; virtual BasicType memory_type() const { return T_DOUBLE; } bool require_atomic_access() const { return _require_atomic_access; } - static StoreDNode* make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, MemOrd mo); + static StoreDNode* make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, MemOrd mo); #ifndef PRODUCT virtual void dump_spec(outputStream *st) const { StoreNode::dump_spec(st); @@ -1138,7 +1138,7 @@ // If the input is a whole memory state, clone it with all its slices intact. // Otherwise, make a new memory state with just that base memory input. // In either case, the result is a newly created MergeMem. - static MergeMemNode* make(Compile* C, Node* base_memory); + static MergeMemNode* make(Node* base_memory); virtual int Opcode() const; virtual Node *Identity( PhaseTransform *phase ); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/movenode.cpp --- a/hotspot/src/share/vm/opto/movenode.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/movenode.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -88,7 +88,7 @@ if( in(Condition)->is_Bool() ) { BoolNode* b = in(Condition)->as_Bool(); BoolNode* b2 = b->negate(phase); - return make( phase->C, in(Control), phase->transform(b2), in(IfTrue), in(IfFalse), _type ); + return make(in(Control), phase->transform(b2), in(IfTrue), in(IfFalse), _type); } } return NULL; @@ -158,7 +158,7 @@ //------------------------------make------------------------------------------- // Make a correctly-flavored CMove. Since _type is directly determined // from the inputs we do not need to specify it here. -CMoveNode *CMoveNode::make( Compile *C, Node *c, Node *bol, Node *left, Node *right, const Type *t ) { +CMoveNode *CMoveNode::make(Node *c, Node *bol, Node *left, Node *right, const Type *t) { switch( t->basic_type() ) { case T_INT: return new CMoveINode( bol, left, right, t->is_int() ); case T_FLOAT: return new CMoveFNode( bol, left, right, t ); @@ -196,7 +196,7 @@ if( in(Condition)->is_Bool() ) { BoolNode* b = in(Condition)->as_Bool(); BoolNode* b2 = b->negate(phase); - return make( phase->C, in(Control), phase->transform(b2), in(IfTrue), in(IfFalse), _type ); + return make(in(Control), phase->transform(b2), in(IfTrue), in(IfFalse), _type); } } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/movenode.hpp --- a/hotspot/src/share/vm/opto/movenode.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/movenode.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -47,7 +47,7 @@ virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); virtual const Type *Value( PhaseTransform *phase ) const; virtual Node *Identity( PhaseTransform *phase ); - static CMoveNode *make( Compile *C, Node *c, Node *bol, Node *left, Node *right, const Type *t ); + static CMoveNode *make(Node *c, Node *bol, Node *left, Node *right, const Type *t); // Helper function to spot cmove graph shapes static Node *is_cmove_id( PhaseTransform *phase, Node *cmp, Node *t, Node *f, BoolNode *b ); }; diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/node.cpp --- a/hotspot/src/share/vm/opto/node.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/node.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -507,7 +507,7 @@ (const void*)(&mthis->_opnds), 1)); mach->_opnds = to; for ( uint i = 0; i < nopnds; ++i ) { - to[i] = from[i]->clone(C); + to[i] = from[i]->clone(); } } // cloning CallNode may need to clone JVMState @@ -620,6 +620,7 @@ *(address*)this = badAddress; // smash the C++ vtbl, probably _in = _out = (Node**) badAddress; _max = _cnt = _outmax = _outcnt = 0; + compile->remove_modified_node(this); #endif } @@ -765,6 +766,7 @@ if (n != NULL) n->del_out((Node *)this); _in[idx] = in(--_cnt); // Compact the array _in[_cnt] = NULL; // NULL out emptied slot + Compile::current()->record_modified_node(this); } //------------------------------del_req_ordered-------------------------------- @@ -780,6 +782,7 @@ Copy::conjoint_words_to_lower((HeapWord*)&_in[idx+1], (HeapWord*)&_in[idx], ((_cnt-idx-1)*sizeof(Node*))); } _in[--_cnt] = NULL; // NULL out emptied slot + Compile::current()->record_modified_node(this); } //------------------------------ins_req---------------------------------------- @@ -1297,6 +1300,7 @@ // Done with outputs. igvn->hash_delete(dead); igvn->_worklist.remove(dead); + igvn->C->remove_modified_node(dead); igvn->set_type(dead, Type::TOP); if (dead->is_macro()) { igvn->C->remove_macro_node(dead); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/node.hpp --- a/hotspot/src/share/vm/opto/node.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/node.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -398,6 +398,7 @@ if (*p != NULL) (*p)->del_out((Node *)this); (*p) = n; if (n != NULL) n->add_out((Node *)this); + Compile::current()->record_modified_node(this); } // Light version of set_req() to init inputs after node creation. void init_req( uint i, Node *n ) { @@ -409,6 +410,7 @@ assert( _in[i] == NULL, "sanity"); _in[i] = n; if (n != NULL) n->add_out((Node *)this); + Compile::current()->record_modified_node(this); } // Find first occurrence of n among my edges: int find_edge(Node* n); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/output.cpp --- a/hotspot/src/share/vm/opto/output.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/output.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -526,7 +526,7 @@ if (_matcher->is_short_branch_offset(mach->rule(), br_size, offset)) { // We've got a winner. Replace this branch. - MachNode* replacement = mach->as_MachBranch()->short_branch_version(this); + MachNode* replacement = mach->as_MachBranch()->short_branch_version(); // Update the jmp_size. int new_size = replacement->size(_regalloc); @@ -785,9 +785,10 @@ // grow downwards in all implementations. // (If, on some machine, the interpreter's Java locals or stack // were to grow upwards, the embedded doubles would be word-swapped.) - jint *dp = (jint*)&d; - array->append(new ConstantIntValue(dp[1])); - array->append(new ConstantIntValue(dp[0])); + jlong_accessor acc; + acc.long_value = jlong_cast(d); + array->append(new ConstantIntValue(acc.words[1])); + array->append(new ConstantIntValue(acc.words[0])); #endif break; } @@ -804,9 +805,10 @@ // grow downwards in all implementations. // (If, on some machine, the interpreter's Java locals or stack // were to grow upwards, the embedded doubles would be word-swapped.) - jint *dp = (jint*)&d; - array->append(new ConstantIntValue(dp[1])); - array->append(new ConstantIntValue(dp[0])); + jlong_accessor acc; + acc.long_value = d; + array->append(new ConstantIntValue(acc.words[1])); + array->append(new ConstantIntValue(acc.words[0])); #endif break; } @@ -1174,7 +1176,7 @@ // fill in the nop array for bundling computations MachNode *_nop_list[Bundle::_nop_count]; - Bundle::initialize_nops(_nop_list, this); + Bundle::initialize_nops(_nop_list); return cb; } @@ -1408,7 +1410,7 @@ if (_matcher->is_short_branch_offset(mach->rule(), br_size, offset)) { // We've got a winner. Replace this branch. - MachNode* replacement = mach->as_MachBranch()->short_branch_version(this); + MachNode* replacement = mach->as_MachBranch()->short_branch_version(); // Update the jmp_size. int new_size = replacement->size(_regalloc); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/parse1.cpp --- a/hotspot/src/share/vm/opto/parse1.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/parse1.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -575,12 +575,13 @@ decrement_age(); } } - if (depth() == 1) { + + if (depth() == 1 && !failing()) { // Add check to deoptimize the nmethod if RTM state was changed rtm_deopt(); } - // Check for bailouts during method entry. + // Check for bailouts during method entry or RTM state check setup. if (failing()) { if (log) log->done("parse"); C->set_default_node_notes(caller_nn); @@ -1756,7 +1757,7 @@ if (remerge == NULL) { assert(base != NULL, ""); assert(base->in(0) != NULL, "should not be xformed away"); - remerge = MergeMemNode::make(C, base->in(pnum)); + remerge = MergeMemNode::make(base->in(pnum)); gvn().set_type(remerge, Type::MEMORY); base->set_req(pnum, remerge); } @@ -2199,7 +2200,7 @@ // down below a SafePoint. // Clone the current memory state - Node* mem = MergeMemNode::make(C, map()->memory()); + Node* mem = MergeMemNode::make(map()->memory()); mem = _gvn.transform(mem); @@ -2213,7 +2214,7 @@ // Create a node for the polling address if( add_poll_param ) { - Node *polladr = ConPNode::make(C, (address)os::get_polling_page()); + Node *polladr = ConPNode::make((address)os::get_polling_page()); sfpnt->init_req(TypeFunc::Parms+0, _gvn.transform(polladr)); } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/parseHelper.cpp --- a/hotspot/src/share/vm/opto/parseHelper.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/parseHelper.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -47,7 +47,7 @@ // Get method const TypePtr* method_type = TypeMetadataPtr::make(method); - Node *method_node = _gvn.transform( ConNode::make(C, method_type) ); + Node *method_node = _gvn.transform(ConNode::make(method_type)); kill_dead_locals(); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/phaseX.cpp --- a/hotspot/src/share/vm/opto/phaseX.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/phaseX.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -615,7 +615,7 @@ // Make an idealized constant - one of ConINode, ConPNode, etc. ConNode* PhaseValues::uncached_makecon(const Type *t) { assert(t->singleton(), "must be a constant"); - ConNode* x = ConNode::make(C, t); + ConNode* x = ConNode::make(t); ConNode* k = (ConNode*)hash_find_insert(x); // Value numbering if (k == NULL) { set_type(x, t); // Missed, provide type mapping @@ -933,9 +933,32 @@ for (int i = 0; i < _verify_window_size; i++) { _verify_window[i] = NULL; } +#ifdef ASSERT + // Verify that all modified nodes are on _worklist + Unique_Node_List* modified_list = C->modified_nodes(); + while (modified_list != NULL && modified_list->size()) { + Node* n = modified_list->pop(); + if (n->outcnt() != 0 && !n->is_Con() && !_worklist.member(n)) { + n->dump(); + assert(false, "modified node is not on IGVN._worklist"); + } + } +#endif } void PhaseIterGVN::verify_PhaseIterGVN() { +#ifdef ASSERT + // Verify nodes with changed inputs. + Unique_Node_List* modified_list = C->modified_nodes(); + while (modified_list != NULL && modified_list->size()) { + Node* n = modified_list->pop(); + if (n->outcnt() != 0 && !n->is_Con()) { // skip dead and Con nodes + n->dump(); + assert(false, "modified node was not processed by IGVN.transform_old()"); + } + } +#endif + C->verify_graph_edges(); if( VerifyOpto && allow_progress() ) { // Must turn off allow_progress to enable assert and break recursion @@ -964,6 +987,14 @@ (int) _verify_counter, (int) _verify_full_passes); } } + +#ifdef ASSERT + while (modified_list->size()) { + Node* n = modified_list->pop(); + n->dump(); + assert(false, "VerifyIterativeGVN: new modified node was added"); + } +#endif } #endif /* PRODUCT */ @@ -1066,6 +1097,7 @@ Node* k = n; DEBUG_ONLY(dead_loop_check(k);) DEBUG_ONLY(bool is_new = (k->outcnt() == 0);) + C->remove_modified_node(k); Node* i = k->Ideal(this, /*can_reshape=*/true); assert(i != k || is_new || i->outcnt() > 0, "don't return dead nodes"); #ifndef PRODUCT @@ -1107,6 +1139,7 @@ DEBUG_ONLY(dead_loop_check(k);) // Try idealizing again DEBUG_ONLY(is_new = (k->outcnt() == 0);) + C->remove_modified_node(k); i = k->Ideal(this, /*can_reshape=*/true); assert(i != k || is_new || (i->outcnt() > 0), "don't return dead nodes"); #ifndef PRODUCT @@ -1259,6 +1292,7 @@ _stack.pop(); // Remove dead node from iterative worklist _worklist.remove(dead); + C->remove_modified_node(dead); // Constant node that has no out-edges and has only one in-edge from // root is usually dead. However, sometimes reshaping walk makes // it reachable by adding use edges. So, we will NOT count Con nodes @@ -1288,7 +1322,7 @@ for (DUIterator_Last imin, i = old->last_outs(imin); i >= imin; ) { Node* use = old->last_out(i); // for each use... // use might need re-hashing (but it won't if it's a new node) - bool is_in_table = _table.hash_delete( use ); + rehash_node_delayed(use); // Update use-def info as well // We remove all occurrences of old within use->in, // so as to avoid rehashing any node more than once. @@ -1300,11 +1334,6 @@ ++num_edges; } } - // Insert into GVN hash table if unique - // If a duplicate, 'use' will be cleaned up when pulled off worklist - if( is_in_table ) { - hash_find_insert(use); - } i -= num_edges; // we deleted 1 or more copies of this edge } @@ -1599,7 +1628,7 @@ if( t == Type::TOP ) { // cache my top node on the Compile instance if( C->cached_top_node() == NULL || C->cached_top_node()->in(0) == NULL ) { - C->set_cached_top_node( ConNode::make(C, Type::TOP) ); + C->set_cached_top_node(ConNode::make(Type::TOP)); set_type(C->top(), Type::TOP); } nn = C->top(); @@ -1725,7 +1754,7 @@ MachNode *m = n->as_Mach(); int deleted_count = 0; // check for peephole opportunities - MachNode *m2 = m->peephole( block, instruction_index, _regalloc, deleted_count, C ); + MachNode *m2 = m->peephole(block, instruction_index, _regalloc, deleted_count); if( m2 != NULL ) { #ifndef PRODUCT if( PrintOptoPeephole ) { diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/phaseX.hpp --- a/hotspot/src/share/vm/opto/phaseX.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/phaseX.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -311,6 +311,9 @@ const Type* limit_type) const { ShouldNotCallThis(); return NULL; } + // Delayed node rehash if this is an IGVN phase + virtual void igvn_rehash_node_delayed(Node* n) {} + #ifndef PRODUCT void dump_old2new_map() const; void dump_new( uint new_lidx ) const; @@ -488,6 +491,10 @@ _worklist.push(n); } + void igvn_rehash_node_delayed(Node* n) { + rehash_node_delayed(n); + } + // Replace ith edge of "n" with "in" void replace_input_of(Node* n, int i, Node* in) { rehash_node_delayed(n); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/rootnode.cpp --- a/hotspot/src/share/vm/opto/rootnode.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/rootnode.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -35,10 +35,12 @@ //------------------------------Ideal------------------------------------------ // Remove dead inputs Node *RootNode::Ideal(PhaseGVN *phase, bool can_reshape) { + bool modified = false; for( uint i = 1; i < req(); i++ ) { // For all inputs // Check for and remove dead inputs if( phase->type(in(i)) == Type::TOP ) { del_req(i--); // Delete TOP inputs + modified = true; } } @@ -56,7 +58,7 @@ // If we want to get the rest of the win later, we should pattern match // simple recursive call trees to closed-form solutions. - return NULL; // No further opportunities exposed + return modified ? this : NULL; } //============================================================================= diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/runtime.cpp --- a/hotspot/src/share/vm/opto/runtime.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/runtime.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -1381,11 +1381,11 @@ } NamedCounter* c; if (tag == NamedCounter::BiasedLockingCounter) { - c = new BiasedLockingNamedCounter(strdup(st.as_string())); + c = new BiasedLockingNamedCounter(st.as_string()); } else if (tag == NamedCounter::RTMLockingCounter) { - c = new RTMLockingNamedCounter(strdup(st.as_string())); + c = new RTMLockingNamedCounter(st.as_string()); } else { - c = new NamedCounter(strdup(st.as_string()), tag); + c = new NamedCounter(st.as_string(), tag); } // atomically add the new counter to the head of the list. We only diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/runtime.hpp --- a/hotspot/src/share/vm/opto/runtime.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/runtime.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -75,11 +75,17 @@ public: NamedCounter(const char *n, CounterTag tag = NoTag): - _name(n), + _name(n == NULL ? NULL : os::strdup(n)), _count(0), _next(NULL), _tag(tag) {} + ~NamedCounter() { + if (_name != NULL) { + os::free((void*)_name); + } + } + const char * name() const { return _name; } int count() const { return _count; } address addr() { return (address)&_count; } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/stringopts.cpp --- a/hotspot/src/share/vm/opto/stringopts.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/stringopts.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -1438,7 +1438,7 @@ } // Make sure the memory state is a MergeMem for parsing. if (!map->in(TypeFunc::Memory)->is_MergeMem()) { - map->set_req(TypeFunc::Memory, MergeMemNode::make(C, map->in(TypeFunc::Memory))); + map->set_req(TypeFunc::Memory, MergeMemNode::make(map->in(TypeFunc::Memory))); } jvms->set_map(map); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/subnode.cpp --- a/hotspot/src/share/vm/opto/subnode.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/subnode.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -1168,7 +1168,6 @@ Node* BoolNode::make_predicate(Node* test_value, PhaseGVN* phase) { if (test_value->is_Con()) return test_value; if (test_value->is_Bool()) return test_value; - Compile* C = phase->C; if (test_value->is_CMove() && test_value->in(CMoveNode::Condition)->is_Bool()) { BoolNode* bol = test_value->in(CMoveNode::Condition)->as_Bool(); @@ -1191,7 +1190,7 @@ //--------------------------------as_int_value--------------------------------- Node* BoolNode::as_int_value(PhaseGVN* phase) { // Inverse to make_predicate. The CMove probably boils down to a Conv2B. - Node* cmov = CMoveNode::make(phase->C, NULL, this, + Node* cmov = CMoveNode::make(NULL, this, phase->intcon(0), phase->intcon(1), TypeInt::BOOL); return phase->transform(cmov); @@ -1199,7 +1198,6 @@ //----------------------------------negate------------------------------------- BoolNode* BoolNode::negate(PhaseGVN* phase) { - Compile* C = phase->C; return new BoolNode(in(1), _test.negate()); } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/superword.cpp --- a/hotspot/src/share/vm/opto/superword.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/superword.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -1378,9 +1378,23 @@ if (n->is_Load()) { Node* ctl = n->in(MemNode::Control); Node* mem = first->in(MemNode::Memory); + SWPointer p1(n->as_Mem(), this); + // Identify the memory dependency for the new loadVector node by + // walking up through memory chain. + // This is done to give flexibility to the new loadVector node so that + // it can move above independent storeVector nodes. + while (mem->is_StoreVector()) { + SWPointer p2(mem->as_Mem(), this); + int cmp = p1.cmp(p2); + if (SWPointer::not_equal(cmp) || !SWPointer::comparable(cmp)) { + mem = mem->in(MemNode::Memory); + } else { + break; // dependent memory + } + } Node* adr = low_adr->in(MemNode::Address); const TypePtr* atyp = n->adr_type(); - vn = LoadVectorNode::make(C, opc, ctl, mem, adr, atyp, vlen, velt_basic_type(n)); + vn = LoadVectorNode::make(opc, ctl, mem, adr, atyp, vlen, velt_basic_type(n)); vlen_in_bytes = vn->as_LoadVector()->memory_size(); } else if (n->is_Store()) { // Promote value to be stored to vector @@ -1389,7 +1403,7 @@ Node* mem = first->in(MemNode::Memory); Node* adr = low_adr->in(MemNode::Address); const TypePtr* atyp = n->adr_type(); - vn = StoreVectorNode::make(C, opc, ctl, mem, adr, atyp, val, vlen); + vn = StoreVectorNode::make(opc, ctl, mem, adr, atyp, val, vlen); vlen_in_bytes = vn->as_StoreVector()->memory_size(); } else if (n->req() == 3) { // Promote operands to vector @@ -1401,7 +1415,7 @@ in1 = in2; in2 = tmp; } - vn = VectorNode::make(C, opc, in1, in2, vlen, velt_basic_type(n)); + vn = VectorNode::make(opc, in1, in2, vlen, velt_basic_type(n)); vlen_in_bytes = vn->as_Vector()->length_in_bytes(); } else { ShouldNotReachHere(); @@ -1450,11 +1464,11 @@ if (t != NULL && t->is_con()) { juint shift = t->get_con(); if (shift > mask) { // Unsigned cmp - cnt = ConNode::make(C, TypeInt::make(shift & mask)); + cnt = ConNode::make(TypeInt::make(shift & mask)); } } else { if (t == NULL || t->_lo < 0 || t->_hi > (int)mask) { - cnt = ConNode::make(C, TypeInt::make(mask)); + cnt = ConNode::make(TypeInt::make(mask)); _igvn.register_new_node_with_optimizer(cnt); cnt = new AndINode(opd, cnt); _igvn.register_new_node_with_optimizer(cnt); @@ -1462,7 +1476,7 @@ } assert(opd->bottom_type()->isa_int(), "int type only"); // Move non constant shift count into vector register. - cnt = VectorNode::shift_count(C, p0, cnt, vlen, velt_basic_type(p0)); + cnt = VectorNode::shift_count(p0, cnt, vlen, velt_basic_type(p0)); } if (cnt != opd) { _igvn.register_new_node_with_optimizer(cnt); @@ -1475,7 +1489,7 @@ // p0's vector. Use p0's type because size of operand's container in // vector should match p0's size regardless operand's size. const Type* p0_t = velt_type(p0); - VectorNode* vn = VectorNode::scalar2vector(_phase->C, opd, vlen, p0_t); + VectorNode* vn = VectorNode::scalar2vector(opd, vlen, p0_t); _igvn.register_new_node_with_optimizer(vn); _phase->set_ctrl(vn, _phase->get_ctrl(opd)); @@ -1490,7 +1504,7 @@ // Insert pack operation BasicType bt = velt_basic_type(p0); - PackNode* pk = PackNode::make(_phase->C, opd, vlen, bt); + PackNode* pk = PackNode::make(opd, vlen, bt); DEBUG_ONLY( const BasicType opd_bt = opd->bottom_type()->basic_type(); ) for (uint i = 1; i < vlen; i++) { @@ -1546,7 +1560,7 @@ _igvn.hash_delete(def); int def_pos = alignment(def) / data_size(def); - Node* ex = ExtractNode::make(_phase->C, def, def_pos, velt_basic_type(def)); + Node* ex = ExtractNode::make(def, def_pos, velt_basic_type(def)); _igvn.register_new_node_with_optimizer(ex); _phase->set_ctrl(ex, _phase->get_ctrl(def)); _igvn.replace_input_of(use, idx, ex); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/type.cpp --- a/hotspot/src/share/vm/opto/type.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/type.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -265,7 +265,7 @@ // locking. Arena* save = current->type_arena(); - Arena* shared_type_arena = new (mtCompiler)Arena(); + Arena* shared_type_arena = new (mtCompiler)Arena(mtCompiler); current->set_type_arena(shared_type_arena); _shared_type_dict = @@ -5087,11 +5087,11 @@ // Dump Function Type #ifndef PRODUCT void TypeFunc::dump2( Dict &d, uint depth, outputStream *st ) const { - if( _range->_cnt <= Parms ) + if( _range->cnt() <= Parms ) st->print("void"); else { uint i; - for (i = Parms; i < _range->_cnt-1; i++) { + for (i = Parms; i < _range->cnt()-1; i++) { _range->field_at(i)->dump2(d,depth,st); st->print("/"); } @@ -5104,9 +5104,9 @@ return; } d.Insert((void*)this,(void*)this); // Stop recursion - if (Parms < _domain->_cnt) + if (Parms < _domain->cnt()) _domain->field_at(Parms)->dump2(d,depth-1,st); - for (uint i = Parms+1; i < _domain->_cnt; i++) { + for (uint i = Parms+1; i < _domain->cnt(); i++) { st->print(", "); _domain->field_at(i)->dump2(d,depth-1,st); } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/type.hpp --- a/hotspot/src/share/vm/opto/type.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/type.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -609,16 +609,16 @@ // signature types. class TypeTuple : public Type { TypeTuple( uint cnt, const Type **fields ) : Type(Tuple), _cnt(cnt), _fields(fields) { } + + const uint _cnt; // Count of fields + const Type ** const _fields; // Array of field types + public: virtual bool eq( const Type *t ) const; virtual int hash() const; // Type specific hashing virtual bool singleton(void) const; // TRUE if type is a singleton virtual bool empty(void) const; // TRUE if type is vacuous -public: - const uint _cnt; // Count of fields - const Type ** const _fields; // Array of field types - // Accessors: uint cnt() const { return _cnt; } const Type* field_at(uint i) const { @@ -1447,6 +1447,10 @@ virtual int hash() const; // Type specific hashing virtual bool singleton(void) const; // TRUE if type is a singleton virtual bool empty(void) const; // TRUE if type is vacuous + + const TypeTuple* const _domain; // Domain of inputs + const TypeTuple* const _range; // Range of results + public: // Constants are shared among ADLC and VM enum { Control = AdlcVMDeps::Control, @@ -1457,8 +1461,6 @@ Parms = AdlcVMDeps::Parms }; - const TypeTuple* const _domain; // Domain of inputs - const TypeTuple* const _range; // Range of results // Accessors: const TypeTuple* domain() const { return _domain; } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/vectornode.cpp --- a/hotspot/src/share/vm/opto/vectornode.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/vectornode.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -245,7 +245,7 @@ } // Return the vector version of a scalar operation node. -VectorNode* VectorNode::make(Compile* C, int opc, Node* n1, Node* n2, uint vlen, BasicType bt) { +VectorNode* VectorNode::make(int opc, Node* n1, Node* n2, uint vlen, BasicType bt) { const TypeVect* vt = TypeVect::make(bt, vlen); int vopc = VectorNode::opcode(opc, bt); // This method should not be called for unimplemented vectors. @@ -299,7 +299,7 @@ } // Scalar promotion -VectorNode* VectorNode::scalar2vector(Compile* C, Node* s, uint vlen, const Type* opd_t) { +VectorNode* VectorNode::scalar2vector(Node* s, uint vlen, const Type* opd_t) { BasicType bt = opd_t->array_element_basic_type(); const TypeVect* vt = opd_t->singleton() ? TypeVect::make(opd_t, vlen) : TypeVect::make(bt, vlen); @@ -323,7 +323,7 @@ return NULL; } -VectorNode* VectorNode::shift_count(Compile* C, Node* shift, Node* cnt, uint vlen, BasicType bt) { +VectorNode* VectorNode::shift_count(Node* shift, Node* cnt, uint vlen, BasicType bt) { assert(VectorNode::is_shift(shift) && !cnt->is_Con(), "only variable shift count"); // Match shift count type with shift vector type. const TypeVect* vt = TypeVect::make(bt, vlen); @@ -342,7 +342,7 @@ } // Return initial Pack node. Additional operands added with add_opd() calls. -PackNode* PackNode::make(Compile* C, Node* s, uint vlen, BasicType bt) { +PackNode* PackNode::make(Node* s, uint vlen, BasicType bt) { const TypeVect* vt = TypeVect::make(bt, vlen); switch (bt) { case T_BOOLEAN: @@ -365,18 +365,18 @@ } // Create a binary tree form for Packs. [lo, hi) (half-open) range -PackNode* PackNode::binary_tree_pack(Compile* C, int lo, int hi) { +PackNode* PackNode::binary_tree_pack(int lo, int hi) { int ct = hi - lo; assert(is_power_of_2(ct), "power of 2"); if (ct == 2) { - PackNode* pk = PackNode::make(C, in(lo), 2, vect_type()->element_basic_type()); + PackNode* pk = PackNode::make(in(lo), 2, vect_type()->element_basic_type()); pk->add_opd(in(lo+1)); return pk; } else { int mid = lo + ct/2; - PackNode* n1 = binary_tree_pack(C, lo, mid); - PackNode* n2 = binary_tree_pack(C, mid, hi ); + PackNode* n1 = binary_tree_pack(lo, mid); + PackNode* n2 = binary_tree_pack(mid, hi ); BasicType bt = n1->vect_type()->element_basic_type(); assert(bt == n2->vect_type()->element_basic_type(), "should be the same"); @@ -402,23 +402,23 @@ } // Return the vector version of a scalar load node. -LoadVectorNode* LoadVectorNode::make(Compile* C, int opc, Node* ctl, Node* mem, +LoadVectorNode* LoadVectorNode::make(int opc, Node* ctl, Node* mem, Node* adr, const TypePtr* atyp, uint vlen, BasicType bt) { const TypeVect* vt = TypeVect::make(bt, vlen); return new LoadVectorNode(ctl, mem, adr, atyp, vt); } // Return the vector version of a scalar store node. -StoreVectorNode* StoreVectorNode::make(Compile* C, int opc, Node* ctl, Node* mem, +StoreVectorNode* StoreVectorNode::make(int opc, Node* ctl, Node* mem, Node* adr, const TypePtr* atyp, Node* val, uint vlen) { return new StoreVectorNode(ctl, mem, adr, atyp, val); } // Extract a scalar element of vector. -Node* ExtractNode::make(Compile* C, Node* v, uint position, BasicType bt) { +Node* ExtractNode::make(Node* v, uint position, BasicType bt) { assert((int)position < Matcher::max_vector_size(bt), "pos in range"); - ConINode* pos = ConINode::make(C, (int)position); + ConINode* pos = ConINode::make((int)position); switch (bt) { case T_BOOLEAN: return new ExtractUBNode(v, pos); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/opto/vectornode.hpp --- a/hotspot/src/share/vm/opto/vectornode.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/opto/vectornode.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -52,9 +52,9 @@ virtual uint ideal_reg() const { return Matcher::vector_ideal_reg(vect_type()->length_in_bytes()); } - static VectorNode* scalar2vector(Compile* C, Node* s, uint vlen, const Type* opd_t); - static VectorNode* shift_count(Compile* C, Node* shift, Node* cnt, uint vlen, BasicType bt); - static VectorNode* make(Compile* C, int opc, Node* n1, Node* n2, uint vlen, BasicType bt); + static VectorNode* scalar2vector(Node* s, uint vlen, const Type* opd_t); + static VectorNode* shift_count(Node* shift, Node* cnt, uint vlen, BasicType bt); + static VectorNode* make(int opc, Node* n1, Node* n2, uint vlen, BasicType bt); static int opcode(int opc, BasicType bt); static bool implemented(int opc, uint vlen, BasicType bt); @@ -371,7 +371,7 @@ virtual int store_Opcode() const { return Op_StoreVector; } - static LoadVectorNode* make(Compile* C, int opc, Node* ctl, Node* mem, + static LoadVectorNode* make(int opc, Node* ctl, Node* mem, Node* adr, const TypePtr* atyp, uint vlen, BasicType bt); }; @@ -394,7 +394,7 @@ virtual BasicType memory_type() const { return T_VOID; } virtual int memory_size() const { return vect_type()->length_in_bytes(); } - static StoreVectorNode* make(Compile* C, int opc, Node* ctl, Node* mem, + static StoreVectorNode* make(int opc, Node* ctl, Node* mem, Node* adr, const TypePtr* atyp, Node* val, uint vlen); }; @@ -465,9 +465,9 @@ } // Create a binary tree form for Packs. [lo, hi) (half-open) range - PackNode* binary_tree_pack(Compile* C, int lo, int hi); + PackNode* binary_tree_pack(int lo, int hi); - static PackNode* make(Compile* C, Node* s, uint vlen, BasicType bt); + static PackNode* make(Node* s, uint vlen, BasicType bt); }; //------------------------------PackBNode-------------------------------------- @@ -552,7 +552,7 @@ virtual int Opcode() const; uint pos() const { return in(2)->get_int(); } - static Node* make(Compile* C, Node* v, uint position, BasicType bt); + static Node* make(Node* v, uint position, BasicType bt); }; //------------------------------ExtractBNode----------------------------------- diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/precompiled/precompiled.hpp --- a/hotspot/src/share/vm/precompiled/precompiled.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/precompiled/precompiled.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -222,10 +222,17 @@ # include "runtime/vmThread.hpp" # include "runtime/vm_operations.hpp" # include "runtime/vm_version.hpp" +# include "services/allocationSite.hpp" # include "services/lowMemoryDetector.hpp" +# include "services/mallocTracker.hpp" +# include "services/memBaseline.hpp" # include "services/memoryPool.hpp" # include "services/memoryService.hpp" # include "services/memoryUsage.hpp" +# include "services/memReporter.hpp" +# include "services/memTracker.hpp" +# include "services/nmtCommon.hpp" +# include "services/virtualMemoryTracker.hpp" # include "utilities/accessFlags.hpp" # include "utilities/array.hpp" # include "utilities/bitMap.hpp" @@ -240,6 +247,7 @@ # include "utilities/hashtable.hpp" # include "utilities/histogram.hpp" # include "utilities/macros.hpp" +# include "utilities/nativeCallStack.hpp" # include "utilities/numberSeq.hpp" # include "utilities/ostream.hpp" # include "utilities/preserveException.hpp" diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/prims/jni.cpp --- a/hotspot/src/share/vm/prims/jni.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/prims/jni.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -74,6 +74,7 @@ #include "runtime/signature.hpp" #include "runtime/thread.inline.hpp" #include "runtime/vm_operations.hpp" +#include "services/memTracker.hpp" #include "services/runtimeService.hpp" #include "trace/tracing.hpp" #include "utilities/defaultStream.hpp" @@ -2697,6 +2698,7 @@ if (bad_address != NULL) { os::protect_memory(bad_address, size, os::MEM_PROT_READ, /*is_committed*/false); + MemTracker::record_virtual_memory_type((void*)bad_address, mtInternal); } } return bad_address; @@ -3857,6 +3859,7 @@ void TestKlass_test(); void TestBitMap_test(); void TestAsUtf8(); +void Test_linked_list(); #if INCLUDE_ALL_GCS void TestOldFreeSpaceCalculation_test(); void TestG1BiasedArray_test(); @@ -3887,6 +3890,7 @@ run_unit_test(TestBitMap_test()); run_unit_test(TestAsUtf8()); run_unit_test(ObjectMonitor::sanity_checks()); + run_unit_test(Test_linked_list()); #if INCLUDE_VM_STRUCTS run_unit_test(VMStructs::test()); #endif diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/prims/jvmtiManageCapabilities.cpp --- a/hotspot/src/share/vm/prims/jvmtiManageCapabilities.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/prims/jvmtiManageCapabilities.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -316,6 +316,7 @@ avail.can_generate_frame_pop_events || avail.can_generate_method_entry_events || avail.can_generate_method_exit_events; +#ifdef ZERO bool enter_all_methods = interp_events || avail.can_generate_breakpoint_events; @@ -324,6 +325,7 @@ UseFastEmptyMethods = false; UseFastAccessorMethods = false; } +#endif // ZERO if (avail.can_generate_breakpoint_events) { RewriteFrequentPairs = false; diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/prims/whitebox.cpp --- a/hotspot/src/share/vm/prims/whitebox.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/prims/whitebox.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -52,8 +52,10 @@ #include "gc_implementation/g1/heapRegionRemSet.hpp" #endif // INCLUDE_ALL_GCS -#ifdef INCLUDE_NMT +#if INCLUDE_NMT +#include "services/mallocSiteTable.hpp" #include "services/memTracker.hpp" +#include "utilities/nativeCallStack.hpp" #endif // INCLUDE_NMT #include "compiler/compileBroker.hpp" @@ -255,12 +257,16 @@ // NMT picks it up correctly WB_ENTRY(jlong, WB_NMTMalloc(JNIEnv* env, jobject o, jlong size)) jlong addr = 0; + addr = (jlong)(uintptr_t)os::malloc(size, mtTest); + return addr; +WB_END - if (MemTracker::is_on() && !MemTracker::shutdown_in_progress()) { - addr = (jlong)(uintptr_t)os::malloc(size, mtTest); - } - - return addr; +// Alloc memory with pseudo call stack. The test can create psudo malloc +// allocation site to stress the malloc tracking. +WB_ENTRY(jlong, WB_NMTMallocWithPseudoStack(JNIEnv* env, jobject o, jlong size, jint pseudo_stack)) + address pc = (address)(size_t)pseudo_stack; + NativeCallStack stack(&pc, 1); + return (jlong)os::malloc(size, mtTest, stack); WB_END // Free the memory allocated by NMTAllocTest @@ -271,10 +277,8 @@ WB_ENTRY(jlong, WB_NMTReserveMemory(JNIEnv* env, jobject o, jlong size)) jlong addr = 0; - if (MemTracker::is_on() && !MemTracker::shutdown_in_progress()) { addr = (jlong)(uintptr_t)os::reserve_memory(size); MemTracker::record_virtual_memory_type((address)addr, mtTest); - } return addr; WB_END @@ -293,20 +297,20 @@ os::release_memory((char *)(uintptr_t)addr, size); WB_END -// Block until the current generation of NMT data to be merged, used to reliably test the NMT feature -WB_ENTRY(jboolean, WB_NMTWaitForDataMerge(JNIEnv* env)) - - if (!MemTracker::is_on() || MemTracker::shutdown_in_progress()) { - return false; - } - - return MemTracker::wbtest_wait_for_data_merge(); +WB_ENTRY(jboolean, WB_NMTIsDetailSupported(JNIEnv* env)) + return MemTracker::tracking_level() == NMT_detail; WB_END -WB_ENTRY(jboolean, WB_NMTIsDetailSupported(JNIEnv* env)) - return MemTracker::tracking_level() == MemTracker::NMT_detail; +WB_ENTRY(void, WB_NMTOverflowHashBucket(JNIEnv* env, jobject o, jlong num)) + address pc = (address)1; + for (jlong index = 0; index < num; index ++) { + NativeCallStack stack(&pc, 1); + os::malloc(0, mtTest, stack); + pc += MallocSiteTable::hash_buckets(); + } WB_END + #endif // INCLUDE_NMT static jmethodID reflected_method_to_jmid(JavaThread* thread, JNIEnv* env, jobject method) { @@ -597,6 +601,15 @@ return NULL; WB_END +WB_ENTRY(jobject, WB_GetSizeTVMFlag(JNIEnv* env, jobject o, jstring name)) + uintx result; + if (GetVMFlag (thread, env, name, &result, &CommandLineFlags::size_tAt)) { + ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI + return longBox(thread, env, result); + } + return NULL; +WB_END + WB_ENTRY(jobject, WB_GetDoubleVMFlag(JNIEnv* env, jobject o, jstring name)) double result; if (GetVMFlag (thread, env, name, &result, &CommandLineFlags::doubleAt)) { @@ -637,6 +650,11 @@ SetVMFlag (thread, env, name, &result, &CommandLineFlags::uint64_tAtPut); WB_END +WB_ENTRY(void, WB_SetSizeTVMFlag(JNIEnv* env, jobject o, jstring name, jlong value)) + size_t result = value; + SetVMFlag (thread, env, name, &result, &CommandLineFlags::size_tAtPut); +WB_END + WB_ENTRY(void, WB_SetDoubleVMFlag(JNIEnv* env, jobject o, jstring name, jdouble value)) double result = value; SetVMFlag (thread, env, name, &result, &CommandLineFlags::doubleAtPut); @@ -843,12 +861,13 @@ #endif // INCLUDE_ALL_GCS #if INCLUDE_NMT {CC"NMTMalloc", CC"(J)J", (void*)&WB_NMTMalloc }, + {CC"NMTMallocWithPseudoStack", CC"(JI)J", (void*)&WB_NMTMallocWithPseudoStack}, {CC"NMTFree", CC"(J)V", (void*)&WB_NMTFree }, {CC"NMTReserveMemory", CC"(J)J", (void*)&WB_NMTReserveMemory }, {CC"NMTCommitMemory", CC"(JJ)V", (void*)&WB_NMTCommitMemory }, {CC"NMTUncommitMemory", CC"(JJ)V", (void*)&WB_NMTUncommitMemory }, {CC"NMTReleaseMemory", CC"(JJ)V", (void*)&WB_NMTReleaseMemory }, - {CC"NMTWaitForDataMerge", CC"()Z", (void*)&WB_NMTWaitForDataMerge}, + {CC"NMTOverflowHashBucket", CC"(J)V", (void*)&WB_NMTOverflowHashBucket}, {CC"NMTIsDetailSupported",CC"()Z", (void*)&WB_NMTIsDetailSupported}, #endif // INCLUDE_NMT {CC"deoptimizeAll", CC"()V", (void*)&WB_DeoptimizeAll }, @@ -880,6 +899,7 @@ {CC"setIntxVMFlag", CC"(Ljava/lang/String;J)V",(void*)&WB_SetIntxVMFlag}, {CC"setUintxVMFlag", CC"(Ljava/lang/String;J)V",(void*)&WB_SetUintxVMFlag}, {CC"setUint64VMFlag", CC"(Ljava/lang/String;J)V",(void*)&WB_SetUint64VMFlag}, + {CC"setSizeTVMFlag", CC"(Ljava/lang/String;J)V",(void*)&WB_SetSizeTVMFlag}, {CC"setDoubleVMFlag", CC"(Ljava/lang/String;D)V",(void*)&WB_SetDoubleVMFlag}, {CC"setStringVMFlag", CC"(Ljava/lang/String;Ljava/lang/String;)V", (void*)&WB_SetStringVMFlag}, @@ -891,6 +911,8 @@ (void*)&WB_GetUintxVMFlag}, {CC"getUint64VMFlag", CC"(Ljava/lang/String;)Ljava/lang/Long;", (void*)&WB_GetUint64VMFlag}, + {CC"getSizeTVMFlag", CC"(Ljava/lang/String;)Ljava/lang/Long;", + (void*)&WB_GetSizeTVMFlag}, {CC"getDoubleVMFlag", CC"(Ljava/lang/String;)Ljava/lang/Double;", (void*)&WB_GetDoubleVMFlag}, {CC"getStringVMFlag", CC"(Ljava/lang/String;)Ljava/lang/String;", diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/runtime/arguments.cpp --- a/hotspot/src/share/vm/runtime/arguments.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/runtime/arguments.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -300,6 +300,11 @@ { "UseNewReflection", JDK_Version::jdk(9), JDK_Version::jdk(10) }, { "ReflectionWrapResolutionErrors",JDK_Version::jdk(9), JDK_Version::jdk(10) }, { "VerifyReflectionBytecodes", JDK_Version::jdk(9), JDK_Version::jdk(10) }, + { "AutoShutdownNMT", JDK_Version::jdk(9), JDK_Version::jdk(10) }, +#ifndef ZERO + { "UseFastAccessorMethods", JDK_Version::jdk(9), JDK_Version::jdk(10) }, + { "UseFastEmptyMethods", JDK_Version::jdk(9), JDK_Version::jdk(10) }, +#endif // ZERO { NULL, JDK_Version(0), JDK_Version(0) } }; @@ -686,6 +691,10 @@ if (!is_neg && CommandLineFlags::uint64_tAtPut(name, &uint64_t_v, origin)) { return true; } + size_t size_t_v = (size_t) v; + if (!is_neg && CommandLineFlags::size_tAtPut(name, &size_t_v, origin)) { + return true; + } return false; } @@ -799,7 +808,7 @@ } else { *bldarray = REALLOC_C_HEAP_ARRAY(char*, *bldarray, new_count, mtInternal); } - (*bldarray)[*count] = strdup(arg); + (*bldarray)[*count] = os::strdup_check_oom(arg); *count = new_count; } @@ -1070,16 +1079,6 @@ UseCompiler = true; UseLoopCounter = true; -#ifndef ZERO - // Turn these off for mixed and comp. Leave them on for Zero. - if (FLAG_IS_DEFAULT(UseFastAccessorMethods)) { - UseFastAccessorMethods = (mode == _int); - } - if (FLAG_IS_DEFAULT(UseFastEmptyMethods)) { - UseFastEmptyMethods = (mode == _int); - } -#endif - // Default values may be platform/compiler dependent - // use the saved values ClipInlining = Arguments::_ClipInlining; @@ -1431,6 +1430,22 @@ (int)ObjectAlignmentInBytes, os::vm_page_size()); return false; } + if(SurvivorAlignmentInBytes == 0) { + SurvivorAlignmentInBytes = ObjectAlignmentInBytes; + } else { + if (!is_power_of_2(SurvivorAlignmentInBytes)) { + jio_fprintf(defaultStream::error_stream(), + "error: SurvivorAlignmentInBytes=%d must be power of 2\n", + (int)SurvivorAlignmentInBytes); + return false; + } + if (SurvivorAlignmentInBytes < ObjectAlignmentInBytes) { + jio_fprintf(defaultStream::error_stream(), + "error: SurvivorAlignmentInBytes=%d must be greater than ObjectAlignmentInBytes=%d \n", + (int)SurvivorAlignmentInBytes, (int)ObjectAlignmentInBytes); + return false; + } + } return true; } @@ -1869,7 +1884,7 @@ } void Arguments::process_java_launcher_argument(const char* launcher, void* extra_info) { - _sun_java_launcher = strdup(launcher); + _sun_java_launcher = os::strdup_check_oom(launcher); } bool Arguments::created_by_java_launcher() { @@ -2372,7 +2387,7 @@ if (PrintNMTStatistics) { #if INCLUDE_NMT - if (MemTracker::tracking_level() == MemTracker::NMT_off) { + if (MemTracker::tracking_level() == NMT_off) { #endif // INCLUDE_NMT warning("PrintNMTStatistics is disabled, because native memory tracking is not enabled"); PrintNMTStatistics = false; @@ -2979,7 +2994,7 @@ // Redirect GC output to the file. -Xloggc: // ostream_init_log(), when called will use this filename // to initialize a fileStream. - _gc_log_filename = strdup(tail); + _gc_log_filename = os::strdup_check_oom(tail); if (!is_filename_valid(_gc_log_filename)) { jio_fprintf(defaultStream::output_stream(), "Invalid file name for use with -Xloggc: Filename can only contain the " @@ -3582,15 +3597,24 @@ CommandLineFlags::printFlags(tty, false); vm_exit(0); } +#if INCLUDE_NMT if (match_option(option, "-XX:NativeMemoryTracking", &tail)) { -#if INCLUDE_NMT - MemTracker::init_tracking_options(tail); -#else - jio_fprintf(defaultStream::error_stream(), - "Native Memory Tracking is not supported in this VM\n"); - return JNI_ERR; + // The launcher did not setup nmt environment variable properly. +// if (!MemTracker::check_launcher_nmt_support(tail)) { +// warning("Native Memory Tracking did not setup properly, using wrong launcher?"); +// } + + // Verify if nmt option is valid. + if (MemTracker::verify_nmt_option()) { + // Late initialization, still in single-threaded mode. + if (MemTracker::tracking_level() >= NMT_summary) { + MemTracker::init(); + } + } else { + vm_exit_during_initialization("Syntax error, expecting -XX:NativeMemoryTracking=[off|summary|detail]", NULL); + } + } #endif - } #ifndef PRODUCT diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/runtime/deoptimization.cpp --- a/hotspot/src/share/vm/runtime/deoptimization.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/runtime/deoptimization.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -661,7 +661,7 @@ (iframe->interpreter_frame_expression_stack_size() == (next_mask_expression_stack_size - top_frame_expression_stack_adjustment))) || (is_top_frame && (exec_mode == Unpack_exception) && iframe->interpreter_frame_expression_stack_size() == 0) || - (is_top_frame && (exec_mode == Unpack_uncommon_trap || exec_mode == Unpack_reexecute) && + (is_top_frame && (exec_mode == Unpack_uncommon_trap || exec_mode == Unpack_reexecute || el->should_reexecute()) && (iframe->interpreter_frame_expression_stack_size() == mask.expression_stack_size() + cur_invoke_parameter_size)) )) { ttyLocker ttyl; diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/runtime/fprofiler.cpp --- a/hotspot/src/share/vm/runtime/fprofiler.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/runtime/fprofiler.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -629,10 +629,16 @@ } vmNode(const char* name, const TickPosition where) : ProfilerNode() { - _name = name; + _name = os::strdup(name); update(where); } + ~vmNode() { + if (_name != NULL) { + os::free((void*)_name); + } + } + const char *name() const { return _name; } bool is_compiled() const { return true; } @@ -784,7 +790,7 @@ assert(index >= 0, "Must be positive"); // Note that we call strdup below since the symbol may be resource allocated if (!table[index]) { - table[index] = new (this) vmNode(os::strdup(name), where); + table[index] = new (this) vmNode(name, where); } else { ProfilerNode* prev = table[index]; for(ProfilerNode* node = prev; node; node = node->next()) { @@ -794,7 +800,7 @@ } prev = node; } - prev->set_next(new (this) vmNode(os::strdup(name), where)); + prev->set_next(new (this) vmNode(name, where)); } } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/runtime/frame.cpp --- a/hotspot/src/share/vm/runtime/frame.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/runtime/frame.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -407,7 +407,8 @@ address frame::interpreter_frame_bcp() const { assert(is_interpreted_frame(), "interpreted frame expected"); - return (address)*interpreter_frame_bcp_addr(); + address bcp = (address)*interpreter_frame_bcp_addr(); + return interpreter_frame_method()->bcp_from(bcp); } void frame::interpreter_frame_set_bcp(address bcp) { diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/runtime/globals.cpp --- a/hotspot/src/share/vm/runtime/globals.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/runtime/globals.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -131,6 +131,19 @@ *((uint64_t*) _addr) = value; } +bool Flag::is_size_t() const { + return strcmp(_type, "size_t") == 0; +} + +size_t Flag::get_size_t() const { + return *((size_t*) _addr); +} + +void Flag::set_size_t(size_t value) { + check_writable(); + *((size_t*) _addr) = value; +} + bool Flag::is_double() const { return strcmp(_type, "double") == 0; } @@ -306,6 +319,9 @@ if (is_uint64_t()) { st->print("%-16lu", get_uint64_t()); } + if (is_size_t()) { + st->print(SIZE_FORMAT_W(-16), get_size_t()); + } if (is_double()) { st->print("%-16f", get_double()); } @@ -395,6 +411,8 @@ st->print("-XX:%s=" UINTX_FORMAT, _name, get_uintx()); } else if (is_uint64_t()) { st->print("-XX:%s=" UINT64_FORMAT, _name, get_uint64_t()); + } else if (is_size_t()) { + st->print("-XX:%s=" SIZE_FORMAT, _name, get_size_t()); } else if (is_double()) { st->print("-XX:%s=%f", _name, get_double()); } else if (is_ccstr()) { @@ -723,6 +741,34 @@ faddr->set_origin(origin); } +bool CommandLineFlags::size_tAt(const char* name, size_t len, size_t* value) { + Flag* result = Flag::find_flag(name, len); + if (result == NULL) return false; + if (!result->is_size_t()) return false; + *value = result->get_size_t(); + return true; +} + +bool CommandLineFlags::size_tAtPut(const char* name, size_t len, size_t* value, Flag::Flags origin) { + Flag* result = Flag::find_flag(name, len); + if (result == NULL) return false; + if (!result->is_size_t()) return false; + size_t old_value = result->get_size_t(); + trace_flag_changed(name, old_value, *value, origin); + result->set_size_t(*value); + *value = old_value; + result->set_origin(origin); + return true; +} + +void CommandLineFlagsEx::size_tAtPut(CommandLineFlagWithType flag, size_t value, Flag::Flags origin) { + Flag* faddr = address_of_flag(flag); + guarantee(faddr != NULL && faddr->is_size_t(), "wrong flag type"); + trace_flag_changed(faddr->_name, faddr->get_size_t(), value, origin); + faddr->set_size_t(value); + faddr->set_origin(origin); +} + bool CommandLineFlags::doubleAt(const char* name, size_t len, double* value) { Flag* result = Flag::find_flag(name, len); if (result == NULL) return false; diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/runtime/globals.hpp --- a/hotspot/src/share/vm/runtime/globals.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/runtime/globals.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -275,6 +275,10 @@ uint64_t get_uint64_t() const; void set_uint64_t(uint64_t value); + bool is_size_t() const; + size_t get_size_t() const; + void set_size_t(size_t value); + bool is_double() const; double get_double() const; void set_double(double value); @@ -350,7 +354,6 @@ ~UIntFlagSetting() { *flag = val; } }; - class DoubleFlagSetting { double val; double* flag; @@ -359,6 +362,14 @@ ~DoubleFlagSetting() { *flag = val; } }; +class SizeTFlagSetting { + size_t val; + size_t* flag; + public: + SizeTFlagSetting(size_t& fl, size_t newValue) { flag = &fl; val = fl; fl = newValue; } + ~SizeTFlagSetting() { *flag = val; } +}; + class CommandLineFlags { public: @@ -377,6 +388,11 @@ static bool uintxAtPut(const char* name, size_t len, uintx* value, Flag::Flags origin); static bool uintxAtPut(const char* name, uintx* value, Flag::Flags origin) { return uintxAtPut(name, strlen(name), value, origin); } + static bool size_tAt(const char* name, size_t len, size_t* value); + static bool size_tAt(const char* name, size_t* value) { return size_tAt(name, strlen(name), value); } + static bool size_tAtPut(const char* name, size_t len, size_t* value, Flag::Flags origin); + static bool size_tAtPut(const char* name, size_t* value, Flag::Flags origin) { return size_tAtPut(name, strlen(name), value, origin); } + static bool uint64_tAt(const char* name, size_t len, uint64_t* value); static bool uint64_tAt(const char* name, uint64_t* value) { return uint64_tAt(name, strlen(name), value); } static bool uint64_tAtPut(const char* name, size_t len, uint64_t* value, Flag::Flags origin); @@ -945,11 +961,6 @@ diagnostic(bool, PrintNMTStatistics, false, \ "Print native memory tracking summary data if it is on") \ \ - diagnostic(bool, AutoShutdownNMT, true, \ - "Automatically shutdown native memory tracking under stress " \ - "situations. When set to false, native memory tracking tries to " \ - "stay alive at the expense of JVM performance") \ - \ diagnostic(bool, LogCompilation, false, \ "Log compilation activity in detail to LogFile") \ \ @@ -1078,6 +1089,9 @@ product(bool, ClassUnloading, true, \ "Do unloading of classes") \ \ + product(bool, ClassUnloadingWithConcurrentMark, true, \ + "Do unloading of classes with a concurrent marking cycle") \ + \ develop(bool, DisableStartThread, false, \ "Disable starting of additional Java threads " \ "(for debugging only)") \ @@ -2786,12 +2800,6 @@ product(bool, UseLoopCounter, true, \ "Increment invocation counter on backward branch") \ \ - product(bool, UseFastEmptyMethods, true, \ - "Use fast method entry code for empty methods") \ - \ - product(bool, UseFastAccessorMethods, true, \ - "Use fast method entry code for accessor methods") \ - \ product_pd(bool, UseOnStackReplacement, \ "Use on stack replacement, calls runtime if invoc. counter " \ "overflows in loop") \ @@ -3871,14 +3879,17 @@ product(bool, PrintGCCause, true, \ "Include GC cause in GC logging") \ \ + experimental(intx, SurvivorAlignmentInBytes, 0, \ + "Default survivor space alignment in bytes") \ + \ product(bool , AllowNonVirtualCalls, false, \ "Obey the ACC_SUPER flag and allow invokenonvirtual calls") \ \ diagnostic(ccstr, SharedArchiveFile, NULL, \ "Override the default location of the CDS archive file") \ \ - experimental(uintx, ArrayAllocatorMallocLimit, \ - SOLARIS_ONLY(64*K) NOT_SOLARIS(max_uintx), \ + experimental(size_t, ArrayAllocatorMallocLimit, \ + SOLARIS_ONLY(64*K) NOT_SOLARIS((size_t)-1), \ "Allocation less than this value will be allocated " \ "using malloc. Larger allocations will use mmap.") \ \ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/runtime/globals_extension.hpp --- a/hotspot/src/share/vm/runtime/globals_extension.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/runtime/globals_extension.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -200,6 +200,7 @@ static void intxAtPut(CommandLineFlagWithType flag, intx value, Flag::Flags origin); static void uintxAtPut(CommandLineFlagWithType flag, uintx value, Flag::Flags origin); static void uint64_tAtPut(CommandLineFlagWithType flag, uint64_t value, Flag::Flags origin); + static void size_tAtPut(CommandLineFlagWithType flag, size_t value, Flag::Flags origin); static void doubleAtPut(CommandLineFlagWithType flag, double value, Flag::Flags origin); // Contract: Flag will make private copy of the incoming value static void ccstrAtPut(CommandLineFlagWithType flag, ccstr value, Flag::Flags origin); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/runtime/handles.hpp --- a/hotspot/src/share/vm/runtime/handles.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/runtime/handles.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -227,7 +227,7 @@ HandleArea* _prev; // link to outer (older) area public: // Constructor - HandleArea(HandleArea* prev) : Arena(Chunk::tiny_size) { + HandleArea(HandleArea* prev) : Arena(mtThread, Chunk::tiny_size) { debug_only(_handle_mark_nesting = 0); debug_only(_no_handle_mark_nesting = 0); _prev = prev; diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/runtime/init.cpp --- a/hotspot/src/share/vm/runtime/init.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/runtime/init.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -34,8 +34,10 @@ #include "runtime/init.hpp" #include "runtime/safepoint.hpp" #include "runtime/sharedRuntime.hpp" +#include "services/memTracker.hpp" #include "utilities/macros.hpp" + // Initialization done by VM thread in vm_init_globals() void check_ThreadShadow(); void eventlog_init(); @@ -131,6 +133,12 @@ javaClasses_init(); // must happen after vtable initialization stubRoutines_init2(); // note: StubRoutines need 2-phase init +#if INCLUDE_NMT + // Solaris stack is walkable only after stubRoutines are set up. + // On Other platforms, the stack is always walkable. + NMT_stack_walkable = true; +#endif // INCLUDE_NMT + // All the flags that get adjusted by VM_Version_init and os::init_2 // have been set so dump the flags now. if (PrintFlagsFinal) { diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/runtime/java.cpp --- a/hotspot/src/share/vm/runtime/java.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/runtime/java.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -57,7 +57,6 @@ #include "runtime/thread.inline.hpp" #include "runtime/timer.hpp" #include "runtime/vm_operations.hpp" -#include "services/memReporter.hpp" #include "services/memTracker.hpp" #include "trace/tracing.hpp" #include "utilities/dtrace.hpp" @@ -349,12 +348,7 @@ #endif // ENABLE_ZAP_DEAD_LOCALS // Native memory tracking data if (PrintNMTStatistics) { - if (MemTracker::is_on()) { - BaselineTTYOutputer outputer(tty); - MemTracker::print_memory_usage(outputer, K, false); - } else { - tty->print_cr("%s", MemTracker::reason()); - } + MemTracker::final_report(tty); } } @@ -390,12 +384,7 @@ // Native memory tracking data if (PrintNMTStatistics) { - if (MemTracker::is_on()) { - BaselineTTYOutputer outputer(tty); - MemTracker::print_memory_usage(outputer, K, false); - } else { - tty->print_cr("%s", MemTracker::reason()); - } + MemTracker::final_report(tty); } } @@ -544,10 +533,6 @@ BeforeExit_lock->notify_all(); } - // Shutdown NMT before exit. Otherwise, - // it will run into trouble when system destroys static variables. - MemTracker::shutdown(MemTracker::NMT_normal); - if (VerifyStringTableAtExit) { int fail_cnt = 0; { diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/runtime/os.cpp --- a/hotspot/src/share/vm/runtime/os.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/runtime/os.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -52,6 +52,7 @@ #include "runtime/thread.inline.hpp" #include "runtime/vm_version.hpp" #include "services/attachListener.hpp" +#include "services/nmtCommon.hpp" #include "services/memTracker.hpp" #include "services/threadService.hpp" #include "utilities/defaultStream.hpp" @@ -516,6 +517,14 @@ return dup_str; } +char* os::strdup_check_oom(const char* str, MEMFLAGS flags) { + char* p = os::strdup(str, flags); + if (p == NULL) { + vm_exit_out_of_memory(strlen(str) + 1, OOM_MALLOC_ERROR, "os::strdup_check_oom"); + } + return p; +} + #define paranoid 0 /* only set to 1 if you suspect checking code has bug */ @@ -553,7 +562,11 @@ return ptr; } -void* os::malloc(size_t size, MEMFLAGS memflags, address caller) { +void* os::malloc(size_t size, MEMFLAGS flags) { + return os::malloc(size, flags, CALLER_PC); +} + +void* os::malloc(size_t size, MEMFLAGS memflags, const NativeCallStack& stack) { NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1)); NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size)); @@ -579,11 +592,15 @@ size = 1; } + // NMT support + NMT_TrackingLevel level = MemTracker::tracking_level(); + size_t nmt_header_size = MemTracker::malloc_header_size(level); + #ifndef ASSERT - const size_t alloc_size = size; + const size_t alloc_size = size + nmt_header_size; #else - const size_t alloc_size = GuardedMemory::get_total_size(size); - if (size > alloc_size) { // Check for rollover. + const size_t alloc_size = GuardedMemory::get_total_size(size + nmt_header_size); + if (size + nmt_header_size > alloc_size) { // Check for rollover. return NULL; } #endif @@ -602,7 +619,7 @@ return NULL; } // Wrap memory with guard - GuardedMemory guarded(ptr, size); + GuardedMemory guarded(ptr, size + nmt_header_size); ptr = guarded.get_user_ptr(); #endif if ((intptr_t)ptr == (intptr_t)MallocCatchPtr) { @@ -615,48 +632,50 @@ } // we do not track guard memory - MemTracker::record_malloc((address)ptr, size, memflags, caller == 0 ? CALLER_PC : caller); - - return ptr; + return MemTracker::record_malloc((address)ptr, size, memflags, stack, level); } +void* os::realloc(void *memblock, size_t size, MEMFLAGS flags) { + return os::realloc(memblock, size, flags, CALLER_PC); +} -void* os::realloc(void *memblock, size_t size, MEMFLAGS memflags, address caller) { +void* os::realloc(void *memblock, size_t size, MEMFLAGS memflags, const NativeCallStack& stack) { #ifndef ASSERT NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1)); NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size)); - MemTracker::Tracker tkr = MemTracker::get_realloc_tracker(); - void* ptr = ::realloc(memblock, size); - if (ptr != NULL) { - tkr.record((address)memblock, (address)ptr, size, memflags, - caller == 0 ? CALLER_PC : caller); - } else { - tkr.discard(); - } - return ptr; + // NMT support + void* membase = MemTracker::record_free(memblock); + NMT_TrackingLevel level = MemTracker::tracking_level(); + size_t nmt_header_size = MemTracker::malloc_header_size(level); + void* ptr = ::realloc(membase, size + nmt_header_size); + return MemTracker::record_malloc(ptr, size, memflags, stack, level); #else if (memblock == NULL) { - return os::malloc(size, memflags, (caller == 0 ? CALLER_PC : caller)); + return os::malloc(size, memflags, stack); } if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) { tty->print_cr("os::realloc caught " PTR_FORMAT, memblock); breakpoint(); } - verify_memory(memblock); + // NMT support + void* membase = MemTracker::malloc_base(memblock); + verify_memory(membase); NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap()); if (size == 0) { return NULL; } // always move the block - void* ptr = os::malloc(size, memflags, caller == 0 ? CALLER_PC : caller); + void* ptr = os::malloc(size, memflags, stack); if (PrintMalloc) { tty->print_cr("os::remalloc " SIZE_FORMAT " bytes, " PTR_FORMAT " --> " PTR_FORMAT, size, memblock, ptr); } // Copy to new memory if malloc didn't fail if ( ptr != NULL ) { - GuardedMemory guarded(memblock); - memcpy(ptr, memblock, MIN2(size, guarded.get_user_size())); - if (paranoid) verify_memory(ptr); + GuardedMemory guarded(MemTracker::malloc_base(memblock)); + // Guard's user data contains NMT header + size_t memblock_size = guarded.get_user_size() - MemTracker::malloc_header_size(memblock); + memcpy(ptr, memblock, MIN2(size, memblock_size)); + if (paranoid) verify_memory(MemTracker::malloc_base(ptr)); if ((intptr_t)ptr == (intptr_t)MallocCatchPtr) { tty->print_cr("os::realloc caught, " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, ptr); breakpoint(); @@ -669,7 +688,6 @@ void os::free(void *memblock, MEMFLAGS memflags) { - address trackp = (address) memblock; NOT_PRODUCT(inc_stat_counter(&num_frees, 1)); #ifdef ASSERT if (memblock == NULL) return; @@ -677,20 +695,22 @@ if (tty != NULL) tty->print_cr("os::free caught " PTR_FORMAT, memblock); breakpoint(); } - verify_memory(memblock); + void* membase = MemTracker::record_free(memblock); + verify_memory(membase); NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap()); - GuardedMemory guarded(memblock); + GuardedMemory guarded(membase); size_t size = guarded.get_user_size(); inc_stat_counter(&free_bytes, size); - memblock = guarded.release_for_freeing(); + membase = guarded.release_for_freeing(); if (PrintMalloc && tty != NULL) { - fprintf(stderr, "os::free " SIZE_FORMAT " bytes --> " PTR_FORMAT "\n", size, (uintptr_t)memblock); + fprintf(stderr, "os::free " SIZE_FORMAT " bytes --> " PTR_FORMAT "\n", size, (uintptr_t)membase); } + ::free(membase); +#else + void* membase = MemTracker::record_free(memblock); + ::free(membase); #endif - MemTracker::record_free(trackp, memflags); - - ::free(memblock); } void os::init_random(long initval) { @@ -1478,7 +1498,7 @@ char* os::reserve_memory(size_t bytes, char* addr, size_t alignment_hint) { char* result = pd_reserve_memory(bytes, addr, alignment_hint); if (result != NULL) { - MemTracker::record_virtual_memory_reserve((address)result, bytes, mtNone, CALLER_PC); + MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC); } return result; @@ -1488,7 +1508,7 @@ MEMFLAGS flags) { char* result = pd_reserve_memory(bytes, addr, alignment_hint); if (result != NULL) { - MemTracker::record_virtual_memory_reserve((address)result, bytes, mtNone, CALLER_PC); + MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC); MemTracker::record_virtual_memory_type((address)result, flags); } @@ -1498,7 +1518,7 @@ char* os::attempt_reserve_memory_at(size_t bytes, char* addr) { char* result = pd_attempt_reserve_memory_at(bytes, addr); if (result != NULL) { - MemTracker::record_virtual_memory_reserve((address)result, bytes, mtNone, CALLER_PC); + MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC); } return result; } @@ -1538,23 +1558,29 @@ } bool os::uncommit_memory(char* addr, size_t bytes) { - MemTracker::Tracker tkr = MemTracker::get_virtual_memory_uncommit_tracker(); - bool res = pd_uncommit_memory(addr, bytes); - if (res) { - tkr.record((address)addr, bytes); + bool res; + if (MemTracker::tracking_level() > NMT_minimal) { + Tracker tkr = MemTracker::get_virtual_memory_uncommit_tracker(); + res = pd_uncommit_memory(addr, bytes); + if (res) { + tkr.record((address)addr, bytes); + } } else { - tkr.discard(); + res = pd_uncommit_memory(addr, bytes); } return res; } bool os::release_memory(char* addr, size_t bytes) { - MemTracker::Tracker tkr = MemTracker::get_virtual_memory_release_tracker(); - bool res = pd_release_memory(addr, bytes); - if (res) { - tkr.record((address)addr, bytes); + bool res; + if (MemTracker::tracking_level() > NMT_minimal) { + Tracker tkr = MemTracker::get_virtual_memory_release_tracker(); + res = pd_release_memory(addr, bytes); + if (res) { + tkr.record((address)addr, bytes); + } } else { - tkr.discard(); + res = pd_release_memory(addr, bytes); } return res; } @@ -1565,7 +1591,7 @@ bool allow_exec) { char* result = pd_map_memory(fd, file_name, file_offset, addr, bytes, read_only, allow_exec); if (result != NULL) { - MemTracker::record_virtual_memory_reserve_and_commit((address)result, bytes, mtNone, CALLER_PC); + MemTracker::record_virtual_memory_reserve_and_commit((address)result, bytes, CALLER_PC); } return result; } @@ -1578,12 +1604,15 @@ } bool os::unmap_memory(char *addr, size_t bytes) { - MemTracker::Tracker tkr = MemTracker::get_virtual_memory_release_tracker(); - bool result = pd_unmap_memory(addr, bytes); - if (result) { - tkr.record((address)addr, bytes); + bool result; + if (MemTracker::tracking_level() > NMT_minimal) { + Tracker tkr = MemTracker::get_virtual_memory_release_tracker(); + result = pd_unmap_memory(addr, bytes); + if (result) { + tkr.record((address)addr, bytes); + } } else { - tkr.discard(); + result = pd_unmap_memory(addr, bytes); } return result; } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/runtime/os.hpp --- a/hotspot/src/share/vm/runtime/os.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/runtime/os.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -65,6 +65,8 @@ class Event; class DLL; class FileHandle; +class NativeCallStack; + template class GrowableArray; // %%%%% Moved ThreadState, START_FN, OSThread to new osThread.hpp. -- Rose @@ -96,9 +98,11 @@ // Typedef for structured exception handling support typedef void (*java_call_t)(JavaValue* value, methodHandle* method, JavaCallArguments* args, Thread* thread); +class MallocTracker; + class os: AllStatic { friend class VMStructs; - + friend class MallocTracker; public: enum { page_sizes_max = 9 }; // Size of _page_sizes array (8 plus a sentinel) @@ -160,7 +164,10 @@ // Override me as needed static int file_name_strcmp(const char* s1, const char* s2); + // get/unset environment variable static bool getenv(const char* name, char* buffer, int len); + static bool unsetenv(const char* name); + static bool have_special_privileges(); static jlong javaTimeMillis(); @@ -207,8 +214,13 @@ // Interface for detecting multiprocessor system static inline bool is_MP() { +#if !INCLUDE_NMT assert(_processor_count > 0, "invalid processor count"); return _processor_count > 1 || AssumeMP; +#else + // NMT needs atomic operations before this initialization. + return true; +#endif } static julong available_memory(); static julong physical_memory(); @@ -635,15 +647,25 @@ static void* thread_local_storage_at(int index); static void free_thread_local_storage(int index); - // Stack walk - static address get_caller_pc(int n = 0); + // Retrieve native stack frames. + // Parameter: + // stack: an array to storage stack pointers. + // frames: size of above array. + // toSkip: number of stack frames to skip at the beginning. + // Return: number of stack frames captured. + static int get_native_stack(address* stack, int size, int toSkip = 0); // General allocation (must be MT-safe) - static void* malloc (size_t size, MEMFLAGS flags, address caller_pc = 0); - static void* realloc (void *memblock, size_t size, MEMFLAGS flags, address caller_pc = 0); + static void* malloc (size_t size, MEMFLAGS flags, const NativeCallStack& stack); + static void* malloc (size_t size, MEMFLAGS flags); + static void* realloc (void *memblock, size_t size, MEMFLAGS flag, const NativeCallStack& stack); + static void* realloc (void *memblock, size_t size, MEMFLAGS flag); + static void free (void *memblock, MEMFLAGS flags = mtNone); static bool check_heap(bool force = false); // verify C heap integrity static char* strdup(const char *, MEMFLAGS flags = mtInternal); // Like strdup + // Like strdup, but exit VM when strdup() returns NULL + static char* strdup_check_oom(const char*, MEMFLAGS flags = mtInternal); #ifndef PRODUCT static julong num_mallocs; // # of calls to malloc/realloc diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/runtime/safepoint.cpp --- a/hotspot/src/share/vm/runtime/safepoint.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/runtime/safepoint.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -52,7 +52,6 @@ #include "runtime/sweeper.hpp" #include "runtime/synchronizer.hpp" #include "runtime/thread.inline.hpp" -#include "services/memTracker.hpp" #include "services/runtimeService.hpp" #include "utilities/events.hpp" #include "utilities/macros.hpp" @@ -527,10 +526,6 @@ TraceTime t7("purging class loader data graph", TraceSafepointCleanupTime); ClassLoaderDataGraph::purge_if_needed(); } - - if (MemTracker::is_on()) { - MemTracker::sync(); - } } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/runtime/sharedRuntimeMath.hpp --- a/hotspot/src/share/vm/runtime/sharedRuntimeMath.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/runtime/sharedRuntimeMath.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -27,20 +27,51 @@ #include -// VM_LITTLE_ENDIAN is #defined appropriately in the Makefiles -// [jk] this is not 100% correct because the float word order may different -// from the byte order (e.g. on ARM FPA) +// Used to access the lower/higher 32 bits of a double +typedef union { + double d; + struct { #ifdef VM_LITTLE_ENDIAN -# define __HI(x) *(1+(int*)&x) -# define __LO(x) *(int*)&x + int lo; + int hi; #else -# define __HI(x) *(int*)&x -# define __LO(x) *(1+(int*)&x) + int hi; + int lo; #endif + } split; +} DoubleIntConv; + +static inline int high(double d) { + DoubleIntConv x; + x.d = d; + return x.split.hi; +} + +static inline int low(double d) { + DoubleIntConv x; + x.d = d; + return x.split.lo; +} + +static inline void set_high(double* d, int high) { + DoubleIntConv conv; + conv.d = *d; + conv.split.hi = high; + *d = conv.d; +} + +static inline void set_low(double* d, int low) { + DoubleIntConv conv; + conv.d = *d; + conv.split.lo = low; + *d = conv.d; +} static double copysignA(double x, double y) { - __HI(x) = (__HI(x)&0x7fffffff)|(__HI(y)&0x80000000); - return x; + DoubleIntConv convX; + convX.d = x; + convX.split.hi = (convX.split.hi & 0x7fffffff) | (high(y) & 0x80000000); + return convX.d; } /* @@ -67,30 +98,32 @@ hugeX = 1.0e+300, tiny = 1.0e-300; -static double scalbnA (double x, int n) { +static double scalbnA(double x, int n) { int k,hx,lx; - hx = __HI(x); - lx = __LO(x); + hx = high(x); + lx = low(x); k = (hx&0x7ff00000)>>20; /* extract exponent */ if (k==0) { /* 0 or subnormal x */ if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */ x *= two54; - hx = __HI(x); + hx = high(x); k = ((hx&0x7ff00000)>>20) - 54; if (n< -50000) return tiny*x; /*underflow*/ } if (k==0x7ff) return x+x; /* NaN or Inf */ k = k+n; - if (k > 0x7fe) return hugeX*copysignA(hugeX,x); /* overflow */ - if (k > 0) /* normal result */ - {__HI(x) = (hx&0x800fffff)|(k<<20); return x;} + if (k > 0x7fe) return hugeX*copysignA(hugeX,x); /* overflow */ + if (k > 0) { /* normal result */ + set_high(&x, (hx&0x800fffff)|(k<<20)); + return x; + } if (k <= -54) { if (n > 50000) /* in case integer overflow in n+k */ return hugeX*copysignA(hugeX,x); /*overflow*/ else return tiny*copysignA(tiny,x); /*underflow*/ } k += 54; /* subnormal result */ - __HI(x) = (hx&0x800fffff)|(k<<20); + set_high(&x, (hx&0x800fffff)|(k<<20)); return x*twom54; } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/runtime/sharedRuntimeTrans.cpp --- a/hotspot/src/share/vm/runtime/sharedRuntimeTrans.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/runtime/sharedRuntimeTrans.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -40,6 +40,7 @@ // generated; can not figure out how to turn down optimization for one // file in the IDE on Windows #ifdef WIN32 +# pragma warning( disable: 4748 ) // /GS can not protect parameters and local variables from local buffer overrun because optimizations are disabled in function # pragma optimize ( "", off ) #endif @@ -114,8 +115,8 @@ int k,hx,i,j; unsigned lx; - hx = __HI(x); /* high word of x */ - lx = __LO(x); /* low word of x */ + hx = high(x); /* high word of x */ + lx = low(x); /* low word of x */ k=0; if (hx < 0x00100000) { /* x < 2**-1022 */ @@ -123,13 +124,13 @@ return -two54/zero; /* log(+-0)=-inf */ if (hx<0) return (x-x)/zero; /* log(-#) = NaN */ k -= 54; x *= two54; /* subnormal number, scale up x */ - hx = __HI(x); /* high word of x */ + hx = high(x); /* high word of x */ } if (hx >= 0x7ff00000) return x+x; k += (hx>>20)-1023; hx &= 0x000fffff; i = (hx+0x95f64)&0x100000; - __HI(x) = hx|(i^0x3ff00000); /* normalize x or x/2 */ + set_high(&x, hx|(i^0x3ff00000)); /* normalize x or x/2 */ k += (i>>20); f = x-1.0; if((0x000fffff&(2+hx))<3) { /* |f| < 2**-20 */ @@ -208,8 +209,8 @@ int i,k,hx; unsigned lx; - hx = __HI(x); /* high word of x */ - lx = __LO(x); /* low word of x */ + hx = high(x); /* high word of x */ + lx = low(x); /* low word of x */ k=0; if (hx < 0x00100000) { /* x < 2**-1022 */ @@ -217,14 +218,14 @@ return -two54/zero; /* log(+-0)=-inf */ if (hx<0) return (x-x)/zero; /* log(-#) = NaN */ k -= 54; x *= two54; /* subnormal number, scale up x */ - hx = __HI(x); /* high word of x */ + hx = high(x); /* high word of x */ } if (hx >= 0x7ff00000) return x+x; k += (hx>>20)-1023; i = ((unsigned)k&0x80000000)>>31; hx = (hx&0x000fffff)|((0x3ff-i)<<20); y = (double)(k+i); - __HI(x) = hx; + set_high(&x, hx); z = y*log10_2lo + ivln10*__ieee754_log(x); return z+y*log10_2hi; } @@ -319,14 +320,14 @@ int k=0,xsb; unsigned hx; - hx = __HI(x); /* high word of x */ + hx = high(x); /* high word of x */ xsb = (hx>>31)&1; /* sign bit of x */ hx &= 0x7fffffff; /* high word of |x| */ /* filter out non-finite argument */ if(hx >= 0x40862E42) { /* if |x|>=709.78... */ if(hx>=0x7ff00000) { - if(((hx&0xfffff)|__LO(x))!=0) + if(((hx&0xfffff)|low(x))!=0) return x+x; /* NaN */ else return (xsb==0)? x:0.0; /* exp(+-inf)={inf,0} */ } @@ -357,10 +358,10 @@ if(k==0) return one-((x*c)/(c-2.0)-x); else y = one-((lo-(x*c)/(2.0-c))-hi); if(k >= -1021) { - __HI(y) += (k<<20); /* add k to y's exponent */ + set_high(&y, high(y) + (k<<20)); /* add k to y's exponent */ return y; } else { - __HI(y) += ((k+1000)<<20);/* add k to y's exponent */ + set_high(&y, high(y) + ((k+1000)<<20)); /* add k to y's exponent */ return y*twom1000; } } @@ -447,8 +448,8 @@ unsigned lx,ly; i0 = ((*(int*)&one)>>29)^1; i1=1-i0; - hx = __HI(x); lx = __LO(x); - hy = __HI(y); ly = __LO(y); + hx = high(x); lx = low(x); + hy = high(y); ly = low(y); ix = hx&0x7fffffff; iy = hy&0x7fffffff; /* y==zero: x**0 = 1 */ @@ -548,14 +549,14 @@ u = ivln2_h*t; /* ivln2_h has 21 sig. bits */ v = t*ivln2_l-w*ivln2; t1 = u+v; - __LO(t1) = 0; + set_low(&t1, 0); t2 = v-(t1-u); } else { double ss,s2,s_h,s_l,t_h,t_l; n = 0; /* take care subnormal number */ if(ix<0x00100000) - {ax *= two53; n -= 53; ix = __HI(ax); } + {ax *= two53; n -= 53; ix = high(ax); } n += ((ix)>>20)-0x3ff; j = ix&0x000fffff; /* determine interval */ @@ -563,17 +564,17 @@ if(j<=0x3988E) k=0; /* |x|>1)|0x20000000)+0x00080000+(k<<18); + set_high(&t_h, ((ix>>1)|0x20000000)+0x00080000+(k<<18)); t_l = ax - (t_h-bp[k]); s_l = v*((u-s_h*t_h)-s_h*t_l); /* compute log(ax) */ @@ -582,32 +583,32 @@ r += s_l*(s_h+ss); s2 = s_h*s_h; t_h = 3.0+s2+r; - __LO(t_h) = 0; + set_low(&t_h, 0); t_l = r-((t_h-3.0)-s2); /* u+v = ss*(1+...) */ u = s_h*t_h; v = s_l*t_h+t_l*ss; /* 2/(3log2)*(ss+...) */ p_h = u+v; - __LO(p_h) = 0; + set_low(&p_h, 0); p_l = v-(p_h-u); z_h = cp_h*p_h; /* cp_h+cp_l = 2/(3*log2) */ z_l = cp_l*p_h+p_l*cp+dp_l[k]; /* log2(ax) = (ss+..)*2/(3*log2) = n + dp_h + z_h + z_l */ t = (double)n; t1 = (((z_h+z_l)+dp_h[k])+t); - __LO(t1) = 0; + set_low(&t1, 0); t2 = z_l-(((t1-t)-dp_h[k])-z_h); } /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */ y1 = y; - __LO(y1) = 0; + set_low(&y1, 0); p_l = (y-y1)*t1+y*t2; p_h = y1*t1; z = p_l+p_h; - j = __HI(z); - i = __LO(z); + j = high(z); + i = low(z); if (j>=0x40900000) { /* z >= 1024 */ if(((j-0x40900000)|i)!=0) /* if z > 1024 */ return s*hugeX*hugeX; /* overflow */ @@ -631,13 +632,13 @@ n = j+(0x00100000>>(k+1)); k = ((n&0x7fffffff)>>20)-0x3ff; /* new k for n */ t = zeroX; - __HI(t) = (n&~(0x000fffff>>k)); + set_high(&t, (n&~(0x000fffff>>k))); n = ((n&0x000fffff)|0x00100000)>>(20-k); if(j<0) n = -n; p_h -= t; } t = p_l+p_h; - __LO(t) = 0; + set_low(&t, 0); u = t*lg2_h; v = (p_l-(t-p_h))*lg2+t*lg2_l; z = u+v; @@ -646,10 +647,10 @@ t1 = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))); r = (z*t1)/(t1-two)-(w+z*w); z = one-(r-z); - j = __HI(z); + j = high(z); j += (n<<20); if((j>>20)<=0) z = scalbnA(z,n); /* subnormal output */ - else __HI(z) += (n<<20); + else set_high(&z, high(z) + (n<<20)); return s*z; } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/runtime/sharedRuntimeTrig.cpp --- a/hotspot/src/share/vm/runtime/sharedRuntimeTrig.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/runtime/sharedRuntimeTrig.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -519,7 +519,7 @@ { double z,r,v; int ix; - ix = __HI(x)&0x7fffffff; /* high word of x */ + ix = high(x)&0x7fffffff; /* high word of x */ if(ix<0x3e400000) /* |x| < 2**-27 */ {if((int)x==0) return x;} /* generate inexact */ z = x*x; @@ -574,9 +574,9 @@ static double __kernel_cos(double x, double y) { - double a,h,z,r,qx; + double a,h,z,r,qx=0; int ix; - ix = __HI(x)&0x7fffffff; /* ix = |x|'s high word*/ + ix = high(x)&0x7fffffff; /* ix = |x|'s high word*/ if(ix<0x3e400000) { /* if x < 2**27 */ if(((int)x)==0) return one; /* generate inexact */ } @@ -588,8 +588,8 @@ if(ix > 0x3fe90000) { /* x > 0.78125 */ qx = 0.28125; } else { - __HI(qx) = ix-0x00200000; /* x/4 */ - __LO(qx) = 0; + set_high(&qx, ix-0x00200000); /* x/4 */ + set_low(&qx, 0); } h = 0.5*z-qx; a = one-qx; @@ -654,11 +654,11 @@ { double z,r,v,w,s; int ix,hx; - hx = __HI(x); /* high word of x */ + hx = high(x); /* high word of x */ ix = hx&0x7fffffff; /* high word of |x| */ if(ix<0x3e300000) { /* x < 2**-28 */ if((int)x==0) { /* generate inexact */ - if (((ix | __LO(x)) | (iy + 1)) == 0) + if (((ix | low(x)) | (iy + 1)) == 0) return one / fabsd(x); else { if (iy == 1) @@ -667,10 +667,10 @@ double a, t; z = w = x + y; - __LO(z) = 0; + set_low(&z, 0); v = y - (z - x); t = a = -one / w; - __LO(t) = 0; + set_low(&t, 0); s = one + t * z; return t + a * (s + t * v); } @@ -705,10 +705,10 @@ /* compute -1.0/(x+r) accurately */ double a,t; z = w; - __LO(z) = 0; + set_low(&z, 0); v = r-(z - x); /* z+v = r+x */ t = a = -1.0/w; /* a = -1.0/w */ - __LO(t) = 0; + set_low(&t, 0); s = 1.0+t*z; return t+a*(s+t*v); } @@ -757,7 +757,7 @@ int n, ix; /* High word of x. */ - ix = __HI(x); + ix = high(x); /* |x| ~< pi/4 */ ix &= 0x7fffffff; @@ -815,7 +815,7 @@ int n, ix; /* High word of x. */ - ix = __HI(x); + ix = high(x); /* |x| ~< pi/4 */ ix &= 0x7fffffff; @@ -872,7 +872,7 @@ int n, ix; /* High word of x. */ - ix = __HI(x); + ix = high(x); /* |x| ~< pi/4 */ ix &= 0x7fffffff; diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/runtime/thread.cpp --- a/hotspot/src/share/vm/runtime/thread.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/runtime/thread.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -297,8 +297,7 @@ #if INCLUDE_NMT // record thread's native stack, stack grows downward address stack_low_addr = stack_base() - stack_size(); - MemTracker::record_thread_stack(stack_low_addr, stack_size(), this, - CURRENT_PC); + MemTracker::record_thread_stack(stack_low_addr, stack_size()); #endif // INCLUDE_NMT } @@ -316,7 +315,7 @@ #if INCLUDE_NMT if (_stack_base != NULL) { address low_stack_addr = stack_base() - stack_size(); - MemTracker::release_thread_stack(low_stack_addr, stack_size(), this); + MemTracker::release_thread_stack(low_stack_addr, stack_size()); #ifdef ASSERT set_stack_base(NULL); #endif @@ -1425,9 +1424,6 @@ set_monitor_chunks(NULL); set_next(NULL); set_thread_state(_thread_new); -#if INCLUDE_NMT - set_recorder(NULL); -#endif _terminated = _not_terminated; _privileged_stack_top = NULL; _array_for_gc = NULL; @@ -1503,7 +1499,6 @@ _jni_attach_state = _not_attaching_via_jni; } assert(deferred_card_mark().is_empty(), "Default MemRegion ctor"); - _safepoint_visible = false; } bool JavaThread::reguard_stack(address cur_sp) { @@ -1566,7 +1561,6 @@ thr_type = entry_point == &compiler_thread_entry ? os::compiler_thread : os::java_thread; os::create_thread(this, thr_type, stack_sz); - _safepoint_visible = false; // The _osthread may be NULL here because we ran out of memory (too many threads active). // We need to throw and OutOfMemoryError - however we cannot do this here because the caller // may hold a lock and all locks must be unlocked before throwing the exception (throwing @@ -1584,13 +1578,6 @@ tty->print_cr("terminate thread %p", this); } - // By now, this thread should already be invisible to safepoint, - // and its per-thread recorder also collected. - assert(!is_safepoint_visible(), "wrong state"); -#if INCLUDE_NMT - assert(get_recorder() == NULL, "Already collected"); -#endif // INCLUDE_NMT - // JSR166 -- return the parker to the free list Parker::Release(_parker); _parker = NULL; @@ -3359,11 +3346,6 @@ // initialize TLS ThreadLocalStorage::init(); - // Bootstrap native memory tracking, so it can start recording memory - // activities before worker thread is started. This is the first phase - // of bootstrapping, VM is currently running in single-thread mode. - MemTracker::bootstrap_single_thread(); - // Initialize output stream logging ostream_init_log(); @@ -3414,9 +3396,6 @@ // Initialize Java-Level synchronization subsystem ObjectMonitor::Initialize(); - // Second phase of bootstrapping, VM is about entering multi-thread mode - MemTracker::bootstrap_multi_thread(); - // Initialize global modules jint status = init_globals(); if (status != JNI_OK) { @@ -3438,9 +3417,6 @@ // real raw monitor. VM is setup enough here for raw monitor enter. JvmtiExport::transition_pending_onload_raw_monitors(); - // Fully start NMT - MemTracker::start(); - // Create the VMThread { TraceTime timer("Start VMThread", TraceStartupTime); VMThread::create(); @@ -3995,8 +3971,6 @@ daemon = false; } - p->set_safepoint_visible(true); - ThreadService::add_thread(p, daemon); // Possible GC point. @@ -4042,13 +4016,6 @@ // to do callbacks into the safepoint code. However, the safepoint code is not aware // of this thread since it is removed from the queue. p->set_terminated_value(); - - // Now, this thread is not visible to safepoint - p->set_safepoint_visible(false); - // once the thread becomes safepoint invisible, we can not use its per-thread - // recorder. And Threads::do_threads() no longer walks this thread, so we have - // to release its per-thread recorder here. - MemTracker::thread_exiting(p); } // unlock Threads_lock // Since Events::log uses a lock, we grab it outside the Threads_lock diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/runtime/thread.hpp --- a/hotspot/src/share/vm/runtime/thread.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/runtime/thread.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -43,10 +43,6 @@ #include "runtime/unhandledOops.hpp" #include "utilities/macros.hpp" -#if INCLUDE_NMT -#include "services/memRecorder.hpp" -#endif // INCLUDE_NMT - #include "trace/traceBackend.hpp" #include "trace/traceMacros.hpp" #include "utilities/exceptions.hpp" @@ -1036,16 +1032,6 @@ bool do_not_unlock_if_synchronized() { return _do_not_unlock_if_synchronized; } void set_do_not_unlock_if_synchronized(bool val) { _do_not_unlock_if_synchronized = val; } -#if INCLUDE_NMT - // native memory tracking - inline MemRecorder* get_recorder() const { return (MemRecorder*)_recorder; } - inline void set_recorder(MemRecorder* rc) { _recorder = rc; } - - private: - // per-thread memory recorder - MemRecorder* volatile _recorder; -#endif // INCLUDE_NMT - // Suspend/resume support for JavaThread private: inline void set_ext_suspended(); @@ -1485,19 +1471,6 @@ return result; } - // NMT (Native memory tracking) support. - // This flag helps NMT to determine if this JavaThread will be blocked - // at safepoint. If not, ThreadCritical is needed for writing memory records. - // JavaThread is only safepoint visible when it is in Threads' thread list, - // it is not visible until it is added to the list and becomes invisible - // once it is removed from the list. - public: - bool is_safepoint_visible() const { return _safepoint_visible; } - void set_safepoint_visible(bool visible) { _safepoint_visible = visible; } - private: - bool _safepoint_visible; - - // Static operations public: // Returns the running thread as a JavaThread static inline JavaThread* current(); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/runtime/vmStructs.cpp --- a/hotspot/src/share/vm/runtime/vmStructs.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -52,6 +52,7 @@ #include "interpreter/bytecodes.hpp" #include "interpreter/interpreter.hpp" #include "memory/allocation.hpp" +#include "memory/allocation.inline.hpp" #include "memory/cardTableRS.hpp" #include "memory/defNewGeneration.hpp" #include "memory/freeBlockDictionary.hpp" @@ -93,6 +94,7 @@ #include "runtime/globals.hpp" #include "runtime/java.hpp" #include "runtime/javaCalls.hpp" +#include "runtime/os.hpp" #include "runtime/perfMemory.hpp" #include "runtime/serviceThread.hpp" #include "runtime/sharedRuntime.hpp" @@ -3296,14 +3298,14 @@ } } if (strstr(typeName, " const") == typeName + len - 6) { - char * s = strdup(typeName); + char * s = os::strdup_check_oom(typeName); s[len - 6] = '\0'; // tty->print_cr("checking \"%s\" for \"%s\"", s, typeName); if (recursiveFindType(origtypes, s, true) == 1) { - free(s); + os::free(s); return 1; } - free(s); + os::free(s); } if (!isRecurse) { tty->print_cr("type \"%s\" not found", typeName); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/services/allocationSite.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/services/allocationSite.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_SERVICES_ALLOCATION_SITE_HPP +#define SHARE_VM_SERVICES_ALLOCATION_SITE_HPP + +#include "memory/allocation.hpp" +#include "utilities/nativeCallStack.hpp" + +// Allocation site represents a code path that makes a memory +// allocation +template class AllocationSite VALUE_OBJ_CLASS_SPEC { + private: + NativeCallStack _call_stack; + E e; + public: + AllocationSite(const NativeCallStack& stack) : _call_stack(stack) { } + int hash() const { return _call_stack.hash(); } + bool equals(const NativeCallStack& stack) const { + return _call_stack.equals(stack); + } + + bool equals(const AllocationSite& other) const { + return other.equals(_call_stack); + } + + const NativeCallStack* call_stack() const { + return &_call_stack; + } + + // Information regarding this allocation + E* data() { return &e; } + const E* peek() const { return &e; } +}; + +#endif // SHARE_VM_SERVICES_ALLOCATION_SITE_HPP diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/services/attachListener.cpp --- a/hotspot/src/share/vm/services/attachListener.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/services/attachListener.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -320,6 +320,25 @@ return res? JNI_OK : JNI_ERR; } +// set a size_t global flag using value from AttachOperation +static jint set_size_t_flag(const char* name, AttachOperation* op, outputStream* out) { + size_t value; + const char* arg1; + if ((arg1 = op->arg(1)) != NULL) { + int n = sscanf(arg1, SIZE_FORMAT, &value); + if (n != 1) { + out->print_cr("flag value must be an unsigned integer"); + return JNI_ERR; + } + } + bool res = CommandLineFlags::size_tAtPut((char*)name, &value, Flag::ATTACH_ON_DEMAND); + if (! res) { + out->print_cr("setting flag %s failed", name); + } + + return res? JNI_OK : JNI_ERR; +} + // set a string global flag using value from AttachOperation static jint set_ccstr_flag(const char* name, AttachOperation* op, outputStream* out) { const char* value; @@ -356,6 +375,8 @@ return set_uintx_flag(name, op, out); } else if (f->is_uint64_t()) { return set_uint64_t_flag(name, op, out); + } else if (f->is_size_t()) { + return set_size_t_flag(name, op, out); } else if (f->is_ccstr()) { return set_ccstr_flag(name, op, out); } else { diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/services/mallocSiteTable.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/services/mallocSiteTable.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#include "precompiled.hpp" + + +#include "memory/allocation.inline.hpp" +#include "runtime/atomic.hpp" +#include "services/mallocSiteTable.hpp" + +/* + * Early os::malloc() calls come from initializations of static variables, long before entering any + * VM code. Upon the arrival of the first os::malloc() call, malloc site hashtable has to be + * initialized, along with the allocation site for the hashtable entries. + * To ensure that malloc site hashtable can be initialized without triggering any additional os::malloc() + * call, the hashtable bucket array and hashtable entry allocation site have to be static. + * It is not a problem for hashtable bucket, since it is an array of pointer type, C runtime just + * allocates a block memory and zero the memory for it. + * But for hashtable entry allocation site object, things get tricky. C runtime not only allocates + * memory for it, but also calls its constructor at some later time. If we initialize the allocation site + * at the first os::malloc() call, the object will be reinitialized when its constructor is called + * by C runtime. + * To workaround above issue, we declare a static size_t array with the size of the CallsiteHashtableEntry, + * the memory is used to instantiate CallsiteHashtableEntry for the hashtable entry allocation site. + * Given it is a primitive type array, C runtime will do nothing other than assign the memory block for the variable, + * which is exactly what we want. + * The same trick is also applied to create NativeCallStack object for CallsiteHashtableEntry memory allocation. + * + * Note: C++ object usually aligns to particular alignment, depends on compiler implementation, we declare + * the memory as size_t arrays, to ensure the memory is aligned to native machine word alignment. + */ + +// Reserve enough memory for NativeCallStack and MallocSiteHashtableEntry objects +size_t MallocSiteTable::_hash_entry_allocation_stack[CALC_OBJ_SIZE_IN_TYPE(NativeCallStack, size_t)]; +size_t MallocSiteTable::_hash_entry_allocation_site[CALC_OBJ_SIZE_IN_TYPE(MallocSiteHashtableEntry, size_t)]; + +// Malloc site hashtable buckets +MallocSiteHashtableEntry* MallocSiteTable::_table[MallocSiteTable::table_size]; + +// concurrent access counter +volatile int MallocSiteTable::_access_count = 0; + +// Tracking hashtable contention +NOT_PRODUCT(int MallocSiteTable::_peak_count = 0;) + + +/* + * Initialize malloc site table. + * Hashtable entry is malloc'd, so it can cause infinite recursion. + * To avoid above problem, we pre-initialize a hash entry for + * this allocation site. + * The method is called during C runtime static variable initialization + * time, it is in single-threaded mode from JVM perspective. + */ +bool MallocSiteTable::initialize() { + assert(sizeof(_hash_entry_allocation_stack) >= sizeof(NativeCallStack), "Sanity Check"); + assert(sizeof(_hash_entry_allocation_site) >= sizeof(MallocSiteHashtableEntry), + "Sanity Check"); + assert((size_t)table_size <= MAX_MALLOCSITE_TABLE_SIZE, "Hashtable overflow"); + + // Fake the call stack for hashtable entry allocation + assert(NMT_TrackingStackDepth > 1, "At least one tracking stack"); + + // Create pseudo call stack for hashtable entry allocation + address pc[3]; + if (NMT_TrackingStackDepth >= 3) { + pc[2] = (address)MallocSiteTable::allocation_at; + } + if (NMT_TrackingStackDepth >= 2) { + pc[1] = (address)MallocSiteTable::lookup_or_add; + } + pc[0] = (address)MallocSiteTable::new_entry; + + // Instantiate NativeCallStack object, have to use placement new operator. (see comments above) + NativeCallStack* stack = ::new ((void*)_hash_entry_allocation_stack) + NativeCallStack(pc, MIN2(((int)(sizeof(pc) / sizeof(address))), ((int)NMT_TrackingStackDepth))); + + // Instantiate hash entry for hashtable entry allocation callsite + MallocSiteHashtableEntry* entry = ::new ((void*)_hash_entry_allocation_site) + MallocSiteHashtableEntry(*stack); + + // Add the allocation site to hashtable. + int index = hash_to_index(stack->hash()); + _table[index] = entry; + + return true; +} + +// Walks entries in the hashtable. +// It stops walk if the walker returns false. +bool MallocSiteTable::walk(MallocSiteWalker* walker) { + MallocSiteHashtableEntry* head; + for (int index = 0; index < table_size; index ++) { + head = _table[index]; + while (head != NULL) { + if (!walker->do_malloc_site(head->peek())) { + return false; + } + head = (MallocSiteHashtableEntry*)head->next(); + } + } + return true; +} + +/* + * The hashtable does not have deletion policy on individual entry, + * and each linked list node is inserted via compare-and-swap, + * so each linked list is stable, the contention only happens + * at the end of linked list. + * This method should not return NULL under normal circumstance. + * If NULL is returned, it indicates: + * 1. Out of memory, it cannot allocate new hash entry. + * 2. Overflow hash bucket. + * Under any of above circumstances, caller should handle the situation. + */ +MallocSite* MallocSiteTable::lookup_or_add(const NativeCallStack& key, size_t* bucket_idx, + size_t* pos_idx) { + int index = hash_to_index(key.hash()); + assert(index >= 0, "Negative index"); + *bucket_idx = (size_t)index; + *pos_idx = 0; + + // First entry for this hash bucket + if (_table[index] == NULL) { + MallocSiteHashtableEntry* entry = new_entry(key); + // OOM check + if (entry == NULL) return NULL; + + // swap in the head + if (Atomic::cmpxchg_ptr((void*)entry, (volatile void *)&_table[index], NULL) == NULL) { + return entry->data(); + } + + delete entry; + } + + MallocSiteHashtableEntry* head = _table[index]; + while (head != NULL && (*pos_idx) <= MAX_BUCKET_LENGTH) { + MallocSite* site = head->data(); + if (site->equals(key)) { + // found matched entry + return head->data(); + } + + if (head->next() == NULL && (*pos_idx) < MAX_BUCKET_LENGTH) { + MallocSiteHashtableEntry* entry = new_entry(key); + // OOM check + if (entry == NULL) return NULL; + if (head->atomic_insert(entry)) { + (*pos_idx) ++; + return entry->data(); + } + // contended, other thread won + delete entry; + } + head = (MallocSiteHashtableEntry*)head->next(); + (*pos_idx) ++; + } + return NULL; +} + +// Access malloc site +MallocSite* MallocSiteTable::malloc_site(size_t bucket_idx, size_t pos_idx) { + assert(bucket_idx < table_size, "Invalid bucket index"); + MallocSiteHashtableEntry* head = _table[bucket_idx]; + for (size_t index = 0; index < pos_idx && head != NULL; + index ++, head = (MallocSiteHashtableEntry*)head->next()); + assert(head != NULL, "Invalid position index"); + return head->data(); +} + +// Allocates MallocSiteHashtableEntry object. Special call stack +// (pre-installed allocation site) has to be used to avoid infinite +// recursion. +MallocSiteHashtableEntry* MallocSiteTable::new_entry(const NativeCallStack& key) { + void* p = AllocateHeap(sizeof(MallocSiteHashtableEntry), mtNMT, + *hash_entry_allocation_stack(), AllocFailStrategy::RETURN_NULL); + return ::new (p) MallocSiteHashtableEntry(key); +} + +void MallocSiteTable::reset() { + for (int index = 0; index < table_size; index ++) { + MallocSiteHashtableEntry* head = _table[index]; + _table[index] = NULL; + delete_linked_list(head); + } +} + +void MallocSiteTable::delete_linked_list(MallocSiteHashtableEntry* head) { + MallocSiteHashtableEntry* p; + while (head != NULL) { + p = head; + head = (MallocSiteHashtableEntry*)head->next(); + if (p != (MallocSiteHashtableEntry*)_hash_entry_allocation_site) { + delete p; + } + } +} + +void MallocSiteTable::shutdown() { + AccessLock locker(&_access_count); + locker.exclusiveLock(); + reset(); +} + +bool MallocSiteTable::walk_malloc_site(MallocSiteWalker* walker) { + assert(walker != NULL, "NuLL walker"); + AccessLock locker(&_access_count); + if (locker.sharedLock()) { + NOT_PRODUCT(_peak_count = MAX2(_peak_count, _access_count);) + return walk(walker); + } + return false; +} + + +void MallocSiteTable::AccessLock::exclusiveLock() { + jint target; + jint val; + + assert(_lock_state != ExclusiveLock, "Can only call once"); + assert(*_lock >= 0, "Can not content exclusive lock"); + + // make counter negative to block out shared locks + do { + val = *_lock; + target = _MAGIC_ + *_lock; + } while (Atomic::cmpxchg(target, _lock, val) != val); + + // wait for all readers to exit + while (*_lock != _MAGIC_) { +#ifdef _WINDOWS + os::naked_short_sleep(1); +#else + os::naked_yield(); +#endif + } + _lock_state = ExclusiveLock; +} + + diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/services/mallocSiteTable.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/services/mallocSiteTable.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_SERVICES_MALLOC_SITE_TABLE_HPP +#define SHARE_VM_SERVICES_MALLOC_SITE_TABLE_HPP + +#if INCLUDE_NMT + +#include "memory/allocation.hpp" +#include "runtime/atomic.hpp" +#include "services/allocationSite.hpp" +#include "services/mallocTracker.hpp" +#include "services/nmtCommon.hpp" + +// MallocSite represents a code path that eventually calls +// os::malloc() to allocate memory +class MallocSite : public AllocationSite { + public: + MallocSite() : + AllocationSite(emptyStack) { } + + MallocSite(const NativeCallStack& stack) : + AllocationSite(stack) { } + + void allocate(size_t size) { data()->allocate(size); } + void deallocate(size_t size) { data()->deallocate(size); } + + // Memory allocated from this code path + size_t size() const { return peek()->size(); } + // The number of calls were made + size_t count() const { return peek()->count(); } +}; + +// Malloc site hashtable entry +class MallocSiteHashtableEntry : public CHeapObj { + private: + MallocSite _malloc_site; + MallocSiteHashtableEntry* _next; + + public: + MallocSiteHashtableEntry() : _next(NULL) { } + + MallocSiteHashtableEntry(NativeCallStack stack): + _malloc_site(stack), _next(NULL) { } + + inline const MallocSiteHashtableEntry* next() const { + return _next; + } + + // Insert an entry atomically. + // Return true if the entry is inserted successfully. + // The operation can be failed due to contention from other thread. + bool atomic_insert(const MallocSiteHashtableEntry* entry) { + return (Atomic::cmpxchg_ptr((void*)entry, (volatile void*)&_next, + NULL) == NULL); + } + + void set_callsite(const MallocSite& site) { + _malloc_site = site; + } + + inline const MallocSite* peek() const { return &_malloc_site; } + inline MallocSite* data() { return &_malloc_site; } + + inline long hash() const { return _malloc_site.hash(); } + inline bool equals(const NativeCallStack& stack) const { + return _malloc_site.equals(stack); + } + // Allocation/deallocation on this allocation site + inline void allocate(size_t size) { _malloc_site.allocate(size); } + inline void deallocate(size_t size) { _malloc_site.deallocate(size); } + // Memory counters + inline size_t size() const { return _malloc_site.size(); } + inline size_t count() const { return _malloc_site.count(); } +}; + +// The walker walks every entry on MallocSiteTable +class MallocSiteWalker : public StackObj { + public: + virtual bool do_malloc_site(const MallocSite* e) { return false; } +}; + +/* + * Native memory tracking call site table. + * The table is only needed when detail tracking is enabled. + */ +class MallocSiteTable : AllStatic { + private: + // The number of hash bucket in this hashtable. The number should + // be tuned if malloc activities changed significantly. + // The statistics data can be obtained via Jcmd + // jcmd VM.native_memory statistics. + + // Currently, (number of buckets / number of entires) ratio is + // about 1 / 6 + enum { + table_base_size = 128, // The base size is calculated from statistics to give + // table ratio around 1:6 + table_size = (table_base_size * NMT_TrackingStackDepth - 1) + }; + + + // This is a very special lock, that allows multiple shared accesses (sharedLock), but + // once exclusive access (exclusiveLock) is requested, all shared accesses are + // rejected forever. + class AccessLock : public StackObj { + enum LockState { + NoLock, + SharedLock, + ExclusiveLock + }; + + private: + // A very large negative number. The only possibility to "overflow" + // this number is when there are more than -min_jint threads in + // this process, which is not going to happen in foreseeable future. + const static int _MAGIC_ = min_jint; + + LockState _lock_state; + volatile int* _lock; + public: + AccessLock(volatile int* lock) : + _lock(lock), _lock_state(NoLock) { + } + + ~AccessLock() { + if (_lock_state == SharedLock) { + Atomic::dec((volatile jint*)_lock); + } + } + // Acquire shared lock. + // Return true if shared access is granted. + inline bool sharedLock() { + jint res = Atomic::add(1, _lock); + if (res < 0) { + Atomic::add(-1, _lock); + return false; + } + _lock_state = SharedLock; + return true; + } + // Acquire exclusive lock + void exclusiveLock(); + }; + + public: + static bool initialize(); + static void shutdown(); + + NOT_PRODUCT(static int access_peak_count() { return _peak_count; }) + + // Number of hash buckets + static inline int hash_buckets() { return (int)table_size; } + + // Access and copy a call stack from this table. Shared lock should be + // acquired before access the entry. + static inline bool access_stack(NativeCallStack& stack, size_t bucket_idx, + size_t pos_idx) { + AccessLock locker(&_access_count); + if (locker.sharedLock()) { + NOT_PRODUCT(_peak_count = MAX2(_peak_count, _access_count);) + MallocSite* site = malloc_site(bucket_idx, pos_idx); + if (site != NULL) { + stack = *site->call_stack(); + return true; + } + } + return false; + } + + // Record a new allocation from specified call path. + // Return true if the allocation is recorded successfully, bucket_idx + // and pos_idx are also updated to indicate the entry where the allocation + // information was recorded. + // Return false only occurs under rare scenarios: + // 1. out of memory + // 2. overflow hash bucket + static inline bool allocation_at(const NativeCallStack& stack, size_t size, + size_t* bucket_idx, size_t* pos_idx) { + AccessLock locker(&_access_count); + if (locker.sharedLock()) { + NOT_PRODUCT(_peak_count = MAX2(_peak_count, _access_count);) + MallocSite* site = lookup_or_add(stack, bucket_idx, pos_idx); + if (site != NULL) site->allocate(size); + return site != NULL; + } + return false; + } + + // Record memory deallocation. bucket_idx and pos_idx indicate where the allocation + // information was recorded. + static inline bool deallocation_at(size_t size, size_t bucket_idx, size_t pos_idx) { + AccessLock locker(&_access_count); + if (locker.sharedLock()) { + NOT_PRODUCT(_peak_count = MAX2(_peak_count, _access_count);) + MallocSite* site = malloc_site(bucket_idx, pos_idx); + if (site != NULL) { + site->deallocate(size); + return true; + } + } + return false; + } + + // Walk this table. + static bool walk_malloc_site(MallocSiteWalker* walker); + + private: + static MallocSiteHashtableEntry* new_entry(const NativeCallStack& key); + static void reset(); + + // Delete a bucket linked list + static void delete_linked_list(MallocSiteHashtableEntry* head); + + static MallocSite* lookup_or_add(const NativeCallStack& key, size_t* bucket_idx, size_t* pos_idx); + static MallocSite* malloc_site(size_t bucket_idx, size_t pos_idx); + static bool walk(MallocSiteWalker* walker); + + static inline int hash_to_index(int hash) { + hash = (hash > 0) ? hash : (-hash); + return (hash % table_size); + } + + static inline const NativeCallStack* hash_entry_allocation_stack() { + return (NativeCallStack*)_hash_entry_allocation_stack; + } + + private: + // Counter for counting concurrent access + static volatile int _access_count; + + // The callsite hashtable. It has to be a static table, + // since malloc call can come from C runtime linker. + static MallocSiteHashtableEntry* _table[table_size]; + + + // Reserve enough memory for placing the objects + + // The memory for hashtable entry allocation stack object + static size_t _hash_entry_allocation_stack[CALC_OBJ_SIZE_IN_TYPE(NativeCallStack, size_t)]; + // The memory for hashtable entry allocation callsite object + static size_t _hash_entry_allocation_site[CALC_OBJ_SIZE_IN_TYPE(MallocSiteHashtableEntry, size_t)]; + NOT_PRODUCT(static int _peak_count;) +}; + +#endif // INCLUDE_NMT +#endif // SHARE_VM_SERVICES_MALLOC_SITE_TABLE_HPP diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/services/mallocTracker.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/services/mallocTracker.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#include "precompiled.hpp" + +#include "runtime/atomic.hpp" +#include "runtime/atomic.inline.hpp" +#include "services/mallocSiteTable.hpp" +#include "services/mallocTracker.hpp" +#include "services/mallocTracker.inline.hpp" +#include "services/memTracker.hpp" + +size_t MallocMemorySummary::_snapshot[CALC_OBJ_SIZE_IN_TYPE(MallocMemorySnapshot, size_t)]; + +// Total malloc'd memory amount +size_t MallocMemorySnapshot::total() const { + size_t amount = 0; + for (int index = 0; index < mt_number_of_types; index ++) { + amount += _malloc[index].malloc_size(); + } + amount += _tracking_header.size() + total_arena(); + return amount; +} + +// Total malloc'd memory used by arenas +size_t MallocMemorySnapshot::total_arena() const { + size_t amount = 0; + for (int index = 0; index < mt_number_of_types; index ++) { + amount += _malloc[index].arena_size(); + } + return amount; +} + + +void MallocMemorySnapshot::reset() { + _tracking_header.reset(); + for (int index = 0; index < mt_number_of_types; index ++) { + _malloc[index].reset(); + } +} + +// Make adjustment by subtracting chunks used by arenas +// from total chunks to get total free chunck size +void MallocMemorySnapshot::make_adjustment() { + size_t arena_size = total_arena(); + int chunk_idx = NMTUtil::flag_to_index(mtChunk); + _malloc[chunk_idx].record_free(arena_size); +} + + +void MallocMemorySummary::initialize() { + assert(sizeof(_snapshot) >= sizeof(MallocMemorySnapshot), "Sanity Check"); + // Uses placement new operator to initialize static area. + ::new ((void*)_snapshot)MallocMemorySnapshot(); +} + +void MallocHeader::release() const { + // Tracking already shutdown, no housekeeping is needed anymore + if (MemTracker::tracking_level() <= NMT_minimal) return; + + MallocMemorySummary::record_free(size(), flags()); + MallocMemorySummary::record_free_malloc_header(sizeof(MallocHeader)); + if (tracking_level() == NMT_detail) { + MallocSiteTable::deallocation_at(size(), _bucket_idx, _pos_idx); + } +} + +bool MallocHeader::record_malloc_site(const NativeCallStack& stack, size_t size, + size_t* bucket_idx, size_t* pos_idx) const { + bool ret = MallocSiteTable::allocation_at(stack, size, bucket_idx, pos_idx); + + // Something went wrong, could be OOM or overflow malloc site table. + // We want to keep tracking data under OOM circumstance, so transition to + // summary tracking. + if (!ret) { + MemTracker::transition_to(NMT_summary); + } + return ret; +} + +bool MallocHeader::get_stack(NativeCallStack& stack) const { + return MallocSiteTable::access_stack(stack, _bucket_idx, _pos_idx); +} + +bool MallocTracker::initialize(NMT_TrackingLevel level) { + if (level >= NMT_summary) { + MallocMemorySummary::initialize(); + } + + if (level == NMT_detail) { + return MallocSiteTable::initialize(); + } + return true; +} + +bool MallocTracker::transition(NMT_TrackingLevel from, NMT_TrackingLevel to) { + assert(from != NMT_off, "Can not transition from off state"); + assert(to != NMT_off, "Can not transition to off state"); + if (from == NMT_minimal) { + MallocMemorySummary::reset(); + } + + if (to == NMT_detail) { + assert(from == NMT_minimal || from == NMT_summary, "Just check"); + return MallocSiteTable::initialize(); + } else if (from == NMT_detail) { + assert(to == NMT_minimal || to == NMT_summary, "Just check"); + MallocSiteTable::shutdown(); + } + return true; +} + +// Record a malloc memory allocation +void* MallocTracker::record_malloc(void* malloc_base, size_t size, MEMFLAGS flags, + const NativeCallStack& stack, NMT_TrackingLevel level) { + void* memblock; // the address for user data + MallocHeader* header = NULL; + + if (malloc_base == NULL) { + return NULL; + } + + // Check malloc size, size has to <= MAX_MALLOC_SIZE. This is only possible on 32-bit + // systems, when malloc size >= 1GB, but is is safe to assume it won't happen. + if (size > MAX_MALLOC_SIZE) { + fatal("Should not use malloc for big memory block, use virtual memory instead"); + } + // Uses placement global new operator to initialize malloc header + switch(level) { + case NMT_off: + return malloc_base; + case NMT_minimal: { + MallocHeader* hdr = ::new (malloc_base) MallocHeader(); + break; + } + case NMT_summary: { + header = ::new (malloc_base) MallocHeader(size, flags); + break; + } + case NMT_detail: { + header = ::new (malloc_base) MallocHeader(size, flags, stack); + break; + } + default: + ShouldNotReachHere(); + } + memblock = (void*)((char*)malloc_base + sizeof(MallocHeader)); + + // The alignment check: 8 bytes alignment for 32 bit systems. + // 16 bytes alignment for 64-bit systems. + assert(((size_t)memblock & (sizeof(size_t) * 2 - 1)) == 0, "Alignment check"); + + // Sanity check + assert(get_memory_tracking_level(memblock) == level, + "Wrong tracking level"); + +#ifdef ASSERT + if (level > NMT_minimal) { + // Read back + assert(get_size(memblock) == size, "Wrong size"); + assert(get_flags(memblock) == flags, "Wrong flags"); + } +#endif + + return memblock; +} + +void* MallocTracker::record_free(void* memblock) { + // Never turned on + if (MemTracker::tracking_level() == NMT_off || + memblock == NULL) { + return memblock; + } + MallocHeader* header = malloc_header(memblock); + header->release(); + + return (void*)header; +} + + diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/services/mallocTracker.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/services/mallocTracker.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,424 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_SERVICES_MALLOC_TRACKER_HPP +#define SHARE_VM_SERVICES_MALLOC_TRACKER_HPP + +#if INCLUDE_NMT + +#include "memory/allocation.hpp" +#include "runtime/atomic.hpp" +#include "services/nmtCommon.hpp" +#include "utilities/nativeCallStack.hpp" + +/* + * This counter class counts memory allocation and deallocation, + * records total memory allocation size and number of allocations. + * The counters are updated atomically. + */ +class MemoryCounter VALUE_OBJ_CLASS_SPEC { + private: + size_t _count; + size_t _size; + + DEBUG_ONLY(size_t _peak_count;) + DEBUG_ONLY(size_t _peak_size; ) + + public: + MemoryCounter() : _count(0), _size(0) { + DEBUG_ONLY(_peak_count = 0;) + DEBUG_ONLY(_peak_size = 0;) + } + + // Reset counters + void reset() { + _size = 0; + _count = 0; + DEBUG_ONLY(_peak_size = 0;) + DEBUG_ONLY(_peak_count = 0;) + } + + inline void allocate(size_t sz) { + Atomic::add(1, (volatile MemoryCounterType*)&_count); + if (sz > 0) { + Atomic::add((MemoryCounterType)sz, (volatile MemoryCounterType*)&_size); + DEBUG_ONLY(_peak_size = MAX2(_peak_size, _size)); + } + DEBUG_ONLY(_peak_count = MAX2(_peak_count, _count);) + } + + inline void deallocate(size_t sz) { + assert(_count > 0, "Negative counter"); + assert(_size >= sz, "Negative size"); + Atomic::add(-1, (volatile MemoryCounterType*)&_count); + if (sz > 0) { + Atomic::add(-(MemoryCounterType)sz, (volatile MemoryCounterType*)&_size); + } + } + + inline void resize(long sz) { + if (sz != 0) { + Atomic::add((MemoryCounterType)sz, (volatile MemoryCounterType*)&_size); + DEBUG_ONLY(_peak_size = MAX2(_size, _peak_size);) + } + } + + inline size_t count() const { return _count; } + inline size_t size() const { return _size; } + DEBUG_ONLY(inline size_t peak_count() const { return _peak_count; }) + DEBUG_ONLY(inline size_t peak_size() const { return _peak_size; }) + +}; + +/* + * Malloc memory used by a particular subsystem. + * It includes the memory acquired through os::malloc() + * call and arena's backing memory. + */ +class MallocMemory VALUE_OBJ_CLASS_SPEC { + private: + MemoryCounter _malloc; + MemoryCounter _arena; + + public: + MallocMemory() { } + + inline void record_malloc(size_t sz) { + _malloc.allocate(sz); + } + + inline void record_free(size_t sz) { + _malloc.deallocate(sz); + } + + inline void record_new_arena() { + _arena.allocate(0); + } + + inline void record_arena_free() { + _arena.deallocate(0); + } + + inline void record_arena_size_change(long sz) { + _arena.resize(sz); + } + + void reset() { + _malloc.reset(); + _arena.reset(); + } + + inline size_t malloc_size() const { return _malloc.size(); } + inline size_t malloc_count() const { return _malloc.count();} + inline size_t arena_size() const { return _arena.size(); } + inline size_t arena_count() const { return _arena.count(); } + + DEBUG_ONLY(inline const MemoryCounter& malloc_counter() const { return _malloc; }) + DEBUG_ONLY(inline const MemoryCounter& arena_counter() const { return _arena; }) +}; + +class MallocMemorySummary; + +// A snapshot of malloc'd memory, includes malloc memory +// usage by types and memory used by tracking itself. +class MallocMemorySnapshot : public ResourceObj { + friend class MallocMemorySummary; + + private: + MallocMemory _malloc[mt_number_of_types]; + MemoryCounter _tracking_header; + + + public: + inline MallocMemory* by_type(MEMFLAGS flags) { + int index = NMTUtil::flag_to_index(flags); + return &_malloc[index]; + } + + inline MallocMemory* by_index(int index) { + assert(index >= 0, "Index out of bound"); + assert(index < mt_number_of_types, "Index out of bound"); + return &_malloc[index]; + } + + inline MemoryCounter* malloc_overhead() { + return &_tracking_header; + } + + // Total malloc'd memory amount + size_t total() const; + // Total malloc'd memory used by arenas + size_t total_arena() const; + + inline size_t thread_count() { + return by_type(mtThreadStack)->malloc_count(); + } + + void reset(); + + void copy_to(MallocMemorySnapshot* s) { + s->_tracking_header = _tracking_header; + for (int index = 0; index < mt_number_of_types; index ++) { + s->_malloc[index] = _malloc[index]; + } + } + + // Make adjustment by subtracting chunks used by arenas + // from total chunks to get total free chunk size + void make_adjustment(); +}; + +/* + * This class is for collecting malloc statistics at summary level + */ +class MallocMemorySummary : AllStatic { + private: + // Reserve memory for placement of MallocMemorySnapshot object + static size_t _snapshot[CALC_OBJ_SIZE_IN_TYPE(MallocMemorySnapshot, size_t)]; + + public: + static void initialize(); + + static inline void record_malloc(size_t size, MEMFLAGS flag) { + as_snapshot()->by_type(flag)->record_malloc(size); + } + + static inline void record_free(size_t size, MEMFLAGS flag) { + as_snapshot()->by_type(flag)->record_free(size); + } + + static inline void record_new_arena(MEMFLAGS flag) { + as_snapshot()->by_type(flag)->record_new_arena(); + } + + static inline void record_arena_free(MEMFLAGS flag) { + as_snapshot()->by_type(flag)->record_arena_free(); + } + + static inline void record_arena_size_change(long size, MEMFLAGS flag) { + as_snapshot()->by_type(flag)->record_arena_size_change(size); + } + + static void snapshot(MallocMemorySnapshot* s) { + as_snapshot()->copy_to(s); + s->make_adjustment(); + } + + // Record memory used by malloc tracking header + static inline void record_new_malloc_header(size_t sz) { + as_snapshot()->malloc_overhead()->allocate(sz); + } + + static inline void record_free_malloc_header(size_t sz) { + as_snapshot()->malloc_overhead()->deallocate(sz); + } + + // The memory used by malloc tracking headers + static inline size_t tracking_overhead() { + return as_snapshot()->malloc_overhead()->size(); + } + + // Reset all counters to zero + static void reset() { + as_snapshot()->reset(); + } + + static MallocMemorySnapshot* as_snapshot() { + return (MallocMemorySnapshot*)_snapshot; + } +}; + + +/* + * Malloc tracking header. + * To satisfy malloc alignment requirement, NMT uses 2 machine words for tracking purpose, + * which ensures 8-bytes alignment on 32-bit systems and 16-bytes on 64-bit systems (Product build). + */ + +class MallocHeader VALUE_OBJ_CLASS_SPEC { +#ifdef _LP64 + size_t _size : 62; + size_t _level : 2; + size_t _flags : 8; + size_t _pos_idx : 16; + size_t _bucket_idx: 40; +#define MAX_MALLOCSITE_TABLE_SIZE ((size_t)1 << 40) +#define MAX_BUCKET_LENGTH ((size_t)(1 << 16)) +#define MAX_MALLOC_SIZE (((size_t)1 << 62) - 1) +#else + size_t _size : 30; + size_t _level : 2; + size_t _flags : 8; + size_t _pos_idx : 8; + size_t _bucket_idx: 16; +#define MAX_MALLOCSITE_TABLE_SIZE ((size_t)(1 << 16)) +#define MAX_BUCKET_LENGTH ((size_t)(1 << 8)) +// Max malloc size = 1GB - 1 on 32 bit system, such has total 4GB memory +#define MAX_MALLOC_SIZE ((size_t)(1 << 30) - 1) +#endif // _LP64 + + public: + // Summary tracking header + MallocHeader(size_t size, MEMFLAGS flags) { + assert(sizeof(MallocHeader) == sizeof(void*) * 2, + "Wrong header size"); + + _level = NMT_summary; + _flags = flags; + set_size(size); + MallocMemorySummary::record_malloc(size, flags); + MallocMemorySummary::record_new_malloc_header(sizeof(MallocHeader)); + } + // Detail tracking header + MallocHeader(size_t size, MEMFLAGS flags, const NativeCallStack& stack) { + assert(sizeof(MallocHeader) == sizeof(void*) * 2, + "Wrong header size"); + + _level = NMT_detail; + _flags = flags; + set_size(size); + size_t bucket_idx; + size_t pos_idx; + if (record_malloc_site(stack, size, &bucket_idx, &pos_idx)) { + assert(bucket_idx <= MAX_MALLOCSITE_TABLE_SIZE, "Overflow bucket index"); + assert(pos_idx <= MAX_BUCKET_LENGTH, "Overflow bucket position index"); + _bucket_idx = bucket_idx; + _pos_idx = pos_idx; + } + MallocMemorySummary::record_malloc(size, flags); + MallocMemorySummary::record_new_malloc_header(sizeof(MallocHeader)); + } + // Minimal tracking header + MallocHeader() { + assert(sizeof(MallocHeader) == sizeof(void*) * 2, + "Wrong header size"); + + _level = (unsigned short)NMT_minimal; + } + + inline NMT_TrackingLevel tracking_level() const { + return (NMT_TrackingLevel)_level; + } + + inline size_t size() const { return _size; } + inline MEMFLAGS flags() const { return (MEMFLAGS)_flags; } + bool get_stack(NativeCallStack& stack) const; + + // Cleanup tracking information before the memory is released. + void release() const; + + private: + inline void set_size(size_t size) { + assert(size <= MAX_MALLOC_SIZE, "Malloc size too large, should use virtual memory?"); + _size = size; + } + bool record_malloc_site(const NativeCallStack& stack, size_t size, + size_t* bucket_idx, size_t* pos_idx) const; +}; + + +// Main class called from MemTracker to track malloc activities +class MallocTracker : AllStatic { + public: + // Initialize malloc tracker for specific tracking level + static bool initialize(NMT_TrackingLevel level); + + static bool transition(NMT_TrackingLevel from, NMT_TrackingLevel to); + + // malloc tracking header size for specific tracking level + static inline size_t malloc_header_size(NMT_TrackingLevel level) { + return (level == NMT_off) ? 0 : sizeof(MallocHeader); + } + + // Parameter name convention: + // memblock : the beginning address for user data + // malloc_base: the beginning address that includes malloc tracking header + // + // The relationship: + // memblock = (char*)malloc_base + sizeof(nmt header) + // + + // Record malloc on specified memory block + static void* record_malloc(void* malloc_base, size_t size, MEMFLAGS flags, + const NativeCallStack& stack, NMT_TrackingLevel level); + + // Record free on specified memory block + static void* record_free(void* memblock); + + // Get tracking level of specified memory block + static inline NMT_TrackingLevel get_memory_tracking_level(void* memblock); + + + // Offset memory address to header address + static inline void* get_base(void* memblock); + static inline void* get_base(void* memblock, NMT_TrackingLevel level) { + if (memblock == NULL || level == NMT_off) return memblock; + return (char*)memblock - malloc_header_size(level); + } + + // Get memory size + static inline size_t get_size(void* memblock) { + MallocHeader* header = malloc_header(memblock); + assert(header->tracking_level() >= NMT_summary, + "Wrong tracking level"); + return header->size(); + } + + // Get memory type + static inline MEMFLAGS get_flags(void* memblock) { + MallocHeader* header = malloc_header(memblock); + assert(header->tracking_level() >= NMT_summary, + "Wrong tracking level"); + return header->flags(); + } + + // Get header size + static inline size_t get_header_size(void* memblock) { + return (memblock == NULL) ? 0 : sizeof(MallocHeader); + } + + static inline void record_new_arena(MEMFLAGS flags) { + MallocMemorySummary::record_new_arena(flags); + } + + static inline void record_arena_free(MEMFLAGS flags) { + MallocMemorySummary::record_arena_free(flags); + } + + static inline void record_arena_size_change(int size, MEMFLAGS flags) { + MallocMemorySummary::record_arena_size_change(size, flags); + } + private: + static inline MallocHeader* malloc_header(void *memblock) { + assert(memblock != NULL, "NULL pointer"); + MallocHeader* header = (MallocHeader*)((char*)memblock - sizeof(MallocHeader)); + assert(header->tracking_level() >= NMT_minimal, "Bad header"); + return header; + } +}; + +#endif // INCLUDE_NMT + + +#endif //SHARE_VM_SERVICES_MALLOC_TRACKER_HPP diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/services/mallocTracker.inline.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/services/mallocTracker.inline.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_SERVICES_MALLOC_TRACKER_INLINE_HPP +#define SHARE_VM_SERVICES_MALLOC_TRACKER_INLINE_HPP + +#include "services/mallocTracker.hpp" +#include "services/memTracker.hpp" + +inline NMT_TrackingLevel MallocTracker::get_memory_tracking_level(void* memblock) { + assert(memblock != NULL, "Sanity check"); + if (MemTracker::tracking_level() == NMT_off) return NMT_off; + MallocHeader* header = malloc_header(memblock); + return header->tracking_level(); +} + +inline void* MallocTracker::get_base(void* memblock){ + return get_base(memblock, MemTracker::tracking_level()); +} + +#endif // SHARE_VM_SERVICES_MALLOC_TRACKER_INLINE_HPP + diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/services/management.cpp --- a/hotspot/src/share/vm/services/management.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/services/management.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -1696,6 +1696,9 @@ } else if (flag->is_uint64_t()) { global->value.j = (jlong)flag->get_uint64_t(); global->type = JMM_VMGLOBAL_TYPE_JLONG; + } else if (flag->is_size_t()) { + global->value.j = (jlong)flag->get_size_t(); + global->type = JMM_VMGLOBAL_TYPE_JLONG; } else if (flag->is_ccstr()) { Handle str = java_lang_String::create_from_str(flag->get_ccstr(), CHECK_false); global->value.l = (jobject)JNIHandles::make_local(env, str()); @@ -1851,6 +1854,9 @@ } else if (flag->is_uint64_t()) { uint64_t uvalue = (uint64_t)new_value.j; succeed = CommandLineFlags::uint64_tAtPut(name, &uvalue, Flag::MANAGEMENT); + } else if (flag->is_size_t()) { + size_t svalue = (size_t)new_value.j; + succeed = CommandLineFlags::size_tAtPut(name, &svalue, Flag::MANAGEMENT); } else if (flag->is_ccstr()) { oop str = JNIHandles::resolve_external_guard(new_value.l); if (str == NULL) { @@ -1914,7 +1920,7 @@ ResourceMark rm(THREAD); // thread->name() uses ResourceArea assert(thread->name() != NULL, "All threads should have a name"); - _names_chars[_count] = strdup(thread->name()); + _names_chars[_count] = os::strdup(thread->name()); _times->long_at_put(_count, os::is_thread_cpu_time_supported() ? os::thread_cpu_time(thread) : -1); _count++; @@ -1932,7 +1938,7 @@ ThreadTimesClosure::~ThreadTimesClosure() { for (int i = 0; i < _count; i++) { - free(_names_chars[i]); + os::free(_names_chars[i]); } FREE_C_HEAP_ARRAY(char *, _names_chars, mtInternal); } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/services/memBaseline.cpp --- a/hotspot/src/share/vm/services/memBaseline.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/services/memBaseline.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -22,471 +22,301 @@ * */ #include "precompiled.hpp" + #include "memory/allocation.hpp" #include "runtime/safepoint.hpp" #include "runtime/thread.inline.hpp" #include "services/memBaseline.hpp" #include "services/memTracker.hpp" - -MemType2Name MemBaseline::MemType2NameMap[NUMBER_OF_MEMORY_TYPE] = { - {mtJavaHeap, "Java Heap"}, - {mtClass, "Class"}, - {mtThreadStack,"Thread Stack"}, - {mtThread, "Thread"}, - {mtCode, "Code"}, - {mtGC, "GC"}, - {mtCompiler, "Compiler"}, - {mtInternal, "Internal"}, - {mtOther, "Other"}, - {mtSymbol, "Symbol"}, - {mtNMT, "Memory Tracking"}, - {mtTracing, "Tracing"}, - {mtChunk, "Pooled Free Chunks"}, - {mtClassShared,"Shared spaces for classes"}, - {mtTest, "Test"}, - {mtNone, "Unknown"} // It can happen when type tagging records are lagging - // behind -}; - -MemBaseline::MemBaseline() { - _baselined = false; - - for (int index = 0; index < NUMBER_OF_MEMORY_TYPE; index ++) { - _malloc_data[index].set_type(MemType2NameMap[index]._flag); - _vm_data[index].set_type(MemType2NameMap[index]._flag); - _arena_data[index].set_type(MemType2NameMap[index]._flag); +/* + * Sizes are sorted in descenting order for reporting + */ +int compare_malloc_size(const MallocSite& s1, const MallocSite& s2) { + if (s1.size() == s2.size()) { + return 0; + } else if (s1.size() > s2.size()) { + return -1; + } else { + return 1; } - - _malloc_cs = NULL; - _vm_cs = NULL; - _vm_map = NULL; - - _number_of_classes = 0; - _number_of_threads = 0; } -void MemBaseline::clear() { - if (_malloc_cs != NULL) { - delete _malloc_cs; - _malloc_cs = NULL; +int compare_virtual_memory_size(const VirtualMemoryAllocationSite& s1, + const VirtualMemoryAllocationSite& s2) { + if (s1.reserved() == s2.reserved()) { + return 0; + } else if (s1.reserved() > s2.reserved()) { + return -1; + } else { + return 1; } +} - if (_vm_cs != NULL) { - delete _vm_cs; - _vm_cs = NULL; - } - - if (_vm_map != NULL) { - delete _vm_map; - _vm_map = NULL; - } - - reset(); +// Sort into allocation site addresses order for baseline comparison +int compare_malloc_site(const MallocSite& s1, const MallocSite& s2) { + return s1.call_stack()->compare(*s2.call_stack()); } -void MemBaseline::reset() { - _baselined = false; - _total_vm_reserved = 0; - _total_vm_committed = 0; - _total_malloced = 0; - _number_of_classes = 0; - - if (_malloc_cs != NULL) _malloc_cs->clear(); - if (_vm_cs != NULL) _vm_cs->clear(); - if (_vm_map != NULL) _vm_map->clear(); - - for (int index = 0; index < NUMBER_OF_MEMORY_TYPE; index ++) { - _malloc_data[index].clear(); - _vm_data[index].clear(); - _arena_data[index].clear(); - } +int compare_virtual_memory_site(const VirtualMemoryAllocationSite& s1, + const VirtualMemoryAllocationSite& s2) { + return s1.call_stack()->compare(*s2.call_stack()); } -MemBaseline::~MemBaseline() { - clear(); +/* + * Walker to walk malloc allocation site table + */ +class MallocAllocationSiteWalker : public MallocSiteWalker { + private: + SortedLinkedList + _malloc_sites; + size_t _count; + + // Entries in MallocSiteTable with size = 0 and count = 0, + // when the malloc site is not longer there. + public: + MallocAllocationSiteWalker(Arena* arena) : _count(0), _malloc_sites(arena) { + } + + inline size_t count() const { return _count; } + + LinkedList* malloc_sites() { + return &_malloc_sites; + } + + bool do_malloc_site(const MallocSite* site) { + if (site->size() >= MemBaseline::SIZE_THRESHOLD) { + if (_malloc_sites.add(*site) != NULL) { + _count++; + return true; + } else { + return false; // OOM + } + } else { + // malloc site does not meet threshold, ignore and continue + return true; + } + } +}; + +// Compare virtual memory region's base address +int compare_virtual_memory_base(const ReservedMemoryRegion& r1, const ReservedMemoryRegion& r2) { + return r1.compare(r2); } -// baseline malloc'd memory records, generate overall summary and summaries by -// memory types -bool MemBaseline::baseline_malloc_summary(const MemPointerArray* malloc_records) { - MemPointerArrayIteratorImpl malloc_itr((MemPointerArray*)malloc_records); - MemPointerRecord* malloc_ptr = (MemPointerRecord*)malloc_itr.current(); - size_t used_arena_size = 0; - int index; - while (malloc_ptr != NULL) { - index = flag2index(FLAGS_TO_MEMORY_TYPE(malloc_ptr->flags())); - size_t size = malloc_ptr->size(); - if (malloc_ptr->is_arena_memory_record()) { - // We do have anonymous arenas, they are either used as value objects, - // which are embedded inside other objects, or used as stack objects. - _arena_data[index].inc(size); - used_arena_size += size; - } else { - _total_malloced += size; - _malloc_data[index].inc(size); - if (malloc_ptr->is_arena_record()) { - // see if arena memory record present - MemPointerRecord* next_malloc_ptr = (MemPointerRecordEx*)malloc_itr.peek_next(); - if (next_malloc_ptr != NULL && next_malloc_ptr->is_arena_memory_record()) { - assert(next_malloc_ptr->is_memory_record_of_arena(malloc_ptr), - "Arena records do not match"); - size = next_malloc_ptr->size(); - _arena_data[index].inc(size); - used_arena_size += size; - malloc_itr.next(); - } +// Walk all virtual memory regions for baselining +class VirtualMemoryAllocationWalker : public VirtualMemoryWalker { + private: + SortedLinkedList + _virtual_memory_regions; + size_t _count; + + public: + VirtualMemoryAllocationWalker(Arena* a) : _count(0), _virtual_memory_regions(a) { + } + + bool do_allocation_site(const ReservedMemoryRegion* rgn) { + if (rgn->size() >= MemBaseline::SIZE_THRESHOLD) { + if (_virtual_memory_regions.add(*rgn) != NULL) { + _count ++; + return true; + } else { + return false; } } - malloc_ptr = (MemPointerRecordEx*)malloc_itr.next(); + return true; } - // substract used arena size to get size of arena chunk in free list - index = flag2index(mtChunk); - _malloc_data[index].reduce(used_arena_size); - // we really don't know how many chunks in free list, so just set to - // 0 - _malloc_data[index].overwrite_counter(0); + LinkedList* virtual_memory_allocations() { + return &_virtual_memory_regions; + } +}; + + +bool MemBaseline::baseline_summary() { + assert(_malloc_memory_snapshot == NULL, "Malloc baseline not yet reset"); + assert(_virtual_memory_snapshot == NULL, "Virtual baseline not yet reset"); + + _malloc_memory_snapshot = new (arena()) MallocMemorySnapshot(); + _virtual_memory_snapshot = new (arena()) VirtualMemorySnapshot(); + if (_malloc_memory_snapshot == NULL || _virtual_memory_snapshot == NULL) { + return false; + } + MallocMemorySummary::snapshot(_malloc_memory_snapshot); + VirtualMemorySummary::snapshot(_virtual_memory_snapshot); + return true; +} + +bool MemBaseline::baseline_allocation_sites() { + assert(arena() != NULL, "Just check"); + // Malloc allocation sites + MallocAllocationSiteWalker malloc_walker(arena()); + if (!MallocSiteTable::walk_malloc_site(&malloc_walker)) { + return false; + } + + _malloc_sites.set_head(malloc_walker.malloc_sites()->head()); + // The malloc sites are collected in size order + _malloc_sites_order = by_size; + + // Virtual memory allocation sites + VirtualMemoryAllocationWalker virtual_memory_walker(arena()); + if (!VirtualMemoryTracker::walk_virtual_memory(&virtual_memory_walker)) { + return false; + } + + // Virtual memory allocations are collected in call stack order + _virtual_memory_allocations.set_head(virtual_memory_walker.virtual_memory_allocations()->head()); + + if (!aggregate_virtual_memory_allocation_sites()) { + return false; + } + // Virtual memory allocation sites are aggregrated in call stack order + _virtual_memory_sites_order = by_address; return true; } -// check if there is a safepoint in progress, if so, block the thread -// for the safepoint -void MemBaseline::check_safepoint(JavaThread* thr) { - if (SafepointSynchronize::is_synchronizing()) { - // grab and drop the SR_lock to honor the safepoint protocol - MutexLocker ml(thr->SR_lock()); - } -} - -// baseline mmap'd memory records, generate overall summary and summaries by -// memory types -bool MemBaseline::baseline_vm_summary(const MemPointerArray* vm_records) { - MemPointerArrayIteratorImpl vm_itr((MemPointerArray*)vm_records); - VMMemRegion* vm_ptr = (VMMemRegion*)vm_itr.current(); - int index; - while (vm_ptr != NULL) { - if (vm_ptr->is_reserved_region()) { - index = flag2index(FLAGS_TO_MEMORY_TYPE(vm_ptr->flags())); - // we use the number of thread stack to count threads - if (IS_MEMORY_TYPE(vm_ptr->flags(), mtThreadStack)) { - _number_of_threads ++; - } - _total_vm_reserved += vm_ptr->size(); - _vm_data[index].inc(vm_ptr->size(), 0); - } else { - _total_vm_committed += vm_ptr->size(); - _vm_data[index].inc(0, vm_ptr->size()); - } - vm_ptr = (VMMemRegion*)vm_itr.next(); - } - return true; -} - -// baseline malloc'd memory by callsites, but only the callsites with memory allocation -// over 1KB are stored. -bool MemBaseline::baseline_malloc_details(const MemPointerArray* malloc_records) { - assert(MemTracker::track_callsite(), "detail tracking is off"); - - MemPointerArrayIteratorImpl malloc_itr(const_cast(malloc_records)); - MemPointerRecordEx* malloc_ptr = (MemPointerRecordEx*)malloc_itr.current(); - MallocCallsitePointer malloc_callsite; - - // initailize malloc callsite array - if (_malloc_cs == NULL) { - _malloc_cs = new (std::nothrow) MemPointerArrayImpl(64); - // out of native memory - if (_malloc_cs == NULL || _malloc_cs->out_of_memory()) { - return false; - } - } else { - _malloc_cs->clear(); - } - - MemPointerArray* malloc_data = const_cast(malloc_records); - - // sort into callsite pc order. Details are aggregated by callsites - malloc_data->sort((FN_SORT)malloc_sort_by_pc); - bool ret = true; - - // baseline memory that is totaled over 1 KB - while (malloc_ptr != NULL) { - if (!MemPointerRecord::is_arena_memory_record(malloc_ptr->flags())) { - // skip thread stacks - if (!IS_MEMORY_TYPE(malloc_ptr->flags(), mtThreadStack)) { - if (malloc_callsite.addr() != malloc_ptr->pc()) { - if ((malloc_callsite.amount()/K) > 0) { - if (!_malloc_cs->append(&malloc_callsite)) { - ret = false; - break; - } - } - malloc_callsite = MallocCallsitePointer(malloc_ptr->pc()); - } - malloc_callsite.inc(malloc_ptr->size()); - } - } - malloc_ptr = (MemPointerRecordEx*)malloc_itr.next(); +bool MemBaseline::baseline(bool summaryOnly) { + if (arena() == NULL) { + _arena = new (std::nothrow, mtNMT) Arena(mtNMT); + if (arena() == NULL) return false; } - // restore to address order. Snapshot malloc data is maintained in memory - // address order. - malloc_data->sort((FN_SORT)malloc_sort_by_addr); - - if (!ret) { - return false; - } - // deal with last record - if (malloc_callsite.addr() != 0 && (malloc_callsite.amount()/K) > 0) { - if (!_malloc_cs->append(&malloc_callsite)) { - return false; - } - } - return true; -} - -// baseline mmap'd memory by callsites -bool MemBaseline::baseline_vm_details(const MemPointerArray* vm_records) { - assert(MemTracker::track_callsite(), "detail tracking is off"); - - VMCallsitePointer vm_callsite; - VMCallsitePointer* cur_callsite = NULL; - MemPointerArrayIteratorImpl vm_itr((MemPointerArray*)vm_records); - VMMemRegionEx* vm_ptr = (VMMemRegionEx*)vm_itr.current(); - - // initialize virtual memory map array - if (_vm_map == NULL) { - _vm_map = new (std::nothrow) MemPointerArrayImpl(vm_records->length()); - if (_vm_map == NULL || _vm_map->out_of_memory()) { - return false; - } - } else { - _vm_map->clear(); - } - - // initialize virtual memory callsite array - if (_vm_cs == NULL) { - _vm_cs = new (std::nothrow) MemPointerArrayImpl(64); - if (_vm_cs == NULL || _vm_cs->out_of_memory()) { - return false; - } - } else { - _vm_cs->clear(); - } - - // consolidate virtual memory data - VMMemRegionEx* reserved_rec = NULL; - VMMemRegionEx* committed_rec = NULL; + reset(); - // vm_ptr is coming in increasing base address order - while (vm_ptr != NULL) { - if (vm_ptr->is_reserved_region()) { - // consolidate reserved memory regions for virtual memory map. - // The criteria for consolidation is: - // 1. two adjacent reserved memory regions - // 2. belong to the same memory type - // 3. reserved from the same callsite - if (reserved_rec == NULL || - reserved_rec->base() + reserved_rec->size() != vm_ptr->addr() || - FLAGS_TO_MEMORY_TYPE(reserved_rec->flags()) != FLAGS_TO_MEMORY_TYPE(vm_ptr->flags()) || - reserved_rec->pc() != vm_ptr->pc()) { - if (!_vm_map->append(vm_ptr)) { - return false; - } - // inserted reserved region, we need the pointer to the element in virtual - // memory map array. - reserved_rec = (VMMemRegionEx*)_vm_map->at(_vm_map->length() - 1); - } else { - reserved_rec->expand_region(vm_ptr->addr(), vm_ptr->size()); - } + _class_count = InstanceKlass::number_of_instance_classes(); - if (cur_callsite != NULL && !_vm_cs->append(cur_callsite)) { - return false; - } - vm_callsite = VMCallsitePointer(vm_ptr->pc()); - cur_callsite = &vm_callsite; - vm_callsite.inc(vm_ptr->size(), 0); - } else { - // consolidate committed memory regions for virtual memory map - // The criterial is: - // 1. two adjacent committed memory regions - // 2. committed from the same callsite - if (committed_rec == NULL || - committed_rec->base() + committed_rec->size() != vm_ptr->addr() || - committed_rec->pc() != vm_ptr->pc()) { - if (!_vm_map->append(vm_ptr)) { - return false; - } - committed_rec = (VMMemRegionEx*)_vm_map->at(_vm_map->length() - 1); - } else { - committed_rec->expand_region(vm_ptr->addr(), vm_ptr->size()); - } - vm_callsite.inc(0, vm_ptr->size()); - } - vm_ptr = (VMMemRegionEx*)vm_itr.next(); - } - // deal with last record - if (cur_callsite != NULL && !_vm_cs->append(cur_callsite)) { + if (!baseline_summary()) { return false; } - // sort it into callsite pc order. Details are aggregated by callsites - _vm_cs->sort((FN_SORT)bl_vm_sort_by_pc); + _baseline_type = Summary_baselined; - // walk the array to consolidate record by pc - MemPointerArrayIteratorImpl itr(_vm_cs); - VMCallsitePointer* callsite_rec = (VMCallsitePointer*)itr.current(); - VMCallsitePointer* next_rec = (VMCallsitePointer*)itr.next(); - while (next_rec != NULL) { - assert(callsite_rec != NULL, "Sanity check"); - if (next_rec->addr() == callsite_rec->addr()) { - callsite_rec->inc(next_rec->reserved_amount(), next_rec->committed_amount()); - itr.remove(); - next_rec = (VMCallsitePointer*)itr.current(); - } else { - callsite_rec = next_rec; - next_rec = (VMCallsitePointer*)itr.next(); - } + // baseline details + if (!summaryOnly && + MemTracker::tracking_level() == NMT_detail) { + baseline_allocation_sites(); + _baseline_type = Detail_baselined; } return true; } -// baseline a snapshot. If summary_only = false, memory usages aggregated by -// callsites are also baselined. -// The method call can be lengthy, especially when detail tracking info is -// requested. So the method checks for safepoint explicitly. -bool MemBaseline::baseline(MemSnapshot& snapshot, bool summary_only) { - Thread* THREAD = Thread::current(); - assert(THREAD->is_Java_thread(), "must be a JavaThread"); - MutexLocker snapshot_locker(snapshot._lock); - reset(); - _baselined = baseline_malloc_summary(snapshot._alloc_ptrs); - if (_baselined) { - check_safepoint((JavaThread*)THREAD); - _baselined = baseline_vm_summary(snapshot._vm_ptrs); +int compare_allocation_site(const VirtualMemoryAllocationSite& s1, + const VirtualMemoryAllocationSite& s2) { + return s1.call_stack()->compare(*s2.call_stack()); +} + +bool MemBaseline::aggregate_virtual_memory_allocation_sites() { + SortedLinkedList + allocation_sites(arena()); + + VirtualMemoryAllocationIterator itr = virtual_memory_allocations(); + const ReservedMemoryRegion* rgn; + VirtualMemoryAllocationSite* site; + while ((rgn = itr.next()) != NULL) { + VirtualMemoryAllocationSite tmp(*rgn->call_stack()); + site = allocation_sites.find(tmp); + if (site == NULL) { + LinkedListNode* node = + allocation_sites.add(tmp); + if (node == NULL) return false; + site = node->data(); + } + site->reserve_memory(rgn->size()); + site->commit_memory(rgn->committed_size()); } - _number_of_classes = snapshot.number_of_classes(); - if (!summary_only && MemTracker::track_callsite() && _baselined) { - check_safepoint((JavaThread*)THREAD); - _baselined = baseline_malloc_details(snapshot._alloc_ptrs); - if (_baselined) { - check_safepoint((JavaThread*)THREAD); - _baselined = baseline_vm_details(snapshot._vm_ptrs); - } - } - return _baselined; + _virtual_memory_sites.set_head(allocation_sites.head()); + return true; } - -int MemBaseline::flag2index(MEMFLAGS flag) const { - for (int index = 0; index < NUMBER_OF_MEMORY_TYPE; index ++) { - if (MemType2NameMap[index]._flag == flag) { - return index; - } +MallocSiteIterator MemBaseline::malloc_sites(SortingOrder order) { + assert(!_malloc_sites.is_empty(), "Detail baseline?"); + switch(order) { + case by_size: + malloc_sites_to_size_order(); + break; + case by_site: + malloc_sites_to_allocation_site_order(); + break; + case by_address: + default: + ShouldNotReachHere(); } - assert(false, "no type"); - return -1; + return MallocSiteIterator(_malloc_sites.head()); } -const char* MemBaseline::type2name(MEMFLAGS type) { - for (int index = 0; index < NUMBER_OF_MEMORY_TYPE; index ++) { - if (MemType2NameMap[index]._flag == type) { - return MemType2NameMap[index]._name; - } +VirtualMemorySiteIterator MemBaseline::virtual_memory_sites(SortingOrder order) { + assert(!_virtual_memory_sites.is_empty(), "Detail baseline?"); + switch(order) { + case by_size: + virtual_memory_sites_to_size_order(); + break; + case by_site: + virtual_memory_sites_to_reservation_site_order(); + break; + case by_address: + default: + ShouldNotReachHere(); } - assert(false, err_msg("bad type %x", type)); - return NULL; + return VirtualMemorySiteIterator(_virtual_memory_sites.head()); } -MemBaseline& MemBaseline::operator=(const MemBaseline& other) { - _total_malloced = other._total_malloced; - _total_vm_reserved = other._total_vm_reserved; - _total_vm_committed = other._total_vm_committed; - - _baselined = other._baselined; - _number_of_classes = other._number_of_classes; - - for (int index = 0; index < NUMBER_OF_MEMORY_TYPE; index ++) { - _malloc_data[index] = other._malloc_data[index]; - _vm_data[index] = other._vm_data[index]; - _arena_data[index] = other._arena_data[index]; - } +// Sorting allocations sites in different orders +void MemBaseline::malloc_sites_to_size_order() { + if (_malloc_sites_order != by_size) { + SortedLinkedList + tmp(arena()); - if (MemTracker::track_callsite()) { - assert(_malloc_cs != NULL && _vm_cs != NULL, "out of memory"); - assert(other._malloc_cs != NULL && other._vm_cs != NULL, - "not properly baselined"); - _malloc_cs->clear(); - _vm_cs->clear(); - int index; - for (index = 0; index < other._malloc_cs->length(); index ++) { - _malloc_cs->append(other._malloc_cs->at(index)); - } - - for (index = 0; index < other._vm_cs->length(); index ++) { - _vm_cs->append(other._vm_cs->at(index)); - } + // Add malloc sites to sorted linked list to sort into size order + tmp.move(&_malloc_sites); + _malloc_sites.set_head(tmp.head()); + tmp.set_head(NULL); + _malloc_sites_order = by_size; } - return *this; } -/* compare functions for sorting */ - -// sort snapshot malloc'd records in callsite pc order -int MemBaseline::malloc_sort_by_pc(const void* p1, const void* p2) { - assert(MemTracker::track_callsite(),"Just check"); - const MemPointerRecordEx* mp1 = (const MemPointerRecordEx*)p1; - const MemPointerRecordEx* mp2 = (const MemPointerRecordEx*)p2; - return UNSIGNED_COMPARE(mp1->pc(), mp2->pc()); +void MemBaseline::malloc_sites_to_allocation_site_order() { + if (_malloc_sites_order != by_site) { + SortedLinkedList + tmp(arena()); + // Add malloc sites to sorted linked list to sort into site (address) order + tmp.move(&_malloc_sites); + _malloc_sites.set_head(tmp.head()); + tmp.set_head(NULL); + _malloc_sites_order = by_site; + } } -// sort baselined malloc'd records in size order -int MemBaseline::bl_malloc_sort_by_size(const void* p1, const void* p2) { - assert(MemTracker::is_on(), "Just check"); - const MallocCallsitePointer* mp1 = (const MallocCallsitePointer*)p1; - const MallocCallsitePointer* mp2 = (const MallocCallsitePointer*)p2; - return UNSIGNED_COMPARE(mp2->amount(), mp1->amount()); -} +void MemBaseline::virtual_memory_sites_to_size_order() { + if (_virtual_memory_sites_order != by_size) { + SortedLinkedList + tmp(arena()); -// sort baselined malloc'd records in callsite pc order -int MemBaseline::bl_malloc_sort_by_pc(const void* p1, const void* p2) { - assert(MemTracker::is_on(), "Just check"); - const MallocCallsitePointer* mp1 = (const MallocCallsitePointer*)p1; - const MallocCallsitePointer* mp2 = (const MallocCallsitePointer*)p2; - return UNSIGNED_COMPARE(mp1->addr(), mp2->addr()); + tmp.move(&_virtual_memory_sites); + + _virtual_memory_sites.set_head(tmp.head()); + tmp.set_head(NULL); + _virtual_memory_sites_order = by_size; + } } +void MemBaseline::virtual_memory_sites_to_reservation_site_order() { + if (_virtual_memory_sites_order != by_size) { + SortedLinkedList + tmp(arena()); -// sort baselined mmap'd records in size (reserved size) order -int MemBaseline::bl_vm_sort_by_size(const void* p1, const void* p2) { - assert(MemTracker::is_on(), "Just check"); - const VMCallsitePointer* mp1 = (const VMCallsitePointer*)p1; - const VMCallsitePointer* mp2 = (const VMCallsitePointer*)p2; - return UNSIGNED_COMPARE(mp2->reserved_amount(), mp1->reserved_amount()); + tmp.add(&_virtual_memory_sites); + + _virtual_memory_sites.set_head(tmp.head()); + tmp.set_head(NULL); + + _virtual_memory_sites_order = by_size; + } } -// sort baselined mmap'd records in callsite pc order -int MemBaseline::bl_vm_sort_by_pc(const void* p1, const void* p2) { - assert(MemTracker::is_on(), "Just check"); - const VMCallsitePointer* mp1 = (const VMCallsitePointer*)p1; - const VMCallsitePointer* mp2 = (const VMCallsitePointer*)p2; - return UNSIGNED_COMPARE(mp1->addr(), mp2->addr()); -} - - -// sort snapshot malloc'd records in memory block address order -int MemBaseline::malloc_sort_by_addr(const void* p1, const void* p2) { - assert(MemTracker::is_on(), "Just check"); - const MemPointerRecord* mp1 = (const MemPointerRecord*)p1; - const MemPointerRecord* mp2 = (const MemPointerRecord*)p2; - int delta = UNSIGNED_COMPARE(mp1->addr(), mp2->addr()); - assert(p1 == p2 || delta != 0, "dup pointer"); - return delta; -} - diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/services/memBaseline.hpp --- a/hotspot/src/share/vm/services/memBaseline.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/services/memBaseline.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -25,425 +25,205 @@ #ifndef SHARE_VM_SERVICES_MEM_BASELINE_HPP #define SHARE_VM_SERVICES_MEM_BASELINE_HPP +#if INCLUDE_NMT + #include "memory/allocation.hpp" #include "runtime/mutex.hpp" -#include "services/memPtr.hpp" -#include "services/memSnapshot.hpp" +#include "services/mallocSiteTable.hpp" +#include "services/mallocTracker.hpp" +#include "services/nmtCommon.hpp" +#include "services/virtualMemoryTracker.hpp" +#include "utilities/linkedlist.hpp" -// compare unsigned number -#define UNSIGNED_COMPARE(a, b) ((a > b) ? 1 : ((a == b) ? 0 : -1)) +typedef LinkedListIterator MallocSiteIterator; +typedef LinkedListIterator VirtualMemorySiteIterator; +typedef LinkedListIterator VirtualMemoryAllocationIterator; /* - * MallocCallsitePointer and VMCallsitePointer are used - * to baseline memory blocks with their callsite information. - * They are only available when detail tracking is turned - * on. + * Baseline a memory snapshot */ - -/* baselined malloc record aggregated by callsite */ -class MallocCallsitePointer : public MemPointer { - private: - size_t _count; // number of malloc invocation from this callsite - size_t _amount; // total amount of memory malloc-ed from this callsite - +class MemBaseline VALUE_OBJ_CLASS_SPEC { public: - MallocCallsitePointer() { - _count = 0; - _amount = 0; - } - - MallocCallsitePointer(address pc) : MemPointer(pc) { - _count = 0; - _amount = 0; - } + enum BaselineThreshold { + SIZE_THRESHOLD = K // Only allocation size over this threshold will be baselined. + }; - MallocCallsitePointer& operator=(const MallocCallsitePointer& p) { - MemPointer::operator=(p); - _count = p.count(); - _amount = p.amount(); - return *this; - } + enum BaselineType { + Not_baselined, + Summary_baselined, + Detail_baselined + }; - inline void inc(size_t size) { - _count ++; - _amount += size; + enum SortingOrder { + by_address, // by memory address + by_size, // by memory size + by_site // by call site where the memory is allocated from }; - inline size_t count() const { - return _count; - } + private: + // All baseline data is stored in this arena + Arena* _arena; + + // Summary information + MallocMemorySnapshot* _malloc_memory_snapshot; + VirtualMemorySnapshot* _virtual_memory_snapshot; + + size_t _class_count; - inline size_t amount() const { - return _amount; - } -}; + // Allocation sites information + // Malloc allocation sites + LinkedListImpl + _malloc_sites; + + // All virtual memory allocations + LinkedListImpl + _virtual_memory_allocations; -// baselined virtual memory record aggregated by callsite -class VMCallsitePointer : public MemPointer { - private: - size_t _count; // number of invocation from this callsite - size_t _reserved_amount; // total reserved amount - size_t _committed_amount; // total committed amount + // Virtual memory allocations by allocation sites, always in by_address + // order + LinkedListImpl + _virtual_memory_sites; + + SortingOrder _malloc_sites_order; + SortingOrder _virtual_memory_sites_order; + + BaselineType _baseline_type; public: - VMCallsitePointer() { - _count = 0; - _reserved_amount = 0; - _committed_amount = 0; - } - - VMCallsitePointer(address pc) : MemPointer(pc) { - _count = 0; - _reserved_amount = 0; - _committed_amount = 0; - } - - VMCallsitePointer& operator=(const VMCallsitePointer& p) { - MemPointer::operator=(p); - _count = p.count(); - _reserved_amount = p.reserved_amount(); - _committed_amount = p.committed_amount(); - return *this; - } - - inline void inc(size_t reserved, size_t committed) { - _count ++; - _reserved_amount += reserved; - _committed_amount += committed; - } - - inline size_t count() const { - return _count; - } - - inline size_t reserved_amount() const { - return _reserved_amount; + // create a memory baseline + MemBaseline(): + _baseline_type(Not_baselined), + _class_count(0), + _arena(NULL), + _malloc_memory_snapshot(NULL), + _virtual_memory_snapshot(NULL), + _malloc_sites(NULL) { } - inline size_t committed_amount() const { - return _committed_amount; - } -}; - -// maps a memory type flag to readable name -typedef struct _memType2Name { - MEMFLAGS _flag; - const char* _name; -} MemType2Name; - - -// This class aggregates malloc'd records by memory type -class MallocMem VALUE_OBJ_CLASS_SPEC { - private: - MEMFLAGS _type; - - size_t _count; - size_t _amount; - - public: - MallocMem() { - _type = mtNone; - _count = 0; - _amount = 0; + ~MemBaseline() { + reset(); + if (_arena != NULL) { + delete _arena; + } } - MallocMem(MEMFLAGS flags) { - assert(HAS_VALID_MEMORY_TYPE(flags), "no type"); - _type = FLAGS_TO_MEMORY_TYPE(flags); - _count = 0; - _amount = 0; - } + bool baseline(bool summaryOnly = true); - inline void set_type(MEMFLAGS flag) { - _type = flag; - } + BaselineType baseline_type() const { return _baseline_type; } - inline void clear() { - _count = 0; - _amount = 0; - _type = mtNone; + MallocMemorySnapshot* malloc_memory_snapshot() const { + return _malloc_memory_snapshot; } - MallocMem& operator=(const MallocMem& m) { - assert(_type == m.type(), "different type"); - _count = m.count(); - _amount = m.amount(); - return *this; + VirtualMemorySnapshot* virtual_memory_snapshot() const { + return _virtual_memory_snapshot; } - inline void inc(size_t amt) { - _amount += amt; - _count ++; - } + MallocSiteIterator malloc_sites(SortingOrder order); + VirtualMemorySiteIterator virtual_memory_sites(SortingOrder order); - inline void reduce(size_t amt) { - assert(_amount >= amt, "Just check"); - _amount -= amt; - } - - inline void overwrite_counter(size_t count) { - _count = count; + // Virtual memory allocation iterator always returns in virtual memory + // base address order. + VirtualMemoryAllocationIterator virtual_memory_allocations() { + assert(!_virtual_memory_allocations.is_empty(), "Not detail baseline"); + return VirtualMemoryAllocationIterator(_virtual_memory_allocations.head()); } - inline MEMFLAGS type() const { - return _type; - } - - inline bool is_type(MEMFLAGS flags) const { - return FLAGS_TO_MEMORY_TYPE(flags) == _type; - } - - inline size_t count() const { - return _count; + // Total reserved memory = total malloc'd memory + total reserved virtual + // memory + size_t total_reserved_memory() const { + assert(baseline_type() != Not_baselined, "Not yet baselined"); + assert(_virtual_memory_snapshot != NULL, "No virtual memory snapshot"); + assert(_malloc_memory_snapshot != NULL, "No malloc memory snapshot"); + size_t amount = _malloc_memory_snapshot->total() + + _virtual_memory_snapshot->total_reserved(); + return amount; } - inline size_t amount() const { - return _amount; - } -}; - -// This class records live arena's memory usage -class ArenaMem : public MallocMem { - public: - ArenaMem(MEMFLAGS typeflag): MallocMem(typeflag) { - } - ArenaMem() { } -}; - -// This class aggregates virtual memory by its memory type -class VMMem VALUE_OBJ_CLASS_SPEC { - private: - MEMFLAGS _type; - - size_t _count; - size_t _reserved_amount; - size_t _committed_amount; - - public: - VMMem() { - _type = mtNone; - _count = 0; - _reserved_amount = 0; - _committed_amount = 0; + // Total committed memory = total malloc'd memory + total committed + // virtual memory + size_t total_committed_memory() const { + assert(baseline_type() != Not_baselined, "Not yet baselined"); + assert(_virtual_memory_snapshot != NULL, + "Not a snapshot"); + size_t amount = _malloc_memory_snapshot->total() + + _virtual_memory_snapshot->total_committed(); + return amount; } - VMMem(MEMFLAGS flags) { - assert(HAS_VALID_MEMORY_TYPE(flags), "no type"); - _type = FLAGS_TO_MEMORY_TYPE(flags); - _count = 0; - _reserved_amount = 0; - _committed_amount = 0; + size_t total_arena_memory() const { + assert(baseline_type() != Not_baselined, "Not yet baselined"); + assert(_malloc_memory_snapshot != NULL, "Not yet baselined"); + return _malloc_memory_snapshot->total_arena(); } - inline void clear() { - _type = mtNone; - _count = 0; - _reserved_amount = 0; - _committed_amount = 0; + size_t malloc_tracking_overhead() const { + assert(baseline_type() != Not_baselined, "Not yet baselined"); + return _malloc_memory_snapshot->malloc_overhead()->size(); } - inline void set_type(MEMFLAGS flags) { - _type = FLAGS_TO_MEMORY_TYPE(flags); + const MallocMemory* malloc_memory(MEMFLAGS flag) const { + assert(_malloc_memory_snapshot != NULL, "Not a snapshot"); + return _malloc_memory_snapshot->by_type(flag); } - VMMem& operator=(const VMMem& m) { - assert(_type == m.type(), "different type"); - - _count = m.count(); - _reserved_amount = m.reserved_amount(); - _committed_amount = m.committed_amount(); - return *this; + const VirtualMemory* virtual_memory(MEMFLAGS flag) const { + assert(_virtual_memory_snapshot != NULL, "Not a snapshot"); + return _virtual_memory_snapshot->by_type(flag); } - inline MEMFLAGS type() const { - return _type; - } - - inline bool is_type(MEMFLAGS flags) const { - return FLAGS_TO_MEMORY_TYPE(flags) == _type; - } - - inline void inc(size_t reserved_amt, size_t committed_amt) { - _reserved_amount += reserved_amt; - _committed_amount += committed_amt; - _count ++; - } - - inline size_t count() const { - return _count; - } - - inline size_t reserved_amount() const { - return _reserved_amount; + size_t class_count() const { + assert(baseline_type() != Not_baselined, "Not yet baselined"); + return _class_count; } - inline size_t committed_amount() const { - return _committed_amount; + size_t thread_count() const { + assert(baseline_type() != Not_baselined, "Not yet baselined"); + assert(_malloc_memory_snapshot != NULL, "Baselined?"); + return _malloc_memory_snapshot->thread_count(); } -}; - - - -#define NUMBER_OF_MEMORY_TYPE (mt_number_of_types + 1) - -class BaselineReporter; -class BaselineComparisonReporter; - -/* - * This class baselines current memory snapshot. - * A memory baseline summarizes memory usage by memory type, - * aggregates memory usage by callsites when detail tracking - * is on. - */ -class MemBaseline VALUE_OBJ_CLASS_SPEC { - friend class BaselineReporter; - friend class BaselineComparisonReporter; - - private: - // overall summaries - size_t _total_malloced; - size_t _total_vm_reserved; - size_t _total_vm_committed; - size_t _number_of_classes; - size_t _number_of_threads; - - // if it has properly baselined - bool _baselined; - - // we categorize memory into three categories within the memory type - MallocMem _malloc_data[NUMBER_OF_MEMORY_TYPE]; - VMMem _vm_data[NUMBER_OF_MEMORY_TYPE]; - ArenaMem _arena_data[NUMBER_OF_MEMORY_TYPE]; - - // memory records that aggregate memory usage by callsites. - // only available when detail tracking is on. - MemPointerArray* _malloc_cs; - MemPointerArray* _vm_cs; - // virtual memory map - MemPointerArray* _vm_map; - - private: - static MemType2Name MemType2NameMap[NUMBER_OF_MEMORY_TYPE]; - - private: - // should not use copy constructor - MemBaseline(MemBaseline& copy) { ShouldNotReachHere(); } - - // check and block at a safepoint - static inline void check_safepoint(JavaThread* thr); - - public: - // create a memory baseline - MemBaseline(); - - ~MemBaseline(); - - inline bool baselined() const { - return _baselined; - } - - MemBaseline& operator=(const MemBaseline& other); // reset the baseline for reuse - void clear(); - - // baseline the snapshot - bool baseline(MemSnapshot& snapshot, bool summary_only = true); - - bool baseline(const MemPointerArray* malloc_records, - const MemPointerArray* vm_records, - bool summary_only = true); + void reset() { + _baseline_type = Not_baselined; + _malloc_memory_snapshot = NULL; + _virtual_memory_snapshot = NULL; + _class_count = 0; - // total malloc'd memory of specified memory type - inline size_t malloc_amount(MEMFLAGS flag) const { - return _malloc_data[flag2index(flag)].amount(); - } - // number of malloc'd memory blocks of specified memory type - inline size_t malloc_count(MEMFLAGS flag) const { - return _malloc_data[flag2index(flag)].count(); - } - // total memory used by arenas of specified memory type - inline size_t arena_amount(MEMFLAGS flag) const { - return _arena_data[flag2index(flag)].amount(); - } - // number of arenas of specified memory type - inline size_t arena_count(MEMFLAGS flag) const { - return _arena_data[flag2index(flag)].count(); - } - // total reserved memory of specified memory type - inline size_t reserved_amount(MEMFLAGS flag) const { - return _vm_data[flag2index(flag)].reserved_amount(); - } - // total committed memory of specified memory type - inline size_t committed_amount(MEMFLAGS flag) const { - return _vm_data[flag2index(flag)].committed_amount(); - } - // total memory (malloc'd + mmap'd + arena) of specified - // memory type - inline size_t total_amount(MEMFLAGS flag) const { - int index = flag2index(flag); - return _malloc_data[index].amount() + - _vm_data[index].reserved_amount() + - _arena_data[index].amount(); + _malloc_sites = NULL; + _virtual_memory_sites = NULL; + _virtual_memory_allocations = NULL; + + if (_arena != NULL) { + _arena->destruct_contents(); + } } - /* overall summaries */ + private: + // Baseline summary information + bool baseline_summary(); - // total malloc'd memory in snapshot - inline size_t total_malloc_amount() const { - return _total_malloced; - } - // total mmap'd memory in snapshot - inline size_t total_reserved_amount() const { - return _total_vm_reserved; - } - // total committed memory in snapshot - inline size_t total_committed_amount() const { - return _total_vm_committed; - } - // number of loaded classes - inline size_t number_of_classes() const { - return _number_of_classes; - } - // number of running threads - inline size_t number_of_threads() const { - return _number_of_threads; - } - // lookup human readable name of a memory type - static const char* type2name(MEMFLAGS type); + // Baseline allocation sites (detail tracking only) + bool baseline_allocation_sites(); + + // Aggregate virtual memory allocation by allocation sites + bool aggregate_virtual_memory_allocation_sites(); - private: - // convert memory flag to the index to mapping table - int flag2index(MEMFLAGS flag) const; - - // reset baseline values - void reset(); - - // summarize the records in global snapshot - bool baseline_malloc_summary(const MemPointerArray* malloc_records); - bool baseline_vm_summary(const MemPointerArray* vm_records); - bool baseline_malloc_details(const MemPointerArray* malloc_records); - bool baseline_vm_details(const MemPointerArray* vm_records); + Arena* arena() { return _arena; } - // print a line of malloc'd memory aggregated by callsite - void print_malloc_callsite(outputStream* st, address pc, size_t size, - size_t count, int diff_amt, int diff_count) const; - // print a line of mmap'd memory aggregated by callsite - void print_vm_callsite(outputStream* st, address pc, size_t rsz, - size_t csz, int diff_rsz, int diff_csz) const; + // Sorting allocation sites in different orders + // Sort allocation sites in size order + void malloc_sites_to_size_order(); + // Sort allocation sites in call site address order + void malloc_sites_to_allocation_site_order(); - // sorting functions for raw records - static int malloc_sort_by_pc(const void* p1, const void* p2); - static int malloc_sort_by_addr(const void* p1, const void* p2); - - private: - // sorting functions for baselined records - static int bl_malloc_sort_by_size(const void* p1, const void* p2); - static int bl_vm_sort_by_size(const void* p1, const void* p2); - static int bl_malloc_sort_by_pc(const void* p1, const void* p2); - static int bl_vm_sort_by_pc(const void* p1, const void* p2); + // Sort allocation sites in reserved size order + void virtual_memory_sites_to_size_order(); + // Sort allocation sites in call site address order + void virtual_memory_sites_to_reservation_site_order(); }; +#endif // INCLUDE_NMT #endif // SHARE_VM_SERVICES_MEM_BASELINE_HPP diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/services/memPtr.cpp --- a/hotspot/src/share/vm/services/memPtr.cpp Fri Aug 29 10:47:32 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "precompiled.hpp" -#include "runtime/atomic.inline.hpp" -#include "services/memPtr.hpp" -#include "services/memTracker.hpp" - -volatile jint SequenceGenerator::_seq_number = 1; -volatile unsigned long SequenceGenerator::_generation = 1; -NOT_PRODUCT(jint SequenceGenerator::_max_seq_number = 1;) - -jint SequenceGenerator::next() { - jint seq = Atomic::add(1, &_seq_number); - if (seq < 0) { - MemTracker::shutdown(MemTracker::NMT_sequence_overflow); - } else { - NOT_PRODUCT(_max_seq_number = (seq > _max_seq_number) ? seq : _max_seq_number;) - } - return seq; -} - diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/services/memPtr.hpp --- a/hotspot/src/share/vm/services/memPtr.hpp Fri Aug 29 10:47:32 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,509 +0,0 @@ -/* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef SHARE_VM_SERVICES_MEM_PTR_HPP -#define SHARE_VM_SERVICES_MEM_PTR_HPP - -#include "memory/allocation.hpp" -#include "runtime/os.hpp" -#include "runtime/safepoint.hpp" - -/* - * global sequence generator that generates sequence numbers to serialize - * memory records. - */ -class SequenceGenerator : AllStatic { - public: - static jint next(); - - // peek last sequence number - static jint peek() { - return _seq_number; - } - - // reset sequence number - static void reset() { - assert(SafepointSynchronize::is_at_safepoint(), "Safepoint required"); - _seq_number = 1; - _generation ++; - }; - - static unsigned long current_generation() { return _generation; } - NOT_PRODUCT(static jint max_seq_num() { return _max_seq_number; }) - - private: - static volatile jint _seq_number; - static volatile unsigned long _generation; - NOT_PRODUCT(static jint _max_seq_number; ) -}; - -/* - * followings are the classes that are used to hold memory activity records in different stages. - * MemPointer - * |--------MemPointerRecord - * | - * |----MemPointerRecordEx - * | | - * | |-------SeqMemPointerRecordEx - * | - * |----SeqMemPointerRecord - * | - * |----VMMemRegion - * | - * |-----VMMemRegionEx - * - * - * prefix 'Seq' - sequenced, the record contains a sequence number - * surfix 'Ex' - extension, the record contains a caller's pc - * - * per-thread recorder : SeqMemPointerRecord(Ex) - * snapshot staging : SeqMemPointerRecord(Ex) - * snapshot : MemPointerRecord(Ex) and VMMemRegion(Ex) - * - */ - -/* - * class that wraps an address to a memory block, - * the memory pointer either points to a malloc'd - * memory block, or a mmap'd memory block - */ -class MemPointer VALUE_OBJ_CLASS_SPEC { - public: - MemPointer(): _addr(0) { } - MemPointer(address addr): _addr(addr) { } - - MemPointer(const MemPointer& copy_from) { - _addr = copy_from.addr(); - } - - inline address addr() const { - return _addr; - } - - inline operator address() const { - return addr(); - } - - inline bool operator == (const MemPointer& other) const { - return addr() == other.addr(); - } - - inline MemPointer& operator = (const MemPointer& other) { - _addr = other.addr(); - return *this; - } - - protected: - inline void set_addr(address addr) { _addr = addr; } - - protected: - // memory address - address _addr; -}; - -/* MemPointerRecord records an activityand associated - * attributes on a memory block. - */ -class MemPointerRecord : public MemPointer { - private: - MEMFLAGS _flags; - size_t _size; - -public: - /* extension of MemoryType enum - * see share/vm/memory/allocation.hpp for details. - * - * The tag values are associated to sorting orders, so be - * careful if changes are needed. - * The allocation records should be sorted ahead of tagging - * records, which in turn ahead of deallocation records - */ - enum MemPointerTags { - tag_alloc = 0x0001, // malloc or reserve record - tag_commit = 0x0002, // commit record - tag_type = 0x0003, // tag virtual memory to a memory type - tag_uncommit = 0x0004, // uncommit record - tag_release = 0x0005, // free or release record - tag_size = 0x0006, // arena size - tag_masks = 0x0007, // all tag bits - vmBit = 0x0008 - }; - - /* helper functions to interpret the tagging flags */ - - inline static bool is_allocation_record(MEMFLAGS flags) { - return (flags & tag_masks) == tag_alloc; - } - - inline static bool is_deallocation_record(MEMFLAGS flags) { - return (flags & tag_masks) == tag_release; - } - - inline static bool is_arena_record(MEMFLAGS flags) { - return (flags & (otArena | tag_size)) == otArena; - } - - inline static bool is_arena_memory_record(MEMFLAGS flags) { - return (flags & (otArena | tag_size)) == (otArena | tag_size); - } - - inline static bool is_virtual_memory_record(MEMFLAGS flags) { - return (flags & vmBit) != 0; - } - - inline static bool is_virtual_memory_reserve_record(MEMFLAGS flags) { - return (flags & 0x0F) == (tag_alloc | vmBit); - } - - inline static bool is_virtual_memory_commit_record(MEMFLAGS flags) { - return (flags & 0x0F) == (tag_commit | vmBit); - } - - inline static bool is_virtual_memory_uncommit_record(MEMFLAGS flags) { - return (flags & 0x0F) == (tag_uncommit | vmBit); - } - - inline static bool is_virtual_memory_release_record(MEMFLAGS flags) { - return (flags & 0x0F) == (tag_release | vmBit); - } - - inline static bool is_virtual_memory_type_record(MEMFLAGS flags) { - return (flags & 0x0F) == (tag_type | vmBit); - } - - /* tagging flags */ - inline static MEMFLAGS malloc_tag() { return tag_alloc; } - inline static MEMFLAGS free_tag() { return tag_release; } - inline static MEMFLAGS arena_size_tag() { return tag_size | otArena; } - inline static MEMFLAGS virtual_memory_tag() { return vmBit; } - inline static MEMFLAGS virtual_memory_reserve_tag() { return (tag_alloc | vmBit); } - inline static MEMFLAGS virtual_memory_commit_tag() { return (tag_commit | vmBit); } - inline static MEMFLAGS virtual_memory_uncommit_tag(){ return (tag_uncommit | vmBit); } - inline static MEMFLAGS virtual_memory_release_tag() { return (tag_release | vmBit); } - inline static MEMFLAGS virtual_memory_type_tag() { return (tag_type | vmBit); } - - public: - MemPointerRecord(): _size(0), _flags(mtNone) { } - - MemPointerRecord(address addr, MEMFLAGS memflags, size_t size = 0): - MemPointer(addr), _flags(memflags), _size(size) { } - - MemPointerRecord(const MemPointerRecord& copy_from): - MemPointer(copy_from), _flags(copy_from.flags()), - _size(copy_from.size()) { - } - - /* MemPointerRecord is not sequenced, it always return - * 0 to indicate non-sequenced - */ - virtual jint seq() const { return 0; } - - inline size_t size() const { return _size; } - inline void set_size(size_t size) { _size = size; } - - inline MEMFLAGS flags() const { return _flags; } - inline void set_flags(MEMFLAGS flags) { _flags = flags; } - - MemPointerRecord& operator= (const MemPointerRecord& ptr) { - MemPointer::operator=(ptr); - _flags = ptr.flags(); -#ifdef ASSERT - if (IS_ARENA_OBJ(_flags)) { - assert(!is_vm_pointer(), "wrong flags"); - assert((_flags & ot_masks) == otArena, "wrong flags"); - } -#endif - _size = ptr.size(); - return *this; - } - - // if the pointer represents a malloc-ed memory address - inline bool is_malloced_pointer() const { - return !is_vm_pointer(); - } - - // if the pointer represents a virtual memory address - inline bool is_vm_pointer() const { - return is_virtual_memory_record(_flags); - } - - // if this record records a 'malloc' or virtual memory - // 'reserve' call - inline bool is_allocation_record() const { - return is_allocation_record(_flags); - } - - // if this record records a size information of an arena - inline bool is_arena_memory_record() const { - return is_arena_memory_record(_flags); - } - - // if this pointer represents an address to an arena object - inline bool is_arena_record() const { - return is_arena_record(_flags); - } - - // if this record represents a size information of specific arena - inline bool is_memory_record_of_arena(const MemPointerRecord* arena_rc) { - assert(is_arena_memory_record(), "not size record"); - assert(arena_rc->is_arena_record(), "not arena record"); - return (arena_rc->addr() + sizeof(void*)) == addr(); - } - - // if this record records a 'free' or virtual memory 'free' call - inline bool is_deallocation_record() const { - return is_deallocation_record(_flags); - } - - // if this record records a virtual memory 'commit' call - inline bool is_commit_record() const { - return is_virtual_memory_commit_record(_flags); - } - - // if this record records a virtual memory 'uncommit' call - inline bool is_uncommit_record() const { - return is_virtual_memory_uncommit_record(_flags); - } - - // if this record is a tagging record of a virtual memory block - inline bool is_type_tagging_record() const { - return is_virtual_memory_type_record(_flags); - } - - // if the two memory pointer records actually represent the same - // memory block - inline bool is_same_region(const MemPointerRecord* other) const { - return (addr() == other->addr() && size() == other->size()); - } - - // if this memory region fully contains another one - inline bool contains_region(const MemPointerRecord* other) const { - return contains_region(other->addr(), other->size()); - } - - // if this memory region fully contains specified memory range - inline bool contains_region(address add, size_t sz) const { - return (addr() <= add && addr() + size() >= add + sz); - } - - inline bool contains_address(address add) const { - return (addr() <= add && addr() + size() > add); - } - - // if this memory region overlaps another region - inline bool overlaps_region(const MemPointerRecord* other) const { - assert(other != NULL, "Just check"); - assert(size() > 0 && other->size() > 0, "empty range"); - return contains_address(other->addr()) || - contains_address(other->addr() + other->size() - 1) || // exclude end address - other->contains_address(addr()) || - other->contains_address(addr() + size() - 1); // exclude end address - } - -}; - -// MemPointerRecordEx also records callsite pc, from where -// the memory block is allocated -class MemPointerRecordEx : public MemPointerRecord { - private: - address _pc; // callsite pc - - public: - MemPointerRecordEx(): _pc(0) { } - - MemPointerRecordEx(address addr, MEMFLAGS memflags, size_t size = 0, address pc = 0): - MemPointerRecord(addr, memflags, size), _pc(pc) {} - - MemPointerRecordEx(const MemPointerRecordEx& copy_from): - MemPointerRecord(copy_from), _pc(copy_from.pc()) {} - - inline address pc() const { return _pc; } - - void init(const MemPointerRecordEx* mpe) { - MemPointerRecord::operator=(*mpe); - _pc = mpe->pc(); - } - - void init(const MemPointerRecord* mp) { - MemPointerRecord::operator=(*mp); - _pc = 0; - } -}; - -// a virtual memory region. The region can represent a reserved -// virtual memory region or a committed memory region -class VMMemRegion : public MemPointerRecord { -public: - VMMemRegion() { } - - void init(const MemPointerRecord* mp) { - assert(mp->is_vm_pointer(), "Sanity check"); - _addr = mp->addr(); - set_size(mp->size()); - set_flags(mp->flags()); - } - - VMMemRegion& operator=(const VMMemRegion& other) { - MemPointerRecord::operator=(other); - return *this; - } - - inline bool is_reserved_region() const { - return is_allocation_record(); - } - - inline bool is_committed_region() const { - return is_commit_record(); - } - - /* base address of this virtual memory range */ - inline address base() const { - return addr(); - } - - /* tag this virtual memory range to the specified memory type */ - inline void tag(MEMFLAGS f) { - set_flags(flags() | (f & mt_masks)); - } - - // expand this region to also cover specified range. - // The range has to be on either end of the memory region. - void expand_region(address addr, size_t sz) { - if (addr < base()) { - assert(addr + sz == base(), "Sanity check"); - _addr = addr; - set_size(size() + sz); - } else { - assert(base() + size() == addr, "Sanity check"); - set_size(size() + sz); - } - } - - // exclude the specified address range from this region. - // The excluded memory range has to be on either end of this memory - // region. - inline void exclude_region(address add, size_t sz) { - assert(is_reserved_region() || is_committed_region(), "Sanity check"); - assert(addr() != NULL && size() != 0, "Sanity check"); - assert(add >= addr() && add < addr() + size(), "Sanity check"); - assert(add == addr() || (add + sz) == (addr() + size()), - "exclude in the middle"); - if (add == addr()) { - set_addr(add + sz); - set_size(size() - sz); - } else { - set_size(size() - sz); - } - } -}; - -class VMMemRegionEx : public VMMemRegion { - private: - jint _seq; // sequence number - - public: - VMMemRegionEx(): _pc(0) { } - - void init(const MemPointerRecordEx* mpe) { - VMMemRegion::init(mpe); - _pc = mpe->pc(); - } - - void init(const MemPointerRecord* mpe) { - VMMemRegion::init(mpe); - _pc = 0; - } - - VMMemRegionEx& operator=(const VMMemRegionEx& other) { - VMMemRegion::operator=(other); - _pc = other.pc(); - return *this; - } - - inline address pc() const { return _pc; } - private: - address _pc; -}; - -/* - * Sequenced memory record - */ -class SeqMemPointerRecord : public MemPointerRecord { - private: - jint _seq; // sequence number - - public: - SeqMemPointerRecord(): _seq(0){ } - - SeqMemPointerRecord(address addr, MEMFLAGS flags, size_t size, jint seq) - : MemPointerRecord(addr, flags, size), _seq(seq) { - } - - SeqMemPointerRecord(const SeqMemPointerRecord& copy_from) - : MemPointerRecord(copy_from) { - _seq = copy_from.seq(); - } - - SeqMemPointerRecord& operator= (const SeqMemPointerRecord& ptr) { - MemPointerRecord::operator=(ptr); - _seq = ptr.seq(); - return *this; - } - - inline jint seq() const { - return _seq; - } -}; - - - -class SeqMemPointerRecordEx : public MemPointerRecordEx { - private: - jint _seq; // sequence number - - public: - SeqMemPointerRecordEx(): _seq(0) { } - - SeqMemPointerRecordEx(address addr, MEMFLAGS flags, size_t size, - jint seq, address pc): - MemPointerRecordEx(addr, flags, size, pc), _seq(seq) { - } - - SeqMemPointerRecordEx(const SeqMemPointerRecordEx& copy_from) - : MemPointerRecordEx(copy_from) { - _seq = copy_from.seq(); - } - - SeqMemPointerRecordEx& operator= (const SeqMemPointerRecordEx& ptr) { - MemPointerRecordEx::operator=(ptr); - _seq = ptr.seq(); - return *this; - } - - inline jint seq() const { - return _seq; - } -}; - -#endif // SHARE_VM_SERVICES_MEM_PTR_HPP diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/services/memPtrArray.hpp --- a/hotspot/src/share/vm/services/memPtrArray.hpp Fri Aug 29 10:47:32 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,306 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -#ifndef SHARE_VM_UTILITIES_MEM_PTR_ARRAY_HPP -#define SHARE_VM_UTILITIES_MEM_PTR_ARRAY_HPP - -#include "memory/allocation.hpp" -#include "services/memPtr.hpp" - -class MemPtr; -class MemRecorder; -class ArenaInfo; -class MemSnapshot; - -extern "C" { - typedef int (*FN_SORT)(const void *, const void *); -} - - -// Memory pointer array interface. This array is used by NMT to hold -// various memory block information. -// The memory pointer arrays are usually walked with their iterators. - -class MemPointerArray : public CHeapObj { - public: - virtual ~MemPointerArray() { } - - // return true if it can not allocate storage for the data - virtual bool out_of_memory() const = 0; - virtual bool is_empty() const = 0; - virtual bool is_full() = 0; - virtual int length() const = 0; - virtual void clear() = 0; - virtual bool append(MemPointer* ptr) = 0; - virtual bool insert_at(MemPointer* ptr, int pos) = 0; - virtual bool remove_at(int pos) = 0; - virtual MemPointer* at(int index) const = 0; - virtual void sort(FN_SORT fn) = 0; - virtual size_t instance_size() const = 0; - virtual bool shrink() = 0; - - NOT_PRODUCT(virtual int capacity() const = 0;) -}; - -// Iterator interface -class MemPointerArrayIterator VALUE_OBJ_CLASS_SPEC { - public: - // return the pointer at current position - virtual MemPointer* current() const = 0; - // return the next pointer and advance current position - virtual MemPointer* next() = 0; - // return next pointer without advancing current position - virtual MemPointer* peek_next() const = 0; - // return previous pointer without changing current position - virtual MemPointer* peek_prev() const = 0; - // remove the pointer at current position - virtual void remove() = 0; - // insert the pointer at current position - virtual bool insert(MemPointer* ptr) = 0; - // insert specified element after current position and - // move current position to newly inserted position - virtual bool insert_after(MemPointer* ptr) = 0; -}; - -// implementation class -class MemPointerArrayIteratorImpl : public MemPointerArrayIterator { - protected: - MemPointerArray* _array; - int _pos; - - public: - MemPointerArrayIteratorImpl(MemPointerArray* arr) { - assert(arr != NULL, "Parameter check"); - _array = arr; - _pos = 0; - } - - virtual MemPointer* current() const { - if (_pos < _array->length()) { - return _array->at(_pos); - } - return NULL; - } - - virtual MemPointer* next() { - if (_pos + 1 < _array->length()) { - return _array->at(++_pos); - } - _pos = _array->length(); - return NULL; - } - - virtual MemPointer* peek_next() const { - if (_pos + 1 < _array->length()) { - return _array->at(_pos + 1); - } - return NULL; - } - - virtual MemPointer* peek_prev() const { - if (_pos > 0) { - return _array->at(_pos - 1); - } - return NULL; - } - - virtual void remove() { - if (_pos < _array->length()) { - _array->remove_at(_pos); - } - } - - virtual bool insert(MemPointer* ptr) { - return _array->insert_at(ptr, _pos); - } - - virtual bool insert_after(MemPointer* ptr) { - if (_array->insert_at(ptr, _pos + 1)) { - _pos ++; - return true; - } - return false; - } -}; - - - -// Memory pointer array implementation. -// This implementation implements expandable array -#define DEFAULT_PTR_ARRAY_SIZE 1024 - -template class MemPointerArrayImpl : public MemPointerArray { - private: - int _max_size; - int _size; - bool _init_elements; - E* _data; - - public: - MemPointerArrayImpl(int initial_size = DEFAULT_PTR_ARRAY_SIZE, bool init_elements = true): - _max_size(initial_size), _size(0), _init_elements(init_elements) { - _data = (E*)raw_allocate(sizeof(E), initial_size); - if (_init_elements) { - for (int index = 0; index < _max_size; index ++) { - ::new ((void*)&_data[index]) E(); - } - } - } - - virtual ~MemPointerArrayImpl() { - if (_data != NULL) { - raw_free(_data); - } - } - - public: - bool out_of_memory() const { - return (_data == NULL); - } - - size_t instance_size() const { - return sizeof(MemPointerArrayImpl) + _max_size * sizeof(E); - } - - bool is_empty() const { - assert(_data != NULL, "Just check"); - return _size == 0; - } - - bool is_full() { - assert(_data != NULL, "Just check"); - if (_size < _max_size) { - return false; - } else { - return !expand_array(); - } - } - - int length() const { - assert(_data != NULL, "Just check"); - return _size; - } - - NOT_PRODUCT(int capacity() const { return _max_size; }) - - void clear() { - assert(_data != NULL, "Just check"); - _size = 0; - } - - bool append(MemPointer* ptr) { - assert(_data != NULL, "Just check"); - if (is_full()) { - return false; - } - _data[_size ++] = *(E*)ptr; - return true; - } - - bool insert_at(MemPointer* ptr, int pos) { - assert(_data != NULL, "Just check"); - if (is_full()) { - return false; - } - for (int index = _size; index > pos; index --) { - _data[index] = _data[index - 1]; - } - _data[pos] = *(E*)ptr; - _size ++; - return true; - } - - bool remove_at(int pos) { - assert(_data != NULL, "Just check"); - if (_size <= pos && pos >= 0) { - return false; - } - -- _size; - - for (int index = pos; index < _size; index ++) { - _data[index] = _data[index + 1]; - } - return true; - } - - MemPointer* at(int index) const { - assert(_data != NULL, "Just check"); - assert(index >= 0 && index < _size, "illegal index"); - return &_data[index]; - } - - bool shrink() { - float used = ((float)_size) / ((float)_max_size); - if (used < 0.40) { - E* old_ptr = _data; - int new_size = ((_max_size) / (2 * DEFAULT_PTR_ARRAY_SIZE) + 1) * DEFAULT_PTR_ARRAY_SIZE; - _data = (E*)raw_reallocate(_data, sizeof(E), new_size); - if (_data == NULL) { - _data = old_ptr; - return false; - } else { - _max_size = new_size; - return true; - } - } - return false; - } - - void sort(FN_SORT fn) { - assert(_data != NULL, "Just check"); - qsort((void*)_data, _size, sizeof(E), fn); - } - - private: - bool expand_array() { - assert(_data != NULL, "Not yet allocated"); - E* old_ptr = _data; - if ((_data = (E*)raw_reallocate((void*)_data, sizeof(E), - _max_size + DEFAULT_PTR_ARRAY_SIZE)) == NULL) { - _data = old_ptr; - return false; - } else { - _max_size += DEFAULT_PTR_ARRAY_SIZE; - if (_init_elements) { - for (int index = _size; index < _max_size; index ++) { - ::new ((void*)&_data[index]) E(); - } - } - return true; - } - } - - void* raw_allocate(size_t elementSize, int items) { - return os::malloc(elementSize * items, mtNMT); - } - - void* raw_reallocate(void* ptr, size_t elementSize, int items) { - return os::realloc(ptr, elementSize * items, mtNMT); - } - - void raw_free(void* ptr) { - os::free(ptr, mtNMT); - } -}; - -#endif // SHARE_VM_UTILITIES_MEM_PTR_ARRAY_HPP diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/services/memRecorder.cpp --- a/hotspot/src/share/vm/services/memRecorder.cpp Fri Aug 29 10:47:32 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,171 +0,0 @@ -/* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "precompiled.hpp" - -#include "runtime/atomic.inline.hpp" -#include "services/memBaseline.hpp" -#include "services/memRecorder.hpp" -#include "services/memPtr.hpp" -#include "services/memTracker.hpp" - -MemPointer* SequencedRecordIterator::next_record() { - MemPointerRecord* itr_cur = (MemPointerRecord*)_itr.current(); - if (itr_cur == NULL) { - return itr_cur; - } - - MemPointerRecord* itr_next = (MemPointerRecord*)_itr.next(); - - // don't collapse virtual memory records - while (itr_next != NULL && !itr_cur->is_vm_pointer() && - !itr_next->is_vm_pointer() && - same_kind(itr_cur, itr_next)) { - itr_cur = itr_next; - itr_next = (MemPointerRecord*)_itr.next(); - } - - return itr_cur; -} - - -volatile jint MemRecorder::_instance_count = 0; - -MemRecorder::MemRecorder() { - assert(MemTracker::is_on(), "Native memory tracking is off"); - Atomic::inc(&_instance_count); - set_generation(); - - if (MemTracker::track_callsite()) { - _pointer_records = new (std::nothrow)FixedSizeMemPointerArray(); - } else { - _pointer_records = new (std::nothrow)FixedSizeMemPointerArray(); - } - _next = NULL; - - - if (_pointer_records != NULL) { - // recode itself - address pc = CURRENT_PC; - record((address)this, (MemPointerRecord::malloc_tag()|mtNMT|otNMTRecorder), - sizeof(MemRecorder), SequenceGenerator::next(), pc); - record((address)_pointer_records, (MemPointerRecord::malloc_tag()|mtNMT|otNMTRecorder), - _pointer_records->instance_size(), SequenceGenerator::next(), pc); - } -} - -MemRecorder::~MemRecorder() { - if (_pointer_records != NULL) { - if (MemTracker::is_on()) { - MemTracker::record_free((address)_pointer_records, mtNMT); - MemTracker::record_free((address)this, mtNMT); - } - delete _pointer_records; - } - // delete all linked recorders - while (_next != NULL) { - MemRecorder* tmp = _next; - _next = _next->next(); - tmp->set_next(NULL); - delete tmp; - } - Atomic::dec(&_instance_count); -} - -// Sorting order: -// 1. memory block address -// 2. mem pointer record tags -// 3. sequence number -int MemRecorder::sort_record_fn(const void* e1, const void* e2) { - const MemPointerRecord* p1 = (const MemPointerRecord*)e1; - const MemPointerRecord* p2 = (const MemPointerRecord*)e2; - int delta = UNSIGNED_COMPARE(p1->addr(), p2->addr()); - if (delta == 0) { - int df = UNSIGNED_COMPARE((p1->flags() & MemPointerRecord::tag_masks), - (p2->flags() & MemPointerRecord::tag_masks)); - if (df == 0) { - assert(p1->seq() != p2->seq(), "dup seq"); - return p1->seq() - p2->seq(); - } else { - return df; - } - } else { - return delta; - } -} - -bool MemRecorder::record(address p, MEMFLAGS flags, size_t size, jint seq, address pc) { - assert(seq > 0, "No sequence number"); -#ifdef ASSERT - if (MemPointerRecord::is_virtual_memory_record(flags)) { - assert((flags & MemPointerRecord::tag_masks) != 0, "bad virtual memory record"); - } else { - assert((flags & MemPointerRecord::tag_masks) == MemPointerRecord::malloc_tag() || - (flags & MemPointerRecord::tag_masks) == MemPointerRecord::free_tag() || - IS_ARENA_OBJ(flags), - "bad malloc record"); - } - // a recorder should only hold records within the same generation - unsigned long cur_generation = SequenceGenerator::current_generation(); - assert(cur_generation == _generation, - "this thread did not enter sync point"); -#endif - - if (MemTracker::track_callsite()) { - SeqMemPointerRecordEx ap(p, flags, size, seq, pc); - debug_only(check_dup_seq(ap.seq());) - return _pointer_records->append(&ap); - } else { - SeqMemPointerRecord ap(p, flags, size, seq); - debug_only(check_dup_seq(ap.seq());) - return _pointer_records->append(&ap); - } -} - - // iterator for alloc pointers -SequencedRecordIterator MemRecorder::pointer_itr() { - assert(_pointer_records != NULL, "just check"); - _pointer_records->sort((FN_SORT)sort_record_fn); - return SequencedRecordIterator(_pointer_records); -} - - -void MemRecorder::set_generation() { - _generation = SequenceGenerator::current_generation(); -} - -#ifdef ASSERT - -void MemRecorder::check_dup_seq(jint seq) const { - MemPointerArrayIteratorImpl itr(_pointer_records); - MemPointerRecord* rc = (MemPointerRecord*)itr.current(); - while (rc != NULL) { - assert(rc->seq() != seq, "dup seq"); - rc = (MemPointerRecord*)itr.next(); - } -} - -#endif diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/services/memRecorder.hpp --- a/hotspot/src/share/vm/services/memRecorder.hpp Fri Aug 29 10:47:32 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,271 +0,0 @@ -/* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef SHARE_VM_SERVICES_MEM_RECORDER_HPP -#define SHARE_VM_SERVICES_MEM_RECORDER_HPP - -#include "memory/allocation.hpp" -#include "runtime/os.hpp" -#include "services/memPtrArray.hpp" - -class MemSnapshot; -class MemTracker; -class MemTrackWorker; - -// Fixed size memory pointer array implementation -template class FixedSizeMemPointerArray : - public MemPointerArray { - // This implementation is for memory recorder only - friend class MemRecorder; - - private: - E _data[SIZE]; - int _size; - - protected: - FixedSizeMemPointerArray(bool init_elements = false): - _size(0){ - if (init_elements) { - for (int index = 0; index < SIZE; index ++) { - ::new ((void*)&_data[index]) E(); - } - } - } - - void* operator new(size_t size, const std::nothrow_t& nothrow_constant) throw() { - // the instance is part of memRecorder, needs to be tagged with 'otNMTRecorder' - // to avoid recursion - return os::malloc(size, (mtNMT | otNMTRecorder)); - } - - void* operator new(size_t size) throw() { - assert(false, "use nothrow version"); - return NULL; - } - - void operator delete(void* p) { - os::free(p, (mtNMT | otNMTRecorder)); - } - - // instance size - inline size_t instance_size() const { - return sizeof(FixedSizeMemPointerArray); - } - - NOT_PRODUCT(int capacity() const { return SIZE; }) - - public: - // implementation of public interface - bool out_of_memory() const { return false; } - bool is_empty() const { return _size == 0; } - bool is_full() { return length() >= SIZE; } - int length() const { return _size; } - - void clear() { - _size = 0; - } - - bool append(MemPointer* ptr) { - if (is_full()) return false; - _data[_size ++] = *(E*)ptr; - return true; - } - - virtual bool insert_at(MemPointer* p, int pos) { - assert(false, "append only"); - return false; - } - - virtual bool remove_at(int pos) { - assert(false, "not supported"); - return false; - } - - MemPointer* at(int index) const { - assert(index >= 0 && index < length(), - "parameter check"); - return ((E*)&_data[index]); - } - - void sort(FN_SORT fn) { - qsort((void*)_data, _size, sizeof(E), fn); - } - - bool shrink() { - return false; - } -}; - - -// This iterator requires pre-sorted MemPointerArray, which is sorted by: -// 1. address -// 2. allocation type -// 3. sequence number -// During the array walking, iterator collapses pointers with the same -// address and allocation type, and only returns the one with highest -// sequence number. -// -// This is read-only iterator, update methods are asserted. -class SequencedRecordIterator : public MemPointerArrayIterator { - private: - MemPointerArrayIteratorImpl _itr; - MemPointer* _cur; - - public: - SequencedRecordIterator(const MemPointerArray* arr): - _itr(const_cast(arr)) { - _cur = next_record(); - } - - SequencedRecordIterator(const SequencedRecordIterator& itr): - _itr(itr._itr) { - _cur = next_record(); - } - - // return the pointer at current position - virtual MemPointer* current() const { - return _cur; - }; - - // return the next pointer and advance current position - virtual MemPointer* next() { - _cur = next_record(); - return _cur; - } - - // return the next pointer without advancing current position - virtual MemPointer* peek_next() const { - assert(false, "not implemented"); - return NULL; - - } - // return the previous pointer without changing current position - virtual MemPointer* peek_prev() const { - assert(false, "not implemented"); - return NULL; - } - - // remove the pointer at current position - virtual void remove() { - assert(false, "read-only iterator"); - }; - // insert the pointer at current position - virtual bool insert(MemPointer* ptr) { - assert(false, "read-only iterator"); - return false; - } - - virtual bool insert_after(MemPointer* ptr) { - assert(false, "read-only iterator"); - return false; - } - private: - // collapse the 'same kind' of records, and return this 'kind' of - // record with highest sequence number - MemPointer* next_record(); - - // Test if the two records are the same kind: the same memory block and allocation - // type. - inline bool same_kind(const MemPointerRecord* p1, const MemPointerRecord* p2) const { - assert(!p1->is_vm_pointer() && !p2->is_vm_pointer(), "malloc pointer only"); - return (p1->addr() == p2->addr() && - (p1->flags() &MemPointerRecord::tag_masks) == - (p2->flags() & MemPointerRecord::tag_masks)); - } -}; - - - -#define DEFAULT_RECORDER_PTR_ARRAY_SIZE 512 - -class MemRecorder : public CHeapObj { - friend class MemSnapshot; - friend class MemTracker; - friend class MemTrackWorker; - friend class GenerationData; - - protected: - // the array that holds memory records - MemPointerArray* _pointer_records; - - private: - // used for linked list - MemRecorder* _next; - // active recorder can only record a certain generation data - unsigned long _generation; - - protected: - _NOINLINE_ MemRecorder(); - ~MemRecorder(); - - // record a memory operation - bool record(address addr, MEMFLAGS flags, size_t size, jint seq, address caller_pc = 0); - - // linked list support - inline void set_next(MemRecorder* rec) { - _next = rec; - } - - inline MemRecorder* next() const { - return _next; - } - - // if the recorder is full - inline bool is_full() const { - assert(_pointer_records != NULL, "just check"); - return _pointer_records->is_full(); - } - - // if running out of memory when initializing recorder's internal - // data - inline bool out_of_memory() const { - return (_pointer_records == NULL || - _pointer_records->out_of_memory()); - } - - inline void clear() { - assert(_pointer_records != NULL, "Just check"); - _pointer_records->clear(); - } - - SequencedRecordIterator pointer_itr(); - - // return the generation of this recorder which it belongs to - unsigned long get_generation() const { return _generation; } - protected: - // number of MemRecorder instance - static volatile jint _instance_count; - - private: - // sorting function, sort records into following order - // 1. memory address - // 2. allocation type - // 3. sequence number - static int sort_record_fn(const void* e1, const void* e2); - - debug_only(void check_dup_seq(jint seq) const;) - void set_generation(); -}; - -#endif // SHARE_VM_SERVICES_MEM_RECORDER_HPP diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/services/memReporter.cpp --- a/hotspot/src/share/vm/services/memReporter.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/services/memReporter.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -22,618 +22,595 @@ * */ #include "precompiled.hpp" -#include "classfile/systemDictionary.hpp" -#include "runtime/os.hpp" + +#include "memory/allocation.hpp" +#include "services/mallocTracker.hpp" #include "services/memReporter.hpp" -#include "services/memPtrArray.hpp" -#include "services/memTracker.hpp" +#include "services/virtualMemoryTracker.hpp" +#include "utilities/globalDefinitions.hpp" + +size_t MemReporterBase::reserved_total(const MallocMemory* malloc, const VirtualMemory* vm) const { + return malloc->malloc_size() + malloc->arena_size() + vm->reserved(); +} + +size_t MemReporterBase::committed_total(const MallocMemory* malloc, const VirtualMemory* vm) const { + return malloc->malloc_size() + malloc->arena_size() + vm->committed(); +} -PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC +void MemReporterBase::print_total(size_t reserved, size_t committed) const { + const char* scale = current_scale(); + output()->print("reserved=" SIZE_FORMAT "%s, committed=" SIZE_FORMAT "%s", + amount_in_current_scale(reserved), scale, amount_in_current_scale(committed), scale); +} + +void MemReporterBase::print_malloc(size_t amount, size_t count) const { + const char* scale = current_scale(); + outputStream* out = output(); + out->print("(malloc=" SIZE_FORMAT "%s", + amount_in_current_scale(amount), scale); + + if (count > 0) { + out->print(" #" SIZE_FORMAT "", count); + } -const char* BaselineOutputer::memory_unit(size_t scale) { - switch(scale) { - case K: return "KB"; - case M: return "MB"; - case G: return "GB"; - } - ShouldNotReachHere(); - return NULL; + out->print(")"); +} + +void MemReporterBase::print_virtual_memory(size_t reserved, size_t committed) const { + const char* scale = current_scale(); + output()->print("(mmap: reserved=" SIZE_FORMAT "%s, committed=" SIZE_FORMAT "%s)", + amount_in_current_scale(reserved), scale, amount_in_current_scale(committed), scale); +} + +void MemReporterBase::print_malloc_line(size_t amount, size_t count) const { + output()->print("%28s", " "); + print_malloc(amount, count); + output()->print_cr(" "); +} + +void MemReporterBase::print_virtual_memory_line(size_t reserved, size_t committed) const { + output()->print("%28s", " "); + print_virtual_memory(reserved, committed); + output()->print_cr(" "); +} + +void MemReporterBase::print_arena_line(size_t amount, size_t count) const { + const char* scale = current_scale(); + output()->print_cr("%27s (arena=" SIZE_FORMAT "%s #" SIZE_FORMAT ")", " ", + amount_in_current_scale(amount), scale, count); +} + +void MemReporterBase::print_virtual_memory_region(const char* type, address base, size_t size) const { + const char* scale = current_scale(); + output()->print("[" PTR_FORMAT " - " PTR_FORMAT "] %s " SIZE_FORMAT "%s", + p2i(base), p2i(base + size), type, amount_in_current_scale(size), scale); } -void BaselineReporter::report_baseline(const MemBaseline& baseline, bool summary_only) { - assert(MemTracker::is_on(), "Native memory tracking is off"); - _outputer.start(scale()); - _outputer.total_usage( - amount_in_current_scale(baseline.total_malloc_amount() + baseline.total_reserved_amount()), - amount_in_current_scale(baseline.total_malloc_amount() + baseline.total_committed_amount())); - - _outputer.num_of_classes(baseline.number_of_classes()); - _outputer.num_of_threads(baseline.number_of_threads()); - - report_summaries(baseline); - if (!summary_only && MemTracker::track_callsite()) { - report_virtual_memory_map(baseline); - report_callsites(baseline); - } - _outputer.done(); -} - -void BaselineReporter::report_summaries(const MemBaseline& baseline) { - _outputer.start_category_summary(); - MEMFLAGS type; +void MemSummaryReporter::report() { + const char* scale = current_scale(); + outputStream* out = output(); + size_t total_reserved_amount = _malloc_snapshot->total() + + _vm_snapshot->total_reserved(); + size_t total_committed_amount = _malloc_snapshot->total() + + _vm_snapshot->total_committed(); - for (int index = 0; index < NUMBER_OF_MEMORY_TYPE; index ++) { - type = MemBaseline::MemType2NameMap[index]._flag; - _outputer.category_summary(type, - amount_in_current_scale(baseline.reserved_amount(type)), - amount_in_current_scale(baseline.committed_amount(type)), - amount_in_current_scale(baseline.malloc_amount(type)), - baseline.malloc_count(type), - amount_in_current_scale(baseline.arena_amount(type)), - baseline.arena_count(type)); - } - - _outputer.done_category_summary(); -} + // Overall total + out->print_cr("\nNative Memory Tracking:\n"); + out->print("Total: "); + print_total(total_reserved_amount, total_committed_amount); + out->print("\n"); -void BaselineReporter::report_virtual_memory_map(const MemBaseline& baseline) { - _outputer.start_virtual_memory_map(); - MemBaseline* pBL = const_cast(&baseline); - MemPointerArrayIteratorImpl itr = MemPointerArrayIteratorImpl(pBL->_vm_map); - VMMemRegionEx* rgn = (VMMemRegionEx*)itr.current(); - while (rgn != NULL) { - if (rgn->is_reserved_region()) { - _outputer.reserved_memory_region(FLAGS_TO_MEMORY_TYPE(rgn->flags()), - rgn->base(), rgn->base() + rgn->size(), amount_in_current_scale(rgn->size()), rgn->pc()); - } else { - _outputer.committed_memory_region(rgn->base(), rgn->base() + rgn->size(), - amount_in_current_scale(rgn->size()), rgn->pc()); - } - rgn = (VMMemRegionEx*)itr.next(); + // Summary by memory type + for (int index = 0; index < mt_number_of_types; index ++) { + MEMFLAGS flag = NMTUtil::index_to_flag(index); + // thread stack is reported as part of thread category + if (flag == mtThreadStack) continue; + MallocMemory* malloc_memory = _malloc_snapshot->by_type(flag); + VirtualMemory* virtual_memory = _vm_snapshot->by_type(flag); + + report_summary_of_type(flag, malloc_memory, virtual_memory); } - - _outputer.done_virtual_memory_map(); } -void BaselineReporter::report_callsites(const MemBaseline& baseline) { - _outputer.start_callsite(); - MemBaseline* pBL = const_cast(&baseline); +void MemSummaryReporter::report_summary_of_type(MEMFLAGS flag, + MallocMemory* malloc_memory, VirtualMemory* virtual_memory) { - pBL->_malloc_cs->sort((FN_SORT)MemBaseline::bl_malloc_sort_by_size); - pBL->_vm_cs->sort((FN_SORT)MemBaseline::bl_vm_sort_by_size); + size_t reserved_amount = reserved_total (malloc_memory, virtual_memory); + size_t committed_amount = committed_total(malloc_memory, virtual_memory); - // walk malloc callsites - MemPointerArrayIteratorImpl malloc_itr(pBL->_malloc_cs); - MallocCallsitePointer* malloc_callsite = - (MallocCallsitePointer*)malloc_itr.current(); - while (malloc_callsite != NULL) { - _outputer.malloc_callsite(malloc_callsite->addr(), - amount_in_current_scale(malloc_callsite->amount()), malloc_callsite->count()); - malloc_callsite = (MallocCallsitePointer*)malloc_itr.next(); + // Count thread's native stack in "Thread" category + if (flag == mtThread) { + const VirtualMemory* thread_stack_usage = + (const VirtualMemory*)_vm_snapshot->by_type(mtThreadStack); + reserved_amount += thread_stack_usage->reserved(); + committed_amount += thread_stack_usage->committed(); + } else if (flag == mtNMT) { + // Count malloc headers in "NMT" category + reserved_amount += _malloc_snapshot->malloc_overhead()->size(); + committed_amount += _malloc_snapshot->malloc_overhead()->size(); } - // walk virtual memory callsite - MemPointerArrayIteratorImpl vm_itr(pBL->_vm_cs); - VMCallsitePointer* vm_callsite = (VMCallsitePointer*)vm_itr.current(); - while (vm_callsite != NULL) { - _outputer.virtual_memory_callsite(vm_callsite->addr(), - amount_in_current_scale(vm_callsite->reserved_amount()), - amount_in_current_scale(vm_callsite->committed_amount())); - vm_callsite = (VMCallsitePointer*)vm_itr.next(); - } - pBL->_malloc_cs->sort((FN_SORT)MemBaseline::bl_malloc_sort_by_pc); - pBL->_vm_cs->sort((FN_SORT)MemBaseline::bl_vm_sort_by_pc); - _outputer.done_callsite(); -} + if (amount_in_current_scale(reserved_amount) > 0) { + outputStream* out = output(); + const char* scale = current_scale(); + out->print("-%26s (", NMTUtil::flag_to_name(flag)); + print_total(reserved_amount, committed_amount); + out->print_cr(")"); -void BaselineReporter::diff_baselines(const MemBaseline& cur, const MemBaseline& prev, - bool summary_only) { - assert(MemTracker::is_on(), "Native memory tracking is off"); - _outputer.start(scale()); - size_t total_reserved = cur.total_malloc_amount() + cur.total_reserved_amount(); - size_t total_committed = cur.total_malloc_amount() + cur.total_committed_amount(); - - _outputer.diff_total_usage( - amount_in_current_scale(total_reserved), amount_in_current_scale(total_committed), - diff_in_current_scale(total_reserved, (prev.total_malloc_amount() + prev.total_reserved_amount())), - diff_in_current_scale(total_committed, (prev.total_committed_amount() + prev.total_malloc_amount()))); + if (flag == mtClass) { + // report class count + out->print_cr("%27s (classes #" SIZE_FORMAT ")", " ", _class_count); + } else if (flag == mtThread) { + // report thread count + out->print_cr("%27s (thread #" SIZE_FORMAT ")", " ", _malloc_snapshot->thread_count()); + const VirtualMemory* thread_stack_usage = + _vm_snapshot->by_type(mtThreadStack); + out->print("%27s (stack: ", " "); + print_total(thread_stack_usage->reserved(), thread_stack_usage->committed()); + out->print_cr(")"); + } - _outputer.diff_num_of_classes(cur.number_of_classes(), - diff(cur.number_of_classes(), prev.number_of_classes())); - _outputer.diff_num_of_threads(cur.number_of_threads(), - diff(cur.number_of_threads(), prev.number_of_threads())); + // report malloc'd memory + if (amount_in_current_scale(malloc_memory->malloc_size()) > 0) { + // We don't know how many arena chunks are in used, so don't report the count + size_t count = (flag == mtChunk) ? 0 : malloc_memory->malloc_count(); + print_malloc_line(malloc_memory->malloc_size(), count); + } - diff_summaries(cur, prev); - if (!summary_only && MemTracker::track_callsite()) { - diff_callsites(cur, prev); - } - _outputer.done(); -} - -void BaselineReporter::diff_summaries(const MemBaseline& cur, const MemBaseline& prev) { - _outputer.start_category_summary(); - MEMFLAGS type; + if (amount_in_current_scale(virtual_memory->reserved()) > 0) { + print_virtual_memory_line(virtual_memory->reserved(), virtual_memory->committed()); + } - for (int index = 0; index < NUMBER_OF_MEMORY_TYPE; index ++) { - type = MemBaseline::MemType2NameMap[index]._flag; - _outputer.diff_category_summary(type, - amount_in_current_scale(cur.reserved_amount(type)), - amount_in_current_scale(cur.committed_amount(type)), - amount_in_current_scale(cur.malloc_amount(type)), - cur.malloc_count(type), - amount_in_current_scale(cur.arena_amount(type)), - cur.arena_count(type), - diff_in_current_scale(cur.reserved_amount(type), prev.reserved_amount(type)), - diff_in_current_scale(cur.committed_amount(type), prev.committed_amount(type)), - diff_in_current_scale(cur.malloc_amount(type), prev.malloc_amount(type)), - diff(cur.malloc_count(type), prev.malloc_count(type)), - diff_in_current_scale(cur.arena_amount(type), prev.arena_amount(type)), - diff(cur.arena_count(type), prev.arena_count(type))); + if (amount_in_current_scale(malloc_memory->arena_size()) > 0) { + print_arena_line(malloc_memory->arena_size(), malloc_memory->arena_count()); + } + + if (flag == mtNMT && + amount_in_current_scale(_malloc_snapshot->malloc_overhead()->size()) > 0) { + out->print_cr("%27s (tracking overhead=" SIZE_FORMAT "%s)", " ", + amount_in_current_scale(_malloc_snapshot->malloc_overhead()->size()), scale); + } + + out->print_cr(" "); } - - _outputer.done_category_summary(); } -void BaselineReporter::diff_callsites(const MemBaseline& cur, const MemBaseline& prev) { - _outputer.start_callsite(); - MemBaseline* pBL_cur = const_cast(&cur); - MemBaseline* pBL_prev = const_cast(&prev); +void MemDetailReporter::report_detail() { + // Start detail report + outputStream* out = output(); + out->print_cr("Details:\n"); + + report_malloc_sites(); + report_virtual_memory_allocation_sites(); +} + +void MemDetailReporter::report_malloc_sites() { + MallocSiteIterator malloc_itr = _baseline.malloc_sites(MemBaseline::by_size); + if (malloc_itr.is_empty()) return; + + outputStream* out = output(); - // walk malloc callsites - MemPointerArrayIteratorImpl cur_malloc_itr(pBL_cur->_malloc_cs); - MemPointerArrayIteratorImpl prev_malloc_itr(pBL_prev->_malloc_cs); + const MallocSite* malloc_site; + while ((malloc_site = malloc_itr.next()) != NULL) { + // Don't report if size is too small + if (amount_in_current_scale(malloc_site->size()) == 0) + continue; - MallocCallsitePointer* cur_malloc_callsite = - (MallocCallsitePointer*)cur_malloc_itr.current(); - MallocCallsitePointer* prev_malloc_callsite = - (MallocCallsitePointer*)prev_malloc_itr.current(); + const NativeCallStack* stack = malloc_site->call_stack(); + stack->print_on(out); + out->print("%29s", " "); + print_malloc(malloc_site->size(), malloc_site->count()); + out->print_cr("\n"); + } +} + +void MemDetailReporter::report_virtual_memory_allocation_sites() { + VirtualMemorySiteIterator virtual_memory_itr = + _baseline.virtual_memory_sites(MemBaseline::by_size); + + if (virtual_memory_itr.is_empty()) return; + + outputStream* out = output(); + const VirtualMemoryAllocationSite* virtual_memory_site; - while (cur_malloc_callsite != NULL || prev_malloc_callsite != NULL) { - if (prev_malloc_callsite == NULL) { - assert(cur_malloc_callsite != NULL, "sanity check"); - // this is a new callsite - _outputer.diff_malloc_callsite(cur_malloc_callsite->addr(), - amount_in_current_scale(cur_malloc_callsite->amount()), - cur_malloc_callsite->count(), - diff_in_current_scale(cur_malloc_callsite->amount(), 0), - diff(cur_malloc_callsite->count(), 0)); - cur_malloc_callsite = (MallocCallsitePointer*)cur_malloc_itr.next(); - } else if (cur_malloc_callsite == NULL) { - assert(prev_malloc_callsite != NULL, "Sanity check"); - // this callsite is already gone - _outputer.diff_malloc_callsite(prev_malloc_callsite->addr(), - 0, 0, - diff_in_current_scale(0, prev_malloc_callsite->amount()), - diff(0, prev_malloc_callsite->count())); - prev_malloc_callsite = (MallocCallsitePointer*)prev_malloc_itr.next(); - } else { - assert(cur_malloc_callsite != NULL, "Sanity check"); - assert(prev_malloc_callsite != NULL, "Sanity check"); - if (cur_malloc_callsite->addr() < prev_malloc_callsite->addr()) { - // this is a new callsite - _outputer.diff_malloc_callsite(cur_malloc_callsite->addr(), - amount_in_current_scale(cur_malloc_callsite->amount()), - cur_malloc_callsite->count(), - diff_in_current_scale(cur_malloc_callsite->amount(), 0), - diff(cur_malloc_callsite->count(), 0)); - cur_malloc_callsite = (MallocCallsitePointer*)cur_malloc_itr.next(); - } else if (cur_malloc_callsite->addr() > prev_malloc_callsite->addr()) { - // this callsite is already gone - _outputer.diff_malloc_callsite(prev_malloc_callsite->addr(), - 0, 0, - diff_in_current_scale(0, prev_malloc_callsite->amount()), - diff(0, prev_malloc_callsite->count())); - prev_malloc_callsite = (MallocCallsitePointer*)prev_malloc_itr.next(); - } else { - // the same callsite - _outputer.diff_malloc_callsite(cur_malloc_callsite->addr(), - amount_in_current_scale(cur_malloc_callsite->amount()), - cur_malloc_callsite->count(), - diff_in_current_scale(cur_malloc_callsite->amount(), prev_malloc_callsite->amount()), - diff(cur_malloc_callsite->count(), prev_malloc_callsite->count())); - cur_malloc_callsite = (MallocCallsitePointer*)cur_malloc_itr.next(); - prev_malloc_callsite = (MallocCallsitePointer*)prev_malloc_itr.next(); - } - } + while ((virtual_memory_site = virtual_memory_itr.next()) != NULL) { + // Don't report if size is too small + if (amount_in_current_scale(virtual_memory_site->reserved()) == 0) + continue; + + const NativeCallStack* stack = virtual_memory_site->call_stack(); + stack->print_on(out); + out->print("%28s (", " "); + print_total(virtual_memory_site->reserved(), virtual_memory_site->committed()); + out->print_cr(")\n"); + } +} + + +void MemDetailReporter::report_virtual_memory_map() { + // Virtual memory map always in base address order + VirtualMemoryAllocationIterator itr = _baseline.virtual_memory_allocations(); + const ReservedMemoryRegion* rgn; + + output()->print_cr("Virtual memory map:"); + while ((rgn = itr.next()) != NULL) { + report_virtual_memory_region(rgn); + } +} + +void MemDetailReporter::report_virtual_memory_region(const ReservedMemoryRegion* reserved_rgn) { + assert(reserved_rgn != NULL, "NULL pointer"); + + // Don't report if size is too small + if (amount_in_current_scale(reserved_rgn->size()) == 0) return; + + outputStream* out = output(); + const char* scale = current_scale(); + const NativeCallStack* stack = reserved_rgn->call_stack(); + bool all_committed = reserved_rgn->all_committed(); + const char* region_type = (all_committed ? "reserved and committed" : "reserved"); + out->print_cr(" "); + print_virtual_memory_region(region_type, reserved_rgn->base(), reserved_rgn->size()); + out->print(" for %s", NMTUtil::flag_to_name(reserved_rgn->flag())); + if (stack->is_empty()) { + out->print_cr(" "); + } else { + out->print_cr(" from"); + stack->print_on(out, 4); } - // walk virtual memory callsite - MemPointerArrayIteratorImpl cur_vm_itr(pBL_cur->_vm_cs); - MemPointerArrayIteratorImpl prev_vm_itr(pBL_prev->_vm_cs); - VMCallsitePointer* cur_vm_callsite = (VMCallsitePointer*)cur_vm_itr.current(); - VMCallsitePointer* prev_vm_callsite = (VMCallsitePointer*)prev_vm_itr.current(); - while (cur_vm_callsite != NULL || prev_vm_callsite != NULL) { - if (prev_vm_callsite == NULL || cur_vm_callsite->addr() < prev_vm_callsite->addr()) { - // this is a new callsite - _outputer.diff_virtual_memory_callsite(cur_vm_callsite->addr(), - amount_in_current_scale(cur_vm_callsite->reserved_amount()), - amount_in_current_scale(cur_vm_callsite->committed_amount()), - diff_in_current_scale(cur_vm_callsite->reserved_amount(), 0), - diff_in_current_scale(cur_vm_callsite->committed_amount(), 0)); - cur_vm_callsite = (VMCallsitePointer*)cur_vm_itr.next(); - } else if (cur_vm_callsite == NULL || cur_vm_callsite->addr() > prev_vm_callsite->addr()) { - // this callsite is already gone - _outputer.diff_virtual_memory_callsite(prev_vm_callsite->addr(), - amount_in_current_scale(0), - amount_in_current_scale(0), - diff_in_current_scale(0, prev_vm_callsite->reserved_amount()), - diff_in_current_scale(0, prev_vm_callsite->committed_amount())); - prev_vm_callsite = (VMCallsitePointer*)prev_vm_itr.next(); - } else { // the same callsite - _outputer.diff_virtual_memory_callsite(cur_vm_callsite->addr(), - amount_in_current_scale(cur_vm_callsite->reserved_amount()), - amount_in_current_scale(cur_vm_callsite->committed_amount()), - diff_in_current_scale(cur_vm_callsite->reserved_amount(), prev_vm_callsite->reserved_amount()), - diff_in_current_scale(cur_vm_callsite->committed_amount(), prev_vm_callsite->committed_amount())); - cur_vm_callsite = (VMCallsitePointer*)cur_vm_itr.next(); - prev_vm_callsite = (VMCallsitePointer*)prev_vm_itr.next(); - } - } - - _outputer.done_callsite(); -} - -size_t BaselineReporter::amount_in_current_scale(size_t amt) const { - return (size_t)(((float)amt/(float)_scale) + 0.5); -} - -int BaselineReporter::diff_in_current_scale(size_t value1, size_t value2) const { - return (int)(((float)value1 - (float)value2)/((float)_scale) + 0.5); -} - -int BaselineReporter::diff(size_t value1, size_t value2) const { - return ((int)value1 - (int)value2); -} - -void BaselineTTYOutputer::start(size_t scale, bool report_diff) { - _scale = scale; - _output->print_cr(" "); - _output->print_cr("Native Memory Tracking:"); - _output->print_cr(" "); -} - -void BaselineTTYOutputer::done() { - -} + if (all_committed) return; -void BaselineTTYOutputer::total_usage(size_t total_reserved, size_t total_committed) { - const char* unit = memory_unit(_scale); - _output->print_cr("Total: reserved=%d%s, committed=%d%s", - total_reserved, unit, total_committed, unit); -} - -void BaselineTTYOutputer::start_category_summary() { - _output->print_cr(" "); -} - -/** - * report a summary of memory type - */ -void BaselineTTYOutputer::category_summary(MEMFLAGS type, - size_t reserved_amt, size_t committed_amt, size_t malloc_amt, - size_t malloc_count, size_t arena_amt, size_t arena_count) { - - // we report mtThreadStack under mtThread category - if (type == mtThreadStack) { - assert(malloc_amt == 0 && malloc_count == 0 && arena_amt == 0, - "Just check"); - _thread_stack_reserved = reserved_amt; - _thread_stack_committed = committed_amt; - } else { - const char* unit = memory_unit(_scale); - size_t total_reserved = (reserved_amt + malloc_amt + arena_amt); - size_t total_committed = (committed_amt + malloc_amt + arena_amt); - if (type == mtThread) { - total_reserved += _thread_stack_reserved; - total_committed += _thread_stack_committed; - } - - if (total_reserved > 0) { - _output->print_cr("-%26s (reserved=%d%s, committed=%d%s)", - MemBaseline::type2name(type), total_reserved, unit, - total_committed, unit); - - if (type == mtClass) { - _output->print_cr("%27s (classes #%d)", " ", _num_of_classes); - } else if (type == mtThread) { - _output->print_cr("%27s (thread #%d)", " ", _num_of_threads); - _output->print_cr("%27s (stack: reserved=%d%s, committed=%d%s)", " ", - _thread_stack_reserved, unit, _thread_stack_committed, unit); - } - - if (malloc_amt > 0) { - if (type != mtChunk) { - _output->print_cr("%27s (malloc=%d%s, #%d)", " ", malloc_amt, unit, - malloc_count); - } else { - _output->print_cr("%27s (malloc=%d%s)", " ", malloc_amt, unit); - } - } - - if (reserved_amt > 0) { - _output->print_cr("%27s (mmap: reserved=%d%s, committed=%d%s)", - " ", reserved_amt, unit, committed_amt, unit); - } - - if (arena_amt > 0) { - _output->print_cr("%27s (arena=%d%s, #%d)", " ", arena_amt, unit, arena_count); - } - - _output->print_cr(" "); + CommittedRegionIterator itr = reserved_rgn->iterate_committed_regions(); + const CommittedMemoryRegion* committed_rgn; + while ((committed_rgn = itr.next()) != NULL) { + // Don't report if size is too small + if (amount_in_current_scale(committed_rgn->size()) == 0) continue; + stack = committed_rgn->call_stack(); + out->print("\n\t"); + print_virtual_memory_region("committed", committed_rgn->base(), committed_rgn->size()); + if (stack->is_empty()) { + out->print_cr(" "); + } else { + out->print_cr(" from"); + stack->print_on(out, 12); } } } -void BaselineTTYOutputer::done_category_summary() { - _output->print_cr(" "); -} +void MemSummaryDiffReporter::report_diff() { + const char* scale = current_scale(); + outputStream* out = output(); + out->print_cr("\nNative Memory Tracking:\n"); - -void BaselineTTYOutputer::start_virtual_memory_map() { - _output->print_cr("Virtual memory map:"); -} + // Overall diff + out->print("Total: "); + print_virtual_memory_diff(_current_baseline.total_reserved_memory(), + _current_baseline.total_committed_memory(), _early_baseline.total_reserved_memory(), + _early_baseline.total_committed_memory()); -void BaselineTTYOutputer::reserved_memory_region(MEMFLAGS type, address base, address end, - size_t size, address pc) { - const char* unit = memory_unit(_scale); - char buf[128]; - int offset; - _output->print_cr(" "); - _output->print_cr("[" PTR_FORMAT " - " PTR_FORMAT "] reserved %d%s for %s", base, end, size, unit, - MemBaseline::type2name(type)); - if (os::dll_address_to_function_name(pc, buf, sizeof(buf), &offset)) { - _output->print_cr("\t\tfrom [%s+0x%x]", buf, offset); - } -} + out->print_cr("\n"); -void BaselineTTYOutputer::committed_memory_region(address base, address end, size_t size, address pc) { - const char* unit = memory_unit(_scale); - char buf[128]; - int offset; - _output->print("\t[" PTR_FORMAT " - " PTR_FORMAT "] committed %d%s", base, end, size, unit); - if (os::dll_address_to_function_name(pc, buf, sizeof(buf), &offset)) { - _output->print_cr(" from [%s+0x%x]", buf, offset); + // Summary diff by memory type + for (int index = 0; index < mt_number_of_types; index ++) { + MEMFLAGS flag = NMTUtil::index_to_flag(index); + // thread stack is reported as part of thread category + if (flag == mtThreadStack) continue; + diff_summary_of_type(flag, _early_baseline.malloc_memory(flag), + _early_baseline.virtual_memory(flag), _current_baseline.malloc_memory(flag), + _current_baseline.virtual_memory(flag)); } } -void BaselineTTYOutputer::done_virtual_memory_map() { - _output->print_cr(" "); -} - - - -void BaselineTTYOutputer::start_callsite() { - _output->print_cr("Details:"); - _output->print_cr(" "); -} - -void BaselineTTYOutputer::done_callsite() { - _output->print_cr(" "); -} +void MemSummaryDiffReporter::print_malloc_diff(size_t current_amount, size_t current_count, + size_t early_amount, size_t early_count) const { + const char* scale = current_scale(); + outputStream* out = output(); -void BaselineTTYOutputer::malloc_callsite(address pc, size_t malloc_amt, - size_t malloc_count) { - if (malloc_amt > 0) { - const char* unit = memory_unit(_scale); - char buf[128]; - int offset; - if (pc == 0) { - _output->print("[BOOTSTRAP]%18s", " "); - } else if (os::dll_address_to_function_name(pc, buf, sizeof(buf), &offset)) { - _output->print_cr("[" PTR_FORMAT "] %s+0x%x", pc, buf, offset); - _output->print("%28s", " "); - } else { - _output->print("[" PTR_FORMAT "]%18s", pc, " "); + out->print("malloc=" SIZE_FORMAT "%s", amount_in_current_scale(current_amount), scale); + long amount_diff = diff_in_current_scale(current_amount, early_amount); + if (amount_diff != 0) { + out->print(" %+ld%s", amount_diff, scale); + } + if (current_count > 0) { + out->print(" #" SIZE_FORMAT "", current_count); + if (current_count != early_count) { + out->print(" %+d", (int)(current_count - early_count)); } - - _output->print_cr("(malloc=%d%s #%d)", malloc_amt, unit, malloc_count); - _output->print_cr(" "); } } -void BaselineTTYOutputer::virtual_memory_callsite(address pc, size_t reserved_amt, - size_t committed_amt) { - if (reserved_amt > 0) { - const char* unit = memory_unit(_scale); - char buf[128]; - int offset; - if (pc == 0) { - _output->print("[BOOTSTRAP]%18s", " "); - } else if (os::dll_address_to_function_name(pc, buf, sizeof(buf), &offset)) { - _output->print_cr("[" PTR_FORMAT "] %s+0x%x", pc, buf, offset); - _output->print("%28s", " "); - } else { - _output->print("[" PTR_FORMAT "]%18s", pc, " "); - } +void MemSummaryDiffReporter::print_arena_diff(size_t current_amount, size_t current_count, + size_t early_amount, size_t early_count) const { + const char* scale = current_scale(); + outputStream* out = output(); + out->print("arena=" SIZE_FORMAT "%s", amount_in_current_scale(current_amount), scale); + if (diff_in_current_scale(current_amount, early_amount) != 0) { + out->print(" %+ld", diff_in_current_scale(current_amount, early_amount)); + } + + out->print(" #" SIZE_FORMAT "", current_count); + if (current_count != early_count) { + out->print(" %+d", (int)(current_count - early_count)); + } +} - _output->print_cr("(mmap: reserved=%d%s, committed=%d%s)", - reserved_amt, unit, committed_amt, unit); - _output->print_cr(" "); +void MemSummaryDiffReporter::print_virtual_memory_diff(size_t current_reserved, size_t current_committed, + size_t early_reserved, size_t early_committed) const { + const char* scale = current_scale(); + outputStream* out = output(); + out->print("reserved=" SIZE_FORMAT "%s", amount_in_current_scale(current_reserved), scale); + long reserved_diff = diff_in_current_scale(current_reserved, early_reserved); + if (reserved_diff != 0) { + out->print(" %+ld%s", reserved_diff, scale); + } + + out->print(", committed=" SIZE_FORMAT "%s", amount_in_current_scale(current_committed), scale); + long committed_diff = diff_in_current_scale(current_committed, early_committed); + if (committed_diff != 0) { + out->print(" %+ld%s", committed_diff, scale); } } -void BaselineTTYOutputer::diff_total_usage(size_t total_reserved, - size_t total_committed, int reserved_diff, int committed_diff) { - const char* unit = memory_unit(_scale); - _output->print_cr("Total: reserved=%d%s %+d%s, committed=%d%s %+d%s", - total_reserved, unit, reserved_diff, unit, total_committed, unit, - committed_diff, unit); -} + +void MemSummaryDiffReporter::diff_summary_of_type(MEMFLAGS flag, const MallocMemory* early_malloc, + const VirtualMemory* early_vm, const MallocMemory* current_malloc, + const VirtualMemory* current_vm) const { + + outputStream* out = output(); + const char* scale = current_scale(); + + // Total reserved and committed memory in current baseline + size_t current_reserved_amount = reserved_total (current_malloc, current_vm); + size_t current_committed_amount = committed_total(current_malloc, current_vm); + + // Total reserved and committed memory in early baseline + size_t early_reserved_amount = reserved_total(early_malloc, early_vm); + size_t early_committed_amount = committed_total(early_malloc, early_vm); -void BaselineTTYOutputer::diff_category_summary(MEMFLAGS type, - size_t cur_reserved_amt, size_t cur_committed_amt, - size_t cur_malloc_amt, size_t cur_malloc_count, - size_t cur_arena_amt, size_t cur_arena_count, - int reserved_diff, int committed_diff, int malloc_diff, - int malloc_count_diff, int arena_diff, int arena_count_diff) { + // Adjust virtual memory total + if (flag == mtThread) { + const VirtualMemory* early_thread_stack_usage = + _early_baseline.virtual_memory(mtThreadStack); + const VirtualMemory* current_thread_stack_usage = + _current_baseline.virtual_memory(mtThreadStack); + + early_reserved_amount += early_thread_stack_usage->reserved(); + early_committed_amount += early_thread_stack_usage->committed(); + + current_reserved_amount += current_thread_stack_usage->reserved(); + current_committed_amount += current_thread_stack_usage->committed(); + } else if (flag == mtNMT) { + early_reserved_amount += _early_baseline.malloc_tracking_overhead(); + early_committed_amount += _early_baseline.malloc_tracking_overhead(); + + current_reserved_amount += _current_baseline.malloc_tracking_overhead(); + current_committed_amount += _current_baseline.malloc_tracking_overhead(); + } - if (type == mtThreadStack) { - assert(cur_malloc_amt == 0 && cur_malloc_count == 0 && - cur_arena_amt == 0, "Just check"); - _thread_stack_reserved = cur_reserved_amt; - _thread_stack_committed = cur_committed_amt; - _thread_stack_reserved_diff = reserved_diff; - _thread_stack_committed_diff = committed_diff; - } else { - const char* unit = memory_unit(_scale); - size_t total_reserved = (cur_reserved_amt + cur_malloc_amt + cur_arena_amt); - // nothing to report in this category - if (total_reserved == 0) { - return; - } - int diff_reserved = (reserved_diff + malloc_diff + arena_diff); + if (amount_in_current_scale(current_reserved_amount) > 0 || + diff_in_current_scale(current_reserved_amount, early_reserved_amount) != 0) { + + // print summary line + out->print("-%26s (", NMTUtil::flag_to_name(flag)); + print_virtual_memory_diff(current_reserved_amount, current_committed_amount, + early_reserved_amount, early_committed_amount); + out->print_cr(")"); - // category summary - _output->print("-%26s (reserved=%d%s", MemBaseline::type2name(type), - total_reserved, unit); + // detail lines + if (flag == mtClass) { + // report class count + out->print("%27s (classes #" SIZE_FORMAT "", " ", _current_baseline.class_count()); + int class_count_diff = (int)(_current_baseline.class_count() - + _early_baseline.class_count()); + if (_current_baseline.class_count() != _early_baseline.class_count()) { + out->print(" %+d", (int)(_current_baseline.class_count() - _early_baseline.class_count())); + } + out->print_cr(")"); + } else if (flag == mtThread) { + // report thread count + out->print("%27s (thread #" SIZE_FORMAT "", " ", _current_baseline.thread_count()); + int thread_count_diff = (int)(_current_baseline.thread_count() - + _early_baseline.thread_count()); + if (thread_count_diff != 0) { + out->print(" %+d", thread_count_diff); + } + out->print_cr(")"); - if (diff_reserved != 0) { - _output->print(" %+d%s", diff_reserved, unit); - } + // report thread stack + const VirtualMemory* current_thread_stack = + _current_baseline.virtual_memory(mtThreadStack); + const VirtualMemory* early_thread_stack = + _early_baseline.virtual_memory(mtThreadStack); - size_t total_committed = cur_committed_amt + cur_malloc_amt + cur_arena_amt; - _output->print(", committed=%d%s", total_committed, unit); - - int total_committed_diff = committed_diff + malloc_diff + arena_diff; - if (total_committed_diff != 0) { - _output->print(" %+d%s", total_committed_diff, unit); + out->print("%27s (stack: ", " "); + print_virtual_memory_diff(current_thread_stack->reserved(), current_thread_stack->committed(), + early_thread_stack->reserved(), early_thread_stack->committed()); + out->print_cr(")"); } - _output->print_cr(")"); + // Report malloc'd memory + size_t current_malloc_amount = current_malloc->malloc_size(); + size_t early_malloc_amount = early_malloc->malloc_size(); + if (amount_in_current_scale(current_malloc_amount) > 0 || + diff_in_current_scale(current_malloc_amount, early_malloc_amount) != 0) { + out->print("%28s(", " "); + print_malloc_diff(current_malloc_amount, (flag == mtChunk) ? 0 : current_malloc->malloc_count(), + early_malloc_amount, early_malloc->malloc_count()); + out->print_cr(")"); + } - // special cases - if (type == mtClass) { - _output->print("%27s (classes #%d", " ", _num_of_classes); - if (_num_of_classes_diff != 0) { - _output->print(" %+d", _num_of_classes_diff); - } - _output->print_cr(")"); - } else if (type == mtThread) { - // thread count - _output->print("%27s (thread #%d", " ", _num_of_threads); - if (_num_of_threads_diff != 0) { - _output->print_cr(" %+d)", _num_of_threads_diff); - } else { - _output->print_cr(")"); - } - _output->print("%27s (stack: reserved=%d%s", " ", _thread_stack_reserved, unit); - if (_thread_stack_reserved_diff != 0) { - _output->print(" %+d%s", _thread_stack_reserved_diff, unit); - } - - _output->print(", committed=%d%s", _thread_stack_committed, unit); - if (_thread_stack_committed_diff != 0) { - _output->print(" %+d%s",_thread_stack_committed_diff, unit); - } - - _output->print_cr(")"); + // Report virtual memory + if (amount_in_current_scale(current_vm->reserved()) > 0 || + diff_in_current_scale(current_vm->reserved(), early_vm->reserved()) != 0) { + out->print("%27s (mmap: ", " "); + print_virtual_memory_diff(current_vm->reserved(), current_vm->committed(), + early_vm->reserved(), early_vm->committed()); + out->print_cr(")"); } - // malloc'd memory - if (cur_malloc_amt > 0) { - _output->print("%27s (malloc=%d%s", " ", cur_malloc_amt, unit); - if (malloc_diff != 0) { - _output->print(" %+d%s", malloc_diff, unit); - } - if (type != mtChunk) { - _output->print(", #%d", cur_malloc_count); - if (malloc_count_diff) { - _output->print(" %+d", malloc_count_diff); - } - } - _output->print_cr(")"); + // Report arena memory + if (amount_in_current_scale(current_malloc->arena_size()) > 0 || + diff_in_current_scale(current_malloc->arena_size(), early_malloc->arena_size()) != 0) { + out->print("%28s(", " "); + print_arena_diff(current_malloc->arena_size(), current_malloc->arena_count(), + early_malloc->arena_size(), early_malloc->arena_count()); + out->print_cr(")"); } - // mmap'd memory - if (cur_reserved_amt > 0) { - _output->print("%27s (mmap: reserved=%d%s", " ", cur_reserved_amt, unit); - if (reserved_diff != 0) { - _output->print(" %+d%s", reserved_diff, unit); - } + // Report native memory tracking overhead + if (flag == mtNMT) { + size_t current_tracking_overhead = amount_in_current_scale(_current_baseline.malloc_tracking_overhead()); + size_t early_tracking_overhead = amount_in_current_scale(_early_baseline.malloc_tracking_overhead()); - _output->print(", committed=%d%s", cur_committed_amt, unit); - if (committed_diff != 0) { - _output->print(" %+d%s", committed_diff, unit); - } - _output->print_cr(")"); - } + out->print("%27s (tracking overhead=" SIZE_FORMAT "%s", " ", + amount_in_current_scale(_current_baseline.malloc_tracking_overhead()), scale); - // arena memory - if (cur_arena_amt > 0) { - _output->print("%27s (arena=%d%s", " ", cur_arena_amt, unit); - if (arena_diff != 0) { - _output->print(" %+d%s", arena_diff, unit); + long overhead_diff = diff_in_current_scale(_current_baseline.malloc_tracking_overhead(), + _early_baseline.malloc_tracking_overhead()); + if (overhead_diff != 0) { + out->print(" %+ld%s", overhead_diff, scale); } - _output->print(", #%d", cur_arena_count); - if (arena_count_diff != 0) { - _output->print(" %+d", arena_count_diff); - } - _output->print_cr(")"); + out->print_cr(")"); } - - _output->print_cr(" "); + out->print_cr(" "); } } -void BaselineTTYOutputer::diff_malloc_callsite(address pc, - size_t cur_malloc_amt, size_t cur_malloc_count, - int malloc_diff, int malloc_count_diff) { - if (malloc_diff != 0) { - const char* unit = memory_unit(_scale); - char buf[128]; - int offset; - if (pc == 0) { - _output->print_cr("[BOOTSTRAP]%18s", " "); +void MemDetailDiffReporter::report_diff() { + MemSummaryDiffReporter::report_diff(); + diff_malloc_sites(); + diff_virtual_memory_sites(); +} + +void MemDetailDiffReporter::diff_malloc_sites() const { + MallocSiteIterator early_itr = _early_baseline.malloc_sites(MemBaseline::by_site); + MallocSiteIterator current_itr = _current_baseline.malloc_sites(MemBaseline::by_site); + + const MallocSite* early_site = early_itr.next(); + const MallocSite* current_site = current_itr.next(); + + while (early_site != NULL || current_site != NULL) { + if (early_site == NULL) { + new_malloc_site(current_site); + current_site = current_itr.next(); + } else if (current_site == NULL) { + old_malloc_site(early_site); + early_site = early_itr.next(); } else { - if (os::dll_address_to_function_name(pc, buf, sizeof(buf), &offset)) { - _output->print_cr("[" PTR_FORMAT "] %s+0x%x", pc, buf, offset); - _output->print("%28s", " "); + int compVal = current_site->call_stack()->compare(*early_site->call_stack()); + if (compVal < 0) { + new_malloc_site(current_site); + current_site = current_itr.next(); + } else if (compVal > 0) { + old_malloc_site(early_site); + early_site = early_itr.next(); } else { - _output->print("[" PTR_FORMAT "]%18s", pc, " "); + diff_malloc_site(early_site, current_site); + early_site = early_itr.next(); + current_site = current_itr.next(); } } + } +} - _output->print("(malloc=%d%s", cur_malloc_amt, unit); - if (malloc_diff != 0) { - _output->print(" %+d%s", malloc_diff, unit); +void MemDetailDiffReporter::diff_virtual_memory_sites() const { + VirtualMemorySiteIterator early_itr = _early_baseline.virtual_memory_sites(MemBaseline::by_site); + VirtualMemorySiteIterator current_itr = _current_baseline.virtual_memory_sites(MemBaseline::by_site); + + const VirtualMemoryAllocationSite* early_site = early_itr.next(); + const VirtualMemoryAllocationSite* current_site = current_itr.next(); + + while (early_site != NULL || current_site != NULL) { + if (early_site == NULL) { + new_virtual_memory_site(current_site); + current_site = current_itr.next(); + } else if (current_site == NULL) { + old_virtual_memory_site(early_site); + early_site = early_itr.next(); + } else { + int compVal = current_site->call_stack()->compare(*early_site->call_stack()); + if (compVal < 0) { + new_virtual_memory_site(current_site); + current_site = current_itr.next(); + } else if (compVal > 0) { + old_virtual_memory_site(early_site); + early_site = early_itr.next(); + } else { + diff_virtual_memory_site(early_site, current_site); + early_site = early_itr.next(); + current_site = current_itr.next(); + } } - _output->print(", #%d", cur_malloc_count); - if (malloc_count_diff != 0) { - _output->print(" %+d", malloc_count_diff); - } - _output->print_cr(")"); - _output->print_cr(" "); } } -void BaselineTTYOutputer::diff_virtual_memory_callsite(address pc, - size_t cur_reserved_amt, size_t cur_committed_amt, - int reserved_diff, int committed_diff) { - if (reserved_diff != 0 || committed_diff != 0) { - const char* unit = memory_unit(_scale); - char buf[64]; - int offset; - if (pc == 0) { - _output->print_cr("[BOOSTRAP]%18s", " "); - } else { - if (os::dll_address_to_function_name(pc, buf, sizeof(buf), &offset)) { - _output->print_cr("[" PTR_FORMAT "] %s+0x%x", pc, buf, offset); - _output->print("%28s", " "); - } else { - _output->print("[" PTR_FORMAT "]%18s", pc, " "); - } - } + +void MemDetailDiffReporter::new_malloc_site(const MallocSite* malloc_site) const { + diff_malloc_site(malloc_site->call_stack(), malloc_site->size(), malloc_site->count(), + 0, 0); +} + +void MemDetailDiffReporter::old_malloc_site(const MallocSite* malloc_site) const { + diff_malloc_site(malloc_site->call_stack(), 0, 0, malloc_site->size(), + malloc_site->count()); +} + +void MemDetailDiffReporter::diff_malloc_site(const MallocSite* early, + const MallocSite* current) const { + diff_malloc_site(current->call_stack(), current->size(), current->count(), + early->size(), early->count()); +} + +void MemDetailDiffReporter::diff_malloc_site(const NativeCallStack* stack, size_t current_size, + size_t current_count, size_t early_size, size_t early_count) const { + outputStream* out = output(); + + assert(stack != NULL, "NULL stack"); + + if (diff_in_current_scale(current_size, early_size) == 0) { + return; + } + + stack->print_on(out); + out->print("%28s (", " "); + print_malloc_diff(current_size, current_count, + early_size, early_count); - _output->print("(mmap: reserved=%d%s", cur_reserved_amt, unit); - if (reserved_diff != 0) { - _output->print(" %+d%s", reserved_diff, unit); - } - _output->print(", committed=%d%s", cur_committed_amt, unit); - if (committed_diff != 0) { - _output->print(" %+d%s", committed_diff, unit); - } - _output->print_cr(")"); - _output->print_cr(" "); + out->print_cr(")\n"); +} + + +void MemDetailDiffReporter::new_virtual_memory_site(const VirtualMemoryAllocationSite* site) const { + diff_virtual_memory_site(site->call_stack(), site->reserved(), site->committed(), 0, 0); +} + +void MemDetailDiffReporter::old_virtual_memory_site(const VirtualMemoryAllocationSite* site) const { + diff_virtual_memory_site(site->call_stack(), 0, 0, site->reserved(), site->committed()); +} + +void MemDetailDiffReporter::diff_virtual_memory_site(const VirtualMemoryAllocationSite* early, + const VirtualMemoryAllocationSite* current) const { + diff_virtual_memory_site(current->call_stack(), current->reserved(), current->committed(), + early->reserved(), early->committed()); +} + +void MemDetailDiffReporter::diff_virtual_memory_site(const NativeCallStack* stack, size_t current_reserved, + size_t current_committed, size_t early_reserved, size_t early_committed) const { + outputStream* out = output(); + + // no change + if (diff_in_current_scale(current_reserved, early_reserved) == 0 && + diff_in_current_scale(current_committed, early_committed) == 0) { + return; } -} + + stack->print_on(out); + out->print("%28s (mmap: ", " "); + print_virtual_memory_diff(current_reserved, current_committed, + early_reserved, early_committed); + + out->print_cr(")\n"); + } + diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/services/memReporter.hpp --- a/hotspot/src/share/vm/services/memReporter.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/services/memReporter.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -25,262 +25,217 @@ #ifndef SHARE_VM_SERVICES_MEM_REPORTER_HPP #define SHARE_VM_SERVICES_MEM_REPORTER_HPP -#include "runtime/mutexLocker.hpp" +#if INCLUDE_NMT + +#include "oops/instanceKlass.hpp" #include "services/memBaseline.hpp" -#include "services/memTracker.hpp" -#include "utilities/ostream.hpp" -#include "utilities/macros.hpp" - -#if INCLUDE_NMT +#include "services/nmtCommon.hpp" +#include "services/mallocTracker.hpp" +#include "services/virtualMemoryTracker.hpp" /* - * MemBaselineReporter reports data to this outputer class, - * ReportOutputer is responsible for format, store and redirect - * the data to the final destination. - */ -class BaselineOutputer : public StackObj { + * Base class that provides helpers +*/ +class MemReporterBase : public StackObj { + private: + size_t _scale; // report in this scale + outputStream* _output; // destination + public: - // start to report memory usage in specified scale. - // if report_diff = true, the reporter reports baseline comparison - // information. - - virtual void start(size_t scale, bool report_diff = false) = 0; - // Done reporting - virtual void done() = 0; + MemReporterBase(outputStream* out = NULL, size_t scale = K) + : _scale(scale) { + _output = (out == NULL) ? tty : out; + } - /* report baseline summary information */ - virtual void total_usage(size_t total_reserved, - size_t total_committed) = 0; - virtual void num_of_classes(size_t classes) = 0; - virtual void num_of_threads(size_t threads) = 0; - - virtual void thread_info(size_t stack_reserved_amt, size_t stack_committed_amt) = 0; + protected: + inline outputStream* output() const { + return _output; + } + // Current reporting scale + inline const char* current_scale() const { + return NMTUtil::scale_name(_scale); + } + // Convert memory amount in bytes to current reporting scale + inline size_t amount_in_current_scale(size_t amount) const { + return NMTUtil::amount_in_scale(amount, _scale); + } - /* report baseline summary comparison */ - virtual void diff_total_usage(size_t total_reserved, - size_t total_committed, - int reserved_diff, - int committed_diff) = 0; - virtual void diff_num_of_classes(size_t classes, int diff) = 0; - virtual void diff_num_of_threads(size_t threads, int diff) = 0; + // Convert diff amount in bytes to current reporting scale + inline long diff_in_current_scale(size_t s1, size_t s2) const { + long amount = (long)(s1 - s2); + long scale = (long)_scale; + amount = (amount > 0) ? (amount + scale / 2) : (amount - scale / 2); + return amount / scale; + } - virtual void diff_thread_info(size_t stack_reserved, size_t stack_committed, - int stack_reserved_diff, int stack_committed_diff) = 0; + // Helper functions + // Calculate total reserved and committed amount + size_t reserved_total(const MallocMemory* malloc, const VirtualMemory* vm) const; + size_t committed_total(const MallocMemory* malloc, const VirtualMemory* vm) const; - /* - * memory summary by memory types. - * for each memory type, following summaries are reported: - * - reserved amount, committed amount - * - malloc'd amount, malloc count - * - arena amount, arena count - */ + // Print summary total, malloc and virtual memory + void print_total(size_t reserved, size_t committed) const; + void print_malloc(size_t amount, size_t count) const; + void print_virtual_memory(size_t reserved, size_t committed) const; - // start reporting memory summary by memory type - virtual void start_category_summary() = 0; + void print_malloc_line(size_t amount, size_t count) const; + void print_virtual_memory_line(size_t reserved, size_t committed) const; + void print_arena_line(size_t amount, size_t count) const; - virtual void category_summary(MEMFLAGS type, size_t reserved_amt, - size_t committed_amt, - size_t malloc_amt, size_t malloc_count, - size_t arena_amt, size_t arena_count) = 0; + void print_virtual_memory_region(const char* type, address base, size_t size) const; +}; - virtual void diff_category_summary(MEMFLAGS type, size_t cur_reserved_amt, - size_t cur_committed_amt, - size_t cur_malloc_amt, size_t cur_malloc_count, - size_t cur_arena_amt, size_t cur_arena_count, - int reserved_diff, int committed_diff, int malloc_diff, - int malloc_count_diff, int arena_diff, - int arena_count_diff) = 0; +/* + * The class is for generating summary tracking report. + */ +class MemSummaryReporter : public MemReporterBase { + private: + MallocMemorySnapshot* _malloc_snapshot; + VirtualMemorySnapshot* _vm_snapshot; + size_t _class_count; - virtual void done_category_summary() = 0; - - virtual void start_virtual_memory_map() = 0; - virtual void reserved_memory_region(MEMFLAGS type, address base, address end, size_t size, address pc) = 0; - virtual void committed_memory_region(address base, address end, size_t size, address pc) = 0; - virtual void done_virtual_memory_map() = 0; + public: + // Report summary tracking data from global snapshots directly. + // This constructor is used for final reporting and hs_err reporting. + MemSummaryReporter(MallocMemorySnapshot* malloc_snapshot, + VirtualMemorySnapshot* vm_snapshot, outputStream* output, + size_t class_count = 0, size_t scale = K) : + MemReporterBase(output, scale), + _malloc_snapshot(malloc_snapshot), + _vm_snapshot(vm_snapshot) { + if (class_count == 0) { + _class_count = InstanceKlass::number_of_instance_classes(); + } else { + _class_count = class_count; + } + } + // This constructor is for normal reporting from a recent baseline. + MemSummaryReporter(MemBaseline& baseline, outputStream* output, + size_t scale = K) : MemReporterBase(output, scale), + _malloc_snapshot(baseline.malloc_memory_snapshot()), + _vm_snapshot(baseline.virtual_memory_snapshot()), + _class_count(baseline.class_count()) { } - /* - * Report callsite information - */ - virtual void start_callsite() = 0; - virtual void malloc_callsite(address pc, size_t malloc_amt, size_t malloc_count) = 0; - virtual void virtual_memory_callsite(address pc, size_t reserved_amt, size_t committed_amt) = 0; - virtual void diff_malloc_callsite(address pc, size_t cur_malloc_amt, size_t cur_malloc_count, - int malloc_diff, int malloc_count_diff) = 0; - virtual void diff_virtual_memory_callsite(address pc, size_t cur_reserved_amt, size_t cur_committed_amt, - int reserved_diff, int committed_diff) = 0; - - virtual void done_callsite() = 0; - - // return current scale in "KB", "MB" or "GB" - static const char* memory_unit(size_t scale); + // Generate summary report + virtual void report(); + private: + // Report summary for each memory type + void report_summary_of_type(MEMFLAGS type, MallocMemory* malloc_memory, + VirtualMemory* virtual_memory); }; /* - * This class reports processed data from a baseline or - * the changes between the two baseline. + * The class is for generating detail tracking report. */ -class BaselineReporter : public StackObj { +class MemDetailReporter : public MemSummaryReporter { private: - BaselineOutputer& _outputer; - size_t _scale; + MemBaseline& _baseline; public: - // construct a reporter that reports memory usage - // in specified scale - BaselineReporter(BaselineOutputer& outputer, size_t scale = K): - _outputer(outputer) { - _scale = scale; + MemDetailReporter(MemBaseline& baseline, outputStream* output, size_t scale = K) : + MemSummaryReporter(baseline, output, scale), + _baseline(baseline) { } + + // Generate detail report. + // The report contains summary and detail sections. + virtual void report() { + MemSummaryReporter::report(); + report_virtual_memory_map(); + report_detail(); } - virtual void report_baseline(const MemBaseline& baseline, bool summary_only = false); - virtual void diff_baselines(const MemBaseline& cur, const MemBaseline& prev, - bool summary_only = false); - - void set_scale(size_t scale); - size_t scale() const { return _scale; } private: - void report_summaries(const MemBaseline& baseline); - void report_virtual_memory_map(const MemBaseline& baseline); - void report_callsites(const MemBaseline& baseline); - - void diff_summaries(const MemBaseline& cur, const MemBaseline& prev); - void diff_callsites(const MemBaseline& cur, const MemBaseline& prev); + // Report detail tracking data. + void report_detail(); + // Report virtual memory map + void report_virtual_memory_map(); + // Report malloc allocation sites + void report_malloc_sites(); + // Report virtual memory reservation sites + void report_virtual_memory_allocation_sites(); - // calculate memory size in current memory scale - size_t amount_in_current_scale(size_t amt) const; - // diff two unsigned values in current memory scale - int diff_in_current_scale(size_t value1, size_t value2) const; - // diff two unsigned value - int diff(size_t value1, size_t value2) const; + // Report a virtual memory region + void report_virtual_memory_region(const ReservedMemoryRegion* rgn); }; /* - * tty output implementation. Native memory tracking - * DCmd uses this outputer. + * The class is for generating summary comparison report. + * It compares current memory baseline against an early baseline. */ -class BaselineTTYOutputer : public BaselineOutputer { - private: - size_t _scale; - - size_t _num_of_classes; - size_t _num_of_threads; - size_t _thread_stack_reserved; - size_t _thread_stack_committed; - - int _num_of_classes_diff; - int _num_of_threads_diff; - int _thread_stack_reserved_diff; - int _thread_stack_committed_diff; - - outputStream* _output; +class MemSummaryDiffReporter : public MemReporterBase { + protected: + MemBaseline& _early_baseline; + MemBaseline& _current_baseline; public: - BaselineTTYOutputer(outputStream* st) { - _scale = K; - _num_of_classes = 0; - _num_of_threads = 0; - _thread_stack_reserved = 0; - _thread_stack_committed = 0; - _num_of_classes_diff = 0; - _num_of_threads_diff = 0; - _thread_stack_reserved_diff = 0; - _thread_stack_committed_diff = 0; - _output = st; - } - - // begin reporting memory usage in specified scale - void start(size_t scale, bool report_diff = false); - // done reporting - void done(); - - // total memory usage - void total_usage(size_t total_reserved, - size_t total_committed); - // report total loaded classes - void num_of_classes(size_t classes) { - _num_of_classes = classes; - } - - void num_of_threads(size_t threads) { - _num_of_threads = threads; - } - - void thread_info(size_t stack_reserved_amt, size_t stack_committed_amt) { - _thread_stack_reserved = stack_reserved_amt; - _thread_stack_committed = stack_committed_amt; + MemSummaryDiffReporter(MemBaseline& early_baseline, MemBaseline& current_baseline, + outputStream* output, size_t scale = K) : MemReporterBase(output, scale), + _early_baseline(early_baseline), _current_baseline(current_baseline) { + assert(early_baseline.baseline_type() != MemBaseline::Not_baselined, "Not baselined"); + assert(current_baseline.baseline_type() != MemBaseline::Not_baselined, "Not baselined"); } - void diff_total_usage(size_t total_reserved, - size_t total_committed, - int reserved_diff, - int committed_diff); - - void diff_num_of_classes(size_t classes, int diff) { - _num_of_classes = classes; - _num_of_classes_diff = diff; - } - - void diff_num_of_threads(size_t threads, int diff) { - _num_of_threads = threads; - _num_of_threads_diff = diff; - } - - void diff_thread_info(size_t stack_reserved_amt, size_t stack_committed_amt, - int stack_reserved_diff, int stack_committed_diff) { - _thread_stack_reserved = stack_reserved_amt; - _thread_stack_committed = stack_committed_amt; - _thread_stack_reserved_diff = stack_reserved_diff; - _thread_stack_committed_diff = stack_committed_diff; - } + // Generate summary comparison report + virtual void report_diff(); - /* - * Report memory summary categoriuzed by memory types. - * For each memory type, following summaries are reported: - * - reserved amount, committed amount - * - malloc-ed amount, malloc count - * - arena amount, arena count - */ - // start reporting memory summary by memory type - void start_category_summary(); - void category_summary(MEMFLAGS type, size_t reserved_amt, size_t committed_amt, - size_t malloc_amt, size_t malloc_count, - size_t arena_amt, size_t arena_count); - - void diff_category_summary(MEMFLAGS type, size_t cur_reserved_amt, - size_t cur_committed_amt, - size_t cur_malloc_amt, size_t cur_malloc_count, - size_t cur_arena_amt, size_t cur_arena_count, - int reserved_diff, int committed_diff, int malloc_diff, - int malloc_count_diff, int arena_diff, - int arena_count_diff); + private: + // report the comparison of each memory type + void diff_summary_of_type(MEMFLAGS type, + const MallocMemory* early_malloc, const VirtualMemory* early_vm, + const MallocMemory* current_malloc, const VirtualMemory* current_vm) const; - void done_category_summary(); - - // virtual memory map - void start_virtual_memory_map(); - void reserved_memory_region(MEMFLAGS type, address base, address end, size_t size, address pc); - void committed_memory_region(address base, address end, size_t size, address pc); - void done_virtual_memory_map(); - - - /* - * Report callsite information - */ - void start_callsite(); - void malloc_callsite(address pc, size_t malloc_amt, size_t malloc_count); - void virtual_memory_callsite(address pc, size_t reserved_amt, size_t committed_amt); - - void diff_malloc_callsite(address pc, size_t cur_malloc_amt, size_t cur_malloc_count, - int malloc_diff, int malloc_count_diff); - void diff_virtual_memory_callsite(address pc, size_t cur_reserved_amt, size_t cur_committed_amt, - int reserved_diff, int committed_diff); - - void done_callsite(); + protected: + void print_malloc_diff(size_t current_amount, size_t current_count, + size_t early_amount, size_t early_count) const; + void print_virtual_memory_diff(size_t current_reserved, size_t current_committed, + size_t early_reserved, size_t early_committed) const; + void print_arena_diff(size_t current_amount, size_t current_count, + size_t early_amount, size_t early_count) const; }; +/* + * The class is for generating detail comparison report. + * It compares current memory baseline against an early baseline, + * both baselines have to be detail baseline. + */ +class MemDetailDiffReporter : public MemSummaryDiffReporter { + public: + MemDetailDiffReporter(MemBaseline& early_baseline, MemBaseline& current_baseline, + outputStream* output, size_t scale = K) : + MemSummaryDiffReporter(early_baseline, current_baseline, output, scale) { } + + // Generate detail comparison report + virtual void report_diff(); + + // Malloc allocation site comparison + void diff_malloc_sites() const; + // Virutal memory reservation site comparison + void diff_virtual_memory_sites() const; + + // New malloc allocation site in recent baseline + void new_malloc_site (const MallocSite* site) const; + // The malloc allocation site is not in recent baseline + void old_malloc_site (const MallocSite* site) const; + // Compare malloc allocation site, it is in both baselines + void diff_malloc_site(const MallocSite* early, const MallocSite* current) const; + + // New virtual memory allocation site in recent baseline + void new_virtual_memory_site (const VirtualMemoryAllocationSite* callsite) const; + // The virtual memory allocation site is not in recent baseline + void old_virtual_memory_site (const VirtualMemoryAllocationSite* callsite) const; + // Compare virtual memory allocation site, it is in both baseline + void diff_virtual_memory_site(const VirtualMemoryAllocationSite* early, + const VirtualMemoryAllocationSite* current) const; + + void diff_malloc_site(const NativeCallStack* stack, size_t current_size, + size_t currrent_count, size_t early_size, size_t early_count) const; + void diff_virtual_memory_site(const NativeCallStack* stack, size_t current_reserved, + size_t current_committed, size_t early_reserved, size_t early_committed) const; +}; #endif // INCLUDE_NMT -#endif // SHARE_VM_SERVICES_MEM_REPORTER_HPP +#endif + diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/services/memSnapshot.cpp --- a/hotspot/src/share/vm/services/memSnapshot.cpp Fri Aug 29 10:47:32 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,748 +0,0 @@ -/* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "precompiled.hpp" -#include "runtime/mutexLocker.hpp" -#include "utilities/decoder.hpp" -#include "services/memBaseline.hpp" -#include "services/memPtr.hpp" -#include "services/memPtrArray.hpp" -#include "services/memSnapshot.hpp" -#include "services/memTracker.hpp" - -PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC - -#ifdef ASSERT - -void decode_pointer_record(MemPointerRecord* rec) { - tty->print("Pointer: [" PTR_FORMAT " - " PTR_FORMAT "] size = %d bytes", rec->addr(), - rec->addr() + rec->size(), (int)rec->size()); - tty->print(" type = %s", MemBaseline::type2name(FLAGS_TO_MEMORY_TYPE(rec->flags()))); - if (rec->is_vm_pointer()) { - if (rec->is_allocation_record()) { - tty->print_cr(" (reserve)"); - } else if (rec->is_commit_record()) { - tty->print_cr(" (commit)"); - } else if (rec->is_uncommit_record()) { - tty->print_cr(" (uncommit)"); - } else if (rec->is_deallocation_record()) { - tty->print_cr(" (release)"); - } else { - tty->print_cr(" (tag)"); - } - } else { - if (rec->is_arena_memory_record()) { - tty->print_cr(" (arena size)"); - } else if (rec->is_allocation_record()) { - tty->print_cr(" (malloc)"); - } else { - tty->print_cr(" (free)"); - } - } - if (MemTracker::track_callsite()) { - char buf[1024]; - address pc = ((MemPointerRecordEx*)rec)->pc(); - if (pc != NULL && os::dll_address_to_function_name(pc, buf, sizeof(buf), NULL)) { - tty->print_cr("\tfrom %s", buf); - } else { - tty->print_cr("\tcould not decode pc = " PTR_FORMAT "", pc); - } - } -} - -void decode_vm_region_record(VMMemRegion* rec) { - tty->print("VM Region [" PTR_FORMAT " - " PTR_FORMAT "]", rec->addr(), - rec->addr() + rec->size()); - tty->print(" type = %s", MemBaseline::type2name(FLAGS_TO_MEMORY_TYPE(rec->flags()))); - if (rec->is_allocation_record()) { - tty->print_cr(" (reserved)"); - } else if (rec->is_commit_record()) { - tty->print_cr(" (committed)"); - } else { - ShouldNotReachHere(); - } - if (MemTracker::track_callsite()) { - char buf[1024]; - address pc = ((VMMemRegionEx*)rec)->pc(); - if (pc != NULL && os::dll_address_to_function_name(pc, buf, sizeof(buf), NULL)) { - tty->print_cr("\tfrom %s", buf); - } else { - tty->print_cr("\tcould not decode pc = " PTR_FORMAT "", pc); - } - - } -} - -#endif - - -bool VMMemPointerIterator::insert_record(MemPointerRecord* rec) { - VMMemRegionEx new_rec; - assert(rec->is_allocation_record() || rec->is_commit_record(), - "Sanity check"); - if (MemTracker::track_callsite()) { - new_rec.init((MemPointerRecordEx*)rec); - } else { - new_rec.init(rec); - } - return insert(&new_rec); -} - -bool VMMemPointerIterator::insert_record_after(MemPointerRecord* rec) { - VMMemRegionEx new_rec; - assert(rec->is_allocation_record() || rec->is_commit_record(), - "Sanity check"); - if (MemTracker::track_callsite()) { - new_rec.init((MemPointerRecordEx*)rec); - } else { - new_rec.init(rec); - } - return insert_after(&new_rec); -} - -// we don't consolidate reserved regions, since they may be categorized -// in different types. -bool VMMemPointerIterator::add_reserved_region(MemPointerRecord* rec) { - assert(rec->is_allocation_record(), "Sanity check"); - VMMemRegion* reserved_region = (VMMemRegion*)current(); - - // we don't have anything yet - if (reserved_region == NULL) { - return insert_record(rec); - } - - assert(reserved_region->is_reserved_region(), "Sanity check"); - // duplicated records - if (reserved_region->is_same_region(rec)) { - return true; - } - // Overlapping stack regions indicate that a JNI thread failed to - // detach from the VM before exiting. This leaks the JavaThread object. - if (CheckJNICalls) { - guarantee(FLAGS_TO_MEMORY_TYPE(reserved_region->flags()) != mtThreadStack || - !reserved_region->overlaps_region(rec), - "Attached JNI thread exited without being detached"); - } - // otherwise, we should not have overlapping reserved regions - assert(FLAGS_TO_MEMORY_TYPE(reserved_region->flags()) == mtThreadStack || - reserved_region->base() > rec->addr(), "Just check: locate()"); - assert(FLAGS_TO_MEMORY_TYPE(reserved_region->flags()) == mtThreadStack || - !reserved_region->overlaps_region(rec), "overlapping reserved regions"); - - return insert_record(rec); -} - -// we do consolidate committed regions -bool VMMemPointerIterator::add_committed_region(MemPointerRecord* rec) { - assert(rec->is_commit_record(), "Sanity check"); - VMMemRegion* reserved_rgn = (VMMemRegion*)current(); - assert(reserved_rgn->is_reserved_region() && reserved_rgn->contains_region(rec), - "Sanity check"); - - // thread's native stack is always marked as "committed", ignore - // the "commit" operation for creating stack guard pages - if (FLAGS_TO_MEMORY_TYPE(reserved_rgn->flags()) == mtThreadStack && - FLAGS_TO_MEMORY_TYPE(rec->flags()) != mtThreadStack) { - return true; - } - - // if the reserved region has any committed regions - VMMemRegion* committed_rgn = (VMMemRegion*)next(); - while (committed_rgn != NULL && committed_rgn->is_committed_region()) { - // duplicated commit records - if(committed_rgn->contains_region(rec)) { - return true; - } else if (committed_rgn->overlaps_region(rec)) { - // overlaps front part - if (rec->addr() < committed_rgn->addr()) { - committed_rgn->expand_region(rec->addr(), - committed_rgn->addr() - rec->addr()); - } else { - // overlaps tail part - address committed_rgn_end = committed_rgn->addr() + - committed_rgn->size(); - assert(committed_rgn_end < rec->addr() + rec->size(), - "overlap tail part"); - committed_rgn->expand_region(committed_rgn_end, - (rec->addr() + rec->size()) - committed_rgn_end); - } - } else if (committed_rgn->base() + committed_rgn->size() == rec->addr()) { - // adjunct each other - committed_rgn->expand_region(rec->addr(), rec->size()); - VMMemRegion* next_reg = (VMMemRegion*)next(); - // see if we can consolidate next committed region - if (next_reg != NULL && next_reg->is_committed_region() && - next_reg->base() == committed_rgn->base() + committed_rgn->size()) { - committed_rgn->expand_region(next_reg->base(), next_reg->size()); - // delete merged region - remove(); - } - return true; - } else if (committed_rgn->base() > rec->addr()) { - // found the location, insert this committed region - return insert_record(rec); - } - committed_rgn = (VMMemRegion*)next(); - } - return insert_record(rec); -} - -bool VMMemPointerIterator::remove_uncommitted_region(MemPointerRecord* rec) { - assert(rec->is_uncommit_record(), "sanity check"); - VMMemRegion* cur; - cur = (VMMemRegion*)current(); - assert(cur->is_reserved_region() && cur->contains_region(rec), - "Sanity check"); - // thread's native stack is always marked as "committed", ignore - // the "commit" operation for creating stack guard pages - if (FLAGS_TO_MEMORY_TYPE(cur->flags()) == mtThreadStack && - FLAGS_TO_MEMORY_TYPE(rec->flags()) != mtThreadStack) { - return true; - } - - cur = (VMMemRegion*)next(); - while (cur != NULL && cur->is_committed_region()) { - // region already uncommitted, must be due to duplicated record - if (cur->addr() >= rec->addr() + rec->size()) { - break; - } else if (cur->contains_region(rec)) { - // uncommit whole region - if (cur->is_same_region(rec)) { - remove(); - break; - } else if (rec->addr() == cur->addr() || - rec->addr() + rec->size() == cur->addr() + cur->size()) { - // uncommitted from either end of current memory region. - cur->exclude_region(rec->addr(), rec->size()); - break; - } else { // split the committed region and release the middle - address high_addr = cur->addr() + cur->size(); - size_t sz = high_addr - rec->addr(); - cur->exclude_region(rec->addr(), sz); - sz = high_addr - (rec->addr() + rec->size()); - if (MemTracker::track_callsite()) { - MemPointerRecordEx tmp(rec->addr() + rec->size(), cur->flags(), sz, - ((VMMemRegionEx*)cur)->pc()); - return insert_record_after(&tmp); - } else { - MemPointerRecord tmp(rec->addr() + rec->size(), cur->flags(), sz); - return insert_record_after(&tmp); - } - } - } - cur = (VMMemRegion*)next(); - } - - // we may not find committed record due to duplicated records - return true; -} - -bool VMMemPointerIterator::remove_released_region(MemPointerRecord* rec) { - assert(rec->is_deallocation_record(), "Sanity check"); - VMMemRegion* cur = (VMMemRegion*)current(); - assert(cur->is_reserved_region() && cur->contains_region(rec), - "Sanity check"); - if (rec->is_same_region(cur)) { - - // In snapshot, the virtual memory records are sorted in following orders: - // 1. virtual memory's base address - // 2. virtual memory reservation record, followed by commit records within this reservation. - // The commit records are also in base address order. - // When a reserved region is released, we want to remove the reservation record and all - // commit records following it. -#ifdef ASSERT - address low_addr = cur->addr(); - address high_addr = low_addr + cur->size(); -#endif - // remove virtual memory reservation record - remove(); - // remove committed regions within above reservation - VMMemRegion* next_region = (VMMemRegion*)current(); - while (next_region != NULL && next_region->is_committed_region()) { - assert(next_region->addr() >= low_addr && - next_region->addr() + next_region->size() <= high_addr, - "Range check"); - remove(); - next_region = (VMMemRegion*)current(); - } - } else if (rec->addr() == cur->addr() || - rec->addr() + rec->size() == cur->addr() + cur->size()) { - // released region is at either end of this region - cur->exclude_region(rec->addr(), rec->size()); - assert(check_reserved_region(), "Integrity check"); - } else { // split the reserved region and release the middle - address high_addr = cur->addr() + cur->size(); - size_t sz = high_addr - rec->addr(); - cur->exclude_region(rec->addr(), sz); - sz = high_addr - rec->addr() - rec->size(); - if (MemTracker::track_callsite()) { - MemPointerRecordEx tmp(rec->addr() + rec->size(), cur->flags(), sz, - ((VMMemRegionEx*)cur)->pc()); - bool ret = insert_reserved_region(&tmp); - assert(!ret || check_reserved_region(), "Integrity check"); - return ret; - } else { - MemPointerRecord tmp(rec->addr() + rec->size(), cur->flags(), sz); - bool ret = insert_reserved_region(&tmp); - assert(!ret || check_reserved_region(), "Integrity check"); - return ret; - } - } - return true; -} - -bool VMMemPointerIterator::insert_reserved_region(MemPointerRecord* rec) { - // skip all 'commit' records associated with previous reserved region - VMMemRegion* p = (VMMemRegion*)next(); - while (p != NULL && p->is_committed_region() && - p->base() + p->size() < rec->addr()) { - p = (VMMemRegion*)next(); - } - return insert_record(rec); -} - -bool VMMemPointerIterator::split_reserved_region(VMMemRegion* rgn, address new_rgn_addr, size_t new_rgn_size) { - assert(rgn->contains_region(new_rgn_addr, new_rgn_size), "Not fully contained"); - address pc = (MemTracker::track_callsite() ? ((VMMemRegionEx*)rgn)->pc() : NULL); - if (rgn->base() == new_rgn_addr) { // new region is at the beginning of the region - size_t sz = rgn->size() - new_rgn_size; - // the original region becomes 'new' region - rgn->exclude_region(new_rgn_addr + new_rgn_size, sz); - // remaining becomes next region - MemPointerRecordEx next_rgn(new_rgn_addr + new_rgn_size, rgn->flags(), sz, pc); - return insert_reserved_region(&next_rgn); - } else if (rgn->base() + rgn->size() == new_rgn_addr + new_rgn_size) { - rgn->exclude_region(new_rgn_addr, new_rgn_size); - MemPointerRecordEx next_rgn(new_rgn_addr, rgn->flags(), new_rgn_size, pc); - return insert_reserved_region(&next_rgn); - } else { - // the orginal region will be split into three - address rgn_high_addr = rgn->base() + rgn->size(); - // first region - rgn->exclude_region(new_rgn_addr, (rgn_high_addr - new_rgn_addr)); - // the second region is the new region - MemPointerRecordEx new_rgn(new_rgn_addr, rgn->flags(), new_rgn_size, pc); - if (!insert_reserved_region(&new_rgn)) return false; - // the remaining region - MemPointerRecordEx rem_rgn(new_rgn_addr + new_rgn_size, rgn->flags(), - rgn_high_addr - (new_rgn_addr + new_rgn_size), pc); - return insert_reserved_region(&rem_rgn); - } -} - -static int sort_in_seq_order(const void* p1, const void* p2) { - assert(p1 != NULL && p2 != NULL, "Sanity check"); - const MemPointerRecord* mp1 = (MemPointerRecord*)p1; - const MemPointerRecord* mp2 = (MemPointerRecord*)p2; - return (mp1->seq() - mp2->seq()); -} - -bool StagingArea::init() { - if (MemTracker::track_callsite()) { - _malloc_data = new (std::nothrow)MemPointerArrayImpl(); - _vm_data = new (std::nothrow)MemPointerArrayImpl(); - } else { - _malloc_data = new (std::nothrow)MemPointerArrayImpl(); - _vm_data = new (std::nothrow)MemPointerArrayImpl(); - } - - if (_malloc_data != NULL && _vm_data != NULL && - !_malloc_data->out_of_memory() && - !_vm_data->out_of_memory()) { - return true; - } else { - if (_malloc_data != NULL) delete _malloc_data; - if (_vm_data != NULL) delete _vm_data; - _malloc_data = NULL; - _vm_data = NULL; - return false; - } -} - - -VMRecordIterator StagingArea::virtual_memory_record_walker() { - MemPointerArray* arr = vm_data(); - // sort into seq number order - arr->sort((FN_SORT)sort_in_seq_order); - return VMRecordIterator(arr); -} - - -MemSnapshot::MemSnapshot() { - if (MemTracker::track_callsite()) { - _alloc_ptrs = new (std::nothrow) MemPointerArrayImpl(); - _vm_ptrs = new (std::nothrow)MemPointerArrayImpl(64, true); - } else { - _alloc_ptrs = new (std::nothrow) MemPointerArrayImpl(); - _vm_ptrs = new (std::nothrow)MemPointerArrayImpl(64, true); - } - - _staging_area.init(); - _lock = new (std::nothrow) Mutex(Monitor::max_nonleaf - 1, "memSnapshotLock"); - NOT_PRODUCT(_untracked_count = 0;) - _number_of_classes = 0; -} - -MemSnapshot::~MemSnapshot() { - assert(MemTracker::shutdown_in_progress(), "native memory tracking still on"); - { - MutexLockerEx locker(_lock); - if (_alloc_ptrs != NULL) { - delete _alloc_ptrs; - _alloc_ptrs = NULL; - } - - if (_vm_ptrs != NULL) { - delete _vm_ptrs; - _vm_ptrs = NULL; - } - } - - if (_lock != NULL) { - delete _lock; - _lock = NULL; - } -} - - -void MemSnapshot::copy_seq_pointer(MemPointerRecord* dest, const MemPointerRecord* src) { - assert(dest != NULL && src != NULL, "Just check"); - assert(dest->addr() == src->addr(), "Just check"); - assert(dest->seq() > 0 && src->seq() > 0, "not sequenced"); - - if (MemTracker::track_callsite()) { - *(SeqMemPointerRecordEx*)dest = *(SeqMemPointerRecordEx*)src; - } else { - *(SeqMemPointerRecord*)dest = *(SeqMemPointerRecord*)src; - } -} - -void MemSnapshot::assign_pointer(MemPointerRecord*dest, const MemPointerRecord* src) { - assert(src != NULL && dest != NULL, "Just check"); - assert(dest->seq() == 0 && src->seq() >0, "cast away sequence"); - - if (MemTracker::track_callsite()) { - *(MemPointerRecordEx*)dest = *(MemPointerRecordEx*)src; - } else { - *(MemPointerRecord*)dest = *(MemPointerRecord*)src; - } -} - -// merge a recorder to the staging area -bool MemSnapshot::merge(MemRecorder* rec) { - assert(rec != NULL && !rec->out_of_memory(), "Just check"); - - SequencedRecordIterator itr(rec->pointer_itr()); - - MutexLockerEx lock(_lock, true); - MemPointerIterator malloc_staging_itr(_staging_area.malloc_data()); - MemPointerRecord* incoming_rec = (MemPointerRecord*) itr.current(); - MemPointerRecord* matched_rec; - - while (incoming_rec != NULL) { - if (incoming_rec->is_vm_pointer()) { - // we don't do anything with virtual memory records during merge - if (!_staging_area.vm_data()->append(incoming_rec)) { - return false; - } - } else { - // locate matched record and/or also position the iterator to proper - // location for this incoming record. - matched_rec = (MemPointerRecord*)malloc_staging_itr.locate(incoming_rec->addr()); - // we have not seen this memory block in this generation, - // so just add to staging area - if (matched_rec == NULL) { - if (!malloc_staging_itr.insert(incoming_rec)) { - return false; - } - } else if (incoming_rec->addr() == matched_rec->addr()) { - // whoever has higher sequence number wins - if (incoming_rec->seq() > matched_rec->seq()) { - copy_seq_pointer(matched_rec, incoming_rec); - } - } else if (incoming_rec->addr() < matched_rec->addr()) { - if (!malloc_staging_itr.insert(incoming_rec)) { - return false; - } - } else { - ShouldNotReachHere(); - } - } - incoming_rec = (MemPointerRecord*)itr.next(); - } - NOT_PRODUCT(void check_staging_data();) - return true; -} - - -// promote data to next generation -bool MemSnapshot::promote(int number_of_classes) { - assert(_alloc_ptrs != NULL && _vm_ptrs != NULL, "Just check"); - assert(_staging_area.malloc_data() != NULL && _staging_area.vm_data() != NULL, - "Just check"); - MutexLockerEx lock(_lock, true); - - MallocRecordIterator malloc_itr = _staging_area.malloc_record_walker(); - bool promoted = false; - if (promote_malloc_records(&malloc_itr)) { - VMRecordIterator vm_itr = _staging_area.virtual_memory_record_walker(); - if (promote_virtual_memory_records(&vm_itr)) { - promoted = true; - } - } - - NOT_PRODUCT(check_malloc_pointers();) - _staging_area.clear(); - _number_of_classes = number_of_classes; - return promoted; -} - -bool MemSnapshot::promote_malloc_records(MemPointerArrayIterator* itr) { - MemPointerIterator malloc_snapshot_itr(_alloc_ptrs); - MemPointerRecord* new_rec = (MemPointerRecord*)itr->current(); - MemPointerRecord* matched_rec; - while (new_rec != NULL) { - matched_rec = (MemPointerRecord*)malloc_snapshot_itr.locate(new_rec->addr()); - // found matched memory block - if (matched_rec != NULL && new_rec->addr() == matched_rec->addr()) { - // snapshot already contains 'live' records - assert(matched_rec->is_allocation_record() || matched_rec->is_arena_memory_record(), - "Sanity check"); - // update block states - if (new_rec->is_allocation_record()) { - assign_pointer(matched_rec, new_rec); - } else if (new_rec->is_arena_memory_record()) { - if (new_rec->size() == 0) { - // remove size record once size drops to 0 - malloc_snapshot_itr.remove(); - } else { - assign_pointer(matched_rec, new_rec); - } - } else { - // a deallocation record - assert(new_rec->is_deallocation_record(), "Sanity check"); - // an arena record can be followed by a size record, we need to remove both - if (matched_rec->is_arena_record()) { - MemPointerRecord* next = (MemPointerRecord*)malloc_snapshot_itr.peek_next(); - if (next != NULL && next->is_arena_memory_record() && - next->is_memory_record_of_arena(matched_rec)) { - malloc_snapshot_itr.remove(); - } - } - // the memory is deallocated, remove related record(s) - malloc_snapshot_itr.remove(); - } - } else { - // don't insert size 0 record - if (new_rec->is_arena_memory_record() && new_rec->size() == 0) { - new_rec = NULL; - } - - if (new_rec != NULL) { - if (new_rec->is_allocation_record() || new_rec->is_arena_memory_record()) { - if (matched_rec != NULL && new_rec->addr() > matched_rec->addr()) { - if (!malloc_snapshot_itr.insert_after(new_rec)) { - return false; - } - } else { - if (!malloc_snapshot_itr.insert(new_rec)) { - return false; - } - } - } -#ifndef PRODUCT - else if (!has_allocation_record(new_rec->addr())) { - // NMT can not track some startup memory, which is allocated before NMT is on - _untracked_count ++; - } -#endif - } - } - new_rec = (MemPointerRecord*)itr->next(); - } - return true; -} - -bool MemSnapshot::promote_virtual_memory_records(MemPointerArrayIterator* itr) { - VMMemPointerIterator vm_snapshot_itr(_vm_ptrs); - MemPointerRecord* new_rec = (MemPointerRecord*)itr->current(); - VMMemRegion* reserved_rec; - while (new_rec != NULL) { - assert(new_rec->is_vm_pointer(), "Sanity check"); - - // locate a reserved region that contains the specified address, or - // the nearest reserved region has base address just above the specified - // address - reserved_rec = (VMMemRegion*)vm_snapshot_itr.locate(new_rec->addr()); - if (reserved_rec != NULL && reserved_rec->contains_region(new_rec)) { - // snapshot can only have 'live' records - assert(reserved_rec->is_reserved_region(), "Sanity check"); - if (new_rec->is_allocation_record()) { - if (!reserved_rec->is_same_region(new_rec)) { - // only deal with split a bigger reserved region into smaller regions. - // So far, CDS is the only use case. - if (!vm_snapshot_itr.split_reserved_region(reserved_rec, new_rec->addr(), new_rec->size())) { - return false; - } - } - } else if (new_rec->is_uncommit_record()) { - if (!vm_snapshot_itr.remove_uncommitted_region(new_rec)) { - return false; - } - } else if (new_rec->is_commit_record()) { - // insert or expand existing committed region to cover this - // newly committed region - if (!vm_snapshot_itr.add_committed_region(new_rec)) { - return false; - } - } else if (new_rec->is_deallocation_record()) { - // release part or all memory region - if (!vm_snapshot_itr.remove_released_region(new_rec)) { - return false; - } - } else if (new_rec->is_type_tagging_record()) { - // tag this reserved virtual memory range to a memory type. Can not re-tag a memory range - // to different type. - assert(FLAGS_TO_MEMORY_TYPE(reserved_rec->flags()) == mtNone || - FLAGS_TO_MEMORY_TYPE(reserved_rec->flags()) == FLAGS_TO_MEMORY_TYPE(new_rec->flags()), - "Sanity check"); - reserved_rec->tag(new_rec->flags()); - } else { - ShouldNotReachHere(); - } - } else { - /* - * The assertion failure indicates mis-matched virtual memory records. The likely - * scenario is, that some virtual memory operations are not going through os::xxxx_memory() - * api, which have to be tracked manually. (perfMemory is an example). - */ - assert(new_rec->is_allocation_record(), "Sanity check"); - if (!vm_snapshot_itr.add_reserved_region(new_rec)) { - return false; - } - } - new_rec = (MemPointerRecord*)itr->next(); - } - return true; -} - -#ifndef PRODUCT -void MemSnapshot::print_snapshot_stats(outputStream* st) { - st->print_cr("Snapshot:"); - st->print_cr("\tMalloced: %d/%d [%5.2f%%] %dKB", _alloc_ptrs->length(), _alloc_ptrs->capacity(), - (100.0 * (float)_alloc_ptrs->length()) / (float)_alloc_ptrs->capacity(), _alloc_ptrs->instance_size()/K); - - st->print_cr("\tVM: %d/%d [%5.2f%%] %dKB", _vm_ptrs->length(), _vm_ptrs->capacity(), - (100.0 * (float)_vm_ptrs->length()) / (float)_vm_ptrs->capacity(), _vm_ptrs->instance_size()/K); - - st->print_cr("\tMalloc staging Area: %d/%d [%5.2f%%] %dKB", _staging_area.malloc_data()->length(), - _staging_area.malloc_data()->capacity(), - (100.0 * (float)_staging_area.malloc_data()->length()) / (float)_staging_area.malloc_data()->capacity(), - _staging_area.malloc_data()->instance_size()/K); - - st->print_cr("\tVirtual memory staging Area: %d/%d [%5.2f%%] %dKB", _staging_area.vm_data()->length(), - _staging_area.vm_data()->capacity(), - (100.0 * (float)_staging_area.vm_data()->length()) / (float)_staging_area.vm_data()->capacity(), - _staging_area.vm_data()->instance_size()/K); - - st->print_cr("\tUntracked allocation: %d", _untracked_count); -} - -void MemSnapshot::check_malloc_pointers() { - MemPointerArrayIteratorImpl mItr(_alloc_ptrs); - MemPointerRecord* p = (MemPointerRecord*)mItr.current(); - MemPointerRecord* prev = NULL; - while (p != NULL) { - if (prev != NULL) { - assert(p->addr() >= prev->addr(), "sorting order"); - } - prev = p; - p = (MemPointerRecord*)mItr.next(); - } -} - -bool MemSnapshot::has_allocation_record(address addr) { - MemPointerArrayIteratorImpl itr(_staging_area.malloc_data()); - MemPointerRecord* cur = (MemPointerRecord*)itr.current(); - while (cur != NULL) { - if (cur->addr() == addr && cur->is_allocation_record()) { - return true; - } - cur = (MemPointerRecord*)itr.next(); - } - return false; -} -#endif // PRODUCT - -#ifdef ASSERT -void MemSnapshot::check_staging_data() { - MemPointerArrayIteratorImpl itr(_staging_area.malloc_data()); - MemPointerRecord* cur = (MemPointerRecord*)itr.current(); - MemPointerRecord* next = (MemPointerRecord*)itr.next(); - while (next != NULL) { - assert((next->addr() > cur->addr()) || - ((next->flags() & MemPointerRecord::tag_masks) > - (cur->flags() & MemPointerRecord::tag_masks)), - "sorting order"); - cur = next; - next = (MemPointerRecord*)itr.next(); - } - - MemPointerArrayIteratorImpl vm_itr(_staging_area.vm_data()); - cur = (MemPointerRecord*)vm_itr.current(); - while (cur != NULL) { - assert(cur->is_vm_pointer(), "virtual memory pointer only"); - cur = (MemPointerRecord*)vm_itr.next(); - } -} - -void MemSnapshot::dump_all_vm_pointers() { - MemPointerArrayIteratorImpl itr(_vm_ptrs); - VMMemRegion* ptr = (VMMemRegion*)itr.current(); - tty->print_cr("dump virtual memory pointers:"); - while (ptr != NULL) { - if (ptr->is_committed_region()) { - tty->print("\t"); - } - tty->print("[" PTR_FORMAT " - " PTR_FORMAT "] [%x]", ptr->addr(), - (ptr->addr() + ptr->size()), ptr->flags()); - - if (MemTracker::track_callsite()) { - VMMemRegionEx* ex = (VMMemRegionEx*)ptr; - if (ex->pc() != NULL) { - char buf[1024]; - if (os::dll_address_to_function_name(ex->pc(), buf, sizeof(buf), NULL)) { - tty->print_cr("\t%s", buf); - } else { - tty->cr(); - } - } - } - - ptr = (VMMemRegion*)itr.next(); - } - tty->flush(); -} -#endif // ASSERT - diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/services/memSnapshot.hpp --- a/hotspot/src/share/vm/services/memSnapshot.hpp Fri Aug 29 10:47:32 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,408 +0,0 @@ -/* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef SHARE_VM_SERVICES_MEM_SNAPSHOT_HPP -#define SHARE_VM_SERVICES_MEM_SNAPSHOT_HPP - -#include "memory/allocation.hpp" -#include "runtime/mutex.hpp" -#include "runtime/mutexLocker.hpp" -#include "services/memBaseline.hpp" -#include "services/memPtrArray.hpp" - -// Snapshot pointer array iterator - -// The pointer array contains malloc-ed pointers -class MemPointerIterator : public MemPointerArrayIteratorImpl { - public: - MemPointerIterator(MemPointerArray* arr): - MemPointerArrayIteratorImpl(arr) { - assert(arr != NULL, "null array"); - } - -#ifdef ASSERT - virtual bool is_dup_pointer(const MemPointer* ptr1, - const MemPointer* ptr2) const { - MemPointerRecord* p1 = (MemPointerRecord*)ptr1; - MemPointerRecord* p2 = (MemPointerRecord*)ptr2; - - if (p1->addr() != p2->addr()) return false; - if ((p1->flags() & MemPointerRecord::tag_masks) != - (p2->flags() & MemPointerRecord::tag_masks)) { - return false; - } - // we do see multiple commit/uncommit on the same memory, it is ok - return (p1->flags() & MemPointerRecord::tag_masks) == MemPointerRecord::tag_alloc || - (p1->flags() & MemPointerRecord::tag_masks) == MemPointerRecord::tag_release; - } - - virtual bool insert(MemPointer* ptr) { - if (_pos > 0) { - MemPointer* p1 = (MemPointer*)ptr; - MemPointer* p2 = (MemPointer*)_array->at(_pos - 1); - assert(!is_dup_pointer(p1, p2), - err_msg("duplicated pointer, flag = [%x]", (unsigned int)((MemPointerRecord*)p1)->flags())); - } - if (_pos < _array->length() -1) { - MemPointer* p1 = (MemPointer*)ptr; - MemPointer* p2 = (MemPointer*)_array->at(_pos + 1); - assert(!is_dup_pointer(p1, p2), - err_msg("duplicated pointer, flag = [%x]", (unsigned int)((MemPointerRecord*)p1)->flags())); - } - return _array->insert_at(ptr, _pos); - } - - virtual bool insert_after(MemPointer* ptr) { - if (_pos > 0) { - MemPointer* p1 = (MemPointer*)ptr; - MemPointer* p2 = (MemPointer*)_array->at(_pos - 1); - assert(!is_dup_pointer(p1, p2), - err_msg("duplicated pointer, flag = [%x]", (unsigned int)((MemPointerRecord*)p1)->flags())); - } - if (_pos < _array->length() - 1) { - MemPointer* p1 = (MemPointer*)ptr; - MemPointer* p2 = (MemPointer*)_array->at(_pos + 1); - - assert(!is_dup_pointer(p1, p2), - err_msg("duplicated pointer, flag = [%x]", (unsigned int)((MemPointerRecord*)p1)->flags())); - } - if (_array->insert_at(ptr, _pos + 1)) { - _pos ++; - return true; - } - return false; - } -#endif - - virtual MemPointer* locate(address addr) { - MemPointer* cur = current(); - while (cur != NULL && cur->addr() < addr) { - cur = next(); - } - return cur; - } -}; - -class VMMemPointerIterator : public MemPointerIterator { - public: - VMMemPointerIterator(MemPointerArray* arr): - MemPointerIterator(arr) { - } - - // locate an existing reserved memory region that contains specified address, - // or the reserved region just above this address, where the incoming - // reserved region should be inserted. - virtual MemPointer* locate(address addr) { - reset(); - VMMemRegion* reg = (VMMemRegion*)current(); - while (reg != NULL) { - if (reg->is_reserved_region()) { - if (reg->contains_address(addr) || addr < reg->base()) { - return reg; - } - } - reg = (VMMemRegion*)next(); - } - return NULL; - } - - // following methods update virtual memory in the context - // of 'current' position, which is properly positioned by - // callers via locate method. - bool add_reserved_region(MemPointerRecord* rec); - bool add_committed_region(MemPointerRecord* rec); - bool remove_uncommitted_region(MemPointerRecord* rec); - bool remove_released_region(MemPointerRecord* rec); - - // split a reserved region to create a new memory region with specified base and size - bool split_reserved_region(VMMemRegion* rgn, address new_rgn_addr, size_t new_rgn_size); - private: - bool insert_record(MemPointerRecord* rec); - bool insert_record_after(MemPointerRecord* rec); - - bool insert_reserved_region(MemPointerRecord* rec); - - // reset current position - inline void reset() { _pos = 0; } -#ifdef ASSERT - // check integrity of records on current reserved memory region. - bool check_reserved_region() { - VMMemRegion* reserved_region = (VMMemRegion*)current(); - assert(reserved_region != NULL && reserved_region->is_reserved_region(), - "Sanity check"); - // all committed regions that follow current reserved region, should all - // belong to the reserved region. - VMMemRegion* next_region = (VMMemRegion*)next(); - for (; next_region != NULL && next_region->is_committed_region(); - next_region = (VMMemRegion*)next() ) { - if(!reserved_region->contains_region(next_region)) { - return false; - } - } - return true; - } - - virtual bool is_dup_pointer(const MemPointer* ptr1, - const MemPointer* ptr2) const { - VMMemRegion* p1 = (VMMemRegion*)ptr1; - VMMemRegion* p2 = (VMMemRegion*)ptr2; - - if (p1->addr() != p2->addr()) return false; - if ((p1->flags() & MemPointerRecord::tag_masks) != - (p2->flags() & MemPointerRecord::tag_masks)) { - return false; - } - // we do see multiple commit/uncommit on the same memory, it is ok - return (p1->flags() & MemPointerRecord::tag_masks) == MemPointerRecord::tag_alloc || - (p1->flags() & MemPointerRecord::tag_masks) == MemPointerRecord::tag_release; - } -#endif -}; - -class MallocRecordIterator : public MemPointerArrayIterator { - private: - MemPointerArrayIteratorImpl _itr; - - - - public: - MallocRecordIterator(MemPointerArray* arr) : _itr(arr) { - } - - virtual MemPointer* current() const { -#ifdef ASSERT - MemPointer* cur_rec = _itr.current(); - if (cur_rec != NULL) { - MemPointer* prev_rec = _itr.peek_prev(); - MemPointer* next_rec = _itr.peek_next(); - assert(prev_rec == NULL || prev_rec->addr() < cur_rec->addr(), "Sorting order"); - assert(next_rec == NULL || next_rec->addr() > cur_rec->addr(), "Sorting order"); - } -#endif - return _itr.current(); - } - virtual MemPointer* next() { - MemPointerRecord* next_rec = (MemPointerRecord*)_itr.next(); - // arena memory record is a special case, which we have to compare - // sequence number against its associated arena record. - if (next_rec != NULL && next_rec->is_arena_memory_record()) { - MemPointerRecord* prev_rec = (MemPointerRecord*)_itr.peek_prev(); - // if there is an associated arena record, it has to be previous - // record because of sorting order (by address) - NMT generates a pseudo address - // for arena's size record by offsetting arena's address, that guarantees - // the order of arena record and it's size record. - if (prev_rec != NULL && prev_rec->is_arena_record() && - next_rec->is_memory_record_of_arena(prev_rec)) { - if (prev_rec->seq() > next_rec->seq()) { - // Skip this arena memory record - // Two scenarios: - // - if the arena record is an allocation record, this early - // size record must be leftover by previous arena, - // and the last size record should have size = 0. - // - if the arena record is a deallocation record, this - // size record should be its cleanup record, which should - // also have size = 0. In other world, arena alway reset - // its size before gone (see Arena's destructor) - assert(next_rec->size() == 0, "size not reset"); - return _itr.next(); - } else { - assert(prev_rec->is_allocation_record(), - "Arena size record ahead of allocation record"); - } - } - } - return next_rec; - } - - MemPointer* peek_next() const { ShouldNotReachHere(); return NULL; } - MemPointer* peek_prev() const { ShouldNotReachHere(); return NULL; } - void remove() { ShouldNotReachHere(); } - bool insert(MemPointer* ptr) { ShouldNotReachHere(); return false; } - bool insert_after(MemPointer* ptr) { ShouldNotReachHere(); return false; } -}; - -// collapse duplicated records. Eliminating duplicated records here, is much -// cheaper than during promotion phase. However, it does have limitation - it -// can only eliminate duplicated records within the generation, there are -// still chances seeing duplicated records during promotion. -// We want to use the record with higher sequence number, because it has -// more accurate callsite pc. -class VMRecordIterator : public MemPointerArrayIterator { - private: - MemPointerArrayIteratorImpl _itr; - - public: - VMRecordIterator(MemPointerArray* arr) : _itr(arr) { - MemPointerRecord* cur = (MemPointerRecord*)_itr.current(); - MemPointerRecord* next = (MemPointerRecord*)_itr.peek_next(); - while (next != NULL) { - assert(cur != NULL, "Sanity check"); - assert(((SeqMemPointerRecord*)next)->seq() > ((SeqMemPointerRecord*)cur)->seq(), - "pre-sort order"); - - if (is_duplicated_record(cur, next)) { - _itr.next(); - next = (MemPointerRecord*)_itr.peek_next(); - } else { - break; - } - } - } - - virtual MemPointer* current() const { - return _itr.current(); - } - - // get next record, but skip the duplicated records - virtual MemPointer* next() { - MemPointerRecord* cur = (MemPointerRecord*)_itr.next(); - MemPointerRecord* next = (MemPointerRecord*)_itr.peek_next(); - while (next != NULL) { - assert(cur != NULL, "Sanity check"); - assert(((SeqMemPointerRecord*)next)->seq() > ((SeqMemPointerRecord*)cur)->seq(), - "pre-sort order"); - - if (is_duplicated_record(cur, next)) { - _itr.next(); - cur = next; - next = (MemPointerRecord*)_itr.peek_next(); - } else { - break; - } - } - return cur; - } - - MemPointer* peek_next() const { ShouldNotReachHere(); return NULL; } - MemPointer* peek_prev() const { ShouldNotReachHere(); return NULL; } - void remove() { ShouldNotReachHere(); } - bool insert(MemPointer* ptr) { ShouldNotReachHere(); return false; } - bool insert_after(MemPointer* ptr) { ShouldNotReachHere(); return false; } - - private: - bool is_duplicated_record(MemPointerRecord* p1, MemPointerRecord* p2) const { - bool ret = (p1->addr() == p2->addr() && p1->size() == p2->size() && p1->flags() == p2->flags()); - assert(!(ret && FLAGS_TO_MEMORY_TYPE(p1->flags()) == mtThreadStack), "dup on stack record"); - return ret; - } -}; - -class StagingArea VALUE_OBJ_CLASS_SPEC { - private: - MemPointerArray* _malloc_data; - MemPointerArray* _vm_data; - - public: - StagingArea() : _malloc_data(NULL), _vm_data(NULL) { - init(); - } - - ~StagingArea() { - if (_malloc_data != NULL) delete _malloc_data; - if (_vm_data != NULL) delete _vm_data; - } - - MallocRecordIterator malloc_record_walker() { - return MallocRecordIterator(malloc_data()); - } - - VMRecordIterator virtual_memory_record_walker(); - - bool init(); - void clear() { - assert(_malloc_data != NULL && _vm_data != NULL, "Just check"); - _malloc_data->shrink(); - _malloc_data->clear(); - _vm_data->clear(); - } - - inline MemPointerArray* malloc_data() { return _malloc_data; } - inline MemPointerArray* vm_data() { return _vm_data; } -}; - -class MemBaseline; -class MemSnapshot : public CHeapObj { - private: - // the following two arrays contain records of all known lived memory blocks - // live malloc-ed memory pointers - MemPointerArray* _alloc_ptrs; - // live virtual memory pointers - MemPointerArray* _vm_ptrs; - - StagingArea _staging_area; - - // the lock to protect this snapshot - Monitor* _lock; - - // the number of instance classes - int _number_of_classes; - - NOT_PRODUCT(size_t _untracked_count;) - friend class MemBaseline; - - public: - MemSnapshot(); - virtual ~MemSnapshot(); - - // if we are running out of native memory - bool out_of_memory() { - return (_alloc_ptrs == NULL || - _staging_area.malloc_data() == NULL || - _staging_area.vm_data() == NULL || - _vm_ptrs == NULL || _lock == NULL || - _alloc_ptrs->out_of_memory() || - _vm_ptrs->out_of_memory()); - } - - // merge a per-thread memory recorder into staging area - bool merge(MemRecorder* rec); - // promote staged data to snapshot - bool promote(int number_of_classes); - - int number_of_classes() const { return _number_of_classes; } - - void wait(long timeout) { - assert(_lock != NULL, "Just check"); - MonitorLockerEx locker(_lock); - locker.wait(true, timeout); - } - - NOT_PRODUCT(void print_snapshot_stats(outputStream* st);) - NOT_PRODUCT(void check_staging_data();) - NOT_PRODUCT(void check_malloc_pointers();) - NOT_PRODUCT(bool has_allocation_record(address addr);) - // dump all virtual memory pointers in snapshot - DEBUG_ONLY( void dump_all_vm_pointers();) - - private: - // copy sequenced pointer from src to dest - void copy_seq_pointer(MemPointerRecord* dest, const MemPointerRecord* src); - // assign a sequenced pointer to non-sequenced pointer - void assign_pointer(MemPointerRecord*dest, const MemPointerRecord* src); - - bool promote_malloc_records(MemPointerArrayIterator* itr); - bool promote_virtual_memory_records(MemPointerArrayIterator* itr); -}; - -#endif // SHARE_VM_SERVICES_MEM_SNAPSHOT_HPP diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/services/memTrackWorker.cpp --- a/hotspot/src/share/vm/services/memTrackWorker.cpp Fri Aug 29 10:47:32 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,212 +0,0 @@ -/* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "precompiled.hpp" -#include "runtime/threadCritical.hpp" -#include "services/memTracker.hpp" -#include "services/memTrackWorker.hpp" -#include "utilities/decoder.hpp" -#include "utilities/vmError.hpp" - - -void GenerationData::reset() { - _number_of_classes = 0; - while (_recorder_list != NULL) { - MemRecorder* tmp = _recorder_list; - _recorder_list = _recorder_list->next(); - MemTracker::release_thread_recorder(tmp); - } -} - -MemTrackWorker::MemTrackWorker(MemSnapshot* snapshot): _snapshot(snapshot) { - // create thread uses cgc thread type for now. We should revisit - // the option, or create new thread type. - _has_error = !os::create_thread(this, os::cgc_thread); - set_name("MemTrackWorker"); - - // initial generation circuit buffer - if (!has_error()) { - _head = _tail = 0; - for(int index = 0; index < MAX_GENERATIONS; index ++) { - ::new ((void*)&_gen[index]) GenerationData(); - } - } - NOT_PRODUCT(_sync_point_count = 0;) - NOT_PRODUCT(_merge_count = 0;) - NOT_PRODUCT(_last_gen_in_use = 0;) -} - -MemTrackWorker::~MemTrackWorker() { - for (int index = 0; index < MAX_GENERATIONS; index ++) { - _gen[index].reset(); - } -} - -void* MemTrackWorker::operator new(size_t size) throw() { - assert(false, "use nothrow version"); - return NULL; -} - -void* MemTrackWorker::operator new(size_t size, const std::nothrow_t& nothrow_constant) throw() { - return allocate(size, false, mtNMT); -} - -void MemTrackWorker::start() { - os::start_thread(this); -} - -/* - * Native memory tracking worker thread loop: - * 1. merge one generation of memory recorders to staging area - * 2. promote staging data to memory snapshot - * - * This thread can run through safepoint. - */ - -void MemTrackWorker::run() { - assert(MemTracker::is_on(), "native memory tracking is off"); - this->initialize_thread_local_storage(); - this->record_stack_base_and_size(); - assert(_snapshot != NULL, "Worker should not be started"); - MemRecorder* rec; - unsigned long processing_generation = 0; - bool worker_idle = false; - - while (!MemTracker::shutdown_in_progress()) { - NOT_PRODUCT(_last_gen_in_use = generations_in_use();) - { - // take a recorder from earliest generation in buffer - ThreadCritical tc; - rec = _gen[_head].next_recorder(); - } - if (rec != NULL) { - if (rec->get_generation() != processing_generation || worker_idle) { - processing_generation = rec->get_generation(); - worker_idle = false; - MemTracker::set_current_processing_generation(processing_generation); - } - - // merge the recorder into staging area - if (!_snapshot->merge(rec)) { - MemTracker::shutdown(MemTracker::NMT_out_of_memory); - } else { - NOT_PRODUCT(_merge_count ++;) - } - MemTracker::release_thread_recorder(rec); - } else { - // no more recorder to merge, promote staging area - // to snapshot - if (_head != _tail) { - long number_of_classes; - { - ThreadCritical tc; - if (_gen[_head].has_more_recorder() || _head == _tail) { - continue; - } - number_of_classes = _gen[_head].number_of_classes(); - _gen[_head].reset(); - - // done with this generation, increment _head pointer - _head = (_head + 1) % MAX_GENERATIONS; - } - // promote this generation data to snapshot - if (!_snapshot->promote(number_of_classes)) { - // failed to promote, means out of memory - MemTracker::shutdown(MemTracker::NMT_out_of_memory); - } - } else { - // worker thread is idle - worker_idle = true; - MemTracker::report_worker_idle(); - _snapshot->wait(1000); - ThreadCritical tc; - // check if more data arrived - if (!_gen[_head].has_more_recorder()) { - _gen[_head].add_recorders(MemTracker::get_pending_recorders()); - } - } - } - } - assert(MemTracker::shutdown_in_progress(), "just check"); - - // transits to final shutdown - MemTracker::final_shutdown(); -} - -// at synchronization point, where 'safepoint visible' Java threads are blocked -// at a safepoint, and the rest of threads are blocked on ThreadCritical lock. -// The caller MemTracker::sync() already takes ThreadCritical before calling this -// method. -// -// Following tasks are performed: -// 1. add all recorders in pending queue to current generation -// 2. increase generation - -void MemTrackWorker::at_sync_point(MemRecorder* rec, int number_of_classes) { - NOT_PRODUCT(_sync_point_count ++;) - assert(count_recorder(rec) <= MemRecorder::_instance_count, - "pending queue has infinite loop"); - - bool out_of_generation_buffer = false; - // check shutdown state inside ThreadCritical - if (MemTracker::shutdown_in_progress()) return; - - _gen[_tail].set_number_of_classes(number_of_classes); - // append the recorders to the end of the generation - _gen[_tail].add_recorders(rec); - assert(count_recorder(_gen[_tail].peek()) <= MemRecorder::_instance_count, - "after add to current generation has infinite loop"); - // we have collected all recorders for this generation. If there is data, - // we need to increment _tail to start a new generation. - if (_gen[_tail].has_more_recorder() || _head == _tail) { - _tail = (_tail + 1) % MAX_GENERATIONS; - out_of_generation_buffer = (_tail == _head); - } - - if (out_of_generation_buffer) { - MemTracker::shutdown(MemTracker::NMT_out_of_generation); - } -} - -#ifndef PRODUCT -int MemTrackWorker::count_recorder(const MemRecorder* head) { - int count = 0; - while(head != NULL) { - count ++; - head = head->next(); - } - return count; -} - -int MemTrackWorker::count_pending_recorders() const { - int count = 0; - for (int index = 0; index < MAX_GENERATIONS; index ++) { - MemRecorder* head = _gen[index].peek(); - if (head != NULL) { - count += count_recorder(head); - } - } - return count; -} -#endif diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/services/memTrackWorker.hpp --- a/hotspot/src/share/vm/services/memTrackWorker.hpp Fri Aug 29 10:47:32 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef SHARE_VM_SERVICES_MEM_TRACK_WORKER_HPP -#define SHARE_VM_SERVICES_MEM_TRACK_WORKER_HPP - -#include "memory/allocation.hpp" -#include "runtime/thread.hpp" -#include "services/memRecorder.hpp" - -// Maximum MAX_GENERATIONS generation data can be tracked. -#define MAX_GENERATIONS 512 - -class GenerationData VALUE_OBJ_CLASS_SPEC { - private: - int _number_of_classes; - MemRecorder* _recorder_list; - - public: - GenerationData(): _number_of_classes(0), _recorder_list(NULL) { } - - inline int number_of_classes() const { return _number_of_classes; } - inline void set_number_of_classes(long num) { _number_of_classes = num; } - - inline MemRecorder* next_recorder() { - if (_recorder_list == NULL) { - return NULL; - } else { - MemRecorder* tmp = _recorder_list; - _recorder_list = _recorder_list->next(); - return tmp; - } - } - - inline bool has_more_recorder() const { - return (_recorder_list != NULL); - } - - // add recorders to this generation - void add_recorders(MemRecorder* head) { - if (head != NULL) { - if (_recorder_list == NULL) { - _recorder_list = head; - } else { - MemRecorder* tmp = _recorder_list; - for (; tmp->next() != NULL; tmp = tmp->next()); - tmp->set_next(head); - } - } - } - - void reset(); - - NOT_PRODUCT(MemRecorder* peek() const { return _recorder_list; }) -}; - -class MemTrackWorker : public NamedThread { - private: - // circular buffer. This buffer contains generation data to be merged into global - // snaphsot. - // Each slot holds a generation - GenerationData _gen[MAX_GENERATIONS]; - int _head, _tail; // head and tail pointers to above circular buffer - - bool _has_error; - - MemSnapshot* _snapshot; - - public: - MemTrackWorker(MemSnapshot* snapshot); - ~MemTrackWorker(); - _NOINLINE_ void* operator new(size_t size) throw(); - _NOINLINE_ void* operator new(size_t size, const std::nothrow_t& nothrow_constant) throw(); - - void start(); - void run(); - - inline bool has_error() const { return _has_error; } - - // task at synchronization point - void at_sync_point(MemRecorder* pending_recorders, int number_of_classes); - - // for debugging purpose, they are not thread safe. - NOT_PRODUCT(static int count_recorder(const MemRecorder* head);) - NOT_PRODUCT(int count_pending_recorders() const;) - - NOT_PRODUCT(int _sync_point_count;) - NOT_PRODUCT(int _merge_count;) - NOT_PRODUCT(int _last_gen_in_use;) - - // how many generations are queued - inline int generations_in_use() const { - return (_tail >= _head ? (_tail - _head + 1) : (MAX_GENERATIONS - (_head - _tail) + 1)); - } -}; - -#endif // SHARE_VM_SERVICES_MEM_TRACK_WORKER_HPP diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/services/memTracker.cpp --- a/hotspot/src/share/vm/services/memTracker.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/services/memTracker.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -23,862 +23,308 @@ */ #include "precompiled.hpp" -#include "oops/instanceKlass.hpp" -#include "runtime/atomic.inline.hpp" -#include "runtime/interfaceSupport.hpp" -#include "runtime/mutexLocker.hpp" -#include "runtime/safepoint.hpp" -#include "runtime/threadCritical.hpp" -#include "runtime/thread.inline.hpp" -#include "runtime/vm_operations.hpp" -#include "services/memPtr.hpp" +#include "runtime/mutex.hpp" +#include "services/memBaseline.hpp" #include "services/memReporter.hpp" +#include "services/mallocTracker.inline.hpp" #include "services/memTracker.hpp" -#include "utilities/decoder.hpp" #include "utilities/defaultStream.hpp" -#include "utilities/globalDefinitions.hpp" -bool NMT_track_callsite = false; +#ifdef SOLARIS + volatile bool NMT_stack_walkable = false; +#else + volatile bool NMT_stack_walkable = true; +#endif -// walk all 'known' threads at NMT sync point, and collect their recorders -void SyncThreadRecorderClosure::do_thread(Thread* thread) { - assert(SafepointSynchronize::is_at_safepoint(), "Safepoint required"); - if (thread->is_Java_thread()) { - JavaThread* javaThread = (JavaThread*)thread; - MemRecorder* recorder = javaThread->get_recorder(); - if (recorder != NULL) { - MemTracker::enqueue_pending_recorder(recorder); - javaThread->set_recorder(NULL); - } - } - _thread_count ++; -} +volatile NMT_TrackingLevel MemTracker::_tracking_level = NMT_unknown; +NMT_TrackingLevel MemTracker::_cmdline_tracking_level = NMT_unknown; + +NativeCallStack emptyStack(0, false); + +MemBaseline MemTracker::_baseline; +Mutex* MemTracker::_query_lock = NULL; +bool MemTracker::_is_nmt_env_valid = true; -MemRecorder* volatile MemTracker::_global_recorder = NULL; -MemSnapshot* MemTracker::_snapshot = NULL; -MemBaseline MemTracker::_baseline; -Mutex* MemTracker::_query_lock = NULL; -MemRecorder* volatile MemTracker::_merge_pending_queue = NULL; -MemRecorder* volatile MemTracker::_pooled_recorders = NULL; -MemTrackWorker* MemTracker::_worker_thread = NULL; -int MemTracker::_sync_point_skip_count = 0; -MemTracker::NMTLevel MemTracker::_tracking_level = MemTracker::NMT_off; -volatile MemTracker::NMTStates MemTracker::_state = NMT_uninited; -MemTracker::ShutdownReason MemTracker::_reason = NMT_shutdown_none; -int MemTracker::_thread_count = 255; -volatile jint MemTracker::_pooled_recorder_count = 0; -volatile unsigned long MemTracker::_processing_generation = 0; -volatile bool MemTracker::_worker_thread_idle = false; -volatile jint MemTracker::_pending_op_count = 0; -volatile bool MemTracker::_slowdown_calling_thread = false; -debug_only(intx MemTracker::_main_thread_tid = 0;) -NOT_PRODUCT(volatile jint MemTracker::_pending_recorder_count = 0;) - -void MemTracker::init_tracking_options(const char* option_line) { - _tracking_level = NMT_off; - if (strcmp(option_line, "=summary") == 0) { - _tracking_level = NMT_summary; - } else if (strcmp(option_line, "=detail") == 0) { - // detail relies on a stack-walking ability that may not - // be available depending on platform and/or compiler flags +NMT_TrackingLevel MemTracker::init_tracking_level() { + NMT_TrackingLevel level = NMT_off; + char buf[64]; + char nmt_option[64]; + jio_snprintf(buf, sizeof(buf), "NMT_LEVEL_%d", os::current_process_id()); + if (os::getenv(buf, nmt_option, sizeof(nmt_option))) { + if (strcmp(nmt_option, "summary") == 0) { + level = NMT_summary; + } else if (strcmp(nmt_option, "detail") == 0) { #if PLATFORM_NATIVE_STACK_WALKING_SUPPORTED - _tracking_level = NMT_detail; + level = NMT_detail; #else - jio_fprintf(defaultStream::error_stream(), - "NMT detail is not supported on this platform. Using NMT summary instead.\n"); - _tracking_level = NMT_summary; -#endif - } else if (strcmp(option_line, "=off") != 0) { - vm_exit_during_initialization("Syntax error, expecting -XX:NativeMemoryTracking=[off|summary|detail]", NULL); - } -} - -// first phase of bootstrapping, when VM is still in single-threaded mode. -void MemTracker::bootstrap_single_thread() { - if (_tracking_level > NMT_off) { - assert(_state == NMT_uninited, "wrong state"); - - // NMT is not supported with UseMallocOnly is on. NMT can NOT - // handle the amount of malloc data without significantly impacting - // runtime performance when this flag is on. - if (UseMallocOnly) { - shutdown(NMT_use_malloc_only); - return; + level = NMT_summary; +#endif // PLATFORM_NATIVE_STACK_WALKING_SUPPORTED + } else if (strcmp(nmt_option, "off") != 0) { + // The option value is invalid + _is_nmt_env_valid = false; } - _query_lock = new (std::nothrow) Mutex(Monitor::max_nonleaf, "NMT_queryLock"); - if (_query_lock == NULL) { - shutdown(NMT_out_of_memory); - return; - } + // Remove the environment variable to avoid leaking to child processes + os::unsetenv(buf); + } - debug_only(_main_thread_tid = os::current_thread_id();) - _state = NMT_bootstrapping_single_thread; - NMT_track_callsite = (_tracking_level == NMT_detail && can_walk_stack()); + if (!MallocTracker::initialize(level) || + !VirtualMemoryTracker::initialize(level)) { + level = NMT_off; } + return level; } -// second phase of bootstrapping, when VM is about to or already entered multi-theaded mode. -void MemTracker::bootstrap_multi_thread() { - if (_tracking_level > NMT_off && _state == NMT_bootstrapping_single_thread) { - // create nmt lock for multi-thread execution - assert(_main_thread_tid == os::current_thread_id(), "wrong thread"); - _state = NMT_bootstrapping_multi_thread; - NMT_track_callsite = (_tracking_level == NMT_detail && can_walk_stack()); - } -} - -// fully start nmt -void MemTracker::start() { - // Native memory tracking is off from command line option - if (_tracking_level == NMT_off || shutdown_in_progress()) return; - - assert(_main_thread_tid == os::current_thread_id(), "wrong thread"); - assert(_state == NMT_bootstrapping_multi_thread, "wrong state"); - - _snapshot = new (std::nothrow)MemSnapshot(); - if (_snapshot != NULL) { - if (!_snapshot->out_of_memory() && start_worker(_snapshot)) { - _state = NMT_started; - NMT_track_callsite = (_tracking_level == NMT_detail && can_walk_stack()); - return; - } - - delete _snapshot; - _snapshot = NULL; - } - - // fail to start native memory tracking, shut it down - shutdown(NMT_initialization); -} - -/** - * Shutting down native memory tracking. - * We can not shutdown native memory tracking immediately, so we just - * setup shutdown pending flag, every native memory tracking component - * should orderly shut itself down. - * - * The shutdown sequences: - * 1. MemTracker::shutdown() sets MemTracker to shutdown pending state - * 2. Worker thread calls MemTracker::final_shutdown(), which transites - * MemTracker to final shutdown state. - * 3. At sync point, MemTracker does final cleanup, before sets memory - * tracking level to off to complete shutdown. - */ -void MemTracker::shutdown(ShutdownReason reason) { - if (_tracking_level == NMT_off) return; - - if (_state <= NMT_bootstrapping_single_thread) { - // we still in single thread mode, there is not contention - _state = NMT_shutdown_pending; - _reason = reason; - } else { - // we want to know who initialized shutdown - if ((jint)NMT_started == Atomic::cmpxchg((jint)NMT_shutdown_pending, - (jint*)&_state, (jint)NMT_started)) { - _reason = reason; - } - } -} - -// final phase of shutdown -void MemTracker::final_shutdown() { - // delete all pending recorders and pooled recorders - delete_all_pending_recorders(); - delete_all_pooled_recorders(); - - { - // shared baseline and snapshot are the only objects needed to - // create query results - MutexLockerEx locker(_query_lock, true); - // cleanup baseline data and snapshot - _baseline.clear(); - delete _snapshot; - _snapshot = NULL; - } - - // shutdown shared decoder instance, since it is only - // used by native memory tracking so far. - Decoder::shutdown(); - - MemTrackWorker* worker = NULL; - { - ThreadCritical tc; - // can not delete worker inside the thread critical - if (_worker_thread != NULL && Thread::current() == _worker_thread) { - worker = _worker_thread; - _worker_thread = NULL; - } - } - if (worker != NULL) { - delete worker; - } - _state = NMT_final_shutdown; -} - -// delete all pooled recorders -void MemTracker::delete_all_pooled_recorders() { - // free all pooled recorders - MemRecorder* volatile cur_head = _pooled_recorders; - if (cur_head != NULL) { - MemRecorder* null_ptr = NULL; - while (cur_head != NULL && (void*)cur_head != Atomic::cmpxchg_ptr((void*)null_ptr, - (void*)&_pooled_recorders, (void*)cur_head)) { - cur_head = _pooled_recorders; - } - if (cur_head != NULL) { - delete cur_head; - _pooled_recorder_count = 0; +void MemTracker::init() { + if (tracking_level() >= NMT_summary) { + _query_lock = new (std::nothrow) Mutex(Monitor::max_nonleaf, "NMT_queryLock"); + // Already OOM. It is unlikely, but still have to handle it. + if (_query_lock == NULL) { + shutdown(); } } } -// delete all recorders in pending queue -void MemTracker::delete_all_pending_recorders() { - // free all pending recorders - MemRecorder* pending_head = get_pending_recorders(); - if (pending_head != NULL) { - delete pending_head; +bool MemTracker::check_launcher_nmt_support(const char* value) { + if (strcmp(value, "=detail") == 0) { +#if !PLATFORM_NATIVE_STACK_WALKING_SUPPORTED + jio_fprintf(defaultStream::error_stream(), + "NMT detail is not supported on this platform. Using NMT summary instead.\n"); + if (MemTracker::tracking_level() != NMT_summary) { + return false; + } +#else + if (MemTracker::tracking_level() != NMT_detail) { + return false; + } +#endif + } else if (strcmp(value, "=summary") == 0) { + if (MemTracker::tracking_level() != NMT_summary) { + return false; + } + } else if (strcmp(value, "=off") == 0) { + if (MemTracker::tracking_level() != NMT_off) { + return false; + } + } else { + _is_nmt_env_valid = false; + } + + return true; +} + +bool MemTracker::verify_nmt_option() { + return _is_nmt_env_valid; +} + +void* MemTracker::malloc_base(void* memblock) { + return MallocTracker::get_base(memblock); +} + +void Tracker::record(address addr, size_t size) { + if (MemTracker::tracking_level() < NMT_summary) return; + switch(_type) { + case uncommit: + VirtualMemoryTracker::remove_uncommitted_region(addr, size); + break; + case release: + VirtualMemoryTracker::remove_released_region(addr, size); + break; + default: + ShouldNotReachHere(); } } -/* - * retrieve per-thread recorder of specified thread. - * if thread == NULL, it means global recorder - */ -MemRecorder* MemTracker::get_thread_recorder(JavaThread* thread) { - if (shutdown_in_progress()) return NULL; + +// Shutdown can only be issued via JCmd, and NMT JCmd is serialized +// by lock +void MemTracker::shutdown() { + // We can only shutdown NMT to minimal tracking level if it is + // ever on. + if (tracking_level () > NMT_minimal) { + transition_to(NMT_minimal); + } +} + +bool MemTracker::transition_to(NMT_TrackingLevel level) { + NMT_TrackingLevel current_level = tracking_level(); - MemRecorder* rc; - if (thread == NULL) { - rc = _global_recorder; + if (current_level == level) { + return true; + } else if (current_level > level) { + // Downgrade tracking level, we want to lower the tracking + // level first + _tracking_level = level; + // Make _tracking_level visible immediately. + OrderAccess::fence(); + VirtualMemoryTracker::transition(current_level, level); + MallocTracker::transition(current_level, level); + + if (level == NMT_minimal) _baseline.reset(); } else { - rc = thread->get_recorder(); - } + VirtualMemoryTracker::transition(current_level, level); + MallocTracker::transition(current_level, level); - if (rc != NULL && rc->is_full()) { - enqueue_pending_recorder(rc); - rc = NULL; + _tracking_level = level; + // Make _tracking_level visible immediately. + OrderAccess::fence(); } - if (rc == NULL) { - rc = get_new_or_pooled_instance(); - if (thread == NULL) { - _global_recorder = rc; - } else { - thread->set_recorder(rc); - } - } - return rc; + return true; } -/* - * get a per-thread recorder from pool, or create a new one if - * there is not one available. - */ -MemRecorder* MemTracker::get_new_or_pooled_instance() { - MemRecorder* cur_head = const_cast (_pooled_recorders); - if (cur_head == NULL) { - MemRecorder* rec = new (std::nothrow)MemRecorder(); - if (rec == NULL || rec->out_of_memory()) { - shutdown(NMT_out_of_memory); - if (rec != NULL) { - delete rec; - rec = NULL; - } - } - return rec; - } else { - MemRecorder* next_head = cur_head->next(); - if ((void*)cur_head != Atomic::cmpxchg_ptr((void*)next_head, (void*)&_pooled_recorders, - (void*)cur_head)) { - return get_new_or_pooled_instance(); - } - cur_head->set_next(NULL); - Atomic::dec(&_pooled_recorder_count); - cur_head->set_generation(); - return cur_head; +void MemTracker::final_report(outputStream* output) { + assert(output != NULL, "No output stream"); + if (tracking_level() >= NMT_summary) { + MallocMemorySnapshot* malloc_memory_snapshot = + MallocMemorySummary::as_snapshot(); + malloc_memory_snapshot->make_adjustment(); + + VirtualMemorySnapshot* virtual_memory_snapshot = + VirtualMemorySummary::as_snapshot(); + + MemSummaryReporter rptr(malloc_memory_snapshot, + virtual_memory_snapshot, output); + rptr.report(); + // shutdown NMT, the data no longer accurate + shutdown(); } } -/* - * retrieve all recorders in pending queue, and empty the queue - */ -MemRecorder* MemTracker::get_pending_recorders() { - MemRecorder* cur_head = const_cast(_merge_pending_queue); - MemRecorder* null_ptr = NULL; - while ((void*)cur_head != Atomic::cmpxchg_ptr((void*)null_ptr, (void*)&_merge_pending_queue, - (void*)cur_head)) { - cur_head = const_cast(_merge_pending_queue); - } - NOT_PRODUCT(Atomic::store(0, &_pending_recorder_count)); - return cur_head; -} +// This is a walker to gather malloc site hashtable statistics, +// the result is used for tuning. +class StatisticsWalker : public MallocSiteWalker { + private: + enum Threshold { + // aggregates statistics over this threshold into one + // line item. + report_threshold = 20 + }; -/* - * release a recorder to recorder pool. - */ -void MemTracker::release_thread_recorder(MemRecorder* rec) { - assert(rec != NULL, "null recorder"); - // we don't want to pool too many recorders - rec->set_next(NULL); - if (shutdown_in_progress() || _pooled_recorder_count > _thread_count * 2) { - delete rec; - return; - } + private: + // Number of allocation sites that have all memory freed + int _empty_entries; + // Total number of allocation sites, include empty sites + int _total_entries; + // Number of captured call stack distribution + int _stack_depth_distribution[NMT_TrackingStackDepth]; + // Hash distribution + int _hash_distribution[report_threshold]; + // Number of hash buckets that have entries over the threshold + int _bucket_over_threshold; - rec->clear(); - MemRecorder* cur_head = const_cast(_pooled_recorders); - rec->set_next(cur_head); - while ((void*)cur_head != Atomic::cmpxchg_ptr((void*)rec, (void*)&_pooled_recorders, - (void*)cur_head)) { - cur_head = const_cast(_pooled_recorders); - rec->set_next(cur_head); - } - Atomic::inc(&_pooled_recorder_count); -} - -// write a record to proper recorder. No lock can be taken from this method -// down. -void MemTracker::write_tracking_record(address addr, MEMFLAGS flags, - size_t size, jint seq, address pc, JavaThread* thread) { + // The hash bucket that walker is currently walking + int _current_hash_bucket; + // The length of current hash bucket + int _current_bucket_length; + // Number of hash buckets that are not empty + int _used_buckets; + // Longest hash bucket length + int _longest_bucket_length; - MemRecorder* rc = get_thread_recorder(thread); - if (rc != NULL) { - rc->record(addr, flags, size, seq, pc); + public: + StatisticsWalker() : _empty_entries(0), _total_entries(0) { + int index = 0; + for (index = 0; index < NMT_TrackingStackDepth; index ++) { + _stack_depth_distribution[index] = 0; } -} - -/** - * enqueue a recorder to pending queue - */ -void MemTracker::enqueue_pending_recorder(MemRecorder* rec) { - assert(rec != NULL, "null recorder"); - - // we are shutting down, so just delete it - if (shutdown_in_progress()) { - rec->set_next(NULL); - delete rec; - return; + for (index = 0; index < report_threshold; index ++) { + _hash_distribution[index] = 0; + } + _bucket_over_threshold = 0; + _longest_bucket_length = 0; + _current_hash_bucket = -1; + _current_bucket_length = 0; + _used_buckets = 0; } - MemRecorder* cur_head = const_cast(_merge_pending_queue); - rec->set_next(cur_head); - while ((void*)cur_head != Atomic::cmpxchg_ptr((void*)rec, (void*)&_merge_pending_queue, - (void*)cur_head)) { - cur_head = const_cast(_merge_pending_queue); - rec->set_next(cur_head); + virtual bool do_malloc_site(const MallocSite* e) { + if (e->size() == 0) _empty_entries ++; + _total_entries ++; + + // stack depth distrubution + int frames = e->call_stack()->frames(); + _stack_depth_distribution[frames - 1] ++; + + // hash distribution + int hash_bucket = e->hash() % MallocSiteTable::hash_buckets(); + if (_current_hash_bucket == -1) { + _current_hash_bucket = hash_bucket; + _current_bucket_length = 1; + } else if (_current_hash_bucket == hash_bucket) { + _current_bucket_length ++; + } else { + record_bucket_length(_current_bucket_length); + _current_hash_bucket = hash_bucket; + _current_bucket_length = 1; + } + return true; } - NOT_PRODUCT(Atomic::inc(&_pending_recorder_count);) -} -/* - * The method is called at global safepoint - * during it synchronization process. - * 1. enqueue all JavaThreads' per-thread recorders - * 2. enqueue global recorder - * 3. retrieve all pending recorders - * 4. reset global sequence number generator - * 5. call worker's sync - */ -#define MAX_SAFEPOINTS_TO_SKIP 128 -#define SAFE_SEQUENCE_THRESHOLD 30 -#define HIGH_GENERATION_THRESHOLD 60 -#define MAX_RECORDER_THREAD_RATIO 30 -#define MAX_RECORDER_PER_THREAD 100 - -void MemTracker::sync() { - assert(_tracking_level > NMT_off, "NMT is not enabled"); - assert(SafepointSynchronize::is_at_safepoint(), "Safepoint required"); + // walk completed + void completed() { + record_bucket_length(_current_bucket_length); + } - // Some GC tests hit large number of safepoints in short period of time - // without meaningful activities. We should prevent going to - // sync point in these cases, which can potentially exhaust generation buffer. - // Here is the factots to determine if we should go into sync point: - // 1. not to overflow sequence number - // 2. if we are in danger to overflow generation buffer - // 3. how many safepoints we already skipped sync point - if (_state == NMT_started) { - // worker thread is not ready, no one can manage generation - // buffer, so skip this safepoint - if (_worker_thread == NULL) return; - - if (_sync_point_skip_count < MAX_SAFEPOINTS_TO_SKIP) { - int per_seq_in_use = SequenceGenerator::peek() * 100 / max_jint; - int per_gen_in_use = _worker_thread->generations_in_use() * 100 / MAX_GENERATIONS; - if (per_seq_in_use < SAFE_SEQUENCE_THRESHOLD && per_gen_in_use >= HIGH_GENERATION_THRESHOLD) { - _sync_point_skip_count ++; - return; + void report_statistics(outputStream* out) { + int index; + out->print_cr("Malloc allocation site table:"); + out->print_cr("\tTotal entries: %d", _total_entries); + out->print_cr("\tEmpty entries: %d (%2.2f%%)", _empty_entries, ((float)_empty_entries * 100) / _total_entries); + out->print_cr(" "); + out->print_cr("Hash distribution:"); + if (_used_buckets < MallocSiteTable::hash_buckets()) { + out->print_cr("empty bucket: %d", (MallocSiteTable::hash_buckets() - _used_buckets)); + } + for (index = 0; index < report_threshold; index ++) { + if (_hash_distribution[index] != 0) { + if (index == 0) { + out->print_cr(" %d entry: %d", 1, _hash_distribution[0]); + } else if (index < 9) { // single digit + out->print_cr(" %d entries: %d", (index + 1), _hash_distribution[index]); + } else { + out->print_cr(" %d entries: %d", (index + 1), _hash_distribution[index]); + } } } - { - // This method is running at safepoint, with ThreadCritical lock, - // it should guarantee that NMT is fully sync-ed. - ThreadCritical tc; - - // We can NOT execute NMT sync-point if there are pending tracking ops. - if (_pending_op_count == 0) { - SequenceGenerator::reset(); - _sync_point_skip_count = 0; - - // walk all JavaThreads to collect recorders - SyncThreadRecorderClosure stc; - Threads::threads_do(&stc); - - _thread_count = stc.get_thread_count(); - MemRecorder* pending_recorders = get_pending_recorders(); - - if (_global_recorder != NULL) { - _global_recorder->set_next(pending_recorders); - pending_recorders = _global_recorder; - _global_recorder = NULL; - } - - // see if NMT has too many outstanding recorder instances, it usually - // means that worker thread is lagging behind in processing them. - if (!AutoShutdownNMT) { - _slowdown_calling_thread = (MemRecorder::_instance_count > MAX_RECORDER_THREAD_RATIO * _thread_count); - } else { - // If auto shutdown is on, enforce MAX_RECORDER_PER_THREAD threshold to prevent OOM - if (MemRecorder::_instance_count >= _thread_count * MAX_RECORDER_PER_THREAD) { - shutdown(NMT_out_of_memory); - } - } - - // check _worker_thread with lock to avoid racing condition - if (_worker_thread != NULL) { - _worker_thread->at_sync_point(pending_recorders, InstanceKlass::number_of_instance_classes()); - } - assert(SequenceGenerator::peek() == 1, "Should not have memory activities during sync-point"); - } else { - _sync_point_skip_count ++; + if (_bucket_over_threshold > 0) { + out->print_cr(" >%d entries: %d", report_threshold, _bucket_over_threshold); + } + out->print_cr("most entries: %d", _longest_bucket_length); + out->print_cr(" "); + out->print_cr("Call stack depth distribution:"); + for (index = 0; index < NMT_TrackingStackDepth; index ++) { + if (_stack_depth_distribution[index] > 0) { + out->print_cr("\t%d: %d", index + 1, _stack_depth_distribution[index]); } } } - // now, it is the time to shut whole things off - if (_state == NMT_final_shutdown) { - // walk all JavaThreads to delete all recorders - SyncThreadRecorderClosure stc; - Threads::threads_do(&stc); - // delete global recorder - { - ThreadCritical tc; - if (_global_recorder != NULL) { - delete _global_recorder; - _global_recorder = NULL; - } - } - MemRecorder* pending_recorders = get_pending_recorders(); - if (pending_recorders != NULL) { - delete pending_recorders; - } - // try at a later sync point to ensure MemRecorder instance drops to zero to - // completely shutdown NMT - if (MemRecorder::_instance_count == 0) { - _state = NMT_shutdown; - _tracking_level = NMT_off; + private: + void record_bucket_length(int length) { + _used_buckets ++; + if (length <= report_threshold) { + _hash_distribution[length - 1] ++; + } else { + _bucket_over_threshold ++; } - } -} - -/* - * Start worker thread. - */ -bool MemTracker::start_worker(MemSnapshot* snapshot) { - assert(_worker_thread == NULL && _snapshot != NULL, "Just Check"); - _worker_thread = new (std::nothrow) MemTrackWorker(snapshot); - if (_worker_thread == NULL) { - return false; - } else if (_worker_thread->has_error()) { - delete _worker_thread; - _worker_thread = NULL; - return false; - } - _worker_thread->start(); - return true; -} - -/* - * We need to collect a JavaThread's per-thread recorder - * before it exits. - */ -void MemTracker::thread_exiting(JavaThread* thread) { - if (is_on()) { - MemRecorder* rec = thread->get_recorder(); - if (rec != NULL) { - enqueue_pending_recorder(rec); - thread->set_recorder(NULL); - } - } -} - -// baseline current memory snapshot -bool MemTracker::baseline() { - MutexLocker lock(_query_lock); - MemSnapshot* snapshot = get_snapshot(); - if (snapshot != NULL) { - return _baseline.baseline(*snapshot, false); - } - return false; -} - -// print memory usage from current snapshot -bool MemTracker::print_memory_usage(BaselineOutputer& out, size_t unit, bool summary_only) { - MemBaseline baseline; - MutexLocker lock(_query_lock); - MemSnapshot* snapshot = get_snapshot(); - if (snapshot != NULL && baseline.baseline(*snapshot, summary_only)) { - BaselineReporter reporter(out, unit); - reporter.report_baseline(baseline, summary_only); - return true; + _longest_bucket_length = MAX2(_longest_bucket_length, length); } - return false; -} - -// Whitebox API for blocking until the current generation of NMT data has been merged -bool MemTracker::wbtest_wait_for_data_merge() { - // NMT can't be shutdown while we're holding _query_lock - MutexLocker lock(_query_lock); - assert(_worker_thread != NULL, "Invalid query"); - // the generation at query time, so NMT will spin till this generation is processed - unsigned long generation_at_query_time = SequenceGenerator::current_generation(); - unsigned long current_processing_generation = _processing_generation; - // if generation counter overflown - bool generation_overflown = (generation_at_query_time < current_processing_generation); - long generations_to_wrap = MAX_UNSIGNED_LONG - current_processing_generation; - // spin - while (!shutdown_in_progress()) { - if (!generation_overflown) { - if (current_processing_generation > generation_at_query_time) { - return true; - } - } else { - assert(generations_to_wrap >= 0, "Sanity check"); - long current_generations_to_wrap = MAX_UNSIGNED_LONG - current_processing_generation; - assert(current_generations_to_wrap >= 0, "Sanity check"); - // to overflow an unsigned long should take long time, so to_wrap check should be sufficient - if (current_generations_to_wrap > generations_to_wrap && - current_processing_generation > generation_at_query_time) { - return true; - } - } - - // if worker thread is idle, but generation is not advancing, that means - // there is not safepoint to let NMT advance generation, force one. - if (_worker_thread_idle) { - VM_ForceSafepoint vfs; - VMThread::execute(&vfs); - } - MemSnapshot* snapshot = get_snapshot(); - if (snapshot == NULL) { - return false; - } - snapshot->wait(1000); - current_processing_generation = _processing_generation; - } - // We end up here if NMT is shutting down before our data has been merged - return false; -} - -// compare memory usage between current snapshot and baseline -bool MemTracker::compare_memory_usage(BaselineOutputer& out, size_t unit, bool summary_only) { - MutexLocker lock(_query_lock); - if (_baseline.baselined()) { - MemBaseline baseline; - MemSnapshot* snapshot = get_snapshot(); - if (snapshot != NULL && baseline.baseline(*snapshot, summary_only)) { - BaselineReporter reporter(out, unit); - reporter.diff_baselines(baseline, _baseline, summary_only); - return true; - } - } - return false; -} - -#ifndef PRODUCT -void MemTracker::walk_stack(int toSkip, char* buf, int len) { - int cur_len = 0; - char tmp[1024]; - address pc; - - while (cur_len < len) { - pc = os::get_caller_pc(toSkip + 1); - if (pc != NULL && os::dll_address_to_function_name(pc, tmp, sizeof(tmp), NULL)) { - jio_snprintf(&buf[cur_len], (len - cur_len), "%s\n", tmp); - cur_len = (int)strlen(buf); - } else { - buf[cur_len] = '\0'; - break; - } - toSkip ++; - } -} - -void MemTracker::print_tracker_stats(outputStream* st) { - st->print_cr("\nMemory Tracker Stats:"); - st->print_cr("\tMax sequence number = %d", SequenceGenerator::max_seq_num()); - st->print_cr("\tthead count = %d", _thread_count); - st->print_cr("\tArena instance = %d", Arena::_instance_count); - st->print_cr("\tpooled recorder count = %d", _pooled_recorder_count); - st->print_cr("\tqueued recorder count = %d", _pending_recorder_count); - st->print_cr("\tmemory recorder instance count = %d", MemRecorder::_instance_count); - if (_worker_thread != NULL) { - st->print_cr("\tWorker thread:"); - st->print_cr("\t\tSync point count = %d", _worker_thread->_sync_point_count); - st->print_cr("\t\tpending recorder count = %d", _worker_thread->count_pending_recorders()); - st->print_cr("\t\tmerge count = %d", _worker_thread->_merge_count); - } else { - st->print_cr("\tWorker thread is not started"); - } - st->print_cr(" "); - - if (_snapshot != NULL) { - _snapshot->print_snapshot_stats(st); - } else { - st->print_cr("No snapshot"); - } -} -#endif +}; -// Tracker Implementation +void MemTracker::tuning_statistics(outputStream* out) { + // NMT statistics + StatisticsWalker walker; + MallocSiteTable::walk_malloc_site(&walker); + walker.completed(); -/* - * Create a tracker. - * This is a fairly complicated constructor, as it has to make two important decisions: - * 1) Does it need to take ThreadCritical lock to write tracking record - * 2) Does it need to pre-reserve a sequence number for the tracking record - * - * The rules to determine if ThreadCritical is needed: - * 1. When nmt is in single-threaded bootstrapping mode, no lock is needed as VM - * still in single thread mode. - * 2. For all threads other than JavaThread, ThreadCritical is needed - * to write to recorders to global recorder. - * 3. For JavaThreads that are no longer visible by safepoint, also - * need to take ThreadCritical and records are written to global - * recorders, since these threads are NOT walked by Threads.do_thread(). - * 4. JavaThreads that are running in safepoint-safe states do not stop - * for safepoints, ThreadCritical lock should be taken to write - * memory records. - * 5. JavaThreads that are running in VM state do not need any lock and - * records are written to per-thread recorders. - * 6. For a thread has yet to attach VM 'Thread', they need to take - * ThreadCritical to write to global recorder. - * - * The memory operations that need pre-reserve sequence numbers: - * The memory operations that "release" memory blocks and the - * operations can fail, need to pre-reserve sequence number. They - * are realloc, uncommit and release. - * - * The reason for pre-reserve sequence number, is to prevent race condition: - * Thread 1 Thread 2 - * - * - * - * - * if Thread 2 happens to obtain the memory address Thread 1 just released, - * then NMT can mistakenly report the memory is free. - * - * Noticeably, free() does not need pre-reserve sequence number, because the call - * does not fail, so we can alway write "release" record before the memory is actaully - * freed. - * - * For realloc, uncommit and release, following coding pattern should be used: - * - * MemTracker::Tracker tkr = MemTracker::get_realloc_tracker(); - * ptr = ::realloc(...); - * if (ptr == NULL) { - * tkr.record(...) - * } else { - * tkr.discard(); - * } - * - * MemTracker::Tracker tkr = MemTracker::get_virtual_memory_uncommit_tracker(); - * if (uncommit(...)) { - * tkr.record(...); - * } else { - * tkr.discard(); - * } - * - * MemTracker::Tracker tkr = MemTracker::get_virtual_memory_release_tracker(); - * if (release(...)) { - * tkr.record(...); - * } else { - * tkr.discard(); - * } - * - * Since pre-reserved sequence number is only good for the generation that it is acquired, - * when there is pending Tracker that reserved sequence number, NMT sync-point has - * to be skipped to prevent from advancing generation. This is done by inc and dec - * MemTracker::_pending_op_count, when MemTracker::_pending_op_count > 0, NMT sync-point is skipped. - * Not all pre-reservation of sequence number will increment pending op count. For JavaThreads - * that honor safepoints, safepoint can not occur during the memory operations, so the - * pre-reserved sequence number won't cross the generation boundry. - */ -MemTracker::Tracker::Tracker(MemoryOperation op, Thread* thr) { - _op = NoOp; - _seq = 0; - if (MemTracker::is_on()) { - _java_thread = NULL; - _op = op; - - // figure out if ThreadCritical lock is needed to write this operation - // to MemTracker - if (MemTracker::is_single_threaded_bootstrap()) { - thr = NULL; - } else if (thr == NULL) { - // don't use Thread::current(), since it is possible that - // the calling thread has yet to attach to VM 'Thread', - // which will result assertion failure - thr = ThreadLocalStorage::thread(); - } - - if (thr != NULL) { - // Check NMT load - MemTracker::check_NMT_load(thr); - - if (thr->is_Java_thread() && ((JavaThread*)thr)->is_safepoint_visible()) { - _java_thread = (JavaThread*)thr; - JavaThreadState state = _java_thread->thread_state(); - // JavaThreads that are safepoint safe, can run through safepoint, - // so ThreadCritical is needed to ensure no threads at safepoint create - // new records while the records are being gathered and the sequence number is changing - _need_thread_critical_lock = - SafepointSynchronize::safepoint_safe(_java_thread, state); - } else { - _need_thread_critical_lock = true; - } - } else { - _need_thread_critical_lock - = !MemTracker::is_single_threaded_bootstrap(); - } - - // see if we need to pre-reserve sequence number for this operation - if (_op == Realloc || _op == Uncommit || _op == Release) { - if (_need_thread_critical_lock) { - ThreadCritical tc; - MemTracker::inc_pending_op_count(); - _seq = SequenceGenerator::next(); - } else { - // for the threads that honor safepoints, no safepoint can occur - // during the lifespan of tracker, so we don't need to increase - // pending op count. - _seq = SequenceGenerator::next(); - } - } - } + out->print_cr("Native Memory Tracking Statistics:"); + out->print_cr("Malloc allocation site table size: %d", MallocSiteTable::hash_buckets()); + out->print_cr(" Tracking stack depth: %d", NMT_TrackingStackDepth); + NOT_PRODUCT(out->print_cr("Peak concurrent access: %d", MallocSiteTable::access_peak_count());) + out->print_cr(" "); + walker.report_statistics(out); } -void MemTracker::Tracker::discard() { - if (MemTracker::is_on() && _seq != 0) { - if (_need_thread_critical_lock) { - ThreadCritical tc; - MemTracker::dec_pending_op_count(); - } - _seq = 0; - } -} - - -void MemTracker::Tracker::record(address old_addr, address new_addr, size_t size, - MEMFLAGS flags, address pc) { - assert(old_addr != NULL && new_addr != NULL, "Sanity check"); - assert(_op == Realloc || _op == NoOp, "Wrong call"); - if (MemTracker::is_on() && NMT_CAN_TRACK(flags) && _op != NoOp && !MemTracker::shutdown_in_progress()) { - assert(_seq > 0, "Need pre-reserve sequence number"); - if (_need_thread_critical_lock) { - ThreadCritical tc; - // free old address, use pre-reserved sequence number - MemTracker::write_tracking_record(old_addr, MemPointerRecord::free_tag(), - 0, _seq, pc, _java_thread); - MemTracker::write_tracking_record(new_addr, flags | MemPointerRecord::malloc_tag(), - size, SequenceGenerator::next(), pc, _java_thread); - // decrement MemTracker pending_op_count - MemTracker::dec_pending_op_count(); - } else { - // free old address, use pre-reserved sequence number - MemTracker::write_tracking_record(old_addr, MemPointerRecord::free_tag(), - 0, _seq, pc, _java_thread); - MemTracker::write_tracking_record(new_addr, flags | MemPointerRecord::malloc_tag(), - size, SequenceGenerator::next(), pc, _java_thread); - } - _seq = 0; - } -} - -void MemTracker::Tracker::record(address addr, size_t size, MEMFLAGS flags, address pc) { - // OOM already? - if (addr == NULL) return; - - if (MemTracker::is_on() && NMT_CAN_TRACK(flags) && _op != NoOp && !MemTracker::shutdown_in_progress()) { - bool pre_reserved_seq = (_seq != 0); - address pc = CALLER_CALLER_PC; - MEMFLAGS orig_flags = flags; - - // or the tagging flags - switch(_op) { - case Malloc: - flags |= MemPointerRecord::malloc_tag(); - break; - case Free: - flags = MemPointerRecord::free_tag(); - break; - case Realloc: - fatal("Use the other Tracker::record()"); - break; - case Reserve: - case ReserveAndCommit: - flags |= MemPointerRecord::virtual_memory_reserve_tag(); - break; - case Commit: - flags = MemPointerRecord::virtual_memory_commit_tag(); - break; - case Type: - flags |= MemPointerRecord::virtual_memory_type_tag(); - break; - case Uncommit: - assert(pre_reserved_seq, "Need pre-reserve sequence number"); - flags = MemPointerRecord::virtual_memory_uncommit_tag(); - break; - case Release: - assert(pre_reserved_seq, "Need pre-reserve sequence number"); - flags = MemPointerRecord::virtual_memory_release_tag(); - break; - case ArenaSize: - // a bit of hack here, add a small postive offset to arena - // address for its size record, so the size record is sorted - // right after arena record. - flags = MemPointerRecord::arena_size_tag(); - addr += sizeof(void*); - break; - case StackRelease: - flags = MemPointerRecord::virtual_memory_release_tag(); - break; - default: - ShouldNotReachHere(); - } - - // write memory tracking record - if (_need_thread_critical_lock) { - ThreadCritical tc; - if (_seq == 0) _seq = SequenceGenerator::next(); - MemTracker::write_tracking_record(addr, flags, size, _seq, pc, _java_thread); - if (_op == ReserveAndCommit) { - MemTracker::write_tracking_record(addr, orig_flags | MemPointerRecord::virtual_memory_commit_tag(), - size, SequenceGenerator::next(), pc, _java_thread); - } - if (pre_reserved_seq) MemTracker::dec_pending_op_count(); - } else { - if (_seq == 0) _seq = SequenceGenerator::next(); - MemTracker::write_tracking_record(addr, flags, size, _seq, pc, _java_thread); - if (_op == ReserveAndCommit) { - MemTracker::write_tracking_record(addr, orig_flags | MemPointerRecord::virtual_memory_commit_tag(), - size, SequenceGenerator::next(), pc, _java_thread); - } - } - _seq = 0; - } -} - diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/services/memTracker.hpp --- a/hotspot/src/share/vm/services/memTracker.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/services/memTracker.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -25,566 +25,289 @@ #ifndef SHARE_VM_SERVICES_MEM_TRACKER_HPP #define SHARE_VM_SERVICES_MEM_TRACKER_HPP -#include "utilities/macros.hpp" +#include "services/nmtCommon.hpp" + +class NativeCallStack; +extern NativeCallStack emptyStack; #if !INCLUDE_NMT -#include "utilities/ostream.hpp" +#define CURRENT_PC emptyStack +#define CALLER_PC emptyStack -class BaselineOutputer : public StackObj { - +class Tracker : public StackObj { + public: + Tracker() { } + void record(address addr, size_t size) { } }; -class BaselineTTYOutputer : public BaselineOutputer { - public: - BaselineTTYOutputer(outputStream* st) { } +class MemTracker : AllStatic { + public: + static inline NMT_TrackingLevel tracking_level() { return NMT_off; } + static inline void shutdown() { } + static inline void init() { } + static bool check_launcher_nmt_support(const char* value) { return true; } + static bool verify_nmt_option() { return true; } + + static inline void* record_malloc(void* mem_base, size_t size, MEMFLAGS flag, + const NativeCallStack& stack, NMT_TrackingLevel level) { return mem_base; } + static inline size_t malloc_header_size(NMT_TrackingLevel level) { return 0; } + static inline size_t malloc_header_size(void* memblock) { return 0; } + static inline void* malloc_base(void* memblock) { return memblock; } + static inline void* record_free(void* memblock) { return memblock; } + + static inline void record_new_arena(MEMFLAGS flag) { } + static inline void record_arena_free(MEMFLAGS flag) { } + static inline void record_arena_size_change(int diff, MEMFLAGS flag) { } + static inline void record_virtual_memory_reserve(void* addr, size_t size, const NativeCallStack& stack, + MEMFLAGS flag = mtNone) { } + static inline void record_virtual_memory_reserve_and_commit(void* addr, size_t size, + const NativeCallStack& stack, MEMFLAGS flag = mtNone) { } + static inline void record_virtual_memory_commit(void* addr, size_t size, const NativeCallStack& stack) { } + static inline Tracker get_virtual_memory_uncommit_tracker() { return Tracker(); } + static inline Tracker get_virtual_memory_release_tracker() { } + static inline void record_virtual_memory_type(void* addr, MEMFLAGS flag) { } + static inline void record_thread_stack(void* addr, size_t size) { } + static inline void release_thread_stack(void* addr, size_t size) { } + + static void final_report(outputStream*) { } +}; + +#else + +#include "runtime/atomic.hpp" +#include "runtime/threadCritical.hpp" +#include "services/mallocTracker.hpp" +#include "services/virtualMemoryTracker.hpp" + +extern volatile bool NMT_stack_walkable; + +#define CURRENT_PC ((MemTracker::tracking_level() == NMT_detail && NMT_stack_walkable) ? \ + NativeCallStack(0, true) : emptyStack) +#define CALLER_PC ((MemTracker::tracking_level() == NMT_detail && NMT_stack_walkable) ? \ + NativeCallStack(1, true) : emptyStack) + +class MemBaseline; +class Mutex; + +// Tracker is used for guarding 'release' semantics of virtual memory operation, to avoid +// the other thread obtains and records the same region that is just 'released' by current +// thread but before it can record the operation. +class Tracker : public StackObj { + public: + enum TrackerType { + uncommit, + release + }; + + public: + Tracker(enum TrackerType type) : _type(type) { } + void record(address addr, size_t size); + private: + enum TrackerType _type; + // Virtual memory tracking data structures are protected by ThreadCritical lock. + ThreadCritical _tc; }; class MemTracker : AllStatic { - public: - enum ShutdownReason { - NMT_shutdown_none, // no shutdown requested - NMT_shutdown_user, // user requested shutdown - NMT_normal, // normal shutdown, process exit - NMT_out_of_memory, // shutdown due to out of memory - NMT_initialization, // shutdown due to initialization failure - NMT_use_malloc_only, // can not combine NMT with UseMallocOnly flag - NMT_error_reporting, // shutdown by vmError::report_and_die() - NMT_out_of_generation, // running out of generation queue - NMT_sequence_overflow // overflow the sequence number - }; - - class Tracker { - public: - void discard() { } - - void record(address addr, size_t size = 0, MEMFLAGS flags = mtNone, address pc = NULL) { } - void record(address old_addr, address new_addr, size_t size, - MEMFLAGS flags, address pc = NULL) { } - }; - - private: - static Tracker _tkr; - - - public: - static inline void init_tracking_options(const char* option_line) { } - static inline bool is_on() { return false; } - static const char* reason() { return "Native memory tracking is not implemented"; } - static inline bool can_walk_stack() { return false; } - - static inline void bootstrap_single_thread() { } - static inline void bootstrap_multi_thread() { } - static inline void start() { } - - static inline void record_malloc(address addr, size_t size, MEMFLAGS flags, - address pc = 0, Thread* thread = NULL) { } - static inline void record_free(address addr, MEMFLAGS flags, Thread* thread = NULL) { } - static inline void record_arena_size(address addr, size_t size) { } - static inline void record_virtual_memory_reserve(address addr, size_t size, - MEMFLAGS flags, address pc = 0, Thread* thread = NULL) { } - static inline void record_virtual_memory_reserve_and_commit(address addr, size_t size, - MEMFLAGS flags, address pc = 0, Thread* thread = NULL) { } - static inline void record_virtual_memory_commit(address addr, size_t size, - address pc = 0, Thread* thread = NULL) { } - static inline void record_virtual_memory_release(address addr, size_t size, - Thread* thread = NULL) { } - static inline void record_virtual_memory_type(address base, MEMFLAGS flags, - Thread* thread = NULL) { } - static inline Tracker get_realloc_tracker() { return _tkr; } - static inline Tracker get_virtual_memory_uncommit_tracker() { return _tkr; } - static inline Tracker get_virtual_memory_release_tracker() { return _tkr; } - static inline bool baseline() { return false; } - static inline bool has_baseline() { return false; } - - static inline void set_autoShutdown(bool value) { } - static void shutdown(ShutdownReason reason) { } - static inline bool shutdown_in_progress() { return false; } - static bool print_memory_usage(BaselineOutputer& out, size_t unit, - bool summary_only = true) { return false; } - static bool compare_memory_usage(BaselineOutputer& out, size_t unit, - bool summary_only = true) { return false; } - - static bool wbtest_wait_for_data_merge() { return false; } - - static inline void sync() { } - static inline void thread_exiting(JavaThread* thread) { } -}; - - -#else // !INCLUDE_NMT - -#include "memory/allocation.hpp" -#include "runtime/globals.hpp" -#include "runtime/mutex.hpp" -#include "runtime/os.hpp" -#include "runtime/thread.hpp" -#include "services/memPtr.hpp" -#include "services/memRecorder.hpp" -#include "services/memSnapshot.hpp" -#include "services/memTrackWorker.hpp" - -extern bool NMT_track_callsite; - -#ifndef MAX_UNSIGNED_LONG -#define MAX_UNSIGNED_LONG (unsigned long)(-1) -#endif - -#ifdef ASSERT - #define DEBUG_CALLER_PC (NMT_track_callsite ? os::get_caller_pc(2) : 0) -#else - #define DEBUG_CALLER_PC 0 -#endif - -// The thread closure walks threads to collect per-thread -// memory recorders at NMT sync point -class SyncThreadRecorderClosure : public ThreadClosure { - private: - int _thread_count; - public: - SyncThreadRecorderClosure() { - _thread_count =0; - } - - void do_thread(Thread* thread); - int get_thread_count() const { - return _thread_count; - } -}; - -class BaselineOutputer; -class MemSnapshot; -class MemTrackWorker; -class Thread; -/* - * MemTracker is the 'gate' class to native memory tracking runtime. - */ -class MemTracker : AllStatic { - friend class GenerationData; - friend class MemTrackWorker; - friend class MemSnapshot; - friend class SyncThreadRecorderClosure; - - // NMT state - enum NMTStates { - NMT_uninited, // not yet initialized - NMT_bootstrapping_single_thread, // bootstrapping, VM is in single thread mode - NMT_bootstrapping_multi_thread, // bootstrapping, VM is about to enter multi-thread mode - NMT_started, // NMT fully started - NMT_shutdown_pending, // shutdown pending - NMT_final_shutdown, // in final phase of shutdown - NMT_shutdown // shutdown - }; - - public: - class Tracker : public StackObj { - friend class MemTracker; - public: - enum MemoryOperation { - NoOp, // no op - Malloc, // malloc - Realloc, // realloc - Free, // free - Reserve, // virtual memory reserve - Commit, // virtual memory commit - ReserveAndCommit, // virtual memory reserve and commit - StackAlloc = ReserveAndCommit, // allocate thread stack - Type, // assign virtual memory type - Uncommit, // virtual memory uncommit - Release, // virtual memory release - ArenaSize, // set arena size - StackRelease // release thread stack - }; - - - protected: - Tracker(MemoryOperation op, Thread* thr = NULL); - - public: - void discard(); - - void record(address addr, size_t size = 0, MEMFLAGS flags = mtNone, address pc = NULL); - void record(address old_addr, address new_addr, size_t size, - MEMFLAGS flags, address pc = NULL); - - private: - bool _need_thread_critical_lock; - JavaThread* _java_thread; - MemoryOperation _op; // memory operation - jint _seq; // reserved sequence number - }; - - - public: - // native memory tracking level - enum NMTLevel { - NMT_off, // native memory tracking is off - NMT_summary, // don't track callsite - NMT_detail // track callsite also - }; - - enum ShutdownReason { - NMT_shutdown_none, // no shutdown requested - NMT_shutdown_user, // user requested shutdown - NMT_normal, // normal shutdown, process exit - NMT_out_of_memory, // shutdown due to out of memory - NMT_initialization, // shutdown due to initialization failure - NMT_use_malloc_only, // can not combine NMT with UseMallocOnly flag - NMT_error_reporting, // shutdown by vmError::report_and_die() - NMT_out_of_generation, // running out of generation queue - NMT_sequence_overflow // overflow the sequence number - }; - - public: - // initialize NMT tracking level from command line options, called - // from VM command line parsing code - static void init_tracking_options(const char* option_line); - - // if NMT is enabled to record memory activities - static inline bool is_on() { - return (_tracking_level >= NMT_summary && - _state >= NMT_bootstrapping_single_thread); - } - - static inline enum NMTLevel tracking_level() { + static inline NMT_TrackingLevel tracking_level() { + if (_tracking_level == NMT_unknown) { + // No fencing is needed here, since JVM is in single-threaded + // mode. + _tracking_level = init_tracking_level(); + _cmdline_tracking_level = _tracking_level; + } return _tracking_level; } - // user readable reason for shutting down NMT - static const char* reason() { - switch(_reason) { - case NMT_shutdown_none: - return "Native memory tracking is not enabled"; - case NMT_shutdown_user: - return "Native memory tracking has been shutdown by user"; - case NMT_normal: - return "Native memory tracking has been shutdown due to process exiting"; - case NMT_out_of_memory: - return "Native memory tracking has been shutdown due to out of native memory"; - case NMT_initialization: - return "Native memory tracking failed to initialize"; - case NMT_error_reporting: - return "Native memory tracking has been shutdown due to error reporting"; - case NMT_out_of_generation: - return "Native memory tracking has been shutdown due to running out of generation buffer"; - case NMT_sequence_overflow: - return "Native memory tracking has been shutdown due to overflow the sequence number"; - case NMT_use_malloc_only: - return "Native memory tracking is not supported when UseMallocOnly is on"; - default: - ShouldNotReachHere(); - return NULL; - } + // A late initialization, for the stuff(s) can not be + // done in init_tracking_level(), which can NOT malloc + // any memory. + static void init(); + + // Shutdown native memory tracking + static void shutdown(); + + // Verify native memory tracking command line option. + // This check allows JVM to detect if compatible launcher + // is used. + // If an incompatible launcher is used, NMT may not be + // able to start, even it is enabled by command line option. + // A warning message should be given if it is encountered. + static bool check_launcher_nmt_support(const char* value); + + // This method checks native memory tracking environment + // variable value passed by launcher. + // Launcher only obligated to pass native memory tracking + // option value, but not obligated to validate the value, + // and launcher has option to discard native memory tracking + // option from the command line once it sets up the environment + // variable, so NMT has to catch the bad value here. + static bool verify_nmt_option(); + + // Transition the tracking level to specified level + static bool transition_to(NMT_TrackingLevel level); + + static inline void* record_malloc(void* mem_base, size_t size, MEMFLAGS flag, + const NativeCallStack& stack, NMT_TrackingLevel level) { + return MallocTracker::record_malloc(mem_base, size, flag, stack, level); + } + + static inline size_t malloc_header_size(NMT_TrackingLevel level) { + return MallocTracker::malloc_header_size(level); } - // test if we can walk native stack - static bool can_walk_stack() { - // native stack is not walkable during bootstrapping on sparc -#if defined(SPARC) - return (_state == NMT_started); -#else - return (_state >= NMT_bootstrapping_single_thread && _state <= NMT_started); -#endif + static size_t malloc_header_size(void* memblock) { + if (tracking_level() != NMT_off) { + return MallocTracker::get_header_size(memblock); + } + return 0; + } + + // To malloc base address, which is the starting address + // of malloc tracking header if tracking is enabled. + // Otherwise, it returns the same address. + static void* malloc_base(void* memblock); + + // Record malloc free and return malloc base address + static inline void* record_free(void* memblock) { + return MallocTracker::record_free(memblock); } - // if native memory tracking tracks callsite - static inline bool track_callsite() { return _tracking_level == NMT_detail; } + + // Record creation of an arena + static inline void record_new_arena(MEMFLAGS flag) { + if (tracking_level() < NMT_summary) return; + MallocTracker::record_new_arena(flag); + } + + // Record destruction of an arena + static inline void record_arena_free(MEMFLAGS flag) { + if (tracking_level() < NMT_summary) return; + MallocTracker::record_arena_free(flag); + } - // NMT automatically shuts itself down under extreme situation by default. - // When the value is set to false, NMT will try its best to stay alive, - // even it has to slow down VM. - static inline void set_autoShutdown(bool value) { - AutoShutdownNMT = value; - if (AutoShutdownNMT && _slowdown_calling_thread) { - _slowdown_calling_thread = false; + // Record arena size change. Arena size is the size of all arena + // chuncks that backing up the arena. + static inline void record_arena_size_change(int diff, MEMFLAGS flag) { + if (tracking_level() < NMT_summary) return; + MallocTracker::record_arena_size_change(diff, flag); + } + + static inline void record_virtual_memory_reserve(void* addr, size_t size, const NativeCallStack& stack, + MEMFLAGS flag = mtNone) { + if (tracking_level() < NMT_summary) return; + if (addr != NULL) { + ThreadCritical tc; + // Recheck to avoid potential racing during NMT shutdown + if (tracking_level() < NMT_summary) return; + VirtualMemoryTracker::add_reserved_region((address)addr, size, stack, flag); } } - // shutdown native memory tracking capability. Native memory tracking - // can be shutdown by VM when it encounters low memory scenarios. - // Memory tracker should gracefully shutdown itself, and preserve the - // latest memory statistics for post morten diagnosis. - static void shutdown(ShutdownReason reason); - - // if there is shutdown requested - static inline bool shutdown_in_progress() { - return (_state >= NMT_shutdown_pending); - } - - // bootstrap native memory tracking, so it can start to collect raw data - // before worker thread can start - - // the first phase of bootstrapping, when VM still in single-threaded mode - static void bootstrap_single_thread(); - // the second phase of bootstrapping, VM is about or already in multi-threaded mode - static void bootstrap_multi_thread(); - - - // start() has to be called when VM still in single thread mode, but after - // command line option parsing is done. - static void start(); - - // record a 'malloc' call - static inline void record_malloc(address addr, size_t size, MEMFLAGS flags, - address pc = 0, Thread* thread = NULL) { - Tracker tkr(Tracker::Malloc, thread); - tkr.record(addr, size, flags, pc); - } - // record a 'free' call - static inline void record_free(address addr, MEMFLAGS flags, Thread* thread = NULL) { - Tracker tkr(Tracker::Free, thread); - tkr.record(addr, 0, flags, DEBUG_CALLER_PC); - } - - static inline void record_arena_size(address addr, size_t size) { - Tracker tkr(Tracker::ArenaSize); - tkr.record(addr, size); - } - - // record a virtual memory 'reserve' call - static inline void record_virtual_memory_reserve(address addr, size_t size, - MEMFLAGS flags, address pc = 0, Thread* thread = NULL) { - assert(size > 0, "Sanity check"); - Tracker tkr(Tracker::Reserve, thread); - tkr.record(addr, size, flags, pc); - } - - static inline void record_thread_stack(address addr, size_t size, Thread* thr, - address pc = 0) { - Tracker tkr(Tracker::StackAlloc, thr); - tkr.record(addr, size, mtThreadStack, pc); - } - - static inline void release_thread_stack(address addr, size_t size, Thread* thr) { - Tracker tkr(Tracker::StackRelease, thr); - tkr.record(addr, size, mtThreadStack, DEBUG_CALLER_PC); - } - - // record a virtual memory 'commit' call - static inline void record_virtual_memory_commit(address addr, size_t size, - address pc, Thread* thread = NULL) { - Tracker tkr(Tracker::Commit, thread); - tkr.record(addr, size, mtNone, pc); - } - - static inline void record_virtual_memory_reserve_and_commit(address addr, size_t size, - MEMFLAGS flags, address pc, Thread* thread = NULL) { - Tracker tkr(Tracker::ReserveAndCommit, thread); - tkr.record(addr, size, flags, pc); - } - - static inline void record_virtual_memory_release(address addr, size_t size, - Thread* thread = NULL) { - if (is_on()) { - Tracker tkr(Tracker::Release, thread); - tkr.record(addr, size); + static inline void record_virtual_memory_reserve_and_commit(void* addr, size_t size, + const NativeCallStack& stack, MEMFLAGS flag = mtNone) { + if (tracking_level() < NMT_summary) return; + if (addr != NULL) { + ThreadCritical tc; + if (tracking_level() < NMT_summary) return; + VirtualMemoryTracker::add_reserved_region((address)addr, size, + stack, flag, true); } } - // record memory type on virtual memory base address - static inline void record_virtual_memory_type(address base, MEMFLAGS flags, - Thread* thread = NULL) { - Tracker tkr(Tracker::Type); - tkr.record(base, 0, flags); - } - - // Get memory trackers for memory operations that can result race conditions. - // The memory tracker has to be obtained before realloc, virtual memory uncommit - // and virtual memory release, and call tracker.record() method if operation - // succeeded, or tracker.discard() to abort the tracking. - static inline Tracker get_realloc_tracker() { - return Tracker(Tracker::Realloc); + static inline void record_virtual_memory_commit(void* addr, size_t size, + const NativeCallStack& stack) { + if (tracking_level() < NMT_summary) return; + if (addr != NULL) { + ThreadCritical tc; + if (tracking_level() < NMT_summary) return; + VirtualMemoryTracker::add_committed_region((address)addr, size, stack); + } } static inline Tracker get_virtual_memory_uncommit_tracker() { - return Tracker(Tracker::Uncommit); + assert(tracking_level() >= NMT_summary, "Check by caller"); + return Tracker(Tracker::uncommit); } static inline Tracker get_virtual_memory_release_tracker() { - return Tracker(Tracker::Release); - } - - - // create memory baseline of current memory snapshot - static bool baseline(); - // is there a memory baseline - static bool has_baseline() { - return _baseline.baselined(); + assert(tracking_level() >= NMT_summary, "Check by caller"); + return Tracker(Tracker::release); } - // print memory usage from current snapshot - static bool print_memory_usage(BaselineOutputer& out, size_t unit, - bool summary_only = true); - // compare memory usage between current snapshot and baseline - static bool compare_memory_usage(BaselineOutputer& out, size_t unit, - bool summary_only = true); - - // the version for whitebox testing support, it ensures that all memory - // activities before this method call, are reflected in the snapshot - // database. - static bool wbtest_wait_for_data_merge(); - - // sync is called within global safepoint to synchronize nmt data - static void sync(); - - // called when a thread is about to exit - static void thread_exiting(JavaThread* thread); - - // retrieve global snapshot - static MemSnapshot* get_snapshot() { - if (shutdown_in_progress()) { - return NULL; + static inline void record_virtual_memory_type(void* addr, MEMFLAGS flag) { + if (tracking_level() < NMT_summary) return; + if (addr != NULL) { + ThreadCritical tc; + if (tracking_level() < NMT_summary) return; + VirtualMemoryTracker::set_reserved_region_type((address)addr, flag); } - return _snapshot; } - // print tracker stats - NOT_PRODUCT(static void print_tracker_stats(outputStream* st);) - NOT_PRODUCT(static void walk_stack(int toSkip, char* buf, int len);) - - private: - // start native memory tracking worker thread - static bool start_worker(MemSnapshot* snapshot); - - // called by worker thread to complete shutdown process - static void final_shutdown(); - - protected: - // retrieve per-thread recorder of the specified thread. - // if the recorder is full, it will be enqueued to overflow - // queue, a new recorder is acquired from recorder pool or a - // new instance is created. - // when thread == NULL, it means global recorder - static MemRecorder* get_thread_recorder(JavaThread* thread); - - // per-thread recorder pool - static void release_thread_recorder(MemRecorder* rec); - static void delete_all_pooled_recorders(); - - // pending recorder queue. Recorders are queued to pending queue - // when they are overflowed or collected at nmt sync point. - static void enqueue_pending_recorder(MemRecorder* rec); - static MemRecorder* get_pending_recorders(); - static void delete_all_pending_recorders(); - - // write a memory tracking record in recorder - static void write_tracking_record(address addr, MEMFLAGS type, - size_t size, jint seq, address pc, JavaThread* thread); - - static bool is_single_threaded_bootstrap() { - return _state == NMT_bootstrapping_single_thread; + static inline void record_thread_stack(void* addr, size_t size) { + if (tracking_level() < NMT_summary) return; + if (addr != NULL) { + // uses thread stack malloc slot for book keeping number of threads + MallocMemorySummary::record_malloc(0, mtThreadStack); + record_virtual_memory_reserve_and_commit(addr, size, CALLER_PC, mtThreadStack); + } } - static void check_NMT_load(Thread* thr) { - assert(thr != NULL, "Sanity check"); - if (_slowdown_calling_thread && thr != _worker_thread) { -#ifdef _WINDOWS - // On Windows, os::NakedYield() does not work as well - // as short sleep. - os::naked_short_sleep(1); -#else - os::naked_yield(); -#endif + static inline void release_thread_stack(void* addr, size_t size) { + if (tracking_level() < NMT_summary) return; + if (addr != NULL) { + // uses thread stack malloc slot for book keeping number of threads + MallocMemorySummary::record_free(0, mtThreadStack); + ThreadCritical tc; + if (tracking_level() < NMT_summary) return; + VirtualMemoryTracker::remove_released_region((address)addr, size); } } - static void inc_pending_op_count() { - Atomic::inc(&_pending_op_count); - } + // Query lock is used to synchronize the access to tracking data. + // So far, it is only used by JCmd query, but it may be used by + // other tools. + static inline Mutex* query_lock() { return _query_lock; } - static void dec_pending_op_count() { - Atomic::dec(&_pending_op_count); - assert(_pending_op_count >= 0, "Sanity check"); + // Make a final report and shutdown. + // This function generates summary report without creating snapshots, + // to avoid additional memory allocation. It uses native memory summary + // counters, and makes adjustment to them, once the adjustment is made, + // the counters are no longer accurate. As the result, this function + // should only be used for final reporting before shutting down. + static void final_report(outputStream*); + + // Stored baseline + static inline MemBaseline& get_baseline() { + return _baseline; } - - private: - // retrieve a pooled memory record or create new one if there is not - // one available - static MemRecorder* get_new_or_pooled_instance(); - static void create_memory_record(address addr, MEMFLAGS type, - size_t size, address pc, Thread* thread); - static void create_record_in_recorder(address addr, MEMFLAGS type, - size_t size, address pc, JavaThread* thread); - - static void set_current_processing_generation(unsigned long generation) { - _worker_thread_idle = false; - _processing_generation = generation; + static NMT_TrackingLevel cmdline_tracking_level() { + return _cmdline_tracking_level; } - static void report_worker_idle() { - _worker_thread_idle = true; - } + static void tuning_statistics(outputStream* out); private: - // global memory snapshot - static MemSnapshot* _snapshot; - - // a memory baseline of snapshot - static MemBaseline _baseline; - - // query lock - static Mutex* _query_lock; - - // a thread can start to allocate memory before it is attached - // to VM 'Thread', those memory activities are recorded here. - // ThreadCritical is required to guard this global recorder. - static MemRecorder* volatile _global_recorder; - - // main thread id - debug_only(static intx _main_thread_tid;) - - // pending recorders to be merged - static MemRecorder* volatile _merge_pending_queue; - - NOT_PRODUCT(static volatile jint _pending_recorder_count;) - - // pooled memory recorders - static MemRecorder* volatile _pooled_recorders; - - // memory recorder pool management, uses following - // counter to determine if a released memory recorder - // should be pooled + static NMT_TrackingLevel init_tracking_level(); - // latest thread count - static int _thread_count; - // pooled recorder count - static volatile jint _pooled_recorder_count; - - - // worker thread to merge pending recorders into snapshot - static MemTrackWorker* _worker_thread; - - // how many safepoints we skipped without entering sync point - static int _sync_point_skip_count; - - // if the tracker is properly intialized - static bool _is_tracker_ready; - // tracking level (off, summary and detail) - static enum NMTLevel _tracking_level; - - // current nmt state - static volatile enum NMTStates _state; - // the reason for shutting down nmt - static enum ShutdownReason _reason; - // the generation that NMT is processing - static volatile unsigned long _processing_generation; - // although NMT is still procesing current generation, but - // there is not more recorder to process, set idle state - static volatile bool _worker_thread_idle; - - // if NMT should slow down calling thread to allow - // worker thread to catch up - static volatile bool _slowdown_calling_thread; - - // pending memory op count. - // Certain memory ops need to pre-reserve sequence number - // before memory operation can happen to avoid race condition. - // See MemTracker::Tracker for detail - static volatile jint _pending_op_count; + private: + // Tracking level + static volatile NMT_TrackingLevel _tracking_level; + // If NMT option value passed by launcher through environment + // variable is valid + static bool _is_nmt_env_valid; + // command line tracking level + static NMT_TrackingLevel _cmdline_tracking_level; + // Stored baseline + static MemBaseline _baseline; + // Query lock + static Mutex* _query_lock; }; -#endif // !INCLUDE_NMT +#endif // INCLUDE_NMT #endif // SHARE_VM_SERVICES_MEM_TRACKER_HPP + diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/services/nmtCommon.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/services/nmtCommon.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#include "precompiled.hpp" +#include "services/nmtCommon.hpp" + +const char* NMTUtil::_memory_type_names[] = { + "Java Heap", + "Class", + "Thread", + "Thread Stack", + "Code", + "GC", + "Compiler", + "Internal", + "Other", + "Symbol", + "Native Memory Tracking", + "Shared class space", + "Arena Chunk", + "Test", + "Tracing", + "Unknown" +}; + + +const char* NMTUtil::scale_name(size_t scale) { + switch(scale) { + case K: return "KB"; + case M: return "MB"; + case G: return "GB"; + } + ShouldNotReachHere(); + return NULL; +} + +size_t NMTUtil::scale_from_name(const char* scale) { + assert(scale != NULL, "Null pointer check"); + if (strncmp(scale, "KB", 2) == 0 || + strncmp(scale, "kb", 2) == 0) { + return K; + } else if (strncmp(scale, "MB", 2) == 0 || + strncmp(scale, "mb", 2) == 0) { + return M; + } else if (strncmp(scale, "GB", 2) == 0 || + strncmp(scale, "gb", 2) == 0) { + return G; + } else { + return 0; // Invalid value + } + return K; +} + diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/services/nmtCommon.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/services/nmtCommon.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_SERVICES_NMT_COMMON_HPP +#define SHARE_VM_SERVICES_NMT_COMMON_HPP + +#include "memory/allocation.hpp" +#include "utilities/globalDefinitions.hpp" + +#define CALC_OBJ_SIZE_IN_TYPE(obj, type) (align_size_up_(sizeof(obj), sizeof(type))/sizeof(type)) + +// Data type for memory counters +#ifdef _LP64 + typedef jlong MemoryCounterType; +#else + typedef jint MemoryCounterType; +#endif + +// Native memory tracking level +enum NMT_TrackingLevel { + NMT_unknown = 0xFF, + NMT_off = 0x00, + NMT_minimal = 0x01, + NMT_summary = 0x02, + NMT_detail = 0x03 +}; + +// Number of stack frames to capture. This is a +// build time decision. +const int NMT_TrackingStackDepth = 4; + +class NativeCallStack; +extern NativeCallStack emptyStack; + +// A few common utilities for native memory tracking +class NMTUtil : AllStatic { + public: + // Map memory type to index + static inline int flag_to_index(MEMFLAGS flag) { + return (flag & 0xff); + } + + // Map memory type to human readable name + static const char* flag_to_name(MEMFLAGS flag) { + return _memory_type_names[flag_to_index(flag)]; + } + + // Map an index to memory type + static MEMFLAGS index_to_flag(int index) { + return (MEMFLAGS)index; + } + + // Memory size scale + static const char* scale_name(size_t scale); + static size_t scale_from_name(const char* scale); + + // Translate memory size in specified scale + static size_t amount_in_scale(size_t amount, size_t scale) { + return (amount + scale / 2) / scale; + } + private: + static const char* _memory_type_names[mt_number_of_types]; +}; + + +#endif diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/services/nmtDCmd.cpp --- a/hotspot/src/share/vm/services/nmtDCmd.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/services/nmtDCmd.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -22,6 +22,8 @@ * */ #include "precompiled.hpp" + +#include "runtime/mutexLocker.hpp" #include "services/nmtDCmd.hpp" #include "services/memReporter.hpp" #include "services/memTracker.hpp" @@ -49,13 +51,8 @@ _shutdown("shutdown", "request runtime to shutdown itself and free the " \ "memory used by runtime.", "BOOLEAN", false, "false"), - _auto_shutdown("autoShutdown", "automatically shutdown itself under " \ - "stress situation", - "BOOLEAN", true, "true"), -#ifndef PRODUCT - _debug("debug", "print tracker statistics. Debug only, not thread safe", \ + _statistics("statistics", "print tracker statistics for tuning purpose.", \ "BOOLEAN", false, "false"), -#endif _scale("scale", "Memory usage in which scale, KB, MB or GB", "STRING", false, "KB") { _dcmdparser.add_dcmd_option(&_summary); @@ -64,25 +61,30 @@ _dcmdparser.add_dcmd_option(&_summary_diff); _dcmdparser.add_dcmd_option(&_detail_diff); _dcmdparser.add_dcmd_option(&_shutdown); - _dcmdparser.add_dcmd_option(&_auto_shutdown); -#ifndef PRODUCT - _dcmdparser.add_dcmd_option(&_debug); -#endif + _dcmdparser.add_dcmd_option(&_statistics); _dcmdparser.add_dcmd_option(&_scale); } + +size_t NMTDCmd::get_scale(const char* scale) const { + if (scale == NULL) return 0; + return NMTUtil::scale_from_name(scale); +} + void NMTDCmd::execute(DCmdSource source, TRAPS) { + // Check NMT state + // native memory tracking has to be on + if (MemTracker::tracking_level() == NMT_off) { + output()->print_cr("Native memory tracking is not enabled"); + return; + } else if (MemTracker::tracking_level() == NMT_minimal) { + output()->print_cr("Native memory tracking has been shutdown"); + return; + } + const char* scale_value = _scale.value(); - size_t scale_unit; - if (strcmp(scale_value, "KB") == 0 || strcmp(scale_value, "kb") == 0) { - scale_unit = K; - } else if (strcmp(scale_value, "MB") == 0 || - strcmp(scale_value, "mb") == 0) { - scale_unit = M; - } else if (strcmp(scale_value, "GB") == 0 || - strcmp(scale_value, "gb") == 0) { - scale_unit = G; - } else { + size_t scale_unit = get_scale(scale_value); + if (scale_unit == 0) { output()->print_cr("Incorrect scale value: %s", scale_value); return; } @@ -94,19 +96,11 @@ if (_summary_diff.is_set() && _summary_diff.value()) { ++nopt; } if (_detail_diff.is_set() && _detail_diff.value()) { ++nopt; } if (_shutdown.is_set() && _shutdown.value()) { ++nopt; } - if (_auto_shutdown.is_set()) { ++nopt; } - -#ifndef PRODUCT - if (_debug.is_set() && _debug.value()) { ++nopt; } -#endif + if (_statistics.is_set() && _statistics.value()) { ++nopt; } if (nopt > 1) { output()->print_cr("At most one of the following option can be specified: " \ - "summary, detail, baseline, summary.diff, detail.diff, shutdown" -#ifndef PRODUCT - ", debug" -#endif - ); + "summary, detail, baseline, summary.diff, detail.diff, shutdown"); return; } else if (nopt == 0) { if (_summary.is_set()) { @@ -117,53 +111,47 @@ } } -#ifndef PRODUCT - if (_debug.value()) { - output()->print_cr("debug command is NOT thread-safe, may cause crash"); - MemTracker::print_tracker_stats(output()); - return; - } -#endif - - // native memory tracking has to be on - if (!MemTracker::is_on() || MemTracker::shutdown_in_progress()) { - // if it is not on, what's the reason? - output()->print_cr("%s", MemTracker::reason()); - return; - } + // Serialize NMT query + MutexLocker locker(MemTracker::query_lock()); if (_summary.value()) { - BaselineTTYOutputer outputer(output()); - MemTracker::print_memory_usage(outputer, scale_unit, true); + report(true, scale_unit); } else if (_detail.value()) { - BaselineTTYOutputer outputer(output()); - MemTracker::print_memory_usage(outputer, scale_unit, false); + if (!check_detail_tracking_level(output())) { + return; + } + report(false, scale_unit); } else if (_baseline.value()) { - if (MemTracker::baseline()) { - output()->print_cr("Successfully baselined."); + MemBaseline& baseline = MemTracker::get_baseline(); + if (!baseline.baseline(MemTracker::tracking_level() != NMT_detail)) { + output()->print_cr("Baseline failed"); } else { - output()->print_cr("Baseline failed."); + output()->print_cr("Baseline succeeded"); } } else if (_summary_diff.value()) { - if (MemTracker::has_baseline()) { - BaselineTTYOutputer outputer(output()); - MemTracker::compare_memory_usage(outputer, scale_unit, true); + MemBaseline& baseline = MemTracker::get_baseline(); + if (baseline.baseline_type() >= MemBaseline::Summary_baselined) { + report_diff(true, scale_unit); } else { - output()->print_cr("No baseline to compare, run 'baseline' command first"); + output()->print_cr("No baseline for comparison"); } } else if (_detail_diff.value()) { - if (MemTracker::has_baseline()) { - BaselineTTYOutputer outputer(output()); - MemTracker::compare_memory_usage(outputer, scale_unit, false); + if (!check_detail_tracking_level(output())) { + return; + } + MemBaseline& baseline = MemTracker::get_baseline(); + if (baseline.baseline_type() == MemBaseline::Detail_baselined) { + report_diff(false, scale_unit); } else { - output()->print_cr("No baseline to compare to, run 'baseline' command first"); + output()->print_cr("No detail baseline for comparison"); } } else if (_shutdown.value()) { - MemTracker::shutdown(MemTracker::NMT_shutdown_user); - output()->print_cr("Shutdown is in progress, it will take a few moments to " \ - "completely shutdown"); - } else if (_auto_shutdown.is_set()) { - MemTracker::set_autoShutdown(_auto_shutdown.value()); + MemTracker::shutdown(); + output()->print_cr("Native memory tracking has been turned off"); + } else if (_statistics.value()) { + if (check_detail_tracking_level(output())) { + MemTracker::tuning_statistics(output()); + } } else { ShouldNotReachHere(); output()->print_cr("Unknown command"); @@ -181,3 +169,46 @@ } } +void NMTDCmd::report(bool summaryOnly, size_t scale_unit) { + MemBaseline baseline; + if (baseline.baseline(summaryOnly)) { + if (summaryOnly) { + MemSummaryReporter rpt(baseline, output(), scale_unit); + rpt.report(); + } else { + MemDetailReporter rpt(baseline, output(), scale_unit); + rpt.report(); + } + } +} + +void NMTDCmd::report_diff(bool summaryOnly, size_t scale_unit) { + MemBaseline& early_baseline = MemTracker::get_baseline(); + assert(early_baseline.baseline_type() != MemBaseline::Not_baselined, + "Not yet baselined"); + assert(summaryOnly || early_baseline.baseline_type() == MemBaseline::Detail_baselined, + "Not a detail baseline"); + + MemBaseline baseline; + if (baseline.baseline(summaryOnly)) { + if (summaryOnly) { + MemSummaryDiffReporter rpt(early_baseline, baseline, output(), scale_unit); + rpt.report_diff(); + } else { + MemDetailDiffReporter rpt(early_baseline, baseline, output(), scale_unit); + rpt.report_diff(); + } + } +} + +bool NMTDCmd::check_detail_tracking_level(outputStream* out) { + if (MemTracker::tracking_level() == NMT_detail) { + return true; + } else if (MemTracker::cmdline_tracking_level() == NMT_detail) { + out->print_cr("Tracking level has been downgraded due to lack of resources"); + return false; + } else { + out->print_cr("Detail tracking is not enabled"); + return false; + } +} diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/services/nmtDCmd.hpp --- a/hotspot/src/share/vm/services/nmtDCmd.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/services/nmtDCmd.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -25,8 +25,12 @@ #ifndef SHARE_VM_SERVICES_NMT_DCMD_HPP #define SHARE_VM_SERVICES_NMT_DCMD_HPP +#if INCLUDE_NMT + #include "services/diagnosticArgument.hpp" #include "services/diagnosticFramework.hpp" +#include "services/memBaseline.hpp" +#include "services/mallocTracker.hpp" /** * Native memory tracking DCmd implementation @@ -39,10 +43,7 @@ DCmdArgument _summary_diff; DCmdArgument _detail_diff; DCmdArgument _shutdown; - DCmdArgument _auto_shutdown; -#ifndef PRODUCT - DCmdArgument _debug; -#endif + DCmdArgument _statistics; DCmdArgument _scale; public: @@ -61,6 +62,17 @@ } static int num_arguments(); virtual void execute(DCmdSource source, TRAPS); + + private: + void report(bool summaryOnly, size_t scale); + void report_diff(bool summaryOnly, size_t scale); + + size_t get_scale(const char* scale) const; + + // check if NMT running at detail tracking level + bool check_detail_tracking_level(outputStream* out); }; +#endif // INCLUDE_NMT + #endif // SHARE_VM_SERVICES_NMT_DCMD_HPP diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/services/virtualMemoryTracker.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/services/virtualMemoryTracker.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,448 @@ +/* + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#include "precompiled.hpp" + +#include "runtime/threadCritical.hpp" +#include "services/virtualMemoryTracker.hpp" + +size_t VirtualMemorySummary::_snapshot[CALC_OBJ_SIZE_IN_TYPE(VirtualMemorySnapshot, size_t)]; + +void VirtualMemorySummary::initialize() { + assert(sizeof(_snapshot) >= sizeof(VirtualMemorySnapshot), "Sanity Check"); + // Use placement operator new to initialize static data area. + ::new ((void*)_snapshot) VirtualMemorySnapshot(); +} + +SortedLinkedList VirtualMemoryTracker::_reserved_regions; + +int compare_committed_region(const CommittedMemoryRegion& r1, const CommittedMemoryRegion& r2) { + return r1.compare(r2); +} + +int compare_reserved_region_base(const ReservedMemoryRegion& r1, const ReservedMemoryRegion& r2) { + return r1.compare(r2); +} + +bool ReservedMemoryRegion::add_committed_region(address addr, size_t size, const NativeCallStack& stack) { + assert(addr != NULL, "Invalid address"); + assert(size > 0, "Invalid size"); + assert(contain_region(addr, size), "Not contain this region"); + + if (all_committed()) return true; + + CommittedMemoryRegion committed_rgn(addr, size, stack); + LinkedListNode* node = _committed_regions.find_node(committed_rgn); + if (node != NULL) { + CommittedMemoryRegion* rgn = node->data(); + if (rgn->same_region(addr, size)) { + return true; + } + + if (rgn->adjacent_to(addr, size)) { + // check if the next region covers this committed region, + // the regions may not be merged due to different call stacks + LinkedListNode* next = + node->next(); + if (next != NULL && next->data()->contain_region(addr, size)) { + if (next->data()->same_region(addr, size)) { + next->data()->set_call_stack(stack); + } + return true; + } + if (rgn->call_stack()->equals(stack)) { + VirtualMemorySummary::record_uncommitted_memory(rgn->size(), flag()); + // the two adjacent regions have the same call stack, merge them + rgn->expand_region(addr, size); + VirtualMemorySummary::record_committed_memory(rgn->size(), flag()); + return true; + } + VirtualMemorySummary::record_committed_memory(size, flag()); + if (rgn->base() > addr) { + return _committed_regions.insert_before(committed_rgn, node) != NULL; + } else { + return _committed_regions.insert_after(committed_rgn, node) != NULL; + } + } + assert(rgn->contain_region(addr, size), "Must cover this region"); + return true; + } else { + // New committed region + VirtualMemorySummary::record_committed_memory(size, flag()); + return add_committed_region(committed_rgn); + } +} + +void ReservedMemoryRegion::set_all_committed(bool b) { + if (all_committed() != b) { + _all_committed = b; + if (b) { + VirtualMemorySummary::record_committed_memory(size(), flag()); + } + } +} + +bool ReservedMemoryRegion::remove_uncommitted_region(LinkedListNode* node, + address addr, size_t size) { + assert(addr != NULL, "Invalid address"); + assert(size > 0, "Invalid size"); + + CommittedMemoryRegion* rgn = node->data(); + assert(rgn->contain_region(addr, size), "Has to be contained"); + assert(!rgn->same_region(addr, size), "Can not be the same region"); + + if (rgn->base() == addr || + rgn->end() == addr + size) { + rgn->exclude_region(addr, size); + return true; + } else { + // split this region + address top =rgn->end(); + // use this region for lower part + size_t exclude_size = rgn->end() - addr; + rgn->exclude_region(addr, exclude_size); + + // higher part + address high_base = addr + size; + size_t high_size = top - high_base; + + CommittedMemoryRegion high_rgn(high_base, high_size, *rgn->call_stack()); + LinkedListNode* high_node = _committed_regions.add(high_rgn); + assert(high_node == NULL || node->next() == high_node, "Should be right after"); + return (high_node != NULL); + } + + return false; +} + +bool ReservedMemoryRegion::remove_uncommitted_region(address addr, size_t sz) { + // uncommit stack guard pages + if (flag() == mtThreadStack && !same_region(addr, sz)) { + return true; + } + + assert(addr != NULL, "Invalid address"); + assert(sz > 0, "Invalid size"); + + if (all_committed()) { + assert(_committed_regions.is_empty(), "Sanity check"); + assert(contain_region(addr, sz), "Reserved region does not contain this region"); + set_all_committed(false); + VirtualMemorySummary::record_uncommitted_memory(sz, flag()); + if (same_region(addr, sz)) { + return true; + } else { + CommittedMemoryRegion rgn(base(), size(), *call_stack()); + if (rgn.base() == addr || rgn.end() == (addr + sz)) { + rgn.exclude_region(addr, sz); + return add_committed_region(rgn); + } else { + // split this region + // top of the whole region + address top =rgn.end(); + // use this region for lower part + size_t exclude_size = rgn.end() - addr; + rgn.exclude_region(addr, exclude_size); + if (add_committed_region(rgn)) { + // higher part + address high_base = addr + sz; + size_t high_size = top - high_base; + CommittedMemoryRegion high_rgn(high_base, high_size, emptyStack); + return add_committed_region(high_rgn); + } else { + return false; + } + } + } + } else { + // we have to walk whole list to remove the committed regions in + // specified range + LinkedListNode* head = + _committed_regions.head(); + LinkedListNode* prev = NULL; + VirtualMemoryRegion uncommitted_rgn(addr, sz); + + while (head != NULL && !uncommitted_rgn.is_empty()) { + CommittedMemoryRegion* crgn = head->data(); + // this committed region overlaps to region to uncommit + if (crgn->overlap_region(uncommitted_rgn.base(), uncommitted_rgn.size())) { + if (crgn->same_region(uncommitted_rgn.base(), uncommitted_rgn.size())) { + // find matched region, remove the node will do + VirtualMemorySummary::record_uncommitted_memory(uncommitted_rgn.size(), flag()); + _committed_regions.remove_after(prev); + return true; + } else if (crgn->contain_region(uncommitted_rgn.base(), uncommitted_rgn.size())) { + // this committed region contains whole uncommitted region + VirtualMemorySummary::record_uncommitted_memory(uncommitted_rgn.size(), flag()); + return remove_uncommitted_region(head, uncommitted_rgn.base(), uncommitted_rgn.size()); + } else if (uncommitted_rgn.contain_region(crgn->base(), crgn->size())) { + // this committed region has been uncommitted + size_t exclude_size = crgn->end() - uncommitted_rgn.base(); + uncommitted_rgn.exclude_region(uncommitted_rgn.base(), exclude_size); + VirtualMemorySummary::record_uncommitted_memory(crgn->size(), flag()); + LinkedListNode* tmp = head; + head = head->next(); + _committed_regions.remove_after(prev); + continue; + } else if (crgn->contain_address(uncommitted_rgn.base())) { + size_t toUncommitted = crgn->end() - uncommitted_rgn.base(); + crgn->exclude_region(uncommitted_rgn.base(), toUncommitted); + uncommitted_rgn.exclude_region(uncommitted_rgn.base(), toUncommitted); + VirtualMemorySummary::record_uncommitted_memory(toUncommitted, flag()); + } else if (uncommitted_rgn.contain_address(crgn->base())) { + size_t toUncommitted = uncommitted_rgn.end() - crgn->base(); + crgn->exclude_region(crgn->base(), toUncommitted); + uncommitted_rgn.exclude_region(uncommitted_rgn.end() - toUncommitted, + toUncommitted); + VirtualMemorySummary::record_uncommitted_memory(toUncommitted, flag()); + } + } + prev = head; + head = head->next(); + } + } + + return true; +} + +void ReservedMemoryRegion::move_committed_regions(address addr, ReservedMemoryRegion& rgn) { + assert(addr != NULL, "Invalid address"); + + // split committed regions + LinkedListNode* head = + _committed_regions.head(); + LinkedListNode* prev = NULL; + + while (head != NULL) { + if (head->data()->base() >= addr) { + break; + } + prev = head; + head = head->next(); + } + + if (head != NULL) { + if (prev != NULL) { + prev->set_next(head->next()); + } else { + _committed_regions.set_head(NULL); + } + } + + rgn._committed_regions.set_head(head); +} + +size_t ReservedMemoryRegion::committed_size() const { + if (all_committed()) { + return size(); + } else { + size_t committed = 0; + LinkedListNode* head = + _committed_regions.head(); + while (head != NULL) { + committed += head->data()->size(); + head = head->next(); + } + return committed; + } +} + +void ReservedMemoryRegion::set_flag(MEMFLAGS f) { + assert((flag() == mtNone || flag() == f), "Overwrite memory type"); + if (flag() != f) { + VirtualMemorySummary::move_reserved_memory(flag(), f, size()); + VirtualMemorySummary::move_committed_memory(flag(), f, committed_size()); + _flag = f; + } +} + +bool VirtualMemoryTracker::initialize(NMT_TrackingLevel level) { + if (level >= NMT_summary) { + VirtualMemorySummary::initialize(); + } + return true; +} + +bool VirtualMemoryTracker::add_reserved_region(address base_addr, size_t size, + const NativeCallStack& stack, MEMFLAGS flag, bool all_committed) { + assert(base_addr != NULL, "Invalid address"); + assert(size > 0, "Invalid size"); + + ReservedMemoryRegion rgn(base_addr, size, stack, flag); + ReservedMemoryRegion* reserved_rgn = _reserved_regions.find(rgn); + LinkedListNode* node; + if (reserved_rgn == NULL) { + VirtualMemorySummary::record_reserved_memory(size, flag); + node = _reserved_regions.add(rgn); + if (node != NULL) { + node->data()->set_all_committed(all_committed); + return true; + } else { + return false; + } + } else { + if (reserved_rgn->same_region(base_addr, size)) { + reserved_rgn->set_call_stack(stack); + reserved_rgn->set_flag(flag); + return true; + } else if (reserved_rgn->adjacent_to(base_addr, size)) { + VirtualMemorySummary::record_reserved_memory(size, flag); + reserved_rgn->expand_region(base_addr, size); + reserved_rgn->set_call_stack(stack); + return true; + } else { + // Overlapped reservation. + // It can happen when the regions are thread stacks, as JNI + // thread does not detach from VM before exits, and leads to + // leak JavaThread object + if (reserved_rgn->flag() == mtThreadStack) { + guarantee(!CheckJNICalls, "Attached JNI thread exited without being detached"); + // Overwrite with new region + + // Release old region + VirtualMemorySummary::record_uncommitted_memory(reserved_rgn->committed_size(), reserved_rgn->flag()); + VirtualMemorySummary::record_released_memory(reserved_rgn->size(), reserved_rgn->flag()); + + // Add new region + VirtualMemorySummary::record_reserved_memory(rgn.size(), flag); + + *reserved_rgn = rgn; + return true; + } else { + ShouldNotReachHere(); + return false; + } + } + } +} + +void VirtualMemoryTracker::set_reserved_region_type(address addr, MEMFLAGS flag) { + assert(addr != NULL, "Invalid address"); + + ReservedMemoryRegion rgn(addr, 1); + ReservedMemoryRegion* reserved_rgn = _reserved_regions.find(rgn); + if (reserved_rgn != NULL) { + assert(reserved_rgn->contain_address(addr), "Containment"); + if (reserved_rgn->flag() != flag) { + assert(reserved_rgn->flag() == mtNone, "Overwrite memory type"); + reserved_rgn->set_flag(flag); + } + } +} + +bool VirtualMemoryTracker::add_committed_region(address addr, size_t size, + const NativeCallStack& stack) { + assert(addr != NULL, "Invalid address"); + assert(size > 0, "Invalid size"); + ReservedMemoryRegion rgn(addr, size); + ReservedMemoryRegion* reserved_rgn = _reserved_regions.find(rgn); + + assert(reserved_rgn != NULL, "No reserved region"); + assert(reserved_rgn->contain_region(addr, size), "Not completely contained"); + return reserved_rgn->add_committed_region(addr, size, stack); +} + +bool VirtualMemoryTracker::remove_uncommitted_region(address addr, size_t size) { + assert(addr != NULL, "Invalid address"); + assert(size > 0, "Invalid size"); + ReservedMemoryRegion rgn(addr, size); + ReservedMemoryRegion* reserved_rgn = _reserved_regions.find(rgn); + assert(reserved_rgn != NULL, "No reserved region"); + assert(reserved_rgn->contain_region(addr, size), "Not completely contained"); + return reserved_rgn->remove_uncommitted_region(addr, size); +} + +bool VirtualMemoryTracker::remove_released_region(address addr, size_t size) { + assert(addr != NULL, "Invalid address"); + assert(size > 0, "Invalid size"); + + ReservedMemoryRegion rgn(addr, size); + ReservedMemoryRegion* reserved_rgn = _reserved_regions.find(rgn); + + assert(reserved_rgn != NULL, "No reserved region"); + + // uncommit regions within the released region + if (!reserved_rgn->remove_uncommitted_region(addr, size)) { + return false; + } + + + VirtualMemorySummary::record_released_memory(size, reserved_rgn->flag()); + + if (reserved_rgn->same_region(addr, size)) { + return _reserved_regions.remove(rgn); + } else { + assert(reserved_rgn->contain_region(addr, size), "Not completely contained"); + if (reserved_rgn->base() == addr || + reserved_rgn->end() == addr + size) { + reserved_rgn->exclude_region(addr, size); + return true; + } else { + address top = reserved_rgn->end(); + address high_base = addr + size; + ReservedMemoryRegion high_rgn(high_base, top - high_base, + *reserved_rgn->call_stack(), reserved_rgn->flag()); + + // use original region for lower region + reserved_rgn->exclude_region(addr, top - addr); + LinkedListNode* new_rgn = _reserved_regions.add(high_rgn); + if (new_rgn == NULL) { + return false; + } else { + reserved_rgn->move_committed_regions(addr, *new_rgn->data()); + return true; + } + } + } +} + + +bool VirtualMemoryTracker::walk_virtual_memory(VirtualMemoryWalker* walker) { + ThreadCritical tc; + LinkedListNode* head = _reserved_regions.head(); + while (head != NULL) { + const ReservedMemoryRegion* rgn = head->peek(); + if (!walker->do_allocation_site(rgn)) { + return false; + } + head = head->next(); + } + return true; +} + +// Transition virtual memory tracking level. +bool VirtualMemoryTracker::transition(NMT_TrackingLevel from, NMT_TrackingLevel to) { + if (from == NMT_minimal) { + assert(to == NMT_summary || to == NMT_detail, "Just check"); + VirtualMemorySummary::reset(); + } else if (to == NMT_minimal) { + assert(from == NMT_summary || from == NMT_detail, "Just check"); + // Clean up virtual memory tracking data structures. + ThreadCritical tc; + _reserved_regions.clear(); + } + + return true; +} + + diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/services/virtualMemoryTracker.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/services/virtualMemoryTracker.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,437 @@ +/* + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_SERVICES_VIRTUAL_MEMORY_TRACKER_HPP +#define SHARE_VM_SERVICES_VIRTUAL_MEMORY_TRACKER_HPP + +#if INCLUDE_NMT + +#include "memory/allocation.hpp" +#include "services/allocationSite.hpp" +#include "services/nmtCommon.hpp" +#include "utilities/linkedlist.hpp" +#include "utilities/nativeCallStack.hpp" +#include "utilities/ostream.hpp" + + +/* + * Virtual memory counter + */ +class VirtualMemory VALUE_OBJ_CLASS_SPEC { + private: + size_t _reserved; + size_t _committed; + + public: + VirtualMemory() : _reserved(0), _committed(0) { } + + inline void reserve_memory(size_t sz) { _reserved += sz; } + inline void commit_memory (size_t sz) { + _committed += sz; + assert(_committed <= _reserved, "Sanity check"); + } + + inline void release_memory (size_t sz) { + assert(_reserved >= sz, "Negative amount"); + _reserved -= sz; + } + + inline void uncommit_memory(size_t sz) { + assert(_committed >= sz, "Negative amount"); + _committed -= sz; + } + + void reset() { + _reserved = 0; + _committed = 0; + } + + inline size_t reserved() const { return _reserved; } + inline size_t committed() const { return _committed; } +}; + +// Virtual memory allocation site, keeps track where the virtual memory is reserved. +class VirtualMemoryAllocationSite : public AllocationSite { + public: + VirtualMemoryAllocationSite(const NativeCallStack& stack) : + AllocationSite(stack) { } + + inline void reserve_memory(size_t sz) { data()->reserve_memory(sz); } + inline void commit_memory (size_t sz) { data()->commit_memory(sz); } + inline void uncommit_memory(size_t sz) { data()->uncommit_memory(sz); } + inline void release_memory(size_t sz) { data()->release_memory(sz); } + inline size_t reserved() const { return peek()->reserved(); } + inline size_t committed() const { return peek()->committed(); } +}; + +class VirtualMemorySummary; + +// This class represents a snapshot of virtual memory at a given time. +// The latest snapshot is saved in a static area. +class VirtualMemorySnapshot : public ResourceObj { + friend class VirtualMemorySummary; + + private: + VirtualMemory _virtual_memory[mt_number_of_types]; + + public: + inline VirtualMemory* by_type(MEMFLAGS flag) { + int index = NMTUtil::flag_to_index(flag); + return &_virtual_memory[index]; + } + + inline VirtualMemory* by_index(int index) { + assert(index >= 0, "Index out of bound"); + assert(index < mt_number_of_types, "Index out of bound"); + return &_virtual_memory[index]; + } + + inline size_t total_reserved() const { + size_t amount = 0; + for (int index = 0; index < mt_number_of_types; index ++) { + amount += _virtual_memory[index].reserved(); + } + return amount; + } + + inline size_t total_committed() const { + size_t amount = 0; + for (int index = 0; index < mt_number_of_types; index ++) { + amount += _virtual_memory[index].committed(); + } + return amount; + } + + inline void reset() { + for (int index = 0; index < mt_number_of_types; index ++) { + _virtual_memory[index].reset(); + } + } + + void copy_to(VirtualMemorySnapshot* s) { + for (int index = 0; index < mt_number_of_types; index ++) { + s->_virtual_memory[index] = _virtual_memory[index]; + } + } +}; + +class VirtualMemorySummary : AllStatic { + public: + static void initialize(); + + static inline void record_reserved_memory(size_t size, MEMFLAGS flag) { + as_snapshot()->by_type(flag)->reserve_memory(size); + } + + static inline void record_committed_memory(size_t size, MEMFLAGS flag) { + as_snapshot()->by_type(flag)->commit_memory(size); + } + + static inline void record_uncommitted_memory(size_t size, MEMFLAGS flag) { + as_snapshot()->by_type(flag)->uncommit_memory(size); + } + + static inline void record_released_memory(size_t size, MEMFLAGS flag) { + as_snapshot()->by_type(flag)->release_memory(size); + } + + // Move virtual memory from one memory type to another. + // Virtual memory can be reserved before it is associated with a memory type, and tagged + // as 'unknown'. Once the memory is tagged, the virtual memory will be moved from 'unknown' + // type to specified memory type. + static inline void move_reserved_memory(MEMFLAGS from, MEMFLAGS to, size_t size) { + as_snapshot()->by_type(from)->release_memory(size); + as_snapshot()->by_type(to)->reserve_memory(size); + } + + static inline void move_committed_memory(MEMFLAGS from, MEMFLAGS to, size_t size) { + as_snapshot()->by_type(from)->uncommit_memory(size); + as_snapshot()->by_type(to)->commit_memory(size); + } + + static inline void snapshot(VirtualMemorySnapshot* s) { + as_snapshot()->copy_to(s); + } + + static inline void reset() { + as_snapshot()->reset(); + } + + static VirtualMemorySnapshot* as_snapshot() { + return (VirtualMemorySnapshot*)_snapshot; + } + + private: + static size_t _snapshot[CALC_OBJ_SIZE_IN_TYPE(VirtualMemorySnapshot, size_t)]; +}; + + + +/* + * A virtual memory region + */ +class VirtualMemoryRegion VALUE_OBJ_CLASS_SPEC { + private: + address _base_address; + size_t _size; + + public: + VirtualMemoryRegion(address addr, size_t size) : + _base_address(addr), _size(size) { + assert(addr != NULL, "Invalid address"); + assert(size > 0, "Invalid size"); + } + + inline address base() const { return _base_address; } + inline address end() const { return base() + size(); } + inline size_t size() const { return _size; } + + inline bool is_empty() const { return size() == 0; } + + inline bool contain_address(address addr) const { + return (addr >= base() && addr < end()); + } + + + inline bool contain_region(address addr, size_t size) const { + return contain_address(addr) && contain_address(addr + size - 1); + } + + inline bool same_region(address addr, size_t sz) const { + return (addr == base() && sz == size()); + } + + + inline bool overlap_region(address addr, size_t sz) const { + VirtualMemoryRegion rgn(addr, sz); + return contain_address(addr) || + contain_address(addr + sz - 1) || + rgn.contain_address(base()) || + rgn.contain_address(end() - 1); + } + + inline bool adjacent_to(address addr, size_t sz) const { + return (addr == end() || (addr + sz) == base()); + } + + void exclude_region(address addr, size_t sz) { + assert(contain_region(addr, sz), "Not containment"); + assert(addr == base() || addr + sz == end(), "Can not exclude from middle"); + size_t new_size = size() - sz; + + if (addr == base()) { + set_base(addr + sz); + } + set_size(new_size); + } + + void expand_region(address addr, size_t sz) { + assert(adjacent_to(addr, sz), "Not adjacent regions"); + if (base() == addr + sz) { + set_base(addr); + } + set_size(size() + sz); + } + + protected: + void set_base(address base) { + assert(base != NULL, "Sanity check"); + _base_address = base; + } + + void set_size(size_t size) { + assert(size > 0, "Sanity check"); + _size = size; + } +}; + + +class CommittedMemoryRegion : public VirtualMemoryRegion { + private: + NativeCallStack _stack; + + public: + CommittedMemoryRegion(address addr, size_t size, const NativeCallStack& stack) : + VirtualMemoryRegion(addr, size), _stack(stack) { } + + inline int compare(const CommittedMemoryRegion& rgn) const { + if (overlap_region(rgn.base(), rgn.size()) || + adjacent_to (rgn.base(), rgn.size())) { + return 0; + } else { + if (base() == rgn.base()) { + return 0; + } else if (base() > rgn.base()) { + return 1; + } else { + return -1; + } + } + } + + inline bool equals(const CommittedMemoryRegion& rgn) const { + return compare(rgn) == 0; + } + + inline void set_call_stack(const NativeCallStack& stack) { _stack = stack; } + inline const NativeCallStack* call_stack() const { return &_stack; } +}; + + +typedef LinkedListIterator CommittedRegionIterator; + +int compare_committed_region(const CommittedMemoryRegion&, const CommittedMemoryRegion&); +class ReservedMemoryRegion : public VirtualMemoryRegion { + private: + SortedLinkedList + _committed_regions; + + NativeCallStack _stack; + MEMFLAGS _flag; + + bool _all_committed; + + public: + ReservedMemoryRegion(address base, size_t size, const NativeCallStack& stack, + MEMFLAGS flag = mtNone) : + VirtualMemoryRegion(base, size), _stack(stack), _flag(flag), + _all_committed(false) { } + + + ReservedMemoryRegion(address base, size_t size) : + VirtualMemoryRegion(base, size), _stack(emptyStack), _flag(mtNone), + _all_committed(false) { } + + // Copy constructor + ReservedMemoryRegion(const ReservedMemoryRegion& rr) : + VirtualMemoryRegion(rr.base(), rr.size()) { + *this = rr; + } + + inline void set_call_stack(const NativeCallStack& stack) { _stack = stack; } + inline const NativeCallStack* call_stack() const { return &_stack; } + + void set_flag(MEMFLAGS flag); + inline MEMFLAGS flag() const { return _flag; } + + inline int compare(const ReservedMemoryRegion& rgn) const { + if (overlap_region(rgn.base(), rgn.size())) { + return 0; + } else { + if (base() == rgn.base()) { + return 0; + } else if (base() > rgn.base()) { + return 1; + } else { + return -1; + } + } + } + + inline bool equals(const ReservedMemoryRegion& rgn) const { + return compare(rgn) == 0; + } + + bool add_committed_region(address addr, size_t size, const NativeCallStack& stack); + bool remove_uncommitted_region(address addr, size_t size); + + size_t committed_size() const; + + // move committed regions that higher than specified address to + // the new region + void move_committed_regions(address addr, ReservedMemoryRegion& rgn); + + inline bool all_committed() const { return _all_committed; } + void set_all_committed(bool b); + + CommittedRegionIterator iterate_committed_regions() const { + return CommittedRegionIterator(_committed_regions.head()); + } + + ReservedMemoryRegion& operator= (const ReservedMemoryRegion& other) { + set_base(other.base()); + set_size(other.size()); + + _stack = *other.call_stack(); + _flag = other.flag(); + _all_committed = other.all_committed(); + if (other.all_committed()) { + set_all_committed(true); + } else { + CommittedRegionIterator itr = other.iterate_committed_regions(); + const CommittedMemoryRegion* rgn = itr.next(); + while (rgn != NULL) { + _committed_regions.add(*rgn); + rgn = itr.next(); + } + } + return *this; + } + + private: + // The committed region contains the uncommitted region, subtract the uncommitted + // region from this committed region + bool remove_uncommitted_region(LinkedListNode* node, + address addr, size_t sz); + + bool add_committed_region(const CommittedMemoryRegion& rgn) { + assert(rgn.base() != NULL, "Invalid base address"); + assert(size() > 0, "Invalid size"); + return _committed_regions.add(rgn) != NULL; + } +}; + +int compare_reserved_region_base(const ReservedMemoryRegion& r1, const ReservedMemoryRegion& r2); + +class VirtualMemoryWalker : public StackObj { + public: + virtual bool do_allocation_site(const ReservedMemoryRegion* rgn) { return false; } +}; + +// Main class called from MemTracker to track virtual memory allocations, commits and releases. +class VirtualMemoryTracker : AllStatic { + public: + static bool initialize(NMT_TrackingLevel level); + + static bool add_reserved_region (address base_addr, size_t size, const NativeCallStack& stack, + MEMFLAGS flag = mtNone, bool all_committed = false); + + static bool add_committed_region (address base_addr, size_t size, const NativeCallStack& stack); + static bool remove_uncommitted_region (address base_addr, size_t size); + static bool remove_released_region (address base_addr, size_t size); + static void set_reserved_region_type (address addr, MEMFLAGS flag); + + // Walk virtual memory data structure for creating baseline, etc. + static bool walk_virtual_memory(VirtualMemoryWalker* walker); + + static bool transition(NMT_TrackingLevel from, NMT_TrackingLevel to); + + private: + static SortedLinkedList _reserved_regions; +}; + + +#endif // INCLUDE_NMT + +#endif // SHARE_VM_SERVICES_VIRTUAL_MEMORY_TRACKER_HPP diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/shark/sharkBuilder.cpp --- a/hotspot/src/share/vm/shark/sharkBuilder.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/shark/sharkBuilder.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -413,7 +413,7 @@ const char *name; if (value->hasName()) // XXX this leaks, but it's only debug code - name = strdup(value->getName().str().c_str()); + name = os::strdup(value->getName().str().c_str()); else name = "unnamed_value"; diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/utilities/bitMap.cpp --- a/hotspot/src/share/vm/utilities/bitMap.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/utilities/bitMap.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -567,7 +567,7 @@ } static void testResizeNonResource() { - const uintx bitmap_bytes = BITMAP_SIZE / BitsPerByte; + const size_t bitmap_bytes = BITMAP_SIZE / BitsPerByte; // Test the default behavior testResize(false); @@ -575,13 +575,13 @@ { // Make sure that AllocatorMallocLimit is larger than our allocation request // forcing it to call standard malloc() - UIntFlagSetting fs(ArrayAllocatorMallocLimit, bitmap_bytes * 4); + SizeTFlagSetting fs(ArrayAllocatorMallocLimit, bitmap_bytes * 4); testResize(false); } { // Make sure that AllocatorMallocLimit is smaller than our allocation request // forcing it to call mmap() (or equivalent) - UIntFlagSetting fs(ArrayAllocatorMallocLimit, bitmap_bytes / 4); + SizeTFlagSetting fs(ArrayAllocatorMallocLimit, bitmap_bytes / 4); testResize(false); } } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/utilities/globalDefinitions.hpp --- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -558,6 +558,27 @@ return fabs(value); } +//---------------------------------------------------------------------------------------------------- +// Special casts +// Cast floats into same-size integers and vice-versa w/o changing bit-pattern +typedef union { + jfloat f; + jint i; +} FloatIntConv; + +typedef union { + jdouble d; + jlong l; + julong ul; +} DoubleLongConv; + +inline jint jint_cast (jfloat x) { return ((FloatIntConv*)&x)->i; } +inline jfloat jfloat_cast (jint x) { return ((FloatIntConv*)&x)->f; } + +inline jlong jlong_cast (jdouble x) { return ((DoubleLongConv*)&x)->l; } +inline julong julong_cast (jdouble x) { return ((DoubleLongConv*)&x)->ul; } +inline jdouble jdouble_cast (jlong x) { return ((DoubleLongConv*)&x)->d; } + inline jint low (jlong value) { return jint(value); } inline jint high(jlong value) { return jint(value >> 32); } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp --- a/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -167,17 +167,6 @@ typedef uint32_t juint; typedef uint64_t julong; -//---------------------------------------------------------------------------------------------------- -// Special (possibly not-portable) casts -// Cast floats into same-size integers and vice-versa w/o changing bit-pattern -// %%%%%% These seem like standard C++ to me--how about factoring them out? - Ungar - -inline jint jint_cast (jfloat x) { return *(jint* )&x; } -inline jlong jlong_cast (jdouble x) { return *(jlong* )&x; } -inline julong julong_cast (jdouble x) { return *(julong* )&x; } - -inline jfloat jfloat_cast (jint x) { return *(jfloat* )&x; } -inline jdouble jdouble_cast(jlong x) { return *(jdouble*)&x; } //---------------------------------------------------------------------------------------------------- // Constant for jlong (specifying an long long canstant is C++ compiler specific) diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp --- a/hotspot/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -183,15 +183,6 @@ typedef unsigned int juint; typedef unsigned long long julong; -//---------------------------------------------------------------------------------------------------- -// Special (possibly not-portable) casts -// Cast floats into same-size integers and vice-versa w/o changing bit-pattern - -inline jint jint_cast (jfloat x) { return *(jint* )&x; } -inline jlong jlong_cast (jdouble x) { return *(jlong* )&x; } - -inline jfloat jfloat_cast (jint x) { return *(jfloat* )&x; } -inline jdouble jdouble_cast(jlong x) { return *(jdouble*)&x; } //---------------------------------------------------------------------------------------------------- // Constant for jlong (specifying an long long constant is C++ compiler specific) diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp --- a/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -116,16 +116,6 @@ typedef unsigned int juint; typedef unsigned __int64 julong; -//---------------------------------------------------------------------------------------------------- -// Special (possibly not-portable) casts -// Cast floats into same-size integers and vice-versa w/o changing bit-pattern - -inline jint jint_cast (jfloat x) { return *(jint* )&x; } -inline jlong jlong_cast (jdouble x) { return *(jlong* )&x; } - -inline jfloat jfloat_cast (jint x) { return *(jfloat* )&x; } -inline jdouble jdouble_cast(jlong x) { return *(jdouble*)&x; } - //---------------------------------------------------------------------------------------------------- // Non-standard stdlib-like stuff: diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/utilities/globalDefinitions_xlc.hpp --- a/hotspot/src/share/vm/utilities/globalDefinitions_xlc.hpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/utilities/globalDefinitions_xlc.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -114,16 +114,6 @@ typedef uint32_t juint; typedef uint64_t julong; -//---------------------------------------------------------------------------------------------------- -// Special (possibly not-portable) casts -// Cast floats into same-size integers and vice-versa w/o changing bit-pattern -// %%%%%% These seem like standard C++ to me--how about factoring them out? - Ungar - -inline jint jint_cast (jfloat x) { return *(jint* )&x; } -inline jlong jlong_cast (jdouble x) { return *(jlong* )&x; } - -inline jfloat jfloat_cast (jint x) { return *(jfloat* )&x; } -inline jdouble jdouble_cast(jlong x) { return *(jdouble*)&x; } //---------------------------------------------------------------------------------------------------- // Constant for jlong (specifying an long long canstant is C++ compiler specific) diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/utilities/linkedlist.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/utilities/linkedlist.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" + +/////////////// Unit tests /////////////// + +#ifndef PRODUCT + +#include "runtime/os.hpp" +#include "utilities/linkedlist.hpp" +#include "memory/allocation.hpp" +#include "memory/allocation.inline.hpp" + +class Integer : public StackObj { + private: + int _value; + public: + Integer(int i) : _value(i) { } + + int value() const { return _value; } + bool equals(const Integer& i) const { + return _value == i.value(); + } +}; + +int compare_Integer(const Integer& i1, const Integer& i2) { + return i1.value() - i2.value(); +} + +void check_list_values(const int* expected, const LinkedList* list) { + LinkedListNode* head = list->head(); + int index = 0; + while (head != NULL) { + assert(head->peek()->value() == expected[index], "Unexpected value"); + head = head->next(); + index ++; + } +} + +void Test_linked_list() { + LinkedListImpl ll; + + + // Test regular linked list + assert(ll.is_empty(), "Start with empty list"); + Integer one(1), two(2), three(3), four(4), five(5), six(6); + + ll.add(six); + assert(!ll.is_empty(), "Should not be empty"); + + Integer* i = ll.find(six); + assert(i != NULL, "Should find it"); + + i = ll.find(three); + assert(i == NULL, "Not in the list"); + + LinkedListNode* node = ll.find_node(six); + assert(node != NULL, "6 is in the list"); + + ll.insert_after(three, node); + ll.insert_before(one, node); + int expected[3] = {1, 6, 3}; + check_list_values(expected, &ll); + + ll.add(two); + ll.add(four); + ll.add(five); + + // Test sorted linked list + SortedLinkedList sl; + assert(sl.is_empty(), "Start with empty list"); + + size_t ll_size = ll.size(); + sl.move(&ll); + size_t sl_size = sl.size(); + + assert(ll_size == sl_size, "Should be the same size"); + assert(ll.is_empty(), "No more entires"); + + // sorted result + int sorted_result[] = {1, 2, 3, 4, 5, 6}; + check_list_values(sorted_result, &sl); + + node = sl.find_node(four); + assert(node != NULL, "4 is in the list"); + sl.remove_before(node); + sl.remove_after(node); + int remains[] = {1, 2, 4, 6}; + check_list_values(remains, &sl); +} +#endif // PRODUCT + diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/utilities/linkedlist.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/utilities/linkedlist.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,416 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_UTILITIES_LINKED_LIST_HPP +#define SHARE_VM_UTILITIES_LINKED_LIST_HPP + +#include "memory/allocation.hpp" + +/* + * The implementation of a generic linked list, which uses various + * backing storages, such as C heap, arena and resource, etc. + */ + + +// An entry in a linked list. It should use the same backing storage +// as the linked list that contains this entry. +template class LinkedListNode : public ResourceObj { + private: + E _data; // embedded content + LinkedListNode* _next; // next entry + + protected: + LinkedListNode() : _next(NULL) { } + + public: + LinkedListNode(const E& e): _data(e), _next(NULL) { } + + inline void set_next(LinkedListNode* node) { _next = node; } + inline LinkedListNode * next() const { return _next; } + + E* data() { return &_data; } + const E* peek() const { return &_data; } +}; + +// A linked list interface. It does not specify +// any storage type it uses, so all methods involving +// memory allocation or deallocation are pure virtual +template class LinkedList : public ResourceObj { + protected: + LinkedListNode* _head; + + public: + LinkedList() : _head(NULL) { } + + inline void set_head(LinkedListNode* h) { _head = h; } + inline LinkedListNode* head() const { return _head; } + inline bool is_empty() const { return head() == NULL; } + + inline size_t size() const { + LinkedListNode* p; + size_t count = 0; + for (p = head(); p != NULL; count++, p = p->next()); + return count; + } + + // Move all entries from specified linked list to this one + virtual void move(LinkedList* list) = 0; + + // Add an entry to this linked list + virtual LinkedListNode* add(const E& e) = 0; + // Add all entries from specified linked list to this one, + virtual void add(LinkedListNode* node) = 0; + + // Add a linked list to this linked list + virtual bool add(const LinkedList* list) = 0; + + // Search entry in the linked list + virtual LinkedListNode* find_node(const E& e) = 0; + virtual E* find(const E& e) = 0; + + // Insert entry to the linked list + virtual LinkedListNode* insert_before(const E& e, LinkedListNode* ref) = 0; + virtual LinkedListNode* insert_after (const E& e, LinkedListNode* ref) = 0; + + // Remove entry from the linked list + virtual bool remove(const E& e) = 0; + virtual bool remove(LinkedListNode* node) = 0; + virtual bool remove_before(LinkedListNode* ref) = 0; + virtual bool remove_after(LinkedListNode* ref) = 0; + + LinkedListNode* unlink_head() { + LinkedListNode* h = this->head(); + if (h != NULL) { + this->set_head(h->next()); + } + return h; + } + + DEBUG_ONLY(virtual ResourceObj::allocation_type storage_type() = 0;) +}; + +// A linked list implementation. +// The linked list can be allocated in various type of memory: C heap, arena and resource area, etc. +template + class LinkedListImpl : public LinkedList { + protected: + Arena* _arena; + public: + LinkedListImpl() : _arena(NULL) { } + LinkedListImpl(Arena* a) : _arena(a) { } + + virtual ~LinkedListImpl() { + clear(); + } + + virtual void clear() { + LinkedListNode* p = this->head(); + this->set_head(NULL); + while (p != NULL) { + LinkedListNode* to_delete = p; + p = p->next(); + delete_node(to_delete); + } + } + + // Add an entry to the linked list + virtual LinkedListNode* add(const E& e) { + LinkedListNode* node = this->new_node(e); + if (node != NULL) { + this->add(node); + } + + return node; + } + + virtual void add(LinkedListNode* node) { + assert(node != NULL, "NULL pointer"); + node->set_next(this->head()); + this->set_head(node); + } + + // Move a linked list to this linked list, both have to be allocated on the same + // storage type. + virtual void move(LinkedList* list) { + assert(list->storage_type() == this->storage_type(), "Different storage type"); + LinkedListNode* node = this->head(); + while (node != NULL && node->next() != NULL) { + node = node->next(); + } + if (node == NULL) { + this->set_head(list->head()); + } else { + node->set_next(list->head()); + } + // All entries are moved + list->set_head(NULL); + } + + virtual bool add(const LinkedList* list) { + LinkedListNode* node = list->head(); + while (node != NULL) { + if (this->add(*node->peek()) == NULL) { + return false; + } + node = node->next(); + } + return true; + } + + + virtual LinkedListNode* find_node(const E& e) { + LinkedListNode* p = this->head(); + while (p != NULL && !p->peek()->equals(e)) { + p = p->next(); + } + return p; + } + + E* find(const E& e) { + LinkedListNode* node = find_node(e); + return (node == NULL) ? NULL : node->data(); + } + + + // Add an entry in front of the reference entry + LinkedListNode* insert_before(const E& e, LinkedListNode* ref_node) { + LinkedListNode* node = this->new_node(e); + if (node == NULL) return NULL; + if (ref_node == this->head()) { + node->set_next(ref_node); + this->set_head(node); + } else { + LinkedListNode* p = this->head(); + while (p != NULL && p->next() != ref_node) { + p = p->next(); + } + assert(p != NULL, "ref_node not in the list"); + node->set_next(ref_node); + p->set_next(node); + } + return node; + } + + // Add an entry behind the reference entry + LinkedListNode* insert_after(const E& e, LinkedListNode* ref_node) { + LinkedListNode* node = this->new_node(e); + if (node == NULL) return NULL; + node->set_next(ref_node->next()); + ref_node->set_next(node); + return node; + } + + // Remove an entry from the linked list. + // Return true if the entry is successfully removed + virtual bool remove(const E& e) { + LinkedListNode* tmp = this->head(); + LinkedListNode* prev = NULL; + + while (tmp != NULL) { + if (tmp->peek()->equals(e)) { + return remove_after(prev); + } + prev = tmp; + tmp = tmp->next(); + } + return false; + } + + // Remove the node after the reference entry + virtual bool remove_after(LinkedListNode* prev) { + LinkedListNode* to_delete; + if (prev == NULL) { + to_delete = this->unlink_head(); + } else { + to_delete = prev->next(); + if (to_delete != NULL) { + prev->set_next(to_delete->next()); + } + } + + if (to_delete != NULL) { + delete_node(to_delete); + return true; + } + return false; + } + + virtual bool remove(LinkedListNode* node) { + LinkedListNode* p = this->head(); + while (p != NULL && p->next() != node) { + p = p->next(); + } + if (p != NULL) { + p->set_next(node->next()); + delete_node(node); + return true; + } else { + return false; + } + } + + virtual bool remove_before(LinkedListNode* ref) { + assert(ref != NULL, "NULL pointer"); + LinkedListNode* p = this->head(); + LinkedListNode* to_delete = NULL; // to be deleted + LinkedListNode* prev = NULL; // node before the node to be deleted + while (p != NULL && p != ref) { + prev = to_delete; + to_delete = p; + p = p->next(); + } + if (p == NULL || to_delete == NULL) return false; + assert(to_delete->next() == ref, "Wrong node to delete"); + assert(prev == NULL || prev->next() == to_delete, + "Sanity check"); + if (prev == NULL) { + assert(to_delete == this->head(), "Must be head"); + this->set_head(to_delete->next()); + } else { + prev->set_next(to_delete->next()); + } + delete_node(to_delete); + return true; + } + + DEBUG_ONLY(ResourceObj::allocation_type storage_type() { return T; }) + protected: + // Create new linked list node object in specified storage + LinkedListNode* new_node(const E& e) const { + switch(T) { + case ResourceObj::ARENA: { + assert(_arena != NULL, "Arena not set"); + return new(_arena) LinkedListNode(e); + } + case ResourceObj::RESOURCE_AREA: + case ResourceObj::C_HEAP: { + if (alloc_failmode == AllocFailStrategy::RETURN_NULL) { + return new(std::nothrow, T, F) LinkedListNode(e); + } else { + return new(T, F) LinkedListNode(e); + } + } + default: + ShouldNotReachHere(); + } + return NULL; + } + + // Delete linked list node object + void delete_node(LinkedListNode* node) { + if (T == ResourceObj::C_HEAP) { + delete node; + } + } +}; + +// Sorted linked list. The linked list maintains sorting order specified by the comparison +// function +template + class SortedLinkedList : public LinkedListImpl { + public: + SortedLinkedList() { } + SortedLinkedList(Arena* a) : LinkedListImpl(a) { } + + virtual LinkedListNode* add(const E& e) { + return LinkedListImpl::add(e); + } + + virtual void move(LinkedList* list) { + assert(list->storage_type() == this->storage_type(), "Different storage type"); + LinkedListNode* node; + while ((node = list->unlink_head()) != NULL) { + this->add(node); + } + assert(list->is_empty(), "All entries are moved"); + } + + virtual void add(LinkedListNode* node) { + assert(node != NULL, "NULL pointer"); + LinkedListNode* tmp = this->head(); + LinkedListNode* prev = NULL; + + int cmp_val; + while (tmp != NULL) { + cmp_val = FUNC(*tmp->peek(), *node->peek()); + if (cmp_val >= 0) { + break; + } + prev = tmp; + tmp = tmp->next(); + } + + if (prev != NULL) { + node->set_next(prev->next()); + prev->set_next(node); + } else { + node->set_next(this->head()); + this->set_head(node); + } + } + + virtual bool add(const LinkedList* list) { + return LinkedListImpl::add(list); + } + + virtual LinkedListNode* find_node(const E& e) { + LinkedListNode* p = this->head(); + + while (p != NULL) { + int comp_val = FUNC(*p->peek(), e); + if (comp_val == 0) { + return p; + } else if (comp_val > 0) { + return NULL; + } + p = p->next(); + } + return NULL; + } +}; + +// Iterates all entries in the list +template class LinkedListIterator : public StackObj { + private: + LinkedListNode* _p; + bool _is_empty; + public: + LinkedListIterator(LinkedListNode* head) : _p(head) { + _is_empty = (head == NULL); + } + + bool is_empty() const { return _is_empty; } + + const E* next() { + if (_p == NULL) return NULL; + const E* e = _p->peek(); + _p = _p->next(); + return e; + } +}; + +#endif diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/utilities/nativeCallStack.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/utilities/nativeCallStack.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "runtime/os.hpp" +#include "utilities/globalDefinitions.hpp" +#include "utilities/nativeCallStack.hpp" + + +NativeCallStack::NativeCallStack(int toSkip, bool fillStack) : + _hash_value(0) { + +#if !PLATFORM_NATIVE_STACK_WALKING_SUPPORTED + fillStack = false; +#endif + + if (fillStack) { + os::get_native_stack(_stack, NMT_TrackingStackDepth, toSkip); + } else { + for (int index = 0; index < NMT_TrackingStackDepth; index ++) { + _stack[index] = NULL; + } + } +} + +NativeCallStack::NativeCallStack(address* pc, int frameCount) { + int frameToCopy = (frameCount < NMT_TrackingStackDepth) ? + frameCount : NMT_TrackingStackDepth; + int index; + for (index = 0; index < frameToCopy; index ++) { + _stack[index] = pc[index]; + } + for (; index < NMT_TrackingStackDepth; index ++) { + _stack[index] = NULL; + } +} + +// number of stack frames captured +int NativeCallStack::frames() const { + int index; + for (index = 0; index < NMT_TrackingStackDepth; index ++) { + if (_stack[index] == NULL) { + break; + } + } + return index; +} + +// Hash code. Any better algorithm? +int NativeCallStack::hash() const { + long hash_val = _hash_value; + if (hash_val == 0) { + long pc; + int index; + for (index = 0; index < NMT_TrackingStackDepth; index ++) { + pc = (long)_stack[index]; + if (pc == 0) break; + hash_val += pc; + } + + NativeCallStack* p = const_cast(this); + p->_hash_value = (int)(hash_val & 0xFFFFFFFF); + } + return _hash_value; +} + +void NativeCallStack::print_on(outputStream* out) const { + print_on(out, 0); +} + +// Decode and print this call path +void NativeCallStack::print_on(outputStream* out, int indent) const { + address pc; + char buf[1024]; + int offset; + if (is_empty()) { + for (int index = 0; index < indent; index ++) out->print(" "); +#if PLATFORM_NATIVE_STACK_WALKING_SUPPORTED + out->print("[BOOTSTRAP]"); +#else + out->print("[No stack]"); +#endif + } else { + for (int frame = 0; frame < NMT_TrackingStackDepth; frame ++) { + pc = get_frame(frame); + if (pc == NULL) break; + // Print indent + for (int index = 0; index < indent; index ++) out->print(" "); + if (os::dll_address_to_function_name(pc, buf, sizeof(buf), &offset)) { + out->print_cr("[" PTR_FORMAT "] %s+0x%x", p2i(pc), buf, offset); + } else { + out->print_cr("[" PTR_FORMAT "]", p2i(pc)); + } + } + } +} + diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/utilities/nativeCallStack.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/utilities/nativeCallStack.hpp Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_UTILITIES_NATIVE_CALL_STACK_HPP +#define SHARE_VM_UTILITIES_NATIVE_CALL_STACK_HPP + +#include "memory/allocation.hpp" +#include "services/nmtCommon.hpp" +#include "utilities/ostream.hpp" + +/* + * This class represents a native call path (does not include Java frame) + * + * This class is developed in the context of native memory tracking, it can + * be an useful tool for debugging purpose. + * + * For example, following code should print out native call path: + * + * .... + * NativeCallStack here; + * here.print_on(tty); + * .... + * + * However, there are a couple of restrictions on this class. If the restrictions are + * not strictly followed, it may break native memory tracking badly. + * + * 1. Number of stack frames to capture, is defined by native memory tracking. + * This number has impacts on how much memory to be used by native + * memory tracking. + * 2. The class is strict stack object, no heap or virtual memory can be allocated + * from it. + */ +class NativeCallStack : public StackObj { + private: + address _stack[NMT_TrackingStackDepth]; + int _hash_value; + + public: + NativeCallStack(int toSkip = 0, bool fillStack = false); + NativeCallStack(address* pc, int frameCount); + + + // if it is an empty stack + inline bool is_empty() const { + return _stack[0] == NULL; + } + + // number of stack frames captured + int frames() const; + + inline int compare(const NativeCallStack& other) const { + return memcmp(_stack, other._stack, sizeof(_stack)); + } + + inline bool equals(const NativeCallStack& other) const { + // compare hash values + if (hash() != other.hash()) return false; + // compare each frame + return compare(other) == 0; + } + + inline address get_frame(int index) const { + assert(index >= 0 && index < NMT_TrackingStackDepth, "Index out of bound"); + return _stack[index]; + } + + // Hash code. Any better algorithm? + int hash() const; + + void print_on(outputStream* out) const; + void print_on(outputStream* out, int indent) const; +}; + +#endif diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/src/share/vm/utilities/vmError.cpp --- a/hotspot/src/share/vm/utilities/vmError.cpp Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/src/share/vm/utilities/vmError.cpp Fri Aug 29 11:58:43 2014 -0700 @@ -774,6 +774,11 @@ st->cr(); } + STEP(228, "(Native Memory Tracking)" ) + if (_verbose) { + MemTracker::final_report(st); + } + STEP(230, "" ) if (_verbose) { @@ -897,9 +902,6 @@ static bool log_done = false; // done saving error log static bool transmit_report_done = false; // done error reporting - // disble NMT to avoid further exception - MemTracker::shutdown(MemTracker::NMT_error_reporting); - if (SuppressFatalErrorMessage) { os::abort(); } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/TEST.ROOT --- a/hotspot/test/TEST.ROOT Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/TEST.ROOT Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 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 @@ -27,6 +27,6 @@ # It also contains test-suite configuration information. # The list of keywords supported in this test suite -keys=cte_test jcmd nmt regression gc +keys=cte_test jcmd nmt regression gc stress groups=TEST.groups [closed/TEST.groups] diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/TEST.groups --- a/hotspot/test/TEST.groups Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/TEST.groups Fri Aug 29 11:58:43 2014 -0700 @@ -70,21 +70,29 @@ runtime/7194254/Test7194254.java \ runtime/Metaspace/FragmentMetaspace.java \ runtime/NMT/BaselineWithParameter.java \ + runtime/NMT/JcmdBaselineDetail.java \ + runtime/NMT/JcmdDetailDiff.java \ + runtime/NMT/JcmdScaleDetail.java \ runtime/NMT/JcmdScale.java \ + runtime/NMT/JcmdSummaryDiff.java \ runtime/NMT/JcmdWithNMTDisabled.java \ + runtime/NMT/MallocRoundingReportTest.java \ + runtime/NMT/MallocSiteHashOverflow.java \ + runtime/NMT/MallocStressTest.java \ runtime/NMT/MallocTestType.java \ runtime/NMT/ReleaseCommittedMemory.java \ + runtime/NMT/ReleaseNoCommit.java \ runtime/NMT/ShutdownTwice.java \ runtime/NMT/SummaryAfterShutdown.java \ runtime/NMT/SummarySanityCheck.java \ runtime/NMT/ThreadedMallocTestType.java \ runtime/NMT/ThreadedVirtualAllocTestType.java \ + runtime/NMT/VirtualAllocCommitUncommitRecommit.java \ runtime/NMT/VirtualAllocTestType.java \ runtime/RedefineObject/TestRedefineObject.java \ runtime/Thread/TestThreadDumpMonitorContention.java \ runtime/XCheckJniJsig/XCheckJSig.java \ serviceability/attach/AttachWithStalePidFile.java \ - serviceability/jvmti/8036666/GetObjectLockCount.java \ serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java \ serviceability/dcmd/DynLibDcmdTest.java @@ -120,16 +128,12 @@ gc/6581734/Test6581734.java \ gc/7072527/TestFullGCCount.java \ gc/g1/TestHumongousAllocInitialMark.java \ - gc/g1/TestHumongousShrinkHeap.java \ gc/arguments/TestG1HeapRegionSize.java \ gc/metaspace/TestMetaspaceMemoryPool.java \ gc/arguments/TestDynMinHeapFreeRatio.java \ gc/arguments/TestDynMaxHeapFreeRatio.java \ - gc/parallelScavenge/TestDynShrinkHeap.java \ runtime/InternalApi/ThreadCpuTimesDeadlock.java \ serviceability/threads/TestFalseDeadLock.java \ - serviceability/jvmti/GetObjectSizeOverflow.java \ - serviceability/jvmti/TestRedefineWithUnresolvedClass.java # Compact 2 adds full VM tests compact2 = \ @@ -217,6 +221,7 @@ gc/arguments/TestMaxHeapSizeTools.java \ gc/arguments/TestMaxNewSize.java \ gc/arguments/TestUseCompressedOopsErgo.java \ + gc/class_unloading/TestG1ClassUnloadingHWM.java \ gc/g1/ \ gc/metaspace/G1AddMetaspaceDependency.java \ gc/metaspace/TestMetaspacePerfCounters.java \ @@ -257,7 +262,7 @@ gc/arguments/TestCMSHeapSizeFlags.java \ gc/arguments/TestMaxNewSize.java \ gc/arguments/TestUseCompressedOopsErgo.java \ - gc/class_unloading/TestCMSClassUnloadingDisabledHWM.java \ + gc/class_unloading/TestCMSClassUnloadingEnabledHWM.java \ gc/concurrentMarkSweep/ \ gc/startup_warnings/TestCMS.java \ gc/startup_warnings/TestCMSIncrementalMode.java \ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/5091921/Test7005594.sh --- a/hotspot/test/compiler/5091921/Test7005594.sh Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/5091921/Test7005594.sh Fri Aug 29 11:58:43 2014 -0700 @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 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 @@ -78,7 +78,7 @@ ${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} -d . Test7005594.java -${TESTJAVA}/bin/java ${TESTVMOPTS} -Xmx1600m -Xms1600m -XX:+IgnoreUnrecognizedVMOptions -XX:-ZapUnusedHeapArea -Xcomp -XX:CompileOnly=Test7005594.test Test7005594 > test.out 2>&1 +${TESTJAVA}/bin/java ${TESTOPTS} -Xmx1600m -Xms1600m -XX:+IgnoreUnrecognizedVMOptions -XX:-ZapUnusedHeapArea -Xcomp -XX:CompileOnly=Test7005594.test Test7005594 > test.out 2>&1 result=$? diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/6857159/Test6857159.sh --- a/hotspot/test/compiler/6857159/Test6857159.sh Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/6857159/Test6857159.sh Fri Aug 29 11:58:43 2014 -0700 @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2009, 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 @@ -39,7 +39,7 @@ ${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} -d . Test6857159.java -${TESTJAVA}/bin/java ${TESTVMOPTS} -Xbatch -XX:+PrintCompilation -XX:CompileOnly=Test6857159\$ct.run Test6857159 > test.out 2>&1 +${TESTJAVA}/bin/java ${TESTOPTS} -Xbatch -XX:+PrintCompilation -XX:CompileOnly=Test6857159\$ct.run Test6857159 > test.out 2>&1 grep "COMPILE SKIPPED" test.out diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/6894807/IsInstanceTest.java --- a/hotspot/test/compiler/6894807/IsInstanceTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/6894807/IsInstanceTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,3 +1,26 @@ +/* + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + /* * @test * @bug 6894807 diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/6894807/Test6894807.sh --- a/hotspot/test/compiler/6894807/Test6894807.sh Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/6894807/Test6894807.sh Fri Aug 29 11:58:43 2014 -0700 @@ -1,55 +1,38 @@ #!/bin/sh +# +# Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# if [ "${TESTSRC}" = "" ] -then TESTSRC=. +then + TESTSRC=${PWD} + echo "TESTSRC not set. Using "${TESTSRC}" as default" fi - -if [ "${TESTJAVA}" = "" ] -then - PARENT=`dirname \`which java\`` - TESTJAVA=`dirname ${PARENT}` - echo "TESTJAVA not set, selecting " ${TESTJAVA} - echo "If this is incorrect, try setting the variable manually." -fi - -if [ "${TESTCLASSES}" = "" ] -then - echo "TESTCLASSES not set. Test cannot execute. Failed." - exit 1 -fi +echo "TESTSRC=${TESTSRC}" -# set platform-dependent variables -OS=`uname -s` -case "$OS" in - SunOS | Linux | Darwin ) - NULL=/dev/null - PS=":" - FS="/" - ;; - Windows_* ) - NULL=NUL - PS=";" - FS="\\" - ;; - CYGWIN_* ) - NULL=/dev/null - PS=";" - FS="/" - ;; - * ) - echo "Unrecognized system!" - exit 1; - ;; -esac +## Adding common setup Variables for running shell tests. +. ${TESTSRC}/../../test_env.sh -JEMMYPATH=${CPAPPEND} -CLASSPATH=.${PS}${TESTCLASSES}${PS}${JEMMYPATH} ; export CLASSPATH - -THIS_DIR=`pwd` - -${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -version - -${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} IsInstanceTest > test.out 2>&1 +${TESTJAVA}${FS}bin${FS}java ${TESTOPTS} IsInstanceTest > test.out 2>&1 cat test.out diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/6932496/Test6932496.java --- a/hotspot/test/compiler/6932496/Test6932496.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/6932496/Test6932496.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -26,26 +26,162 @@ * @test * @bug 6932496 * @summary incorrect deopt of jsr subroutine on 64 bit c1 - * - * @compile -source 1.5 -target 1.5 -XDjsrlimit=0 Test6932496.java - * @run main/othervm -Xcomp -XX:CompileOnly=Test6932496.m Test6932496 + * @run main/othervm -Xcomp -XX:CompileOnly=Test.test Test6932496 */ +import java.lang.reflect.Method; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.io.IOException; -public class Test6932496 { - static class A { - volatile boolean flag = false; +import jdk.internal.org.objectweb.asm.ClassWriter; +import jdk.internal.org.objectweb.asm.MethodVisitor; +import jdk.internal.org.objectweb.asm.FieldVisitor; +import jdk.internal.org.objectweb.asm.Opcodes; +import jdk.internal.org.objectweb.asm.Type; +import jdk.internal.org.objectweb.asm.Label; + +public class Test6932496 extends ClassLoader { + private static final int CLASS_FILE_VERSION = 49; + private static final String CLASS_TEST = "Test"; + private static final String CLASS_OBJECT = "java/lang/Object"; + private static final String METHOD_INIT = ""; + private static final String METHOD_TEST = "test"; + private static final String DESC_VOID_METHOD = "()V"; + private static final String FIELD_FLAG = "flag"; + + public static void main(String[] args) { + Test6932496 test = new Test6932496(); + test.execute(); } - static void m() { + private void execute() { + byte[] bytecode = Test6932496.generateTestClass(); + try { - } finally { - A a = new A(); - a.flag = true; + Files.write(Paths.get("Test.class.dump"), bytecode); + } catch (IOException e) { + System.err.println("classfile dump failed : " + e.getMessage()); + e.printStackTrace(); + } + try { + Class aClass = defineClass(CLASS_TEST, bytecode, 0, bytecode.length); + Method test = aClass.getDeclaredMethod(METHOD_TEST); + test.invoke(null); + } catch (ClassFormatError | IllegalArgumentException + | ReflectiveOperationException e) { + throw new RuntimeException("TESTBUG : generated class is invalid", e); } } + /* + public class Test { + volatile boolean flag = false; + public static void m() { + try { + } finally { + Test test = new Test(); + test.flag = true; + } + } + } + */ + private static byte[] generateTestClass() { + ClassWriter cw = new ClassWriter(0); + cw.visit(CLASS_FILE_VERSION, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, + CLASS_TEST, null, CLASS_OBJECT, null); + // volatile boolean flag; + { + FieldVisitor fv = cw.visitField(Opcodes.ACC_VOLATILE, FIELD_FLAG, + Type.BOOLEAN_TYPE.getDescriptor(), + /* signature = */ null, /* value = */ null); + } - static public void main(String[] args) { - m(); + /* + public Test() { + flag = false; + } + */ + { + MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, + METHOD_INIT, DESC_VOID_METHOD, + /* signature = */ null, /* exceptions = */ null); + + mv.visitCode(); + mv.visitVarInsn(Opcodes.ALOAD, 0); + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, CLASS_OBJECT, METHOD_INIT, + DESC_VOID_METHOD, false); + + mv.visitVarInsn(Opcodes.ALOAD, 0); + mv.visitInsn(Opcodes.ICONST_0); + mv.visitFieldInsn(Opcodes.PUTFIELD, CLASS_TEST, FIELD_FLAG, + Type.BOOLEAN_TYPE.getDescriptor()); + + mv.visitInsn(Opcodes.RETURN); + mv.visitMaxs(/* stack = */ 2, /* locals = */ 1); + mv.visitEnd(); + } + + /* + public static void m() { + try { + } finally { + Test test = new Test(); + test.flag = true; + } + } + */ + { + MethodVisitor mv = cw.visitMethod( + Opcodes.ACC_STATIC + Opcodes.ACC_PUBLIC, + METHOD_TEST, DESC_VOID_METHOD, + /* signature = */ null, /* exceptions = */ null); + Label beginLabel = new Label(); + Label block1EndLabel = new Label(); + Label handlerLabel = new Label(); + Label block2EndLabel = new Label(); + Label label = new Label(); + Label endLabel = new Label(); + + mv.visitCode(); + mv.visitTryCatchBlock(beginLabel, block1EndLabel, handlerLabel, + /* type = */ null); + mv.visitTryCatchBlock(handlerLabel, block2EndLabel, handlerLabel, + /* type = */ null); + + mv.visitLabel(beginLabel); + mv.visitJumpInsn(Opcodes.JSR, label); + mv.visitLabel(block1EndLabel); + mv.visitJumpInsn(Opcodes.GOTO, endLabel); + + mv.visitLabel(handlerLabel); + mv.visitVarInsn(Opcodes.ASTORE, 0); + mv.visitJumpInsn(Opcodes.JSR, label); + mv.visitLabel(block2EndLabel); + mv.visitVarInsn(Opcodes.ALOAD, 0); + mv.visitInsn(Opcodes.ATHROW); + + mv.visitLabel(label); + mv.visitVarInsn(Opcodes.ASTORE, 1); + mv.visitTypeInsn(Opcodes.NEW, CLASS_TEST); + mv.visitInsn(Opcodes.DUP); + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, CLASS_TEST, METHOD_INIT, + DESC_VOID_METHOD); + mv.visitVarInsn(Opcodes.ASTORE, 2); + + mv.visitVarInsn(Opcodes.ALOAD, 2); + mv.visitInsn(Opcodes.ICONST_1); + mv.visitFieldInsn(Opcodes.PUTFIELD, CLASS_TEST, FIELD_FLAG, + Type.BOOLEAN_TYPE.getDescriptor()); + + mv.visitVarInsn(Opcodes.RET, 1); + + mv.visitLabel(endLabel); + mv.visitInsn(Opcodes.RETURN); + mv.visitMaxs(/* stack = */ 2, /* locals = */ 3); + mv.visitEnd(); + } + + cw.visitEnd(); + return cw.toByteArray(); } } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/7068051/Test7068051.sh --- a/hotspot/test/compiler/7068051/Test7068051.sh Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/7068051/Test7068051.sh Fri Aug 29 11:58:43 2014 -0700 @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 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 @@ -41,5 +41,5 @@ ${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} -d . Test7068051.java -${TESTJAVA}/bin/java ${TESTVMOPTS} -showversion -Xbatch Test7068051 foo.jar +${TESTJAVA}/bin/java ${TESTOPTS} -showversion -Xbatch Test7068051 foo.jar diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/7070134/Test7070134.sh --- a/hotspot/test/compiler/7070134/Test7070134.sh Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/7070134/Test7070134.sh Fri Aug 29 11:58:43 2014 -0700 @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 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 @@ -39,7 +39,7 @@ ${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} -d . Stemmer.java -${TESTJAVA}/bin/java ${TESTVMOPTS} -Xbatch Stemmer words > test.out 2>&1 +${TESTJAVA}/bin/java ${TESTOPTS} -Xbatch Stemmer words > test.out 2>&1 exit $? diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/7200264/Test7200264.sh --- a/hotspot/test/compiler/7200264/Test7200264.sh Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/7200264/Test7200264.sh Fri Aug 29 11:58:43 2014 -0700 @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 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 @@ -33,7 +33,7 @@ ## Adding common setup Variables for running shell tests. . ${TESTSRC}/../../test_env.sh -${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -Xinternalversion | sed 's/amd64/x86/' | grep "x86" | grep "Server VM" | grep "debug" +${TESTJAVA}${FS}bin${FS}java ${TESTOPTS} -Xinternalversion | sed 's/amd64/x86/' | grep "x86" | grep "Server VM" | grep "debug" # Only test fastdebug Server VM on x86 if [ $? != 0 ] @@ -43,7 +43,7 @@ fi # grep for support integer multiply vectors (cpu with SSE4.1) -${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -XX:+PrintMiscellaneous -XX:+Verbose -version | grep "cores per cpu" | grep "sse4.1" +${TESTJAVA}${FS}bin${FS}java ${TESTOPTS} -XX:+PrintMiscellaneous -XX:+Verbose -version | grep "cores per cpu" | grep "sse4.1" if [ $? != 0 ] then @@ -55,7 +55,7 @@ cp ${TESTSRC}${FS}TestIntVect.java . ${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} -d . TestIntVect.java -${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -Xbatch -XX:-TieredCompilation -XX:CICompilerCount=1 -XX:+PrintCompilation -XX:+TraceNewVectors TestIntVect > test.out 2>&1 +${TESTJAVA}${FS}bin${FS}java ${TESTOPTS} -Xbatch -XX:-TieredCompilation -XX:CICompilerCount=1 -XX:+PrintCompilation -XX:+TraceNewVectors TestIntVect > test.out 2>&1 COUNT=`grep AddVI test.out | wc -l | awk '{print $1}'` if [ $COUNT -lt 4 ] diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/8009761/Test8009761.java --- a/hotspot/test/compiler/8009761/Test8009761.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/8009761/Test8009761.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -31,6 +31,7 @@ * @summary Deoptimization on sparc doesn't set Llast_SP correctly in the interpreter frames it creates * @build Test8009761 * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=exclude,Test8009761::m2 -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -Xss256K Test8009761 */ public class Test8009761 { diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/8010927/Test8010927.java --- a/hotspot/test/compiler/8010927/Test8010927.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/8010927/Test8010927.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -28,6 +28,7 @@ * @library /testlibrary/whitebox /testlibrary * @build Test8010927 * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. -Xmx64m -XX:NewSize=20971520 -XX:MaxNewSize=32m -XX:-UseTLAB -XX:-UseParNewGC -XX:-UseAdaptiveSizePolicy Test8010927 */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/arguments/TestUseBMI1InstructionsOnSupportedCPU.java --- a/hotspot/test/compiler/arguments/TestUseBMI1InstructionsOnSupportedCPU.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/arguments/TestUseBMI1InstructionsOnSupportedCPU.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @build TestUseBMI1InstructionsOnSupportedCPU * BMISupportedCPUTest * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestUseBMI1InstructionsOnSupportedCPU */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/arguments/TestUseBMI1InstructionsOnUnsupportedCPU.java --- a/hotspot/test/compiler/arguments/TestUseBMI1InstructionsOnUnsupportedCPU.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/arguments/TestUseBMI1InstructionsOnUnsupportedCPU.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @build TestUseBMI1InstructionsOnUnsupportedCPU * BMIUnsupportedCPUTest * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestUseBMI1InstructionsOnUnsupportedCPU */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/arguments/TestUseCountLeadingZerosInstructionOnSupportedCPU.java --- a/hotspot/test/compiler/arguments/TestUseCountLeadingZerosInstructionOnSupportedCPU.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/arguments/TestUseCountLeadingZerosInstructionOnSupportedCPU.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @build TestUseCountLeadingZerosInstructionOnSupportedCPU * BMISupportedCPUTest * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI * TestUseCountLeadingZerosInstructionOnSupportedCPU diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/arguments/TestUseCountLeadingZerosInstructionOnUnsupportedCPU.java --- a/hotspot/test/compiler/arguments/TestUseCountLeadingZerosInstructionOnUnsupportedCPU.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/arguments/TestUseCountLeadingZerosInstructionOnUnsupportedCPU.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @build TestUseCountLeadingZerosInstructionOnUnsupportedCPU * BMIUnsupportedCPUTest * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI * TestUseCountLeadingZerosInstructionOnUnsupportedCPU diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/arguments/TestUseCountTrailingZerosInstructionOnSupportedCPU.java --- a/hotspot/test/compiler/arguments/TestUseCountTrailingZerosInstructionOnSupportedCPU.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/arguments/TestUseCountTrailingZerosInstructionOnSupportedCPU.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @build TestUseCountTrailingZerosInstructionOnSupportedCPU * BMISupportedCPUTest * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI * TestUseCountTrailingZerosInstructionOnSupportedCPU diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/arguments/TestUseCountTrailingZerosInstructionOnUnsupportedCPU.java --- a/hotspot/test/compiler/arguments/TestUseCountTrailingZerosInstructionOnUnsupportedCPU.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/arguments/TestUseCountTrailingZerosInstructionOnUnsupportedCPU.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @build TestUseCountTrailingZerosInstructionOnUnsupportedCPU * BMIUnsupportedCPUTest * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI * TestUseCountTrailingZerosInstructionOnUnsupportedCPU diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/ciReplay/TestSA.sh --- a/hotspot/test/compiler/ciReplay/TestSA.sh Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/ciReplay/TestSA.sh Fri Aug 29 11:58:43 2014 -0700 @@ -68,7 +68,7 @@ fi echo "dumpreplaydata -a > ${replay_data}" | \ - ${JAVA} ${TESTVMOPTS} \ + ${JAVA} ${TESTOPTS} \ -cp ${TESTJAVA}${FS}lib${FS}sa-jdi.jar \ sun.jvm.hotspot.CLHSDB ${JAVA} ${core_file} diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/ciReplay/common.sh --- a/hotspot/test/compiler/ciReplay/common.sh Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/ciReplay/common.sh Fri Aug 29 11:58:43 2014 -0700 @@ -22,6 +22,7 @@ # questions. # # +set -x # $1 - error code # $2 - test name @@ -56,7 +57,7 @@ shift name=$1 shift - VMOPTS="${TESTVMOPTS} $@" + VMOPTS="${TESTOPTS} $@" echo "POSITIVE TEST [$name]" start_test ${VMOPTS} exit_code=$? @@ -75,7 +76,7 @@ shift name=$1 shift - VMOPTS="${TESTVMOPTS} $@" + VMOPTS="${TESTOPTS} $@" echo "NEGATIVE TEST [$name]" start_test ${VMOPTS} exit_code=$? @@ -149,7 +150,7 @@ replay_data=test_replay.txt -${JAVA} ${TESTVMOPTS} -Xinternalversion 2>&1 | grep debug +${JAVA} ${TESTOPTS} -Xinternalversion 2>&1 | grep debug # Only test fastdebug if [ $? -ne 0 ] @@ -158,7 +159,7 @@ exit 0 fi -is_int=`${JAVA} ${TESTVMOPTS} -version 2>&1 | grep -c "interpreted mode"` +is_int=`${JAVA} ${TESTOPTS} -version 2>&1 | grep -c "interpreted mode"` # Not applicable for Xint if [ $is_int -ne 0 ] then @@ -168,14 +169,14 @@ cleanup -client_available=`${JAVA} ${TESTVMOPTS} -client -Xinternalversion 2>&1 | \ +client_available=`${JAVA} ${TESTOPTS} -client -Xinternalversion 2>&1 | \ grep -c Client` -server_available=`${JAVA} ${TESTVMOPTS} -server -Xinternalversion 2>&1 | \ +server_available=`${JAVA} ${TESTOPTS} -server -Xinternalversion 2>&1 | \ grep -c Server` -tiered_available=`${JAVA} ${TESTVMOPTS} -XX:+TieredCompilation -XX:+PrintFlagsFinal -version | \ +tiered_available=`${JAVA} ${TESTOPTS} -XX:+TieredCompilation -XX:+PrintFlagsFinal -version | \ grep TieredCompilation | \ grep -c true` -is_tiered=`${JAVA} ${TESTVMOPTS} -XX:+PrintFlagsFinal -version | \ +is_tiered=`${JAVA} ${TESTOPTS} -XX:+PrintFlagsFinal -version | \ grep TieredCompilation | \ grep -c true` # CompLevel_simple -- C1 @@ -207,7 +208,7 @@ fi fi - cmd="${JAVA} ${TESTVMOPTS} $@ \ + cmd="${JAVA} ${TESTOPTS} $@ \ -Xms8m \ -Xmx32m \ -XX:MetaspaceSize=4m \ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/classUnloading/methodUnloading/TestMethodUnloading.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/classUnloading/methodUnloading/TestMethodUnloading.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import sun.hotspot.WhiteBox; + +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +/* + * @test MethodUnloadingTest + * @bug 8029443 + * @summary "Tests the unloading of methods to to class unloading" + * @library /testlibrary /testlibrary/whitebox + * @build TestMethodUnloading + * @build WorkerClass + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-BackgroundCompilation -XX:-UseCompressedOops -XX:+UseParallelGC -XX:CompileOnly=TestMethodUnloading::doWork TestMethodUnloading + */ +public class TestMethodUnloading { + private static final String workerClassName = "WorkerClass"; + private static int work = -1; + + private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); + private static int COMP_LEVEL_SIMPLE = 1; + private static int COMP_LEVEL_FULL_OPTIMIZATION = 4; + + /** + * Does some work by either using the workerClass or locally producing values. + * @param workerClass Class performing some work (will be unloaded) + * @param useWorker If true the workerClass is used + */ + static private void doWork(Class workerClass, boolean useWorker) throws InstantiationException, IllegalAccessException { + if (useWorker) { + // Create a new instance + Object worker = workerClass.newInstance(); + // We would like to call a method of WorkerClass here but we cannot cast to WorkerClass + // because the class was loaded by a different class loader. One solution would be to use + // reflection but since we want C2 to implement the call as an optimized IC we call + // Object::hashCode() here which actually calls WorkerClass::hashCode(). + // C2 will then implement this call as an optimized IC that points to a to-interpreter stub + // referencing the Method* for WorkerClass::hashCode(). + work = worker.hashCode(); + if (work != 42) { + new RuntimeException("Work not done"); + } + } else { + // Do some important work here + work = 1; + } + } + + /** + * Makes sure that method is compiled by forcing compilation if not yet compiled. + * @param m Method to be checked + */ + static private void makeSureIsCompiled(Method m) { + // Make sure background compilation is disabled + if (WHITE_BOX.getBooleanVMFlag("BackgroundCompilation")) { + throw new RuntimeException("Background compilation enabled"); + } + + // Check if already compiled + if (!WHITE_BOX.isMethodCompiled(m)) { + // If not, try to compile it with C2 + if(!WHITE_BOX.enqueueMethodForCompilation(m, COMP_LEVEL_FULL_OPTIMIZATION)) { + // C2 compiler not available, try to compile with C1 + WHITE_BOX.enqueueMethodForCompilation(m, COMP_LEVEL_SIMPLE); + } + // Because background compilation is disabled, method should now be compiled + if(!WHITE_BOX.isMethodCompiled(m)) { + throw new RuntimeException(m + " not compiled"); + } + } + } + + /** + * This test creates stale Method* metadata in a to-interpreter stub of an optimized IC. + * + * The following steps are performed: + * (1) A workerClass is loaded by a custom class loader + * (2) The method doWork that calls a method of the workerClass is compiled. The call + * is implemented as an optimized IC calling a to-interpreted stub. The to-interpreter + * stub contains a Method* to a workerClass method. + * (3) Unloading of the workerClass is enforced. The to-interpreter stub now contains a dead Method*. + * (4) Depending on the implementation of the IC, the compiled version of doWork should still be + * valid. We call it again without using the workerClass. + */ + static public void main(String[] args) throws Exception { + // (1) Create a custom class loader with no parent class loader + URL url = TestMethodUnloading.class.getProtectionDomain().getCodeSource().getLocation(); + URLClassLoader loader = new URLClassLoader(new URL[] {url}, null); + + // Load worker class with custom class loader + Class workerClass = Class.forName(workerClassName, true, loader); + + // (2) Make sure all paths of doWork are profiled and compiled + for (int i = 0; i < 100000; ++i) { + doWork(workerClass, true); + doWork(workerClass, false); + } + + // Make sure doWork is compiled now + Method doWork = TestMethodUnloading.class.getDeclaredMethod("doWork", Class.class, boolean.class); + makeSureIsCompiled(doWork); + + // (3) Throw away class loader and reference to workerClass to allow unloading + loader.close(); + loader = null; + workerClass = null; + + // Force garbage collection to trigger unloading of workerClass + // Dead reference to WorkerClass::hashCode triggers JDK-8029443 + WHITE_BOX.fullGC(); + + // (4) Depending on the implementation of the IC, the compiled version of doWork + // may still be valid here. Execute it without a workerClass. + doWork(null, false); + if (work != 1) { + throw new RuntimeException("Work not done"); + } + + doWork(Object.class, false); + } +} diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/classUnloading/methodUnloading/WorkerClass.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/classUnloading/methodUnloading/WorkerClass.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * Worker class that is dynamically loaded/unloaded by TestMethodUnloading. + */ +public class WorkerClass { + /** + * We override hashCode here to be able to access this implementation + * via an Object reference (we cannot cast to WorkerClass). + */ + @Override + public int hashCode() { + return 42; + } +} + diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/intrinsics/bmi/TestAndnI.java --- a/hotspot/test/compiler/intrinsics/bmi/TestAndnI.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/intrinsics/bmi/TestAndnI.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @library /testlibrary /testlibrary/whitebox * @build TestAndnI BMITestRunner Expr * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestAndnI */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/intrinsics/bmi/TestAndnL.java --- a/hotspot/test/compiler/intrinsics/bmi/TestAndnL.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/intrinsics/bmi/TestAndnL.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @library /testlibrary /testlibrary/whitebox * @build TestAndnL BMITestRunner Expr * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestAndnL */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/intrinsics/bmi/TestBlsiI.java --- a/hotspot/test/compiler/intrinsics/bmi/TestBlsiI.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/intrinsics/bmi/TestBlsiI.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @library /testlibrary /testlibrary/whitebox * @build TestBlsiI BMITestRunner Expr * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestBlsiI */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/intrinsics/bmi/TestBlsiL.java --- a/hotspot/test/compiler/intrinsics/bmi/TestBlsiL.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/intrinsics/bmi/TestBlsiL.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @library /testlibrary /testlibrary/whitebox * @build TestBlsiL BMITestRunner Expr * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestBlsiL */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/intrinsics/bmi/TestBlsmskI.java --- a/hotspot/test/compiler/intrinsics/bmi/TestBlsmskI.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/intrinsics/bmi/TestBlsmskI.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @library /testlibrary /testlibrary/whitebox * @build TestBlsmskI BMITestRunner Expr * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestBlsmskI */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/intrinsics/bmi/TestBlsmskL.java --- a/hotspot/test/compiler/intrinsics/bmi/TestBlsmskL.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/intrinsics/bmi/TestBlsmskL.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @library /testlibrary /testlibrary/whitebox * @build TestBlsmskL BMITestRunner Expr * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestBlsmskL */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/intrinsics/bmi/TestBlsrI.java --- a/hotspot/test/compiler/intrinsics/bmi/TestBlsrI.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/intrinsics/bmi/TestBlsrI.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @library /testlibrary /testlibrary/whitebox * @build TestBlsrI BMITestRunner Expr * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestBlsrI */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/intrinsics/bmi/TestBlsrL.java --- a/hotspot/test/compiler/intrinsics/bmi/TestBlsrL.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/intrinsics/bmi/TestBlsrL.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @library /testlibrary /testlibrary/whitebox * @build TestBlsrL BMITestRunner Expr * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestBlsrL */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/intrinsics/bmi/TestLzcntI.java --- a/hotspot/test/compiler/intrinsics/bmi/TestLzcntI.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/intrinsics/bmi/TestLzcntI.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @library /testlibrary /testlibrary/whitebox * @build TestLzcntI BMITestRunner Expr * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestLzcntI */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/intrinsics/bmi/TestLzcntL.java --- a/hotspot/test/compiler/intrinsics/bmi/TestLzcntL.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/intrinsics/bmi/TestLzcntL.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @library /testlibrary /testlibrary/whitebox * @build TestLzcntL BMITestRunner Expr * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestLzcntL */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/intrinsics/bmi/TestTzcntI.java --- a/hotspot/test/compiler/intrinsics/bmi/TestTzcntI.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/intrinsics/bmi/TestTzcntI.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @library /testlibrary /testlibrary/whitebox * @build TestTzcntI BMITestRunner Expr * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestTzcntI */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/intrinsics/bmi/TestTzcntL.java --- a/hotspot/test/compiler/intrinsics/bmi/TestTzcntL.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/intrinsics/bmi/TestTzcntL.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @library /testlibrary /testlibrary/whitebox * @build TestTzcntL BMITestRunner Expr * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestTzcntL */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/intrinsics/bmi/verifycode/AddnTestI.java --- a/hotspot/test/compiler/intrinsics/bmi/verifycode/AddnTestI.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/AddnTestI.java Fri Aug 29 11:58:43 2014 -0700 @@ -27,6 +27,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. * @build AddnTestI * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions AddnTestI */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/intrinsics/bmi/verifycode/AddnTestL.java --- a/hotspot/test/compiler/intrinsics/bmi/verifycode/AddnTestL.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/AddnTestL.java Fri Aug 29 11:58:43 2014 -0700 @@ -27,6 +27,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. * @build AddnTestL * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions AddnTestL */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/intrinsics/bmi/verifycode/BlsiTestI.java --- a/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsiTestI.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsiTestI.java Fri Aug 29 11:58:43 2014 -0700 @@ -27,6 +27,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. * @build BlsiTestI * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions BlsiTestI */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/intrinsics/bmi/verifycode/BlsiTestL.java --- a/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsiTestL.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsiTestL.java Fri Aug 29 11:58:43 2014 -0700 @@ -27,6 +27,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. * @build BlsiTestL * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions BlsiTestL */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/intrinsics/bmi/verifycode/BlsmskTestI.java --- a/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsmskTestI.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsmskTestI.java Fri Aug 29 11:58:43 2014 -0700 @@ -27,6 +27,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. * @build BlsmskTestI * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions BlsmskTestI */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/intrinsics/bmi/verifycode/BlsmskTestL.java --- a/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsmskTestL.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsmskTestL.java Fri Aug 29 11:58:43 2014 -0700 @@ -27,6 +27,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. * @build BlsmskTestL * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions BlsmskTestL */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/intrinsics/bmi/verifycode/BlsrTestI.java --- a/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsrTestI.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsrTestI.java Fri Aug 29 11:58:43 2014 -0700 @@ -27,6 +27,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. * @build BlsrTestI * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions BlsrTestI */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/intrinsics/bmi/verifycode/BlsrTestL.java --- a/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsrTestL.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsrTestL.java Fri Aug 29 11:58:43 2014 -0700 @@ -27,6 +27,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. * @build BlsrTestL * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions BlsrTestL */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/intrinsics/bmi/verifycode/LZcntTestI.java --- a/hotspot/test/compiler/intrinsics/bmi/verifycode/LZcntTestI.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/LZcntTestI.java Fri Aug 29 11:58:43 2014 -0700 @@ -27,6 +27,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. * @build LZcntTestI * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCountLeadingZerosInstruction LZcntTestI */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/intrinsics/bmi/verifycode/LZcntTestL.java --- a/hotspot/test/compiler/intrinsics/bmi/verifycode/LZcntTestL.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/LZcntTestL.java Fri Aug 29 11:58:43 2014 -0700 @@ -27,6 +27,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. * @build LZcntTestL * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCountLeadingZerosInstruction LZcntTestL */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/intrinsics/bmi/verifycode/TZcntTestI.java --- a/hotspot/test/compiler/intrinsics/bmi/verifycode/TZcntTestI.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/TZcntTestI.java Fri Aug 29 11:58:43 2014 -0700 @@ -27,6 +27,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. * @build TZcntTestI * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCountTrailingZerosInstruction TZcntTestI */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/intrinsics/bmi/verifycode/TZcntTestL.java --- a/hotspot/test/compiler/intrinsics/bmi/verifycode/TZcntTestL.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/TZcntTestL.java Fri Aug 29 11:58:43 2014 -0700 @@ -27,6 +27,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. * @build TZcntTestL * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCountTrailingZerosInstruction TZcntTestL */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactIntTest.java --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactIntTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactIntTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -26,6 +26,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox * @build AddExactIntTest * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactLongTest.java --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactLongTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactLongTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -26,6 +26,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox * @build AddExactLongTest * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactIntTest.java --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactIntTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactIntTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -26,6 +26,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox * @build DecrementExactIntTest * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactLongTest.java --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactLongTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactLongTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -26,6 +26,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox * @build DecrementExactLongTest * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactIntTest.java --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactIntTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactIntTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -26,6 +26,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox * @build IncrementExactIntTest * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactLongTest.java --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactLongTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactLongTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -26,6 +26,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox * @build IncrementExactLongTest * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactIntTest.java --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactIntTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactIntTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -26,6 +26,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox * @build MultiplyExactIntTest * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactLongTest.java --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactLongTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactLongTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -26,6 +26,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox * @build MultiplyExactLongTest * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactIntTest.java --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactIntTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactIntTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -26,6 +26,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox * @build NegateExactIntTest * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactLongTest.java --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactLongTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactLongTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -26,6 +26,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox * @build NegateExactLongTest * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactIntTest.java --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactIntTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactIntTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -26,6 +26,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox * @build SubtractExactIntTest * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactLongTest.java --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactLongTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactLongTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -26,6 +26,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox * @build SubtractExactLongTest * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation * -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/macronodes/TestEliminateAllocationPhi.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/macronodes/TestEliminateAllocationPhi.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8046698 + * @summary PhiNode inserted between AllocateNode and Initialization node confuses allocation elimination + * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestEliminateAllocationPhi + * + */ + +public class TestEliminateAllocationPhi { + + // This will return I when called from m(0 and once optimized will + // go away but this will confuse escape analysis in m(): it will + // find I as non escaping but non scalar replaceable. In its own + // method so that we can make the profile of the if() branch look + // like it's taken sometimes. + static Integer m2(Integer I, int i) { + for (; i < 10; i=(i+2)*(i+2)) { + } + if (i == 121) { + return II; + } + return I; + } + + static Integer II = new Integer(42); + + static int m(int[] integers, boolean flag) { + int j = 0; + while(true) { + try { + int k = integers[j++]; + // A branch that will cause loop unswitching + if (flag) { + k += 42; + } + if (k < 1000) { + throw new Exception(); + } + // Because of the try/catch the Allocate node for this + // new will be in the loop while the Initialization + // node will be outside the loop. When loop + // unswitching happens, the Allocate node will be + // cloned and the results of both will be inputs to a + // Phi that will be between the Allocate nodes and the + // Initialization nodes. + Integer I = new Integer(k); + + I = m2(I, 0); + + int i = I.intValue(); + return i; + } catch(Exception e) { + } + } + } + + static public void main(String[] args) { + for (int i = 0; i < 5000; i++) { + m2(null, 1); + } + + int[] integers = { 2000 }; + for (int i = 0; i < 6000; i++) { + m(integers, (i%2) == 0); + } + int[] integers2 = { 1, 2, 3, 4, 5, 2000 }; + for (int i = 0; i < 10000; i++) { + m(integers2, (i%2) == 0); + } + } +} diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/osr/TestOSRWithNonEmptyStack.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/osr/TestOSRWithNonEmptyStack.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; + +import jdk.internal.org.objectweb.asm.ClassWriter; +import jdk.internal.org.objectweb.asm.Label; +import jdk.internal.org.objectweb.asm.MethodVisitor; +import static jdk.internal.org.objectweb.asm.Opcodes.*; + +/** + * @test + * @bug 8051344 + * @summary Force OSR compilation with non-empty stack at the OSR entry point. + * @compile -XDignore.symbol.file TestOSRWithNonEmptyStack.java + * @run main/othervm -XX:CompileOnly=TestCase.test TestOSRWithNonEmptyStack + */ +public class TestOSRWithNonEmptyStack extends ClassLoader { + private static final int CLASS_FILE_VERSION = 52; + private static final String CLASS_NAME = "TestCase"; + private static final String METHOD_NAME = "test"; + private static final int ITERATIONS = 1_000_000; + + private static byte[] generateTestClass() { + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); + + cw.visit(TestOSRWithNonEmptyStack.CLASS_FILE_VERSION, ACC_PUBLIC, + TestOSRWithNonEmptyStack.CLASS_NAME, null, "java/lang/Object", + null); + + TestOSRWithNonEmptyStack.generateConstructor(cw); + TestOSRWithNonEmptyStack.generateTestMethod(cw); + + cw.visitEnd(); + return cw.toByteArray(); + } + + private static void generateConstructor(ClassWriter classWriter) { + MethodVisitor mv = classWriter.visitMethod(ACC_PUBLIC, "", "()V", + null, null); + + mv.visitCode(); + + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", + false); + mv.visitInsn(RETURN); + + mv.visitMaxs(0, 0); + mv.visitEnd(); + } + + private static void generateTestMethod(ClassWriter classWriter) { + MethodVisitor mv = classWriter.visitMethod(ACC_PUBLIC, + TestOSRWithNonEmptyStack.METHOD_NAME, "()V", null, null); + Label osrEntryPoint = new Label(); + + mv.visitCode(); + // Push 'this' into stack before OSR entry point to bail out compilation + mv.visitVarInsn(ALOAD, 0); + // Setup loop counter + mv.visitInsn(ICONST_0); + mv.visitVarInsn(ISTORE, 1); + // Begin loop + mv.visitLabel(osrEntryPoint); + // Increment loop counter + mv.visitVarInsn(ILOAD, 1); + mv.visitInsn(ICONST_1); + mv.visitInsn(IADD); + // Duplicate it for loop condition check + mv.visitInsn(DUP); + mv.visitVarInsn(ISTORE, 1); + // Check loop condition + mv.visitLdcInsn(TestOSRWithNonEmptyStack.ITERATIONS); + mv.visitJumpInsn(IF_ICMPLT, osrEntryPoint); + // Pop 'this'. + mv.visitInsn(POP); + mv.visitInsn(RETURN); + + mv.visitMaxs(0, 0); + mv.visitEnd(); + } + + private void run() { + byte[] bytecode = TestOSRWithNonEmptyStack.generateTestClass(); + + try { + Class klass = defineClass(TestOSRWithNonEmptyStack.CLASS_NAME, + bytecode, 0, bytecode.length); + + Constructor ctor = klass.getConstructor(); + Method method = klass.getDeclaredMethod( + TestOSRWithNonEmptyStack.METHOD_NAME); + + Object testCase = ctor.newInstance(); + method.invoke(testCase); + } catch (Exception e) { + throw new RuntimeException( + "Test bug: generated class should be valid.", e); + } + } + + public static void main(String args[]) { + new TestOSRWithNonEmptyStack().run(); + } +} diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig.java --- a/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary * @build TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI * TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig.java --- a/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary * @build TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI * TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/rtm/cli/TestRTMAbortRatioOptionOnSupportedConfig.java --- a/hotspot/test/compiler/rtm/cli/TestRTMAbortRatioOptionOnSupportedConfig.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/rtm/cli/TestRTMAbortRatioOptionOnSupportedConfig.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary * @build TestRTMAbortRatioOptionOnSupportedConfig * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestRTMAbortRatioOptionOnSupportedConfig */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/rtm/cli/TestRTMAbortRatioOptionOnUnsupportedConfig.java --- a/hotspot/test/compiler/rtm/cli/TestRTMAbortRatioOptionOnUnsupportedConfig.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/rtm/cli/TestRTMAbortRatioOptionOnUnsupportedConfig.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary * @build TestRTMAbortRatioOptionOnUnsupportedConfig * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestRTMAbortRatioOptionOnUnsupportedConfig */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnSupportedConfig.java --- a/hotspot/test/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnSupportedConfig.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnSupportedConfig.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary * @build TestRTMTotalCountIncrRateOptionOnSupportedConfig * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI * TestRTMTotalCountIncrRateOptionOnSupportedConfig diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnUnsupportedConfig.java --- a/hotspot/test/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnUnsupportedConfig.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnUnsupportedConfig.java Fri Aug 29 11:58:43 2014 -0700 @@ -35,6 +35,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary * @build TestRTMTotalCountIncrRateOptionOnUnsupportedConfig * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI * TestRTMTotalCountIncrRateOptionOnUnsupportedConfig diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnSupportedConfig.java --- a/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnSupportedConfig.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnSupportedConfig.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary * @build TestUseRTMDeoptOptionOnSupportedConfig * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestUseRTMDeoptOptionOnSupportedConfig */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnUnsupportedConfig.java --- a/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnUnsupportedConfig.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnUnsupportedConfig.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary * @build TestUseRTMDeoptOptionOnUnsupportedConfig * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestUseRTMDeoptOptionOnUnsupportedConfig */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnSupportedConfig.java --- a/hotspot/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnSupportedConfig.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnSupportedConfig.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary * @build TestUseRTMForStackLocksOptionOnSupportedConfig * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI * TestUseRTMForStackLocksOptionOnSupportedConfig diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnUnsupportedConfig.java --- a/hotspot/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnUnsupportedConfig.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnUnsupportedConfig.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary * @build TestUseRTMForStackLocksOptionOnUnsupportedConfig * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI * TestUseRTMForStackLocksOptionOnUnsupportedConfig diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnSupportedConfig.java --- a/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnSupportedConfig.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnSupportedConfig.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary * @build TestUseRTMLockingOptionOnSupportedConfig * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestUseRTMLockingOptionOnSupportedConfig */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedCPU.java --- a/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedCPU.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedCPU.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary * @build TestUseRTMLockingOptionOnUnsupportedCPU * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestUseRTMLockingOptionOnUnsupportedCPU */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedVM.java --- a/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedVM.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedVM.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary * @build TestUseRTMLockingOptionOnUnsupportedVM * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestUseRTMLockingOptionOnUnsupportedVM */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionWithBiasedLocking.java --- a/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionWithBiasedLocking.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionWithBiasedLocking.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary * @build TestUseRTMLockingOptionWithBiasedLocking * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestUseRTMLockingOptionWithBiasedLocking */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/rtm/locking/TestRTMAbortRatio.java --- a/hotspot/test/compiler/rtm/locking/TestRTMAbortRatio.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/rtm/locking/TestRTMAbortRatio.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary * @build TestRTMAbortRatio * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestRTMAbortRatio */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/rtm/locking/TestRTMAbortThreshold.java --- a/hotspot/test/compiler/rtm/locking/TestRTMAbortThreshold.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/rtm/locking/TestRTMAbortThreshold.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary * @build TestRTMAbortThreshold * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestRTMAbortThreshold */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java --- a/hotspot/test/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java Fri Aug 29 11:58:43 2014 -0700 @@ -32,6 +32,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary * @build TestRTMAfterNonRTMDeopt * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestRTMAfterNonRTMDeopt */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/rtm/locking/TestRTMDeoptOnHighAbortRatio.java --- a/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnHighAbortRatio.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnHighAbortRatio.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary * @build TestRTMDeoptOnHighAbortRatio * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestRTMDeoptOnHighAbortRatio */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java --- a/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java Fri Aug 29 11:58:43 2014 -0700 @@ -29,6 +29,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary * @build TestRTMDeoptOnLowAbortRatio * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestRTMDeoptOnLowAbortRatio */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/rtm/locking/TestRTMLockingCalculationDelay.java --- a/hotspot/test/compiler/rtm/locking/TestRTMLockingCalculationDelay.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/rtm/locking/TestRTMLockingCalculationDelay.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary * @build TestRTMLockingCalculationDelay * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestRTMLockingCalculationDelay */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/rtm/locking/TestRTMLockingThreshold.java --- a/hotspot/test/compiler/rtm/locking/TestRTMLockingThreshold.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/rtm/locking/TestRTMLockingThreshold.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary * @build TestRTMLockingThreshold * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestRTMLockingThreshold */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/rtm/locking/TestRTMRetryCount.java --- a/hotspot/test/compiler/rtm/locking/TestRTMRetryCount.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/rtm/locking/TestRTMRetryCount.java Fri Aug 29 11:58:43 2014 -0700 @@ -29,6 +29,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary * @build TestRTMRetryCount * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestRTMRetryCount */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/rtm/locking/TestRTMSpinLoopCount.java --- a/hotspot/test/compiler/rtm/locking/TestRTMSpinLoopCount.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/rtm/locking/TestRTMSpinLoopCount.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary * @build TestRTMSpinLoopCount * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestRTMSpinLoopCount */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java --- a/hotspot/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary * @build TestRTMTotalCountIncrRate * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestRTMTotalCountIncrRate */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/rtm/locking/TestUseRTMAfterLockInflation.java --- a/hotspot/test/compiler/rtm/locking/TestUseRTMAfterLockInflation.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/rtm/locking/TestUseRTMAfterLockInflation.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary * @build TestUseRTMAfterLockInflation * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestUseRTMAfterLockInflation */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/rtm/locking/TestUseRTMDeopt.java --- a/hotspot/test/compiler/rtm/locking/TestUseRTMDeopt.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/rtm/locking/TestUseRTMDeopt.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary * @build TestUseRTMDeopt * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestUseRTMDeopt */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/rtm/locking/TestUseRTMForInflatedLocks.java --- a/hotspot/test/compiler/rtm/locking/TestUseRTMForInflatedLocks.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/rtm/locking/TestUseRTMForInflatedLocks.java Fri Aug 29 11:58:43 2014 -0700 @@ -29,6 +29,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary * @build TestUseRTMForInflatedLocks * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestUseRTMForInflatedLocks */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/rtm/locking/TestUseRTMForStackLocks.java --- a/hotspot/test/compiler/rtm/locking/TestUseRTMForStackLocks.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/rtm/locking/TestUseRTMForStackLocks.java Fri Aug 29 11:58:43 2014 -0700 @@ -29,6 +29,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary * @build TestUseRTMForStackLocks * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestUseRTMForStackLocks */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/rtm/locking/TestUseRTMXendForLockBusy.java --- a/hotspot/test/compiler/rtm/locking/TestUseRTMXendForLockBusy.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/rtm/locking/TestUseRTMXendForLockBusy.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary * @build TestUseRTMXendForLockBusy * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestUseRTMXendForLockBusy */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/rtm/method_options/TestNoRTMLockElidingOption.java --- a/hotspot/test/compiler/rtm/method_options/TestNoRTMLockElidingOption.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/rtm/method_options/TestNoRTMLockElidingOption.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary * @build TestNoRTMLockElidingOption * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestNoRTMLockElidingOption */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/rtm/method_options/TestUseRTMLockElidingOption.java --- a/hotspot/test/compiler/rtm/method_options/TestUseRTMLockElidingOption.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/rtm/method_options/TestUseRTMLockElidingOption.java Fri Aug 29 11:58:43 2014 -0700 @@ -31,6 +31,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary * @build TestUseRTMLockElidingOption * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestUseRTMLockElidingOption */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java --- a/hotspot/test/compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java Fri Aug 29 11:58:43 2014 -0700 @@ -32,6 +32,7 @@ * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary * @build TestPrintPreciseRTMLockingStatistics * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI TestPrintPreciseRTMLockingStatistics */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/tiered/NonTieredLevelsTest.java --- a/hotspot/test/compiler/tiered/NonTieredLevelsTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/tiered/NonTieredLevelsTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -29,6 +29,7 @@ * @ignore 8046268 * @build NonTieredLevelsTest * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:-TieredCompilation * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:CompileCommand=compileonly,SimpleTestCase$Helper::* diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/tiered/TieredLevelsTest.java --- a/hotspot/test/compiler/tiered/TieredLevelsTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/tiered/TieredLevelsTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -27,6 +27,7 @@ * @ignore 8046268 * @build TieredLevelsTest * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+TieredCompilation * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:CompileCommand=compileonly,SimpleTestCase$Helper::* diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/types/correctness/CorrectnessTest.java --- a/hotspot/test/compiler/types/correctness/CorrectnessTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/types/correctness/CorrectnessTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -29,6 +29,7 @@ * execution/MethodHandleDelegate.java * @build CorrectnessTest * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:TypeProfileLevel=222 -XX:+UseTypeSpeculation diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/types/correctness/OffTest.java --- a/hotspot/test/compiler/types/correctness/OffTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/types/correctness/OffTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @build CorrectnessTest * @build OffTest * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/timeout=1200 OffTest */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/whitebox/ClearMethodStateTest.java --- a/hotspot/test/compiler/whitebox/ClearMethodStateTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/whitebox/ClearMethodStateTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,6 +30,7 @@ * @ignore 8046268 * @build ClearMethodStateTest * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,SimpleTestCase$Helper::* ClearMethodStateTest * @summary testing of WB::clearMethodState() * @author igor.ignatyev@oracle.com diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/whitebox/DeoptimizeAllTest.java --- a/hotspot/test/compiler/whitebox/DeoptimizeAllTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/whitebox/DeoptimizeAllTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -28,6 +28,7 @@ * @ignore 8046268 * @build DeoptimizeAllTest * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,SimpleTestCase$Helper::* DeoptimizeAllTest * @summary testing of WB::deoptimizeAll() * @author igor.ignatyev@oracle.com diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/whitebox/DeoptimizeMethodTest.java --- a/hotspot/test/compiler/whitebox/DeoptimizeMethodTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/whitebox/DeoptimizeMethodTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -28,6 +28,7 @@ * @ignore 8046268 * @build DeoptimizeMethodTest * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,SimpleTestCase$Helper::* DeoptimizeMethodTest * @summary testing of WB::deoptimizeMethod() * @author igor.ignatyev@oracle.com diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/whitebox/EnqueueMethodForCompilationTest.java --- a/hotspot/test/compiler/whitebox/EnqueueMethodForCompilationTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/whitebox/EnqueueMethodForCompilationTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -28,6 +28,7 @@ * @ignore 8046268 * @build EnqueueMethodForCompilationTest * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm/timeout=600 -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,SimpleTestCase$Helper::* EnqueueMethodForCompilationTest * @summary testing of WB::enqueueMethodForCompilation() * @author igor.ignatyev@oracle.com diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/whitebox/GetNMethodTest.java --- a/hotspot/test/compiler/whitebox/GetNMethodTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/whitebox/GetNMethodTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -31,6 +31,7 @@ * @ignore 8046268 * @build GetNMethodTest * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,SimpleTestCase$Helper::* GetNMethodTest * @summary testing of WB::getNMethod() * @author igor.ignatyev@oracle.com diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/whitebox/IsMethodCompilableTest.java --- a/hotspot/test/compiler/whitebox/IsMethodCompilableTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/whitebox/IsMethodCompilableTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -27,6 +27,7 @@ * @library /testlibrary /testlibrary/whitebox /testlibrary/com/oracle/java/testlibrary * @build IsMethodCompilableTest * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main ClassFileInstaller com.oracle.java.testlibrary.Platform * @run main/othervm/timeout=2400 -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:PerMethodRecompilationCutoff=3 -XX:CompileCommand=compileonly,SimpleTestCase$Helper::* IsMethodCompilableTest * @summary testing of WB::isMethodCompilable() diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/whitebox/MakeMethodNotCompilableTest.java --- a/hotspot/test/compiler/whitebox/MakeMethodNotCompilableTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/whitebox/MakeMethodNotCompilableTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -28,6 +28,7 @@ * @ignore 8046268 * @build MakeMethodNotCompilableTest * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm/timeout=2400 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,SimpleTestCase$Helper::* MakeMethodNotCompilableTest * @summary testing of WB::makeMethodNotCompilable() * @author igor.ignatyev@oracle.com diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/whitebox/SetDontInlineMethodTest.java --- a/hotspot/test/compiler/whitebox/SetDontInlineMethodTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/whitebox/SetDontInlineMethodTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -27,6 +27,7 @@ * @library /testlibrary /testlibrary/whitebox * @build SetDontInlineMethodTest * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,SimpleTestCase$Helper::* SetDontInlineMethodTest * @summary testing of WB::testSetDontInlineMethod() * @author igor.ignatyev@oracle.com diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/compiler/whitebox/SetForceInlineMethodTest.java --- a/hotspot/test/compiler/whitebox/SetForceInlineMethodTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/compiler/whitebox/SetForceInlineMethodTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -27,6 +27,7 @@ * @library /testlibrary /testlibrary/whitebox * @build SetForceInlineMethodTest * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,SimpleTestCase$Helper::* SetForceInlineMethodTest * @summary testing of WB::testSetForceInlineMethod() * @author igor.ignatyev@oracle.com diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/gc/arguments/TestArrayAllocatorMallocLimit.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/gc/arguments/TestArrayAllocatorMallocLimit.java Fri Aug 29 11:58:43 2014 -0700 @@ -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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test TestArrayAllocatorMallocLimit + * @summary Sanity check that the ArrayAllocatorMallocLimit flag can be set. + * The test helps verifying that size_t flags can be set/read. + * @bug 8054823 + * @key gc + * @library /testlibrary + * @run driver TestArrayAllocatorMallocLimit + */ + +import com.oracle.java.testlibrary.Asserts; +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; +import java.math.BigInteger; + +public class TestArrayAllocatorMallocLimit { + public static void main(String [] args) throws Exception { + testDefaultValue(); + testSetValue(); + } + + private static final String flagName = "ArrayAllocatorMallocLimit"; + + // size_t ArrayAllocatorMallocLimit = 18446744073709551615{experimental} + private static final String printFlagsFinalPattern = " *size_t *" + flagName + " *:?= *(\\d+) *\\{experimental\\} *"; + + public static void testDefaultValue() throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UnlockExperimentalVMOptions", "-XX:+PrintFlagsFinal", "-version"); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + String value = output.firstMatch(printFlagsFinalPattern, 1); + + try { + Asserts.assertNotNull(value, "Couldn't find size_t flag " + flagName); + + // A size_t is not always parseable with Long.parseValue, + // use BigInteger instead. + BigInteger biValue = new BigInteger(value); + + // Sanity check that we got a non-zero value. + Asserts.assertNotEquals(biValue, "0"); + + output.shouldHaveExitValue(0); + } catch (Exception e) { + System.err.println(output.getOutput()); + throw e; + } + } + + public static void testSetValue() throws Exception { + long flagValue = 2048; + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UnlockExperimentalVMOptions", "-XX:" + flagName + "=" + flagValue, "-XX:+PrintFlagsFinal", "-version"); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + String value = output.firstMatch(printFlagsFinalPattern, 1); + + try { + Asserts.assertNotNull("Couldn't find size_t flag " + flagName); + + long longValue = Long.parseLong(value); + + Asserts.assertEquals(longValue, flagValue); + + output.shouldHaveExitValue(0); + } catch (Exception e) { + System.err.println(output.getOutput()); + throw e; + } + } + +} diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/gc/arguments/TestCMSHeapSizeFlags.java --- a/hotspot/test/gc/arguments/TestCMSHeapSizeFlags.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/gc/arguments/TestCMSHeapSizeFlags.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2013, 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 @@ -29,6 +29,7 @@ * @library /testlibrary /testlibrary/whitebox * @build TestCMSHeapSizeFlags TestMaxHeapSizeTools * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm TestCMSHeapSizeFlags * @author thomas.schatzl@oracle.com */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/gc/arguments/TestG1HeapSizeFlags.java --- a/hotspot/test/gc/arguments/TestG1HeapSizeFlags.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/gc/arguments/TestG1HeapSizeFlags.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2013, 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 @@ -29,6 +29,7 @@ * @library /testlibrary /testlibrary/whitebox * @build TestG1HeapSizeFlags TestMaxHeapSizeTools * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm TestG1HeapSizeFlags * @author thomas.schatzl@oracle.com */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/gc/arguments/TestMinInitialErgonomics.java --- a/hotspot/test/gc/arguments/TestMinInitialErgonomics.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/gc/arguments/TestMinInitialErgonomics.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2013, 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 @@ -29,6 +29,7 @@ * @library /testlibrary /testlibrary/whitebox * @build TestMinInitialErgonomics TestMaxHeapSizeTools * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm TestMinInitialErgonomics * @author thomas.schatzl@oracle.com */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/gc/arguments/TestParallelHeapSizeFlags.java --- a/hotspot/test/gc/arguments/TestParallelHeapSizeFlags.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/gc/arguments/TestParallelHeapSizeFlags.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2013, 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 @@ -31,6 +31,7 @@ * @library /testlibrary /testlibrary/whitebox * @build TestParallelHeapSizeFlags TestMaxHeapSizeTools * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm TestParallelHeapSizeFlags * @author thomas.schatzl@oracle.com */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/gc/arguments/TestSerialHeapSizeFlags.java --- a/hotspot/test/gc/arguments/TestSerialHeapSizeFlags.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/gc/arguments/TestSerialHeapSizeFlags.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2013, 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 @@ -29,6 +29,7 @@ * @library /testlibrary /testlibrary/whitebox * @build TestSerialHeapSizeFlags TestMaxHeapSizeTools * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm TestSerialHeapSizeFlags * @author thomas.schatzl@oracle.com */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/gc/arguments/TestUseCompressedOopsErgo.java --- a/hotspot/test/gc/arguments/TestUseCompressedOopsErgo.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/gc/arguments/TestUseCompressedOopsErgo.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2013, 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 @@ -30,6 +30,7 @@ * @library /testlibrary /testlibrary/whitebox * @build TestUseCompressedOopsErgo TestUseCompressedOopsErgoTools * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm TestUseCompressedOopsErgo -XX:+UseG1GC * @run main/othervm TestUseCompressedOopsErgo -XX:+UseParallelGC * @run main/othervm TestUseCompressedOopsErgo -XX:+UseParallelGC -XX:-UseParallelOldGC diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/gc/class_unloading/AllocateBeyondMetaspaceSize.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/gc/class_unloading/AllocateBeyondMetaspaceSize.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import sun.hotspot.WhiteBox; + +class AllocateBeyondMetaspaceSize { + public static Object dummy; + + public static void main(String [] args) { + if (args.length != 2) { + throw new IllegalArgumentException("Usage: "); + } + + long metaspaceSize = Long.parseLong(args[0]); + long youngGenSize = Long.parseLong(args[1]); + + run(metaspaceSize, youngGenSize); + } + + private static void run(long metaspaceSize, long youngGenSize) { + WhiteBox wb = WhiteBox.getWhiteBox(); + + long allocationBeyondMetaspaceSize = metaspaceSize * 2; + long metaspace = wb.allocateMetaspace(null, allocationBeyondMetaspaceSize); + + triggerYoungGC(youngGenSize); + + wb.freeMetaspace(null, metaspace, metaspace); + } + + private static void triggerYoungGC(long youngGenSize) { + long approxAllocSize = 32 * 1024; + long numAllocations = 2 * youngGenSize / approxAllocSize; + + for (long i = 0; i < numAllocations; i++) { + dummy = new byte[(int)approxAllocSize]; + } + } +} diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/gc/class_unloading/TestCMSClassUnloadingEnabledHWM.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/gc/class_unloading/TestCMSClassUnloadingEnabledHWM.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @key gc + * @bug 8049831 + * @library /testlibrary /testlibrary/whitebox + * @build TestCMSClassUnloadingEnabledHWM AllocateBeyondMetaspaceSize + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run driver TestCMSClassUnloadingEnabledHWM + * @summary Test that -XX:-CMSClassUnloadingEnabled will trigger a Full GC when more than MetaspaceSize metadata is allocated. + */ + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; + +import java.util.ArrayList; +import java.util.Arrays; + +public class TestCMSClassUnloadingEnabledHWM { + private static long MetaspaceSize = 32 * 1024 * 1024; + private static long YoungGenSize = 32 * 1024 * 1024; + + private static OutputAnalyzer run(boolean enableUnloading) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-Xbootclasspath/a:.", + "-XX:+WhiteBoxAPI", + "-XX:MetaspaceSize=" + MetaspaceSize, + "-Xmn" + YoungGenSize, + "-XX:+UseConcMarkSweepGC", + "-XX:" + (enableUnloading ? "+" : "-") + "CMSClassUnloadingEnabled", + "-XX:+PrintHeapAtGC", + "-XX:+PrintGCDetails", + "AllocateBeyondMetaspaceSize", + "" + MetaspaceSize, + "" + YoungGenSize); + return new OutputAnalyzer(pb.start()); + } + + public static OutputAnalyzer runWithCMSClassUnloading() throws Exception { + return run(true); + } + + public static OutputAnalyzer runWithoutCMSClassUnloading() throws Exception { + return run(false); + } + + public static void testWithoutCMSClassUnloading() throws Exception { + // -XX:-CMSClassUnloadingEnabled is used, so we expect a full GC instead of a concurrent cycle. + OutputAnalyzer out = runWithoutCMSClassUnloading(); + + out.shouldMatch(".*Full GC.*"); + out.shouldNotMatch(".*CMS Initial Mark.*"); + } + + public static void testWithCMSClassUnloading() throws Exception { + // -XX:+CMSClassUnloadingEnabled is used, so we expect a concurrent cycle instead of a full GC. + OutputAnalyzer out = runWithCMSClassUnloading(); + + out.shouldMatch(".*CMS Initial Mark.*"); + out.shouldNotMatch(".*Full GC.*"); + } + + public static void main(String args[]) throws Exception { + testWithCMSClassUnloading(); + testWithoutCMSClassUnloading(); + } +} + diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/gc/class_unloading/TestG1ClassUnloadingHWM.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/gc/class_unloading/TestG1ClassUnloadingHWM.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @key gc + * @bug 8049831 + * @library /testlibrary /testlibrary/whitebox + * @build TestG1ClassUnloadingHWM AllocateBeyondMetaspaceSize + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run driver TestG1ClassUnloadingHWM + * @summary Test that -XX:-ClassUnloadingWithConcurrentMark will trigger a Full GC when more than MetaspaceSize metadata is allocated. + */ + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; + +import java.util.ArrayList; +import java.util.Arrays; + +public class TestG1ClassUnloadingHWM { + private static long MetaspaceSize = 32 * 1024 * 1024; + private static long YoungGenSize = 32 * 1024 * 1024; + + private static OutputAnalyzer run(boolean enableUnloading) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-Xbootclasspath/a:.", + "-XX:+WhiteBoxAPI", + "-XX:MetaspaceSize=" + MetaspaceSize, + "-Xmn" + YoungGenSize, + "-XX:+UseG1GC", + "-XX:" + (enableUnloading ? "+" : "-") + "ClassUnloadingWithConcurrentMark", + "-XX:+PrintHeapAtGC", + "-XX:+PrintGCDetails", + "AllocateBeyondMetaspaceSize", + "" + MetaspaceSize, + "" + YoungGenSize); + return new OutputAnalyzer(pb.start()); + } + + public static OutputAnalyzer runWithG1ClassUnloading() throws Exception { + return run(true); + } + + public static OutputAnalyzer runWithoutG1ClassUnloading() throws Exception { + return run(false); + } + + public static void testWithoutG1ClassUnloading() throws Exception { + // -XX:-ClassUnloadingWithConcurrentMark is used, so we expect a full GC instead of a concurrent cycle. + OutputAnalyzer out = runWithoutG1ClassUnloading(); + + out.shouldMatch(".*Full GC.*"); + out.shouldNotMatch(".*initial-mark.*"); + } + + public static void testWithG1ClassUnloading() throws Exception { + // -XX:+ClassUnloadingWithConcurrentMark is used, so we expect a concurrent cycle instead of a full GC. + OutputAnalyzer out = runWithG1ClassUnloading(); + + out.shouldMatch(".*initial-mark.*"); + out.shouldNotMatch(".*Full GC.*"); + } + + public static void main(String args[]) throws Exception { + testWithG1ClassUnloading(); + testWithoutG1ClassUnloading(); + } +} + diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/gc/g1/TestDeferredRSUpdate.java --- a/hotspot/test/gc/g1/TestDeferredRSUpdate.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/gc/g1/TestDeferredRSUpdate.java Fri Aug 29 11:58:43 2014 -0700 @@ -23,7 +23,7 @@ /* * @test TestDeferredRSUpdate - * @bug 8040977 + * @bug 8040977 8052170 * @summary Ensure that running with -XX:-G1DeferredRSUpdate does not crash the VM * @key gc * @library /testlibrary @@ -38,6 +38,7 @@ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", "-Xmx10M", + "-XX:+PrintGCDetails", // G1DeferredRSUpdate is a develop option, but we cannot limit execution of this test to only debug VMs. "-XX:+IgnoreUnrecognizedVMOptions", "-XX:-G1DeferredRSUpdate", diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/gc/g1/TestEagerReclaimHumongousRegions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/gc/g1/TestEagerReclaimHumongousRegions.java Fri Aug 29 11:58:43 2014 -0700 @@ -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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test TestEagerReclaimHumongousRegions + * @bug 8027959 + * @summary Test to make sure that eager reclaim of humongous objects work. We simply try to fill + * up the heap with humongous objects that should be eagerly reclaimable to avoid Full GC. + * @key gc + * @library /testlibrary + */ + +import java.util.regex.Pattern; +import java.util.regex.Matcher; +import java.util.LinkedList; + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; +import com.oracle.java.testlibrary.Asserts; + +class ReclaimRegionFast { + public static final int M = 1024*1024; + + public static LinkedList garbageList = new LinkedList(); + + public static void genGarbage() { + for (int i = 0; i < 32*1024; i++) { + garbageList.add(new int[100]); + } + garbageList.clear(); + } + + // A large object referenced by a static. + static int[] filler = new int[10 * M]; + + public static void main(String[] args) { + + int[] large = new int[M]; + + Object ref_from_stack = large; + + for (int i = 0; i < 100; i++) { + // A large object that will be reclaimed eagerly. + large = new int[6*M]; + genGarbage(); + // Make sure that the compiler cannot completely remove + // the allocation of the large object until here. + System.out.println(large); + } + + // Keep the reference to the first object alive. + System.out.println(ref_from_stack); + } +} + +public class TestEagerReclaimHumongousRegions { + public static void main(String[] args) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UseG1GC", + "-Xms128M", + "-Xmx128M", + "-Xmn16M", + "-XX:+PrintGC", + ReclaimRegionFast.class.getName()); + + Pattern p = Pattern.compile("Full GC"); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + int found = 0; + Matcher m = p.matcher(output.getStdout()); + while (m.find()) { found++; } + System.out.println("Issued " + found + " Full GCs"); + Asserts.assertLT(found, 10, "Found that " + found + " Full GCs were issued. This is larger than the bound. Eager reclaim seems to not work at all"); + + output.shouldHaveExitValue(0); + } +} diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/gc/g1/TestEagerReclaimHumongousRegions2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/gc/g1/TestEagerReclaimHumongousRegions2.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test TestEagerReclaimHumongousRegions2 + * @bug 8051973 + * @summary Test to make sure that eager reclaim of humongous objects correctly clears + * mark bitmaps at reclaim. + * @key gc + * @library /testlibrary + */ + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.Random; + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; + +// An object that has a few references to other instances to slow down marking. +class ObjectWithSomeRefs { + public ObjectWithSomeRefs other1; + public ObjectWithSomeRefs other2; + public ObjectWithSomeRefs other3; + public ObjectWithSomeRefs other4; +} + +class ReclaimRegionFast { + public static final int M = 1024*1024; + + public static LinkedList garbageList = new LinkedList(); + + public static void genGarbage(Object large) { + for (int i = 0; i < 64*1024; i++) { + Object[] garbage = new Object[50]; + garbage[0] = large; + garbageList.add(garbage); + } + garbageList.clear(); + } + + public static ArrayList longList = new ArrayList(); + + public static void main(String[] args) { + + for (int i = 0; i < 16*1024; i++) { + longList.add(new ObjectWithSomeRefs()); + } + + Random rnd = new Random(); + for (int i = 0; i < longList.size(); i++) { + int len = longList.size(); + longList.get(i).other1 = longList.get(rnd.nextInt(len)); + longList.get(i).other2 = longList.get(rnd.nextInt(len)); + longList.get(i).other3 = longList.get(rnd.nextInt(len)); + longList.get(i).other4 = longList.get(rnd.nextInt(len)); + } + + int[] large1 = new int[M]; + int[] large2 = null; + int[] large3 = null; + int[] large4 = null; + + Object ref_from_stack = large1; + + for (int i = 0; i < 20; i++) { + // A set of large objects that will be reclaimed eagerly - and hopefully marked. + large1 = new int[M - 20]; + large2 = new int[M - 20]; + large3 = new int[M - 20]; + large4 = new int[M - 20]; + genGarbage(large1); + // Make sure that the compiler cannot completely remove + // the allocation of the large object until here. + System.out.println(large1 + " " + large2 + " " + large3 + " " + large4); + } + + // Keep the reference to the first object alive. + System.out.println(ref_from_stack); + } +} + +public class TestEagerReclaimHumongousRegions2 { + public static void main(String[] args) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UseG1GC", + "-Xms128M", + "-Xmx128M", + "-Xmn2M", + "-XX:G1HeapRegionSize=1M", + "-XX:InitiatingHeapOccupancyPercent=0", // Want to have as much as possible initial marks. + "-XX:+PrintGC", + "-XX:+VerifyAfterGC", + "-XX:ConcGCThreads=1", // Want to make marking as slow as possible. + "-XX:+IgnoreUnrecognizedVMOptions", // G1VerifyBitmaps is develop only. + "-XX:+G1VerifyBitmaps", + ReclaimRegionFast.class.getName()); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldHaveExitValue(0); + } +} + diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/gc/g1/TestGCLogMessages.java --- a/hotspot/test/gc/g1/TestGCLogMessages.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/gc/g1/TestGCLogMessages.java Fri Aug 29 11:58:43 2014 -0700 @@ -23,7 +23,7 @@ /* * @test TestGCLogMessages - * @bug 8035406 8027295 8035398 8019342 + * @bug 8035406 8027295 8035398 8019342 8027959 * @summary Ensure that the PrintGCDetails output for a minor GC with G1 * includes the expected necessary messages. * @key gc @@ -54,6 +54,7 @@ output.shouldNotContain("[String Dedup Fixup"); output.shouldNotContain("[Young Free CSet"); output.shouldNotContain("[Non-Young Free CSet"); + output.shouldNotContain("[Humongous Reclaim"); output.shouldHaveExitValue(0); pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", @@ -71,6 +72,10 @@ output.shouldContain("[String Dedup Fixup"); output.shouldNotContain("[Young Free CSet"); output.shouldNotContain("[Non-Young Free CSet"); + output.shouldContain("[Humongous Reclaim"); + output.shouldNotContain("[Humongous Total"); + output.shouldNotContain("[Humongous Candidate"); + output.shouldNotContain("[Humongous Reclaimed"); output.shouldHaveExitValue(0); pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", @@ -90,6 +95,10 @@ output.shouldContain("[String Dedup Fixup"); output.shouldContain("[Young Free CSet"); output.shouldContain("[Non-Young Free CSet"); + output.shouldContain("[Humongous Reclaim"); + output.shouldContain("[Humongous Total"); + output.shouldContain("[Humongous Candidate"); + output.shouldContain("[Humongous Reclaimed"); output.shouldHaveExitValue(0); } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/gc/g1/TestHumongousCodeCacheRoots.java --- a/hotspot/test/gc/g1/TestHumongousCodeCacheRoots.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/gc/g1/TestHumongousCodeCacheRoots.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -29,6 +29,7 @@ * @library /testlibrary /testlibrary/whitebox * @build TestHumongousCodeCacheRoots * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @summary Humongous objects may have references from the code cache * @run main TestHumongousCodeCacheRoots */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/6626217/Test6626217.sh --- a/hotspot/test/runtime/6626217/Test6626217.sh Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/runtime/6626217/Test6626217.sh Fri Aug 29 11:58:43 2014 -0700 @@ -69,7 +69,7 @@ ${MV} many_loader.impl1 many_loader.class ${RM} many_loader.java -${JAVA} ${TESTVMOPTS} -Xverify -Xint -cp . bug_21227 >test.out 2>&1 +${JAVA} ${TESTOPTS} -Xverify -Xint -cp . bug_21227 >test.out 2>&1 grep "loader constraint" test.out exit $? diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/6888954/vmerrors.sh --- a/hotspot/test/runtime/6888954/vmerrors.sh Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/runtime/6888954/vmerrors.sh Fri Aug 29 11:58:43 2014 -0700 @@ -1,4 +1,4 @@ -# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2013, 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 @@ -44,6 +44,16 @@ # export TESTJAVA TESTVMOPTS # sh test/runtime/6888954/vmerrors.sh +if [ "${TESTSRC}" = "" ] +then + TESTSRC=${PWD} + echo "TESTSRC not set. Using "${TESTSRC}" as default" +fi +echo "TESTSRC=${TESTSRC}" + +## Adding common setup Variables for running shell tests. +. ${TESTSRC}/../../test_env.sh + ulimit -c 0 # no core files i=1 @@ -84,7 +94,7 @@ i2=$i [ $i -lt 10 ] && i2=0$i - "$TESTJAVA/bin/java" $TESTVMOPTS -XX:+IgnoreUnrecognizedVMOptions \ + "$TESTJAVA/bin/java" $TESTOPTS -XX:+IgnoreUnrecognizedVMOptions \ -XX:-TransmitErrorReport -XX:-CreateMinidumpOnCrash \ -XX:ErrorHandlerTest=${i} -version > ${i2}.out 2>&1 diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/7107135/Test7107135.sh --- a/hotspot/test/runtime/7107135/Test7107135.sh Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/runtime/7107135/Test7107135.sh Fri Aug 29 11:58:43 2014 -0700 @@ -25,7 +25,6 @@ # ## -## @ignore 8025519 ## @test Test7107135.sh ## @bug 7107135 ## @bug 8021296 diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/7116786/Test7116786.java --- a/hotspot/test/runtime/7116786/Test7116786.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/runtime/7116786/Test7116786.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -147,7 +147,8 @@ "no stackmap frame at jump location or bad jump", "Inconsistent stackmap frames at branch target "), - new Case("case15", "stackMapTable.cpp", true, "check_new_object", + /* Backward jump with uninit is allowed starting with JDK 8 */ + new Case("case15", "stackMapTable.cpp", false, "check_new_object", "backward jump with uninit", "Uninitialized object exists on backward branch "), diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/7162488/Test7162488.sh --- a/hotspot/test/runtime/7162488/Test7162488.sh Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/runtime/7162488/Test7162488.sh Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ # -# Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 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 @@ -45,14 +45,14 @@ # OPTION=this_is_not_an_option -${JAVA} ${TESTVMOPTS} -showversion -XX:${OPTION} 2>&1 | grep "Unrecognized VM option" +${JAVA} -showversion -XX:${OPTION} 2>&1 | grep "Unrecognized VM option" if [ "$?" != "0" ] then printf "FAILED: option not flagged as unrecognized.\n" exit 1 fi -${JAVA} ${TESTVMOPTS} -showversion -XX:${OPTION} 2>&1 | grep ${OPTION} +${JAVA} -showversion -XX:${OPTION} 2>&1 | grep ${OPTION} if [ "$?" != "0" ] then printf "FAILED: bad option not named as being bad.\n" diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/ClassUnload/KeepAliveClass.java --- a/hotspot/test/runtime/ClassUnload/KeepAliveClass.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/runtime/ClassUnload/KeepAliveClass.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -29,6 +29,7 @@ * @build KeepAliveClass test.Empty * @build ClassUnloadCommon * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -Xmn8m -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI KeepAliveClass */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/ClassUnload/KeepAliveClassLoader.java --- a/hotspot/test/runtime/ClassUnload/KeepAliveClassLoader.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/runtime/ClassUnload/KeepAliveClassLoader.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -29,6 +29,7 @@ * @build KeepAliveClassLoader test.Empty * @build ClassUnloadCommon * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -Xmn8m -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI KeepAliveClassLoader */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/ClassUnload/KeepAliveObject.java --- a/hotspot/test/runtime/ClassUnload/KeepAliveObject.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/runtime/ClassUnload/KeepAliveObject.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -29,6 +29,7 @@ * @build KeepAliveObject test.Empty * @build ClassUnloadCommon * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -Xmn8m -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI KeepAliveObject */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/ClassUnload/KeepAliveSoftReference.java --- a/hotspot/test/runtime/ClassUnload/KeepAliveSoftReference.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/runtime/ClassUnload/KeepAliveSoftReference.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -29,6 +29,7 @@ * @build KeepAliveSoftReference test.Empty * @build ClassUnloadCommon * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -Xmn8m -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI KeepAliveSoftReference */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/ClassUnload/UnloadTest.java --- a/hotspot/test/runtime/ClassUnload/UnloadTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/runtime/ClassUnload/UnloadTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -28,6 +28,7 @@ * @build ClassUnloadCommon test.Empty * @build UnloadTest * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -Xmn8m -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI UnloadTest */ import sun.hotspot.WhiteBox; diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/NMT/AutoshutdownNMT.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/NMT/AutoshutdownNMT.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @key nmt + * @summary Test for deprecated message if -XX:-AutoShutdownNMT is specified + * @library /testlibrary + * @ignore + */ + +import com.oracle.java.testlibrary.*; + +public class AutoshutdownNMT { + + public static void main(String args[]) throws Exception { + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:NativeMemoryTracking=detail", + "-XX:-AutoShutdownNMT", + "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("ignoring option AutoShutdownNMT"); + } +} diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/NMT/BaselineWithParameter.java --- a/hotspot/test/runtime/NMT/BaselineWithParameter.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/runtime/NMT/BaselineWithParameter.java Fri Aug 29 11:58:43 2014 -0700 @@ -27,6 +27,7 @@ * @key nmt jcmd regression * @summary Regression test for invoking a jcmd with baseline=false, result was that the target VM crashed * @library /testlibrary + * @ignore * @run main/othervm -XX:NativeMemoryTracking=detail BaselineWithParameter */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/NMT/CommandLineDetail.java --- a/hotspot/test/runtime/NMT/CommandLineDetail.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/runtime/NMT/CommandLineDetail.java Fri Aug 29 11:58:43 2014 -0700 @@ -26,6 +26,7 @@ * @key nmt * @summary Running with NMT detail should not result in an error * @library /testlibrary + * @ignore */ import com.oracle.java.testlibrary.*; diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/NMT/CommandLineEmptyArgument.java --- a/hotspot/test/runtime/NMT/CommandLineEmptyArgument.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/runtime/NMT/CommandLineEmptyArgument.java Fri Aug 29 11:58:43 2014 -0700 @@ -26,6 +26,7 @@ * @key nmt * @summary Empty argument to NMT should result in an informative error message * @library /testlibrary + * @ignore */ import com.oracle.java.testlibrary.*; diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/NMT/CommandLineInvalidArgument.java --- a/hotspot/test/runtime/NMT/CommandLineInvalidArgument.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/runtime/NMT/CommandLineInvalidArgument.java Fri Aug 29 11:58:43 2014 -0700 @@ -26,6 +26,7 @@ * @key nmt * @summary Invalid argument to NMT should result in an informative error message * @library /testlibrary + * @ignore */ import com.oracle.java.testlibrary.*; diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/NMT/CommandLineSummary.java --- a/hotspot/test/runtime/NMT/CommandLineSummary.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/runtime/NMT/CommandLineSummary.java Fri Aug 29 11:58:43 2014 -0700 @@ -26,6 +26,7 @@ * @key nmt * @summary Running with NMT summary should not result in an error * @library /testlibrary + * @ignore */ import com.oracle.java.testlibrary.*; diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/NMT/CommandLineTurnOffNMT.java --- a/hotspot/test/runtime/NMT/CommandLineTurnOffNMT.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/runtime/NMT/CommandLineTurnOffNMT.java Fri Aug 29 11:58:43 2014 -0700 @@ -26,6 +26,7 @@ * @key nmt * @summary Turning off NMT should not result in an error * @library /testlibrary + * @ignore */ import com.oracle.java.testlibrary.*; diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/NMT/JcmdBaselineDetail.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/NMT/JcmdBaselineDetail.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @key nmt jcmd + * @summary Verify that jcmd correctly reports that baseline succeeds with NMT enabled with detailed tracking. + * @library /testlibrary + * @ignore + * @run main/othervm -XX:NativeMemoryTracking=detail JcmdBaselineDetail + */ + +import com.oracle.java.testlibrary.*; + +public class JcmdBaselineDetail { + + public static void main(String args[]) throws Exception { + // Grab my own PID + String pid = Integer.toString(ProcessTools.getProcessId()); + OutputAnalyzer output; + + ProcessBuilder pb = new ProcessBuilder(); + + // Run 'jcmd VM.native_memory baseline=true' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "baseline=true"}); + + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Baseline succeeded"); + } +} diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/NMT/JcmdDetailDiff.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/NMT/JcmdDetailDiff.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary run NMT baseline, allocate memory and verify output from detail.diff + * @key nmt jcmd + * @library /testlibrary /testlibrary/whitebox + * @ignore + * @build JcmdDetailDiff + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail JcmdDetailDiff + */ + +import com.oracle.java.testlibrary.*; + +import sun.hotspot.WhiteBox; + +public class JcmdDetailDiff { + + public static WhiteBox wb = WhiteBox.getWhiteBox(); + + public static void main(String args[]) throws Exception { + ProcessBuilder pb = new ProcessBuilder(); + OutputAnalyzer output; + // Grab my own PID + String pid = Integer.toString(ProcessTools.getProcessId()); + + long commitSize = 128 * 1024; + long reserveSize = 256 * 1024; + long addr; + + // Run 'jcmd VM.native_memory baseline=true' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "baseline=true"}); + pb.start().waitFor(); + + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Baseline succeeded"); + + addr = wb.NMTReserveMemory(reserveSize); + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "detail.diff", "scale=KB"}); + + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=256KB +256KB, committed=0KB)"); + output.shouldContain("WB_NMTReserveMemory"); + + wb.NMTCommitMemory(addr, commitSize); + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "detail.diff", "scale=KB"}); + + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=256KB +256KB, committed=128KB +128KB)"); + output.shouldContain("WB_NMTReserveMemory"); + + wb.NMTUncommitMemory(addr, commitSize); + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "detail.diff", "scale=KB"}); + + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=256KB +256KB, committed=0KB)"); + output.shouldContain("WB_NMTReserveMemory"); + + wb.NMTReleaseMemory(addr, reserveSize); + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "detail.diff", "scale=KB"}); + + output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("Test (reserved="); + } +} diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/NMT/JcmdScale.java --- a/hotspot/test/runtime/NMT/JcmdScale.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/runtime/NMT/JcmdScale.java Fri Aug 29 11:58:43 2014 -0700 @@ -26,6 +26,7 @@ * @key nmt jcmd * @summary Test the NMT scale parameter * @library /testlibrary + * @ignore * @run main/othervm -XX:NativeMemoryTracking=summary JcmdScale */ @@ -41,15 +42,15 @@ pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=KB"}); output = new OutputAnalyzer(pb.start()); - output.shouldContain("KB, committed="); + output.shouldContain("KB, committed="); pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=MB"}); output = new OutputAnalyzer(pb.start()); - output.shouldContain("MB, committed="); + output.shouldContain("MB, committed="); pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=GB"}); output = new OutputAnalyzer(pb.start()); - output.shouldContain("GB, committed="); + output.shouldContain("GB, committed="); pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=apa"}); output = new OutputAnalyzer(pb.start()); @@ -57,7 +58,7 @@ pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary", "scale=GB"}); output = new OutputAnalyzer(pb.start()); - output.shouldContain("GB, committed="); + output.shouldContain("GB, committed="); pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary", "scale=apa"}); output = new OutputAnalyzer(pb.start()); diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/NMT/JcmdScaleDetail.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/NMT/JcmdScaleDetail.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @key nmt jcmd + * @summary Test the NMT scale parameter with detail tracking level + * @library /testlibrary + * @ignore + * @run main/othervm -XX:NativeMemoryTracking=detail JcmdScaleDetail + */ + +import com.oracle.java.testlibrary.*; + +public class JcmdScaleDetail { + + public static void main(String args[]) throws Exception { + ProcessBuilder pb = new ProcessBuilder(); + OutputAnalyzer output; + // Grab my own PID + String pid = Integer.toString(ProcessTools.getProcessId()); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=KB"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("KB, committed="); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=MB"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("MB, committed="); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=GB"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("GB, committed="); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=apa"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Incorrect scale value: apa"); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary", "scale=GB"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("GB, committed="); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary", "scale=apa"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Incorrect scale value: apa"); + } +} diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/NMT/JcmdSummaryDiff.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/NMT/JcmdSummaryDiff.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary run NMT baseline, allocate memory and verify output from summary.diff + * @key nmt jcmd + * @library /testlibrary /testlibrary/whitebox + * @build JcmdSummaryDiff + * @ignore + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=summary JcmdSummaryDiff + */ + +import com.oracle.java.testlibrary.*; + +import sun.hotspot.WhiteBox; + +public class JcmdSummaryDiff { + + public static WhiteBox wb = WhiteBox.getWhiteBox(); + + public static void main(String args[]) throws Exception { + ProcessBuilder pb = new ProcessBuilder(); + OutputAnalyzer output; + // Grab my own PID + String pid = Integer.toString(ProcessTools.getProcessId()); + + long commitSize = 128 * 1024; + long reserveSize = 256 * 1024; + long addr; + + // Run 'jcmd VM.native_memory baseline=true' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "baseline=true"}); + pb.start().waitFor(); + + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Baseline succeeded"); + + addr = wb.NMTReserveMemory(reserveSize); + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary.diff", "scale=KB"}); + + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=256KB +256KB, committed=0KB)"); + + wb.NMTCommitMemory(addr, commitSize); + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary.diff", "scale=KB"}); + + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=256KB +256KB, committed=128KB +128KB)"); + + wb.NMTUncommitMemory(addr, commitSize); + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary.diff", "scale=KB"}); + + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=256KB +256KB, committed=0KB)"); + + wb.NMTReleaseMemory(addr, reserveSize); + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary.diff", "scale=KB"}); + + output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("Test (reserved="); + } +} diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/NMT/JcmdWithNMTDisabled.java --- a/hotspot/test/runtime/NMT/JcmdWithNMTDisabled.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/runtime/NMT/JcmdWithNMTDisabled.java Fri Aug 29 11:58:43 2014 -0700 @@ -26,6 +26,7 @@ * @key nmt jcmd * @summary Verify that jcmd correctly reports that NMT is not enabled * @library /testlibrary + * @ignore * @run main JcmdWithNMTDisabled 1 */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/NMT/MallocRoundingReportTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/NMT/MallocRoundingReportTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Test consistency of NMT by creating allocations of the Test type with various sizes and verifying visibility with jcmd + * @key nmt jcmd + * @library /testlibrary /testlibrary/whitebox + * @build MallocRoundingReportTest + * @ignore + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail MallocRoundingReportTest + * + */ + +import com.oracle.java.testlibrary.*; + +import sun.hotspot.WhiteBox; + +public class MallocRoundingReportTest { + private static long K = 1024; + + public static void main(String args[]) throws Exception { + OutputAnalyzer output; + WhiteBox wb = WhiteBox.getWhiteBox(); + + // Grab my own PID + String pid = Integer.toString(ProcessTools.getProcessId()); + ProcessBuilder pb = new ProcessBuilder(); + + long[] additionalBytes = {0, 1, 512, 650}; + long[] kByteSize = {1024, 2048}; + long mallocd_total = 0; + for ( int i = 0; i < kByteSize.length; i++) + { + for (int j = 0; j < (additionalBytes.length); j++) { + long curKB = kByteSize[i] + additionalBytes[j]; + // round up/down to the nearest KB to match NMT reporting + long numKB = (curKB % kByteSize[i] >= 512) ? ((curKB / K) + 1) : curKB / K; + // Use WB API to alloc and free with the mtTest type + mallocd_total = wb.NMTMalloc(curKB); + // Run 'jcmd VM.native_memory summary', check for expected output + // NMT does not track memory allocations less than 1KB, and rounds to the nearest KB + String expectedOut = ("Test (reserved=" + numKB + "KB, committed=" + numKB + "KB)"); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary" }); + output = new OutputAnalyzer(pb.start()); + output.shouldContain(expectedOut); + + wb.NMTFree(mallocd_total); + // Run 'jcmd VM.native_memory summary', check for expected output + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary" }); + output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("Test (reserved="); + } + } + } +} diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/NMT/MallocSiteHashOverflow.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/NMT/MallocSiteHashOverflow.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @key stress + * @test + * @summary Test corner case that overflows malloc site hashtable bucket + * @key nmt jcmd + * @library /testlibrary /testlibrary/whitebox + * @ignore - This test is disabled since it will stress NMT and timeout during normal testing + * @build MallocSiteHashOverflow + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm/timeout=480 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail MallocSiteHashOverflow + */ + +import com.oracle.java.testlibrary.*; +import sun.hotspot.WhiteBox; + +public class MallocSiteHashOverflow { + private static long K = 1024; + public static void main(String args[]) throws Exception { + String vm_name = System.getProperty("java.vm.name"); + + // For 32-bit systems, create 257 malloc sites with the same hash bucket to overflow a hash bucket + // For 64-bit systems, create 64K + 1 malloc sites with the same hash bucket to overflow a hash bucket + long entries = 257; + if (Platform.is64bit()) { + entries = 64 * K + 1; + } + + OutputAnalyzer output; + WhiteBox wb = WhiteBox.getWhiteBox(); + + // Grab my own PID + String pid = Integer.toString(ProcessTools.getProcessId()); + ProcessBuilder pb = new ProcessBuilder(); + + wb.NMTOverflowHashBucket(entries); + + // Run 'jcmd VM.native_memory summary' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "statistics"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Tracking level has been downgraded due to lack of resources"); + } +} diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/NMT/MallocStressTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/NMT/MallocStressTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @key stress + * @test + * @summary Stress test for malloc tracking + * @key nmt jcmd + * @library /testlibrary /testlibrary/whitebox + * @build MallocStressTest + * @ignore - This test is disabled since it will stress NMT and timeout during normal testing + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm/timeout=600 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail MallocStressTest + */ + +import java.util.concurrent.atomic.AtomicInteger; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import com.oracle.java.testlibrary.*; +import sun.hotspot.WhiteBox; + +public class MallocStressTest { + private static int K = 1024; + + // The stress test runs in three phases: + // 1. alloc: A lot of malloc with fewer free, which simulates a burst memory allocation + // that is usually seen during startup or class loading. + // 2. pause: Pause the test to check accuracy of native memory tracking + // 3. release: Release all malloc'd memory and check native memory tracking result. + public enum TestPhase { + alloc, + pause, + release + }; + + static TestPhase phase = TestPhase.alloc; + + // malloc'd memory + static ArrayList mallocd_memory = new ArrayList(); + static long mallocd_total = 0; + static WhiteBox whiteBox; + static AtomicInteger pause_count = new AtomicInteger(); + + static boolean is_64_bit_system; + + private static boolean is_64_bit_system() { return is_64_bit_system; } + + public static void main(String args[]) throws Exception { + is_64_bit_system = (Platform.is64bit()); + + OutputAnalyzer output; + whiteBox = WhiteBox.getWhiteBox(); + + // Grab my own PID + String pid = Integer.toString(ProcessTools.getProcessId()); + ProcessBuilder pb = new ProcessBuilder(); + + AllocThread[] alloc_threads = new AllocThread[256]; + ReleaseThread[] release_threads = new ReleaseThread[64]; + + int index; + // Create many allocation threads + for (index = 0; index < alloc_threads.length; index ++) { + alloc_threads[index] = new AllocThread(); + } + + // Fewer release threads + for (index = 0; index < release_threads.length; index ++) { + release_threads[index] = new ReleaseThread(); + } + + if (is_64_bit_system()) { + sleep_wait(2*60*1000); + } else { + sleep_wait(60*1000); + } + // pause the stress test + phase = TestPhase.pause; + while (pause_count.intValue() < alloc_threads.length + release_threads.length) { + sleep_wait(10); + } + + long mallocd_total_in_KB = (mallocd_total + K / 2) / K; + + // Now check if the result from NMT matches the total memory allocated. + String expected_test_summary = "Test (reserved=" + mallocd_total_in_KB +"KB, committed=" + mallocd_total_in_KB + "KB)"; + // Run 'jcmd VM.native_memory summary' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain(expected_test_summary); + + // Release all allocated memory + phase = TestPhase.release; + synchronized(mallocd_memory) { + mallocd_memory.notifyAll(); + } + + // Join all threads + for (index = 0; index < alloc_threads.length; index ++) { + try { + alloc_threads[index].join(); + } catch (InterruptedException e) { + } + } + + for (index = 0; index < release_threads.length; index ++) { + try { + release_threads[index].join(); + } catch (InterruptedException e) { + } + } + + // All test memory allocated should be released + output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("Test (reserved="); + + // Verify that tracking level has not been downgraded + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "statistics"}); + output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("Tracking level has been downgraded due to lack of resources"); + } + + private static void sleep_wait(int n) { + try { + Thread.sleep(n); + } catch (InterruptedException e) { + } + } + + + static class MallocMemory { + private long addr; + private int size; + + MallocMemory(long addr, int size) { + this.addr = addr; + this.size = size; + } + + long addr() { return this.addr; } + int size() { return this.size; } + } + + static class AllocThread extends Thread { + AllocThread() { + this.setName("MallocThread"); + this.start(); + } + + // AllocThread only runs "Alloc" phase + public void run() { + Random random = new Random(); + while (MallocStressTest.phase == TestPhase.alloc) { + int r = Math.abs(random.nextInt()); + // Only malloc small amount to avoid OOM + int size = r % 32; + if (is_64_bit_system()) { + r = r % 32 * K; + } else { + r = r % 64; + } + if (size == 0) size = 1; + long addr = MallocStressTest.whiteBox.NMTMallocWithPseudoStack(size, r); + if (addr != 0) { + MallocMemory mem = new MallocMemory(addr, size); + synchronized(MallocStressTest.mallocd_memory) { + MallocStressTest.mallocd_memory.add(mem); + MallocStressTest.mallocd_total += size; + } + } else { + System.out.println("Out of malloc memory"); + break; + } + } + MallocStressTest.pause_count.incrementAndGet(); + } + } + + static class ReleaseThread extends Thread { + private Random random = new Random(); + ReleaseThread() { + this.setName("ReleaseThread"); + this.start(); + } + + public void run() { + while(true) { + switch(MallocStressTest.phase) { + case alloc: + slow_release(); + break; + case pause: + enter_pause(); + break; + case release: + quick_release(); + return; + } + } + } + + private void enter_pause() { + MallocStressTest.pause_count.incrementAndGet(); + while (MallocStressTest.phase != MallocStressTest.TestPhase.release) { + try { + synchronized(MallocStressTest.mallocd_memory) { + MallocStressTest.mallocd_memory.wait(10); + } + } catch (InterruptedException e) { + } + } + } + + private void quick_release() { + List free_list; + while (true) { + synchronized(MallocStressTest.mallocd_memory) { + if (MallocStressTest.mallocd_memory.isEmpty()) return; + int size = Math.min(MallocStressTest.mallocd_memory.size(), 5000); + List subList = MallocStressTest.mallocd_memory.subList(0, size); + free_list = new ArrayList(subList); + subList.clear(); + } + for (int index = 0; index < free_list.size(); index ++) { + MallocMemory mem = free_list.get(index); + MallocStressTest.whiteBox.NMTFree(mem.addr()); + } + } + } + + private void slow_release() { + try { + Thread.sleep(10); + } catch (InterruptedException e) { + } + synchronized(MallocStressTest.mallocd_memory) { + if (MallocStressTest.mallocd_memory.isEmpty()) return; + int n = Math.abs(random.nextInt()) % MallocStressTest.mallocd_memory.size(); + MallocMemory mem = mallocd_memory.remove(n); + MallocStressTest.whiteBox.NMTFree(mem.addr()); + MallocStressTest.mallocd_total -= mem.size(); + } + } + } +} diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/NMT/MallocTestType.java --- a/hotspot/test/runtime/NMT/MallocTestType.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/runtime/NMT/MallocTestType.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -27,7 +27,9 @@ * @key nmt jcmd * @library /testlibrary /testlibrary/whitebox * @build MallocTestType + * @ignore * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail MallocTestType */ @@ -51,11 +53,6 @@ long memAlloc1 = wb.NMTMalloc(512 * 1024); wb.NMTFree(memAlloc2); - // Use WB API to ensure that all data has been merged before we continue - if (!wb.NMTWaitForDataMerge()) { - throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); - } - // Run 'jcmd VM.native_memory summary' pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary"}); output = new OutputAnalyzer(pb.start()); @@ -64,10 +61,6 @@ // Free the memory allocated by NMTAllocTest wb.NMTFree(memAlloc1); - // Use WB API to ensure that all data has been merged before we continue - if (!wb.NMTWaitForDataMerge()) { - throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); - } output = new OutputAnalyzer(pb.start()); output.shouldNotContain("Test (reserved="); } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/NMT/PrintNMTStatistics.java --- a/hotspot/test/runtime/NMT/PrintNMTStatistics.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/runtime/NMT/PrintNMTStatistics.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -28,7 +28,9 @@ * @summary Make sure PrintNMTStatistics works on normal JVM exit * @library /testlibrary /testlibrary/whitebox * @build PrintNMTStatistics + * @ignore * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main PrintNMTStatistics */ @@ -45,10 +47,6 @@ // We start a new java process running with an argument and use WB API to ensure // we have data for NMT on VM exit if (args.length > 0) { - // Use WB API to ensure that all data has been merged before we continue - if (!WhiteBox.getWhiteBox().NMTWaitForDataMerge()) { - throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); - } return; } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/NMT/PrintNMTStatisticsWithNMTDisabled.java --- a/hotspot/test/runtime/NMT/PrintNMTStatisticsWithNMTDisabled.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/runtime/NMT/PrintNMTStatisticsWithNMTDisabled.java Fri Aug 29 11:58:43 2014 -0700 @@ -26,6 +26,7 @@ * @key nmt * @summary Trying to enable PrintNMTStatistics should result in a warning * @library /testlibrary + * @ignore */ import com.oracle.java.testlibrary.*; diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/NMT/ReleaseCommittedMemory.java --- a/hotspot/test/runtime/NMT/ReleaseCommittedMemory.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/runtime/NMT/ReleaseCommittedMemory.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -28,7 +28,9 @@ * @key nmt regression * @library /testlibrary /testlibrary/whitebox * @build ReleaseCommittedMemory + * @ignore * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail ReleaseCommittedMemory */ @@ -44,7 +46,6 @@ addr = wb.NMTReserveMemory(reserveSize); wb.NMTCommitMemory(addr, 128*1024); wb.NMTReleaseMemory(addr, reserveSize); - wb.NMTWaitForDataMerge(); } } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/NMT/ReleaseNoCommit.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/NMT/ReleaseNoCommit.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Release uncommitted memory and make sure NMT handles it correctly + * @key nmt regression + * @library /testlibrary /testlibrary/whitebox + * @build ReleaseNoCommit + * @ignore + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=summary ReleaseNoCommit + */ + +import com.oracle.java.testlibrary.JDKToolFinder; +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; + +import sun.hotspot.WhiteBox; + +public class ReleaseNoCommit { + + public static void main(String args[]) throws Exception { + WhiteBox wb = WhiteBox.getWhiteBox(); + long reserveSize = 256 * 1024; + long addr; + + ProcessBuilder pb = new ProcessBuilder(); + OutputAnalyzer output; + // Grab my own PID + String pid = Integer.toString(ProcessTools.getProcessId()); + + addr = wb.NMTReserveMemory(reserveSize); + // Check for reserved + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=KB"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain(" Test (reserved=256KB, committed=0KB)"); + + wb.NMTReleaseMemory(addr, reserveSize); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=KB"}); + output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("Test (reserved="); + } +} diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/NMT/ShutdownTwice.java --- a/hotspot/test/runtime/NMT/ShutdownTwice.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/runtime/NMT/ShutdownTwice.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -26,6 +26,7 @@ * @key nmt jcmd * @summary Run shutdown twice * @library /testlibrary + * @ignore * @run main/othervm -XX:NativeMemoryTracking=detail ShutdownTwice */ @@ -45,12 +46,12 @@ output = new OutputAnalyzer(pb.start()); // Verify that jcmd reports that NMT is shutting down - output.shouldContain("Shutdown is in progress, it will take a few moments to completely shutdown"); + output.shouldContain("Native memory tracking has been turned off"); // Run shutdown again output = new OutputAnalyzer(pb.start()); // Verify that jcmd reports that NMT has been shutdown already - output.shouldContain("Native memory tracking has been shutdown by user"); + output.shouldContain("Native memory tracking has been shutdown"); } } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/NMT/SummaryAfterShutdown.java --- a/hotspot/test/runtime/NMT/SummaryAfterShutdown.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/runtime/NMT/SummaryAfterShutdown.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -26,6 +26,7 @@ * @key nmt jcmd * @summary Verify that jcmd correctly reports that NMT is not enabled after a shutdown * @library /testlibrary + * @ignore * @run main/othervm -XX:NativeMemoryTracking=detail SummaryAfterShutdown */ @@ -44,13 +45,13 @@ output = new OutputAnalyzer(pb.start()); // Verify that jcmd reports that NMT is shutting down - output.shouldContain("Shutdown is in progress, it will take a few moments to completely shutdown"); + output.shouldContain("Native memory tracking has been turned off"); // Run 'jcmd VM.native_memory summary' pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary"}); output = new OutputAnalyzer(pb.start()); // Verify that jcmd reports that NMT has been shutdown - output.shouldContain("Native memory tracking has been shutdown by user"); + output.shouldContain("Native memory tracking has been shutdown"); } } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/NMT/SummarySanityCheck.java --- a/hotspot/test/runtime/NMT/SummarySanityCheck.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/runtime/NMT/SummarySanityCheck.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -27,7 +27,9 @@ * @summary Sanity check the output of NMT * @library /testlibrary /testlibrary/whitebox * @build SummarySanityCheck + * @ignore * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=summary -XX:+WhiteBoxAPI SummarySanityCheck */ @@ -44,11 +46,6 @@ // Grab my own PID String pid = Integer.toString(ProcessTools.getProcessId()); - // Use WB API to ensure that all data has been merged before we continue - if (!WhiteBox.getWhiteBox().NMTWaitForDataMerge()) { - throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); - } - ProcessBuilder pb = new ProcessBuilder(); // Run 'jcmd VM.native_memory summary scale=KB' @@ -69,13 +66,13 @@ // Match '- (reserved=KB, committed=KB) Pattern mtTypePattern = Pattern.compile("-\\s+(?[\\w\\s]+)\\(reserved=(?\\d+)KB,\\scommitted=(?\\d+)KB\\)"); // Match 'Total: reserved=KB, committed=KB' - Pattern totalMemoryPattern = Pattern.compile("Total\\:\\s\\sreserved=(?\\d+)KB,\\s\\scommitted=(?\\d+)KB"); + Pattern totalMemoryPattern = Pattern.compile("Total\\:\\sreserved=(?\\d+)KB,\\scommitted=(?\\d+)KB"); for (int i = 0; i < lines.length; i++) { if (lines[i].startsWith("Total")) { Matcher totalMemoryMatcher = totalMemoryPattern.matcher(lines[i]); - if (totalMemoryMatcher.matches() && totalMemoryMatcher.groupCount() == 2) { + if (totalMemoryMatcher.matches()) { totalCommitted = Integer.parseInt(totalMemoryMatcher.group("committed")); totalReserved = Integer.parseInt(totalMemoryMatcher.group("reserved")); } else { diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/NMT/ThreadedMallocTestType.java --- a/hotspot/test/runtime/NMT/ThreadedMallocTestType.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/runtime/NMT/ThreadedMallocTestType.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -26,7 +26,9 @@ * @key nmt jcmd * @library /testlibrary /testlibrary/whitebox * @build ThreadedMallocTestType + * @ignore * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail ThreadedMallocTestType */ @@ -58,11 +60,6 @@ allocThread.start(); allocThread.join(); - // Use WB API to ensure that all data has been merged before we continue - if (!wb.NMTWaitForDataMerge()) { - throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); - } - // Run 'jcmd VM.native_memory summary' pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary"}); output = new OutputAnalyzer(pb.start()); @@ -80,11 +77,6 @@ freeThread.start(); freeThread.join(); - // Use WB API to ensure that all data has been merged before we continue - if (!wb.NMTWaitForDataMerge()) { - throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); - } - output = new OutputAnalyzer(pb.start()); output.shouldNotContain("Test (reserved="); } diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/NMT/ThreadedVirtualAllocTestType.java --- a/hotspot/test/runtime/NMT/ThreadedVirtualAllocTestType.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/runtime/NMT/ThreadedVirtualAllocTestType.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -26,7 +26,9 @@ * @key nmt jcmd * @library /testlibrary /testlibrary/whitebox * @build ThreadedVirtualAllocTestType + * @ignore * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail ThreadedVirtualAllocTestType */ @@ -60,8 +62,6 @@ reserveThread.start(); reserveThread.join(); - mergeData(); - pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "detail"}); output = new OutputAnalyzer(pb.start()); output.shouldContain("Test (reserved=512KB, committed=0KB)"); @@ -77,8 +77,6 @@ commitThread.start(); commitThread.join(); - mergeData(); - output = new OutputAnalyzer(pb.start()); output.shouldContain("Test (reserved=512KB, committed=128KB)"); if (has_nmt_detail) { @@ -93,8 +91,6 @@ uncommitThread.start(); uncommitThread.join(); - mergeData(); - output = new OutputAnalyzer(pb.start()); output.shouldContain("Test (reserved=512KB, committed=0KB)"); output.shouldNotMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + commitSize) + "\\] committed"); @@ -107,17 +103,9 @@ releaseThread.start(); releaseThread.join(); - mergeData(); - output = new OutputAnalyzer(pb.start()); output.shouldNotContain("Test (reserved="); output.shouldNotContain("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + reserveSize) + "\\] reserved"); } - public static void mergeData() throws Exception { - // Use WB API to ensure that all data has been merged before we continue - if (!wb.NMTWaitForDataMerge()) { - throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); } - } -} diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/NMT/VirtualAllocCommitUncommitRecommit.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/NMT/VirtualAllocCommitUncommitRecommit.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Test reserve/commit/uncommit/release of virtual memory and that we track it correctly + * @key nmt jcmd + * @library /testlibrary /testlibrary/whitebox + * @ignore + * @build VirtualAllocCommitUncommitRecommit + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail VirtualAllocCommitUncommitRecommit + * + */ + +import com.oracle.java.testlibrary.*; + +import sun.hotspot.WhiteBox; + +public class VirtualAllocCommitUncommitRecommit { + + public static WhiteBox wb = WhiteBox.getWhiteBox(); + + public static void main(String args[]) throws Exception { + OutputAnalyzer output; + long commitSize = 4 * 1024; // 4KB + long reserveSize = 1024 * 1024; // 1024KB + long addr; + + String pid = Integer.toString(ProcessTools.getProcessId()); + ProcessBuilder pb = new ProcessBuilder(); + + boolean has_nmt_detail = wb.NMTIsDetailSupported(); + if (has_nmt_detail) { + System.out.println("NMT detail support detected."); + } else { + System.out.println("NMT detail support not detected."); + } + + // reserve + addr = wb.NMTReserveMemory(reserveSize); + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, + "VM.native_memory", "detail" }); + + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=1024KB, committed=0KB)"); + if (has_nmt_detail) { + output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + + Long.toHexString(addr + reserveSize) + + "\\] reserved 1024KB for Test"); + } + + long addrA = addr; + long addrB = addr + commitSize; + long addrC = addr + (2 * commitSize); + long addrD = addr + (3 * commitSize); + long addrE = addr + (4 * commitSize); + long addrF = addr + (5 * commitSize); + + // commit ABCD + wb.NMTCommitMemory(addrA, commitSize); + wb.NMTCommitMemory(addrB, commitSize); + wb.NMTCommitMemory(addrC, commitSize); + wb.NMTCommitMemory(addrD, commitSize); + + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=1024KB, committed=16KB)"); + + if (has_nmt_detail) { + output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + + Long.toHexString(addr + reserveSize) + + "\\] reserved 1024KB for Test"); + } + // uncommit BC + wb.NMTUncommitMemory(addrB, commitSize); + wb.NMTUncommitMemory(addrC, commitSize); + + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=1024KB, committed=8KB)"); + + if (has_nmt_detail) { + output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + + Long.toHexString(addr + reserveSize) + + "\\] reserved 1024KB for Test"); + } + + // commit EF + wb.NMTCommitMemory(addrE, commitSize); + wb.NMTCommitMemory(addrF, commitSize); + + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=1024KB, committed=16KB)"); + if (has_nmt_detail) { + output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + + Long.toHexString(addr + reserveSize) + + "\\] reserved 1024KB for Test"); + } + + // uncommit A + wb.NMTUncommitMemory(addrA, commitSize); + + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=1024KB, committed=12KB)"); + if (has_nmt_detail) { + output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + + Long.toHexString(addr + reserveSize) + + "\\] reserved 1024KB for Test"); + } + + // commit ABC + wb.NMTCommitMemory(addrA, commitSize); + wb.NMTCommitMemory(addrB, commitSize); + wb.NMTCommitMemory(addrC, commitSize); + + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=1024KB, committed=24KB)"); + if (has_nmt_detail) { + output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + + Long.toHexString(addr + reserveSize) + + "\\] reserved 1024KB for Test"); + } + + // uncommit ABCDEF + wb.NMTUncommitMemory(addrA, commitSize); + wb.NMTUncommitMemory(addrB, commitSize); + wb.NMTUncommitMemory(addrC, commitSize); + wb.NMTUncommitMemory(addrD, commitSize); + wb.NMTUncommitMemory(addrE, commitSize); + wb.NMTUncommitMemory(addrF, commitSize); + + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=1024KB, committed=0KB)"); + if (has_nmt_detail) { + output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + + Long.toHexString(addr + reserveSize) + + "\\] reserved 1024KB for Test"); + } + + // release + wb.NMTReleaseMemory(addr, reserveSize); + output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("Test (reserved="); + output.shouldNotMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + + Long.toHexString(addr + reserveSize) + "\\] reserved"); + } +} diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/NMT/VirtualAllocTestType.java --- a/hotspot/test/runtime/NMT/VirtualAllocTestType.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/runtime/NMT/VirtualAllocTestType.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -26,8 +26,10 @@ * @summary Test Reserve/Commit/Uncommit/Release of virtual memory and that we track it correctly * @key nmt jcmd * @library /testlibrary /testlibrary/whitebox + * @ignore * @build VirtualAllocTestType * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail VirtualAllocTestType */ @@ -54,7 +56,6 @@ } addr = wb.NMTReserveMemory(reserveSize); - mergeData(); pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "detail"}); output = new OutputAnalyzer(pb.start()); @@ -65,7 +66,6 @@ wb.NMTCommitMemory(addr, commitSize); - mergeData(); output = new OutputAnalyzer(pb.start()); output.shouldContain("Test (reserved=256KB, committed=128KB)"); @@ -75,24 +75,15 @@ wb.NMTUncommitMemory(addr, commitSize); - mergeData(); output = new OutputAnalyzer(pb.start()); output.shouldContain("Test (reserved=256KB, committed=0KB)"); output.shouldNotMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + commitSize) + "\\] committed"); wb.NMTReleaseMemory(addr, reserveSize); - mergeData(); output = new OutputAnalyzer(pb.start()); output.shouldNotContain("Test (reserved="); output.shouldNotMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + reserveSize) + "\\] reserved"); } - - public static void mergeData() throws Exception { - // Use WB API to ensure that all data has been merged before we continue - if (!wb.NMTWaitForDataMerge()) { - throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); } - } -} diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/SharedArchiveFile/LimitSharedSizes.java --- a/hotspot/test/runtime/SharedArchiveFile/LimitSharedSizes.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/runtime/SharedArchiveFile/LimitSharedSizes.java Fri Aug 29 11:58:43 2014 -0700 @@ -21,8 +21,7 @@ * questions. */ -/* @ignore JDK-8043896 - * @test LimitSharedSizes +/* @test LimitSharedSizes * @summary Test handling of limits on shared space size * @library /testlibrary * @run main LimitSharedSizes diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/interned/SanityTest.java --- a/hotspot/test/runtime/interned/SanityTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/runtime/interned/SanityTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -27,6 +27,7 @@ * @library /testlibrary /testlibrary/whitebox * @build SanityTest * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI SanityTest */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/jsig/Test8017498.sh --- a/hotspot/test/runtime/jsig/Test8017498.sh Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/runtime/jsig/Test8017498.sh Fri Aug 29 11:58:43 2014 -0700 @@ -24,7 +24,6 @@ # ## -## @ignore 8028806 ## @test Test8017498.sh ## @bug 8017498 ## @bug 8020791 @@ -75,7 +74,7 @@ $gcc_cmd -DLINUX -fPIC -shared \ ${EXTRA_CFLAG} -z noexecstack \ - -o ${TESTSRC}${FS}libTestJNI.so \ + -o libTestJNI.so \ -I${COMPILEJAVA}${FS}include \ -I${COMPILEJAVA}${FS}include${FS}linux \ ${TESTSRC}${FS}TestJNI.c @@ -83,7 +82,7 @@ # run the java test in the background cmd="LD_PRELOAD=$MY_LD_PRELOAD \ ${TESTJAVA}${FS}bin${FS}java \ - -Djava.library.path=${TESTSRC}${FS} -server TestJNI 100" + -Djava.library.path=. -server TestJNI 100" echo "$cmd > test.out 2>&1" eval $cmd > test.out 2>&1 diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/memory/ReadFromNoaccessArea.java --- a/hotspot/test/runtime/memory/ReadFromNoaccessArea.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/runtime/memory/ReadFromNoaccessArea.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -27,6 +27,7 @@ * @library /testlibrary /testlibrary/whitebox * @build ReadFromNoaccessArea * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main ReadFromNoaccessArea */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/memory/ReserveMemory.java --- a/hotspot/test/runtime/memory/ReserveMemory.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/runtime/memory/ReserveMemory.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -29,6 +29,7 @@ * @library /testlibrary /testlibrary/whitebox * @build ReserveMemory * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main ReserveMemory */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/memory/RunUnitTestsConcurrently.java --- a/hotspot/test/runtime/memory/RunUnitTestsConcurrently.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/runtime/memory/RunUnitTestsConcurrently.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -27,6 +27,7 @@ * @library /testlibrary /testlibrary/whitebox * @build RunUnitTestsConcurrently * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI RunUnitTestsConcurrently 30 15000 */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/memory/StressVirtualSpaceResize.java --- a/hotspot/test/runtime/memory/StressVirtualSpaceResize.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/runtime/memory/StressVirtualSpaceResize.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -27,6 +27,7 @@ * @library /testlibrary /testlibrary/whitebox * @build StressVirtualSpaceResize * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI StressVirtualSpaceResize */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/runtime/whitebox/WBStackSize.java --- a/hotspot/test/runtime/whitebox/WBStackSize.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/runtime/whitebox/WBStackSize.java Fri Aug 29 11:58:43 2014 -0700 @@ -27,6 +27,7 @@ * @library /testlibrary /testlibrary/whitebox * @build WBStackSize * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xss512k WBStackSize */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/sanity/WBApi.java --- a/hotspot/test/sanity/WBApi.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/sanity/WBApi.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -27,6 +27,7 @@ * @library /testlibrary /testlibrary/whitebox * @build WBApi * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI WBApi */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/sanity/WhiteBox.java --- a/hotspot/test/sanity/WhiteBox.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/sanity/WhiteBox.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -29,6 +29,7 @@ * @library /testlibrary * @compile WhiteBox.java * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI sun.hotspot.WhiteBox * @clean sun.hotspot.WhiteBox */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/serviceability/ParserTest.java --- a/hotspot/test/serviceability/ParserTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/serviceability/ParserTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -27,6 +27,7 @@ * @library /testlibrary /testlibrary/whitebox * @build ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.parser.* * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ParserTest */ diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/serviceability/attach/AttachSetGetFlag.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/serviceability/attach/AttachSetGetFlag.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8054823 + * @summary Tests the setFlag and printFlag attach command + * @library /testlibrary + * @build com.oracle.java.testlibrary.* AttachSetGetFlag + * @run driver AttachSetGetFlag + */ + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.InputStream; +import java.lang.reflect.Field; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import sun.tools.attach.HotSpotVirtualMachine; + +import com.oracle.java.testlibrary.Asserts; +import com.oracle.java.testlibrary.Platform; +import com.oracle.java.testlibrary.ProcessTools; +import com.sun.tools.attach.VirtualMachine; + +public class AttachSetGetFlag { + + public static void main(String... args) throws Exception { + // Test a manageable uintx flag. + testGetFlag("MaxHeapFreeRatio", "60"); + testSetFlag("MaxHeapFreeRatio", "50", "60"); + + // Test a non-manageable size_t flag. + // Since it is not manageable, we can't test the setFlag functionality. + testGetFlag("ArrayAllocatorMallocLimit", "128"); + // testSetFlag("ArrayAllocatorMallocLimit", "64", "128"); + } + + public static ProcessBuilder runTarget(String flagName, String flagValue) throws Exception { + return ProcessTools.createJavaProcessBuilder( + "-XX:+UnlockExperimentalVMOptions", + "-XX:" + flagName + "=" + flagValue, + "AttachSetGetFlag$Target"); + } + + public static void testGetFlag(String flagName, String flagValue) throws Exception { + ProcessBuilder pb = runTarget(flagName, flagValue); + + Process target = pb.start(); + + try { + waitForReady(target); + + int pid = (int)target.getPid(); + + HotSpotVirtualMachine vm = (HotSpotVirtualMachine)VirtualMachine.attach(((Integer)pid).toString()); + + // Test Get + BufferedReader remoteDataReader = new BufferedReader(new InputStreamReader( + vm.printFlag(flagName))); + + boolean foundExpectedLine = false; + + String line = null; + while((line = remoteDataReader.readLine()) != null) { + System.out.println("printFlag: " + line); + if (line.equals("-XX:" + flagName + "=" + flagValue)) { + foundExpectedLine = true; + } + } + + Asserts.assertTrue(foundExpectedLine, "Didn't get the expected output: '-XX:" + flagName + "=" + flagValue + "'"); + + vm.detach(); + } + finally { + target.destroy(); + target.waitFor(); + } + } + + public static void testSetFlag(String flagName, String initialFlagValue, String flagValue) throws Exception { + ProcessBuilder pb = runTarget(flagName, initialFlagValue); + + Process target = pb.start(); + + try { + waitForReady(target); + + int pid = (int)target.getPid(); + + HotSpotVirtualMachine vm = (HotSpotVirtualMachine)VirtualMachine.attach(((Integer)pid).toString()); + + // First set the value. + BufferedReader remoteDataReader = new BufferedReader(new InputStreamReader( + vm.setFlag(flagName, flagValue))); + + String line; + while((line = remoteDataReader.readLine()) != null) { + System.out.println("setFlag: " + line); + // Just empty the stream. + } + remoteDataReader.close(); + + // Then read and make sure we get back the set value. + remoteDataReader = new BufferedReader(new InputStreamReader(vm.printFlag(flagName))); + + boolean foundExpectedLine = false; + line = null; + while((line = remoteDataReader.readLine()) != null) { + System.out.println("getFlag: " + line); + if (line.equals("-XX:" + flagName + "=" + flagValue)) { + foundExpectedLine = true; + } + } + + Asserts.assertTrue(foundExpectedLine, "Didn't get the expected output: '-XX:" + flagName + "=" + flagValue + "'"); + + vm.detach(); + + } finally { + target.destroy(); + target.waitFor(); + } + } + + private static void waitForReady(Process target) throws Exception { + InputStream os = target.getInputStream(); + try (BufferedReader reader = new BufferedReader(new InputStreamReader(os))) { + String line; + while ((line = reader.readLine()) != null) { + if ("Ready".equals(line)) { + return; + } + } + } + } + + + public static class Target { + public static void main(String [] args) throws Exception { + System.out.println("Ready"); + System.out.flush(); + while (true) { + Thread.sleep(1000); + } + } + } +} diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/test_env.sh --- a/hotspot/test/test_env.sh Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/test_env.sh Fri Aug 29 11:58:43 2014 -0700 @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2013, 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 @@ -50,6 +50,9 @@ fi echo "TESTCLASSES=${TESTCLASSES}" +TESTOPTS="${TESTVMOPTS} ${TESTJAVAOPTS}" +echo "TESTOPTS=${TESTOPTS}" + # set platform-dependent variables OS=`uname -s` case "$OS" in @@ -101,14 +104,14 @@ echo "THIS_DIR=${THIS_DIR}" # Check to ensure the java defined actually works -${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -version +${TESTJAVA}${FS}bin${FS}java ${TESTOPTS} -version if [ $? != 0 ]; then - echo "Wrong TESTJAVA or TESTVMOPTS:" - echo $TESTJAVA TESTVMOPTS + echo "Wrong TESTJAVA or TESTJAVAOPTS or TESTVMOPTS:" + echo ''$TESTJAVA'' ''$TESTJAVAOPTS'' ''$TESTVMOPTS'' exit 1 fi -${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -Xinternalversion > vm_version.out 2>&1 +${TESTJAVA}${FS}bin${FS}java ${TESTOPTS} -Xinternalversion > vm_version.out 2>&1 VM_TYPE="unknown" grep "Server" vm_version.out > ${NULL} diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/testlibrary/ctw/test/ClassesDirTest.java --- a/hotspot/test/testlibrary/ctw/test/ClassesDirTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/testlibrary/ctw/test/ClassesDirTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -27,6 +27,7 @@ * @library /testlibrary /testlibrary/whitebox /testlibrary/ctw/src * @build ClassFileInstaller sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox Foo Bar * @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main ClassesDirTest prepare * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Dsun.hotspot.tools.ctw.logfile=ctw.log sun.hotspot.tools.ctw.CompileTheWorld classes * @run main ClassesDirTest check ctw.log diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/testlibrary/ctw/test/ClassesListTest.java --- a/hotspot/test/testlibrary/ctw/test/ClassesListTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/testlibrary/ctw/test/ClassesListTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -27,6 +27,7 @@ * @library /testlibrary /testlibrary/whitebox /testlibrary/ctw/src * @build ClassFileInstaller sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox Foo Bar * @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main ClassesListTest prepare * @run main/othervm/timeout=600 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Dsun.hotspot.tools.ctw.logfile=ctw.log sun.hotspot.tools.ctw.CompileTheWorld classes.lst * @run main ClassesListTest check ctw.log diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/testlibrary/ctw/test/JarDirTest.java --- a/hotspot/test/testlibrary/ctw/test/JarDirTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/testlibrary/ctw/test/JarDirTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -27,6 +27,7 @@ * @library /testlibrary /testlibrary/whitebox /testlibrary/ctw/src * @build ClassFileInstaller com.oracle.java.testlibrary.* sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox Foo Bar * @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main JarDirTest prepare * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Dsun.hotspot.tools.ctw.logfile=ctw.log sun.hotspot.tools.ctw.CompileTheWorld jars/* * @run main JarDirTest check ctw.log diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/testlibrary/ctw/test/JarsTest.java --- a/hotspot/test/testlibrary/ctw/test/JarsTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/testlibrary/ctw/test/JarsTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -27,6 +27,7 @@ * @library /testlibrary /testlibrary/whitebox /testlibrary/ctw/src * @build ClassFileInstaller com.oracle.java.testlibrary.* sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox Foo Bar * @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main JarsTest prepare * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Dsun.hotspot.tools.ctw.logfile=ctw.log sun.hotspot.tools.ctw.CompileTheWorld foo.jar bar.jar * @run main JarsTest check ctw.log diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java --- a/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Fri Aug 29 11:58:43 2014 -0700 @@ -95,7 +95,8 @@ public native void NMTCommitMemory(long addr, long size); public native void NMTUncommitMemory(long addr, long size); public native void NMTReleaseMemory(long addr, long size); - public native boolean NMTWaitForDataMerge(); + public native void NMTOverflowHashBucket(long num); + public native long NMTMallocWithPseudoStack(long size, int index); public native boolean NMTIsDetailSupported(); // Compiler @@ -167,17 +168,20 @@ public native void setIntxVMFlag(String name, long value); public native void setUintxVMFlag(String name, long value); public native void setUint64VMFlag(String name, long value); + public native void setSizeTVMFlag(String name, long value); public native void setStringVMFlag(String name, String value); public native void setDoubleVMFlag(String name, double value); public native Boolean getBooleanVMFlag(String name); public native Long getIntxVMFlag(String name); public native Long getUintxVMFlag(String name); public native Long getUint64VMFlag(String name); + public native Long getSizeTVMFlag(String name); public native String getStringVMFlag(String name); public native Double getDoubleVMFlag(String name); private final List> flagsGetters = Arrays.asList( this::getBooleanVMFlag, this::getIntxVMFlag, this::getUintxVMFlag, - this::getUint64VMFlag, this::getStringVMFlag, this::getDoubleVMFlag); + this::getUint64VMFlag, this::getSizeTVMFlag, this::getStringVMFlag, + this::getDoubleVMFlag); public Object getVMFlag(String name) { return flagsGetters.stream() diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/testlibrary_tests/whitebox/vm_flags/BooleanTest.java --- a/hotspot/test/testlibrary_tests/whitebox/vm_flags/BooleanTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/BooleanTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -27,6 +27,7 @@ * @library /testlibrary /testlibrary/whitebox * @build BooleanTest ClassFileInstaller sun.hotspot.WhiteBox com.oracle.java.testlibrary.* * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm/timeout=600 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI BooleanTest * @summary testing of WB::set/getBooleanVMFlag() * @author igor.ignatyev@oracle.com diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/testlibrary_tests/whitebox/vm_flags/DoubleTest.java --- a/hotspot/test/testlibrary_tests/whitebox/vm_flags/DoubleTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/DoubleTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -27,6 +27,7 @@ * @library /testlibrary /testlibrary/whitebox * @build DoubleTest * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm/timeout=600 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI DoubleTest * @summary testing of WB::set/getDoubleVMFlag() * @author igor.ignatyev@oracle.com diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/testlibrary_tests/whitebox/vm_flags/IntxTest.java --- a/hotspot/test/testlibrary_tests/whitebox/vm_flags/IntxTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/IntxTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -27,6 +27,7 @@ * @library /testlibrary /testlibrary/whitebox * @build IntxTest * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm/timeout=600 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI IntxTest * @summary testing of WB::set/getIntxVMFlag() * @author igor.ignatyev@oracle.com diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/testlibrary_tests/whitebox/vm_flags/SizeTTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/SizeTTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test SizeTTest + * @bug 8054823 + * @library /testlibrary /testlibrary/whitebox + * @build SizeTTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm/timeout=600 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions SizeTTest + * @summary testing of WB::set/getSizeTVMFlag() + */ +import com.oracle.java.testlibrary.Platform; + +public class SizeTTest { + private static final String FLAG_NAME = "ArrayAllocatorMallocLimit"; + private static final Long[] TESTS = {0L, 100L, (long) Integer.MAX_VALUE, + (1L << 32L) - 1L, 1L << 32L}; + private static final Long[] EXPECTED_64 = TESTS; + private static final Long[] EXPECTED_32 = {0L, 100L, + (long) Integer.MAX_VALUE, (1L << 32L) - 1L, 0L}; + + public static void main(String[] args) throws Exception { + VmFlagTest.runTest(FLAG_NAME, TESTS, + Platform.is64bit() ? EXPECTED_64 : EXPECTED_32, + VmFlagTest.WHITE_BOX::setSizeTVMFlag, + VmFlagTest.WHITE_BOX::getSizeTVMFlag); + } +} diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/testlibrary_tests/whitebox/vm_flags/StringTest.java --- a/hotspot/test/testlibrary_tests/whitebox/vm_flags/StringTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/StringTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -27,6 +27,7 @@ * @library /testlibrary /testlibrary/whitebox * @build StringTest * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm/timeout=600 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI StringTest * @summary testing of WB::set/getStringVMFlag() * @author igor.ignatyev@oracle.com diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/testlibrary_tests/whitebox/vm_flags/Uint64Test.java --- a/hotspot/test/testlibrary_tests/whitebox/vm_flags/Uint64Test.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/Uint64Test.java Fri Aug 29 11:58:43 2014 -0700 @@ -27,6 +27,7 @@ * @library /testlibrary /testlibrary/whitebox * @build Uint64Test * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm/timeout=600 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI Uint64Test * @summary testing of WB::set/getUint64VMFlag() * @author igor.ignatyev@oracle.com diff -r aa7ada31eb77 -r 317aad3480c8 hotspot/test/testlibrary_tests/whitebox/vm_flags/UintxTest.java --- a/hotspot/test/testlibrary_tests/whitebox/vm_flags/UintxTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/UintxTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -27,6 +27,7 @@ * @library /testlibrary /testlibrary/whitebox * @build UintxTest * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm/timeout=600 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI UintxTest * @summary testing of WB::set/getUintxVMFlag() * @author igor.ignatyev@oracle.com diff -r aa7ada31eb77 -r 317aad3480c8 jaxp/.hgtags --- a/jaxp/.hgtags Fri Aug 29 10:47:32 2014 -0700 +++ b/jaxp/.hgtags Fri Aug 29 11:58:43 2014 -0700 @@ -269,3 +269,4 @@ 345af113f57206711f75089c3ebf84a36a789122 jdk9-b24 73757f4b8aa353ca8937abc07e79e7ece4c011a1 jdk9-b25 a5aea8318ae4a9c2105228568688875142d70344 jdk9-b26 +2bfaf29cc90b19948938e3ef1a0983eee68806c7 jdk9-b27 diff -r aa7ada31eb77 -r 317aad3480c8 jaxws/.hgtags --- a/jaxws/.hgtags Fri Aug 29 10:47:32 2014 -0700 +++ b/jaxws/.hgtags Fri Aug 29 11:58:43 2014 -0700 @@ -272,3 +272,4 @@ 0b35542d6bf32af23a9fc59a37c52aa091fee388 jdk9-b24 ab8726a0fcde897e4cfd1ea581ed90b0d8a7cbb7 jdk9-b25 9b43f3993b96c2213428e95127a2d3fd0e709d3a jdk9-b26 +dcaa586ab756420e9a62643793bacef2c84bf637 jdk9-b27 diff -r aa7ada31eb77 -r 317aad3480c8 jdk/.hgtags --- a/jdk/.hgtags Fri Aug 29 10:47:32 2014 -0700 +++ b/jdk/.hgtags Fri Aug 29 11:58:43 2014 -0700 @@ -269,3 +269,5 @@ 875450e7ef8dde8f59db662ec1351ea30b8cb35d jdk9-b24 a31efe49556a7c12f9ea2c9ee8b4fae8aa67723a jdk9-b25 dde9f5cfde5f46e62ceb5fab81151578e5277aef jdk9-b26 +f0870554049807d3392bd7976ab114f7f2b7bafa jdk9-b27 +1828f73b35cfe35e460e41fd6e087ab1f83e0621 jdk9-b28 diff -r aa7ada31eb77 -r 317aad3480c8 langtools/.hgtags --- a/langtools/.hgtags Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/.hgtags Fri Aug 29 11:58:43 2014 -0700 @@ -269,3 +269,4 @@ 980b18627fd3f4936be2d9e2b013abb461cb2ddb jdk9-b24 d60b572d759449913d02478219ad87e0574a3909 jdk9-b25 5b20a93f8db0b87b902bde48bb7cbb05e88e6e9c jdk9-b26 +10fc81ac75b445528851c9e46c6eeb4438d4e363 jdk9-b27 diff -r aa7ada31eb77 -r 317aad3480c8 langtools/make/build.properties --- a/langtools/make/build.properties Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/make/build.properties Fri Aug 29 11:58:43 2014 -0700 @@ -68,7 +68,7 @@ # set the following to -version to verify the versions of javac being used javac.version.opt = # in time, there should be no exceptions to -Xlint:all -javac.lint.opts = -Xlint:all -Werror +javac.lint.opts = -Xlint:all,-deprecation -Werror # options for the task for javac #javadoc.jls3.url=http://java.sun.com/docs/books/jls/ diff -r aa7ada31eb77 -r 317aad3480c8 langtools/make/intellij/langtools.iml --- a/langtools/make/intellij/langtools.iml Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/make/intellij/langtools.iml Fri Aug 29 11:58:43 2014 -0700 @@ -6,10 +6,14 @@ - - + + + + + + - + diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Fri Aug 29 11:58:43 2014 -0700 @@ -2196,16 +2196,6 @@ } @Override - public Type visitWildcardType(WildcardType t, Boolean recurse) { - final List annos = t.getAnnotationMirrors(); - Type erased = erasure(wildUpperBound(t), recurse); - if (!annos.isEmpty()) { - erased = erased.annotatedType(annos); - } - return erased; - } - - @Override public Type visitClassType(ClassType t, Boolean recurse) { Type erased = t.tsym.erasure(Types.this); List annos = t.getAnnotationMirrors(); diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Fri Aug 29 11:58:43 2014 -0700 @@ -919,14 +919,14 @@ // Empty bodies are only allowed for // abstract, native, or interface methods, or for methods // in a retrofit signature class. - if (isDefaultMethod || (tree.sym.flags() & (ABSTRACT | NATIVE)) == 0 && - !relax) - log.error(tree.pos(), "missing.meth.body.or.decl.abstract"); if (tree.defaultValue != null) { if ((owner.flags() & ANNOTATION) == 0) log.error(tree.pos(), "default.allowed.in.intf.annotation.member"); } + if (isDefaultMethod || (tree.sym.flags() & (ABSTRACT | NATIVE)) == 0 && + !relax) + log.error(tree.pos(), "missing.meth.body.or.decl.abstract"); } else if ((tree.sym.flags() & ABSTRACT) != 0 && !isDefaultMethod) { if ((owner.flags() & INTERFACE) != 0) { log.error(tree.body.pos(), "intf.meth.cant.have.body"); diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/BuildState.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/BuildState.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/BuildState.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -31,15 +31,17 @@ import java.util.Map; import java.util.Set; +import com.sun.tools.javac.util.Assert; + /** * The build state class captures the source code and generated artifacts * from a build. There are usually two build states, the previous one (prev), * loaded from the javac_state file, and the current one (now). * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own - * risk. This code and its internal interfaces are subject to change - * or deletion without notice.

+ *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. */ public class BuildState { private Map modules = new HashMap<>(); @@ -75,7 +77,7 @@ */ Module findModuleFromPackageName(String pkg) { int cp = pkg.indexOf(':'); - assert(cp != -1); + Assert.check(cp != -1); String mod = pkg.substring(0, cp); return lookupModule(mod); } @@ -94,7 +96,7 @@ for (Map.Entry j : i.packages().entrySet()) { Package p = packages.get(j.getKey()); // Check that no two different packages are stored under same name. - assert(p == null || p == j.getValue()); + Assert.check(p == null || p == j.getValue()); if (p == null) { p = j.getValue(); packages.put(j.getKey(),j.getValue()); @@ -102,7 +104,7 @@ for (Map.Entry k : p.sources().entrySet()) { Source s = sources.get(k.getKey()); // Check that no two different sources are stored under same name. - assert(s == null || s == k.getValue()); + Assert.check(s == null || s == k.getValue()); if (s == null) { s = k.getValue(); sources.put(k.getKey(), k.getValue()); @@ -111,7 +113,7 @@ for (Map.Entry g : p.artifacts().entrySet()) { File f = artifacts.get(g.getKey()); // Check that no two artifacts are stored under the same file. - assert(f == null || f == g.getValue()); + Assert.check(f == null || f == g.getValue()); if (f == null) { f = g.getValue(); artifacts.put(g.getKey(), g.getValue()); @@ -134,13 +136,13 @@ for (Map.Entry j : i.packages().entrySet()) { Package p = packages.get(j.getKey()); // Check that no two different packages are stored under same name. - assert(p == null || p == j.getValue()); + Assert.check(p == null || p == j.getValue()); p = j.getValue(); packages.put(j.getKey(),j.getValue()); for (Map.Entry g : p.artifacts().entrySet()) { File f = artifacts.get(g.getKey()); // Check that no two artifacts are stored under the same file. - assert(f == null || f == g.getValue()); + Assert.check(f == null || f == g.getValue()); artifacts.put(g.getKey(), g.getValue()); } } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CleanProperties.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CleanProperties.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CleanProperties.java Fri Aug 29 11:58:43 2014 -0700 @@ -36,19 +36,18 @@ import java.util.Properties; import com.sun.tools.sjavac.options.Options; -import com.sun.tools.sjavac.server.JavacService; +import com.sun.tools.sjavac.server.Sjavac; /** * The clean properties transform should not be necessary. * Eventually we will cleanup the property file sources in the OpenJDK instead. * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own - * risk. This code and its internal interfaces are subject to change - * or deletion without notice.

+ *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. */ -public class CleanProperties implements Transformer -{ +public class CleanProperties implements Transformer { public void setExtra(String e) { // Any extra information is ignored for clean properties. } @@ -57,7 +56,7 @@ // Any extra information is ignored for clean properties. } - public boolean transform(JavacService javacService, + public boolean transform(Sjavac sjavac, Map> pkgSrcs, Set visibleSrcs, Map> visibleClasses, @@ -70,8 +69,7 @@ boolean incremental, int numCores, PrintStream out, - PrintStream err) - { + PrintStream err) { boolean rc = true; for (String pkgName : pkgSrcs.keySet()) { String pkgNameF = pkgName.replace('.',File.separatorChar); @@ -87,9 +85,12 @@ return rc; } - boolean clean(String pkgName, String pkgNameF, File src, File destRoot, int debugLevel, - Map> packageArtifacts) - { + boolean clean(String pkgName, + String pkgNameF, + File src, + File destRoot, + int debugLevel, + Map> packageArtifacts) { // Load the properties file. Properties p = new Properties(); try { diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileChunk.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileChunk.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileChunk.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -33,10 +33,10 @@ * A compile chunk is a list of sources/packages to be compiled. Possibly a subset of * the total number of sources/packages to be compiled for this sjavac invocation. * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own - * risk. This code and its internal interfaces are subject to change - * or deletion without notice.

+ *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. */ public class CompileChunk implements Comparable { public int numPackages; diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,13 +30,12 @@ import java.net.URI; import java.util.Arrays; import java.util.Collections; -import java.util.Random; import java.util.Set; import java.util.Map; import com.sun.tools.sjavac.options.Options; import com.sun.tools.sjavac.server.CompilationResult; -import com.sun.tools.sjavac.server.JavacService; +import com.sun.tools.sjavac.server.Sjavac; import com.sun.tools.sjavac.server.SysInfo; /** @@ -67,7 +66,7 @@ args = a; } - public boolean transform(final JavacService javacService, + public boolean transform(final Sjavac sjavac, Map> pkgSrcs, final Set visibleSources, final Map> visibleClasses, @@ -86,18 +85,12 @@ boolean concurrentCompiles = true; // Fetch the id. - String idOpt = Util.extractStringOption("id", args.getServerConf()); - if (idOpt == null || idOpt.equals("")) { - // No explicit id set. Create a random id so that the requests can be - // grouped properly in the server. - idOpt = "id"+(((new Random()).nextLong())&Long.MAX_VALUE); - } - final String id = idOpt; + final String id = Util.extractStringOption("id", sjavac.serverSettings()); // Only keep portfile and sjavac settings.. - String psServerSettings = Util.cleanSubOptions(Util.set("portfile","sjavac","background","keepalive"), args.getServerConf()); + String psServerSettings = Util.cleanSubOptions(Util.set("portfile","sjavac","background","keepalive"), sjavac.serverSettings()); // Get maximum heap size from the server! - SysInfo sysinfo = javacService.getSysInfo(); + SysInfo sysinfo = sjavac.getSysInfo(); if (sysinfo.numCores == -1) { Log.error("Could not query server for sysinfo!"); return false; @@ -222,7 +215,7 @@ requests[i] = new Thread() { @Override public void run() { - rn[ii] = javacService.compile("n/a", + rn[ii] = sjavac.compile("n/a", id + "-" + ii, args.prepJavacArgs(), Collections.emptyList(), @@ -253,6 +246,8 @@ requests[ii].run(); // If there was an error, then stop early when running single threaded. if (rn[i].returnCode != 0) { + Log.info(rn[i].stdout); + Log.error(rn[i].stderr); return false; } } @@ -269,6 +264,8 @@ for (int i=0; i 0) { if (rn[i].returnCode != 0) { + Log.info(rn[i].stdout); + Log.error(rn[i].stderr); rc = false; } } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileProperties.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileProperties.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileProperties.java Fri Aug 29 11:58:43 2014 -0700 @@ -38,20 +38,19 @@ import java.util.Map; import com.sun.tools.sjavac.options.Options; -import com.sun.tools.sjavac.server.JavacService; +import com.sun.tools.sjavac.server.Sjavac; /** * Compile properties transform a properties file into a Java source file. * Java has built in support for reading properties from either a text file * in the source or a compiled java source file. * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own - * risk. This code and its internal interfaces are subject to change - * or deletion without notice.

+ *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. */ -public class CompileProperties implements Transformer -{ +public class CompileProperties implements Transformer { // Any extra information passed from the command line, for example if: // -tr .proppp=com.sun.tools.javac.smart.CompileProperties,sun.util.resources.LocaleNamesBundle // then extra will be "sun.util.resources.LocaleNamesBundle" @@ -64,7 +63,7 @@ public void setExtra(Options a) { } - public boolean transform(JavacService javacService, + public boolean transform(Sjavac sjavac, Map> pkgSrcs, Set visibleSrcs, Map> visibleClasses, diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CopyFile.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CopyFile.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CopyFile.java Fri Aug 29 11:58:43 2014 -0700 @@ -32,16 +32,16 @@ import java.util.Map; import com.sun.tools.sjavac.options.Options; -import com.sun.tools.sjavac.server.JavacService; +import com.sun.tools.sjavac.server.Sjavac; /** * The copy file transform simply copies a matching file from -src to -d . * Such files are typically images, xml documents and other data files. * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own - * risk. This code and its internal interfaces are subject to change - * or deletion without notice.

+ *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. */ public class CopyFile implements Transformer { @@ -51,7 +51,7 @@ public void setExtra(Options a) { } - public boolean transform(JavacService javacService, + public boolean transform(Sjavac sjavac, Map> pkgSrcs, Set visibleSrcs, Map> visibleClasses, diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/JavacState.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/JavacState.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/JavacState.java Fri Aug 29 11:58:43 2014 -0700 @@ -26,7 +26,6 @@ package com.sun.tools.sjavac; import java.io.*; -import java.nio.file.Path; import java.util.Collections; import java.util.Date; import java.util.Set; @@ -39,20 +38,18 @@ import java.util.*; import com.sun.tools.sjavac.options.Options; -import com.sun.tools.sjavac.options.SourceLocation; -import com.sun.tools.sjavac.server.JavacService; +import com.sun.tools.sjavac.server.Sjavac; /** * The javac state class maintains the previous (prev) and the current (now) * build states and everything else that goes into the javac_state file. * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own - * risk. This code and its internal interfaces are subject to change - * or deletion without notice.

+ *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. */ -public class JavacState -{ +public class JavacState { // The arguments to the compile. If not identical, then it cannot // be an incremental build! String theArgs; @@ -60,7 +57,6 @@ int numCores; // The bin_dir/javac_state - private String javacStateFilename; private File javacState; // The previous build state is loaded from javac_state @@ -99,7 +95,7 @@ private Set recompiledPackages; // The output directories filled with tasty artifacts. - private File binDir, gensrcDir, headerDir; + private File binDir, gensrcDir, headerDir, stateDir; // The current status of the file system. private Set binArtifacts; @@ -128,7 +124,11 @@ // Where to send stdout and stderr. private PrintStream out, err; - JavacState(Options options, boolean removeJavacState, PrintStream o, PrintStream e) { + // Command line options. + private Options options; + + JavacState(Options op, boolean removeJavacState, PrintStream o, PrintStream e) { + options = op; out = o; err = e; numCores = options.getNumCores(); @@ -136,8 +136,8 @@ binDir = Util.pathToFile(options.getDestDir()); gensrcDir = Util.pathToFile(options.getGenSrcDir()); headerDir = Util.pathToFile(options.getHeaderDir()); - javacStateFilename = binDir.getPath()+File.separator+"javac_state"; - javacState = new File(javacStateFilename); + stateDir = Util.pathToFile(options.getStateDir()); + javacState = new File(stateDir, "javac_state"); if (removeJavacState && javacState.exists()) { javacState.delete(); } @@ -148,7 +148,7 @@ // We do not want to risk building a broken incremental build. // BUT since the makefiles still copy things straight into the bin_dir et al, // we avoid deleting files here, if the option --permit-unidentified-classes was supplied. - if (!options.isUnidentifiedArtifactPermitted()) { + if (!options.areUnidentifiedArtifactsPermitted()) { deleteContents(binDir); deleteContents(gensrcDir); deleteContents(headerDir); @@ -268,7 +268,7 @@ */ public void save() throws IOException { if (!needsSaving) return; - try (FileWriter out = new FileWriter(javacStateFilename)) { + try (FileWriter out = new FileWriter(javacState)) { StringBuilder b = new StringBuilder(); long millisNow = System.currentTimeMillis(); Date d = new Date(millisNow); @@ -311,7 +311,7 @@ boolean newCommandLine = false; boolean syntaxError = false; - try (BufferedReader in = new BufferedReader(new FileReader(db.javacStateFilename))) { + try (BufferedReader in = new BufferedReader(new FileReader(db.javacState))) { for (;;) { String l = in.readLine(); if (l==null) break; @@ -512,7 +512,8 @@ allKnownArtifacts.add(javacState); for (File f : binArtifacts) { - if (!allKnownArtifacts.contains(f)) { + if (!allKnownArtifacts.contains(f) && + !options.isUnidentifiedArtifactPermitted(f.getAbsolutePath())) { Log.debug("Removing "+f.getPath()+" since it is unknown to the javac_state."); f.delete(); } @@ -605,13 +606,16 @@ /** * Recursively delete a directory and all its contents. */ - private static void deleteContents(File dir) { + private void deleteContents(File dir) { if (dir != null && dir.exists()) { for (File f : dir.listFiles()) { if (f.isDirectory()) { deleteContents(f); } - f.delete(); + if (!options.isUnidentifiedArtifactPermitted(f.getAbsolutePath())) { + Log.debug("Removing "+f.getAbsolutePath()); + f.delete(); + } } } } @@ -648,7 +652,7 @@ /** * Compile all the java sources. Return true, if it needs to be called again! */ - public boolean performJavaCompilations(JavacService javacService, + public boolean performJavaCompilations(Sjavac sjavac, Options args, Set recentlyCompiled, boolean[] rcValue) { @@ -656,7 +660,7 @@ suffixRules.put(".java", compileJavaPackages); compileJavaPackages.setExtra(args); - rcValue[0] = perform(javacService, binDir, suffixRules); + rcValue[0] = perform(sjavac, binDir, suffixRules); recentlyCompiled.addAll(taintedPackages()); clearTaintedPackages(); boolean again = !packagesWithChangedPublicApis.isEmpty(); @@ -686,10 +690,9 @@ * For all packages, find all sources belonging to the package, group the sources * based on their transformers and apply the transformers on each source code group. */ - private boolean perform(JavacService javacService, + private boolean perform(Sjavac sjavac, File outputDir, - Map suffixRules) - { + Map suffixRules) { boolean rc = true; // Group sources based on transforms. A source file can only belong to a single transform. Map>> groupedSources = new HashMap<>(); @@ -713,7 +716,7 @@ Map packagePublicApis = Collections.synchronizedMap(new HashMap()); - boolean r = t.transform(javacService, + boolean r = t.transform(sjavac, srcs, visibleSrcs, visibleClasses, @@ -791,9 +794,7 @@ * Used to detect bugs where the makefile and sjavac have different opinions on which files * should be compiled. */ - public void compareWithMakefileList(File makefileSourceList) - throws ProblemException - { + public void compareWithMakefileList(File makefileSourceList) throws ProblemException { // If we are building on win32 using for example cygwin the paths in the makefile source list // might be /cygdrive/c/.... which does not match c:\.... // We need to adjust our calculated sources to be identical, if necessary. diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Log.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Log.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Log.java Fri Aug 29 11:58:43 2014 -0700 @@ -31,10 +31,10 @@ * Utility class only for sjavac logging. * The log level can be set using for example --log=DEBUG on the sjavac command line. * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own - * risk. This code and its internal interfaces are subject to change - * or deletion without notice.

+ *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. */ public class Log { private static PrintStream out, err; diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Main.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Main.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Main.java Fri Aug 29 11:58:43 2014 -0700 @@ -31,19 +31,21 @@ import java.nio.file.Path; import java.nio.file.Files; +import com.sun.tools.sjavac.client.SjavacClient; +import com.sun.tools.sjavac.comp.SjavacImpl; +import com.sun.tools.sjavac.comp.PooledSjavac; import com.sun.tools.sjavac.options.Options; import com.sun.tools.sjavac.options.SourceLocation; -import com.sun.tools.sjavac.server.JavacService; -import com.sun.tools.sjavac.server.JavacServer; -import com.sun.tools.sjavac.server.JavacServiceClient; +import com.sun.tools.sjavac.server.Sjavac; +import com.sun.tools.sjavac.server.SjavacServer; /** * The main class of the smart javac wrapper tool. * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own - * risk. This code and its internal interfaces are subject to change - * or deletion without notice.

+ *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. */ public class Main { @@ -163,13 +165,19 @@ return; } // Spawn a background server. - int rc = JavacServer.startServer(args[0], System.err); - System.exit(rc); + try { + SjavacServer server = new SjavacServer(args[0], System.err); + int rc = server.startServer(); + System.exit(rc); + } catch (IOException ioex) { + Log.error("IOException caught: " + ioex); + System.exit(-1); + } } Main main = new Main(); int rc = main.go(args, System.out, System.err); // Remove the portfile, but only if this background=false was used. - JavacServer.cleanup(args); + SjavacServer.cleanup(args); System.exit(rc); } @@ -205,6 +213,9 @@ if (!createIfMissing(options.getDestDir())) return -1; + if (!createIfMissing(options.getStateDir())) + return -1; + Path gensrc = options.getGenSrcDir(); if (gensrc != null && !createIfMissing(gensrc)) return -1; @@ -302,7 +313,7 @@ // For examples, files that have been manually copied into these dirs. // Artifacts with bad timestamps (ie the on disk timestamp does not match the timestamp // in javac_state) have already been removed when the javac_state was loaded. - if (!options.isUnidentifiedArtifactPermitted()) { + if (!options.areUnidentifiedArtifactsPermitted()) { javac_state.removeUnidentifiedArtifacts(); } // Go through all sources and taint all packages that miss artifacts. @@ -338,15 +349,22 @@ // Collect the name of all compiled packages. Set recently_compiled = new HashSet<>(); boolean[] rc = new boolean[1]; + Sjavac sjavac; + boolean background = Util.extractBooleanOption("background", options.getServerConf(), true); do { // Clean out artifacts in tainted packages. javac_state.deleteClassArtifactsInTaintedPackages(); - // Create a JavacService to delegate the actual compilation to. - // Currently sjavac always connects to a server through a socket - // regardless if sjavac runs as a background service or not. - // This will most likely change in the future. - JavacService javacService = new JavacServiceClient(options.getServerConf()); - again = javac_state.performJavaCompilations(javacService, options, recently_compiled, rc); + // Create an sjavac implementation to be used for compilation + if (background) { + sjavac = new SjavacClient(options); + } else { + int poolsize = Util.extractIntOption("poolsize", options.getServerConf()); + if (poolsize <= 0) + poolsize = Runtime.getRuntime().availableProcessors(); + sjavac = new PooledSjavac(new SjavacImpl(), poolsize); + } + + again = javac_state.performJavaCompilations(sjavac, options, recently_compiled, rc); if (!rc[0]) break; } while (again); // Only update the state if the compile went well. @@ -357,6 +375,8 @@ // Remove artifacts that were generated during the last compile, but not this one. javac_state.removeSuperfluousArtifacts(recently_compiled); } + if (!background) + sjavac.shutdown(); return rc[0] ? 0 : -1; } catch (ProblemException e) { Log.error(e.getMessage()); @@ -375,8 +395,6 @@ err = "Please specify output directory."; } else if (options.isJavaFilesAmongJavacArgs()) { err = "Sjavac does not handle explicit compilation of single .java files."; - } else if (options.isAtFilePresent()) { - err = "Sjavac does not handle @-files."; } else if (options.getServerConf() == null) { err = "No server configuration provided."; } else if (!options.getImplicitPolicy().equals("none")) { diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Module.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Module.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Module.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -36,10 +36,10 @@ * The module is the root of a set of packages/sources/artifacts. * At the moment there is only one module in use, the empty/no-name/default module. * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own - * risk. This code and its internal interfaces are subject to change - * or deletion without notice.

+ *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. */ public class Module implements Comparable { private String name; diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Package.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Package.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Package.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -35,6 +35,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import com.sun.tools.javac.util.Assert; /** * The Package class maintains meta information about a package. @@ -54,10 +55,10 @@ * the visible recompilation of the dependent packages indicates how much circular * dependencies your code has. * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own - * risk. This code and its internal interfaces are subject to change - * or deletion without notice.

+ *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. */ public class Package implements Comparable { // The module this package belongs to. (There is a legacy module with an empty string name, @@ -83,9 +84,9 @@ public Package(Module m, String n) { int c = n.indexOf(":"); - assert(c != -1); + Assert.check(c != -1); String mn = n.substring(0,c); - assert(m.name().equals(m.name())); + Assert.check(m.name().equals(m.name())); name = n; dirname = n.replace('.', File.separatorChar); if (m.name().length() > 0) { @@ -256,7 +257,7 @@ } public void setArtifacts(Set as) { - assert(!artifacts.isEmpty()); + Assert.check(!artifacts.isEmpty()); artifacts = new HashMap<>(); addArtifacts(as); } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/ProblemException.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/ProblemException.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/ProblemException.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -28,10 +28,10 @@ /** * Used to signal serious problems when running sjavac. * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own - * risk. This code and its internal interfaces are subject to change - * or deletion without notice.

+ *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. */ public class ProblemException extends Exception { static final long serialVersionUID = -3387516993124229949L; diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Source.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Source.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Source.java Fri Aug 29 11:58:43 2014 -0700 @@ -37,10 +37,10 @@ * The class also knows how to find source files (scanRoot) given include/exclude * patterns and a root. * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own - * risk. This code and its internal interfaces are subject to change - * or deletion without notice.

+ *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. */ public class Source implements Comparable { // The package the source belongs to. diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Transformer.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Transformer.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Transformer.java Fri Aug 29 11:58:43 2014 -0700 @@ -31,7 +31,7 @@ import java.util.Map; import com.sun.tools.sjavac.options.Options; -import com.sun.tools.sjavac.server.JavacService; +import com.sun.tools.sjavac.server.Sjavac; /** * The transform interface is used to transform content inside a package, from one form to another. @@ -39,13 +39,12 @@ * but can also be an unpredictable number of generated source files (eg idl2java) * or a single predictable output file (eg when copying,cleaning or compiling a properties file). * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own - * risk. This code and its internal interfaces are subject to change - * or deletion without notice.

+ *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. */ -public interface Transformer -{ +public interface Transformer { /** * The transform method takes a set of package names, mapped to their source files and to the * pubapis of the packages. @@ -83,7 +82,7 @@ * If num_cores is set to a non-zero value. The transform should attempt to use no more than these * number of threads for heavy work. */ - boolean transform(JavacService javacService, + boolean transform(Sjavac sjavac, Map> pkgSrcs, Set visibleSources, Map> visibleClasses, diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Util.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Util.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Util.java Fri Aug 29 11:58:43 2014 -0700 @@ -26,8 +26,6 @@ package com.sun.tools.sjavac; import java.io.File; -import java.io.FileWriter; -import java.io.IOException; import java.nio.file.Path; import java.util.Arrays; import java.util.HashSet; @@ -37,10 +35,10 @@ /** * Utilities. * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own - * risk. This code and its internal interfaces are subject to change - * or deletion without notice.

+ *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. */ public class Util { @@ -64,7 +62,8 @@ public static String justPackageName(String pkgName) { int c = pkgName.indexOf(":"); - assert(c != -1); + if (c == -1) + throw new IllegalArgumentException("Expected ':' in package name (" + pkgName + ")"); return pkgName.substring(c+1); } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,275 @@ +/* + * 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 com.sun.tools.sjavac.client; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.URI; +import java.util.List; +import java.util.Set; + +import com.sun.tools.sjavac.Log; +import com.sun.tools.sjavac.ProblemException; +import com.sun.tools.sjavac.Util; +import com.sun.tools.sjavac.server.CompilationResult; +import com.sun.tools.sjavac.server.PortFile; +import com.sun.tools.sjavac.server.Sjavac; +import com.sun.tools.sjavac.server.SjavacServer; +import com.sun.tools.sjavac.server.SysInfo; +import com.sun.tools.sjavac.options.Options; + +/** + * Sjavac implementation that delegates requests to a SjavacServer. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + */ +public class SjavacClient implements Sjavac { + + // The id can perhaps be used in the future by the javac server to reuse the + // JavaCompiler instance for several compiles using the same id. + private final String id; + private final String portfileName; + private final String logfile; + private final String stdouterrfile; + private final boolean background; + + // Default keepalive for server is 120 seconds. + // I.e. it will accept 120 seconds of inactivity before quitting. + private final int keepalive; + private final int poolsize; + + // The sjavac option specifies how the server part of sjavac is spawned. + // If you have the experimental sjavac in your path, you are done. If not, you have + // to point to a com.sun.tools.sjavac.Main that supports --startserver + // for example by setting: sjavac=java%20-jar%20...javac.jar%com.sun.tools.sjavac.Main + private final String sjavacForkCmd; + + // Wait 2 seconds for response, before giving up on javac server. + static int CONNECTION_TIMEOUT = 2000; + static int MAX_CONNECT_ATTEMPTS = 3; + static int WAIT_BETWEEN_CONNECT_ATTEMPTS = 2000; + + // Store the server conf settings here. + private final String settings; + + public SjavacClient(Options options) { + String tmpServerConf = options.getServerConf(); + String serverConf = (tmpServerConf!=null)? tmpServerConf : ""; + String tmpId = Util.extractStringOption("id", serverConf); + id = (tmpId!=null) ? tmpId : "id"+(((new java.util.Random()).nextLong())&Long.MAX_VALUE); + String p = Util.extractStringOption("portfile", serverConf); + portfileName = (p!=null) ? p : options.getStateDir().toFile().getAbsolutePath()+File.separatorChar+"javac_server"; + logfile = Util.extractStringOption("logfile", serverConf, portfileName + ".javaclog"); + stdouterrfile = Util.extractStringOption("stdouterrfile", serverConf, portfileName + ".stdouterr"); + background = Util.extractBooleanOption("background", serverConf, true); + sjavacForkCmd = Util.extractStringOption("sjavac", serverConf, "sjavac"); + int poolsize = Util.extractIntOption("poolsize", serverConf); + keepalive = Util.extractIntOption("keepalive", serverConf, 120); + + this.poolsize = poolsize > 0 ? poolsize : Runtime.getRuntime().availableProcessors(); + settings = (serverConf.equals("")) ? "id="+id+",portfile="+portfileName : serverConf; + } + + /** + * Hand out the server settings. + * @return The server settings, possibly a default value. + */ + public String serverSettings() { + return settings; + } + + /** + * Make a request to the server only to get the maximum possible heap size to use for compilations. + * + * @param port_file The port file used to synchronize creation of this server. + * @param id The identify of the compilation. + * @param out Standard out information. + * @param err Standard err information. + * @return The maximum heap size in bytes. + */ + @Override + public SysInfo getSysInfo() { + try (Socket socket = tryConnect()) { + // The ObjectInputStream constructor will block until the + // corresponding ObjectOutputStream has written and flushed the + // header, so it is important that the ObjectOutputStreams on server + // and client are opened before the ObjectInputStreams. + ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream()); + ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); + oos.writeObject(id); + oos.writeObject(SjavacServer.CMD_SYS_INFO); + oos.flush(); + return (SysInfo) ois.readObject(); + } catch (IOException | ClassNotFoundException ex) { + Log.error("[CLIENT] Exception caught: " + ex); + StringWriter sw = new StringWriter(); + ex.printStackTrace(new PrintWriter(sw)); + } + return null; + } + + @Override + public CompilationResult compile(String protocolId, + String invocationId, + String[] args, + List explicitSources, + Set sourcesToCompile, + Set visibleSources) { + CompilationResult result; + try (Socket socket = tryConnect()) { + // The ObjectInputStream constructor will block until the + // corresponding ObjectOutputStream has written and flushed the + // header, so it is important that the ObjectOutputStreams on server + // and client are opened before the ObjectInputStreams. + ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream()); + ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); + oos.writeObject(id); + oos.writeObject(SjavacServer.CMD_COMPILE); + oos.writeObject(protocolId); + oos.writeObject(invocationId); + oos.writeObject(args); + oos.writeObject(explicitSources); + oos.writeObject(sourcesToCompile); + oos.writeObject(visibleSources); + oos.flush(); + result = (CompilationResult) ois.readObject(); + } catch (IOException | ClassNotFoundException ex) { + Log.error("Exception caught: " + ex); + result = new CompilationResult(CompilationResult.ERROR_FATAL); + result.stderr = ex.getMessage(); + } + return result; + } + + private Socket tryConnect() throws IOException { + + PortFile portFile; + try { + // This should be taken care of at a higher level (JDK-8048451) + portFile = SjavacServer.getPortFile(portfileName); + } catch (FileNotFoundException e) { + // Reached for instance if directory of port file does not exist + Log.error("Port file inaccessable: " + e); + throw new RuntimeException(e); + } + for (int i = 0; i < MAX_CONNECT_ATTEMPTS; i++) { + Log.info(String.format("Trying to connect (attempt %d of %d)", + i+1, MAX_CONNECT_ATTEMPTS)); + try { + if (!makeSureServerIsRunning(portFile)) + continue; + Socket socket = new Socket(); + InetAddress localhost = InetAddress.getByName(null); + socket.connect(new InetSocketAddress(localhost, portFile.getPort()), + CONNECTION_TIMEOUT); + return socket; + } catch (ProblemException | IOException ex) { + Log.error("Caught exception during tryConnect: " + ex); + } + + try { + Thread.sleep(WAIT_BETWEEN_CONNECT_ATTEMPTS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + throw new IOException("Could not connect to server"); + } + + private boolean makeSureServerIsRunning(PortFile portFile) + throws IOException, ProblemException, FileNotFoundException { + + synchronized (portFile) { + portFile.lock(); + portFile.getValues(); + portFile.unlock(); + } + + if (!portFile.containsPortInfo()) { + String forkCmd = SjavacServer.fork(sjavacForkCmd, + portFile.getFilename(), + logfile, + poolsize, + keepalive, + System.err, + stdouterrfile, + background); + if (!portFile.waitForValidValues()) { + // This can be simplified once JDK-8048457 has been addressed + // since we won't have an SjavacClient if background = false + if (background) { + // There seems be some problem with spawning the external + // process (for instance no fork command provided and no + // sjavac on path) + StringWriter sw = new StringWriter(); + SjavacClient.printFailedAttempt(forkCmd, + stdouterrfile, + new PrintWriter(sw)); + Log.error(sw.toString()); + } + } + } + return portFile.containsPortInfo(); + } + + + public static void printFailedAttempt(String cmd, String f, PrintWriter err) { + err.println("---- Failed to start javac server with this command -----"); + err.println(cmd); + try { + BufferedReader in = new BufferedReader(new FileReader(f)); + err.println("---- stdout/stderr output from attempt to start javac server -----"); + for (;;) { + String l = in.readLine(); + if (l == null) { + break; + } + err.println(l); + } + err.println("------------------------------------------------------------------"); + } catch (Exception e) { + err.println("The stdout/stderr output in file " + f + " does not exist and the server did not start."); + } + } + + @Override + public void shutdown() { + // Nothing to clean up + } +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/AttrWithDeps.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/AttrWithDeps.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/AttrWithDeps.java Fri Aug 29 11:58:43 2014 -0700 @@ -30,10 +30,10 @@ /** Subclass to Attr that overrides reportDepedence. * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own - * risk. This code and its internal interfaces are subject to change - * or deletion without notice.

+ *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. */ public class AttrWithDeps extends Attr { diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/Dependencies.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/Dependencies.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/Dependencies.java Fri Aug 29 11:58:43 2014 -0700 @@ -34,6 +34,7 @@ import java.util.Set; import com.sun.tools.javac.code.Symbol.ClassSymbol; +import com.sun.tools.javac.util.Assert; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.Log; import com.sun.tools.javac.util.Name; @@ -41,10 +42,10 @@ /** Utility class containing dependency information between packages * and the pubapi for a package. * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own - * risk. This code and its internal interfaces are subject to change - * or deletion without notice.

+ *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. */ public class Dependencies { protected static final Context.Key dependenciesKey = new Context.Key<>(); @@ -154,7 +155,7 @@ Name n = ((ClassSymbol)e).fullname; Name p = ((ClassSymbol)e).packge().fullname; StringBuffer sb = publicApiPerClass.get(n); - assert(sb == null); + Assert.check(sb == null); sb = new StringBuffer(); PubapiVisitor v = new PubapiVisitor(sb); v.visit(e); diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/JavaCompilerWithDeps.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/JavaCompilerWithDeps.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/JavaCompilerWithDeps.java Fri Aug 29 11:58:43 2014 -0700 @@ -32,29 +32,29 @@ /** Subclass to Resolve that overrides collect. * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own - * risk. This code and its internal interfaces are subject to change - * or deletion without notice.

+ *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. */ public class JavaCompilerWithDeps extends JavaCompiler { /** The dependency database */ protected Dependencies deps; - protected JavacServiceImpl javacService; + protected SjavacErrorHandler errorHandler; - public JavaCompilerWithDeps(Context context, JavacServiceImpl jsi) { + public JavaCompilerWithDeps(Context context, SjavacErrorHandler eh) { super(context); deps = Dependencies.instance(context); - javacService = jsi; + errorHandler = eh; needRootClasses = true; } - public static void preRegister(Context context, final JavacServiceImpl t) { + public static void preRegister(Context context, final SjavacErrorHandler eh) { context.put(compilerKey, new Context.Factory() { public JavaCompiler make(Context c) { - JavaCompiler instance = new JavaCompilerWithDeps(c, t); + JavaCompiler instance = new JavaCompilerWithDeps(c, eh); c.put(JavaCompiler.class, instance); return instance; } @@ -97,7 +97,7 @@ // Now check if the truncated uri ends with the path. (It does not == failure!) if (path.length() > 0 && !path.equals("/unnamed package/") && !pp.endsWith(path)) { - javacService.logError("Error: The source file "+sym.sourcefile.getName()+ + errorHandler.logError("Error: The source file "+sym.sourcefile.getName()+ " is located in the wrong package directory, because it contains the class "+ sym.getQualifiedName()); } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/JavacServiceImpl.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/JavacServiceImpl.java Fri Aug 29 10:47:32 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,146 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. 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 com.sun.tools.sjavac.comp; - -import java.io.File; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.net.URI; -import java.util.Arrays; -import java.util.List; -import java.util.Set; - -import javax.tools.JavaCompiler.CompilationTask; -import javax.tools.JavaFileObject; -import javax.tools.StandardJavaFileManager; - -import com.sun.tools.javac.api.JavacTaskImpl; -import com.sun.tools.javac.api.JavacTool; -import com.sun.tools.javac.util.Context; -import com.sun.tools.javac.util.ListBuffer; -import com.sun.tools.sjavac.Util; -import com.sun.tools.sjavac.server.CompilationResult; -import com.sun.tools.sjavac.server.JavacServer; -import com.sun.tools.sjavac.server.JavacService; -import com.sun.tools.sjavac.server.SysInfo; - -public class JavacServiceImpl implements JavacService { - - JavacServer javacServer; - private ThreadLocal forcedExit; - - public JavacServiceImpl(JavacServer javacServer) { - this.javacServer = javacServer; - - } - - public void logError(String msg) { -// stderr.println(msg); - forcedExit.set(true); - } - - @Override - public SysInfo getSysInfo() { - return new SysInfo(Runtime.getRuntime().availableProcessors(), - Runtime.getRuntime().maxMemory()); - } - - @Override - public CompilationResult compile(String protocolId, - String invocationId, - String[] args, - List explicitSources, - Set sourcesToCompile, - Set visibleSources) { - - JavacTool compiler = JavacTool.create(); - StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null); - SmartFileManager smartFileManager = new SmartFileManager(fileManager); - Context context = new Context(); - ResolveWithDeps.preRegister(context); - AttrWithDeps.preRegister(context); - JavaCompilerWithDeps.preRegister(context, this); - - // Now setup the actual compilation.... - CompilationResult compilationResult = new CompilationResult(0); - - // First deal with explicit source files on cmdline and in at file. - ListBuffer compilationUnits = new ListBuffer<>(); - for (JavaFileObject i : fileManager.getJavaFileObjectsFromFiles(explicitSources)) { - compilationUnits.append(i); - } - // Now deal with sources supplied as source_to_compile. - ListBuffer sourcesToCompileFiles = new ListBuffer<>(); - for (URI u : sourcesToCompile) { - sourcesToCompileFiles.append(new File(u)); - } - for (JavaFileObject i : fileManager.getJavaFileObjectsFromFiles(sourcesToCompileFiles)) { - compilationUnits.append(i); - } - // Log the options to be used. - StringBuilder options = new StringBuilder(); - for (String s : args) { - options.append(">").append(s).append("< "); - } - javacServer.log(protocolId+" <"+invocationId+"> options "+options.toString()); - - forcedExit.set(false); - // Create a new logger. - StringWriter stdoutLog = new StringWriter(); - StringWriter stderrLog = new StringWriter(); - PrintWriter stdout = new PrintWriter(stdoutLog); - PrintWriter stderr = new PrintWriter(stderrLog); - com.sun.tools.javac.main.Main.Result rc = com.sun.tools.javac.main.Main.Result.OK; - try { - if (compilationUnits.size() > 0) { - smartFileManager.setVisibleSources(visibleSources); - smartFileManager.cleanArtifacts(); - smartFileManager.setLog(stdout); - - - // Do the compilation! - CompilationTask task = compiler.getTask(stderr, smartFileManager, null, Arrays.asList(args), null, compilationUnits, context); - rc = ((JavacTaskImpl) task).doCall(); - smartFileManager.flush(); - } - } catch (Exception e) { - stderr.println(e.getMessage()); - forcedExit.set(true); - } - - compilationResult.packageArtifacts = smartFileManager.getPackageArtifacts(); - - Dependencies deps = Dependencies.instance(context); - compilationResult.packageDependencies = deps.getDependencies(); - compilationResult.packagePubapis = deps.getPubapis(); - - compilationResult.stdout = stdoutLog.toString(); - compilationResult.stderr = stderrLog.toString(); - compilationResult.returnCode = rc.exitCode == 0 && forcedExit.get() ? -1 : rc.exitCode; - - return compilationResult; - } -} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PooledSjavac.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PooledSjavac.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,141 @@ +/* + * 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 com.sun.tools.sjavac.comp; + +import java.io.File; +import java.net.URI; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import com.sun.tools.sjavac.Log; +import com.sun.tools.sjavac.server.CompilationResult; +import com.sun.tools.sjavac.server.Sjavac; +import com.sun.tools.sjavac.server.SysInfo; + +/** + * An sjavac implementation that limits the number of concurrent calls by + * wrapping invocations in Callables and delegating them to a FixedThreadPool. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + */ +public class PooledSjavac implements Sjavac { + + final Sjavac delegate; + final ExecutorService pool; + + public PooledSjavac(Sjavac delegate, int poolsize) { + Objects.requireNonNull(delegate); + this.delegate = delegate; + pool = Executors.newFixedThreadPool(poolsize, new ThreadFactory() { + AtomicInteger count = new AtomicInteger(); + @Override + public Thread newThread(Runnable runnable) { + String cls = PooledSjavac.class.getSimpleName(); + int num = count.incrementAndGet(); + Thread t = new Thread(runnable, cls + "-" + num); + t.setDaemon(true); + return t; + } + }); + } + + @Override + public SysInfo getSysInfo() { + try { + return pool.submit(new Callable() { + @Override + public SysInfo call() throws Exception { + return delegate.getSysInfo(); + } + }).get(); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("Error during getSysInfo", e); + } + } + + @Override + public CompilationResult compile(final String protocolId, + final String invocationId, + final String[] args, + final List explicitSources, + final Set sourcesToCompile, + final Set visibleSources) { + try { + return pool.submit(new Callable() { + @Override + public CompilationResult call() throws Exception { + return delegate.compile(protocolId, + invocationId, + args, + explicitSources, + sourcesToCompile, + visibleSources); + } + }).get(); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("Error during compile", e); + } + } + + @Override + public void shutdown() { + pool.shutdown(); // Disable new tasks from being submitted + try { + // Wait a while for existing tasks to terminate + if (!pool.awaitTermination(60, TimeUnit.SECONDS)) { + pool.shutdownNow(); // Cancel currently executing tasks + // Wait a while for tasks to respond to being cancelled + if (!pool.awaitTermination(60, TimeUnit.SECONDS)) + Log.error("ThreadPool did not terminate"); + } + // Grace period for thread termination + Thread.sleep(1000); + } catch (InterruptedException ie) { + // (Re-)Cancel if current thread also interrupted + pool.shutdownNow(); + // Preserve interrupt status + Thread.currentThread().interrupt(); + } + + delegate.shutdown(); + } + + @Override + public String serverSettings() { + return delegate.serverSettings(); + } +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PubapiVisitor.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PubapiVisitor.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PubapiVisitor.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -37,10 +37,10 @@ /** Utility class that constructs a textual representation * of the public api of a class. * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own - * risk. This code and its internal interfaces are subject to change - * or deletion without notice.

+ *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. */ public class PubapiVisitor extends ElementScanner9 { diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/ResolveWithDeps.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/ResolveWithDeps.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/ResolveWithDeps.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -30,10 +30,10 @@ /** Subclass to Resolve that overrides collect. * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own - * risk. This code and its internal interfaces are subject to change - * or deletion without notice.

+ *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. */ public class ResolveWithDeps extends Resolve { diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacErrorHandler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacErrorHandler.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,36 @@ +/* + * 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 com.sun.tools.sjavac.comp; + +/** + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + */ +public interface SjavacErrorHandler { + void logError(String msg); +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,160 @@ +/* + * 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 com.sun.tools.sjavac.comp; + +import java.io.File; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.net.URI; +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; + +import javax.tools.JavaCompiler.CompilationTask; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; + +import com.sun.tools.javac.api.JavacTaskImpl; +import com.sun.tools.javac.api.JavacTool; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.ListBuffer; +import com.sun.tools.javac.util.Options; +import com.sun.tools.sjavac.server.CompilationResult; +import com.sun.tools.sjavac.server.Sjavac; +import com.sun.tools.sjavac.server.SysInfo; + +/** + * The sjavac implementation that interacts with javac and performs the actual + * compilation. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + */ +public class SjavacImpl implements Sjavac { + + @Override + public SysInfo getSysInfo() { + return new SysInfo(Runtime.getRuntime().availableProcessors(), + Runtime.getRuntime().maxMemory()); + } + + @Override + public CompilationResult compile(String protocolId, + String invocationId, + String[] args, + List explicitSources, + Set sourcesToCompile, + Set visibleSources) { + final AtomicBoolean forcedExit = new AtomicBoolean(); + + JavacTool compiler = JavacTool.create(); + StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null); + SmartFileManager smartFileManager = new SmartFileManager(fileManager); + Context context = new Context(); + ResolveWithDeps.preRegister(context); + AttrWithDeps.preRegister(context); + JavaCompilerWithDeps.preRegister(context, new SjavacErrorHandler() { + @Override + public void logError(String msg) { + forcedExit.set(true); + } + }); + + // Now setup the actual compilation.... + CompilationResult compilationResult = new CompilationResult(0); + + // First deal with explicit source files on cmdline and in at file. + ListBuffer compilationUnits = new ListBuffer<>(); + for (JavaFileObject i : fileManager.getJavaFileObjectsFromFiles(explicitSources)) { + compilationUnits.append(i); + } + // Now deal with sources supplied as source_to_compile. + ListBuffer sourcesToCompileFiles = new ListBuffer<>(); + for (URI u : sourcesToCompile) { + sourcesToCompileFiles.append(new File(u)); + } + for (JavaFileObject i : fileManager.getJavaFileObjectsFromFiles(sourcesToCompileFiles)) { + compilationUnits.append(i); + } + forcedExit.set(false); + // Create a new logger. + StringWriter stdoutLog = new StringWriter(); + StringWriter stderrLog = new StringWriter(); + PrintWriter stdout = new PrintWriter(stdoutLog); + PrintWriter stderr = new PrintWriter(stderrLog); + com.sun.tools.javac.main.Main.Result rc = com.sun.tools.javac.main.Main.Result.OK; + try { + if (compilationUnits.size() > 0) { + smartFileManager.setVisibleSources(visibleSources); + smartFileManager.cleanArtifacts(); + smartFileManager.setLog(stdout); + + // Do the compilation! + CompilationTask task = compiler.getTask(stderr, + smartFileManager, + null, + Arrays.asList(args), + null, + compilationUnits, + context); + smartFileManager.setSymbolFileEnabled(!Options.instance(context).isSet("ignore.symbol.file")); + rc = ((JavacTaskImpl) task).doCall(); + smartFileManager.flush(); + } + } catch (Exception e) { + stderrLog.append(e.getMessage()); + forcedExit.set(true); + } + + compilationResult.packageArtifacts = smartFileManager.getPackageArtifacts(); + + Dependencies deps = Dependencies.instance(context); + compilationResult.packageDependencies = deps.getDependencies(); + compilationResult.packagePubapis = deps.getPubapis(); + + compilationResult.stdout = stdoutLog.toString(); + compilationResult.stderr = stderrLog.toString(); + + compilationResult.returnCode = rc.exitCode == 0 && forcedExit.get() ? -1 : rc.exitCode; + + return compilationResult; + } + + @Override + public void shutdown() { + // Nothing to clean up + // ... maybe we should wait for any current request to finish? + } + + + @Override + public String serverSettings() { + return ""; + } + +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileManager.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileManager.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileManager.java Fri Aug 29 11:58:43 2014 -0700 @@ -37,7 +37,6 @@ import javax.tools.JavaFileObject.Kind; import com.sun.tools.javac.file.JavacFileManager; -import com.sun.tools.javac.util.BaseFileManager; import com.sun.tools.javac.util.ListBuffer; /** @@ -50,10 +49,10 @@ * Can also blind out the filemanager from seeing certain files in the file system. * Necessary to prevent javac from seeing some sources where the source path points. * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own - * risk. This code and its internal interfaces are subject to change - * or deletion without notice.

+ *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. */ public class SmartFileManager extends ForwardingJavaFileManager { @@ -97,9 +96,7 @@ public Iterable list(Location location, String packageName, Set kinds, - boolean recurse) - throws IOException - { + boolean recurse) throws IOException { // Acquire the list of files. Iterable files = super.list(location, packageName, kinds, recurse); if (visibleSources.isEmpty()) { @@ -112,8 +109,7 @@ String t = uri.toString(); if (t.startsWith("jar:") || t.endsWith(".class") - || visibleSources.contains(uri)) - { + || visibleSources.contains(uri)) { filteredFiles.add(f); } } @@ -128,9 +124,7 @@ @Override public JavaFileObject getJavaFileForInput(Location location, String className, - Kind kind) - throws IOException - { + Kind kind) throws IOException { JavaFileObject file = super.getJavaFileForInput(location, className, kind); if (file == null || visibleSources.isEmpty()) { return file; @@ -146,9 +140,7 @@ public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, - FileObject sibling) - throws IOException - { + FileObject sibling) throws IOException { JavaFileObject file = super.getJavaFileForOutput(location, className, kind, sibling); if (file == null) return file; int dp = className.lastIndexOf('.'); @@ -165,9 +157,7 @@ @Override public FileObject getFileForInput(Location location, String packageName, - String relativeName) - throws IOException - { + String relativeName) throws IOException { FileObject file = super.getFileForInput(location, packageName, relativeName); if (file == null || visibleSources.isEmpty()) { return file; @@ -183,9 +173,7 @@ public FileObject getFileForOutput(Location location, String packageName, String relativeName, - FileObject sibling) - throws IOException - { + FileObject sibling) throws IOException { FileObject file = super.getFileForOutput(location, packageName, relativeName, sibling); if (file == null) return file; if (location.equals(StandardLocation.NATIVE_HEADER_OUTPUT) && diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileObject.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileObject.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileObject.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -36,10 +36,10 @@ * and compare the new content with the old content on disk. Only if they differ, * will the file be updated. * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own - * risk. This code and its internal interfaces are subject to change - * or deletion without notice.

+ *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. */ public class SmartFileObject implements JavaFileObject { diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartWriter.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartWriter.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartWriter.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -34,9 +34,9 @@ * If not, the file is not touched. * *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own - * risk. This code and its internal interfaces are subject to change - * or deletion without notice.

+ * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. */ public class SmartWriter extends Writer { diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/ArgumentIterator.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/ArgumentIterator.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/ArgumentIterator.java Fri Aug 29 11:58:43 2014 -0700 @@ -27,6 +27,12 @@ import java.util.Iterator; +/** + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + */ public class ArgumentIterator implements Iterator { /** The underlying argument iterator */ diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/Option.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/Option.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/Option.java Fri Aug 29 11:58:43 2014 -0700 @@ -47,6 +47,11 @@ * This enum represents all options from (1) and (2). Note that instances of * this enum only entail static information about the option. For storage of * option values, refer to com.sun.tools.sjavac.options.Options. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. */ public enum Option { @@ -231,7 +236,14 @@ helper.logLevel("info"); } }, - PERMIT_UNIDENTIFIED_ARTIFACTS("--permit-unidentified-artifacts", "Keep unidentified artifacts in destination directory") { + PERMIT_ARTIFACT("--permit-artifact=", "Allow this artifact in destination directory") { + @Override + protected void processMatching(ArgumentIterator iter, OptionHelper helper) { + String a = iter.current().substring(arg.length()); + helper.permitArtifact(Paths.get(a).toFile().getAbsolutePath()); + } + }, + PERMIT_UNIDENTIFIED_ARTIFACTS("--permit-unidentified-artifacts", "Allow unidentified artifacts in destination directory") { @Override protected void processMatching(ArgumentIterator iter, OptionHelper helper) { helper.permitUnidentifiedArtifacts(); @@ -274,8 +286,16 @@ if (dir != null) helper.headerDir(dir); } + }, + STATE_DIR("--state-dir=", "Directory used to store sjavac state and log files.") { + @Override + protected void processMatching(ArgumentIterator iter, OptionHelper helper) { + String p = iter.current().substring(arg.length()); + helper.stateDir(Paths.get(p)); + } }; + public final String arg; final String description; diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/OptionHelper.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/OptionHelper.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/OptionHelper.java Fri Aug 29 11:58:43 2014 -0700 @@ -25,17 +25,23 @@ package com.sun.tools.sjavac.options; -import java.nio.file.Files; +import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; import java.util.List; +import com.sun.tools.javac.main.CommandLine; import com.sun.tools.sjavac.Transformer; /** * This class is used to decode sjavac options. * See com.sun.tools.sjavac.options.Options for example usage. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. */ public abstract class OptionHelper { @@ -78,6 +84,9 @@ /** Record path for reference source list */ public abstract void compareFoundSources(Path referenceList); + /** Record a single permitted artifact */ + public abstract void permitArtifact(String f); + /** Record the fact that unidentified artifacts are permitted */ public abstract void permitUnidentifiedArtifacts(); @@ -102,6 +111,9 @@ /** Sets the directory for generated headers */ public abstract void headerDir(Path dir); + /** Sets the directory for state and log files generated by sjavac */ + public abstract void stateDir(Path dir); + /** Sets the implicit policy */ public abstract void implicit(String policy); @@ -112,7 +124,11 @@ * @param args the arguments to traverse. */ void traverse(String[] args) { - + try { + args = CommandLine.parse(args); // Detect @file and load it as a command line. + } catch (java.io.IOException e) { + throw new IllegalArgumentException("Problem reading @"+e.getMessage()); + } ArgumentIterator argIter = new ArgumentIterator(Arrays.asList(args)); nextArg: diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/Options.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/Options.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/Options.java Fri Aug 29 11:58:43 2014 -0700 @@ -32,16 +32,23 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.HashSet; import com.sun.tools.sjavac.Transformer; /** * Instances of this class represent values for sjavac command line options. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. */ public class Options { // Output directories - private Path destDir, genSrcDir, headerDir; + private Path destDir, genSrcDir, headerDir, stateDir; // Input directories private List sources = new ArrayList<>(); @@ -51,7 +58,8 @@ private String logLevel = "info"; - private boolean permitUnidentifiedArtifact = false; + private Set permitted_artifacts = new HashSet<>(); + private boolean permitUnidentifiedArtifacts = false; private boolean permitSourcesInDefaultPackage = false; private Path sourceReferenceList; @@ -86,6 +94,11 @@ return headerDir; } + /** Get the path for the state directory, defaults to destDir. */ + public Path getStateDir() { + return stateDir != null ? stateDir : destDir; + } + /** Get all source locations for files to be compiled */ public List getSources() { return sources; @@ -114,10 +127,15 @@ return logLevel; } + /** Returns true iff the artifact is permitted in the output dir. */ + public boolean isUnidentifiedArtifactPermitted(String f) { + return permitted_artifacts.contains(f); + } + /** Returns true iff artifacts in the output directories should be kept, * even if they would not be generated in a clean build. */ - public boolean isUnidentifiedArtifactPermitted() { - return permitUnidentifiedArtifact; + public boolean areUnidentifiedArtifactsPermitted() { + return permitUnidentifiedArtifacts; } /** Returns true iff sources in the default package should be permitted. */ @@ -176,14 +194,6 @@ return false; } - /** Returns true iff an @-file is among the javac arguments */ - public boolean isAtFilePresent() { - for (String javacArg : javacArgs) - if (javacArg.startsWith("@")) - return true; - return false; - } - /** * Returns a string representation of the options that affect the result of * the compilation. (Used for saving the state of the options used in a @@ -239,6 +249,9 @@ if (destDir != null) args.addArg(Option.D, destDir.normalize()); + if (stateDir != null) + args.addArg(Option.STATE_DIR, stateDir.normalize()); + // Source roots args.addSourceLocations(Option.SRC, sources); args.addSourceLocations(Option.SOURCEPATH, sourceSearchPaths); @@ -249,7 +262,11 @@ if (permitSourcesInDefaultPackage) args.addArg(Option.PERMIT_SOURCES_WITHOUT_PACKAGE); - if (permitUnidentifiedArtifact) + for (String f : permitted_artifacts) { + args.addArg(Option.PERMIT_ARTIFACT, f); + } + + if (permitUnidentifiedArtifacts) args.addArg(Option.PERMIT_UNIDENTIFIED_ARTIFACTS); // Translation rules @@ -327,6 +344,7 @@ boolean headerProvided = false; boolean genSrcProvided = false; + boolean stateProvided = false; @Override public void reportError(String msg) { @@ -399,8 +417,13 @@ } @Override + public void permitArtifact(String f) { + permitted_artifacts.add(f); + } + + @Override public void permitUnidentifiedArtifacts() { - permitUnidentifiedArtifact = true; + permitUnidentifiedArtifacts = true; } @Override @@ -465,6 +488,16 @@ headerDir = dir.toAbsolutePath(); } + @Override + public void stateDir(Path dir) { + if (stateProvided) { + reportError("State directory already specified."); + return; + } + stateProvided = true; + stateDir = dir.toAbsolutePath(); + } + private List createSourceLocations(List paths) { List result = new ArrayList<>(); for (Path path : paths) { diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/SourceLocation.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/SourceLocation.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/SourceLocation.java Fri Aug 29 11:58:43 2014 -0700 @@ -37,6 +37,11 @@ /** * Represents a directory to be used for input to sjavac. (For instance a * sourcepath or classpath.) + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. */ public class SourceLocation { diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/CompilationResult.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/CompilationResult.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/CompilationResult.java Fri Aug 29 11:58:43 2014 -0700 @@ -25,28 +25,35 @@ package com.sun.tools.sjavac.server; +import java.io.Serializable; import java.net.URI; import java.util.HashMap; import java.util.Map; import java.util.Set; -public class CompilationResult { +/** + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + */ +public class CompilationResult implements Serializable { + + static final long serialVersionUID = 46739181113L; // Return code constants - public final static int ERROR_BUT_TRY_AGAIN = -4712; public final static int ERROR_FATAL = -1; public int returnCode; public Map> packageArtifacts = new HashMap<>(); public Map> packageDependencies = new HashMap<>(); public Map packagePubapis = new HashMap<>(); - public SysInfo sysinfo; - public String stdout; - public String stderr; + public String stdout = ""; + public String stderr = ""; public CompilationResult(int returnCode) { this.returnCode = returnCode; - this.sysinfo = new SysInfo(-1, -1); } public void setReturnCode(int returnCode) { diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/CompilerPool.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/CompilerPool.java Fri Aug 29 10:47:32 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,165 +0,0 @@ -/* - * Copyright (c) 2012, 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 com.sun.tools.sjavac.server; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Semaphore; -import java.util.Stack; -import java.util.concurrent.Future; - -import com.sun.tools.sjavac.comp.JavacServiceImpl; - -/** The compiler pool maintains compiler threads. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own - * risk. This code and its internal interfaces are subject to change - * or deletion without notice.

- */ -public class CompilerPool { - // The javac server that created this pool. - private JavacServer javacServer; - // A semaphore protecting the poolsize number of threads. - private Semaphore available; - // The stack of compiler threads. - private Stack compilers = new Stack<>(); - // And the executor server to spawn threads. - private final ExecutorService executorPool; - // How many requests are active right now? - private int concurrentRequests = 0; - // When was the last request finished? - private long lastRequestFinished = 0; - // The total number of requests to this pool. - private int numRequests = 0; - // Protect access to the three above values. - private static final Object conc = new Object(); - - /** - * Return the javac server that this pool belongs to. - */ - public JavacServer getJavacServer() { - return javacServer; - } - - /** - * Return how many threads are running at this very moment. - */ - public int numActiveRequests() - { - synchronized (conc) { - return concurrentRequests; - } - } - - /** - * Return when the last request was finished. - * I.e. the pool has been idle since. - */ - public long lastRequestFinished() - { - synchronized (conc) { - return lastRequestFinished; - } - } - - /** - * Up the number of active requests. - */ - public int startRequest() { - int n; - synchronized (conc) { - concurrentRequests++; - numRequests++; - n = numRequests; - } - return n; - } - - /** - * Down the number of active requests. Return the current time. - */ - public long stopRequest() { - synchronized (conc) { - concurrentRequests--; - lastRequestFinished = System.currentTimeMillis(); - } - return lastRequestFinished; - } - - /** - * Create a new compiler pool. - */ - CompilerPool(int poolsize, JavacServer server) { - available = new Semaphore(poolsize, true); - javacServer = server; - executorPool = Executors.newFixedThreadPool(poolsize); - lastRequestFinished = System.currentTimeMillis(); - } - - /** - * Execute a compiler thread. - */ - public void execute(CompilerThread ct) { - executorPool.execute(ct); - } - - /** - * Execute a minor task, for example generating bytecodes and writing them to disk, - * that belong to a major compiler thread task. - */ - public Future executeSubtask(CompilerThread t, Runnable r) { - return executorPool.submit(r); - } - - /** - * Shutdown the pool. - */ - public void shutdown() { - executorPool.shutdown(); - } - - /** - * Acquire a compiler thread from the pool, or block until a thread is available. - * If the pools is empty, create a new thread, but never more than is "available". - */ - public CompilerThread grabCompilerThread() throws InterruptedException { - available.acquire(); - if (compilers.empty()) { - return new CompilerThread(this, new JavacServiceImpl(javacServer)); - } - return compilers.pop(); - } - - /** - * Return the specified compiler thread to the pool. - */ - public void returnCompilerThread(CompilerThread h) { - compilers.push(h); - available.release(); - } -} - diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/CompilerThread.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/CompilerThread.java Fri Aug 29 10:47:32 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,412 +0,0 @@ -/* - * Copyright (c) 2012, 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 com.sun.tools.sjavac.server; - -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.net.Socket; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.Future; - -import javax.tools.JavaCompiler.CompilationTask; -import javax.tools.JavaFileObject; -import javax.tools.StandardJavaFileManager; - -import com.sun.tools.javac.api.JavacTaskImpl; -import com.sun.tools.javac.util.Context; -import com.sun.tools.javac.util.ListBuffer; -import com.sun.tools.javac.util.Options; -import com.sun.tools.javac.util.StringUtils; -import com.sun.tools.sjavac.comp.AttrWithDeps; -import com.sun.tools.sjavac.comp.Dependencies; -import com.sun.tools.sjavac.comp.JavaCompilerWithDeps; -import com.sun.tools.sjavac.comp.JavacServiceImpl; -import com.sun.tools.sjavac.comp.ResolveWithDeps; -import com.sun.tools.sjavac.comp.SmartFileManager; - -/** - * The compiler thread maintains a JavaCompiler instance and - * can receive a request from the client, perform the compilation - * requested and report back the results. - * - * *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own - * risk. This code and its internal interfaces are subject to change - * or deletion without notice.

- */ -public class CompilerThread implements Runnable { - private JavacServer javacServer; - private CompilerPool compilerPool; - private JavacServiceImpl javacServiceImpl; - private List> subTasks; - - // Communicating over this socket. - private Socket socket; - - // The necessary classes to do a compilation. - private com.sun.tools.javac.api.JavacTool compiler; - private StandardJavaFileManager fileManager; - private SmartFileManager smartFileManager; - private Context context; - - // If true, then this thread is serving a request. - private boolean inUse = false; - - CompilerThread(CompilerPool cp, JavacServiceImpl javacServiceImpl) { - compilerPool = cp; - javacServer = cp.getJavacServer(); - this.javacServiceImpl = javacServiceImpl; - } - - /** - * Execute a minor task, for example generating bytecodes and writing them to disk, - * that belong to a major compiler thread task. - */ - public synchronized void executeSubtask(Runnable r) { - subTasks.add(compilerPool.executeSubtask(this, r)); - } - - /** - * Count the number of active sub tasks. - */ - public synchronized int numActiveSubTasks() { - int c = 0; - for (Future f : subTasks) { - if (!f.isDone() && !f.isCancelled()) { - c++; - } - } - return c; - } - - /** - * Use this socket for the upcoming request. - */ - public void setSocket(Socket s) { - socket = s; - } - - /** - * Prepare the compiler thread for use. It is not yet started. - * It will be started by the executor service. - */ - public synchronized void use() { - assert(!inUse); - inUse = true; - compiler = com.sun.tools.javac.api.JavacTool.create(); - fileManager = compiler.getStandardFileManager(null, null, null); - smartFileManager = new SmartFileManager(fileManager); - context = new Context(); - ResolveWithDeps.preRegister(context); - AttrWithDeps.preRegister(context); - JavaCompilerWithDeps.preRegister(context, javacServiceImpl); - subTasks = new ArrayList<>(); - } - - /** - * Prepare the compiler thread for idleness. - */ - public synchronized void unuse() { - assert(inUse); - inUse = false; - compiler = null; - fileManager = null; - smartFileManager = null; - context = null; - subTasks = null; - } - - /** - * Expect this key on the next line read from the reader. - */ - private static boolean expect(BufferedReader in, String key) throws IOException { - String s = in.readLine(); - if (s != null && s.equals(key)) { - return true; - } - return false; - } - - // The request identifier, for example GENERATE_NEWBYTECODE - String id = ""; - - public String currentRequestId() { - return id; - } - - PrintWriter stdout; - PrintWriter stderr; - int forcedExitCode = 0; - - public void logError(String msg) { - stderr.println(msg); - forcedExitCode = -1; - } - - /** - * Invoked by the executor service. - */ - public void run() { - // Unique nr that identifies this request. - int thisRequest = compilerPool.startRequest(); - long start = System.currentTimeMillis(); - int numClasses = 0; - StringBuilder compiledPkgs = new StringBuilder(); - use(); - - PrintWriter out = null; - try { - javacServer.log("<"+thisRequest+"> Connect from "+socket.getRemoteSocketAddress()+" activethreads="+compilerPool.numActiveRequests()); - BufferedReader in = new BufferedReader(new InputStreamReader( - socket.getInputStream())); - out = new PrintWriter(new OutputStreamWriter( - socket.getOutputStream())); - if (!expect(in, JavacServer.PROTOCOL_COOKIE_VERSION)) { - javacServer.log("<"+thisRequest+"> Bad protocol from ip "+socket.getRemoteSocketAddress()); - return; - } - - String cookie = in.readLine(); - if (cookie == null || !cookie.equals(""+javacServer.getCookie())) { - javacServer.log("<"+thisRequest+"> Bad cookie from ip "+socket.getRemoteSocketAddress()); - return; - } - if (!expect(in, JavacServer.PROTOCOL_CWD)) { - return; - } - String cwd = in.readLine(); - if (cwd == null) - return; - if (!expect(in, JavacServer.PROTOCOL_ID)) { - return; - } - id = in.readLine(); - if (id == null) - return; - if (!expect(in, JavacServer.PROTOCOL_ARGS)) { - return; - } - ArrayList the_options = new ArrayList<>(); - ArrayList the_classes = new ArrayList<>(); - Iterable path = Arrays. asList(new File(cwd)); - - for (;;) { - String l = in.readLine(); - if (l == null) - return; - if (l.equals(JavacServer.PROTOCOL_SOURCES_TO_COMPILE)) - break; - if (l.startsWith("--server:")) - continue; - if (!l.startsWith("-") && l.endsWith(".java")) { - the_classes.add(new File(l)); - numClasses++; - } else { - the_options.add(l); - } - continue; - } - - // Load sources to compile - Set sourcesToCompile = new HashSet<>(); - for (;;) { - String l = in.readLine(); - if (l == null) - return; - if (l.equals(JavacServer.PROTOCOL_VISIBLE_SOURCES)) - break; - try { - sourcesToCompile.add(new URI(l)); - numClasses++; - } catch (URISyntaxException e) { - return; - } - } - // Load visible sources - Set visibleSources = new HashSet<>(); - boolean fix_drive_letter_case = - StringUtils.toLowerCase(System.getProperty("os.name")).startsWith("windows"); - for (;;) { - String l = in.readLine(); - if (l == null) - return; - if (l.equals(JavacServer.PROTOCOL_END)) - break; - try { - URI u = new URI(l); - if (fix_drive_letter_case) { - // Make sure the driver letter is lower case. - String s = u.toString(); - if (s.startsWith("file:/") && - Character.isUpperCase(s.charAt(6))) { - u = new URI("file:/"+Character.toLowerCase(s.charAt(6))+s.substring(7)); - } - } - visibleSources.add(u); - } catch (URISyntaxException e) { - return; - } - } - - // A completed request has been received. - - // Now setup the actual compilation.... - // First deal with explicit source files on cmdline and in at file. - ListBuffer compilationUnits = new ListBuffer<>(); - for (JavaFileObject i : fileManager.getJavaFileObjectsFromFiles(the_classes)) { - compilationUnits.append(i); - } - // Now deal with sources supplied as source_to_compile. - ListBuffer sourcesToCompileFiles = new ListBuffer<>(); - for (URI u : sourcesToCompile) { - sourcesToCompileFiles.append(new File(u)); - } - for (JavaFileObject i : fileManager.getJavaFileObjectsFromFiles(sourcesToCompileFiles)) { - compilationUnits.append(i); - } - // Log the options to be used. - StringBuilder options = new StringBuilder(); - for (String s : the_options) { - options.append(">").append(s).append("< "); - } - javacServer.log(id+" <"+thisRequest+"> options "+options.toString()); - - forcedExitCode = 0; - // Create a new logger. - StringWriter stdoutLog = new StringWriter(); - StringWriter stderrLog = new StringWriter(); - stdout = new PrintWriter(stdoutLog); - stderr = new PrintWriter(stderrLog); - com.sun.tools.javac.main.Main.Result rc = com.sun.tools.javac.main.Main.Result.OK; - try { - if (compilationUnits.size() > 0) { - smartFileManager.setVisibleSources(visibleSources); - smartFileManager.cleanArtifacts(); - smartFileManager.setLog(stdout); - - // Do the compilation! - CompilationTask task = compiler.getTask(stderr, smartFileManager, null, the_options, null, compilationUnits, context); - smartFileManager.setSymbolFileEnabled(!Options.instance(context).isSet("ignore.symbol.file")); - rc = ((JavacTaskImpl) task).doCall(); - - while (numActiveSubTasks()>0) { - try { Thread.sleep(1000); } catch (InterruptedException e) { } - } - - smartFileManager.flush(); - } - } catch (Exception e) { - stderr.println(e.getMessage()); - forcedExitCode = -1; - } - - // Send the response.. - out.println(JavacServer.PROTOCOL_STDOUT); - out.print(stdoutLog); - out.println(JavacServer.PROTOCOL_STDERR); - out.print(stderrLog); - // The compilation is complete! And errors will have already been printed on out! - out.println(JavacServer.PROTOCOL_PACKAGE_ARTIFACTS); - Map> pa = smartFileManager.getPackageArtifacts(); - for (String aPkgName : pa.keySet()) { - out.println("+"+aPkgName); - Set as = pa.get(aPkgName); - for (URI a : as) { - out.println(" "+a.toString()); - } - } - Dependencies deps = Dependencies.instance(context); - out.println(JavacServer.PROTOCOL_PACKAGE_DEPENDENCIES); - Map> pd = deps.getDependencies(); - for (String aPkgName : pd.keySet()) { - out.println("+"+aPkgName); - Set ds = pd.get(aPkgName); - // Everything depends on java.lang - if (!ds.contains(":java.lang")) ds.add(":java.lang"); - for (String d : ds) { - out.println(" "+d); - } - } - out.println(JavacServer.PROTOCOL_PACKAGE_PUBLIC_APIS); - Map pp = deps.getPubapis(); - for (String aPkgName : pp.keySet()) { - out.println("+"+aPkgName); - String ps = pp.get(aPkgName); - // getPubapis added a space to each line! - out.println(ps); - compiledPkgs.append(aPkgName+" "); - } - out.println(JavacServer.PROTOCOL_SYSINFO); - out.println("num_cores=" + Runtime.getRuntime().availableProcessors()); - out.println("max_memory=" + Runtime.getRuntime().maxMemory()); - out.println(JavacServer.PROTOCOL_RETURN_CODE); - - // Errors from sjavac that affect compilation status! - int rcv = rc.exitCode; - if (rcv == 0 && forcedExitCode != 0) { - rcv = forcedExitCode; - } - out.println("" + rcv); - out.println(JavacServer.PROTOCOL_END); - out.flush(); - } catch (IOException e) { - e.printStackTrace(); - } finally { - try { - if (out != null) out.close(); - if (!socket.isClosed()) { - socket.close(); - } - socket = null; - } catch (Exception e) { - javacServer.log("ERROR "+e); - e.printStackTrace(); - } - compilerPool.stopRequest(); - long duration = System.currentTimeMillis()-start; - javacServer.addBuildTime(duration); - float classpersec = ((float)numClasses)*(((float)1000.0)/((float)duration)); - javacServer.log(id+" <"+thisRequest+"> "+compiledPkgs+" duration " + duration+ " ms num_classes="+numClasses+ - " classpersec="+classpersec+" subtasks="+subTasks.size()); - javacServer.flushLog(); - unuse(); - compilerPool.returnCompilerThread(this); - } - } -} - diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/IdleResetSjavac.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/IdleResetSjavac.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,137 @@ +/* + * 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 com.sun.tools.sjavac.server; + +import java.io.File; +import java.net.URI; +import java.util.List; +import java.util.Set; +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * An sjavac implementation that keeps track of idleness and shuts down the + * given Terminable upon idleness timeout. + * + * An idleness timeout kicks in {@code idleTimeout} milliseconds after the last + * request is completed. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + */ +public class IdleResetSjavac implements Sjavac { + + private final Sjavac delegate; + private final AtomicInteger outstandingCalls = new AtomicInteger(); + private final Terminable toShutdown; + private final Timer idlenessTimer = new Timer(); + private final long idleTimeout; + + // Class invariant: idlenessTimerTask != null <-> idlenessTimerTask is scheduled + private TimerTask idlenessTimerTask; + + public IdleResetSjavac(Sjavac delegate, + Terminable toShutdown, + long idleTimeout) { + this.delegate = delegate; + this.toShutdown = toShutdown; + this.idleTimeout = idleTimeout; + scheduleTimeout(); + } + + @Override + public SysInfo getSysInfo() { + startCall(); + try { + return delegate.getSysInfo(); + } finally { + endCall(); + } + } + + @Override + public CompilationResult compile(String protocolId, + String invocationId, + String[] args, + List explicitSources, + Set sourcesToCompile, + Set visibleSources) { + startCall(); + try { + return delegate.compile(protocolId, + invocationId, + args, + explicitSources, + sourcesToCompile, + visibleSources); + } finally { + endCall(); + } + } + + private void startCall() { + // Was there no outstanding calls before this call? + if (outstandingCalls.incrementAndGet() == 1) { + // Then the timer task must have been scheduled + if (idlenessTimerTask == null) + throw new IllegalStateException("Idle timeout already cancelled"); + // Cancel timeout task + idlenessTimerTask.cancel(); + idlenessTimerTask = null; + } + } + + private void endCall() { + if (outstandingCalls.decrementAndGet() == 0) { + // No more outstanding calls. Schedule timeout. + scheduleTimeout(); + } + } + + private void scheduleTimeout() { + if (idlenessTimerTask != null) + throw new IllegalStateException("Idle timeout already scheduled"); + idlenessTimerTask = new TimerTask() { + public void run() { + toShutdown.shutdown("Server has been idle for " + (idleTimeout / 1000) + " seconds."); + } + }; + idlenessTimer.schedule(idlenessTimerTask, idleTimeout); + } + + @Override + public void shutdown() { + idlenessTimer.cancel(); + delegate.shutdown(); + } + + @Override + public String serverSettings() { + return delegate.serverSettings(); + } +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/JavacServer.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/JavacServer.java Fri Aug 29 10:47:32 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,382 +0,0 @@ -/* - * Copyright (c) 2011-2012, 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 com.sun.tools.sjavac.server; - -import java.io.File; -import java.io.IOException; -import java.io.PrintWriter; -import java.io.FileNotFoundException; -import java.util.HashMap; -import java.util.Map; - -import java.net.InetAddress; -import java.net.ServerSocket; -import java.net.Socket; -import java.util.ArrayList; -import java.util.Random; - -import com.sun.tools.sjavac.Util; -import com.sun.tools.sjavac.ProblemException; -import java.io.*; - -/** - * The JavacServer class contains methods both to setup a server that responds to requests and methods to connect to this server. - * - *

This is NOT part of any supported API. If you write code that depends on this, you do so at your own risk. This code and its internal interfaces are - * subject to change or deletion without notice.

- */ -public class JavacServer { - // Responding to this tcp/ip port on localhost. - - private final ServerSocket serverSocket; - // The secret cookie shared between server and client through the port file. - private final long myCookie; - // When the server was started. - private long serverStart; - // Accumulated build time for all requests, not counting idle time. - private long totalBuildTime; - // The javac server specific log file. - PrintWriter theLog; - // The compiler pool that maintains the compiler threads. - CompilerPool compilerPool; - // For the client, all port files fetched, one per started javac server. - // Though usually only one javac server is started by a client. - private static Map allPortFiles; - private static Map maxServerMemory; - final static String PROTOCOL_COOKIE_VERSION = "----THE-COOKIE-V2----"; - final static String PROTOCOL_CWD = "----THE-CWD----"; - final static String PROTOCOL_ID = "----THE-ID----"; - final static String PROTOCOL_ARGS = "----THE-ARGS----"; - final static String PROTOCOL_SOURCES_TO_COMPILE = "----THE-SOURCES-TO-COMPILE----"; - final static String PROTOCOL_VISIBLE_SOURCES = "----THE-VISIBLE-SOURCES----"; - final static String PROTOCOL_END = "----THE-END----"; - final static String PROTOCOL_STDOUT = "----THE-STDOUT----"; - final static String PROTOCOL_STDERR = "----THE-STDERR----"; - final static String PROTOCOL_PACKAGE_ARTIFACTS = "----THE-PACKAGE_ARTIFACTS----"; - final static String PROTOCOL_PACKAGE_DEPENDENCIES = "----THE-PACKAGE_DEPENDENCIES----"; - final static String PROTOCOL_PACKAGE_PUBLIC_APIS = "----THE-PACKAGE-PUBLIC-APIS----"; - final static String PROTOCOL_SYSINFO = "----THE-SYSINFO----"; - final static String PROTOCOL_RETURN_CODE = "----THE-RETURN-CODE----"; - // Check if the portfile is gone, every 5 seconds. - static int CHECK_PORTFILE_INTERVAL = 5; - // Wait 2 seconds for response, before giving up on javac server. - static int CONNECTION_TIMEOUT = 2; - static int WAIT_BETWEEN_CONNECT_ATTEMPTS = 1; - static int MAX_NUM_CONNECT_ATTEMPTS = 3; - - /** - * Acquire the port file. Synchronized since several threads inside an smart javac wrapper client acquires the same port file at the same time. - */ - public static synchronized PortFile getPortFile(String filename) throws FileNotFoundException { - if (allPortFiles == null) { - allPortFiles = new HashMap<>(); - } - PortFile pf = allPortFiles.get(filename); - - // Port file known. Does it still exist? - if (pf != null) { - try { - if (!pf.exists()) - pf = null; - } catch (IOException ioex) { - ioex.printStackTrace(); - } - } - - if (pf == null) { - pf = new PortFile(filename); - allPortFiles.put(filename, pf); - } - return pf; - } - - /** - * Get the cookie used for this server. - */ - long getCookie() { - return myCookie; - } - - /** - * Get the port used for this server. - */ - int getPort() { - return serverSocket.getLocalPort(); - } - - /** - * Sum up the total build time for this javac server. - */ - public void addBuildTime(long inc) { - totalBuildTime += inc; - } - - /** - * Log this message. - */ - public void log(String msg) { - if (theLog != null) { - theLog.println(msg); - } else { - System.err.println(msg); - } - } - - /** - * Make sure the log is flushed. - */ - public void flushLog() { - if (theLog != null) { - theLog.flush(); - } - } - - /** - * Start a server using a settings string. Typically: "--startserver:portfile=/tmp/myserver,poolsize=3" and the string "portfile=/tmp/myserver,poolsize=3" - * is sent as the settings parameter. Returns 0 on success, -1 on failure. - */ - public static int startServer(String settings, PrintStream err) { - try { - String portfile = Util.extractStringOption("portfile", settings); - // The log file collects more javac server specific log information. - String logfile = Util.extractStringOption("logfile", settings); - // The stdouterr file collects all the System.out and System.err writes to disk. - String stdouterrfile = Util.extractStringOption("stdouterrfile", settings); - // We could perhaps use System.setOut and setErr here. - // But for the moment we rely on the client to spawn a shell where stdout - // and stderr are redirected already. - // The pool size is a limit the number of concurrent compiler threads used. - // The server might use less than these to avoid memory problems. - int defaultPoolSize = Runtime.getRuntime().availableProcessors(); - int poolsize = Util.extractIntOption("poolsize", settings, defaultPoolSize); - - // How many seconds of inactivity will the server accept before quitting? - int keepalive = Util.extractIntOption("keepalive", settings, 120); - - // The port file is locked and the server port and cookie is written into it. - PortFile portFile = getPortFile(portfile); - JavacServer s; - - synchronized (portFile) { - portFile.lock(); - portFile.getValues(); - if (portFile.containsPortInfo()) { - err.println("Javac server not started because portfile exists!"); - portFile.unlock(); - return -1; - } - s = new JavacServer(poolsize, logfile); - portFile.setValues(s.getPort(), s.getCookie()); - portFile.unlock(); - } - - // Run the server. Will delete the port file when shutting down. - // It will shut down automatically when no new requests have come in - // during the last 125 seconds. - s.run(portFile, err, keepalive); - // The run loop for the server has exited. - return 0; - } catch (Exception e) { - e.printStackTrace(err); - return -1; - } - } - - /** - * Spawn the server instance. - */ - - private JavacServer(int poolSize, String logfile) throws IOException { - serverStart = System.currentTimeMillis(); - // Create a server socket on a random port that is bound to the localhost/127.0.0.1 interface. - // I.e only local processes can connect to this port. - serverSocket = new ServerSocket(0, 128, InetAddress.getByName(null)); - compilerPool = new CompilerPool(poolSize, this); - Random rnd = new Random(); - myCookie = rnd.nextLong(); - theLog = new PrintWriter(logfile); - log("Javac server started. port=" + getPort() + " date=" + (new java.util.Date()) + " with poolsize=" + poolSize); - flushLog(); - } - - /** - * Fork a background process. Returns the command line used that can be printed if something failed. - */ - public static String fork(String sjavac, String portfile, String logfile, int poolsize, int keepalive, - final PrintStream err, String stdouterrfile, boolean background) - throws IOException, ProblemException { - if (stdouterrfile != null && stdouterrfile.trim().equals("")) { - stdouterrfile = null; - } - final String startserver = "--startserver:portfile=" + portfile + ",logfile=" + logfile + ",stdouterrfile=" + stdouterrfile + ",poolsize=" + poolsize + ",keepalive="+ keepalive; - - if (background) { - sjavac += "%20" + startserver; - sjavac = sjavac.replaceAll("%20", " "); - sjavac = sjavac.replaceAll("%2C", ","); - // If the java/sh/cmd launcher fails the failure will be captured by stdouterr because of the redirection here. - String[] cmd = {"/bin/sh", "-c", sjavac + " >> " + stdouterrfile + " 2>&1"}; - if (!(new File("/bin/sh")).canExecute()) { - ArrayList wincmd = new ArrayList<>(); - wincmd.add("cmd"); - wincmd.add("/c"); - wincmd.add("start"); - wincmd.add("cmd"); - wincmd.add("/c"); - wincmd.add(sjavac + " >> " + stdouterrfile + " 2>&1"); - cmd = wincmd.toArray(new String[wincmd.size()]); - } - Process pp = null; - try { - pp = Runtime.getRuntime().exec(cmd); - } catch (Exception e) { - e.printStackTrace(err); - e.printStackTrace(new PrintWriter(stdouterrfile)); - } - StringBuilder rs = new StringBuilder(); - for (String s : cmd) { - rs.append(s + " "); - } - return rs.toString(); - } - - // Do not spawn a background server, instead run it within the same JVM. - Thread t = new Thread() { - @Override - public void run() { - try { - JavacServer.startServer(startserver, err); - } catch (Throwable t) { - t.printStackTrace(err); - } - } - }; - t.start(); - return ""; - } - - /** - * Run the server thread until it exits. Either because of inactivity or because the port file has been deleted by someone else, or overtaken by some other - * javac server. - */ - private void run(PortFile portFile, PrintStream err, int keepalive) { - boolean fileDeleted = false; - long timeSinceLastCompile; - try { - // Every 5 second (check_portfile_interval) we test if the portfile has disappeared => quit - // Or if the last request was finished more than 125 seconds ago => quit - // 125 = seconds_of_inactivity_before_shutdown+check_portfile_interval - serverSocket.setSoTimeout(CHECK_PORTFILE_INTERVAL*1000); - for (;;) { - try { - Socket s = serverSocket.accept(); - CompilerThread ct = compilerPool.grabCompilerThread(); - ct.setSocket(s); - compilerPool.execute(ct); - flushLog(); - } catch (java.net.SocketTimeoutException e) { - if (compilerPool.numActiveRequests() > 0) { - // Never quit while there are active requests! - continue; - } - // If this is the timeout after the portfile - // has been deleted by us. Then we truly stop. - if (fileDeleted) { - log("Quitting because of "+(keepalive+CHECK_PORTFILE_INTERVAL)+" seconds of inactivity!"); - break; - } - // Check if the portfile is still there. - if (!portFile.exists()) { - // Time to quit because the portfile was deleted by another - // process, probably by the makefile that is done building. - log("Quitting because portfile was deleted!"); - flushLog(); - break; - } - // Check if portfile.stop is still there. - if (portFile.markedForStop()) { - // Time to quit because another process touched the file - // server.port.stop to signal that the server should stop. - // This is necessary on some operating systems that lock - // the port file hard! - log("Quitting because a portfile.stop file was found!"); - portFile.delete(); - flushLog(); - break; - } - // Does the portfile still point to me? - if (!portFile.stillMyValues()) { - // Time to quit because another build has started. - log("Quitting because portfile is now owned by another javac server!"); - flushLog(); - break; - } - - // Check how long since the last request finished. - long diff = System.currentTimeMillis() - compilerPool.lastRequestFinished(); - if (diff < keepalive * 1000) { - // Do not quit if we have waited less than 120 seconds. - continue; - } - // Ok, time to quit because of inactivity. Perhaps the build - // was killed and the portfile not cleaned up properly. - portFile.delete(); - fileDeleted = true; - log("" + keepalive + " seconds of inactivity quitting in " - + CHECK_PORTFILE_INTERVAL + " seconds!"); - flushLog(); - // Now we have a second 5 second grace - // period where javac remote requests - // that have loaded the data from the - // recently deleted portfile can connect - // and complete their requests. - } - } - } catch (Exception e) { - e.printStackTrace(err); - e.printStackTrace(theLog); - flushLog(); - } finally { - compilerPool.shutdown(); - } - long realTime = System.currentTimeMillis() - serverStart; - log("Shutting down."); - log("Total wall clock time " + realTime + "ms build time " + totalBuildTime + "ms"); - flushLog(); - } - - public static void cleanup(String... args) { - String settings = Util.findServerSettings(args); - if (settings == null) return; - String portfile = Util.extractStringOption("portfile", settings); - String background = Util.extractStringOption("background", settings); - if (background != null && background.equals("false")) { - // If the server runs within this jvm, then delete the portfile, - // since this jvm is about to exit soon. - File f = new File(portfile); - f.delete(); - } - } -} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/JavacService.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/JavacService.java Fri Aug 29 10:47:32 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. 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 com.sun.tools.sjavac.server; - -import java.io.File; -import java.net.URI; -import java.util.List; -import java.util.Set; - -public interface JavacService { - - SysInfo getSysInfo(); - - CompilationResult compile(String protocolId, - String invocationId, - String[] args, - List explicitSources, - Set sourcesToCompile, - Set visibleSources); -} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/JavacServiceClient.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/JavacServiceClient.java Fri Aug 29 10:47:32 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,433 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. 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 com.sun.tools.sjavac.server; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.PrintStream; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.net.SocketAddress; -import java.net.URI; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import com.sun.tools.sjavac.Util; - -import static com.sun.tools.sjavac.server.CompilationResult.ERROR_BUT_TRY_AGAIN; -import static com.sun.tools.sjavac.server.CompilationResult.ERROR_FATAL; - -public class JavacServiceClient implements JavacService { - - - // The id can perhaps be used in the future by the javac server to reuse the - // JavaCompiler instance for several compiles using the same id. - private final String id; - private final String portfile; - private final String logfile; - private final String stdouterrfile; - private final boolean background; - - // Default keepalive for server is 120 seconds. - // I.e. it will accept 120 seconds of inactivity before quitting. - private final int keepalive; - private final int poolsize; - - // The sjavac option specifies how the server part of sjavac is spawned. - // If you have the experimental sjavac in your path, you are done. If not, you have - // to point to a com.sun.tools.sjavac.Main that supports --startserver - // for example by setting: sjavac=java%20-jar%20...javac.jar%com.sun.tools.sjavac.Main - private final String sjavac; - - public JavacServiceClient(String settings) { - id = Util.extractStringOption("id", settings); - portfile = Util.extractStringOption("portfile", settings); - logfile = Util.extractStringOption("logfile", settings, portfile + ".javaclog"); - stdouterrfile = Util.extractStringOption("stdouterrfile", settings, portfile + ".stdouterr"); - background = Util.extractBooleanOption("background", settings, true); - sjavac = Util.extractStringOption("sjavac", settings, "sjavac"); - int poolsize = Util.extractIntOption("poolsize", settings); - keepalive = Util.extractIntOption("keepalive", settings, 120); - - this.poolsize = poolsize > 0 ? poolsize : Runtime.getRuntime().availableProcessors(); - } - - - /** - * Make a request to the server only to get the maximum possible heap size to use for compilations. - * - * @param port_file The port file used to synchronize creation of this server. - * @param id The identify of the compilation. - * @param out Standard out information. - * @param err Standard err information. - * @return The maximum heap size in bytes. - */ - @Override - public SysInfo getSysInfo() { - try { - CompilationResult cr = useServer(new String[0], - Collections.emptySet(), - Collections.emptySet(), - Collections.>emptyMap()); - return cr.sysinfo; - } catch (Exception e) { - return new SysInfo(-1, -1); - } - } - - @Override - public CompilationResult compile(String protocolId, - String invocationId, - String[] args, - List explicitSources, - Set sourcesToCompile, - Set visibleSources) { - // Delegate to useServer, which delegates to compileHelper - return useServer(args, sourcesToCompile, visibleSources, null); - } - - /** - * Connect and compile using the javac server settings and the args. When using more advanced features, the sources_to_compile and visible_sources are - * supplied to the server and meta data is returned in package_artifacts, package_dependencies and package_pubapis. - */ - public CompilationResult compileHelper(String id, - String[] args, - Set sourcesToCompile, - Set visibleSources) { - - CompilationResult rc = new CompilationResult(-3); - - try { - PortFile portFile = JavacServer.getPortFile(this.portfile); - - int port = portFile.containsPortInfo() ? portFile.getPort() : 0; - if (port == 0) { - return new CompilationResult(ERROR_BUT_TRY_AGAIN); - } - long cookie = portFile.getCookie(); - // Acquire the localhost/127.0.0.1 address. - InetAddress addr = InetAddress.getByName(null); - SocketAddress sockaddr = new InetSocketAddress(addr, port); - Socket sock = new Socket(); - int timeoutMs = JavacServer.CONNECTION_TIMEOUT * 1000; - try { - sock.connect(sockaddr, timeoutMs); - } catch (java.net.ConnectException e) { - rc.setReturnCode(ERROR_BUT_TRY_AGAIN); - rc.stderr = "Could not connect to javac server found in portfile: " + portFile.getFilename() + " " + e; - return rc; - } - if (!sock.isConnected()) { - rc.setReturnCode(ERROR_BUT_TRY_AGAIN); - rc.stderr = "Could not connect to javac server found in portfile: " + portFile.getFilename(); - return rc; - } - - // - // Send arguments - // - BufferedReader in = new BufferedReader(new InputStreamReader(sock.getInputStream())); - PrintWriter sockout = new PrintWriter(sock.getOutputStream()); - - sockout.println(JavacServer.PROTOCOL_COOKIE_VERSION); - sockout.println("" + cookie); - sockout.println(JavacServer.PROTOCOL_CWD); - sockout.println(System.getProperty("user.dir")); - sockout.println(JavacServer.PROTOCOL_ID); - sockout.println(id); - sockout.println(JavacServer.PROTOCOL_ARGS); - for (String s : args) { - StringBuffer buf = new StringBuffer(); - String[] paths = s.split(File.pathSeparator); - int c = 0; - for (String path : paths) { - File f = new File(path); - if (f.isFile() || f.isDirectory()) { - buf.append(f.getAbsolutePath()); - c++; - if (c < paths.length) { - buf.append(File.pathSeparator); - } - } else { - buf = new StringBuffer(s); - break; - } - } - sockout.println(buf.toString()); - } - sockout.println(JavacServer.PROTOCOL_SOURCES_TO_COMPILE); - for (URI uri : sourcesToCompile) { - sockout.println(uri.toString()); - } - sockout.println(JavacServer.PROTOCOL_VISIBLE_SOURCES); - for (URI uri : visibleSources) { - sockout.println(uri.toString()); - } - sockout.println(JavacServer.PROTOCOL_END); - sockout.flush(); - - // - // Receive result - // - StringBuffer stdout = new StringBuffer(); - StringBuffer stderr = new StringBuffer(); - - if (!JavacServiceClient.expect(in, JavacServer.PROTOCOL_STDOUT)) { - return new CompilationResult(ERROR_FATAL); - } - // Load stdout - for (;;) { - String l = in.readLine(); - if (l == null) { - return new CompilationResult(ERROR_FATAL); - } - if (l.equals(JavacServer.PROTOCOL_STDERR)) { - break; - } - stdout.append(l); - stdout.append('\n'); - } - // Load stderr - for (;;) { - String l = in.readLine(); - if (l == null) { - return new CompilationResult(ERROR_FATAL); - } - if (l.equals(JavacServer.PROTOCOL_PACKAGE_ARTIFACTS)) { - break; - } - stderr.append(l); - stderr.append('\n'); - } - // Load the package artifacts - Set lastUriSet = null; - for (;;) { - String l = in.readLine(); - if (l == null) { - return new CompilationResult(ERROR_FATAL); - } - if (l.equals(JavacServer.PROTOCOL_PACKAGE_DEPENDENCIES)) { - break; - } - if (l.length() > 1 && l.charAt(0) == '+') { - String pkg = l.substring(1); - lastUriSet = new HashSet<>(); - rc.packageArtifacts.put(pkg, lastUriSet); - } else if (l.length() > 1 && lastUriSet != null) { - lastUriSet.add(new URI(l.substring(1))); - } - } - // Load package dependencies - Set lastPackageSet = null; - for (;;) { - String l = in.readLine(); - if (l == null) { - return new CompilationResult(ERROR_FATAL); - } - if (l.equals(JavacServer.PROTOCOL_PACKAGE_PUBLIC_APIS)) { - break; - } - if (l.length() > 1 && l.charAt(0) == '+') { - String pkg = l.substring(1); - lastPackageSet = new HashSet<>(); - rc.packageDependencies.put(pkg, lastPackageSet); - } else if (l.length() > 1 && lastPackageSet != null) { - lastPackageSet.add(l.substring(1)); - } - } - // Load package pubapis - Map tmp = new HashMap<>(); - StringBuffer lastPublicApi = null; - for (;;) { - String l = in.readLine(); - if (l == null) { - return new CompilationResult(ERROR_FATAL); - } - if (l.equals(JavacServer.PROTOCOL_SYSINFO)) { - break; - } - if (l.length() > 1 && l.charAt(0) == '+') { - String pkg = l.substring(1); - lastPublicApi = new StringBuffer(); - tmp.put(pkg, lastPublicApi); - } else if (l.length() > 1 && lastPublicApi != null) { - lastPublicApi.append(l.substring(1)); - lastPublicApi.append("\n"); - } - } - for (String p : tmp.keySet()) { - //assert (packagePublicApis.get(p) == null); - String api = tmp.get(p).toString(); - rc.packagePubapis.put(p, api); - } - // Now reading the max memory possible. - for (;;) { - String l = in.readLine(); - if (l == null) { - return new CompilationResult(ERROR_FATAL); - } - if (l.equals(JavacServer.PROTOCOL_RETURN_CODE)) { - break; - } - if (l.startsWith("num_cores=")) { - rc.sysinfo.numCores = Integer.parseInt(l.substring(10)); - } - if (l.startsWith("max_memory=")) { - rc.sysinfo.maxMemory = Long.parseLong(l.substring(11)); - } - } - String l = in.readLine(); - if (l == null) { - rc.setReturnCode(ERROR_FATAL); - rc.stderr = "No return value from the server!"; - return rc; - } - rc.setReturnCode(Integer.parseInt(l)); - rc.stdout = stdout.toString(); - rc.stderr = stderr.toString(); - } catch (Exception e) { - StringWriter sw = new StringWriter(); - e.printStackTrace(new PrintWriter(sw)); - rc.stderr = sw.toString(); - } - return rc; - } - - /** - * Dispatch a compilation request to a javac server. - * - * @param args are the command line args to javac and is allowed to contain source files, @file and other command line options to javac. - * - * The generated classes, h files and other artifacts from the javac invocation are stored by the javac server to disk. - * - * @param sources_to_compile The sources to compile. - * - * @param visibleSources If visible sources has a non zero size, then visible_sources are the only files in the file system that the javac server can see! - * (Sources to compile are always visible.) The visible sources are those supplied by the (filtered) -sourcepath - * - * @param visibleClasses If visible classes for a specific root/jar has a non zero size, then visible_classes are the only class files that the javac server - * can see, in that root/jar. It maps from a classpath root or a jar file to the set of visible classes for that root/jar. - * - * The server return meta data about the build in the following parameters. - * @param package_artifacts, map from package name to set of created artifacts for that package. - * @param package_dependencies, map from package name to set of packages that it depends upon. - * @param package_pubapis, map from package name to unique string identifying its pub api. - */ - public CompilationResult useServer(String[] args, - Set sourcesToCompile, - Set visibleSources, - Map> visibleClasses) { - try { - if (portfile == null) { - CompilationResult cr = new CompilationResult(CompilationResult.ERROR_FATAL); - cr.stderr = "No portfile was specified!"; - return cr; - } - - int attempts = 0; - CompilationResult rc; - do { - PortFile port_file = JavacServer.getPortFile(portfile); - synchronized (port_file) { - port_file.lock(); - port_file.getValues(); - port_file.unlock(); - } - if (!port_file.containsPortInfo()) { - String cmd = JavacServer.fork(sjavac, port_file.getFilename(), logfile, poolsize, keepalive, System.err, stdouterrfile, background); - - if (background && !port_file.waitForValidValues()) { - // Ouch the server did not start! Lets print its stdouterrfile and the command used. - StringWriter sw = new StringWriter(); - JavacServiceClient.printFailedAttempt(cmd, stdouterrfile, new PrintWriter(sw)); - // And give up. - CompilationResult cr = new CompilationResult(ERROR_FATAL); - cr.stderr = sw.toString(); - return cr; - } - } - rc = compileHelper(id, args, sourcesToCompile, visibleSources); - // Try again until we manage to connect. Any error after that - // will cause the compilation to fail. - if (rc.returnCode == CompilationResult.ERROR_BUT_TRY_AGAIN) { - // We could not connect to the server. Try again. - attempts++; - try { - Thread.sleep(JavacServer.WAIT_BETWEEN_CONNECT_ATTEMPTS * 1000); - } catch (InterruptedException e) { - } - } - } while (rc.returnCode == ERROR_BUT_TRY_AGAIN && attempts < JavacServer.MAX_NUM_CONNECT_ATTEMPTS); - return rc; - } catch (Exception e) { - StringWriter sw = new StringWriter(); - e.printStackTrace(new PrintWriter(sw)); - CompilationResult cr = new CompilationResult(ERROR_FATAL); - cr.stderr = sw.toString(); - return cr; - } - } - - public static void printFailedAttempt(String cmd, String f, PrintWriter err) { - err.println("---- Failed to start javac server with this command -----"); - err.println(cmd); - try { - BufferedReader in = new BufferedReader(new FileReader(f)); - err.println("---- stdout/stderr output from attempt to start javac server -----"); - for (;;) { - String l = in.readLine(); - if (l == null) { - break; - } - err.println(l); - } - err.println("------------------------------------------------------------------"); - } catch (Exception e) { - err.println("The stdout/stderr output in file " + f + " does not exist and the server did not start."); - } - } - - /** - * Expect this key on the next line read from the reader. - */ - public static boolean expect(BufferedReader in, String key) throws IOException { - String s = in.readLine(); - if (s != null && s.equals(key)) { - return true; - } - return false; - } -} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFile.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFile.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFile.java Fri Aug 29 11:58:43 2014 -0700 @@ -33,6 +33,7 @@ import java.nio.channels.FileChannel; import java.nio.channels.FileLock; import java.nio.channels.FileLockInterruptionException; +import com.sun.tools.javac.util.Assert; import com.sun.tools.sjavac.Log; /** @@ -41,12 +42,12 @@ * primitives to avoid race conditions when several javac clients are started at the same. Note that file * system locking is not always supported on a all operating systems and/or file systems. * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own - * risk. This code and its internal interfaces are subject to change - * or deletion without notice.

+ *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. */ -class PortFile { +public class PortFile { // Port file format: // byte ordering: high byte first = big endian @@ -72,8 +73,7 @@ * Create a new portfile. * @param filename is the path to the file. */ - public PortFile(String fn) throws FileNotFoundException - { + public PortFile(String fn) throws FileNotFoundException { filename = fn; file = new File(filename); stopFile = new File(filename+".stop"); @@ -88,7 +88,7 @@ /** * Lock the port file. */ - void lock() throws IOException { + public void lock() throws IOException { lock = channel.lock(); } @@ -115,7 +115,7 @@ containsPortInfo = false; } } - } catch (Exception e) { + } catch (IOException e) { containsPortInfo = false; } } @@ -131,7 +131,7 @@ * If so, then we can acquire the tcp/ip port on localhost. */ public int getPort() { - assert(containsPortInfo); + Assert.check(containsPortInfo); return serverPort; } @@ -139,7 +139,7 @@ * If so, then we can acquire the server cookie. */ public long getCookie() { - assert(containsPortInfo); + Assert.check(containsPortInfo); return serverCookie; } @@ -147,7 +147,7 @@ * Store the values into the locked port file. */ public void setValues(int port, long cookie) throws IOException { - assert(lock != null); + Assert.check(lock != null); rwfile.seek(0); // Write the magic nr that identifes a port file. rwfile.writeInt(magicNr); @@ -192,7 +192,7 @@ * Unlock the port file. */ public void unlock() throws IOException { - assert(lock != null); + Assert.check(lock != null); lock.release(); lock = null; } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFileMonitor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFileMonitor.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,88 @@ +/* + * 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 com.sun.tools.sjavac.server; + +import java.io.IOException; +import java.util.Timer; +import java.util.TimerTask; + +/** + * Monitors the presence of a port file and shuts down the given SjavacServer + * whenever the port file is deleted or invalidated. + * + * TODO: JDK-8046882 + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + */ +public class PortFileMonitor { + + // Check if the portfile is gone, every 5 seconds. + private final static int CHECK_PORTFILE_INTERVAL = 5000; + + final private Timer timer = new Timer(); + final private PortFile portFile; + final private SjavacServer server; + + public PortFileMonitor(PortFile portFile, + SjavacServer server) { + this.portFile = portFile; + this.server = server; + } + + public void start() { + TimerTask shutdownCheck = new TimerTask() { + public void run() { + try { + if (!portFile.exists()) { + // Time to quit because the portfile was deleted by another + // process, probably by the makefile that is done building. + server.shutdown("Quitting because portfile was deleted!"); + } else if (portFile.markedForStop()) { + // Time to quit because another process touched the file + // server.port.stop to signal that the server should stop. + // This is necessary on some operating systems that lock + // the port file hard! + server.shutdown("Quitting because a portfile.stop file was found!"); + } else if (!portFile.stillMyValues()) { + // Time to quit because another build has started. + server.shutdown("Quitting because portfile is now owned by another javac server!"); + } + } catch (IOException e) { + e.printStackTrace(server.theLog); + server.flushLog(); + } + } + }; + + timer.schedule(shutdownCheck, 0, CHECK_PORTFILE_INTERVAL); + } + + public void shutdown() { + timer.cancel(); + } +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/RequestHandler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/RequestHandler.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,120 @@ +/* + * 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 com.sun.tools.sjavac.server; + +import java.io.File; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.net.Socket; +import java.net.URI; +import java.util.List; +import java.util.Set; + +import com.sun.tools.sjavac.Log; + +/** + * A RequestHandler handles requests performed over a socket. Specifically it + * - Reads the command string specifying which method is to be invoked + * - Reads the appropriate arguments + * - Delegates the actual invocation to the given sjavac implementation + * - Writes the result back to the socket output stream + * + * None of the work performed by this class is really bound by the CPU. It + * should be completely fine to have a large number of RequestHandlers active. + * To limit the number of concurrent compilations, use PooledSjavac. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + */ +public class RequestHandler implements Runnable { + + private final Socket socket; + private final Sjavac sjavac; + + public RequestHandler(Socket socket, Sjavac sjavac) { + this.socket = socket; + this.sjavac = sjavac; + } + + @Override + public void run() { + try (ObjectOutputStream oout = new ObjectOutputStream(socket.getOutputStream()); + ObjectInputStream oin = new ObjectInputStream(socket.getInputStream())) { + String id = (String) oin.readObject(); + String cmd = (String) oin.readObject(); + Log.info("Handling request, id: " + id + " cmd: " + cmd); + switch (cmd) { + case SjavacServer.CMD_SYS_INFO: handleSysInfoRequest(oin, oout); break; + case SjavacServer.CMD_COMPILE: handleCompileRequest(oin, oout); break; + default: Log.error("Unknown command: " + cmd); + } + } catch (Exception ex) { + // Not much to be done at this point. The client side request + // code will most likely throw an IOException and the + // compilation will fail. + StringWriter sw = new StringWriter(); + ex.printStackTrace(new PrintWriter(sw)); + Log.error(sw.toString()); + } + } + + private void handleSysInfoRequest(ObjectInputStream oin, + ObjectOutputStream oout) throws IOException { + oout.writeObject(sjavac.getSysInfo()); + oout.flush(); + } + + @SuppressWarnings("unchecked") + private void handleCompileRequest(ObjectInputStream oin, + ObjectOutputStream oout) throws IOException { + try { + // Read request arguments + String protocolId = (String) oin.readObject(); + String invocationId = (String) oin.readObject(); + String[] args = (String[]) oin.readObject(); + List explicitSources = (List) oin.readObject(); + Set sourcesToCompile = (Set) oin.readObject(); + Set visibleSources = (Set) oin.readObject(); + + // Perform compilation + CompilationResult cr = sjavac.compile(protocolId, + invocationId, + args, + explicitSources, + sourcesToCompile, + visibleSources); + // Write request response + oout.writeObject(cr); + oout.flush(); + } catch (ClassNotFoundException cnfe) { + throw new IOException(cnfe); + } + } +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/Sjavac.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/Sjavac.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,54 @@ +/* + * 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 com.sun.tools.sjavac.server; + +import java.io.File; +import java.net.URI; +import java.util.List; +import java.util.Set; + +/** + * Interface of the SjavacImpl, the sjavac client and all wrappers such as + * PooledSjavac etc. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + */ +public interface Sjavac { + + SysInfo getSysInfo(); + + CompilationResult compile(String protocolId, + String invocationId, + String[] args, + List explicitSources, + Set sourcesToCompile, + Set visibleSources); + + void shutdown(); + String serverSettings(); +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SjavacServer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SjavacServer.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,349 @@ +/* + * Copyright (c) 2011, 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 com.sun.tools.sjavac.server; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; +import java.util.concurrent.atomic.AtomicBoolean; + +import com.sun.tools.sjavac.ProblemException; +import com.sun.tools.sjavac.Util; +import com.sun.tools.sjavac.comp.SjavacImpl; +import com.sun.tools.sjavac.comp.PooledSjavac; + +/** + * The JavacServer class contains methods both to setup a server that responds to requests and methods to connect to this server. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + */ +public class SjavacServer implements Terminable { + + // Used in protocol to indicate which method to invoke + public final static String CMD_COMPILE = "compile"; + public final static String CMD_SYS_INFO = "sys-info"; + + final private String portfilename; + final private String logfile; + final private String stdouterrfile; + final private int poolsize; + final private int keepalive; + final private PrintStream err; + + // The secret cookie shared between server and client through the port file. + // Used to prevent clients from believing that they are communicating with + // an old server when a new server has started and reused the same port as + // an old server. + private final long myCookie; + + // Accumulated build time, not counting idle time, used for logging purposes + private long totalBuildTime; + + // The javac server specific log file. + PrintWriter theLog; + + // The sjavac implementation to delegate requests to + Sjavac sjavac; + + private ServerSocket serverSocket; + + private PortFile portFile; + private PortFileMonitor portFileMonitor; + + // Set to false break accept loop + final AtomicBoolean keepAcceptingRequests = new AtomicBoolean(); + + // For the client, all port files fetched, one per started javac server. + // Though usually only one javac server is started by a client. + private static Map allPortFiles; + private static Map maxServerMemory; + + public SjavacServer(String settings, PrintStream err) throws FileNotFoundException { + // Extract options. TODO: Change to proper constructor args + portfilename = Util.extractStringOption("portfile", settings); + logfile = Util.extractStringOption("logfile", settings); + stdouterrfile = Util.extractStringOption("stdouterrfile", settings); + keepalive = Util.extractIntOption("keepalive", settings, 120); + poolsize = Util.extractIntOption("poolsize", settings, + Runtime.getRuntime().availableProcessors()); + this.err = err; + + myCookie = new Random().nextLong(); + theLog = new PrintWriter(logfile); + } + + + /** + * Acquire the port file. Synchronized since several threads inside an smart javac wrapper client acquires the same port file at the same time. + */ + public static synchronized PortFile getPortFile(String filename) throws FileNotFoundException { + if (allPortFiles == null) { + allPortFiles = new HashMap<>(); + } + PortFile pf = allPortFiles.get(filename); + + // Port file known. Does it still exist? + if (pf != null) { + try { + if (!pf.exists()) + pf = null; + } catch (IOException ioex) { + ioex.printStackTrace(); + } + } + + if (pf == null) { + pf = new PortFile(filename); + allPortFiles.put(filename, pf); + } + return pf; + } + + /** + * Get the cookie used for this server. + */ + long getCookie() { + return myCookie; + } + + /** + * Get the port used for this server. + */ + int getPort() { + return serverSocket.getLocalPort(); + } + + /** + * Sum up the total build time for this javac server. + */ + public void addBuildTime(long inc) { + totalBuildTime += inc; + } + + /** + * Log this message. + */ + public void log(String msg) { + if (theLog != null) { + theLog.println(msg); + } else { + System.err.println(msg); + } + } + + /** + * Make sure the log is flushed. + */ + public void flushLog() { + if (theLog != null) { + theLog.flush(); + } + } + + /** + * Start a server using a settings string. Typically: "--startserver:portfile=/tmp/myserver,poolsize=3" and the string "portfile=/tmp/myserver,poolsize=3" + * is sent as the settings parameter. Returns 0 on success, -1 on failure. + */ + public int startServer() throws IOException { + long serverStart = System.currentTimeMillis(); + + // The port file is locked and the server port and cookie is written into it. + portFile = getPortFile(portfilename); + + synchronized (portFile) { + portFile.lock(); + portFile.getValues(); + if (portFile.containsPortInfo()) { + err.println("Javac server not started because portfile exists!"); + portFile.unlock(); + return -1; + } + + // .-----------. .--------. .------. + // socket -->| IdleReset |-->| Pooled |-->| Impl |--> javac + // '-----------' '--------' '------' + sjavac = new SjavacImpl(); + sjavac = new PooledSjavac(sjavac, poolsize); + sjavac = new IdleResetSjavac(sjavac, + this, + keepalive * 1000); + + serverSocket = new ServerSocket(); + InetAddress localhost = InetAddress.getByName(null); + serverSocket.bind(new InetSocketAddress(localhost, 0)); + + // At this point the server accepts connections, so it is now safe + // to publish the port / cookie information + portFile.setValues(getPort(), getCookie()); + portFile.unlock(); + } + + portFileMonitor = new PortFileMonitor(portFile, this); + portFileMonitor.start(); + + log("Sjavac server started. Accepting connections..."); + log(" port: " + getPort()); + log(" time: " + new java.util.Date()); + log(" poolsize: " + poolsize); + flushLog(); + + keepAcceptingRequests.set(true); + do { + try { + Socket socket = serverSocket.accept(); + new Thread(new RequestHandler(socket, sjavac)).start(); + } catch (SocketException se) { + // Caused by serverSocket.close() and indicates shutdown + } + } while (keepAcceptingRequests.get()); + + log("Shutting down."); + + // No more connections accepted. If any client managed to connect after + // the accept() was interrupted but before the server socket is closed + // here, any attempt to read or write to the socket will result in an + // IOException on the client side. + + long realTime = System.currentTimeMillis() - serverStart; + log("Total wall clock time " + realTime + "ms build time " + totalBuildTime + "ms"); + flushLog(); + + // Shut down + sjavac.shutdown(); + + return 0; + } + + /** + * Fork a background process. Returns the command line used that can be printed if something failed. + */ + public static String fork(String sjavac, String portfile, String logfile, int poolsize, int keepalive, + final PrintStream err, String stdouterrfile, boolean background) + throws IOException, ProblemException { + if (stdouterrfile != null && stdouterrfile.trim().equals("")) { + stdouterrfile = null; + } + final String startserver = "--startserver:portfile=" + portfile + ",logfile=" + logfile + ",stdouterrfile=" + stdouterrfile + ",poolsize=" + poolsize + ",keepalive="+ keepalive; + + if (background) { + sjavac += "%20" + startserver; + sjavac = sjavac.replaceAll("%20", " "); + sjavac = sjavac.replaceAll("%2C", ","); + // If the java/sh/cmd launcher fails the failure will be captured by stdouterr because of the redirection here. + String[] cmd = {"/bin/sh", "-c", sjavac + " >> " + stdouterrfile + " 2>&1"}; + if (!(new File("/bin/sh")).canExecute()) { + ArrayList wincmd = new ArrayList<>(); + wincmd.add("cmd"); + wincmd.add("/c"); + wincmd.add("start"); + wincmd.add("cmd"); + wincmd.add("/c"); + wincmd.add(sjavac + " >> " + stdouterrfile + " 2>&1"); + cmd = wincmd.toArray(new String[wincmd.size()]); + } + Process pp = null; + try { + pp = Runtime.getRuntime().exec(cmd); + } catch (Exception e) { + e.printStackTrace(err); + e.printStackTrace(new PrintWriter(stdouterrfile)); + } + StringBuilder rs = new StringBuilder(); + for (String s : cmd) { + rs.append(s + " "); + } + return rs.toString(); + } + + // Do not spawn a background server, instead run it within the same JVM. + Thread t = new Thread() { + @Override + public void run() { + try { + SjavacServer server = new SjavacServer(startserver, err); + server.startServer(); + } catch (Throwable t) { + t.printStackTrace(err); + } + } + }; + t.setDaemon(true); + t.start(); + return ""; + } + + @Override + public void shutdown(String quitMsg) { + if (!keepAcceptingRequests.compareAndSet(false, true)) { + // Already stopped, no need to shut down again + return; + } + + log("Quitting: " + quitMsg); + flushLog(); + + portFileMonitor.shutdown(); // No longer any need to monitor port file + + // Unpublish port before shutting down socket to minimize the number of + // failed connection attempts + try { + portFile.delete(); + } catch (IOException e) { + e.printStackTrace(theLog); + } + try { + serverSocket.close(); + } catch (IOException e) { + e.printStackTrace(theLog); + } + } + + public static void cleanup(String... args) { + String settings = Util.findServerSettings(args); + if (settings == null) return; + String portfile = Util.extractStringOption("portfile", settings); + String background = Util.extractStringOption("background", settings); + if (background != null && background.equals("false")) { + // If the server runs within this jvm, then delete the portfile, + // since this jvm is about to exit soon. + File f = new File(portfile); + f.delete(); + } + } +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SysInfo.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SysInfo.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SysInfo.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -34,7 +34,18 @@ */ package com.sun.tools.sjavac.server; -public class SysInfo { +import java.io.Serializable; + +/** + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + */ +public class SysInfo implements Serializable { + + static final long serialVersionUID = -3096346807579L; + public int numCores; public long maxMemory; diff -r aa7ada31eb77 -r 317aad3480c8 langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/Terminable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/Terminable.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,35 @@ +/* + * 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 com.sun.tools.sjavac.server; + +/** + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + */ +public interface Terminable { + void shutdown(String quitMsg); +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/com/sun/javadoc/lib/JavadocTester.java --- a/langtools/test/com/sun/javadoc/lib/JavadocTester.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/com/sun/javadoc/lib/JavadocTester.java Fri Aug 29 11:58:43 2014 -0700 @@ -38,6 +38,7 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.nio.file.Files; +import java.util.Arrays; import java.util.ArrayList; import java.util.EnumMap; import java.util.HashMap; @@ -290,6 +291,7 @@ break; } } + out.println("args: " + Arrays.toString(args)); // log.setOutDir(outputDir); outputDirectoryCheck.check(outputDir); diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/apt/Basics/CheckAptIsRemovedTest.java --- a/langtools/test/tools/apt/Basics/CheckAptIsRemovedTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/apt/Basics/CheckAptIsRemovedTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -25,7 +25,7 @@ * @test * @bug 4908512 5024825 4957203 4993280 4996963 6174696 6177059 7041249 * @summary Make sure apt is removed and doesn't come back - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main CheckAptIsRemovedTest */ @@ -34,7 +34,7 @@ import java.nio.file.Path; import java.nio.file.Paths; -//original test: test/tools/apt/Basics/apt.sh +// Original test: test/tools/apt/Basics/apt.sh public class CheckAptIsRemovedTest { //I think this class can be let with the imports only and that should be enough for as test's purpose private static final String NullAPFSrc = @@ -77,20 +77,18 @@ Path aptLin = Paths.get(testJDK, "bin", "apt"); Path aptWin = Paths.get(testJDK, "bin", "apt.exe"); -// if [ -f "${TESTJAVA}/bin/apt" -o -f "${TESTJAVA}/bin/apt.exe" ];then if (Files.exists(aptLin) || Files.exists(aptWin)) { throw new AssertionError("apt executable should not exist"); } -// JAVAC="${TESTJAVA}/bin/javac ${TESTTOOLVMOPTS} -source 1.5 -sourcepath ${TESTSRC} -classpath ${TESTJAVA}/lib/tools.jar -d . " -// $JAVAC ${TESTSRC}/NullAPF.java Path classpath = Paths.get(testJDK, "lib", "tools.jar"); - ToolBox.JavaToolArgs javacArgs = - new ToolBox.JavaToolArgs(ToolBox.Expect.FAIL) - .setOptions("-sourcepath", ".", - "-classpath", classpath.toString()) - .setSources(NullAPFSrc); - ToolBox.javac(javacArgs); + ToolBox tb = new ToolBox(); + tb.new JavacTask() + .classpath(classpath.toString()) // TODO: add overload + .sourcepath(".") + .sources(NullAPFSrc) + .run(ToolBox.Expect.FAIL) + .writeAll(); } } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/4846262/CheckEBCDICLocaleTest.java --- a/langtools/test/tools/javac/4846262/CheckEBCDICLocaleTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/4846262/CheckEBCDICLocaleTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -25,15 +25,17 @@ * @test * @bug 4846262 * @summary check that javac operates correctly in EBCDIC locale - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main CheckEBCDICLocaleTest */ import java.io.File; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; +import java.util.List; public class CheckEBCDICLocaleTest { @@ -58,39 +60,32 @@ } public void test() throws Exception { - String native2asciiBinary = Paths.get( - System.getProperty("test.jdk"),"bin", "native2ascii").toString(); - - ToolBox.createJavaFileFromSource(TestSrc); - Files.createDirectory(Paths.get("output")); + ToolBox tb = new ToolBox(); + Path native2asciiBinary = tb.getJDKTool("native2ascii"); - ToolBox.AnyToolArgs nativeCmdParams = - new ToolBox.AnyToolArgs() - .appendArgs(native2asciiBinary) - .appendArgs(ToolBox.testToolVMOpts) - .appendArgs("-reverse", "-encoding", "IBM1047", "Test.java", - "output/Test.java"); - ToolBox.executeCommand(nativeCmdParams); + tb.writeFile("Test.java", TestSrc); + tb.createDirectories("output"); + + tb.new ExecTask(native2asciiBinary) + .args("-reverse", "-encoding", "IBM1047", "Test.java", "output/Test.java") + .run(); - ToolBox.AnyToolArgs javacParams = - new ToolBox.AnyToolArgs(ToolBox.Expect.FAIL) - .appendArgs(ToolBox.javacBinary) - .appendArgs(ToolBox.testToolVMOpts) - .appendArgs("-J-Duser.language=en", - "-J-Duser.region=US", "-J-Dfile.encoding=IBM1047", - "output/Test.java") - .setErrOutput(new File("Test.tmp")); - ToolBox.executeCommand(javacParams); + tb.new JavacTask(ToolBox.Mode.EXEC) + .redirect(ToolBox.OutputKind.STDERR, "Test.tmp") + .options("-J-Duser.language=en", + "-J-Duser.region=US", + "-J-Dfile.encoding=IBM1047") + .files("output/Test.java") + .run(ToolBox.Expect.FAIL); - nativeCmdParams = new ToolBox.AnyToolArgs() - .appendArgs(native2asciiBinary) - .appendArgs(ToolBox.testToolVMOpts) - .appendArgs("-encoding", "IBM1047", "Test.tmp", "Test.out"); - ToolBox.executeCommand(nativeCmdParams); + tb.new ExecTask(native2asciiBinary) + .args("-encoding", "IBM1047", "Test.tmp", "Test.out") + .run(); - String goldenFile = String.format(TestOutTemplate, File.separator); - ToolBox.compareLines(Paths.get("Test.out"), - Arrays.asList(goldenFile.split("\n")), null, true); + List expectLines = Arrays.asList( + String.format(TestOutTemplate, File.separator).split("\n")); + List actualLines = Files.readAllLines(Paths.get("Test.out")); + tb.checkEqual(expectLines, actualLines); } } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/6302184/HiddenOptionsShouldUseGivenEncodingTest.java --- a/langtools/test/tools/javac/6302184/HiddenOptionsShouldUseGivenEncodingTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/6302184/HiddenOptionsShouldUseGivenEncodingTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -26,7 +26,7 @@ * @bug 6302184 6350124 6357979 * @summary javac hidden options that generate source should use the given * encoding, if available - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run compile -encoding iso-8859-1 -XD-printsource T6302184.java * @run main HiddenOptionsShouldUseGivenEncodingTest @@ -34,16 +34,19 @@ import java.nio.file.Path; import java.nio.file.Paths; +import java.util.List; -//original test: test/tools/javac/6302184/T6302184.sh +// Original test: test/tools/javac/6302184/T6302184.sh public class HiddenOptionsShouldUseGivenEncodingTest { public static void main(String[] args) throws Exception { -//"${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d ${TC} -cp ${TC} -encoding iso-8859-1 -XD-printsource ${TS}${FS}T6302184.java 2>&1 -//diff ${DIFFOPTS} -c ${TC}${FS}T6302184.java ${TS}${FS}T6302184.out - Path path1 = Paths.get(System.getProperty("test.classes"), "T6302184.java"); - Path path2 = Paths.get(System.getProperty("test.src"), "T6302184.out"); - ToolBox.compareLines(path1, path2, "iso-8859-1"); + ToolBox tb = new ToolBox(); + String encoding = "iso-8859-1"; + Path path1 = Paths.get(ToolBox.testClasses, "T6302184.java"); + List file1 = tb.readAllLines(path1, encoding); + Path path2 = Paths.get(ToolBox.testSrc, "T6302184.out"); + List file2 = tb.readAllLines(path2, encoding); + tb.checkEqual(file1, file2); } } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/AnonymousSubclassTest.java --- a/langtools/test/tools/javac/AnonymousSubclassTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/AnonymousSubclassTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -25,19 +25,18 @@ * @test * @bug 8023945 * @summary javac wrongly allows a subclass of an anonymous class - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main AnonymousSubclassTest */ -import java.util.ArrayList; -import java.io.IOException; - public class AnonymousSubclassTest { public static void main(String... args) throws Exception { new AnonymousSubclassTest().run(); } + ToolBox tb = new ToolBox(); + // To trigger the error we want, first we need to compile // a class with an anonymous inner class: Foo$1. final String foo = @@ -65,20 +64,21 @@ "}"; void compOk(String code) throws Exception { - ToolBox.javac(new ToolBox.JavaToolArgs().setSources(code)); + tb.new JavacTask() + .sources(code) + .run(); } void compFail(String code) throws Exception { - ArrayList errors = new ArrayList<>(); - ToolBox.JavaToolArgs args = new ToolBox.JavaToolArgs(); - args.setSources(code) - .appendArgs("-cp", ".", "-XDrawDiagnostics") - .set(ToolBox.Expect.FAIL) - .setErrOutput(errors); - ToolBox.javac(args); + String errs = tb.new JavacTask() + .sources(code) + .classpath(".") + .options("-XDrawDiagnostics") + .run(ToolBox.Expect.FAIL) + .writeAll() + .getOutput(ToolBox.OutputKind.DIRECT); - if (!errors.get(0).contains("cant.inherit.from.anon")) { - System.out.println(errors.get(0)); + if (!errs.contains("cant.inherit.from.anon")) { throw new Exception("test failed"); } } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/ClassPathTest/ClassPathTest.java --- a/langtools/test/tools/javac/ClassPathTest/ClassPathTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/ClassPathTest/ClassPathTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -25,19 +25,14 @@ * @test * @bug 4241229 4785453 * @summary Test -classpath option and classpath defaults. - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main ClassPathTest */ import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; -//original test: test/tools/javac/ClassPathTest/ClassPathTest.sh +// Original test: test/tools/javac/ClassPathTest/ClassPathTest.sh public class ClassPathTest { private static final String ClassPathTest1Src = @@ -70,12 +65,12 @@ "package pkg;\n" + "public class ClassPathTestAux3 {}"; - ProcessBuilder pb = null; - public static void main(String[] args) throws Exception { new ClassPathTest().test(); } + ToolBox tb = new ToolBox(); + public void test() throws Exception { createOutputDirAndSourceFiles(); checkCompileCommands(); @@ -83,14 +78,16 @@ void createOutputDirAndSourceFiles() throws Exception { //dirs and files creation - ToolBox.createJavaFileFromSource(ClassPathTest1Src); - ToolBox.createJavaFileFromSource(ClassPathTest2Src); - ToolBox.createJavaFileFromSource(ClassPathTest3Src); - ToolBox.createJavaFileFromSource(Paths.get("foo"), + tb.writeJavaFiles(Paths.get("."), + ClassPathTest1Src, + ClassPathTest2Src, + ClassPathTest3Src); + tb.writeJavaFiles(Paths.get("foo"), fooPkgClassPathTestAux1Src); - ToolBox.createJavaFileFromSource(Paths.get("bar"), + tb.writeJavaFiles(Paths.get("bar"), barPkgClassPathTestAux2Src); - ToolBox.createJavaFileFromSource(pkgClassPathTestAux3Src); + tb.writeJavaFiles(Paths.get("."), + pkgClassPathTestAux3Src); } void checkCompileCommands() throws Exception { @@ -99,80 +96,55 @@ // automatically but this is not happening when called using ProcessBuilder // testJavac success ClassPathTest3.java - List mainArgs = new ArrayList<>(); - mainArgs.add(ToolBox.javacBinary.toString()); - if (ToolBox.testToolVMOpts != null) { - mainArgs.addAll(ToolBox.testToolVMOpts); - } - - List commonArgs = new ArrayList<>(); - commonArgs.addAll(mainArgs); - commonArgs.addAll(Arrays.asList("-cp", ".")); - - ToolBox.AnyToolArgs successParams = new ToolBox.AnyToolArgs() - .appendArgs(commonArgs) - .appendArgs("ClassPathTest3.java"); - ToolBox.executeCommand(successParams); + tb.new JavacTask(ToolBox.Mode.EXEC) + .classpath(".") + .files("ClassPathTest3.java") + .run(); // testJavac failure ClassPathTest1.java - ToolBox.AnyToolArgs failParams = - new ToolBox.AnyToolArgs(ToolBox.Expect.FAIL) - .appendArgs(commonArgs) - .appendArgs("ClassPathTest1.java"); - ToolBox.executeCommand(failParams); - -// This is done inside the executeCommand method -// CLASSPATH=bar; export CLASSPATH - - Map extVars = new TreeMap<>(); - extVars.put("CLASSPATH", "bar"); + tb.new JavacTask(ToolBox.Mode.EXEC) + .classpath(".") + .files("ClassPathTest1.java") + .run(ToolBox.Expect.FAIL); // testJavac success ClassPathTest2.java - successParams = new ToolBox.AnyToolArgs() - .appendArgs(mainArgs) - .appendArgs("ClassPathTest2.java") - .set(extVars); - ToolBox.executeCommand(successParams); + tb.new JavacTask(ToolBox.Mode.EXEC) + .envVar("CLASSPATH", "bar") + .files("ClassPathTest2.java") + .run(); // testJavac failure ClassPathTest1.java - failParams = new ToolBox.AnyToolArgs(ToolBox.Expect.FAIL) - .appendArgs(mainArgs) - .appendArgs("ClassPathTest1.java") - .set(extVars); - ToolBox.executeCommand(failParams); + tb.new JavacTask(ToolBox.Mode.EXEC) + .envVar("CLASSPATH", "bar") + .files("ClassPathTest1.java") + .run(ToolBox.Expect.FAIL); // testJavac failure ClassPathTest3.java - failParams = new ToolBox.AnyToolArgs(ToolBox.Expect.FAIL) - .appendArgs(mainArgs) - .appendArgs("ClassPathTest3.java") - .set(extVars); - ToolBox.executeCommand(failParams); + tb.new JavacTask(ToolBox.Mode.EXEC) + .envVar("CLASSPATH", "bar") + .files("ClassPathTest3.java") + .run(ToolBox.Expect.FAIL); // testJavac success -classpath foo ClassPathTest1.java - - commonArgs.clear(); - commonArgs.addAll(mainArgs); - commonArgs.addAll(Arrays.asList("-cp", "foo")); - - successParams = new ToolBox.AnyToolArgs() - .appendArgs(commonArgs) - .appendArgs("ClassPathTest1.java") - .set(extVars); - ToolBox.executeCommand(successParams); + tb.new JavacTask(ToolBox.Mode.EXEC) + .envVar("CLASSPATH", "bar") + .classpath("foo") + .files("ClassPathTest1.java") + .run(); // testJavac failure -classpath foo ClassPathTest2.java - failParams = new ToolBox.AnyToolArgs(ToolBox.Expect.FAIL) - .appendArgs(commonArgs) - .appendArgs("ClassPathTest2.java") - .set(extVars); - ToolBox.executeCommand(failParams); + tb.new JavacTask(ToolBox.Mode.EXEC) + .envVar("CLASSPATH", "bar") + .classpath("foo") + .files("ClassPathTest2.java") + .run(ToolBox.Expect.FAIL); // testJavac failure -classpath foo ClassPathTest3.java - failParams = new ToolBox.AnyToolArgs(ToolBox.Expect.FAIL) - .appendArgs(commonArgs) - .appendArgs("ClassPathTest3.java") - .set(extVars); - ToolBox.executeCommand(failParams); + tb.new JavacTask(ToolBox.Mode.EXEC) + .envVar("CLASSPATH", "bar") + .classpath("foo") + .files("ClassPathTest3.java") + .run(ToolBox.Expect.FAIL); } } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/ConstFoldTest.java --- a/langtools/test/tools/javac/ConstFoldTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/ConstFoldTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -25,7 +25,7 @@ * @test * @bug 8025505 * @summary Constant folding deficiency - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main ConstFoldTest */ @@ -45,23 +45,23 @@ int x; if (1 != 2) x=1; else x=0; if (1 == 2) x=1; else x=0; - if ("" != null) x=1; else x=0; - if ("" == null) x=1; else x=0; + if ("" != null) x=1; else x=0; + if ("" == null) x=1; else x=0; if (null == null) x=1; else x=0; if (null != null) x=1; else x=0; x = 1 != 2 ? 1 : 0; x = 1 == 2 ? 1 : 0; - x = "" != null ? 1 : 0; - x = "" == null ? 1 : 0; + x = "" != null ? 1 : 0; + x = "" == null ? 1 : 0; x = null == null ? 1 : 0; x = null != null ? 1 : 0; boolean b; b = 1 != 2 && true; b = 1 == 2 || true; - b = ("" != null) && true; - b = ("" == null) || true; + b = ("" != null) && true; + b = ("" == null) || true; b = (null == null) && true; b = (null != null) || true; } @@ -72,11 +72,17 @@ final String regex = "\\sif(?:null|nonnull|eq|ne){1}\\s"; void run() throws Exception { + ToolBox tb = new ToolBox(); + URL url = ConstFoldTest.class.getResource("ConstFoldTest$CFTest.class"); - String result = ToolBox.javap(new ToolBox.JavaToolArgs().setAllArgs("-c", url.getFile())); - System.out.println(result); + List result = tb.new JavapTask() + .options("-c") + .classes(url.getFile()) + .run() + .write(ToolBox.OutputKind.DIRECT) + .getOutputLines(ToolBox.OutputKind.DIRECT); - List bad_codes = ToolBox.grep(regex, result, "\n"); + List bad_codes = tb.grep(regex, result); if (!bad_codes.isEmpty()) { for (String code : bad_codes) System.out.println("Bad OpCode Found: " + code); diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/ExtDirs/ExtDirTest.java --- a/langtools/test/tools/javac/ExtDirs/ExtDirTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/ExtDirs/ExtDirTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -25,18 +25,14 @@ * @test * @bug 4204897 4256097 4785453 4863609 * @summary Test that '.jar' files in -extdirs are found. - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main ExtDirTest */ import java.io.File; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.Arrays; -import java.util.List; -//original test: test/tools/javac/ExtDirs/ExtDirs.sh +// Original test: test/tools/javac/ExtDirs/ExtDirs.sh public class ExtDirTest { private static final String ExtDirTestClass1Src = @@ -100,72 +96,73 @@ "SHA-Digest: ILJOhwHg5US+yuw1Sc1d+Avu628=\n" + "MD5-Digest: j8wnz8wneEcuJ/gjXBBQNA==\n"; - List ouputDirParam = Arrays.asList("-d", "."); - public static void main(String args[]) throws Exception { new ExtDirTest().run(); } + private final ToolBox tb = new ToolBox(); + void run() throws Exception { createJars(); compileWithExtDirs(); } void createJars() throws Exception { - sun.tools.jar.Main jarGenerator = - new sun.tools.jar.Main(System.out, System.err, "jar"); + tb.new JavacTask() + .outdir(".") + .sources(ExtDirTestClass1Src) + .run(); - ToolBox.JavaToolArgs javacParams = - new ToolBox.JavaToolArgs() - .setOptions(ouputDirParam) - .setSources(ExtDirTestClass1Src); - ToolBox.javac(javacParams); + tb.new JarTask("pkg1.jar") + .manifest(jar1Manifest) + .files("pkg1/ExtDirTestClass1.class") + .run(); - ToolBox.writeFile(Paths.get("pkg1", "MANIFEST.MF"), jar1Manifest); - jarGenerator.run(new String[] {"cfm", "pkg1.jar", "pkg1/MANIFEST.MF", - "pkg1/ExtDirTestClass1.class"}); - - javacParams.setSources(ExtDirTestClass2Src); - ToolBox.javac(javacParams); + tb.new JavacTask() + .outdir(".") + .sources(ExtDirTestClass2Src) + .run(); - ToolBox.writeFile(Paths.get("pkg2", "MANIFEST.MF"), jar2Manifest); - jarGenerator.run(new String[] {"cfm", "pkg2.jar", "pkg2/MANIFEST.MF", - "pkg2/ExtDirTestClass2.class"}); - - ToolBox.copyFile(Paths.get("ext1", "pkg1.jar"), Paths.get("pkg1.jar")); - ToolBox.copyFile(Paths.get("ext2", "pkg2.jar"), Paths.get("pkg2.jar")); - ToolBox.copyFile(Paths.get("ext3", "pkg1.jar"), Paths.get("pkg1.jar")); - ToolBox.copyFile(Paths.get("ext3", "pkg2.jar"), Paths.get("pkg2.jar")); + tb.new JarTask("pkg2.jar") + .manifest(jar2Manifest) + .files("pkg2/ExtDirTestClass2.class") + .run(); - Files.delete(Paths.get("pkg1.jar")); - Files.delete(Paths.get("pkg2.jar")); + tb.createDirectories("ext1", "ext2", "ext3"); + tb.copyFile("pkg1.jar", "ext1"); + tb.copyFile("pkg2.jar", "ext2"); + tb.copyFile("pkg1.jar", "ext3"); + tb.copyFile("pkg2.jar", "ext3"); - Files.delete(Paths.get("pkg1", "ExtDirTestClass1.class")); - Files.delete(Paths.get("pkg1", "MANIFEST.MF")); - Files.delete(Paths.get("pkg1")); - Files.delete(Paths.get("pkg2", "ExtDirTestClass2.class")); - Files.delete(Paths.get("pkg2", "MANIFEST.MF")); - Files.delete(Paths.get("pkg2")); + tb.deleteFiles( + "pkg1.jar", + "pkg2.jar", + "pkg1/ExtDirTestClass1.class", + "pkg1", + "pkg2/ExtDirTestClass2.class", + "pkg2" + ); } void compileWithExtDirs() throws Exception { - -//javac -extdirs ext1 ExtDirTest_1.java - ToolBox.JavaToolArgs params = - new ToolBox.JavaToolArgs() - .setOptions("-d", ".", "-extdirs", "ext1") - .setSources(ExtDirTest_1Src); - ToolBox.javac(params); + tb.new JavacTask() + .outdir(".") + .options("-extdirs", "ext1") + .sources(ExtDirTest_1Src) + .run() + .writeAll(); -//javac -extdirs ext1:ext2 ExtDirTest_2.java - params.setOptions("-d", ".", "-extdirs", "ext1" + File.pathSeparator + "ext2") - .setSources(ExtDirTest_2Src); - ToolBox.javac(params); + tb.new JavacTask() + .outdir(".") + .options("-extdirs", "ext1" + File.pathSeparator + "ext2") + .sources(ExtDirTest_2Src) + .run(); -//javac -extdirs ext3 ExtDirTest_3.java - params.setOptions("-d", ".", "-extdirs", "ext3") - .setSources(ExtDirTest_3Src); - ToolBox.javac(params); + tb.new JavacTask() + .outdir(".") + .options("-extdirs", "ext3") + .sources(ExtDirTest_3Src) + .run(); } } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/IncorrectInheritance/IncorrectInheritanceTest.java --- a/langtools/test/tools/javac/IncorrectInheritance/IncorrectInheritanceTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/IncorrectInheritance/IncorrectInheritanceTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -25,7 +25,7 @@ * @test * @bug 8034924 * @summary Incorrect inheritance of inaccessible static method - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main IncorrectInheritanceTest */ @@ -59,10 +59,11 @@ } public void test() throws Exception { - ToolBox.JavaToolArgs javacParams = - new ToolBox.JavaToolArgs() - .setSources(ASrc, BSrc, CSrc); - ToolBox.javac(javacParams); + ToolBox tb = new ToolBox(); + + tb.new JavacTask() + .sources(ASrc, BSrc, CSrc) + .run(); } } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/MissingInclude/MissingIncludeTest.java --- a/langtools/test/tools/javac/MissingInclude/MissingIncludeTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/MissingInclude/MissingIncludeTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -26,25 +26,26 @@ * @bug 4509051 4785453 * @summary javac sourcefiles should catch Exception, when sourcefiles * doesn't exist. - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main MissingIncludeTest */ -//original test: test/tools/javac/MissingInclude.sh +// Original test: test/tools/javac/MissingInclude.sh public class MissingIncludeTest { - private static final String MissingIncludeSrc = - "class MissingInclude {}"; + private static final String MissingIncludeFile = "MissingInclude.java"; + private static final String MissingIncludeSrc = "class MissingInclude {}"; public static void main(String[] args) throws Exception { - ToolBox.createJavaFileFromSource(MissingIncludeSrc); + ToolBox tb = new ToolBox(); + + tb.writeFile(MissingIncludeFile, MissingIncludeSrc); -// "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} @/nonexistent_file MissingInclude.java 2> ${TMP1} - ToolBox.JavaToolArgs params = - new ToolBox.JavaToolArgs(ToolBox.Expect.FAIL) - .setAllArgs("@/nonexistent_file", "MissingInclude.java"); - ToolBox.javac(params); + tb.new JavacTask(ToolBox.Mode.CMDLINE) + .options("@/nonexistent_file") + .files(MissingIncludeFile) + .run(ToolBox.Expect.FAIL); } } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/Paths/AbsolutePathTest.java --- a/langtools/test/tools/javac/Paths/AbsolutePathTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/Paths/AbsolutePathTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -23,36 +23,49 @@ /* * @test + * @ignore 8055500 [javac] fix for 8030046 is incorrect * @bug 8030046 * @summary javac incorrectly handles absolute paths in manifest classpath * @author govereau - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main AbsolutePathTest */ import java.io.File; +import java.nio.file.Files; +import java.nio.file.Paths; public class AbsolutePathTest { public static void main(String... cmdline) throws Exception { + ToolBox tb = new ToolBox(); + // compile test.Test - ToolBox.JavaToolArgs args = new ToolBox.JavaToolArgs(); - args.appendArgs("-d", "."); // this is needed to get the classfiles in test - ToolBox.javac(args.setSources("package test; public class Test{}")); + tb.new JavacTask() + .outdir(".") // this is needed to get the classfiles in test + .sources("package test; public class Test{}") + .run(); // build test.jar containing test.Test // we need the jars in a directory different from the working - // directory to trigger the bug. I will reuse test/ - ToolBox.jar("cf", "test/test.jar", "test/Test.class"); + // directory to trigger the bug. + Files.createDirectory(Paths.get("jars")); + tb.new JarTask("jars/test.jar") + .files("test/Test.class") + .run(); - // build second jar in test directory using + // build second jar in jars directory using // an absolute path reference to the first jar - String path = new File("test/test.jar").getAbsolutePath(); - ToolBox.mkManifestWithClassPath(null, path); - ToolBox.jar("cfm", "test/test2.jar", "MANIFEST.MF"); + tb.new JarTask("jars/test2.jar") + .classpath(new File("jars/test.jar").getAbsolutePath()) + .run(); // this should not fail - args.appendArgs("-cp", "."); - ToolBox.javac(args.setSources("import test.Test; class Test2 {}")); + tb.new JavacTask() + .outdir(".") + .classpath("jars/test2.jar") + .sources("import test.Test; class Test2 {}") + .run() + .writeAll(); } } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/ProtectedInnerClass/ProtectedInnerClassesTest.java --- a/langtools/test/tools/javac/ProtectedInnerClass/ProtectedInnerClassesTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/ProtectedInnerClass/ProtectedInnerClassesTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -25,13 +25,13 @@ * @test * @bug 4087314 4800342 4307565 * @summary Verify allowed access to protected class from another package - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main ProtectedInnerClassesTest */ -//original tests: test/tools/javac/ProtectedInnerClass/ProtectedInnerClass.sh -//and test/tools/javac/ProtectedInnerClass/ProtectedInnerClass_2.java +// Original tests: test/tools/javac/ProtectedInnerClass/ProtectedInnerClass.sh +// and test/tools/javac/ProtectedInnerClass/ProtectedInnerClass_2.java public class ProtectedInnerClassesTest { private static final String protectedInnerClass1Src = @@ -74,45 +74,36 @@ new ProtectedInnerClassesTest().run(); } + ToolBox tb = new ToolBox(); + void run() throws Exception { compileAndExecute(); compileOnly(); } void compileAndExecute() throws Exception { -//"${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d "${TESTCLASSES}" "${TESTSRC}${FS}p1${FS}ProtectedInnerClass1.java" "${TESTSRC}${FS}p2${FS}ProtectedInnerClass2.java" - ToolBox.JavaToolArgs javacParams = - new ToolBox.JavaToolArgs() - .setOptions("-d", ".") - .setSources(protectedInnerClass1Src, protectedInnerClass2Src); - - ToolBox.javac(javacParams); + tb.new JavacTask() + .outdir(".") + .sources(protectedInnerClass1Src, protectedInnerClass2Src) + .run(); -//"${TESTJAVA}${FS}bin${FS}java" ${TESTVMOPTS} -classpath "${CLASSPATH}${PS}${TESTCLASSES}" p2.ProtectedInnerClass2 - ToolBox.AnyToolArgs javaParams = - new ToolBox.AnyToolArgs() - .appendArgs(ToolBox.javaBinary) - .appendArgs(ToolBox.testVMOpts) - .appendArgs("-classpath", System.getProperty("user.dir"), - "p2.ProtectedInnerClass2"); - ToolBox.executeCommand(javaParams); + tb.new JavaTask() + .classpath(System.getProperty("user.dir")) + .className("p2.ProtectedInnerClass2") + .run(); } //from test/tools/javac/ProtectedInnerClass/ProtectedInnerClass_2.java void compileOnly() throws Exception { -//@run compile p1/ProtectedInnerClass1.java - ToolBox.JavaToolArgs javacParams = - new ToolBox.JavaToolArgs() - .appendArgs("-d", ".") - .setSources(protectedInnerClass1Src); + tb.new JavacTask() + .outdir(".") + .sources(protectedInnerClass1Src) + .run(); - ToolBox.javac(javacParams); - -//@run compile/fail p2/ProtectedInnerClass3.java - javacParams = new ToolBox.JavaToolArgs(ToolBox.Expect.FAIL) - .appendArgs("-d", ".") - .setSources(protectedInnerClass3Src); - ToolBox.javac(javacParams); + tb.new JavacTask() + .outdir(".") + .sources(protectedInnerClass3Src) + .run(ToolBox.Expect.FAIL); } } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/T5090006/AssertionFailureTest.java --- a/langtools/test/tools/javac/T5090006/AssertionFailureTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/T5090006/AssertionFailureTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -25,7 +25,7 @@ * @test * @bug 5090006 * @summary javac fails with assertion error - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main AssertionFailureTest */ @@ -33,7 +33,7 @@ import java.io.File; import java.nio.file.Paths; -//original test: test/tools/javac/T5090006/compiler.sh +// Original test: test/tools/javac/T5090006/compiler.sh public class AssertionFailureTest { private static final String testSrc = @@ -54,16 +54,14 @@ "}"; public static void main(String args[]) throws Exception { - String classpath = Paths.get(System.getProperty("test.src"), "broken.jar") - .toString(); - classpath = new StringBuilder(classpath) - .append(File.pathSeparator).append(".").toString(); -// "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -verbose -d "${TESTCLASSES}" -cp "${TESTSRC}${FS}broken.jar" "${TESTSRC}${FS}$1" - ToolBox.JavaToolArgs params = - new ToolBox.JavaToolArgs() - .setOptions("-cp", classpath) - .setSources(testSrc); - ToolBox.javac(params); + ToolBox tb = new ToolBox(); + String classpath = Paths.get(tb.testSrc, "broken.jar") + + File.pathSeparator + + "."; + tb.new JavacTask() + .classpath(classpath) + .sources(testSrc) + .run(); } } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/T6970173/DebugPointerAtBadPositionTest.java --- a/langtools/test/tools/javac/T6970173/DebugPointerAtBadPositionTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/T6970173/DebugPointerAtBadPositionTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -25,7 +25,7 @@ * @test * @bug 6970173 * @summary Debug pointer at bad position - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main DebugPointerAtBadPositionTest */ @@ -75,9 +75,10 @@ } void compileTestClass() throws Exception { - ToolBox.JavaToolArgs javacSuccessArgs = - new ToolBox.JavaToolArgs().setSources(testSource); - ToolBox.javac(javacSuccessArgs); + ToolBox tb = new ToolBox(); + tb.new JavacTask() + .sources(testSource) + .run(); } void checkClassFile(final File cfile, String methodToFind) throws Exception { diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/T7008643/InlinedFinallyConfuseDebuggersTest.java --- a/langtools/test/tools/javac/T7008643/InlinedFinallyConfuseDebuggersTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/T7008643/InlinedFinallyConfuseDebuggersTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -25,7 +25,7 @@ * @test * @bug 7008643 * @summary inlined finally clauses confuse debuggers - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main InlinedFinallyConfuseDebuggersTest */ @@ -73,6 +73,8 @@ new InlinedFinallyConfuseDebuggersTest().run(); } + ToolBox tb = new ToolBox(); + void run() throws Exception { compileTestClass(); checkClassFile(new File(Paths.get(System.getProperty("user.dir"), @@ -80,9 +82,9 @@ } void compileTestClass() throws Exception { - ToolBox.JavaToolArgs javacSuccessArgs = - new ToolBox.JavaToolArgs().setSources(testSource); - ToolBox.javac(javacSuccessArgs); + tb.new JavacTask() + .sources(testSource) + .run(); } void checkClassFile(final File cfile, String methodToFind) throws Exception { diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/T8009640/CheckRejectProfileBCPOptionsIfUsedTogetherTest.java --- a/langtools/test/tools/javac/T8009640/CheckRejectProfileBCPOptionsIfUsedTogetherTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/T8009640/CheckRejectProfileBCPOptionsIfUsedTogetherTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -27,14 +27,13 @@ * @test * @bug 8009640 * @summary -profile does not work when -bootclasspath specified - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main CheckRejectProfileBCPOptionsIfUsedTogetherTest */ import com.sun.tools.javac.util.Assert; -import java.util.ArrayList; -import java.util.List; +import java.nio.file.Paths; public class CheckRejectProfileBCPOptionsIfUsedTogetherTest { @@ -44,21 +43,16 @@ "}"; public static void main(String args[]) throws Exception { - List errOutput = new ArrayList<>(); - String testJDK = ToolBox.jdkUnderTest; - ToolBox.createJavaFileFromSource(TestSrc); + ToolBox tb = new ToolBox(); - ToolBox.AnyToolArgs javacParams = - new ToolBox.AnyToolArgs(ToolBox.Expect.FAIL) - .appendArgs(ToolBox.javacBinary) - .appendArgs(ToolBox.testToolVMOpts) - .appendArgs("-profile", "compact1", "-bootclasspath", - testJDK + "/jre/lib/rt.jar", "Test.java") - .setErrOutput(errOutput); + ToolBox.Result result = tb.new JavacTask(ToolBox.Mode.CMDLINE) + .options("-profile", "compact1", + "-bootclasspath", Paths.get(ToolBox.testJDK, "jre/lib/rt.jar").toString()) + .sources(TestSrc) + .run(ToolBox.Expect.FAIL); - ToolBox.executeCommand(javacParams); - - Assert.check(errOutput.get(0).startsWith( + String out = result.getOutput(ToolBox.OutputKind.DIRECT); + Assert.check(out.startsWith( "javac: profile and bootclasspath options cannot be used together"), "Incorrect javac error output"); } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/T8010659/CompilerCrashWhenMixingBinariesAndSourcesTest.java --- a/langtools/test/tools/javac/T8010659/CompilerCrashWhenMixingBinariesAndSourcesTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/T8010659/CompilerCrashWhenMixingBinariesAndSourcesTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -27,7 +27,7 @@ * @test * @bug 8010659 * @summary Javac Crashes while building OpenJFX - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main CompilerCrashWhenMixingBinariesAndSourcesTest */ @@ -48,19 +48,18 @@ " Object m(int i) {return null;}\n" + "}"; - public static void main (String[] args) throws Exception{ - ToolBox.JavaToolArgs javacParams = new ToolBox.JavaToolArgs() - .setSources(ASource, BSource, CSource, DSource); - ToolBox.javac(javacParams); + public static void main(String[] args) throws Exception { + ToolBox tb = new ToolBox(); + + tb.new JavacTask() + .sources(ASource, BSource, CSource, DSource) + .run(); - ToolBox.rm("A.class"); - ToolBox.rm("A$1.class"); - ToolBox.rm("C.class"); - ToolBox.rm("D.class"); + tb.deleteFiles("A.class", "A$1.class", "C.class", "D.class"); - javacParams = new ToolBox.JavaToolArgs() - .setOptions("-cp", ".") - .setSources(ASource, CSource, DSource); - ToolBox.javac(javacParams); + tb.new JavacTask() + .classpath(".") + .sources(ASource, CSource, DSource) + .run(); } } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/T8013394/CompileErrorWithIteratorTest.java --- a/langtools/test/tools/javac/T8013394/CompileErrorWithIteratorTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/T8013394/CompileErrorWithIteratorTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -27,7 +27,7 @@ * @test * @bug 8013394 * @summary compile of iterator use fails with error "defined in an inaccessible class or interface" - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main CompileErrorWithIteratorTest */ @@ -71,15 +71,16 @@ new CompileErrorWithIteratorTest().run(); } + ToolBox tb = new ToolBox(); + void run() throws Exception { compile(); } void compile() throws Exception { - ToolBox.JavaToolArgs javacParams = - new ToolBox.JavaToolArgs() - .setSources(TestCollectionSrc, TestSrc); - ToolBox.javac(javacParams); + tb.new JavacTask() + .sources(TestCollectionSrc, TestSrc) + .run(); } } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/T8019486/WrongLNTForLambdaTest.java --- a/langtools/test/tools/javac/T8019486/WrongLNTForLambdaTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/T8019486/WrongLNTForLambdaTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -27,7 +27,7 @@ * @test * @bug 8019486 8026861 8027142 * @summary javac, generates erroneous LVT for a test case with lambda code - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main WrongLNTForLambdaTest */ @@ -125,6 +125,8 @@ new WrongLNTForLambdaTest().run(); } + ToolBox tb = new ToolBox(); + void run() throws Exception { compileTestClass(); checkClassFile(new File(Paths.get(System.getProperty("user.dir"), @@ -146,9 +148,9 @@ } void compileTestClass() throws Exception { - ToolBox.JavaToolArgs javacSuccessArgs = - new ToolBox.JavaToolArgs().setSources(testSource); - ToolBox.javac(javacSuccessArgs); + tb.new JavacTask() + .sources(testSource) + .run(); } void checkClassFile(final File cfile, String methodToFind, int[][] expectedLNT) throws Exception { diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/T8022162/IncorrectSignatureDeterminationForInnerClassesTest.java --- a/langtools/test/tools/javac/T8022162/IncorrectSignatureDeterminationForInnerClassesTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/T8022162/IncorrectSignatureDeterminationForInnerClassesTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -25,14 +25,11 @@ * @test * @bug 8022162 * @summary Incorrect signature determination for certain inner class generics - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main IncorrectSignatureDeterminationForInnerClassesTest */ -import java.nio.file.Files; -import java.nio.file.Paths; - public class IncorrectSignatureDeterminationForInnerClassesTest { private static final String DSrc = @@ -69,21 +66,20 @@ } void compile() throws Exception { - Files.createDirectory(Paths.get("classes")); + ToolBox tb = new ToolBox(); + tb.createDirectories("classes"); - ToolBox.JavaToolArgs javacParams = - new ToolBox.JavaToolArgs() - .appendArgs("-d", "classes") - .setSources(DSrc); - - ToolBox.javac(javacParams); + tb.new JavacTask() + .outdir("classes") + .sources(DSrc) + .run(); // compile class H against the class files for classes D and Q - javacParams = - new ToolBox.JavaToolArgs() - .appendArgs("-d", "classes", "-cp", "classes") - .setSources(HSrc); - ToolBox.javac(javacParams); + tb.new JavacTask() + .outdir("classes") + .classpath("classes") + .sources(HSrc) + .run(); } } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/T8024039/NoDeadCodeGenerationOnTrySmtTest.java --- a/langtools/test/tools/javac/T8024039/NoDeadCodeGenerationOnTrySmtTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/T8024039/NoDeadCodeGenerationOnTrySmtTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -27,7 +27,7 @@ * @test * @bug 8024039 * @summary javac, previous solution for JDK-8022186 was incorrect - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main NoDeadCodeGenerationOnTrySmtTest */ @@ -76,6 +76,8 @@ static final String[] methodsToLookFor = {"m1", "m2"}; + ToolBox tb = new ToolBox(); + public static void main(String[] args) throws Exception { new NoDeadCodeGenerationOnTrySmtTest().run(); } @@ -87,9 +89,9 @@ } void compileTestClass() throws Exception { - ToolBox.JavaToolArgs javacSuccessArgs = - new ToolBox.JavaToolArgs().setSources(testSource); - ToolBox.javac(javacSuccessArgs); + tb.new JavacTask() + .sources(testSource) + .run(); } void checkClassFile(final File cfile, String[] methodsToFind) throws Exception { diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/T8024437/ExceptionInferenceFromClassFileTest.java --- a/langtools/test/tools/javac/T8024437/ExceptionInferenceFromClassFileTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/T8024437/ExceptionInferenceFromClassFileTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -27,7 +27,7 @@ * @test * @bug 8024437 * @summary Inferring the exception thrown by a lambda: sometimes fails to compile - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main ExceptionInferenceFromClassFileTest */ @@ -56,19 +56,19 @@ "}"; public static void main(String[] args) throws Exception { - Files.createDirectory(Paths.get("out")); + ToolBox tb = new ToolBox(); + tb.createDirectories("out"); - ToolBox.JavaToolArgs compileABParams = - new ToolBox.JavaToolArgs() - .setOptions("-d", "out") - .setSources(ABSrc); - ToolBox.javac(compileABParams); + tb.new JavacTask() + .outdir("out") + .sources(ABSrc) + .run(); - ToolBox.JavaToolArgs compileCParams = - new ToolBox.JavaToolArgs() - .setOptions("-d", "out", "-cp", "out") - .setSources(CSrc); - ToolBox.javac(compileCParams); + tb.new JavacTask() + .outdir("out") + .classpath("out") + .sources(CSrc) + .run(); } } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/InvalidPackageAnno.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/InvalidPackageAnno.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,11 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8054964 + * @summary Invalid package annotations + * @author sogoel + * + * @compile/fail/ref=InvalidPackageAnno.out -XDrawDiagnostics bar/package-info.java + */ + +package bar; + diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/InvalidPackageAnno.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/InvalidPackageAnno.out Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,2 @@ +package-info.java:24:1: compiler.err.annotation.type.not.applicable +1 error diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/NoAnnotationMethods.java --- a/langtools/test/tools/javac/annotations/neg/NoAnnotationMethods.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/NoAnnotationMethods.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,32 +1,9 @@ /* - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 6393539 * @summary no compile-time error for clone, etc. in annotation type * @author Peter von der Ah\u00e9 - * @compile/fail NoAnnotationMethods.java + * @compile/fail/ref=NoAnnotationMethods.out -XDrawDiagnostics NoAnnotationMethods.java */ public @interface NoAnnotationMethods { diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/NoAnnotationMethods.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/NoAnnotationMethods.out Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,2 @@ +NoAnnotationMethods.java:10:9: compiler.err.intf.annotation.member.clash: annotationType(), java.lang.annotation.Annotation +1 error diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/NoClone.java --- a/langtools/test/tools/javac/annotations/neg/NoClone.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/NoClone.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,32 +1,9 @@ /* - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 6393539 * @summary no compile-time error for clone, etc. in annotation type * @author Peter von der Ah\u00e9 - * @compile/fail NoClone.java + * @compile/fail/ref=NoClone.out -XDrawDiagnostics NoClone.java */ public @interface NoClone { diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/NoClone.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/NoClone.out Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,3 @@ +NoClone.java:10:5: compiler.err.invalid.annotation.member.type +NoClone.java:10:12: compiler.err.intf.annotation.member.clash: clone(), java.lang.Object +2 errors diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/NoObjectMethods.java --- a/langtools/test/tools/javac/annotations/neg/NoObjectMethods.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/NoObjectMethods.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,32 +1,9 @@ /* - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 6393539 * @summary no compile-time error for clone, etc. in annotation type * @author Peter von der Ah\u00e9 - * @compile/fail NoObjectMethods.java + * @compile/fail/ref=NoObjectMethods.out -XDrawDiagnostics NoObjectMethods.java */ public @interface NoObjectMethods { diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/NoObjectMethods.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/NoObjectMethods.out Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,2 @@ +NoObjectMethods.java:10:9: compiler.err.intf.annotation.member.clash: clone(), java.lang.Object +1 error diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/ObjectMembers.java --- a/langtools/test/tools/javac/annotations/neg/ObjectMembers.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/ObjectMembers.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,33 +1,10 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4901264 * @summary JSR175 (2): don't allow annotating members from Object * @author gafter * - * @compile/fail ObjectMembers.java + * @compile/fail/ref=ObjectMembers.out -XDrawDiagnostics ObjectMembers.java */ @ObjectMembers(hashCode = 23) diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/ObjectMembers.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/ObjectMembers.out Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,2 @@ +ObjectMembers.java:10:16: compiler.err.no.annotation.member: hashCode, ObjectMembers +1 error diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/OverrideNo.java --- a/langtools/test/tools/javac/annotations/neg/OverrideNo.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/OverrideNo.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,33 +1,10 @@ /* - * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4901275 4989669 * @summary JSR175 (7): implement Overrides * @author gafter * - * @compile/fail OverrideNo.java + * @compile/fail/ref=OverrideNo.out -XDrawDiagnostics OverrideNo.java */ package overrideNo; diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/OverrideNo.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/OverrideNo.out Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,2 @@ +OverrideNo.java:16:5: compiler.err.method.does.not.override.superclass +1 error diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Package.java --- a/langtools/test/tools/javac/annotations/neg/Package.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Package.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,33 +1,10 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4901290 * @summary Package annotations * @author gafter * - * @compile/fail Package.java + * @compile/fail/ref=Package.out -XDrawDiagnostics Package.java */ @java.lang.annotation.Documented diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Package.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Package.out Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,2 @@ +Package.java:10:1: compiler.err.pkg.annotations.sb.in.package-info.java +1 error diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Recovery.java --- a/langtools/test/tools/javac/annotations/neg/Recovery.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Recovery.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,33 +1,10 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4993451 * @summary compiler crash with malformed annotations * @author gafter * - * @compile/fail Recovery.java + * @compile/fail/ref=Recovery.out -XDrawDiagnostics Recovery.java */ import java.lang.annotation.*; diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Recovery.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Recovery.out Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,2 @@ +Recovery.java:12:2: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.annotation.RetentionPolicy, java.lang.annotation.Annotation) +1 error diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Recovery1.java --- a/langtools/test/tools/javac/annotations/neg/Recovery1.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Recovery1.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,33 +1,10 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4963450 * @summary Assertion error is thrown when an annotation class cannot be found. * @author gafter * - * @compile/fail Recovery1.java + * @compile/fail/ref=Recovery1.out -XDrawDiagnostics Recovery1.java */ package recovery1; diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Recovery1.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Recovery1.out Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,4 @@ +Recovery1.java:14:5: compiler.err.cant.resolve.location: kindname.class, Marker, , , (compiler.misc.location: kindname.annotation, recovery1.MyAnnotation, null) +Recovery1.java:14:30: compiler.err.cant.resolve.location: kindname.class, Marker, , , (compiler.misc.location: kindname.annotation, recovery1.MyAnnotation, null) +Recovery1.java:18:43: compiler.err.cant.resolve.location.args: kindname.method, markerToo, , , (compiler.misc.location: kindname.annotation, recovery1.MyAnnotation, null) +3 errors diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Scope.java --- a/langtools/test/tools/javac/annotations/neg/Scope.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Scope.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,33 +1,10 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4901280 * @summary name lookup scope for annotations * @author gafter * - * @compile/fail Scope.java + * @compile/fail/ref=Scope.out -XDrawDiagnostics Scope.java */ package annotation.scope; diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Scope.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Scope.out Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,2 @@ +Scope.java:12:4: compiler.err.cant.resolve: kindname.variable, red, , +1 error diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Syntax1.java --- a/langtools/test/tools/javac/annotations/neg/Syntax1.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Syntax1.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,33 +1,10 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4974524 * @summary compiler crash with ill-formed annotation * @author gafter * - * @compile/fail Syntax1.java + * @compile/fail/ref=Syntax1.out -XDrawDiagnostics Syntax1.java */ package syntax1; diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Syntax1.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Syntax1.out Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,4 @@ +Syntax1.java:17:20: compiler.err.annotation.value.must.be.name.value +Syntax1.java:17:40: compiler.err.annotation.value.must.be.name.value +Syntax1.java:17:1: compiler.err.annotation.missing.default.value: java.lang.annotation.Target, value +3 errors diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/WrongTarget.java --- a/langtools/test/tools/javac/annotations/neg/WrongTarget.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/WrongTarget.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,35 +1,14 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4901271 * @summary java.lang.annotation.Target * @author gafter * - * @compile/fail WrongTarget.java + * @compile/fail/ref=WrongTarget.out -XDrawDiagnostics WrongTarget.java */ +import static java.lang.annotation.ElementType.*; + @java.lang.annotation.Target({FIELD}) @interface foo { } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/WrongTarget.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/WrongTarget.out Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,2 @@ +WrongTarget.java:16:1: compiler.err.annotation.type.not.applicable +1 error diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/WrongTarget2.java --- a/langtools/test/tools/javac/annotations/neg/WrongTarget2.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/WrongTarget2.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,33 +1,10 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4973504 * @summary Compiler allows Inherited meta-attribute on local variable declaration. * @author gafter * - * @compile/fail WrongTarget2.java + * @compile/fail/ref=WrongTarget2.out -XDrawDiagnostics WrongTarget2.java */ import java.lang.annotation.Inherited; diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/WrongTarget2.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/WrongTarget2.out Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,2 @@ +WrongTarget2.java:12:6: compiler.err.annotation.type.not.applicable +1 error diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/WrongValue.java --- a/langtools/test/tools/javac/annotations/neg/WrongValue.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/WrongValue.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,33 +1,10 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4951298 * @summary compiler: crashes when attributes with same elements are used in place of other * @author gafter * - * @compile/fail WrongValue.java + * @compile/fail/ref=WrongValue.out -XDrawDiagnostics WrongValue.java */ @interface TestM2 { diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/WrongValue.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/WrongValue.out Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,2 @@ +WrongValue.java:25:5: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: TestM3, TestM2) +1 error diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Z1.java --- a/langtools/test/tools/javac/annotations/neg/Z1.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Z1.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,33 +1,10 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4865660 * @summary implement "metadata" (attribute interfaces and program annotations) * @author gafter * - * @compile/fail Z1.java + * @compile/fail/ref=Z1.out -XDrawDiagnostics Z1.java */ enum Color { red, green, blue } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Z1.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Z1.out Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,2 @@ +Z1.java:16:10: compiler.err.cant.resolve: kindname.variable, teal, , +1 error diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Z10.java --- a/langtools/test/tools/javac/annotations/neg/Z10.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Z10.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,37 +1,12 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4865660 * @summary implement "metadata" (attribute interfaces and program annotations) * @author gafter * - * @compile/fail Z10.java + * @compile/fail/ref=Z10.out -XDrawDiagnostics Z10.java */ -enum Color { red, green, blue } - @interface An { int[][] a(); } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Z10.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Z10.out Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,2 @@ +Z10.java:11:8: compiler.err.invalid.annotation.member.type +1 error diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Z11.java --- a/langtools/test/tools/javac/annotations/neg/Z11.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Z11.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,37 +1,12 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4865660 * @summary implement "metadata" (attribute interfaces and program annotations) * @author gafter * - * @compile/fail Z11.java + * @compile/fail/ref=Z11.out -XDrawDiagnostics Z11.java */ -enum Color { red, green, blue } - class X {} @interface An { diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Z11.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Z11.out Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,2 @@ +Z11.java:13:5: compiler.err.invalid.annotation.member.type +1 error diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Z12.java --- a/langtools/test/tools/javac/annotations/neg/Z12.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Z12.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,37 +1,12 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4865660 * @summary implement "metadata" (attribute interfaces and program annotations) * @author gafter * - * @compile/fail Z12.java + * @compile/fail/ref=Z12.out -XDrawDiagnostics Z12.java */ -enum Color { red, green, blue } - @interface An { void a(); } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Z12.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Z12.out Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,2 @@ +Z12.java:11:5: compiler.err.invalid.annotation.member.type +1 error diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Z13.java --- a/langtools/test/tools/javac/annotations/neg/Z13.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Z13.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,33 +1,10 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4865660 * @summary implement "metadata" (attribute interfaces and program annotations) * @author gafter * - * @compile/fail Z13.java + * @compile/fail/ref=Z13.out -XDrawDiagnostics Z13.java */ @interface An { diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Z13.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Z13.out Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,2 @@ +Z13.java:11:20: compiler.err.throws.not.allowed.in.intf.annotation +1 error diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Z14.java --- a/langtools/test/tools/javac/annotations/neg/Z14.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Z14.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,33 +1,10 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4865660 * @summary implement "metadata" (attribute interfaces and program annotations) * @author gafter * - * @compile/fail Z14.java + * @compile/fail/ref=Z14.out -XDrawDiagnostics Z14.java */ @interface An { diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Z14.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Z14.out Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,2 @@ +Z14.java:10:15: compiler.err.intf.annotation.cant.have.type.params +1 error diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Z15.java --- a/langtools/test/tools/javac/annotations/neg/Z15.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Z15.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,33 +1,10 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4865660 * @summary implement "metadata" (attribute interfaces and program annotations) * @author gafter * - * @compile/fail Z15.java + * @compile/fail/ref=Z15.out -XDrawDiagnostics Z15.java */ @interface An { diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Z15.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Z15.out Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,2 @@ +Z15.java:11:36: compiler.err.attribute.value.must.be.constant +1 error diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Z16.java --- a/langtools/test/tools/javac/annotations/neg/Z16.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Z16.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,33 +1,10 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4865660 * @summary implement "metadata" (attribute interfaces and program annotations) * @author gafter * - * @compile/fail Z16.java + * @compile/fail/ref=Z16.out -XDrawDiagnostics Z16.java */ enum Color { red, green, blue } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Z16.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Z16.out Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,2 @@ +Z16.java:13:27: compiler.err.cant.resolve.location: kindname.variable, redx, , , (compiler.misc.location: kindname.annotation, Colored, null) +1 error diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Z2.java --- a/langtools/test/tools/javac/annotations/neg/Z2.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Z2.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,37 +1,14 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4865660 * @summary implement "metadata" (attribute interfaces and program annotations) * @author gafter * - * @compile/fail Z2.java + * @compile/fail/ref=Z2.out -XDrawDiagnostics Z2.java */ enum Color { red, green, blue } interface Colored { - Color value() default red; + Color value() default Color.red; } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Z2.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Z2.out Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,2 @@ +Z2.java:13:11: compiler.err.default.allowed.in.intf.annotation.member +1 error diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Z3.java --- a/langtools/test/tools/javac/annotations/neg/Z3.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Z3.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,37 +1,14 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 4865660 + * @test /nodynamiccopyright/ + * @bug 4865660 8054556 * @summary implement "metadata" (attribute interfaces and program annotations) * @author gafter * - * @compile/fail Z3.java + * @compile/fail/ref=Z3.out -XDrawDiagnostics Z3.java */ enum Color { red, green, blue } class Colored { - Color value() default red; + Color value() default Color.red; } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Z3.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Z3.out Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,2 @@ +Z3.java:13:11: compiler.err.default.allowed.in.intf.annotation.member +1 error diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Z4.java --- a/langtools/test/tools/javac/annotations/neg/Z4.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Z4.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,37 +1,14 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4865660 * @summary implement "metadata" (attribute interfaces and program annotations) * @author gafter * - * @compile/fail Z4.java + * @compile/fail/ref=Z4.out -XDrawDiagnostics Z4.java */ enum Color { red, green, blue } @interface Colored { - Color value() default teal; + Color value() default Color.teal; } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Z4.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Z4.out Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,2 @@ +Z4.java:13:32: compiler.err.cant.resolve.location: kindname.variable, teal, , , (compiler.misc.location: kindname.class, Color, null) +1 error diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Z5.java --- a/langtools/test/tools/javac/annotations/neg/Z5.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Z5.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,33 +1,10 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4865660 * @summary implement "metadata" (attribute interfaces and program annotations) * @author gafter * - * @compile/fail Z5.java + * @compile/fail/ref=Z5.out -XDrawDiagnostics Z5.java */ interface Foo {} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Z5.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Z5.out Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,2 @@ +Z5.java:12:28: compiler.err.cant.extend.intf.annotation +1 error diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Z8.java --- a/langtools/test/tools/javac/annotations/neg/Z8.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Z8.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,33 +1,10 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4865660 * @summary implement "metadata" (attribute interfaces and program annotations) * @author gafter * - * @compile/fail Z8.java + * @compile/fail/ref=Z8.out -XDrawDiagnostics Z8.java */ @interface An { diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Z8.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Z8.out Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,2 @@ +Z8.java:11:15: compiler.err.intf.annotation.members.cant.have.params +1 error diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Z9.java --- a/langtools/test/tools/javac/annotations/neg/Z9.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/annotations/neg/Z9.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,33 +1,10 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 4865660 * @summary implement "metadata" (attribute interfaces and program annotations) * @author gafter * - * @compile/fail Z9.java + * @compile/fail/ref=Z9.out -XDrawDiagnostics Z9.java */ @interface An { diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/Z9.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/Z9.out Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,2 @@ +Z9.java:11:6: compiler.err.intf.annotation.members.cant.have.type.params +1 error diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/neg/bar/package-info.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/neg/bar/package-info.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +@java.lang.annotation.Documented +package bar; diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingAndContainerPresent.java --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingAndContainerPresent.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingAndContainerPresent.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,30 +1,7 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/** - * @test + * @test /nodynamiccopyright/ * @summary Smoke test for repeating annotations - * @compile/fail RepeatingAndContainerPresent.java + * @compile/fail/ref=RepeatingAndContainerPresent.out -XDrawDiagnostics RepeatingAndContainerPresent.java * @bug 7151010 */ diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingAndContainerPresent.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingAndContainerPresent.out Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,2 @@ +RepeatingAndContainerPresent.java:20:1: compiler.err.invalid.repeatable.annotation.repeated.and.container.present: Foos +1 error diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongRepeatable.java --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongRepeatable.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongRepeatable.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,30 +1,7 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/** - * @test + * @test /nodynamiccopyright/ * @summary Smoke test for repeating annotations - * @compile/fail UseWrongRepeatable.java + * @compile/fail/ref=UseWrongRepeatable.out -XDrawDiagnostics UseWrongRepeatable.java * @bug 7151010 */ diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongRepeatable.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongRepeatable.out Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,4 @@ +UseWrongRepeatable.java:17:1: compiler.err.invalid.repeatable.annotation.value.return: java.lang.annotation.Target, java.lang.annotation.ElementType[], UseWrongRepeatable[] +UseWrongRepeatable.java:17:21: compiler.err.invalid.repeatable.annotation.value.return: java.lang.annotation.Target, java.lang.annotation.ElementType[], UseWrongRepeatable[] +UseWrongRepeatable.java:14:1: compiler.err.invalid.repeatable.annotation.value.return: java.lang.annotation.Target, java.lang.annotation.ElementType[], UseWrongRepeatable[] +3 errors diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/typeAnnotations/failures/VoidGenericMethod.java --- a/langtools/test/tools/javac/annotations/typeAnnotations/failures/VoidGenericMethod.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/VoidGenericMethod.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,35 +1,12 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. + * @test /nodynamiccopyright/ + * @bug 6843077 8006775 + * @summary test type annotation on void generic methods + * @author Mahmood Ali + * @compile/fail/ref=VoidGenericMethod.out -XDrawDiagnostics VoidGenericMethod.java */ import java.lang.annotation.*; - -/* - * @test - * @bug 6843077 8006775 - * @summary test type annotation on void generic methods - * @author Mahmood Ali - * @compile/fail VoidGenericMethod.java - */ class VoidGenericMethod { public @A void method() { } } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/annotations/typeAnnotations/failures/VoidGenericMethod.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/typeAnnotations/failures/VoidGenericMethod.out Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,2 @@ +VoidGenericMethod.java:11:10: compiler.err.annotation.type.not.applicable +1 error diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/api/ToolProvider/HelloWorldTest.java --- a/langtools/test/tools/javac/api/ToolProvider/HelloWorldTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/api/ToolProvider/HelloWorldTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -25,21 +25,19 @@ * @test * @bug 6604599 * @summary ToolProvider should be less compiler-specific - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main HelloWorldTest */ -import java.util.ArrayList; import java.util.Arrays; -import java.util.List; // verify that running a simple program, such as this one, does not trigger // the loading of ToolProvider or any com.sun.tools.javac class public class HelloWorldTest { public static void main(String... args) throws Exception { if (args.length > 0) { - System.err.println(Arrays.asList(args)); + System.err.println(Arrays.toString(args)); return; } @@ -47,27 +45,26 @@ } void run() throws Exception { + ToolBox tb = new ToolBox(); + String classpath = System.getProperty("java.class.path"); - List output = new ArrayList<>(); - ToolBox.AnyToolArgs javaParams = - new ToolBox.AnyToolArgs() - .appendArgs(ToolBox.javaBinary) - .appendArgs(ToolBox.testVMOpts) - .appendArgs(ToolBox.testJavaOpts) - .appendArgs("-verbose:class", - "-classpath", classpath, - HelloWorldTest.class.getName(), - "Hello", "World") - .setErrOutput(output) - .setStdOutput(output); + ToolBox.Result tr = tb.new JavaTask() + .vmOptions("-verbose:class") + .classpath(classpath) + .className(HelloWorldTest.class.getName()) + .classArgs("Hello", "World") + .run(); - ToolBox.executeCommand(javaParams); - - for (String line : output) { - System.err.println(line); - if (line.contains("javax.tools.ToolProvider") || line.contains("com.sun.tools.javac.")) - error(">>> " + line); + if (tr.getOutput(ToolBox.OutputKind.STDOUT).contains("java.lang.Object")) { + for (String line : tr.getOutputLines(ToolBox.OutputKind.STDOUT)) { + System.err.println(line); + if (line.contains("javax.tools.ToolProvider") || line.contains("com.sun.tools.javac.")) + error(">>> " + line); + } + } else { + tr.writeAll(); + error("verbose output not as expected"); } if (errors > 0) diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/api/ToolProvider/ToolProviderTest1.java --- a/langtools/test/tools/javac/api/ToolProvider/ToolProviderTest1.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/api/ToolProvider/ToolProviderTest1.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -25,12 +25,11 @@ * @test * @bug 6604599 * @summary ToolProvider should be less compiler-specific - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main ToolProviderTest1 */ -import java.util.ArrayList; import java.util.List; // verify that running accessing ToolProvider by itself does not @@ -46,24 +45,18 @@ } void run() throws Exception { + ToolBox tb = new ToolBox(); String classpath = System.getProperty("java.class.path"); - List output = new ArrayList<>(); - ToolBox.AnyToolArgs javaParams = - new ToolBox.AnyToolArgs() - .appendArgs(ToolBox.javaBinary) - .appendArgs(ToolBox.testVMOpts) - .appendArgs(ToolBox.testJavaOpts) - .appendArgs("-verbose:class", - "-classpath", classpath, - ToolProviderTest1.class.getName(), - "javax.tools.ToolProvider") - .setErrOutput(output) - .setStdOutput(output); + List lines = tb.new JavaTask() + .vmOptions("-verbose:class") + .classpath(classpath) + .className(getClass().getName()) + .classArgs("javax.tools.ToolProvider") + .run() + .getOutputLines(ToolBox.OutputKind.STDOUT); - ToolBox.executeCommand(javaParams); - - for (String line : output) { + for (String line : lines) { System.err.println(line); if (line.contains("com.sun.tools.javac.")) error(">>> " + line); diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/api/ToolProvider/ToolProviderTest2.java --- a/langtools/test/tools/javac/api/ToolProvider/ToolProviderTest2.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/api/ToolProvider/ToolProviderTest2.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -25,13 +25,12 @@ * @test * @bug 6604599 * @summary ToolProvider should be less compiler-specific - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main ToolProviderTest2 */ import javax.tools.ToolProvider; -import java.util.ArrayList; import java.util.List; // control for ToolProviderTest1 -- verify that using ToolProvider to @@ -47,25 +46,19 @@ } void run() throws Exception { + ToolBox tb = new ToolBox(); String classpath = System.getProperty("java.class.path"); - List output = new ArrayList<>(); - ToolBox.AnyToolArgs javaParams = - new ToolBox.AnyToolArgs() - .appendArgs(ToolBox.javaBinary) - .appendArgs(ToolBox.testVMOpts) - .appendArgs(ToolBox.testJavaOpts) - .appendArgs( "-verbose:class", - "-classpath", classpath, - ToolProviderTest2.class.getName(), - "javax.tools.ToolProvider") - .setErrOutput(output) - .setStdOutput(output); - - ToolBox.executeCommand(javaParams); + List lines = tb.new JavaTask() + .vmOptions("-verbose:class") + .classpath(classpath) + .className(getClass().getName()) + .classArgs("javax.tools.ToolProvider") + .run() + .getOutputLines(ToolBox.OutputKind.STDOUT); boolean found = false; - for (String line : output) { + for (String line : lines) { System.err.println(line); if (line.contains("com.sun.tools.javac.")) found = true; diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/LocalVariableTable/LocalVariableTableTest.java --- a/langtools/test/tools/javac/classfiles/attributes/LocalVariableTable/LocalVariableTableTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/classfiles/attributes/LocalVariableTable/LocalVariableTableTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -25,8 +25,8 @@ * @test * @summary local variable table attribute test. * @bug 8040097 - * @library /tools/javac/lib ../lib - * @build LocalVariableTestBase TestBase InMemoryFileManager ToolBox + * @library /tools/lib /tools/javac/lib ../lib + * @build ToolBox LocalVariableTestBase TestBase InMemoryFileManager * @compile -g LocalVariableTableTest.java * @run main LocalVariableTableTest */ diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/LocalVariableTable/LocalVariableTypeTableTest.java --- a/langtools/test/tools/javac/classfiles/attributes/LocalVariableTable/LocalVariableTypeTableTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/classfiles/attributes/LocalVariableTable/LocalVariableTypeTableTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -25,8 +25,8 @@ * @test * @summary local variable type table attribute test. * @bug 8040097 - * @library /tools/javac/lib ../lib - * @build LocalVariableTestBase TestBase InMemoryFileManager ToolBox + * @library /tools/lib /tools/javac/lib ../lib + * @build ToolBox LocalVariableTestBase TestBase InMemoryFileManager * @compile -g LocalVariableTypeTableTest.java * @run main LocalVariableTypeTableTest */ diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/SourceFile/AnonymousClassTest.java --- a/langtools/test/tools/javac/classfiles/attributes/SourceFile/AnonymousClassTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/classfiles/attributes/SourceFile/AnonymousClassTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -25,8 +25,8 @@ * @test * @summary sourcefile attribute test for anonymous class. * @bug 8040129 - * @library /tools/javac/lib ../lib - * @build SourceFileTestBase TestBase InMemoryFileManager ToolBox + * @library /tools/lib /tools/javac/lib ../lib + * @build ToolBox SourceFileTestBase TestBase InMemoryFileManager * @run main AnonymousClassTest */ diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/SourceFile/InnerClassTest.java --- a/langtools/test/tools/javac/classfiles/attributes/SourceFile/InnerClassTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/classfiles/attributes/SourceFile/InnerClassTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -25,8 +25,8 @@ * @test * @summary sourcefile attribute test for inner class. * @bug 8040129 - * @library /tools/javac/lib ../lib - * @build SourceFileTestBase TestBase InMemoryFileManager ToolBox + * @library /tools/lib /tools/javac/lib ../lib + * @build ToolBox SourceFileTestBase TestBase InMemoryFileManager * @run main InnerClassTest */ diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/SourceFile/LocalClassTest.java --- a/langtools/test/tools/javac/classfiles/attributes/SourceFile/LocalClassTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/classfiles/attributes/SourceFile/LocalClassTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -25,8 +25,8 @@ * @test * @summary sourcefile attribute test for local class. * @bug 8040129 - * @library /tools/javac/lib ../lib - * @build SourceFileTestBase TestBase InMemoryFileManager ToolBox + * @library /tools/lib /tools/javac/lib ../lib + * @build ToolBox SourceFileTestBase TestBase InMemoryFileManager * @run main LocalClassTest */ diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/SourceFile/MixTest.java --- a/langtools/test/tools/javac/classfiles/attributes/SourceFile/MixTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/classfiles/attributes/SourceFile/MixTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -25,8 +25,8 @@ * @test * @summary sourcefile attribute test for complex structure of nested classes and other types. * @bug 8040129 - * @library /tools/javac/lib ../lib - * @build SourceFileTestBase TestBase InMemoryFileManager ToolBox + * @library /tools/lib /tools/javac/lib ../lib + * @build ToolBox SourceFileTestBase TestBase InMemoryFileManager * @run main MixTest */ diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/SourceFile/NoSourceFileAttribute.java --- a/langtools/test/tools/javac/classfiles/attributes/SourceFile/NoSourceFileAttribute.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/classfiles/attributes/SourceFile/NoSourceFileAttribute.java Fri Aug 29 11:58:43 2014 -0700 @@ -25,8 +25,8 @@ * @test * @summary sourcefile attribute test for file compiled without debug information. * @bug 8040129 - * @library /tools/javac/lib ../lib - * @build SourceFileTestBase TestBase InMemoryFileManager ToolBox + * @library /tools/lib /tools/javac/lib ../lib + * @build ToolBox SourceFileTestBase TestBase InMemoryFileManager * @compile -g:none NoSourceFileAttribute.java * @run main NoSourceFileAttribute */ diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/SourceFile/SyntheticClassTest.java --- a/langtools/test/tools/javac/classfiles/attributes/SourceFile/SyntheticClassTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/classfiles/attributes/SourceFile/SyntheticClassTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -25,8 +25,8 @@ * @test * @summary sourcefile attribute test for synthetic class. * @bug 8040129 - * @library /tools/javac/lib ../lib - * @build SourceFileTestBase TestBase InMemoryFileManager ToolBox + * @library /tools/lib /tools/javac/lib ../lib + * @build ToolBox SourceFileTestBase TestBase InMemoryFileManager * @run main SyntheticClassTest */ diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/SourceFile/TopLevelClassesOneFileTest.java --- a/langtools/test/tools/javac/classfiles/attributes/SourceFile/TopLevelClassesOneFileTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/classfiles/attributes/SourceFile/TopLevelClassesOneFileTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -25,8 +25,8 @@ * @test * @summary sourcefile attribute test for two type in one file. * @bug 8040129 - * @library /tools/javac/lib ../lib - * @build SourceFileTestBase TestBase InMemoryFileManager ToolBox + * @library /tools/lib /tools/javac/lib ../lib + * @build ToolBox SourceFileTestBase TestBase InMemoryFileManager * @run main TopLevelClassesOneFileTest */ diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/deprecated/DeprecatedPackageTest.java --- a/langtools/test/tools/javac/classfiles/attributes/deprecated/DeprecatedPackageTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/classfiles/attributes/deprecated/DeprecatedPackageTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -25,8 +25,8 @@ * @test * @bug 8042261 * @summary Checking that deprecated attribute does not apply to classes of deprecated package. - * @library /tools/javac/lib ../lib - * @build DeprecatedPackageTest TestBase TestResult InMemoryFileManager ToolBox + * @library /tools/lib /tools/javac/lib ../lib + * @build ToolBox TestBase TestResult InMemoryFileManager * @run main DeprecatedPackageTest */ diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/deprecated/DeprecatedTest.java --- a/langtools/test/tools/javac/classfiles/attributes/deprecated/DeprecatedTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/classfiles/attributes/deprecated/DeprecatedTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -26,8 +26,8 @@ * @bug 8042261 * @summary Checking what attribute is generated by annotation Deprecated * or javadoc deprecated for field, method, class(inner/local), interface. - * @library /tools/javac/lib ../lib - * @build DeprecatedTest TestBase TestResult InMemoryFileManager ToolBox + * @library /tools/lib /tools/javac/lib ../lib + * @build ToolBox TestBase TestResult InMemoryFileManager * @run main DeprecatedTest */ diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerAnnotationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerAnnotationTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner annotations in inner annotation. + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerAnnotationsInInnerAnnotationTest + */ + +public class InnerAnnotationsInInnerAnnotationTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerAnnotationsInInnerAnnotationTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setInnerAccessModifiers(Modifier.EMPTY, Modifier.PUBLIC); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setOuterClassType(ClassType.ANNOTATION); + setInnerClassType(ClassType.ANNOTATION); + } +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerClassTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerClassTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner annotations in inner class. + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerAnnotationsInInnerClassTest + */ + +public class InnerAnnotationsInInnerClassTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerAnnotationsInInnerClassTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setForbiddenWithoutStaticInOuterMods(true); + setOuterClassType(ClassType.CLASS); + setInnerClassType(ClassType.ANNOTATION); + } +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerEnumTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerEnumTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner annotations in inner enum. + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerAnnotationsInInnerEnumTest + */ + +public class InnerAnnotationsInInnerEnumTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerAnnotationsInInnerEnumTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.STATIC); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.STATIC, Modifier.ABSTRACT); + setOuterClassType(ClassType.ENUM); + setInnerClassType(ClassType.ANNOTATION); + setPrefix("Inner {;"); + setSuffix("}"); + } +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerInterfaceTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerInterfaceTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner annotations in inner interface. + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerAnnotationsInInnerInterfaceTest + */ + +public class InnerAnnotationsInInnerInterfaceTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerAnnotationsInInnerInterfaceTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setInnerAccessModifiers(Modifier.EMPTY, Modifier.PUBLIC); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setOuterClassType(ClassType.INTERFACE); + setInnerClassType(ClassType.ANNOTATION); + } +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesHierarchyTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesHierarchyTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,433 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Test that inner classes have in its inner classes attribute enclosing classes and its immediate members. + * @library /tools/lib /tools/javac/lib ../lib + * @build TestResult TestBase InMemoryFileManager ToolBox + * @run main InnerClassesHierarchyTest + */ + +import com.sun.tools.classfile.*; +import com.sun.tools.classfile.InnerClasses_attribute.Info; + +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.util.*; +import java.util.stream.Collectors; + +public class InnerClassesHierarchyTest extends TestResult { + + private final Map> innerClasses; + private final String outerClassName; + + public InnerClassesHierarchyTest() throws IOException, ConstantPoolException { + innerClasses = new HashMap<>(); + outerClassName = InnerClassesHierarchyTest.class.getSimpleName(); + File classDir = getClassDir(); + FilenameFilter filter = + (dir, name) -> name.matches(outerClassName + ".*\\.class"); + for (File file : Arrays.asList(classDir.listFiles(filter))) { + ClassFile classFile = readClassFile(file); + String className = classFile.getName(); + for (ConstantPool.CPInfo info : classFile.constant_pool.entries()) { + if (info instanceof ConstantPool.CONSTANT_Class_info) { + ConstantPool.CONSTANT_Class_info classInfo = + (ConstantPool.CONSTANT_Class_info) info; + String cpClassName = classInfo.getBaseName(); + if (isInnerClass(cpClassName)) { + get(className).add(cpClassName); + } + } + } + } + } + + private boolean isInnerClass(String cpClassName) { + return cpClassName.contains("$"); + } + + private Set get(String className) { + if (!innerClasses.containsKey(className)) { + innerClasses.put(className, new HashSet<>()); + } + return innerClasses.get(className); + } + + public static void main(String[] args) throws IOException, ConstantPoolException, TestFailedException { + new InnerClassesHierarchyTest().test(); + } + + private void test() throws TestFailedException { + addTestCase("Source file is InnerClassesHierarchyTest.java"); + try { + Queue queue = new LinkedList<>(); + Set visitedClasses = new HashSet<>(); + queue.add(outerClassName); + while (!queue.isEmpty()) { + String currentClassName = queue.poll(); + if (!currentClassName.startsWith(outerClassName)) { + continue; + } + ClassFile cf = readClassFile(currentClassName); + InnerClasses_attribute attr = (InnerClasses_attribute) + cf.getAttribute(Attribute.InnerClasses); + assertNotNull(attr, "Class should not contain " + + "inner classes attribute : " + currentClassName); + assertTrue(innerClasses.containsKey(currentClassName), + "map contains class name : " + currentClassName); + Set setClasses = innerClasses.get(currentClassName); + if (setClasses == null) { + continue; + } + assertEquals(attr.number_of_classes, + setClasses.size(), + "Check number of inner classes : " + setClasses); + for (Info info : attr.classes) { + String innerClassName = info + .getInnerClassInfo(cf.constant_pool).getBaseName(); + assertTrue(setClasses.contains(innerClassName), + currentClassName + " contains inner class : " + + innerClassName); + if (visitedClasses.add(innerClassName)) { + queue.add(innerClassName); + } + } + } + Set allClasses = innerClasses.entrySet().stream() + .flatMap(entry -> entry.getValue().stream()) + .collect(Collectors.toSet()); + + Set a_b = removeAll(visitedClasses, allClasses); + Set b_a = removeAll(allClasses, visitedClasses); + assertEquals(visitedClasses, allClasses, + "All classes are found\n" + + "visited - all classes : " + a_b + + "\nall classes - visited : " + b_a); + } catch (Exception e) { + addFailure(e); + } finally { + checkStatus(); + } + } + + private Set removeAll(Set set1, Set set2) { + Set set = new HashSet<>(set1); + set.removeAll(set2); + return set; + } + + public static class A1 { + + public class B1 { + } + + public enum B2 { + } + + public interface B3 { + } + + public @interface B4 { + } + + public void f() { + new B1() { + }; + new B3() { + }; + new B4() { + @Override + public Class annotationType() { + return null; + } + }; + class B5 { + } + } + + Runnable r = () -> { + new B1() { + }; + new B3() { + }; + new B4() { + @Override + public Class annotationType() { + return null; + } + }; + class B5 { + } + }; + } + + public enum A2 {; + + public class B1 { + } + + public enum B2 { + } + + public interface B3 { + } + + public @interface B4 { + } + + public void a2() { + new B1() { + }; + new B3() { + }; + new B4() { + @Override + public Class annotationType() { + return null; + } + }; + class B5 { + } + } + + Runnable r = () -> { + new B1() { + }; + new B3() { + }; + new B4() { + @Override + public Class annotationType() { + return null; + } + }; + class B5 { + } + }; + } + + public interface A3 { + + public class B1 { + } + + public enum B2 { + } + + public interface B3 { + } + + public @interface B4 { + } + + default void a1() { + new B1() { + }; + new B3() { + }; + new B4() { + @Override + public Class annotationType() { + return null; + } + }; + class B5 { + } + } + + static void a2() { + new B1() { + }; + new B3() { + }; + new B4() { + @Override + public Class annotationType() { + return null; + } + }; + class B5 { + } + } + } + + public @interface A4 { + + public class B1 { + } + + public enum B2 { + } + + public interface B3 { + } + + public @interface B4 { + } + } + + { + new A1() { + class B1 { + } + + public void a2() { + new B1() { + }; + class B5 { + } + } + }; + new A3() { + class B1 { + } + + public void a3() { + new B1() { + }; + class B5 { + } + } + }; + new A4() { + @Override + public Class annotationType() { + return null; + } + + class B1 { + } + + public void a4() { + new B1() { + }; + class B5 { + } + } + }; + Runnable r = () -> { + new A1() { + }; + new A3() { + }; + new A4() { + @Override + public Class annotationType() { + return null; + } + }; + class B5 { + } + }; + } + + static { + new A1() { + class B1 { + } + + public void a2() { + new B1() { + }; + class B5 { + } + } + }; + new A3() { + class B1 { + } + + public void a3() { + new B1() { + }; + class B5 { + } + } + }; + new A4() { + @Override + public Class annotationType() { + return null; + } + + class B1 { + } + + public void a4() { + new B1() { + }; + class B5 { + } + } + }; + Runnable r = () -> { + new A1() { + }; + new A3() { + }; + new A4() { + @Override + public Class annotationType() { + return null; + } + }; + class B5 { + } + }; + } + + public void a5() { + class A5 { + + class B1 { + } + + public void a5() { + new B1() { + }; + + class B5 { + } + } + } + Runnable r = () -> { + new A1() { + }; + new A3() { + }; + new A4() { + @Override + public Class annotationType() { + return null; + } + }; + class B5 { + } + }; + } +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInAnonymousClassTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInAnonymousClassTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner classes in anonymous class. + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesTestBase TestResult TestBase InMemoryFileManager ToolBox + * @run main InnerClassesInAnonymousClassTest + */ + +import java.util.*; + +public class InnerClassesInAnonymousClassTest extends InnerClassesTestBase { + + private ClassType currentClassType; + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerClassesInAnonymousClassTest(); + test.test("InnerClassesSrc$1", "Anonymous", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setInnerAccessModifiers(Modifier.EMPTY); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.FINAL); + setOuterClassType(ClassType.OTHER); + setInnerClassType(ClassType.CLASS); + setSuffix("};}"); + } + + @Override + public List generateTestCases() { + currentClassType = ClassType.CLASS; + setPrefix("class Anonymous {} {new Anonymous() {"); + List sources = super.generateTestCases(); + + currentClassType = ClassType.INTERFACE; + setPrefix("interface Anonymous {} {new Anonymous() {"); + sources.addAll(super.generateTestCases()); + + currentClassType = ClassType.ANNOTATION; + setPrefix("@interface Anonymous {} {new Anonymous() {@Override public " + + "Class " + + "annotationType() {return null;}"); + sources.addAll(super.generateTestCases()); + return sources; + } + + @Override + public void getAdditionalFlags(Map> class2Flags, ClassType type, Modifier... flags) { + super.getAdditionalFlags(class2Flags, type, flags); + class2Flags.put("Anonymous", getFlags(currentClassType, Arrays.asList(flags))); + class2Flags.put("1", new HashSet<>()); + } +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerAnnotationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerAnnotationTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner classes in inner annotation. + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestResult TestBase InMemoryFileManager ToolBox + * @run main InnerClassesInInnerAnnotationTest + */ + +public class InnerClassesInInnerAnnotationTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerClassesInInnerAnnotationTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setInnerAccessModifiers(Modifier.EMPTY, Modifier.PUBLIC); + setOuterClassType(ClassType.ANNOTATION); + setInnerClassType(ClassType.CLASS); + } +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerClassTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerClassTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8034854 8042251 + * @summary Testing InnerClasses_attribute of inner classes in inner class. + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestResult TestBase InMemoryFileManager ToolBox + * @run main InnerClassesInInnerClassTest + */ + +import java.util.List; + +public class InnerClassesInInnerClassTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerClassesInInnerClassTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setHasSyntheticClass(true); + setOuterClassType(ClassType.CLASS); + setInnerClassType(ClassType.CLASS); + } + + @Override + public List generateTestCases() { + setForbiddenWithoutStaticInOuterMods(true); + List sources = super.generateTestCases(); + + setForbiddenWithoutStaticInOuterMods(false); + setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.FINAL); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.FINAL); + sources.addAll(super.generateTestCases()); + + return sources; + } +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerClassTestBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerClassTestBase.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.Arrays; +import java.util.Map; +import java.util.Set; + +/** + * + * Base class for tests that check inner classes in inner class. + * + * @author Andrei Eremeev + */ +public abstract class InnerClassesInInnerClassTestBase extends InnerClassesTestBase { + + public InnerClassesInInnerClassTestBase() { + setPrefix("Inner {"); + setSuffix("}"); + } + + @Override + public void getAdditionalFlags( + Map> class2Flags, ClassType type, Modifier...flags) { + super.getAdditionalFlags(class2Flags, type, flags); + class2Flags.put("Inner", getFlags(type, Arrays.asList(flags))); + } +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerEnumTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerEnumTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8034854 8042251 + * @summary Testing InnerClasses_attribute of inner classes in inner enum. + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestResult TestBase InMemoryFileManager ToolBox + * @run main InnerClassesInInnerEnumTest + */ + +public class InnerClassesInInnerEnumTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerClassesInInnerEnumTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.STATIC); + setOuterClassType(ClassType.ENUM); + setInnerClassType(ClassType.CLASS); + setHasSyntheticClass(true); + setPrefix("Inner {;"); + setSuffix("}"); + } +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerInterfaceTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerInterfaceTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner classes in inner interface. + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestResult TestBase InMemoryFileManager ToolBox + * @run main InnerClassesInInnerInterfaceTest + */ + +public class InnerClassesInInnerInterfaceTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerClassesInInnerInterfaceTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT); + setInnerAccessModifiers(Modifier.EMPTY, Modifier.PUBLIC); + setOuterClassType(ClassType.INTERFACE); + setInnerClassType(ClassType.CLASS); + } +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInLocalClassTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInLocalClassTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner classes in local class. + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesTestBase TestResult TestBase InMemoryFileManager ToolBox + * @run main InnerClassesInLocalClassTest + */ + +import java.util.*; + +public class InnerClassesInLocalClassTest extends InnerClassesTestBase { + + private final static Modifier[] LOCAL_CLASS_MODIFIERS = + new Modifier[]{Modifier.EMPTY, Modifier.ABSTRACT, Modifier.FINAL}; + private final static String CLASS_TEMPLATE = + "public %CLASS% OuterClass {\n" + + "%SOURCE%\n" + + "}"; + + private final List innerClassesData; + + public InnerClassesInLocalClassTest() { + innerClassesData = new ArrayList<>(); + for (Modifier outerModifier : LOCAL_CLASS_MODIFIERS) { + StringBuilder sb = new StringBuilder(); + sb.append(outerModifier.getString()).append(' '); + sb.append("class Local {"); + Map> class2Flags = new HashMap<>(); + for (int i = 0; i < LOCAL_CLASS_MODIFIERS.length; ++i) { + Modifier innerModifier = LOCAL_CLASS_MODIFIERS[i]; + sb.append(innerModifier.getString()).append(' ') + .append("class").append(' ') + .append('A').append(i).append("{}\n"); + class2Flags.put("A" + i, getFlags(innerModifier)); + } + sb.append("};"); + class2Flags.put("1Local", getFlags(outerModifier)); + innerClassesData.add(new Data(sb.toString(), class2Flags)); + } + } + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerClassesInLocalClassTest(); + test.test("OuterClass$1Local", "1Local"); + } + + @Override + public void setProperties() { + } + + @Override + public List generateTestCases() { + List testCases = new ArrayList<>(); + testCases.addAll(localClassInClassMethod()); + testCases.addAll(localClassInInterfaceMethod()); + return testCases; + } + + private List localClassInClassMethod() { + List list = new ArrayList<>(); + String template = CLASS_TEMPLATE.replace("%CLASS%", "class"); + list.addAll(lambda(template)); + list.addAll(constructor(template)); + list.addAll(method(template, + new Modifier[]{Modifier.EMPTY, Modifier.PRIVATE, Modifier.PROTECTED, Modifier.PUBLIC}, + new Modifier[]{Modifier.EMPTY, Modifier.FINAL, Modifier.STATIC})); + list.addAll(staticAndInstanceInitializer(template)); + return list; + } + + private List localClassInInterfaceMethod() { + String template = CLASS_TEMPLATE.replace("%CLASS%", "interface"); + return method(template, + new Modifier[]{Modifier.EMPTY, Modifier.PUBLIC}, + new Modifier[]{Modifier.DEFAULT, Modifier.STATIC}); + } + + private List generate(String template, String prefix, String suffix) { + List list = new ArrayList<>(); + for (Data data : innerClassesData) { + list.add(new TestCase(template.replace("%SOURCE%", + prefix + data.sources + suffix), + data.class2Flags)); + } + return list; + } + + private List lambda(String template) { + return generate(template, "Runnable run = () -> {", "};"); + } + + private List constructor(String template) { + List list = new ArrayList<>(); + for (Modifier modifier : + new Modifier[]{Modifier.EMPTY, Modifier.PRIVATE, Modifier.PROTECTED, Modifier.PUBLIC}) { + list.addAll(generate(template, modifier.getString() + " OuterClass() {", "}")); + } + return list; + } + + private List method(String template, Modifier[] mods, Modifier[] otherMods) { + List list = new ArrayList<>(); + for (Modifier modifier : mods) { + for (Modifier otherMod : otherMods) { + list.addAll(generate(template, + String.format("%s %s void method() {", + modifier.getString(), + otherMod.getString()), + "}")); + } + } + return list; + } + + private List staticAndInstanceInitializer(String template) { + List list = new ArrayList<>(); + for (Modifier modifier : new Modifier[]{Modifier.EMPTY, Modifier.STATIC}) { + list.addAll(generate(template, modifier.getString() + "{", "}")); + } + return list; + } + + private Set getFlags(Modifier modifier) { + HashSet set = new HashSet<>(); + if (modifier != Modifier.EMPTY) { + set.add("ACC_" + modifier.getString().toUpperCase()); + } + return set; + } + + /** + * Class represents part of sources which is inserted in other code. + */ + private static class Data { + public final String sources; + public final Map> class2Flags; + + public Data(String sources, Map> class2Flags) { + this.sources = sources; + this.class2Flags = class2Flags; + } + } +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesIndexTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesIndexTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Test that outer_class_info_index of local and anonymous class is zero. + * @library /tools/lib /tools/javac/lib ../lib + * @build TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerClassesIndexTest + */ + +import java.io.File; +import java.io.FilenameFilter; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import com.sun.tools.classfile.Attribute; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.InnerClasses_attribute; +import com.sun.tools.classfile.InnerClasses_attribute.Info; + +public class InnerClassesIndexTest extends TestResult { + + public static void main(String[] args) throws TestFailedException { + new InnerClassesIndexTest().test(); + } + + private boolean isExcluded(String className) { + return !className.startsWith(InnerClassesIndexTest.class.getName()) + || "InnerClassesIndexTest$Inner".equals(className); + } + + private Set getInnerClasses() { + FilenameFilter filter = (dir, name) -> name.matches("InnerClassesIndexTest\\$.*\\.class"); + return Stream.of(getClassDir().listFiles(filter)) + .map(File::getName) + .map(s -> s.replace(".class", "")) + .collect(Collectors.toSet()); + } + + public void test() throws TestFailedException { + try { + addTestCase("Source is InnerClassesIndexTest.java"); + ClassFile classFile = readClassFile(InnerClassesIndexTest.class); + InnerClasses_attribute attr = (InnerClasses_attribute) + classFile.getAttribute(Attribute.InnerClasses); + + Set foundClasses = new HashSet<>(); + for (Info info : attr.classes) { + String innerName = classFile.constant_pool. + getClassInfo(info.inner_class_info_index).getBaseName(); + echo("Testing class : " + innerName); + if (isExcluded(innerName)) { + echo("Ignored : " + innerName); + continue; + } + foundClasses.add(innerName); + assertEquals(info.outer_class_info_index, 0, + "outer_class_info_index of " + innerName); + if (innerName.matches("\\$\\d+")) { + assertEquals(info.inner_name_index, 0, + "inner_name_index of anonymous class"); + } + } + Set expectedClasses = getInnerClasses(); + expectedClasses.remove("InnerClassesIndexTest$Inner"); + assertEquals(foundClasses, expectedClasses, "All classes are found"); + } catch (Exception e) { + addFailure(e); + } finally { + checkStatus(); + } + } + + static class Inner { + } + + Inner inner1 = new Inner() { + }; + + static Inner inner2 = new Inner() { + }; + + Runnable r = () -> { + class Local { + } + new Local() { + }; + }; + + public void local() { + class Local { + } + new Local() { + }; + } + + public InnerClassesIndexTest() { + class Local { + } + new Local() { + }; + } + + { + class Local { + } + new Local() { + }; + } + + static { + class Local { + } + new Local() { + }; + } +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * @test + * @bug 8034854 8042251 + * @summary Testing inner classes attributes. + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerClassesTest + */ + +import java.util.List; + +public class InnerClassesTest extends InnerClassesTestBase { + + public static void main(String[] args) throws TestFailedException { + new InnerClassesTest().test("InnerClassesSrc"); + } + + private List generateClasses() { + setInnerClassType(ClassType.CLASS); + setHasSyntheticClass(true); + return super.generateTestCases(); + } + + private List generateEnums() { + setInnerOtherModifiers(Modifier.EMPTY, Modifier.STATIC); + setInnerClassType(ClassType.ENUM); + setHasSyntheticClass(false); + return super.generateTestCases(); + } + + private List generateInterfaces() { + setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setInnerClassType(ClassType.INTERFACE); + return super.generateTestCases(); + } + + private List generateAnnotations() { + setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setInnerClassType(ClassType.ANNOTATION); + return super.generateTestCases(); + } + + @Override + public void setProperties() { + setOuterAccessModifiers(Modifier.EMPTY); + setOuterOtherModifiers(Modifier.EMPTY); + setOuterClassType(ClassType.OTHER); + } + + @Override + public List generateTestCases() { + List sources = generateClasses(); + sources.addAll(generateEnums()); + sources.addAll(generateInterfaces()); + sources.addAll(generateAnnotations()); + return sources; + } +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesTestBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesTestBase.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,446 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.sun.tools.classfile.Attribute; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.InnerClasses_attribute; +import com.sun.tools.classfile.InnerClasses_attribute.Info; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * Base class for tests of inner classes attribute. + * The scenario of tests: + * 1. set possible values of class modifiers. + * 2. according to set class modifiers, a test generates sources + * and golden data with {@code generateTestCases}. + * 3. a test loops through all test cases and checks InnerClasses + * attribute with {@code test}. + * + * Example, possible flags for outer class are {@code Modifier.PRIVATE and Modifier.PUBLIC}, + * possible flags for inner class are {@code Modifier.EMPTY}. + * At the second step the test generates two test cases: + * 1. public class A { + * public class B { + * class C {} + * } + * } + * 2. public class A { + * private class B { + * class C {} + * } + * } + */ +public abstract class InnerClassesTestBase extends TestResult { + + private Modifier[] outerAccessModifiers = {Modifier.EMPTY, Modifier.PRIVATE, Modifier.PROTECTED, Modifier.PUBLIC}; + private Modifier[] outerOtherModifiers = {Modifier.EMPTY, Modifier.STATIC, Modifier.FINAL, Modifier.ABSTRACT}; + private Modifier[] innerAccessModifiers = outerAccessModifiers; + private Modifier[] innerOtherModifiers = outerOtherModifiers; + private boolean isForbiddenWithoutStaticInOuterMods = false; + + private ClassType outerClassType; + private ClassType innerClassType; + private boolean hasSyntheticClass; + private String prefix = ""; + private String suffix = ""; + + /** + * Sets properties. + * + * Returns generated list of test cases. Method is called in {@code test()}. + */ + public abstract void setProperties(); + + /** + * Runs the test. + * + * @param classToTest expected name of outer class + * @param skipClasses classes that names should not be checked + */ + public void test(String classToTest, String...skipClasses) throws TestFailedException { + try { + for (TestCase test : generateTestCases()) { + addTestCase(test.getSource()); + test(classToTest, test, skipClasses); + } + } catch (Exception e) { + addFailure(e); + } finally { + checkStatus(); + } + } + + /** + * If {@code flag} is {@code true} an outer class can not have static modifier. + * + * @param flag if {@code true} the outer class can not have static modifier + */ + public void setForbiddenWithoutStaticInOuterMods(boolean flag) { + isForbiddenWithoutStaticInOuterMods = flag; + } + + /** + * Sets the possible access flags of an outer class. + * + * @param mods the possible access flags of an outer class + */ + public void setOuterAccessModifiers(Modifier...mods) { + outerAccessModifiers = mods; + } + + /** + * Sets the possible flags of an outer class. + * + * @param mods the possible flags of an outer class + */ + public void setOuterOtherModifiers(Modifier...mods) { + outerOtherModifiers = mods; + } + + /** + * Sets the possible access flags of an inner class. + * + * @param mods the possible access flags of an inner class + */ + public void setInnerAccessModifiers(Modifier...mods) { + innerAccessModifiers = mods; + } + + /** + * Sets the possible flags of an inner class. + * + * @param mods the possible flags of an inner class + */ + public void setInnerOtherModifiers(Modifier...mods) { + innerOtherModifiers = mods; + } + + /** + * Sets the suffix for the generated source. + * + * @param suffix a suffix + */ + public void setSuffix(String suffix) { + this.suffix = suffix; + } + + /** + * Sets the prefix for the generated source. + * + * @param prefix a prefix + */ + public void setPrefix(String prefix) { + this.prefix = prefix; + } + + /** + * If {@code true} synthetic class is generated. + * + * @param hasSyntheticClass if {@code true} synthetic class is generated + */ + public void setHasSyntheticClass(boolean hasSyntheticClass) { + this.hasSyntheticClass = hasSyntheticClass; + } + + /** + * Sets the inner class type. + * + * @param innerClassType the inner class type + */ + public void setInnerClassType(ClassType innerClassType) { + this.innerClassType = innerClassType; + } + + /** + * Sets the outer class type. + * + * @param outerClassType the outer class type + */ + public void setOuterClassType(ClassType outerClassType) { + this.outerClassType = outerClassType; + } + + private void test(String classToTest, TestCase test, String...skipClasses) { + printf("Testing :\n%s\n", test.getSource()); + try { + Map> class2Flags = test.getFlags(); + ClassFile cf = readClassFile(compile(test.getSource()) + .getClasses().get(classToTest)); + InnerClasses_attribute innerClasses = (InnerClasses_attribute) + cf.getAttribute(Attribute.InnerClasses); + int count = 0; + for (Attribute a : cf.attributes.attrs) { + if (a instanceof InnerClasses_attribute) { + ++count; + } + } + assertEquals(1, count, "Number of inner classes attribute"); + if (innerClasses == null) { + return; + } + assertEquals(cf.constant_pool. + getUTF8Info(innerClasses.attribute_name_index).value, "InnerClasses", + "innerClasses.attribute_name_index"); + // Inner Classes attribute consists of length (2 bytes) + // and 8 bytes for each inner class's entry. + assertEquals(innerClasses.attribute_length, + 2 + 8 * class2Flags.size(), "innerClasses.attribute_length"); + assertEquals(innerClasses.number_of_classes, + class2Flags.size(), "innerClasses.number_of_classes"); + Set visitedClasses = new HashSet<>(); + for (Info e : innerClasses.classes) { + String baseName = cf.constant_pool.getClassInfo( + e.inner_class_info_index).getBaseName(); + if (cf.major_version >= 51 && e.inner_name_index == 0) { + assertEquals(e.outer_class_info_index, 0, + "outer_class_info_index " + + "in case of inner_name_index is zero : " + + baseName); + } + String className = baseName.replaceFirst(".*\\$", ""); + assertTrue(class2Flags.containsKey(className), + className); + assertTrue(visitedClasses.add(className), + "there are no duplicates in attribute : " + className); + assertEquals(e.inner_class_access_flags.getInnerClassFlags(), + class2Flags.get(className), + "inner_class_access_flags " + className); + if (!Arrays.asList(skipClasses).contains(className)) { + assertEquals( + cf.constant_pool.getClassInfo(e.inner_class_info_index).getBaseName(), + classToTest + "$" + className, + "inner_class_info_index of " + className); + if (e.outer_class_info_index > 0) { + assertEquals( + cf.constant_pool.getClassInfo(e.outer_class_info_index).getName(), + classToTest, + "outer_class_info_index of " + className); + } + } + } + } catch (Exception e) { + addFailure(e); + } + } + + /** + * Methods generates list of test cases. Method generates all possible combinations + * of acceptable flags for nested inner classes. + * + * @return generated list of test cases + */ + protected List generateTestCases() { + setProperties(); + List list = new ArrayList<>(); + + List> outerMods = getAllCombinations(outerAccessModifiers, outerOtherModifiers); + List> innerMods = getAllCombinations(innerAccessModifiers, innerOtherModifiers); + + for (List outerMod : outerMods) { + if (isForbiddenWithoutStaticInOuterMods && !outerMod.contains(Modifier.STATIC)) { + continue; + } + StringBuilder sb = new StringBuilder(); + sb.append("public class InnerClassesSrc {") + .append(toString(outerMod)).append(' ') + .append(outerClassType).append(' ') + .append(prefix).append(' ').append('\n'); + int count = 0; + Map> class2Flags = new HashMap<>(); + List syntheticClasses = new ArrayList<>(); + for (List innerMod : innerMods) { + ++count; + String privateConstructor = ""; + if (hasSyntheticClass && !innerMod.contains(Modifier.ABSTRACT)) { + privateConstructor = "private A" + count + "() {}"; + syntheticClasses.add("new A" + count + "();"); + } + sb.append(toString(innerMod)).append(' '); + sb.append(String.format("%s A%d {%s}\n", innerClassType, count, privateConstructor)); + Set flags = getFlags(innerClassType, innerMod); + class2Flags.put("A" + count, flags); + } + if (hasSyntheticClass) { + // Source to generate synthetic classes + sb.append(syntheticClasses.stream().collect(Collectors.joining(" ", "{", "}"))); + class2Flags.put("1", new HashSet<>(Arrays.asList("ACC_STATIC", "ACC_SYNTHETIC"))); + } + sb.append(suffix).append("\n}"); + getAdditionalFlags(class2Flags, outerClassType, outerMod.toArray(new Modifier[outerMod.size()])); + list.add(new TestCase(sb.toString(), class2Flags)); + } + return list; + } + + /** + * Methods returns flags which must have type. + * + * @param type class, interface, enum or annotation + * @param mods modifiers + * @return set of access flags + */ + protected Set getFlags(ClassType type, List mods) { + Set flags = mods.stream() + .map(Modifier::getString) + .filter(str -> !str.isEmpty()) + .map(str -> "ACC_" + str.toUpperCase()) + .collect(Collectors.toSet()); + type.addSpecificFlags(flags); + return flags; + } + + private List> getAllCombinations(Modifier[] accessModifiers, Modifier[] otherModifiers) { + List> list = new ArrayList<>(); + for (Modifier access : accessModifiers) { + for (int i = 0; i < otherModifiers.length; ++i) { + Modifier mod1 = otherModifiers[i]; + for (int j = i + 1; j < otherModifiers.length; ++j) { + Modifier mod2 = otherModifiers[j]; + if (isForbidden(mod1, mod2)) { + continue; + } + list.add(Arrays.asList(access, mod1, mod2)); + } + if (mod1 == Modifier.EMPTY) { + list.add(Arrays.asList(access)); + } + } + } + return list; + } + + private boolean isForbidden(Modifier mod1, Modifier mod2) { + return mod1 == Modifier.FINAL && mod2 == Modifier.ABSTRACT + || mod1 == Modifier.ABSTRACT && mod2 == Modifier.FINAL; + } + + private String toString(List mods) { + return mods.stream() + .map(Modifier::getString) + .filter(s -> !s.isEmpty()) + .collect(Collectors.joining(" ")); + } + + /** + * Method is called in generateTestCases(). + * If you need to add additional access flags, you should override this method. + * + * + * @param class2Flags map with flags + * @param type class, interface, enum or @annotation + * @param mods modifiers + */ + public void getAdditionalFlags(Map> class2Flags, ClassType type, Modifier...mods) { + class2Flags.values().forEach(type::addFlags); + } + + public enum ClassType { + CLASS("class") { + @Override + public void addSpecificFlags(Set flags) { + } + }, + INTERFACE("interface") { + @Override + public void addFlags(Set flags) { + flags.add("ACC_STATIC"); + flags.add("ACC_PUBLIC"); + } + + @Override + public void addSpecificFlags(Set flags) { + flags.add("ACC_INTERFACE"); + flags.add("ACC_ABSTRACT"); + flags.add("ACC_STATIC"); + } + }, + ANNOTATION("@interface") { + @Override + public void addFlags(Set flags) { + flags.add("ACC_STATIC"); + flags.add("ACC_PUBLIC"); + } + + @Override + public void addSpecificFlags(Set flags) { + flags.add("ACC_INTERFACE"); + flags.add("ACC_ABSTRACT"); + flags.add("ACC_STATIC"); + flags.add("ACC_ANNOTATION"); + } + }, + ENUM("enum") { + @Override + public void addSpecificFlags(Set flags) { + flags.add("ACC_ENUM"); + flags.add("ACC_FINAL"); + flags.add("ACC_STATIC"); + } + }, + OTHER("") { + @Override + public void addSpecificFlags(Set flags) { + } + }; + + private final String classType; + + private ClassType(String clazz) { + this.classType = clazz; + } + + public abstract void addSpecificFlags(Set flags); + + public String toString() { + return classType; + } + + public void addFlags(Set set) { + } + } + + public enum Modifier { + PUBLIC("public"), PRIVATE("private"), + PROTECTED("protected"), DEFAULT("default"), + FINAL("final"), ABSTRACT("abstract"), + STATIC("static"), EMPTY(""); + + private final String str; + + private Modifier(String str) { + this.str = str; + } + + public String getString() { + return str; + } + } +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumInInnerAnnotationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumInInnerAnnotationTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner enums in inner annotation. + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerEnumInInnerAnnotationTest + */ + +public class InnerEnumInInnerAnnotationTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerEnumInInnerAnnotationTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setInnerAccessModifiers(Modifier.EMPTY, Modifier.PUBLIC); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.STATIC); + setOuterClassType(ClassType.ANNOTATION); + setInnerClassType(ClassType.ENUM); + } +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumInInnerEnumTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumInInnerEnumTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner enums in inner enum. + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerEnumInInnerEnumTest + */ + +public class InnerEnumInInnerEnumTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerEnumInInnerEnumTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.STATIC); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.STATIC); + setOuterClassType(ClassType.ENUM); + setInnerClassType(ClassType.ENUM); + setPrefix("Inner {;"); + setSuffix("}"); + } +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumInInnerInterfaceTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumInInnerInterfaceTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner enums in inner interface. + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerEnumInInnerInterfaceTest + */ + +public class InnerEnumInInnerInterfaceTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerEnumInInnerInterfaceTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setInnerAccessModifiers(Modifier.EMPTY, Modifier.PUBLIC); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.STATIC); + setOuterClassType(ClassType.INTERFACE); + setInnerClassType(ClassType.ENUM); + } +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumsInInnerClassTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumsInInnerClassTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner enums in inner class. + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerEnumsInInnerClassTest + */ + +public class InnerEnumsInInnerClassTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerEnumsInInnerClassTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setForbiddenWithoutStaticInOuterMods(true); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.STATIC); + setOuterClassType(ClassType.CLASS); + setInnerClassType(ClassType.ENUM); + } +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerAnnotationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerAnnotationTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner interfaces in inner annotation. + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerInterfacesInInnerAnnotationTest + */ + +public class InnerInterfacesInInnerAnnotationTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerInterfacesInInnerAnnotationTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setInnerAccessModifiers(Modifier.EMPTY, Modifier.PUBLIC); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setOuterClassType(ClassType.ANNOTATION); + setInnerClassType(ClassType.INTERFACE); + } +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerClassTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerClassTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Testing InnerClasses_attribute of inner interfaces in inner class. + * @author aeremeev + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerInterfacesInInnerClassTest + */ + +public class InnerInterfacesInInnerClassTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerInterfacesInInnerClassTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setForbiddenWithoutStaticInOuterMods(true); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setOuterClassType(ClassType.CLASS); + setInnerClassType(ClassType.INTERFACE); + } +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerEnumTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerEnumTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner interfaces in inner enum. + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerInterfacesInInnerEnumTest + */ + +public class InnerInterfacesInInnerEnumTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerInterfacesInInnerEnumTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.STATIC); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setOuterClassType(ClassType.ENUM); + setInnerClassType(ClassType.INTERFACE); + setPrefix("Inner {;"); + setSuffix("}"); + } +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerInterfaceTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerInterfaceTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner interfaces in inner interface. + * @library /tools/lib /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerInterfacesInInnerInterfaceTest + */ + +import java.util.List; + +public class InnerInterfacesInInnerInterfaceTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerInterfacesInInnerInterfaceTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setInnerAccessModifiers(Modifier.EMPTY, Modifier.PUBLIC); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setOuterClassType(ClassType.INTERFACE); + setInnerClassType(ClassType.INTERFACE); + } +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/innerclasses/NoInnerClassesTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/NoInnerClassesTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Test that there are no inner classes attributes in case of there are no inner classes. + * @library /tools/lib /tools/javac/lib ../lib + * @build TestBase InMemoryFileManager ToolBox + * @run main NoInnerClassesTest + */ + +import com.sun.tools.classfile.Attribute; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.ConstantPoolException; + +import java.io.IOException; + +public class NoInnerClassesTest extends TestBase { + + public static void main(String[] args) throws IOException, ConstantPoolException { + new NoInnerClassesTest().test(); + } + + public void test() throws IOException, ConstantPoolException { + ClassFile classFile = readClassFile("NoInnerClassesTest"); + assertNull(classFile.getAttribute(Attribute.InnerClasses), "Found inner class attribute"); + } +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/innerclasses/README.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/README.txt Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,92 @@ +The description of the tests for the InnerClasses attribute. + +InnerClassesTestBase is the base class for tests of inner classes attribute. +Each tests extends the base class. +The scenario of tests: + 1. set possible values of class modifiers, outer/inner class types. + 2. according to set class modifiers, a test generates sources + and golden data with generateTestCases. + 3. a test loops through all test cases and checks InnerClasses attribute in method test(). + +Example, possible flags for outer class are Modifier.PRIVATE and Modifier.PUBLIC, +possible flags for inner class are Modifier.EMPTY, outer class type is CLASS +and inner class type is CLASS. +At the second step the test generates two test cases: + 1. public class A { + public class B { + class C {} + } + } + 2. public class A { + private class B { + class C {} + } + } + +The list of tests. + +Test: test if there is not inner class, the InnerClasses attribute +is not generated (NoInnerClasses.java). + +Test: inner classes in anonymous class (InnerClassesInAnonymousClassTest.java). +Possible access flags of the inner class: abstract and final. + +Test: inner classes in local class (InnerClassesInLocalClassTest.java). +Locations of local class: static and instance initializer, constructor, method, lambda, +default and static methods of interface. + +Test: test the outer_class_info_index and inner_name_index of +local and anonymous classes (InnerClassesIndexTest.java). + +List of test cases for Inner*InInner*Test: + * InnerClassesInInnerClassTest + outer flags: all possible flags + inner flags: all possible flags + * InnerClassesInInnerEnumTest + outer flags: all access flags, abstract + inner flags: all possible flags + * InnerClassesInInnerAnnotationTest + outer flags: all access flags, abstract + inner flags: all flags, except private and protected + * InnerClassesInInnerInterfaceTest + outer flags: all access flags, abstract + inner flags: all flags, except private and protected + + * InnerEnumsInInnerClassTest + outer flags: all possible flags + inner flags: all possible flags + * InnerEnumsInInnerEnumTest + outer flags: all possible flags + inner flags: all possible flags + * InnerEnumsInInnerAnnotationTest + outer flags: all access flags, abstract, static + inner flags: public, static + * InnerEnumsInInnerInterfaceTest + outer flags: all access flags, abstract, static + inner flags: public, static + + * InnerAnnotationInInnerClassTest + outer flags: all possible flags, except static + inner flags: all access flags, abstract and static + * InnerAnnotationInInnerEnumTest + outer flags: all access flags, static + inner flags: all access flags, abstract and static + * InnerAnnotationInInnerAnnotation + outer flags: all access flags, static and abstract + inner flags: public, abstract, static + * InnerAnnotationInInnerInterface + outer flags: all access flags, static and abstract + inner flags: public, abstract, static + + * InnerInterfaceInInnerClassTest + outer flags: all possible flags, except static + inner flags: all access flags, abstract and static + * InnerInterfaceInInnerEnumTest + outer flags: all access flags, static + inner flags: all access flags, abstract and static + * InnerInterfaceInInnerAnnotation + outer flags: all access flags, static and abstract + inner flags: public, abstract, static + * InnerInterfaceInInnerInterface + outer flags: all access flags, static and abstract + inner flags: public, abstract, static \ No newline at end of file diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/innerclasses/TestCase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/TestCase.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.Map; +import java.util.Set; + +/** + * Class represents test cases. This class contains source code and + * access flags for each inner class in source code. + */ +public class TestCase { + + private final String sourceCode; + private final Map> class2Flags; + + public TestCase(String sourceCode, Map> class2Flags) { + this.sourceCode = sourceCode; + this.class2Flags = class2Flags; + } + + /** + * Returns source code. + * + * @return source code + */ + public String getSource() { + return sourceCode; + } + + /** + * Returns map with entries (ClassName, set of access flags for the ClassName). + * + * @return map with entries (ClassName, set of access flags for the ClassName) + */ + public Map> getFlags() { + return class2Flags; + } +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/lib/TestBase.java --- a/langtools/test/tools/javac/classfiles/attributes/lib/TestBase.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/classfiles/attributes/lib/TestBase.java Fri Aug 29 11:58:43 2014 -0700 @@ -22,22 +22,23 @@ */ import java.io.File; +import java.io.FileInputStream; import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.function.Function; -import java.util.stream.Stream; +import java.util.stream.Collectors; + import javax.tools.DiagnosticCollector; import javax.tools.JavaCompiler; import javax.tools.JavaFileObject; import javax.tools.ToolProvider; -import static java.lang.String.format; -import static java.lang.System.lineSeparator; -import static java.util.Arrays.asList; -import static java.util.Collections.emptyList; -import static java.util.stream.Collectors.joining; -import static java.util.stream.Collectors.toList; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.ConstantPoolException; /** * Base class for class file attribute tests. @@ -46,7 +47,7 @@ */ public class TestBase { - public static final String LINE_SEPARATOR = lineSeparator(); + public static final String LINE_SEPARATOR = System.lineSeparator(); private InMemoryFileManager compile( List options, @@ -57,7 +58,7 @@ JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); List src = sources.stream() .map(src2JavaFileObject) - .collect(toList()); + .collect(Collectors.toList()); DiagnosticCollector dc = new DiagnosticCollector<>(); try (InMemoryFileManager fileManager @@ -67,7 +68,7 @@ if (!success) { String errorMessage = dc.getDiagnostics().stream() .map(Object::toString) - .collect(joining("\n")); + .collect(Collectors.joining("\n")); throw new CompilationException("Compilation Error\n\n" + errorMessage); } return fileManager; @@ -82,7 +83,7 @@ */ public InMemoryFileManager compile(String... sources) throws IOException, CompilationException { - return compile(emptyList(), sources); + return compile(Collections.emptyList(), sources); } /** @@ -94,7 +95,7 @@ */ public InMemoryFileManager compile(List options, String... sources) throws IOException, CompilationException { - return compile(options, ToolBox.JavaSource::new, asList(sources)); + return compile(options, ToolBox.JavaSource::new, Arrays.asList(sources)); } /** @@ -105,7 +106,7 @@ */ public InMemoryFileManager compile(String[]... sources) throws IOException, CompilationException { - return compile(emptyList(), sources); + return compile(Collections.emptyList(), sources); } /** @@ -117,12 +118,73 @@ */ public InMemoryFileManager compile(List options, String[]... sources) throws IOException, CompilationException { - return compile(options, src -> new ToolBox.JavaSource(src[0], src[1]), asList(sources)); + return compile(options, src -> new ToolBox.JavaSource(src[0], src[1]), Arrays.asList(sources)); + } + + /** + * Returns class file that is read from {@code is}. + * + * @param is an input stream + * @return class file that is read from {@code is} + * @throws IOException if I/O error occurs + * @throws ConstantPoolException if constant pool error occurs + */ + public ClassFile readClassFile(InputStream is) throws IOException, ConstantPoolException { + return ClassFile.read(is); + } + + /** + * Returns class file that is read from {@code fileObject}. + * + * @param fileObject a file object + * @return class file that is read from {@code fileObject} + * @throws IOException if I/O error occurs + * @throws ConstantPoolException if constant pool error occurs + */ + public ClassFile readClassFile(JavaFileObject fileObject) throws IOException, ConstantPoolException { + return readClassFile(fileObject.openInputStream()); + } + + /** + * Returns class file that corresponds to {@code clazz}. + * + * @param clazz a class + * @return class file that is read from {@code clazz} + * @throws IOException if I/O error occurs + * @throws ConstantPoolException if constant pool error occurs + */ + public ClassFile readClassFile(Class clazz) throws IOException, ConstantPoolException { + return readClassFile(getClassFile(clazz)); + } + + /** + * Returns class file that corresponds to {@code className}. + * + * @param className a class name + * @return class file that is read from {@code className} + * @throws IOException if I/O error occurs + * @throws ConstantPoolException if constant pool error occurs + */ + public ClassFile readClassFile(String className) throws IOException, ConstantPoolException { + return readClassFile(getClassFile(className + ".class")); + } + + /** + * Returns class file that is read from {@code file}. + * + * @param file a file + * @return class file that is read from {@code file} + * @throws IOException if I/O error occurs + * @throws ConstantPoolException if constant pool error occurs + */ + public ClassFile readClassFile(File file) throws IOException, ConstantPoolException { + return readClassFile(new FileInputStream(file)); } public void assertEquals(Object actual, Object expected, String message) { if (!Objects.equals(actual, expected)) - throw new AssertionFailedException(format("%s%nGot: %s, Expected: %s", message, actual, expected)); + throw new AssertionFailedException(String.format("%s%nGot: %s, Expected: %s", + message, actual, expected)); } public void assertNull(Object actual, String message) { @@ -169,22 +231,18 @@ * @param message string to print. */ public void echo(String message) { - System.err.println(message.replace("\n", LINE_SEPARATOR)); + printf(message + "\n"); } /** - * Substitutes args in template and prints result to standard error. New lines are converted to system dependent NL. + * Substitutes args in template and prints result to standard error. + * New lines are converted to system dependent NL. * * @param template template in standard String.format(...) format. * @param args arguments to substitute in template. */ public void printf(String template, Object... args) { - System.err.printf(template, Stream.of(args) - .map(Objects::toString) - .map(m -> m.replace("\n", LINE_SEPARATOR)) - .collect(toList()) - .toArray()); - + System.err.printf(String.format(template, args).replace("\n", LINE_SEPARATOR)); } public static class CompilationException extends Exception { diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/classfiles/attributes/lib/TestResult.java --- a/langtools/test/tools/javac/classfiles/attributes/lib/TestResult.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/classfiles/attributes/lib/TestResult.java Fri Aug 29 11:58:43 2014 -0700 @@ -23,13 +23,15 @@ import java.io.PrintWriter; import java.io.StringWriter; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; +import java.util.*; +import java.util.stream.Stream; import static java.lang.String.format; import static java.util.stream.Collectors.joining; +/** + * This class accumulates test results. Test results can be checked with method @{code checkStatus}. + */ public class TestResult extends TestBase { private final List testCases; @@ -39,15 +41,18 @@ testCases.add(new Info("Global test info")); } - public void addTestCase(String src) { - testCases.add(new Info(src)); + /** + * Adds new test case info. + * + * @param info the information about test case + */ + public void addTestCase(String info) { + testCases.add(new Info(info)); } - public String errorMessage() { + private String errorMessage() { return testCases.stream().filter(Info::isFailed) - .map(tc -> format("Failure in test case:\n%s\n%s", tc.info(), - (tc.asserts.size() > 0 ? tc.getAssertMessage() + "\n" : "") - + tc.getErrorMessage())) + .map(tc -> format("Failure in test case:\n%s\n%s", tc.info(), tc.getMessage())) .collect(joining("\n")); } @@ -76,8 +81,14 @@ getLastTestCase().assertEquals(actual, true, message); } + public void assertContains(Set found, Set expected, String message) { + Set copy = new HashSet<>(expected); + copy.removeAll(found); + assertTrue(found.containsAll(expected), message + " : " + copy); + } + public void addFailure(Throwable th) { - getLastTestCase().addFailure(th); + testCases.get(testCases.size() - 1).addFailure(th); } private Info getLastTestCase() { @@ -87,6 +98,13 @@ return testCases.get(testCases.size() - 1); } + /** + * Throws {@code TestFailedException} if one of the asserts are failed + * or an exception occurs. Prints error message of failed test cases. + * + * @throws TestFailedException if one of the asserts are failed + * or an exception occurs + */ public void checkStatus() throws TestFailedException { if (testCases.stream().anyMatch(Info::isFailed)) { echo(errorMessage()); @@ -120,7 +138,13 @@ } public void addFailure(String message) { - asserts.add(message); + String stackTrace = Stream.of(Thread.currentThread().getStackTrace()) + // just to get stack trace without TestResult and Thread + .filter(e -> !"TestResult.java".equals(e.getFileName()) && + !"java.lang.Thread".equals(e.getClassName())) + .map(e -> "\tat " + e) + .collect(joining("\n")); + asserts.add(format("%s\n%s", message, stackTrace)); printf("[ASSERT] : %s\n", message); } @@ -138,6 +162,10 @@ } } + public String getMessage() { + return (asserts.size() > 0 ? getAssertMessage() + "\n" : "") + getErrorMessage(); + } + public String getAssertMessage() { return asserts.stream() .map(failure -> "[ASSERT] : " + failure) @@ -146,8 +174,7 @@ public String getErrorMessage() { return errors.stream() - .map(throwable -> - format("[ERROR] : %s", getStackTrace(throwable))) + .map(throwable -> format("[ERROR] : %s", getStackTrace(throwable))) .collect(joining("\n")); } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/defaultMethodsVisibility/DefaultMethodsNotVisibleForSourceLessThan8Test.java --- a/langtools/test/tools/javac/defaultMethodsVisibility/DefaultMethodsNotVisibleForSourceLessThan8Test.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/defaultMethodsVisibility/DefaultMethodsNotVisibleForSourceLessThan8Test.java Fri Aug 29 11:58:43 2014 -0700 @@ -26,7 +26,7 @@ * @bug 8029240 8030855 * @summary Default methods not always visible under -source 7 * Default methods should be visible under source previous to 8 - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main DefaultMethodsNotVisibleForSourceLessThan8Test */ @@ -111,6 +111,7 @@ String outDir; String source; + ToolBox tb = new ToolBox(); void run(String source) throws Exception { this.source = source; @@ -127,50 +128,53 @@ /* as an extra check let's make sure that interface 'I' can't be compiled * with source < 8 */ - ToolBox.JavaToolArgs javacArgs = - new ToolBox.JavaToolArgs(ToolBox.Expect.FAIL) - .setOptions("-d", outDir, "-source", source) - .setSources(ISrc); - ToolBox.javac(javacArgs); + tb.new JavacTask() + .outdir(outDir) + .options("-source", source) + .sources(ISrc) + .run(ToolBox.Expect.FAIL); //but it should compile with source >= 8 - javacArgs = - new ToolBox.JavaToolArgs() - .setOptions("-d", outDir) - .setSources(ISrc); - ToolBox.javac(javacArgs); + tb.new JavacTask() + .outdir(outDir) + .sources(ISrc) + .run(); - javacArgs = - new ToolBox.JavaToolArgs() - .setOptions("-cp", outDir, "-d", outDir, "-source", source) - .setSources(JSrc, ASrc, BSrc); - ToolBox.javac(javacArgs); + tb.new JavacTask() + .outdir(outDir) + .classpath(outDir) + .options("-source", source) + .sources(JSrc, ASrc, BSrc) + .run(); } void testLegacyImplementations() throws Exception { //compile C1-4 - ToolBox.JavaToolArgs javacArgs = - new ToolBox.JavaToolArgs() - .setOptions("-cp", outDir, "-d", outDir, "-source", source) - .setSources(C1Src, C2Src, C3Src, C4Src); - ToolBox.javac(javacArgs); + tb.new JavacTask() + .outdir(outDir) + .classpath(outDir) + .options("-source", source) + .sources(C1Src, C2Src, C3Src, C4Src) + .run(); } void testLegacyInvocations() throws Exception { //compile LegacyInvocation - ToolBox.JavaToolArgs javacArgs = - new ToolBox.JavaToolArgs() - .setOptions("-cp", outDir, "-d", outDir, "-source", source) - .setSources(LegacyInvocationSrc); - ToolBox.javac(javacArgs); + tb.new JavacTask() + .outdir(outDir) + .classpath(outDir) + .options("-source", source) + .sources(LegacyInvocationSrc) + .run(); } void testSuperInvocations() throws Exception { //compile SubA, SubB - ToolBox.JavaToolArgs javacArgs = - new ToolBox.JavaToolArgs() - .setOptions("-cp", outDir, "-d", outDir, "-source", source) - .setSources(SubASrc, SubBSrc); - ToolBox.javac(javacArgs); + tb.new JavacTask() + .outdir(outDir) + .classpath(outDir) + .options("-source", source) + .sources(SubASrc, SubBSrc) + .run(); } } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/fatalErrors/NoJavaLangTest.java --- a/langtools/test/tools/javac/fatalErrors/NoJavaLangTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/fatalErrors/NoJavaLangTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -25,15 +25,12 @@ * @test * @bug 4263768 4785453 * @summary Verify that the compiler does not crash when java.lang is not - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main NoJavaLangTest */ -import java.util.ArrayList; -import java.util.List; - -//original test: test/tools/javac/fatalErrors/NoJavaLang.sh +// Original test: test/tools/javac/fatalErrors/NoJavaLang.sh public class NoJavaLangTest { private static final String noJavaLangSrc = @@ -49,26 +46,20 @@ "Fatal Error: Unable to find package java.lang in classpath or bootclasspath"; public static void main(String[] args) throws Exception { -// "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} NoJavaLang.java 2> "${TMP1}" - ToolBox.JavaToolArgs javacSuccessArgs = - new ToolBox.JavaToolArgs().setSources(noJavaLangSrc); - ToolBox.javac(javacSuccessArgs); + ToolBox tb = new ToolBox(); + + tb.new JavacTask() + .sources(noJavaLangSrc) + .run(); -// "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -bootclasspath . NoJavaLang.java 2> "${TMP1}" - List output = new ArrayList<>(); - ToolBox.JavaToolArgs javacFailArgs = - new ToolBox.JavaToolArgs(ToolBox.Expect.FAIL) - .setOptions("-bootclasspath", ".") - .setSources(noJavaLangSrc) - .setErrOutput(output); + String out = tb.new JavacTask() + .options("-bootclasspath", ".") + .sources(noJavaLangSrc) + .run(ToolBox.Expect.FAIL, 3) + .writeAll() + .getOutput(ToolBox.OutputKind.DIRECT); - int cr = ToolBox.javac(javacFailArgs); - if (cr != 3) { - throw new AssertionError("Compiler exit result should be 3"); - } - -// diff ${DIFFOPTS} -c "${TESTSRC}${FS}NoJavaLang.out" "${TMP1}" - if (!(output.size() == 1 && output.get(0).equals(compilerErrorMessage))) { + if (!out.trim().equals(compilerErrorMessage)) { throw new AssertionError("javac generated error output is not correct"); } } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/innerClassFile/InnerClassFileTest.java --- a/langtools/test/tools/javac/innerClassFile/InnerClassFileTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/innerClassFile/InnerClassFileTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -25,14 +25,15 @@ * @test * @bug 4491755 4785453 * @summary Prob w/static inner class with same name as a regular class - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main InnerClassFileTest */ +import java.nio.file.Path; import java.nio.file.Paths; -//original test: test/tools/javac/innerClassFile/Driver.sh +// Original test: test/tools/javac/innerClassFile/Driver.sh public class InnerClassFileTest { private static final String BSrc = @@ -90,38 +91,37 @@ new InnerClassFileTest().run(); } + private final ToolBox tb = new ToolBox(); + void run() throws Exception { createFiles(); compileFiles(); } void createFiles() throws Exception { -// mkdir src -// cp -r ${TESTSRC}${FS}* src - ToolBox.createJavaFileFromSource(Paths.get("src"), BSrc); - ToolBox.createJavaFileFromSource(Paths.get("src"), CSrc); - ToolBox.createJavaFileFromSource(Paths.get("src"), MainSrc); - ToolBox.createJavaFileFromSource(Paths.get("src"), R1Src); - ToolBox.createJavaFileFromSource(Paths.get("src"), R2Src); - ToolBox.createJavaFileFromSource(Paths.get("src"), R3Src); + Path srcDir = Paths.get("src"); + tb.writeJavaFiles(srcDir, BSrc, CSrc, MainSrc, R1Src, R2Src, R3Src); } void compileFiles() throws Exception { -// "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d . -classpath . -// -sourcepath src src/x/B.java src/x/C.java src/y/Main.java - ToolBox.JavaToolArgs args = - new ToolBox.JavaToolArgs() - .setAllArgs("-d", ".", "-cp" , ".", "-sourcepath", "src", - "src/x/B.java", "src/x/C.java", "src/y/Main.java"); - ToolBox.javac(args); + tb.new JavacTask() + .outdir(".") + .classpath(".") + .sourcepath("src") + .files("src/x/B.java", "src/x/C.java", "src/y/Main.java") + .run() + .writeAll(); -// rm y/R3.class - ToolBox.rm(Paths.get("y", "R3.class")); + tb.deleteFiles("y/R3.class"); -// "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d . -classpath . -// -sourcepath src src/y/Main.java - args.setAllArgs("-d", ".", "-cp", ".", "-sourcepath", "src", "src/y/Main.java"); - ToolBox.javac(args); + tb.new JavacTask() + .outdir(".") + .classpath(".") + .sourcepath("src") + .files("src/y/Main.java") + .run() + .writeAll(); + } } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/javazip/JavaZipTest.java --- a/langtools/test/tools/javac/javazip/JavaZipTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/javazip/JavaZipTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -25,15 +25,16 @@ * @test * @bug 4098712 6304984 6388453 * @summary check that source files inside zip files on the class path are ignored - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main JavaZipTest */ -import java.io.File; +import java.nio.file.Files; import java.nio.file.Paths; +import java.util.Arrays; -//original test: test/tools/javac/javazip/Test.sh +// Original test: test/tools/javac/javazip/Test.sh public class JavaZipTest { private static final String ASrc = @@ -62,7 +63,7 @@ {"-d", "output", "-cp", "good.jar", "A.java"}, }; - private static final String[][] unSuccessfulCompilationArgs = { + private static final String[][] unsuccessfulCompilationArgs = { {"-d", "output", "A.java", "bad/B.java"}, {"-d", "output", "-cp", "bad", "A.java"}, {"-d", "output", "-sourcepath", "bad", "A.java"}, @@ -74,53 +75,57 @@ new JavaZipTest().test(); } + private final ToolBox tb = new ToolBox(); + public void test() throws Exception { createOutputDirAndSourceFiles(); createZipsAndJars(); check(ToolBox.Expect.SUCCESS, successfulCompilationArgs); - check(ToolBox.Expect.FAIL, unSuccessfulCompilationArgs); + check(ToolBox.Expect.FAIL, unsuccessfulCompilationArgs); } void createOutputDirAndSourceFiles() throws Exception { //create output dir - new File("output").mkdir(); + Files.createDirectory(Paths.get("output")); //source file creation - ToolBox.createJavaFileFromSource(Paths.get("good"), BGoodSrc); - ToolBox.createJavaFileFromSource(Paths.get("bad"), BBadSrc); - ToolBox.createJavaFileFromSource(ASrc); + tb.writeJavaFiles(Paths.get("good"), BGoodSrc); + tb.writeJavaFiles(Paths.get("bad"), BBadSrc); + tb.writeJavaFiles(ToolBox.currDir, ASrc); } void createZipsAndJars() throws Exception { //jar and zip creation -// check ok "${TESTJAVA}${FS}bin${FS}jar" cf "${SCR}${FS}good.jar" -C "${TESTSRC}${FS}good" B.java -// check ok "${TESTJAVA}${FS}bin${FS}jar" cf "${SCR}${FS}good.zip" -C "${TESTSRC}${FS}good" B.java -// check ok "${TESTJAVA}${FS}bin${FS}jar" cf "${SCR}${FS}bad.jar" -C "${TESTSRC}${FS}bad" B.java -// check ok "${TESTJAVA}${FS}bin${FS}jar" cf "${SCR}${FS}bad.zip" -C "${TESTSRC}${FS}bad" B.java for (String[] args: jarArgs) { - ToolBox.jar(args); + tb.new JarTask().run(args).writeAll(); } } - void check(ToolBox.Expect whatToExpect, String[][] theArgs) throws Exception { -// check ok "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d ${TC} "${TESTSRC}${FS}A.java" "${TESTSRC}${FS}good${FS}B.java" -// check ok "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d ${TC} -classpath "${TESTSRC}${FS}good" "${TESTSRC}${FS}A.java" -// check ok "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d ${TC} -sourcepath "${TESTSRC}${FS}good" "${TESTSRC}${FS}A.java" -// check ok "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d ${TC} -classpath "${SCR}${FS}good.zip" "${TESTSRC}${FS}A.java" -// check ok "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d ${TC} -classpath "${SCR}${FS}good.jar" "${TESTSRC}${FS}A.java" + void check(ToolBox.Expect expectedStatus, String[][] theArgs) throws Exception { -// check err "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d ${TC} "${TESTSRC}${FS}A.java" "${TESTSRC}${FS}bad${FS}B.java" -// check err "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d ${TC} -classpath "${TESTSRC}${FS}bad" "${TESTSRC}${FS}A.java" -// check err "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d ${TC} -sourcepath "${TESTSRC}${FS}bad" "${TESTSRC}${FS}A.java" -// check err "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d ${TC} -sourcepath "${SCR}${FS}bad.zip" "${TESTSRC}${FS}A.java" -// check err "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d ${TC} -sourcepath "${SCR}${FS}bad.jar" "${TESTSRC}${FS}A.java" - ToolBox.JavaToolArgs args = - new ToolBox.JavaToolArgs(whatToExpect); for (String[] allArgs: theArgs) { - args.setAllArgs(allArgs); - ToolBox.javac(args); + tb.new JavacTask() + .options(opts(allArgs)) + .files(files(allArgs)) + .run(expectedStatus) + .writeAll(); + } } + private String[] opts(String... allArgs) { + int i = allArgs.length; + while (allArgs[i - 1].endsWith(".java")) + i--; + return Arrays.copyOfRange(allArgs, 0, i); + } + + private String[] files(String... allArgs) { + int i = allArgs.length; + while (allArgs[i - 1].endsWith(".java")) + i--; + return Arrays.copyOfRange(allArgs, i, allArgs.length); + } + } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/lambda/lambdaNaming/TestSerializedLambdaNameStability.java --- a/langtools/test/tools/javac/lambda/lambdaNaming/TestSerializedLambdaNameStability.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/lambda/lambdaNaming/TestSerializedLambdaNameStability.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -25,7 +25,7 @@ * @test * @bug 8023668 * @summary Desugar serializable lambda bodies using more robust naming scheme - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main TestSerializedLambdaNameStability */ @@ -125,6 +125,7 @@ static final String compiledDir = System.getProperty("user.dir"); static final String sourceBaseDir = System.getProperty("test.src"); + final ToolBox tb = new ToolBox(); final String context; public TestClassLoader(String context) { @@ -154,10 +155,10 @@ else throw new Exception("Did not expect to load " + name); Path srcFile = Paths.get(sourceBaseDir, context, srcName + ".java"); - String testSource = new String(Files.readAllBytes(srcFile)); - ToolBox.JavaToolArgs javacSuccessArgs = - new ToolBox.JavaToolArgs().setSources(testSource); - ToolBox.javac(javacSuccessArgs); + tb.new JavacTask() + .outdir(compiledDir) + .files(srcFile) + .run(); Path cfFile = Paths.get(compiledDir, name + ".class"); byte[] bytes = Files.readAllBytes(cfFile); return bytes; diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/lib/ToolBox.java --- a/langtools/test/tools/javac/lib/ToolBox.java Fri Aug 29 10:47:32 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1080 +0,0 @@ -/* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.io.BufferedReader; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileWriter; -import java.io.FilterOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.net.URI; -import java.nio.charset.Charset; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.StandardOpenOption; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.tools.FileObject; -import javax.tools.ForwardingJavaFileManager; -import javax.tools.JavaCompiler; -import javax.tools.JavaFileManager; -import javax.tools.JavaFileManager.Location; -import javax.tools.JavaFileObject; -import javax.tools.JavaFileObject.Kind; -import javax.tools.SimpleJavaFileObject; -import javax.tools.StandardJavaFileManager; -import javax.tools.ToolProvider; - -import com.sun.source.util.JavacTask; -import com.sun.tools.javac.api.JavacTaskImpl; - -import sun.tools.jar.Main; - -import static java.nio.file.StandardCopyOption.*; - -/** - * Toolbox for jtreg tests. - */ - -public class ToolBox { - - public static final String lineSeparator = System.getProperty("line.separator"); - public static final String jdkUnderTest = System.getProperty("test.jdk"); - public static final Path javaBinary = Paths.get(jdkUnderTest, "bin", "java"); - public static final Path javacBinary = Paths.get(jdkUnderTest, "bin", "javac"); - - public static final List testVMOpts = readOptions("test.vm.opts"); - public static final List testToolVMOpts = readOptions("test.tool.vm.opts"); - public static final List testJavaOpts = readOptions("test.java.opts"); - - private static final Charset defaultCharset = Charset.defaultCharset(); - - static final JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); - - private static List readOptions(String property) { - String options = System.getProperty(property, ""); - return options.length() > 0 ? Arrays.asList(options.split("\\s+")) : Collections.emptyList(); - } - - /** - * The expected result of command-like method execution. - */ - public enum Expect {SUCCESS, FAIL} - - enum AcceptedParams { - EXPECT, - SOURCES, - OPTIONS, - STD_OUTPUT, - ERR_OUTPUT, - EXTRA_ENV, - } - - enum OutputKind {STD, ERR} - - /** - * Helper class to abstract the processing of command's output. - */ - static abstract class WriterHelper { - OutputKind kind; - public abstract void pipeOutput(ProcessBuilder pb); - public abstract void readFromStream(Process p) throws IOException; - public abstract void addAll(Collection c) throws IOException; - } - - /** - * Helper class for redirecting command's output to a file. - */ - static class FileWriterHelper extends WriterHelper { - File file; - - FileWriterHelper(File file, OutputKind kind) { - this.file = file; - this.kind = kind; - } - - @Override - public void pipeOutput(ProcessBuilder pb) { - if (file != null) { - switch (kind) { - case STD: - pb.redirectInput(file); - break; - case ERR: - pb.redirectError(file); - break; - } - } - } - - @Override - public void readFromStream(Process p) throws IOException {} - - @Override - public void addAll(Collection c) throws IOException { - if (file.exists()) - Files.write(file.toPath(), c, defaultCharset, - StandardOpenOption.WRITE, StandardOpenOption.APPEND); - else - Files.write(file.toPath(), c, defaultCharset); - } - } - - /** - * Helper class for redirecting command's output to a String list. - */ - static class ListWriterHelper extends WriterHelper { - List list; - - public ListWriterHelper(List list, OutputKind kind) { - this.kind = kind; - this.list = list; - } - - @Override - public void pipeOutput(ProcessBuilder pb) {} - - @Override - public void readFromStream(Process p) throws IOException { - BufferedReader br = null; - switch (kind) { - case STD: - br = new BufferedReader(new InputStreamReader(p.getInputStream())); - break; - case ERR: - br = new BufferedReader(new InputStreamReader(p.getErrorStream())); - break; - } - String line; - while ((line = br.readLine()) != null) { - list.add(line); - } - } - - public void addAll(Collection c) { - list.addAll(c); - } - } - - /** - * Simple factory class for creating a WriterHelper instance. - */ - static class WriterHelperFactory { - static WriterHelper make(File file, OutputKind kind) { - return new FileWriterHelper(file, kind); - } - - static WriterHelper make(List list, OutputKind kind) { - return new ListWriterHelper(list, kind); - } - } - - /** - * A generic class for holding command's arguments. - */ - public static abstract class GenericArgs { - protected static List> minAcceptedParams; - - protected Set currentParams = - EnumSet.noneOf(AcceptedParams.class); - - protected Expect whatToExpect; - protected WriterHelper stdOutput; - protected WriterHelper errOutput; - protected List args = new ArrayList<>(); - protected String[] argsArr; - - protected GenericArgs() { - set(Expect.SUCCESS); - } - - public T set(Expect whatToExpt) { - currentParams.add(AcceptedParams.EXPECT); - this.whatToExpect = whatToExpt; - return (T)this; - } - - public T setStdOutput(List stdOutput) { - currentParams.add(AcceptedParams.STD_OUTPUT); - this.stdOutput = WriterHelperFactory.make(stdOutput, OutputKind.STD); - return (T)this; - } - - public T setStdOutput(File output) { - currentParams.add(AcceptedParams.STD_OUTPUT); - this.stdOutput = WriterHelperFactory.make(output, OutputKind.STD); - return (T)this; - } - - public T setErrOutput(List errOutput) { - currentParams.add(AcceptedParams.ERR_OUTPUT); - this.errOutput = WriterHelperFactory.make(errOutput, OutputKind.ERR); - return (T)this; - } - - public T setErrOutput(File errOutput) { - currentParams.add(AcceptedParams.ERR_OUTPUT); - this.errOutput = WriterHelperFactory.make(errOutput, OutputKind.ERR); - return (T)this; - } - - public T setAllArgs(String... args) { - currentParams.add(AcceptedParams.OPTIONS); - this.argsArr = args; - return (T) this; - } - - - public T appendArgs(String... args) { - appendArgs(Arrays.asList(args)); - return (T)this; - } - - public T appendArgs(Path... args) { - if (args != null) { - List list = new ArrayList<>(); - for (int i = 0; i < args.length; i++) { - if (args[i] != null) { - list.add(args[i].toString()); - } - } - appendArgs(list); - } - return (T)this; - } - - public T appendArgs(List args) { - if (args != null && args.size() > 0) { - currentParams.add(AcceptedParams.OPTIONS); - for (int i = 0; i < args.size(); i++) { - if (args.get(i) != null) { - this.args.add(args.get(i)); - } - } - } - return (T)this; - } - - public T setOptions(List options) { - currentParams.add(AcceptedParams.OPTIONS); - this.args = options; - return (T)this; - } - - public T setOptions(String... options) { - currentParams.add(AcceptedParams.OPTIONS); - this.args = Arrays.asList(options); - return (T)this; - } - - public boolean hasMinParams() { - for (Set minSet : minAcceptedParams) { - if (currentParams.containsAll(minSet)) { - return true; - } - } - return false; - } - } - - /** - * A more specific class for holding javac-like command's arguments. - */ - public static class JavaToolArgs extends GenericArgs { - - static { - minAcceptedParams = new ArrayList<>(); - minAcceptedParams.add(EnumSet.of( - AcceptedParams.EXPECT, AcceptedParams.OPTIONS)); - minAcceptedParams.add(EnumSet.of( - AcceptedParams.EXPECT, AcceptedParams.SOURCES)); - } - - protected List sources; - - public JavaToolArgs() { - super(); - } - - public JavaToolArgs(Expect whatToExpt) { - super.set(whatToExpt); - } - - public JavaToolArgs setSources(List sources) { - currentParams.add(AcceptedParams.SOURCES); - this.sources = sources; - return this; - } - - public JavaToolArgs setSources(JavaSource... sources) { - return setSources(Arrays.asList(sources)); - } - - public JavaToolArgs setSources(String... sources) { - List javaSrcs = new ArrayList<>(); - for (String source : sources) { - javaSrcs.add(new JavaSource(source)); - } - return setSources(javaSrcs); - } - } - - /** - * A more specific class for holding any command's arguments. - */ - public static class AnyToolArgs extends GenericArgs { - - static { - minAcceptedParams = new ArrayList<>(); - minAcceptedParams.add(EnumSet.of( - AcceptedParams.EXPECT, AcceptedParams.OPTIONS)); - } - - Map extraEnv; - - public AnyToolArgs() { - super(); - } - - public AnyToolArgs(Expect whatToExpt) { - set(whatToExpt); - } - - public AnyToolArgs set(Map extraEnv) { - currentParams.add(AcceptedParams.EXTRA_ENV); - this.extraEnv = extraEnv; - return this; - } - } - - /** - * Custom exception for bad command execution. - */ - public static class CommandExecutionException extends Exception { - CommandExecutionException(List command, Expect whatToExpt) { - super(createMessage(command, whatToExpt)); - } - - CommandExecutionException(Expect whatToExpt, String... command) { - this(Arrays.asList(command), whatToExpt); - } - - private static String createMessage(List command, Expect whatToExpt) { - StringBuilder sb = new StringBuilder().append("Command : "); - sb.append(command.toString()).append(lineSeparator); - switch (whatToExpt) { - case SUCCESS: - sb.append(" has unexpectedly failed"); - break; - case FAIL: - sb.append(" has been unexpectedly successful"); - break; - } - return sb.toString(); - } - } - - /** - * Custom exception for not equal resources. - */ - public static class ResourcesNotEqualException extends Exception { - public ResourcesNotEqualException(List res1, List res2) { - super(createMessage(res1, res2)); - } - - public ResourcesNotEqualException(String line1, String line2) { - super(createMessage(line1, line2)); - } - - public ResourcesNotEqualException(Path path1, Path path2) { - super(createMessage(path1, path2)); - } - - private static String createMessage(Path path1, Path path2) { - return new StringBuilder() - .append("The resources provided for comparison in paths \n") - .append(path1.toString()).append(" and \n") - .append(path2.toString()).append("are different").toString(); - } - - private static String createMessage(String line1, String line2) { - return new StringBuilder() - .append("The resources provided for comparison are different at lines: \n") - .append(line1).append(" and \n") - .append(line2).toString(); - } - - private static String createMessage(List res1, List res2) { - return new StringBuilder() - .append("The resources provided for comparison are different: \n") - .append("Resource 1 is: ").append(res1).append("\n and \n") - .append("Resource 2 is: ").append(res2).append("\n").toString(); - } - } - - /** - * A javac compiler caller method. - */ - public static int javac(JavaToolArgs params) - throws CommandExecutionException, IOException { - if (params.hasMinParams()) { - if (params.argsArr != null) { - return genericJavaCMD(JavaCMD.JAVAC, params); - } else { - return genericJavaCMD(JavaCMD.JAVAC_API, params); - } - } - throw new AssertionError("javac command has been invoked with less parameters than needed"); - } - - /** - * Run javac and return the resulting classfiles. - */ - public static Map compile(JavaToolArgs params) - throws CommandExecutionException, IOException { - if (params.hasMinParams()) { - if (params.argsArr != null) { - throw new AssertionError("setAllArgs is not supported for compile"); - } - - StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null); - MemoryFileManager mfm = new MemoryFileManager(fm); - StringWriter sw = null; - boolean rc; - - try (PrintWriter pw = (params.errOutput == null) ? - null : new PrintWriter(sw = new StringWriter())) { - JavacTask ct = (JavacTask)comp.getTask(pw, mfm, null, - params.args, null, params.sources); - rc = ct.call(); - } - - String out = (sw == null) ? null : sw.toString(); - - if (params.errOutput != null && (out != null) && !out.isEmpty()) { - params.errOutput.addAll(splitLines(out, lineSeparator)); - } - - if ( ( rc && params.whatToExpect == Expect.SUCCESS) || - (!rc && params.whatToExpect == Expect.FAIL) ) { - return mfm.classes; - } - - throw new CommandExecutionException(JavaCMD.JAVAC_API.getExceptionMsgContent(params), - params.whatToExpect); - } - throw new AssertionError("compile command has been invoked with less parameters than needed"); - } - - /** - * A javap calling method. - */ - public static String javap(JavaToolArgs params) - throws CommandExecutionException, IOException { - if (params.hasMinParams()) { - List list = new ArrayList<>(); - params.setErrOutput(list); - genericJavaCMD(JavaCMD.JAVAP, params); - return listToString(list); - } - throw new AssertionError("javap command has been invoked with less parameters than needed"); - } - - /** - * A javah calling method. - */ - public static int javah(JavaToolArgs params) - throws CommandExecutionException, IOException { - if (params.hasMinParams()) { - return genericJavaCMD(JavaCMD.JAVAH, params); - } - throw new AssertionError("javah command has been invoked with less parameters than needed"); - } - - /** - * A enum class for langtools commands. - */ - enum JavaCMD { - JAVAC { - @Override - int run(JavaToolArgs params, PrintWriter pw) { - return com.sun.tools.javac.Main.compile(params.argsArr, pw); - } - }, - JAVAC_API { - @Override - int run(JavaToolArgs params, PrintWriter pw) { - JavacTask ct = (JavacTask)comp.getTask(pw, null, null, - params.args, null, params.sources); - return ((JavacTaskImpl)ct).doCall().exitCode; - } - - @Override - String getName() { - return "javac"; - } - - @Override - List getExceptionMsgContent(JavaToolArgs params) { - List result = super.getExceptionMsgContent(params); - for (JavaFileObject source : params.sources) { - if (source instanceof JavaSource) { - result.add(((JavaSource)source).name); - } - } - return result; - } - }, - JAVAH { - @Override - int run(JavaToolArgs params, PrintWriter pw) { - return com.sun.tools.javah.Main.run(params.argsArr, pw); - } - }, - JAVAP { - @Override - int run(JavaToolArgs params, PrintWriter pw) { - return com.sun.tools.javap.Main.run(params.argsArr, pw); - } - }; - - abstract int run(JavaToolArgs params, PrintWriter pw); - - String getName() { - return this.name().toLowerCase(); - } - - List getExceptionMsgContent(JavaToolArgs params) { - List result = new ArrayList<>(); - result.add(getName()); - result.addAll(params.argsArr != null ? - Arrays.asList(params.argsArr) : - params.args); - return result; - } - } - - /** - * A helper method for executing langtools commands. - */ - private static int genericJavaCMD( - JavaCMD cmd, - JavaToolArgs params) - throws CommandExecutionException, IOException { - int rc = 0; - StringWriter sw = null; - try (PrintWriter pw = (params.errOutput == null) ? - null : new PrintWriter(sw = new StringWriter())) { - rc = cmd.run(params, pw); - } - String out = (sw == null) ? null : sw.toString(); - - if (params.errOutput != null && (out != null) && !out.isEmpty()) { - params.errOutput.addAll(splitLines(out, lineSeparator)); - } - - if ( (rc == 0 && params.whatToExpect == Expect.SUCCESS) || - (rc != 0 && params.whatToExpect == Expect.FAIL) ) { - return rc; - } - - throw new CommandExecutionException(cmd.getExceptionMsgContent(params), - params.whatToExpect); - } - - /** - * A jar calling method. - */ - public static boolean jar(String... params) throws CommandExecutionException { - Main jarGenerator = new Main(System.out, System.err, "jar"); - boolean result = jarGenerator.run(params); - if (!result) { - List command = new ArrayList<>(); - command.add("jar"); - command.addAll(Arrays.asList(params)); - throw new CommandExecutionException(command, Expect.SUCCESS); - } - return result; - } - - /** - * A general command calling method. - */ - public static int executeCommand(AnyToolArgs params) - throws CommandExecutionException, IOException, InterruptedException { - if (params.hasMinParams()) { - List cmd = (params.args != null) ? - params.args : - Arrays.asList(params.argsArr); - return executeCommand(cmd, params.extraEnv, params.stdOutput, - params.errOutput, params.whatToExpect); - } - throw new AssertionError("command has been invoked with less parameters than needed"); - } - - /** - * A helper method for calling a general command. - */ - private static int executeCommand( - List command, - Map extraEnv, - WriterHelper stdOutput, - WriterHelper errOutput, - Expect whatToExpt) - throws IOException, InterruptedException, CommandExecutionException { - ProcessBuilder pb = new ProcessBuilder(command); - - if (stdOutput != null) stdOutput.pipeOutput(pb); - if (errOutput != null) errOutput.pipeOutput(pb); - - if (extraEnv != null) { - pb.environment().putAll(extraEnv); - } - - Process p = pb.start(); - - if (stdOutput != null) stdOutput.readFromStream(p); - if (errOutput != null) errOutput.readFromStream(p); - - int result = p.waitFor(); - if ( (result == 0 && whatToExpt == Expect.SUCCESS) || - (result != 0 && whatToExpt == Expect.FAIL) ) { - return result; - } - - throw new CommandExecutionException(command, whatToExpt); - } - - /** - * This set of methods can be used instead of diff when the only needed - * result is the equality or inequality of the two given resources. - * - * A resource can be a file or a String list. - */ - public static void compareLines(Path aPath, Path otherPath, String encoding) - throws FileNotFoundException, IOException, ResourcesNotEqualException { - compareLines(aPath, otherPath, encoding, false); - } - - public static void compareLines( - Path aPath, Path otherPath, String encoding, boolean trim) - throws FileNotFoundException, IOException, ResourcesNotEqualException { - Charset charset = encoding != null ? - Charset.forName(encoding) : - defaultCharset; - List list1 = Files.readAllLines(aPath, charset); - List list2 = Files.readAllLines(otherPath, charset); - compareLines(list1, list2, trim); - } - - public static void compareLines(Path path, List strings, String encoding) - throws FileNotFoundException, IOException, ResourcesNotEqualException { - compareLines(path, strings, encoding, false); - } - - public static void compareLines(Path path, List strings, - String encoding, boolean trim) - throws FileNotFoundException, IOException, ResourcesNotEqualException { - Charset charset = encoding != null ? - Charset.forName(encoding) : - defaultCharset; - List list = Files.readAllLines(path, charset); - compareLines(list, strings, trim); - } - - public static void compareLines(List list1, List list2) - throws ResourcesNotEqualException { - compareLines(list1, list2, false); - } - - public static void compareLines(List list1, - List list2, boolean trim) throws ResourcesNotEqualException { - if ((list1 == list2) || (list1 == null && list2 == null)) return; - if (list1.size() != list2.size()) - throw new ResourcesNotEqualException(list1, list2); - int i = 0; - int j = 0; - while (i < list1.size() && - j < list2.size() && - equals(list1.get(i), list2.get(j), trim)) { - i++; j++; - } - if (!(i == list1.size() && j == list2.size())) - throw new ResourcesNotEqualException(list1, list2); - } - - private static boolean equals(String s1, String s2, boolean trim) { - return (trim ? s1.trim().equals(s2.trim()) : s1.equals(s2)); - } - - /** - * A set of simple grep-like methods, looks for regExpr in text. - * The content of text is split using the new line character as a pattern - * and later the regExpr is seek in every split line. If a match is found, - * the whole line is added to the result. - */ - public static List grep(String regExpr, String text, String sep) { - return grep(regExpr, splitLines(text, sep)); - } - - public static List grep(String regExpr, List text) { - List result = new ArrayList<>(); - Pattern pattern = Pattern.compile(regExpr); - for (String s : text) { - if (pattern.matcher(s).find()) { - result.add(s); - } - } - return result; - } - - public static List grep(String regExpr, File f) - throws IOException { - List lines = Files.readAllLines(f.toPath(), defaultCharset); - return grep(regExpr, lines); - } - - /** - * A touch-like method. - */ - public static boolean touch(String fileName) { - File file = new File(fileName); - return touch(file); - } - - public static boolean touch(File file) { - if (file.exists()) { - file.setLastModified(System.currentTimeMillis()); - return true; - } - return false; - } - - public static void createJavaFile(File outFile) throws IOException { - createJavaFile(outFile, null); - } - - /** - * A method for creating a valid but very simple java file. - */ - public static void createJavaFile(File outFile, File superClass) - throws IOException { - String srcStr = "public class " + getSimpleName(outFile) + " "; - if (superClass != null) { - srcStr = srcStr.concat("extends " + getSimpleName(superClass) + " "); - } - srcStr = srcStr.concat("{}"); - try (PrintWriter ps = new PrintWriter(new FileWriter(outFile))) { - ps.println(srcStr); - } - } - - /** - * Creates a java file name given its source. - * The file is created in the working directory, creating a directory - * tree if there is a package declaration. - */ - public static void createJavaFileFromSource(String source) throws IOException { - createJavaFileFromSource(null, source); - } - - /** - * Creates a java file name given its source. - * The file is created in the working directory, creating a directory - * tree if there is a package declaration or the argument initialPath - * has a valid path. - * - * e.i. if initialPath is foo/ and the source is: - * package bar; - * - * public class bazz {} - * - * this method will create the file foo/bar/bazz.java in the working - * directory. - */ - public static void createJavaFileFromSource(Path initialPath, - String source) throws IOException { - String fileName = getJavaFileNameFromSource(source); - String dirTree = getDirTreeFromSource(source); - Path path = (dirTree != null) ? - Paths.get(dirTree, fileName) : - Paths.get(fileName); - path = (initialPath != null) ? - initialPath.resolve(path): - path; - writeFile(path, source); - } - - static Pattern publicClassPattern = - Pattern.compile("public\\s+(?:class|enum|interface){1}\\s+(\\w+)"); - static Pattern packageClassPattern = - Pattern.compile("(?:class|enum|interface){1}\\s+(\\w+)"); - - /** - * Extracts the java file name from the class declaration. - * This method is intended for simple files and uses regular expressions, - * so comments matching the pattern can make the method fail. - */ - static String getJavaFileNameFromSource(String source) { - String className = null; - Matcher matcher = publicClassPattern.matcher(source); - if (matcher.find()) { - className = matcher.group(1) + ".java"; - } else { - matcher = packageClassPattern.matcher(source); - if (matcher.find()) { - className = matcher.group(1) + ".java"; - } else { - throw new AssertionError("Could not extract the java class " + - "name from the provided source"); - } - } - return className; - } - - static Pattern packagePattern = - Pattern.compile("package\\s+(((?:\\w+\\.)*)(?:\\w+))"); - - /** - * Extracts the path from the package declaration if present. - * This method is intended for simple files and uses regular expressions, - * so comments matching the pattern can make the method fail. - */ - private static String getDirTreeFromSource(String source) { - Matcher matcher = packagePattern.matcher(source); - return matcher.find() ? - matcher.group(1).replace(".", File.separator) : - null; - } - - /** - * A method for creating a jar's manifest file with supplied data. - */ - public static void mkManifestWithClassPath(String mainClass, - String... classes) throws IOException { - List lines = new ArrayList<>(); - - StringBuilder sb = new StringBuilder("Class-Path: ".length() + - classes[0].length()).append("Class-Path: ").append(classes[0]); - for (int i = 1; i < classes.length; i++) { - sb.append(" ").append(classes[i]); - } - lines.add(sb.toString()); - if (mainClass != null) { - lines.add(new StringBuilder("Main-Class: ".length() + - mainClass.length()) - .append("Main-Class: ") - .append(mainClass).toString()); - } - Files.write(Paths.get("MANIFEST.MF"), lines, - StandardOpenOption.CREATE, StandardOpenOption.WRITE, - StandardOpenOption.TRUNCATE_EXISTING); - } - - /** - * A utility method to obtain the file name. - */ - static String getSimpleName(File inFile) { - return inFile.toPath().getFileName().toString(); - } - - /** - * A method to write to a file, the directory tree is created if needed. - */ - public static File writeFile(Path path, String body) throws IOException { - File result; - if (path.getParent() != null) { - Files.createDirectories(path.getParent()); - } - try (FileWriter out = new FileWriter(result = path.toAbsolutePath().toFile())) { - out.write(body); - } - return result; - } - - public static File writeFile(String path, String body) throws IOException { - return writeFile(Paths.get(path), body); - } - - /** - * A rm-like method, the file is deleted only if it exists. - */ - public static void rm(Path path) throws Exception { - Files.deleteIfExists(path); - } - - public static void rm(String filename) throws Exception { - rm(Paths.get(filename)); - } - - public static void rm(File f) throws Exception { - rm(f.toPath()); - } - - /** - * Copy source file to destination file. - */ - public static void copyFile(File destfile, File srcfile) - throws IOException { - copyFile(destfile.toPath(), srcfile.toPath()); - } - - public static void copyFile(Path destPath, Path srcPath) - throws IOException { - Files.createDirectories(destPath); - Files.copy(srcPath, destPath, REPLACE_EXISTING); - } - - /** - * Splits a String using the System's line separator character as splitting point. - */ - public static List splitLines(String lines, String sep) { - return Arrays.asList(lines.split(sep)); - } - - /** - * Converts a String list into one String by appending the System's line separator - * character after each component. - */ - private static String listToString(List lines) { - StringBuilder sb = new StringBuilder(); - for (String s : lines) { - sb.append(s).append(lineSeparator); - } - return sb.toString(); - } - - /** - * Returns true if the OS is a Windows version. - */ - public static boolean isWindows() { - String osName = System.getProperty("os.name"); - return osName.toUpperCase().startsWith("WINDOWS"); - } - - /** - * Class representing an in-memory java source file. It is able to extract - * the file name from simple source codes using regular expressions. - */ - public static class JavaSource extends SimpleJavaFileObject { - String source; - String name; - - public JavaSource(String className, String source) { - super(URI.create(className), - JavaFileObject.Kind.SOURCE); - this.name = className; - this.source = source; - } - - public JavaSource(String source) { - super(URI.create(getJavaFileNameFromSource(source)), - JavaFileObject.Kind.SOURCE); - this.name = getJavaFileNameFromSource(source); - this.source = source; - } - - @Override - public CharSequence getCharContent(boolean ignoreEncodingErrors) { - return source; - } - } - - /** - * A file manager for compiling strings to byte arrays. - * This file manager delegates to another file manager - * to lookup classes on boot class path. - */ - public static final class MemoryFileManager extends ForwardingJavaFileManager { - /** - * Maps binary class names to class files stored as byte arrays. - */ - private final Map classes; - - /** - * Construct a memory file manager which delegates to the specified - * file manager for unknown sources. - * @param fileManager a file manager used to look up class files on class path, etc. - */ - public MemoryFileManager(JavaFileManager fileManager) { - super(fileManager); - classes = new HashMap<>(); - } - - @java.lang.Override - public JavaFileObject getJavaFileForOutput(Location location, - String name, - Kind kind, - FileObject sibling) - throws UnsupportedOperationException - { - return new JavaClassInArray(name); - } - - /** - * A file object representing a Java class file stored in a byte array. - */ - private class JavaClassInArray extends SimpleJavaFileObject { - - private final String name; - - /** - * Constructs a JavaClassInArray object. - * @param name binary name of the class to be stored in this file object - */ - JavaClassInArray(String name) { - super(URI.create("mfm:///" + name.replace('.','/') + Kind.CLASS.extension), - Kind.CLASS); - this.name = name; - } - - public OutputStream openOutputStream() { - return new FilterOutputStream(new ByteArrayOutputStream()) { - public void close() throws IOException { - out.close(); - ByteArrayOutputStream bos = (ByteArrayOutputStream)out; - classes.put(name, bos.toByteArray()); - } - }; - } - } - - } - -} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/links/LinksTest.java --- a/langtools/test/tools/javac/links/LinksTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/links/LinksTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -25,7 +25,7 @@ * @test * @bug 4266026 * @summary javac no longer follows symlinks - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main LinksTest */ @@ -33,7 +33,7 @@ import java.nio.file.Files; import java.nio.file.Paths; -//original test: test/tools/javac/links/links.sh +// Original test: test/tools/javac/links/links.sh public class LinksTest { private static final String BSrc = @@ -44,20 +44,18 @@ private static final String TSrc = "class T extends a.B {}"; - public static void main(String args[]) - throws Exception { -// mkdir tmp -// cp ${TESTSRC}/b/B.java tmp - ToolBox.writeFile(Paths.get("tmp", "B.java"), BSrc); + public static void main(String... args) throws Exception { + ToolBox tb = new ToolBox(); + tb.writeFile("tmp/B.java", BSrc); try { -// ln -s `pwd`/tmp "${TESTCLASSES}/a" Files.createSymbolicLink(Paths.get("a"), Paths.get("tmp")); - ////"${TESTJAVA}/bin/javac" ${TESTTOOLVMOPTS} -sourcepath "${TESTCLASSES}" -d "${TESTCLASSES}/classes" "${TESTSRC}/T.java" 2>&1 - ToolBox.JavaToolArgs javacArgs = - new ToolBox.JavaToolArgs() - .setOptions("-sourcepath", ".", "-d", ".").setSources(TSrc); - ToolBox.javac(javacArgs); + + tb.new JavacTask() + .sourcepath(".") + .outdir(".") + .sources(TSrc) + .run(); } catch (UnsupportedOperationException e) { System.err.println("Symbolic links not supported on this system. The test can't finish"); } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/newlines/NewLineTest.java --- a/langtools/test/tools/javac/newlines/NewLineTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/newlines/NewLineTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -25,7 +25,7 @@ * @test * @bug 4110560 4785453 * @summary portability : javac.properties - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main NewLineTest */ @@ -39,18 +39,13 @@ public class NewLineTest { public static void main(String args[]) throws Exception { -// "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -J-Dline.separator='@' > ${TMP1} 2>&1 + ToolBox tb = new ToolBox(); File javacErrOutput = new File("output.txt"); - ToolBox.AnyToolArgs cmdArgs = - new ToolBox.AnyToolArgs(ToolBox.Expect.FAIL) - .appendArgs(ToolBox.javacBinary) - .appendArgs(ToolBox.testToolVMOpts) - .appendArgs("-J-Dline.separator='@'") - .setErrOutput(javacErrOutput); - ToolBox.executeCommand(cmdArgs); + tb.new JavacTask(ToolBox.Mode.EXEC) + .redirect(ToolBox.OutputKind.STDERR, javacErrOutput.getPath()) + .options("-J-Dline.separator='@'") + .run(ToolBox.Expect.FAIL); -// result=`cat ${TMP1} | wc -l` -// if [ "$result" -eq 0 ] passed List lines = Files.readAllLines(javacErrOutput.toPath(), Charset.defaultCharset()); if (lines.size() != 1) { diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/processing/rounds/CompleteOnClosed.java --- a/langtools/test/tools/javac/processing/rounds/CompleteOnClosed.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/processing/rounds/CompleteOnClosed.java Fri Aug 29 11:58:43 2014 -0700 @@ -26,8 +26,8 @@ * @bug 8038455 * @summary Ensure that formatting diagnostics with an already closed JavaCompiler won't crash * the compiler. - * @library /tools/javac/lib - * @build CompleteOnClosed ToolBox JavacTestingAbstractProcessor + * @library /tools/lib /tools/javac/lib + * @build ToolBox JavacTestingAbstractProcessor * @run main CompleteOnClosed */ diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/processing/rounds/OverwriteBetweenCompilations.java --- a/langtools/test/tools/javac/processing/rounds/OverwriteBetweenCompilations.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/processing/rounds/OverwriteBetweenCompilations.java Fri Aug 29 11:58:43 2014 -0700 @@ -26,7 +26,7 @@ * @bug 8038455 * @summary Verify that annotation processor can overwrite source and class files it generated * during previous compilations, and that the Symbols are updated appropriatelly. - * @library /tools/javac/lib/ + * @library /tools/lib /tools/javac/lib/ * @clean * * @build OverwriteBetweenCompilations ToolBox JavacTestingAbstractProcessor * @compile/ref=OverwriteBetweenCompilations_1.out -processor OverwriteBetweenCompilations -Apass=1 -parameters -XDrawDiagnostics OverwriteBetweenCompilationsSource.java @@ -49,6 +49,7 @@ @SupportedOptions("pass") public class OverwriteBetweenCompilations extends JavacTestingAbstractProcessor { int round = 1; + @Override public boolean process(Set annotations, RoundEnvironment roundEnv) { Log log = Log.instance(((JavacProcessingEnvironment) processingEnv).getContext()); @@ -85,11 +86,17 @@ try (OutputStream out = filer.createClassFile("GeneratedClass").openOutputStream()) { String code = pass != 2 ? GENERATED_INIT : GENERATED_UPDATE; code = code.replace("NAME", "GeneratedClass"); - ToolBox.JavaToolArgs args = - new ToolBox.JavaToolArgs().appendArgs("-parameters").setSources(code); - Map codeMap = ToolBox.compile(args); - out.write(codeMap.get("GeneratedClass")); - } catch (IOException | ToolBox.CommandExecutionException e) { + + ToolBox tb = new ToolBox(); + ToolBox.MemoryFileManager mfm = new ToolBox.MemoryFileManager(); + tb.new JavacTask() + .fileManager(mfm) + .options("-parameters") + .sources(code) + .run(); + + out.write(mfm.getFileBytes(StandardLocation.CLASS_OUTPUT, "GeneratedClass")); + } catch (IOException e) { processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, e.toString()); } } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javac/stackmap/StackMapTest.java --- a/langtools/test/tools/javac/stackmap/StackMapTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javac/stackmap/StackMapTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -25,7 +25,7 @@ * @test * @bug 4955930 * @summary The "method0" StackMap attribute should have two entries instead of three - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run compile StackMapTest.java * @run main StackMapTest @@ -34,7 +34,7 @@ import java.nio.file.Path; import java.nio.file.Paths; -//original test: test/tools/javac/stackmap/T4955930.sh +// Original test: test/tools/javac/stackmap/T4955930.sh public class StackMapTest { class Test { @@ -48,16 +48,15 @@ } public static void main(String args[]) throws Exception { -// "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} T4955930.java + ToolBox tb = new ToolBox(); + Path pathToClass = Paths.get(ToolBox.testClasses, "StackMapTest$Test.class"); + String javapOut = tb.new JavapTask() + .options("-v") + .classes(pathToClass.toString()) + .run() + .getOutput(ToolBox.OutputKind.DIRECT); -// "${TESTJAVA}${FS}bin${FS}javap" ${TESTTOOLVMOPTS} -verbose T4955930 > ${TMP1} - Path pathToClass = Paths.get(System.getProperty("test.classes"), - "StackMapTest$Test.class"); - ToolBox.JavaToolArgs javapArgs = - new ToolBox.JavaToolArgs().setAllArgs("-v", pathToClass.toString()); - -// grep "StackMapTable: number_of_entries = 2" ${TMP1} - if (!ToolBox.javap(javapArgs).contains("StackMapTable: number_of_entries = 2")) + if (!javapOut.contains("StackMapTable: number_of_entries = 2")) throw new AssertionError("The number of entries of the stack map " + "table should be equal to 2"); } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javah/6257087/T6257087.java --- a/langtools/test/tools/javah/6257087/T6257087.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javah/6257087/T6257087.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -25,12 +25,12 @@ * @test * @bug 6257087 * @summary javah doesn't produce proper signatures for inner class native methods - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main T6257087 */ -import java.nio.file.Paths; +import java.util.List; public class T6257087 { @@ -58,13 +58,14 @@ "#endif"; public static void main(String[] args) throws Exception { - ToolBox.JavaToolArgs javahArgs = - new ToolBox.JavaToolArgs() - .setAllArgs("-cp", System.getProperty("test.classes"), "foo"); - ToolBox.javah(javahArgs); + ToolBox tb = new ToolBox(); + tb.new JavahTask() + .classpath(ToolBox.testClasses) + .classes("foo") + .run(); - ToolBox.compareLines(Paths.get("foo_bar.h"), - ToolBox.splitLines(fooBarGoldenFile, "\n"), null, true); + List fooBarFile = tb.readAllLines("foo_bar.h"); + tb.checkEqual(fooBarFile, tb.split(fooBarGoldenFile, "\n")); } } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javah/T4942232/MissingParamClassTest.java --- a/langtools/test/tools/javah/T4942232/MissingParamClassTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javah/T4942232/MissingParamClassTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -27,7 +27,7 @@ * @summary Verifies that javah won't attempt to generate a header file if a * native method in a supplied class contains a parameter type whose corresponding * class is missing or not in the classpath - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run compile MissingParamClassTest.java * @clean MissingParamClassException @@ -39,32 +39,21 @@ import java.nio.file.Files; import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.List; -//original test: test/tools/javah/MissingParamClassTest.sh +// Original test: test/tools/javah/MissingParamClassTest.sh public class MissingParamClassTest { public static void main(String[] args) throws Exception { - //first steps done now by jtreg -//"${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d . "${TESTSRC}${FS}ParamClassTest.java" "${TESTSRC}${FS}MissingParamClassException.java" -//rm -f MissingParamClassException.class + ToolBox tb = new ToolBox(); -//"${TESTJAVA}${FS}bin${FS}javah" ${TESTTOOLVMOPTS} ParamClassTest 2>${TMP1} - List errOutput = new ArrayList<>(); - ToolBox.JavaToolArgs javahParams = - new ToolBox.JavaToolArgs(ToolBox.Expect.FAIL) - .setAllArgs("-classpath", System.getProperty("test.classes"), "ParamClassTest") - .setErrOutput(errOutput); - ToolBox.javah(javahParams); + String out = tb.new JavahTask() + .classpath(ToolBox.testClasses) + .classes("ParamClassTest") + .run(ToolBox.Expect.FAIL) + .getOutput(ToolBox.OutputKind.DIRECT); -//if [ -f $GENERATED_HEADER_FILE ]; then fail -//if [ ! -s ${TMP1} ]; then fail - if (Files.exists(Paths.get("ParamClassTest.h")) || errOutput.size() == 0) + if (Files.exists(Paths.get("ParamClassTest.h")) || out.isEmpty()) throw new AssertionError("The only output generated by javah must be an error message"); - //jtreg again -//rm -f MissingParamClassException.class ParamClassTest.class -//rm -f $GENERATED_HEADER_FILE $TMP1 } } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javah/constMacroTest/ConstMacroTest.java --- a/langtools/test/tools/javah/constMacroTest/ConstMacroTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javah/constMacroTest/ConstMacroTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -27,15 +27,15 @@ * @summary Validates rewritten javah handling of class defined constants and * ensures that the appropriate macro definitions are placed in the generated * header file. - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main ConstMacroTest */ import java.io.*; -import java.nio.file.Paths; +import java.util.List; -//original test: test/tools/javah/ConstMacroTest.sh +// Original test: test/tools/javah/ConstMacroTest.sh public class ConstMacroTest { private static final String subClassConstsGoldenFileTemplate = @@ -71,27 +71,21 @@ "#endif\n" + "#endif"; - private static final String serialVersionUIDSuffix = - ToolBox.isWindows() ? "i64" : "LL"; ; + public static void main(String[] args) throws Exception { + ToolBox tb = new ToolBox(); - public static void main(String[] args) throws Exception { - //first steps are now done by jtreg -// cp "${TESTSRC}${FS}SuperClassConsts.java" . -// cp "${TESTSRC}${FS}SubClassConsts.java" . - -// "${TESTJAVA}${FS}bin${FS}javac" ${TESTTOOLVMOPTS} -d . "${TESTSRC}${FS}SubClassConsts.java" + tb.new JavahTask() + .classpath(ToolBox.testClasses) + .classes("SubClassConsts") + .run(); -// "${TESTJAVA}${FS}bin${FS}javah" ${TESTTOOLVMOPTS} SubClassConsts - ToolBox.JavaToolArgs successParams = - new ToolBox.JavaToolArgs() - .setAllArgs("-cp", System.getProperty("test.classes"), "SubClassConsts"); - ToolBox.javah(successParams); + String longSuffix = tb.isWindows() ? "i64" : "LL"; + List subClassConstsGoldenFile = tb.split( + String.format(subClassConstsGoldenFileTemplate, longSuffix), "\n"); -// diff ${DIFFOPTS} "${TESTSRC}${FS}${EXPECTED_JAVAH_OUT_FILE}" "${GENERATED_HEADER_FILE}" - String subClassConstGoldenFile = String.format(subClassConstsGoldenFileTemplate, - serialVersionUIDSuffix); - ToolBox.compareLines(Paths.get("SubClassConsts.h"), - ToolBox.splitLines(subClassConstGoldenFile, "\n"), null, true); + List subClassConstsFile = tb.readAllLines("SubClassConsts.h"); + + tb.checkEqual(subClassConstsFile, subClassConstsGoldenFile); } } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javap/4798312/JavapShouldLoadClassesFromRTJarTest.java --- a/langtools/test/tools/javap/4798312/JavapShouldLoadClassesFromRTJarTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javap/4798312/JavapShouldLoadClassesFromRTJarTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -24,19 +24,23 @@ /* * @test * @bug 4798312 - * @summary In Windows, javap doesnt load classes from rt.jar - * @library /tools/javac/lib + * @summary In Windows, javap doesn't load classes from rt.jar + * @library /tools/lib * @build ToolBox * @run main JavapShouldLoadClassesFromRTJarTest */ + public class JavapShouldLoadClassesFromRTJarTest { public static void main(String[] args) throws Exception { -// "${TESTJAVA}${FS}bin${FS}javap" ${TESTTOOLVMOPTS} java.lang.String - ToolBox.JavaToolArgs params = - new ToolBox.JavaToolArgs(). - setAllArgs("-v", "java.lang.String"); - if (ToolBox.javap(params).isEmpty()) + ToolBox tb = new ToolBox(); + String out = tb.new JavapTask() + .options("-v") + .classes("java.lang.String") + .run() + .getOutput(ToolBox.OutputKind.DIRECT); + + if (out.isEmpty()) throw new AssertionError("javap generated no output"); } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javap/4866831/PublicInterfaceTest.java --- a/langtools/test/tools/javap/4866831/PublicInterfaceTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javap/4866831/PublicInterfaceTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,9 +1,5 @@ - -import java.nio.file.Path; -import java.nio.file.Paths; - /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -29,23 +25,29 @@ * @test * @bug 4866831 * @summary Verify that javap marks public interfaces as public - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main PublicInterfaceTest */ -//original test: test/tools/javap/PublicInterfaceTest.sh +import java.nio.file.Path; +import java.nio.file.Paths; + +// Original test: test/tools/javap/PublicInterfaceTest.sh public class PublicInterfaceTest { public interface Test {} public static void main(String[] args) throws Exception { -// "$JAVAP" ${TESTTOOLVMOPTS} -classpath "${TESTCLASSES}" NotPackagePrivateInterface | grep public - Path pathToClass = Paths.get(System.getProperty("test.classes"), - "PublicInterfaceTest$Test.class"); - ToolBox.JavaToolArgs javapParams = - new ToolBox.JavaToolArgs() - .setAllArgs(pathToClass.toString()); - if (!ToolBox.javap(javapParams).contains("public")) + ToolBox tb = new ToolBox(); + + Path pathToClass = Paths.get(ToolBox.testClasses, "PublicInterfaceTest$Test.class"); + + String out = tb.new JavapTask() + .classes(pathToClass.toString()) + .run() + .getOutput(ToolBox.OutputKind.DIRECT); + + if (!out.contains("public")) throw new AssertionError("The javap output does not contain \"public\""); } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/javap/stackmap/StackmapTest.java --- a/langtools/test/tools/javap/stackmap/StackmapTest.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/javap/stackmap/StackmapTest.java Fri Aug 29 11:58:43 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -25,15 +25,15 @@ * @test * @bug 6271292 * @summary Verify that javap prints StackMapTable attribute contents - * @library /tools/javac/lib + * @library /tools/lib * @build ToolBox * @run main StackmapTest */ -import java.util.Arrays; +import java.util.ArrayList; import java.util.List; -//original test: test/tools/javap/stackmap/T6271292.sh +// Original test: test/tools/javap/stackmap/T6271292.sh public class StackmapTest { private static final String TestSrc = @@ -58,41 +58,42 @@ "}\n"; private static final String goldenOut = - "frame_type = 255 /* full_frame */\n" + - "frame_type = 255 /* full_frame */\n" + - "frame_type = 73 /* same_locals_1_stack_item */\n" + - "frame_type = 255 /* full_frame */\n" + - "offset_delta = 19\n" + - "offset_delta = 0\n" + - "offset_delta = 2\n" + - "stack = [ uninitialized 0, uninitialized 0 ]\n" + - "stack = [ uninitialized 0, uninitialized 0, double ]\n" + - "stack = [ this ]\n" + - "stack = [ this, double ]\n" + - "locals = [ class \"[Ljava/lang/String;\" ]\n" + - "locals = [ class \"[Ljava/lang/String;\" ]\n" + - "locals = [ this, int ]\n"; + " frame_type = 255 /* full_frame */\n" + + " frame_type = 255 /* full_frame */\n" + + " frame_type = 73 /* same_locals_1_stack_item */\n" + + " frame_type = 255 /* full_frame */\n" + + " offset_delta = 19\n" + + " offset_delta = 0\n" + + " offset_delta = 2\n" + + " stack = [ uninitialized 0, uninitialized 0 ]\n" + + " stack = [ uninitialized 0, uninitialized 0, double ]\n" + + " stack = [ this ]\n" + + " stack = [ this, double ]\n" + + " locals = [ class \"[Ljava/lang/String;\" ]\n" + + " locals = [ class \"[Ljava/lang/String;\" ]\n" + + " locals = [ this, int ]\n"; public static void main(String[] args) throws Exception { - // @compile T6271292.java - ToolBox.JavaToolArgs javacParams = - new ToolBox.JavaToolArgs().setSources(TestSrc); - ToolBox.javac(javacParams); + ToolBox tb = new ToolBox(); + + tb.new JavacTask() + .sources(TestSrc) + .run(); -// "${TESTJAVA}${FS}bin${FS}javap" ${TESTTOOLVMOPTS} -classpath "${TESTCLASSES}" -verbose T6271292 > "${JAVAPFILE}" - ToolBox.JavaToolArgs javapParams = - new ToolBox.JavaToolArgs() - .setAllArgs("-v", "Test.class"); - String out = ToolBox.javap(javapParams); - List grepResult = ToolBox.grep("frame_type", out, - ToolBox.lineSeparator); - grepResult.addAll(ToolBox.grep("offset_delta", out, ToolBox.lineSeparator)); - grepResult.addAll(ToolBox.grep("stack = ", out, ToolBox.lineSeparator)); - grepResult.addAll(ToolBox.grep("locals = ", out, ToolBox.lineSeparator)); - List goldenList = Arrays.asList(goldenOut.split("\n")); + List out = tb.new JavapTask() + .options("-v") + .classes("Test.class") + .run() + .getOutputLines(ToolBox.OutputKind.DIRECT); -// diff -w "${OUTFILE}" "${TESTSRC}${FS}T6271292.out" - ToolBox.compareLines(goldenList, grepResult, true); + List grepResult = new ArrayList<>(); + grepResult.addAll(tb.grep("frame_type", out)); + grepResult.addAll(tb.grep("offset_delta", out)); + grepResult.addAll(tb.grep("stack = ", out)); + grepResult.addAll(tb.grep("locals = ", out)); + + List goldenList = tb.split(goldenOut, "\n"); + tb.checkEqual(goldenList, grepResult); } } diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/lib/ToolBox.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/lib/ToolBox.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,1920 @@ +/* + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FilterOutputStream; +import java.io.FilterWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.io.Writer; +import java.net.URI; +import java.nio.charset.Charset; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.StandardCopyOption; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.List; +import java.util.ListIterator; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.jar.Attributes; +import java.util.jar.JarEntry; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; +import javax.tools.FileObject; +import javax.tools.ForwardingJavaFileManager; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileManager; +import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.StandardLocation; + +import com.sun.tools.javac.api.JavacTaskImpl; +import com.sun.tools.javac.api.JavacTool; +import java.io.IOError; + +/** + * Utility methods and classes for writing jtreg tests for + * javac, javah, javap, and sjavac. (For javadoc support, + * see JavadocTester.) + * + *

There is support for common file operations similar to + * shell commands like cat, cp, diff, mv, rm, grep. + * + *

There is also support for invoking various tools, like + * javac, javah, javap, jar, java and other JDK tools. + * + *

File separators: for convenience, many operations accept strings + * to represent filenames. On all platforms on which JDK is supported, + * "/" is a legal filename component separator. In particular, even + * on Windows, where the official file separator is "\", "/" is a legal + * alternative. It is therefore recommended that any client code using + * strings to specify filenames should use "/". + * + * @author Vicente Romero (original) + * @author Jonathan Gibbons (revised) + */ +public class ToolBox { + /** The platform line separator. */ + public static final String lineSeparator = System.getProperty("line.separator"); + /** The platform OS name. */ + public static final String osName = System.getProperty("os.name"); + + /** The location of the class files for this test, or null if not set. */ + public static final String testClasses = System.getProperty("test.classes"); + /** The location of the source files for this test, or null if not set. */ + public static final String testSrc = System.getProperty("test.src"); + /** The location of the test JDK for this test, or null if not set. */ + public static final String testJDK = System.getProperty("test.jdk"); + + /** The current directory. */ + public static final Path currDir = Paths.get("."); + + /** The stream used for logging output. */ + public PrintStream out = System.err; + + JavaCompiler compiler; + StandardJavaFileManager standardJavaFileManager; + + /** + * Checks if the host OS is some version of Windows. + * @return true if the host OS is some version of Windows + */ + public boolean isWindows() { + return osName.toLowerCase(Locale.ENGLISH).startsWith("windows"); + } + + /** + * Splits a string around matches of the given regular expression. + * If the string is empty, an empty list will be returned. + * @param text the string to be split + * @param sep the delimiting regular expression + * @return the strings between the separators + */ + public List split(String text, String sep) { + if (text.isEmpty()) + return Collections.emptyList(); + return Arrays.asList(text.split(sep)); + } + + /** + * Checks if two lists of strings are equal. + * @param l1 the first list of strings to be compared + * @param l2 the second list of strings to be compared + * @throws Error if the lists are not equal + */ + public void checkEqual(List l1, List l2) throws Error { + if (!Objects.equals(l1, l2)) { + // l1 and l2 cannot both be null + if (l1 == null) + throw new Error("comparison failed: l1 is null"); + if (l2 == null) + throw new Error("comparison failed: l2 is null"); + // report first difference + for (int i = 0; i < Math.min(l1.size(), l2.size()); i++) { + String s1 = l1.get(i); + String s2 = l1.get(i); + if (!Objects.equals(s1, s2)) { + throw new Error("comparison failed, index " + i + + ", (" + s1 + ":" + s2 + ")"); + } + } + throw new Error("comparison failed: l1.size=" + l1.size() + ", l2.size=" + l2.size()); + } + } + + /** + * Filters a list of strings according to the given regular expression. + * @param regex the regular expression + * @param lines the strings to be filtered + * @return the strings matching the regular expression + */ + public List grep(String regex, List lines) { + return grep(Pattern.compile(regex), lines); + } + + /** + * Filters a list of strings according to the given regular expression. + * @param pattern the regular expression + * @param lines the strings to be filtered + * @return the strings matching the regular expression + */ + public List grep(Pattern pattern, List lines) { + return lines.stream() + .filter(s -> pattern.matcher(s).find()) + .collect(Collectors.toList()); + } + + /** + * Copies a file. + * If the given destination exists and is a directory, the copy is created + * in that directory. Otherwise, the copy will be placed at the destination, + * possibly overwriting any existing file. + *

Similar to the shell "cp" command: {@code cp from to}. + * @param from the file to be copied + * @param to where to copy the file + * @throws IOException if any error occurred while copying the file + */ + public void copyFile(String from, String to) throws IOException { + copyFile(Paths.get(from), Paths.get(to)); + } + + /** + * Copies a file. + * If the given destination exists and is a directory, the copy is created + * in that directory. Otherwise, the copy will be placed at the destination, + * possibly overwriting any existing file. + *

Similar to the shell "cp" command: {@code cp from to}. + * @param from the file to be copied + * @param to where to copy the file + * @throws IOException if an error occurred while copying the file + */ + public void copyFile(Path from, Path to) throws IOException { + if (Files.isDirectory(to)) { + to = to.resolve(from.getFileName()); + } else { + Files.createDirectories(to.getParent()); + } + Files.copy(from, to, StandardCopyOption.REPLACE_EXISTING); + } + + /** + * Creates one of more directories. + * For each of the series of paths, a directory will be created, + * including any necessary parent directories. + *

Similar to the shell command: {@code mkdir -p paths}. + * @param paths the directories to be created + * @throws IOException if an error occurred while creating the directories + */ + public void createDirectories(String... paths) throws IOException { + if (paths.length == 0) + throw new IllegalArgumentException("no directories specified"); + for (String p: paths) + Files.createDirectories(Paths.get(p)); + } + + /** + * Creates one or more directories. + * For each of the series of paths, a directory will be created, + * including any necessary parent directories. + *

Similar to the shell command: {@code mkdir -p paths}. + * @param paths the directories to be created + * @throws IOException if an error occurred while creating the directories + */ + public void createDirectories(Path... paths) throws IOException { + if (paths.length == 0) + throw new IllegalArgumentException("no directories specified"); + for (Path p: paths) + Files.createDirectories(p); + } + + /** + * Deletes one or more files. + * Any directories to be deleted must be empty. + *

Similar to the shell command: {@code rm files}. + * @param files the files to be deleted + * @throws IOException if an error occurred while deleting the files + */ + public void deleteFiles(String... files) throws IOException { + if (files.length == 0) + throw new IllegalArgumentException("no files specified"); + for (String file: files) + Files.delete(Paths.get(file)); + } + + /** + * Moves a file. + * If the given destination exists and is a directory, the file will be moved + * to that directory. Otherwise, the file will be moved to the destination, + * possibly overwriting any existing file. + *

Similar to the shell "mv" command: {@code mv from to}. + * @param from the file to be moved + * @param to where to move the file + * @throws IOException if an error occurred while moving the file + */ + public void moveFile(String from, String to) throws IOException { + moveFile(Paths.get(from), Paths.get(to)); + } + + /** + * Moves a file. + * If the given destination exists and is a directory, the file will be moved + * to that directory. Otherwise, the file will be moved to the destination, + * possibly overwriting any existing file. + *

Similar to the shell "mv" command: {@code mv from to}. + * @param from the file to be moved + * @param to where to move the file + * @throws IOException if an error occurred while moving the file + */ + public void moveFile(Path from, Path to) throws IOException { + if (Files.isDirectory(to)) { + to = to.resolve(from.getFileName()); + } else { + Files.createDirectories(to.getParent()); + } + Files.move(from, to, StandardCopyOption.REPLACE_EXISTING); + } + + /** + * Reads the lines of a file. + * The file is read using the default character encoding. + * @param path the file to be read + * @return the lines of the file. + * @throws IOException if an error occurred while reading the file + */ + public List readAllLines(String path) throws IOException { + return readAllLines(path, null); + } + + /** + * Reads the lines of a file. + * The file is read using the default character encoding. + * @param path the file to be read + * @return the lines of the file. + * @throws IOException if an error occurred while reading the file + */ + public List readAllLines(Path path) throws IOException { + return readAllLines(path, null); + } + + /** + * Reads the lines of a file using the given encoding. + * @param path the file to be read + * @param encoding the encoding to be used to read the file + * @return the lines of the file. + * @throws IOException if an error occurred while reading the file + */ + public List readAllLines(String path, String encoding) throws IOException { + return readAllLines(Paths.get(path), encoding); + } + + /** + * Reads the lines of a file using the given encoding. + * @param path the file to be read + * @param encoding the encoding to be used to read the file + * @return the lines of the file. + * @throws IOException if an error occurred while reading the file + */ + public List readAllLines(Path path, String encoding) throws IOException { + return Files.readAllLines(path, getCharset(encoding)); + } + + private Charset getCharset(String encoding) { + return (encoding == null) ? Charset.defaultCharset() : Charset.forName(encoding); + } + + /** + * Writes a file containing the given content. + * Any necessary directories for the file will be created. + * @param path where to write the file + * @param content the content for the file + * @throws IOException if an error occurred while writing the file + */ + public void writeFile(String path, String content) throws IOException { + writeFile(Paths.get(path), content); + } + + /** + * Writes a file containing the given content. + * Any necessary directories for the file will be created. + * @param path where to write the file + * @param content the content for the file + * @throws IOException if an error occurred while writing the file + */ + public void writeFile(Path path, String content) throws IOException { + Path dir = path.getParent(); + if (dir != null) + Files.createDirectories(dir); + try (BufferedWriter w = Files.newBufferedWriter(path)) { + w.write(content); + } + } + + /** + * Writes one or more files containing Java source code. + * For each file to be written, the filename will be inferred from the + * given base directory, the package declaration (if present) and from the + * the name of the first class, interface or enum declared in the file. + *

For example, if the base directory is /my/dir/ and the content + * contains "package p; class C { }", the file will be written to + * /my/dir/p/C.java. + *

Note: the content is analyzed using regular expressions; + * errors can occur if any contents have initial comments that might trip + * up the analysis. + * @param dir the base directory + * @param contents the contents of the files to be written + * @throws IOException if an error occurred while writing any of the files. + */ + public void writeJavaFiles(Path dir, String... contents) throws IOException { + if (contents.length == 0) + throw new IllegalArgumentException("no content specified for any files"); + for (String c: contents) { + new JavaSource(c).write(dir); + } + } + + /** + * Returns the path for the binary of a JDK tool within {@link testJDK}. + * @param tool the name of the tool + * @return the path of the tool + */ + public Path getJDKTool(String tool) { + return Paths.get(testJDK, "bin", tool); + } + + /** + * Returns a string representing the contents of an {@code Iterable} as a list. + * @param the type parameter of the {@code Iterable} + * @param items the iterable + * @return the string + */ + String toString(Iterable items) { + return StreamSupport.stream(items.spliterator(), false) + .map(Objects::toString) + .collect(Collectors.joining(",", "[", "]")); + } + + /** + * The supertype for tasks. + * Complex operations are modelled by building and running a "Task" object. + * Tasks are typically configured in a fluent series of calls. + */ + public interface Task { + /** + * Returns the name of the task. + * @return the name of the task + */ + String name(); + + /** + * Executes the task as currently configured. + * @return a Result object containing the results of running the task + * @throws TaskError if the outcome of the task was not as expected + */ + Result run() throws TaskError; + } + + /** + * Exception thrown by {@code Task.run} when the outcome is not as + * expected. + */ + public static class TaskError extends Error { + /** + * Creates a TaskError object with the given message. + * @param message the message + */ + public TaskError(String message) { + super(message); + } + } + + /** + * An enum to indicate the mode a task should use it is when executed. + */ + public enum Mode { + /** + * The task should use the interface used by the command + * line launcher for the task. + * For example, for javac: com.sun.tools.javac.Main.compile + */ + CMDLINE, + /** + * The task should use a publicly defined API for the task. + * For example, for javac: javax.tools.JavaCompiler + */ + API, + /** + * The task should use the standard launcher for the task. + * For example, $JAVA_HOME/bin/javac + */ + EXEC + } + + /** + * An enum to indicate the expected success or failure of executing a task. + */ + public enum Expect { + /** It is expected that the task will complete successfully. */ + SUCCESS, + /** It is expected that the task will not complete successfully. */ + FAIL + } + + /** + * An enum to identify the streams that may be written by a {@code Task}. + */ + public enum OutputKind { + /** Identifies output written to {@code System.out} or {@code stdout}. */ + STDOUT, + /** Identifies output written to {@code System.err} or {@code stderr}. */ + STDERR, + /** Identifies output written to a stream provided directly to the task. */ + DIRECT + }; + + /** + * The results from running a {@link Task}. + * The results contain the exit code returned when the tool was invoked, + * and a map containing the output written to any streams during the + * execution of the tool. + * All tools support "stdout" and "stderr". + * Tools that take an explicit PrintWriter save output written to that + * stream as "main". + */ + public class Result { + + final Task task; + final int exitCode; + final Map outputMap; + + Result(Task task, int exitCode, Map outputMap) { + this.task = task; + this.exitCode = exitCode; + this.outputMap = outputMap; + } + + /** + * Returns the content of a specified stream. + * @param outputKind the kind of the selected stream + * @return the content that was written to that stream when the tool + * was executed. + */ + public String getOutput(OutputKind outputKind) { + return outputMap.get(outputKind); + } + + /** + * Returns the content of a named stream as a list of lines. + * @param outputKind the kind of the selected stream + * @return the content that was written to that stream when the tool + * was executed. + */ + public List getOutputLines(OutputKind outputKind) { + return Arrays.asList(outputMap.get(outputKind).split(lineSeparator)); + } + + /** + * Writes the content of the specified stream to the log. + * @param kind the kind of the selected stream + * @return this Result object + */ + public Result write(OutputKind kind) { + String text = getOutput(kind); + if (text == null || text.isEmpty()) + out.println("[" + task.name() + ":" + kind + "]: empty"); + else { + out.println("[" + task.name() + ":" + kind + "]:"); + out.print(text); + } + return this; + } + + /** + * Writes the content of all streams with any content to the log. + * @return this Result object + */ + public Result writeAll() { + outputMap.forEach((name, text) -> { + if (!text.isEmpty()) { + out.println("[" + name + "]:"); + out.print(text); + } + }); + return this; + } + } + + /** + * A utility base class to simplify the implementation of tasks. + * Provides support for running the task in a process and for + * capturing output written by the task to stdout, stderr and + * other writers where applicable. + * @param the implementing subclass + */ + protected static abstract class AbstractTask> implements Task { + protected final Mode mode; + private final Map redirects = new EnumMap<>(OutputKind.class); + private final Map envVars = new HashMap<>(); + private Expect expect = Expect.SUCCESS; + int expectedExitCode = 0; + + /** + * Create a task that will execute in the specified mode. + * @param mode the mode + */ + protected AbstractTask(Mode mode) { + this.mode = mode; + } + + /** + * Sets the expected outcome of the task and calls {@code run()}. + * @param expect the expected outcome + * @return the result of calling {@code run()} + */ + public Result run(Expect expect) { + expect(expect, Integer.MIN_VALUE); + return run(); + } + + /** + * Sets the expected outcome of the task and calls {@code run()}. + * @param expect the expected outcome + * @param exitCode the expected exit code if the expected outcome + * is {@code FAIL} + * @return the result of calling {@code run()} + */ + public Result run(Expect expect, int exitCode) { + expect(expect, exitCode); + return run(); + } + + /** + * Sets the expected outcome and expected exit code of the task. + * The exit code will not be checked if the outcome is + * {@code Expect.SUCCESS} or if the exit code is set to + * {@code Integer.MIN_VALUE}. + * @param expect the expected outcome + * @param exitCode the expected exit code + */ + protected void expect(Expect expect, int exitCode) { + this.expect = expect; + this.expectedExitCode = exitCode; + } + + /** + * Checks the exit code contained in a {@code Result} against the + * expected outcome and exit value + * @param result the result object + * @return the result object + * @throws TaskError if the exit code stored in the result object + * does not match the expected outcome and exit code. + */ + protected Result checkExit(Result result) throws TaskError { + switch (expect) { + case SUCCESS: + if (result.exitCode != 0) { + result.writeAll(); + throw new TaskError("Task " + name() + " failed: rc=" + result.exitCode); + } + break; + + case FAIL: + if (result.exitCode == 0) { + result.writeAll(); + throw new TaskError("Task " + name() + " succeeded unexpectedly"); + } + + if (expectedExitCode != Integer.MIN_VALUE + && result.exitCode != expectedExitCode) { + result.writeAll(); + throw new TaskError("Task " + name() + "failed with unexpected exit code " + + result.exitCode + ", expected " + expectedExitCode); + } + break; + } + return result; + } + + /** + * Sets an environment variable to be used by this task. + * @param name the name of the environment variable + * @param value the value for the environment variable + * @return this task object + * @throws IllegalStateException if the task mode is not {@code EXEC} + */ + protected T envVar(String name, String value) { + if (mode != Mode.EXEC) + throw new IllegalStateException(); + envVars.put(name, value); + return (T) this; + } + + /** + * Redirects output from an output stream to a file. + * @param outputKind the name of the stream to be redirected. + * @param path the file + * @return this task object + * @throws IllegalStateException if the task mode is not {@code EXEC} + */ + protected T redirect(OutputKind outputKind, String path) { + if (mode != Mode.EXEC) + throw new IllegalStateException(); + redirects.put(outputKind, path); + return (T) this; + } + + /** + * Returns a {@code ProcessBuilder} initialized with any + * redirects and environment variables that have been set. + * @return a {@code ProcessBuilder} + */ + protected ProcessBuilder getProcessBuilder() { + if (mode != Mode.EXEC) + throw new IllegalStateException(); + ProcessBuilder pb = new ProcessBuilder(); + if (redirects.get(OutputKind.STDOUT) != null) + pb.redirectOutput(new File(redirects.get(OutputKind.STDOUT))); + if (redirects.get(OutputKind.STDERR) != null) + pb.redirectError(new File(redirects.get(OutputKind.STDERR))); + pb.environment().putAll(envVars); + return pb; + } + + /** + * Collects the output from a process and saves it in a {@code Result}. + * @param tb the {@code ToolBox} containing the task {@code t} + * @param t the task initiating the process + * @param p the process + * @return a Result object containing the output from the process and its + * exit value. + * @throws InterruptedException if the thread is interrupted + */ + protected Result runProcess(ToolBox tb, Task t, Process p) throws InterruptedException { + if (mode != Mode.EXEC) + throw new IllegalStateException(); + ProcessOutput sysOut = new ProcessOutput(p.getInputStream()).start(); + ProcessOutput sysErr = new ProcessOutput(p.getErrorStream()).start(); + sysOut.waitUntilDone(); + sysErr.waitUntilDone(); + int rc = p.waitFor(); + Map outputMap = new EnumMap<>(OutputKind.class); + outputMap.put(OutputKind.STDOUT, sysOut.getOutput()); + outputMap.put(OutputKind.STDERR, sysErr.getOutput()); + return checkExit(tb.new Result(t, rc, outputMap)); + } + + /** + * Thread-friendly class to read the output from a process until the stream + * is exhausted. + */ + static class ProcessOutput implements Runnable { + ProcessOutput(InputStream from) { + in = new BufferedReader(new InputStreamReader(from)); + out = new StringBuilder(); + } + + ProcessOutput start() { + new Thread(this).start(); + return this; + } + + @Override + public void run() { + try { + String line; + while ((line = in.readLine()) != null) { + out.append(line).append("\n"); + } + } catch (IOException e) { + } + synchronized (this) { + done = true; + notifyAll(); + } + } + + synchronized void waitUntilDone() throws InterruptedException { + boolean interrupted = false; + + // poll interrupted flag, while waiting for copy to complete + while (!(interrupted = Thread.interrupted()) && !done) + wait(1000); + + if (interrupted) + throw new InterruptedException(); + } + + String getOutput() { + return out.toString(); + } + + private BufferedReader in; + private final StringBuilder out; + private boolean done; + } + + /** + * Utility class to simplify the handling of temporarily setting a + * new stream for System.out or System.err. + */ + static class StreamOutput { + // Functional interface to set a stream. + // Expected use: System::setOut, System::setErr + private interface Initializer { + void set(PrintStream s); + } + + private final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + private final PrintStream ps = new PrintStream(baos); + private final PrintStream prev; + private final Initializer init; + + StreamOutput(PrintStream s, Initializer init) { + prev = s; + init.set(ps); + this.init = init; + } + + /** + * Closes the stream and returns the contents that were written to it. + * @return the contents that were written to it. + */ + String close() { + init.set(prev); + ps.close(); + return baos.toString(); + } + } + + /** + * Utility class to simplify the handling of creating an in-memory PrintWriter. + */ + static class WriterOutput { + private final StringWriter sw = new StringWriter(); + final PrintWriter pw = new PrintWriter(sw); + + /** + * Closes the stream and returns the contents that were written to it. + * @return the contents that were written to it. + */ + String close() { + pw.close(); + return sw.toString(); + } + } + } + + /** + * A task to configure and run the Java compiler, javac. + */ + public class JavacTask extends AbstractTask { + private boolean includeStandardOptions; + private String classpath; + private String sourcepath; + private String outdir; + private List options; + private List classes; + private List files; + private List fileObjects; + private JavaFileManager fileManager; + + /** + * Creates a task to execute {@code javac} using API mode. + */ + public JavacTask() { + super(Mode.API); + } + + /** + * Creates a task to execute {@code javac} in a specified mode. + * @param mode the mode to be used + */ + public JavacTask(Mode mode) { + super(mode); + } + + /** + * Sets the classpath. + * @param classpath the classpath + * @return this task object + */ + public JavacTask classpath(String classpath) { + this.classpath = classpath; + return this; + } + + /** + * Sets the sourcepath. + * @param sourcepath the sourcepath + * @return this task object + */ + public JavacTask sourcepath(String sourcepath) { + this.sourcepath = sourcepath; + return this; + } + + /** + * Sets the output directory. + * @param outdir the output directory + * @return this task object + */ + public JavacTask outdir(String outdir) { + this.outdir = outdir; + return this; + } + + /** + * Sets the options. + * @param options the options + * @return this task object + */ + public JavacTask options(String... options) { + this.options = Arrays.asList(options); + return this; + } + + /** + * Sets the classes to be analyzed. + * @param classes the classes + * @return this task object + */ + public JavacTask classes(String... classes) { + this.classes = Arrays.asList(classes); + return this; + } + + /** + * Sets the files to be compiled or analyzed. + * @param files the files + * @return this task object + */ + public JavacTask files(String... files) { + this.files = Arrays.asList(files); + return this; + } + + /** + * Sets the files to be compiled or analyzed. + * @param files the files + * @return this task object + */ + public JavacTask files(Path... files) { + this.files = Stream.of(files) + .map(Path::toString) + .collect(Collectors.toList()); + return this; + } + + /** + * Sets the sources to be compiled or analyzed. + * Each source string is converted into an in-memory object that + * can be passed directly to the compiler. + * @param sources the sources + * @return this task object + */ + public JavacTask sources(String... sources) { + fileObjects = Stream.of(sources) + .map(s -> new JavaSource(s)) + .collect(Collectors.toList()); + return this; + } + + /** + * Sets the file manager to be used by this task. + * @param fileManager the file manager + * @return this task object + */ + public JavacTask fileManager(JavaFileManager fileManager) { + this.fileManager = fileManager; + return this; + } + + /** + * {@inheritDoc} + * @return the name "javac" + */ + @Override + public String name() { + return "javac"; + } + + /** + * Calls the compiler with the arguments as currently configured. + * @return a Result object indicating the outcome of the compilation + * and the content of any output written to stdout, stderr, or the + * main stream by the compiler. + * @throws TaskError if the outcome of the task is not as expected. + */ + @Override + public Result run() { + if (mode == Mode.EXEC) + return runExec(); + + WriterOutput direct = new WriterOutput(); + // The following are to catch output to System.out and System.err, + // in case these are used instead of the primary (main) stream + StreamOutput sysOut = new StreamOutput(System.out, System::setOut); + StreamOutput sysErr = new StreamOutput(System.err, System::setErr); + int rc; + Map outputMap = new HashMap<>(); + try { + switch (mode == null ? Mode.API : mode) { + case API: + rc = runAPI(direct.pw); + break; + case CMDLINE: + rc = runCommand(direct.pw); + break; + default: + throw new IllegalStateException(); + } + } catch (IOException e) { + out.println("Exception occurred: " + e); + rc = 99; + } finally { + outputMap.put(OutputKind.STDOUT, sysOut.close()); + outputMap.put(OutputKind.STDERR, sysErr.close()); + outputMap.put(OutputKind.DIRECT, direct.close()); + } + return checkExit(new Result(this, rc, outputMap)); + } + + private int runAPI(PrintWriter pw) throws IOException { +// if (compiler == null) { + // TODO: allow this to be set externally +// compiler = ToolProvider.getSystemJavaCompiler(); + compiler = JavacTool.create(); +// } + + if (fileManager == null) + fileManager = compiler.getStandardFileManager(null, null, null); + if (outdir != null) + setLocation(StandardLocation.CLASS_OUTPUT, toFiles(outdir)); + if (classpath != null) + setLocation(StandardLocation.CLASS_PATH, toFiles(classpath)); + if (sourcepath != null) + setLocation(StandardLocation.SOURCE_PATH, toFiles(sourcepath)); + List allOpts = new ArrayList<>(); + if (options != null) + allOpts.addAll(options); + + Iterable allFiles = joinFiles(files, fileObjects); + JavaCompiler.CompilationTask task = compiler.getTask(pw, + fileManager, + null, // diagnostic listener; should optionally collect diags + allOpts, + classes, + allFiles); + return ((JavacTaskImpl) task).doCall().exitCode; + } + + private void setLocation(StandardLocation location, List files) throws IOException { + if (!(fileManager instanceof StandardJavaFileManager)) + throw new IllegalStateException("not a StandardJavaFileManager"); + ((StandardJavaFileManager) fileManager).setLocation(location, files); + } + + private int runCommand(PrintWriter pw) { + List args = getAllArgs(); + String[] argsArray = args.toArray(new String[args.size()]); + return com.sun.tools.javac.Main.compile(argsArray, pw); + } + + private Result runExec() { + List args = new ArrayList<>(); + Path javac = getJDKTool("javac"); + args.add(javac.toString()); + if (includeStandardOptions) { + args.addAll(split(System.getProperty("test.tool.vm.opts"), " +")); + args.addAll(split(System.getProperty("test.compiler.opts"), " +")); + } + args.addAll(getAllArgs()); + + String[] argsArray = args.toArray(new String[args.size()]); + ProcessBuilder pb = getProcessBuilder(); + pb.command(argsArray); + try { + return runProcess(ToolBox.this, this, pb.start()); + } catch (IOException | InterruptedException e) { + throw new Error(e); + } + } + + private List getAllArgs() { + List args = new ArrayList<>(); + if (options != null) + args.addAll(options); + if (outdir != null) { + args.add("-d"); + args.add(outdir); + } + if (classpath != null) { + args.add("-classpath"); + args.add(classpath); + } + if (sourcepath != null) { + args.add("-sourcepath"); + args.add(sourcepath); + } + if (classes != null) + args.addAll(classes); + if (files != null) + args.addAll(files); + + return args; + } + + private List toFiles(String path) { + List result = new ArrayList<>(); + for (String s: path.split(File.pathSeparator)) { + if (!s.isEmpty()) + result.add(new File(s)); + } + return result; + } + + private Iterable joinFiles( + List files, List fileObjects) { + if (files == null) + return fileObjects; + if (standardJavaFileManager == null) + standardJavaFileManager = compiler.getStandardFileManager(null, null, null); + Iterable filesAsFileObjects = + standardJavaFileManager.getJavaFileObjectsFromStrings(files); + if (fileObjects == null) + return filesAsFileObjects; + List combinedList = new ArrayList<>(); + for (JavaFileObject o: filesAsFileObjects) + combinedList.add(o); + combinedList.addAll(fileObjects); + return combinedList; + } + } + + /** + * A task to configure and run the native header tool, javah. + */ + public class JavahTask extends AbstractTask { + private String classpath; + private List options; + private List classes; + + /** + * Create a task to execute {@code javah} using {@code CMDLINE} mode. + */ + public JavahTask() { + super(Mode.CMDLINE); + } + + /** + * Sets the classpath. + * @param classpath the classpath + * @return this task object + */ + public JavahTask classpath(String classpath) { + this.classpath = classpath; + return this; + } + + /** + * Sets the options. + * @param options the options + * @return this task object + */ + public JavahTask options(String... options) { + this.options = Arrays.asList(options); + return this; + } + + /** + * Sets the classes to be analyzed. + * @param classes the classes + * @return this task object + */ + public JavahTask classes(String... classes) { + this.classes = Arrays.asList(classes); + return this; + } + + /** + * {@inheritDoc} + * @return the name "javah" + */ + @Override + public String name() { + return "javah"; + } + + /** + * Calls the javah tool with the arguments as currently configured. + * @return a Result object indicating the outcome of the task + * and the content of any output written to stdout, stderr, or the + * main stream provided to the task. + * @throws TaskError if the outcome of the task is not as expected. + */ + @Override + public Result run() { + List args = new ArrayList<>(); + if (options != null) + args.addAll(options); + if (classpath != null) { + args.add("-classpath"); + args.add(classpath); + } + if (classes != null) + args.addAll(classes); + + WriterOutput direct = new WriterOutput(); + // These are to catch output to System.out and System.err, + // in case these are used instead of the primary streams + StreamOutput sysOut = new StreamOutput(System.out, System::setOut); + StreamOutput sysErr = new StreamOutput(System.err, System::setErr); + int rc; + Map outputMap = new HashMap<>(); + try { + rc = com.sun.tools.javah.Main.run(args.toArray(new String[args.size()]), direct.pw); + } finally { + outputMap.put(OutputKind.STDOUT, sysOut.close()); + outputMap.put(OutputKind.STDERR, sysErr.close()); + outputMap.put(OutputKind.DIRECT, direct.close()); + } + return checkExit(new Result(this, rc, outputMap)); + } + } + + /** + * A task to configure and run the disassembler tool, javap. + */ + public class JavapTask extends AbstractTask { + private String classpath; + private List options; + private List classes; + + /** + * Create a task to execute {@code javap} using {@code CMDLINE} mode. + */ + public JavapTask() { + super(Mode.CMDLINE); + } + + /** + * Sets the classpath. + * @param classpath the classpath + * @return this task object + */ + public JavapTask classpath(String classpath) { + this.classpath = classpath; + return this; + } + + /** + * Sets the options. + * @param options the options + * @return this task object + */ + public JavapTask options(String... options) { + this.options = Arrays.asList(options); + return this; + } + + /** + * Sets the classes to be analyzed. + * @param classes the classes + * @return this task object + */ + public JavapTask classes(String... classes) { + this.classes = Arrays.asList(classes); + return this; + } + + /** + * {@inheritDoc} + * @return the name "javap" + */ + @Override + public String name() { + return "javap"; + } + + /** + * Calls the javap tool with the arguments as currently configured. + * @return a Result object indicating the outcome of the task + * and the content of any output written to stdout, stderr, or the + * main stream. + * @throws TaskError if the outcome of the task is not as expected. + */ + @Override + public Result run() { + List args = new ArrayList<>(); + if (options != null) + args.addAll(options); + if (classpath != null) { + args.add("-classpath"); + args.add(classpath); + } + if (classes != null) + args.addAll(classes); + + WriterOutput direct = new WriterOutput(); + // These are to catch output to System.out and System.err, + // in case these are used instead of the primary streams + StreamOutput sysOut = new StreamOutput(System.out, System::setOut); + StreamOutput sysErr = new StreamOutput(System.err, System::setErr); + + int rc; + Map outputMap = new HashMap<>(); + try { + rc = com.sun.tools.javap.Main.run(args.toArray(new String[args.size()]), direct.pw); + } finally { + outputMap.put(OutputKind.STDOUT, sysOut.close()); + outputMap.put(OutputKind.STDERR, sysErr.close()); + outputMap.put(OutputKind.DIRECT, direct.close()); + } + return checkExit(new Result(this, rc, outputMap)); + } + } + + /** + * A task to configure and run the jar file utility. + */ + public class JarTask extends AbstractTask { + private Path jar; + private Manifest manifest; + private String classpath; + private String mainClass; + private Path baseDir; + private List paths; + + /** + * Creates a task to write jar files, using API mode. + */ + public JarTask() { + super(Mode.API); + paths = Collections.emptyList(); + } + + /** + * Creates a JarTask for use with a given jar file. + * @param path the file + */ + public JarTask(String path) { + this(); + jar = Paths.get(path); + } + + /** + * Sets a manifest for the jar file. + * @param manifest the manifest + * @return this task object + */ + public JarTask manifest(Manifest manifest) { + this.manifest = manifest; + return this; + } + + /** + * Sets a manifest for the jar file. + * @param manifest a string containing the contents of the manifest + * @return this task object + * @throws IOException if there is a problem creating the manifest + */ + public JarTask manifest(String manifest) throws IOException { + this.manifest = new Manifest(new ByteArrayInputStream(manifest.getBytes())); + return this; + } + + /** + * Sets the classpath to be written to the {@code Class-Path} + * entry in the manifest. + * @param classpath the classpath + * @return this task object + */ + public JarTask classpath(String classpath) { + this.classpath = classpath; + return this; + } + + /** + * Sets the class to be written to the {@code Main-Class} + * entry in the manifest.. + * @param mainClass the name of the main class + * @return this task object + */ + public JarTask mainClass(String mainClass) { + this.mainClass = mainClass; + return this; + } + + /** + * Sets the base directory for files to be written into the jar file. + * @param baseDir the base directory + * @return this task object + */ + public JarTask baseDir(String baseDir) { + this.baseDir = Paths.get(baseDir); + return this; + } + + /** + * Sets the files to be written into the jar file. + * @param files the files + * @return this task object + */ + public JarTask files(String... files) { + this.paths = Stream.of(files) + .map(file -> Paths.get(file)) + .collect(Collectors.toList()); + return this; + } + + /** + * Provides limited jar command-like functionality. + * The supported commands are: + *

    + *
  • jar cf jarfile -C dir files... + *
  • jar cfm jarfile manifestfile -C dir files... + *
+ * Any values specified by other configuration methods will be ignored. + * @param args arguments in the style of those for the jar command + * @return a Result object containing the results of running the task + */ + public Result run(String... args) { + if (args.length < 2) + throw new IllegalArgumentException(); + + ListIterator iter = Arrays.asList(args).listIterator(); + String first = iter.next(); + switch (first) { + case "cf": + jar = Paths.get(iter.next()); + break; + case "cfm": + jar = Paths.get(iter.next()); + try (InputStream in = Files.newInputStream(Paths.get(iter.next()))) { + manifest = new Manifest(in); + } catch (IOException e) { + throw new IOError(e); + } + break; + } + + if (iter.hasNext()) { + if (iter.next().equals("-C")) + baseDir = Paths.get(iter.next()); + else + iter.previous(); + } + + paths = new ArrayList<>(); + while (iter.hasNext()) + paths.add(Paths.get(iter.next())); + + return run(); + } + + /** + * {@inheritDoc} + * @return the name "jar" + */ + @Override + public String name() { + return "jar"; + } + + /** + * Creates a jar file with the arguments as currently configured. + * @return a Result object indicating the outcome of the compilation + * and the content of any output written to stdout, stderr, or the + * main stream by the compiler. + * @throws TaskError if the outcome of the task is not as expected. + */ + @Override + public Result run() { + Manifest m = (manifest == null) ? new Manifest() : manifest; + Attributes mainAttrs = m.getMainAttributes(); + if (mainClass != null) + mainAttrs.put(Attributes.Name.MAIN_CLASS, mainClass); + if (classpath != null) + mainAttrs.put(Attributes.Name.CLASS_PATH, classpath); + + StreamOutput sysOut = new StreamOutput(System.out, System::setOut); + StreamOutput sysErr = new StreamOutput(System.err, System::setErr); + + int rc; + Map outputMap = new HashMap<>(); + + try (OutputStream os = Files.newOutputStream(jar); + JarOutputStream jos = openJar(os, m)) { + Path base = (baseDir == null) ? currDir : baseDir; + for (Path path: paths) { + Files.walkFileTree(base.resolve(path), new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { + try { + JarEntry e = new JarEntry(base.relativize(file).toString()); + jos.putNextEntry(e); + jos.write(Files.readAllBytes(file)); + jos.closeEntry(); + return FileVisitResult.CONTINUE; + } catch (IOException e) { + System.err.println("Error adding " + file + " to jar file: " + e); + return FileVisitResult.TERMINATE; + } + } + }); + } + rc = 0; + } catch (IOException e) { + System.err.println("Error opening " + jar + ": " + e); + rc = 1; + } finally { + outputMap.put(OutputKind.STDOUT, sysOut.close()); + outputMap.put(OutputKind.STDERR, sysErr.close()); + } + return checkExit(new Result(this, rc, outputMap)); + } + + private JarOutputStream openJar(OutputStream os, Manifest m) throws IOException { + if (m == null || m.getMainAttributes().isEmpty() && m.getEntries().isEmpty()) { + return new JarOutputStream(os); + } else { + if (m.getMainAttributes().get(Attributes.Name.MANIFEST_VERSION) == null) + m.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0"); + return new JarOutputStream(os, m); + } + } + + } + + /** + * A task to configure and run the Java launcher. + */ + public class JavaTask extends AbstractTask { + boolean includeStandardOptions = true; + private String classpath; + private List vmOptions; + private String className; + private List classArgs; + + /** + * Create a task to run the Java launcher, using {@code EXEC} mode. + */ + public JavaTask() { + super(Mode.EXEC); + } + + /** + * Sets the classpath. + * @param classpath the classpath + * @return this task object + */ + public JavaTask classpath(String classpath) { + this.classpath = classpath; + return this; + } + + /** + * Sets the VM options. + * @param vmOptions the options + * @return this task object + */ + public JavaTask vmOptions(String... vmOptions) { + this.vmOptions = Arrays.asList(vmOptions); + return this; + } + + /** + * Sets the name of the class to be executed. + * @param className the name of the class + * @return this task object + */ + public JavaTask className(String className) { + this.className = className; + return this; + } + + /** + * Sets the arguments for the class to be executed. + * @param classArgs the arguments + * @return this task object + */ + public JavaTask classArgs(String... classArgs) { + this.classArgs = Arrays.asList(classArgs); + return this; + } + + /** + * {@inheritDoc} + * @return the name "java" + */ + @Override + public String name() { + return "java"; + } + + /** + * Calls the Java launcher with the arguments as currently configured. + * @return a Result object indicating the outcome of the task + * and the content of any output written to stdout or stderr. + * @throws TaskError if the outcome of the task is not as expected. + */ + @Override + public Result run() { + List args = new ArrayList<>(); + args.add(getJDKTool("java").toString()); + if (includeStandardOptions) { + args.addAll(split(System.getProperty("test.vm.opts"), " +")); + args.addAll(split(System.getProperty("test.java.opts"), " +")); + } + if (classpath != null) { + args.add("-classpath"); + args.add(classpath); + } + if (vmOptions != null) + args.addAll(vmOptions); + if (className != null) + args.add(className); + if (classArgs != null) + args.addAll(classArgs); + ProcessBuilder pb = getProcessBuilder(); + pb.command(args); + try { + return runProcess(ToolBox.this, this, pb.start()); + } catch (IOException | InterruptedException e) { + throw new Error(e); + } + } + } + + /** + * A task to configure and run a general command. + */ + public class ExecTask extends AbstractTask { + private final String command; + private List args; + + /** + * Create a task to execute a given command, to be run using {@code EXEC} mode. + * @param command the command to be executed + */ + public ExecTask(String command) { + super(Mode.EXEC); + this.command = command; + } + + /** + * Create a task to execute a given command, to be run using {@code EXEC} mode. + * @param command the command to be executed + */ + public ExecTask(Path command) { + super(Mode.EXEC); + this.command = command.toString(); + } + + /** + * Sets the arguments for the command to be executed + * @param args the arguments + * @return this task object + */ + public ExecTask args(String... args) { + this.args = Arrays.asList(args); + return this; + } + + /** + * {@inheritDoc} + * @return the name "exec" + */ + @Override + public String name() { + return "exec"; + } + + /** + * Calls the command with the arguments as currently configured. + * @return a Result object indicating the outcome of the task + * and the content of any output written to stdout or stderr. + * @throws TaskError if the outcome of the task is not as expected. + */ + @Override + public Result run() { + List cmdArgs = new ArrayList<>(); + cmdArgs.add(command); + if (args != null) + cmdArgs.addAll(args); + ProcessBuilder pb = getProcessBuilder(); + pb.command(cmdArgs); + try { + return runProcess(ToolBox.this, this, pb.start()); + } catch (IOException | InterruptedException e) { + throw new Error(e); + } + } + } + + /** + * An in-memory Java source file. + * It is able to extract the file name from simple source text using + * regular expressions. + */ + public static class JavaSource extends SimpleJavaFileObject { + private final String source; + + /** + * Creates a in-memory file object for Java source code. + * @param className the name of the class + * @param source the source text + */ + public JavaSource(String className, String source) { + super(URI.create(className), JavaFileObject.Kind.SOURCE); + this.source = source; + } + + /** + * Creates a in-memory file object for Java source code. + * The name of the class will be inferred from the source code. + * @param source the source text + */ + public JavaSource(String source) { + super(URI.create(getJavaFileNameFromSource(source)), + JavaFileObject.Kind.SOURCE); + this.source = source; + } + + /** + * Writes the source code to a file in the current directory. + * @throws IOException if there is a problem writing the file + */ + public void write() throws IOException { + write(currDir); + } + + /** + * Writes the source code to a file in a specified directory. + * @param dir the directory + * @throws IOException if there is a problem writing the file + */ + public void write(Path dir) throws IOException { + Path file = dir.resolve(getJavaFileNameFromSource(source)); + Files.createDirectories(file.getParent()); + try (BufferedWriter out = Files.newBufferedWriter(file)) { + out.write(source.replace("\n", lineSeparator)); + } + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return source; + } + + private static Pattern packagePattern = + Pattern.compile("package\\s+(((?:\\w+\\.)*)(?:\\w+))"); + private static Pattern classPattern = + Pattern.compile("(?:public\\s+)?(?:class|enum|interface)\\s+(\\w+)"); + + /** + * Extracts the Java file name from the class declaration. + * This method is intended for simple files and uses regular expressions, + * so comments matching the pattern can make the method fail. + */ + static String getJavaFileNameFromSource(String source) { + String packageName = null; + + Matcher matcher = packagePattern.matcher(source); + if (matcher.find()) + packageName = matcher.group(1).replace(".", "/"); + + matcher = classPattern.matcher(source); + if (matcher.find()) { + String className = matcher.group(1) + ".java"; + return (packageName == null) ? className : packageName + "/" + className; + } else { + throw new Error("Could not extract the java class " + + "name from the provided source"); + } + } + } + + /** + * Extracts the Java file name from the class declaration. + * This method is intended for simple files and uses regular expressions, + * so comments matching the pattern can make the method fail. + * @deprecated This is a legacy method for compatibility with ToolBox v1. + * Use {@link JavaSource#getName JavaSource.getName} instead. + * @param source the source text + * @return the Java file name inferred from the source + */ + @Deprecated + public static String getJavaFileNameFromSource(String source) { + return JavaSource.getJavaFileNameFromSource(source); + } + + /** + * A memory file manager, for saving generated files in memory. + * The file manager delegates to a separate file manager for listing and + * reading input files. + */ + public static class MemoryFileManager extends ForwardingJavaFileManager { + private interface Content { + byte[] getBytes(); + String getString(); + } + + /** + * Maps binary class names to generated content. + */ + final Map> files; + + /** + * Construct a memory file manager which stores output files in memory, + * and delegates to a default file manager for input files. + */ + public MemoryFileManager() { + this(JavacTool.create().getStandardFileManager(null, null, null)); + } + + /** + * Construct a memory file manager which stores output files in memory, + * and delegates to a specified file manager for input files. + * @param fileManager the file manager to be used for input files + */ + public MemoryFileManager(JavaFileManager fileManager) { + super(fileManager); + files = new HashMap<>(); + } + + @Override + public JavaFileObject getJavaFileForOutput(Location location, + String name, + JavaFileObject.Kind kind, + FileObject sibling) + { + return new MemoryFileObject(location, name, kind); + } + + /** + * Returns the content written to a file in a given location, + * or null if no such file has been written. + * @param location the location + * @param name the name of the file + * @return the content as an array of bytes + */ + public byte[] getFileBytes(Location location, String name) { + Content content = getFile(location, name); + return (content == null) ? null : content.getBytes(); + } + + /** + * Returns the content written to a file in a given location, + * or null if no such file has been written. + * @param location the location + * @param name the name of the file + * @return the content as a string + */ + public String getFileString(Location location, String name) { + Content content = getFile(location, name); + return (content == null) ? null : content.getString(); + } + + private Content getFile(Location location, String name) { + Map filesForLocation = files.get(location); + return (filesForLocation == null) ? null : filesForLocation.get(name); + } + + private void save(Location location, String name, Content content) { + Map filesForLocation = files.get(location); + if (filesForLocation == null) + files.put(location, filesForLocation = new HashMap<>()); + filesForLocation.put(name, content); + } + + /** + * A writable file object stored in memory. + */ + private class MemoryFileObject extends SimpleJavaFileObject { + private final Location location; + private final String name; + + /** + * Constructs a memory file object. + * @param name binary name of the class to be stored in this file object + */ + MemoryFileObject(Location location, String name, JavaFileObject.Kind kind) { + super(URI.create("mfm:///" + name.replace('.','/') + kind.extension), + Kind.CLASS); + this.location = location; + this.name = name; + } + + @Override + public OutputStream openOutputStream() { + return new FilterOutputStream(new ByteArrayOutputStream()) { + @Override + public void close() throws IOException { + out.close(); + byte[] bytes = ((ByteArrayOutputStream) out).toByteArray(); + save(location, name, new Content() { + @Override + public byte[] getBytes() { + return bytes; + } + @Override + public String getString() { + return new String(bytes); + } + + }); + } + }; + } + + @Override + public Writer openWriter() { + return new FilterWriter(new StringWriter()) { + @Override + public void close() throws IOException { + out.close(); + String text = ((StringWriter) out).toString(); + save(location, name, new Content() { + @Override + public byte[] getBytes() { + return text.getBytes(); + } + @Override + public String getString() { + return text; + } + + }); + } + }; + } + } + + } + +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/sjavac/IdleShutdown.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/sjavac/IdleShutdown.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,156 @@ +/* + * 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. + */ + +/* + * @test + * @bug 8044131 + * @summary Tests the hooks used for detecting idleness of the sjavac server. + * @build Wrapper + * @run main Wrapper IdleShutdown + */ +import java.io.File; +import java.net.URI; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.concurrent.atomic.AtomicLong; + +import com.sun.tools.sjavac.server.CompilationResult; +import com.sun.tools.sjavac.server.IdleResetSjavac; +import com.sun.tools.sjavac.server.Sjavac; +import com.sun.tools.sjavac.server.SysInfo; +import com.sun.tools.sjavac.server.Terminable; + + +public class IdleShutdown { + + final static long TEST_START = System.currentTimeMillis(); + final static long TIMEOUT_MS = 3000; + + public static void main(String[] args) throws InterruptedException { + + final AtomicLong timeoutTimestamp = new AtomicLong(-1); + + log("Starting IdleCallbackJavacService with timeout: " + TIMEOUT_MS); + Sjavac service = new IdleResetSjavac( + new NoopJavacService(), + new Terminable() { + public void shutdown(String msg) { + // Record the idle timeout time + log("Timeout detected"); + timeoutTimestamp.set(System.currentTimeMillis()); + } + }, + TIMEOUT_MS); + + // Make sure it didn't timeout immediately + if (timeoutTimestamp.get() != -1) + throw new AssertionError("Premature timeout detected."); + + // Call various methods and wait less than TIMEOUT_MS in between + Thread.sleep(TIMEOUT_MS - 1000); + log("Getting sys info"); + service.getSysInfo(); + + Thread.sleep(TIMEOUT_MS - 1000); + log("Getting sys info"); + service.getSysInfo(); + + if (timeoutTimestamp.get() != -1) + throw new AssertionError("Premature timeout detected."); + + Thread.sleep(TIMEOUT_MS - 1000); + log("Compiling"); + service.compile("", + "", + new String[0], + Collections.emptyList(), + Collections.emptySet(), + Collections.emptySet()); + + Thread.sleep(TIMEOUT_MS - 1000); + log("Compiling"); + service.compile("", + "", + new String[0], + Collections.emptyList(), + Collections.emptySet(), + Collections.emptySet()); + + if (timeoutTimestamp.get() != -1) + throw new AssertionError("Premature timeout detected."); + + long expectedTimeout = System.currentTimeMillis() + TIMEOUT_MS; + + // Wait for actual timeout + log("Awaiting idle timeout"); + Thread.sleep(TIMEOUT_MS + 1000); + + // Check result + if (timeoutTimestamp.get() == -1) + throw new AssertionError("Timeout never occurred"); + + long error = Math.abs(expectedTimeout - timeoutTimestamp.get()); + log("Timeout error: " + error + " ms"); + if (error > TIMEOUT_MS * .1) + throw new AssertionError("Error too big"); + + log("Shutting down"); + service.shutdown(); + } + + private static void log(String msg) { + long logTime = System.currentTimeMillis() - TEST_START; + System.out.printf("After %5d ms: %s%n", logTime, msg); + } + + private static class NoopJavacService implements Sjavac { + @Override + public SysInfo getSysInfo() { + // Attempt to trigger idle timeout during a call by sleeping + try { + Thread.sleep(TIMEOUT_MS + 1000); + } catch (InterruptedException e) { + } + return null; + } + @Override + public void shutdown() { + } + @Override + public CompilationResult compile(String protocolId, + String invocationId, + String[] args, + List explicitSources, + Set sourcesToCompile, + Set visibleSources) { + return null; + } + @Override + public String serverSettings() { + return ""; + } + } +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/sjavac/OptionDecoding.java --- a/langtools/test/tools/sjavac/OptionDecoding.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/sjavac/OptionDecoding.java Fri Aug 29 11:58:43 2014 -0700 @@ -25,7 +25,7 @@ /* * @test - * @bug 8035063 + * @bug 8035063 8054465 * @summary Tests decoding of String[] into Options. * * @build Wrapper @@ -192,13 +192,16 @@ assertEquals(17, options.getNumCores()); assertEquals("debug", options.getLogLevel()); assertEquals(false, options.isDefaultPackagePermitted()); - assertEquals(false, options.isUnidentifiedArtifactPermitted()); + assertEquals(false, options.areUnidentifiedArtifactsPermitted()); + assertEquals(false, options.isUnidentifiedArtifactPermitted(Paths.get("bar.txt").toFile().getAbsolutePath())); options = Options.parseArgs("--permit-unidentified-artifacts", + "--permit-artifact=bar.txt", "--permit-sources-without-package"); assertEquals("info", options.getLogLevel()); assertEquals(true, options.isDefaultPackagePermitted()); - assertEquals(true, options.isUnidentifiedArtifactPermitted()); + assertEquals(true, options.areUnidentifiedArtifactsPermitted()); + assertEquals(true, options.isUnidentifiedArtifactPermitted(Paths.get("bar.txt").toFile().getAbsolutePath())); } // Test server configuration options diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/sjavac/PooledExecution.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/sjavac/PooledExecution.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,160 @@ +/* + * 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. + */ + +/* + * @test + * @bug 8044131 + * @summary Makes sure sjavac poolsize option is honored. + * @build Wrapper + * @run main Wrapper PooledExecution + */ +import java.io.File; +import java.net.URI; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicInteger; + +import com.sun.tools.sjavac.comp.PooledSjavac; +import com.sun.tools.sjavac.server.CompilationResult; +import com.sun.tools.sjavac.server.Sjavac; +import com.sun.tools.sjavac.server.SysInfo; + + +public class PooledExecution { + + public static void main(String[] args) throws InterruptedException { + new PooledExecutionTest().runTest(); + } + + static class PooledExecutionTest { + + final int POOL_SIZE = 15; + final int NUM_REQUESTS = 100; + + // Number of tasks that has not yet started + CountDownLatch leftToStart = new CountDownLatch(NUM_REQUESTS); + + // Highest number of concurrently active request seen + int highWaterMark = 0; + + public void runTest() throws InterruptedException { + ConcurrencyLoggingService loggingService = new ConcurrencyLoggingService(); + final Sjavac service = new PooledSjavac(loggingService, POOL_SIZE); + + // Keep track of the number of finished tasks so we can make sure all + // tasks finishes gracefully upon shutdown. + Thread[] tasks = new Thread[NUM_REQUESTS]; + final AtomicInteger tasksFinished = new AtomicInteger(0); + + for (int i = 0; i < NUM_REQUESTS; i++) { + tasks[i] = new Thread() { + public void run() { + service.compile("", + "", + new String[0], + Collections.emptyList(), + Collections.emptySet(), + Collections.emptySet()); + tasksFinished.incrementAndGet(); + } + }; + tasks[i].start(); + } + + // Wait for all tasks to start (but not necessarily run to completion) + leftToStart.await(); + + // Shutdown before all tasks are completed + System.out.println("Shutting down!"); + service.shutdown(); + + // Wait for all tasks to complete + for (Thread t : tasks) + t.join(); + + if (tasksFinished.get() != NUM_REQUESTS) { + throw new AssertionError(tasksFinished.get() + " out of " + + NUM_REQUESTS + " finished. Broken shutdown?"); + } + + if (highWaterMark > POOL_SIZE) { + throw new AssertionError("Pool size overused: " + highWaterMark + + " used out of " + POOL_SIZE + " allowed."); + } + + // Assuming more than POOL_SIZE requests can be processed within 1 sek: + if (highWaterMark < POOL_SIZE) { + throw new AssertionError("Pool size underused: " + highWaterMark + + " used out of " + POOL_SIZE + " allowed."); + } + } + + + private class ConcurrencyLoggingService implements Sjavac { + + // Keeps track of currently active requests + AtomicInteger activeRequests = new AtomicInteger(0); + + @Override + public CompilationResult compile(String protocolId, + String invocationId, + String[] args, + List explicitSources, + Set sourcesToCompile, + Set visibleSources) { + leftToStart.countDown(); + int numActiveRequests = activeRequests.incrementAndGet(); + System.out.printf("Left to start: %2d / Currently active: %2d%n", + leftToStart.getCount(), + numActiveRequests); + highWaterMark = Math.max(highWaterMark, numActiveRequests); + try { + Thread.sleep(1000); + } catch (InterruptedException ie) { + throw new RuntimeException("Interrupted", ie); + } + activeRequests.decrementAndGet(); + System.out.println("Task completed"); + return null; + } + + @Override + public SysInfo getSysInfo() { + return null; + } + + @Override + public void shutdown() { + } + + @Override + public String serverSettings() { + return ""; + } + } + } +} diff -r aa7ada31eb77 -r 317aad3480c8 langtools/test/tools/sjavac/SJavac.java --- a/langtools/test/tools/sjavac/SJavac.java Fri Aug 29 10:47:32 2014 -0700 +++ b/langtools/test/tools/sjavac/SJavac.java Fri Aug 29 11:58:43 2014 -0700 @@ -25,7 +25,7 @@ /* * @test * @summary Test all aspects of sjavac. - * @bug 8004658 8042441 8042699 + * @bug 8004658 8042441 8042699 8054461 8054474 8054465 * * @build Wrapper * @run main Wrapper SJavac @@ -99,6 +99,9 @@ compileCircularSources(); compileExcludingDependency(); incrementalCompileTestFullyQualifiedRef(); + compileWithAtFile(); + testStateDir(); + testPermittedArtifact(); delete(gensrc); delete(gensrc2); @@ -463,6 +466,98 @@ "bin/javac_state"); } + /** + * Tests @atfile + * @throws Exception If test fails + */ + void compileWithAtFile() throws Exception { + System.out.println("\nTest @atfile with command line content."); + System.out.println("---------------------------------------"); + + delete(gensrc); + delete(gensrc2); + delete(bin); + + populate(gensrc, + "list.txt", + "-if */alfa/omega/A.java\n-if */beta/B.java\ngensrc\n-d bin\n", + "alfa/omega/A.java", + "package alfa.omega; import beta.B; public class A { B b; }", + "beta/B.java", + "package beta; public class B { }", + "beta/C.java", + "broken"); + previous_bin_state = collectState(bin); + compile("@gensrc/list.txt", "--server:portfile=testserver,background=false"); + + Map new_bin_state = collectState(bin); + verifyThatFilesHaveBeenAdded(previous_bin_state, new_bin_state, + "bin/javac_state", + "bin/alfa/omega/A.class", + "bin/beta/B.class"); + } + + /** + * Tests storing javac_state into another directory. + * @throws Exception If test fails + */ + void testStateDir() throws Exception { + System.out.println("\nVerify that --state-dir=bar works."); + System.out.println("----------------------------------"); + + Path bar = defaultfs.getPath("bar"); + Files.createDirectory(bar); + + delete(gensrc); + delete(bin); + delete(bar); + previous_bin_state = collectState(bin); + Map previous_bar_state = collectState(bar); + + populate(gensrc, + "alfa/omega/A.java", + "package alfa.omega; public class A { }"); + + compile("--state-dir=bar", "-src", "gensrc", "-d", "bin", serverArg); + + Map new_bin_state = collectState(bin); + verifyThatFilesHaveBeenAdded(previous_bin_state, new_bin_state, + "bin/alfa/omega/A.class"); + Map new_bar_state = collectState(bar); + verifyThatFilesHaveBeenAdded(previous_bar_state, new_bar_state, + "bar/javac_state"); + } + + /** + * Test white listing of external artifacts inside the destination dir. + * @throws Exception If test fails + */ + void testPermittedArtifact() throws Exception { + System.out.println("\nVerify that --permit-artifact=bar works."); + System.out.println("-------------------------------------------"); + + delete(gensrc); + delete(bin); + + previous_bin_state = collectState(bin); + + populate(gensrc, + "alfa/omega/A.java", + "package alfa.omega; public class A { }"); + + populate(bin, + "alfa/omega/AA.class", + "Ugh, a messy build system (tobefixed) wrote this class file, sjavac must not delete it."); + + compile("--log=debug", "--permit-artifact=bin/alfa/omega/AA.class", "-src", "gensrc", "-d", "bin", serverArg); + + Map new_bin_state = collectState(bin); + verifyThatFilesHaveBeenAdded(previous_bin_state, new_bin_state, + "bin/alfa/omega/A.class", + "bin/alfa/omega/AA.class", + "bin/javac_state"); + } + void removeFrom(Path dir, String... args) throws IOException { for (String filename : args) { Path p = dir.resolve(filename); diff -r aa7ada31eb77 -r 317aad3480c8 make/Main.gmk --- a/make/Main.gmk Fri Aug 29 10:47:32 2014 -0700 +++ b/make/Main.gmk Fri Aug 29 11:58:43 2014 -0700 @@ -234,7 +234,8 @@ +($(CD) $(NASHORN_TOPDIR)/make && $(MAKE) $(MAKE_ARGS) -f BuildNashorn.gmk all) # Creates the jar files (rt.jar resources.jar etc) -main-jars: +# this depends on all modules built +main-jars: exploded-image +($(CD) $(JDK_TOPDIR)/make && $(MAKE) $(MAKE_ARGS) -f CreateJars.gmk) # Creates the images (j2sdk-image j2re-image etc) diff -r aa7ada31eb77 -r 317aad3480c8 make/common/IdlCompilation.gmk --- a/make/common/IdlCompilation.gmk Fri Aug 29 10:47:32 2014 -0700 +++ b/make/common/IdlCompilation.gmk Fri Aug 29 11:58:43 2014 -0700 @@ -60,7 +60,7 @@ $(RM) -rf $3/$$($4_TMPDIR) $(MKDIR) -p $(dir $5) $(ECHO) $(LOG_INFO) Compiling IDL $(patsubst $2/%,%,$4) - $8 -td $3/$$($4_TMPDIR) \ + LC_ALL=C $8 -td $3/$$($4_TMPDIR) \ -i $2/org/omg/CORBA \ -i $2/org/omg/PortableInterceptor \ -i $2/org/omg/PortableServer \ diff -r aa7ada31eb77 -r 317aad3480c8 make/common/NativeCompilation.gmk --- a/make/common/NativeCompilation.gmk Fri Aug 29 10:47:32 2014 -0700 +++ b/make/common/NativeCompilation.gmk Fri Aug 29 11:58:43 2014 -0700 @@ -46,6 +46,12 @@ ARCHIVING_MSG= endif +ifeq ($(OPENJDK_BUILD_OS_ENV), windows.cygwin) + UNIX_PATH_PREFIX := /cygdrive +else ifeq ($(OPENJDK_BUILD_OS_ENV), windows.msys) + UNIX_PATH_PREFIX := +endif + define add_native_source # param 1 = BUILD_MYPACKAGE # parma 2 = the source file name (..../alfa.c or .../beta.cpp) @@ -120,7 +126,7 @@ && $(SED) -e '/^Note: including file:/!d' \ -e 's|Note: including file: *||' \ -e 's|\\|/|g' \ - -e 's|^\([a-zA-Z]\):|/cygdrive/\1|g' \ + -e 's|^\([a-zA-Z]\):|$(UNIX_PATH_PREFIX)/\1|g' \ -e '/$(subst /,\/,$(TOPDIR))/!d' \ -e 's|$$$$| \\|g' \ $$($1_$2_DEP).raw) > $$($1_$2_DEP) diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/.hgtags --- a/nashorn/.hgtags Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/.hgtags Fri Aug 29 11:58:43 2014 -0700 @@ -260,3 +260,4 @@ 49d7a2a66ae6b70fee367e2ceb29d0c20f8be01b jdk9-b24 b33633fc10c5bffd39d3492ed2602dadd8d44642 jdk9-b25 ed60a4e9dd35dcabb9b24e90434f5f615d988981 jdk9-b26 +221a84ef44c00335b563d92f470efaf8162b471e jdk9-b27 diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/Main.java --- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/Main.java Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/Main.java Fri Aug 29 11:58:43 2014 -0700 @@ -32,6 +32,7 @@ import java.io.PrintWriter; import jdk.internal.org.objectweb.asm.ClassReader; import jdk.internal.org.objectweb.asm.ClassWriter; +import jdk.internal.org.objectweb.asm.Opcodes; import jdk.internal.org.objectweb.asm.util.CheckClassAdapter; /** @@ -39,6 +40,11 @@ * */ public class Main { + /** + * ASM version to be used by nasgen tool. + */ + public static final int ASM_VERSION = Opcodes.ASM5; + private static final boolean DEBUG = Boolean.getBoolean("nasgen.debug"); private interface ErrorReporter { diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java --- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java Fri Aug 29 11:58:43 2014 -0700 @@ -32,7 +32,6 @@ import static jdk.internal.org.objectweb.asm.Opcodes.ALOAD; import static jdk.internal.org.objectweb.asm.Opcodes.ANEWARRAY; import static jdk.internal.org.objectweb.asm.Opcodes.ARETURN; -import static jdk.internal.org.objectweb.asm.Opcodes.ASM4; import static jdk.internal.org.objectweb.asm.Opcodes.ASTORE; import static jdk.internal.org.objectweb.asm.Opcodes.BALOAD; import static jdk.internal.org.objectweb.asm.Opcodes.BASTORE; @@ -96,7 +95,7 @@ private final Type[] argumentTypes; MethodGenerator(final MethodVisitor mv, final int access, final String name, final String descriptor) { - super(ASM4, mv); + super(Main.ASM_VERSION, mv); this.access = access; this.name = name; this.descriptor = descriptor; diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/NullVisitor.java --- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/NullVisitor.java Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/NullVisitor.java Fri Aug 29 11:58:43 2014 -0700 @@ -29,7 +29,6 @@ import jdk.internal.org.objectweb.asm.ClassVisitor; import jdk.internal.org.objectweb.asm.FieldVisitor; import jdk.internal.org.objectweb.asm.MethodVisitor; -import jdk.internal.org.objectweb.asm.Opcodes; /** * A visitor that does nothing on visitXXX calls. @@ -37,7 +36,7 @@ */ public class NullVisitor extends ClassVisitor { NullVisitor() { - super(Opcodes.ASM4); + super(Main.ASM_VERSION); } @Override @@ -47,7 +46,7 @@ final String desc, final String signature, final String[] exceptions) { - return new MethodVisitor(Opcodes.ASM4) { + return new MethodVisitor(Main.ASM_VERSION) { @Override public AnnotationVisitor visitAnnotationDefault() { return new NullAnnotationVisitor(); @@ -67,7 +66,7 @@ final String desc, final String signature, final Object value) { - return new FieldVisitor(Opcodes.ASM4) { + return new FieldVisitor(Main.ASM_VERSION) { @Override public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) { return new NullAnnotationVisitor(); @@ -82,7 +81,7 @@ private static class NullAnnotationVisitor extends AnnotationVisitor { NullAnnotationVisitor() { - super(Opcodes.ASM4); + super(Main.ASM_VERSION); } } } diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java --- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java Fri Aug 29 11:58:43 2014 -0700 @@ -55,7 +55,7 @@ private String javaClassName; ScriptClassInfoCollector(final ClassVisitor visitor) { - super(Opcodes.ASM4, visitor); + super(Main.ASM_VERSION, visitor); } ScriptClassInfoCollector() { @@ -80,7 +80,7 @@ public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) { final AnnotationVisitor delegateAV = super.visitAnnotation(desc, visible); if (SCRIPT_CLASS_ANNO_DESC.equals(desc)) { - return new AnnotationVisitor(Opcodes.ASM4, delegateAV) { + return new AnnotationVisitor(Main.ASM_VERSION, delegateAV) { @Override public void visit(final String name, final Object value) { if ("value".equals(name)) { @@ -98,7 +98,7 @@ public FieldVisitor visitField(final int fieldAccess, final String fieldName, final String fieldDesc, final String signature, final Object value) { final FieldVisitor delegateFV = super.visitField(fieldAccess, fieldName, fieldDesc, signature, value); - return new FieldVisitor(Opcodes.ASM4, delegateFV) { + return new FieldVisitor(Main.ASM_VERSION, delegateFV) { @Override public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) { final AnnotationVisitor delegateAV = super.visitAnnotation(descriptor, visible); @@ -117,7 +117,7 @@ addScriptMember(memInfo); - return new AnnotationVisitor(Opcodes.ASM4, delegateAV) { + return new AnnotationVisitor(Main.ASM_VERSION, delegateAV) { // These could be "null" if values are not suppiled, // in which case we have to use the default values. private String name; @@ -180,7 +180,7 @@ final MethodVisitor delegateMV = super.visitMethod(methodAccess, methodName, methodDesc, signature, exceptions); - return new MethodVisitor(Opcodes.ASM4, delegateMV) { + return new MethodVisitor(Main.ASM_VERSION, delegateMV) { @Override public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) { @@ -201,7 +201,7 @@ addScriptMember(memInfo); - return new AnnotationVisitor(Opcodes.ASM4, delegateAV) { + return new AnnotationVisitor(Main.ASM_VERSION, delegateAV) { // These could be "null" if values are not suppiled, // in which case we have to use the default values. private String name; diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java --- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java Fri Aug 29 11:58:43 2014 -0700 @@ -73,7 +73,7 @@ private boolean staticInitFound; ScriptClassInstrumentor(final ClassVisitor visitor, final ScriptClassInfo sci) { - super(Opcodes.ASM4, visitor); + super(Main.ASM_VERSION, visitor); if (sci == null) { throw new IllegalArgumentException("Null ScriptClassInfo, is the class annotated?"); } @@ -103,7 +103,7 @@ final FieldVisitor delegateFV = super.visitField(fieldAccess, fieldName, fieldDesc, signature, value); - return new FieldVisitor(Opcodes.ASM4, delegateFV) { + return new FieldVisitor(Main.ASM_VERSION, delegateFV) { @Override public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) { if (ScriptClassInfo.annotations.containsKey(desc)) { @@ -140,7 +140,7 @@ final MethodGenerator delegateMV = new MethodGenerator(super.visitMethod(methodAccess, methodName, methodDesc, signature, exceptions), methodAccess, methodName, methodDesc); - return new MethodVisitor(Opcodes.ASM4, delegateMV) { + return new MethodVisitor(Main.ASM_VERSION, delegateMV) { @Override public void visitInsn(final int opcode) { // call $clinit$ just before return from diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/docs/genshelldoc.js --- a/nashorn/docs/genshelldoc.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/docs/genshelldoc.js Fri Aug 29 11:58:43 2014 -0700 @@ -1,21 +1,21 @@ /* * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. - * + * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). - * + * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * + * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. @@ -61,7 +61,7 @@ for each (opt in Options.validOptions) { -var isTimezone = (opt.type == "timezone"); +var isTimezone = (opt.type == "timezone"); var defValue = opt.defaultValue; if (defValue == null) { defValue = "<none>"; diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/docs/source/importpackageclass.js --- a/nashorn/docs/source/importpackageclass.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/docs/source/importpackageclass.js Fri Aug 29 11:58:43 2014 -0700 @@ -1,21 +1,21 @@ /* * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR @@ -32,7 +32,7 @@ // load compatibility script load("nashorn:mozilla_compat.js"); -// Import Java packages and classes +// Import Java packages and classes // like import package.*; in Java importPackage(java.awt); // like import java.awt.Frame in Java diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/docs/source/javaarray.js --- a/nashorn/docs/source/javaarray.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/docs/source/javaarray.js Fri Aug 29 11:58:43 2014 -0700 @@ -1,21 +1,21 @@ /* * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/docs/source/javaextend.js --- a/nashorn/docs/source/javaextend.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/docs/source/javaextend.js Fri Aug 29 11:58:43 2014 -0700 @@ -1,21 +1,21 @@ /* * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/docs/source/javaimporter.js --- a/nashorn/docs/source/javaimporter.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/docs/source/javaimporter.js Fri Aug 29 11:58:43 2014 -0700 @@ -1,21 +1,21 @@ /* * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/docs/source/javatypes.js --- a/nashorn/docs/source/javatypes.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/docs/source/javatypes.js Fri Aug 29 11:58:43 2014 -0700 @@ -1,21 +1,21 @@ /* * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/docs/source/overload.js --- a/nashorn/docs/source/overload.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/docs/source/overload.js Fri Aug 29 11:58:43 2014 -0700 @@ -1,21 +1,21 @@ /* * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR @@ -31,6 +31,6 @@ var out = java.lang.System.out; -// select a particular print function +// select a particular print function out["println(java.lang.Object)"]("hello"); diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/docs/source/runnable.js --- a/nashorn/docs/source/runnable.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/docs/source/runnable.js Fri Aug 29 11:58:43 2014 -0700 @@ -1,21 +1,21 @@ /* * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/docs/source/samfunc.js --- a/nashorn/docs/source/samfunc.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/docs/source/samfunc.js Fri Aug 29 11:58:43 2014 -0700 @@ -1,21 +1,21 @@ /* * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/docs/source/test.js --- a/nashorn/docs/source/test.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/docs/source/test.js Fri Aug 29 11:58:43 2014 -0700 @@ -1,21 +1,21 @@ /* * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/make/build.xml --- a/nashorn/make/build.xml Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/make/build.xml Fri Aug 29 11:58:43 2014 -0700 @@ -128,6 +128,7 @@ + @@ -519,6 +520,8 @@ + + @@ -582,6 +585,8 @@ + + diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/make/project.properties --- a/nashorn/make/project.properties Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/make/project.properties Fri Aug 29 11:58:43 2014 -0700 @@ -28,8 +28,8 @@ # source and target levels build.compiler=modern -javac.source=1.7 -javac.target=1.7 +javac.source=1.8 +javac.target=1.8 # nashorn version information nashorn.version=0.1 @@ -202,7 +202,7 @@ # list of test262 test dirs to be excluded test262-test-sys-prop.test.js.exclude.dir=\ ${test262.suite.dir}/intl402/ \ - ${test262.suite.dir}/bestPractice/ + ${test262.suite.dir}/bestPractice/ test262-test-sys-prop.test.failed.list.file=${build.dir}/test/failedTests @@ -217,7 +217,7 @@ ${test262.dir}/test/harness/sta.js # testmarkdown test root -testmarkdown-test-sys-prop.test.js.roots=${testmarkdown.dir} +testmarkdown-test-sys-prop.test.js.roots=${testmarkdown.dir} # execute testmarkdown tests in shared nashorn context or not? testmarkdown-test-sys-prop.test.js.shared.context=false @@ -227,7 +227,7 @@ ${test.script.dir}${file.separator}markdown.js # testjfx test root -testjfx-test-sys-prop.test.js.roots=${testjfx.dir} +testjfx-test-sys-prop.test.js.roots=${testjfx.dir} # execute testjfx tests in shared nashorn context or not? testjfx-test-sys-prop.test.js.shared.context=false @@ -257,7 +257,7 @@ ${nashorn.internal.tests.jar}:\ ${nashorn.api.tests.jar} -src.dir=src +src.dir=src/jdk.scripting.nashorn/share/classes test.src.dir=test/src # -Xmx is used for all tests, -Xms only for octane benchmark diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/array_mapreduce.js --- a/nashorn/samples/array_mapreduce.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/array_mapreduce.js Fri Aug 29 11:58:43 2014 -0700 @@ -1,21 +1,21 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR @@ -31,9 +31,9 @@ // Usage: jjs array_mapreduce.js -// Many Array.prototype functions such as map, +// Many Array.prototype functions such as map, // filter, reduce, reduceRight, every, some are generic. -// These functions accept ECMAScript array as well as +// These functions accept ECMAScript array as well as // many array-like objects including java arrays. // So, you can do map/filter/reduce with Java streams or // you can also use Array.prototype functions as below. @@ -73,6 +73,6 @@ // print sum of squares of the random numbers print("Square sum:", reduce.call( - map.call(jarr, function(x) x*x), + map.call(jarr, function(x) x*x), function(x, y) x + y) ); diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/astviewer.js --- a/nashorn/samples/astviewer.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/astviewer.js Fri Aug 29 11:58:43 2014 -0700 @@ -2,22 +2,22 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR @@ -82,7 +82,7 @@ // load parser.js from nashorn resources load("nashorn:parser.js"); -// read the full content of the file and parse it +// read the full content of the file and parse it // to get AST of the script specified var ast = parse(readFully(sourceName)); diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/barchart_weather.js --- a/nashorn/samples/barchart_weather.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/barchart_weather.js Fri Aug 29 11:58:43 2014 -0700 @@ -2,22 +2,22 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/call_lambda.js --- a/nashorn/samples/call_lambda.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/call_lambda.js Fri Aug 29 11:58:43 2014 -0700 @@ -1,21 +1,21 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/counters.js --- a/nashorn/samples/counters.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/counters.js Fri Aug 29 11:58:43 2014 -0700 @@ -1,21 +1,21 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/dirname.js --- a/nashorn/samples/dirname.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/dirname.js Fri Aug 29 11:58:43 2014 -0700 @@ -1,21 +1,21 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/disassemble.js --- a/nashorn/samples/disassemble.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/disassemble.js Fri Aug 29 11:58:43 2014 -0700 @@ -1,21 +1,21 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR @@ -33,7 +33,7 @@ // Simple .class disassembler that uses bundled ObjectWeb ASM // classes in jdk8. WARNING: Bundled ObjectWeb ASM classes are -// not part of official jdk8 API. It can be changed/removed +// not part of official jdk8 API. It can be changed/removed // without notice. So, this script is brittle by design! // This example demonstrates passing arguments to script diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/engine/accessvar.js --- a/nashorn/samples/engine/accessvar.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/engine/accessvar.js Fri Aug 29 11:58:43 2014 -0700 @@ -1,21 +1,21 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/engine/callfunc.js --- a/nashorn/samples/engine/callfunc.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/engine/callfunc.js Fri Aug 29 11:58:43 2014 -0700 @@ -1,21 +1,21 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR @@ -29,7 +29,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// simple example showing how to call a global script +// simple example showing how to call a global script // function from caller var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager"); @@ -42,7 +42,7 @@ engine.eval("function func(name) { print('I am func, hello ' + name) }"); // invoke functions, methods of code evaluated by engine -// from javax.script.Invocable interface. But, hey, +// from javax.script.Invocable interface. But, hey, // calling code is JavaScript and don't worry about types :) engine.invokeFunction("func", "Nashorn"); diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/engine/callmethod.js --- a/nashorn/samples/engine/callmethod.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/engine/callmethod.js Fri Aug 29 11:58:43 2014 -0700 @@ -2,22 +2,22 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR @@ -55,7 +55,7 @@ CODE); // invoke methods of an object in script world -// from javax.script.Invocable interface. But, hey, +// from javax.script.Invocable interface. But, hey, // calling code is JavaScript and don't worry about types :) // get that script object on which to call a method diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/engine/exposevar.js --- a/nashorn/samples/engine/exposevar.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/engine/exposevar.js Fri Aug 29 11:58:43 2014 -0700 @@ -1,21 +1,21 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/engine/foreignobject.js --- a/nashorn/samples/engine/foreignobject.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/engine/foreignobject.js Fri Aug 29 11:58:43 2014 -0700 @@ -2,22 +2,22 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR @@ -54,7 +54,7 @@ // the class jdk.nashorn.api.scripting.ScriptObjectMirror // But nashorn's dynalink linker can treat these objects // specially to support natural script syntax to access.. -// In Java code, you need to use ScriptObjectMirror's +// In Java code, you need to use ScriptObjectMirror's // methods though. Once again, script world is simpler :-) var foreignObj = engine.get("obj"); diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/engine/hello.js --- a/nashorn/samples/engine/hello.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/engine/hello.js Fri Aug 29 11:58:43 2014 -0700 @@ -1,21 +1,21 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/engine/interface.js --- a/nashorn/samples/engine/interface.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/engine/interface.js Fri Aug 29 11:58:43 2014 -0700 @@ -2,22 +2,22 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR @@ -50,7 +50,7 @@ // create Java interface object whose methods are // implemented by script functions. This is from -// javax.script.Invocable. But we are in JS world, +// javax.script.Invocable. But we are in JS world, // don't worry about types :) var Runnable = Java.type("java.lang.Runnable"); diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/engine/interface2.js --- a/nashorn/samples/engine/interface2.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/engine/interface2.js Fri Aug 29 11:58:43 2014 -0700 @@ -2,22 +2,22 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/engine/lambda_as_func.js --- a/nashorn/samples/engine/lambda_as_func.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/engine/lambda_as_func.js Fri Aug 29 11:58:43 2014 -0700 @@ -1,21 +1,21 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/env.js --- a/nashorn/samples/env.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/env.js Fri Aug 29 11:58:43 2014 -0700 @@ -2,22 +2,22 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR @@ -31,8 +31,8 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// In nashorn -scripting mode, -// "$ENV" object exposes process +// In nashorn -scripting mode, +// "$ENV" object exposes process // environment variables print($ENV.PATH); diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/expression_closure.js --- a/nashorn/samples/expression_closure.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/expression_closure.js Fri Aug 29 11:58:43 2014 -0700 @@ -1,21 +1,21 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/filebrowser.js --- a/nashorn/samples/filebrowser.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/filebrowser.js Fri Aug 29 11:58:43 2014 -0700 @@ -2,22 +2,22 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/fileline.js --- a/nashorn/samples/fileline.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/fileline.js Fri Aug 29 11:58:43 2014 -0700 @@ -1,21 +1,21 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/find_nonfinals.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/samples/find_nonfinals.js Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * Nashorn project uses "final" modifier for method parameters + * (like 'val' of Scala). This tool finds method parameters that + * miss final modifier. + */ + +// Usage: jjs -J-Djava.ext.dirs= find_nonfinals.js + +var Class = Java.type("java.lang.Class"); +var System = Java.type("java.lang.System"); +var File = Java.type("java.io.File"); +var JarFile = Java.type("java.util.jar.JarFile"); +var Modifier = Java.type("java.lang.reflect.Modifier"); + +// locate nashorn.jar from java.ext.dirs +function findNashorn() { + var paths = System.getProperty("java.ext.dirs").split(':'); + for each (var p in paths) { + var nashorn = p + File.separator + "nashorn.jar"; + if (new File(nashorn).exists()) { + return nashorn; + } + } +} + +// analyze a single Class and print info on non-final parameters +function analyzeClass(cls) { + var methods = cls.getDeclaredMethods(); + for each (var method in methods) { + // this requires -parameters option when compiling java sources + var params = method.parameters; + for each (var p in params) { + var modifiers = p.modifiers; + if (!Modifier.isFinal(modifiers)) { + if (! method.name.startsWith("access$")) { + print(method); + print(" ->", p); + } + } + } + } +} + +var jarFile = findNashorn(); +// load each class and use reflection to analyze each Class +new JarFile(jarFile).stream().forEach( + function(entry) { + var name = entry.name; + if (name.endsWith(".class")) { + var clsName = name.substring(0, name.lastIndexOf('.class')); + clsName = clsName.replace(/\//g, '.'); + var cls = Class.forName(clsName); + analyzeClass(cls); + } + } +) diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/fizzbuzz.js --- a/nashorn/samples/fizzbuzz.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/fizzbuzz.js Fri Aug 29 11:58:43 2014 -0700 @@ -1,21 +1,21 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/for_each.js --- a/nashorn/samples/for_each.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/for_each.js Fri Aug 29 11:58:43 2014 -0700 @@ -1,21 +1,21 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR @@ -42,7 +42,7 @@ var arr = new JArray(10); // store squares as values -for (i in arr) +for (i in arr) arr[i] = i*i; // for .. each on java arrays @@ -57,7 +57,7 @@ print("System properties"); for each (p in System.properties.entrySet()) { print(p.key, "=", p.value); -} +} // print process environment vars as name = value pairs print("Process environment"); diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/gaussian_random.js --- a/nashorn/samples/gaussian_random.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/gaussian_random.js Fri Aug 29 11:58:43 2014 -0700 @@ -1,21 +1,21 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR @@ -37,7 +37,7 @@ var r = new Random(); // expression closure (see expression_closure.js as well) -// passed as lambda double generator. "print" passed as +// passed as lambda double generator. "print" passed as // double consumer lambda to 'forEach' method. DoubleStream diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/gaussian_random_bind.js --- a/nashorn/samples/gaussian_random_bind.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/gaussian_random_bind.js Fri Aug 29 11:58:43 2014 -0700 @@ -1,21 +1,21 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR @@ -34,7 +34,7 @@ var Random = Java.type("java.util.Random"); var DoubleStream = Java.type("java.util.stream.DoubleStream"); -// function as lambda double generator. "print" passed as +// function as lambda double generator. "print" passed as // double consumer lambda to 'forEach' method. // Function.prototype.bind used to attach 'state' for the // generator function. diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/gutenberg.js --- a/nashorn/samples/gutenberg.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/gutenberg.js Fri Aug 29 11:58:43 2014 -0700 @@ -2,22 +2,22 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR @@ -69,7 +69,7 @@ // capture title, description now inItem = true; } - + if (inItem) { switch (local) { case 'title': diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/heredoc.js --- a/nashorn/samples/heredoc.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/heredoc.js Fri Aug 29 11:58:43 2014 -0700 @@ -2,22 +2,22 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR @@ -38,14 +38,14 @@ var sender = "Buffy the Vampire Slayer"; var recipient = "Spike"; - + print(<"); exit(1); } - + // Java types used var File = Java.type("java.io.File"); var Files = Java.type("java.nio.file.Files"); @@ -48,7 +48,7 @@ var Tree = Java.type("com.sun.source.tree.Tree"); var TreeScanner = Java.type("com.sun.source.util.TreeScanner"); var VariableTree = Java.type("com.sun.source.tree.VariableTree"); - + // count "foo"-s in the given .java files function countFoo() { // get the system compiler tool @@ -63,7 +63,7 @@ // subclass SimpleTreeVisitor - to count variables called "foo" var FooCounterVisitor = Java.extend(TreeScanner); var fooCount = 0; - + var visitor = new FooCounterVisitor() { visitVariable: function (node, p) { if (node.name.toString() == "foo") { @@ -71,13 +71,13 @@ } } } - + for each (var cu in task.parse()) { cu.accept(visitor, null); } return fooCount; } - + // for each ".java" file in directory (recursively) count "foo". function main(dir) { var totalCount = 0; @@ -99,5 +99,5 @@ }); print("Total foo count: " + totalCount); } - + main(new File(arguments[0])); diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/javaimporter.js --- a/nashorn/samples/javaimporter.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/javaimporter.js Fri Aug 29 11:58:43 2014 -0700 @@ -1,21 +1,21 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR @@ -34,14 +34,14 @@ function readTextFromURL(url) { - // equivalent to - // + // equivalent to + // // import java.io.*; // import java.net.*; // import java.lang.StringBuffer; // // only inside the 'with' statement - with (new JavaImporter(java.io, + with (new JavaImporter(java.io, java.net, java.lang.StringBuilder)) { var buf = new StringBuilder(); diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/javalist.js --- a/nashorn/samples/javalist.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/javalist.js Fri Aug 29 11:58:43 2014 -0700 @@ -1,21 +1,21 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/javamap.js --- a/nashorn/samples/javamap.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/javamap.js Fri Aug 29 11:58:43 2014 -0700 @@ -1,21 +1,21 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR @@ -45,7 +45,7 @@ print(map['js']); print(map.js); -// also assign new key-value pair +// also assign new key-value pair // as 'property-value' map['language'] = 'java'; print(map.get("language")); diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/javashell.js --- a/nashorn/samples/javashell.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/javashell.js Fri Aug 29 11:58:43 2014 -0700 @@ -2,22 +2,22 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR @@ -130,7 +130,7 @@ // generate unique name function uniqueName() { var now = LocalDateTime.now().toString(); - // replace unsafe chars with '_' + // replace unsafe chars with '_' return "JavaShell" + now.replace(/-|:|\./g, '_'); } diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/jsadapter_dom.js --- a/nashorn/samples/jsadapter_dom.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/jsadapter_dom.js Fri Aug 29 11:58:43 2014 -0700 @@ -2,22 +2,22 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR @@ -33,7 +33,7 @@ // Simple example that demonstrates reading XML Rss feed // to generate a HTML file from script and show it by browser -// Uses XML DOM parser and DOM element wrapped by script +// Uses XML DOM parser and DOM element wrapped by script // "proxy" (JSAdapter constructor) // Java classes used @@ -78,7 +78,7 @@ var node = nodeList.item(i); if (node.nodeType == TEXT_NODE) { text += node.nodeValue; - } + } } return text; diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/jsobj_example.js --- a/nashorn/samples/jsobj_example.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/jsobj_example.js Fri Aug 29 11:58:43 2014 -0700 @@ -1,21 +1,21 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR @@ -33,7 +33,7 @@ var AbstractJSObject = Java.type("jdk.nashorn.api.scripting.AbstractJSObject"); -// JSObject example that uses a map for properties and +// JSObject example that uses a map for properties and // falls back to with methods on a java object (for missing // properties @@ -49,7 +49,7 @@ return function() { var a = arguments; switch (a.length) { - case 0: return fallback[name](); + case 0: return fallback[name](); case 1: return fallback[name](a[0]); case 2: return fallback[name](a[0], a[1]); case 3: return fallback[name](a[0], a[1], a[2]); diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/jsobject.js --- a/nashorn/samples/jsobject.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/jsobject.js Fri Aug 29 11:58:43 2014 -0700 @@ -2,22 +2,22 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/jsobject_mapreduce.js --- a/nashorn/samples/jsobject_mapreduce.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/jsobject_mapreduce.js Fri Aug 29 11:58:43 2014 -0700 @@ -2,22 +2,22 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR @@ -31,9 +31,9 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// Many Array.prototype functions such as map, +// Many Array.prototype functions such as map, // filter, reduce, reduceRight, every, some are generic. -// These functions accept ECMAScript array as well as +// These functions accept ECMAScript array as well as // many array-like objects including JSObjects. // See also http://en.wikipedia.org/wiki/MapReduce @@ -57,6 +57,6 @@ // print sum of squares of the random numbers print("Square sum:", reduce.call( - map.call(buf, function(x) x*x), + map.call(buf, function(x) x*x), function(x, y) x + y) ); diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/jsonviewer.js --- a/nashorn/samples/jsonviewer.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/jsonviewer.js Fri Aug 29 11:58:43 2014 -0700 @@ -4,22 +4,22 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR @@ -52,8 +52,8 @@ // read text content of a URL function readTextFromURL(url) { - // equivalent to - // + // equivalent to + // // import java.io.*; // import java.net.*; // import java.lang.StringBuffer; diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/letter.js --- a/nashorn/samples/letter.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/letter.js Fri Aug 29 11:58:43 2014 -0700 @@ -2,22 +2,22 @@ /* * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR @@ -43,7 +43,7 @@ // JavaScript style line comment is ok too. print(< (stack.js:52) +// at g (stack.js:37) +// at f (stack.js:41) +// at (stack.js:52) try { f(); diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/try_with_resource.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/samples/try_with_resource.js Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* This sample implements Java-like try..with..resource construct for nashorn */ + +if (arguments.length == 0) { + print("Usage: jjs try_with_resource.js -- "); + exit(1); +} + +// Object.create accepts prototype and properties object +function With(res) { + return Object.create(With.prototype, + { res: { value: res } }); +} + +// reserved words can be used as property names - for example "try" +With.prototype.try = function(callback) { + try { + callback(); + } finally { + this.res.close(); + } +} + +var BufferedReader = Java.type("java.io.BufferedReader"); +var FileReader = Java.type("java.io.FileReader"); + +var r = new BufferedReader(new FileReader(arguments[0])); + +// Java-like try..with..resource +With(r).try(function() { + var s; + while ((s = r.readLine()) != null) { + print(s); + } +}) diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/uniform_random.js --- a/nashorn/samples/uniform_random.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/uniform_random.js Fri Aug 29 11:58:43 2014 -0700 @@ -1,21 +1,21 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/uniq.js --- a/nashorn/samples/uniq.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/uniq.js Fri Aug 29 11:58:43 2014 -0700 @@ -1,21 +1,21 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/uniqs.js --- a/nashorn/samples/uniqs.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/uniqs.js Fri Aug 29 11:58:43 2014 -0700 @@ -1,21 +1,21 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR @@ -31,7 +31,7 @@ // Usage: jjs uniqs.js -- // omit repeated lines and print unique lines -// But this version uses Stream API +// But this version uses Stream API if (arguments.length < 1) { print("Usage: jjs uniqs.js -- "); diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/weather.js --- a/nashorn/samples/weather.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/weather.js Fri Aug 29 11:58:43 2014 -0700 @@ -2,22 +2,22 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/word_histogram.js --- a/nashorn/samples/word_histogram.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/word_histogram.js Fri Aug 29 11:58:43 2014 -0700 @@ -2,22 +2,22 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/zipfs.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/samples/zipfs.js Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +if (arguments.length == 0) { + print("Usage: jjs zipfs.js -- <.zip/.jar file>") + exit(1) +} + +var Files = Java.type("java.nio.file.Files") +var FileSystems = Java.type("java.nio.file.FileSystems") +var FileVisitOption = Java.type("java.nio.file.FileVisitOption") +var Paths = Java.type("java.nio.file.Paths") + +var zipfile = Paths.get(arguments[0]) +var fs = FileSystems.newFileSystem(zipfile, null) +var root = fs.rootDirectories[0] +Files.walk(root, FileVisitOption.FOLLOW_LINKS).forEach( + function(p) (print(p), print(Files.readAttributes(p, "zip:*"))) +) +fs.close() diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/samples/ziplist.js --- a/nashorn/samples/ziplist.js Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/samples/ziplist.js Fri Aug 29 11:58:43 2014 -0700 @@ -1,21 +1,21 @@ /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR @@ -30,7 +30,7 @@ */ if (arguments.length == 0) { - print("Usage: jjs ziplist "); + print("Usage: jjs ziplist -- "); exit(1); } diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ClassFilter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ClassFilter.java Fri Aug 29 11:58:43 2014 -0700 @@ -0,0 +1,41 @@ +/* + * 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 jdk.nashorn.api.scripting; + +/** + * Class filter (optional) to be used by nashorn script engine. + * jsr-223 program embedding nashorn script can set ClassFilter instance + * to be used when an engine instance is created. + */ +public interface ClassFilter { + /** + * Should the Java class of the specified name be exposed to scripts? + * @param className is the fully qualified name of the java class being + * checked. This will not be null. Only non-array class names will be + * passed. + * @return true if the java class can be exposed to scripts false otherwise + */ + public boolean exposeToScripts(String className); +} diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngine.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngine.java Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngine.java Fri Aug 29 11:58:43 2014 -0700 @@ -40,7 +40,6 @@ import java.text.MessageFormat; import java.util.Locale; import java.util.ResourceBundle; - import javax.script.AbstractScriptEngine; import javax.script.Bindings; import javax.script.Compilable; @@ -51,7 +50,6 @@ import javax.script.ScriptEngineFactory; import javax.script.ScriptException; import javax.script.SimpleBindings; - import jdk.nashorn.internal.objects.Global; import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.ErrorManager; @@ -95,9 +93,6 @@ // This is used as "shared" global if above option is true. private final Global global; - // default options passed to Nashorn Options object - private static final String[] DEFAULT_OPTIONS = new String[] { "-doe" }; - // Nashorn script engine error message management private static final String MESSAGES_RESOURCE = "jdk.nashorn.api.scripting.resources.Messages"; @@ -115,11 +110,8 @@ } } - NashornScriptEngine(final NashornScriptEngineFactory factory, final ClassLoader appLoader) { - this(factory, DEFAULT_OPTIONS, appLoader); - } - - NashornScriptEngine(final NashornScriptEngineFactory factory, final String[] args, final ClassLoader appLoader) { + NashornScriptEngine(final NashornScriptEngineFactory factory, final String[] args, final ClassLoader appLoader, final ClassFilter classFilter) { + assert args != null : "null argument array"; this.factory = factory; final Options options = new Options("nashorn"); options.process(args); @@ -131,7 +123,7 @@ @Override public Context run() { try { - return new Context(options, errMgr, appLoader); + return new Context(options, errMgr, appLoader, classFilter); } catch (final RuntimeException e) { if (Context.DEBUG) { e.printStackTrace(); diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java Fri Aug 29 11:58:43 2014 -0700 @@ -135,10 +135,13 @@ return sb.toString(); } + // default options passed to Nashorn script engine + private static final String[] DEFAULT_OPTIONS = new String[] { "-doe" }; + @Override public ScriptEngine getScriptEngine() { try { - return new NashornScriptEngine(this, getAppClassLoader()); + return new NashornScriptEngine(this, DEFAULT_OPTIONS, getAppClassLoader(), null); } catch (final RuntimeException e) { if (Context.DEBUG) { e.printStackTrace(); @@ -152,10 +155,27 @@ * * @param appLoader class loader to be used as script "app" class loader. * @return newly created script engine. + * @throws SecurityException + * if the security manager's {@code checkPermission} + * denies {@code RuntimePermission("nashorn.setConfig")} */ public ScriptEngine getScriptEngine(final ClassLoader appLoader) { - checkConfigPermission(); - return new NashornScriptEngine(this, appLoader); + return newEngine(DEFAULT_OPTIONS, appLoader, null); + } + + /** + * Create a new Script engine initialized by given class filter. + * + * @param classFilter class filter to use. + * @return newly created script engine. + * @throws NullPointerException if {@code classFilter} is {@code null} + * @throws SecurityException + * if the security manager's {@code checkPermission} + * denies {@code RuntimePermission("nashorn.setConfig")} + */ + public ScriptEngine getScriptEngine(final ClassFilter classFilter) { + classFilter.getClass(); // null check + return newEngine(DEFAULT_OPTIONS, getAppClassLoader(), classFilter); } /** @@ -163,10 +183,14 @@ * * @param args arguments array passed to script engine. * @return newly created script engine. + * @throws NullPointerException if {@code args} is {@code null} + * @throws SecurityException + * if the security manager's {@code checkPermission} + * denies {@code RuntimePermission("nashorn.setConfig")} */ public ScriptEngine getScriptEngine(final String... args) { - checkConfigPermission(); - return new NashornScriptEngine(this, args, getAppClassLoader()); + args.getClass(); // null check + return newEngine(args, getAppClassLoader(), null); } /** @@ -175,10 +199,44 @@ * @param args arguments array passed to script engine. * @param appLoader class loader to be used as script "app" class loader. * @return newly created script engine. + * @throws NullPointerException if {@code args} is {@code null} + * @throws SecurityException + * if the security manager's {@code checkPermission} + * denies {@code RuntimePermission("nashorn.setConfig")} */ public ScriptEngine getScriptEngine(final String[] args, final ClassLoader appLoader) { + args.getClass(); // null check + return newEngine(args, appLoader, null); + } + + /** + * Create a new Script engine initialized by given arguments. + * + * @param args arguments array passed to script engine. + * @param appLoader class loader to be used as script "app" class loader. + * @param classFilter class filter to use. + * @return newly created script engine. + * @throws NullPointerException if {@code args} or {@code classFilter} is {@code null} + * @throws SecurityException + * if the security manager's {@code checkPermission} + * denies {@code RuntimePermission("nashorn.setConfig")} + */ + public ScriptEngine getScriptEngine(final String[] args, final ClassLoader appLoader, final ClassFilter classFilter) { + args.getClass(); // null check + classFilter.getClass(); // null check + return newEngine(args, appLoader, classFilter); + } + + private ScriptEngine newEngine(final String[] args, final ClassLoader appLoader, final ClassFilter classFilter) { checkConfigPermission(); - return new NashornScriptEngine(this, args, appLoader); + try { + return new NashornScriptEngine(this, args, appLoader, classFilter); + } catch (final RuntimeException e) { + if (Context.DEBUG) { + e.printStackTrace(); + } + throw e; + } } // -- Internals only below this point diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptObjectMirror.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptObjectMirror.java Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptObjectMirror.java Fri Aug 29 11:58:43 2014 -0700 @@ -715,6 +715,23 @@ return newArgs; } + /** + * Are the given objects mirrors to same underlying object? + * + * @param obj1 first object + * @param obj2 second object + * @return true if obj1 and obj2 are identical script objects or mirrors of it. + */ + public static boolean identical(final Object obj1, final Object obj2) { + final Object o1 = (obj1 instanceof ScriptObjectMirror)? + ((ScriptObjectMirror)obj1).sobj : obj1; + + final Object o2 = (obj2 instanceof ScriptObjectMirror)? + ((ScriptObjectMirror)obj2).sobj : obj2; + + return o1 == o2; + } + // package-privates below this. ScriptObjectMirror(final ScriptObject sobj, final Global global) { diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java Fri Aug 29 11:58:43 2014 -0700 @@ -382,10 +382,6 @@ symbol.setFlags(flags); } - if((isVar || isParam) && compiler.useOptimisticTypes() && compiler.isOnDemandCompilation()) { - compiler.declareLocalSymbol(name); - } - return symbol; } @@ -688,6 +684,22 @@ } @Override + public Node leaveBlock(final Block block) { + // It's not necessary to guard the marking of symbols as locals with this "if"condition for correctness, it's + // just an optimization -- runtime type calculation is not used when the compilation is not an on-demand + // optimistic compilation, so we can skip locals marking then. + if (compiler.useOptimisticTypes() && compiler.isOnDemandCompilation()) { + for (final Symbol symbol: block.getSymbols()) { + if (!symbol.isScope()) { + assert symbol.isVar() || symbol.isParam(); + compiler.declareLocalSymbol(symbol.getName()); + } + } + } + return block; + } + + @Override public Node leaveDELETE(final UnaryNode unaryNode) { final FunctionNode currentFunctionNode = lc.getCurrentFunction(); final boolean strictMode = currentFunctionNode.isStrict(); diff -r aa7ada31eb77 -r 317aad3480c8 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java Fri Aug 29 10:47:32 2014 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java Fri Aug 29 11:58:43 2014 -0700 @@ -56,7 +56,6 @@ import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_OPTIMISTIC; import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_PROGRAM_POINT_SHIFT; import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_SCOPE; -import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_STRICT; import java.io.PrintWriter; import java.util.ArrayDeque; @@ -250,8 +249,6 @@ private final Deque