diff --git a/.hgtags b/.hgtags index bc3091b729f..18cec6f39a5 100644 --- a/.hgtags +++ b/.hgtags @@ -188,3 +188,5 @@ cdaa6122185f9bf512dcd6600f56bfccc4824e8c jdk8-b61 70fa4b11f26522e69b51fd652215f60ce350bac3 jdk8-b64 a2cf4d4a484378caea2e827ed604b2bbae58bdba jdk8-b65 17820b958ae84f7c1cc6719319c8e2232f7a4f1d jdk8-b66 +76cc9bd3ece407d3a15d3bea537b57927973c5e7 jdk8-b67 +cb33628d4e8f11e879c371959e5948b66a53376f jdk8-b68 diff --git a/.hgtags-top-repo b/.hgtags-top-repo index cce276c0a8f..e46dc2409da 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -188,3 +188,5 @@ e07f499b9dccb529ecf74172cf6ac11a195ec57a jdk8-b60 1c8370a55b305d35353346202bde042ba9e8a9fd jdk8-b64 b772de306dc24c17f7bd1398531ddeb58723b804 jdk8-b65 13bb8c326e7b7b0b19d78c8088033e3932e3f7ca jdk8-b66 +9a6ec97ec45c1a62d5233cefa91e8390e380e13a jdk8-b67 +cdb401a60cea6ad5ef3f498725ed1decf8dda1ea jdk8-b68 diff --git a/common/autoconf/basics.m4 b/common/autoconf/basics.m4 index f2398978543..0074e8c16b1 100644 --- a/common/autoconf/basics.m4 +++ b/common/autoconf/basics.m4 @@ -90,13 +90,25 @@ AC_DEFUN([BASIC_FIXUP_EXECUTABLE], tmp="$complete EOL" arguments="${tmp#* }" - new_path=`$WHICH $path 2> /dev/null` + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + AC_MSG_NOTICE([Resolving $1 (as $path) failed, using $path directly.]) + new_path="$path" + fi + if test "x$new_path" = x; then - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test "x$is_absolute_path" != x; then - AC_MSG_NOTICE([Resolving $1 (as $path) with 'which' failed, using $path directly.]) - new_path="$path" - else AC_MSG_NOTICE([The path of $1, which resolves as "$complete", is not found.]) has_space=`$ECHO "$complete" | $GREP " "` if test "x$has_space" != x; then @@ -104,20 +116,19 @@ AC_DEFUN([BASIC_FIXUP_EXECUTABLE], fi AC_MSG_ERROR([Cannot locate the the path of $1]) fi - fi fi - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi if test "x$complete" != "x$new_complete"; then - $1="$new_complete" - AC_MSG_NOTICE([Rewriting $1 to "$new_complete"]) - fi + $1="$new_complete" + AC_MSG_NOTICE([Rewriting $1 to "$new_complete"]) + fi ]) AC_DEFUN([BASIC_REMOVE_SYMBOLIC_LINKS], diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index ad5cc0675e0..2b50f389549 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -708,6 +708,7 @@ CXX ac_ct_PROPER_COMPILER_CXX PROPER_COMPILER_CXX POTENTIAL_CXX +TOOLS_DIR_CXX OBJEXT EXEEXT ac_ct_CC @@ -718,6 +719,7 @@ CC ac_ct_PROPER_COMPILER_CC PROPER_COMPILER_CC POTENTIAL_CC +TOOLS_DIR_CC BUILD_LD BUILD_CXX BUILD_CC @@ -3672,7 +3674,7 @@ fi #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1354721616 +DATE_WHEN_GENERATED=1355849613 ############################################################################### # @@ -8163,14 +8165,26 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh tmp="$complete EOL" arguments="${tmp#* }" - new_path=`$WHICH $path 2> /dev/null` + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving FOUND_MAKE (as $path) failed, using $path directly." >&5 +$as_echo "$as_me: Resolving FOUND_MAKE (as $path) failed, using $path directly." >&6;} + new_path="$path" + fi + if test "x$new_path" = x; then - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test "x$is_absolute_path" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving FOUND_MAKE (as $path) with 'which' failed, using $path directly." >&5 -$as_echo "$as_me: Resolving FOUND_MAKE (as $path) with 'which' failed, using $path directly." >&6;} - new_path="$path" - else { $as_echo "$as_me:${as_lineno-$LINENO}: The path of FOUND_MAKE, which resolves as \"$complete\", is not found." >&5 $as_echo "$as_me: The path of FOUND_MAKE, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` @@ -8180,21 +8194,20 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow fi as_fn_error $? "Cannot locate the the path of FOUND_MAKE" "$LINENO" 5 fi - fi fi - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi if test "x$complete" != "x$new_complete"; then - FOUND_MAKE="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting FOUND_MAKE to \"$new_complete\"" >&5 + FOUND_MAKE="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting FOUND_MAKE to \"$new_complete\"" >&5 $as_echo "$as_me: Rewriting FOUND_MAKE to \"$new_complete\"" >&6;} - fi + fi fi fi @@ -8509,14 +8522,26 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh tmp="$complete EOL" arguments="${tmp#* }" - new_path=`$WHICH $path 2> /dev/null` + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving FOUND_MAKE (as $path) failed, using $path directly." >&5 +$as_echo "$as_me: Resolving FOUND_MAKE (as $path) failed, using $path directly." >&6;} + new_path="$path" + fi + if test "x$new_path" = x; then - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test "x$is_absolute_path" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving FOUND_MAKE (as $path) with 'which' failed, using $path directly." >&5 -$as_echo "$as_me: Resolving FOUND_MAKE (as $path) with 'which' failed, using $path directly." >&6;} - new_path="$path" - else { $as_echo "$as_me:${as_lineno-$LINENO}: The path of FOUND_MAKE, which resolves as \"$complete\", is not found." >&5 $as_echo "$as_me: The path of FOUND_MAKE, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` @@ -8526,21 +8551,20 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow fi as_fn_error $? "Cannot locate the the path of FOUND_MAKE" "$LINENO" 5 fi - fi fi - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi if test "x$complete" != "x$new_complete"; then - FOUND_MAKE="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting FOUND_MAKE to \"$new_complete\"" >&5 + FOUND_MAKE="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting FOUND_MAKE to \"$new_complete\"" >&5 $as_echo "$as_me: Rewriting FOUND_MAKE to \"$new_complete\"" >&6;} - fi + fi fi fi @@ -8852,14 +8876,26 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh tmp="$complete EOL" arguments="${tmp#* }" - new_path=`$WHICH $path 2> /dev/null` + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving FOUND_MAKE (as $path) failed, using $path directly." >&5 +$as_echo "$as_me: Resolving FOUND_MAKE (as $path) failed, using $path directly." >&6;} + new_path="$path" + fi + if test "x$new_path" = x; then - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test "x$is_absolute_path" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving FOUND_MAKE (as $path) with 'which' failed, using $path directly." >&5 -$as_echo "$as_me: Resolving FOUND_MAKE (as $path) with 'which' failed, using $path directly." >&6;} - new_path="$path" - else { $as_echo "$as_me:${as_lineno-$LINENO}: The path of FOUND_MAKE, which resolves as \"$complete\", is not found." >&5 $as_echo "$as_me: The path of FOUND_MAKE, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` @@ -8869,21 +8905,20 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow fi as_fn_error $? "Cannot locate the the path of FOUND_MAKE" "$LINENO" 5 fi - fi fi - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi if test "x$complete" != "x$new_complete"; then - FOUND_MAKE="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting FOUND_MAKE to \"$new_complete\"" >&5 + FOUND_MAKE="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting FOUND_MAKE to \"$new_complete\"" >&5 $as_echo "$as_me: Rewriting FOUND_MAKE to \"$new_complete\"" >&6;} - fi + fi fi fi @@ -9200,14 +9235,26 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh tmp="$complete EOL" arguments="${tmp#* }" - new_path=`$WHICH $path 2> /dev/null` + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving FOUND_MAKE (as $path) failed, using $path directly." >&5 +$as_echo "$as_me: Resolving FOUND_MAKE (as $path) failed, using $path directly." >&6;} + new_path="$path" + fi + if test "x$new_path" = x; then - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test "x$is_absolute_path" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving FOUND_MAKE (as $path) with 'which' failed, using $path directly." >&5 -$as_echo "$as_me: Resolving FOUND_MAKE (as $path) with 'which' failed, using $path directly." >&6;} - new_path="$path" - else { $as_echo "$as_me:${as_lineno-$LINENO}: The path of FOUND_MAKE, which resolves as \"$complete\", is not found." >&5 $as_echo "$as_me: The path of FOUND_MAKE, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` @@ -9217,21 +9264,20 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow fi as_fn_error $? "Cannot locate the the path of FOUND_MAKE" "$LINENO" 5 fi - fi fi - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi if test "x$complete" != "x$new_complete"; then - FOUND_MAKE="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting FOUND_MAKE to \"$new_complete\"" >&5 + FOUND_MAKE="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting FOUND_MAKE to \"$new_complete\"" >&5 $as_echo "$as_me: Rewriting FOUND_MAKE to \"$new_complete\"" >&6;} - fi + fi fi fi @@ -9542,14 +9588,26 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh tmp="$complete EOL" arguments="${tmp#* }" - new_path=`$WHICH $path 2> /dev/null` + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving FOUND_MAKE (as $path) failed, using $path directly." >&5 +$as_echo "$as_me: Resolving FOUND_MAKE (as $path) failed, using $path directly." >&6;} + new_path="$path" + fi + if test "x$new_path" = x; then - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test "x$is_absolute_path" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving FOUND_MAKE (as $path) with 'which' failed, using $path directly." >&5 -$as_echo "$as_me: Resolving FOUND_MAKE (as $path) with 'which' failed, using $path directly." >&6;} - new_path="$path" - else { $as_echo "$as_me:${as_lineno-$LINENO}: The path of FOUND_MAKE, which resolves as \"$complete\", is not found." >&5 $as_echo "$as_me: The path of FOUND_MAKE, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` @@ -9559,21 +9617,20 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow fi as_fn_error $? "Cannot locate the the path of FOUND_MAKE" "$LINENO" 5 fi - fi fi - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi if test "x$complete" != "x$new_complete"; then - FOUND_MAKE="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting FOUND_MAKE to \"$new_complete\"" >&5 + FOUND_MAKE="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting FOUND_MAKE to \"$new_complete\"" >&5 $as_echo "$as_me: Rewriting FOUND_MAKE to \"$new_complete\"" >&6;} - fi + fi fi fi @@ -16371,14 +16428,26 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh tmp="$complete EOL" arguments="${tmp#* }" - new_path=`$WHICH $path 2> /dev/null` + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving VS_ENV_CMD (as $path) failed, using $path directly." >&5 +$as_echo "$as_me: Resolving VS_ENV_CMD (as $path) failed, using $path directly." >&6;} + new_path="$path" + fi + if test "x$new_path" = x; then - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test "x$is_absolute_path" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving VS_ENV_CMD (as $path) with 'which' failed, using $path directly." >&5 -$as_echo "$as_me: Resolving VS_ENV_CMD (as $path) with 'which' failed, using $path directly." >&6;} - new_path="$path" - else { $as_echo "$as_me:${as_lineno-$LINENO}: The path of VS_ENV_CMD, which resolves as \"$complete\", is not found." >&5 $as_echo "$as_me: The path of VS_ENV_CMD, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` @@ -16388,21 +16457,20 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow fi as_fn_error $? "Cannot locate the the path of VS_ENV_CMD" "$LINENO" 5 fi - fi fi - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi if test "x$complete" != "x$new_complete"; then - VS_ENV_CMD="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting VS_ENV_CMD to \"$new_complete\"" >&5 + VS_ENV_CMD="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting VS_ENV_CMD to \"$new_complete\"" >&5 $as_echo "$as_me: Rewriting VS_ENV_CMD to \"$new_complete\"" >&6;} - fi + fi # Lets extract the variables that are set by vcvarsall.bat/vsvars32.bat/vsvars64.bat @@ -16960,14 +17028,26 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh tmp="$complete EOL" arguments="${tmp#* }" - new_path=`$WHICH $path 2> /dev/null` + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving BUILD_CC (as $path) failed, using $path directly." >&5 +$as_echo "$as_me: Resolving BUILD_CC (as $path) failed, using $path directly." >&6;} + new_path="$path" + fi + if test "x$new_path" = x; then - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test "x$is_absolute_path" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving BUILD_CC (as $path) with 'which' failed, using $path directly." >&5 -$as_echo "$as_me: Resolving BUILD_CC (as $path) with 'which' failed, using $path directly." >&6;} - new_path="$path" - else { $as_echo "$as_me:${as_lineno-$LINENO}: The path of BUILD_CC, which resolves as \"$complete\", is not found." >&5 $as_echo "$as_me: The path of BUILD_CC, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` @@ -16977,21 +17057,20 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow fi as_fn_error $? "Cannot locate the the path of BUILD_CC" "$LINENO" 5 fi - fi fi - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi if test "x$complete" != "x$new_complete"; then - BUILD_CC="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting BUILD_CC to \"$new_complete\"" >&5 + BUILD_CC="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting BUILD_CC to \"$new_complete\"" >&5 $as_echo "$as_me: Rewriting BUILD_CC to \"$new_complete\"" >&6;} - fi + fi for ac_prog in cl CC g++ do @@ -17260,14 +17339,26 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh tmp="$complete EOL" arguments="${tmp#* }" - new_path=`$WHICH $path 2> /dev/null` + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving BUILD_CXX (as $path) failed, using $path directly." >&5 +$as_echo "$as_me: Resolving BUILD_CXX (as $path) failed, using $path directly." >&6;} + new_path="$path" + fi + if test "x$new_path" = x; then - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test "x$is_absolute_path" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving BUILD_CXX (as $path) with 'which' failed, using $path directly." >&5 -$as_echo "$as_me: Resolving BUILD_CXX (as $path) with 'which' failed, using $path directly." >&6;} - new_path="$path" - else { $as_echo "$as_me:${as_lineno-$LINENO}: The path of BUILD_CXX, which resolves as \"$complete\", is not found." >&5 $as_echo "$as_me: The path of BUILD_CXX, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` @@ -17277,21 +17368,20 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow fi as_fn_error $? "Cannot locate the the path of BUILD_CXX" "$LINENO" 5 fi - fi fi - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi if test "x$complete" != "x$new_complete"; then - BUILD_CXX="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting BUILD_CXX to \"$new_complete\"" >&5 + BUILD_CXX="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting BUILD_CXX to \"$new_complete\"" >&5 $as_echo "$as_me: Rewriting BUILD_CXX to \"$new_complete\"" >&6;} - fi + fi # Extract the first word of "ld", so it can be a program name with args. set dummy ld; ac_word=$2 @@ -17555,14 +17645,26 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh tmp="$complete EOL" arguments="${tmp#* }" - new_path=`$WHICH $path 2> /dev/null` + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving BUILD_LD (as $path) failed, using $path directly." >&5 +$as_echo "$as_me: Resolving BUILD_LD (as $path) failed, using $path directly." >&6;} + new_path="$path" + fi + if test "x$new_path" = x; then - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test "x$is_absolute_path" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving BUILD_LD (as $path) with 'which' failed, using $path directly." >&5 -$as_echo "$as_me: Resolving BUILD_LD (as $path) with 'which' failed, using $path directly." >&6;} - new_path="$path" - else { $as_echo "$as_me:${as_lineno-$LINENO}: The path of BUILD_LD, which resolves as \"$complete\", is not found." >&5 $as_echo "$as_me: The path of BUILD_LD, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` @@ -17572,21 +17674,20 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow fi as_fn_error $? "Cannot locate the the path of BUILD_LD" "$LINENO" 5 fi - fi fi - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi if test "x$complete" != "x$new_complete"; then - BUILD_LD="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting BUILD_LD to \"$new_complete\"" >&5 + BUILD_LD="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting BUILD_LD to \"$new_complete\"" >&5 $as_echo "$as_me: Rewriting BUILD_LD to \"$new_complete\"" >&6;} - fi + fi fi @@ -17786,10 +17887,65 @@ fi COMPILER_NAME=C - # Do a first initial attempt at searching the list of compiler names. + CC= + # If TOOLS_DIR is set, check for all compiler names in there first + # before checking the rest of the PATH. + if test -n "$TOOLS_DIR"; then + PATH_save="$PATH" + PATH="$TOOLS_DIR" + for ac_prog in $COMPILER_CHECK_LIST +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 test "${ac_cv_path_TOOLS_DIR_CC+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + case $TOOLS_DIR_CC in + [\\/]* | ?:[\\/]*) + ac_cv_path_TOOLS_DIR_CC="$TOOLS_DIR_CC" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_TOOLS_DIR_CC="$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 +TOOLS_DIR_CC=$ac_cv_path_TOOLS_DIR_CC +if test -n "$TOOLS_DIR_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $TOOLS_DIR_CC" >&5 +$as_echo "$TOOLS_DIR_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$TOOLS_DIR_CC" && break +done + + CC=$TOOLS_DIR_CC + PATH="$PATH_save" + fi + # AC_PATH_PROGS can't be run multiple times with the same variable, # so create a new name for this run. - for ac_prog in $COMPILER_CHECK_LIST + if test "x$CC" = x; then + for ac_prog in $COMPILER_CHECK_LIST do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 @@ -17834,9 +17990,10 @@ fi test -n "$POTENTIAL_CC" && break done - CC=$POTENTIAL_CC + CC=$POTENTIAL_CC + fi - if test "x$$CC" = x; then + if test "x$CC" = x; then # Print a helpful message on how to acquire the necessary build dependency. # devkit is the help tag: freetyp2, cups, pulse, alsa etc @@ -18086,14 +18243,26 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh tmp="$complete EOL" arguments="${tmp#* }" - new_path=`$WHICH $path 2> /dev/null` + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving CC (as $path) failed, using $path directly." >&5 +$as_echo "$as_me: Resolving CC (as $path) failed, using $path directly." >&6;} + new_path="$path" + fi + if test "x$new_path" = x; then - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test "x$is_absolute_path" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving CC (as $path) with 'which' failed, using $path directly." >&5 -$as_echo "$as_me: Resolving CC (as $path) with 'which' failed, using $path directly." >&6;} - new_path="$path" - else { $as_echo "$as_me:${as_lineno-$LINENO}: The path of CC, which resolves as \"$complete\", is not found." >&5 $as_echo "$as_me: The path of CC, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` @@ -18103,21 +18272,20 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow fi as_fn_error $? "Cannot locate the the path of CC" "$LINENO" 5 fi - fi fi - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi if test "x$complete" != "x$new_complete"; then - CC="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting CC to \"$new_complete\"" >&5 + CC="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting CC to \"$new_complete\"" >&5 $as_echo "$as_me: Rewriting CC to \"$new_complete\"" >&6;} - fi + fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking resolved symbolic links for CC" >&5 $as_echo_n "checking resolved symbolic links for CC... " >&6; } @@ -18511,14 +18679,26 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh tmp="$complete EOL" arguments="${tmp#* }" - new_path=`$WHICH $path 2> /dev/null` + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving PROPER_COMPILER_CC (as $path) failed, using $path directly." >&5 +$as_echo "$as_me: Resolving PROPER_COMPILER_CC (as $path) failed, using $path directly." >&6;} + new_path="$path" + fi + if test "x$new_path" = x; then - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test "x$is_absolute_path" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving PROPER_COMPILER_CC (as $path) with 'which' failed, using $path directly." >&5 -$as_echo "$as_me: Resolving PROPER_COMPILER_CC (as $path) with 'which' failed, using $path directly." >&6;} - new_path="$path" - else { $as_echo "$as_me:${as_lineno-$LINENO}: The path of PROPER_COMPILER_CC, which resolves as \"$complete\", is not found." >&5 $as_echo "$as_me: The path of PROPER_COMPILER_CC, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` @@ -18528,21 +18708,20 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow fi as_fn_error $? "Cannot locate the the path of PROPER_COMPILER_CC" "$LINENO" 5 fi - fi fi - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi if test "x$complete" != "x$new_complete"; then - PROPER_COMPILER_CC="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting PROPER_COMPILER_CC to \"$new_complete\"" >&5 + PROPER_COMPILER_CC="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting PROPER_COMPILER_CC to \"$new_complete\"" >&5 $as_echo "$as_me: Rewriting PROPER_COMPILER_CC to \"$new_complete\"" >&6;} - fi + fi PATH="$RETRY_COMPILER_SAVED_PATH" @@ -19277,10 +19456,65 @@ fi COMPILER_NAME=C++ - # Do a first initial attempt at searching the list of compiler names. + CXX= + # If TOOLS_DIR is set, check for all compiler names in there first + # before checking the rest of the PATH. + if test -n "$TOOLS_DIR"; then + PATH_save="$PATH" + PATH="$TOOLS_DIR" + for ac_prog in $COMPILER_CHECK_LIST +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 test "${ac_cv_path_TOOLS_DIR_CXX+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + case $TOOLS_DIR_CXX in + [\\/]* | ?:[\\/]*) + ac_cv_path_TOOLS_DIR_CXX="$TOOLS_DIR_CXX" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_TOOLS_DIR_CXX="$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 +TOOLS_DIR_CXX=$ac_cv_path_TOOLS_DIR_CXX +if test -n "$TOOLS_DIR_CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $TOOLS_DIR_CXX" >&5 +$as_echo "$TOOLS_DIR_CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$TOOLS_DIR_CXX" && break +done + + CXX=$TOOLS_DIR_CXX + PATH="$PATH_save" + fi + # AC_PATH_PROGS can't be run multiple times with the same variable, # so create a new name for this run. - for ac_prog in $COMPILER_CHECK_LIST + if test "x$CXX" = x; then + for ac_prog in $COMPILER_CHECK_LIST do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 @@ -19325,9 +19559,10 @@ fi test -n "$POTENTIAL_CXX" && break done - CXX=$POTENTIAL_CXX + CXX=$POTENTIAL_CXX + fi - if test "x$$CXX" = x; then + if test "x$CXX" = x; then # Print a helpful message on how to acquire the necessary build dependency. # devkit is the help tag: freetyp2, cups, pulse, alsa etc @@ -19577,14 +19812,26 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh tmp="$complete EOL" arguments="${tmp#* }" - new_path=`$WHICH $path 2> /dev/null` + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving CXX (as $path) failed, using $path directly." >&5 +$as_echo "$as_me: Resolving CXX (as $path) failed, using $path directly." >&6;} + new_path="$path" + fi + if test "x$new_path" = x; then - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test "x$is_absolute_path" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving CXX (as $path) with 'which' failed, using $path directly." >&5 -$as_echo "$as_me: Resolving CXX (as $path) with 'which' failed, using $path directly." >&6;} - new_path="$path" - else { $as_echo "$as_me:${as_lineno-$LINENO}: The path of CXX, which resolves as \"$complete\", is not found." >&5 $as_echo "$as_me: The path of CXX, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` @@ -19594,21 +19841,20 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow fi as_fn_error $? "Cannot locate the the path of CXX" "$LINENO" 5 fi - fi fi - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi if test "x$complete" != "x$new_complete"; then - CXX="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting CXX to \"$new_complete\"" >&5 + CXX="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting CXX to \"$new_complete\"" >&5 $as_echo "$as_me: Rewriting CXX to \"$new_complete\"" >&6;} - fi + fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking resolved symbolic links for CXX" >&5 $as_echo_n "checking resolved symbolic links for CXX... " >&6; } @@ -20002,14 +20248,26 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh tmp="$complete EOL" arguments="${tmp#* }" - new_path=`$WHICH $path 2> /dev/null` + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving PROPER_COMPILER_CXX (as $path) failed, using $path directly." >&5 +$as_echo "$as_me: Resolving PROPER_COMPILER_CXX (as $path) failed, using $path directly." >&6;} + new_path="$path" + fi + if test "x$new_path" = x; then - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test "x$is_absolute_path" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving PROPER_COMPILER_CXX (as $path) with 'which' failed, using $path directly." >&5 -$as_echo "$as_me: Resolving PROPER_COMPILER_CXX (as $path) with 'which' failed, using $path directly." >&6;} - new_path="$path" - else { $as_echo "$as_me:${as_lineno-$LINENO}: The path of PROPER_COMPILER_CXX, which resolves as \"$complete\", is not found." >&5 $as_echo "$as_me: The path of PROPER_COMPILER_CXX, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` @@ -20019,21 +20277,20 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow fi as_fn_error $? "Cannot locate the the path of PROPER_COMPILER_CXX" "$LINENO" 5 fi - fi fi - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi if test "x$complete" != "x$new_complete"; then - PROPER_COMPILER_CXX="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting PROPER_COMPILER_CXX to \"$new_complete\"" >&5 + PROPER_COMPILER_CXX="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting PROPER_COMPILER_CXX to \"$new_complete\"" >&5 $as_echo "$as_me: Rewriting PROPER_COMPILER_CXX to \"$new_complete\"" >&6;} - fi + fi PATH="$RETRY_COMPILER_SAVED_PATH" @@ -20892,14 +21149,26 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh tmp="$complete EOL" arguments="${tmp#* }" - new_path=`$WHICH $path 2> /dev/null` + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving OBJC (as $path) failed, using $path directly." >&5 +$as_echo "$as_me: Resolving OBJC (as $path) failed, using $path directly." >&6;} + new_path="$path" + fi + if test "x$new_path" = x; then - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test "x$is_absolute_path" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving OBJC (as $path) with 'which' failed, using $path directly." >&5 -$as_echo "$as_me: Resolving OBJC (as $path) with 'which' failed, using $path directly." >&6;} - new_path="$path" - else { $as_echo "$as_me:${as_lineno-$LINENO}: The path of OBJC, which resolves as \"$complete\", is not found." >&5 $as_echo "$as_me: The path of OBJC, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` @@ -20909,21 +21178,20 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow fi as_fn_error $? "Cannot locate the the path of OBJC" "$LINENO" 5 fi - fi fi - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi if test "x$complete" != "x$new_complete"; then - OBJC="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting OBJC to \"$new_complete\"" >&5 + OBJC="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting OBJC to \"$new_complete\"" >&5 $as_echo "$as_me: Rewriting OBJC to \"$new_complete\"" >&6;} - fi + fi else OBJC= @@ -21262,14 +21530,26 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh tmp="$complete EOL" arguments="${tmp#* }" - new_path=`$WHICH $path 2> /dev/null` + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving AR (as $path) failed, using $path directly." >&5 +$as_echo "$as_me: Resolving AR (as $path) failed, using $path directly." >&6;} + new_path="$path" + fi + if test "x$new_path" = x; then - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test "x$is_absolute_path" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving AR (as $path) with 'which' failed, using $path directly." >&5 -$as_echo "$as_me: Resolving AR (as $path) with 'which' failed, using $path directly." >&6;} - new_path="$path" - else { $as_echo "$as_me:${as_lineno-$LINENO}: The path of AR, which resolves as \"$complete\", is not found." >&5 $as_echo "$as_me: The path of AR, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` @@ -21279,21 +21559,20 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow fi as_fn_error $? "Cannot locate the the path of AR" "$LINENO" 5 fi - fi fi - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi if test "x$complete" != "x$new_complete"; then - AR="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting AR to \"$new_complete\"" >&5 + AR="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting AR to \"$new_complete\"" >&5 $as_echo "$as_me: Rewriting AR to \"$new_complete\"" >&6;} - fi + fi fi if test "x$OPENJDK_TARGET_OS" = xmacosx; then @@ -21598,14 +21877,26 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh tmp="$complete EOL" arguments="${tmp#* }" - new_path=`$WHICH $path 2> /dev/null` + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving WINLD (as $path) failed, using $path directly." >&5 +$as_echo "$as_me: Resolving WINLD (as $path) failed, using $path directly." >&6;} + new_path="$path" + fi + if test "x$new_path" = x; then - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test "x$is_absolute_path" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving WINLD (as $path) with 'which' failed, using $path directly." >&5 -$as_echo "$as_me: Resolving WINLD (as $path) with 'which' failed, using $path directly." >&6;} - new_path="$path" - else { $as_echo "$as_me:${as_lineno-$LINENO}: The path of WINLD, which resolves as \"$complete\", is not found." >&5 $as_echo "$as_me: The path of WINLD, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` @@ -21615,21 +21906,20 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow fi as_fn_error $? "Cannot locate the the path of WINLD" "$LINENO" 5 fi - fi fi - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi if test "x$complete" != "x$new_complete"; then - WINLD="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting WINLD to \"$new_complete\"" >&5 + WINLD="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting WINLD to \"$new_complete\"" >&5 $as_echo "$as_me: Rewriting WINLD to \"$new_complete\"" >&6;} - fi + fi printf "Windows linker was found at $WINLD\n" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the found link.exe is actually the Visual Studio linker" >&5 @@ -21924,14 +22214,26 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh tmp="$complete EOL" arguments="${tmp#* }" - new_path=`$WHICH $path 2> /dev/null` + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving MT (as $path) failed, using $path directly." >&5 +$as_echo "$as_me: Resolving MT (as $path) failed, using $path directly." >&6;} + new_path="$path" + fi + if test "x$new_path" = x; then - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test "x$is_absolute_path" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving MT (as $path) with 'which' failed, using $path directly." >&5 -$as_echo "$as_me: Resolving MT (as $path) with 'which' failed, using $path directly." >&6;} - new_path="$path" - else { $as_echo "$as_me:${as_lineno-$LINENO}: The path of MT, which resolves as \"$complete\", is not found." >&5 $as_echo "$as_me: The path of MT, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` @@ -21941,21 +22243,20 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow fi as_fn_error $? "Cannot locate the the path of MT" "$LINENO" 5 fi - fi fi - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi if test "x$complete" != "x$new_complete"; then - MT="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting MT to \"$new_complete\"" >&5 + MT="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting MT to \"$new_complete\"" >&5 $as_echo "$as_me: Rewriting MT to \"$new_complete\"" >&6;} - fi + fi # The resource compiler # Extract the first word of "rc", so it can be a program name with args. @@ -22234,14 +22535,26 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh tmp="$complete EOL" arguments="${tmp#* }" - new_path=`$WHICH $path 2> /dev/null` + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving RC (as $path) failed, using $path directly." >&5 +$as_echo "$as_me: Resolving RC (as $path) failed, using $path directly." >&6;} + new_path="$path" + fi + if test "x$new_path" = x; then - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test "x$is_absolute_path" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving RC (as $path) with 'which' failed, using $path directly." >&5 -$as_echo "$as_me: Resolving RC (as $path) with 'which' failed, using $path directly." >&6;} - new_path="$path" - else { $as_echo "$as_me:${as_lineno-$LINENO}: The path of RC, which resolves as \"$complete\", is not found." >&5 $as_echo "$as_me: The path of RC, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` @@ -22251,21 +22564,20 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow fi as_fn_error $? "Cannot locate the the path of RC" "$LINENO" 5 fi - fi fi - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi if test "x$complete" != "x$new_complete"; then - RC="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting RC to \"$new_complete\"" >&5 + RC="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting RC to \"$new_complete\"" >&5 $as_echo "$as_me: Rewriting RC to \"$new_complete\"" >&6;} - fi + fi # For hotspot, we need these in Windows mixed path, @@ -22597,14 +22909,26 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh tmp="$complete EOL" arguments="${tmp#* }" - new_path=`$WHICH $path 2> /dev/null` + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving WINAR (as $path) failed, using $path directly." >&5 +$as_echo "$as_me: Resolving WINAR (as $path) failed, using $path directly." >&6;} + new_path="$path" + fi + if test "x$new_path" = x; then - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test "x$is_absolute_path" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving WINAR (as $path) with 'which' failed, using $path directly." >&5 -$as_echo "$as_me: Resolving WINAR (as $path) with 'which' failed, using $path directly." >&6;} - new_path="$path" - else { $as_echo "$as_me:${as_lineno-$LINENO}: The path of WINAR, which resolves as \"$complete\", is not found." >&5 $as_echo "$as_me: The path of WINAR, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` @@ -22614,21 +22938,20 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow fi as_fn_error $? "Cannot locate the the path of WINAR" "$LINENO" 5 fi - fi fi - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi if test "x$complete" != "x$new_complete"; then - WINAR="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting WINAR to \"$new_complete\"" >&5 + WINAR="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting WINAR to \"$new_complete\"" >&5 $as_echo "$as_me: Rewriting WINAR to \"$new_complete\"" >&6;} - fi + fi AR="$WINAR" ARFLAGS="-nologo -NODEFAULTLIB:MSVCRT" @@ -22892,14 +23215,26 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh tmp="$complete EOL" arguments="${tmp#* }" - new_path=`$WHICH $path 2> /dev/null` + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving DUMPBIN (as $path) failed, using $path directly." >&5 +$as_echo "$as_me: Resolving DUMPBIN (as $path) failed, using $path directly." >&6;} + new_path="$path" + fi + if test "x$new_path" = x; then - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test "x$is_absolute_path" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving DUMPBIN (as $path) with 'which' failed, using $path directly." >&5 -$as_echo "$as_me: Resolving DUMPBIN (as $path) with 'which' failed, using $path directly." >&6;} - new_path="$path" - else { $as_echo "$as_me:${as_lineno-$LINENO}: The path of DUMPBIN, which resolves as \"$complete\", is not found." >&5 $as_echo "$as_me: The path of DUMPBIN, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` @@ -22909,21 +23244,20 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow fi as_fn_error $? "Cannot locate the the path of DUMPBIN" "$LINENO" 5 fi - fi fi - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi if test "x$complete" != "x$new_complete"; then - DUMPBIN="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting DUMPBIN to \"$new_complete\"" >&5 + DUMPBIN="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting DUMPBIN to \"$new_complete\"" >&5 $as_echo "$as_me: Rewriting DUMPBIN to \"$new_complete\"" >&6;} - fi + fi COMPILER_TYPE=CL @@ -23292,14 +23626,26 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh tmp="$complete EOL" arguments="${tmp#* }" - new_path=`$WHICH $path 2> /dev/null` + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving CPP (as $path) failed, using $path directly." >&5 +$as_echo "$as_me: Resolving CPP (as $path) failed, using $path directly." >&6;} + new_path="$path" + fi + if test "x$new_path" = x; then - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test "x$is_absolute_path" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving CPP (as $path) with 'which' failed, using $path directly." >&5 -$as_echo "$as_me: Resolving CPP (as $path) with 'which' failed, using $path directly." >&6;} - new_path="$path" - else { $as_echo "$as_me:${as_lineno-$LINENO}: The path of CPP, which resolves as \"$complete\", is not found." >&5 $as_echo "$as_me: The path of CPP, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` @@ -23309,21 +23655,20 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow fi as_fn_error $? "Cannot locate the the path of CPP" "$LINENO" 5 fi - fi fi - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi if test "x$complete" != "x$new_complete"; then - CPP="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting CPP to \"$new_complete\"" >&5 + CPP="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting CPP to \"$new_complete\"" >&5 $as_echo "$as_me: Rewriting CPP to \"$new_complete\"" >&6;} - fi + fi ac_ext=cpp @@ -23681,14 +24026,26 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh tmp="$complete EOL" arguments="${tmp#* }" - new_path=`$WHICH $path 2> /dev/null` + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving CXXCPP (as $path) failed, using $path directly." >&5 +$as_echo "$as_me: Resolving CXXCPP (as $path) failed, using $path directly." >&6;} + new_path="$path" + fi + if test "x$new_path" = x; then - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test "x$is_absolute_path" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving CXXCPP (as $path) with 'which' failed, using $path directly." >&5 -$as_echo "$as_me: Resolving CXXCPP (as $path) with 'which' failed, using $path directly." >&6;} - new_path="$path" - else { $as_echo "$as_me:${as_lineno-$LINENO}: The path of CXXCPP, which resolves as \"$complete\", is not found." >&5 $as_echo "$as_me: The path of CXXCPP, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` @@ -23698,21 +24055,20 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow fi as_fn_error $? "Cannot locate the the path of CXXCPP" "$LINENO" 5 fi - fi fi - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi if test "x$complete" != "x$new_complete"; then - CXXCPP="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting CXXCPP to \"$new_complete\"" >&5 + CXXCPP="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting CXXCPP to \"$new_complete\"" >&5 $as_echo "$as_me: Rewriting CXXCPP to \"$new_complete\"" >&6;} - fi + fi if test "x$COMPILE_TYPE" != "xcross"; then @@ -23999,14 +24355,26 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh tmp="$complete EOL" arguments="${tmp#* }" - new_path=`$WHICH $path 2> /dev/null` + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving AS (as $path) failed, using $path directly." >&5 +$as_echo "$as_me: Resolving AS (as $path) failed, using $path directly." >&6;} + new_path="$path" + fi + if test "x$new_path" = x; then - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test "x$is_absolute_path" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving AS (as $path) with 'which' failed, using $path directly." >&5 -$as_echo "$as_me: Resolving AS (as $path) with 'which' failed, using $path directly." >&6;} - new_path="$path" - else { $as_echo "$as_me:${as_lineno-$LINENO}: The path of AS, which resolves as \"$complete\", is not found." >&5 $as_echo "$as_me: The path of AS, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` @@ -24016,21 +24384,20 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow fi as_fn_error $? "Cannot locate the the path of AS" "$LINENO" 5 fi - fi fi - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi if test "x$complete" != "x$new_complete"; then - AS="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting AS to \"$new_complete\"" >&5 + AS="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting AS to \"$new_complete\"" >&5 $as_echo "$as_me: Rewriting AS to \"$new_complete\"" >&6;} - fi + fi else AS="$CC -c" @@ -24305,14 +24672,26 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh tmp="$complete EOL" arguments="${tmp#* }" - new_path=`$WHICH $path 2> /dev/null` + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving NM (as $path) failed, using $path directly." >&5 +$as_echo "$as_me: Resolving NM (as $path) failed, using $path directly." >&6;} + new_path="$path" + fi + if test "x$new_path" = x; then - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test "x$is_absolute_path" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving NM (as $path) with 'which' failed, using $path directly." >&5 -$as_echo "$as_me: Resolving NM (as $path) with 'which' failed, using $path directly." >&6;} - new_path="$path" - else { $as_echo "$as_me:${as_lineno-$LINENO}: The path of NM, which resolves as \"$complete\", is not found." >&5 $as_echo "$as_me: The path of NM, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` @@ -24322,21 +24701,20 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow fi as_fn_error $? "Cannot locate the the path of NM" "$LINENO" 5 fi - fi fi - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi if test "x$complete" != "x$new_complete"; then - NM="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting NM to \"$new_complete\"" >&5 + NM="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting NM to \"$new_complete\"" >&5 $as_echo "$as_me: Rewriting NM to \"$new_complete\"" >&6;} - fi + fi # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 @@ -24600,14 +24978,26 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh tmp="$complete EOL" arguments="${tmp#* }" - new_path=`$WHICH $path 2> /dev/null` + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving STRIP (as $path) failed, using $path directly." >&5 +$as_echo "$as_me: Resolving STRIP (as $path) failed, using $path directly." >&6;} + new_path="$path" + fi + if test "x$new_path" = x; then - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test "x$is_absolute_path" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving STRIP (as $path) with 'which' failed, using $path directly." >&5 -$as_echo "$as_me: Resolving STRIP (as $path) with 'which' failed, using $path directly." >&6;} - new_path="$path" - else { $as_echo "$as_me:${as_lineno-$LINENO}: The path of STRIP, which resolves as \"$complete\", is not found." >&5 $as_echo "$as_me: The path of STRIP, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` @@ -24617,21 +25007,20 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow fi as_fn_error $? "Cannot locate the the path of STRIP" "$LINENO" 5 fi - fi fi - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi if test "x$complete" != "x$new_complete"; then - STRIP="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting STRIP to \"$new_complete\"" >&5 + STRIP="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting STRIP to \"$new_complete\"" >&5 $as_echo "$as_me: Rewriting STRIP to \"$new_complete\"" >&6;} - fi + fi # Extract the first word of "mcs", so it can be a program name with args. set dummy mcs; ac_word=$2 @@ -24895,14 +25284,26 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh tmp="$complete EOL" arguments="${tmp#* }" - new_path=`$WHICH $path 2> /dev/null` + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving MCS (as $path) failed, using $path directly." >&5 +$as_echo "$as_me: Resolving MCS (as $path) failed, using $path directly." >&6;} + new_path="$path" + fi + if test "x$new_path" = x; then - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test "x$is_absolute_path" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving MCS (as $path) with 'which' failed, using $path directly." >&5 -$as_echo "$as_me: Resolving MCS (as $path) with 'which' failed, using $path directly." >&6;} - new_path="$path" - else { $as_echo "$as_me:${as_lineno-$LINENO}: The path of MCS, which resolves as \"$complete\", is not found." >&5 $as_echo "$as_me: The path of MCS, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` @@ -24912,21 +25313,20 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow fi as_fn_error $? "Cannot locate the the path of MCS" "$LINENO" 5 fi - fi fi - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi if test "x$complete" != "x$new_complete"; then - MCS="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting MCS to \"$new_complete\"" >&5 + MCS="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting MCS to \"$new_complete\"" >&5 $as_echo "$as_me: Rewriting MCS to \"$new_complete\"" >&6;} - fi + fi elif test "x$OPENJDK_TARGET_OS" != xwindows; then if test -n "$ac_tool_prefix"; then @@ -25243,14 +25643,26 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh tmp="$complete EOL" arguments="${tmp#* }" - new_path=`$WHICH $path 2> /dev/null` + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving NM (as $path) failed, using $path directly." >&5 +$as_echo "$as_me: Resolving NM (as $path) failed, using $path directly." >&6;} + new_path="$path" + fi + if test "x$new_path" = x; then - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test "x$is_absolute_path" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving NM (as $path) with 'which' failed, using $path directly." >&5 -$as_echo "$as_me: Resolving NM (as $path) with 'which' failed, using $path directly." >&6;} - new_path="$path" - else { $as_echo "$as_me:${as_lineno-$LINENO}: The path of NM, which resolves as \"$complete\", is not found." >&5 $as_echo "$as_me: The path of NM, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` @@ -25260,21 +25672,20 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow fi as_fn_error $? "Cannot locate the the path of NM" "$LINENO" 5 fi - fi fi - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi if test "x$complete" != "x$new_complete"; then - NM="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting NM to \"$new_complete\"" >&5 + NM="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting NM to \"$new_complete\"" >&5 $as_echo "$as_me: Rewriting NM to \"$new_complete\"" >&6;} - fi + fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. @@ -25590,14 +26001,26 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh tmp="$complete EOL" arguments="${tmp#* }" - new_path=`$WHICH $path 2> /dev/null` + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving STRIP (as $path) failed, using $path directly." >&5 +$as_echo "$as_me: Resolving STRIP (as $path) failed, using $path directly." >&6;} + new_path="$path" + fi + if test "x$new_path" = x; then - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test "x$is_absolute_path" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving STRIP (as $path) with 'which' failed, using $path directly." >&5 -$as_echo "$as_me: Resolving STRIP (as $path) with 'which' failed, using $path directly." >&6;} - new_path="$path" - else { $as_echo "$as_me:${as_lineno-$LINENO}: The path of STRIP, which resolves as \"$complete\", is not found." >&5 $as_echo "$as_me: The path of STRIP, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` @@ -25607,21 +26030,20 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow fi as_fn_error $? "Cannot locate the the path of STRIP" "$LINENO" 5 fi - fi fi - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi if test "x$complete" != "x$new_complete"; then - STRIP="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting STRIP to \"$new_complete\"" >&5 + STRIP="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting STRIP to \"$new_complete\"" >&5 $as_echo "$as_me: Rewriting STRIP to \"$new_complete\"" >&6;} - fi + fi fi @@ -25952,14 +26374,26 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh tmp="$complete EOL" arguments="${tmp#* }" - new_path=`$WHICH $path 2> /dev/null` + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving OBJCOPY (as $path) failed, using $path directly." >&5 +$as_echo "$as_me: Resolving OBJCOPY (as $path) failed, using $path directly." >&6;} + new_path="$path" + fi + if test "x$new_path" = x; then - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test "x$is_absolute_path" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving OBJCOPY (as $path) with 'which' failed, using $path directly." >&5 -$as_echo "$as_me: Resolving OBJCOPY (as $path) with 'which' failed, using $path directly." >&6;} - new_path="$path" - else { $as_echo "$as_me:${as_lineno-$LINENO}: The path of OBJCOPY, which resolves as \"$complete\", is not found." >&5 $as_echo "$as_me: The path of OBJCOPY, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` @@ -25969,21 +26403,20 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow fi as_fn_error $? "Cannot locate the the path of OBJCOPY" "$LINENO" 5 fi - fi fi - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi if test "x$complete" != "x$new_complete"; then - OBJCOPY="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting OBJCOPY to \"$new_complete\"" >&5 + OBJCOPY="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting OBJCOPY to \"$new_complete\"" >&5 $as_echo "$as_me: Rewriting OBJCOPY to \"$new_complete\"" >&6;} - fi + fi fi fi @@ -26312,14 +26745,26 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh tmp="$complete EOL" arguments="${tmp#* }" - new_path=`$WHICH $path 2> /dev/null` + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving OBJDUMP (as $path) failed, using $path directly." >&5 +$as_echo "$as_me: Resolving OBJDUMP (as $path) failed, using $path directly." >&6;} + new_path="$path" + fi + if test "x$new_path" = x; then - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test "x$is_absolute_path" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving OBJDUMP (as $path) with 'which' failed, using $path directly." >&5 -$as_echo "$as_me: Resolving OBJDUMP (as $path) with 'which' failed, using $path directly." >&6;} - new_path="$path" - else { $as_echo "$as_me:${as_lineno-$LINENO}: The path of OBJDUMP, which resolves as \"$complete\", is not found." >&5 $as_echo "$as_me: The path of OBJDUMP, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` @@ -26329,21 +26774,20 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow fi as_fn_error $? "Cannot locate the the path of OBJDUMP" "$LINENO" 5 fi - fi fi - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi if test "x$complete" != "x$new_complete"; then - OBJDUMP="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting OBJDUMP to \"$new_complete\"" >&5 + OBJDUMP="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting OBJDUMP to \"$new_complete\"" >&5 $as_echo "$as_me: Rewriting OBJDUMP to \"$new_complete\"" >&6;} - fi + fi fi @@ -26610,14 +27054,26 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh tmp="$complete EOL" arguments="${tmp#* }" - new_path=`$WHICH $path 2> /dev/null` + # Cannot rely on the command "which" here since it doesn't always work. + is_absolute_path=`$ECHO "$path" | $GREP ^/` + if test -z "$is_absolute_path"; then + # Path to executable is not absolute. Find it. + IFS_save="$IFS" + IFS=: + for p in $PATH; do + if test -f "$p/$path" && test -x "$p/$path"; then + new_path="$p/$path" + break + fi + done + IFS="$IFS_save" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving LIPO (as $path) failed, using $path directly." >&5 +$as_echo "$as_me: Resolving LIPO (as $path) failed, using $path directly." >&6;} + new_path="$path" + fi + if test "x$new_path" = x; then - is_absolute_path=`$ECHO "$path" | $GREP ^/` - if test "x$is_absolute_path" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Resolving LIPO (as $path) with 'which' failed, using $path directly." >&5 -$as_echo "$as_me: Resolving LIPO (as $path) with 'which' failed, using $path directly." >&6;} - new_path="$path" - else { $as_echo "$as_me:${as_lineno-$LINENO}: The path of LIPO, which resolves as \"$complete\", is not found." >&5 $as_echo "$as_me: The path of LIPO, which resolves as \"$complete\", is not found." >&6;} has_space=`$ECHO "$complete" | $GREP " "` @@ -26627,21 +27083,20 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow fi as_fn_error $? "Cannot locate the the path of LIPO" "$LINENO" 5 fi - fi fi - # Now join together the path and the arguments once again - if test "x$arguments" != xEOL; then - new_complete="$new_path ${arguments% *}" - else - new_complete="$new_path" - fi + # Now join together the path and the arguments once again + if test "x$arguments" != xEOL; then + new_complete="$new_path ${arguments% *}" + else + new_complete="$new_path" + fi if test "x$complete" != "x$new_complete"; then - LIPO="$new_complete" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting LIPO to \"$new_complete\"" >&5 + LIPO="$new_complete" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting LIPO to \"$new_complete\"" >&5 $as_echo "$as_me: Rewriting LIPO to \"$new_complete\"" >&6;} - fi + fi fi @@ -27706,34 +28161,34 @@ esac # ENABLE_DEBUG_SYMBOLS # This must be done after the toolchain is setup, since we're looking at objcopy. # -ENABLE_DEBUG_SYMBOLS=default - -# default on macosx is no... -if test "x$OPENJDK_TARGET_OS" = xmacosx; then - ENABLE_DEBUG_SYMBOLS=no -fi - # Check whether --enable-debug-symbols was given. if test "${enable_debug_symbols+set}" = set; then : - enableval=$enable_debug_symbols; ENABLE_DEBUG_SYMBOLS=${enable_debug_symbols} + enableval=$enable_debug_symbols; fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we should generate debug symbols" >&5 $as_echo_n "checking if we should generate debug symbols... " >&6; } -if test "x$ENABLE_DEBUG_SYMBOLS" = "xyes" && test "x$OBJCOPY" = x; then +if test "x$enable_debug_symbols" = "xyes" && test "x$OBJCOPY" = x; then # explicit enabling of enable-debug-symbols and can't find objcopy # this is an error as_fn_error $? "Unable to find objcopy, cannot enable debug-symbols" "$LINENO" 5 fi -if test "x$ENABLE_DEBUG_SYMBOLS" = "xdefault"; then +if test "x$enable_debug_symbols" = "xyes"; then + ENABLE_DEBUG_SYMBOLS=true +elif test "x$enable_debug_symbols" = "xno"; then + ENABLE_DEBUG_SYMBOLS=false +else + # default on macosx is false + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + ENABLE_DEBUG_SYMBOLS=false # Default is on if objcopy is found, otherwise off - if test "x$OBJCOPY" != x || test "x$OPENJDK_TARGET_OS" = xwindows; then - ENABLE_DEBUG_SYMBOLS=yes + elif test "x$OBJCOPY" != x || test "x$OPENJDK_TARGET_OS" = xwindows; then + ENABLE_DEBUG_SYMBOLS=true else - ENABLE_DEBUG_SYMBOLS=no + ENABLE_DEBUG_SYMBOLS=false fi fi @@ -27743,25 +28198,21 @@ $as_echo "$ENABLE_DEBUG_SYMBOLS" >&6; } # # ZIP_DEBUGINFO_FILES # -ZIP_DEBUGINFO_FILES=yes - # Check whether --enable-zip-debug-info was given. if test "${enable_zip_debug_info+set}" = set; then : - enableval=$enable_zip_debug_info; ZIP_DEBUGINFO_FILES=${enable_zip_debug_info} + enableval=$enable_zip_debug_info; fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we should zip debug-info files" >&5 $as_echo_n "checking if we should zip debug-info files... " >&6; } -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ZIP_DEBUGINFO_FILES" >&5 -$as_echo "$ZIP_DEBUGINFO_FILES" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${enable_zip_debug_info}" >&5 +$as_echo "${enable_zip_debug_info}" >&6; } -# Hotspot wants ZIP_DEBUGINFO_FILES to be 1 for yes -# use that... -if test "x$ZIP_DEBUGINFO_FILES" = "xyes"; then - ZIP_DEBUGINFO_FILES=1 +if test "x${enable_zip_debug_info}" = "xno"; then + ZIP_DEBUGINFO_FILES=false else - ZIP_DEBUGINFO_FILES=0 + ZIP_DEBUGINFO_FILES=true fi diff --git a/common/autoconf/hotspot-spec.gmk.in b/common/autoconf/hotspot-spec.gmk.in index 884a911a26d..afc887a5ec9 100644 --- a/common/autoconf/hotspot-spec.gmk.in +++ b/common/autoconf/hotspot-spec.gmk.in @@ -97,6 +97,24 @@ EXTRA_LDFLAGS=@LEGACY_EXTRA_LDFLAGS@ USE_PRECOMPILED_HEADER=@USE_PRECOMPILED_HEADER@ +# Hotspot expects the variable FULL_DEBUG_SYMBOLS=1/0 to control debug symbols +# creation. +ifeq ($(ENABLE_DEBUG_SYMBOLS), true) + FULL_DEBUG_SYMBOLS=1 + # Ensure hotspot uses the objcopy that configure located + ALT_OBJCOPY:=$(OBJCOPY) +else + FULL_DEBUG_SYMBOLS=0 +endif + +# Hotspot expects the variable ZIP_DEBUGINFO_FILES=1/0 and not true/false. +ifeq ($(ZIP_DEBUGINFO_FILES)$(ENABLE_DEBUG_SYMBOLS), truetrue) + ZIP_DEBUGINFO_FILES:=1 +endif +ifeq ($(ZIP_DEBUGINFO_FILES), false) + ZIP_DEBUGINFO_FILES:=0 +endif + # Sneak this in via the spec.gmk file, since we don't want to mess around too much with the Hotspot make files. # This is needed to get the LOG setting to work properly. include $(SRC_ROOT)/common/makefiles/MakeBase.gmk diff --git a/common/autoconf/jdk-options.m4 b/common/autoconf/jdk-options.m4 index 39e003fd9f0..756c614f439 100644 --- a/common/autoconf/jdk-options.m4 +++ b/common/autoconf/jdk-options.m4 @@ -432,32 +432,30 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_DEBUG_SYMBOLS], # ENABLE_DEBUG_SYMBOLS # This must be done after the toolchain is setup, since we're looking at objcopy. # -ENABLE_DEBUG_SYMBOLS=default - -# default on macosx is no... -if test "x$OPENJDK_TARGET_OS" = xmacosx; then - ENABLE_DEBUG_SYMBOLS=no -fi - AC_ARG_ENABLE([debug-symbols], - [AS_HELP_STRING([--disable-debug-symbols],[disable generation of debug symbols @<:@enabled@:>@])], - [ENABLE_DEBUG_SYMBOLS=${enable_debug_symbols}], -) + [AS_HELP_STRING([--disable-debug-symbols],[disable generation of debug symbols @<:@enabled@:>@])]) AC_MSG_CHECKING([if we should generate debug symbols]) -if test "x$ENABLE_DEBUG_SYMBOLS" = "xyes" && test "x$OBJCOPY" = x; then +if test "x$enable_debug_symbols" = "xyes" && test "x$OBJCOPY" = x; then # explicit enabling of enable-debug-symbols and can't find objcopy # this is an error AC_MSG_ERROR([Unable to find objcopy, cannot enable debug-symbols]) fi -if test "x$ENABLE_DEBUG_SYMBOLS" = "xdefault"; then +if test "x$enable_debug_symbols" = "xyes"; then + ENABLE_DEBUG_SYMBOLS=true +elif test "x$enable_debug_symbols" = "xno"; then + ENABLE_DEBUG_SYMBOLS=false +else + # default on macosx is false + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + ENABLE_DEBUG_SYMBOLS=false # Default is on if objcopy is found, otherwise off - if test "x$OBJCOPY" != x || test "x$OPENJDK_TARGET_OS" = xwindows; then - ENABLE_DEBUG_SYMBOLS=yes + elif test "x$OBJCOPY" != x || test "x$OPENJDK_TARGET_OS" = xwindows; then + ENABLE_DEBUG_SYMBOLS=true else - ENABLE_DEBUG_SYMBOLS=no + ENABLE_DEBUG_SYMBOLS=false fi fi @@ -466,22 +464,16 @@ AC_MSG_RESULT([$ENABLE_DEBUG_SYMBOLS]) # # ZIP_DEBUGINFO_FILES # -ZIP_DEBUGINFO_FILES=yes - AC_ARG_ENABLE([zip-debug-info], - [AS_HELP_STRING([--disable-zip-debug-info],[disable zipping of debug-info files @<:@enabled@:>@])], - [ZIP_DEBUGINFO_FILES=${enable_zip_debug_info}], -) + [AS_HELP_STRING([--disable-zip-debug-info],[disable zipping of debug-info files @<:@enabled@:>@])]) AC_MSG_CHECKING([if we should zip debug-info files]) -AC_MSG_RESULT([$ZIP_DEBUGINFO_FILES]) +AC_MSG_RESULT([${enable_zip_debug_info}]) -# Hotspot wants ZIP_DEBUGINFO_FILES to be 1 for yes -# use that... -if test "x$ZIP_DEBUGINFO_FILES" = "xyes"; then - ZIP_DEBUGINFO_FILES=1 +if test "x${enable_zip_debug_info}" = "xno"; then + ZIP_DEBUGINFO_FILES=false else - ZIP_DEBUGINFO_FILES=0 + ZIP_DEBUGINFO_FILES=true fi AC_SUBST(ENABLE_DEBUG_SYMBOLS) diff --git a/common/autoconf/toolchain.m4 b/common/autoconf/toolchain.m4 index 406a2511677..92c9f2e5960 100644 --- a/common/autoconf/toolchain.m4 +++ b/common/autoconf/toolchain.m4 @@ -114,13 +114,25 @@ AC_DEFUN([TOOLCHAIN_FIND_COMPILER], [ COMPILER_NAME=$2 - # Do a first initial attempt at searching the list of compiler names. + $1= + # If TOOLS_DIR is set, check for all compiler names in there first + # before checking the rest of the PATH. + if test -n "$TOOLS_DIR"; then + PATH_save="$PATH" + PATH="$TOOLS_DIR" + AC_PATH_PROGS(TOOLS_DIR_$1, $3) + $1=$TOOLS_DIR_$1 + PATH="$PATH_save" + fi + # AC_PATH_PROGS can't be run multiple times with the same variable, # so create a new name for this run. - AC_PATH_PROGS(POTENTIAL_$1, $3) - $1=$POTENTIAL_$1 + if test "x[$]$1" = x; then + AC_PATH_PROGS(POTENTIAL_$1, $3) + $1=$POTENTIAL_$1 + fi - if test "x$[$]$1" = x; then + if test "x[$]$1" = x; then HELP_MSG_MISSING_DEPENDENCY([devkit]) AC_MSG_ERROR([Could not find a $COMPILER_NAME compiler. $HELP_MSG]) fi diff --git a/common/bin/hgforest.sh b/common/bin/hgforest.sh new file mode 100644 index 00000000000..cbda87160ba --- /dev/null +++ b/common/bin/hgforest.sh @@ -0,0 +1,194 @@ +#!/bin/sh + +# +# Copyright (c) 2009, 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. +# + +# Shell script for a fast parallel forest command +command="$1" +pull_extra_base="$2" + +# Python always buffers stdout significantly, thus we will not see any output from hg clone jdk, +# until a lot of time has passed! By passing -u to python, we get incremental updates +# on stdout. Much nicer. +whichhg="`which hg`" + +if [ "${whichhg}" = "" ] ; then + echo Cannot find hg! + exit 1 +fi + +if [ "" = "$command" ] ; then + echo No command to hg supplied! + exit 1 +fi + +has_hash_bang="`head -n 1 "${whichhg}" | cut -b 1-2`" +python="" +bpython="" + +if [ "#!" = "$has_hash_bang" ] ; then + python="`head -n 1 ${whichhg} | cut -b 3-`" + bpython="`basename "$python"`" +fi + +if [ "python" = "$bpython" -a -x "$python" ] ; then + hg="${python} -u ${whichhg}" +else + echo Cannot find python from hg launcher. Running plain hg, which probably has buffered stdout. + hg="hg" +fi + +# Clean out the temporary directory that stores the pid files. +tmp=/tmp/forest.$$ +rm -f -r ${tmp} +mkdir -p ${tmp} + +safe_interrupt () { + if [ -d ${tmp} ]; then + if [ "`ls ${tmp}`" != "" ]; then + echo "Waiting for processes ( `cat ${tmp}/* | tr '\n' ' '`) to terminate nicely!" + sleep 1 + # Pipe stderr to dev/null to silence kill, that complains when trying to kill + # a subprocess that has already exited. + kill -TERM `cat ${tmp}/* | tr '\n' ' '` 2> /dev/null + wait + echo Interrupt complete! + fi + fi + rm -f -r ${tmp} + exit 1 +} + +nice_exit () { + if [ -d ${tmp} ]; then + if [ "`ls ${tmp}`" != "" ]; then + wait + fi + fi + rm -f -r ${tmp} +} + +trap 'safe_interrupt' INT QUIT +trap 'nice_exit' EXIT + +# Only look in specific locations for possible forests (avoids long searches) +pull_default="" +repos="" +repos_extra="" +if [ "${command}" = "clone" -o "${command}" = "fclone" ] ; then + subrepos="corba jaxp jaxws langtools jdk hotspot" + if [ -f .hg/hgrc ] ; then + pull_default=`hg paths default` + if [ "${pull_default}" = "" ] ; then + echo "ERROR: Need initial clone with 'hg paths default' defined" + exit 1 + fi + fi + if [ "${pull_default}" = "" ] ; then + echo "ERROR: Need initial repository to use this script" + exit 1 + fi + for i in ${subrepos} ; do + if [ ! -f ${i}/.hg/hgrc ] ; then + repos="${repos} ${i}" + fi + done + if [ "${pull_extra_base}" != "" ] ; then + subrepos_extra="jdk/src/closed jdk/make/closed jdk/test/closed hotspot/make/closed hotspot/src/closed hotspot/test/closed deploy install sponsors pubs" + pull_default_tail=`echo ${pull_default} | sed -e 's@^.*://[^/]*/\(.*\)@\1@'` + pull_extra="${pull_extra_base}/${pull_default_tail}" + for i in ${subrepos_extra} ; do + if [ ! -f ${i}/.hg/hgrc ] ; then + repos_extra="${repos_extra} ${i}" + fi + done + fi + at_a_time=2 + # Any repos to deal with? + if [ "${repos}" = "" -a "${repos_extra}" = "" ] ; then + exit + fi +else + hgdirs=`ls -d ./.hg ./*/.hg ./*/*/.hg ./*/*/*/.hg ./*/*/*/*/.hg 2>/dev/null` + # Derive repository names from the .hg directory locations + for i in ${hgdirs} ; do + repos="${repos} `echo ${i} | sed -e 's@/.hg$@@'`" + done + for i in ${repos} ; do + if [ -h ${i}/.hg/store/lock -o -f ${i}/.hg/store/lock ] ; then + locked="${i} ${locked}" + fi + done + at_a_time=8 + # Any repos to deal with? + if [ "${repos}" = "" ] ; then + echo "No repositories to process." + exit + fi + if [ "${locked}" != "" ] ; then + echo "These repositories are locked: ${locked}" + exit + fi +fi + +# Echo out what repositories we do a command on. +echo "# Repositories: ${repos} ${repos_extra}" +echo + +# Run the supplied command on all repos in parallel. +n=0 +for i in ${repos} ${repos_extra} ; do + n=`expr ${n} '+' 1` + repopidfile=`echo ${i} | sed -e 's@./@@' -e 's@/@_@g'` + reponame=`echo ${i} | sed -e :a -e 's/^.\{1,20\}$/ &/;ta'` + pull_base="${pull_default}" + for j in $repos_extra ; do + if [ "$i" = "$j" ] ; then + pull_base="${pull_extra}" + fi + done + ( + ( + if [ "${command}" = "clone" -o "${command}" = "fclone" ] ; then + pull_newrepo="`echo ${pull_base}/${i} | sed -e 's@\([^:]/\)//*@\1@g'`" + echo ${hg} clone ${pull_newrepo} ${i} + ${hg} clone ${pull_newrepo} ${i} & + else + echo "cd ${i} && ${hg} $*" + cd ${i} && ${hg} "$@" & + fi + echo $! > ${tmp}/${repopidfile}.pid + ) 2>&1 | sed -e "s@^@${reponame}: @") & + + if [ `expr ${n} '%' ${at_a_time}` -eq 0 ] ; then + sleep 2 + echo Waiting 5 secs before spawning next background command. + sleep 3 + fi +done +# Wait for all hg commands to complete +wait + +# Terminate with exit 0 all the time (hard to know when to say "failed") +exit 0 + diff --git a/common/makefiles/JavaCompilation.gmk b/common/makefiles/JavaCompilation.gmk index a5b0b532677..ab6004452c3 100644 --- a/common/makefiles/JavaCompilation.gmk +++ b/common/makefiles/JavaCompilation.gmk @@ -275,10 +275,12 @@ define SetupZipArchive # Explicitly excluded files can be given with absolute path. The patsubst solution # isn't perfect but the likelyhood of an absolute path to match something in a src # dir is very small. + # If zip has nothing to do, it returns 12 and would fail the build. Check for 12 + # and only fail if it's not. $$($1_ZIP) : $$($1_ALL_SRCS) $$($1_EXTRA_DEPS) $(MKDIR) -p $$(@D) $(ECHO) Updating $$($1_NAME) - $$(foreach i,$$($1_SRC),(cd $$i && $(ZIP) -qru $$@ . $$($1_ZIP_INCLUDES) $$($1_ZIP_EXCLUDES) -x \*_the.\* $$(addprefix -x$(SPACE),$$(patsubst $$i/%,%,$$($1_EXCLUDE_FILES))))$$(NEWLINE)) true + $$(foreach i,$$($1_SRC),(cd $$i && $(ZIP) -qru $$@ . $$($1_ZIP_INCLUDES) $$($1_ZIP_EXCLUDES) -x \*_the.\* $$(addprefix -x$(SPACE),$$(patsubst $$i/%,%,$$($1_EXCLUDE_FILES))) || test "$$$$?" = "12" )$$(NEWLINE)) true $(TOUCH) $$@ endef diff --git a/common/makefiles/NativeCompilation.gmk b/common/makefiles/NativeCompilation.gmk index 441dfafa502..7ead10caa09 100644 --- a/common/makefiles/NativeCompilation.gmk +++ b/common/makefiles/NativeCompilation.gmk @@ -302,7 +302,7 @@ define SetupNativeCompilation endif ifneq (,$$($1_DEBUG_SYMBOLS)) - ifeq ($(ENABLE_DEBUG_SYMBOLS), yes) + ifeq ($(ENABLE_DEBUG_SYMBOLS), true) # Programs don't get the debug symbols added in the old build. It's not clear if # this is intentional. ifeq ($$($1_PROGRAM),) @@ -394,7 +394,7 @@ define SetupNativeCompilation endif ifneq (,$$($1_DEBUG_SYMBOLS)) - ifeq ($(ENABLE_DEBUG_SYMBOLS), yes) + ifeq ($(ENABLE_DEBUG_SYMBOLS), true) ifeq ($(OPENJDK_TARGET_OS), windows) $1_EXTRA_LDFLAGS+="-pdb:$$($1_OBJECT_DIR)/$$($1_LIBRARY).pdb" \ "-map:$$($1_OBJECT_DIR)/$$($1_LIBRARY).map" @@ -429,7 +429,7 @@ define SetupNativeCompilation endif # Touch to not retrigger rule on rebuild $(TOUCH) $$@ - ifeq ($(ZIP_DEBUGINFO_FILES), 1) + ifeq ($(ZIP_DEBUGINFO_FILES), true) $1 += $$($1_OUTPUT_DIR)/$$(LIBRARY_PREFIX)$$($1_LIBRARY).diz ifeq ($(OPENJDK_TARGET_OS), windows) @@ -472,7 +472,7 @@ define SetupNativeCompilation ifneq (,$$($1_PROGRAM)) # A executable binary has been specified, setup the target for it. ifneq (,$$($1_DEBUG_SYMBOLS)) - ifeq ($(ENABLE_DEBUG_SYMBOLS), yes) + ifeq ($(ENABLE_DEBUG_SYMBOLS), true) ifeq ($(OPENJDK_TARGET_OS), windows) $1_EXTRA_LDFLAGS+="-pdb:$$($1_OBJECT_DIR)/$$($1_PROGRAM).pdb" \ "-map:$$($1_OBJECT_DIR)/$$($1_PROGRAM).map" @@ -507,7 +507,7 @@ define SetupNativeCompilation endif $(TOUCH) $$@ - ifeq ($(ZIP_DEBUGINFO_FILES), 1) + ifeq ($(ZIP_DEBUGINFO_FILES), true) $1 += $$($1_OUTPUT_DIR)/$$($1_PROGRAM).diz ifeq ($(OPENJDK_TARGET_OS), windows) diff --git a/common/makefiles/javadoc/CORE_PKGS.gmk b/common/makefiles/javadoc/CORE_PKGS.gmk index e292869f951..dcfda026ded 100644 --- a/common/makefiles/javadoc/CORE_PKGS.gmk +++ b/common/makefiles/javadoc/CORE_PKGS.gmk @@ -131,6 +131,7 @@ CORE_PKGS = \ java.util.concurrent \ java.util.concurrent.atomic \ java.util.concurrent.locks \ + java.util.function \ java.util.jar \ java.util.logging \ java.util.prefs \ diff --git a/corba/.hgtags b/corba/.hgtags index ce04e380e05..ac56df78b59 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -188,3 +188,5 @@ d54dc53e223ed9ce7d5f4d2cd02ad9d5def3c2db jdk8-b59 54d599a5b4aad83c235d590652fc81f41c2824fb jdk8-b64 5132f7900a8f0c30c3ca7f7a32f9433f4fee7745 jdk8-b65 65771ad1ca557ca26e4979d4dc633cf685435cb8 jdk8-b66 +394515ad2a55d4d54df990b36065505d3e7a3cbb jdk8-b67 +82000531feaa7baef76b6406099e5cd88943d635 jdk8-b68 diff --git a/get_source.sh b/get_source.sh index 24dca4aed48..bc4d18d24c9 100644 --- a/get_source.sh +++ b/get_source.sh @@ -26,8 +26,8 @@ # # Get clones of all nested repositories -sh ./make/scripts/hgforest.sh clone $* +sh ./common/bin/hgforest.sh clone "$@" # Update all existing repositories to the latest sources -sh ./make/scripts/hgforest.sh pull -u +sh ./common/bin/hgforest.sh pull -u diff --git a/hotspot/.hgtags b/hotspot/.hgtags index e9563254ec4..3df3c07725d 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -297,3 +297,7 @@ b4ee7b773144a88af8b6b92e4384dea82cb948d8 hs25-b09 cfc5309f03b7bd6c1567618b63cf1fc74c0f2a8f hs25-b10 01684f7fee1b86222be69bc23841ec2a4416696c jdk8-b66 b61d9c88b759d1594b8af1655598e8fa00393672 hs25-b11 +25bdce771bb3a7ae9825261a284d292cda700122 jdk8-b67 +a35a72dd2e1255239d31f796f9f693e49b36bc9f hs25-b12 +121aa71316af6cd877bf455e775fa3fdbcdd4b65 jdk8-b68 +b6c9c0109a608eedbb6b868d260952990e3c91fe hs25-b13 diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstMethod.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstMethod.java index 3e30820206a..ad495d73bea 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstMethod.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstMethod.java @@ -69,6 +69,8 @@ public class ConstMethod extends VMObject { signatureIndex = new CIntField(type.getCIntegerField("_signature_index"), 0); idnum = new CIntField(type.getCIntegerField("_method_idnum"), 0); maxStack = new CIntField(type.getCIntegerField("_max_stack"), 0); + maxLocals = new CIntField(type.getCIntegerField("_max_locals"), 0); + sizeOfParameters = new CIntField(type.getCIntegerField("_size_of_parameters"), 0); // start of byte code bytecodeOffset = type.getSize(); @@ -96,6 +98,8 @@ public class ConstMethod extends VMObject { private static CIntField signatureIndex; private static CIntField idnum; private static CIntField maxStack; + private static CIntField maxLocals; + private static CIntField sizeOfParameters; // start of bytecode private static long bytecodeOffset; @@ -151,6 +155,14 @@ public class ConstMethod extends VMObject { return maxStack.getValue(this); } + public long getMaxLocals() { + return maxLocals.getValue(this); + } + + public long getSizeOfParameters() { + return sizeOfParameters.getValue(this); + } + public Symbol getName() { return getMethod().getName(); } @@ -247,6 +259,8 @@ public class ConstMethod extends VMObject { visitor.doCInt(signatureIndex, true); visitor.doCInt(codeSize, true); visitor.doCInt(maxStack, true); + visitor.doCInt(maxLocals, true); + visitor.doCInt(sizeOfParameters, true); } // Accessors diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Method.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Method.java index a12d0b1e84e..31dc39c5431 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Method.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Method.java @@ -50,8 +50,6 @@ public class Method extends Metadata { constMethod = type.getAddressField("_constMethod"); methodData = type.getAddressField("_method_data"); methodSize = new CIntField(type.getCIntegerField("_method_size"), 0); - maxLocals = new CIntField(type.getCIntegerField("_max_locals"), 0); - sizeOfParameters = new CIntField(type.getCIntegerField("_size_of_parameters"), 0); accessFlags = new CIntField(type.getCIntegerField("_access_flags"), 0); code = type.getAddressField("_code"); vtableIndex = new CIntField(type.getCIntegerField("_vtable_index"), 0); @@ -83,8 +81,6 @@ public class Method extends Metadata { private static AddressField constMethod; private static AddressField methodData; private static CIntField methodSize; - private static CIntField maxLocals; - private static CIntField sizeOfParameters; private static CIntField accessFlags; private static CIntField vtableIndex; private static CIntField invocationCounter; @@ -134,8 +130,8 @@ public class Method extends Metadata { /** WARNING: this is in words, not useful in this system; use getObjectSize() instead */ public long getMethodSize() { return methodSize.getValue(this); } public long getMaxStack() { return getConstMethod().getMaxStack(); } - public long getMaxLocals() { return maxLocals.getValue(this); } - public long getSizeOfParameters() { return sizeOfParameters.getValue(this); } + public long getMaxLocals() { return getConstMethod().getMaxLocals(); } + public long getSizeOfParameters() { return getConstMethod().getSizeOfParameters(); } public long getNameIndex() { return getConstMethod().getNameIndex(); } public long getSignatureIndex() { return getConstMethod().getSignatureIndex(); } public long getGenericSignatureIndex() { return getConstMethod().getGenericSignatureIndex(); } @@ -282,8 +278,6 @@ public class Method extends Metadata { public void iterateFields(MetadataVisitor visitor) { visitor.doCInt(methodSize, true); - visitor.doCInt(maxLocals, true); - visitor.doCInt(sizeOfParameters, true); visitor.doCInt(accessFlags, true); } diff --git a/hotspot/make/hotspot_version b/hotspot/make/hotspot_version index b49a5266cf4..7883b9bfb56 100644 --- a/hotspot/make/hotspot_version +++ b/hotspot/make/hotspot_version @@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2012 HS_MAJOR_VER=25 HS_MINOR_VER=0 -HS_BUILD_NUMBER=11 +HS_BUILD_NUMBER=13 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 diff --git a/hotspot/make/windows/projectfiles/common/Makefile b/hotspot/make/windows/projectfiles/common/Makefile index f14f9c4ba07..125923e67b2 100644 --- a/hotspot/make/windows/projectfiles/common/Makefile +++ b/hotspot/make/windows/projectfiles/common/Makefile @@ -71,41 +71,36 @@ default:: $(AdditionalTargets) $(JvmtiGeneratedFiles) !include $(HOTSPOTWORKSPACE)/make/hotspot_version -!if "$(HOTSPOT_RELEASE_VERSION)" != "" -HOTSPOT_RELEASE_VERSION="$(HOTSPOT_RELEASE_VERSION)" -!else -HOTSPOT_RELEASE_VERSION="$(HS_MAJOR_VER).$(HS_MINOR_VER)-b$(HS_BUILD_NUMBER)" -!endif !if "$(USER_RELEASE_SUFFIX)" != "" -HOTSPOT_BUILD_VERSION$(HOTSPOT_BUILD_VERSION) = internal-$(USER_RELEASE_SUFFIX) +HOTSPOT_BUILD_VERSION = internal-$(USER_RELEASE_SUFFIX) !else -HOTSPOT_BUILD_VERSION$(HOTSPOT_BUILD_VERSION) = internal +HOTSPOT_BUILD_VERSION = internal !endif -!if "$(HOTSPOT_BUILD_VERSION)" != "" -HOTSPOT_RELEASE_VERSION="$(HOTSPOT_RELEASE_VERSION)-$(HOTSPOT_BUILD_VERSION)" +!if "$(HOTSPOT_RELEASE_VERSION)" != "" +HOTSPOT_RELEASE_VERSION="\\\"$(HOTSPOT_RELEASE_VERSION)\\\"" +!else +HOTSPOT_RELEASE_VERSION="\\\"$(HS_MAJOR_VER).$(HS_MINOR_VER)-b$(HS_BUILD_NUMBER)-$(HOTSPOT_BUILD_VERSION)\\\"" !endif !if "$(JRE_RELEASE_VERSION)" != "" -JRE_RELEASE_VERSION="$(JRE_RELEASE_VERSION)" +JRE_RELEASE_VERSION="\\\"$(JRE_RELEASE_VERSION)\\\"" !else -JRE_RELEASE_VERSION="$(JDK_MAJOR_VER).$(JDK_MINOR_VER).$(JDK_MICRO_VER)" +JRE_RELEASE_VERSION="\\\"$(JDK_MAJOR_VER).$(JDK_MINOR_VER).$(JDK_MICRO_VER)\\\"" !endif # Define HOTSPOT_VM_DISTRO if HOTSPOT_VM_DISTRO is set, # and if it is not see if we have the src/closed directory !if "$(HOTSPOT_VM_DISTRO)" != "" -HOTSPOT_VM_DISTRO="$(HOTSPOT_VM_DISTRO)" +HOTSPOT_VM_DISTRO=$(HOTSPOT_VM_DISTRO) !else !if exists($(HOTSPOTWORKSPACE)\src\closed) -HOTSPOT_VM_DISTRO="Java HotSpot(TM)" +HOTSPOT_VM_DISTRO="\\\"Java HotSpot(TM)\\\"" !else -HOTSPOT_VM_DISTRO="OpenJDK" +HOTSPOT_VM_DISTRO="\\\"OpenJDK\\\"" !endif !endif -ProjectCreatorIDEOptions = $(ProjectCreatorIDEOptions) \ - -define HOTSPOT_RELEASE_VERSION=\\\"$(HOTSPOT_RELEASE_VERSION)\\\" \ - -define JRE_RELEASE_VERSION=\\\"$(JRE_RELEASE_VERSION)\\\" \ - -define HOTSPOT_VM_DISTRO=\\\"$(HOTSPOT_VM_DISTRO)\\\" +ReleaseOptions = -define HOTSPOT_RELEASE_VERSION=$(HOTSPOT_RELEASE_VERSION) -define JRE_RELEASE_VERSION=$(JRE_RELEASE_VERSION) -define HOTSPOT_VM_DISTRO=$(HOTSPOT_VM_DISTRO) +ProjectCreatorIDEOptions = $(ProjectCreatorIDEOptions) $(ReleaseOptions) $(HOTSPOTBUILDSPACE)/$(ProjectFile): $(HOTSPOTBUILDSPACE)/classes/ProjectCreator.class @$(RUN_JAVA) -Djava.class.path="$(HOTSPOTBUILDSPACE)/classes" ProjectCreator WinGammaPlatform$(VcVersion) $(ProjectCreatorIDEOptions) diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp index 25c850c8b46..2cc945ad2a1 100644 --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp @@ -24,4985 +24,8 @@ #include "precompiled.hpp" #include "asm/assembler.hpp" -#include "assembler_sparc.inline.hpp" -#include "gc_interface/collectedHeap.inline.hpp" -#include "interpreter/interpreter.hpp" -#include "memory/cardTableModRefBS.hpp" -#include "memory/resourceArea.hpp" -#include "prims/methodHandles.hpp" -#include "runtime/biasedLocking.hpp" -#include "runtime/interfaceSupport.hpp" -#include "runtime/objectMonitor.hpp" -#include "runtime/os.hpp" -#include "runtime/sharedRuntime.hpp" -#include "runtime/stubRoutines.hpp" -#ifndef SERIALGC -#include "gc_implementation/g1/g1CollectedHeap.inline.hpp" -#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" -#include "gc_implementation/g1/heapRegion.hpp" -#endif - -#ifdef PRODUCT -#define BLOCK_COMMENT(str) /* nothing */ -#define STOP(error) stop(error) -#else -#define BLOCK_COMMENT(str) block_comment(str) -#define STOP(error) block_comment(error); stop(error) -#endif - -// Convert the raw encoding form into the form expected by the -// constructor for Address. -Address Address::make_raw(int base, int index, int scale, int disp, relocInfo::relocType disp_reloc) { - assert(scale == 0, "not supported"); - RelocationHolder rspec; - if (disp_reloc != relocInfo::none) { - rspec = Relocation::spec_simple(disp_reloc); - } - - Register rindex = as_Register(index); - if (rindex != G0) { - Address madr(as_Register(base), rindex); - madr._rspec = rspec; - return madr; - } else { - Address madr(as_Register(base), disp); - madr._rspec = rspec; - return madr; - } -} - -Address Argument::address_in_frame() const { - // Warning: In LP64 mode disp will occupy more than 10 bits, but - // op codes such as ld or ldx, only access disp() to get - // their simm13 argument. - int disp = ((_number - Argument::n_register_parameters + frame::memory_parameter_word_sp_offset) * BytesPerWord) + STACK_BIAS; - if (is_in()) - return Address(FP, disp); // In argument. - else - return Address(SP, disp); // Out argument. -} - -static const char* argumentNames[][2] = { - {"A0","P0"}, {"A1","P1"}, {"A2","P2"}, {"A3","P3"}, {"A4","P4"}, - {"A5","P5"}, {"A6","P6"}, {"A7","P7"}, {"A8","P8"}, {"A9","P9"}, - {"A(n>9)","P(n>9)"} -}; - -const char* Argument::name() const { - int nofArgs = sizeof argumentNames / sizeof argumentNames[0]; - int num = number(); - if (num >= nofArgs) num = nofArgs - 1; - return argumentNames[num][is_in() ? 1 : 0]; -} - -void Assembler::print_instruction(int inst) { - const char* s; - switch (inv_op(inst)) { - default: s = "????"; break; - case call_op: s = "call"; break; - case branch_op: - switch (inv_op2(inst)) { - case fb_op2: s = "fb"; break; - case fbp_op2: s = "fbp"; break; - case br_op2: s = "br"; break; - case bp_op2: s = "bp"; break; - case cb_op2: s = "cb"; break; - case bpr_op2: { - if (is_cbcond(inst)) { - s = is_cxb(inst) ? "cxb" : "cwb"; - } else { - s = "bpr"; - } - break; - } - default: s = "????"; break; - } - } - ::tty->print("%s", s); -} - - -// Patch instruction inst at offset inst_pos to refer to dest_pos -// and return the resulting instruction. -// We should have pcs, not offsets, but since all is relative, it will work out -// OK. -int Assembler::patched_branch(int dest_pos, int inst, int inst_pos) { - - int m; // mask for displacement field - int v; // new value for displacement field - const int word_aligned_ones = -4; - switch (inv_op(inst)) { - default: ShouldNotReachHere(); - case call_op: m = wdisp(word_aligned_ones, 0, 30); v = wdisp(dest_pos, inst_pos, 30); break; - case branch_op: - switch (inv_op2(inst)) { - case fbp_op2: m = wdisp( word_aligned_ones, 0, 19); v = wdisp( dest_pos, inst_pos, 19); break; - case bp_op2: m = wdisp( word_aligned_ones, 0, 19); v = wdisp( dest_pos, inst_pos, 19); break; - case fb_op2: m = wdisp( word_aligned_ones, 0, 22); v = wdisp( dest_pos, inst_pos, 22); break; - case br_op2: m = wdisp( word_aligned_ones, 0, 22); v = wdisp( dest_pos, inst_pos, 22); break; - case cb_op2: m = wdisp( word_aligned_ones, 0, 22); v = wdisp( dest_pos, inst_pos, 22); break; - case bpr_op2: { - if (is_cbcond(inst)) { - m = wdisp10(word_aligned_ones, 0); - v = wdisp10(dest_pos, inst_pos); - } else { - m = wdisp16(word_aligned_ones, 0); - v = wdisp16(dest_pos, inst_pos); - } - break; - } - default: ShouldNotReachHere(); - } - } - return inst & ~m | v; -} - -// Return the offset of the branch destionation of instruction inst -// at offset pos. -// Should have pcs, but since all is relative, it works out. -int Assembler::branch_destination(int inst, int pos) { - int r; - switch (inv_op(inst)) { - default: ShouldNotReachHere(); - case call_op: r = inv_wdisp(inst, pos, 30); break; - case branch_op: - switch (inv_op2(inst)) { - case fbp_op2: r = inv_wdisp( inst, pos, 19); break; - case bp_op2: r = inv_wdisp( inst, pos, 19); break; - case fb_op2: r = inv_wdisp( inst, pos, 22); break; - case br_op2: r = inv_wdisp( inst, pos, 22); break; - case cb_op2: r = inv_wdisp( inst, pos, 22); break; - case bpr_op2: { - if (is_cbcond(inst)) { - r = inv_wdisp10(inst, pos); - } else { - r = inv_wdisp16(inst, pos); - } - break; - } - default: ShouldNotReachHere(); - } - } - return r; -} +#include "asm/assembler.inline.hpp" int AbstractAssembler::code_fill_byte() { return 0x00; // illegal instruction 0x00000000 } - -Assembler::Condition Assembler::reg_cond_to_cc_cond(Assembler::RCondition in) { - switch (in) { - case rc_z: return equal; - case rc_lez: return lessEqual; - case rc_lz: return less; - case rc_nz: return notEqual; - case rc_gz: return greater; - case rc_gez: return greaterEqual; - default: - ShouldNotReachHere(); - } - return equal; -} - -// Generate a bunch 'o stuff (including v9's -#ifndef PRODUCT -void Assembler::test_v9() { - add( G0, G1, G2 ); - add( G3, 0, G4 ); - - addcc( G5, G6, G7 ); - addcc( I0, 1, I1 ); - addc( I2, I3, I4 ); - addc( I5, -1, I6 ); - addccc( I7, L0, L1 ); - addccc( L2, (1 << 12) - 2, L3 ); - - Label lbl1, lbl2, lbl3; - - bind(lbl1); - - bpr( rc_z, true, pn, L4, pc(), relocInfo::oop_type ); - delayed()->nop(); - bpr( rc_lez, false, pt, L5, lbl1); - delayed()->nop(); - - fb( f_never, true, pc() + 4, relocInfo::none); - delayed()->nop(); - fb( f_notEqual, false, lbl2 ); - delayed()->nop(); - - fbp( f_notZero, true, fcc0, pn, pc() - 4, relocInfo::none); - delayed()->nop(); - fbp( f_lessOrGreater, false, fcc1, pt, lbl3 ); - delayed()->nop(); - - br( equal, true, pc() + 1024, relocInfo::none); - delayed()->nop(); - br( lessEqual, false, lbl1 ); - delayed()->nop(); - br( never, false, lbl1 ); - delayed()->nop(); - - bp( less, true, icc, pn, pc(), relocInfo::none); - delayed()->nop(); - bp( lessEqualUnsigned, false, xcc, pt, lbl2 ); - delayed()->nop(); - - call( pc(), relocInfo::none); - delayed()->nop(); - call( lbl3 ); - delayed()->nop(); - - - casa( L6, L7, O0 ); - casxa( O1, O2, O3, 0 ); - - udiv( O4, O5, O7 ); - udiv( G0, (1 << 12) - 1, G1 ); - sdiv( G1, G2, G3 ); - sdiv( G4, -((1 << 12) - 1), G5 ); - udivcc( G6, G7, I0 ); - udivcc( I1, -((1 << 12) - 2), I2 ); - sdivcc( I3, I4, I5 ); - sdivcc( I6, -((1 << 12) - 0), I7 ); - - done(); - retry(); - - fadd( FloatRegisterImpl::S, F0, F1, F2 ); - fsub( FloatRegisterImpl::D, F34, F0, F62 ); - - fcmp( FloatRegisterImpl::Q, fcc0, F0, F60); - fcmpe( FloatRegisterImpl::S, fcc1, F31, F30); - - ftox( FloatRegisterImpl::D, F2, F4 ); - ftoi( FloatRegisterImpl::Q, F4, F8 ); - - ftof( FloatRegisterImpl::S, FloatRegisterImpl::Q, F3, F12 ); - - fxtof( FloatRegisterImpl::S, F4, F5 ); - fitof( FloatRegisterImpl::D, F6, F8 ); - - fmov( FloatRegisterImpl::Q, F16, F20 ); - fneg( FloatRegisterImpl::S, F6, F7 ); - fabs( FloatRegisterImpl::D, F10, F12 ); - - fmul( FloatRegisterImpl::Q, F24, F28, F32 ); - fmul( FloatRegisterImpl::S, FloatRegisterImpl::D, F8, F9, F14 ); - fdiv( FloatRegisterImpl::S, F10, F11, F12 ); - - fsqrt( FloatRegisterImpl::S, F13, F14 ); - - flush( L0, L1 ); - flush( L2, -1 ); - - flushw(); - - illtrap( (1 << 22) - 2); - - impdep1( 17, (1 << 19) - 1 ); - impdep2( 3, 0 ); - - jmpl( L3, L4, L5 ); - delayed()->nop(); - jmpl( L6, -1, L7, Relocation::spec_simple(relocInfo::none)); - delayed()->nop(); - - - ldf( FloatRegisterImpl::S, O0, O1, F15 ); - ldf( FloatRegisterImpl::D, O2, -1, F14 ); - - - ldfsr( O3, O4 ); - ldfsr( O5, -1 ); - ldxfsr( O6, O7 ); - ldxfsr( I0, -1 ); - - ldfa( FloatRegisterImpl::D, I1, I2, 1, F16 ); - ldfa( FloatRegisterImpl::Q, I3, -1, F36 ); - - ldsb( I4, I5, I6 ); - ldsb( I7, -1, G0 ); - ldsh( G1, G3, G4 ); - ldsh( G5, -1, G6 ); - ldsw( G7, L0, L1 ); - ldsw( L2, -1, L3 ); - ldub( L4, L5, L6 ); - ldub( L7, -1, O0 ); - lduh( O1, O2, O3 ); - lduh( O4, -1, O5 ); - lduw( O6, O7, G0 ); - lduw( G1, -1, G2 ); - ldx( G3, G4, G5 ); - ldx( G6, -1, G7 ); - ldd( I0, I1, I2 ); - ldd( I3, -1, I4 ); - - ldsba( I5, I6, 2, I7 ); - ldsba( L0, -1, L1 ); - ldsha( L2, L3, 3, L4 ); - ldsha( L5, -1, L6 ); - ldswa( L7, O0, (1 << 8) - 1, O1 ); - ldswa( O2, -1, O3 ); - lduba( O4, O5, 0, O6 ); - lduba( O7, -1, I0 ); - lduha( I1, I2, 1, I3 ); - lduha( I4, -1, I5 ); - lduwa( I6, I7, 2, L0 ); - lduwa( L1, -1, L2 ); - ldxa( L3, L4, 3, L5 ); - ldxa( L6, -1, L7 ); - ldda( G0, G1, 4, G2 ); - ldda( G3, -1, G4 ); - - ldstub( G5, G6, G7 ); - ldstub( O0, -1, O1 ); - - ldstuba( O2, O3, 5, O4 ); - ldstuba( O5, -1, O6 ); - - and3( I0, L0, O0 ); - and3( G7, -1, O7 ); - andcc( L2, I2, G2 ); - andcc( L4, -1, G4 ); - andn( I5, I6, I7 ); - andn( I6, -1, I7 ); - andncc( I5, I6, I7 ); - andncc( I7, -1, I6 ); - or3( I5, I6, I7 ); - or3( I7, -1, I6 ); - orcc( I5, I6, I7 ); - orcc( I7, -1, I6 ); - orn( I5, I6, I7 ); - orn( I7, -1, I6 ); - orncc( I5, I6, I7 ); - orncc( I7, -1, I6 ); - xor3( I5, I6, I7 ); - xor3( I7, -1, I6 ); - xorcc( I5, I6, I7 ); - xorcc( I7, -1, I6 ); - xnor( I5, I6, I7 ); - xnor( I7, -1, I6 ); - xnorcc( I5, I6, I7 ); - xnorcc( I7, -1, I6 ); - - membar( Membar_mask_bits(StoreStore | LoadStore | StoreLoad | LoadLoad | Sync | MemIssue | Lookaside ) ); - membar( StoreStore ); - membar( LoadStore ); - membar( StoreLoad ); - membar( LoadLoad ); - membar( Sync ); - membar( MemIssue ); - membar( Lookaside ); - - fmov( FloatRegisterImpl::S, f_ordered, true, fcc2, F16, F17 ); - fmov( FloatRegisterImpl::D, rc_lz, L5, F18, F20 ); - - movcc( overflowClear, false, icc, I6, L4 ); - movcc( f_unorderedOrEqual, true, fcc2, (1 << 10) - 1, O0 ); - - movr( rc_nz, I5, I6, I7 ); - movr( rc_gz, L1, -1, L2 ); - - mulx( I5, I6, I7 ); - mulx( I7, -1, I6 ); - sdivx( I5, I6, I7 ); - sdivx( I7, -1, I6 ); - udivx( I5, I6, I7 ); - udivx( I7, -1, I6 ); - - umul( I5, I6, I7 ); - umul( I7, -1, I6 ); - smul( I5, I6, I7 ); - smul( I7, -1, I6 ); - umulcc( I5, I6, I7 ); - umulcc( I7, -1, I6 ); - smulcc( I5, I6, I7 ); - smulcc( I7, -1, I6 ); - - mulscc( I5, I6, I7 ); - mulscc( I7, -1, I6 ); - - nop(); - - - popc( G0, G1); - popc( -1, G2); - - prefetch( L1, L2, severalReads ); - prefetch( L3, -1, oneRead ); - prefetcha( O3, O2, 6, severalWritesAndPossiblyReads ); - prefetcha( G2, -1, oneWrite ); - - rett( I7, I7); - delayed()->nop(); - rett( G0, -1, relocInfo::none); - delayed()->nop(); - - save( I5, I6, I7 ); - save( I7, -1, I6 ); - restore( I5, I6, I7 ); - restore( I7, -1, I6 ); - - saved(); - restored(); - - sethi( 0xaaaaaaaa, I3, Relocation::spec_simple(relocInfo::none)); - - sll( I5, I6, I7 ); - sll( I7, 31, I6 ); - srl( I5, I6, I7 ); - srl( I7, 0, I6 ); - sra( I5, I6, I7 ); - sra( I7, 30, I6 ); - sllx( I5, I6, I7 ); - sllx( I7, 63, I6 ); - srlx( I5, I6, I7 ); - srlx( I7, 0, I6 ); - srax( I5, I6, I7 ); - srax( I7, 62, I6 ); - - sir( -1 ); - - stbar(); - - stf( FloatRegisterImpl::Q, F40, G0, I7 ); - stf( FloatRegisterImpl::S, F18, I3, -1 ); - - stfsr( L1, L2 ); - stfsr( I7, -1 ); - stxfsr( I6, I5 ); - stxfsr( L4, -1 ); - - stfa( FloatRegisterImpl::D, F22, I6, I7, 7 ); - stfa( FloatRegisterImpl::Q, F44, G0, -1 ); - - stb( L5, O2, I7 ); - stb( I7, I6, -1 ); - sth( L5, O2, I7 ); - sth( I7, I6, -1 ); - stw( L5, O2, I7 ); - stw( I7, I6, -1 ); - stx( L5, O2, I7 ); - stx( I7, I6, -1 ); - std( L5, O2, I7 ); - std( I7, I6, -1 ); - - stba( L5, O2, I7, 8 ); - stba( I7, I6, -1 ); - stha( L5, O2, I7, 9 ); - stha( I7, I6, -1 ); - stwa( L5, O2, I7, 0 ); - stwa( I7, I6, -1 ); - stxa( L5, O2, I7, 11 ); - stxa( I7, I6, -1 ); - stda( L5, O2, I7, 12 ); - stda( I7, I6, -1 ); - - sub( I5, I6, I7 ); - sub( I7, -1, I6 ); - subcc( I5, I6, I7 ); - subcc( I7, -1, I6 ); - subc( I5, I6, I7 ); - subc( I7, -1, I6 ); - subccc( I5, I6, I7 ); - subccc( I7, -1, I6 ); - - swap( I5, I6, I7 ); - swap( I7, -1, I6 ); - - swapa( G0, G1, 13, G2 ); - swapa( I7, -1, I6 ); - - taddcc( I5, I6, I7 ); - taddcc( I7, -1, I6 ); - taddcctv( I5, I6, I7 ); - taddcctv( I7, -1, I6 ); - - tsubcc( I5, I6, I7 ); - tsubcc( I7, -1, I6 ); - tsubcctv( I5, I6, I7 ); - tsubcctv( I7, -1, I6 ); - - trap( overflowClear, xcc, G0, G1 ); - trap( lessEqual, icc, I7, 17 ); - - bind(lbl2); - bind(lbl3); - - code()->decode(); -} - -// Generate a bunch 'o stuff unique to V8 -void Assembler::test_v8_onlys() { - Label lbl1; - - cb( cp_0or1or2, false, pc() - 4, relocInfo::none); - delayed()->nop(); - cb( cp_never, true, lbl1); - delayed()->nop(); - - cpop1(1, 2, 3, 4); - cpop2(5, 6, 7, 8); - - ldc( I0, I1, 31); - ldc( I2, -1, 0); - - lddc( I4, I4, 30); - lddc( I6, 0, 1 ); - - ldcsr( L0, L1, 0); - ldcsr( L1, (1 << 12) - 1, 17 ); - - stc( 31, L4, L5); - stc( 30, L6, -(1 << 12) ); - - stdc( 0, L7, G0); - stdc( 1, G1, 0 ); - - stcsr( 16, G2, G3); - stcsr( 17, G4, 1 ); - - stdcq( 4, G5, G6); - stdcq( 5, G7, -1 ); - - bind(lbl1); - - code()->decode(); -} -#endif - -// Implementation of MacroAssembler - -void MacroAssembler::null_check(Register reg, int offset) { - if (needs_explicit_null_check((intptr_t)offset)) { - // provoke OS NULL exception if reg = NULL by - // accessing M[reg] w/o changing any registers - ld_ptr(reg, 0, G0); - } - else { - // nothing to do, (later) access of M[reg + offset] - // will provoke OS NULL exception if reg = NULL - } -} - -// Ring buffer jumps - -#ifndef PRODUCT -void MacroAssembler::ret( bool trace ) { if (trace) { - mov(I7, O7); // traceable register - JMP(O7, 2 * BytesPerInstWord); - } else { - jmpl( I7, 2 * BytesPerInstWord, G0 ); - } - } - -void MacroAssembler::retl( bool trace ) { if (trace) JMP(O7, 2 * BytesPerInstWord); - else jmpl( O7, 2 * BytesPerInstWord, G0 ); } -#endif /* PRODUCT */ - - -void MacroAssembler::jmp2(Register r1, Register r2, const char* file, int line ) { - assert_not_delayed(); - // This can only be traceable if r1 & r2 are visible after a window save - if (TraceJumps) { -#ifndef PRODUCT - save_frame(0); - verify_thread(); - ld(G2_thread, in_bytes(JavaThread::jmp_ring_index_offset()), O0); - add(G2_thread, in_bytes(JavaThread::jmp_ring_offset()), O1); - sll(O0, exact_log2(4*sizeof(intptr_t)), O2); - add(O2, O1, O1); - - add(r1->after_save(), r2->after_save(), O2); - set((intptr_t)file, O3); - set(line, O4); - Label L; - // get nearby pc, store jmp target - call(L, relocInfo::none); // No relocation for call to pc+0x8 - delayed()->st(O2, O1, 0); - bind(L); - - // store nearby pc - st(O7, O1, sizeof(intptr_t)); - // store file - st(O3, O1, 2*sizeof(intptr_t)); - // store line - st(O4, O1, 3*sizeof(intptr_t)); - add(O0, 1, O0); - and3(O0, JavaThread::jump_ring_buffer_size - 1, O0); - st(O0, G2_thread, in_bytes(JavaThread::jmp_ring_index_offset())); - restore(); -#endif /* PRODUCT */ - } - jmpl(r1, r2, G0); -} -void MacroAssembler::jmp(Register r1, int offset, const char* file, int line ) { - assert_not_delayed(); - // This can only be traceable if r1 is visible after a window save - if (TraceJumps) { -#ifndef PRODUCT - save_frame(0); - verify_thread(); - ld(G2_thread, in_bytes(JavaThread::jmp_ring_index_offset()), O0); - add(G2_thread, in_bytes(JavaThread::jmp_ring_offset()), O1); - sll(O0, exact_log2(4*sizeof(intptr_t)), O2); - add(O2, O1, O1); - - add(r1->after_save(), offset, O2); - set((intptr_t)file, O3); - set(line, O4); - Label L; - // get nearby pc, store jmp target - call(L, relocInfo::none); // No relocation for call to pc+0x8 - delayed()->st(O2, O1, 0); - bind(L); - - // store nearby pc - st(O7, O1, sizeof(intptr_t)); - // store file - st(O3, O1, 2*sizeof(intptr_t)); - // store line - st(O4, O1, 3*sizeof(intptr_t)); - add(O0, 1, O0); - and3(O0, JavaThread::jump_ring_buffer_size - 1, O0); - st(O0, G2_thread, in_bytes(JavaThread::jmp_ring_index_offset())); - restore(); -#endif /* PRODUCT */ - } - jmp(r1, offset); -} - -// This code sequence is relocatable to any address, even on LP64. -void MacroAssembler::jumpl(const AddressLiteral& addrlit, Register temp, Register d, int offset, const char* file, int line) { - assert_not_delayed(); - // Force fixed length sethi because NativeJump and NativeFarCall don't handle - // variable length instruction streams. - patchable_sethi(addrlit, temp); - Address a(temp, addrlit.low10() + offset); // Add the offset to the displacement. - if (TraceJumps) { -#ifndef PRODUCT - // Must do the add here so relocation can find the remainder of the - // value to be relocated. - add(a.base(), a.disp(), a.base(), addrlit.rspec(offset)); - save_frame(0); - verify_thread(); - ld(G2_thread, in_bytes(JavaThread::jmp_ring_index_offset()), O0); - add(G2_thread, in_bytes(JavaThread::jmp_ring_offset()), O1); - sll(O0, exact_log2(4*sizeof(intptr_t)), O2); - add(O2, O1, O1); - - set((intptr_t)file, O3); - set(line, O4); - Label L; - - // get nearby pc, store jmp target - call(L, relocInfo::none); // No relocation for call to pc+0x8 - delayed()->st(a.base()->after_save(), O1, 0); - bind(L); - - // store nearby pc - st(O7, O1, sizeof(intptr_t)); - // store file - st(O3, O1, 2*sizeof(intptr_t)); - // store line - st(O4, O1, 3*sizeof(intptr_t)); - add(O0, 1, O0); - and3(O0, JavaThread::jump_ring_buffer_size - 1, O0); - st(O0, G2_thread, in_bytes(JavaThread::jmp_ring_index_offset())); - restore(); - jmpl(a.base(), G0, d); -#else - jmpl(a.base(), a.disp(), d); -#endif /* PRODUCT */ - } else { - jmpl(a.base(), a.disp(), d); - } -} - -void MacroAssembler::jump(const AddressLiteral& addrlit, Register temp, int offset, const char* file, int line) { - jumpl(addrlit, temp, G0, offset, file, line); -} - - -// Conditional breakpoint (for assertion checks in assembly code) -void MacroAssembler::breakpoint_trap(Condition c, CC cc) { - trap(c, cc, G0, ST_RESERVED_FOR_USER_0); -} - -// We want to use ST_BREAKPOINT here, but the debugger is confused by it. -void MacroAssembler::breakpoint_trap() { - trap(ST_RESERVED_FOR_USER_0); -} - -// flush windows (except current) using flushw instruction if avail. -void MacroAssembler::flush_windows() { - if (VM_Version::v9_instructions_work()) flushw(); - else flush_windows_trap(); -} - -// Write serialization page so VM thread can do a pseudo remote membar -// We use the current thread pointer to calculate a thread specific -// offset to write to within the page. This minimizes bus traffic -// due to cache line collision. -void MacroAssembler::serialize_memory(Register thread, Register tmp1, Register tmp2) { - srl(thread, os::get_serialize_page_shift_count(), tmp2); - if (Assembler::is_simm13(os::vm_page_size())) { - and3(tmp2, (os::vm_page_size() - sizeof(int)), tmp2); - } - else { - set((os::vm_page_size() - sizeof(int)), tmp1); - and3(tmp2, tmp1, tmp2); - } - set(os::get_memory_serialize_page(), tmp1); - st(G0, tmp1, tmp2); -} - - - -void MacroAssembler::enter() { - Unimplemented(); -} - -void MacroAssembler::leave() { - Unimplemented(); -} - -void MacroAssembler::mult(Register s1, Register s2, Register d) { - if(VM_Version::v9_instructions_work()) { - mulx (s1, s2, d); - } else { - smul (s1, s2, d); - } -} - -void MacroAssembler::mult(Register s1, int simm13a, Register d) { - if(VM_Version::v9_instructions_work()) { - mulx (s1, simm13a, d); - } else { - smul (s1, simm13a, d); - } -} - - -#ifdef ASSERT -void MacroAssembler::read_ccr_v8_assert(Register ccr_save) { - const Register s1 = G3_scratch; - const Register s2 = G4_scratch; - Label get_psr_test; - // Get the condition codes the V8 way. - read_ccr_trap(s1); - mov(ccr_save, s2); - // This is a test of V8 which has icc but not xcc - // so mask off the xcc bits - and3(s2, 0xf, s2); - // Compare condition codes from the V8 and V9 ways. - subcc(s2, s1, G0); - br(Assembler::notEqual, true, Assembler::pt, get_psr_test); - delayed()->breakpoint_trap(); - bind(get_psr_test); -} - -void MacroAssembler::write_ccr_v8_assert(Register ccr_save) { - const Register s1 = G3_scratch; - const Register s2 = G4_scratch; - Label set_psr_test; - // Write out the saved condition codes the V8 way - write_ccr_trap(ccr_save, s1, s2); - // Read back the condition codes using the V9 instruction - rdccr(s1); - mov(ccr_save, s2); - // This is a test of V8 which has icc but not xcc - // so mask off the xcc bits - and3(s2, 0xf, s2); - and3(s1, 0xf, s1); - // Compare the V8 way with the V9 way. - subcc(s2, s1, G0); - br(Assembler::notEqual, true, Assembler::pt, set_psr_test); - delayed()->breakpoint_trap(); - bind(set_psr_test); -} -#else -#define read_ccr_v8_assert(x) -#define write_ccr_v8_assert(x) -#endif // ASSERT - -void MacroAssembler::read_ccr(Register ccr_save) { - if (VM_Version::v9_instructions_work()) { - rdccr(ccr_save); - // Test code sequence used on V8. Do not move above rdccr. - read_ccr_v8_assert(ccr_save); - } else { - read_ccr_trap(ccr_save); - } -} - -void MacroAssembler::write_ccr(Register ccr_save) { - if (VM_Version::v9_instructions_work()) { - // Test code sequence used on V8. Do not move below wrccr. - write_ccr_v8_assert(ccr_save); - wrccr(ccr_save); - } else { - const Register temp_reg1 = G3_scratch; - const Register temp_reg2 = G4_scratch; - write_ccr_trap(ccr_save, temp_reg1, temp_reg2); - } -} - - -// Calls to C land - -#ifdef ASSERT -// a hook for debugging -static Thread* reinitialize_thread() { - return ThreadLocalStorage::thread(); -} -#else -#define reinitialize_thread ThreadLocalStorage::thread -#endif - -#ifdef ASSERT -address last_get_thread = NULL; -#endif - -// call this when G2_thread is not known to be valid -void MacroAssembler::get_thread() { - save_frame(0); // to avoid clobbering O0 - mov(G1, L0); // avoid clobbering G1 - mov(G5_method, L1); // avoid clobbering G5 - mov(G3, L2); // avoid clobbering G3 also - mov(G4, L5); // avoid clobbering G4 -#ifdef ASSERT - AddressLiteral last_get_thread_addrlit(&last_get_thread); - set(last_get_thread_addrlit, L3); - inc(L4, get_pc(L4) + 2 * BytesPerInstWord); // skip getpc() code + inc + st_ptr to point L4 at call - st_ptr(L4, L3, 0); -#endif - call(CAST_FROM_FN_PTR(address, reinitialize_thread), relocInfo::runtime_call_type); - delayed()->nop(); - mov(L0, G1); - mov(L1, G5_method); - mov(L2, G3); - mov(L5, G4); - restore(O0, 0, G2_thread); -} - -static Thread* verify_thread_subroutine(Thread* gthread_value) { - Thread* correct_value = ThreadLocalStorage::thread(); - guarantee(gthread_value == correct_value, "G2_thread value must be the thread"); - return correct_value; -} - -void MacroAssembler::verify_thread() { - if (VerifyThread) { - // NOTE: this chops off the heads of the 64-bit O registers. -#ifdef CC_INTERP - save_frame(0); -#else - // make sure G2_thread contains the right value - save_frame_and_mov(0, Lmethod, Lmethod); // to avoid clobbering O0 (and propagate Lmethod for -Xprof) - mov(G1, L1); // avoid clobbering G1 - // G2 saved below - mov(G3, L3); // avoid clobbering G3 - mov(G4, L4); // avoid clobbering G4 - mov(G5_method, L5); // avoid clobbering G5_method -#endif /* CC_INTERP */ -#if defined(COMPILER2) && !defined(_LP64) - // Save & restore possible 64-bit Long arguments in G-regs - srlx(G1,32,L0); - srlx(G4,32,L6); -#endif - call(CAST_FROM_FN_PTR(address,verify_thread_subroutine), relocInfo::runtime_call_type); - delayed()->mov(G2_thread, O0); - - mov(L1, G1); // Restore G1 - // G2 restored below - mov(L3, G3); // restore G3 - mov(L4, G4); // restore G4 - mov(L5, G5_method); // restore G5_method -#if defined(COMPILER2) && !defined(_LP64) - // Save & restore possible 64-bit Long arguments in G-regs - sllx(L0,32,G2); // Move old high G1 bits high in G2 - srl(G1, 0,G1); // Clear current high G1 bits - or3 (G1,G2,G1); // Recover 64-bit G1 - sllx(L6,32,G2); // Move old high G4 bits high in G2 - srl(G4, 0,G4); // Clear current high G4 bits - or3 (G4,G2,G4); // Recover 64-bit G4 -#endif - restore(O0, 0, G2_thread); - } -} - - -void MacroAssembler::save_thread(const Register thread_cache) { - verify_thread(); - if (thread_cache->is_valid()) { - assert(thread_cache->is_local() || thread_cache->is_in(), "bad volatile"); - mov(G2_thread, thread_cache); - } - if (VerifyThread) { - // smash G2_thread, as if the VM were about to anyway - set(0x67676767, G2_thread); - } -} - - -void MacroAssembler::restore_thread(const Register thread_cache) { - if (thread_cache->is_valid()) { - assert(thread_cache->is_local() || thread_cache->is_in(), "bad volatile"); - mov(thread_cache, G2_thread); - verify_thread(); - } else { - // do it the slow way - get_thread(); - } -} - - -// %%% maybe get rid of [re]set_last_Java_frame -void MacroAssembler::set_last_Java_frame(Register last_java_sp, Register last_Java_pc) { - assert_not_delayed(); - Address flags(G2_thread, JavaThread::frame_anchor_offset() + - JavaFrameAnchor::flags_offset()); - Address pc_addr(G2_thread, JavaThread::last_Java_pc_offset()); - - // Always set last_Java_pc and flags first because once last_Java_sp is visible - // has_last_Java_frame is true and users will look at the rest of the fields. - // (Note: flags should always be zero before we get here so doesn't need to be set.) - -#ifdef ASSERT - // Verify that flags was zeroed on return to Java - Label PcOk; - save_frame(0); // to avoid clobbering O0 - ld_ptr(pc_addr, L0); - br_null_short(L0, Assembler::pt, PcOk); - STOP("last_Java_pc not zeroed before leaving Java"); - bind(PcOk); - - // Verify that flags was zeroed on return to Java - Label FlagsOk; - ld(flags, L0); - tst(L0); - br(Assembler::zero, false, Assembler::pt, FlagsOk); - delayed() -> restore(); - STOP("flags not zeroed before leaving Java"); - bind(FlagsOk); -#endif /* ASSERT */ - // - // When returning from calling out from Java mode the frame anchor's last_Java_pc - // will always be set to NULL. It is set here so that if we are doing a call to - // native (not VM) that we capture the known pc and don't have to rely on the - // native call having a standard frame linkage where we can find the pc. - - if (last_Java_pc->is_valid()) { - st_ptr(last_Java_pc, pc_addr); - } - -#ifdef _LP64 -#ifdef ASSERT - // Make sure that we have an odd stack - Label StackOk; - andcc(last_java_sp, 0x01, G0); - br(Assembler::notZero, false, Assembler::pt, StackOk); - delayed()->nop(); - STOP("Stack Not Biased in set_last_Java_frame"); - bind(StackOk); -#endif // ASSERT - assert( last_java_sp != G4_scratch, "bad register usage in set_last_Java_frame"); - add( last_java_sp, STACK_BIAS, G4_scratch ); - st_ptr(G4_scratch, G2_thread, JavaThread::last_Java_sp_offset()); -#else - st_ptr(last_java_sp, G2_thread, JavaThread::last_Java_sp_offset()); -#endif // _LP64 -} - -void MacroAssembler::reset_last_Java_frame(void) { - assert_not_delayed(); - - Address sp_addr(G2_thread, JavaThread::last_Java_sp_offset()); - Address pc_addr(G2_thread, JavaThread::frame_anchor_offset() + JavaFrameAnchor::last_Java_pc_offset()); - Address flags (G2_thread, JavaThread::frame_anchor_offset() + JavaFrameAnchor::flags_offset()); - -#ifdef ASSERT - // check that it WAS previously set -#ifdef CC_INTERP - save_frame(0); -#else - save_frame_and_mov(0, Lmethod, Lmethod); // Propagate Lmethod to helper frame for -Xprof -#endif /* CC_INTERP */ - ld_ptr(sp_addr, L0); - tst(L0); - breakpoint_trap(Assembler::zero, Assembler::ptr_cc); - restore(); -#endif // ASSERT - - st_ptr(G0, sp_addr); - // Always return last_Java_pc to zero - st_ptr(G0, pc_addr); - // Always null flags after return to Java - st(G0, flags); -} - - -void MacroAssembler::call_VM_base( - Register oop_result, - Register thread_cache, - Register last_java_sp, - address entry_point, - int number_of_arguments, - bool check_exceptions) -{ - assert_not_delayed(); - - // determine last_java_sp register - if (!last_java_sp->is_valid()) { - last_java_sp = SP; - } - // debugging support - assert(number_of_arguments >= 0 , "cannot have negative number of arguments"); - - // 64-bit last_java_sp is biased! - set_last_Java_frame(last_java_sp, noreg); - if (VerifyThread) mov(G2_thread, O0); // about to be smashed; pass early - save_thread(thread_cache); - // do the call - call(entry_point, relocInfo::runtime_call_type); - if (!VerifyThread) - delayed()->mov(G2_thread, O0); // pass thread as first argument - else - delayed()->nop(); // (thread already passed) - restore_thread(thread_cache); - reset_last_Java_frame(); - - // check for pending exceptions. use Gtemp as scratch register. - if (check_exceptions) { - check_and_forward_exception(Gtemp); - } - -#ifdef ASSERT - set(badHeapWordVal, G3); - set(badHeapWordVal, G4); - set(badHeapWordVal, G5); -#endif - - // get oop result if there is one and reset the value in the thread - if (oop_result->is_valid()) { - get_vm_result(oop_result); - } -} - -void MacroAssembler::check_and_forward_exception(Register scratch_reg) -{ - Label L; - - check_and_handle_popframe(scratch_reg); - check_and_handle_earlyret(scratch_reg); - - Address exception_addr(G2_thread, Thread::pending_exception_offset()); - ld_ptr(exception_addr, scratch_reg); - br_null_short(scratch_reg, pt, L); - // we use O7 linkage so that forward_exception_entry has the issuing PC - call(StubRoutines::forward_exception_entry(), relocInfo::runtime_call_type); - delayed()->nop(); - bind(L); -} - - -void MacroAssembler::check_and_handle_popframe(Register scratch_reg) { -} - - -void MacroAssembler::check_and_handle_earlyret(Register scratch_reg) { -} - - -void MacroAssembler::call_VM(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions) { - call_VM_base(oop_result, noreg, noreg, entry_point, number_of_arguments, check_exceptions); -} - - -void MacroAssembler::call_VM(Register oop_result, address entry_point, Register arg_1, bool check_exceptions) { - // O0 is reserved for the thread - mov(arg_1, O1); - call_VM(oop_result, entry_point, 1, check_exceptions); -} - - -void MacroAssembler::call_VM(Register oop_result, address entry_point, Register arg_1, Register arg_2, bool check_exceptions) { - // O0 is reserved for the thread - mov(arg_1, O1); - mov(arg_2, O2); assert(arg_2 != O1, "smashed argument"); - call_VM(oop_result, entry_point, 2, check_exceptions); -} - - -void MacroAssembler::call_VM(Register oop_result, address entry_point, Register arg_1, Register arg_2, Register arg_3, bool check_exceptions) { - // O0 is reserved for the thread - mov(arg_1, O1); - mov(arg_2, O2); assert(arg_2 != O1, "smashed argument"); - mov(arg_3, O3); assert(arg_3 != O1 && arg_3 != O2, "smashed argument"); - call_VM(oop_result, entry_point, 3, check_exceptions); -} - - - -// Note: The following call_VM overloadings are useful when a "save" -// has already been performed by a stub, and the last Java frame is -// the previous one. In that case, last_java_sp must be passed as FP -// instead of SP. - - -void MacroAssembler::call_VM(Register oop_result, Register last_java_sp, address entry_point, int number_of_arguments, bool check_exceptions) { - call_VM_base(oop_result, noreg, last_java_sp, entry_point, number_of_arguments, check_exceptions); -} - - -void MacroAssembler::call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, bool check_exceptions) { - // O0 is reserved for the thread - mov(arg_1, O1); - call_VM(oop_result, last_java_sp, entry_point, 1, check_exceptions); -} - - -void MacroAssembler::call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, Register arg_2, bool check_exceptions) { - // O0 is reserved for the thread - mov(arg_1, O1); - mov(arg_2, O2); assert(arg_2 != O1, "smashed argument"); - call_VM(oop_result, last_java_sp, entry_point, 2, check_exceptions); -} - - -void MacroAssembler::call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, Register arg_2, Register arg_3, bool check_exceptions) { - // O0 is reserved for the thread - mov(arg_1, O1); - mov(arg_2, O2); assert(arg_2 != O1, "smashed argument"); - mov(arg_3, O3); assert(arg_3 != O1 && arg_3 != O2, "smashed argument"); - call_VM(oop_result, last_java_sp, entry_point, 3, check_exceptions); -} - - - -void MacroAssembler::call_VM_leaf_base(Register thread_cache, address entry_point, int number_of_arguments) { - assert_not_delayed(); - save_thread(thread_cache); - // do the call - call(entry_point, relocInfo::runtime_call_type); - delayed()->nop(); - restore_thread(thread_cache); -#ifdef ASSERT - set(badHeapWordVal, G3); - set(badHeapWordVal, G4); - set(badHeapWordVal, G5); -#endif -} - - -void MacroAssembler::call_VM_leaf(Register thread_cache, address entry_point, int number_of_arguments) { - call_VM_leaf_base(thread_cache, entry_point, number_of_arguments); -} - - -void MacroAssembler::call_VM_leaf(Register thread_cache, address entry_point, Register arg_1) { - mov(arg_1, O0); - call_VM_leaf(thread_cache, entry_point, 1); -} - - -void MacroAssembler::call_VM_leaf(Register thread_cache, address entry_point, Register arg_1, Register arg_2) { - mov(arg_1, O0); - mov(arg_2, O1); assert(arg_2 != O0, "smashed argument"); - call_VM_leaf(thread_cache, entry_point, 2); -} - - -void MacroAssembler::call_VM_leaf(Register thread_cache, address entry_point, Register arg_1, Register arg_2, Register arg_3) { - mov(arg_1, O0); - mov(arg_2, O1); assert(arg_2 != O0, "smashed argument"); - mov(arg_3, O2); assert(arg_3 != O0 && arg_3 != O1, "smashed argument"); - call_VM_leaf(thread_cache, entry_point, 3); -} - - -void MacroAssembler::get_vm_result(Register oop_result) { - verify_thread(); - Address vm_result_addr(G2_thread, JavaThread::vm_result_offset()); - ld_ptr( vm_result_addr, oop_result); - st_ptr(G0, vm_result_addr); - verify_oop(oop_result); -} - - -void MacroAssembler::get_vm_result_2(Register metadata_result) { - verify_thread(); - Address vm_result_addr_2(G2_thread, JavaThread::vm_result_2_offset()); - ld_ptr(vm_result_addr_2, metadata_result); - st_ptr(G0, vm_result_addr_2); -} - - -// We require that C code which does not return a value in vm_result will -// leave it undisturbed. -void MacroAssembler::set_vm_result(Register oop_result) { - verify_thread(); - Address vm_result_addr(G2_thread, JavaThread::vm_result_offset()); - verify_oop(oop_result); - -# ifdef ASSERT - // Check that we are not overwriting any other oop. -#ifdef CC_INTERP - save_frame(0); -#else - save_frame_and_mov(0, Lmethod, Lmethod); // Propagate Lmethod for -Xprof -#endif /* CC_INTERP */ - ld_ptr(vm_result_addr, L0); - tst(L0); - restore(); - breakpoint_trap(notZero, Assembler::ptr_cc); - // } -# endif - - st_ptr(oop_result, vm_result_addr); -} - - -void MacroAssembler::ic_call(address entry, bool emit_delay) { - RelocationHolder rspec = virtual_call_Relocation::spec(pc()); - patchable_set((intptr_t)Universe::non_oop_word(), G5_inline_cache_reg); - relocate(rspec); - call(entry, relocInfo::none); - if (emit_delay) { - delayed()->nop(); - } -} - - -void MacroAssembler::card_table_write(jbyte* byte_map_base, - Register tmp, Register obj) { -#ifdef _LP64 - srlx(obj, CardTableModRefBS::card_shift, obj); -#else - srl(obj, CardTableModRefBS::card_shift, obj); -#endif - assert(tmp != obj, "need separate temp reg"); - set((address) byte_map_base, tmp); - stb(G0, tmp, obj); -} - - -void MacroAssembler::internal_sethi(const AddressLiteral& addrlit, Register d, bool ForceRelocatable) { - address save_pc; - int shiftcnt; -#ifdef _LP64 -# ifdef CHECK_DELAY - assert_not_delayed((char*) "cannot put two instructions in delay slot"); -# endif - v9_dep(); - save_pc = pc(); - - int msb32 = (int) (addrlit.value() >> 32); - int lsb32 = (int) (addrlit.value()); - - if (msb32 == 0 && lsb32 >= 0) { - Assembler::sethi(lsb32, d, addrlit.rspec()); - } - else if (msb32 == -1) { - Assembler::sethi(~lsb32, d, addrlit.rspec()); - xor3(d, ~low10(~0), d); - } - else { - Assembler::sethi(msb32, d, addrlit.rspec()); // msb 22-bits - if (msb32 & 0x3ff) // Any bits? - or3(d, msb32 & 0x3ff, d); // msb 32-bits are now in lsb 32 - if (lsb32 & 0xFFFFFC00) { // done? - if ((lsb32 >> 20) & 0xfff) { // Any bits set? - sllx(d, 12, d); // Make room for next 12 bits - or3(d, (lsb32 >> 20) & 0xfff, d); // Or in next 12 - shiftcnt = 0; // We already shifted - } - else - shiftcnt = 12; - if ((lsb32 >> 10) & 0x3ff) { - sllx(d, shiftcnt + 10, d); // Make room for last 10 bits - or3(d, (lsb32 >> 10) & 0x3ff, d); // Or in next 10 - shiftcnt = 0; - } - else - shiftcnt = 10; - sllx(d, shiftcnt + 10, d); // Shift leaving disp field 0'd - } - else - sllx(d, 32, d); - } - // Pad out the instruction sequence so it can be patched later. - if (ForceRelocatable || (addrlit.rtype() != relocInfo::none && - addrlit.rtype() != relocInfo::runtime_call_type)) { - while (pc() < (save_pc + (7 * BytesPerInstWord))) - nop(); - } -#else - Assembler::sethi(addrlit.value(), d, addrlit.rspec()); -#endif -} - - -void MacroAssembler::sethi(const AddressLiteral& addrlit, Register d) { - internal_sethi(addrlit, d, false); -} - - -void MacroAssembler::patchable_sethi(const AddressLiteral& addrlit, Register d) { - internal_sethi(addrlit, d, true); -} - - -int MacroAssembler::insts_for_sethi(address a, bool worst_case) { -#ifdef _LP64 - if (worst_case) return 7; - intptr_t iaddr = (intptr_t) a; - int msb32 = (int) (iaddr >> 32); - int lsb32 = (int) (iaddr); - int count; - if (msb32 == 0 && lsb32 >= 0) - count = 1; - else if (msb32 == -1) - count = 2; - else { - count = 2; - if (msb32 & 0x3ff) - count++; - if (lsb32 & 0xFFFFFC00 ) { - if ((lsb32 >> 20) & 0xfff) count += 2; - if ((lsb32 >> 10) & 0x3ff) count += 2; - } - } - return count; -#else - return 1; -#endif -} - -int MacroAssembler::worst_case_insts_for_set() { - return insts_for_sethi(NULL, true) + 1; -} - - -// Keep in sync with MacroAssembler::insts_for_internal_set -void MacroAssembler::internal_set(const AddressLiteral& addrlit, Register d, bool ForceRelocatable) { - intptr_t value = addrlit.value(); - - if (!ForceRelocatable && addrlit.rspec().type() == relocInfo::none) { - // can optimize - if (-4096 <= value && value <= 4095) { - or3(G0, value, d); // setsw (this leaves upper 32 bits sign-extended) - return; - } - if (inv_hi22(hi22(value)) == value) { - sethi(addrlit, d); - return; - } - } - assert_not_delayed((char*) "cannot put two instructions in delay slot"); - internal_sethi(addrlit, d, ForceRelocatable); - if (ForceRelocatable || addrlit.rspec().type() != relocInfo::none || addrlit.low10() != 0) { - add(d, addrlit.low10(), d, addrlit.rspec()); - } -} - -// Keep in sync with MacroAssembler::internal_set -int MacroAssembler::insts_for_internal_set(intptr_t value) { - // can optimize - if (-4096 <= value && value <= 4095) { - return 1; - } - if (inv_hi22(hi22(value)) == value) { - return insts_for_sethi((address) value); - } - int count = insts_for_sethi((address) value); - AddressLiteral al(value); - if (al.low10() != 0) { - count++; - } - return count; -} - -void MacroAssembler::set(const AddressLiteral& al, Register d) { - internal_set(al, d, false); -} - -void MacroAssembler::set(intptr_t value, Register d) { - AddressLiteral al(value); - internal_set(al, d, false); -} - -void MacroAssembler::set(address addr, Register d, RelocationHolder const& rspec) { - AddressLiteral al(addr, rspec); - internal_set(al, d, false); -} - -void MacroAssembler::patchable_set(const AddressLiteral& al, Register d) { - internal_set(al, d, true); -} - -void MacroAssembler::patchable_set(intptr_t value, Register d) { - AddressLiteral al(value); - internal_set(al, d, true); -} - - -void MacroAssembler::set64(jlong value, Register d, Register tmp) { - assert_not_delayed(); - v9_dep(); - - int hi = (int)(value >> 32); - int lo = (int)(value & ~0); - // (Matcher::isSimpleConstant64 knows about the following optimizations.) - if (Assembler::is_simm13(lo) && value == lo) { - or3(G0, lo, d); - } else if (hi == 0) { - Assembler::sethi(lo, d); // hardware version zero-extends to upper 32 - if (low10(lo) != 0) - or3(d, low10(lo), d); - } - else if (hi == -1) { - Assembler::sethi(~lo, d); // hardware version zero-extends to upper 32 - xor3(d, low10(lo) ^ ~low10(~0), d); - } - else if (lo == 0) { - if (Assembler::is_simm13(hi)) { - or3(G0, hi, d); - } else { - Assembler::sethi(hi, d); // hardware version zero-extends to upper 32 - if (low10(hi) != 0) - or3(d, low10(hi), d); - } - sllx(d, 32, d); - } - else { - Assembler::sethi(hi, tmp); - Assembler::sethi(lo, d); // macro assembler version sign-extends - if (low10(hi) != 0) - or3 (tmp, low10(hi), tmp); - if (low10(lo) != 0) - or3 ( d, low10(lo), d); - sllx(tmp, 32, tmp); - or3 (d, tmp, d); - } -} - -int MacroAssembler::insts_for_set64(jlong value) { - v9_dep(); - - int hi = (int) (value >> 32); - int lo = (int) (value & ~0); - int count = 0; - - // (Matcher::isSimpleConstant64 knows about the following optimizations.) - if (Assembler::is_simm13(lo) && value == lo) { - count++; - } else if (hi == 0) { - count++; - if (low10(lo) != 0) - count++; - } - else if (hi == -1) { - count += 2; - } - else if (lo == 0) { - if (Assembler::is_simm13(hi)) { - count++; - } else { - count++; - if (low10(hi) != 0) - count++; - } - count++; - } - else { - count += 2; - if (low10(hi) != 0) - count++; - if (low10(lo) != 0) - count++; - count += 2; - } - return count; -} - -// compute size in bytes of sparc frame, given -// number of extraWords -int MacroAssembler::total_frame_size_in_bytes(int extraWords) { - - int nWords = frame::memory_parameter_word_sp_offset; - - nWords += extraWords; - - if (nWords & 1) ++nWords; // round up to double-word - - return nWords * BytesPerWord; -} - - -// save_frame: given number of "extra" words in frame, -// issue approp. save instruction (p 200, v8 manual) - -void MacroAssembler::save_frame(int extraWords) { - int delta = -total_frame_size_in_bytes(extraWords); - if (is_simm13(delta)) { - save(SP, delta, SP); - } else { - set(delta, G3_scratch); - save(SP, G3_scratch, SP); - } -} - - -void MacroAssembler::save_frame_c1(int size_in_bytes) { - if (is_simm13(-size_in_bytes)) { - save(SP, -size_in_bytes, SP); - } else { - set(-size_in_bytes, G3_scratch); - save(SP, G3_scratch, SP); - } -} - - -void MacroAssembler::save_frame_and_mov(int extraWords, - Register s1, Register d1, - Register s2, Register d2) { - assert_not_delayed(); - - // The trick here is to use precisely the same memory word - // that trap handlers also use to save the register. - // This word cannot be used for any other purpose, but - // it works fine to save the register's value, whether or not - // an interrupt flushes register windows at any given moment! - Address s1_addr; - if (s1->is_valid() && (s1->is_in() || s1->is_local())) { - s1_addr = s1->address_in_saved_window(); - st_ptr(s1, s1_addr); - } - - Address s2_addr; - if (s2->is_valid() && (s2->is_in() || s2->is_local())) { - s2_addr = s2->address_in_saved_window(); - st_ptr(s2, s2_addr); - } - - save_frame(extraWords); - - if (s1_addr.base() == SP) { - ld_ptr(s1_addr.after_save(), d1); - } else if (s1->is_valid()) { - mov(s1->after_save(), d1); - } - - if (s2_addr.base() == SP) { - ld_ptr(s2_addr.after_save(), d2); - } else if (s2->is_valid()) { - mov(s2->after_save(), d2); - } -} - - -AddressLiteral MacroAssembler::allocate_metadata_address(Metadata* obj) { - assert(oop_recorder() != NULL, "this assembler needs a Recorder"); - int index = oop_recorder()->allocate_metadata_index(obj); - RelocationHolder rspec = metadata_Relocation::spec(index); - return AddressLiteral((address)obj, rspec); -} - -AddressLiteral MacroAssembler::constant_metadata_address(Metadata* obj) { - assert(oop_recorder() != NULL, "this assembler needs a Recorder"); - int index = oop_recorder()->find_index(obj); - RelocationHolder rspec = metadata_Relocation::spec(index); - return AddressLiteral((address)obj, rspec); -} - - -AddressLiteral MacroAssembler::constant_oop_address(jobject obj) { - assert(oop_recorder() != NULL, "this assembler needs an OopRecorder"); - assert(Universe::heap()->is_in_reserved(JNIHandles::resolve(obj)), "not an oop"); - int oop_index = oop_recorder()->find_index(obj); - return AddressLiteral(obj, oop_Relocation::spec(oop_index)); -} - -void MacroAssembler::set_narrow_oop(jobject obj, Register d) { - assert(oop_recorder() != NULL, "this assembler needs an OopRecorder"); - int oop_index = oop_recorder()->find_index(obj); - RelocationHolder rspec = oop_Relocation::spec(oop_index); - - assert_not_delayed(); - // Relocation with special format (see relocInfo_sparc.hpp). - relocate(rspec, 1); - // Assembler::sethi(0x3fffff, d); - emit_long( op(branch_op) | rd(d) | op2(sethi_op2) | hi22(0x3fffff) ); - // Don't add relocation for 'add'. Do patching during 'sethi' processing. - add(d, 0x3ff, d); - -} - -void MacroAssembler::set_narrow_klass(Klass* k, Register d) { - assert(oop_recorder() != NULL, "this assembler needs an OopRecorder"); - int klass_index = oop_recorder()->find_index(k); - RelocationHolder rspec = metadata_Relocation::spec(klass_index); - narrowOop encoded_k = oopDesc::encode_klass(k); - - assert_not_delayed(); - // Relocation with special format (see relocInfo_sparc.hpp). - relocate(rspec, 1); - // Assembler::sethi(encoded_k, d); - emit_long( op(branch_op) | rd(d) | op2(sethi_op2) | hi22(encoded_k) ); - // Don't add relocation for 'add'. Do patching during 'sethi' processing. - add(d, low10(encoded_k), d); - -} - -void MacroAssembler::align(int modulus) { - while (offset() % modulus != 0) nop(); -} - - -void MacroAssembler::safepoint() { - relocate(breakpoint_Relocation::spec(breakpoint_Relocation::safepoint)); -} - - -void RegistersForDebugging::print(outputStream* s) { - FlagSetting fs(Debugging, true); - int j; - for (j = 0; j < 8; ++j) { - if (j != 6) { s->print("i%d = ", j); os::print_location(s, i[j]); } - else { s->print( "fp = " ); os::print_location(s, i[j]); } - } - s->cr(); - - for (j = 0; j < 8; ++j) { - s->print("l%d = ", j); os::print_location(s, l[j]); - } - s->cr(); - - for (j = 0; j < 8; ++j) { - if (j != 6) { s->print("o%d = ", j); os::print_location(s, o[j]); } - else { s->print( "sp = " ); os::print_location(s, o[j]); } - } - s->cr(); - - for (j = 0; j < 8; ++j) { - s->print("g%d = ", j); os::print_location(s, g[j]); - } - s->cr(); - - // print out floats with compression - for (j = 0; j < 32; ) { - jfloat val = f[j]; - int last = j; - for ( ; last+1 < 32; ++last ) { - char b1[1024], b2[1024]; - sprintf(b1, "%f", val); - sprintf(b2, "%f", f[last+1]); - if (strcmp(b1, b2)) - break; - } - s->print("f%d", j); - if ( j != last ) s->print(" - f%d", last); - s->print(" = %f", val); - s->fill_to(25); - s->print_cr(" (0x%x)", val); - j = last + 1; - } - s->cr(); - - // and doubles (evens only) - for (j = 0; j < 32; ) { - jdouble val = d[j]; - int last = j; - for ( ; last+1 < 32; ++last ) { - char b1[1024], b2[1024]; - sprintf(b1, "%f", val); - sprintf(b2, "%f", d[last+1]); - if (strcmp(b1, b2)) - break; - } - s->print("d%d", 2 * j); - if ( j != last ) s->print(" - d%d", last); - s->print(" = %f", val); - s->fill_to(30); - s->print("(0x%x)", *(int*)&val); - s->fill_to(42); - s->print_cr("(0x%x)", *(1 + (int*)&val)); - j = last + 1; - } - s->cr(); -} - -void RegistersForDebugging::save_registers(MacroAssembler* a) { - a->sub(FP, round_to(sizeof(RegistersForDebugging), sizeof(jdouble)) - STACK_BIAS, O0); - a->flush_windows(); - int i; - for (i = 0; i < 8; ++i) { - a->ld_ptr(as_iRegister(i)->address_in_saved_window().after_save(), L1); a->st_ptr( L1, O0, i_offset(i)); - a->ld_ptr(as_lRegister(i)->address_in_saved_window().after_save(), L1); a->st_ptr( L1, O0, l_offset(i)); - a->st_ptr(as_oRegister(i)->after_save(), O0, o_offset(i)); - a->st_ptr(as_gRegister(i)->after_save(), O0, g_offset(i)); - } - for (i = 0; i < 32; ++i) { - a->stf(FloatRegisterImpl::S, as_FloatRegister(i), O0, f_offset(i)); - } - for (i = 0; i < (VM_Version::v9_instructions_work() ? 64 : 32); i += 2) { - a->stf(FloatRegisterImpl::D, as_FloatRegister(i), O0, d_offset(i)); - } -} - -void RegistersForDebugging::restore_registers(MacroAssembler* a, Register r) { - for (int i = 1; i < 8; ++i) { - a->ld_ptr(r, g_offset(i), as_gRegister(i)); - } - for (int j = 0; j < 32; ++j) { - a->ldf(FloatRegisterImpl::S, O0, f_offset(j), as_FloatRegister(j)); - } - for (int k = 0; k < (VM_Version::v9_instructions_work() ? 64 : 32); k += 2) { - a->ldf(FloatRegisterImpl::D, O0, d_offset(k), as_FloatRegister(k)); - } -} - - -// pushes double TOS element of FPU stack on CPU stack; pops from FPU stack -void MacroAssembler::push_fTOS() { - // %%%%%% need to implement this -} - -// pops double TOS element from CPU stack and pushes on FPU stack -void MacroAssembler::pop_fTOS() { - // %%%%%% need to implement this -} - -void MacroAssembler::empty_FPU_stack() { - // %%%%%% need to implement this -} - -void MacroAssembler::_verify_oop(Register reg, const char* msg, const char * file, int line) { - // plausibility check for oops - if (!VerifyOops) return; - - if (reg == G0) return; // always NULL, which is always an oop - - BLOCK_COMMENT("verify_oop {"); - char buffer[64]; -#ifdef COMPILER1 - if (CommentedAssembly) { - snprintf(buffer, sizeof(buffer), "verify_oop at %d", offset()); - block_comment(buffer); - } -#endif - - int len = strlen(file) + strlen(msg) + 1 + 4; - sprintf(buffer, "%d", line); - len += strlen(buffer); - sprintf(buffer, " at offset %d ", offset()); - len += strlen(buffer); - char * real_msg = new char[len]; - sprintf(real_msg, "%s%s(%s:%d)", msg, buffer, file, line); - - // Call indirectly to solve generation ordering problem - AddressLiteral a(StubRoutines::verify_oop_subroutine_entry_address()); - - // Make some space on stack above the current register window. - // Enough to hold 8 64-bit registers. - add(SP,-8*8,SP); - - // Save some 64-bit registers; a normal 'save' chops the heads off - // of 64-bit longs in the 32-bit build. - stx(O0,SP,frame::register_save_words*wordSize+STACK_BIAS+0*8); - stx(O1,SP,frame::register_save_words*wordSize+STACK_BIAS+1*8); - mov(reg,O0); // Move arg into O0; arg might be in O7 which is about to be crushed - stx(O7,SP,frame::register_save_words*wordSize+STACK_BIAS+7*8); - - // Size of set() should stay the same - patchable_set((intptr_t)real_msg, O1); - // Load address to call to into O7 - load_ptr_contents(a, O7); - // Register call to verify_oop_subroutine - callr(O7, G0); - delayed()->nop(); - // recover frame size - add(SP, 8*8,SP); - BLOCK_COMMENT("} verify_oop"); -} - -void MacroAssembler::_verify_oop_addr(Address addr, const char* msg, const char * file, int line) { - // plausibility check for oops - if (!VerifyOops) return; - - char buffer[64]; - sprintf(buffer, "%d", line); - int len = strlen(file) + strlen(msg) + 1 + 4 + strlen(buffer); - sprintf(buffer, " at SP+%d ", addr.disp()); - len += strlen(buffer); - char * real_msg = new char[len]; - sprintf(real_msg, "%s at SP+%d (%s:%d)", msg, addr.disp(), file, line); - - // Call indirectly to solve generation ordering problem - AddressLiteral a(StubRoutines::verify_oop_subroutine_entry_address()); - - // Make some space on stack above the current register window. - // Enough to hold 8 64-bit registers. - add(SP,-8*8,SP); - - // Save some 64-bit registers; a normal 'save' chops the heads off - // of 64-bit longs in the 32-bit build. - stx(O0,SP,frame::register_save_words*wordSize+STACK_BIAS+0*8); - stx(O1,SP,frame::register_save_words*wordSize+STACK_BIAS+1*8); - ld_ptr(addr.base(), addr.disp() + 8*8, O0); // Load arg into O0; arg might be in O7 which is about to be crushed - stx(O7,SP,frame::register_save_words*wordSize+STACK_BIAS+7*8); - - // Size of set() should stay the same - patchable_set((intptr_t)real_msg, O1); - // Load address to call to into O7 - load_ptr_contents(a, O7); - // Register call to verify_oop_subroutine - callr(O7, G0); - delayed()->nop(); - // recover frame size - add(SP, 8*8,SP); -} - -// side-door communication with signalHandler in os_solaris.cpp -address MacroAssembler::_verify_oop_implicit_branch[3] = { NULL }; - -// This macro is expanded just once; it creates shared code. Contract: -// receives an oop in O0. Must restore O0 & O7 from TLS. Must not smash ANY -// registers, including flags. May not use a register 'save', as this blows -// the high bits of the O-regs if they contain Long values. Acts as a 'leaf' -// call. -void MacroAssembler::verify_oop_subroutine() { - assert( VM_Version::v9_instructions_work(), "VerifyOops not supported for V8" ); - - // Leaf call; no frame. - Label succeed, fail, null_or_fail; - - // O0 and O7 were saved already (O0 in O0's TLS home, O7 in O5's TLS home). - // O0 is now the oop to be checked. O7 is the return address. - Register O0_obj = O0; - - // Save some more registers for temps. - stx(O2,SP,frame::register_save_words*wordSize+STACK_BIAS+2*8); - stx(O3,SP,frame::register_save_words*wordSize+STACK_BIAS+3*8); - stx(O4,SP,frame::register_save_words*wordSize+STACK_BIAS+4*8); - stx(O5,SP,frame::register_save_words*wordSize+STACK_BIAS+5*8); - - // Save flags - Register O5_save_flags = O5; - rdccr( O5_save_flags ); - - { // count number of verifies - Register O2_adr = O2; - Register O3_accum = O3; - inc_counter(StubRoutines::verify_oop_count_addr(), O2_adr, O3_accum); - } - - Register O2_mask = O2; - Register O3_bits = O3; - Register O4_temp = O4; - - // mark lower end of faulting range - assert(_verify_oop_implicit_branch[0] == NULL, "set once"); - _verify_oop_implicit_branch[0] = pc(); - - // We can't check the mark oop because it could be in the process of - // locking or unlocking while this is running. - set(Universe::verify_oop_mask (), O2_mask); - set(Universe::verify_oop_bits (), O3_bits); - - // assert((obj & oop_mask) == oop_bits); - and3(O0_obj, O2_mask, O4_temp); - cmp_and_brx_short(O4_temp, O3_bits, notEqual, pn, null_or_fail); - - if ((NULL_WORD & Universe::verify_oop_mask()) == Universe::verify_oop_bits()) { - // the null_or_fail case is useless; must test for null separately - br_null_short(O0_obj, pn, succeed); - } - - // Check the Klass* of this object for being in the right area of memory. - // Cannot do the load in the delay above slot in case O0 is null - load_klass(O0_obj, O0_obj); - // assert((klass != NULL) - br_null_short(O0_obj, pn, fail); - // TODO: Future assert that klass is lower 4g memory for UseCompressedKlassPointers - - wrccr( O5_save_flags ); // Restore CCR's - - // mark upper end of faulting range - _verify_oop_implicit_branch[1] = pc(); - - //----------------------- - // all tests pass - bind(succeed); - - // Restore prior 64-bit registers - ldx(SP,frame::register_save_words*wordSize+STACK_BIAS+0*8,O0); - ldx(SP,frame::register_save_words*wordSize+STACK_BIAS+1*8,O1); - ldx(SP,frame::register_save_words*wordSize+STACK_BIAS+2*8,O2); - ldx(SP,frame::register_save_words*wordSize+STACK_BIAS+3*8,O3); - ldx(SP,frame::register_save_words*wordSize+STACK_BIAS+4*8,O4); - ldx(SP,frame::register_save_words*wordSize+STACK_BIAS+5*8,O5); - - retl(); // Leaf return; restore prior O7 in delay slot - delayed()->ldx(SP,frame::register_save_words*wordSize+STACK_BIAS+7*8,O7); - - //----------------------- - bind(null_or_fail); // nulls are less common but OK - br_null(O0_obj, false, pt, succeed); - delayed()->wrccr( O5_save_flags ); // Restore CCR's - - //----------------------- - // report failure: - bind(fail); - _verify_oop_implicit_branch[2] = pc(); - - wrccr( O5_save_flags ); // Restore CCR's - - save_frame(::round_to(sizeof(RegistersForDebugging) / BytesPerWord, 2)); - - // stop_subroutine expects message pointer in I1. - mov(I1, O1); - - // Restore prior 64-bit registers - ldx(FP,frame::register_save_words*wordSize+STACK_BIAS+0*8,I0); - ldx(FP,frame::register_save_words*wordSize+STACK_BIAS+1*8,I1); - ldx(FP,frame::register_save_words*wordSize+STACK_BIAS+2*8,I2); - ldx(FP,frame::register_save_words*wordSize+STACK_BIAS+3*8,I3); - ldx(FP,frame::register_save_words*wordSize+STACK_BIAS+4*8,I4); - ldx(FP,frame::register_save_words*wordSize+STACK_BIAS+5*8,I5); - - // factor long stop-sequence into subroutine to save space - assert(StubRoutines::Sparc::stop_subroutine_entry_address(), "hasn't been generated yet"); - - // call indirectly to solve generation ordering problem - AddressLiteral al(StubRoutines::Sparc::stop_subroutine_entry_address()); - load_ptr_contents(al, O5); - jmpl(O5, 0, O7); - delayed()->nop(); -} - - -void MacroAssembler::stop(const char* msg) { - // save frame first to get O7 for return address - // add one word to size in case struct is odd number of words long - // It must be doubleword-aligned for storing doubles into it. - - save_frame(::round_to(sizeof(RegistersForDebugging) / BytesPerWord, 2)); - - // stop_subroutine expects message pointer in I1. - // Size of set() should stay the same - patchable_set((intptr_t)msg, O1); - - // factor long stop-sequence into subroutine to save space - assert(StubRoutines::Sparc::stop_subroutine_entry_address(), "hasn't been generated yet"); - - // call indirectly to solve generation ordering problem - AddressLiteral a(StubRoutines::Sparc::stop_subroutine_entry_address()); - load_ptr_contents(a, O5); - jmpl(O5, 0, O7); - delayed()->nop(); - - breakpoint_trap(); // make stop actually stop rather than writing - // unnoticeable results in the output files. - - // restore(); done in callee to save space! -} - - -void MacroAssembler::warn(const char* msg) { - save_frame(::round_to(sizeof(RegistersForDebugging) / BytesPerWord, 2)); - RegistersForDebugging::save_registers(this); - mov(O0, L0); - // Size of set() should stay the same - patchable_set((intptr_t)msg, O0); - call( CAST_FROM_FN_PTR(address, warning) ); - delayed()->nop(); -// ret(); -// delayed()->restore(); - RegistersForDebugging::restore_registers(this, L0); - restore(); -} - - -void MacroAssembler::untested(const char* what) { - // We must be able to turn interactive prompting off - // in order to run automated test scripts on the VM - // Use the flag ShowMessageBoxOnError - - char* b = new char[1024]; - sprintf(b, "untested: %s", what); - - if (ShowMessageBoxOnError) { STOP(b); } - else { warn(b); } -} - - -void MacroAssembler::stop_subroutine() { - RegistersForDebugging::save_registers(this); - - // for the sake of the debugger, stick a PC on the current frame - // (this assumes that the caller has performed an extra "save") - mov(I7, L7); - add(O7, -7 * BytesPerInt, I7); - - save_frame(); // one more save to free up another O7 register - mov(I0, O1); // addr of reg save area - - // We expect pointer to message in I1. Caller must set it up in O1 - mov(I1, O0); // get msg - call (CAST_FROM_FN_PTR(address, MacroAssembler::debug), relocInfo::runtime_call_type); - delayed()->nop(); - - restore(); - - RegistersForDebugging::restore_registers(this, O0); - - save_frame(0); - call(CAST_FROM_FN_PTR(address,breakpoint)); - delayed()->nop(); - restore(); - - mov(L7, I7); - retl(); - delayed()->restore(); // see stop above -} - - -void MacroAssembler::debug(char* msg, RegistersForDebugging* regs) { - if ( ShowMessageBoxOnError ) { - JavaThread* thread = JavaThread::current(); - JavaThreadState saved_state = thread->thread_state(); - thread->set_thread_state(_thread_in_vm); - { - // In order to get locks work, we need to fake a in_VM state - ttyLocker ttyl; - ::tty->print_cr("EXECUTION STOPPED: %s\n", msg); - if (CountBytecodes || TraceBytecodes || StopInterpreterAt) { - BytecodeCounter::print(); - } - if (os::message_box(msg, "Execution stopped, print registers?")) - regs->print(::tty); - } - BREAKPOINT; - ThreadStateTransition::transition(JavaThread::current(), _thread_in_vm, saved_state); - } - else { - ::tty->print_cr("=============== DEBUG MESSAGE: %s ================\n", msg); - } - assert(false, err_msg("DEBUG MESSAGE: %s", msg)); -} - -#ifndef PRODUCT -void MacroAssembler::test() { - ResourceMark rm; - - CodeBuffer cb("test", 10000, 10000); - MacroAssembler* a = new MacroAssembler(&cb); - VM_Version::allow_all(); - a->test_v9(); - a->test_v8_onlys(); - VM_Version::revert(); - - StubRoutines::Sparc::test_stop_entry()(); -} -#endif - - -void MacroAssembler::calc_mem_param_words(Register Rparam_words, Register Rresult) { - subcc( Rparam_words, Argument::n_register_parameters, Rresult); // how many mem words? - Label no_extras; - br( negative, true, pt, no_extras ); // if neg, clear reg - delayed()->set(0, Rresult); // annuled, so only if taken - bind( no_extras ); -} - - -void MacroAssembler::calc_frame_size(Register Rextra_words, Register Rresult) { -#ifdef _LP64 - add(Rextra_words, frame::memory_parameter_word_sp_offset, Rresult); -#else - add(Rextra_words, frame::memory_parameter_word_sp_offset + 1, Rresult); -#endif - bclr(1, Rresult); - sll(Rresult, LogBytesPerWord, Rresult); // Rresult has total frame bytes -} - - -void MacroAssembler::calc_frame_size_and_save(Register Rextra_words, Register Rresult) { - calc_frame_size(Rextra_words, Rresult); - neg(Rresult); - save(SP, Rresult, SP); -} - - -// --------------------------------------------------------- -Assembler::RCondition cond2rcond(Assembler::Condition c) { - switch (c) { - /*case zero: */ - case Assembler::equal: return Assembler::rc_z; - case Assembler::lessEqual: return Assembler::rc_lez; - case Assembler::less: return Assembler::rc_lz; - /*case notZero:*/ - case Assembler::notEqual: return Assembler::rc_nz; - case Assembler::greater: return Assembler::rc_gz; - case Assembler::greaterEqual: return Assembler::rc_gez; - } - ShouldNotReachHere(); - return Assembler::rc_z; -} - -// compares (32 bit) register with zero and branches. NOT FOR USE WITH 64-bit POINTERS -void MacroAssembler::cmp_zero_and_br(Condition c, Register s1, Label& L, bool a, Predict p) { - tst(s1); - br (c, a, p, L); -} - -// Compares a pointer register with zero and branches on null. -// Does a test & branch on 32-bit systems and a register-branch on 64-bit. -void MacroAssembler::br_null( Register s1, bool a, Predict p, Label& L ) { - assert_not_delayed(); -#ifdef _LP64 - bpr( rc_z, a, p, s1, L ); -#else - tst(s1); - br ( zero, a, p, L ); -#endif -} - -void MacroAssembler::br_notnull( Register s1, bool a, Predict p, Label& L ) { - assert_not_delayed(); -#ifdef _LP64 - bpr( rc_nz, a, p, s1, L ); -#else - tst(s1); - br ( notZero, a, p, L ); -#endif -} - -// Compare registers and branch with nop in delay slot or cbcond without delay slot. - -// Compare integer (32 bit) values (icc only). -void MacroAssembler::cmp_and_br_short(Register s1, Register s2, Condition c, - Predict p, Label& L) { - assert_not_delayed(); - if (use_cbcond(L)) { - Assembler::cbcond(c, icc, s1, s2, L); - } else { - cmp(s1, s2); - br(c, false, p, L); - delayed()->nop(); - } -} - -// Compare integer (32 bit) values (icc only). -void MacroAssembler::cmp_and_br_short(Register s1, int simm13a, Condition c, - Predict p, Label& L) { - assert_not_delayed(); - if (is_simm(simm13a,5) && use_cbcond(L)) { - Assembler::cbcond(c, icc, s1, simm13a, L); - } else { - cmp(s1, simm13a); - br(c, false, p, L); - delayed()->nop(); - } -} - -// Branch that tests xcc in LP64 and icc in !LP64 -void MacroAssembler::cmp_and_brx_short(Register s1, Register s2, Condition c, - Predict p, Label& L) { - assert_not_delayed(); - if (use_cbcond(L)) { - Assembler::cbcond(c, ptr_cc, s1, s2, L); - } else { - cmp(s1, s2); - brx(c, false, p, L); - delayed()->nop(); - } -} - -// Branch that tests xcc in LP64 and icc in !LP64 -void MacroAssembler::cmp_and_brx_short(Register s1, int simm13a, Condition c, - Predict p, Label& L) { - assert_not_delayed(); - if (is_simm(simm13a,5) && use_cbcond(L)) { - Assembler::cbcond(c, ptr_cc, s1, simm13a, L); - } else { - cmp(s1, simm13a); - brx(c, false, p, L); - delayed()->nop(); - } -} - -// Short branch version for compares a pointer with zero. - -void MacroAssembler::br_null_short(Register s1, Predict p, Label& L) { - assert_not_delayed(); - if (use_cbcond(L)) { - Assembler::cbcond(zero, ptr_cc, s1, 0, L); - return; - } - br_null(s1, false, p, L); - delayed()->nop(); -} - -void MacroAssembler::br_notnull_short(Register s1, Predict p, Label& L) { - assert_not_delayed(); - if (use_cbcond(L)) { - Assembler::cbcond(notZero, ptr_cc, s1, 0, L); - return; - } - br_notnull(s1, false, p, L); - delayed()->nop(); -} - -// Unconditional short branch -void MacroAssembler::ba_short(Label& L) { - if (use_cbcond(L)) { - Assembler::cbcond(equal, icc, G0, G0, L); - return; - } - br(always, false, pt, L); - delayed()->nop(); -} - -// instruction sequences factored across compiler & interpreter - - -void MacroAssembler::lcmp( Register Ra_hi, Register Ra_low, - Register Rb_hi, Register Rb_low, - Register Rresult) { - - Label check_low_parts, done; - - cmp(Ra_hi, Rb_hi ); // compare hi parts - br(equal, true, pt, check_low_parts); - delayed()->cmp(Ra_low, Rb_low); // test low parts - - // And, with an unsigned comparison, it does not matter if the numbers - // are negative or not. - // E.g., -2 cmp -1: the low parts are 0xfffffffe and 0xffffffff. - // The second one is bigger (unsignedly). - - // Other notes: The first move in each triplet can be unconditional - // (and therefore probably prefetchable). - // And the equals case for the high part does not need testing, - // since that triplet is reached only after finding the high halves differ. - - if (VM_Version::v9_instructions_work()) { - mov(-1, Rresult); - ba(done); delayed()-> movcc(greater, false, icc, 1, Rresult); - } else { - br(less, true, pt, done); delayed()-> set(-1, Rresult); - br(greater, true, pt, done); delayed()-> set( 1, Rresult); - } - - bind( check_low_parts ); - - if (VM_Version::v9_instructions_work()) { - mov( -1, Rresult); - movcc(equal, false, icc, 0, Rresult); - movcc(greaterUnsigned, false, icc, 1, Rresult); - } else { - set(-1, Rresult); - br(equal, true, pt, done); delayed()->set( 0, Rresult); - br(greaterUnsigned, true, pt, done); delayed()->set( 1, Rresult); - } - bind( done ); -} - -void MacroAssembler::lneg( Register Rhi, Register Rlow ) { - subcc( G0, Rlow, Rlow ); - subc( G0, Rhi, Rhi ); -} - -void MacroAssembler::lshl( Register Rin_high, Register Rin_low, - Register Rcount, - Register Rout_high, Register Rout_low, - Register Rtemp ) { - - - Register Ralt_count = Rtemp; - Register Rxfer_bits = Rtemp; - - assert( Ralt_count != Rin_high - && Ralt_count != Rin_low - && Ralt_count != Rcount - && Rxfer_bits != Rin_low - && Rxfer_bits != Rin_high - && Rxfer_bits != Rcount - && Rxfer_bits != Rout_low - && Rout_low != Rin_high, - "register alias checks"); - - Label big_shift, done; - - // This code can be optimized to use the 64 bit shifts in V9. - // Here we use the 32 bit shifts. - - and3( Rcount, 0x3f, Rcount); // take least significant 6 bits - subcc(Rcount, 31, Ralt_count); - br(greater, true, pn, big_shift); - delayed()->dec(Ralt_count); - - // shift < 32 bits, Ralt_count = Rcount-31 - - // We get the transfer bits by shifting right by 32-count the low - // register. This is done by shifting right by 31-count and then by one - // more to take care of the special (rare) case where count is zero - // (shifting by 32 would not work). - - neg(Ralt_count); - - // The order of the next two instructions is critical in the case where - // Rin and Rout are the same and should not be reversed. - - srl(Rin_low, Ralt_count, Rxfer_bits); // shift right by 31-count - if (Rcount != Rout_low) { - sll(Rin_low, Rcount, Rout_low); // low half - } - sll(Rin_high, Rcount, Rout_high); - if (Rcount == Rout_low) { - sll(Rin_low, Rcount, Rout_low); // low half - } - srl(Rxfer_bits, 1, Rxfer_bits ); // shift right by one more - ba(done); - delayed()->or3(Rout_high, Rxfer_bits, Rout_high); // new hi value: or in shifted old hi part and xfer from low - - // shift >= 32 bits, Ralt_count = Rcount-32 - bind(big_shift); - sll(Rin_low, Ralt_count, Rout_high ); - clr(Rout_low); - - bind(done); -} - - -void MacroAssembler::lshr( Register Rin_high, Register Rin_low, - Register Rcount, - Register Rout_high, Register Rout_low, - Register Rtemp ) { - - Register Ralt_count = Rtemp; - Register Rxfer_bits = Rtemp; - - assert( Ralt_count != Rin_high - && Ralt_count != Rin_low - && Ralt_count != Rcount - && Rxfer_bits != Rin_low - && Rxfer_bits != Rin_high - && Rxfer_bits != Rcount - && Rxfer_bits != Rout_high - && Rout_high != Rin_low, - "register alias checks"); - - Label big_shift, done; - - // This code can be optimized to use the 64 bit shifts in V9. - // Here we use the 32 bit shifts. - - and3( Rcount, 0x3f, Rcount); // take least significant 6 bits - subcc(Rcount, 31, Ralt_count); - br(greater, true, pn, big_shift); - delayed()->dec(Ralt_count); - - // shift < 32 bits, Ralt_count = Rcount-31 - - // We get the transfer bits by shifting left by 32-count the high - // register. This is done by shifting left by 31-count and then by one - // more to take care of the special (rare) case where count is zero - // (shifting by 32 would not work). - - neg(Ralt_count); - if (Rcount != Rout_low) { - srl(Rin_low, Rcount, Rout_low); - } - - // The order of the next two instructions is critical in the case where - // Rin and Rout are the same and should not be reversed. - - sll(Rin_high, Ralt_count, Rxfer_bits); // shift left by 31-count - sra(Rin_high, Rcount, Rout_high ); // high half - sll(Rxfer_bits, 1, Rxfer_bits); // shift left by one more - if (Rcount == Rout_low) { - srl(Rin_low, Rcount, Rout_low); - } - ba(done); - delayed()->or3(Rout_low, Rxfer_bits, Rout_low); // new low value: or shifted old low part and xfer from high - - // shift >= 32 bits, Ralt_count = Rcount-32 - bind(big_shift); - - sra(Rin_high, Ralt_count, Rout_low); - sra(Rin_high, 31, Rout_high); // sign into hi - - bind( done ); -} - - - -void MacroAssembler::lushr( Register Rin_high, Register Rin_low, - Register Rcount, - Register Rout_high, Register Rout_low, - Register Rtemp ) { - - Register Ralt_count = Rtemp; - Register Rxfer_bits = Rtemp; - - assert( Ralt_count != Rin_high - && Ralt_count != Rin_low - && Ralt_count != Rcount - && Rxfer_bits != Rin_low - && Rxfer_bits != Rin_high - && Rxfer_bits != Rcount - && Rxfer_bits != Rout_high - && Rout_high != Rin_low, - "register alias checks"); - - Label big_shift, done; - - // This code can be optimized to use the 64 bit shifts in V9. - // Here we use the 32 bit shifts. - - and3( Rcount, 0x3f, Rcount); // take least significant 6 bits - subcc(Rcount, 31, Ralt_count); - br(greater, true, pn, big_shift); - delayed()->dec(Ralt_count); - - // shift < 32 bits, Ralt_count = Rcount-31 - - // We get the transfer bits by shifting left by 32-count the high - // register. This is done by shifting left by 31-count and then by one - // more to take care of the special (rare) case where count is zero - // (shifting by 32 would not work). - - neg(Ralt_count); - if (Rcount != Rout_low) { - srl(Rin_low, Rcount, Rout_low); - } - - // The order of the next two instructions is critical in the case where - // Rin and Rout are the same and should not be reversed. - - sll(Rin_high, Ralt_count, Rxfer_bits); // shift left by 31-count - srl(Rin_high, Rcount, Rout_high ); // high half - sll(Rxfer_bits, 1, Rxfer_bits); // shift left by one more - if (Rcount == Rout_low) { - srl(Rin_low, Rcount, Rout_low); - } - ba(done); - delayed()->or3(Rout_low, Rxfer_bits, Rout_low); // new low value: or shifted old low part and xfer from high - - // shift >= 32 bits, Ralt_count = Rcount-32 - bind(big_shift); - - srl(Rin_high, Ralt_count, Rout_low); - clr(Rout_high); - - bind( done ); -} - -#ifdef _LP64 -void MacroAssembler::lcmp( Register Ra, Register Rb, Register Rresult) { - cmp(Ra, Rb); - mov(-1, Rresult); - movcc(equal, false, xcc, 0, Rresult); - movcc(greater, false, xcc, 1, Rresult); -} -#endif - - -void MacroAssembler::load_sized_value(Address src, Register dst, size_t size_in_bytes, bool is_signed) { - switch (size_in_bytes) { - case 8: ld_long(src, dst); break; - case 4: ld( src, dst); break; - case 2: is_signed ? ldsh(src, dst) : lduh(src, dst); break; - case 1: is_signed ? ldsb(src, dst) : ldub(src, dst); break; - default: ShouldNotReachHere(); - } -} - -void MacroAssembler::store_sized_value(Register src, Address dst, size_t size_in_bytes) { - switch (size_in_bytes) { - case 8: st_long(src, dst); break; - case 4: st( src, dst); break; - case 2: sth( src, dst); break; - case 1: stb( src, dst); break; - default: ShouldNotReachHere(); - } -} - - -void MacroAssembler::float_cmp( bool is_float, int unordered_result, - FloatRegister Fa, FloatRegister Fb, - Register Rresult) { - - fcmp(is_float ? FloatRegisterImpl::S : FloatRegisterImpl::D, fcc0, Fa, Fb); - - Condition lt = unordered_result == -1 ? f_unorderedOrLess : f_less; - Condition eq = f_equal; - Condition gt = unordered_result == 1 ? f_unorderedOrGreater : f_greater; - - if (VM_Version::v9_instructions_work()) { - - mov(-1, Rresult); - movcc(eq, true, fcc0, 0, Rresult); - movcc(gt, true, fcc0, 1, Rresult); - - } else { - Label done; - - set( -1, Rresult ); - //fb(lt, true, pn, done); delayed()->set( -1, Rresult ); - fb( eq, true, pn, done); delayed()->set( 0, Rresult ); - fb( gt, true, pn, done); delayed()->set( 1, Rresult ); - - bind (done); - } -} - - -void MacroAssembler::fneg( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d) -{ - if (VM_Version::v9_instructions_work()) { - Assembler::fneg(w, s, d); - } else { - if (w == FloatRegisterImpl::S) { - Assembler::fneg(w, s, d); - } else if (w == FloatRegisterImpl::D) { - // number() does a sanity check on the alignment. - assert(((s->encoding(FloatRegisterImpl::D) & 1) == 0) && - ((d->encoding(FloatRegisterImpl::D) & 1) == 0), "float register alignment check"); - - Assembler::fneg(FloatRegisterImpl::S, s, d); - Assembler::fmov(FloatRegisterImpl::S, s->successor(), d->successor()); - } else { - assert(w == FloatRegisterImpl::Q, "Invalid float register width"); - - // number() does a sanity check on the alignment. - assert(((s->encoding(FloatRegisterImpl::D) & 3) == 0) && - ((d->encoding(FloatRegisterImpl::D) & 3) == 0), "float register alignment check"); - - Assembler::fneg(FloatRegisterImpl::S, s, d); - Assembler::fmov(FloatRegisterImpl::S, s->successor(), d->successor()); - Assembler::fmov(FloatRegisterImpl::S, s->successor()->successor(), d->successor()->successor()); - Assembler::fmov(FloatRegisterImpl::S, s->successor()->successor()->successor(), d->successor()->successor()->successor()); - } - } -} - -void MacroAssembler::fmov( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d) -{ - if (VM_Version::v9_instructions_work()) { - Assembler::fmov(w, s, d); - } else { - if (w == FloatRegisterImpl::S) { - Assembler::fmov(w, s, d); - } else if (w == FloatRegisterImpl::D) { - // number() does a sanity check on the alignment. - assert(((s->encoding(FloatRegisterImpl::D) & 1) == 0) && - ((d->encoding(FloatRegisterImpl::D) & 1) == 0), "float register alignment check"); - - Assembler::fmov(FloatRegisterImpl::S, s, d); - Assembler::fmov(FloatRegisterImpl::S, s->successor(), d->successor()); - } else { - assert(w == FloatRegisterImpl::Q, "Invalid float register width"); - - // number() does a sanity check on the alignment. - assert(((s->encoding(FloatRegisterImpl::D) & 3) == 0) && - ((d->encoding(FloatRegisterImpl::D) & 3) == 0), "float register alignment check"); - - Assembler::fmov(FloatRegisterImpl::S, s, d); - Assembler::fmov(FloatRegisterImpl::S, s->successor(), d->successor()); - Assembler::fmov(FloatRegisterImpl::S, s->successor()->successor(), d->successor()->successor()); - Assembler::fmov(FloatRegisterImpl::S, s->successor()->successor()->successor(), d->successor()->successor()->successor()); - } - } -} - -void MacroAssembler::fabs( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d) -{ - if (VM_Version::v9_instructions_work()) { - Assembler::fabs(w, s, d); - } else { - if (w == FloatRegisterImpl::S) { - Assembler::fabs(w, s, d); - } else if (w == FloatRegisterImpl::D) { - // number() does a sanity check on the alignment. - assert(((s->encoding(FloatRegisterImpl::D) & 1) == 0) && - ((d->encoding(FloatRegisterImpl::D) & 1) == 0), "float register alignment check"); - - Assembler::fabs(FloatRegisterImpl::S, s, d); - Assembler::fmov(FloatRegisterImpl::S, s->successor(), d->successor()); - } else { - assert(w == FloatRegisterImpl::Q, "Invalid float register width"); - - // number() does a sanity check on the alignment. - assert(((s->encoding(FloatRegisterImpl::D) & 3) == 0) && - ((d->encoding(FloatRegisterImpl::D) & 3) == 0), "float register alignment check"); - - Assembler::fabs(FloatRegisterImpl::S, s, d); - Assembler::fmov(FloatRegisterImpl::S, s->successor(), d->successor()); - Assembler::fmov(FloatRegisterImpl::S, s->successor()->successor(), d->successor()->successor()); - Assembler::fmov(FloatRegisterImpl::S, s->successor()->successor()->successor(), d->successor()->successor()->successor()); - } - } -} - -void MacroAssembler::save_all_globals_into_locals() { - mov(G1,L1); - mov(G2,L2); - mov(G3,L3); - mov(G4,L4); - mov(G5,L5); - mov(G6,L6); - mov(G7,L7); -} - -void MacroAssembler::restore_globals_from_locals() { - mov(L1,G1); - mov(L2,G2); - mov(L3,G3); - mov(L4,G4); - mov(L5,G5); - mov(L6,G6); - mov(L7,G7); -} - -// Use for 64 bit operation. -void MacroAssembler::casx_under_lock(Register top_ptr_reg, Register top_reg, Register ptr_reg, address lock_addr, bool use_call_vm) -{ - // store ptr_reg as the new top value -#ifdef _LP64 - casx(top_ptr_reg, top_reg, ptr_reg); -#else - cas_under_lock(top_ptr_reg, top_reg, ptr_reg, lock_addr, use_call_vm); -#endif // _LP64 -} - -// [RGV] This routine does not handle 64 bit operations. -// use casx_under_lock() or casx directly!!! -void MacroAssembler::cas_under_lock(Register top_ptr_reg, Register top_reg, Register ptr_reg, address lock_addr, bool use_call_vm) -{ - // store ptr_reg as the new top value - if (VM_Version::v9_instructions_work()) { - cas(top_ptr_reg, top_reg, ptr_reg); - } else { - - // If the register is not an out nor global, it is not visible - // after the save. Allocate a register for it, save its - // value in the register save area (the save may not flush - // registers to the save area). - - Register top_ptr_reg_after_save; - Register top_reg_after_save; - Register ptr_reg_after_save; - - if (top_ptr_reg->is_out() || top_ptr_reg->is_global()) { - top_ptr_reg_after_save = top_ptr_reg->after_save(); - } else { - Address reg_save_addr = top_ptr_reg->address_in_saved_window(); - top_ptr_reg_after_save = L0; - st(top_ptr_reg, reg_save_addr); - } - - if (top_reg->is_out() || top_reg->is_global()) { - top_reg_after_save = top_reg->after_save(); - } else { - Address reg_save_addr = top_reg->address_in_saved_window(); - top_reg_after_save = L1; - st(top_reg, reg_save_addr); - } - - if (ptr_reg->is_out() || ptr_reg->is_global()) { - ptr_reg_after_save = ptr_reg->after_save(); - } else { - Address reg_save_addr = ptr_reg->address_in_saved_window(); - ptr_reg_after_save = L2; - st(ptr_reg, reg_save_addr); - } - - const Register& lock_reg = L3; - const Register& lock_ptr_reg = L4; - const Register& value_reg = L5; - const Register& yield_reg = L6; - const Register& yieldall_reg = L7; - - save_frame(); - - if (top_ptr_reg_after_save == L0) { - ld(top_ptr_reg->address_in_saved_window().after_save(), top_ptr_reg_after_save); - } - - if (top_reg_after_save == L1) { - ld(top_reg->address_in_saved_window().after_save(), top_reg_after_save); - } - - if (ptr_reg_after_save == L2) { - ld(ptr_reg->address_in_saved_window().after_save(), ptr_reg_after_save); - } - - Label(retry_get_lock); - Label(not_same); - Label(dont_yield); - - assert(lock_addr, "lock_address should be non null for v8"); - set((intptr_t)lock_addr, lock_ptr_reg); - // Initialize yield counter - mov(G0,yield_reg); - mov(G0, yieldall_reg); - set(StubRoutines::Sparc::locked, lock_reg); - - bind(retry_get_lock); - cmp_and_br_short(yield_reg, V8AtomicOperationUnderLockSpinCount, Assembler::less, Assembler::pt, dont_yield); - - if(use_call_vm) { - Untested("Need to verify global reg consistancy"); - call_VM(noreg, CAST_FROM_FN_PTR(address, SharedRuntime::yield_all), yieldall_reg); - } else { - // Save the regs and make space for a C call - save(SP, -96, SP); - save_all_globals_into_locals(); - call(CAST_FROM_FN_PTR(address,os::yield_all)); - delayed()->mov(yieldall_reg, O0); - restore_globals_from_locals(); - restore(); - } - - // reset the counter - mov(G0,yield_reg); - add(yieldall_reg, 1, yieldall_reg); - - bind(dont_yield); - // try to get lock - swap(lock_ptr_reg, 0, lock_reg); - - // did we get the lock? - cmp(lock_reg, StubRoutines::Sparc::unlocked); - br(Assembler::notEqual, true, Assembler::pn, retry_get_lock); - delayed()->add(yield_reg,1,yield_reg); - - // yes, got lock. do we have the same top? - ld(top_ptr_reg_after_save, 0, value_reg); - cmp_and_br_short(value_reg, top_reg_after_save, Assembler::notEqual, Assembler::pn, not_same); - - // yes, same top. - st(ptr_reg_after_save, top_ptr_reg_after_save, 0); - membar(Assembler::StoreStore); - - bind(not_same); - mov(value_reg, ptr_reg_after_save); - st(lock_reg, lock_ptr_reg, 0); // unlock - - restore(); - } -} - -RegisterOrConstant MacroAssembler::delayed_value_impl(intptr_t* delayed_value_addr, - Register tmp, - int offset) { - intptr_t value = *delayed_value_addr; - if (value != 0) - return RegisterOrConstant(value + offset); - - // load indirectly to solve generation ordering problem - AddressLiteral a(delayed_value_addr); - load_ptr_contents(a, tmp); - -#ifdef ASSERT - tst(tmp); - breakpoint_trap(zero, xcc); -#endif - - if (offset != 0) - add(tmp, offset, tmp); - - return RegisterOrConstant(tmp); -} - - -RegisterOrConstant MacroAssembler::regcon_andn_ptr(RegisterOrConstant s1, RegisterOrConstant s2, RegisterOrConstant d, Register temp) { - assert(d.register_or_noreg() != G0, "lost side effect"); - if ((s2.is_constant() && s2.as_constant() == 0) || - (s2.is_register() && s2.as_register() == G0)) { - // Do nothing, just move value. - if (s1.is_register()) { - if (d.is_constant()) d = temp; - mov(s1.as_register(), d.as_register()); - return d; - } else { - return s1; - } - } - - if (s1.is_register()) { - assert_different_registers(s1.as_register(), temp); - if (d.is_constant()) d = temp; - andn(s1.as_register(), ensure_simm13_or_reg(s2, temp), d.as_register()); - return d; - } else { - if (s2.is_register()) { - assert_different_registers(s2.as_register(), temp); - if (d.is_constant()) d = temp; - set(s1.as_constant(), temp); - andn(temp, s2.as_register(), d.as_register()); - return d; - } else { - intptr_t res = s1.as_constant() & ~s2.as_constant(); - return res; - } - } -} - -RegisterOrConstant MacroAssembler::regcon_inc_ptr(RegisterOrConstant s1, RegisterOrConstant s2, RegisterOrConstant d, Register temp) { - assert(d.register_or_noreg() != G0, "lost side effect"); - if ((s2.is_constant() && s2.as_constant() == 0) || - (s2.is_register() && s2.as_register() == G0)) { - // Do nothing, just move value. - if (s1.is_register()) { - if (d.is_constant()) d = temp; - mov(s1.as_register(), d.as_register()); - return d; - } else { - return s1; - } - } - - if (s1.is_register()) { - assert_different_registers(s1.as_register(), temp); - if (d.is_constant()) d = temp; - add(s1.as_register(), ensure_simm13_or_reg(s2, temp), d.as_register()); - return d; - } else { - if (s2.is_register()) { - assert_different_registers(s2.as_register(), temp); - if (d.is_constant()) d = temp; - add(s2.as_register(), ensure_simm13_or_reg(s1, temp), d.as_register()); - return d; - } else { - intptr_t res = s1.as_constant() + s2.as_constant(); - return res; - } - } -} - -RegisterOrConstant MacroAssembler::regcon_sll_ptr(RegisterOrConstant s1, RegisterOrConstant s2, RegisterOrConstant d, Register temp) { - assert(d.register_or_noreg() != G0, "lost side effect"); - if (!is_simm13(s2.constant_or_zero())) - s2 = (s2.as_constant() & 0xFF); - if ((s2.is_constant() && s2.as_constant() == 0) || - (s2.is_register() && s2.as_register() == G0)) { - // Do nothing, just move value. - if (s1.is_register()) { - if (d.is_constant()) d = temp; - mov(s1.as_register(), d.as_register()); - return d; - } else { - return s1; - } - } - - if (s1.is_register()) { - assert_different_registers(s1.as_register(), temp); - if (d.is_constant()) d = temp; - sll_ptr(s1.as_register(), ensure_simm13_or_reg(s2, temp), d.as_register()); - return d; - } else { - if (s2.is_register()) { - assert_different_registers(s2.as_register(), temp); - if (d.is_constant()) d = temp; - set(s1.as_constant(), temp); - sll_ptr(temp, s2.as_register(), d.as_register()); - return d; - } else { - intptr_t res = s1.as_constant() << s2.as_constant(); - return res; - } - } -} - - -// Look up the method for a megamorphic invokeinterface call. -// The target method is determined by . -// The receiver klass is in recv_klass. -// On success, the result will be in method_result, and execution falls through. -// On failure, execution transfers to the given label. -void MacroAssembler::lookup_interface_method(Register recv_klass, - Register intf_klass, - RegisterOrConstant itable_index, - Register method_result, - Register scan_temp, - Register sethi_temp, - Label& L_no_such_interface) { - assert_different_registers(recv_klass, intf_klass, method_result, scan_temp); - assert(itable_index.is_constant() || itable_index.as_register() == method_result, - "caller must use same register for non-constant itable index as for method"); - - Label L_no_such_interface_restore; - bool did_save = false; - if (scan_temp == noreg || sethi_temp == noreg) { - Register recv_2 = recv_klass->is_global() ? recv_klass : L0; - Register intf_2 = intf_klass->is_global() ? intf_klass : L1; - assert(method_result->is_global(), "must be able to return value"); - scan_temp = L2; - sethi_temp = L3; - save_frame_and_mov(0, recv_klass, recv_2, intf_klass, intf_2); - recv_klass = recv_2; - intf_klass = intf_2; - did_save = true; - } - - // Compute start of first itableOffsetEntry (which is at the end of the vtable) - int vtable_base = InstanceKlass::vtable_start_offset() * wordSize; - int scan_step = itableOffsetEntry::size() * wordSize; - int vte_size = vtableEntry::size() * wordSize; - - lduw(recv_klass, InstanceKlass::vtable_length_offset() * wordSize, scan_temp); - // %%% We should store the aligned, prescaled offset in the klassoop. - // Then the next several instructions would fold away. - - int round_to_unit = ((HeapWordsPerLong > 1) ? BytesPerLong : 0); - int itb_offset = vtable_base; - if (round_to_unit != 0) { - // hoist first instruction of round_to(scan_temp, BytesPerLong): - itb_offset += round_to_unit - wordSize; - } - int itb_scale = exact_log2(vtableEntry::size() * wordSize); - sll(scan_temp, itb_scale, scan_temp); - add(scan_temp, itb_offset, scan_temp); - if (round_to_unit != 0) { - // Round up to align_object_offset boundary - // see code for InstanceKlass::start_of_itable! - // Was: round_to(scan_temp, BytesPerLong); - // Hoisted: add(scan_temp, BytesPerLong-1, scan_temp); - and3(scan_temp, -round_to_unit, scan_temp); - } - add(recv_klass, scan_temp, scan_temp); - - // Adjust recv_klass by scaled itable_index, so we can free itable_index. - RegisterOrConstant itable_offset = itable_index; - itable_offset = regcon_sll_ptr(itable_index, exact_log2(itableMethodEntry::size() * wordSize), itable_offset); - itable_offset = regcon_inc_ptr(itable_offset, itableMethodEntry::method_offset_in_bytes(), itable_offset); - add(recv_klass, ensure_simm13_or_reg(itable_offset, sethi_temp), recv_klass); - - // for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) { - // if (scan->interface() == intf) { - // result = (klass + scan->offset() + itable_index); - // } - // } - Label L_search, L_found_method; - - for (int peel = 1; peel >= 0; peel--) { - // %%%% Could load both offset and interface in one ldx, if they were - // in the opposite order. This would save a load. - ld_ptr(scan_temp, itableOffsetEntry::interface_offset_in_bytes(), method_result); - - // Check that this entry is non-null. A null entry means that - // the receiver class doesn't implement the interface, and wasn't the - // same as when the caller was compiled. - bpr(Assembler::rc_z, false, Assembler::pn, method_result, did_save ? L_no_such_interface_restore : L_no_such_interface); - delayed()->cmp(method_result, intf_klass); - - if (peel) { - brx(Assembler::equal, false, Assembler::pt, L_found_method); - } else { - brx(Assembler::notEqual, false, Assembler::pn, L_search); - // (invert the test to fall through to found_method...) - } - delayed()->add(scan_temp, scan_step, scan_temp); - - if (!peel) break; - - bind(L_search); - } - - bind(L_found_method); - - // Got a hit. - int ito_offset = itableOffsetEntry::offset_offset_in_bytes(); - // scan_temp[-scan_step] points to the vtable offset we need - ito_offset -= scan_step; - lduw(scan_temp, ito_offset, scan_temp); - ld_ptr(recv_klass, scan_temp, method_result); - - if (did_save) { - Label L_done; - ba(L_done); - delayed()->restore(); - - bind(L_no_such_interface_restore); - ba(L_no_such_interface); - delayed()->restore(); - - bind(L_done); - } -} - - -// virtual method calling -void MacroAssembler::lookup_virtual_method(Register recv_klass, - RegisterOrConstant vtable_index, - Register method_result) { - assert_different_registers(recv_klass, method_result, vtable_index.register_or_noreg()); - Register sethi_temp = method_result; - const int base = (InstanceKlass::vtable_start_offset() * wordSize + - // method pointer offset within the vtable entry: - vtableEntry::method_offset_in_bytes()); - RegisterOrConstant vtable_offset = vtable_index; - // Each of the following three lines potentially generates an instruction. - // But the total number of address formation instructions will always be - // at most two, and will often be zero. In any case, it will be optimal. - // If vtable_index is a register, we will have (sll_ptr N,x; inc_ptr B,x; ld_ptr k,x). - // If vtable_index is a constant, we will have at most (set B+X<is_global()) sub_2 = L0; - if (!sup_2->is_global()) sup_2 = L1; - bool did_save = false; - if (temp_reg == noreg || temp2_reg == noreg) { - temp_reg = L2; - temp2_reg = L3; - save_frame_and_mov(0, sub_klass, sub_2, super_klass, sup_2); - sub_klass = sub_2; - super_klass = sup_2; - did_save = true; - } - Label L_failure, L_pop_to_failure, L_pop_to_success; - check_klass_subtype_fast_path(sub_klass, super_klass, - temp_reg, temp2_reg, - (did_save ? &L_pop_to_success : &L_success), - (did_save ? &L_pop_to_failure : &L_failure), NULL); - - if (!did_save) - save_frame_and_mov(0, sub_klass, sub_2, super_klass, sup_2); - check_klass_subtype_slow_path(sub_2, sup_2, - L2, L3, L4, L5, - NULL, &L_pop_to_failure); - - // on success: - bind(L_pop_to_success); - restore(); - ba_short(L_success); - - // on failure: - bind(L_pop_to_failure); - restore(); - bind(L_failure); -} - - -void MacroAssembler::check_klass_subtype_fast_path(Register sub_klass, - Register super_klass, - Register temp_reg, - Register temp2_reg, - Label* L_success, - Label* L_failure, - Label* L_slow_path, - RegisterOrConstant super_check_offset) { - int sc_offset = in_bytes(Klass::secondary_super_cache_offset()); - int sco_offset = in_bytes(Klass::super_check_offset_offset()); - - bool must_load_sco = (super_check_offset.constant_or_zero() == -1); - bool need_slow_path = (must_load_sco || - super_check_offset.constant_or_zero() == sco_offset); - - assert_different_registers(sub_klass, super_klass, temp_reg); - if (super_check_offset.is_register()) { - assert_different_registers(sub_klass, super_klass, temp_reg, - super_check_offset.as_register()); - } else if (must_load_sco) { - assert(temp2_reg != noreg, "supply either a temp or a register offset"); - } - - Label L_fallthrough; - int label_nulls = 0; - if (L_success == NULL) { L_success = &L_fallthrough; label_nulls++; } - if (L_failure == NULL) { L_failure = &L_fallthrough; label_nulls++; } - if (L_slow_path == NULL) { L_slow_path = &L_fallthrough; label_nulls++; } - assert(label_nulls <= 1 || - (L_slow_path == &L_fallthrough && label_nulls <= 2 && !need_slow_path), - "at most one NULL in the batch, usually"); - - // If the pointers are equal, we are done (e.g., String[] elements). - // This self-check enables sharing of secondary supertype arrays among - // non-primary types such as array-of-interface. Otherwise, each such - // type would need its own customized SSA. - // We move this check to the front of the fast path because many - // type checks are in fact trivially successful in this manner, - // so we get a nicely predicted branch right at the start of the check. - cmp(super_klass, sub_klass); - brx(Assembler::equal, false, Assembler::pn, *L_success); - delayed()->nop(); - - // Check the supertype display: - if (must_load_sco) { - // The super check offset is always positive... - lduw(super_klass, sco_offset, temp2_reg); - super_check_offset = RegisterOrConstant(temp2_reg); - // super_check_offset is register. - assert_different_registers(sub_klass, super_klass, temp_reg, super_check_offset.as_register()); - } - ld_ptr(sub_klass, super_check_offset, temp_reg); - cmp(super_klass, temp_reg); - - // This check has worked decisively for primary supers. - // Secondary supers are sought in the super_cache ('super_cache_addr'). - // (Secondary supers are interfaces and very deeply nested subtypes.) - // This works in the same check above because of a tricky aliasing - // between the super_cache and the primary super display elements. - // (The 'super_check_addr' can address either, as the case requires.) - // Note that the cache is updated below if it does not help us find - // what we need immediately. - // So if it was a primary super, we can just fail immediately. - // Otherwise, it's the slow path for us (no success at this point). - - // Hacked ba(), which may only be used just before L_fallthrough. -#define FINAL_JUMP(label) \ - if (&(label) != &L_fallthrough) { \ - ba(label); delayed()->nop(); \ - } - - if (super_check_offset.is_register()) { - brx(Assembler::equal, false, Assembler::pn, *L_success); - delayed()->cmp(super_check_offset.as_register(), sc_offset); - - if (L_failure == &L_fallthrough) { - brx(Assembler::equal, false, Assembler::pt, *L_slow_path); - delayed()->nop(); - } else { - brx(Assembler::notEqual, false, Assembler::pn, *L_failure); - delayed()->nop(); - FINAL_JUMP(*L_slow_path); - } - } else if (super_check_offset.as_constant() == sc_offset) { - // Need a slow path; fast failure is impossible. - if (L_slow_path == &L_fallthrough) { - brx(Assembler::equal, false, Assembler::pt, *L_success); - delayed()->nop(); - } else { - brx(Assembler::notEqual, false, Assembler::pn, *L_slow_path); - delayed()->nop(); - FINAL_JUMP(*L_success); - } - } else { - // No slow path; it's a fast decision. - if (L_failure == &L_fallthrough) { - brx(Assembler::equal, false, Assembler::pt, *L_success); - delayed()->nop(); - } else { - brx(Assembler::notEqual, false, Assembler::pn, *L_failure); - delayed()->nop(); - FINAL_JUMP(*L_success); - } - } - - bind(L_fallthrough); - -#undef FINAL_JUMP -} - - -void MacroAssembler::check_klass_subtype_slow_path(Register sub_klass, - Register super_klass, - Register count_temp, - Register scan_temp, - Register scratch_reg, - Register coop_reg, - Label* L_success, - Label* L_failure) { - assert_different_registers(sub_klass, super_klass, - count_temp, scan_temp, scratch_reg, coop_reg); - - Label L_fallthrough, L_loop; - int label_nulls = 0; - if (L_success == NULL) { L_success = &L_fallthrough; label_nulls++; } - if (L_failure == NULL) { L_failure = &L_fallthrough; label_nulls++; } - assert(label_nulls <= 1, "at most one NULL in the batch"); - - // a couple of useful fields in sub_klass: - int ss_offset = in_bytes(Klass::secondary_supers_offset()); - int sc_offset = in_bytes(Klass::secondary_super_cache_offset()); - - // Do a linear scan of the secondary super-klass chain. - // This code is rarely used, so simplicity is a virtue here. - -#ifndef PRODUCT - int* pst_counter = &SharedRuntime::_partial_subtype_ctr; - inc_counter((address) pst_counter, count_temp, scan_temp); -#endif - - // We will consult the secondary-super array. - ld_ptr(sub_klass, ss_offset, scan_temp); - - Register search_key = super_klass; - - // Load the array length. (Positive movl does right thing on LP64.) - lduw(scan_temp, Array::length_offset_in_bytes(), count_temp); - - // Check for empty secondary super list - tst(count_temp); - - // In the array of super classes elements are pointer sized. - int element_size = wordSize; - - // Top of search loop - bind(L_loop); - br(Assembler::equal, false, Assembler::pn, *L_failure); - delayed()->add(scan_temp, element_size, scan_temp); - - // Skip the array header in all array accesses. - int elem_offset = Array::base_offset_in_bytes(); - elem_offset -= element_size; // the scan pointer was pre-incremented also - - // Load next super to check - ld_ptr( scan_temp, elem_offset, scratch_reg ); - - // Look for Rsuper_klass on Rsub_klass's secondary super-class-overflow list - cmp(scratch_reg, search_key); - - // A miss means we are NOT a subtype and need to keep looping - brx(Assembler::notEqual, false, Assembler::pn, L_loop); - delayed()->deccc(count_temp); // decrement trip counter in delay slot - - // Success. Cache the super we found and proceed in triumph. - st_ptr(super_klass, sub_klass, sc_offset); - - if (L_success != &L_fallthrough) { - ba(*L_success); - delayed()->nop(); - } - - bind(L_fallthrough); -} - - -RegisterOrConstant MacroAssembler::argument_offset(RegisterOrConstant arg_slot, - Register temp_reg, - int extra_slot_offset) { - // cf. TemplateTable::prepare_invoke(), if (load_receiver). - int stackElementSize = Interpreter::stackElementSize; - int offset = extra_slot_offset * stackElementSize; - if (arg_slot.is_constant()) { - offset += arg_slot.as_constant() * stackElementSize; - return offset; - } else { - assert(temp_reg != noreg, "must specify"); - sll_ptr(arg_slot.as_register(), exact_log2(stackElementSize), temp_reg); - if (offset != 0) - add(temp_reg, offset, temp_reg); - return temp_reg; - } -} - - -Address MacroAssembler::argument_address(RegisterOrConstant arg_slot, - Register temp_reg, - int extra_slot_offset) { - return Address(Gargs, argument_offset(arg_slot, temp_reg, extra_slot_offset)); -} - - -void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg, - Register temp_reg, - Label& done, Label* slow_case, - BiasedLockingCounters* counters) { - assert(UseBiasedLocking, "why call this otherwise?"); - - if (PrintBiasedLockingStatistics) { - assert_different_registers(obj_reg, mark_reg, temp_reg, O7); - if (counters == NULL) - counters = BiasedLocking::counters(); - } - - Label cas_label; - - // Biased locking - // See whether the lock is currently biased toward our thread and - // whether the epoch is still valid - // Note that the runtime guarantees sufficient alignment of JavaThread - // pointers to allow age to be placed into low bits - assert(markOopDesc::age_shift == markOopDesc::lock_bits + markOopDesc::biased_lock_bits, "biased locking makes assumptions about bit layout"); - and3(mark_reg, markOopDesc::biased_lock_mask_in_place, temp_reg); - cmp_and_brx_short(temp_reg, markOopDesc::biased_lock_pattern, Assembler::notEqual, Assembler::pn, cas_label); - - load_klass(obj_reg, temp_reg); - ld_ptr(Address(temp_reg, Klass::prototype_header_offset()), temp_reg); - or3(G2_thread, temp_reg, temp_reg); - xor3(mark_reg, temp_reg, temp_reg); - andcc(temp_reg, ~((int) markOopDesc::age_mask_in_place), temp_reg); - if (counters != NULL) { - cond_inc(Assembler::equal, (address) counters->biased_lock_entry_count_addr(), mark_reg, temp_reg); - // Reload mark_reg as we may need it later - ld_ptr(Address(obj_reg, oopDesc::mark_offset_in_bytes()), mark_reg); - } - brx(Assembler::equal, true, Assembler::pt, done); - delayed()->nop(); - - Label try_revoke_bias; - Label try_rebias; - Address mark_addr = Address(obj_reg, oopDesc::mark_offset_in_bytes()); - assert(mark_addr.disp() == 0, "cas must take a zero displacement"); - - // At this point we know that the header has the bias pattern and - // that we are not the bias owner in the current epoch. We need to - // figure out more details about the state of the header in order to - // know what operations can be legally performed on the object's - // header. - - // If the low three bits in the xor result aren't clear, that means - // the prototype header is no longer biased and we have to revoke - // the bias on this object. - btst(markOopDesc::biased_lock_mask_in_place, temp_reg); - brx(Assembler::notZero, false, Assembler::pn, try_revoke_bias); - - // Biasing is still enabled for this data type. See whether the - // epoch of the current bias is still valid, meaning that the epoch - // bits of the mark word are equal to the epoch bits of the - // prototype header. (Note that the prototype header's epoch bits - // only change at a safepoint.) If not, attempt to rebias the object - // toward the current thread. Note that we must be absolutely sure - // that the current epoch is invalid in order to do this because - // otherwise the manipulations it performs on the mark word are - // illegal. - delayed()->btst(markOopDesc::epoch_mask_in_place, temp_reg); - brx(Assembler::notZero, false, Assembler::pn, try_rebias); - - // The epoch of the current bias is still valid but we know nothing - // about the owner; it might be set or it might be clear. Try to - // acquire the bias of the object using an atomic operation. If this - // fails we will go in to the runtime to revoke the object's bias. - // Note that we first construct the presumed unbiased header so we - // don't accidentally blow away another thread's valid bias. - delayed()->and3(mark_reg, - markOopDesc::biased_lock_mask_in_place | markOopDesc::age_mask_in_place | markOopDesc::epoch_mask_in_place, - mark_reg); - or3(G2_thread, mark_reg, temp_reg); - casn(mark_addr.base(), mark_reg, temp_reg); - // If the biasing toward our thread failed, this means that - // another thread succeeded in biasing it toward itself and we - // need to revoke that bias. The revocation will occur in the - // interpreter runtime in the slow case. - cmp(mark_reg, temp_reg); - if (counters != NULL) { - cond_inc(Assembler::zero, (address) counters->anonymously_biased_lock_entry_count_addr(), mark_reg, temp_reg); - } - if (slow_case != NULL) { - brx(Assembler::notEqual, true, Assembler::pn, *slow_case); - delayed()->nop(); - } - ba_short(done); - - bind(try_rebias); - // At this point we know the epoch has expired, meaning that the - // current "bias owner", if any, is actually invalid. Under these - // circumstances _only_, we are allowed to use the current header's - // value as the comparison value when doing the cas to acquire the - // bias in the current epoch. In other words, we allow transfer of - // the bias from one thread to another directly in this situation. - // - // FIXME: due to a lack of registers we currently blow away the age - // bits in this situation. Should attempt to preserve them. - load_klass(obj_reg, temp_reg); - ld_ptr(Address(temp_reg, Klass::prototype_header_offset()), temp_reg); - or3(G2_thread, temp_reg, temp_reg); - casn(mark_addr.base(), mark_reg, temp_reg); - // If the biasing toward our thread failed, this means that - // another thread succeeded in biasing it toward itself and we - // need to revoke that bias. The revocation will occur in the - // interpreter runtime in the slow case. - cmp(mark_reg, temp_reg); - if (counters != NULL) { - cond_inc(Assembler::zero, (address) counters->rebiased_lock_entry_count_addr(), mark_reg, temp_reg); - } - if (slow_case != NULL) { - brx(Assembler::notEqual, true, Assembler::pn, *slow_case); - delayed()->nop(); - } - ba_short(done); - - bind(try_revoke_bias); - // The prototype mark in the klass doesn't have the bias bit set any - // more, indicating that objects of this data type are not supposed - // to be biased any more. We are going to try to reset the mark of - // this object to the prototype value and fall through to the - // CAS-based locking scheme. Note that if our CAS fails, it means - // that another thread raced us for the privilege of revoking the - // bias of this particular object, so it's okay to continue in the - // normal locking code. - // - // FIXME: due to a lack of registers we currently blow away the age - // bits in this situation. Should attempt to preserve them. - load_klass(obj_reg, temp_reg); - ld_ptr(Address(temp_reg, Klass::prototype_header_offset()), temp_reg); - casn(mark_addr.base(), mark_reg, temp_reg); - // Fall through to the normal CAS-based lock, because no matter what - // the result of the above CAS, some thread must have succeeded in - // removing the bias bit from the object's header. - if (counters != NULL) { - cmp(mark_reg, temp_reg); - cond_inc(Assembler::zero, (address) counters->revoked_lock_entry_count_addr(), mark_reg, temp_reg); - } - - bind(cas_label); -} - -void MacroAssembler::biased_locking_exit (Address mark_addr, Register temp_reg, Label& done, - bool allow_delay_slot_filling) { - // Check for biased locking unlock case, which is a no-op - // Note: we do not have to check the thread ID for two reasons. - // First, the interpreter checks for IllegalMonitorStateException at - // a higher level. Second, if the bias was revoked while we held the - // lock, the object could not be rebiased toward another thread, so - // the bias bit would be clear. - ld_ptr(mark_addr, temp_reg); - and3(temp_reg, markOopDesc::biased_lock_mask_in_place, temp_reg); - cmp(temp_reg, markOopDesc::biased_lock_pattern); - brx(Assembler::equal, allow_delay_slot_filling, Assembler::pt, done); - delayed(); - if (!allow_delay_slot_filling) { - nop(); - } -} - - -// CASN -- 32-64 bit switch hitter similar to the synthetic CASN provided by -// Solaris/SPARC's "as". Another apt name would be cas_ptr() - -void MacroAssembler::casn (Register addr_reg, Register cmp_reg, Register set_reg ) { - casx_under_lock (addr_reg, cmp_reg, set_reg, (address)StubRoutines::Sparc::atomic_memory_operation_lock_addr()); -} - - - -// compiler_lock_object() and compiler_unlock_object() are direct transliterations -// of i486.ad fast_lock() and fast_unlock(). See those methods for detailed comments. -// The code could be tightened up considerably. -// -// box->dhw disposition - post-conditions at DONE_LABEL. -// - Successful inflated lock: box->dhw != 0. -// Any non-zero value suffices. -// Consider G2_thread, rsp, boxReg, or unused_mark() -// - Successful Stack-lock: box->dhw == mark. -// box->dhw must contain the displaced mark word value -// - Failure -- icc.ZFlag == 0 and box->dhw is undefined. -// The slow-path fast_enter() and slow_enter() operators -// are responsible for setting box->dhw = NonZero (typically ::unused_mark). -// - Biased: box->dhw is undefined -// -// SPARC refworkload performance - specifically jetstream and scimark - are -// extremely sensitive to the size of the code emitted by compiler_lock_object -// and compiler_unlock_object. Critically, the key factor is code size, not path -// length. (Simply experiments to pad CLO with unexecuted NOPs demonstrte the -// effect). - - -void MacroAssembler::compiler_lock_object(Register Roop, Register Rmark, - Register Rbox, Register Rscratch, - BiasedLockingCounters* counters, - bool try_bias) { - Address mark_addr(Roop, oopDesc::mark_offset_in_bytes()); - - verify_oop(Roop); - Label done ; - - if (counters != NULL) { - inc_counter((address) counters->total_entry_count_addr(), Rmark, Rscratch); - } - - if (EmitSync & 1) { - mov(3, Rscratch); - st_ptr(Rscratch, Rbox, BasicLock::displaced_header_offset_in_bytes()); - cmp(SP, G0); - return ; - } - - if (EmitSync & 2) { - - // Fetch object's markword - ld_ptr(mark_addr, Rmark); - - if (try_bias) { - biased_locking_enter(Roop, Rmark, Rscratch, done, NULL, counters); - } - - // Save Rbox in Rscratch to be used for the cas operation - mov(Rbox, Rscratch); - - // set Rmark to markOop | markOopDesc::unlocked_value - or3(Rmark, markOopDesc::unlocked_value, Rmark); - - // Initialize the box. (Must happen before we update the object mark!) - st_ptr(Rmark, Rbox, BasicLock::displaced_header_offset_in_bytes()); - - // compare object markOop with Rmark and if equal exchange Rscratch with object markOop - assert(mark_addr.disp() == 0, "cas must take a zero displacement"); - casx_under_lock(mark_addr.base(), Rmark, Rscratch, - (address)StubRoutines::Sparc::atomic_memory_operation_lock_addr()); - - // if compare/exchange succeeded we found an unlocked object and we now have locked it - // hence we are done - cmp(Rmark, Rscratch); -#ifdef _LP64 - sub(Rscratch, STACK_BIAS, Rscratch); -#endif - brx(Assembler::equal, false, Assembler::pt, done); - delayed()->sub(Rscratch, SP, Rscratch); //pull next instruction into delay slot - - // we did not find an unlocked object so see if this is a recursive case - // sub(Rscratch, SP, Rscratch); - assert(os::vm_page_size() > 0xfff, "page size too small - change the constant"); - andcc(Rscratch, 0xfffff003, Rscratch); - st_ptr(Rscratch, Rbox, BasicLock::displaced_header_offset_in_bytes()); - bind (done); - return ; - } - - Label Egress ; - - if (EmitSync & 256) { - Label IsInflated ; - - ld_ptr(mark_addr, Rmark); // fetch obj->mark - // Triage: biased, stack-locked, neutral, inflated - if (try_bias) { - biased_locking_enter(Roop, Rmark, Rscratch, done, NULL, counters); - // Invariant: if control reaches this point in the emitted stream - // then Rmark has not been modified. - } - - // Store mark into displaced mark field in the on-stack basic-lock "box" - // Critically, this must happen before the CAS - // Maximize the ST-CAS distance to minimize the ST-before-CAS penalty. - st_ptr(Rmark, Rbox, BasicLock::displaced_header_offset_in_bytes()); - andcc(Rmark, 2, G0); - brx(Assembler::notZero, false, Assembler::pn, IsInflated); - delayed()-> - - // Try stack-lock acquisition. - // Beware: the 1st instruction is in a delay slot - mov(Rbox, Rscratch); - or3(Rmark, markOopDesc::unlocked_value, Rmark); - assert(mark_addr.disp() == 0, "cas must take a zero displacement"); - casn(mark_addr.base(), Rmark, Rscratch); - cmp(Rmark, Rscratch); - brx(Assembler::equal, false, Assembler::pt, done); - delayed()->sub(Rscratch, SP, Rscratch); - - // Stack-lock attempt failed - check for recursive stack-lock. - // See the comments below about how we might remove this case. -#ifdef _LP64 - sub(Rscratch, STACK_BIAS, Rscratch); -#endif - assert(os::vm_page_size() > 0xfff, "page size too small - change the constant"); - andcc(Rscratch, 0xfffff003, Rscratch); - br(Assembler::always, false, Assembler::pt, done); - delayed()-> st_ptr(Rscratch, Rbox, BasicLock::displaced_header_offset_in_bytes()); - - bind(IsInflated); - if (EmitSync & 64) { - // If m->owner != null goto IsLocked - // Pessimistic form: Test-and-CAS vs CAS - // The optimistic form avoids RTS->RTO cache line upgrades. - ld_ptr(Rmark, ObjectMonitor::owner_offset_in_bytes() - 2, Rscratch); - andcc(Rscratch, Rscratch, G0); - brx(Assembler::notZero, false, Assembler::pn, done); - delayed()->nop(); - // m->owner == null : it's unlocked. - } - - // Try to CAS m->owner from null to Self - // Invariant: if we acquire the lock then _recursions should be 0. - add(Rmark, ObjectMonitor::owner_offset_in_bytes()-2, Rmark); - mov(G2_thread, Rscratch); - casn(Rmark, G0, Rscratch); - cmp(Rscratch, G0); - // Intentional fall-through into done - } else { - // Aggressively avoid the Store-before-CAS penalty - // Defer the store into box->dhw until after the CAS - Label IsInflated, Recursive ; - -// Anticipate CAS -- Avoid RTS->RTO upgrade -// prefetch (mark_addr, Assembler::severalWritesAndPossiblyReads); - - ld_ptr(mark_addr, Rmark); // fetch obj->mark - // Triage: biased, stack-locked, neutral, inflated - - if (try_bias) { - biased_locking_enter(Roop, Rmark, Rscratch, done, NULL, counters); - // Invariant: if control reaches this point in the emitted stream - // then Rmark has not been modified. - } - andcc(Rmark, 2, G0); - brx(Assembler::notZero, false, Assembler::pn, IsInflated); - delayed()-> // Beware - dangling delay-slot - - // Try stack-lock acquisition. - // Transiently install BUSY (0) encoding in the mark word. - // if the CAS of 0 into the mark was successful then we execute: - // ST box->dhw = mark -- save fetched mark in on-stack basiclock box - // ST obj->mark = box -- overwrite transient 0 value - // This presumes TSO, of course. - - mov(0, Rscratch); - or3(Rmark, markOopDesc::unlocked_value, Rmark); - assert(mark_addr.disp() == 0, "cas must take a zero displacement"); - casn(mark_addr.base(), Rmark, Rscratch); -// prefetch (mark_addr, Assembler::severalWritesAndPossiblyReads); - cmp(Rscratch, Rmark); - brx(Assembler::notZero, false, Assembler::pn, Recursive); - delayed()->st_ptr(Rmark, Rbox, BasicLock::displaced_header_offset_in_bytes()); - if (counters != NULL) { - cond_inc(Assembler::equal, (address) counters->fast_path_entry_count_addr(), Rmark, Rscratch); - } - ba(done); - delayed()->st_ptr(Rbox, mark_addr); - - bind(Recursive); - // Stack-lock attempt failed - check for recursive stack-lock. - // Tests show that we can remove the recursive case with no impact - // on refworkload 0.83. If we need to reduce the size of the code - // emitted by compiler_lock_object() the recursive case is perfect - // candidate. - // - // A more extreme idea is to always inflate on stack-lock recursion. - // This lets us eliminate the recursive checks in compiler_lock_object - // and compiler_unlock_object and the (box->dhw == 0) encoding. - // A brief experiment - requiring changes to synchronizer.cpp, interpreter, - // and showed a performance *increase*. In the same experiment I eliminated - // the fast-path stack-lock code from the interpreter and always passed - // control to the "slow" operators in synchronizer.cpp. - - // RScratch contains the fetched obj->mark value from the failed CASN. -#ifdef _LP64 - sub(Rscratch, STACK_BIAS, Rscratch); -#endif - sub(Rscratch, SP, Rscratch); - assert(os::vm_page_size() > 0xfff, "page size too small - change the constant"); - andcc(Rscratch, 0xfffff003, Rscratch); - if (counters != NULL) { - // Accounting needs the Rscratch register - st_ptr(Rscratch, Rbox, BasicLock::displaced_header_offset_in_bytes()); - cond_inc(Assembler::equal, (address) counters->fast_path_entry_count_addr(), Rmark, Rscratch); - ba_short(done); - } else { - ba(done); - delayed()->st_ptr(Rscratch, Rbox, BasicLock::displaced_header_offset_in_bytes()); - } - - bind (IsInflated); - if (EmitSync & 64) { - // If m->owner != null goto IsLocked - // Test-and-CAS vs CAS - // Pessimistic form avoids futile (doomed) CAS attempts - // The optimistic form avoids RTS->RTO cache line upgrades. - ld_ptr(Rmark, ObjectMonitor::owner_offset_in_bytes() - 2, Rscratch); - andcc(Rscratch, Rscratch, G0); - brx(Assembler::notZero, false, Assembler::pn, done); - delayed()->nop(); - // m->owner == null : it's unlocked. - } - - // Try to CAS m->owner from null to Self - // Invariant: if we acquire the lock then _recursions should be 0. - add(Rmark, ObjectMonitor::owner_offset_in_bytes()-2, Rmark); - mov(G2_thread, Rscratch); - casn(Rmark, G0, Rscratch); - cmp(Rscratch, G0); - // ST box->displaced_header = NonZero. - // Any non-zero value suffices: - // unused_mark(), G2_thread, RBox, RScratch, rsp, etc. - st_ptr(Rbox, Rbox, BasicLock::displaced_header_offset_in_bytes()); - // Intentional fall-through into done - } - - bind (done); -} - -void MacroAssembler::compiler_unlock_object(Register Roop, Register Rmark, - Register Rbox, Register Rscratch, - bool try_bias) { - Address mark_addr(Roop, oopDesc::mark_offset_in_bytes()); - - Label done ; - - if (EmitSync & 4) { - cmp(SP, G0); - return ; - } - - if (EmitSync & 8) { - if (try_bias) { - biased_locking_exit(mark_addr, Rscratch, done); - } - - // Test first if it is a fast recursive unlock - ld_ptr(Rbox, BasicLock::displaced_header_offset_in_bytes(), Rmark); - br_null_short(Rmark, Assembler::pt, done); - - // Check if it is still a light weight lock, this is is true if we see - // the stack address of the basicLock in the markOop of the object - assert(mark_addr.disp() == 0, "cas must take a zero displacement"); - casx_under_lock(mark_addr.base(), Rbox, Rmark, - (address)StubRoutines::Sparc::atomic_memory_operation_lock_addr()); - ba(done); - delayed()->cmp(Rbox, Rmark); - bind(done); - return ; - } - - // Beware ... If the aggregate size of the code emitted by CLO and CUO is - // is too large performance rolls abruptly off a cliff. - // This could be related to inlining policies, code cache management, or - // I$ effects. - Label LStacked ; - - if (try_bias) { - // TODO: eliminate redundant LDs of obj->mark - biased_locking_exit(mark_addr, Rscratch, done); - } - - ld_ptr(Roop, oopDesc::mark_offset_in_bytes(), Rmark); - ld_ptr(Rbox, BasicLock::displaced_header_offset_in_bytes(), Rscratch); - andcc(Rscratch, Rscratch, G0); - brx(Assembler::zero, false, Assembler::pn, done); - delayed()->nop(); // consider: relocate fetch of mark, above, into this DS - andcc(Rmark, 2, G0); - brx(Assembler::zero, false, Assembler::pt, LStacked); - delayed()->nop(); - - // It's inflated - // Conceptually we need a #loadstore|#storestore "release" MEMBAR before - // the ST of 0 into _owner which releases the lock. This prevents loads - // and stores within the critical section from reordering (floating) - // past the store that releases the lock. But TSO is a strong memory model - // and that particular flavor of barrier is a noop, so we can safely elide it. - // Note that we use 1-0 locking by default for the inflated case. We - // close the resultant (and rare) race by having contented threads in - // monitorenter periodically poll _owner. - ld_ptr(Rmark, ObjectMonitor::owner_offset_in_bytes() - 2, Rscratch); - ld_ptr(Rmark, ObjectMonitor::recursions_offset_in_bytes() - 2, Rbox); - xor3(Rscratch, G2_thread, Rscratch); - orcc(Rbox, Rscratch, Rbox); - brx(Assembler::notZero, false, Assembler::pn, done); - delayed()-> - ld_ptr(Rmark, ObjectMonitor::EntryList_offset_in_bytes() - 2, Rscratch); - ld_ptr(Rmark, ObjectMonitor::cxq_offset_in_bytes() - 2, Rbox); - orcc(Rbox, Rscratch, G0); - if (EmitSync & 65536) { - Label LSucc ; - brx(Assembler::notZero, false, Assembler::pn, LSucc); - delayed()->nop(); - ba(done); - delayed()->st_ptr(G0, Rmark, ObjectMonitor::owner_offset_in_bytes() - 2); - - bind(LSucc); - st_ptr(G0, Rmark, ObjectMonitor::owner_offset_in_bytes() - 2); - if (os::is_MP()) { membar (StoreLoad); } - ld_ptr(Rmark, ObjectMonitor::succ_offset_in_bytes() - 2, Rscratch); - andcc(Rscratch, Rscratch, G0); - brx(Assembler::notZero, false, Assembler::pt, done); - delayed()->andcc(G0, G0, G0); - add(Rmark, ObjectMonitor::owner_offset_in_bytes()-2, Rmark); - mov(G2_thread, Rscratch); - casn(Rmark, G0, Rscratch); - // invert icc.zf and goto done - br_notnull(Rscratch, false, Assembler::pt, done); - delayed()->cmp(G0, G0); - ba(done); - delayed()->cmp(G0, 1); - } else { - brx(Assembler::notZero, false, Assembler::pn, done); - delayed()->nop(); - ba(done); - delayed()->st_ptr(G0, Rmark, ObjectMonitor::owner_offset_in_bytes() - 2); - } - - bind (LStacked); - // Consider: we could replace the expensive CAS in the exit - // path with a simple ST of the displaced mark value fetched from - // the on-stack basiclock box. That admits a race where a thread T2 - // in the slow lock path -- inflating with monitor M -- could race a - // thread T1 in the fast unlock path, resulting in a missed wakeup for T2. - // More precisely T1 in the stack-lock unlock path could "stomp" the - // inflated mark value M installed by T2, resulting in an orphan - // object monitor M and T2 becoming stranded. We can remedy that situation - // by having T2 periodically poll the object's mark word using timed wait - // operations. If T2 discovers that a stomp has occurred it vacates - // the monitor M and wakes any other threads stranded on the now-orphan M. - // In addition the monitor scavenger, which performs deflation, - // would also need to check for orpan monitors and stranded threads. - // - // Finally, inflation is also used when T2 needs to assign a hashCode - // to O and O is stack-locked by T1. The "stomp" race could cause - // an assigned hashCode value to be lost. We can avoid that condition - // and provide the necessary hashCode stability invariants by ensuring - // that hashCode generation is idempotent between copying GCs. - // For example we could compute the hashCode of an object O as - // O's heap address XOR some high quality RNG value that is refreshed - // at GC-time. The monitor scavenger would install the hashCode - // found in any orphan monitors. Again, the mechanism admits a - // lost-update "stomp" WAW race but detects and recovers as needed. - // - // A prototype implementation showed excellent results, although - // the scavenger and timeout code was rather involved. - - casn(mark_addr.base(), Rbox, Rscratch); - cmp(Rbox, Rscratch); - // Intentional fall through into done ... - - bind(done); -} - - - -void MacroAssembler::print_CPU_state() { - // %%%%% need to implement this -} - -void MacroAssembler::verify_FPU(int stack_depth, const char* s) { - // %%%%% need to implement this -} - -void MacroAssembler::push_IU_state() { - // %%%%% need to implement this -} - - -void MacroAssembler::pop_IU_state() { - // %%%%% need to implement this -} - - -void MacroAssembler::push_FPU_state() { - // %%%%% need to implement this -} - - -void MacroAssembler::pop_FPU_state() { - // %%%%% need to implement this -} - - -void MacroAssembler::push_CPU_state() { - // %%%%% need to implement this -} - - -void MacroAssembler::pop_CPU_state() { - // %%%%% need to implement this -} - - - -void MacroAssembler::verify_tlab() { -#ifdef ASSERT - if (UseTLAB && VerifyOops) { - Label next, next2, ok; - Register t1 = L0; - Register t2 = L1; - Register t3 = L2; - - save_frame(0); - ld_ptr(G2_thread, in_bytes(JavaThread::tlab_top_offset()), t1); - ld_ptr(G2_thread, in_bytes(JavaThread::tlab_start_offset()), t2); - or3(t1, t2, t3); - cmp_and_br_short(t1, t2, Assembler::greaterEqual, Assembler::pn, next); - STOP("assert(top >= start)"); - should_not_reach_here(); - - bind(next); - ld_ptr(G2_thread, in_bytes(JavaThread::tlab_top_offset()), t1); - ld_ptr(G2_thread, in_bytes(JavaThread::tlab_end_offset()), t2); - or3(t3, t2, t3); - cmp_and_br_short(t1, t2, Assembler::lessEqual, Assembler::pn, next2); - STOP("assert(top <= end)"); - should_not_reach_here(); - - bind(next2); - and3(t3, MinObjAlignmentInBytesMask, t3); - cmp_and_br_short(t3, 0, Assembler::lessEqual, Assembler::pn, ok); - STOP("assert(aligned)"); - should_not_reach_here(); - - bind(ok); - restore(); - } -#endif -} - - -void MacroAssembler::eden_allocate( - Register obj, // result: pointer to object after successful allocation - Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise - int con_size_in_bytes, // object size in bytes if known at compile time - Register t1, // temp register - Register t2, // temp register - Label& slow_case // continuation point if fast allocation fails -){ - // make sure arguments make sense - assert_different_registers(obj, var_size_in_bytes, t1, t2); - assert(0 <= con_size_in_bytes && Assembler::is_simm13(con_size_in_bytes), "illegal object size"); - assert((con_size_in_bytes & MinObjAlignmentInBytesMask) == 0, "object size is not multiple of alignment"); - - if (CMSIncrementalMode || !Universe::heap()->supports_inline_contig_alloc()) { - // No allocation in the shared eden. - ba_short(slow_case); - } else { - // get eden boundaries - // note: we need both top & top_addr! - const Register top_addr = t1; - const Register end = t2; - - CollectedHeap* ch = Universe::heap(); - set((intx)ch->top_addr(), top_addr); - intx delta = (intx)ch->end_addr() - (intx)ch->top_addr(); - ld_ptr(top_addr, delta, end); - ld_ptr(top_addr, 0, obj); - - // try to allocate - Label retry; - bind(retry); -#ifdef ASSERT - // make sure eden top is properly aligned - { - Label L; - btst(MinObjAlignmentInBytesMask, obj); - br(Assembler::zero, false, Assembler::pt, L); - delayed()->nop(); - STOP("eden top is not properly aligned"); - bind(L); - } -#endif // ASSERT - const Register free = end; - sub(end, obj, free); // compute amount of free space - if (var_size_in_bytes->is_valid()) { - // size is unknown at compile time - cmp(free, var_size_in_bytes); - br(Assembler::lessUnsigned, false, Assembler::pn, slow_case); // if there is not enough space go the slow case - delayed()->add(obj, var_size_in_bytes, end); - } else { - // size is known at compile time - cmp(free, con_size_in_bytes); - br(Assembler::lessUnsigned, false, Assembler::pn, slow_case); // if there is not enough space go the slow case - delayed()->add(obj, con_size_in_bytes, end); - } - // Compare obj with the value at top_addr; if still equal, swap the value of - // end with the value at top_addr. If not equal, read the value at top_addr - // into end. - casx_under_lock(top_addr, obj, end, (address)StubRoutines::Sparc::atomic_memory_operation_lock_addr()); - // if someone beat us on the allocation, try again, otherwise continue - cmp(obj, end); - brx(Assembler::notEqual, false, Assembler::pn, retry); - delayed()->mov(end, obj); // nop if successfull since obj == end - -#ifdef ASSERT - // make sure eden top is properly aligned - { - Label L; - const Register top_addr = t1; - - set((intx)ch->top_addr(), top_addr); - ld_ptr(top_addr, 0, top_addr); - btst(MinObjAlignmentInBytesMask, top_addr); - br(Assembler::zero, false, Assembler::pt, L); - delayed()->nop(); - STOP("eden top is not properly aligned"); - bind(L); - } -#endif // ASSERT - } -} - - -void MacroAssembler::tlab_allocate( - Register obj, // result: pointer to object after successful allocation - Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise - int con_size_in_bytes, // object size in bytes if known at compile time - Register t1, // temp register - Label& slow_case // continuation point if fast allocation fails -){ - // make sure arguments make sense - assert_different_registers(obj, var_size_in_bytes, t1); - assert(0 <= con_size_in_bytes && is_simm13(con_size_in_bytes), "illegal object size"); - assert((con_size_in_bytes & MinObjAlignmentInBytesMask) == 0, "object size is not multiple of alignment"); - - const Register free = t1; - - verify_tlab(); - - ld_ptr(G2_thread, in_bytes(JavaThread::tlab_top_offset()), obj); - - // calculate amount of free space - ld_ptr(G2_thread, in_bytes(JavaThread::tlab_end_offset()), free); - sub(free, obj, free); - - Label done; - if (var_size_in_bytes == noreg) { - cmp(free, con_size_in_bytes); - } else { - cmp(free, var_size_in_bytes); - } - br(Assembler::less, false, Assembler::pn, slow_case); - // calculate the new top pointer - if (var_size_in_bytes == noreg) { - delayed()->add(obj, con_size_in_bytes, free); - } else { - delayed()->add(obj, var_size_in_bytes, free); - } - - bind(done); - -#ifdef ASSERT - // make sure new free pointer is properly aligned - { - Label L; - btst(MinObjAlignmentInBytesMask, free); - br(Assembler::zero, false, Assembler::pt, L); - delayed()->nop(); - STOP("updated TLAB free is not properly aligned"); - bind(L); - } -#endif // ASSERT - - // update the tlab top pointer - st_ptr(free, G2_thread, in_bytes(JavaThread::tlab_top_offset())); - verify_tlab(); -} - - -void MacroAssembler::tlab_refill(Label& retry, Label& try_eden, Label& slow_case) { - Register top = O0; - Register t1 = G1; - Register t2 = G3; - Register t3 = O1; - assert_different_registers(top, t1, t2, t3, G4, G5 /* preserve G4 and G5 */); - Label do_refill, discard_tlab; - - if (CMSIncrementalMode || !Universe::heap()->supports_inline_contig_alloc()) { - // No allocation in the shared eden. - ba_short(slow_case); - } - - ld_ptr(G2_thread, in_bytes(JavaThread::tlab_top_offset()), top); - ld_ptr(G2_thread, in_bytes(JavaThread::tlab_end_offset()), t1); - ld_ptr(G2_thread, in_bytes(JavaThread::tlab_refill_waste_limit_offset()), t2); - - // calculate amount of free space - sub(t1, top, t1); - srl_ptr(t1, LogHeapWordSize, t1); - - // Retain tlab and allocate object in shared space if - // the amount free in the tlab is too large to discard. - cmp(t1, t2); - brx(Assembler::lessEqual, false, Assembler::pt, discard_tlab); - - // increment waste limit to prevent getting stuck on this slow path - delayed()->add(t2, ThreadLocalAllocBuffer::refill_waste_limit_increment(), t2); - st_ptr(t2, G2_thread, in_bytes(JavaThread::tlab_refill_waste_limit_offset())); - if (TLABStats) { - // increment number of slow_allocations - ld(G2_thread, in_bytes(JavaThread::tlab_slow_allocations_offset()), t2); - add(t2, 1, t2); - stw(t2, G2_thread, in_bytes(JavaThread::tlab_slow_allocations_offset())); - } - ba_short(try_eden); - - bind(discard_tlab); - if (TLABStats) { - // increment number of refills - ld(G2_thread, in_bytes(JavaThread::tlab_number_of_refills_offset()), t2); - add(t2, 1, t2); - stw(t2, G2_thread, in_bytes(JavaThread::tlab_number_of_refills_offset())); - // accumulate wastage - ld(G2_thread, in_bytes(JavaThread::tlab_fast_refill_waste_offset()), t2); - add(t2, t1, t2); - stw(t2, G2_thread, in_bytes(JavaThread::tlab_fast_refill_waste_offset())); - } - - // if tlab is currently allocated (top or end != null) then - // fill [top, end + alignment_reserve) with array object - br_null_short(top, Assembler::pn, do_refill); - - set((intptr_t)markOopDesc::prototype()->copy_set_hash(0x2), t2); - st_ptr(t2, top, oopDesc::mark_offset_in_bytes()); // set up the mark word - // set klass to intArrayKlass - sub(t1, typeArrayOopDesc::header_size(T_INT), t1); - add(t1, ThreadLocalAllocBuffer::alignment_reserve(), t1); - sll_ptr(t1, log2_intptr(HeapWordSize/sizeof(jint)), t1); - st(t1, top, arrayOopDesc::length_offset_in_bytes()); - set((intptr_t)Universe::intArrayKlassObj_addr(), t2); - ld_ptr(t2, 0, t2); - // store klass last. concurrent gcs assumes klass length is valid if - // klass field is not null. - store_klass(t2, top); - verify_oop(top); - - ld_ptr(G2_thread, in_bytes(JavaThread::tlab_start_offset()), t1); - sub(top, t1, t1); // size of tlab's allocated portion - incr_allocated_bytes(t1, t2, t3); - - // refill the tlab with an eden allocation - bind(do_refill); - ld_ptr(G2_thread, in_bytes(JavaThread::tlab_size_offset()), t1); - sll_ptr(t1, LogHeapWordSize, t1); - // allocate new tlab, address returned in top - eden_allocate(top, t1, 0, t2, t3, slow_case); - - st_ptr(top, G2_thread, in_bytes(JavaThread::tlab_start_offset())); - st_ptr(top, G2_thread, in_bytes(JavaThread::tlab_top_offset())); -#ifdef ASSERT - // check that tlab_size (t1) is still valid - { - Label ok; - ld_ptr(G2_thread, in_bytes(JavaThread::tlab_size_offset()), t2); - sll_ptr(t2, LogHeapWordSize, t2); - cmp_and_br_short(t1, t2, Assembler::equal, Assembler::pt, ok); - STOP("assert(t1 == tlab_size)"); - should_not_reach_here(); - - bind(ok); - } -#endif // ASSERT - add(top, t1, top); // t1 is tlab_size - sub(top, ThreadLocalAllocBuffer::alignment_reserve_in_bytes(), top); - st_ptr(top, G2_thread, in_bytes(JavaThread::tlab_end_offset())); - verify_tlab(); - ba_short(retry); -} - -void MacroAssembler::incr_allocated_bytes(RegisterOrConstant size_in_bytes, - Register t1, Register t2) { - // Bump total bytes allocated by this thread - assert(t1->is_global(), "must be global reg"); // so all 64 bits are saved on a context switch - assert_different_registers(size_in_bytes.register_or_noreg(), t1, t2); - // v8 support has gone the way of the dodo - ldx(G2_thread, in_bytes(JavaThread::allocated_bytes_offset()), t1); - add(t1, ensure_simm13_or_reg(size_in_bytes, t2), t1); - stx(t1, G2_thread, in_bytes(JavaThread::allocated_bytes_offset())); -} - -Assembler::Condition MacroAssembler::negate_condition(Assembler::Condition cond) { - switch (cond) { - // Note some conditions are synonyms for others - case Assembler::never: return Assembler::always; - case Assembler::zero: return Assembler::notZero; - case Assembler::lessEqual: return Assembler::greater; - case Assembler::less: return Assembler::greaterEqual; - case Assembler::lessEqualUnsigned: return Assembler::greaterUnsigned; - case Assembler::lessUnsigned: return Assembler::greaterEqualUnsigned; - case Assembler::negative: return Assembler::positive; - case Assembler::overflowSet: return Assembler::overflowClear; - case Assembler::always: return Assembler::never; - case Assembler::notZero: return Assembler::zero; - case Assembler::greater: return Assembler::lessEqual; - case Assembler::greaterEqual: return Assembler::less; - case Assembler::greaterUnsigned: return Assembler::lessEqualUnsigned; - case Assembler::greaterEqualUnsigned: return Assembler::lessUnsigned; - case Assembler::positive: return Assembler::negative; - case Assembler::overflowClear: return Assembler::overflowSet; - } - - ShouldNotReachHere(); return Assembler::overflowClear; -} - -void MacroAssembler::cond_inc(Assembler::Condition cond, address counter_ptr, - Register Rtmp1, Register Rtmp2 /*, Register Rtmp3, Register Rtmp4 */) { - Condition negated_cond = negate_condition(cond); - Label L; - brx(negated_cond, false, Assembler::pt, L); - delayed()->nop(); - inc_counter(counter_ptr, Rtmp1, Rtmp2); - bind(L); -} - -void MacroAssembler::inc_counter(address counter_addr, Register Rtmp1, Register Rtmp2) { - AddressLiteral addrlit(counter_addr); - sethi(addrlit, Rtmp1); // Move hi22 bits into temporary register. - Address addr(Rtmp1, addrlit.low10()); // Build an address with low10 bits. - ld(addr, Rtmp2); - inc(Rtmp2); - st(Rtmp2, addr); -} - -void MacroAssembler::inc_counter(int* counter_addr, Register Rtmp1, Register Rtmp2) { - inc_counter((address) counter_addr, Rtmp1, Rtmp2); -} - -SkipIfEqual::SkipIfEqual( - MacroAssembler* masm, Register temp, const bool* flag_addr, - Assembler::Condition condition) { - _masm = masm; - AddressLiteral flag(flag_addr); - _masm->sethi(flag, temp); - _masm->ldub(temp, flag.low10(), temp); - _masm->tst(temp); - _masm->br(condition, false, Assembler::pt, _label); - _masm->delayed()->nop(); -} - -SkipIfEqual::~SkipIfEqual() { - _masm->bind(_label); -} - - -// Writes to stack successive pages until offset reached to check for -// stack overflow + shadow pages. This clobbers tsp and scratch. -void MacroAssembler::bang_stack_size(Register Rsize, Register Rtsp, - Register Rscratch) { - // Use stack pointer in temp stack pointer - mov(SP, Rtsp); - - // Bang stack for total size given plus stack shadow page size. - // Bang one page at a time because a large size can overflow yellow and - // red zones (the bang will fail but stack overflow handling can't tell that - // it was a stack overflow bang vs a regular segv). - int offset = os::vm_page_size(); - Register Roffset = Rscratch; - - Label loop; - bind(loop); - set((-offset)+STACK_BIAS, Rscratch); - st(G0, Rtsp, Rscratch); - set(offset, Roffset); - sub(Rsize, Roffset, Rsize); - cmp(Rsize, G0); - br(Assembler::greater, false, Assembler::pn, loop); - delayed()->sub(Rtsp, Roffset, Rtsp); - - // Bang down shadow pages too. - // The -1 because we already subtracted 1 page. - for (int i = 0; i< StackShadowPages-1; i++) { - set((-i*offset)+STACK_BIAS, Rscratch); - st(G0, Rtsp, Rscratch); - } -} - -/////////////////////////////////////////////////////////////////////////////////// -#ifndef SERIALGC - -static address satb_log_enqueue_with_frame = NULL; -static u_char* satb_log_enqueue_with_frame_end = NULL; - -static address satb_log_enqueue_frameless = NULL; -static u_char* satb_log_enqueue_frameless_end = NULL; - -static int EnqueueCodeSize = 128 DEBUG_ONLY( + 256); // Instructions? - -static void generate_satb_log_enqueue(bool with_frame) { - BufferBlob* bb = BufferBlob::create("enqueue_with_frame", EnqueueCodeSize); - CodeBuffer buf(bb); - MacroAssembler masm(&buf); - -#define __ masm. - - address start = __ pc(); - Register pre_val; - - Label refill, restart; - if (with_frame) { - __ save_frame(0); - pre_val = I0; // Was O0 before the save. - } else { - pre_val = O0; - } - - int satb_q_index_byte_offset = - in_bytes(JavaThread::satb_mark_queue_offset() + - PtrQueue::byte_offset_of_index()); - - int satb_q_buf_byte_offset = - in_bytes(JavaThread::satb_mark_queue_offset() + - PtrQueue::byte_offset_of_buf()); - - assert(in_bytes(PtrQueue::byte_width_of_index()) == sizeof(intptr_t) && - in_bytes(PtrQueue::byte_width_of_buf()) == sizeof(intptr_t), - "check sizes in assembly below"); - - __ bind(restart); - - // Load the index into the SATB buffer. PtrQueue::_index is a size_t - // so ld_ptr is appropriate. - __ ld_ptr(G2_thread, satb_q_index_byte_offset, L0); - - // index == 0? - __ cmp_and_brx_short(L0, G0, Assembler::equal, Assembler::pn, refill); - - __ ld_ptr(G2_thread, satb_q_buf_byte_offset, L1); - __ sub(L0, oopSize, L0); - - __ st_ptr(pre_val, L1, L0); // [_buf + index] := I0 - if (!with_frame) { - // Use return-from-leaf - __ retl(); - __ delayed()->st_ptr(L0, G2_thread, satb_q_index_byte_offset); - } else { - // Not delayed. - __ st_ptr(L0, G2_thread, satb_q_index_byte_offset); - } - if (with_frame) { - __ ret(); - __ delayed()->restore(); - } - __ bind(refill); - - address handle_zero = - CAST_FROM_FN_PTR(address, - &SATBMarkQueueSet::handle_zero_index_for_thread); - // This should be rare enough that we can afford to save all the - // scratch registers that the calling context might be using. - __ mov(G1_scratch, L0); - __ mov(G3_scratch, L1); - __ mov(G4, L2); - // We need the value of O0 above (for the write into the buffer), so we - // save and restore it. - __ mov(O0, L3); - // Since the call will overwrite O7, we save and restore that, as well. - __ mov(O7, L4); - __ call_VM_leaf(L5, handle_zero, G2_thread); - __ mov(L0, G1_scratch); - __ mov(L1, G3_scratch); - __ mov(L2, G4); - __ mov(L3, O0); - __ br(Assembler::always, /*annul*/false, Assembler::pt, restart); - __ delayed()->mov(L4, O7); - - if (with_frame) { - satb_log_enqueue_with_frame = start; - satb_log_enqueue_with_frame_end = __ pc(); - } else { - satb_log_enqueue_frameless = start; - satb_log_enqueue_frameless_end = __ pc(); - } - -#undef __ -} - -static inline void generate_satb_log_enqueue_if_necessary(bool with_frame) { - if (with_frame) { - if (satb_log_enqueue_with_frame == 0) { - generate_satb_log_enqueue(with_frame); - assert(satb_log_enqueue_with_frame != 0, "postcondition."); - if (G1SATBPrintStubs) { - tty->print_cr("Generated with-frame satb enqueue:"); - Disassembler::decode((u_char*)satb_log_enqueue_with_frame, - satb_log_enqueue_with_frame_end, - tty); - } - } - } else { - if (satb_log_enqueue_frameless == 0) { - generate_satb_log_enqueue(with_frame); - assert(satb_log_enqueue_frameless != 0, "postcondition."); - if (G1SATBPrintStubs) { - tty->print_cr("Generated frameless satb enqueue:"); - Disassembler::decode((u_char*)satb_log_enqueue_frameless, - satb_log_enqueue_frameless_end, - tty); - } - } - } -} - -void MacroAssembler::g1_write_barrier_pre(Register obj, - Register index, - int offset, - Register pre_val, - Register tmp, - bool preserve_o_regs) { - Label filtered; - - if (obj == noreg) { - // We are not loading the previous value so make - // sure that we don't trash the value in pre_val - // with the code below. - assert_different_registers(pre_val, tmp); - } else { - // We will be loading the previous value - // in this code so... - assert(offset == 0 || index == noreg, "choose one"); - assert(pre_val == noreg, "check this code"); - } - - // Is marking active? - if (in_bytes(PtrQueue::byte_width_of_active()) == 4) { - ld(G2, - in_bytes(JavaThread::satb_mark_queue_offset() + - PtrQueue::byte_offset_of_active()), - tmp); - } else { - guarantee(in_bytes(PtrQueue::byte_width_of_active()) == 1, - "Assumption"); - ldsb(G2, - in_bytes(JavaThread::satb_mark_queue_offset() + - PtrQueue::byte_offset_of_active()), - tmp); - } - - // Is marking active? - cmp_and_br_short(tmp, G0, Assembler::equal, Assembler::pt, filtered); - - // Do we need to load the previous value? - if (obj != noreg) { - // Load the previous value... - if (index == noreg) { - if (Assembler::is_simm13(offset)) { - load_heap_oop(obj, offset, tmp); - } else { - set(offset, tmp); - load_heap_oop(obj, tmp, tmp); - } - } else { - load_heap_oop(obj, index, tmp); - } - // Previous value has been loaded into tmp - pre_val = tmp; - } - - assert(pre_val != noreg, "must have a real register"); - - // Is the previous value null? - cmp_and_brx_short(pre_val, G0, Assembler::equal, Assembler::pt, filtered); - - // OK, it's not filtered, so we'll need to call enqueue. In the normal - // case, pre_val will be a scratch G-reg, but there are some cases in - // which it's an O-reg. In the first case, do a normal call. In the - // latter, do a save here and call the frameless version. - - guarantee(pre_val->is_global() || pre_val->is_out(), - "Or we need to think harder."); - - if (pre_val->is_global() && !preserve_o_regs) { - generate_satb_log_enqueue_if_necessary(true); // with frame - - call(satb_log_enqueue_with_frame); - delayed()->mov(pre_val, O0); - } else { - generate_satb_log_enqueue_if_necessary(false); // frameless - - save_frame(0); - call(satb_log_enqueue_frameless); - delayed()->mov(pre_val->after_save(), O0); - restore(); - } - - bind(filtered); -} - -static address dirty_card_log_enqueue = 0; -static u_char* dirty_card_log_enqueue_end = 0; - -// This gets to assume that o0 contains the object address. -static void generate_dirty_card_log_enqueue(jbyte* byte_map_base) { - BufferBlob* bb = BufferBlob::create("dirty_card_enqueue", EnqueueCodeSize*2); - CodeBuffer buf(bb); - MacroAssembler masm(&buf); -#define __ masm. - address start = __ pc(); - - Label not_already_dirty, restart, refill; - -#ifdef _LP64 - __ srlx(O0, CardTableModRefBS::card_shift, O0); -#else - __ srl(O0, CardTableModRefBS::card_shift, O0); -#endif - AddressLiteral addrlit(byte_map_base); - __ set(addrlit, O1); // O1 := - __ ldub(O0, O1, O2); // O2 := [O0 + O1] - - assert(CardTableModRefBS::dirty_card_val() == 0, "otherwise check this code"); - __ cmp_and_br_short(O2, G0, Assembler::notEqual, Assembler::pt, not_already_dirty); - - // We didn't take the branch, so we're already dirty: return. - // Use return-from-leaf - __ retl(); - __ delayed()->nop(); - - // Not dirty. - __ bind(not_already_dirty); - - // Get O0 + O1 into a reg by itself - __ add(O0, O1, O3); - - // First, dirty it. - __ stb(G0, O3, G0); // [cardPtr] := 0 (i.e., dirty). - - int dirty_card_q_index_byte_offset = - in_bytes(JavaThread::dirty_card_queue_offset() + - PtrQueue::byte_offset_of_index()); - int dirty_card_q_buf_byte_offset = - in_bytes(JavaThread::dirty_card_queue_offset() + - PtrQueue::byte_offset_of_buf()); - __ bind(restart); - - // Load the index into the update buffer. PtrQueue::_index is - // a size_t so ld_ptr is appropriate here. - __ ld_ptr(G2_thread, dirty_card_q_index_byte_offset, L0); - - // index == 0? - __ cmp_and_brx_short(L0, G0, Assembler::equal, Assembler::pn, refill); - - __ ld_ptr(G2_thread, dirty_card_q_buf_byte_offset, L1); - __ sub(L0, oopSize, L0); - - __ st_ptr(O3, L1, L0); // [_buf + index] := I0 - // Use return-from-leaf - __ retl(); - __ delayed()->st_ptr(L0, G2_thread, dirty_card_q_index_byte_offset); - - __ bind(refill); - address handle_zero = - CAST_FROM_FN_PTR(address, - &DirtyCardQueueSet::handle_zero_index_for_thread); - // This should be rare enough that we can afford to save all the - // scratch registers that the calling context might be using. - __ mov(G1_scratch, L3); - __ mov(G3_scratch, L5); - // We need the value of O3 above (for the write into the buffer), so we - // save and restore it. - __ mov(O3, L6); - // Since the call will overwrite O7, we save and restore that, as well. - __ mov(O7, L4); - - __ call_VM_leaf(L7_thread_cache, handle_zero, G2_thread); - __ mov(L3, G1_scratch); - __ mov(L5, G3_scratch); - __ mov(L6, O3); - __ br(Assembler::always, /*annul*/false, Assembler::pt, restart); - __ delayed()->mov(L4, O7); - - dirty_card_log_enqueue = start; - dirty_card_log_enqueue_end = __ pc(); - // XXX Should have a guarantee here about not going off the end! - // Does it already do so? Do an experiment... - -#undef __ - -} - -static inline void -generate_dirty_card_log_enqueue_if_necessary(jbyte* byte_map_base) { - if (dirty_card_log_enqueue == 0) { - generate_dirty_card_log_enqueue(byte_map_base); - assert(dirty_card_log_enqueue != 0, "postcondition."); - if (G1SATBPrintStubs) { - tty->print_cr("Generated dirty_card enqueue:"); - Disassembler::decode((u_char*)dirty_card_log_enqueue, - dirty_card_log_enqueue_end, - tty); - } - } -} - - -void MacroAssembler::g1_write_barrier_post(Register store_addr, Register new_val, Register tmp) { - - Label filtered; - MacroAssembler* post_filter_masm = this; - - if (new_val == G0) return; - - G1SATBCardTableModRefBS* bs = (G1SATBCardTableModRefBS*) Universe::heap()->barrier_set(); - assert(bs->kind() == BarrierSet::G1SATBCT || - bs->kind() == BarrierSet::G1SATBCTLogging, "wrong barrier"); - - if (G1RSBarrierRegionFilter) { - xor3(store_addr, new_val, tmp); -#ifdef _LP64 - srlx(tmp, HeapRegion::LogOfHRGrainBytes, tmp); -#else - srl(tmp, HeapRegion::LogOfHRGrainBytes, tmp); -#endif - - // XXX Should I predict this taken or not? Does it matter? - cmp_and_brx_short(tmp, G0, Assembler::equal, Assembler::pt, filtered); - } - - // If the "store_addr" register is an "in" or "local" register, move it to - // a scratch reg so we can pass it as an argument. - bool use_scr = !(store_addr->is_global() || store_addr->is_out()); - // Pick a scratch register different from "tmp". - Register scr = (tmp == G1_scratch ? G3_scratch : G1_scratch); - // Make sure we use up the delay slot! - if (use_scr) { - post_filter_masm->mov(store_addr, scr); - } else { - post_filter_masm->nop(); - } - generate_dirty_card_log_enqueue_if_necessary(bs->byte_map_base); - save_frame(0); - call(dirty_card_log_enqueue); - if (use_scr) { - delayed()->mov(scr, O0); - } else { - delayed()->mov(store_addr->after_save(), O0); - } - restore(); - - bind(filtered); -} - -#endif // SERIALGC -/////////////////////////////////////////////////////////////////////////////////// - -void MacroAssembler::card_write_barrier_post(Register store_addr, Register new_val, Register tmp) { - // If we're writing constant NULL, we can skip the write barrier. - if (new_val == G0) return; - CardTableModRefBS* bs = (CardTableModRefBS*) Universe::heap()->barrier_set(); - assert(bs->kind() == BarrierSet::CardTableModRef || - bs->kind() == BarrierSet::CardTableExtension, "wrong barrier"); - card_table_write(bs->byte_map_base, tmp, store_addr); -} - -void MacroAssembler::load_klass(Register src_oop, Register klass) { - // The number of bytes in this code is used by - // MachCallDynamicJavaNode::ret_addr_offset() - // if this changes, change that. - if (UseCompressedKlassPointers) { - lduw(src_oop, oopDesc::klass_offset_in_bytes(), klass); - decode_klass_not_null(klass); - } else { - ld_ptr(src_oop, oopDesc::klass_offset_in_bytes(), klass); - } -} - -void MacroAssembler::store_klass(Register klass, Register dst_oop) { - if (UseCompressedKlassPointers) { - assert(dst_oop != klass, "not enough registers"); - encode_klass_not_null(klass); - st(klass, dst_oop, oopDesc::klass_offset_in_bytes()); - } else { - st_ptr(klass, dst_oop, oopDesc::klass_offset_in_bytes()); - } -} - -void MacroAssembler::store_klass_gap(Register s, Register d) { - if (UseCompressedKlassPointers) { - assert(s != d, "not enough registers"); - st(s, d, oopDesc::klass_gap_offset_in_bytes()); - } -} - -void MacroAssembler::load_heap_oop(const Address& s, Register d) { - if (UseCompressedOops) { - lduw(s, d); - decode_heap_oop(d); - } else { - ld_ptr(s, d); - } -} - -void MacroAssembler::load_heap_oop(Register s1, Register s2, Register d) { - if (UseCompressedOops) { - lduw(s1, s2, d); - decode_heap_oop(d, d); - } else { - ld_ptr(s1, s2, d); - } -} - -void MacroAssembler::load_heap_oop(Register s1, int simm13a, Register d) { - if (UseCompressedOops) { - lduw(s1, simm13a, d); - decode_heap_oop(d, d); - } else { - ld_ptr(s1, simm13a, d); - } -} - -void MacroAssembler::load_heap_oop(Register s1, RegisterOrConstant s2, Register d) { - if (s2.is_constant()) load_heap_oop(s1, s2.as_constant(), d); - else load_heap_oop(s1, s2.as_register(), d); -} - -void MacroAssembler::store_heap_oop(Register d, Register s1, Register s2) { - if (UseCompressedOops) { - assert(s1 != d && s2 != d, "not enough registers"); - encode_heap_oop(d); - st(d, s1, s2); - } else { - st_ptr(d, s1, s2); - } -} - -void MacroAssembler::store_heap_oop(Register d, Register s1, int simm13a) { - if (UseCompressedOops) { - assert(s1 != d, "not enough registers"); - encode_heap_oop(d); - st(d, s1, simm13a); - } else { - st_ptr(d, s1, simm13a); - } -} - -void MacroAssembler::store_heap_oop(Register d, const Address& a, int offset) { - if (UseCompressedOops) { - assert(a.base() != d, "not enough registers"); - encode_heap_oop(d); - st(d, a, offset); - } else { - st_ptr(d, a, offset); - } -} - - -void MacroAssembler::encode_heap_oop(Register src, Register dst) { - assert (UseCompressedOops, "must be compressed"); - assert (Universe::heap() != NULL, "java heap should be initialized"); - assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); - verify_oop(src); - if (Universe::narrow_oop_base() == NULL) { - srlx(src, LogMinObjAlignmentInBytes, dst); - return; - } - Label done; - if (src == dst) { - // optimize for frequent case src == dst - bpr(rc_nz, true, Assembler::pt, src, done); - delayed() -> sub(src, G6_heapbase, dst); // annuled if not taken - bind(done); - srlx(src, LogMinObjAlignmentInBytes, dst); - } else { - bpr(rc_z, false, Assembler::pn, src, done); - delayed() -> mov(G0, dst); - // could be moved before branch, and annulate delay, - // but may add some unneeded work decoding null - sub(src, G6_heapbase, dst); - srlx(dst, LogMinObjAlignmentInBytes, dst); - bind(done); - } -} - - -void MacroAssembler::encode_heap_oop_not_null(Register r) { - assert (UseCompressedOops, "must be compressed"); - assert (Universe::heap() != NULL, "java heap should be initialized"); - assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); - verify_oop(r); - if (Universe::narrow_oop_base() != NULL) - sub(r, G6_heapbase, r); - srlx(r, LogMinObjAlignmentInBytes, r); -} - -void MacroAssembler::encode_heap_oop_not_null(Register src, Register dst) { - assert (UseCompressedOops, "must be compressed"); - assert (Universe::heap() != NULL, "java heap should be initialized"); - assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); - verify_oop(src); - if (Universe::narrow_oop_base() == NULL) { - srlx(src, LogMinObjAlignmentInBytes, dst); - } else { - sub(src, G6_heapbase, dst); - srlx(dst, LogMinObjAlignmentInBytes, dst); - } -} - -// Same algorithm as oops.inline.hpp decode_heap_oop. -void MacroAssembler::decode_heap_oop(Register src, Register dst) { - assert (UseCompressedOops, "must be compressed"); - assert (Universe::heap() != NULL, "java heap should be initialized"); - assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); - sllx(src, LogMinObjAlignmentInBytes, dst); - if (Universe::narrow_oop_base() != NULL) { - Label done; - bpr(rc_nz, true, Assembler::pt, dst, done); - delayed() -> add(dst, G6_heapbase, dst); // annuled if not taken - bind(done); - } - verify_oop(dst); -} - -void MacroAssembler::decode_heap_oop_not_null(Register r) { - // Do not add assert code to this unless you change vtableStubs_sparc.cpp - // pd_code_size_limit. - // Also do not verify_oop as this is called by verify_oop. - assert (UseCompressedOops, "must be compressed"); - assert (Universe::heap() != NULL, "java heap should be initialized"); - assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); - sllx(r, LogMinObjAlignmentInBytes, r); - if (Universe::narrow_oop_base() != NULL) - add(r, G6_heapbase, r); -} - -void MacroAssembler::decode_heap_oop_not_null(Register src, Register dst) { - // Do not add assert code to this unless you change vtableStubs_sparc.cpp - // pd_code_size_limit. - // Also do not verify_oop as this is called by verify_oop. - assert (UseCompressedOops, "must be compressed"); - assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); - sllx(src, LogMinObjAlignmentInBytes, dst); - if (Universe::narrow_oop_base() != NULL) - add(dst, G6_heapbase, dst); -} - -void MacroAssembler::encode_klass_not_null(Register r) { - assert(Metaspace::is_initialized(), "metaspace should be initialized"); - assert (UseCompressedKlassPointers, "must be compressed"); - assert (LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong"); - if (Universe::narrow_klass_base() != NULL) - sub(r, G6_heapbase, r); - srlx(r, LogKlassAlignmentInBytes, r); -} - -void MacroAssembler::encode_klass_not_null(Register src, Register dst) { - assert(Metaspace::is_initialized(), "metaspace should be initialized"); - assert (UseCompressedKlassPointers, "must be compressed"); - assert (LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong"); - if (Universe::narrow_klass_base() == NULL) { - srlx(src, LogKlassAlignmentInBytes, dst); - } else { - sub(src, G6_heapbase, dst); - srlx(dst, LogKlassAlignmentInBytes, dst); - } -} - -void MacroAssembler::decode_klass_not_null(Register r) { - assert(Metaspace::is_initialized(), "metaspace should be initialized"); - // Do not add assert code to this unless you change vtableStubs_sparc.cpp - // pd_code_size_limit. - assert (UseCompressedKlassPointers, "must be compressed"); - assert (LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong"); - sllx(r, LogKlassAlignmentInBytes, r); - if (Universe::narrow_klass_base() != NULL) - add(r, G6_heapbase, r); -} - -void MacroAssembler::decode_klass_not_null(Register src, Register dst) { - assert(Metaspace::is_initialized(), "metaspace should be initialized"); - // Do not add assert code to this unless you change vtableStubs_sparc.cpp - // pd_code_size_limit. - assert (UseCompressedKlassPointers, "must be compressed"); - assert (LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong"); - sllx(src, LogKlassAlignmentInBytes, dst); - if (Universe::narrow_klass_base() != NULL) - add(dst, G6_heapbase, dst); -} - -void MacroAssembler::reinit_heapbase() { - if (UseCompressedOops || UseCompressedKlassPointers) { - AddressLiteral base(Universe::narrow_ptrs_base_addr()); - load_ptr_contents(base, G6_heapbase); - } -} - -// Compare char[] arrays aligned to 4 bytes. -void MacroAssembler::char_arrays_equals(Register ary1, Register ary2, - Register limit, Register result, - Register chr1, Register chr2, Label& Ldone) { - Label Lvector, Lloop; - assert(chr1 == result, "should be the same"); - - // Note: limit contains number of bytes (2*char_elements) != 0. - andcc(limit, 0x2, chr1); // trailing character ? - br(Assembler::zero, false, Assembler::pt, Lvector); - delayed()->nop(); - - // compare the trailing char - sub(limit, sizeof(jchar), limit); - lduh(ary1, limit, chr1); - lduh(ary2, limit, chr2); - cmp(chr1, chr2); - br(Assembler::notEqual, true, Assembler::pt, Ldone); - delayed()->mov(G0, result); // not equal - - // only one char ? - cmp_zero_and_br(zero, limit, Ldone, true, Assembler::pn); - delayed()->add(G0, 1, result); // zero-length arrays are equal - - // word by word compare, dont't need alignment check - bind(Lvector); - // Shift ary1 and ary2 to the end of the arrays, negate limit - add(ary1, limit, ary1); - add(ary2, limit, ary2); - neg(limit, limit); - - lduw(ary1, limit, chr1); - bind(Lloop); - lduw(ary2, limit, chr2); - cmp(chr1, chr2); - br(Assembler::notEqual, true, Assembler::pt, Ldone); - delayed()->mov(G0, result); // not equal - inccc(limit, 2*sizeof(jchar)); - // annul LDUW if branch is not taken to prevent access past end of array - br(Assembler::notZero, true, Assembler::pt, Lloop); - delayed()->lduw(ary1, limit, chr1); // hoisted - - // Caller should set it: - // add(G0, 1, result); // equals -} - -// Use BIS for zeroing (count is in bytes). -void MacroAssembler::bis_zeroing(Register to, Register count, Register temp, Label& Ldone) { - assert(UseBlockZeroing && VM_Version::has_block_zeroing(), "only works with BIS zeroing"); - Register end = count; - int cache_line_size = VM_Version::prefetch_data_size(); - // Minimum count when BIS zeroing can be used since - // it needs membar which is expensive. - int block_zero_size = MAX2(cache_line_size*3, (int)BlockZeroingLowLimit); - - Label small_loop; - // Check if count is negative (dead code) or zero. - // Note, count uses 64bit in 64 bit VM. - cmp_and_brx_short(count, 0, Assembler::lessEqual, Assembler::pn, Ldone); - - // Use BIS zeroing only for big arrays since it requires membar. - if (Assembler::is_simm13(block_zero_size)) { // < 4096 - cmp(count, block_zero_size); - } else { - set(block_zero_size, temp); - cmp(count, temp); - } - br(Assembler::lessUnsigned, false, Assembler::pt, small_loop); - delayed()->add(to, count, end); - - // Note: size is >= three (32 bytes) cache lines. - - // Clean the beginning of space up to next cache line. - for (int offs = 0; offs < cache_line_size; offs += 8) { - stx(G0, to, offs); - } - - // align to next cache line - add(to, cache_line_size, to); - and3(to, -cache_line_size, to); - - // Note: size left >= two (32 bytes) cache lines. - - // BIS should not be used to zero tail (64 bytes) - // to avoid zeroing a header of the following object. - sub(end, (cache_line_size*2)-8, end); - - Label bis_loop; - bind(bis_loop); - stxa(G0, to, G0, Assembler::ASI_ST_BLKINIT_PRIMARY); - add(to, cache_line_size, to); - cmp_and_brx_short(to, end, Assembler::lessUnsigned, Assembler::pt, bis_loop); - - // BIS needs membar. - membar(Assembler::StoreLoad); - - add(end, (cache_line_size*2)-8, end); // restore end - cmp_and_brx_short(to, end, Assembler::greaterEqualUnsigned, Assembler::pn, Ldone); - - // Clean the tail. - bind(small_loop); - stx(G0, to, 0); - add(to, 8, to); - cmp_and_brx_short(to, end, Assembler::lessUnsigned, Assembler::pt, small_loop); - nop(); // Separate short branches -} diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp index f9b893258be..6e4812abcd4 100644 --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp @@ -25,554 +25,13 @@ #ifndef CPU_SPARC_VM_ASSEMBLER_SPARC_HPP #define CPU_SPARC_VM_ASSEMBLER_SPARC_HPP -class BiasedLockingCounters; - -// promises that the system will not use traps 16-31 -#define ST_RESERVED_FOR_USER_0 0x10 - -/* Written: David Ungar 4/19/97 */ - -// Contains all the definitions needed for sparc assembly code generation. - -// Register aliases for parts of the system: - -// 64 bit values can be kept in g1-g5, o1-o5 and o7 and all 64 bits are safe -// across context switches in V8+ ABI. Of course, there are no 64 bit regs -// in V8 ABI. All 64 bits are preserved in V9 ABI for all registers. - -// g2-g4 are scratch registers called "application globals". Their -// meaning is reserved to the "compilation system"--which means us! -// They are are not supposed to be touched by ordinary C code, although -// highly-optimized C code might steal them for temps. They are safe -// across thread switches, and the ABI requires that they be safe -// across function calls. -// -// g1 and g3 are touched by more modules. V8 allows g1 to be clobbered -// across func calls, and V8+ also allows g5 to be clobbered across -// func calls. Also, g1 and g5 can get touched while doing shared -// library loading. -// -// We must not touch g7 (it is the thread-self register) and g6 is -// reserved for certain tools. g0, of course, is always zero. -// -// (Sources: SunSoft Compilers Group, thread library engineers.) - -// %%%% The interpreter should be revisited to reduce global scratch regs. - -// This global always holds the current JavaThread pointer: - -REGISTER_DECLARATION(Register, G2_thread , G2); -REGISTER_DECLARATION(Register, G6_heapbase , G6); - -// The following globals are part of the Java calling convention: - -REGISTER_DECLARATION(Register, G5_method , G5); -REGISTER_DECLARATION(Register, G5_megamorphic_method , G5_method); -REGISTER_DECLARATION(Register, G5_inline_cache_reg , G5_method); - -// The following globals are used for the new C1 & interpreter calling convention: -REGISTER_DECLARATION(Register, Gargs , G4); // pointing to the last argument - -// This local is used to preserve G2_thread in the interpreter and in stubs: -REGISTER_DECLARATION(Register, L7_thread_cache , L7); - -// These globals are used as scratch registers in the interpreter: - -REGISTER_DECLARATION(Register, Gframe_size , G1); // SAME REG as G1_scratch -REGISTER_DECLARATION(Register, G1_scratch , G1); // also SAME -REGISTER_DECLARATION(Register, G3_scratch , G3); -REGISTER_DECLARATION(Register, G4_scratch , G4); - -// These globals are used as short-lived scratch registers in the compiler: - -REGISTER_DECLARATION(Register, Gtemp , G5); - -// JSR 292 fixed register usages: -REGISTER_DECLARATION(Register, G5_method_type , G5); -REGISTER_DECLARATION(Register, G3_method_handle , G3); -REGISTER_DECLARATION(Register, L7_mh_SP_save , L7); - -// The compiler requires that G5_megamorphic_method is G5_inline_cache_klass, -// because a single patchable "set" instruction (NativeMovConstReg, -// or NativeMovConstPatching for compiler1) instruction -// serves to set up either quantity, depending on whether the compiled -// call site is an inline cache or is megamorphic. See the function -// CompiledIC::set_to_megamorphic. -// -// If a inline cache targets an interpreted method, then the -// G5 register will be used twice during the call. First, -// the call site will be patched to load a compiledICHolder -// into G5. (This is an ordered pair of ic_klass, method.) -// The c2i adapter will first check the ic_klass, then load -// G5_method with the method part of the pair just before -// jumping into the interpreter. -// -// Note that G5_method is only the method-self for the interpreter, -// and is logically unrelated to G5_megamorphic_method. -// -// Invariants on G2_thread (the JavaThread pointer): -// - it should not be used for any other purpose anywhere -// - it must be re-initialized by StubRoutines::call_stub() -// - it must be preserved around every use of call_VM - -// We can consider using g2/g3/g4 to cache more values than the -// JavaThread, such as the card-marking base or perhaps pointers into -// Eden. It's something of a waste to use them as scratch temporaries, -// since they are not supposed to be volatile. (Of course, if we find -// that Java doesn't benefit from application globals, then we can just -// use them as ordinary temporaries.) -// -// Since g1 and g5 (and/or g6) are the volatile (caller-save) registers, -// it makes sense to use them routinely for procedure linkage, -// whenever the On registers are not applicable. Examples: G5_method, -// G5_inline_cache_klass, and a double handful of miscellaneous compiler -// stubs. This means that compiler stubs, etc., should be kept to a -// maximum of two or three G-register arguments. - - -// stub frames - -REGISTER_DECLARATION(Register, Lentry_args , L0); // pointer to args passed to callee (interpreter) not stub itself - -// Interpreter frames - -#ifdef CC_INTERP -REGISTER_DECLARATION(Register, Lstate , L0); // interpreter state object pointer -REGISTER_DECLARATION(Register, L1_scratch , L1); // scratch -REGISTER_DECLARATION(Register, Lmirror , L1); // mirror (for native methods only) -REGISTER_DECLARATION(Register, L2_scratch , L2); -REGISTER_DECLARATION(Register, L3_scratch , L3); -REGISTER_DECLARATION(Register, L4_scratch , L4); -REGISTER_DECLARATION(Register, Lscratch , L5); // C1 uses -REGISTER_DECLARATION(Register, Lscratch2 , L6); // C1 uses -REGISTER_DECLARATION(Register, L7_scratch , L7); // constant pool cache -REGISTER_DECLARATION(Register, O5_savedSP , O5); -REGISTER_DECLARATION(Register, I5_savedSP , I5); // Saved SP before bumping for locals. This is simply - // a copy SP, so in 64-bit it's a biased value. The bias - // is added and removed as needed in the frame code. -// Interface to signature handler -REGISTER_DECLARATION(Register, Llocals , L7); // pointer to locals for signature handler -REGISTER_DECLARATION(Register, Lmethod , L6); // Method* when calling signature handler - -#else -REGISTER_DECLARATION(Register, Lesp , L0); // expression stack pointer -REGISTER_DECLARATION(Register, Lbcp , L1); // pointer to next bytecode -REGISTER_DECLARATION(Register, Lmethod , L2); -REGISTER_DECLARATION(Register, Llocals , L3); -REGISTER_DECLARATION(Register, Largs , L3); // pointer to locals for signature handler - // must match Llocals in asm interpreter -REGISTER_DECLARATION(Register, Lmonitors , L4); -REGISTER_DECLARATION(Register, Lbyte_code , L5); -// When calling out from the interpreter we record SP so that we can remove any extra stack -// space allocated during adapter transitions. This register is only live from the point -// of the call until we return. -REGISTER_DECLARATION(Register, Llast_SP , L5); -REGISTER_DECLARATION(Register, Lscratch , L5); -REGISTER_DECLARATION(Register, Lscratch2 , L6); -REGISTER_DECLARATION(Register, LcpoolCache , L6); // constant pool cache - -REGISTER_DECLARATION(Register, O5_savedSP , O5); -REGISTER_DECLARATION(Register, I5_savedSP , I5); // Saved SP before bumping for locals. This is simply - // a copy SP, so in 64-bit it's a biased value. The bias - // is added and removed as needed in the frame code. -REGISTER_DECLARATION(Register, IdispatchTables , I4); // Base address of the bytecode dispatch tables -REGISTER_DECLARATION(Register, IdispatchAddress , I3); // Register which saves the dispatch address for each bytecode -REGISTER_DECLARATION(Register, ImethodDataPtr , I2); // Pointer to the current method data -#endif /* CC_INTERP */ - -// NOTE: Lscratch2 and LcpoolCache point to the same registers in -// the interpreter code. If Lscratch2 needs to be used for some -// purpose than LcpoolCache should be restore after that for -// the interpreter to work right -// (These assignments must be compatible with L7_thread_cache; see above.) - -// Since Lbcp points into the middle of the method object, -// it is temporarily converted into a "bcx" during GC. - -// Exception processing -// These registers are passed into exception handlers. -// All exception handlers require the exception object being thrown. -// In addition, an nmethod's exception handler must be passed -// the address of the call site within the nmethod, to allow -// proper selection of the applicable catch block. -// (Interpreter frames use their own bcp() for this purpose.) -// -// The Oissuing_pc value is not always needed. When jumping to a -// handler that is known to be interpreted, the Oissuing_pc value can be -// omitted. An actual catch block in compiled code receives (from its -// nmethod's exception handler) the thrown exception in the Oexception, -// but it doesn't need the Oissuing_pc. -// -// If an exception handler (either interpreted or compiled) -// discovers there is no applicable catch block, it updates -// the Oissuing_pc to the continuation PC of its own caller, -// pops back to that caller's stack frame, and executes that -// caller's exception handler. Obviously, this process will -// iterate until the control stack is popped back to a method -// containing an applicable catch block. A key invariant is -// that the Oissuing_pc value is always a value local to -// the method whose exception handler is currently executing. -// -// Note: The issuing PC value is __not__ a raw return address (I7 value). -// It is a "return pc", the address __following__ the call. -// Raw return addresses are converted to issuing PCs by frame::pc(), -// or by stubs. Issuing PCs can be used directly with PC range tables. -// -REGISTER_DECLARATION(Register, Oexception , O0); // exception being thrown -REGISTER_DECLARATION(Register, Oissuing_pc , O1); // where the exception is coming from - - -// These must occur after the declarations above -#ifndef DONT_USE_REGISTER_DEFINES - -#define Gthread AS_REGISTER(Register, Gthread) -#define Gmethod AS_REGISTER(Register, Gmethod) -#define Gmegamorphic_method AS_REGISTER(Register, Gmegamorphic_method) -#define Ginline_cache_reg AS_REGISTER(Register, Ginline_cache_reg) -#define Gargs AS_REGISTER(Register, Gargs) -#define Lthread_cache AS_REGISTER(Register, Lthread_cache) -#define Gframe_size AS_REGISTER(Register, Gframe_size) -#define Gtemp AS_REGISTER(Register, Gtemp) - -#ifdef CC_INTERP -#define Lstate AS_REGISTER(Register, Lstate) -#define Lesp AS_REGISTER(Register, Lesp) -#define L1_scratch AS_REGISTER(Register, L1_scratch) -#define Lmirror AS_REGISTER(Register, Lmirror) -#define L2_scratch AS_REGISTER(Register, L2_scratch) -#define L3_scratch AS_REGISTER(Register, L3_scratch) -#define L4_scratch AS_REGISTER(Register, L4_scratch) -#define Lscratch AS_REGISTER(Register, Lscratch) -#define Lscratch2 AS_REGISTER(Register, Lscratch2) -#define L7_scratch AS_REGISTER(Register, L7_scratch) -#define Ostate AS_REGISTER(Register, Ostate) -#else -#define Lesp AS_REGISTER(Register, Lesp) -#define Lbcp AS_REGISTER(Register, Lbcp) -#define Lmethod AS_REGISTER(Register, Lmethod) -#define Llocals AS_REGISTER(Register, Llocals) -#define Lmonitors AS_REGISTER(Register, Lmonitors) -#define Lbyte_code AS_REGISTER(Register, Lbyte_code) -#define Lscratch AS_REGISTER(Register, Lscratch) -#define Lscratch2 AS_REGISTER(Register, Lscratch2) -#define LcpoolCache AS_REGISTER(Register, LcpoolCache) -#endif /* ! CC_INTERP */ - -#define Lentry_args AS_REGISTER(Register, Lentry_args) -#define I5_savedSP AS_REGISTER(Register, I5_savedSP) -#define O5_savedSP AS_REGISTER(Register, O5_savedSP) -#define IdispatchAddress AS_REGISTER(Register, IdispatchAddress) -#define ImethodDataPtr AS_REGISTER(Register, ImethodDataPtr) -#define IdispatchTables AS_REGISTER(Register, IdispatchTables) - -#define Oexception AS_REGISTER(Register, Oexception) -#define Oissuing_pc AS_REGISTER(Register, Oissuing_pc) - - -#endif - -// Address is an abstraction used to represent a memory location. -// -// Note: A register location is represented via a Register, not -// via an address for efficiency & simplicity reasons. - -class Address VALUE_OBJ_CLASS_SPEC { - private: - Register _base; // Base register. - RegisterOrConstant _index_or_disp; // Index register or constant displacement. - RelocationHolder _rspec; - - public: - Address() : _base(noreg), _index_or_disp(noreg) {} - - Address(Register base, RegisterOrConstant index_or_disp) - : _base(base), - _index_or_disp(index_or_disp) { - } - - Address(Register base, Register index) - : _base(base), - _index_or_disp(index) { - } - - Address(Register base, int disp) - : _base(base), - _index_or_disp(disp) { - } - -#ifdef ASSERT - // ByteSize is only a class when ASSERT is defined, otherwise it's an int. - Address(Register base, ByteSize disp) - : _base(base), - _index_or_disp(in_bytes(disp)) { - } -#endif - - // accessors - Register base() const { return _base; } - Register index() const { return _index_or_disp.as_register(); } - int disp() const { return _index_or_disp.as_constant(); } - - bool has_index() const { return _index_or_disp.is_register(); } - bool has_disp() const { return _index_or_disp.is_constant(); } - - bool uses(Register reg) const { return base() == reg || (has_index() && index() == reg); } - - const relocInfo::relocType rtype() { return _rspec.type(); } - const RelocationHolder& rspec() { return _rspec; } - - RelocationHolder rspec(int offset) const { - return offset == 0 ? _rspec : _rspec.plus(offset); - } - - inline bool is_simm13(int offset = 0); // check disp+offset for overflow - - Address plus_disp(int plusdisp) const { // bump disp by a small amount - assert(_index_or_disp.is_constant(), "must have a displacement"); - Address a(base(), disp() + plusdisp); - return a; - } - bool is_same_address(Address a) const { - // disregard _rspec - return base() == a.base() && (has_index() ? index() == a.index() : disp() == a.disp()); - } - - Address after_save() const { - Address a = (*this); - a._base = a._base->after_save(); - return a; - } - - Address after_restore() const { - Address a = (*this); - a._base = a._base->after_restore(); - return a; - } - - // Convert the raw encoding form into the form expected by the - // constructor for Address. - static Address make_raw(int base, int index, int scale, int disp, relocInfo::relocType disp_reloc); - - friend class Assembler; -}; - - -class AddressLiteral VALUE_OBJ_CLASS_SPEC { - private: - address _address; - RelocationHolder _rspec; - - RelocationHolder rspec_from_rtype(relocInfo::relocType rtype, address addr) { - switch (rtype) { - case relocInfo::external_word_type: - return external_word_Relocation::spec(addr); - case relocInfo::internal_word_type: - return internal_word_Relocation::spec(addr); -#ifdef _LP64 - case relocInfo::opt_virtual_call_type: - return opt_virtual_call_Relocation::spec(); - case relocInfo::static_call_type: - return static_call_Relocation::spec(); - case relocInfo::runtime_call_type: - return runtime_call_Relocation::spec(); -#endif - case relocInfo::none: - return RelocationHolder(); - default: - ShouldNotReachHere(); - return RelocationHolder(); - } - } - - protected: - // creation - AddressLiteral() : _address(NULL), _rspec(NULL) {} - - public: - AddressLiteral(address addr, RelocationHolder const& rspec) - : _address(addr), - _rspec(rspec) {} - - // Some constructors to avoid casting at the call site. - AddressLiteral(jobject obj, RelocationHolder const& rspec) - : _address((address) obj), - _rspec(rspec) {} - - AddressLiteral(intptr_t value, RelocationHolder const& rspec) - : _address((address) value), - _rspec(rspec) {} - - AddressLiteral(address addr, relocInfo::relocType rtype = relocInfo::none) - : _address((address) addr), - _rspec(rspec_from_rtype(rtype, (address) addr)) {} - - // Some constructors to avoid casting at the call site. - AddressLiteral(address* addr, relocInfo::relocType rtype = relocInfo::none) - : _address((address) addr), - _rspec(rspec_from_rtype(rtype, (address) addr)) {} - - AddressLiteral(bool* addr, relocInfo::relocType rtype = relocInfo::none) - : _address((address) addr), - _rspec(rspec_from_rtype(rtype, (address) addr)) {} - - AddressLiteral(const bool* addr, relocInfo::relocType rtype = relocInfo::none) - : _address((address) addr), - _rspec(rspec_from_rtype(rtype, (address) addr)) {} - - AddressLiteral(signed char* addr, relocInfo::relocType rtype = relocInfo::none) - : _address((address) addr), - _rspec(rspec_from_rtype(rtype, (address) addr)) {} - - AddressLiteral(int* addr, relocInfo::relocType rtype = relocInfo::none) - : _address((address) addr), - _rspec(rspec_from_rtype(rtype, (address) addr)) {} - - AddressLiteral(intptr_t addr, relocInfo::relocType rtype = relocInfo::none) - : _address((address) addr), - _rspec(rspec_from_rtype(rtype, (address) addr)) {} - -#ifdef _LP64 - // 32-bit complains about a multiple declaration for int*. - AddressLiteral(intptr_t* addr, relocInfo::relocType rtype = relocInfo::none) - : _address((address) addr), - _rspec(rspec_from_rtype(rtype, (address) addr)) {} -#endif - - AddressLiteral(Metadata* addr, relocInfo::relocType rtype = relocInfo::none) - : _address((address) addr), - _rspec(rspec_from_rtype(rtype, (address) addr)) {} - - AddressLiteral(Metadata** addr, relocInfo::relocType rtype = relocInfo::none) - : _address((address) addr), - _rspec(rspec_from_rtype(rtype, (address) addr)) {} - - AddressLiteral(float* addr, relocInfo::relocType rtype = relocInfo::none) - : _address((address) addr), - _rspec(rspec_from_rtype(rtype, (address) addr)) {} - - AddressLiteral(double* addr, relocInfo::relocType rtype = relocInfo::none) - : _address((address) addr), - _rspec(rspec_from_rtype(rtype, (address) addr)) {} - - intptr_t value() const { return (intptr_t) _address; } - int low10() const; - - const relocInfo::relocType rtype() const { return _rspec.type(); } - const RelocationHolder& rspec() const { return _rspec; } - - RelocationHolder rspec(int offset) const { - return offset == 0 ? _rspec : _rspec.plus(offset); - } -}; - -// Convenience classes -class ExternalAddress: public AddressLiteral { - private: - static relocInfo::relocType reloc_for_target(address target) { - // Sometimes ExternalAddress is used for values which aren't - // exactly addresses, like the card table base. - // external_word_type can't be used for values in the first page - // so just skip the reloc in that case. - return external_word_Relocation::can_be_relocated(target) ? relocInfo::external_word_type : relocInfo::none; - } - - public: - ExternalAddress(address target) : AddressLiteral(target, reloc_for_target( target)) {} - ExternalAddress(Metadata** target) : AddressLiteral(target, reloc_for_target((address) target)) {} -}; - -inline Address RegisterImpl::address_in_saved_window() const { - return (Address(SP, (sp_offset_in_saved_window() * wordSize) + STACK_BIAS)); -} - - - -// Argument is an abstraction used to represent an outgoing -// actual argument or an incoming formal parameter, whether -// it resides in memory or in a register, in a manner consistent -// with the SPARC Application Binary Interface, or ABI. This is -// often referred to as the native or C calling convention. - -class Argument VALUE_OBJ_CLASS_SPEC { - private: - int _number; - bool _is_in; - - public: -#ifdef _LP64 - enum { - n_register_parameters = 6, // only 6 registers may contain integer parameters - n_float_register_parameters = 16 // Can have up to 16 floating registers - }; -#else - enum { - n_register_parameters = 6 // only 6 registers may contain integer parameters - }; -#endif - - // creation - Argument(int number, bool is_in) : _number(number), _is_in(is_in) {} - - int number() const { return _number; } - bool is_in() const { return _is_in; } - bool is_out() const { return !is_in(); } - - Argument successor() const { return Argument(number() + 1, is_in()); } - Argument as_in() const { return Argument(number(), true ); } - Argument as_out() const { return Argument(number(), false); } - - // locating register-based arguments: - bool is_register() const { return _number < n_register_parameters; } - -#ifdef _LP64 - // locating Floating Point register-based arguments: - bool is_float_register() const { return _number < n_float_register_parameters; } - - FloatRegister as_float_register() const { - assert(is_float_register(), "must be a register argument"); - return as_FloatRegister(( number() *2 ) + 1); - } - FloatRegister as_double_register() const { - assert(is_float_register(), "must be a register argument"); - return as_FloatRegister(( number() *2 )); - } -#endif - - Register as_register() const { - assert(is_register(), "must be a register argument"); - return is_in() ? as_iRegister(number()) : as_oRegister(number()); - } - - // locating memory-based arguments - Address as_address() const { - assert(!is_register(), "must be a memory argument"); - return address_in_frame(); - } - - // When applied to a register-based argument, give the corresponding address - // into the 6-word area "into which callee may store register arguments" - // (This is a different place than the corresponding register-save area location.) - Address address_in_frame() const; - - // debugging - const char* name() const; - - friend class Assembler; -}; - +#include "asm/register.hpp" // The SPARC Assembler: Pure assembler doing NO optimizations on the instruction // level; i.e., what you write // is what you get. The Assembler is generating code into a CodeBuffer. class Assembler : public AbstractAssembler { - protected: - - static void print_instruction(int inst); - static int patched_branch(int dest_pos, int inst, int inst_pos); - static int branch_destination(int inst, int pos); - - friend class AbstractAssembler; friend class AddressLiteral; @@ -1230,10 +689,7 @@ public: // pp 135 (addc was addx in v8) inline void add(Register s1, Register s2, Register d ); - inline void add(Register s1, int simm13a, Register d, relocInfo::relocType rtype = relocInfo::none); - inline void add(Register s1, int simm13a, Register d, RelocationHolder const& rspec); - inline void add(Register s1, RegisterOrConstant s2, Register d, int offset = 0); - inline void add(const Address& a, Register d, int offset = 0); + inline void add(Register s1, int simm13a, Register d ); void addcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(add_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); } void addcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(add_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } @@ -1395,12 +851,9 @@ public: // 171 - inline void ldf(FloatRegisterImpl::Width w, Register s1, RegisterOrConstant s2, FloatRegister d); inline void ldf(FloatRegisterImpl::Width w, Register s1, Register s2, FloatRegister d); inline void ldf(FloatRegisterImpl::Width w, Register s1, int simm13a, FloatRegister d, RelocationHolder const& rspec = RelocationHolder()); - inline void ldf(FloatRegisterImpl::Width w, const Address& a, FloatRegister d, int offset = 0); - inline void ldfsr( Register s1, Register s2 ); inline void ldfsr( Register s1, int simm13a); @@ -1438,36 +891,9 @@ public: inline void lduw( Register s1, int simm13a, Register d); inline void ldx( Register s1, Register s2, Register d ); inline void ldx( Register s1, int simm13a, Register d); - inline void ld( Register s1, Register s2, Register d ); - inline void ld( Register s1, int simm13a, Register d); inline void ldd( Register s1, Register s2, Register d ); inline void ldd( Register s1, int simm13a, Register d); -#ifdef ASSERT - // ByteSize is only a class when ASSERT is defined, otherwise it's an int. - inline void ld( Register s1, ByteSize simm13a, Register d); -#endif - - inline void ldsb(const Address& a, Register d, int offset = 0); - inline void ldsh(const Address& a, Register d, int offset = 0); - inline void ldsw(const Address& a, Register d, int offset = 0); - inline void ldub(const Address& a, Register d, int offset = 0); - inline void lduh(const Address& a, Register d, int offset = 0); - inline void lduw(const Address& a, Register d, int offset = 0); - inline void ldx( const Address& a, Register d, int offset = 0); - inline void ld( const Address& a, Register d, int offset = 0); - inline void ldd( const Address& a, Register d, int offset = 0); - - inline void ldub( Register s1, RegisterOrConstant s2, Register d ); - inline void ldsb( Register s1, RegisterOrConstant s2, Register d ); - inline void lduh( Register s1, RegisterOrConstant s2, Register d ); - inline void ldsh( Register s1, RegisterOrConstant s2, Register d ); - inline void lduw( Register s1, RegisterOrConstant s2, Register d ); - inline void ldsw( Register s1, RegisterOrConstant s2, Register d ); - inline void ldx( Register s1, RegisterOrConstant s2, Register d ); - inline void ld( Register s1, RegisterOrConstant s2, Register d ); - inline void ldd( Register s1, RegisterOrConstant s2, Register d ); - // pp 177 void ldsba( Register s1, Register s2, int ia, Register d ) { emit_long( op(ldst_op) | rd(d) | op3(ldsb_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } @@ -1505,7 +931,6 @@ public: void andcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(and_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } void andn( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(andn_op3 ) | rs1(s1) | rs2(s2) ); } void andn( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(andn_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } - void andn( Register s1, RegisterOrConstant s2, Register d); void andncc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(andn_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); } void andncc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(andn_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } void or3( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(or_op3 ) | rs1(s1) | rs2(s2) ); } @@ -1584,13 +1009,12 @@ public: // pp 203 - void prefetch( Register s1, Register s2, PrefetchFcn f); - void prefetch( Register s1, int simm13a, PrefetchFcn f); + void prefetch( Register s1, Register s2, PrefetchFcn f) { v9_only(); emit_long( op(ldst_op) | fcn(f) | op3(prefetch_op3) | rs1(s1) | rs2(s2) ); } + void prefetch( Register s1, int simm13a, PrefetchFcn f) { v9_only(); emit_data( op(ldst_op) | fcn(f) | op3(prefetch_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } + void prefetcha( Register s1, Register s2, int ia, PrefetchFcn f ) { v9_only(); emit_long( op(ldst_op) | fcn(f) | op3(prefetch_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } void prefetcha( Register s1, int simm13a, PrefetchFcn f ) { v9_only(); emit_long( op(ldst_op) | fcn(f) | op3(prefetch_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } - inline void prefetch(const Address& a, PrefetchFcn F, int offset = 0); - // pp 208 // not implementing read privileged register @@ -1653,10 +1077,8 @@ public: // pp 222 - inline void stf( FloatRegisterImpl::Width w, FloatRegister d, Register s1, RegisterOrConstant s2); inline void stf( FloatRegisterImpl::Width w, FloatRegister d, Register s1, Register s2); inline void stf( FloatRegisterImpl::Width w, FloatRegister d, Register s1, int simm13a); - inline void stf( FloatRegisterImpl::Width w, FloatRegister d, const Address& a, int offset = 0); inline void stfsr( Register s1, Register s2 ); inline void stfsr( Register s1, int simm13a); @@ -1676,32 +1098,11 @@ public: inline void sth( Register d, Register s1, int simm13a); inline void stw( Register d, Register s1, Register s2 ); inline void stw( Register d, Register s1, int simm13a); - inline void st( Register d, Register s1, Register s2 ); - inline void st( Register d, Register s1, int simm13a); inline void stx( Register d, Register s1, Register s2 ); inline void stx( Register d, Register s1, int simm13a); inline void std( Register d, Register s1, Register s2 ); inline void std( Register d, Register s1, int simm13a); -#ifdef ASSERT - // ByteSize is only a class when ASSERT is defined, otherwise it's an int. - inline void st( Register d, Register s1, ByteSize simm13a); -#endif - - inline void stb( Register d, const Address& a, int offset = 0 ); - inline void sth( Register d, const Address& a, int offset = 0 ); - inline void stw( Register d, const Address& a, int offset = 0 ); - inline void stx( Register d, const Address& a, int offset = 0 ); - inline void st( Register d, const Address& a, int offset = 0 ); - inline void std( Register d, const Address& a, int offset = 0 ); - - inline void stb( Register d, Register s1, RegisterOrConstant s2 ); - inline void sth( Register d, Register s1, RegisterOrConstant s2 ); - inline void stw( Register d, Register s1, RegisterOrConstant s2 ); - inline void stx( Register d, Register s1, RegisterOrConstant s2 ); - inline void std( Register d, Register s1, RegisterOrConstant s2 ); - inline void st( Register d, Register s1, RegisterOrConstant s2 ); - // pp 177 void stba( Register d, Register s1, Register s2, int ia ) { emit_long( op(ldst_op) | rd(d) | op3(stb_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } @@ -1731,9 +1132,6 @@ public: void sub( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sub_op3 ) | rs1(s1) | rs2(s2) ); } void sub( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sub_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } - // Note: offset is added to s2. - inline void sub(Register s1, RegisterOrConstant s2, Register d, int offset = 0); - void subcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sub_op3 | cc_bit_op3 ) | rs1(s1) | rs2(s2) ); } void subcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sub_op3 | cc_bit_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } void subc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(subc_op3 ) | rs1(s1) | rs2(s2) ); } @@ -1745,7 +1143,6 @@ public: inline void swap( Register s1, Register s2, Register d ); inline void swap( Register s1, int simm13a, Register d); - inline void swap( Address& a, Register d, int offset = 0 ); // pp 232 @@ -1799,879 +1196,12 @@ public: void movwtos( Register s, FloatRegister d ) { vis3_only(); emit_long( op(arith_op) | fd(d, FloatRegisterImpl::S) | op3(mftoi_op3) | opf(mwtos_opf) | rs2(s)); } void movxtod( Register s, FloatRegister d ) { vis3_only(); emit_long( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(mftoi_op3) | opf(mxtod_opf) | rs2(s)); } - - - - // For a given register condition, return the appropriate condition code - // Condition (the one you would use to get the same effect after "tst" on - // the target register.) - Assembler::Condition reg_cond_to_cc_cond(RCondition in); - - // Creation Assembler(CodeBuffer* code) : AbstractAssembler(code) { #ifdef CHECK_DELAY delay_state = no_delay; #endif } - - // Testing -#ifndef PRODUCT - void test_v9(); - void test_v8_onlys(); -#endif }; - -class RegistersForDebugging : public StackObj { - public: - intptr_t i[8], l[8], o[8], g[8]; - float f[32]; - double d[32]; - - void print(outputStream* s); - - static int i_offset(int j) { return offset_of(RegistersForDebugging, i[j]); } - static int l_offset(int j) { return offset_of(RegistersForDebugging, l[j]); } - static int o_offset(int j) { return offset_of(RegistersForDebugging, o[j]); } - static int g_offset(int j) { return offset_of(RegistersForDebugging, g[j]); } - static int f_offset(int j) { return offset_of(RegistersForDebugging, f[j]); } - static int d_offset(int j) { return offset_of(RegistersForDebugging, d[j / 2]); } - - // gen asm code to save regs - static void save_registers(MacroAssembler* a); - - // restore global registers in case C code disturbed them - static void restore_registers(MacroAssembler* a, Register r); - - -}; - - -// MacroAssembler extends Assembler by a few frequently used macros. -// -// Most of the standard SPARC synthetic ops are defined here. -// Instructions for which a 'better' code sequence exists depending -// on arguments should also go in here. - -#define JMP2(r1, r2) jmp(r1, r2, __FILE__, __LINE__) -#define JMP(r1, off) jmp(r1, off, __FILE__, __LINE__) -#define JUMP(a, temp, off) jump(a, temp, off, __FILE__, __LINE__) -#define JUMPL(a, temp, d, off) jumpl(a, temp, d, off, __FILE__, __LINE__) - - -class MacroAssembler: public Assembler { - protected: - // Support for VM calls - // This is the base routine called by the different versions of call_VM_leaf. The interpreter - // may customize this version by overriding it for its purposes (e.g., to save/restore - // additional registers when doing a VM call). -#ifdef CC_INTERP - #define VIRTUAL -#else - #define VIRTUAL virtual -#endif - - VIRTUAL void call_VM_leaf_base(Register thread_cache, address entry_point, int number_of_arguments); - - // - // It is imperative that all calls into the VM are handled via the call_VM macros. - // They make sure that the stack linkage is setup correctly. call_VM's correspond - // to ENTRY/ENTRY_X entry points while call_VM_leaf's correspond to LEAF entry points. - // - // This is the base routine called by the different versions of call_VM. The interpreter - // may customize this version by overriding it for its purposes (e.g., to save/restore - // additional registers when doing a VM call). - // - // A non-volatile java_thread_cache register should be specified so - // that the G2_thread value can be preserved across the call. - // (If java_thread_cache is noreg, then a slow get_thread call - // will re-initialize the G2_thread.) call_VM_base returns the register that contains the - // thread. - // - // If no last_java_sp is specified (noreg) than SP will be used instead. - - virtual void call_VM_base( - Register oop_result, // where an oop-result ends up if any; use noreg otherwise - Register java_thread_cache, // the thread if computed before ; use noreg otherwise - Register last_java_sp, // to set up last_Java_frame in stubs; use noreg otherwise - address entry_point, // the entry point - int number_of_arguments, // the number of arguments (w/o thread) to pop after call - bool check_exception=true // flag which indicates if exception should be checked - ); - - // This routine should emit JVMTI PopFrame and ForceEarlyReturn handling code. - // The implementation is only non-empty for the InterpreterMacroAssembler, - // as only the interpreter handles and ForceEarlyReturn PopFrame requests. - virtual void check_and_handle_popframe(Register scratch_reg); - virtual void check_and_handle_earlyret(Register scratch_reg); - - public: - MacroAssembler(CodeBuffer* code) : Assembler(code) {} - - // Support for NULL-checks - // - // Generates code that causes a NULL OS exception if the content of reg is NULL. - // If the accessed location is M[reg + offset] and the offset is known, provide the - // offset. No explicit code generation is needed if the offset is within a certain - // range (0 <= offset <= page_size). - // - // %%%%%% Currently not done for SPARC - - void null_check(Register reg, int offset = -1); - static bool needs_explicit_null_check(intptr_t offset); - - // support for delayed instructions - MacroAssembler* delayed() { Assembler::delayed(); return this; } - - // branches that use right instruction for v8 vs. v9 - inline void br( Condition c, bool a, Predict p, address d, relocInfo::relocType rt = relocInfo::none ); - inline void br( Condition c, bool a, Predict p, Label& L ); - - inline void fb( Condition c, bool a, Predict p, address d, relocInfo::relocType rt = relocInfo::none ); - inline void fb( Condition c, bool a, Predict p, Label& L ); - - // compares register with zero (32 bit) and branches (V9 and V8 instructions) - void cmp_zero_and_br( Condition c, Register s1, Label& L, bool a = false, Predict p = pn ); - // Compares a pointer register with zero and branches on (not)null. - // Does a test & branch on 32-bit systems and a register-branch on 64-bit. - void br_null ( Register s1, bool a, Predict p, Label& L ); - void br_notnull( Register s1, bool a, Predict p, Label& L ); - - // - // Compare registers and branch with nop in delay slot or cbcond without delay slot. - // - // ATTENTION: use these instructions with caution because cbcond instruction - // has very short distance: 512 instructions (2Kbyte). - - // Compare integer (32 bit) values (icc only). - void cmp_and_br_short(Register s1, Register s2, Condition c, Predict p, Label& L); - void cmp_and_br_short(Register s1, int simm13a, Condition c, Predict p, Label& L); - // Platform depending version for pointer compare (icc on !LP64 and xcc on LP64). - void cmp_and_brx_short(Register s1, Register s2, Condition c, Predict p, Label& L); - void cmp_and_brx_short(Register s1, int simm13a, Condition c, Predict p, Label& L); - - // Short branch version for compares a pointer pwith zero. - void br_null_short ( Register s1, Predict p, Label& L ); - void br_notnull_short( Register s1, Predict p, Label& L ); - - // unconditional short branch - void ba_short(Label& L); - - inline void bp( Condition c, bool a, CC cc, Predict p, address d, relocInfo::relocType rt = relocInfo::none ); - inline void bp( Condition c, bool a, CC cc, Predict p, Label& L ); - - // Branch that tests xcc in LP64 and icc in !LP64 - inline void brx( Condition c, bool a, Predict p, address d, relocInfo::relocType rt = relocInfo::none ); - inline void brx( Condition c, bool a, Predict p, Label& L ); - - // unconditional branch - inline void ba( Label& L ); - - // Branch that tests fp condition codes - inline void fbp( Condition c, bool a, CC cc, Predict p, address d, relocInfo::relocType rt = relocInfo::none ); - inline void fbp( Condition c, bool a, CC cc, Predict p, Label& L ); - - // get PC the best way - inline int get_pc( Register d ); - - // Sparc shorthands(pp 85, V8 manual, pp 289 V9 manual) - inline void cmp( Register s1, Register s2 ) { subcc( s1, s2, G0 ); } - inline void cmp( Register s1, int simm13a ) { subcc( s1, simm13a, G0 ); } - - inline void jmp( Register s1, Register s2 ); - inline void jmp( Register s1, int simm13a, RelocationHolder const& rspec = RelocationHolder() ); - - // Check if the call target is out of wdisp30 range (relative to the code cache) - static inline bool is_far_target(address d); - inline void call( address d, relocInfo::relocType rt = relocInfo::runtime_call_type ); - inline void call( Label& L, relocInfo::relocType rt = relocInfo::runtime_call_type ); - inline void callr( Register s1, Register s2 ); - inline void callr( Register s1, int simm13a, RelocationHolder const& rspec = RelocationHolder() ); - - // Emits nothing on V8 - inline void iprefetch( address d, relocInfo::relocType rt = relocInfo::none ); - inline void iprefetch( Label& L); - - inline void tst( Register s ) { orcc( G0, s, G0 ); } - -#ifdef PRODUCT - inline void ret( bool trace = TraceJumps ) { if (trace) { - mov(I7, O7); // traceable register - JMP(O7, 2 * BytesPerInstWord); - } else { - jmpl( I7, 2 * BytesPerInstWord, G0 ); - } - } - - inline void retl( bool trace = TraceJumps ) { if (trace) JMP(O7, 2 * BytesPerInstWord); - else jmpl( O7, 2 * BytesPerInstWord, G0 ); } -#else - void ret( bool trace = TraceJumps ); - void retl( bool trace = TraceJumps ); -#endif /* PRODUCT */ - - // Required platform-specific helpers for Label::patch_instructions. - // They _shadow_ the declarations in AbstractAssembler, which are undefined. - void pd_patch_instruction(address branch, address target); -#ifndef PRODUCT - static void pd_print_patched_instruction(address branch); -#endif - - // sethi Macro handles optimizations and relocations -private: - void internal_sethi(const AddressLiteral& addrlit, Register d, bool ForceRelocatable); -public: - void sethi(const AddressLiteral& addrlit, Register d); - void patchable_sethi(const AddressLiteral& addrlit, Register d); - - // compute the number of instructions for a sethi/set - static int insts_for_sethi( address a, bool worst_case = false ); - static int worst_case_insts_for_set(); - - // set may be either setsw or setuw (high 32 bits may be zero or sign) -private: - void internal_set(const AddressLiteral& al, Register d, bool ForceRelocatable); - static int insts_for_internal_set(intptr_t value); -public: - void set(const AddressLiteral& addrlit, Register d); - void set(intptr_t value, Register d); - void set(address addr, Register d, RelocationHolder const& rspec); - static int insts_for_set(intptr_t value) { return insts_for_internal_set(value); } - - void patchable_set(const AddressLiteral& addrlit, Register d); - void patchable_set(intptr_t value, Register d); - void set64(jlong value, Register d, Register tmp); - static int insts_for_set64(jlong value); - - // sign-extend 32 to 64 - inline void signx( Register s, Register d ) { sra( s, G0, d); } - inline void signx( Register d ) { sra( d, G0, d); } - - inline void not1( Register s, Register d ) { xnor( s, G0, d ); } - inline void not1( Register d ) { xnor( d, G0, d ); } - - inline void neg( Register s, Register d ) { sub( G0, s, d ); } - inline void neg( Register d ) { sub( G0, d, d ); } - - inline void cas( Register s1, Register s2, Register d) { casa( s1, s2, d, ASI_PRIMARY); } - inline void casx( Register s1, Register s2, Register d) { casxa(s1, s2, d, ASI_PRIMARY); } - // Functions for isolating 64 bit atomic swaps for LP64 - // cas_ptr will perform cas for 32 bit VM's and casx for 64 bit VM's - inline void cas_ptr( Register s1, Register s2, Register d) { -#ifdef _LP64 - casx( s1, s2, d ); -#else - cas( s1, s2, d ); -#endif - } - - // Functions for isolating 64 bit shifts for LP64 - inline void sll_ptr( Register s1, Register s2, Register d ); - inline void sll_ptr( Register s1, int imm6a, Register d ); - inline void sll_ptr( Register s1, RegisterOrConstant s2, Register d ); - inline void srl_ptr( Register s1, Register s2, Register d ); - inline void srl_ptr( Register s1, int imm6a, Register d ); - - // little-endian - inline void casl( Register s1, Register s2, Register d) { casa( s1, s2, d, ASI_PRIMARY_LITTLE); } - inline void casxl( Register s1, Register s2, Register d) { casxa(s1, s2, d, ASI_PRIMARY_LITTLE); } - - inline void inc( Register d, int const13 = 1 ) { add( d, const13, d); } - inline void inccc( Register d, int const13 = 1 ) { addcc( d, const13, d); } - - inline void dec( Register d, int const13 = 1 ) { sub( d, const13, d); } - inline void deccc( Register d, int const13 = 1 ) { subcc( d, const13, d); } - - inline void btst( Register s1, Register s2 ) { andcc( s1, s2, G0 ); } - inline void btst( int simm13a, Register s ) { andcc( s, simm13a, G0 ); } - - inline void bset( Register s1, Register s2 ) { or3( s1, s2, s2 ); } - inline void bset( int simm13a, Register s ) { or3( s, simm13a, s ); } - - inline void bclr( Register s1, Register s2 ) { andn( s1, s2, s2 ); } - inline void bclr( int simm13a, Register s ) { andn( s, simm13a, s ); } - - inline void btog( Register s1, Register s2 ) { xor3( s1, s2, s2 ); } - inline void btog( int simm13a, Register s ) { xor3( s, simm13a, s ); } - - inline void clr( Register d ) { or3( G0, G0, d ); } - - inline void clrb( Register s1, Register s2); - inline void clrh( Register s1, Register s2); - inline void clr( Register s1, Register s2); - inline void clrx( Register s1, Register s2); - - inline void clrb( Register s1, int simm13a); - inline void clrh( Register s1, int simm13a); - inline void clr( Register s1, int simm13a); - inline void clrx( Register s1, int simm13a); - - // copy & clear upper word - inline void clruw( Register s, Register d ) { srl( s, G0, d); } - // clear upper word - inline void clruwu( Register d ) { srl( d, G0, d); } - - // membar psuedo instruction. takes into account target memory model. - inline void membar( Assembler::Membar_mask_bits const7a ); - - // returns if membar generates anything. - inline bool membar_has_effect( Assembler::Membar_mask_bits const7a ); - - // mov pseudo instructions - inline void mov( Register s, Register d) { - if ( s != d ) or3( G0, s, d); - else assert_not_delayed(); // Put something useful in the delay slot! - } - - inline void mov_or_nop( Register s, Register d) { - if ( s != d ) or3( G0, s, d); - else nop(); - } - - inline void mov( int simm13a, Register d) { or3( G0, simm13a, d); } - - // address pseudos: make these names unlike instruction names to avoid confusion - inline intptr_t load_pc_address( Register reg, int bytes_to_skip ); - inline void load_contents(const AddressLiteral& addrlit, Register d, int offset = 0); - inline void load_bool_contents(const AddressLiteral& addrlit, Register d, int offset = 0); - inline void load_ptr_contents(const AddressLiteral& addrlit, Register d, int offset = 0); - inline void store_contents(Register s, const AddressLiteral& addrlit, Register temp, int offset = 0); - inline void store_ptr_contents(Register s, const AddressLiteral& addrlit, Register temp, int offset = 0); - inline void jumpl_to(const AddressLiteral& addrlit, Register temp, Register d, int offset = 0); - inline void jump_to(const AddressLiteral& addrlit, Register temp, int offset = 0); - inline void jump_indirect_to(Address& a, Register temp, int ld_offset = 0, int jmp_offset = 0); - - // ring buffer traceable jumps - - void jmp2( Register r1, Register r2, const char* file, int line ); - void jmp ( Register r1, int offset, const char* file, int line ); - - void jumpl(const AddressLiteral& addrlit, Register temp, Register d, int offset, const char* file, int line); - void jump (const AddressLiteral& addrlit, Register temp, int offset, const char* file, int line); - - - // argument pseudos: - - inline void load_argument( Argument& a, Register d ); - inline void store_argument( Register s, Argument& a ); - inline void store_ptr_argument( Register s, Argument& a ); - inline void store_float_argument( FloatRegister s, Argument& a ); - inline void store_double_argument( FloatRegister s, Argument& a ); - inline void store_long_argument( Register s, Argument& a ); - - // handy macros: - - inline void round_to( Register r, int modulus ) { - assert_not_delayed(); - inc( r, modulus - 1 ); - and3( r, -modulus, r ); - } - - // -------------------------------------------------- - - // Functions for isolating 64 bit loads for LP64 - // ld_ptr will perform ld for 32 bit VM's and ldx for 64 bit VM's - // st_ptr will perform st for 32 bit VM's and stx for 64 bit VM's - inline void ld_ptr(Register s1, Register s2, Register d); - inline void ld_ptr(Register s1, int simm13a, Register d); - inline void ld_ptr(Register s1, RegisterOrConstant s2, Register d); - inline void ld_ptr(const Address& a, Register d, int offset = 0); - inline void st_ptr(Register d, Register s1, Register s2); - inline void st_ptr(Register d, Register s1, int simm13a); - inline void st_ptr(Register d, Register s1, RegisterOrConstant s2); - inline void st_ptr(Register d, const Address& a, int offset = 0); - -#ifdef ASSERT - // ByteSize is only a class when ASSERT is defined, otherwise it's an int. - inline void ld_ptr(Register s1, ByteSize simm13a, Register d); - inline void st_ptr(Register d, Register s1, ByteSize simm13a); -#endif - - // ld_long will perform ldd for 32 bit VM's and ldx for 64 bit VM's - // st_long will perform std for 32 bit VM's and stx for 64 bit VM's - inline void ld_long(Register s1, Register s2, Register d); - inline void ld_long(Register s1, int simm13a, Register d); - inline void ld_long(Register s1, RegisterOrConstant s2, Register d); - inline void ld_long(const Address& a, Register d, int offset = 0); - inline void st_long(Register d, Register s1, Register s2); - inline void st_long(Register d, Register s1, int simm13a); - inline void st_long(Register d, Register s1, RegisterOrConstant s2); - inline void st_long(Register d, const Address& a, int offset = 0); - - // Helpers for address formation. - // - They emit only a move if s2 is a constant zero. - // - If dest is a constant and either s1 or s2 is a register, the temp argument is required and becomes the result. - // - If dest is a register and either s1 or s2 is a non-simm13 constant, the temp argument is required and used to materialize the constant. - RegisterOrConstant regcon_andn_ptr(RegisterOrConstant s1, RegisterOrConstant s2, RegisterOrConstant d, Register temp = noreg); - RegisterOrConstant regcon_inc_ptr( RegisterOrConstant s1, RegisterOrConstant s2, RegisterOrConstant d, Register temp = noreg); - RegisterOrConstant regcon_sll_ptr( RegisterOrConstant s1, RegisterOrConstant s2, RegisterOrConstant d, Register temp = noreg); - - RegisterOrConstant ensure_simm13_or_reg(RegisterOrConstant src, Register temp) { - if (is_simm13(src.constant_or_zero())) - return src; // register or short constant - guarantee(temp != noreg, "constant offset overflow"); - set(src.as_constant(), temp); - return temp; - } - - // -------------------------------------------------- - - public: - // traps as per trap.h (SPARC ABI?) - - void breakpoint_trap(); - void breakpoint_trap(Condition c, CC cc); - void flush_windows_trap(); - void clean_windows_trap(); - void get_psr_trap(); - void set_psr_trap(); - - // V8/V9 flush_windows - void flush_windows(); - - // Support for serializing memory accesses between threads - void serialize_memory(Register thread, Register tmp1, Register tmp2); - - // Stack frame creation/removal - void enter(); - void leave(); - - // V8/V9 integer multiply - void mult(Register s1, Register s2, Register d); - void mult(Register s1, int simm13a, Register d); - - // V8/V9 read and write of condition codes. - void read_ccr(Register d); - void write_ccr(Register s); - - // Manipulation of C++ bools - // These are idioms to flag the need for care with accessing bools but on - // this platform we assume byte size - - inline void stbool(Register d, const Address& a) { stb(d, a); } - inline void ldbool(const Address& a, Register d) { ldub(a, d); } - inline void movbool( bool boolconst, Register d) { mov( (int) boolconst, d); } - - // klass oop manipulations if compressed - void load_klass(Register src_oop, Register klass); - void store_klass(Register klass, Register dst_oop); - void store_klass_gap(Register s, Register dst_oop); - - // oop manipulations - void load_heap_oop(const Address& s, Register d); - void load_heap_oop(Register s1, Register s2, Register d); - void load_heap_oop(Register s1, int simm13a, Register d); - void load_heap_oop(Register s1, RegisterOrConstant s2, Register d); - void store_heap_oop(Register d, Register s1, Register s2); - void store_heap_oop(Register d, Register s1, int simm13a); - void store_heap_oop(Register d, const Address& a, int offset = 0); - - void encode_heap_oop(Register src, Register dst); - void encode_heap_oop(Register r) { - encode_heap_oop(r, r); - } - void decode_heap_oop(Register src, Register dst); - void decode_heap_oop(Register r) { - decode_heap_oop(r, r); - } - void encode_heap_oop_not_null(Register r); - void decode_heap_oop_not_null(Register r); - void encode_heap_oop_not_null(Register src, Register dst); - void decode_heap_oop_not_null(Register src, Register dst); - - void encode_klass_not_null(Register r); - void decode_klass_not_null(Register r); - void encode_klass_not_null(Register src, Register dst); - void decode_klass_not_null(Register src, Register dst); - - // Support for managing the JavaThread pointer (i.e.; the reference to - // thread-local information). - void get_thread(); // load G2_thread - void verify_thread(); // verify G2_thread contents - void save_thread (const Register threache); // save to cache - void restore_thread(const Register thread_cache); // restore from cache - - // Support for last Java frame (but use call_VM instead where possible) - void set_last_Java_frame(Register last_java_sp, Register last_Java_pc); - void reset_last_Java_frame(void); - - // Call into the VM. - // Passes the thread pointer (in O0) as a prepended argument. - // Makes sure oop return values are visible to the GC. - void call_VM(Register oop_result, address entry_point, int number_of_arguments = 0, bool check_exceptions = true); - void call_VM(Register oop_result, address entry_point, Register arg_1, bool check_exceptions = true); - void call_VM(Register oop_result, address entry_point, Register arg_1, Register arg_2, bool check_exceptions = true); - void call_VM(Register oop_result, address entry_point, Register arg_1, Register arg_2, Register arg_3, bool check_exceptions = true); - - // these overloadings are not presently used on SPARC: - void call_VM(Register oop_result, Register last_java_sp, address entry_point, int number_of_arguments = 0, bool check_exceptions = true); - void call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, bool check_exceptions = true); - void call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, Register arg_2, bool check_exceptions = true); - void call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, Register arg_2, Register arg_3, bool check_exceptions = true); - - void call_VM_leaf(Register thread_cache, address entry_point, int number_of_arguments = 0); - void call_VM_leaf(Register thread_cache, address entry_point, Register arg_1); - void call_VM_leaf(Register thread_cache, address entry_point, Register arg_1, Register arg_2); - void call_VM_leaf(Register thread_cache, address entry_point, Register arg_1, Register arg_2, Register arg_3); - - void get_vm_result (Register oop_result); - void get_vm_result_2(Register metadata_result); - - // vm result is currently getting hijacked to for oop preservation - void set_vm_result(Register oop_result); - - // Emit the CompiledIC call idiom - void ic_call(address entry, bool emit_delay = true); - - // if call_VM_base was called with check_exceptions=false, then call - // check_and_forward_exception to handle exceptions when it is safe - void check_and_forward_exception(Register scratch_reg); - - private: - // For V8 - void read_ccr_trap(Register ccr_save); - void write_ccr_trap(Register ccr_save1, Register scratch1, Register scratch2); - -#ifdef ASSERT - // For V8 debugging. Uses V8 instruction sequence and checks - // result with V9 insturctions rdccr and wrccr. - // Uses Gscatch and Gscatch2 - void read_ccr_v8_assert(Register ccr_save); - void write_ccr_v8_assert(Register ccr_save); -#endif // ASSERT - - public: - - // Write to card table for - register is destroyed afterwards. - void card_table_write(jbyte* byte_map_base, Register tmp, Register obj); - - void card_write_barrier_post(Register store_addr, Register new_val, Register tmp); - -#ifndef SERIALGC - // General G1 pre-barrier generator. - void g1_write_barrier_pre(Register obj, Register index, int offset, Register pre_val, Register tmp, bool preserve_o_regs); - - // General G1 post-barrier generator - void g1_write_barrier_post(Register store_addr, Register new_val, Register tmp); -#endif // SERIALGC - - // pushes double TOS element of FPU stack on CPU stack; pops from FPU stack - void push_fTOS(); - - // pops double TOS element from CPU stack and pushes on FPU stack - void pop_fTOS(); - - void empty_FPU_stack(); - - void push_IU_state(); - void pop_IU_state(); - - void push_FPU_state(); - void pop_FPU_state(); - - void push_CPU_state(); - void pop_CPU_state(); - - // if heap base register is used - reinit it with the correct value - void reinit_heapbase(); - - // Debugging - void _verify_oop(Register reg, const char * msg, const char * file, int line); - void _verify_oop_addr(Address addr, const char * msg, const char * file, int line); - - // TODO: verify_method and klass metadata (compare against vptr?) - void _verify_method_ptr(Register reg, const char * msg, const char * file, int line) {} - void _verify_klass_ptr(Register reg, const char * msg, const char * file, int line){} - -#define verify_oop(reg) _verify_oop(reg, "broken oop " #reg, __FILE__, __LINE__) -#define verify_oop_addr(addr) _verify_oop_addr(addr, "broken oop addr ", __FILE__, __LINE__) -#define verify_method_ptr(reg) _verify_method_ptr(reg, "broken method " #reg, __FILE__, __LINE__) -#define verify_klass_ptr(reg) _verify_klass_ptr(reg, "broken klass " #reg, __FILE__, __LINE__) - - // only if +VerifyOops - void verify_FPU(int stack_depth, const char* s = "illegal FPU state"); - // only if +VerifyFPU - void stop(const char* msg); // prints msg, dumps registers and stops execution - void warn(const char* msg); // prints msg, but don't stop - void untested(const char* what = ""); - void unimplemented(const char* what = "") { char* b = new char[1024]; jio_snprintf(b, 1024, "unimplemented: %s", what); stop(b); } - void should_not_reach_here() { stop("should not reach here"); } - void print_CPU_state(); - - // oops in code - AddressLiteral allocate_oop_address(jobject obj); // allocate_index - AddressLiteral constant_oop_address(jobject obj); // find_index - inline void set_oop (jobject obj, Register d); // uses allocate_oop_address - inline void set_oop_constant (jobject obj, Register d); // uses constant_oop_address - inline void set_oop (const AddressLiteral& obj_addr, Register d); // same as load_address - - // metadata in code that we have to keep track of - AddressLiteral allocate_metadata_address(Metadata* obj); // allocate_index - AddressLiteral constant_metadata_address(Metadata* obj); // find_index - inline void set_metadata (Metadata* obj, Register d); // uses allocate_metadata_address - inline void set_metadata_constant (Metadata* obj, Register d); // uses constant_metadata_address - inline void set_metadata (const AddressLiteral& obj_addr, Register d); // same as load_address - - void set_narrow_oop( jobject obj, Register d ); - void set_narrow_klass( Klass* k, Register d ); - - // nop padding - void align(int modulus); - - // declare a safepoint - void safepoint(); - - // factor out part of stop into subroutine to save space - void stop_subroutine(); - // factor out part of verify_oop into subroutine to save space - void verify_oop_subroutine(); - - // side-door communication with signalHandler in os_solaris.cpp - static address _verify_oop_implicit_branch[3]; - -#ifndef PRODUCT - static void test(); -#endif - - int total_frame_size_in_bytes(int extraWords); - - // used when extraWords known statically - void save_frame(int extraWords = 0); - void save_frame_c1(int size_in_bytes); - // make a frame, and simultaneously pass up one or two register value - // into the new register window - void save_frame_and_mov(int extraWords, Register s1, Register d1, Register s2 = Register(), Register d2 = Register()); - - // give no. (outgoing) params, calc # of words will need on frame - void calc_mem_param_words(Register Rparam_words, Register Rresult); - - // used to calculate frame size dynamically - // result is in bytes and must be negated for save inst - void calc_frame_size(Register extraWords, Register resultReg); - - // calc and also save - void calc_frame_size_and_save(Register extraWords, Register resultReg); - - static void debug(char* msg, RegistersForDebugging* outWindow); - - // implementations of bytecodes used by both interpreter and compiler - - void lcmp( Register Ra_hi, Register Ra_low, - Register Rb_hi, Register Rb_low, - Register Rresult); - - void lneg( Register Rhi, Register Rlow ); - - void lshl( Register Rin_high, Register Rin_low, Register Rcount, - Register Rout_high, Register Rout_low, Register Rtemp ); - - void lshr( Register Rin_high, Register Rin_low, Register Rcount, - Register Rout_high, Register Rout_low, Register Rtemp ); - - void lushr( Register Rin_high, Register Rin_low, Register Rcount, - Register Rout_high, Register Rout_low, Register Rtemp ); - -#ifdef _LP64 - void lcmp( Register Ra, Register Rb, Register Rresult); -#endif - - // Load and store values by size and signed-ness - void load_sized_value( Address src, Register dst, size_t size_in_bytes, bool is_signed); - void store_sized_value(Register src, Address dst, size_t size_in_bytes); - - void float_cmp( bool is_float, int unordered_result, - FloatRegister Fa, FloatRegister Fb, - Register Rresult); - - void fneg( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d); - void fneg( FloatRegisterImpl::Width w, FloatRegister sd ) { Assembler::fneg(w, sd); } - void fmov( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d); - void fabs( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d); - - void save_all_globals_into_locals(); - void restore_globals_from_locals(); - - void casx_under_lock(Register top_ptr_reg, Register top_reg, Register ptr_reg, - address lock_addr=0, bool use_call_vm=false); - void cas_under_lock(Register top_ptr_reg, Register top_reg, Register ptr_reg, - address lock_addr=0, bool use_call_vm=false); - void casn (Register addr_reg, Register cmp_reg, Register set_reg) ; - - // These set the icc condition code to equal if the lock succeeded - // and notEqual if it failed and requires a slow case - void compiler_lock_object(Register Roop, Register Rmark, Register Rbox, - Register Rscratch, - BiasedLockingCounters* counters = NULL, - bool try_bias = UseBiasedLocking); - void compiler_unlock_object(Register Roop, Register Rmark, Register Rbox, - Register Rscratch, - bool try_bias = UseBiasedLocking); - - // Biased locking support - // Upon entry, lock_reg must point to the lock record on the stack, - // obj_reg must contain the target object, and mark_reg must contain - // the target object's header. - // Destroys mark_reg if an attempt is made to bias an anonymously - // biased lock. In this case a failure will go either to the slow - // case or fall through with the notEqual condition code set with - // the expectation that the slow case in the runtime will be called. - // In the fall-through case where the CAS-based lock is done, - // mark_reg is not destroyed. - void biased_locking_enter(Register obj_reg, Register mark_reg, Register temp_reg, - Label& done, Label* slow_case = NULL, - BiasedLockingCounters* counters = NULL); - // Upon entry, the base register of mark_addr must contain the oop. - // Destroys temp_reg. - - // If allow_delay_slot_filling is set to true, the next instruction - // emitted after this one will go in an annulled delay slot if the - // biased locking exit case failed. - void biased_locking_exit(Address mark_addr, Register temp_reg, Label& done, bool allow_delay_slot_filling = false); - - // allocation - void eden_allocate( - Register obj, // result: pointer to object after successful allocation - Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise - int con_size_in_bytes, // object size in bytes if known at compile time - Register t1, // temp register - Register t2, // temp register - Label& slow_case // continuation point if fast allocation fails - ); - void tlab_allocate( - Register obj, // result: pointer to object after successful allocation - Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise - int con_size_in_bytes, // object size in bytes if known at compile time - Register t1, // temp register - Label& slow_case // continuation point if fast allocation fails - ); - void tlab_refill(Label& retry_tlab, Label& try_eden, Label& slow_case); - void incr_allocated_bytes(RegisterOrConstant size_in_bytes, - Register t1, Register t2); - - // interface method calling - void lookup_interface_method(Register recv_klass, - Register intf_klass, - RegisterOrConstant itable_index, - Register method_result, - Register temp_reg, Register temp2_reg, - Label& no_such_interface); - - // virtual method calling - void lookup_virtual_method(Register recv_klass, - RegisterOrConstant vtable_index, - Register method_result); - - // Test sub_klass against super_klass, with fast and slow paths. - - // The fast path produces a tri-state answer: yes / no / maybe-slow. - // One of the three labels can be NULL, meaning take the fall-through. - // If super_check_offset is -1, the value is loaded up from super_klass. - // No registers are killed, except temp_reg and temp2_reg. - // If super_check_offset is not -1, temp2_reg is not used and can be noreg. - void check_klass_subtype_fast_path(Register sub_klass, - Register super_klass, - Register temp_reg, - Register temp2_reg, - Label* L_success, - Label* L_failure, - Label* L_slow_path, - RegisterOrConstant super_check_offset = RegisterOrConstant(-1)); - - // The rest of the type check; must be wired to a corresponding fast path. - // It does not repeat the fast path logic, so don't use it standalone. - // The temp_reg can be noreg, if no temps are available. - // It can also be sub_klass or super_klass, meaning it's OK to kill that one. - // Updates the sub's secondary super cache as necessary. - void check_klass_subtype_slow_path(Register sub_klass, - Register super_klass, - Register temp_reg, - Register temp2_reg, - Register temp3_reg, - Register temp4_reg, - Label* L_success, - Label* L_failure); - - // Simplified, combined version, good for typical uses. - // Falls through on failure. - void check_klass_subtype(Register sub_klass, - Register super_klass, - Register temp_reg, - Register temp2_reg, - Label& L_success); - - // method handles (JSR 292) - // offset relative to Gargs of argument at tos[arg_slot]. - // (arg_slot == 0 means the last argument, not the first). - RegisterOrConstant argument_offset(RegisterOrConstant arg_slot, - Register temp_reg, - int extra_slot_offset = 0); - // Address of Gargs and argument_offset. - Address argument_address(RegisterOrConstant arg_slot, - Register temp_reg = noreg, - int extra_slot_offset = 0); - - // Stack overflow checking - - // Note: this clobbers G3_scratch - void bang_stack_with_offset(int offset) { - // stack grows down, caller passes positive offset - assert(offset > 0, "must bang with negative offset"); - set((-offset)+STACK_BIAS, G3_scratch); - st(G0, SP, G3_scratch); - } - - // Writes to stack successive pages until offset reached to check for - // stack overflow + shadow pages. Clobbers tsp and scratch registers. - void bang_stack_size(Register Rsize, Register Rtsp, Register Rscratch); - - virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr, Register tmp, int offset); - - void verify_tlab(); - - Condition negate_condition(Condition cond); - - // Helper functions for statistics gathering. - // Conditionally (non-atomically) increments passed counter address, preserving condition codes. - void cond_inc(Condition cond, address counter_addr, Register Rtemp1, Register Rtemp2); - // Unconditional increment. - void inc_counter(address counter_addr, Register Rtmp1, Register Rtmp2); - void inc_counter(int* counter_addr, Register Rtmp1, Register Rtmp2); - - // Compare char[] arrays aligned to 4 bytes. - void char_arrays_equals(Register ary1, Register ary2, - Register limit, Register result, - Register chr1, Register chr2, Label& Ldone); - // Use BIS for zeroing - void bis_zeroing(Register to, Register count, Register temp, Label& Ldone); - -#undef VIRTUAL - -}; - -/** - * class SkipIfEqual: - * - * Instantiating this class will result in assembly code being output that will - * jump around any code emitted between the creation of the instance and it's - * automatic destruction at the end of a scope block, depending on the value of - * the flag passed to the constructor, which will be checked at run-time. - */ -class SkipIfEqual : public StackObj { - private: - MacroAssembler* _masm; - Label _label; - - public: - // 'temp' is a temp register that this object can use (and trash) - SkipIfEqual(MacroAssembler*, Register temp, - const bool* flag_addr, Assembler::Condition condition); - ~SkipIfEqual(); -}; - -#ifdef ASSERT -// On RISC, there's no benefit to verifying instruction boundaries. -inline bool AbstractAssembler::pd_check_instruction_mark() { return false; } -#endif - #endif // CPU_SPARC_VM_ASSEMBLER_SPARC_HPP diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp index 63359d511eb..fac53f2cfd7 100644 --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp @@ -25,33 +25,8 @@ #ifndef CPU_SPARC_VM_ASSEMBLER_SPARC_INLINE_HPP #define CPU_SPARC_VM_ASSEMBLER_SPARC_INLINE_HPP -#include "asm/assembler.inline.hpp" -#include "asm/codeBuffer.hpp" -#include "code/codeCache.hpp" -#include "runtime/handles.inline.hpp" +#include "asm/assembler.hpp" -inline void MacroAssembler::pd_patch_instruction(address branch, address target) { - jint& stub_inst = *(jint*) branch; - stub_inst = patched_branch(target - branch, stub_inst, 0); -} - -#ifndef PRODUCT -inline void MacroAssembler::pd_print_patched_instruction(address branch) { - jint stub_inst = *(jint*) branch; - print_instruction(stub_inst); - ::tty->print("%s", " (unresolved)"); -} -#endif // PRODUCT - -inline bool Address::is_simm13(int offset) { return Assembler::is_simm13(disp() + offset); } - - -inline int AddressLiteral::low10() const { - return Assembler::low10(value()); -} - - -// inlines for SPARC assembler -- dmu 5/97 inline void Assembler::check_delay() { # ifdef CHECK_DELAY @@ -76,9 +51,8 @@ inline void Assembler::emit_data(int x, RelocationHolder const& rspec) { } -inline void Assembler::add(Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(add_op3) | rs1(s1) | rs2(s2) ); } -inline void Assembler::add(Register s1, int simm13a, Register d, relocInfo::relocType rtype ) { emit_data( op(arith_op) | rd(d) | op3(add_op3) | rs1(s1) | immed(true) | simm(simm13a, 13), rtype ); } -inline void Assembler::add(Register s1, int simm13a, Register d, RelocationHolder const& rspec ) { emit_data( op(arith_op) | rd(d) | op3(add_op3) | rs1(s1) | immed(true) | simm(simm13a, 13), rspec ); } +inline void Assembler::add(Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(add_op3) | rs1(s1) | rs2(s2) ); } +inline void Assembler::add(Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(add_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } inline void Assembler::bpr( RCondition c, bool a, Predict p, Register s1, address d, relocInfo::relocType rt ) { v9_only(); cti(); emit_data( op(branch_op) | annul(a) | cond(c) | op2(bpr_op2) | wdisp16(intptr_t(d), intptr_t(pc())) | predict(p) | rs1(s1), rt); has_delay_slot(); } inline void Assembler::bpr( RCondition c, bool a, Predict p, Register s1, Label& L) { bpr( c, a, p, s1, target(L)); } @@ -111,16 +85,9 @@ inline void Assembler::flush( Register s1, int simm13a) { emit_data( op(arith_op inline void Assembler::jmpl( Register s1, Register s2, Register d ) { cti(); emit_long( op(arith_op) | rd(d) | op3(jmpl_op3) | rs1(s1) | rs2(s2)); has_delay_slot(); } inline void Assembler::jmpl( Register s1, int simm13a, Register d, RelocationHolder const& rspec ) { cti(); emit_data( op(arith_op) | rd(d) | op3(jmpl_op3) | rs1(s1) | immed(true) | simm(simm13a, 13), rspec); has_delay_slot(); } -inline void Assembler::ldf(FloatRegisterImpl::Width w, Register s1, RegisterOrConstant s2, FloatRegister d) { - if (s2.is_register()) ldf(w, s1, s2.as_register(), d); - else ldf(w, s1, s2.as_constant(), d); -} - inline void Assembler::ldf(FloatRegisterImpl::Width w, Register s1, Register s2, FloatRegister d) { emit_long( op(ldst_op) | fd(d, w) | alt_op3(ldf_op3, w) | rs1(s1) | rs2(s2) ); } inline void Assembler::ldf(FloatRegisterImpl::Width w, Register s1, int simm13a, FloatRegister d, RelocationHolder const& rspec) { emit_data( op(ldst_op) | fd(d, w) | alt_op3(ldf_op3, w) | rs1(s1) | immed(true) | simm(simm13a, 13), rspec); } -inline void Assembler::ldf(FloatRegisterImpl::Width w, const Address& a, FloatRegister d, int offset) { relocate(a.rspec(offset)); ldf( w, a.base(), a.disp() + offset, d); } - inline void Assembler::ldfsr( Register s1, Register s2) { v9_dep(); emit_long( op(ldst_op) | op3(ldfsr_op3) | rs1(s1) | rs2(s2) ); } inline void Assembler::ldfsr( Register s1, int simm13a) { v9_dep(); emit_data( op(ldst_op) | op3(ldfsr_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } inline void Assembler::ldxfsr( Register s1, Register s2) { v9_only(); emit_long( op(ldst_op) | rd(G1) | op3(ldfsr_op3) | rs1(s1) | rs2(s2) ); } @@ -152,98 +119,9 @@ inline void Assembler::ldx( Register s1, int simm13a, Register d) { v9_only(); inline void Assembler::ldd( Register s1, Register s2, Register d) { v9_dep(); assert(d->is_even(), "not even"); emit_long( op(ldst_op) | rd(d) | op3(ldd_op3) | rs1(s1) | rs2(s2) ); } inline void Assembler::ldd( Register s1, int simm13a, Register d) { v9_dep(); assert(d->is_even(), "not even"); emit_data( op(ldst_op) | rd(d) | op3(ldd_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } -#ifdef _LP64 -// Make all 32 bit loads signed so 64 bit registers maintain proper sign -inline void Assembler::ld( Register s1, Register s2, Register d) { ldsw( s1, s2, d); } -inline void Assembler::ld( Register s1, int simm13a, Register d) { ldsw( s1, simm13a, d); } -#else -inline void Assembler::ld( Register s1, Register s2, Register d) { lduw( s1, s2, d); } -inline void Assembler::ld( Register s1, int simm13a, Register d) { lduw( s1, simm13a, d); } -#endif - -#ifdef ASSERT - // ByteSize is only a class when ASSERT is defined, otherwise it's an int. -# ifdef _LP64 -inline void Assembler::ld( Register s1, ByteSize simm13a, Register d) { ldsw( s1, in_bytes(simm13a), d); } -# else -inline void Assembler::ld( Register s1, ByteSize simm13a, Register d) { lduw( s1, in_bytes(simm13a), d); } -# endif -#endif - -inline void Assembler::ld( const Address& a, Register d, int offset) { - if (a.has_index()) { assert(offset == 0, ""); ld( a.base(), a.index(), d); } - else { ld( a.base(), a.disp() + offset, d); } -} -inline void Assembler::ldsb(const Address& a, Register d, int offset) { - if (a.has_index()) { assert(offset == 0, ""); ldsb(a.base(), a.index(), d); } - else { ldsb(a.base(), a.disp() + offset, d); } -} -inline void Assembler::ldsh(const Address& a, Register d, int offset) { - if (a.has_index()) { assert(offset == 0, ""); ldsh(a.base(), a.index(), d); } - else { ldsh(a.base(), a.disp() + offset, d); } -} -inline void Assembler::ldsw(const Address& a, Register d, int offset) { - if (a.has_index()) { assert(offset == 0, ""); ldsw(a.base(), a.index(), d); } - else { ldsw(a.base(), a.disp() + offset, d); } -} -inline void Assembler::ldub(const Address& a, Register d, int offset) { - if (a.has_index()) { assert(offset == 0, ""); ldub(a.base(), a.index(), d); } - else { ldub(a.base(), a.disp() + offset, d); } -} -inline void Assembler::lduh(const Address& a, Register d, int offset) { - if (a.has_index()) { assert(offset == 0, ""); lduh(a.base(), a.index(), d); } - else { lduh(a.base(), a.disp() + offset, d); } -} -inline void Assembler::lduw(const Address& a, Register d, int offset) { - if (a.has_index()) { assert(offset == 0, ""); lduw(a.base(), a.index(), d); } - else { lduw(a.base(), a.disp() + offset, d); } -} -inline void Assembler::ldd( const Address& a, Register d, int offset) { - if (a.has_index()) { assert(offset == 0, ""); ldd( a.base(), a.index(), d); } - else { ldd( a.base(), a.disp() + offset, d); } -} -inline void Assembler::ldx( const Address& a, Register d, int offset) { - if (a.has_index()) { assert(offset == 0, ""); ldx( a.base(), a.index(), d); } - else { ldx( a.base(), a.disp() + offset, d); } -} - -inline void Assembler::ldub(Register s1, RegisterOrConstant s2, Register d) { ldub(Address(s1, s2), d); } -inline void Assembler::ldsb(Register s1, RegisterOrConstant s2, Register d) { ldsb(Address(s1, s2), d); } -inline void Assembler::lduh(Register s1, RegisterOrConstant s2, Register d) { lduh(Address(s1, s2), d); } -inline void Assembler::ldsh(Register s1, RegisterOrConstant s2, Register d) { ldsh(Address(s1, s2), d); } -inline void Assembler::lduw(Register s1, RegisterOrConstant s2, Register d) { lduw(Address(s1, s2), d); } -inline void Assembler::ldsw(Register s1, RegisterOrConstant s2, Register d) { ldsw(Address(s1, s2), d); } -inline void Assembler::ldx( Register s1, RegisterOrConstant s2, Register d) { ldx( Address(s1, s2), d); } -inline void Assembler::ld( Register s1, RegisterOrConstant s2, Register d) { ld( Address(s1, s2), d); } -inline void Assembler::ldd( Register s1, RegisterOrConstant s2, Register d) { ldd( Address(s1, s2), d); } - -// form effective addresses this way: -inline void Assembler::add(const Address& a, Register d, int offset) { - if (a.has_index()) add(a.base(), a.index(), d); - else { add(a.base(), a.disp() + offset, d, a.rspec(offset)); offset = 0; } - if (offset != 0) add(d, offset, d); -} -inline void Assembler::add(Register s1, RegisterOrConstant s2, Register d, int offset) { - if (s2.is_register()) add(s1, s2.as_register(), d); - else { add(s1, s2.as_constant() + offset, d); offset = 0; } - if (offset != 0) add(d, offset, d); -} - -inline void Assembler::andn(Register s1, RegisterOrConstant s2, Register d) { - if (s2.is_register()) andn(s1, s2.as_register(), d); - else andn(s1, s2.as_constant(), d); -} - inline void Assembler::ldstub( Register s1, Register s2, Register d) { emit_long( op(ldst_op) | rd(d) | op3(ldstub_op3) | rs1(s1) | rs2(s2) ); } inline void Assembler::ldstub( Register s1, int simm13a, Register d) { emit_data( op(ldst_op) | rd(d) | op3(ldstub_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } - -inline void Assembler::prefetch(Register s1, Register s2, PrefetchFcn f) { v9_only(); emit_long( op(ldst_op) | fcn(f) | op3(prefetch_op3) | rs1(s1) | rs2(s2) ); } -inline void Assembler::prefetch(Register s1, int simm13a, PrefetchFcn f) { v9_only(); emit_data( op(ldst_op) | fcn(f) | op3(prefetch_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } - -inline void Assembler::prefetch(const Address& a, PrefetchFcn f, int offset) { v9_only(); relocate(a.rspec(offset)); prefetch(a.base(), a.disp() + offset, f); } - - inline void Assembler::rett( Register s1, Register s2 ) { cti(); emit_long( op(arith_op) | op3(rett_op3) | rs1(s1) | rs2(s2)); has_delay_slot(); } inline void Assembler::rett( Register s1, int simm13a, relocInfo::relocType rt) { cti(); emit_data( op(arith_op) | op3(rett_op3) | rs1(s1) | immed(true) | simm(simm13a, 13), rt); has_delay_slot(); } @@ -251,20 +129,9 @@ inline void Assembler::sethi( int imm22a, Register d, RelocationHolder const& rs // pp 222 -inline void Assembler::stf( FloatRegisterImpl::Width w, FloatRegister d, Register s1, RegisterOrConstant s2) { - if (s2.is_register()) stf(w, d, s1, s2.as_register()); - else stf(w, d, s1, s2.as_constant()); -} - inline void Assembler::stf( FloatRegisterImpl::Width w, FloatRegister d, Register s1, Register s2) { emit_long( op(ldst_op) | fd(d, w) | alt_op3(stf_op3, w) | rs1(s1) | rs2(s2) ); } inline void Assembler::stf( FloatRegisterImpl::Width w, FloatRegister d, Register s1, int simm13a) { emit_data( op(ldst_op) | fd(d, w) | alt_op3(stf_op3, w) | rs1(s1) | immed(true) | simm(simm13a, 13)); } -inline void Assembler::stf( FloatRegisterImpl::Width w, FloatRegister d, const Address& a, int offset) { - relocate(a.rspec(offset)); - if (a.has_index()) { assert(offset == 0, ""); stf(w, d, a.base(), a.index() ); } - else { stf(w, d, a.base(), a.disp() + offset); } -} - inline void Assembler::stfsr( Register s1, Register s2) { v9_dep(); emit_long( op(ldst_op) | op3(stfsr_op3) | rs1(s1) | rs2(s2) ); } inline void Assembler::stfsr( Register s1, int simm13a) { v9_dep(); emit_data( op(ldst_op) | op3(stfsr_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } inline void Assembler::stxfsr( Register s1, Register s2) { v9_only(); emit_long( op(ldst_op) | rd(G1) | op3(stfsr_op3) | rs1(s1) | rs2(s2) ); } @@ -285,46 +152,6 @@ inline void Assembler::stx( Register d, Register s1, int simm13a) { v9_only(); inline void Assembler::std( Register d, Register s1, Register s2) { v9_dep(); assert(d->is_even(), "not even"); emit_long( op(ldst_op) | rd(d) | op3(std_op3) | rs1(s1) | rs2(s2) ); } inline void Assembler::std( Register d, Register s1, int simm13a) { v9_dep(); assert(d->is_even(), "not even"); emit_data( op(ldst_op) | rd(d) | op3(std_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } -inline void Assembler::st( Register d, Register s1, Register s2) { stw(d, s1, s2); } -inline void Assembler::st( Register d, Register s1, int simm13a) { stw(d, s1, simm13a); } - -#ifdef ASSERT -// ByteSize is only a class when ASSERT is defined, otherwise it's an int. -inline void Assembler::st( Register d, Register s1, ByteSize simm13a) { stw(d, s1, in_bytes(simm13a)); } -#endif - -inline void Assembler::stb(Register d, const Address& a, int offset) { - if (a.has_index()) { assert(offset == 0, ""); stb(d, a.base(), a.index() ); } - else { stb(d, a.base(), a.disp() + offset); } -} -inline void Assembler::sth(Register d, const Address& a, int offset) { - if (a.has_index()) { assert(offset == 0, ""); sth(d, a.base(), a.index() ); } - else { sth(d, a.base(), a.disp() + offset); } -} -inline void Assembler::stw(Register d, const Address& a, int offset) { - if (a.has_index()) { assert(offset == 0, ""); stw(d, a.base(), a.index() ); } - else { stw(d, a.base(), a.disp() + offset); } -} -inline void Assembler::st( Register d, const Address& a, int offset) { - if (a.has_index()) { assert(offset == 0, ""); st( d, a.base(), a.index() ); } - else { st( d, a.base(), a.disp() + offset); } -} -inline void Assembler::std(Register d, const Address& a, int offset) { - if (a.has_index()) { assert(offset == 0, ""); std(d, a.base(), a.index() ); } - else { std(d, a.base(), a.disp() + offset); } -} -inline void Assembler::stx(Register d, const Address& a, int offset) { - if (a.has_index()) { assert(offset == 0, ""); stx(d, a.base(), a.index() ); } - else { stx(d, a.base(), a.disp() + offset); } -} - -inline void Assembler::stb(Register d, Register s1, RegisterOrConstant s2) { stb(d, Address(s1, s2)); } -inline void Assembler::sth(Register d, Register s1, RegisterOrConstant s2) { sth(d, Address(s1, s2)); } -inline void Assembler::stw(Register d, Register s1, RegisterOrConstant s2) { stw(d, Address(s1, s2)); } -inline void Assembler::stx(Register d, Register s1, RegisterOrConstant s2) { stx(d, Address(s1, s2)); } -inline void Assembler::std(Register d, Register s1, RegisterOrConstant s2) { std(d, Address(s1, s2)); } -inline void Assembler::st( Register d, Register s1, RegisterOrConstant s2) { st( d, Address(s1, s2)); } - // v8 p 99 inline void Assembler::stc( int crd, Register s1, Register s2) { v8_only(); emit_long( op(ldst_op) | fcn(crd) | op3(stc_op3 ) | rs1(s1) | rs2(s2) ); } @@ -336,561 +163,9 @@ inline void Assembler::stcsr( int crd, Register s1, int simm13a) { v8_only(); inline void Assembler::stdcq( int crd, Register s1, Register s2) { v8_only(); emit_long( op(ldst_op) | fcn(crd) | op3(stdcq_op3) | rs1(s1) | rs2(s2) ); } inline void Assembler::stdcq( int crd, Register s1, int simm13a) { v8_only(); emit_data( op(ldst_op) | fcn(crd) | op3(stdcq_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } -inline void Assembler::sub(Register s1, RegisterOrConstant s2, Register d, int offset) { - if (s2.is_register()) sub(s1, s2.as_register(), d); - else { sub(s1, s2.as_constant() + offset, d); offset = 0; } - if (offset != 0) sub(d, offset, d); -} - // pp 231 inline void Assembler::swap( Register s1, Register s2, Register d) { v9_dep(); emit_long( op(ldst_op) | rd(d) | op3(swap_op3) | rs1(s1) | rs2(s2) ); } inline void Assembler::swap( Register s1, int simm13a, Register d) { v9_dep(); emit_data( op(ldst_op) | rd(d) | op3(swap_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } -inline void Assembler::swap( Address& a, Register d, int offset ) { - relocate(a.rspec(offset)); - if (a.has_index()) { assert(offset == 0, ""); swap( a.base(), a.index(), d ); } - else { swap( a.base(), a.disp() + offset, d ); } -} - - -// Use the right loads/stores for the platform -inline void MacroAssembler::ld_ptr( Register s1, Register s2, Register d ) { -#ifdef _LP64 - Assembler::ldx(s1, s2, d); -#else - Assembler::ld( s1, s2, d); -#endif -} - -inline void MacroAssembler::ld_ptr( Register s1, int simm13a, Register d ) { -#ifdef _LP64 - Assembler::ldx(s1, simm13a, d); -#else - Assembler::ld( s1, simm13a, d); -#endif -} - -#ifdef ASSERT -// ByteSize is only a class when ASSERT is defined, otherwise it's an int. -inline void MacroAssembler::ld_ptr( Register s1, ByteSize simm13a, Register d ) { - ld_ptr(s1, in_bytes(simm13a), d); -} -#endif - -inline void MacroAssembler::ld_ptr( Register s1, RegisterOrConstant s2, Register d ) { -#ifdef _LP64 - Assembler::ldx(s1, s2, d); -#else - Assembler::ld( s1, s2, d); -#endif -} - -inline void MacroAssembler::ld_ptr(const Address& a, Register d, int offset) { -#ifdef _LP64 - Assembler::ldx(a, d, offset); -#else - Assembler::ld( a, d, offset); -#endif -} - -inline void MacroAssembler::st_ptr( Register d, Register s1, Register s2 ) { -#ifdef _LP64 - Assembler::stx(d, s1, s2); -#else - Assembler::st( d, s1, s2); -#endif -} - -inline void MacroAssembler::st_ptr( Register d, Register s1, int simm13a ) { -#ifdef _LP64 - Assembler::stx(d, s1, simm13a); -#else - Assembler::st( d, s1, simm13a); -#endif -} - -#ifdef ASSERT -// ByteSize is only a class when ASSERT is defined, otherwise it's an int. -inline void MacroAssembler::st_ptr( Register d, Register s1, ByteSize simm13a ) { - st_ptr(d, s1, in_bytes(simm13a)); -} -#endif - -inline void MacroAssembler::st_ptr( Register d, Register s1, RegisterOrConstant s2 ) { -#ifdef _LP64 - Assembler::stx(d, s1, s2); -#else - Assembler::st( d, s1, s2); -#endif -} - -inline void MacroAssembler::st_ptr(Register d, const Address& a, int offset) { -#ifdef _LP64 - Assembler::stx(d, a, offset); -#else - Assembler::st( d, a, offset); -#endif -} - -// Use the right loads/stores for the platform -inline void MacroAssembler::ld_long( Register s1, Register s2, Register d ) { -#ifdef _LP64 - Assembler::ldx(s1, s2, d); -#else - Assembler::ldd(s1, s2, d); -#endif -} - -inline void MacroAssembler::ld_long( Register s1, int simm13a, Register d ) { -#ifdef _LP64 - Assembler::ldx(s1, simm13a, d); -#else - Assembler::ldd(s1, simm13a, d); -#endif -} - -inline void MacroAssembler::ld_long( Register s1, RegisterOrConstant s2, Register d ) { -#ifdef _LP64 - Assembler::ldx(s1, s2, d); -#else - Assembler::ldd(s1, s2, d); -#endif -} - -inline void MacroAssembler::ld_long(const Address& a, Register d, int offset) { -#ifdef _LP64 - Assembler::ldx(a, d, offset); -#else - Assembler::ldd(a, d, offset); -#endif -} - -inline void MacroAssembler::st_long( Register d, Register s1, Register s2 ) { -#ifdef _LP64 - Assembler::stx(d, s1, s2); -#else - Assembler::std(d, s1, s2); -#endif -} - -inline void MacroAssembler::st_long( Register d, Register s1, int simm13a ) { -#ifdef _LP64 - Assembler::stx(d, s1, simm13a); -#else - Assembler::std(d, s1, simm13a); -#endif -} - -inline void MacroAssembler::st_long( Register d, Register s1, RegisterOrConstant s2 ) { -#ifdef _LP64 - Assembler::stx(d, s1, s2); -#else - Assembler::std(d, s1, s2); -#endif -} - -inline void MacroAssembler::st_long( Register d, const Address& a, int offset ) { -#ifdef _LP64 - Assembler::stx(d, a, offset); -#else - Assembler::std(d, a, offset); -#endif -} - -// Functions for isolating 64 bit shifts for LP64 - -inline void MacroAssembler::sll_ptr( Register s1, Register s2, Register d ) { -#ifdef _LP64 - Assembler::sllx(s1, s2, d); -#else - Assembler::sll( s1, s2, d); -#endif -} - -inline void MacroAssembler::sll_ptr( Register s1, int imm6a, Register d ) { -#ifdef _LP64 - Assembler::sllx(s1, imm6a, d); -#else - Assembler::sll( s1, imm6a, d); -#endif -} - -inline void MacroAssembler::srl_ptr( Register s1, Register s2, Register d ) { -#ifdef _LP64 - Assembler::srlx(s1, s2, d); -#else - Assembler::srl( s1, s2, d); -#endif -} - -inline void MacroAssembler::srl_ptr( Register s1, int imm6a, Register d ) { -#ifdef _LP64 - Assembler::srlx(s1, imm6a, d); -#else - Assembler::srl( s1, imm6a, d); -#endif -} - -inline void MacroAssembler::sll_ptr( Register s1, RegisterOrConstant s2, Register d ) { - if (s2.is_register()) sll_ptr(s1, s2.as_register(), d); - else sll_ptr(s1, s2.as_constant(), d); -} - -// Use the right branch for the platform - -inline void MacroAssembler::br( Condition c, bool a, Predict p, address d, relocInfo::relocType rt ) { - if (VM_Version::v9_instructions_work()) - Assembler::bp(c, a, icc, p, d, rt); - else - Assembler::br(c, a, d, rt); -} - -inline void MacroAssembler::br( Condition c, bool a, Predict p, Label& L ) { - br(c, a, p, target(L)); -} - - -// Branch that tests either xcc or icc depending on the -// architecture compiled (LP64 or not) -inline void MacroAssembler::brx( Condition c, bool a, Predict p, address d, relocInfo::relocType rt ) { -#ifdef _LP64 - Assembler::bp(c, a, xcc, p, d, rt); -#else - MacroAssembler::br(c, a, p, d, rt); -#endif -} - -inline void MacroAssembler::brx( Condition c, bool a, Predict p, Label& L ) { - brx(c, a, p, target(L)); -} - -inline void MacroAssembler::ba( Label& L ) { - br(always, false, pt, L); -} - -// Warning: V9 only functions -inline void MacroAssembler::bp( Condition c, bool a, CC cc, Predict p, address d, relocInfo::relocType rt ) { - Assembler::bp(c, a, cc, p, d, rt); -} - -inline void MacroAssembler::bp( Condition c, bool a, CC cc, Predict p, Label& L ) { - Assembler::bp(c, a, cc, p, L); -} - -inline void MacroAssembler::fb( Condition c, bool a, Predict p, address d, relocInfo::relocType rt ) { - if (VM_Version::v9_instructions_work()) - fbp(c, a, fcc0, p, d, rt); - else - Assembler::fb(c, a, d, rt); -} - -inline void MacroAssembler::fb( Condition c, bool a, Predict p, Label& L ) { - fb(c, a, p, target(L)); -} - -inline void MacroAssembler::fbp( Condition c, bool a, CC cc, Predict p, address d, relocInfo::relocType rt ) { - Assembler::fbp(c, a, cc, p, d, rt); -} - -inline void MacroAssembler::fbp( Condition c, bool a, CC cc, Predict p, Label& L ) { - Assembler::fbp(c, a, cc, p, L); -} - -inline void MacroAssembler::jmp( Register s1, Register s2 ) { jmpl( s1, s2, G0 ); } -inline void MacroAssembler::jmp( Register s1, int simm13a, RelocationHolder const& rspec ) { jmpl( s1, simm13a, G0, rspec); } - -inline bool MacroAssembler::is_far_target(address d) { - if (ForceUnreachable) { - // References outside the code cache should be treated as far - return d < CodeCache::low_bound() || d > CodeCache::high_bound(); - } - return !is_in_wdisp30_range(d, CodeCache::low_bound()) || !is_in_wdisp30_range(d, CodeCache::high_bound()); -} - -// Call with a check to see if we need to deal with the added -// expense of relocation and if we overflow the displacement -// of the quick call instruction. -inline void MacroAssembler::call( address d, relocInfo::relocType rt ) { -#ifdef _LP64 - intptr_t disp; - // NULL is ok because it will be relocated later. - // Must change NULL to a reachable address in order to - // pass asserts here and in wdisp. - if ( d == NULL ) - d = pc(); - - // Is this address within range of the call instruction? - // If not, use the expensive instruction sequence - if (is_far_target(d)) { - relocate(rt); - AddressLiteral dest(d); - jumpl_to(dest, O7, O7); - } else { - Assembler::call(d, rt); - } -#else - Assembler::call( d, rt ); -#endif -} - -inline void MacroAssembler::call( Label& L, relocInfo::relocType rt ) { - MacroAssembler::call( target(L), rt); -} - - - -inline void MacroAssembler::callr( Register s1, Register s2 ) { jmpl( s1, s2, O7 ); } -inline void MacroAssembler::callr( Register s1, int simm13a, RelocationHolder const& rspec ) { jmpl( s1, simm13a, O7, rspec); } - -// prefetch instruction -inline void MacroAssembler::iprefetch( address d, relocInfo::relocType rt ) { - if (VM_Version::v9_instructions_work()) - Assembler::bp( never, true, xcc, pt, d, rt ); -} -inline void MacroAssembler::iprefetch( Label& L) { iprefetch( target(L) ); } - - -// clobbers o7 on V8!! -// returns delta from gotten pc to addr after -inline int MacroAssembler::get_pc( Register d ) { - int x = offset(); - if (VM_Version::v9_instructions_work()) - rdpc(d); - else { - Label lbl; - Assembler::call(lbl, relocInfo::none); // No relocation as this is call to pc+0x8 - if (d == O7) delayed()->nop(); - else delayed()->mov(O7, d); - bind(lbl); - } - return offset() - x; -} - - -// Note: All MacroAssembler::set_foo functions are defined out-of-line. - - -// Loads the current PC of the following instruction as an immediate value in -// 2 instructions. All PCs in the CodeCache are within 2 Gig of each other. -inline intptr_t MacroAssembler::load_pc_address( Register reg, int bytes_to_skip ) { - intptr_t thepc = (intptr_t)pc() + 2*BytesPerInstWord + bytes_to_skip; -#ifdef _LP64 - Unimplemented(); -#else - Assembler::sethi( thepc & ~0x3ff, reg, internal_word_Relocation::spec((address)thepc)); - Assembler::add(reg,thepc & 0x3ff, reg, internal_word_Relocation::spec((address)thepc)); -#endif - return thepc; -} - - -inline void MacroAssembler::load_contents(const AddressLiteral& addrlit, Register d, int offset) { - assert_not_delayed(); - if (ForceUnreachable) { - patchable_sethi(addrlit, d); - } else { - sethi(addrlit, d); - } - ld(d, addrlit.low10() + offset, d); -} - - -inline void MacroAssembler::load_bool_contents(const AddressLiteral& addrlit, Register d, int offset) { - assert_not_delayed(); - if (ForceUnreachable) { - patchable_sethi(addrlit, d); - } else { - sethi(addrlit, d); - } - ldub(d, addrlit.low10() + offset, d); -} - - -inline void MacroAssembler::load_ptr_contents(const AddressLiteral& addrlit, Register d, int offset) { - assert_not_delayed(); - if (ForceUnreachable) { - patchable_sethi(addrlit, d); - } else { - sethi(addrlit, d); - } - ld_ptr(d, addrlit.low10() + offset, d); -} - - -inline void MacroAssembler::store_contents(Register s, const AddressLiteral& addrlit, Register temp, int offset) { - assert_not_delayed(); - if (ForceUnreachable) { - patchable_sethi(addrlit, temp); - } else { - sethi(addrlit, temp); - } - st(s, temp, addrlit.low10() + offset); -} - - -inline void MacroAssembler::store_ptr_contents(Register s, const AddressLiteral& addrlit, Register temp, int offset) { - assert_not_delayed(); - if (ForceUnreachable) { - patchable_sethi(addrlit, temp); - } else { - sethi(addrlit, temp); - } - st_ptr(s, temp, addrlit.low10() + offset); -} - - -// This code sequence is relocatable to any address, even on LP64. -inline void MacroAssembler::jumpl_to(const AddressLiteral& addrlit, Register temp, Register d, int offset) { - assert_not_delayed(); - // Force fixed length sethi because NativeJump and NativeFarCall don't handle - // variable length instruction streams. - patchable_sethi(addrlit, temp); - jmpl(temp, addrlit.low10() + offset, d); -} - - -inline void MacroAssembler::jump_to(const AddressLiteral& addrlit, Register temp, int offset) { - jumpl_to(addrlit, temp, G0, offset); -} - - -inline void MacroAssembler::jump_indirect_to(Address& a, Register temp, - int ld_offset, int jmp_offset) { - assert_not_delayed(); - //sethi(al); // sethi is caller responsibility for this one - ld_ptr(a, temp, ld_offset); - jmp(temp, jmp_offset); -} - - -inline void MacroAssembler::set_metadata(Metadata* obj, Register d) { - set_metadata(allocate_metadata_address(obj), d); -} - -inline void MacroAssembler::set_metadata_constant(Metadata* obj, Register d) { - set_metadata(constant_metadata_address(obj), d); -} - -inline void MacroAssembler::set_metadata(const AddressLiteral& obj_addr, Register d) { - assert(obj_addr.rspec().type() == relocInfo::metadata_type, "must be a metadata reloc"); - set(obj_addr, d); -} - -inline void MacroAssembler::set_oop(jobject obj, Register d) { - set_oop(allocate_oop_address(obj), d); -} - - -inline void MacroAssembler::set_oop_constant(jobject obj, Register d) { - set_oop(constant_oop_address(obj), d); -} - - -inline void MacroAssembler::set_oop(const AddressLiteral& obj_addr, Register d) { - assert(obj_addr.rspec().type() == relocInfo::oop_type, "must be an oop reloc"); - set(obj_addr, d); -} - - -inline void MacroAssembler::load_argument( Argument& a, Register d ) { - if (a.is_register()) - mov(a.as_register(), d); - else - ld (a.as_address(), d); -} - -inline void MacroAssembler::store_argument( Register s, Argument& a ) { - if (a.is_register()) - mov(s, a.as_register()); - else - st_ptr (s, a.as_address()); // ABI says everything is right justified. -} - -inline void MacroAssembler::store_ptr_argument( Register s, Argument& a ) { - if (a.is_register()) - mov(s, a.as_register()); - else - st_ptr (s, a.as_address()); -} - - -#ifdef _LP64 -inline void MacroAssembler::store_float_argument( FloatRegister s, Argument& a ) { - if (a.is_float_register()) -// V9 ABI has F1, F3, F5 are used to pass instead of O0, O1, O2 - fmov(FloatRegisterImpl::S, s, a.as_float_register() ); - else - // Floats are stored in the high half of the stack entry - // The low half is undefined per the ABI. - stf(FloatRegisterImpl::S, s, a.as_address(), sizeof(jfloat)); -} - -inline void MacroAssembler::store_double_argument( FloatRegister s, Argument& a ) { - if (a.is_float_register()) -// V9 ABI has D0, D2, D4 are used to pass instead of O0, O1, O2 - fmov(FloatRegisterImpl::D, s, a.as_double_register() ); - else - stf(FloatRegisterImpl::D, s, a.as_address()); -} - -inline void MacroAssembler::store_long_argument( Register s, Argument& a ) { - if (a.is_register()) - mov(s, a.as_register()); - else - stx(s, a.as_address()); -} -#endif - -inline void MacroAssembler::clrb( Register s1, Register s2) { stb( G0, s1, s2 ); } -inline void MacroAssembler::clrh( Register s1, Register s2) { sth( G0, s1, s2 ); } -inline void MacroAssembler::clr( Register s1, Register s2) { stw( G0, s1, s2 ); } -inline void MacroAssembler::clrx( Register s1, Register s2) { stx( G0, s1, s2 ); } - -inline void MacroAssembler::clrb( Register s1, int simm13a) { stb( G0, s1, simm13a); } -inline void MacroAssembler::clrh( Register s1, int simm13a) { sth( G0, s1, simm13a); } -inline void MacroAssembler::clr( Register s1, int simm13a) { stw( G0, s1, simm13a); } -inline void MacroAssembler::clrx( Register s1, int simm13a) { stx( G0, s1, simm13a); } - -// returns if membar generates anything, obviously this code should mirror -// membar below. -inline bool MacroAssembler::membar_has_effect( Membar_mask_bits const7a ) { - if( !os::is_MP() ) return false; // Not needed on single CPU - if( VM_Version::v9_instructions_work() ) { - const Membar_mask_bits effective_mask = - Membar_mask_bits(const7a & ~(LoadLoad | LoadStore | StoreStore)); - return (effective_mask != 0); - } else { - return true; - } -} - -inline void MacroAssembler::membar( Membar_mask_bits const7a ) { - // Uniprocessors do not need memory barriers - if (!os::is_MP()) return; - // Weakened for current Sparcs and TSO. See the v9 manual, sections 8.4.3, - // 8.4.4.3, a.31 and a.50. - if( VM_Version::v9_instructions_work() ) { - // Under TSO, setting bit 3, 2, or 0 is redundant, so the only value - // of the mmask subfield of const7a that does anything that isn't done - // implicitly is StoreLoad. - const Membar_mask_bits effective_mask = - Membar_mask_bits(const7a & ~(LoadLoad | LoadStore | StoreStore)); - if ( effective_mask != 0 ) { - Assembler::membar( effective_mask ); - } - } else { - // stbar is the closest there is on v8. Equivalent to membar(StoreStore). We - // do not issue the stbar because to my knowledge all v8 machines implement TSO, - // which guarantees that all stores behave as if an stbar were issued just after - // each one of them. On these machines, stbar ought to be a nop. There doesn't - // appear to be an equivalent of membar(StoreLoad) on v8: TSO doesn't require it, - // it can't be specified by stbar, nor have I come up with a way to simulate it. - // - // Addendum. Dave says that ldstub guarantees a write buffer flush to coherent - // space. Put one here to be on the safe side. - Assembler::ldstub(SP, 0, G0); - } -} - #endif // CPU_SPARC_VM_ASSEMBLER_SPARC_INLINE_HPP diff --git a/hotspot/src/cpu/sparc/vm/codeBuffer_sparc.hpp b/hotspot/src/cpu/sparc/vm/codeBuffer_sparc.hpp index f1a371acf1e..d3c0744d56c 100644 --- a/hotspot/src/cpu/sparc/vm/codeBuffer_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/codeBuffer_sparc.hpp @@ -31,9 +31,4 @@ private: public: void flush_bundle(bool start_new_bundle) {} - // Heuristic for pre-packing the pt/pn bit of a predicted branch. - bool is_backward_branch(Label& L) { - return L.is_bound() && insts_end() <= locator_address(L.loc()); - } - #endif // CPU_SPARC_VM_CODEBUFFER_SPARC_HPP diff --git a/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp b/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp index eacb4d3fd66..7031597b6cf 100644 --- a/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp @@ -582,7 +582,9 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) { // the following temporary registers are used during frame creation const Register Gtmp1 = G3_scratch ; const Register Gtmp2 = G1_scratch; - const Address size_of_parameters(G5_method, 0, in_bytes(Method::size_of_parameters_offset())); + const Register RconstMethod = Gtmp1; + const Address constMethod(G5_method, 0, in_bytes(Method::const_offset())); + const Address size_of_parameters(RconstMethod, 0, in_bytes(ConstMethod::size_of_parameters_offset())); bool inc_counter = UseCompiler || CountCompiledCalls; @@ -618,6 +620,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) { } #endif // ASSERT + __ ld_ptr(constMethod, RconstMethod); __ lduh(size_of_parameters, Gtmp1); __ sll(Gtmp1, LogBytesPerWord, Gtmp2); // parameter size in bytes __ add(Gargs, Gtmp2, Gargs); // points to first local + BytesPerWord @@ -1047,8 +1050,6 @@ void CppInterpreterGenerator::generate_compute_interpreter_state(const Register const Register Gtmp = G3_scratch; const Address constMethod (G5_method, 0, in_bytes(Method::const_offset())); const Address access_flags (G5_method, 0, in_bytes(Method::access_flags_offset())); - const Address size_of_parameters(G5_method, 0, in_bytes(Method::size_of_parameters_offset())); - const Address size_of_locals (G5_method, 0, in_bytes(Method::size_of_locals_offset())); // slop factor is two extra slots on the expression stack so that // we always have room to store a result when returning from a call without parameters @@ -1066,6 +1067,9 @@ void CppInterpreterGenerator::generate_compute_interpreter_state(const Register // Now compute new frame size if (native) { + const Register RconstMethod = Gtmp; + const Address size_of_parameters(RconstMethod, 0, in_bytes(ConstMethod::size_of_parameters_offset())); + __ ld_ptr(constMethod, RconstMethod); __ lduh( size_of_parameters, Gtmp ); __ calc_mem_param_words(Gtmp, Gtmp); // space for native call parameters passed on the stack in words } else { @@ -1236,9 +1240,13 @@ void CppInterpreterGenerator::generate_compute_interpreter_state(const Register } if (init_value != noreg) { Label clear_loop; + const Register RconstMethod = O1; + const Address size_of_parameters(RconstMethod, 0, in_bytes(ConstMethod::size_of_parameters_offset())); + const Address size_of_locals (RconstMethod, 0, in_bytes(ConstMethod::size_of_locals_offset())); // NOTE: If you change the frame layout, this code will need to // be updated! + __ ld_ptr( constMethod, RconstMethod ); __ lduh( size_of_locals, O2 ); __ lduh( size_of_parameters, O1 ); __ sll( O2, LogBytesPerWord, O2); @@ -1483,13 +1491,16 @@ void CppInterpreterGenerator::adjust_callers_stack(Register args) { // // assert_different_registers(state, prev_state); const Register Gtmp = G3_scratch; + const RconstMethod = G3_scratch; const Register tmp = O2; - const Address size_of_parameters(G5_method, 0, in_bytes(Method::size_of_parameters_offset())); - const Address size_of_locals (G5_method, 0, in_bytes(Method::size_of_locals_offset())); + const Address constMethod(G5_method, 0, in_bytes(Method::const_offset())); + const Address size_of_parameters(RconstMethod, 0, in_bytes(ConstMethod::size_of_parameters_offset())); + const Address size_of_locals (RconstMethod, 0, in_bytes(ConstMethod::size_of_locals_offset())); + __ ld_ptr(constMethod, RconstMethod); __ lduh(size_of_parameters, tmp); - __ sll(tmp, LogBytesPerWord, Gtmp); // parameter size in bytes - __ add(args, Gtmp, Gargs); // points to first local + BytesPerWord + __ sll(tmp, LogBytesPerWord, Gargs); // parameter size in bytes + __ add(args, Gargs, Gargs); // points to first local + BytesPerWord // NEW __ add(Gargs, -wordSize, Gargs); // points to first local[0] // determine extra space for non-argument locals & adjust caller's SP @@ -1541,8 +1552,6 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) { const Address constMethod (G5_method, 0, in_bytes(Method::const_offset())); const Address access_flags (G5_method, 0, in_bytes(Method::access_flags_offset())); - const Address size_of_parameters(G5_method, 0, in_bytes(Method::size_of_parameters_offset())); - const Address size_of_locals (G5_method, 0, in_bytes(Method::size_of_locals_offset())); address entry_point = __ pc(); __ mov(G0, prevState); // no current activation @@ -1750,7 +1759,9 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) { __ ld_ptr(STATE(_result._to_call._callee), L4_scratch); // called method __ ld_ptr(STATE(_stack), L1_scratch); // get top of java expr stack - __ lduh(L4_scratch, in_bytes(Method::size_of_parameters_offset()), L2_scratch); // get parameter size + // get parameter size + __ ld_ptr(L4_scratch, in_bytes(Method::const_offset()), L2_scratch); + __ lduh(L2_scratch, in_bytes(ConstMethod::size_of_parameters_offset()), L2_scratch); __ sll(L2_scratch, LogBytesPerWord, L2_scratch ); // parameter size in bytes __ add(L1_scratch, L2_scratch, L1_scratch); // stack destination for result __ ld(L4_scratch, in_bytes(Method::result_index_offset()), L3_scratch); // called method result type index diff --git a/hotspot/src/cpu/sparc/vm/frame_sparc.hpp b/hotspot/src/cpu/sparc/vm/frame_sparc.hpp index af2287d8a93..25bfea2a2c3 100644 --- a/hotspot/src/cpu/sparc/vm/frame_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/frame_sparc.hpp @@ -204,25 +204,6 @@ intptr_t* out_register_addr(Register reg) const { return younger_sp_addr_at(reg->after_save()->sp_offset_in_saved_window()); } - intptr_t* memory_param_addr(int param_ix, bool is_in) const { - int offset = callee_register_argument_save_area_sp_offset + param_ix; - if (is_in) - return fp_addr_at(offset); - else - return sp_addr_at(offset); - } - intptr_t* param_addr(int param_ix, bool is_in) const { - if (param_ix >= callee_register_argument_save_area_words) - return memory_param_addr(param_ix, is_in); - else if (is_in) - return register_addr(Argument(param_ix, true).as_register()); - else { - // the registers are stored in the next younger frame - // %%% is this really necessary? - ShouldNotReachHere(); - return NULL; - } - } // Interpreter frames @@ -269,12 +250,8 @@ #ifndef CC_INTERP // where Lmonitors is saved: - BasicObjectLock** interpreter_frame_monitors_addr() const { - return (BasicObjectLock**) sp_addr_at(Lmonitors->sp_offset_in_saved_window()); - } - intptr_t** interpreter_frame_esp_addr() const { - return (intptr_t**)sp_addr_at(Lesp->sp_offset_in_saved_window()); - } + inline BasicObjectLock** interpreter_frame_monitors_addr() const; + inline intptr_t** interpreter_frame_esp_addr() const; inline void interpreter_frame_set_tos_address(intptr_t* x); diff --git a/hotspot/src/cpu/sparc/vm/frame_sparc.inline.hpp b/hotspot/src/cpu/sparc/vm/frame_sparc.inline.hpp index 33b1b7f9598..71655f6d760 100644 --- a/hotspot/src/cpu/sparc/vm/frame_sparc.inline.hpp +++ b/hotspot/src/cpu/sparc/vm/frame_sparc.inline.hpp @@ -25,6 +25,8 @@ #ifndef CPU_SPARC_VM_FRAME_SPARC_INLINE_HPP #define CPU_SPARC_VM_FRAME_SPARC_INLINE_HPP +#include "asm/macroAssembler.hpp" + // Inline functions for SPARC frames: // Constructors @@ -185,6 +187,13 @@ inline intptr_t* frame::interpreter_frame_tos_address() const { return *interpreter_frame_esp_addr() + 1; } +inline BasicObjectLock** frame::interpreter_frame_monitors_addr() const { + return (BasicObjectLock**) sp_addr_at(Lmonitors->sp_offset_in_saved_window()); +} +inline intptr_t** frame::interpreter_frame_esp_addr() const { + return (intptr_t**)sp_addr_at(Lesp->sp_offset_in_saved_window()); +} + inline void frame::interpreter_frame_set_tos_address( intptr_t* x ) { *interpreter_frame_esp_addr() = x - 1; } diff --git a/hotspot/src/cpu/sparc/vm/icBuffer_sparc.cpp b/hotspot/src/cpu/sparc/vm/icBuffer_sparc.cpp index b72d4c76030..ee2b0380345 100644 --- a/hotspot/src/cpu/sparc/vm/icBuffer_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/icBuffer_sparc.cpp @@ -23,8 +23,7 @@ */ #include "precompiled.hpp" -#include "asm/assembler.hpp" -#include "assembler_sparc.inline.hpp" +#include "asm/macroAssembler.inline.hpp" #include "code/icBuffer.hpp" #include "gc_interface/collectedHeap.inline.hpp" #include "interpreter/bytecodes.hpp" diff --git a/hotspot/src/cpu/sparc/vm/icache_sparc.cpp b/hotspot/src/cpu/sparc/vm/icache_sparc.cpp index af7a4c09b01..01914de00b4 100644 --- a/hotspot/src/cpu/sparc/vm/icache_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/icache_sparc.cpp @@ -23,7 +23,7 @@ */ #include "precompiled.hpp" -#include "assembler_sparc.inline.hpp" +#include "asm/macroAssembler.inline.hpp" #include "runtime/icache.hpp" #define __ _masm-> diff --git a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp index d06cccd8b5a..bf84848aa61 100644 --- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp @@ -25,7 +25,7 @@ #ifndef CPU_SPARC_VM_INTERP_MASM_SPARC_HPP #define CPU_SPARC_VM_INTERP_MASM_SPARC_HPP -#include "assembler_sparc.inline.hpp" +#include "asm/macroAssembler.inline.hpp" #include "interpreter/invocationCounter.hpp" // This file specializes the assember with interpreter-specific macros diff --git a/hotspot/src/cpu/sparc/vm/interpreter_sparc.cpp b/hotspot/src/cpu/sparc/vm/interpreter_sparc.cpp index 42099468eda..132c5292a06 100644 --- a/hotspot/src/cpu/sparc/vm/interpreter_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/interpreter_sparc.cpp @@ -23,7 +23,7 @@ */ #include "precompiled.hpp" -#include "asm/assembler.hpp" +#include "asm/macroAssembler.hpp" #include "interpreter/bytecodeHistogram.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/interpreterGenerator.hpp" diff --git a/hotspot/src/cpu/sparc/vm/jniFastGetField_sparc.cpp b/hotspot/src/cpu/sparc/vm/jniFastGetField_sparc.cpp index e31fa87b3aa..6d3f05a2aab 100644 --- a/hotspot/src/cpu/sparc/vm/jniFastGetField_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/jniFastGetField_sparc.cpp @@ -23,7 +23,7 @@ */ #include "precompiled.hpp" -#include "assembler_sparc.inline.hpp" +#include "asm/macroAssembler.inline.hpp" #include "memory/resourceArea.hpp" #include "prims/jniFastGetField.hpp" #include "prims/jvm_misc.hpp" diff --git a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp new file mode 100644 index 00000000000..2801a35a10d --- /dev/null +++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp @@ -0,0 +1,4610 @@ +/* + * Copyright (c) 1997, 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. + * + */ + +#include "precompiled.hpp" +#include "asm/assembler.inline.hpp" +#include "compiler/disassembler.hpp" +#include "gc_interface/collectedHeap.inline.hpp" +#include "interpreter/interpreter.hpp" +#include "memory/cardTableModRefBS.hpp" +#include "memory/resourceArea.hpp" +#include "prims/methodHandles.hpp" +#include "runtime/biasedLocking.hpp" +#include "runtime/interfaceSupport.hpp" +#include "runtime/objectMonitor.hpp" +#include "runtime/os.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" +#ifndef SERIALGC +#include "gc_implementation/g1/g1CollectedHeap.inline.hpp" +#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" +#include "gc_implementation/g1/heapRegion.hpp" +#endif + +#ifdef PRODUCT +#define BLOCK_COMMENT(str) /* nothing */ +#define STOP(error) stop(error) +#else +#define BLOCK_COMMENT(str) block_comment(str) +#define STOP(error) block_comment(error); stop(error) +#endif + +// Convert the raw encoding form into the form expected by the +// constructor for Address. +Address Address::make_raw(int base, int index, int scale, int disp, relocInfo::relocType disp_reloc) { + assert(scale == 0, "not supported"); + RelocationHolder rspec; + if (disp_reloc != relocInfo::none) { + rspec = Relocation::spec_simple(disp_reloc); + } + + Register rindex = as_Register(index); + if (rindex != G0) { + Address madr(as_Register(base), rindex); + madr._rspec = rspec; + return madr; + } else { + Address madr(as_Register(base), disp); + madr._rspec = rspec; + return madr; + } +} + +Address Argument::address_in_frame() const { + // Warning: In LP64 mode disp will occupy more than 10 bits, but + // op codes such as ld or ldx, only access disp() to get + // their simm13 argument. + int disp = ((_number - Argument::n_register_parameters + frame::memory_parameter_word_sp_offset) * BytesPerWord) + STACK_BIAS; + if (is_in()) + return Address(FP, disp); // In argument. + else + return Address(SP, disp); // Out argument. +} + +static const char* argumentNames[][2] = { + {"A0","P0"}, {"A1","P1"}, {"A2","P2"}, {"A3","P3"}, {"A4","P4"}, + {"A5","P5"}, {"A6","P6"}, {"A7","P7"}, {"A8","P8"}, {"A9","P9"}, + {"A(n>9)","P(n>9)"} +}; + +const char* Argument::name() const { + int nofArgs = sizeof argumentNames / sizeof argumentNames[0]; + int num = number(); + if (num >= nofArgs) num = nofArgs - 1; + return argumentNames[num][is_in() ? 1 : 0]; +} + +#ifdef ASSERT +// On RISC, there's no benefit to verifying instruction boundaries. +bool AbstractAssembler::pd_check_instruction_mark() { return false; } +#endif + + +void MacroAssembler::print_instruction(int inst) { + const char* s; + switch (inv_op(inst)) { + default: s = "????"; break; + case call_op: s = "call"; break; + case branch_op: + switch (inv_op2(inst)) { + case fb_op2: s = "fb"; break; + case fbp_op2: s = "fbp"; break; + case br_op2: s = "br"; break; + case bp_op2: s = "bp"; break; + case cb_op2: s = "cb"; break; + case bpr_op2: { + if (is_cbcond(inst)) { + s = is_cxb(inst) ? "cxb" : "cwb"; + } else { + s = "bpr"; + } + break; + } + default: s = "????"; break; + } + } + ::tty->print("%s", s); +} + + +// Patch instruction inst at offset inst_pos to refer to dest_pos +// and return the resulting instruction. +// We should have pcs, not offsets, but since all is relative, it will work out +// OK. +int MacroAssembler::patched_branch(int dest_pos, int inst, int inst_pos) { + int m; // mask for displacement field + int v; // new value for displacement field + const int word_aligned_ones = -4; + switch (inv_op(inst)) { + default: ShouldNotReachHere(); + case call_op: m = wdisp(word_aligned_ones, 0, 30); v = wdisp(dest_pos, inst_pos, 30); break; + case branch_op: + switch (inv_op2(inst)) { + case fbp_op2: m = wdisp( word_aligned_ones, 0, 19); v = wdisp( dest_pos, inst_pos, 19); break; + case bp_op2: m = wdisp( word_aligned_ones, 0, 19); v = wdisp( dest_pos, inst_pos, 19); break; + case fb_op2: m = wdisp( word_aligned_ones, 0, 22); v = wdisp( dest_pos, inst_pos, 22); break; + case br_op2: m = wdisp( word_aligned_ones, 0, 22); v = wdisp( dest_pos, inst_pos, 22); break; + case cb_op2: m = wdisp( word_aligned_ones, 0, 22); v = wdisp( dest_pos, inst_pos, 22); break; + case bpr_op2: { + if (is_cbcond(inst)) { + m = wdisp10(word_aligned_ones, 0); + v = wdisp10(dest_pos, inst_pos); + } else { + m = wdisp16(word_aligned_ones, 0); + v = wdisp16(dest_pos, inst_pos); + } + break; + } + default: ShouldNotReachHere(); + } + } + return inst & ~m | v; +} + +// Return the offset of the branch destionation of instruction inst +// at offset pos. +// Should have pcs, but since all is relative, it works out. +int MacroAssembler::branch_destination(int inst, int pos) { + int r; + switch (inv_op(inst)) { + default: ShouldNotReachHere(); + case call_op: r = inv_wdisp(inst, pos, 30); break; + case branch_op: + switch (inv_op2(inst)) { + case fbp_op2: r = inv_wdisp( inst, pos, 19); break; + case bp_op2: r = inv_wdisp( inst, pos, 19); break; + case fb_op2: r = inv_wdisp( inst, pos, 22); break; + case br_op2: r = inv_wdisp( inst, pos, 22); break; + case cb_op2: r = inv_wdisp( inst, pos, 22); break; + case bpr_op2: { + if (is_cbcond(inst)) { + r = inv_wdisp10(inst, pos); + } else { + r = inv_wdisp16(inst, pos); + } + break; + } + default: ShouldNotReachHere(); + } + } + return r; +} + +void MacroAssembler::null_check(Register reg, int offset) { + if (needs_explicit_null_check((intptr_t)offset)) { + // provoke OS NULL exception if reg = NULL by + // accessing M[reg] w/o changing any registers + ld_ptr(reg, 0, G0); + } + else { + // nothing to do, (later) access of M[reg + offset] + // will provoke OS NULL exception if reg = NULL + } +} + +// Ring buffer jumps + +#ifndef PRODUCT +void MacroAssembler::ret( bool trace ) { if (trace) { + mov(I7, O7); // traceable register + JMP(O7, 2 * BytesPerInstWord); + } else { + jmpl( I7, 2 * BytesPerInstWord, G0 ); + } + } + +void MacroAssembler::retl( bool trace ) { if (trace) JMP(O7, 2 * BytesPerInstWord); + else jmpl( O7, 2 * BytesPerInstWord, G0 ); } +#endif /* PRODUCT */ + + +void MacroAssembler::jmp2(Register r1, Register r2, const char* file, int line ) { + assert_not_delayed(); + // This can only be traceable if r1 & r2 are visible after a window save + if (TraceJumps) { +#ifndef PRODUCT + save_frame(0); + verify_thread(); + ld(G2_thread, in_bytes(JavaThread::jmp_ring_index_offset()), O0); + add(G2_thread, in_bytes(JavaThread::jmp_ring_offset()), O1); + sll(O0, exact_log2(4*sizeof(intptr_t)), O2); + add(O2, O1, O1); + + add(r1->after_save(), r2->after_save(), O2); + set((intptr_t)file, O3); + set(line, O4); + Label L; + // get nearby pc, store jmp target + call(L, relocInfo::none); // No relocation for call to pc+0x8 + delayed()->st(O2, O1, 0); + bind(L); + + // store nearby pc + st(O7, O1, sizeof(intptr_t)); + // store file + st(O3, O1, 2*sizeof(intptr_t)); + // store line + st(O4, O1, 3*sizeof(intptr_t)); + add(O0, 1, O0); + and3(O0, JavaThread::jump_ring_buffer_size - 1, O0); + st(O0, G2_thread, in_bytes(JavaThread::jmp_ring_index_offset())); + restore(); +#endif /* PRODUCT */ + } + jmpl(r1, r2, G0); +} +void MacroAssembler::jmp(Register r1, int offset, const char* file, int line ) { + assert_not_delayed(); + // This can only be traceable if r1 is visible after a window save + if (TraceJumps) { +#ifndef PRODUCT + save_frame(0); + verify_thread(); + ld(G2_thread, in_bytes(JavaThread::jmp_ring_index_offset()), O0); + add(G2_thread, in_bytes(JavaThread::jmp_ring_offset()), O1); + sll(O0, exact_log2(4*sizeof(intptr_t)), O2); + add(O2, O1, O1); + + add(r1->after_save(), offset, O2); + set((intptr_t)file, O3); + set(line, O4); + Label L; + // get nearby pc, store jmp target + call(L, relocInfo::none); // No relocation for call to pc+0x8 + delayed()->st(O2, O1, 0); + bind(L); + + // store nearby pc + st(O7, O1, sizeof(intptr_t)); + // store file + st(O3, O1, 2*sizeof(intptr_t)); + // store line + st(O4, O1, 3*sizeof(intptr_t)); + add(O0, 1, O0); + and3(O0, JavaThread::jump_ring_buffer_size - 1, O0); + st(O0, G2_thread, in_bytes(JavaThread::jmp_ring_index_offset())); + restore(); +#endif /* PRODUCT */ + } + jmp(r1, offset); +} + +// This code sequence is relocatable to any address, even on LP64. +void MacroAssembler::jumpl(const AddressLiteral& addrlit, Register temp, Register d, int offset, const char* file, int line) { + assert_not_delayed(); + // Force fixed length sethi because NativeJump and NativeFarCall don't handle + // variable length instruction streams. + patchable_sethi(addrlit, temp); + Address a(temp, addrlit.low10() + offset); // Add the offset to the displacement. + if (TraceJumps) { +#ifndef PRODUCT + // Must do the add here so relocation can find the remainder of the + // value to be relocated. + add(a.base(), a.disp(), a.base(), addrlit.rspec(offset)); + save_frame(0); + verify_thread(); + ld(G2_thread, in_bytes(JavaThread::jmp_ring_index_offset()), O0); + add(G2_thread, in_bytes(JavaThread::jmp_ring_offset()), O1); + sll(O0, exact_log2(4*sizeof(intptr_t)), O2); + add(O2, O1, O1); + + set((intptr_t)file, O3); + set(line, O4); + Label L; + + // get nearby pc, store jmp target + call(L, relocInfo::none); // No relocation for call to pc+0x8 + delayed()->st(a.base()->after_save(), O1, 0); + bind(L); + + // store nearby pc + st(O7, O1, sizeof(intptr_t)); + // store file + st(O3, O1, 2*sizeof(intptr_t)); + // store line + st(O4, O1, 3*sizeof(intptr_t)); + add(O0, 1, O0); + and3(O0, JavaThread::jump_ring_buffer_size - 1, O0); + st(O0, G2_thread, in_bytes(JavaThread::jmp_ring_index_offset())); + restore(); + jmpl(a.base(), G0, d); +#else + jmpl(a.base(), a.disp(), d); +#endif /* PRODUCT */ + } else { + jmpl(a.base(), a.disp(), d); + } +} + +void MacroAssembler::jump(const AddressLiteral& addrlit, Register temp, int offset, const char* file, int line) { + jumpl(addrlit, temp, G0, offset, file, line); +} + + +// Conditional breakpoint (for assertion checks in assembly code) +void MacroAssembler::breakpoint_trap(Condition c, CC cc) { + trap(c, cc, G0, ST_RESERVED_FOR_USER_0); +} + +// We want to use ST_BREAKPOINT here, but the debugger is confused by it. +void MacroAssembler::breakpoint_trap() { + trap(ST_RESERVED_FOR_USER_0); +} + +// flush windows (except current) using flushw instruction if avail. +void MacroAssembler::flush_windows() { + if (VM_Version::v9_instructions_work()) flushw(); + else flush_windows_trap(); +} + +// Write serialization page so VM thread can do a pseudo remote membar +// We use the current thread pointer to calculate a thread specific +// offset to write to within the page. This minimizes bus traffic +// due to cache line collision. +void MacroAssembler::serialize_memory(Register thread, Register tmp1, Register tmp2) { + srl(thread, os::get_serialize_page_shift_count(), tmp2); + if (Assembler::is_simm13(os::vm_page_size())) { + and3(tmp2, (os::vm_page_size() - sizeof(int)), tmp2); + } + else { + set((os::vm_page_size() - sizeof(int)), tmp1); + and3(tmp2, tmp1, tmp2); + } + set(os::get_memory_serialize_page(), tmp1); + st(G0, tmp1, tmp2); +} + + + +void MacroAssembler::enter() { + Unimplemented(); +} + +void MacroAssembler::leave() { + Unimplemented(); +} + +void MacroAssembler::mult(Register s1, Register s2, Register d) { + if(VM_Version::v9_instructions_work()) { + mulx (s1, s2, d); + } else { + smul (s1, s2, d); + } +} + +void MacroAssembler::mult(Register s1, int simm13a, Register d) { + if(VM_Version::v9_instructions_work()) { + mulx (s1, simm13a, d); + } else { + smul (s1, simm13a, d); + } +} + + +#ifdef ASSERT +void MacroAssembler::read_ccr_v8_assert(Register ccr_save) { + const Register s1 = G3_scratch; + const Register s2 = G4_scratch; + Label get_psr_test; + // Get the condition codes the V8 way. + read_ccr_trap(s1); + mov(ccr_save, s2); + // This is a test of V8 which has icc but not xcc + // so mask off the xcc bits + and3(s2, 0xf, s2); + // Compare condition codes from the V8 and V9 ways. + subcc(s2, s1, G0); + br(Assembler::notEqual, true, Assembler::pt, get_psr_test); + delayed()->breakpoint_trap(); + bind(get_psr_test); +} + +void MacroAssembler::write_ccr_v8_assert(Register ccr_save) { + const Register s1 = G3_scratch; + const Register s2 = G4_scratch; + Label set_psr_test; + // Write out the saved condition codes the V8 way + write_ccr_trap(ccr_save, s1, s2); + // Read back the condition codes using the V9 instruction + rdccr(s1); + mov(ccr_save, s2); + // This is a test of V8 which has icc but not xcc + // so mask off the xcc bits + and3(s2, 0xf, s2); + and3(s1, 0xf, s1); + // Compare the V8 way with the V9 way. + subcc(s2, s1, G0); + br(Assembler::notEqual, true, Assembler::pt, set_psr_test); + delayed()->breakpoint_trap(); + bind(set_psr_test); +} +#else +#define read_ccr_v8_assert(x) +#define write_ccr_v8_assert(x) +#endif // ASSERT + +void MacroAssembler::read_ccr(Register ccr_save) { + if (VM_Version::v9_instructions_work()) { + rdccr(ccr_save); + // Test code sequence used on V8. Do not move above rdccr. + read_ccr_v8_assert(ccr_save); + } else { + read_ccr_trap(ccr_save); + } +} + +void MacroAssembler::write_ccr(Register ccr_save) { + if (VM_Version::v9_instructions_work()) { + // Test code sequence used on V8. Do not move below wrccr. + write_ccr_v8_assert(ccr_save); + wrccr(ccr_save); + } else { + const Register temp_reg1 = G3_scratch; + const Register temp_reg2 = G4_scratch; + write_ccr_trap(ccr_save, temp_reg1, temp_reg2); + } +} + + +// Calls to C land + +#ifdef ASSERT +// a hook for debugging +static Thread* reinitialize_thread() { + return ThreadLocalStorage::thread(); +} +#else +#define reinitialize_thread ThreadLocalStorage::thread +#endif + +#ifdef ASSERT +address last_get_thread = NULL; +#endif + +// call this when G2_thread is not known to be valid +void MacroAssembler::get_thread() { + save_frame(0); // to avoid clobbering O0 + mov(G1, L0); // avoid clobbering G1 + mov(G5_method, L1); // avoid clobbering G5 + mov(G3, L2); // avoid clobbering G3 also + mov(G4, L5); // avoid clobbering G4 +#ifdef ASSERT + AddressLiteral last_get_thread_addrlit(&last_get_thread); + set(last_get_thread_addrlit, L3); + inc(L4, get_pc(L4) + 2 * BytesPerInstWord); // skip getpc() code + inc + st_ptr to point L4 at call + st_ptr(L4, L3, 0); +#endif + call(CAST_FROM_FN_PTR(address, reinitialize_thread), relocInfo::runtime_call_type); + delayed()->nop(); + mov(L0, G1); + mov(L1, G5_method); + mov(L2, G3); + mov(L5, G4); + restore(O0, 0, G2_thread); +} + +static Thread* verify_thread_subroutine(Thread* gthread_value) { + Thread* correct_value = ThreadLocalStorage::thread(); + guarantee(gthread_value == correct_value, "G2_thread value must be the thread"); + return correct_value; +} + +void MacroAssembler::verify_thread() { + if (VerifyThread) { + // NOTE: this chops off the heads of the 64-bit O registers. +#ifdef CC_INTERP + save_frame(0); +#else + // make sure G2_thread contains the right value + save_frame_and_mov(0, Lmethod, Lmethod); // to avoid clobbering O0 (and propagate Lmethod for -Xprof) + mov(G1, L1); // avoid clobbering G1 + // G2 saved below + mov(G3, L3); // avoid clobbering G3 + mov(G4, L4); // avoid clobbering G4 + mov(G5_method, L5); // avoid clobbering G5_method +#endif /* CC_INTERP */ +#if defined(COMPILER2) && !defined(_LP64) + // Save & restore possible 64-bit Long arguments in G-regs + srlx(G1,32,L0); + srlx(G4,32,L6); +#endif + call(CAST_FROM_FN_PTR(address,verify_thread_subroutine), relocInfo::runtime_call_type); + delayed()->mov(G2_thread, O0); + + mov(L1, G1); // Restore G1 + // G2 restored below + mov(L3, G3); // restore G3 + mov(L4, G4); // restore G4 + mov(L5, G5_method); // restore G5_method +#if defined(COMPILER2) && !defined(_LP64) + // Save & restore possible 64-bit Long arguments in G-regs + sllx(L0,32,G2); // Move old high G1 bits high in G2 + srl(G1, 0,G1); // Clear current high G1 bits + or3 (G1,G2,G1); // Recover 64-bit G1 + sllx(L6,32,G2); // Move old high G4 bits high in G2 + srl(G4, 0,G4); // Clear current high G4 bits + or3 (G4,G2,G4); // Recover 64-bit G4 +#endif + restore(O0, 0, G2_thread); + } +} + + +void MacroAssembler::save_thread(const Register thread_cache) { + verify_thread(); + if (thread_cache->is_valid()) { + assert(thread_cache->is_local() || thread_cache->is_in(), "bad volatile"); + mov(G2_thread, thread_cache); + } + if (VerifyThread) { + // smash G2_thread, as if the VM were about to anyway + set(0x67676767, G2_thread); + } +} + + +void MacroAssembler::restore_thread(const Register thread_cache) { + if (thread_cache->is_valid()) { + assert(thread_cache->is_local() || thread_cache->is_in(), "bad volatile"); + mov(thread_cache, G2_thread); + verify_thread(); + } else { + // do it the slow way + get_thread(); + } +} + + +// %%% maybe get rid of [re]set_last_Java_frame +void MacroAssembler::set_last_Java_frame(Register last_java_sp, Register last_Java_pc) { + assert_not_delayed(); + Address flags(G2_thread, JavaThread::frame_anchor_offset() + + JavaFrameAnchor::flags_offset()); + Address pc_addr(G2_thread, JavaThread::last_Java_pc_offset()); + + // Always set last_Java_pc and flags first because once last_Java_sp is visible + // has_last_Java_frame is true and users will look at the rest of the fields. + // (Note: flags should always be zero before we get here so doesn't need to be set.) + +#ifdef ASSERT + // Verify that flags was zeroed on return to Java + Label PcOk; + save_frame(0); // to avoid clobbering O0 + ld_ptr(pc_addr, L0); + br_null_short(L0, Assembler::pt, PcOk); + STOP("last_Java_pc not zeroed before leaving Java"); + bind(PcOk); + + // Verify that flags was zeroed on return to Java + Label FlagsOk; + ld(flags, L0); + tst(L0); + br(Assembler::zero, false, Assembler::pt, FlagsOk); + delayed() -> restore(); + STOP("flags not zeroed before leaving Java"); + bind(FlagsOk); +#endif /* ASSERT */ + // + // When returning from calling out from Java mode the frame anchor's last_Java_pc + // will always be set to NULL. It is set here so that if we are doing a call to + // native (not VM) that we capture the known pc and don't have to rely on the + // native call having a standard frame linkage where we can find the pc. + + if (last_Java_pc->is_valid()) { + st_ptr(last_Java_pc, pc_addr); + } + +#ifdef _LP64 +#ifdef ASSERT + // Make sure that we have an odd stack + Label StackOk; + andcc(last_java_sp, 0x01, G0); + br(Assembler::notZero, false, Assembler::pt, StackOk); + delayed()->nop(); + STOP("Stack Not Biased in set_last_Java_frame"); + bind(StackOk); +#endif // ASSERT + assert( last_java_sp != G4_scratch, "bad register usage in set_last_Java_frame"); + add( last_java_sp, STACK_BIAS, G4_scratch ); + st_ptr(G4_scratch, G2_thread, JavaThread::last_Java_sp_offset()); +#else + st_ptr(last_java_sp, G2_thread, JavaThread::last_Java_sp_offset()); +#endif // _LP64 +} + +void MacroAssembler::reset_last_Java_frame(void) { + assert_not_delayed(); + + Address sp_addr(G2_thread, JavaThread::last_Java_sp_offset()); + Address pc_addr(G2_thread, JavaThread::frame_anchor_offset() + JavaFrameAnchor::last_Java_pc_offset()); + Address flags (G2_thread, JavaThread::frame_anchor_offset() + JavaFrameAnchor::flags_offset()); + +#ifdef ASSERT + // check that it WAS previously set +#ifdef CC_INTERP + save_frame(0); +#else + save_frame_and_mov(0, Lmethod, Lmethod); // Propagate Lmethod to helper frame for -Xprof +#endif /* CC_INTERP */ + ld_ptr(sp_addr, L0); + tst(L0); + breakpoint_trap(Assembler::zero, Assembler::ptr_cc); + restore(); +#endif // ASSERT + + st_ptr(G0, sp_addr); + // Always return last_Java_pc to zero + st_ptr(G0, pc_addr); + // Always null flags after return to Java + st(G0, flags); +} + + +void MacroAssembler::call_VM_base( + Register oop_result, + Register thread_cache, + Register last_java_sp, + address entry_point, + int number_of_arguments, + bool check_exceptions) +{ + assert_not_delayed(); + + // determine last_java_sp register + if (!last_java_sp->is_valid()) { + last_java_sp = SP; + } + // debugging support + assert(number_of_arguments >= 0 , "cannot have negative number of arguments"); + + // 64-bit last_java_sp is biased! + set_last_Java_frame(last_java_sp, noreg); + if (VerifyThread) mov(G2_thread, O0); // about to be smashed; pass early + save_thread(thread_cache); + // do the call + call(entry_point, relocInfo::runtime_call_type); + if (!VerifyThread) + delayed()->mov(G2_thread, O0); // pass thread as first argument + else + delayed()->nop(); // (thread already passed) + restore_thread(thread_cache); + reset_last_Java_frame(); + + // check for pending exceptions. use Gtemp as scratch register. + if (check_exceptions) { + check_and_forward_exception(Gtemp); + } + +#ifdef ASSERT + set(badHeapWordVal, G3); + set(badHeapWordVal, G4); + set(badHeapWordVal, G5); +#endif + + // get oop result if there is one and reset the value in the thread + if (oop_result->is_valid()) { + get_vm_result(oop_result); + } +} + +void MacroAssembler::check_and_forward_exception(Register scratch_reg) +{ + Label L; + + check_and_handle_popframe(scratch_reg); + check_and_handle_earlyret(scratch_reg); + + Address exception_addr(G2_thread, Thread::pending_exception_offset()); + ld_ptr(exception_addr, scratch_reg); + br_null_short(scratch_reg, pt, L); + // we use O7 linkage so that forward_exception_entry has the issuing PC + call(StubRoutines::forward_exception_entry(), relocInfo::runtime_call_type); + delayed()->nop(); + bind(L); +} + + +void MacroAssembler::check_and_handle_popframe(Register scratch_reg) { +} + + +void MacroAssembler::check_and_handle_earlyret(Register scratch_reg) { +} + + +void MacroAssembler::call_VM(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions) { + call_VM_base(oop_result, noreg, noreg, entry_point, number_of_arguments, check_exceptions); +} + + +void MacroAssembler::call_VM(Register oop_result, address entry_point, Register arg_1, bool check_exceptions) { + // O0 is reserved for the thread + mov(arg_1, O1); + call_VM(oop_result, entry_point, 1, check_exceptions); +} + + +void MacroAssembler::call_VM(Register oop_result, address entry_point, Register arg_1, Register arg_2, bool check_exceptions) { + // O0 is reserved for the thread + mov(arg_1, O1); + mov(arg_2, O2); assert(arg_2 != O1, "smashed argument"); + call_VM(oop_result, entry_point, 2, check_exceptions); +} + + +void MacroAssembler::call_VM(Register oop_result, address entry_point, Register arg_1, Register arg_2, Register arg_3, bool check_exceptions) { + // O0 is reserved for the thread + mov(arg_1, O1); + mov(arg_2, O2); assert(arg_2 != O1, "smashed argument"); + mov(arg_3, O3); assert(arg_3 != O1 && arg_3 != O2, "smashed argument"); + call_VM(oop_result, entry_point, 3, check_exceptions); +} + + + +// Note: The following call_VM overloadings are useful when a "save" +// has already been performed by a stub, and the last Java frame is +// the previous one. In that case, last_java_sp must be passed as FP +// instead of SP. + + +void MacroAssembler::call_VM(Register oop_result, Register last_java_sp, address entry_point, int number_of_arguments, bool check_exceptions) { + call_VM_base(oop_result, noreg, last_java_sp, entry_point, number_of_arguments, check_exceptions); +} + + +void MacroAssembler::call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, bool check_exceptions) { + // O0 is reserved for the thread + mov(arg_1, O1); + call_VM(oop_result, last_java_sp, entry_point, 1, check_exceptions); +} + + +void MacroAssembler::call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, Register arg_2, bool check_exceptions) { + // O0 is reserved for the thread + mov(arg_1, O1); + mov(arg_2, O2); assert(arg_2 != O1, "smashed argument"); + call_VM(oop_result, last_java_sp, entry_point, 2, check_exceptions); +} + + +void MacroAssembler::call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, Register arg_2, Register arg_3, bool check_exceptions) { + // O0 is reserved for the thread + mov(arg_1, O1); + mov(arg_2, O2); assert(arg_2 != O1, "smashed argument"); + mov(arg_3, O3); assert(arg_3 != O1 && arg_3 != O2, "smashed argument"); + call_VM(oop_result, last_java_sp, entry_point, 3, check_exceptions); +} + + + +void MacroAssembler::call_VM_leaf_base(Register thread_cache, address entry_point, int number_of_arguments) { + assert_not_delayed(); + save_thread(thread_cache); + // do the call + call(entry_point, relocInfo::runtime_call_type); + delayed()->nop(); + restore_thread(thread_cache); +#ifdef ASSERT + set(badHeapWordVal, G3); + set(badHeapWordVal, G4); + set(badHeapWordVal, G5); +#endif +} + + +void MacroAssembler::call_VM_leaf(Register thread_cache, address entry_point, int number_of_arguments) { + call_VM_leaf_base(thread_cache, entry_point, number_of_arguments); +} + + +void MacroAssembler::call_VM_leaf(Register thread_cache, address entry_point, Register arg_1) { + mov(arg_1, O0); + call_VM_leaf(thread_cache, entry_point, 1); +} + + +void MacroAssembler::call_VM_leaf(Register thread_cache, address entry_point, Register arg_1, Register arg_2) { + mov(arg_1, O0); + mov(arg_2, O1); assert(arg_2 != O0, "smashed argument"); + call_VM_leaf(thread_cache, entry_point, 2); +} + + +void MacroAssembler::call_VM_leaf(Register thread_cache, address entry_point, Register arg_1, Register arg_2, Register arg_3) { + mov(arg_1, O0); + mov(arg_2, O1); assert(arg_2 != O0, "smashed argument"); + mov(arg_3, O2); assert(arg_3 != O0 && arg_3 != O1, "smashed argument"); + call_VM_leaf(thread_cache, entry_point, 3); +} + + +void MacroAssembler::get_vm_result(Register oop_result) { + verify_thread(); + Address vm_result_addr(G2_thread, JavaThread::vm_result_offset()); + ld_ptr( vm_result_addr, oop_result); + st_ptr(G0, vm_result_addr); + verify_oop(oop_result); +} + + +void MacroAssembler::get_vm_result_2(Register metadata_result) { + verify_thread(); + Address vm_result_addr_2(G2_thread, JavaThread::vm_result_2_offset()); + ld_ptr(vm_result_addr_2, metadata_result); + st_ptr(G0, vm_result_addr_2); +} + + +// We require that C code which does not return a value in vm_result will +// leave it undisturbed. +void MacroAssembler::set_vm_result(Register oop_result) { + verify_thread(); + Address vm_result_addr(G2_thread, JavaThread::vm_result_offset()); + verify_oop(oop_result); + +# ifdef ASSERT + // Check that we are not overwriting any other oop. +#ifdef CC_INTERP + save_frame(0); +#else + save_frame_and_mov(0, Lmethod, Lmethod); // Propagate Lmethod for -Xprof +#endif /* CC_INTERP */ + ld_ptr(vm_result_addr, L0); + tst(L0); + restore(); + breakpoint_trap(notZero, Assembler::ptr_cc); + // } +# endif + + st_ptr(oop_result, vm_result_addr); +} + + +void MacroAssembler::ic_call(address entry, bool emit_delay) { + RelocationHolder rspec = virtual_call_Relocation::spec(pc()); + patchable_set((intptr_t)Universe::non_oop_word(), G5_inline_cache_reg); + relocate(rspec); + call(entry, relocInfo::none); + if (emit_delay) { + delayed()->nop(); + } +} + + +void MacroAssembler::card_table_write(jbyte* byte_map_base, + Register tmp, Register obj) { +#ifdef _LP64 + srlx(obj, CardTableModRefBS::card_shift, obj); +#else + srl(obj, CardTableModRefBS::card_shift, obj); +#endif + assert(tmp != obj, "need separate temp reg"); + set((address) byte_map_base, tmp); + stb(G0, tmp, obj); +} + + +void MacroAssembler::internal_sethi(const AddressLiteral& addrlit, Register d, bool ForceRelocatable) { + address save_pc; + int shiftcnt; +#ifdef _LP64 +# ifdef CHECK_DELAY + assert_not_delayed((char*) "cannot put two instructions in delay slot"); +# endif + v9_dep(); + save_pc = pc(); + + int msb32 = (int) (addrlit.value() >> 32); + int lsb32 = (int) (addrlit.value()); + + if (msb32 == 0 && lsb32 >= 0) { + Assembler::sethi(lsb32, d, addrlit.rspec()); + } + else if (msb32 == -1) { + Assembler::sethi(~lsb32, d, addrlit.rspec()); + xor3(d, ~low10(~0), d); + } + else { + Assembler::sethi(msb32, d, addrlit.rspec()); // msb 22-bits + if (msb32 & 0x3ff) // Any bits? + or3(d, msb32 & 0x3ff, d); // msb 32-bits are now in lsb 32 + if (lsb32 & 0xFFFFFC00) { // done? + if ((lsb32 >> 20) & 0xfff) { // Any bits set? + sllx(d, 12, d); // Make room for next 12 bits + or3(d, (lsb32 >> 20) & 0xfff, d); // Or in next 12 + shiftcnt = 0; // We already shifted + } + else + shiftcnt = 12; + if ((lsb32 >> 10) & 0x3ff) { + sllx(d, shiftcnt + 10, d); // Make room for last 10 bits + or3(d, (lsb32 >> 10) & 0x3ff, d); // Or in next 10 + shiftcnt = 0; + } + else + shiftcnt = 10; + sllx(d, shiftcnt + 10, d); // Shift leaving disp field 0'd + } + else + sllx(d, 32, d); + } + // Pad out the instruction sequence so it can be patched later. + if (ForceRelocatable || (addrlit.rtype() != relocInfo::none && + addrlit.rtype() != relocInfo::runtime_call_type)) { + while (pc() < (save_pc + (7 * BytesPerInstWord))) + nop(); + } +#else + Assembler::sethi(addrlit.value(), d, addrlit.rspec()); +#endif +} + + +void MacroAssembler::sethi(const AddressLiteral& addrlit, Register d) { + internal_sethi(addrlit, d, false); +} + + +void MacroAssembler::patchable_sethi(const AddressLiteral& addrlit, Register d) { + internal_sethi(addrlit, d, true); +} + + +int MacroAssembler::insts_for_sethi(address a, bool worst_case) { +#ifdef _LP64 + if (worst_case) return 7; + intptr_t iaddr = (intptr_t) a; + int msb32 = (int) (iaddr >> 32); + int lsb32 = (int) (iaddr); + int count; + if (msb32 == 0 && lsb32 >= 0) + count = 1; + else if (msb32 == -1) + count = 2; + else { + count = 2; + if (msb32 & 0x3ff) + count++; + if (lsb32 & 0xFFFFFC00 ) { + if ((lsb32 >> 20) & 0xfff) count += 2; + if ((lsb32 >> 10) & 0x3ff) count += 2; + } + } + return count; +#else + return 1; +#endif +} + +int MacroAssembler::worst_case_insts_for_set() { + return insts_for_sethi(NULL, true) + 1; +} + + +// Keep in sync with MacroAssembler::insts_for_internal_set +void MacroAssembler::internal_set(const AddressLiteral& addrlit, Register d, bool ForceRelocatable) { + intptr_t value = addrlit.value(); + + if (!ForceRelocatable && addrlit.rspec().type() == relocInfo::none) { + // can optimize + if (-4096 <= value && value <= 4095) { + or3(G0, value, d); // setsw (this leaves upper 32 bits sign-extended) + return; + } + if (inv_hi22(hi22(value)) == value) { + sethi(addrlit, d); + return; + } + } + assert_not_delayed((char*) "cannot put two instructions in delay slot"); + internal_sethi(addrlit, d, ForceRelocatable); + if (ForceRelocatable || addrlit.rspec().type() != relocInfo::none || addrlit.low10() != 0) { + add(d, addrlit.low10(), d, addrlit.rspec()); + } +} + +// Keep in sync with MacroAssembler::internal_set +int MacroAssembler::insts_for_internal_set(intptr_t value) { + // can optimize + if (-4096 <= value && value <= 4095) { + return 1; + } + if (inv_hi22(hi22(value)) == value) { + return insts_for_sethi((address) value); + } + int count = insts_for_sethi((address) value); + AddressLiteral al(value); + if (al.low10() != 0) { + count++; + } + return count; +} + +void MacroAssembler::set(const AddressLiteral& al, Register d) { + internal_set(al, d, false); +} + +void MacroAssembler::set(intptr_t value, Register d) { + AddressLiteral al(value); + internal_set(al, d, false); +} + +void MacroAssembler::set(address addr, Register d, RelocationHolder const& rspec) { + AddressLiteral al(addr, rspec); + internal_set(al, d, false); +} + +void MacroAssembler::patchable_set(const AddressLiteral& al, Register d) { + internal_set(al, d, true); +} + +void MacroAssembler::patchable_set(intptr_t value, Register d) { + AddressLiteral al(value); + internal_set(al, d, true); +} + + +void MacroAssembler::set64(jlong value, Register d, Register tmp) { + assert_not_delayed(); + v9_dep(); + + int hi = (int)(value >> 32); + int lo = (int)(value & ~0); + // (Matcher::isSimpleConstant64 knows about the following optimizations.) + if (Assembler::is_simm13(lo) && value == lo) { + or3(G0, lo, d); + } else if (hi == 0) { + Assembler::sethi(lo, d); // hardware version zero-extends to upper 32 + if (low10(lo) != 0) + or3(d, low10(lo), d); + } + else if (hi == -1) { + Assembler::sethi(~lo, d); // hardware version zero-extends to upper 32 + xor3(d, low10(lo) ^ ~low10(~0), d); + } + else if (lo == 0) { + if (Assembler::is_simm13(hi)) { + or3(G0, hi, d); + } else { + Assembler::sethi(hi, d); // hardware version zero-extends to upper 32 + if (low10(hi) != 0) + or3(d, low10(hi), d); + } + sllx(d, 32, d); + } + else { + Assembler::sethi(hi, tmp); + Assembler::sethi(lo, d); // macro assembler version sign-extends + if (low10(hi) != 0) + or3 (tmp, low10(hi), tmp); + if (low10(lo) != 0) + or3 ( d, low10(lo), d); + sllx(tmp, 32, tmp); + or3 (d, tmp, d); + } +} + +int MacroAssembler::insts_for_set64(jlong value) { + v9_dep(); + + int hi = (int) (value >> 32); + int lo = (int) (value & ~0); + int count = 0; + + // (Matcher::isSimpleConstant64 knows about the following optimizations.) + if (Assembler::is_simm13(lo) && value == lo) { + count++; + } else if (hi == 0) { + count++; + if (low10(lo) != 0) + count++; + } + else if (hi == -1) { + count += 2; + } + else if (lo == 0) { + if (Assembler::is_simm13(hi)) { + count++; + } else { + count++; + if (low10(hi) != 0) + count++; + } + count++; + } + else { + count += 2; + if (low10(hi) != 0) + count++; + if (low10(lo) != 0) + count++; + count += 2; + } + return count; +} + +// compute size in bytes of sparc frame, given +// number of extraWords +int MacroAssembler::total_frame_size_in_bytes(int extraWords) { + + int nWords = frame::memory_parameter_word_sp_offset; + + nWords += extraWords; + + if (nWords & 1) ++nWords; // round up to double-word + + return nWords * BytesPerWord; +} + + +// save_frame: given number of "extra" words in frame, +// issue approp. save instruction (p 200, v8 manual) + +void MacroAssembler::save_frame(int extraWords) { + int delta = -total_frame_size_in_bytes(extraWords); + if (is_simm13(delta)) { + save(SP, delta, SP); + } else { + set(delta, G3_scratch); + save(SP, G3_scratch, SP); + } +} + + +void MacroAssembler::save_frame_c1(int size_in_bytes) { + if (is_simm13(-size_in_bytes)) { + save(SP, -size_in_bytes, SP); + } else { + set(-size_in_bytes, G3_scratch); + save(SP, G3_scratch, SP); + } +} + + +void MacroAssembler::save_frame_and_mov(int extraWords, + Register s1, Register d1, + Register s2, Register d2) { + assert_not_delayed(); + + // The trick here is to use precisely the same memory word + // that trap handlers also use to save the register. + // This word cannot be used for any other purpose, but + // it works fine to save the register's value, whether or not + // an interrupt flushes register windows at any given moment! + Address s1_addr; + if (s1->is_valid() && (s1->is_in() || s1->is_local())) { + s1_addr = s1->address_in_saved_window(); + st_ptr(s1, s1_addr); + } + + Address s2_addr; + if (s2->is_valid() && (s2->is_in() || s2->is_local())) { + s2_addr = s2->address_in_saved_window(); + st_ptr(s2, s2_addr); + } + + save_frame(extraWords); + + if (s1_addr.base() == SP) { + ld_ptr(s1_addr.after_save(), d1); + } else if (s1->is_valid()) { + mov(s1->after_save(), d1); + } + + if (s2_addr.base() == SP) { + ld_ptr(s2_addr.after_save(), d2); + } else if (s2->is_valid()) { + mov(s2->after_save(), d2); + } +} + + +AddressLiteral MacroAssembler::allocate_metadata_address(Metadata* obj) { + assert(oop_recorder() != NULL, "this assembler needs a Recorder"); + int index = oop_recorder()->allocate_metadata_index(obj); + RelocationHolder rspec = metadata_Relocation::spec(index); + return AddressLiteral((address)obj, rspec); +} + +AddressLiteral MacroAssembler::constant_metadata_address(Metadata* obj) { + assert(oop_recorder() != NULL, "this assembler needs a Recorder"); + int index = oop_recorder()->find_index(obj); + RelocationHolder rspec = metadata_Relocation::spec(index); + return AddressLiteral((address)obj, rspec); +} + + +AddressLiteral MacroAssembler::constant_oop_address(jobject obj) { + assert(oop_recorder() != NULL, "this assembler needs an OopRecorder"); + assert(Universe::heap()->is_in_reserved(JNIHandles::resolve(obj)), "not an oop"); + int oop_index = oop_recorder()->find_index(obj); + return AddressLiteral(obj, oop_Relocation::spec(oop_index)); +} + +void MacroAssembler::set_narrow_oop(jobject obj, Register d) { + assert(oop_recorder() != NULL, "this assembler needs an OopRecorder"); + int oop_index = oop_recorder()->find_index(obj); + RelocationHolder rspec = oop_Relocation::spec(oop_index); + + assert_not_delayed(); + // Relocation with special format (see relocInfo_sparc.hpp). + relocate(rspec, 1); + // Assembler::sethi(0x3fffff, d); + emit_long( op(branch_op) | rd(d) | op2(sethi_op2) | hi22(0x3fffff) ); + // Don't add relocation for 'add'. Do patching during 'sethi' processing. + add(d, 0x3ff, d); + +} + +void MacroAssembler::set_narrow_klass(Klass* k, Register d) { + assert(oop_recorder() != NULL, "this assembler needs an OopRecorder"); + int klass_index = oop_recorder()->find_index(k); + RelocationHolder rspec = metadata_Relocation::spec(klass_index); + narrowOop encoded_k = oopDesc::encode_klass(k); + + assert_not_delayed(); + // Relocation with special format (see relocInfo_sparc.hpp). + relocate(rspec, 1); + // Assembler::sethi(encoded_k, d); + emit_long( op(branch_op) | rd(d) | op2(sethi_op2) | hi22(encoded_k) ); + // Don't add relocation for 'add'. Do patching during 'sethi' processing. + add(d, low10(encoded_k), d); + +} + +void MacroAssembler::align(int modulus) { + while (offset() % modulus != 0) nop(); +} + + +void MacroAssembler::safepoint() { + relocate(breakpoint_Relocation::spec(breakpoint_Relocation::safepoint)); +} + + +void RegistersForDebugging::print(outputStream* s) { + FlagSetting fs(Debugging, true); + int j; + for (j = 0; j < 8; ++j) { + if (j != 6) { s->print("i%d = ", j); os::print_location(s, i[j]); } + else { s->print( "fp = " ); os::print_location(s, i[j]); } + } + s->cr(); + + for (j = 0; j < 8; ++j) { + s->print("l%d = ", j); os::print_location(s, l[j]); + } + s->cr(); + + for (j = 0; j < 8; ++j) { + if (j != 6) { s->print("o%d = ", j); os::print_location(s, o[j]); } + else { s->print( "sp = " ); os::print_location(s, o[j]); } + } + s->cr(); + + for (j = 0; j < 8; ++j) { + s->print("g%d = ", j); os::print_location(s, g[j]); + } + s->cr(); + + // print out floats with compression + for (j = 0; j < 32; ) { + jfloat val = f[j]; + int last = j; + for ( ; last+1 < 32; ++last ) { + char b1[1024], b2[1024]; + sprintf(b1, "%f", val); + sprintf(b2, "%f", f[last+1]); + if (strcmp(b1, b2)) + break; + } + s->print("f%d", j); + if ( j != last ) s->print(" - f%d", last); + s->print(" = %f", val); + s->fill_to(25); + s->print_cr(" (0x%x)", val); + j = last + 1; + } + s->cr(); + + // and doubles (evens only) + for (j = 0; j < 32; ) { + jdouble val = d[j]; + int last = j; + for ( ; last+1 < 32; ++last ) { + char b1[1024], b2[1024]; + sprintf(b1, "%f", val); + sprintf(b2, "%f", d[last+1]); + if (strcmp(b1, b2)) + break; + } + s->print("d%d", 2 * j); + if ( j != last ) s->print(" - d%d", last); + s->print(" = %f", val); + s->fill_to(30); + s->print("(0x%x)", *(int*)&val); + s->fill_to(42); + s->print_cr("(0x%x)", *(1 + (int*)&val)); + j = last + 1; + } + s->cr(); +} + +void RegistersForDebugging::save_registers(MacroAssembler* a) { + a->sub(FP, round_to(sizeof(RegistersForDebugging), sizeof(jdouble)) - STACK_BIAS, O0); + a->flush_windows(); + int i; + for (i = 0; i < 8; ++i) { + a->ld_ptr(as_iRegister(i)->address_in_saved_window().after_save(), L1); a->st_ptr( L1, O0, i_offset(i)); + a->ld_ptr(as_lRegister(i)->address_in_saved_window().after_save(), L1); a->st_ptr( L1, O0, l_offset(i)); + a->st_ptr(as_oRegister(i)->after_save(), O0, o_offset(i)); + a->st_ptr(as_gRegister(i)->after_save(), O0, g_offset(i)); + } + for (i = 0; i < 32; ++i) { + a->stf(FloatRegisterImpl::S, as_FloatRegister(i), O0, f_offset(i)); + } + for (i = 0; i < (VM_Version::v9_instructions_work() ? 64 : 32); i += 2) { + a->stf(FloatRegisterImpl::D, as_FloatRegister(i), O0, d_offset(i)); + } +} + +void RegistersForDebugging::restore_registers(MacroAssembler* a, Register r) { + for (int i = 1; i < 8; ++i) { + a->ld_ptr(r, g_offset(i), as_gRegister(i)); + } + for (int j = 0; j < 32; ++j) { + a->ldf(FloatRegisterImpl::S, O0, f_offset(j), as_FloatRegister(j)); + } + for (int k = 0; k < (VM_Version::v9_instructions_work() ? 64 : 32); k += 2) { + a->ldf(FloatRegisterImpl::D, O0, d_offset(k), as_FloatRegister(k)); + } +} + + +// pushes double TOS element of FPU stack on CPU stack; pops from FPU stack +void MacroAssembler::push_fTOS() { + // %%%%%% need to implement this +} + +// pops double TOS element from CPU stack and pushes on FPU stack +void MacroAssembler::pop_fTOS() { + // %%%%%% need to implement this +} + +void MacroAssembler::empty_FPU_stack() { + // %%%%%% need to implement this +} + +void MacroAssembler::_verify_oop(Register reg, const char* msg, const char * file, int line) { + // plausibility check for oops + if (!VerifyOops) return; + + if (reg == G0) return; // always NULL, which is always an oop + + BLOCK_COMMENT("verify_oop {"); + char buffer[64]; +#ifdef COMPILER1 + if (CommentedAssembly) { + snprintf(buffer, sizeof(buffer), "verify_oop at %d", offset()); + block_comment(buffer); + } +#endif + + int len = strlen(file) + strlen(msg) + 1 + 4; + sprintf(buffer, "%d", line); + len += strlen(buffer); + sprintf(buffer, " at offset %d ", offset()); + len += strlen(buffer); + char * real_msg = new char[len]; + sprintf(real_msg, "%s%s(%s:%d)", msg, buffer, file, line); + + // Call indirectly to solve generation ordering problem + AddressLiteral a(StubRoutines::verify_oop_subroutine_entry_address()); + + // Make some space on stack above the current register window. + // Enough to hold 8 64-bit registers. + add(SP,-8*8,SP); + + // Save some 64-bit registers; a normal 'save' chops the heads off + // of 64-bit longs in the 32-bit build. + stx(O0,SP,frame::register_save_words*wordSize+STACK_BIAS+0*8); + stx(O1,SP,frame::register_save_words*wordSize+STACK_BIAS+1*8); + mov(reg,O0); // Move arg into O0; arg might be in O7 which is about to be crushed + stx(O7,SP,frame::register_save_words*wordSize+STACK_BIAS+7*8); + + // Size of set() should stay the same + patchable_set((intptr_t)real_msg, O1); + // Load address to call to into O7 + load_ptr_contents(a, O7); + // Register call to verify_oop_subroutine + callr(O7, G0); + delayed()->nop(); + // recover frame size + add(SP, 8*8,SP); + BLOCK_COMMENT("} verify_oop"); +} + +void MacroAssembler::_verify_oop_addr(Address addr, const char* msg, const char * file, int line) { + // plausibility check for oops + if (!VerifyOops) return; + + char buffer[64]; + sprintf(buffer, "%d", line); + int len = strlen(file) + strlen(msg) + 1 + 4 + strlen(buffer); + sprintf(buffer, " at SP+%d ", addr.disp()); + len += strlen(buffer); + char * real_msg = new char[len]; + sprintf(real_msg, "%s at SP+%d (%s:%d)", msg, addr.disp(), file, line); + + // Call indirectly to solve generation ordering problem + AddressLiteral a(StubRoutines::verify_oop_subroutine_entry_address()); + + // Make some space on stack above the current register window. + // Enough to hold 8 64-bit registers. + add(SP,-8*8,SP); + + // Save some 64-bit registers; a normal 'save' chops the heads off + // of 64-bit longs in the 32-bit build. + stx(O0,SP,frame::register_save_words*wordSize+STACK_BIAS+0*8); + stx(O1,SP,frame::register_save_words*wordSize+STACK_BIAS+1*8); + ld_ptr(addr.base(), addr.disp() + 8*8, O0); // Load arg into O0; arg might be in O7 which is about to be crushed + stx(O7,SP,frame::register_save_words*wordSize+STACK_BIAS+7*8); + + // Size of set() should stay the same + patchable_set((intptr_t)real_msg, O1); + // Load address to call to into O7 + load_ptr_contents(a, O7); + // Register call to verify_oop_subroutine + callr(O7, G0); + delayed()->nop(); + // recover frame size + add(SP, 8*8,SP); +} + +// side-door communication with signalHandler in os_solaris.cpp +address MacroAssembler::_verify_oop_implicit_branch[3] = { NULL }; + +// This macro is expanded just once; it creates shared code. Contract: +// receives an oop in O0. Must restore O0 & O7 from TLS. Must not smash ANY +// registers, including flags. May not use a register 'save', as this blows +// the high bits of the O-regs if they contain Long values. Acts as a 'leaf' +// call. +void MacroAssembler::verify_oop_subroutine() { + assert( VM_Version::v9_instructions_work(), "VerifyOops not supported for V8" ); + + // Leaf call; no frame. + Label succeed, fail, null_or_fail; + + // O0 and O7 were saved already (O0 in O0's TLS home, O7 in O5's TLS home). + // O0 is now the oop to be checked. O7 is the return address. + Register O0_obj = O0; + + // Save some more registers for temps. + stx(O2,SP,frame::register_save_words*wordSize+STACK_BIAS+2*8); + stx(O3,SP,frame::register_save_words*wordSize+STACK_BIAS+3*8); + stx(O4,SP,frame::register_save_words*wordSize+STACK_BIAS+4*8); + stx(O5,SP,frame::register_save_words*wordSize+STACK_BIAS+5*8); + + // Save flags + Register O5_save_flags = O5; + rdccr( O5_save_flags ); + + { // count number of verifies + Register O2_adr = O2; + Register O3_accum = O3; + inc_counter(StubRoutines::verify_oop_count_addr(), O2_adr, O3_accum); + } + + Register O2_mask = O2; + Register O3_bits = O3; + Register O4_temp = O4; + + // mark lower end of faulting range + assert(_verify_oop_implicit_branch[0] == NULL, "set once"); + _verify_oop_implicit_branch[0] = pc(); + + // We can't check the mark oop because it could be in the process of + // locking or unlocking while this is running. + set(Universe::verify_oop_mask (), O2_mask); + set(Universe::verify_oop_bits (), O3_bits); + + // assert((obj & oop_mask) == oop_bits); + and3(O0_obj, O2_mask, O4_temp); + cmp_and_brx_short(O4_temp, O3_bits, notEqual, pn, null_or_fail); + + if ((NULL_WORD & Universe::verify_oop_mask()) == Universe::verify_oop_bits()) { + // the null_or_fail case is useless; must test for null separately + br_null_short(O0_obj, pn, succeed); + } + + // Check the Klass* of this object for being in the right area of memory. + // Cannot do the load in the delay above slot in case O0 is null + load_klass(O0_obj, O0_obj); + // assert((klass != NULL) + br_null_short(O0_obj, pn, fail); + // TODO: Future assert that klass is lower 4g memory for UseCompressedKlassPointers + + wrccr( O5_save_flags ); // Restore CCR's + + // mark upper end of faulting range + _verify_oop_implicit_branch[1] = pc(); + + //----------------------- + // all tests pass + bind(succeed); + + // Restore prior 64-bit registers + ldx(SP,frame::register_save_words*wordSize+STACK_BIAS+0*8,O0); + ldx(SP,frame::register_save_words*wordSize+STACK_BIAS+1*8,O1); + ldx(SP,frame::register_save_words*wordSize+STACK_BIAS+2*8,O2); + ldx(SP,frame::register_save_words*wordSize+STACK_BIAS+3*8,O3); + ldx(SP,frame::register_save_words*wordSize+STACK_BIAS+4*8,O4); + ldx(SP,frame::register_save_words*wordSize+STACK_BIAS+5*8,O5); + + retl(); // Leaf return; restore prior O7 in delay slot + delayed()->ldx(SP,frame::register_save_words*wordSize+STACK_BIAS+7*8,O7); + + //----------------------- + bind(null_or_fail); // nulls are less common but OK + br_null(O0_obj, false, pt, succeed); + delayed()->wrccr( O5_save_flags ); // Restore CCR's + + //----------------------- + // report failure: + bind(fail); + _verify_oop_implicit_branch[2] = pc(); + + wrccr( O5_save_flags ); // Restore CCR's + + save_frame(::round_to(sizeof(RegistersForDebugging) / BytesPerWord, 2)); + + // stop_subroutine expects message pointer in I1. + mov(I1, O1); + + // Restore prior 64-bit registers + ldx(FP,frame::register_save_words*wordSize+STACK_BIAS+0*8,I0); + ldx(FP,frame::register_save_words*wordSize+STACK_BIAS+1*8,I1); + ldx(FP,frame::register_save_words*wordSize+STACK_BIAS+2*8,I2); + ldx(FP,frame::register_save_words*wordSize+STACK_BIAS+3*8,I3); + ldx(FP,frame::register_save_words*wordSize+STACK_BIAS+4*8,I4); + ldx(FP,frame::register_save_words*wordSize+STACK_BIAS+5*8,I5); + + // factor long stop-sequence into subroutine to save space + assert(StubRoutines::Sparc::stop_subroutine_entry_address(), "hasn't been generated yet"); + + // call indirectly to solve generation ordering problem + AddressLiteral al(StubRoutines::Sparc::stop_subroutine_entry_address()); + load_ptr_contents(al, O5); + jmpl(O5, 0, O7); + delayed()->nop(); +} + + +void MacroAssembler::stop(const char* msg) { + // save frame first to get O7 for return address + // add one word to size in case struct is odd number of words long + // It must be doubleword-aligned for storing doubles into it. + + save_frame(::round_to(sizeof(RegistersForDebugging) / BytesPerWord, 2)); + + // stop_subroutine expects message pointer in I1. + // Size of set() should stay the same + patchable_set((intptr_t)msg, O1); + + // factor long stop-sequence into subroutine to save space + assert(StubRoutines::Sparc::stop_subroutine_entry_address(), "hasn't been generated yet"); + + // call indirectly to solve generation ordering problem + AddressLiteral a(StubRoutines::Sparc::stop_subroutine_entry_address()); + load_ptr_contents(a, O5); + jmpl(O5, 0, O7); + delayed()->nop(); + + breakpoint_trap(); // make stop actually stop rather than writing + // unnoticeable results in the output files. + + // restore(); done in callee to save space! +} + + +void MacroAssembler::warn(const char* msg) { + save_frame(::round_to(sizeof(RegistersForDebugging) / BytesPerWord, 2)); + RegistersForDebugging::save_registers(this); + mov(O0, L0); + // Size of set() should stay the same + patchable_set((intptr_t)msg, O0); + call( CAST_FROM_FN_PTR(address, warning) ); + delayed()->nop(); +// ret(); +// delayed()->restore(); + RegistersForDebugging::restore_registers(this, L0); + restore(); +} + + +void MacroAssembler::untested(const char* what) { + // We must be able to turn interactive prompting off + // in order to run automated test scripts on the VM + // Use the flag ShowMessageBoxOnError + + char* b = new char[1024]; + sprintf(b, "untested: %s", what); + + if (ShowMessageBoxOnError) { STOP(b); } + else { warn(b); } +} + + +void MacroAssembler::stop_subroutine() { + RegistersForDebugging::save_registers(this); + + // for the sake of the debugger, stick a PC on the current frame + // (this assumes that the caller has performed an extra "save") + mov(I7, L7); + add(O7, -7 * BytesPerInt, I7); + + save_frame(); // one more save to free up another O7 register + mov(I0, O1); // addr of reg save area + + // We expect pointer to message in I1. Caller must set it up in O1 + mov(I1, O0); // get msg + call (CAST_FROM_FN_PTR(address, MacroAssembler::debug), relocInfo::runtime_call_type); + delayed()->nop(); + + restore(); + + RegistersForDebugging::restore_registers(this, O0); + + save_frame(0); + call(CAST_FROM_FN_PTR(address,breakpoint)); + delayed()->nop(); + restore(); + + mov(L7, I7); + retl(); + delayed()->restore(); // see stop above +} + + +void MacroAssembler::debug(char* msg, RegistersForDebugging* regs) { + if ( ShowMessageBoxOnError ) { + JavaThread* thread = JavaThread::current(); + JavaThreadState saved_state = thread->thread_state(); + thread->set_thread_state(_thread_in_vm); + { + // In order to get locks work, we need to fake a in_VM state + ttyLocker ttyl; + ::tty->print_cr("EXECUTION STOPPED: %s\n", msg); + if (CountBytecodes || TraceBytecodes || StopInterpreterAt) { + BytecodeCounter::print(); + } + if (os::message_box(msg, "Execution stopped, print registers?")) + regs->print(::tty); + } + BREAKPOINT; + ThreadStateTransition::transition(JavaThread::current(), _thread_in_vm, saved_state); + } + else { + ::tty->print_cr("=============== DEBUG MESSAGE: %s ================\n", msg); + } + assert(false, err_msg("DEBUG MESSAGE: %s", msg)); +} + + +void MacroAssembler::calc_mem_param_words(Register Rparam_words, Register Rresult) { + subcc( Rparam_words, Argument::n_register_parameters, Rresult); // how many mem words? + Label no_extras; + br( negative, true, pt, no_extras ); // if neg, clear reg + delayed()->set(0, Rresult); // annuled, so only if taken + bind( no_extras ); +} + + +void MacroAssembler::calc_frame_size(Register Rextra_words, Register Rresult) { +#ifdef _LP64 + add(Rextra_words, frame::memory_parameter_word_sp_offset, Rresult); +#else + add(Rextra_words, frame::memory_parameter_word_sp_offset + 1, Rresult); +#endif + bclr(1, Rresult); + sll(Rresult, LogBytesPerWord, Rresult); // Rresult has total frame bytes +} + + +void MacroAssembler::calc_frame_size_and_save(Register Rextra_words, Register Rresult) { + calc_frame_size(Rextra_words, Rresult); + neg(Rresult); + save(SP, Rresult, SP); +} + + +// --------------------------------------------------------- +Assembler::RCondition cond2rcond(Assembler::Condition c) { + switch (c) { + /*case zero: */ + case Assembler::equal: return Assembler::rc_z; + case Assembler::lessEqual: return Assembler::rc_lez; + case Assembler::less: return Assembler::rc_lz; + /*case notZero:*/ + case Assembler::notEqual: return Assembler::rc_nz; + case Assembler::greater: return Assembler::rc_gz; + case Assembler::greaterEqual: return Assembler::rc_gez; + } + ShouldNotReachHere(); + return Assembler::rc_z; +} + +// compares (32 bit) register with zero and branches. NOT FOR USE WITH 64-bit POINTERS +void MacroAssembler::cmp_zero_and_br(Condition c, Register s1, Label& L, bool a, Predict p) { + tst(s1); + br (c, a, p, L); +} + +// Compares a pointer register with zero and branches on null. +// Does a test & branch on 32-bit systems and a register-branch on 64-bit. +void MacroAssembler::br_null( Register s1, bool a, Predict p, Label& L ) { + assert_not_delayed(); +#ifdef _LP64 + bpr( rc_z, a, p, s1, L ); +#else + tst(s1); + br ( zero, a, p, L ); +#endif +} + +void MacroAssembler::br_notnull( Register s1, bool a, Predict p, Label& L ) { + assert_not_delayed(); +#ifdef _LP64 + bpr( rc_nz, a, p, s1, L ); +#else + tst(s1); + br ( notZero, a, p, L ); +#endif +} + +// Compare registers and branch with nop in delay slot or cbcond without delay slot. + +// Compare integer (32 bit) values (icc only). +void MacroAssembler::cmp_and_br_short(Register s1, Register s2, Condition c, + Predict p, Label& L) { + assert_not_delayed(); + if (use_cbcond(L)) { + Assembler::cbcond(c, icc, s1, s2, L); + } else { + cmp(s1, s2); + br(c, false, p, L); + delayed()->nop(); + } +} + +// Compare integer (32 bit) values (icc only). +void MacroAssembler::cmp_and_br_short(Register s1, int simm13a, Condition c, + Predict p, Label& L) { + assert_not_delayed(); + if (is_simm(simm13a,5) && use_cbcond(L)) { + Assembler::cbcond(c, icc, s1, simm13a, L); + } else { + cmp(s1, simm13a); + br(c, false, p, L); + delayed()->nop(); + } +} + +// Branch that tests xcc in LP64 and icc in !LP64 +void MacroAssembler::cmp_and_brx_short(Register s1, Register s2, Condition c, + Predict p, Label& L) { + assert_not_delayed(); + if (use_cbcond(L)) { + Assembler::cbcond(c, ptr_cc, s1, s2, L); + } else { + cmp(s1, s2); + brx(c, false, p, L); + delayed()->nop(); + } +} + +// Branch that tests xcc in LP64 and icc in !LP64 +void MacroAssembler::cmp_and_brx_short(Register s1, int simm13a, Condition c, + Predict p, Label& L) { + assert_not_delayed(); + if (is_simm(simm13a,5) && use_cbcond(L)) { + Assembler::cbcond(c, ptr_cc, s1, simm13a, L); + } else { + cmp(s1, simm13a); + brx(c, false, p, L); + delayed()->nop(); + } +} + +// Short branch version for compares a pointer with zero. + +void MacroAssembler::br_null_short(Register s1, Predict p, Label& L) { + assert_not_delayed(); + if (use_cbcond(L)) { + Assembler::cbcond(zero, ptr_cc, s1, 0, L); + return; + } + br_null(s1, false, p, L); + delayed()->nop(); +} + +void MacroAssembler::br_notnull_short(Register s1, Predict p, Label& L) { + assert_not_delayed(); + if (use_cbcond(L)) { + Assembler::cbcond(notZero, ptr_cc, s1, 0, L); + return; + } + br_notnull(s1, false, p, L); + delayed()->nop(); +} + +// Unconditional short branch +void MacroAssembler::ba_short(Label& L) { + if (use_cbcond(L)) { + Assembler::cbcond(equal, icc, G0, G0, L); + return; + } + br(always, false, pt, L); + delayed()->nop(); +} + +// instruction sequences factored across compiler & interpreter + + +void MacroAssembler::lcmp( Register Ra_hi, Register Ra_low, + Register Rb_hi, Register Rb_low, + Register Rresult) { + + Label check_low_parts, done; + + cmp(Ra_hi, Rb_hi ); // compare hi parts + br(equal, true, pt, check_low_parts); + delayed()->cmp(Ra_low, Rb_low); // test low parts + + // And, with an unsigned comparison, it does not matter if the numbers + // are negative or not. + // E.g., -2 cmp -1: the low parts are 0xfffffffe and 0xffffffff. + // The second one is bigger (unsignedly). + + // Other notes: The first move in each triplet can be unconditional + // (and therefore probably prefetchable). + // And the equals case for the high part does not need testing, + // since that triplet is reached only after finding the high halves differ. + + if (VM_Version::v9_instructions_work()) { + mov(-1, Rresult); + ba(done); delayed()-> movcc(greater, false, icc, 1, Rresult); + } else { + br(less, true, pt, done); delayed()-> set(-1, Rresult); + br(greater, true, pt, done); delayed()-> set( 1, Rresult); + } + + bind( check_low_parts ); + + if (VM_Version::v9_instructions_work()) { + mov( -1, Rresult); + movcc(equal, false, icc, 0, Rresult); + movcc(greaterUnsigned, false, icc, 1, Rresult); + } else { + set(-1, Rresult); + br(equal, true, pt, done); delayed()->set( 0, Rresult); + br(greaterUnsigned, true, pt, done); delayed()->set( 1, Rresult); + } + bind( done ); +} + +void MacroAssembler::lneg( Register Rhi, Register Rlow ) { + subcc( G0, Rlow, Rlow ); + subc( G0, Rhi, Rhi ); +} + +void MacroAssembler::lshl( Register Rin_high, Register Rin_low, + Register Rcount, + Register Rout_high, Register Rout_low, + Register Rtemp ) { + + + Register Ralt_count = Rtemp; + Register Rxfer_bits = Rtemp; + + assert( Ralt_count != Rin_high + && Ralt_count != Rin_low + && Ralt_count != Rcount + && Rxfer_bits != Rin_low + && Rxfer_bits != Rin_high + && Rxfer_bits != Rcount + && Rxfer_bits != Rout_low + && Rout_low != Rin_high, + "register alias checks"); + + Label big_shift, done; + + // This code can be optimized to use the 64 bit shifts in V9. + // Here we use the 32 bit shifts. + + and3( Rcount, 0x3f, Rcount); // take least significant 6 bits + subcc(Rcount, 31, Ralt_count); + br(greater, true, pn, big_shift); + delayed()->dec(Ralt_count); + + // shift < 32 bits, Ralt_count = Rcount-31 + + // We get the transfer bits by shifting right by 32-count the low + // register. This is done by shifting right by 31-count and then by one + // more to take care of the special (rare) case where count is zero + // (shifting by 32 would not work). + + neg(Ralt_count); + + // The order of the next two instructions is critical in the case where + // Rin and Rout are the same and should not be reversed. + + srl(Rin_low, Ralt_count, Rxfer_bits); // shift right by 31-count + if (Rcount != Rout_low) { + sll(Rin_low, Rcount, Rout_low); // low half + } + sll(Rin_high, Rcount, Rout_high); + if (Rcount == Rout_low) { + sll(Rin_low, Rcount, Rout_low); // low half + } + srl(Rxfer_bits, 1, Rxfer_bits ); // shift right by one more + ba(done); + delayed()->or3(Rout_high, Rxfer_bits, Rout_high); // new hi value: or in shifted old hi part and xfer from low + + // shift >= 32 bits, Ralt_count = Rcount-32 + bind(big_shift); + sll(Rin_low, Ralt_count, Rout_high ); + clr(Rout_low); + + bind(done); +} + + +void MacroAssembler::lshr( Register Rin_high, Register Rin_low, + Register Rcount, + Register Rout_high, Register Rout_low, + Register Rtemp ) { + + Register Ralt_count = Rtemp; + Register Rxfer_bits = Rtemp; + + assert( Ralt_count != Rin_high + && Ralt_count != Rin_low + && Ralt_count != Rcount + && Rxfer_bits != Rin_low + && Rxfer_bits != Rin_high + && Rxfer_bits != Rcount + && Rxfer_bits != Rout_high + && Rout_high != Rin_low, + "register alias checks"); + + Label big_shift, done; + + // This code can be optimized to use the 64 bit shifts in V9. + // Here we use the 32 bit shifts. + + and3( Rcount, 0x3f, Rcount); // take least significant 6 bits + subcc(Rcount, 31, Ralt_count); + br(greater, true, pn, big_shift); + delayed()->dec(Ralt_count); + + // shift < 32 bits, Ralt_count = Rcount-31 + + // We get the transfer bits by shifting left by 32-count the high + // register. This is done by shifting left by 31-count and then by one + // more to take care of the special (rare) case where count is zero + // (shifting by 32 would not work). + + neg(Ralt_count); + if (Rcount != Rout_low) { + srl(Rin_low, Rcount, Rout_low); + } + + // The order of the next two instructions is critical in the case where + // Rin and Rout are the same and should not be reversed. + + sll(Rin_high, Ralt_count, Rxfer_bits); // shift left by 31-count + sra(Rin_high, Rcount, Rout_high ); // high half + sll(Rxfer_bits, 1, Rxfer_bits); // shift left by one more + if (Rcount == Rout_low) { + srl(Rin_low, Rcount, Rout_low); + } + ba(done); + delayed()->or3(Rout_low, Rxfer_bits, Rout_low); // new low value: or shifted old low part and xfer from high + + // shift >= 32 bits, Ralt_count = Rcount-32 + bind(big_shift); + + sra(Rin_high, Ralt_count, Rout_low); + sra(Rin_high, 31, Rout_high); // sign into hi + + bind( done ); +} + + + +void MacroAssembler::lushr( Register Rin_high, Register Rin_low, + Register Rcount, + Register Rout_high, Register Rout_low, + Register Rtemp ) { + + Register Ralt_count = Rtemp; + Register Rxfer_bits = Rtemp; + + assert( Ralt_count != Rin_high + && Ralt_count != Rin_low + && Ralt_count != Rcount + && Rxfer_bits != Rin_low + && Rxfer_bits != Rin_high + && Rxfer_bits != Rcount + && Rxfer_bits != Rout_high + && Rout_high != Rin_low, + "register alias checks"); + + Label big_shift, done; + + // This code can be optimized to use the 64 bit shifts in V9. + // Here we use the 32 bit shifts. + + and3( Rcount, 0x3f, Rcount); // take least significant 6 bits + subcc(Rcount, 31, Ralt_count); + br(greater, true, pn, big_shift); + delayed()->dec(Ralt_count); + + // shift < 32 bits, Ralt_count = Rcount-31 + + // We get the transfer bits by shifting left by 32-count the high + // register. This is done by shifting left by 31-count and then by one + // more to take care of the special (rare) case where count is zero + // (shifting by 32 would not work). + + neg(Ralt_count); + if (Rcount != Rout_low) { + srl(Rin_low, Rcount, Rout_low); + } + + // The order of the next two instructions is critical in the case where + // Rin and Rout are the same and should not be reversed. + + sll(Rin_high, Ralt_count, Rxfer_bits); // shift left by 31-count + srl(Rin_high, Rcount, Rout_high ); // high half + sll(Rxfer_bits, 1, Rxfer_bits); // shift left by one more + if (Rcount == Rout_low) { + srl(Rin_low, Rcount, Rout_low); + } + ba(done); + delayed()->or3(Rout_low, Rxfer_bits, Rout_low); // new low value: or shifted old low part and xfer from high + + // shift >= 32 bits, Ralt_count = Rcount-32 + bind(big_shift); + + srl(Rin_high, Ralt_count, Rout_low); + clr(Rout_high); + + bind( done ); +} + +#ifdef _LP64 +void MacroAssembler::lcmp( Register Ra, Register Rb, Register Rresult) { + cmp(Ra, Rb); + mov(-1, Rresult); + movcc(equal, false, xcc, 0, Rresult); + movcc(greater, false, xcc, 1, Rresult); +} +#endif + + +void MacroAssembler::load_sized_value(Address src, Register dst, size_t size_in_bytes, bool is_signed) { + switch (size_in_bytes) { + case 8: ld_long(src, dst); break; + case 4: ld( src, dst); break; + case 2: is_signed ? ldsh(src, dst) : lduh(src, dst); break; + case 1: is_signed ? ldsb(src, dst) : ldub(src, dst); break; + default: ShouldNotReachHere(); + } +} + +void MacroAssembler::store_sized_value(Register src, Address dst, size_t size_in_bytes) { + switch (size_in_bytes) { + case 8: st_long(src, dst); break; + case 4: st( src, dst); break; + case 2: sth( src, dst); break; + case 1: stb( src, dst); break; + default: ShouldNotReachHere(); + } +} + + +void MacroAssembler::float_cmp( bool is_float, int unordered_result, + FloatRegister Fa, FloatRegister Fb, + Register Rresult) { + + fcmp(is_float ? FloatRegisterImpl::S : FloatRegisterImpl::D, fcc0, Fa, Fb); + + Condition lt = unordered_result == -1 ? f_unorderedOrLess : f_less; + Condition eq = f_equal; + Condition gt = unordered_result == 1 ? f_unorderedOrGreater : f_greater; + + if (VM_Version::v9_instructions_work()) { + + mov(-1, Rresult); + movcc(eq, true, fcc0, 0, Rresult); + movcc(gt, true, fcc0, 1, Rresult); + + } else { + Label done; + + set( -1, Rresult ); + //fb(lt, true, pn, done); delayed()->set( -1, Rresult ); + fb( eq, true, pn, done); delayed()->set( 0, Rresult ); + fb( gt, true, pn, done); delayed()->set( 1, Rresult ); + + bind (done); + } +} + + +void MacroAssembler::fneg( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d) +{ + if (VM_Version::v9_instructions_work()) { + Assembler::fneg(w, s, d); + } else { + if (w == FloatRegisterImpl::S) { + Assembler::fneg(w, s, d); + } else if (w == FloatRegisterImpl::D) { + // number() does a sanity check on the alignment. + assert(((s->encoding(FloatRegisterImpl::D) & 1) == 0) && + ((d->encoding(FloatRegisterImpl::D) & 1) == 0), "float register alignment check"); + + Assembler::fneg(FloatRegisterImpl::S, s, d); + Assembler::fmov(FloatRegisterImpl::S, s->successor(), d->successor()); + } else { + assert(w == FloatRegisterImpl::Q, "Invalid float register width"); + + // number() does a sanity check on the alignment. + assert(((s->encoding(FloatRegisterImpl::D) & 3) == 0) && + ((d->encoding(FloatRegisterImpl::D) & 3) == 0), "float register alignment check"); + + Assembler::fneg(FloatRegisterImpl::S, s, d); + Assembler::fmov(FloatRegisterImpl::S, s->successor(), d->successor()); + Assembler::fmov(FloatRegisterImpl::S, s->successor()->successor(), d->successor()->successor()); + Assembler::fmov(FloatRegisterImpl::S, s->successor()->successor()->successor(), d->successor()->successor()->successor()); + } + } +} + +void MacroAssembler::fmov( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d) +{ + if (VM_Version::v9_instructions_work()) { + Assembler::fmov(w, s, d); + } else { + if (w == FloatRegisterImpl::S) { + Assembler::fmov(w, s, d); + } else if (w == FloatRegisterImpl::D) { + // number() does a sanity check on the alignment. + assert(((s->encoding(FloatRegisterImpl::D) & 1) == 0) && + ((d->encoding(FloatRegisterImpl::D) & 1) == 0), "float register alignment check"); + + Assembler::fmov(FloatRegisterImpl::S, s, d); + Assembler::fmov(FloatRegisterImpl::S, s->successor(), d->successor()); + } else { + assert(w == FloatRegisterImpl::Q, "Invalid float register width"); + + // number() does a sanity check on the alignment. + assert(((s->encoding(FloatRegisterImpl::D) & 3) == 0) && + ((d->encoding(FloatRegisterImpl::D) & 3) == 0), "float register alignment check"); + + Assembler::fmov(FloatRegisterImpl::S, s, d); + Assembler::fmov(FloatRegisterImpl::S, s->successor(), d->successor()); + Assembler::fmov(FloatRegisterImpl::S, s->successor()->successor(), d->successor()->successor()); + Assembler::fmov(FloatRegisterImpl::S, s->successor()->successor()->successor(), d->successor()->successor()->successor()); + } + } +} + +void MacroAssembler::fabs( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d) +{ + if (VM_Version::v9_instructions_work()) { + Assembler::fabs(w, s, d); + } else { + if (w == FloatRegisterImpl::S) { + Assembler::fabs(w, s, d); + } else if (w == FloatRegisterImpl::D) { + // number() does a sanity check on the alignment. + assert(((s->encoding(FloatRegisterImpl::D) & 1) == 0) && + ((d->encoding(FloatRegisterImpl::D) & 1) == 0), "float register alignment check"); + + Assembler::fabs(FloatRegisterImpl::S, s, d); + Assembler::fmov(FloatRegisterImpl::S, s->successor(), d->successor()); + } else { + assert(w == FloatRegisterImpl::Q, "Invalid float register width"); + + // number() does a sanity check on the alignment. + assert(((s->encoding(FloatRegisterImpl::D) & 3) == 0) && + ((d->encoding(FloatRegisterImpl::D) & 3) == 0), "float register alignment check"); + + Assembler::fabs(FloatRegisterImpl::S, s, d); + Assembler::fmov(FloatRegisterImpl::S, s->successor(), d->successor()); + Assembler::fmov(FloatRegisterImpl::S, s->successor()->successor(), d->successor()->successor()); + Assembler::fmov(FloatRegisterImpl::S, s->successor()->successor()->successor(), d->successor()->successor()->successor()); + } + } +} + +void MacroAssembler::save_all_globals_into_locals() { + mov(G1,L1); + mov(G2,L2); + mov(G3,L3); + mov(G4,L4); + mov(G5,L5); + mov(G6,L6); + mov(G7,L7); +} + +void MacroAssembler::restore_globals_from_locals() { + mov(L1,G1); + mov(L2,G2); + mov(L3,G3); + mov(L4,G4); + mov(L5,G5); + mov(L6,G6); + mov(L7,G7); +} + +// Use for 64 bit operation. +void MacroAssembler::casx_under_lock(Register top_ptr_reg, Register top_reg, Register ptr_reg, address lock_addr, bool use_call_vm) +{ + // store ptr_reg as the new top value +#ifdef _LP64 + casx(top_ptr_reg, top_reg, ptr_reg); +#else + cas_under_lock(top_ptr_reg, top_reg, ptr_reg, lock_addr, use_call_vm); +#endif // _LP64 +} + +// [RGV] This routine does not handle 64 bit operations. +// use casx_under_lock() or casx directly!!! +void MacroAssembler::cas_under_lock(Register top_ptr_reg, Register top_reg, Register ptr_reg, address lock_addr, bool use_call_vm) +{ + // store ptr_reg as the new top value + if (VM_Version::v9_instructions_work()) { + cas(top_ptr_reg, top_reg, ptr_reg); + } else { + + // If the register is not an out nor global, it is not visible + // after the save. Allocate a register for it, save its + // value in the register save area (the save may not flush + // registers to the save area). + + Register top_ptr_reg_after_save; + Register top_reg_after_save; + Register ptr_reg_after_save; + + if (top_ptr_reg->is_out() || top_ptr_reg->is_global()) { + top_ptr_reg_after_save = top_ptr_reg->after_save(); + } else { + Address reg_save_addr = top_ptr_reg->address_in_saved_window(); + top_ptr_reg_after_save = L0; + st(top_ptr_reg, reg_save_addr); + } + + if (top_reg->is_out() || top_reg->is_global()) { + top_reg_after_save = top_reg->after_save(); + } else { + Address reg_save_addr = top_reg->address_in_saved_window(); + top_reg_after_save = L1; + st(top_reg, reg_save_addr); + } + + if (ptr_reg->is_out() || ptr_reg->is_global()) { + ptr_reg_after_save = ptr_reg->after_save(); + } else { + Address reg_save_addr = ptr_reg->address_in_saved_window(); + ptr_reg_after_save = L2; + st(ptr_reg, reg_save_addr); + } + + const Register& lock_reg = L3; + const Register& lock_ptr_reg = L4; + const Register& value_reg = L5; + const Register& yield_reg = L6; + const Register& yieldall_reg = L7; + + save_frame(); + + if (top_ptr_reg_after_save == L0) { + ld(top_ptr_reg->address_in_saved_window().after_save(), top_ptr_reg_after_save); + } + + if (top_reg_after_save == L1) { + ld(top_reg->address_in_saved_window().after_save(), top_reg_after_save); + } + + if (ptr_reg_after_save == L2) { + ld(ptr_reg->address_in_saved_window().after_save(), ptr_reg_after_save); + } + + Label(retry_get_lock); + Label(not_same); + Label(dont_yield); + + assert(lock_addr, "lock_address should be non null for v8"); + set((intptr_t)lock_addr, lock_ptr_reg); + // Initialize yield counter + mov(G0,yield_reg); + mov(G0, yieldall_reg); + set(StubRoutines::Sparc::locked, lock_reg); + + bind(retry_get_lock); + cmp_and_br_short(yield_reg, V8AtomicOperationUnderLockSpinCount, Assembler::less, Assembler::pt, dont_yield); + + if(use_call_vm) { + Untested("Need to verify global reg consistancy"); + call_VM(noreg, CAST_FROM_FN_PTR(address, SharedRuntime::yield_all), yieldall_reg); + } else { + // Save the regs and make space for a C call + save(SP, -96, SP); + save_all_globals_into_locals(); + call(CAST_FROM_FN_PTR(address,os::yield_all)); + delayed()->mov(yieldall_reg, O0); + restore_globals_from_locals(); + restore(); + } + + // reset the counter + mov(G0,yield_reg); + add(yieldall_reg, 1, yieldall_reg); + + bind(dont_yield); + // try to get lock + Assembler::swap(lock_ptr_reg, 0, lock_reg); + + // did we get the lock? + cmp(lock_reg, StubRoutines::Sparc::unlocked); + br(Assembler::notEqual, true, Assembler::pn, retry_get_lock); + delayed()->add(yield_reg,1,yield_reg); + + // yes, got lock. do we have the same top? + ld(top_ptr_reg_after_save, 0, value_reg); + cmp_and_br_short(value_reg, top_reg_after_save, Assembler::notEqual, Assembler::pn, not_same); + + // yes, same top. + st(ptr_reg_after_save, top_ptr_reg_after_save, 0); + membar(Assembler::StoreStore); + + bind(not_same); + mov(value_reg, ptr_reg_after_save); + st(lock_reg, lock_ptr_reg, 0); // unlock + + restore(); + } +} + +RegisterOrConstant MacroAssembler::delayed_value_impl(intptr_t* delayed_value_addr, + Register tmp, + int offset) { + intptr_t value = *delayed_value_addr; + if (value != 0) + return RegisterOrConstant(value + offset); + + // load indirectly to solve generation ordering problem + AddressLiteral a(delayed_value_addr); + load_ptr_contents(a, tmp); + +#ifdef ASSERT + tst(tmp); + breakpoint_trap(zero, xcc); +#endif + + if (offset != 0) + add(tmp, offset, tmp); + + return RegisterOrConstant(tmp); +} + + +RegisterOrConstant MacroAssembler::regcon_andn_ptr(RegisterOrConstant s1, RegisterOrConstant s2, RegisterOrConstant d, Register temp) { + assert(d.register_or_noreg() != G0, "lost side effect"); + if ((s2.is_constant() && s2.as_constant() == 0) || + (s2.is_register() && s2.as_register() == G0)) { + // Do nothing, just move value. + if (s1.is_register()) { + if (d.is_constant()) d = temp; + mov(s1.as_register(), d.as_register()); + return d; + } else { + return s1; + } + } + + if (s1.is_register()) { + assert_different_registers(s1.as_register(), temp); + if (d.is_constant()) d = temp; + andn(s1.as_register(), ensure_simm13_or_reg(s2, temp), d.as_register()); + return d; + } else { + if (s2.is_register()) { + assert_different_registers(s2.as_register(), temp); + if (d.is_constant()) d = temp; + set(s1.as_constant(), temp); + andn(temp, s2.as_register(), d.as_register()); + return d; + } else { + intptr_t res = s1.as_constant() & ~s2.as_constant(); + return res; + } + } +} + +RegisterOrConstant MacroAssembler::regcon_inc_ptr(RegisterOrConstant s1, RegisterOrConstant s2, RegisterOrConstant d, Register temp) { + assert(d.register_or_noreg() != G0, "lost side effect"); + if ((s2.is_constant() && s2.as_constant() == 0) || + (s2.is_register() && s2.as_register() == G0)) { + // Do nothing, just move value. + if (s1.is_register()) { + if (d.is_constant()) d = temp; + mov(s1.as_register(), d.as_register()); + return d; + } else { + return s1; + } + } + + if (s1.is_register()) { + assert_different_registers(s1.as_register(), temp); + if (d.is_constant()) d = temp; + add(s1.as_register(), ensure_simm13_or_reg(s2, temp), d.as_register()); + return d; + } else { + if (s2.is_register()) { + assert_different_registers(s2.as_register(), temp); + if (d.is_constant()) d = temp; + add(s2.as_register(), ensure_simm13_or_reg(s1, temp), d.as_register()); + return d; + } else { + intptr_t res = s1.as_constant() + s2.as_constant(); + return res; + } + } +} + +RegisterOrConstant MacroAssembler::regcon_sll_ptr(RegisterOrConstant s1, RegisterOrConstant s2, RegisterOrConstant d, Register temp) { + assert(d.register_or_noreg() != G0, "lost side effect"); + if (!is_simm13(s2.constant_or_zero())) + s2 = (s2.as_constant() & 0xFF); + if ((s2.is_constant() && s2.as_constant() == 0) || + (s2.is_register() && s2.as_register() == G0)) { + // Do nothing, just move value. + if (s1.is_register()) { + if (d.is_constant()) d = temp; + mov(s1.as_register(), d.as_register()); + return d; + } else { + return s1; + } + } + + if (s1.is_register()) { + assert_different_registers(s1.as_register(), temp); + if (d.is_constant()) d = temp; + sll_ptr(s1.as_register(), ensure_simm13_or_reg(s2, temp), d.as_register()); + return d; + } else { + if (s2.is_register()) { + assert_different_registers(s2.as_register(), temp); + if (d.is_constant()) d = temp; + set(s1.as_constant(), temp); + sll_ptr(temp, s2.as_register(), d.as_register()); + return d; + } else { + intptr_t res = s1.as_constant() << s2.as_constant(); + return res; + } + } +} + + +// Look up the method for a megamorphic invokeinterface call. +// The target method is determined by . +// The receiver klass is in recv_klass. +// On success, the result will be in method_result, and execution falls through. +// On failure, execution transfers to the given label. +void MacroAssembler::lookup_interface_method(Register recv_klass, + Register intf_klass, + RegisterOrConstant itable_index, + Register method_result, + Register scan_temp, + Register sethi_temp, + Label& L_no_such_interface) { + assert_different_registers(recv_klass, intf_klass, method_result, scan_temp); + assert(itable_index.is_constant() || itable_index.as_register() == method_result, + "caller must use same register for non-constant itable index as for method"); + + Label L_no_such_interface_restore; + bool did_save = false; + if (scan_temp == noreg || sethi_temp == noreg) { + Register recv_2 = recv_klass->is_global() ? recv_klass : L0; + Register intf_2 = intf_klass->is_global() ? intf_klass : L1; + assert(method_result->is_global(), "must be able to return value"); + scan_temp = L2; + sethi_temp = L3; + save_frame_and_mov(0, recv_klass, recv_2, intf_klass, intf_2); + recv_klass = recv_2; + intf_klass = intf_2; + did_save = true; + } + + // Compute start of first itableOffsetEntry (which is at the end of the vtable) + int vtable_base = InstanceKlass::vtable_start_offset() * wordSize; + int scan_step = itableOffsetEntry::size() * wordSize; + int vte_size = vtableEntry::size() * wordSize; + + lduw(recv_klass, InstanceKlass::vtable_length_offset() * wordSize, scan_temp); + // %%% We should store the aligned, prescaled offset in the klassoop. + // Then the next several instructions would fold away. + + int round_to_unit = ((HeapWordsPerLong > 1) ? BytesPerLong : 0); + int itb_offset = vtable_base; + if (round_to_unit != 0) { + // hoist first instruction of round_to(scan_temp, BytesPerLong): + itb_offset += round_to_unit - wordSize; + } + int itb_scale = exact_log2(vtableEntry::size() * wordSize); + sll(scan_temp, itb_scale, scan_temp); + add(scan_temp, itb_offset, scan_temp); + if (round_to_unit != 0) { + // Round up to align_object_offset boundary + // see code for InstanceKlass::start_of_itable! + // Was: round_to(scan_temp, BytesPerLong); + // Hoisted: add(scan_temp, BytesPerLong-1, scan_temp); + and3(scan_temp, -round_to_unit, scan_temp); + } + add(recv_klass, scan_temp, scan_temp); + + // Adjust recv_klass by scaled itable_index, so we can free itable_index. + RegisterOrConstant itable_offset = itable_index; + itable_offset = regcon_sll_ptr(itable_index, exact_log2(itableMethodEntry::size() * wordSize), itable_offset); + itable_offset = regcon_inc_ptr(itable_offset, itableMethodEntry::method_offset_in_bytes(), itable_offset); + add(recv_klass, ensure_simm13_or_reg(itable_offset, sethi_temp), recv_klass); + + // for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) { + // if (scan->interface() == intf) { + // result = (klass + scan->offset() + itable_index); + // } + // } + Label L_search, L_found_method; + + for (int peel = 1; peel >= 0; peel--) { + // %%%% Could load both offset and interface in one ldx, if they were + // in the opposite order. This would save a load. + ld_ptr(scan_temp, itableOffsetEntry::interface_offset_in_bytes(), method_result); + + // Check that this entry is non-null. A null entry means that + // the receiver class doesn't implement the interface, and wasn't the + // same as when the caller was compiled. + bpr(Assembler::rc_z, false, Assembler::pn, method_result, did_save ? L_no_such_interface_restore : L_no_such_interface); + delayed()->cmp(method_result, intf_klass); + + if (peel) { + brx(Assembler::equal, false, Assembler::pt, L_found_method); + } else { + brx(Assembler::notEqual, false, Assembler::pn, L_search); + // (invert the test to fall through to found_method...) + } + delayed()->add(scan_temp, scan_step, scan_temp); + + if (!peel) break; + + bind(L_search); + } + + bind(L_found_method); + + // Got a hit. + int ito_offset = itableOffsetEntry::offset_offset_in_bytes(); + // scan_temp[-scan_step] points to the vtable offset we need + ito_offset -= scan_step; + lduw(scan_temp, ito_offset, scan_temp); + ld_ptr(recv_klass, scan_temp, method_result); + + if (did_save) { + Label L_done; + ba(L_done); + delayed()->restore(); + + bind(L_no_such_interface_restore); + ba(L_no_such_interface); + delayed()->restore(); + + bind(L_done); + } +} + + +// virtual method calling +void MacroAssembler::lookup_virtual_method(Register recv_klass, + RegisterOrConstant vtable_index, + Register method_result) { + assert_different_registers(recv_klass, method_result, vtable_index.register_or_noreg()); + Register sethi_temp = method_result; + const int base = (InstanceKlass::vtable_start_offset() * wordSize + + // method pointer offset within the vtable entry: + vtableEntry::method_offset_in_bytes()); + RegisterOrConstant vtable_offset = vtable_index; + // Each of the following three lines potentially generates an instruction. + // But the total number of address formation instructions will always be + // at most two, and will often be zero. In any case, it will be optimal. + // If vtable_index is a register, we will have (sll_ptr N,x; inc_ptr B,x; ld_ptr k,x). + // If vtable_index is a constant, we will have at most (set B+X<is_global()) sub_2 = L0; + if (!sup_2->is_global()) sup_2 = L1; + bool did_save = false; + if (temp_reg == noreg || temp2_reg == noreg) { + temp_reg = L2; + temp2_reg = L3; + save_frame_and_mov(0, sub_klass, sub_2, super_klass, sup_2); + sub_klass = sub_2; + super_klass = sup_2; + did_save = true; + } + Label L_failure, L_pop_to_failure, L_pop_to_success; + check_klass_subtype_fast_path(sub_klass, super_klass, + temp_reg, temp2_reg, + (did_save ? &L_pop_to_success : &L_success), + (did_save ? &L_pop_to_failure : &L_failure), NULL); + + if (!did_save) + save_frame_and_mov(0, sub_klass, sub_2, super_klass, sup_2); + check_klass_subtype_slow_path(sub_2, sup_2, + L2, L3, L4, L5, + NULL, &L_pop_to_failure); + + // on success: + bind(L_pop_to_success); + restore(); + ba_short(L_success); + + // on failure: + bind(L_pop_to_failure); + restore(); + bind(L_failure); +} + + +void MacroAssembler::check_klass_subtype_fast_path(Register sub_klass, + Register super_klass, + Register temp_reg, + Register temp2_reg, + Label* L_success, + Label* L_failure, + Label* L_slow_path, + RegisterOrConstant super_check_offset) { + int sc_offset = in_bytes(Klass::secondary_super_cache_offset()); + int sco_offset = in_bytes(Klass::super_check_offset_offset()); + + bool must_load_sco = (super_check_offset.constant_or_zero() == -1); + bool need_slow_path = (must_load_sco || + super_check_offset.constant_or_zero() == sco_offset); + + assert_different_registers(sub_klass, super_klass, temp_reg); + if (super_check_offset.is_register()) { + assert_different_registers(sub_klass, super_klass, temp_reg, + super_check_offset.as_register()); + } else if (must_load_sco) { + assert(temp2_reg != noreg, "supply either a temp or a register offset"); + } + + Label L_fallthrough; + int label_nulls = 0; + if (L_success == NULL) { L_success = &L_fallthrough; label_nulls++; } + if (L_failure == NULL) { L_failure = &L_fallthrough; label_nulls++; } + if (L_slow_path == NULL) { L_slow_path = &L_fallthrough; label_nulls++; } + assert(label_nulls <= 1 || + (L_slow_path == &L_fallthrough && label_nulls <= 2 && !need_slow_path), + "at most one NULL in the batch, usually"); + + // If the pointers are equal, we are done (e.g., String[] elements). + // This self-check enables sharing of secondary supertype arrays among + // non-primary types such as array-of-interface. Otherwise, each such + // type would need its own customized SSA. + // We move this check to the front of the fast path because many + // type checks are in fact trivially successful in this manner, + // so we get a nicely predicted branch right at the start of the check. + cmp(super_klass, sub_klass); + brx(Assembler::equal, false, Assembler::pn, *L_success); + delayed()->nop(); + + // Check the supertype display: + if (must_load_sco) { + // The super check offset is always positive... + lduw(super_klass, sco_offset, temp2_reg); + super_check_offset = RegisterOrConstant(temp2_reg); + // super_check_offset is register. + assert_different_registers(sub_klass, super_klass, temp_reg, super_check_offset.as_register()); + } + ld_ptr(sub_klass, super_check_offset, temp_reg); + cmp(super_klass, temp_reg); + + // This check has worked decisively for primary supers. + // Secondary supers are sought in the super_cache ('super_cache_addr'). + // (Secondary supers are interfaces and very deeply nested subtypes.) + // This works in the same check above because of a tricky aliasing + // between the super_cache and the primary super display elements. + // (The 'super_check_addr' can address either, as the case requires.) + // Note that the cache is updated below if it does not help us find + // what we need immediately. + // So if it was a primary super, we can just fail immediately. + // Otherwise, it's the slow path for us (no success at this point). + + // Hacked ba(), which may only be used just before L_fallthrough. +#define FINAL_JUMP(label) \ + if (&(label) != &L_fallthrough) { \ + ba(label); delayed()->nop(); \ + } + + if (super_check_offset.is_register()) { + brx(Assembler::equal, false, Assembler::pn, *L_success); + delayed()->cmp(super_check_offset.as_register(), sc_offset); + + if (L_failure == &L_fallthrough) { + brx(Assembler::equal, false, Assembler::pt, *L_slow_path); + delayed()->nop(); + } else { + brx(Assembler::notEqual, false, Assembler::pn, *L_failure); + delayed()->nop(); + FINAL_JUMP(*L_slow_path); + } + } else if (super_check_offset.as_constant() == sc_offset) { + // Need a slow path; fast failure is impossible. + if (L_slow_path == &L_fallthrough) { + brx(Assembler::equal, false, Assembler::pt, *L_success); + delayed()->nop(); + } else { + brx(Assembler::notEqual, false, Assembler::pn, *L_slow_path); + delayed()->nop(); + FINAL_JUMP(*L_success); + } + } else { + // No slow path; it's a fast decision. + if (L_failure == &L_fallthrough) { + brx(Assembler::equal, false, Assembler::pt, *L_success); + delayed()->nop(); + } else { + brx(Assembler::notEqual, false, Assembler::pn, *L_failure); + delayed()->nop(); + FINAL_JUMP(*L_success); + } + } + + bind(L_fallthrough); + +#undef FINAL_JUMP +} + + +void MacroAssembler::check_klass_subtype_slow_path(Register sub_klass, + Register super_klass, + Register count_temp, + Register scan_temp, + Register scratch_reg, + Register coop_reg, + Label* L_success, + Label* L_failure) { + assert_different_registers(sub_klass, super_klass, + count_temp, scan_temp, scratch_reg, coop_reg); + + Label L_fallthrough, L_loop; + int label_nulls = 0; + if (L_success == NULL) { L_success = &L_fallthrough; label_nulls++; } + if (L_failure == NULL) { L_failure = &L_fallthrough; label_nulls++; } + assert(label_nulls <= 1, "at most one NULL in the batch"); + + // a couple of useful fields in sub_klass: + int ss_offset = in_bytes(Klass::secondary_supers_offset()); + int sc_offset = in_bytes(Klass::secondary_super_cache_offset()); + + // Do a linear scan of the secondary super-klass chain. + // This code is rarely used, so simplicity is a virtue here. + +#ifndef PRODUCT + int* pst_counter = &SharedRuntime::_partial_subtype_ctr; + inc_counter((address) pst_counter, count_temp, scan_temp); +#endif + + // We will consult the secondary-super array. + ld_ptr(sub_klass, ss_offset, scan_temp); + + Register search_key = super_klass; + + // Load the array length. (Positive movl does right thing on LP64.) + lduw(scan_temp, Array::length_offset_in_bytes(), count_temp); + + // Check for empty secondary super list + tst(count_temp); + + // In the array of super classes elements are pointer sized. + int element_size = wordSize; + + // Top of search loop + bind(L_loop); + br(Assembler::equal, false, Assembler::pn, *L_failure); + delayed()->add(scan_temp, element_size, scan_temp); + + // Skip the array header in all array accesses. + int elem_offset = Array::base_offset_in_bytes(); + elem_offset -= element_size; // the scan pointer was pre-incremented also + + // Load next super to check + ld_ptr( scan_temp, elem_offset, scratch_reg ); + + // Look for Rsuper_klass on Rsub_klass's secondary super-class-overflow list + cmp(scratch_reg, search_key); + + // A miss means we are NOT a subtype and need to keep looping + brx(Assembler::notEqual, false, Assembler::pn, L_loop); + delayed()->deccc(count_temp); // decrement trip counter in delay slot + + // Success. Cache the super we found and proceed in triumph. + st_ptr(super_klass, sub_klass, sc_offset); + + if (L_success != &L_fallthrough) { + ba(*L_success); + delayed()->nop(); + } + + bind(L_fallthrough); +} + + +RegisterOrConstant MacroAssembler::argument_offset(RegisterOrConstant arg_slot, + Register temp_reg, + int extra_slot_offset) { + // cf. TemplateTable::prepare_invoke(), if (load_receiver). + int stackElementSize = Interpreter::stackElementSize; + int offset = extra_slot_offset * stackElementSize; + if (arg_slot.is_constant()) { + offset += arg_slot.as_constant() * stackElementSize; + return offset; + } else { + assert(temp_reg != noreg, "must specify"); + sll_ptr(arg_slot.as_register(), exact_log2(stackElementSize), temp_reg); + if (offset != 0) + add(temp_reg, offset, temp_reg); + return temp_reg; + } +} + + +Address MacroAssembler::argument_address(RegisterOrConstant arg_slot, + Register temp_reg, + int extra_slot_offset) { + return Address(Gargs, argument_offset(arg_slot, temp_reg, extra_slot_offset)); +} + + +void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg, + Register temp_reg, + Label& done, Label* slow_case, + BiasedLockingCounters* counters) { + assert(UseBiasedLocking, "why call this otherwise?"); + + if (PrintBiasedLockingStatistics) { + assert_different_registers(obj_reg, mark_reg, temp_reg, O7); + if (counters == NULL) + counters = BiasedLocking::counters(); + } + + Label cas_label; + + // Biased locking + // See whether the lock is currently biased toward our thread and + // whether the epoch is still valid + // Note that the runtime guarantees sufficient alignment of JavaThread + // pointers to allow age to be placed into low bits + assert(markOopDesc::age_shift == markOopDesc::lock_bits + markOopDesc::biased_lock_bits, "biased locking makes assumptions about bit layout"); + and3(mark_reg, markOopDesc::biased_lock_mask_in_place, temp_reg); + cmp_and_brx_short(temp_reg, markOopDesc::biased_lock_pattern, Assembler::notEqual, Assembler::pn, cas_label); + + load_klass(obj_reg, temp_reg); + ld_ptr(Address(temp_reg, Klass::prototype_header_offset()), temp_reg); + or3(G2_thread, temp_reg, temp_reg); + xor3(mark_reg, temp_reg, temp_reg); + andcc(temp_reg, ~((int) markOopDesc::age_mask_in_place), temp_reg); + if (counters != NULL) { + cond_inc(Assembler::equal, (address) counters->biased_lock_entry_count_addr(), mark_reg, temp_reg); + // Reload mark_reg as we may need it later + ld_ptr(Address(obj_reg, oopDesc::mark_offset_in_bytes()), mark_reg); + } + brx(Assembler::equal, true, Assembler::pt, done); + delayed()->nop(); + + Label try_revoke_bias; + Label try_rebias; + Address mark_addr = Address(obj_reg, oopDesc::mark_offset_in_bytes()); + assert(mark_addr.disp() == 0, "cas must take a zero displacement"); + + // At this point we know that the header has the bias pattern and + // that we are not the bias owner in the current epoch. We need to + // figure out more details about the state of the header in order to + // know what operations can be legally performed on the object's + // header. + + // If the low three bits in the xor result aren't clear, that means + // the prototype header is no longer biased and we have to revoke + // the bias on this object. + btst(markOopDesc::biased_lock_mask_in_place, temp_reg); + brx(Assembler::notZero, false, Assembler::pn, try_revoke_bias); + + // Biasing is still enabled for this data type. See whether the + // epoch of the current bias is still valid, meaning that the epoch + // bits of the mark word are equal to the epoch bits of the + // prototype header. (Note that the prototype header's epoch bits + // only change at a safepoint.) If not, attempt to rebias the object + // toward the current thread. Note that we must be absolutely sure + // that the current epoch is invalid in order to do this because + // otherwise the manipulations it performs on the mark word are + // illegal. + delayed()->btst(markOopDesc::epoch_mask_in_place, temp_reg); + brx(Assembler::notZero, false, Assembler::pn, try_rebias); + + // The epoch of the current bias is still valid but we know nothing + // about the owner; it might be set or it might be clear. Try to + // acquire the bias of the object using an atomic operation. If this + // fails we will go in to the runtime to revoke the object's bias. + // Note that we first construct the presumed unbiased header so we + // don't accidentally blow away another thread's valid bias. + delayed()->and3(mark_reg, + markOopDesc::biased_lock_mask_in_place | markOopDesc::age_mask_in_place | markOopDesc::epoch_mask_in_place, + mark_reg); + or3(G2_thread, mark_reg, temp_reg); + casn(mark_addr.base(), mark_reg, temp_reg); + // If the biasing toward our thread failed, this means that + // another thread succeeded in biasing it toward itself and we + // need to revoke that bias. The revocation will occur in the + // interpreter runtime in the slow case. + cmp(mark_reg, temp_reg); + if (counters != NULL) { + cond_inc(Assembler::zero, (address) counters->anonymously_biased_lock_entry_count_addr(), mark_reg, temp_reg); + } + if (slow_case != NULL) { + brx(Assembler::notEqual, true, Assembler::pn, *slow_case); + delayed()->nop(); + } + ba_short(done); + + bind(try_rebias); + // At this point we know the epoch has expired, meaning that the + // current "bias owner", if any, is actually invalid. Under these + // circumstances _only_, we are allowed to use the current header's + // value as the comparison value when doing the cas to acquire the + // bias in the current epoch. In other words, we allow transfer of + // the bias from one thread to another directly in this situation. + // + // FIXME: due to a lack of registers we currently blow away the age + // bits in this situation. Should attempt to preserve them. + load_klass(obj_reg, temp_reg); + ld_ptr(Address(temp_reg, Klass::prototype_header_offset()), temp_reg); + or3(G2_thread, temp_reg, temp_reg); + casn(mark_addr.base(), mark_reg, temp_reg); + // If the biasing toward our thread failed, this means that + // another thread succeeded in biasing it toward itself and we + // need to revoke that bias. The revocation will occur in the + // interpreter runtime in the slow case. + cmp(mark_reg, temp_reg); + if (counters != NULL) { + cond_inc(Assembler::zero, (address) counters->rebiased_lock_entry_count_addr(), mark_reg, temp_reg); + } + if (slow_case != NULL) { + brx(Assembler::notEqual, true, Assembler::pn, *slow_case); + delayed()->nop(); + } + ba_short(done); + + bind(try_revoke_bias); + // The prototype mark in the klass doesn't have the bias bit set any + // more, indicating that objects of this data type are not supposed + // to be biased any more. We are going to try to reset the mark of + // this object to the prototype value and fall through to the + // CAS-based locking scheme. Note that if our CAS fails, it means + // that another thread raced us for the privilege of revoking the + // bias of this particular object, so it's okay to continue in the + // normal locking code. + // + // FIXME: due to a lack of registers we currently blow away the age + // bits in this situation. Should attempt to preserve them. + load_klass(obj_reg, temp_reg); + ld_ptr(Address(temp_reg, Klass::prototype_header_offset()), temp_reg); + casn(mark_addr.base(), mark_reg, temp_reg); + // Fall through to the normal CAS-based lock, because no matter what + // the result of the above CAS, some thread must have succeeded in + // removing the bias bit from the object's header. + if (counters != NULL) { + cmp(mark_reg, temp_reg); + cond_inc(Assembler::zero, (address) counters->revoked_lock_entry_count_addr(), mark_reg, temp_reg); + } + + bind(cas_label); +} + +void MacroAssembler::biased_locking_exit (Address mark_addr, Register temp_reg, Label& done, + bool allow_delay_slot_filling) { + // Check for biased locking unlock case, which is a no-op + // Note: we do not have to check the thread ID for two reasons. + // First, the interpreter checks for IllegalMonitorStateException at + // a higher level. Second, if the bias was revoked while we held the + // lock, the object could not be rebiased toward another thread, so + // the bias bit would be clear. + ld_ptr(mark_addr, temp_reg); + and3(temp_reg, markOopDesc::biased_lock_mask_in_place, temp_reg); + cmp(temp_reg, markOopDesc::biased_lock_pattern); + brx(Assembler::equal, allow_delay_slot_filling, Assembler::pt, done); + delayed(); + if (!allow_delay_slot_filling) { + nop(); + } +} + + +// CASN -- 32-64 bit switch hitter similar to the synthetic CASN provided by +// Solaris/SPARC's "as". Another apt name would be cas_ptr() + +void MacroAssembler::casn (Register addr_reg, Register cmp_reg, Register set_reg ) { + casx_under_lock (addr_reg, cmp_reg, set_reg, (address)StubRoutines::Sparc::atomic_memory_operation_lock_addr()); +} + + + +// compiler_lock_object() and compiler_unlock_object() are direct transliterations +// of i486.ad fast_lock() and fast_unlock(). See those methods for detailed comments. +// The code could be tightened up considerably. +// +// box->dhw disposition - post-conditions at DONE_LABEL. +// - Successful inflated lock: box->dhw != 0. +// Any non-zero value suffices. +// Consider G2_thread, rsp, boxReg, or unused_mark() +// - Successful Stack-lock: box->dhw == mark. +// box->dhw must contain the displaced mark word value +// - Failure -- icc.ZFlag == 0 and box->dhw is undefined. +// The slow-path fast_enter() and slow_enter() operators +// are responsible for setting box->dhw = NonZero (typically ::unused_mark). +// - Biased: box->dhw is undefined +// +// SPARC refworkload performance - specifically jetstream and scimark - are +// extremely sensitive to the size of the code emitted by compiler_lock_object +// and compiler_unlock_object. Critically, the key factor is code size, not path +// length. (Simply experiments to pad CLO with unexecuted NOPs demonstrte the +// effect). + + +void MacroAssembler::compiler_lock_object(Register Roop, Register Rmark, + Register Rbox, Register Rscratch, + BiasedLockingCounters* counters, + bool try_bias) { + Address mark_addr(Roop, oopDesc::mark_offset_in_bytes()); + + verify_oop(Roop); + Label done ; + + if (counters != NULL) { + inc_counter((address) counters->total_entry_count_addr(), Rmark, Rscratch); + } + + if (EmitSync & 1) { + mov(3, Rscratch); + st_ptr(Rscratch, Rbox, BasicLock::displaced_header_offset_in_bytes()); + cmp(SP, G0); + return ; + } + + if (EmitSync & 2) { + + // Fetch object's markword + ld_ptr(mark_addr, Rmark); + + if (try_bias) { + biased_locking_enter(Roop, Rmark, Rscratch, done, NULL, counters); + } + + // Save Rbox in Rscratch to be used for the cas operation + mov(Rbox, Rscratch); + + // set Rmark to markOop | markOopDesc::unlocked_value + or3(Rmark, markOopDesc::unlocked_value, Rmark); + + // Initialize the box. (Must happen before we update the object mark!) + st_ptr(Rmark, Rbox, BasicLock::displaced_header_offset_in_bytes()); + + // compare object markOop with Rmark and if equal exchange Rscratch with object markOop + assert(mark_addr.disp() == 0, "cas must take a zero displacement"); + casx_under_lock(mark_addr.base(), Rmark, Rscratch, + (address)StubRoutines::Sparc::atomic_memory_operation_lock_addr()); + + // if compare/exchange succeeded we found an unlocked object and we now have locked it + // hence we are done + cmp(Rmark, Rscratch); +#ifdef _LP64 + sub(Rscratch, STACK_BIAS, Rscratch); +#endif + brx(Assembler::equal, false, Assembler::pt, done); + delayed()->sub(Rscratch, SP, Rscratch); //pull next instruction into delay slot + + // we did not find an unlocked object so see if this is a recursive case + // sub(Rscratch, SP, Rscratch); + assert(os::vm_page_size() > 0xfff, "page size too small - change the constant"); + andcc(Rscratch, 0xfffff003, Rscratch); + st_ptr(Rscratch, Rbox, BasicLock::displaced_header_offset_in_bytes()); + bind (done); + return ; + } + + Label Egress ; + + if (EmitSync & 256) { + Label IsInflated ; + + ld_ptr(mark_addr, Rmark); // fetch obj->mark + // Triage: biased, stack-locked, neutral, inflated + if (try_bias) { + biased_locking_enter(Roop, Rmark, Rscratch, done, NULL, counters); + // Invariant: if control reaches this point in the emitted stream + // then Rmark has not been modified. + } + + // Store mark into displaced mark field in the on-stack basic-lock "box" + // Critically, this must happen before the CAS + // Maximize the ST-CAS distance to minimize the ST-before-CAS penalty. + st_ptr(Rmark, Rbox, BasicLock::displaced_header_offset_in_bytes()); + andcc(Rmark, 2, G0); + brx(Assembler::notZero, false, Assembler::pn, IsInflated); + delayed()-> + + // Try stack-lock acquisition. + // Beware: the 1st instruction is in a delay slot + mov(Rbox, Rscratch); + or3(Rmark, markOopDesc::unlocked_value, Rmark); + assert(mark_addr.disp() == 0, "cas must take a zero displacement"); + casn(mark_addr.base(), Rmark, Rscratch); + cmp(Rmark, Rscratch); + brx(Assembler::equal, false, Assembler::pt, done); + delayed()->sub(Rscratch, SP, Rscratch); + + // Stack-lock attempt failed - check for recursive stack-lock. + // See the comments below about how we might remove this case. +#ifdef _LP64 + sub(Rscratch, STACK_BIAS, Rscratch); +#endif + assert(os::vm_page_size() > 0xfff, "page size too small - change the constant"); + andcc(Rscratch, 0xfffff003, Rscratch); + br(Assembler::always, false, Assembler::pt, done); + delayed()-> st_ptr(Rscratch, Rbox, BasicLock::displaced_header_offset_in_bytes()); + + bind(IsInflated); + if (EmitSync & 64) { + // If m->owner != null goto IsLocked + // Pessimistic form: Test-and-CAS vs CAS + // The optimistic form avoids RTS->RTO cache line upgrades. + ld_ptr(Rmark, ObjectMonitor::owner_offset_in_bytes() - 2, Rscratch); + andcc(Rscratch, Rscratch, G0); + brx(Assembler::notZero, false, Assembler::pn, done); + delayed()->nop(); + // m->owner == null : it's unlocked. + } + + // Try to CAS m->owner from null to Self + // Invariant: if we acquire the lock then _recursions should be 0. + add(Rmark, ObjectMonitor::owner_offset_in_bytes()-2, Rmark); + mov(G2_thread, Rscratch); + casn(Rmark, G0, Rscratch); + cmp(Rscratch, G0); + // Intentional fall-through into done + } else { + // Aggressively avoid the Store-before-CAS penalty + // Defer the store into box->dhw until after the CAS + Label IsInflated, Recursive ; + +// Anticipate CAS -- Avoid RTS->RTO upgrade +// prefetch (mark_addr, Assembler::severalWritesAndPossiblyReads); + + ld_ptr(mark_addr, Rmark); // fetch obj->mark + // Triage: biased, stack-locked, neutral, inflated + + if (try_bias) { + biased_locking_enter(Roop, Rmark, Rscratch, done, NULL, counters); + // Invariant: if control reaches this point in the emitted stream + // then Rmark has not been modified. + } + andcc(Rmark, 2, G0); + brx(Assembler::notZero, false, Assembler::pn, IsInflated); + delayed()-> // Beware - dangling delay-slot + + // Try stack-lock acquisition. + // Transiently install BUSY (0) encoding in the mark word. + // if the CAS of 0 into the mark was successful then we execute: + // ST box->dhw = mark -- save fetched mark in on-stack basiclock box + // ST obj->mark = box -- overwrite transient 0 value + // This presumes TSO, of course. + + mov(0, Rscratch); + or3(Rmark, markOopDesc::unlocked_value, Rmark); + assert(mark_addr.disp() == 0, "cas must take a zero displacement"); + casn(mark_addr.base(), Rmark, Rscratch); +// prefetch (mark_addr, Assembler::severalWritesAndPossiblyReads); + cmp(Rscratch, Rmark); + brx(Assembler::notZero, false, Assembler::pn, Recursive); + delayed()->st_ptr(Rmark, Rbox, BasicLock::displaced_header_offset_in_bytes()); + if (counters != NULL) { + cond_inc(Assembler::equal, (address) counters->fast_path_entry_count_addr(), Rmark, Rscratch); + } + ba(done); + delayed()->st_ptr(Rbox, mark_addr); + + bind(Recursive); + // Stack-lock attempt failed - check for recursive stack-lock. + // Tests show that we can remove the recursive case with no impact + // on refworkload 0.83. If we need to reduce the size of the code + // emitted by compiler_lock_object() the recursive case is perfect + // candidate. + // + // A more extreme idea is to always inflate on stack-lock recursion. + // This lets us eliminate the recursive checks in compiler_lock_object + // and compiler_unlock_object and the (box->dhw == 0) encoding. + // A brief experiment - requiring changes to synchronizer.cpp, interpreter, + // and showed a performance *increase*. In the same experiment I eliminated + // the fast-path stack-lock code from the interpreter and always passed + // control to the "slow" operators in synchronizer.cpp. + + // RScratch contains the fetched obj->mark value from the failed CASN. +#ifdef _LP64 + sub(Rscratch, STACK_BIAS, Rscratch); +#endif + sub(Rscratch, SP, Rscratch); + assert(os::vm_page_size() > 0xfff, "page size too small - change the constant"); + andcc(Rscratch, 0xfffff003, Rscratch); + if (counters != NULL) { + // Accounting needs the Rscratch register + st_ptr(Rscratch, Rbox, BasicLock::displaced_header_offset_in_bytes()); + cond_inc(Assembler::equal, (address) counters->fast_path_entry_count_addr(), Rmark, Rscratch); + ba_short(done); + } else { + ba(done); + delayed()->st_ptr(Rscratch, Rbox, BasicLock::displaced_header_offset_in_bytes()); + } + + bind (IsInflated); + if (EmitSync & 64) { + // If m->owner != null goto IsLocked + // Test-and-CAS vs CAS + // Pessimistic form avoids futile (doomed) CAS attempts + // The optimistic form avoids RTS->RTO cache line upgrades. + ld_ptr(Rmark, ObjectMonitor::owner_offset_in_bytes() - 2, Rscratch); + andcc(Rscratch, Rscratch, G0); + brx(Assembler::notZero, false, Assembler::pn, done); + delayed()->nop(); + // m->owner == null : it's unlocked. + } + + // Try to CAS m->owner from null to Self + // Invariant: if we acquire the lock then _recursions should be 0. + add(Rmark, ObjectMonitor::owner_offset_in_bytes()-2, Rmark); + mov(G2_thread, Rscratch); + casn(Rmark, G0, Rscratch); + cmp(Rscratch, G0); + // ST box->displaced_header = NonZero. + // Any non-zero value suffices: + // unused_mark(), G2_thread, RBox, RScratch, rsp, etc. + st_ptr(Rbox, Rbox, BasicLock::displaced_header_offset_in_bytes()); + // Intentional fall-through into done + } + + bind (done); +} + +void MacroAssembler::compiler_unlock_object(Register Roop, Register Rmark, + Register Rbox, Register Rscratch, + bool try_bias) { + Address mark_addr(Roop, oopDesc::mark_offset_in_bytes()); + + Label done ; + + if (EmitSync & 4) { + cmp(SP, G0); + return ; + } + + if (EmitSync & 8) { + if (try_bias) { + biased_locking_exit(mark_addr, Rscratch, done); + } + + // Test first if it is a fast recursive unlock + ld_ptr(Rbox, BasicLock::displaced_header_offset_in_bytes(), Rmark); + br_null_short(Rmark, Assembler::pt, done); + + // Check if it is still a light weight lock, this is is true if we see + // the stack address of the basicLock in the markOop of the object + assert(mark_addr.disp() == 0, "cas must take a zero displacement"); + casx_under_lock(mark_addr.base(), Rbox, Rmark, + (address)StubRoutines::Sparc::atomic_memory_operation_lock_addr()); + ba(done); + delayed()->cmp(Rbox, Rmark); + bind(done); + return ; + } + + // Beware ... If the aggregate size of the code emitted by CLO and CUO is + // is too large performance rolls abruptly off a cliff. + // This could be related to inlining policies, code cache management, or + // I$ effects. + Label LStacked ; + + if (try_bias) { + // TODO: eliminate redundant LDs of obj->mark + biased_locking_exit(mark_addr, Rscratch, done); + } + + ld_ptr(Roop, oopDesc::mark_offset_in_bytes(), Rmark); + ld_ptr(Rbox, BasicLock::displaced_header_offset_in_bytes(), Rscratch); + andcc(Rscratch, Rscratch, G0); + brx(Assembler::zero, false, Assembler::pn, done); + delayed()->nop(); // consider: relocate fetch of mark, above, into this DS + andcc(Rmark, 2, G0); + brx(Assembler::zero, false, Assembler::pt, LStacked); + delayed()->nop(); + + // It's inflated + // Conceptually we need a #loadstore|#storestore "release" MEMBAR before + // the ST of 0 into _owner which releases the lock. This prevents loads + // and stores within the critical section from reordering (floating) + // past the store that releases the lock. But TSO is a strong memory model + // and that particular flavor of barrier is a noop, so we can safely elide it. + // Note that we use 1-0 locking by default for the inflated case. We + // close the resultant (and rare) race by having contented threads in + // monitorenter periodically poll _owner. + ld_ptr(Rmark, ObjectMonitor::owner_offset_in_bytes() - 2, Rscratch); + ld_ptr(Rmark, ObjectMonitor::recursions_offset_in_bytes() - 2, Rbox); + xor3(Rscratch, G2_thread, Rscratch); + orcc(Rbox, Rscratch, Rbox); + brx(Assembler::notZero, false, Assembler::pn, done); + delayed()-> + ld_ptr(Rmark, ObjectMonitor::EntryList_offset_in_bytes() - 2, Rscratch); + ld_ptr(Rmark, ObjectMonitor::cxq_offset_in_bytes() - 2, Rbox); + orcc(Rbox, Rscratch, G0); + if (EmitSync & 65536) { + Label LSucc ; + brx(Assembler::notZero, false, Assembler::pn, LSucc); + delayed()->nop(); + ba(done); + delayed()->st_ptr(G0, Rmark, ObjectMonitor::owner_offset_in_bytes() - 2); + + bind(LSucc); + st_ptr(G0, Rmark, ObjectMonitor::owner_offset_in_bytes() - 2); + if (os::is_MP()) { membar (StoreLoad); } + ld_ptr(Rmark, ObjectMonitor::succ_offset_in_bytes() - 2, Rscratch); + andcc(Rscratch, Rscratch, G0); + brx(Assembler::notZero, false, Assembler::pt, done); + delayed()->andcc(G0, G0, G0); + add(Rmark, ObjectMonitor::owner_offset_in_bytes()-2, Rmark); + mov(G2_thread, Rscratch); + casn(Rmark, G0, Rscratch); + // invert icc.zf and goto done + br_notnull(Rscratch, false, Assembler::pt, done); + delayed()->cmp(G0, G0); + ba(done); + delayed()->cmp(G0, 1); + } else { + brx(Assembler::notZero, false, Assembler::pn, done); + delayed()->nop(); + ba(done); + delayed()->st_ptr(G0, Rmark, ObjectMonitor::owner_offset_in_bytes() - 2); + } + + bind (LStacked); + // Consider: we could replace the expensive CAS in the exit + // path with a simple ST of the displaced mark value fetched from + // the on-stack basiclock box. That admits a race where a thread T2 + // in the slow lock path -- inflating with monitor M -- could race a + // thread T1 in the fast unlock path, resulting in a missed wakeup for T2. + // More precisely T1 in the stack-lock unlock path could "stomp" the + // inflated mark value M installed by T2, resulting in an orphan + // object monitor M and T2 becoming stranded. We can remedy that situation + // by having T2 periodically poll the object's mark word using timed wait + // operations. If T2 discovers that a stomp has occurred it vacates + // the monitor M and wakes any other threads stranded on the now-orphan M. + // In addition the monitor scavenger, which performs deflation, + // would also need to check for orpan monitors and stranded threads. + // + // Finally, inflation is also used when T2 needs to assign a hashCode + // to O and O is stack-locked by T1. The "stomp" race could cause + // an assigned hashCode value to be lost. We can avoid that condition + // and provide the necessary hashCode stability invariants by ensuring + // that hashCode generation is idempotent between copying GCs. + // For example we could compute the hashCode of an object O as + // O's heap address XOR some high quality RNG value that is refreshed + // at GC-time. The monitor scavenger would install the hashCode + // found in any orphan monitors. Again, the mechanism admits a + // lost-update "stomp" WAW race but detects and recovers as needed. + // + // A prototype implementation showed excellent results, although + // the scavenger and timeout code was rather involved. + + casn(mark_addr.base(), Rbox, Rscratch); + cmp(Rbox, Rscratch); + // Intentional fall through into done ... + + bind(done); +} + + + +void MacroAssembler::print_CPU_state() { + // %%%%% need to implement this +} + +void MacroAssembler::verify_FPU(int stack_depth, const char* s) { + // %%%%% need to implement this +} + +void MacroAssembler::push_IU_state() { + // %%%%% need to implement this +} + + +void MacroAssembler::pop_IU_state() { + // %%%%% need to implement this +} + + +void MacroAssembler::push_FPU_state() { + // %%%%% need to implement this +} + + +void MacroAssembler::pop_FPU_state() { + // %%%%% need to implement this +} + + +void MacroAssembler::push_CPU_state() { + // %%%%% need to implement this +} + + +void MacroAssembler::pop_CPU_state() { + // %%%%% need to implement this +} + + + +void MacroAssembler::verify_tlab() { +#ifdef ASSERT + if (UseTLAB && VerifyOops) { + Label next, next2, ok; + Register t1 = L0; + Register t2 = L1; + Register t3 = L2; + + save_frame(0); + ld_ptr(G2_thread, in_bytes(JavaThread::tlab_top_offset()), t1); + ld_ptr(G2_thread, in_bytes(JavaThread::tlab_start_offset()), t2); + or3(t1, t2, t3); + cmp_and_br_short(t1, t2, Assembler::greaterEqual, Assembler::pn, next); + STOP("assert(top >= start)"); + should_not_reach_here(); + + bind(next); + ld_ptr(G2_thread, in_bytes(JavaThread::tlab_top_offset()), t1); + ld_ptr(G2_thread, in_bytes(JavaThread::tlab_end_offset()), t2); + or3(t3, t2, t3); + cmp_and_br_short(t1, t2, Assembler::lessEqual, Assembler::pn, next2); + STOP("assert(top <= end)"); + should_not_reach_here(); + + bind(next2); + and3(t3, MinObjAlignmentInBytesMask, t3); + cmp_and_br_short(t3, 0, Assembler::lessEqual, Assembler::pn, ok); + STOP("assert(aligned)"); + should_not_reach_here(); + + bind(ok); + restore(); + } +#endif +} + + +void MacroAssembler::eden_allocate( + Register obj, // result: pointer to object after successful allocation + Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise + int con_size_in_bytes, // object size in bytes if known at compile time + Register t1, // temp register + Register t2, // temp register + Label& slow_case // continuation point if fast allocation fails +){ + // make sure arguments make sense + assert_different_registers(obj, var_size_in_bytes, t1, t2); + assert(0 <= con_size_in_bytes && Assembler::is_simm13(con_size_in_bytes), "illegal object size"); + assert((con_size_in_bytes & MinObjAlignmentInBytesMask) == 0, "object size is not multiple of alignment"); + + if (CMSIncrementalMode || !Universe::heap()->supports_inline_contig_alloc()) { + // No allocation in the shared eden. + ba_short(slow_case); + } else { + // get eden boundaries + // note: we need both top & top_addr! + const Register top_addr = t1; + const Register end = t2; + + CollectedHeap* ch = Universe::heap(); + set((intx)ch->top_addr(), top_addr); + intx delta = (intx)ch->end_addr() - (intx)ch->top_addr(); + ld_ptr(top_addr, delta, end); + ld_ptr(top_addr, 0, obj); + + // try to allocate + Label retry; + bind(retry); +#ifdef ASSERT + // make sure eden top is properly aligned + { + Label L; + btst(MinObjAlignmentInBytesMask, obj); + br(Assembler::zero, false, Assembler::pt, L); + delayed()->nop(); + STOP("eden top is not properly aligned"); + bind(L); + } +#endif // ASSERT + const Register free = end; + sub(end, obj, free); // compute amount of free space + if (var_size_in_bytes->is_valid()) { + // size is unknown at compile time + cmp(free, var_size_in_bytes); + br(Assembler::lessUnsigned, false, Assembler::pn, slow_case); // if there is not enough space go the slow case + delayed()->add(obj, var_size_in_bytes, end); + } else { + // size is known at compile time + cmp(free, con_size_in_bytes); + br(Assembler::lessUnsigned, false, Assembler::pn, slow_case); // if there is not enough space go the slow case + delayed()->add(obj, con_size_in_bytes, end); + } + // Compare obj with the value at top_addr; if still equal, swap the value of + // end with the value at top_addr. If not equal, read the value at top_addr + // into end. + casx_under_lock(top_addr, obj, end, (address)StubRoutines::Sparc::atomic_memory_operation_lock_addr()); + // if someone beat us on the allocation, try again, otherwise continue + cmp(obj, end); + brx(Assembler::notEqual, false, Assembler::pn, retry); + delayed()->mov(end, obj); // nop if successfull since obj == end + +#ifdef ASSERT + // make sure eden top is properly aligned + { + Label L; + const Register top_addr = t1; + + set((intx)ch->top_addr(), top_addr); + ld_ptr(top_addr, 0, top_addr); + btst(MinObjAlignmentInBytesMask, top_addr); + br(Assembler::zero, false, Assembler::pt, L); + delayed()->nop(); + STOP("eden top is not properly aligned"); + bind(L); + } +#endif // ASSERT + } +} + + +void MacroAssembler::tlab_allocate( + Register obj, // result: pointer to object after successful allocation + Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise + int con_size_in_bytes, // object size in bytes if known at compile time + Register t1, // temp register + Label& slow_case // continuation point if fast allocation fails +){ + // make sure arguments make sense + assert_different_registers(obj, var_size_in_bytes, t1); + assert(0 <= con_size_in_bytes && is_simm13(con_size_in_bytes), "illegal object size"); + assert((con_size_in_bytes & MinObjAlignmentInBytesMask) == 0, "object size is not multiple of alignment"); + + const Register free = t1; + + verify_tlab(); + + ld_ptr(G2_thread, in_bytes(JavaThread::tlab_top_offset()), obj); + + // calculate amount of free space + ld_ptr(G2_thread, in_bytes(JavaThread::tlab_end_offset()), free); + sub(free, obj, free); + + Label done; + if (var_size_in_bytes == noreg) { + cmp(free, con_size_in_bytes); + } else { + cmp(free, var_size_in_bytes); + } + br(Assembler::less, false, Assembler::pn, slow_case); + // calculate the new top pointer + if (var_size_in_bytes == noreg) { + delayed()->add(obj, con_size_in_bytes, free); + } else { + delayed()->add(obj, var_size_in_bytes, free); + } + + bind(done); + +#ifdef ASSERT + // make sure new free pointer is properly aligned + { + Label L; + btst(MinObjAlignmentInBytesMask, free); + br(Assembler::zero, false, Assembler::pt, L); + delayed()->nop(); + STOP("updated TLAB free is not properly aligned"); + bind(L); + } +#endif // ASSERT + + // update the tlab top pointer + st_ptr(free, G2_thread, in_bytes(JavaThread::tlab_top_offset())); + verify_tlab(); +} + + +void MacroAssembler::tlab_refill(Label& retry, Label& try_eden, Label& slow_case) { + Register top = O0; + Register t1 = G1; + Register t2 = G3; + Register t3 = O1; + assert_different_registers(top, t1, t2, t3, G4, G5 /* preserve G4 and G5 */); + Label do_refill, discard_tlab; + + if (CMSIncrementalMode || !Universe::heap()->supports_inline_contig_alloc()) { + // No allocation in the shared eden. + ba_short(slow_case); + } + + ld_ptr(G2_thread, in_bytes(JavaThread::tlab_top_offset()), top); + ld_ptr(G2_thread, in_bytes(JavaThread::tlab_end_offset()), t1); + ld_ptr(G2_thread, in_bytes(JavaThread::tlab_refill_waste_limit_offset()), t2); + + // calculate amount of free space + sub(t1, top, t1); + srl_ptr(t1, LogHeapWordSize, t1); + + // Retain tlab and allocate object in shared space if + // the amount free in the tlab is too large to discard. + cmp(t1, t2); + brx(Assembler::lessEqual, false, Assembler::pt, discard_tlab); + + // increment waste limit to prevent getting stuck on this slow path + delayed()->add(t2, ThreadLocalAllocBuffer::refill_waste_limit_increment(), t2); + st_ptr(t2, G2_thread, in_bytes(JavaThread::tlab_refill_waste_limit_offset())); + if (TLABStats) { + // increment number of slow_allocations + ld(G2_thread, in_bytes(JavaThread::tlab_slow_allocations_offset()), t2); + add(t2, 1, t2); + stw(t2, G2_thread, in_bytes(JavaThread::tlab_slow_allocations_offset())); + } + ba_short(try_eden); + + bind(discard_tlab); + if (TLABStats) { + // increment number of refills + ld(G2_thread, in_bytes(JavaThread::tlab_number_of_refills_offset()), t2); + add(t2, 1, t2); + stw(t2, G2_thread, in_bytes(JavaThread::tlab_number_of_refills_offset())); + // accumulate wastage + ld(G2_thread, in_bytes(JavaThread::tlab_fast_refill_waste_offset()), t2); + add(t2, t1, t2); + stw(t2, G2_thread, in_bytes(JavaThread::tlab_fast_refill_waste_offset())); + } + + // if tlab is currently allocated (top or end != null) then + // fill [top, end + alignment_reserve) with array object + br_null_short(top, Assembler::pn, do_refill); + + set((intptr_t)markOopDesc::prototype()->copy_set_hash(0x2), t2); + st_ptr(t2, top, oopDesc::mark_offset_in_bytes()); // set up the mark word + // set klass to intArrayKlass + sub(t1, typeArrayOopDesc::header_size(T_INT), t1); + add(t1, ThreadLocalAllocBuffer::alignment_reserve(), t1); + sll_ptr(t1, log2_intptr(HeapWordSize/sizeof(jint)), t1); + st(t1, top, arrayOopDesc::length_offset_in_bytes()); + set((intptr_t)Universe::intArrayKlassObj_addr(), t2); + ld_ptr(t2, 0, t2); + // store klass last. concurrent gcs assumes klass length is valid if + // klass field is not null. + store_klass(t2, top); + verify_oop(top); + + ld_ptr(G2_thread, in_bytes(JavaThread::tlab_start_offset()), t1); + sub(top, t1, t1); // size of tlab's allocated portion + incr_allocated_bytes(t1, t2, t3); + + // refill the tlab with an eden allocation + bind(do_refill); + ld_ptr(G2_thread, in_bytes(JavaThread::tlab_size_offset()), t1); + sll_ptr(t1, LogHeapWordSize, t1); + // allocate new tlab, address returned in top + eden_allocate(top, t1, 0, t2, t3, slow_case); + + st_ptr(top, G2_thread, in_bytes(JavaThread::tlab_start_offset())); + st_ptr(top, G2_thread, in_bytes(JavaThread::tlab_top_offset())); +#ifdef ASSERT + // check that tlab_size (t1) is still valid + { + Label ok; + ld_ptr(G2_thread, in_bytes(JavaThread::tlab_size_offset()), t2); + sll_ptr(t2, LogHeapWordSize, t2); + cmp_and_br_short(t1, t2, Assembler::equal, Assembler::pt, ok); + STOP("assert(t1 == tlab_size)"); + should_not_reach_here(); + + bind(ok); + } +#endif // ASSERT + add(top, t1, top); // t1 is tlab_size + sub(top, ThreadLocalAllocBuffer::alignment_reserve_in_bytes(), top); + st_ptr(top, G2_thread, in_bytes(JavaThread::tlab_end_offset())); + verify_tlab(); + ba_short(retry); +} + +void MacroAssembler::incr_allocated_bytes(RegisterOrConstant size_in_bytes, + Register t1, Register t2) { + // Bump total bytes allocated by this thread + assert(t1->is_global(), "must be global reg"); // so all 64 bits are saved on a context switch + assert_different_registers(size_in_bytes.register_or_noreg(), t1, t2); + // v8 support has gone the way of the dodo + ldx(G2_thread, in_bytes(JavaThread::allocated_bytes_offset()), t1); + add(t1, ensure_simm13_or_reg(size_in_bytes, t2), t1); + stx(t1, G2_thread, in_bytes(JavaThread::allocated_bytes_offset())); +} + +Assembler::Condition MacroAssembler::negate_condition(Assembler::Condition cond) { + switch (cond) { + // Note some conditions are synonyms for others + case Assembler::never: return Assembler::always; + case Assembler::zero: return Assembler::notZero; + case Assembler::lessEqual: return Assembler::greater; + case Assembler::less: return Assembler::greaterEqual; + case Assembler::lessEqualUnsigned: return Assembler::greaterUnsigned; + case Assembler::lessUnsigned: return Assembler::greaterEqualUnsigned; + case Assembler::negative: return Assembler::positive; + case Assembler::overflowSet: return Assembler::overflowClear; + case Assembler::always: return Assembler::never; + case Assembler::notZero: return Assembler::zero; + case Assembler::greater: return Assembler::lessEqual; + case Assembler::greaterEqual: return Assembler::less; + case Assembler::greaterUnsigned: return Assembler::lessEqualUnsigned; + case Assembler::greaterEqualUnsigned: return Assembler::lessUnsigned; + case Assembler::positive: return Assembler::negative; + case Assembler::overflowClear: return Assembler::overflowSet; + } + + ShouldNotReachHere(); return Assembler::overflowClear; +} + +void MacroAssembler::cond_inc(Assembler::Condition cond, address counter_ptr, + Register Rtmp1, Register Rtmp2 /*, Register Rtmp3, Register Rtmp4 */) { + Condition negated_cond = negate_condition(cond); + Label L; + brx(negated_cond, false, Assembler::pt, L); + delayed()->nop(); + inc_counter(counter_ptr, Rtmp1, Rtmp2); + bind(L); +} + +void MacroAssembler::inc_counter(address counter_addr, Register Rtmp1, Register Rtmp2) { + AddressLiteral addrlit(counter_addr); + sethi(addrlit, Rtmp1); // Move hi22 bits into temporary register. + Address addr(Rtmp1, addrlit.low10()); // Build an address with low10 bits. + ld(addr, Rtmp2); + inc(Rtmp2); + st(Rtmp2, addr); +} + +void MacroAssembler::inc_counter(int* counter_addr, Register Rtmp1, Register Rtmp2) { + inc_counter((address) counter_addr, Rtmp1, Rtmp2); +} + +SkipIfEqual::SkipIfEqual( + MacroAssembler* masm, Register temp, const bool* flag_addr, + Assembler::Condition condition) { + _masm = masm; + AddressLiteral flag(flag_addr); + _masm->sethi(flag, temp); + _masm->ldub(temp, flag.low10(), temp); + _masm->tst(temp); + _masm->br(condition, false, Assembler::pt, _label); + _masm->delayed()->nop(); +} + +SkipIfEqual::~SkipIfEqual() { + _masm->bind(_label); +} + + +// Writes to stack successive pages until offset reached to check for +// stack overflow + shadow pages. This clobbers tsp and scratch. +void MacroAssembler::bang_stack_size(Register Rsize, Register Rtsp, + Register Rscratch) { + // Use stack pointer in temp stack pointer + mov(SP, Rtsp); + + // Bang stack for total size given plus stack shadow page size. + // Bang one page at a time because a large size can overflow yellow and + // red zones (the bang will fail but stack overflow handling can't tell that + // it was a stack overflow bang vs a regular segv). + int offset = os::vm_page_size(); + Register Roffset = Rscratch; + + Label loop; + bind(loop); + set((-offset)+STACK_BIAS, Rscratch); + st(G0, Rtsp, Rscratch); + set(offset, Roffset); + sub(Rsize, Roffset, Rsize); + cmp(Rsize, G0); + br(Assembler::greater, false, Assembler::pn, loop); + delayed()->sub(Rtsp, Roffset, Rtsp); + + // Bang down shadow pages too. + // The -1 because we already subtracted 1 page. + for (int i = 0; i< StackShadowPages-1; i++) { + set((-i*offset)+STACK_BIAS, Rscratch); + st(G0, Rtsp, Rscratch); + } +} + +/////////////////////////////////////////////////////////////////////////////////// +#ifndef SERIALGC + +static address satb_log_enqueue_with_frame = NULL; +static u_char* satb_log_enqueue_with_frame_end = NULL; + +static address satb_log_enqueue_frameless = NULL; +static u_char* satb_log_enqueue_frameless_end = NULL; + +static int EnqueueCodeSize = 128 DEBUG_ONLY( + 256); // Instructions? + +static void generate_satb_log_enqueue(bool with_frame) { + BufferBlob* bb = BufferBlob::create("enqueue_with_frame", EnqueueCodeSize); + CodeBuffer buf(bb); + MacroAssembler masm(&buf); + +#define __ masm. + + address start = __ pc(); + Register pre_val; + + Label refill, restart; + if (with_frame) { + __ save_frame(0); + pre_val = I0; // Was O0 before the save. + } else { + pre_val = O0; + } + + int satb_q_index_byte_offset = + in_bytes(JavaThread::satb_mark_queue_offset() + + PtrQueue::byte_offset_of_index()); + + int satb_q_buf_byte_offset = + in_bytes(JavaThread::satb_mark_queue_offset() + + PtrQueue::byte_offset_of_buf()); + + assert(in_bytes(PtrQueue::byte_width_of_index()) == sizeof(intptr_t) && + in_bytes(PtrQueue::byte_width_of_buf()) == sizeof(intptr_t), + "check sizes in assembly below"); + + __ bind(restart); + + // Load the index into the SATB buffer. PtrQueue::_index is a size_t + // so ld_ptr is appropriate. + __ ld_ptr(G2_thread, satb_q_index_byte_offset, L0); + + // index == 0? + __ cmp_and_brx_short(L0, G0, Assembler::equal, Assembler::pn, refill); + + __ ld_ptr(G2_thread, satb_q_buf_byte_offset, L1); + __ sub(L0, oopSize, L0); + + __ st_ptr(pre_val, L1, L0); // [_buf + index] := I0 + if (!with_frame) { + // Use return-from-leaf + __ retl(); + __ delayed()->st_ptr(L0, G2_thread, satb_q_index_byte_offset); + } else { + // Not delayed. + __ st_ptr(L0, G2_thread, satb_q_index_byte_offset); + } + if (with_frame) { + __ ret(); + __ delayed()->restore(); + } + __ bind(refill); + + address handle_zero = + CAST_FROM_FN_PTR(address, + &SATBMarkQueueSet::handle_zero_index_for_thread); + // This should be rare enough that we can afford to save all the + // scratch registers that the calling context might be using. + __ mov(G1_scratch, L0); + __ mov(G3_scratch, L1); + __ mov(G4, L2); + // We need the value of O0 above (for the write into the buffer), so we + // save and restore it. + __ mov(O0, L3); + // Since the call will overwrite O7, we save and restore that, as well. + __ mov(O7, L4); + __ call_VM_leaf(L5, handle_zero, G2_thread); + __ mov(L0, G1_scratch); + __ mov(L1, G3_scratch); + __ mov(L2, G4); + __ mov(L3, O0); + __ br(Assembler::always, /*annul*/false, Assembler::pt, restart); + __ delayed()->mov(L4, O7); + + if (with_frame) { + satb_log_enqueue_with_frame = start; + satb_log_enqueue_with_frame_end = __ pc(); + } else { + satb_log_enqueue_frameless = start; + satb_log_enqueue_frameless_end = __ pc(); + } + +#undef __ +} + +static inline void generate_satb_log_enqueue_if_necessary(bool with_frame) { + if (with_frame) { + if (satb_log_enqueue_with_frame == 0) { + generate_satb_log_enqueue(with_frame); + assert(satb_log_enqueue_with_frame != 0, "postcondition."); + if (G1SATBPrintStubs) { + tty->print_cr("Generated with-frame satb enqueue:"); + Disassembler::decode((u_char*)satb_log_enqueue_with_frame, + satb_log_enqueue_with_frame_end, + tty); + } + } + } else { + if (satb_log_enqueue_frameless == 0) { + generate_satb_log_enqueue(with_frame); + assert(satb_log_enqueue_frameless != 0, "postcondition."); + if (G1SATBPrintStubs) { + tty->print_cr("Generated frameless satb enqueue:"); + Disassembler::decode((u_char*)satb_log_enqueue_frameless, + satb_log_enqueue_frameless_end, + tty); + } + } + } +} + +void MacroAssembler::g1_write_barrier_pre(Register obj, + Register index, + int offset, + Register pre_val, + Register tmp, + bool preserve_o_regs) { + Label filtered; + + if (obj == noreg) { + // We are not loading the previous value so make + // sure that we don't trash the value in pre_val + // with the code below. + assert_different_registers(pre_val, tmp); + } else { + // We will be loading the previous value + // in this code so... + assert(offset == 0 || index == noreg, "choose one"); + assert(pre_val == noreg, "check this code"); + } + + // Is marking active? + if (in_bytes(PtrQueue::byte_width_of_active()) == 4) { + ld(G2, + in_bytes(JavaThread::satb_mark_queue_offset() + + PtrQueue::byte_offset_of_active()), + tmp); + } else { + guarantee(in_bytes(PtrQueue::byte_width_of_active()) == 1, + "Assumption"); + ldsb(G2, + in_bytes(JavaThread::satb_mark_queue_offset() + + PtrQueue::byte_offset_of_active()), + tmp); + } + + // Is marking active? + cmp_and_br_short(tmp, G0, Assembler::equal, Assembler::pt, filtered); + + // Do we need to load the previous value? + if (obj != noreg) { + // Load the previous value... + if (index == noreg) { + if (Assembler::is_simm13(offset)) { + load_heap_oop(obj, offset, tmp); + } else { + set(offset, tmp); + load_heap_oop(obj, tmp, tmp); + } + } else { + load_heap_oop(obj, index, tmp); + } + // Previous value has been loaded into tmp + pre_val = tmp; + } + + assert(pre_val != noreg, "must have a real register"); + + // Is the previous value null? + cmp_and_brx_short(pre_val, G0, Assembler::equal, Assembler::pt, filtered); + + // OK, it's not filtered, so we'll need to call enqueue. In the normal + // case, pre_val will be a scratch G-reg, but there are some cases in + // which it's an O-reg. In the first case, do a normal call. In the + // latter, do a save here and call the frameless version. + + guarantee(pre_val->is_global() || pre_val->is_out(), + "Or we need to think harder."); + + if (pre_val->is_global() && !preserve_o_regs) { + generate_satb_log_enqueue_if_necessary(true); // with frame + + call(satb_log_enqueue_with_frame); + delayed()->mov(pre_val, O0); + } else { + generate_satb_log_enqueue_if_necessary(false); // frameless + + save_frame(0); + call(satb_log_enqueue_frameless); + delayed()->mov(pre_val->after_save(), O0); + restore(); + } + + bind(filtered); +} + +static address dirty_card_log_enqueue = 0; +static u_char* dirty_card_log_enqueue_end = 0; + +// This gets to assume that o0 contains the object address. +static void generate_dirty_card_log_enqueue(jbyte* byte_map_base) { + BufferBlob* bb = BufferBlob::create("dirty_card_enqueue", EnqueueCodeSize*2); + CodeBuffer buf(bb); + MacroAssembler masm(&buf); +#define __ masm. + address start = __ pc(); + + Label not_already_dirty, restart, refill; + +#ifdef _LP64 + __ srlx(O0, CardTableModRefBS::card_shift, O0); +#else + __ srl(O0, CardTableModRefBS::card_shift, O0); +#endif + AddressLiteral addrlit(byte_map_base); + __ set(addrlit, O1); // O1 := + __ ldub(O0, O1, O2); // O2 := [O0 + O1] + + assert(CardTableModRefBS::dirty_card_val() == 0, "otherwise check this code"); + __ cmp_and_br_short(O2, G0, Assembler::notEqual, Assembler::pt, not_already_dirty); + + // We didn't take the branch, so we're already dirty: return. + // Use return-from-leaf + __ retl(); + __ delayed()->nop(); + + // Not dirty. + __ bind(not_already_dirty); + + // Get O0 + O1 into a reg by itself + __ add(O0, O1, O3); + + // First, dirty it. + __ stb(G0, O3, G0); // [cardPtr] := 0 (i.e., dirty). + + int dirty_card_q_index_byte_offset = + in_bytes(JavaThread::dirty_card_queue_offset() + + PtrQueue::byte_offset_of_index()); + int dirty_card_q_buf_byte_offset = + in_bytes(JavaThread::dirty_card_queue_offset() + + PtrQueue::byte_offset_of_buf()); + __ bind(restart); + + // Load the index into the update buffer. PtrQueue::_index is + // a size_t so ld_ptr is appropriate here. + __ ld_ptr(G2_thread, dirty_card_q_index_byte_offset, L0); + + // index == 0? + __ cmp_and_brx_short(L0, G0, Assembler::equal, Assembler::pn, refill); + + __ ld_ptr(G2_thread, dirty_card_q_buf_byte_offset, L1); + __ sub(L0, oopSize, L0); + + __ st_ptr(O3, L1, L0); // [_buf + index] := I0 + // Use return-from-leaf + __ retl(); + __ delayed()->st_ptr(L0, G2_thread, dirty_card_q_index_byte_offset); + + __ bind(refill); + address handle_zero = + CAST_FROM_FN_PTR(address, + &DirtyCardQueueSet::handle_zero_index_for_thread); + // This should be rare enough that we can afford to save all the + // scratch registers that the calling context might be using. + __ mov(G1_scratch, L3); + __ mov(G3_scratch, L5); + // We need the value of O3 above (for the write into the buffer), so we + // save and restore it. + __ mov(O3, L6); + // Since the call will overwrite O7, we save and restore that, as well. + __ mov(O7, L4); + + __ call_VM_leaf(L7_thread_cache, handle_zero, G2_thread); + __ mov(L3, G1_scratch); + __ mov(L5, G3_scratch); + __ mov(L6, O3); + __ br(Assembler::always, /*annul*/false, Assembler::pt, restart); + __ delayed()->mov(L4, O7); + + dirty_card_log_enqueue = start; + dirty_card_log_enqueue_end = __ pc(); + // XXX Should have a guarantee here about not going off the end! + // Does it already do so? Do an experiment... + +#undef __ + +} + +static inline void +generate_dirty_card_log_enqueue_if_necessary(jbyte* byte_map_base) { + if (dirty_card_log_enqueue == 0) { + generate_dirty_card_log_enqueue(byte_map_base); + assert(dirty_card_log_enqueue != 0, "postcondition."); + if (G1SATBPrintStubs) { + tty->print_cr("Generated dirty_card enqueue:"); + Disassembler::decode((u_char*)dirty_card_log_enqueue, + dirty_card_log_enqueue_end, + tty); + } + } +} + + +void MacroAssembler::g1_write_barrier_post(Register store_addr, Register new_val, Register tmp) { + + Label filtered; + MacroAssembler* post_filter_masm = this; + + if (new_val == G0) return; + + G1SATBCardTableModRefBS* bs = (G1SATBCardTableModRefBS*) Universe::heap()->barrier_set(); + assert(bs->kind() == BarrierSet::G1SATBCT || + bs->kind() == BarrierSet::G1SATBCTLogging, "wrong barrier"); + + if (G1RSBarrierRegionFilter) { + xor3(store_addr, new_val, tmp); +#ifdef _LP64 + srlx(tmp, HeapRegion::LogOfHRGrainBytes, tmp); +#else + srl(tmp, HeapRegion::LogOfHRGrainBytes, tmp); +#endif + + // XXX Should I predict this taken or not? Does it matter? + cmp_and_brx_short(tmp, G0, Assembler::equal, Assembler::pt, filtered); + } + + // If the "store_addr" register is an "in" or "local" register, move it to + // a scratch reg so we can pass it as an argument. + bool use_scr = !(store_addr->is_global() || store_addr->is_out()); + // Pick a scratch register different from "tmp". + Register scr = (tmp == G1_scratch ? G3_scratch : G1_scratch); + // Make sure we use up the delay slot! + if (use_scr) { + post_filter_masm->mov(store_addr, scr); + } else { + post_filter_masm->nop(); + } + generate_dirty_card_log_enqueue_if_necessary(bs->byte_map_base); + save_frame(0); + call(dirty_card_log_enqueue); + if (use_scr) { + delayed()->mov(scr, O0); + } else { + delayed()->mov(store_addr->after_save(), O0); + } + restore(); + + bind(filtered); +} + +#endif // SERIALGC +/////////////////////////////////////////////////////////////////////////////////// + +void MacroAssembler::card_write_barrier_post(Register store_addr, Register new_val, Register tmp) { + // If we're writing constant NULL, we can skip the write barrier. + if (new_val == G0) return; + CardTableModRefBS* bs = (CardTableModRefBS*) Universe::heap()->barrier_set(); + assert(bs->kind() == BarrierSet::CardTableModRef || + bs->kind() == BarrierSet::CardTableExtension, "wrong barrier"); + card_table_write(bs->byte_map_base, tmp, store_addr); +} + +void MacroAssembler::load_klass(Register src_oop, Register klass) { + // The number of bytes in this code is used by + // MachCallDynamicJavaNode::ret_addr_offset() + // if this changes, change that. + if (UseCompressedKlassPointers) { + lduw(src_oop, oopDesc::klass_offset_in_bytes(), klass); + decode_klass_not_null(klass); + } else { + ld_ptr(src_oop, oopDesc::klass_offset_in_bytes(), klass); + } +} + +void MacroAssembler::store_klass(Register klass, Register dst_oop) { + if (UseCompressedKlassPointers) { + assert(dst_oop != klass, "not enough registers"); + encode_klass_not_null(klass); + st(klass, dst_oop, oopDesc::klass_offset_in_bytes()); + } else { + st_ptr(klass, dst_oop, oopDesc::klass_offset_in_bytes()); + } +} + +void MacroAssembler::store_klass_gap(Register s, Register d) { + if (UseCompressedKlassPointers) { + assert(s != d, "not enough registers"); + st(s, d, oopDesc::klass_gap_offset_in_bytes()); + } +} + +void MacroAssembler::load_heap_oop(const Address& s, Register d) { + if (UseCompressedOops) { + lduw(s, d); + decode_heap_oop(d); + } else { + ld_ptr(s, d); + } +} + +void MacroAssembler::load_heap_oop(Register s1, Register s2, Register d) { + if (UseCompressedOops) { + lduw(s1, s2, d); + decode_heap_oop(d, d); + } else { + ld_ptr(s1, s2, d); + } +} + +void MacroAssembler::load_heap_oop(Register s1, int simm13a, Register d) { + if (UseCompressedOops) { + lduw(s1, simm13a, d); + decode_heap_oop(d, d); + } else { + ld_ptr(s1, simm13a, d); + } +} + +void MacroAssembler::load_heap_oop(Register s1, RegisterOrConstant s2, Register d) { + if (s2.is_constant()) load_heap_oop(s1, s2.as_constant(), d); + else load_heap_oop(s1, s2.as_register(), d); +} + +void MacroAssembler::store_heap_oop(Register d, Register s1, Register s2) { + if (UseCompressedOops) { + assert(s1 != d && s2 != d, "not enough registers"); + encode_heap_oop(d); + st(d, s1, s2); + } else { + st_ptr(d, s1, s2); + } +} + +void MacroAssembler::store_heap_oop(Register d, Register s1, int simm13a) { + if (UseCompressedOops) { + assert(s1 != d, "not enough registers"); + encode_heap_oop(d); + st(d, s1, simm13a); + } else { + st_ptr(d, s1, simm13a); + } +} + +void MacroAssembler::store_heap_oop(Register d, const Address& a, int offset) { + if (UseCompressedOops) { + assert(a.base() != d, "not enough registers"); + encode_heap_oop(d); + st(d, a, offset); + } else { + st_ptr(d, a, offset); + } +} + + +void MacroAssembler::encode_heap_oop(Register src, Register dst) { + assert (UseCompressedOops, "must be compressed"); + assert (Universe::heap() != NULL, "java heap should be initialized"); + assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); + verify_oop(src); + if (Universe::narrow_oop_base() == NULL) { + srlx(src, LogMinObjAlignmentInBytes, dst); + return; + } + Label done; + if (src == dst) { + // optimize for frequent case src == dst + bpr(rc_nz, true, Assembler::pt, src, done); + delayed() -> sub(src, G6_heapbase, dst); // annuled if not taken + bind(done); + srlx(src, LogMinObjAlignmentInBytes, dst); + } else { + bpr(rc_z, false, Assembler::pn, src, done); + delayed() -> mov(G0, dst); + // could be moved before branch, and annulate delay, + // but may add some unneeded work decoding null + sub(src, G6_heapbase, dst); + srlx(dst, LogMinObjAlignmentInBytes, dst); + bind(done); + } +} + + +void MacroAssembler::encode_heap_oop_not_null(Register r) { + assert (UseCompressedOops, "must be compressed"); + assert (Universe::heap() != NULL, "java heap should be initialized"); + assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); + verify_oop(r); + if (Universe::narrow_oop_base() != NULL) + sub(r, G6_heapbase, r); + srlx(r, LogMinObjAlignmentInBytes, r); +} + +void MacroAssembler::encode_heap_oop_not_null(Register src, Register dst) { + assert (UseCompressedOops, "must be compressed"); + assert (Universe::heap() != NULL, "java heap should be initialized"); + assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); + verify_oop(src); + if (Universe::narrow_oop_base() == NULL) { + srlx(src, LogMinObjAlignmentInBytes, dst); + } else { + sub(src, G6_heapbase, dst); + srlx(dst, LogMinObjAlignmentInBytes, dst); + } +} + +// Same algorithm as oops.inline.hpp decode_heap_oop. +void MacroAssembler::decode_heap_oop(Register src, Register dst) { + assert (UseCompressedOops, "must be compressed"); + assert (Universe::heap() != NULL, "java heap should be initialized"); + assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); + sllx(src, LogMinObjAlignmentInBytes, dst); + if (Universe::narrow_oop_base() != NULL) { + Label done; + bpr(rc_nz, true, Assembler::pt, dst, done); + delayed() -> add(dst, G6_heapbase, dst); // annuled if not taken + bind(done); + } + verify_oop(dst); +} + +void MacroAssembler::decode_heap_oop_not_null(Register r) { + // Do not add assert code to this unless you change vtableStubs_sparc.cpp + // pd_code_size_limit. + // Also do not verify_oop as this is called by verify_oop. + assert (UseCompressedOops, "must be compressed"); + assert (Universe::heap() != NULL, "java heap should be initialized"); + assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); + sllx(r, LogMinObjAlignmentInBytes, r); + if (Universe::narrow_oop_base() != NULL) + add(r, G6_heapbase, r); +} + +void MacroAssembler::decode_heap_oop_not_null(Register src, Register dst) { + // Do not add assert code to this unless you change vtableStubs_sparc.cpp + // pd_code_size_limit. + // Also do not verify_oop as this is called by verify_oop. + assert (UseCompressedOops, "must be compressed"); + assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); + sllx(src, LogMinObjAlignmentInBytes, dst); + if (Universe::narrow_oop_base() != NULL) + add(dst, G6_heapbase, dst); +} + +void MacroAssembler::encode_klass_not_null(Register r) { + assert(Metaspace::is_initialized(), "metaspace should be initialized"); + assert (UseCompressedKlassPointers, "must be compressed"); + assert (LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong"); + if (Universe::narrow_klass_base() != NULL) + sub(r, G6_heapbase, r); + srlx(r, LogKlassAlignmentInBytes, r); +} + +void MacroAssembler::encode_klass_not_null(Register src, Register dst) { + assert(Metaspace::is_initialized(), "metaspace should be initialized"); + assert (UseCompressedKlassPointers, "must be compressed"); + assert (LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong"); + if (Universe::narrow_klass_base() == NULL) { + srlx(src, LogKlassAlignmentInBytes, dst); + } else { + sub(src, G6_heapbase, dst); + srlx(dst, LogKlassAlignmentInBytes, dst); + } +} + +void MacroAssembler::decode_klass_not_null(Register r) { + assert(Metaspace::is_initialized(), "metaspace should be initialized"); + // Do not add assert code to this unless you change vtableStubs_sparc.cpp + // pd_code_size_limit. + assert (UseCompressedKlassPointers, "must be compressed"); + assert (LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong"); + sllx(r, LogKlassAlignmentInBytes, r); + if (Universe::narrow_klass_base() != NULL) + add(r, G6_heapbase, r); +} + +void MacroAssembler::decode_klass_not_null(Register src, Register dst) { + assert(Metaspace::is_initialized(), "metaspace should be initialized"); + // Do not add assert code to this unless you change vtableStubs_sparc.cpp + // pd_code_size_limit. + assert (UseCompressedKlassPointers, "must be compressed"); + assert (LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong"); + sllx(src, LogKlassAlignmentInBytes, dst); + if (Universe::narrow_klass_base() != NULL) + add(dst, G6_heapbase, dst); +} + +void MacroAssembler::reinit_heapbase() { + if (UseCompressedOops || UseCompressedKlassPointers) { + AddressLiteral base(Universe::narrow_ptrs_base_addr()); + load_ptr_contents(base, G6_heapbase); + } +} + +// Compare char[] arrays aligned to 4 bytes. +void MacroAssembler::char_arrays_equals(Register ary1, Register ary2, + Register limit, Register result, + Register chr1, Register chr2, Label& Ldone) { + Label Lvector, Lloop; + assert(chr1 == result, "should be the same"); + + // Note: limit contains number of bytes (2*char_elements) != 0. + andcc(limit, 0x2, chr1); // trailing character ? + br(Assembler::zero, false, Assembler::pt, Lvector); + delayed()->nop(); + + // compare the trailing char + sub(limit, sizeof(jchar), limit); + lduh(ary1, limit, chr1); + lduh(ary2, limit, chr2); + cmp(chr1, chr2); + br(Assembler::notEqual, true, Assembler::pt, Ldone); + delayed()->mov(G0, result); // not equal + + // only one char ? + cmp_zero_and_br(zero, limit, Ldone, true, Assembler::pn); + delayed()->add(G0, 1, result); // zero-length arrays are equal + + // word by word compare, dont't need alignment check + bind(Lvector); + // Shift ary1 and ary2 to the end of the arrays, negate limit + add(ary1, limit, ary1); + add(ary2, limit, ary2); + neg(limit, limit); + + lduw(ary1, limit, chr1); + bind(Lloop); + lduw(ary2, limit, chr2); + cmp(chr1, chr2); + br(Assembler::notEqual, true, Assembler::pt, Ldone); + delayed()->mov(G0, result); // not equal + inccc(limit, 2*sizeof(jchar)); + // annul LDUW if branch is not taken to prevent access past end of array + br(Assembler::notZero, true, Assembler::pt, Lloop); + delayed()->lduw(ary1, limit, chr1); // hoisted + + // Caller should set it: + // add(G0, 1, result); // equals +} + +// Use BIS for zeroing (count is in bytes). +void MacroAssembler::bis_zeroing(Register to, Register count, Register temp, Label& Ldone) { + assert(UseBlockZeroing && VM_Version::has_block_zeroing(), "only works with BIS zeroing"); + Register end = count; + int cache_line_size = VM_Version::prefetch_data_size(); + // Minimum count when BIS zeroing can be used since + // it needs membar which is expensive. + int block_zero_size = MAX2(cache_line_size*3, (int)BlockZeroingLowLimit); + + Label small_loop; + // Check if count is negative (dead code) or zero. + // Note, count uses 64bit in 64 bit VM. + cmp_and_brx_short(count, 0, Assembler::lessEqual, Assembler::pn, Ldone); + + // Use BIS zeroing only for big arrays since it requires membar. + if (Assembler::is_simm13(block_zero_size)) { // < 4096 + cmp(count, block_zero_size); + } else { + set(block_zero_size, temp); + cmp(count, temp); + } + br(Assembler::lessUnsigned, false, Assembler::pt, small_loop); + delayed()->add(to, count, end); + + // Note: size is >= three (32 bytes) cache lines. + + // Clean the beginning of space up to next cache line. + for (int offs = 0; offs < cache_line_size; offs += 8) { + stx(G0, to, offs); + } + + // align to next cache line + add(to, cache_line_size, to); + and3(to, -cache_line_size, to); + + // Note: size left >= two (32 bytes) cache lines. + + // BIS should not be used to zero tail (64 bytes) + // to avoid zeroing a header of the following object. + sub(end, (cache_line_size*2)-8, end); + + Label bis_loop; + bind(bis_loop); + stxa(G0, to, G0, Assembler::ASI_ST_BLKINIT_PRIMARY); + add(to, cache_line_size, to); + cmp_and_brx_short(to, end, Assembler::lessUnsigned, Assembler::pt, bis_loop); + + // BIS needs membar. + membar(Assembler::StoreLoad); + + add(end, (cache_line_size*2)-8, end); // restore end + cmp_and_brx_short(to, end, Assembler::greaterEqualUnsigned, Assembler::pn, Ldone); + + // Clean the tail. + bind(small_loop); + stx(G0, to, 0); + add(to, 8, to); + cmp_and_brx_short(to, end, Assembler::lessUnsigned, Assembler::pt, small_loop); + nop(); // Separate short branches +} diff --git a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp new file mode 100644 index 00000000000..1e1e6de9e47 --- /dev/null +++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp @@ -0,0 +1,1504 @@ +/* + * Copyright (c) 1997, 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 CPU_SPARC_VM_MACROASSEMBLER_SPARC_HPP +#define CPU_SPARC_VM_MACROASSEMBLER_SPARC_HPP + +#include "asm/assembler.hpp" + +// promises that the system will not use traps 16-31 +#define ST_RESERVED_FOR_USER_0 0x10 + +class BiasedLockingCounters; + + +// Register aliases for parts of the system: + +// 64 bit values can be kept in g1-g5, o1-o5 and o7 and all 64 bits are safe +// across context switches in V8+ ABI. Of course, there are no 64 bit regs +// in V8 ABI. All 64 bits are preserved in V9 ABI for all registers. + +// g2-g4 are scratch registers called "application globals". Their +// meaning is reserved to the "compilation system"--which means us! +// They are are not supposed to be touched by ordinary C code, although +// highly-optimized C code might steal them for temps. They are safe +// across thread switches, and the ABI requires that they be safe +// across function calls. +// +// g1 and g3 are touched by more modules. V8 allows g1 to be clobbered +// across func calls, and V8+ also allows g5 to be clobbered across +// func calls. Also, g1 and g5 can get touched while doing shared +// library loading. +// +// We must not touch g7 (it is the thread-self register) and g6 is +// reserved for certain tools. g0, of course, is always zero. +// +// (Sources: SunSoft Compilers Group, thread library engineers.) + +// %%%% The interpreter should be revisited to reduce global scratch regs. + +// This global always holds the current JavaThread pointer: + +REGISTER_DECLARATION(Register, G2_thread , G2); +REGISTER_DECLARATION(Register, G6_heapbase , G6); + +// The following globals are part of the Java calling convention: + +REGISTER_DECLARATION(Register, G5_method , G5); +REGISTER_DECLARATION(Register, G5_megamorphic_method , G5_method); +REGISTER_DECLARATION(Register, G5_inline_cache_reg , G5_method); + +// The following globals are used for the new C1 & interpreter calling convention: +REGISTER_DECLARATION(Register, Gargs , G4); // pointing to the last argument + +// This local is used to preserve G2_thread in the interpreter and in stubs: +REGISTER_DECLARATION(Register, L7_thread_cache , L7); + +// These globals are used as scratch registers in the interpreter: + +REGISTER_DECLARATION(Register, Gframe_size , G1); // SAME REG as G1_scratch +REGISTER_DECLARATION(Register, G1_scratch , G1); // also SAME +REGISTER_DECLARATION(Register, G3_scratch , G3); +REGISTER_DECLARATION(Register, G4_scratch , G4); + +// These globals are used as short-lived scratch registers in the compiler: + +REGISTER_DECLARATION(Register, Gtemp , G5); + +// JSR 292 fixed register usages: +REGISTER_DECLARATION(Register, G5_method_type , G5); +REGISTER_DECLARATION(Register, G3_method_handle , G3); +REGISTER_DECLARATION(Register, L7_mh_SP_save , L7); + +// The compiler requires that G5_megamorphic_method is G5_inline_cache_klass, +// because a single patchable "set" instruction (NativeMovConstReg, +// or NativeMovConstPatching for compiler1) instruction +// serves to set up either quantity, depending on whether the compiled +// call site is an inline cache or is megamorphic. See the function +// CompiledIC::set_to_megamorphic. +// +// If a inline cache targets an interpreted method, then the +// G5 register will be used twice during the call. First, +// the call site will be patched to load a compiledICHolder +// into G5. (This is an ordered pair of ic_klass, method.) +// The c2i adapter will first check the ic_klass, then load +// G5_method with the method part of the pair just before +// jumping into the interpreter. +// +// Note that G5_method is only the method-self for the interpreter, +// and is logically unrelated to G5_megamorphic_method. +// +// Invariants on G2_thread (the JavaThread pointer): +// - it should not be used for any other purpose anywhere +// - it must be re-initialized by StubRoutines::call_stub() +// - it must be preserved around every use of call_VM + +// We can consider using g2/g3/g4 to cache more values than the +// JavaThread, such as the card-marking base or perhaps pointers into +// Eden. It's something of a waste to use them as scratch temporaries, +// since they are not supposed to be volatile. (Of course, if we find +// that Java doesn't benefit from application globals, then we can just +// use them as ordinary temporaries.) +// +// Since g1 and g5 (and/or g6) are the volatile (caller-save) registers, +// it makes sense to use them routinely for procedure linkage, +// whenever the On registers are not applicable. Examples: G5_method, +// G5_inline_cache_klass, and a double handful of miscellaneous compiler +// stubs. This means that compiler stubs, etc., should be kept to a +// maximum of two or three G-register arguments. + + +// stub frames + +REGISTER_DECLARATION(Register, Lentry_args , L0); // pointer to args passed to callee (interpreter) not stub itself + +// Interpreter frames + +#ifdef CC_INTERP +REGISTER_DECLARATION(Register, Lstate , L0); // interpreter state object pointer +REGISTER_DECLARATION(Register, L1_scratch , L1); // scratch +REGISTER_DECLARATION(Register, Lmirror , L1); // mirror (for native methods only) +REGISTER_DECLARATION(Register, L2_scratch , L2); +REGISTER_DECLARATION(Register, L3_scratch , L3); +REGISTER_DECLARATION(Register, L4_scratch , L4); +REGISTER_DECLARATION(Register, Lscratch , L5); // C1 uses +REGISTER_DECLARATION(Register, Lscratch2 , L6); // C1 uses +REGISTER_DECLARATION(Register, L7_scratch , L7); // constant pool cache +REGISTER_DECLARATION(Register, O5_savedSP , O5); +REGISTER_DECLARATION(Register, I5_savedSP , I5); // Saved SP before bumping for locals. This is simply + // a copy SP, so in 64-bit it's a biased value. The bias + // is added and removed as needed in the frame code. +// Interface to signature handler +REGISTER_DECLARATION(Register, Llocals , L7); // pointer to locals for signature handler +REGISTER_DECLARATION(Register, Lmethod , L6); // Method* when calling signature handler + +#else +REGISTER_DECLARATION(Register, Lesp , L0); // expression stack pointer +REGISTER_DECLARATION(Register, Lbcp , L1); // pointer to next bytecode +REGISTER_DECLARATION(Register, Lmethod , L2); +REGISTER_DECLARATION(Register, Llocals , L3); +REGISTER_DECLARATION(Register, Largs , L3); // pointer to locals for signature handler + // must match Llocals in asm interpreter +REGISTER_DECLARATION(Register, Lmonitors , L4); +REGISTER_DECLARATION(Register, Lbyte_code , L5); +// When calling out from the interpreter we record SP so that we can remove any extra stack +// space allocated during adapter transitions. This register is only live from the point +// of the call until we return. +REGISTER_DECLARATION(Register, Llast_SP , L5); +REGISTER_DECLARATION(Register, Lscratch , L5); +REGISTER_DECLARATION(Register, Lscratch2 , L6); +REGISTER_DECLARATION(Register, LcpoolCache , L6); // constant pool cache + +REGISTER_DECLARATION(Register, O5_savedSP , O5); +REGISTER_DECLARATION(Register, I5_savedSP , I5); // Saved SP before bumping for locals. This is simply + // a copy SP, so in 64-bit it's a biased value. The bias + // is added and removed as needed in the frame code. +REGISTER_DECLARATION(Register, IdispatchTables , I4); // Base address of the bytecode dispatch tables +REGISTER_DECLARATION(Register, IdispatchAddress , I3); // Register which saves the dispatch address for each bytecode +REGISTER_DECLARATION(Register, ImethodDataPtr , I2); // Pointer to the current method data +#endif /* CC_INTERP */ + +// NOTE: Lscratch2 and LcpoolCache point to the same registers in +// the interpreter code. If Lscratch2 needs to be used for some +// purpose than LcpoolCache should be restore after that for +// the interpreter to work right +// (These assignments must be compatible with L7_thread_cache; see above.) + +// Since Lbcp points into the middle of the method object, +// it is temporarily converted into a "bcx" during GC. + +// Exception processing +// These registers are passed into exception handlers. +// All exception handlers require the exception object being thrown. +// In addition, an nmethod's exception handler must be passed +// the address of the call site within the nmethod, to allow +// proper selection of the applicable catch block. +// (Interpreter frames use their own bcp() for this purpose.) +// +// The Oissuing_pc value is not always needed. When jumping to a +// handler that is known to be interpreted, the Oissuing_pc value can be +// omitted. An actual catch block in compiled code receives (from its +// nmethod's exception handler) the thrown exception in the Oexception, +// but it doesn't need the Oissuing_pc. +// +// If an exception handler (either interpreted or compiled) +// discovers there is no applicable catch block, it updates +// the Oissuing_pc to the continuation PC of its own caller, +// pops back to that caller's stack frame, and executes that +// caller's exception handler. Obviously, this process will +// iterate until the control stack is popped back to a method +// containing an applicable catch block. A key invariant is +// that the Oissuing_pc value is always a value local to +// the method whose exception handler is currently executing. +// +// Note: The issuing PC value is __not__ a raw return address (I7 value). +// It is a "return pc", the address __following__ the call. +// Raw return addresses are converted to issuing PCs by frame::pc(), +// or by stubs. Issuing PCs can be used directly with PC range tables. +// +REGISTER_DECLARATION(Register, Oexception , O0); // exception being thrown +REGISTER_DECLARATION(Register, Oissuing_pc , O1); // where the exception is coming from + + +// These must occur after the declarations above +#ifndef DONT_USE_REGISTER_DEFINES + +#define Gthread AS_REGISTER(Register, Gthread) +#define Gmethod AS_REGISTER(Register, Gmethod) +#define Gmegamorphic_method AS_REGISTER(Register, Gmegamorphic_method) +#define Ginline_cache_reg AS_REGISTER(Register, Ginline_cache_reg) +#define Gargs AS_REGISTER(Register, Gargs) +#define Lthread_cache AS_REGISTER(Register, Lthread_cache) +#define Gframe_size AS_REGISTER(Register, Gframe_size) +#define Gtemp AS_REGISTER(Register, Gtemp) + +#ifdef CC_INTERP +#define Lstate AS_REGISTER(Register, Lstate) +#define Lesp AS_REGISTER(Register, Lesp) +#define L1_scratch AS_REGISTER(Register, L1_scratch) +#define Lmirror AS_REGISTER(Register, Lmirror) +#define L2_scratch AS_REGISTER(Register, L2_scratch) +#define L3_scratch AS_REGISTER(Register, L3_scratch) +#define L4_scratch AS_REGISTER(Register, L4_scratch) +#define Lscratch AS_REGISTER(Register, Lscratch) +#define Lscratch2 AS_REGISTER(Register, Lscratch2) +#define L7_scratch AS_REGISTER(Register, L7_scratch) +#define Ostate AS_REGISTER(Register, Ostate) +#else +#define Lesp AS_REGISTER(Register, Lesp) +#define Lbcp AS_REGISTER(Register, Lbcp) +#define Lmethod AS_REGISTER(Register, Lmethod) +#define Llocals AS_REGISTER(Register, Llocals) +#define Lmonitors AS_REGISTER(Register, Lmonitors) +#define Lbyte_code AS_REGISTER(Register, Lbyte_code) +#define Lscratch AS_REGISTER(Register, Lscratch) +#define Lscratch2 AS_REGISTER(Register, Lscratch2) +#define LcpoolCache AS_REGISTER(Register, LcpoolCache) +#endif /* ! CC_INTERP */ + +#define Lentry_args AS_REGISTER(Register, Lentry_args) +#define I5_savedSP AS_REGISTER(Register, I5_savedSP) +#define O5_savedSP AS_REGISTER(Register, O5_savedSP) +#define IdispatchAddress AS_REGISTER(Register, IdispatchAddress) +#define ImethodDataPtr AS_REGISTER(Register, ImethodDataPtr) +#define IdispatchTables AS_REGISTER(Register, IdispatchTables) + +#define Oexception AS_REGISTER(Register, Oexception) +#define Oissuing_pc AS_REGISTER(Register, Oissuing_pc) + +#endif + + +// Address is an abstraction used to represent a memory location. +// +// Note: A register location is represented via a Register, not +// via an address for efficiency & simplicity reasons. + +class Address VALUE_OBJ_CLASS_SPEC { + private: + Register _base; // Base register. + RegisterOrConstant _index_or_disp; // Index register or constant displacement. + RelocationHolder _rspec; + + public: + Address() : _base(noreg), _index_or_disp(noreg) {} + + Address(Register base, RegisterOrConstant index_or_disp) + : _base(base), + _index_or_disp(index_or_disp) { + } + + Address(Register base, Register index) + : _base(base), + _index_or_disp(index) { + } + + Address(Register base, int disp) + : _base(base), + _index_or_disp(disp) { + } + +#ifdef ASSERT + // ByteSize is only a class when ASSERT is defined, otherwise it's an int. + Address(Register base, ByteSize disp) + : _base(base), + _index_or_disp(in_bytes(disp)) { + } +#endif + + // accessors + Register base() const { return _base; } + Register index() const { return _index_or_disp.as_register(); } + int disp() const { return _index_or_disp.as_constant(); } + + bool has_index() const { return _index_or_disp.is_register(); } + bool has_disp() const { return _index_or_disp.is_constant(); } + + bool uses(Register reg) const { return base() == reg || (has_index() && index() == reg); } + + const relocInfo::relocType rtype() { return _rspec.type(); } + const RelocationHolder& rspec() { return _rspec; } + + RelocationHolder rspec(int offset) const { + return offset == 0 ? _rspec : _rspec.plus(offset); + } + + inline bool is_simm13(int offset = 0); // check disp+offset for overflow + + Address plus_disp(int plusdisp) const { // bump disp by a small amount + assert(_index_or_disp.is_constant(), "must have a displacement"); + Address a(base(), disp() + plusdisp); + return a; + } + bool is_same_address(Address a) const { + // disregard _rspec + return base() == a.base() && (has_index() ? index() == a.index() : disp() == a.disp()); + } + + Address after_save() const { + Address a = (*this); + a._base = a._base->after_save(); + return a; + } + + Address after_restore() const { + Address a = (*this); + a._base = a._base->after_restore(); + return a; + } + + // Convert the raw encoding form into the form expected by the + // constructor for Address. + static Address make_raw(int base, int index, int scale, int disp, relocInfo::relocType disp_reloc); + + friend class Assembler; +}; + + +class AddressLiteral VALUE_OBJ_CLASS_SPEC { + private: + address _address; + RelocationHolder _rspec; + + RelocationHolder rspec_from_rtype(relocInfo::relocType rtype, address addr) { + switch (rtype) { + case relocInfo::external_word_type: + return external_word_Relocation::spec(addr); + case relocInfo::internal_word_type: + return internal_word_Relocation::spec(addr); +#ifdef _LP64 + case relocInfo::opt_virtual_call_type: + return opt_virtual_call_Relocation::spec(); + case relocInfo::static_call_type: + return static_call_Relocation::spec(); + case relocInfo::runtime_call_type: + return runtime_call_Relocation::spec(); +#endif + case relocInfo::none: + return RelocationHolder(); + default: + ShouldNotReachHere(); + return RelocationHolder(); + } + } + + protected: + // creation + AddressLiteral() : _address(NULL), _rspec(NULL) {} + + public: + AddressLiteral(address addr, RelocationHolder const& rspec) + : _address(addr), + _rspec(rspec) {} + + // Some constructors to avoid casting at the call site. + AddressLiteral(jobject obj, RelocationHolder const& rspec) + : _address((address) obj), + _rspec(rspec) {} + + AddressLiteral(intptr_t value, RelocationHolder const& rspec) + : _address((address) value), + _rspec(rspec) {} + + AddressLiteral(address addr, relocInfo::relocType rtype = relocInfo::none) + : _address((address) addr), + _rspec(rspec_from_rtype(rtype, (address) addr)) {} + + // Some constructors to avoid casting at the call site. + AddressLiteral(address* addr, relocInfo::relocType rtype = relocInfo::none) + : _address((address) addr), + _rspec(rspec_from_rtype(rtype, (address) addr)) {} + + AddressLiteral(bool* addr, relocInfo::relocType rtype = relocInfo::none) + : _address((address) addr), + _rspec(rspec_from_rtype(rtype, (address) addr)) {} + + AddressLiteral(const bool* addr, relocInfo::relocType rtype = relocInfo::none) + : _address((address) addr), + _rspec(rspec_from_rtype(rtype, (address) addr)) {} + + AddressLiteral(signed char* addr, relocInfo::relocType rtype = relocInfo::none) + : _address((address) addr), + _rspec(rspec_from_rtype(rtype, (address) addr)) {} + + AddressLiteral(int* addr, relocInfo::relocType rtype = relocInfo::none) + : _address((address) addr), + _rspec(rspec_from_rtype(rtype, (address) addr)) {} + + AddressLiteral(intptr_t addr, relocInfo::relocType rtype = relocInfo::none) + : _address((address) addr), + _rspec(rspec_from_rtype(rtype, (address) addr)) {} + +#ifdef _LP64 + // 32-bit complains about a multiple declaration for int*. + AddressLiteral(intptr_t* addr, relocInfo::relocType rtype = relocInfo::none) + : _address((address) addr), + _rspec(rspec_from_rtype(rtype, (address) addr)) {} +#endif + + AddressLiteral(Metadata* addr, relocInfo::relocType rtype = relocInfo::none) + : _address((address) addr), + _rspec(rspec_from_rtype(rtype, (address) addr)) {} + + AddressLiteral(Metadata** addr, relocInfo::relocType rtype = relocInfo::none) + : _address((address) addr), + _rspec(rspec_from_rtype(rtype, (address) addr)) {} + + AddressLiteral(float* addr, relocInfo::relocType rtype = relocInfo::none) + : _address((address) addr), + _rspec(rspec_from_rtype(rtype, (address) addr)) {} + + AddressLiteral(double* addr, relocInfo::relocType rtype = relocInfo::none) + : _address((address) addr), + _rspec(rspec_from_rtype(rtype, (address) addr)) {} + + intptr_t value() const { return (intptr_t) _address; } + int low10() const; + + const relocInfo::relocType rtype() const { return _rspec.type(); } + const RelocationHolder& rspec() const { return _rspec; } + + RelocationHolder rspec(int offset) const { + return offset == 0 ? _rspec : _rspec.plus(offset); + } +}; + +// Convenience classes +class ExternalAddress: public AddressLiteral { + private: + static relocInfo::relocType reloc_for_target(address target) { + // Sometimes ExternalAddress is used for values which aren't + // exactly addresses, like the card table base. + // external_word_type can't be used for values in the first page + // so just skip the reloc in that case. + return external_word_Relocation::can_be_relocated(target) ? relocInfo::external_word_type : relocInfo::none; + } + + public: + ExternalAddress(address target) : AddressLiteral(target, reloc_for_target( target)) {} + ExternalAddress(Metadata** target) : AddressLiteral(target, reloc_for_target((address) target)) {} +}; + +inline Address RegisterImpl::address_in_saved_window() const { + return (Address(SP, (sp_offset_in_saved_window() * wordSize) + STACK_BIAS)); +} + + + +// Argument is an abstraction used to represent an outgoing +// actual argument or an incoming formal parameter, whether +// it resides in memory or in a register, in a manner consistent +// with the SPARC Application Binary Interface, or ABI. This is +// often referred to as the native or C calling convention. + +class Argument VALUE_OBJ_CLASS_SPEC { + private: + int _number; + bool _is_in; + + public: +#ifdef _LP64 + enum { + n_register_parameters = 6, // only 6 registers may contain integer parameters + n_float_register_parameters = 16 // Can have up to 16 floating registers + }; +#else + enum { + n_register_parameters = 6 // only 6 registers may contain integer parameters + }; +#endif + + // creation + Argument(int number, bool is_in) : _number(number), _is_in(is_in) {} + + int number() const { return _number; } + bool is_in() const { return _is_in; } + bool is_out() const { return !is_in(); } + + Argument successor() const { return Argument(number() + 1, is_in()); } + Argument as_in() const { return Argument(number(), true ); } + Argument as_out() const { return Argument(number(), false); } + + // locating register-based arguments: + bool is_register() const { return _number < n_register_parameters; } + +#ifdef _LP64 + // locating Floating Point register-based arguments: + bool is_float_register() const { return _number < n_float_register_parameters; } + + FloatRegister as_float_register() const { + assert(is_float_register(), "must be a register argument"); + return as_FloatRegister(( number() *2 ) + 1); + } + FloatRegister as_double_register() const { + assert(is_float_register(), "must be a register argument"); + return as_FloatRegister(( number() *2 )); + } +#endif + + Register as_register() const { + assert(is_register(), "must be a register argument"); + return is_in() ? as_iRegister(number()) : as_oRegister(number()); + } + + // locating memory-based arguments + Address as_address() const { + assert(!is_register(), "must be a memory argument"); + return address_in_frame(); + } + + // When applied to a register-based argument, give the corresponding address + // into the 6-word area "into which callee may store register arguments" + // (This is a different place than the corresponding register-save area location.) + Address address_in_frame() const; + + // debugging + const char* name() const; + + friend class Assembler; +}; + + +class RegistersForDebugging : public StackObj { + public: + intptr_t i[8], l[8], o[8], g[8]; + float f[32]; + double d[32]; + + void print(outputStream* s); + + static int i_offset(int j) { return offset_of(RegistersForDebugging, i[j]); } + static int l_offset(int j) { return offset_of(RegistersForDebugging, l[j]); } + static int o_offset(int j) { return offset_of(RegistersForDebugging, o[j]); } + static int g_offset(int j) { return offset_of(RegistersForDebugging, g[j]); } + static int f_offset(int j) { return offset_of(RegistersForDebugging, f[j]); } + static int d_offset(int j) { return offset_of(RegistersForDebugging, d[j / 2]); } + + // gen asm code to save regs + static void save_registers(MacroAssembler* a); + + // restore global registers in case C code disturbed them + static void restore_registers(MacroAssembler* a, Register r); +}; + + +// MacroAssembler extends Assembler by a few frequently used macros. +// +// Most of the standard SPARC synthetic ops are defined here. +// Instructions for which a 'better' code sequence exists depending +// on arguments should also go in here. + +#define JMP2(r1, r2) jmp(r1, r2, __FILE__, __LINE__) +#define JMP(r1, off) jmp(r1, off, __FILE__, __LINE__) +#define JUMP(a, temp, off) jump(a, temp, off, __FILE__, __LINE__) +#define JUMPL(a, temp, d, off) jumpl(a, temp, d, off, __FILE__, __LINE__) + + +class MacroAssembler : public Assembler { + // code patchers need various routines like inv_wdisp() + friend class NativeInstruction; + friend class NativeGeneralJump; + friend class Relocation; + friend class Label; + + protected: + static void print_instruction(int inst); + static int patched_branch(int dest_pos, int inst, int inst_pos); + static int branch_destination(int inst, int pos); + + // Support for VM calls + // This is the base routine called by the different versions of call_VM_leaf. The interpreter + // may customize this version by overriding it for its purposes (e.g., to save/restore + // additional registers when doing a VM call). +#ifdef CC_INTERP + #define VIRTUAL +#else + #define VIRTUAL virtual +#endif + + VIRTUAL void call_VM_leaf_base(Register thread_cache, address entry_point, int number_of_arguments); + + // + // It is imperative that all calls into the VM are handled via the call_VM macros. + // They make sure that the stack linkage is setup correctly. call_VM's correspond + // to ENTRY/ENTRY_X entry points while call_VM_leaf's correspond to LEAF entry points. + // + // This is the base routine called by the different versions of call_VM. The interpreter + // may customize this version by overriding it for its purposes (e.g., to save/restore + // additional registers when doing a VM call). + // + // A non-volatile java_thread_cache register should be specified so + // that the G2_thread value can be preserved across the call. + // (If java_thread_cache is noreg, then a slow get_thread call + // will re-initialize the G2_thread.) call_VM_base returns the register that contains the + // thread. + // + // If no last_java_sp is specified (noreg) than SP will be used instead. + + virtual void call_VM_base( + Register oop_result, // where an oop-result ends up if any; use noreg otherwise + Register java_thread_cache, // the thread if computed before ; use noreg otherwise + Register last_java_sp, // to set up last_Java_frame in stubs; use noreg otherwise + address entry_point, // the entry point + int number_of_arguments, // the number of arguments (w/o thread) to pop after call + bool check_exception=true // flag which indicates if exception should be checked + ); + + // This routine should emit JVMTI PopFrame and ForceEarlyReturn handling code. + // The implementation is only non-empty for the InterpreterMacroAssembler, + // as only the interpreter handles and ForceEarlyReturn PopFrame requests. + virtual void check_and_handle_popframe(Register scratch_reg); + virtual void check_and_handle_earlyret(Register scratch_reg); + + public: + MacroAssembler(CodeBuffer* code) : Assembler(code) {} + + // Support for NULL-checks + // + // Generates code that causes a NULL OS exception if the content of reg is NULL. + // If the accessed location is M[reg + offset] and the offset is known, provide the + // offset. No explicit code generation is needed if the offset is within a certain + // range (0 <= offset <= page_size). + // + // %%%%%% Currently not done for SPARC + + void null_check(Register reg, int offset = -1); + static bool needs_explicit_null_check(intptr_t offset); + + // support for delayed instructions + MacroAssembler* delayed() { Assembler::delayed(); return this; } + + // branches that use right instruction for v8 vs. v9 + inline void br( Condition c, bool a, Predict p, address d, relocInfo::relocType rt = relocInfo::none ); + inline void br( Condition c, bool a, Predict p, Label& L ); + + inline void fb( Condition c, bool a, Predict p, address d, relocInfo::relocType rt = relocInfo::none ); + inline void fb( Condition c, bool a, Predict p, Label& L ); + + // compares register with zero (32 bit) and branches (V9 and V8 instructions) + void cmp_zero_and_br( Condition c, Register s1, Label& L, bool a = false, Predict p = pn ); + // Compares a pointer register with zero and branches on (not)null. + // Does a test & branch on 32-bit systems and a register-branch on 64-bit. + void br_null ( Register s1, bool a, Predict p, Label& L ); + void br_notnull( Register s1, bool a, Predict p, Label& L ); + + // + // Compare registers and branch with nop in delay slot or cbcond without delay slot. + // + // ATTENTION: use these instructions with caution because cbcond instruction + // has very short distance: 512 instructions (2Kbyte). + + // Compare integer (32 bit) values (icc only). + void cmp_and_br_short(Register s1, Register s2, Condition c, Predict p, Label& L); + void cmp_and_br_short(Register s1, int simm13a, Condition c, Predict p, Label& L); + // Platform depending version for pointer compare (icc on !LP64 and xcc on LP64). + void cmp_and_brx_short(Register s1, Register s2, Condition c, Predict p, Label& L); + void cmp_and_brx_short(Register s1, int simm13a, Condition c, Predict p, Label& L); + + // Short branch version for compares a pointer pwith zero. + void br_null_short ( Register s1, Predict p, Label& L ); + void br_notnull_short( Register s1, Predict p, Label& L ); + + // unconditional short branch + void ba_short(Label& L); + + inline void bp( Condition c, bool a, CC cc, Predict p, address d, relocInfo::relocType rt = relocInfo::none ); + inline void bp( Condition c, bool a, CC cc, Predict p, Label& L ); + + // Branch that tests xcc in LP64 and icc in !LP64 + inline void brx( Condition c, bool a, Predict p, address d, relocInfo::relocType rt = relocInfo::none ); + inline void brx( Condition c, bool a, Predict p, Label& L ); + + // unconditional branch + inline void ba( Label& L ); + + // Branch that tests fp condition codes + inline void fbp( Condition c, bool a, CC cc, Predict p, address d, relocInfo::relocType rt = relocInfo::none ); + inline void fbp( Condition c, bool a, CC cc, Predict p, Label& L ); + + // get PC the best way + inline int get_pc( Register d ); + + // Sparc shorthands(pp 85, V8 manual, pp 289 V9 manual) + inline void cmp( Register s1, Register s2 ) { subcc( s1, s2, G0 ); } + inline void cmp( Register s1, int simm13a ) { subcc( s1, simm13a, G0 ); } + + inline void jmp( Register s1, Register s2 ); + inline void jmp( Register s1, int simm13a, RelocationHolder const& rspec = RelocationHolder() ); + + // Check if the call target is out of wdisp30 range (relative to the code cache) + static inline bool is_far_target(address d); + inline void call( address d, relocInfo::relocType rt = relocInfo::runtime_call_type ); + inline void call( Label& L, relocInfo::relocType rt = relocInfo::runtime_call_type ); + inline void callr( Register s1, Register s2 ); + inline void callr( Register s1, int simm13a, RelocationHolder const& rspec = RelocationHolder() ); + + // Emits nothing on V8 + inline void iprefetch( address d, relocInfo::relocType rt = relocInfo::none ); + inline void iprefetch( Label& L); + + inline void tst( Register s ) { orcc( G0, s, G0 ); } + +#ifdef PRODUCT + inline void ret( bool trace = TraceJumps ) { if (trace) { + mov(I7, O7); // traceable register + JMP(O7, 2 * BytesPerInstWord); + } else { + jmpl( I7, 2 * BytesPerInstWord, G0 ); + } + } + + inline void retl( bool trace = TraceJumps ) { if (trace) JMP(O7, 2 * BytesPerInstWord); + else jmpl( O7, 2 * BytesPerInstWord, G0 ); } +#else + void ret( bool trace = TraceJumps ); + void retl( bool trace = TraceJumps ); +#endif /* PRODUCT */ + + // Required platform-specific helpers for Label::patch_instructions. + // They _shadow_ the declarations in AbstractAssembler, which are undefined. + void pd_patch_instruction(address branch, address target); +#ifndef PRODUCT + static void pd_print_patched_instruction(address branch); +#endif + + // sethi Macro handles optimizations and relocations +private: + void internal_sethi(const AddressLiteral& addrlit, Register d, bool ForceRelocatable); +public: + void sethi(const AddressLiteral& addrlit, Register d); + void patchable_sethi(const AddressLiteral& addrlit, Register d); + + // compute the number of instructions for a sethi/set + static int insts_for_sethi( address a, bool worst_case = false ); + static int worst_case_insts_for_set(); + + // set may be either setsw or setuw (high 32 bits may be zero or sign) +private: + void internal_set(const AddressLiteral& al, Register d, bool ForceRelocatable); + static int insts_for_internal_set(intptr_t value); +public: + void set(const AddressLiteral& addrlit, Register d); + void set(intptr_t value, Register d); + void set(address addr, Register d, RelocationHolder const& rspec); + static int insts_for_set(intptr_t value) { return insts_for_internal_set(value); } + + void patchable_set(const AddressLiteral& addrlit, Register d); + void patchable_set(intptr_t value, Register d); + void set64(jlong value, Register d, Register tmp); + static int insts_for_set64(jlong value); + + // sign-extend 32 to 64 + inline void signx( Register s, Register d ) { sra( s, G0, d); } + inline void signx( Register d ) { sra( d, G0, d); } + + inline void not1( Register s, Register d ) { xnor( s, G0, d ); } + inline void not1( Register d ) { xnor( d, G0, d ); } + + inline void neg( Register s, Register d ) { sub( G0, s, d ); } + inline void neg( Register d ) { sub( G0, d, d ); } + + inline void cas( Register s1, Register s2, Register d) { casa( s1, s2, d, ASI_PRIMARY); } + inline void casx( Register s1, Register s2, Register d) { casxa(s1, s2, d, ASI_PRIMARY); } + // Functions for isolating 64 bit atomic swaps for LP64 + // cas_ptr will perform cas for 32 bit VM's and casx for 64 bit VM's + inline void cas_ptr( Register s1, Register s2, Register d) { +#ifdef _LP64 + casx( s1, s2, d ); +#else + cas( s1, s2, d ); +#endif + } + + // Functions for isolating 64 bit shifts for LP64 + inline void sll_ptr( Register s1, Register s2, Register d ); + inline void sll_ptr( Register s1, int imm6a, Register d ); + inline void sll_ptr( Register s1, RegisterOrConstant s2, Register d ); + inline void srl_ptr( Register s1, Register s2, Register d ); + inline void srl_ptr( Register s1, int imm6a, Register d ); + + // little-endian + inline void casl( Register s1, Register s2, Register d) { casa( s1, s2, d, ASI_PRIMARY_LITTLE); } + inline void casxl( Register s1, Register s2, Register d) { casxa(s1, s2, d, ASI_PRIMARY_LITTLE); } + + inline void inc( Register d, int const13 = 1 ) { add( d, const13, d); } + inline void inccc( Register d, int const13 = 1 ) { addcc( d, const13, d); } + + inline void dec( Register d, int const13 = 1 ) { sub( d, const13, d); } + inline void deccc( Register d, int const13 = 1 ) { subcc( d, const13, d); } + + using Assembler::add; + inline void add(Register s1, int simm13a, Register d, relocInfo::relocType rtype); + inline void add(Register s1, int simm13a, Register d, RelocationHolder const& rspec); + inline void add(Register s1, RegisterOrConstant s2, Register d, int offset = 0); + inline void add(const Address& a, Register d, int offset = 0); + + using Assembler::andn; + inline void andn( Register s1, RegisterOrConstant s2, Register d); + + inline void btst( Register s1, Register s2 ) { andcc( s1, s2, G0 ); } + inline void btst( int simm13a, Register s ) { andcc( s, simm13a, G0 ); } + + inline void bset( Register s1, Register s2 ) { or3( s1, s2, s2 ); } + inline void bset( int simm13a, Register s ) { or3( s, simm13a, s ); } + + inline void bclr( Register s1, Register s2 ) { andn( s1, s2, s2 ); } + inline void bclr( int simm13a, Register s ) { andn( s, simm13a, s ); } + + inline void btog( Register s1, Register s2 ) { xor3( s1, s2, s2 ); } + inline void btog( int simm13a, Register s ) { xor3( s, simm13a, s ); } + + inline void clr( Register d ) { or3( G0, G0, d ); } + + inline void clrb( Register s1, Register s2); + inline void clrh( Register s1, Register s2); + inline void clr( Register s1, Register s2); + inline void clrx( Register s1, Register s2); + + inline void clrb( Register s1, int simm13a); + inline void clrh( Register s1, int simm13a); + inline void clr( Register s1, int simm13a); + inline void clrx( Register s1, int simm13a); + + // copy & clear upper word + inline void clruw( Register s, Register d ) { srl( s, G0, d); } + // clear upper word + inline void clruwu( Register d ) { srl( d, G0, d); } + + using Assembler::ldsb; + using Assembler::ldsh; + using Assembler::ldsw; + using Assembler::ldub; + using Assembler::lduh; + using Assembler::lduw; + using Assembler::ldx; + using Assembler::ldd; + +#ifdef ASSERT + // ByteSize is only a class when ASSERT is defined, otherwise it's an int. + inline void ld(Register s1, ByteSize simm13a, Register d); +#endif + + inline void ld(Register s1, Register s2, Register d); + inline void ld(Register s1, int simm13a, Register d); + + inline void ldsb(const Address& a, Register d, int offset = 0); + inline void ldsh(const Address& a, Register d, int offset = 0); + inline void ldsw(const Address& a, Register d, int offset = 0); + inline void ldub(const Address& a, Register d, int offset = 0); + inline void lduh(const Address& a, Register d, int offset = 0); + inline void lduw(const Address& a, Register d, int offset = 0); + inline void ldx( const Address& a, Register d, int offset = 0); + inline void ld( const Address& a, Register d, int offset = 0); + inline void ldd( const Address& a, Register d, int offset = 0); + + inline void ldub(Register s1, RegisterOrConstant s2, Register d ); + inline void ldsb(Register s1, RegisterOrConstant s2, Register d ); + inline void lduh(Register s1, RegisterOrConstant s2, Register d ); + inline void ldsh(Register s1, RegisterOrConstant s2, Register d ); + inline void lduw(Register s1, RegisterOrConstant s2, Register d ); + inline void ldsw(Register s1, RegisterOrConstant s2, Register d ); + inline void ldx( Register s1, RegisterOrConstant s2, Register d ); + inline void ld( Register s1, RegisterOrConstant s2, Register d ); + inline void ldd( Register s1, RegisterOrConstant s2, Register d ); + + using Assembler::ldf; + inline void ldf(FloatRegisterImpl::Width w, Register s1, RegisterOrConstant s2, FloatRegister d); + inline void ldf(FloatRegisterImpl::Width w, const Address& a, FloatRegister d, int offset = 0); + + // membar psuedo instruction. takes into account target memory model. + inline void membar( Assembler::Membar_mask_bits const7a ); + + // returns if membar generates anything. + inline bool membar_has_effect( Assembler::Membar_mask_bits const7a ); + + // mov pseudo instructions + inline void mov( Register s, Register d) { + if ( s != d ) or3( G0, s, d); + else assert_not_delayed(); // Put something useful in the delay slot! + } + + inline void mov_or_nop( Register s, Register d) { + if ( s != d ) or3( G0, s, d); + else nop(); + } + + inline void mov( int simm13a, Register d) { or3( G0, simm13a, d); } + + using Assembler::prefetch; + inline void prefetch(const Address& a, PrefetchFcn F, int offset = 0); + + using Assembler::stb; + using Assembler::sth; + using Assembler::stw; + using Assembler::stx; + using Assembler::std; + +#ifdef ASSERT + // ByteSize is only a class when ASSERT is defined, otherwise it's an int. + inline void st(Register d, Register s1, ByteSize simm13a); +#endif + + inline void st(Register d, Register s1, Register s2); + inline void st(Register d, Register s1, int simm13a); + + inline void stb(Register d, const Address& a, int offset = 0 ); + inline void sth(Register d, const Address& a, int offset = 0 ); + inline void stw(Register d, const Address& a, int offset = 0 ); + inline void stx(Register d, const Address& a, int offset = 0 ); + inline void st( Register d, const Address& a, int offset = 0 ); + inline void std(Register d, const Address& a, int offset = 0 ); + + inline void stb(Register d, Register s1, RegisterOrConstant s2 ); + inline void sth(Register d, Register s1, RegisterOrConstant s2 ); + inline void stw(Register d, Register s1, RegisterOrConstant s2 ); + inline void stx(Register d, Register s1, RegisterOrConstant s2 ); + inline void std(Register d, Register s1, RegisterOrConstant s2 ); + inline void st( Register d, Register s1, RegisterOrConstant s2 ); + + using Assembler::stf; + inline void stf(FloatRegisterImpl::Width w, FloatRegister d, Register s1, RegisterOrConstant s2); + inline void stf(FloatRegisterImpl::Width w, FloatRegister d, const Address& a, int offset = 0); + + // Note: offset is added to s2. + using Assembler::sub; + inline void sub(Register s1, RegisterOrConstant s2, Register d, int offset = 0); + + using Assembler::swap; + inline void swap(Address& a, Register d, int offset = 0); + + // address pseudos: make these names unlike instruction names to avoid confusion + inline intptr_t load_pc_address( Register reg, int bytes_to_skip ); + inline void load_contents(const AddressLiteral& addrlit, Register d, int offset = 0); + inline void load_bool_contents(const AddressLiteral& addrlit, Register d, int offset = 0); + inline void load_ptr_contents(const AddressLiteral& addrlit, Register d, int offset = 0); + inline void store_contents(Register s, const AddressLiteral& addrlit, Register temp, int offset = 0); + inline void store_ptr_contents(Register s, const AddressLiteral& addrlit, Register temp, int offset = 0); + inline void jumpl_to(const AddressLiteral& addrlit, Register temp, Register d, int offset = 0); + inline void jump_to(const AddressLiteral& addrlit, Register temp, int offset = 0); + inline void jump_indirect_to(Address& a, Register temp, int ld_offset = 0, int jmp_offset = 0); + + // ring buffer traceable jumps + + void jmp2( Register r1, Register r2, const char* file, int line ); + void jmp ( Register r1, int offset, const char* file, int line ); + + void jumpl(const AddressLiteral& addrlit, Register temp, Register d, int offset, const char* file, int line); + void jump (const AddressLiteral& addrlit, Register temp, int offset, const char* file, int line); + + + // argument pseudos: + + inline void load_argument( Argument& a, Register d ); + inline void store_argument( Register s, Argument& a ); + inline void store_ptr_argument( Register s, Argument& a ); + inline void store_float_argument( FloatRegister s, Argument& a ); + inline void store_double_argument( FloatRegister s, Argument& a ); + inline void store_long_argument( Register s, Argument& a ); + + // handy macros: + + inline void round_to( Register r, int modulus ) { + assert_not_delayed(); + inc( r, modulus - 1 ); + and3( r, -modulus, r ); + } + + // -------------------------------------------------- + + // Functions for isolating 64 bit loads for LP64 + // ld_ptr will perform ld for 32 bit VM's and ldx for 64 bit VM's + // st_ptr will perform st for 32 bit VM's and stx for 64 bit VM's + inline void ld_ptr(Register s1, Register s2, Register d); + inline void ld_ptr(Register s1, int simm13a, Register d); + inline void ld_ptr(Register s1, RegisterOrConstant s2, Register d); + inline void ld_ptr(const Address& a, Register d, int offset = 0); + inline void st_ptr(Register d, Register s1, Register s2); + inline void st_ptr(Register d, Register s1, int simm13a); + inline void st_ptr(Register d, Register s1, RegisterOrConstant s2); + inline void st_ptr(Register d, const Address& a, int offset = 0); + +#ifdef ASSERT + // ByteSize is only a class when ASSERT is defined, otherwise it's an int. + inline void ld_ptr(Register s1, ByteSize simm13a, Register d); + inline void st_ptr(Register d, Register s1, ByteSize simm13a); +#endif + + // ld_long will perform ldd for 32 bit VM's and ldx for 64 bit VM's + // st_long will perform std for 32 bit VM's and stx for 64 bit VM's + inline void ld_long(Register s1, Register s2, Register d); + inline void ld_long(Register s1, int simm13a, Register d); + inline void ld_long(Register s1, RegisterOrConstant s2, Register d); + inline void ld_long(const Address& a, Register d, int offset = 0); + inline void st_long(Register d, Register s1, Register s2); + inline void st_long(Register d, Register s1, int simm13a); + inline void st_long(Register d, Register s1, RegisterOrConstant s2); + inline void st_long(Register d, const Address& a, int offset = 0); + + // Helpers for address formation. + // - They emit only a move if s2 is a constant zero. + // - If dest is a constant and either s1 or s2 is a register, the temp argument is required and becomes the result. + // - If dest is a register and either s1 or s2 is a non-simm13 constant, the temp argument is required and used to materialize the constant. + RegisterOrConstant regcon_andn_ptr(RegisterOrConstant s1, RegisterOrConstant s2, RegisterOrConstant d, Register temp = noreg); + RegisterOrConstant regcon_inc_ptr( RegisterOrConstant s1, RegisterOrConstant s2, RegisterOrConstant d, Register temp = noreg); + RegisterOrConstant regcon_sll_ptr( RegisterOrConstant s1, RegisterOrConstant s2, RegisterOrConstant d, Register temp = noreg); + + RegisterOrConstant ensure_simm13_or_reg(RegisterOrConstant src, Register temp) { + if (is_simm13(src.constant_or_zero())) + return src; // register or short constant + guarantee(temp != noreg, "constant offset overflow"); + set(src.as_constant(), temp); + return temp; + } + + // -------------------------------------------------- + + public: + // traps as per trap.h (SPARC ABI?) + + void breakpoint_trap(); + void breakpoint_trap(Condition c, CC cc); + void flush_windows_trap(); + void clean_windows_trap(); + void get_psr_trap(); + void set_psr_trap(); + + // V8/V9 flush_windows + void flush_windows(); + + // Support for serializing memory accesses between threads + void serialize_memory(Register thread, Register tmp1, Register tmp2); + + // Stack frame creation/removal + void enter(); + void leave(); + + // V8/V9 integer multiply + void mult(Register s1, Register s2, Register d); + void mult(Register s1, int simm13a, Register d); + + // V8/V9 read and write of condition codes. + void read_ccr(Register d); + void write_ccr(Register s); + + // Manipulation of C++ bools + // These are idioms to flag the need for care with accessing bools but on + // this platform we assume byte size + + inline void stbool(Register d, const Address& a) { stb(d, a); } + inline void ldbool(const Address& a, Register d) { ldub(a, d); } + inline void movbool( bool boolconst, Register d) { mov( (int) boolconst, d); } + + // klass oop manipulations if compressed + void load_klass(Register src_oop, Register klass); + void store_klass(Register klass, Register dst_oop); + void store_klass_gap(Register s, Register dst_oop); + + // oop manipulations + void load_heap_oop(const Address& s, Register d); + void load_heap_oop(Register s1, Register s2, Register d); + void load_heap_oop(Register s1, int simm13a, Register d); + void load_heap_oop(Register s1, RegisterOrConstant s2, Register d); + void store_heap_oop(Register d, Register s1, Register s2); + void store_heap_oop(Register d, Register s1, int simm13a); + void store_heap_oop(Register d, const Address& a, int offset = 0); + + void encode_heap_oop(Register src, Register dst); + void encode_heap_oop(Register r) { + encode_heap_oop(r, r); + } + void decode_heap_oop(Register src, Register dst); + void decode_heap_oop(Register r) { + decode_heap_oop(r, r); + } + void encode_heap_oop_not_null(Register r); + void decode_heap_oop_not_null(Register r); + void encode_heap_oop_not_null(Register src, Register dst); + void decode_heap_oop_not_null(Register src, Register dst); + + void encode_klass_not_null(Register r); + void decode_klass_not_null(Register r); + void encode_klass_not_null(Register src, Register dst); + void decode_klass_not_null(Register src, Register dst); + + // Support for managing the JavaThread pointer (i.e.; the reference to + // thread-local information). + void get_thread(); // load G2_thread + void verify_thread(); // verify G2_thread contents + void save_thread (const Register threache); // save to cache + void restore_thread(const Register thread_cache); // restore from cache + + // Support for last Java frame (but use call_VM instead where possible) + void set_last_Java_frame(Register last_java_sp, Register last_Java_pc); + void reset_last_Java_frame(void); + + // Call into the VM. + // Passes the thread pointer (in O0) as a prepended argument. + // Makes sure oop return values are visible to the GC. + void call_VM(Register oop_result, address entry_point, int number_of_arguments = 0, bool check_exceptions = true); + void call_VM(Register oop_result, address entry_point, Register arg_1, bool check_exceptions = true); + void call_VM(Register oop_result, address entry_point, Register arg_1, Register arg_2, bool check_exceptions = true); + void call_VM(Register oop_result, address entry_point, Register arg_1, Register arg_2, Register arg_3, bool check_exceptions = true); + + // these overloadings are not presently used on SPARC: + void call_VM(Register oop_result, Register last_java_sp, address entry_point, int number_of_arguments = 0, bool check_exceptions = true); + void call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, bool check_exceptions = true); + void call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, Register arg_2, bool check_exceptions = true); + void call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, Register arg_2, Register arg_3, bool check_exceptions = true); + + void call_VM_leaf(Register thread_cache, address entry_point, int number_of_arguments = 0); + void call_VM_leaf(Register thread_cache, address entry_point, Register arg_1); + void call_VM_leaf(Register thread_cache, address entry_point, Register arg_1, Register arg_2); + void call_VM_leaf(Register thread_cache, address entry_point, Register arg_1, Register arg_2, Register arg_3); + + void get_vm_result (Register oop_result); + void get_vm_result_2(Register metadata_result); + + // vm result is currently getting hijacked to for oop preservation + void set_vm_result(Register oop_result); + + // Emit the CompiledIC call idiom + void ic_call(address entry, bool emit_delay = true); + + // if call_VM_base was called with check_exceptions=false, then call + // check_and_forward_exception to handle exceptions when it is safe + void check_and_forward_exception(Register scratch_reg); + + private: + // For V8 + void read_ccr_trap(Register ccr_save); + void write_ccr_trap(Register ccr_save1, Register scratch1, Register scratch2); + +#ifdef ASSERT + // For V8 debugging. Uses V8 instruction sequence and checks + // result with V9 insturctions rdccr and wrccr. + // Uses Gscatch and Gscatch2 + void read_ccr_v8_assert(Register ccr_save); + void write_ccr_v8_assert(Register ccr_save); +#endif // ASSERT + + public: + + // Write to card table for - register is destroyed afterwards. + void card_table_write(jbyte* byte_map_base, Register tmp, Register obj); + + void card_write_barrier_post(Register store_addr, Register new_val, Register tmp); + +#ifndef SERIALGC + // General G1 pre-barrier generator. + void g1_write_barrier_pre(Register obj, Register index, int offset, Register pre_val, Register tmp, bool preserve_o_regs); + + // General G1 post-barrier generator + void g1_write_barrier_post(Register store_addr, Register new_val, Register tmp); +#endif // SERIALGC + + // pushes double TOS element of FPU stack on CPU stack; pops from FPU stack + void push_fTOS(); + + // pops double TOS element from CPU stack and pushes on FPU stack + void pop_fTOS(); + + void empty_FPU_stack(); + + void push_IU_state(); + void pop_IU_state(); + + void push_FPU_state(); + void pop_FPU_state(); + + void push_CPU_state(); + void pop_CPU_state(); + + // if heap base register is used - reinit it with the correct value + void reinit_heapbase(); + + // Debugging + void _verify_oop(Register reg, const char * msg, const char * file, int line); + void _verify_oop_addr(Address addr, const char * msg, const char * file, int line); + + // TODO: verify_method and klass metadata (compare against vptr?) + void _verify_method_ptr(Register reg, const char * msg, const char * file, int line) {} + void _verify_klass_ptr(Register reg, const char * msg, const char * file, int line){} + +#define verify_oop(reg) _verify_oop(reg, "broken oop " #reg, __FILE__, __LINE__) +#define verify_oop_addr(addr) _verify_oop_addr(addr, "broken oop addr ", __FILE__, __LINE__) +#define verify_method_ptr(reg) _verify_method_ptr(reg, "broken method " #reg, __FILE__, __LINE__) +#define verify_klass_ptr(reg) _verify_klass_ptr(reg, "broken klass " #reg, __FILE__, __LINE__) + + // only if +VerifyOops + void verify_FPU(int stack_depth, const char* s = "illegal FPU state"); + // only if +VerifyFPU + void stop(const char* msg); // prints msg, dumps registers and stops execution + void warn(const char* msg); // prints msg, but don't stop + void untested(const char* what = ""); + void unimplemented(const char* what = "") { char* b = new char[1024]; jio_snprintf(b, 1024, "unimplemented: %s", what); stop(b); } + void should_not_reach_here() { stop("should not reach here"); } + void print_CPU_state(); + + // oops in code + AddressLiteral allocate_oop_address(jobject obj); // allocate_index + AddressLiteral constant_oop_address(jobject obj); // find_index + inline void set_oop (jobject obj, Register d); // uses allocate_oop_address + inline void set_oop_constant (jobject obj, Register d); // uses constant_oop_address + inline void set_oop (const AddressLiteral& obj_addr, Register d); // same as load_address + + // metadata in code that we have to keep track of + AddressLiteral allocate_metadata_address(Metadata* obj); // allocate_index + AddressLiteral constant_metadata_address(Metadata* obj); // find_index + inline void set_metadata (Metadata* obj, Register d); // uses allocate_metadata_address + inline void set_metadata_constant (Metadata* obj, Register d); // uses constant_metadata_address + inline void set_metadata (const AddressLiteral& obj_addr, Register d); // same as load_address + + void set_narrow_oop( jobject obj, Register d ); + void set_narrow_klass( Klass* k, Register d ); + + // nop padding + void align(int modulus); + + // declare a safepoint + void safepoint(); + + // factor out part of stop into subroutine to save space + void stop_subroutine(); + // factor out part of verify_oop into subroutine to save space + void verify_oop_subroutine(); + + // side-door communication with signalHandler in os_solaris.cpp + static address _verify_oop_implicit_branch[3]; + + int total_frame_size_in_bytes(int extraWords); + + // used when extraWords known statically + void save_frame(int extraWords = 0); + void save_frame_c1(int size_in_bytes); + // make a frame, and simultaneously pass up one or two register value + // into the new register window + void save_frame_and_mov(int extraWords, Register s1, Register d1, Register s2 = Register(), Register d2 = Register()); + + // give no. (outgoing) params, calc # of words will need on frame + void calc_mem_param_words(Register Rparam_words, Register Rresult); + + // used to calculate frame size dynamically + // result is in bytes and must be negated for save inst + void calc_frame_size(Register extraWords, Register resultReg); + + // calc and also save + void calc_frame_size_and_save(Register extraWords, Register resultReg); + + static void debug(char* msg, RegistersForDebugging* outWindow); + + // implementations of bytecodes used by both interpreter and compiler + + void lcmp( Register Ra_hi, Register Ra_low, + Register Rb_hi, Register Rb_low, + Register Rresult); + + void lneg( Register Rhi, Register Rlow ); + + void lshl( Register Rin_high, Register Rin_low, Register Rcount, + Register Rout_high, Register Rout_low, Register Rtemp ); + + void lshr( Register Rin_high, Register Rin_low, Register Rcount, + Register Rout_high, Register Rout_low, Register Rtemp ); + + void lushr( Register Rin_high, Register Rin_low, Register Rcount, + Register Rout_high, Register Rout_low, Register Rtemp ); + +#ifdef _LP64 + void lcmp( Register Ra, Register Rb, Register Rresult); +#endif + + // Load and store values by size and signed-ness + void load_sized_value( Address src, Register dst, size_t size_in_bytes, bool is_signed); + void store_sized_value(Register src, Address dst, size_t size_in_bytes); + + void float_cmp( bool is_float, int unordered_result, + FloatRegister Fa, FloatRegister Fb, + Register Rresult); + + void fneg( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d); + void fneg( FloatRegisterImpl::Width w, FloatRegister sd ) { Assembler::fneg(w, sd); } + void fmov( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d); + void fabs( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d); + + void save_all_globals_into_locals(); + void restore_globals_from_locals(); + + void casx_under_lock(Register top_ptr_reg, Register top_reg, Register ptr_reg, + address lock_addr=0, bool use_call_vm=false); + void cas_under_lock(Register top_ptr_reg, Register top_reg, Register ptr_reg, + address lock_addr=0, bool use_call_vm=false); + void casn (Register addr_reg, Register cmp_reg, Register set_reg) ; + + // These set the icc condition code to equal if the lock succeeded + // and notEqual if it failed and requires a slow case + void compiler_lock_object(Register Roop, Register Rmark, Register Rbox, + Register Rscratch, + BiasedLockingCounters* counters = NULL, + bool try_bias = UseBiasedLocking); + void compiler_unlock_object(Register Roop, Register Rmark, Register Rbox, + Register Rscratch, + bool try_bias = UseBiasedLocking); + + // Biased locking support + // Upon entry, lock_reg must point to the lock record on the stack, + // obj_reg must contain the target object, and mark_reg must contain + // the target object's header. + // Destroys mark_reg if an attempt is made to bias an anonymously + // biased lock. In this case a failure will go either to the slow + // case or fall through with the notEqual condition code set with + // the expectation that the slow case in the runtime will be called. + // In the fall-through case where the CAS-based lock is done, + // mark_reg is not destroyed. + void biased_locking_enter(Register obj_reg, Register mark_reg, Register temp_reg, + Label& done, Label* slow_case = NULL, + BiasedLockingCounters* counters = NULL); + // Upon entry, the base register of mark_addr must contain the oop. + // Destroys temp_reg. + + // If allow_delay_slot_filling is set to true, the next instruction + // emitted after this one will go in an annulled delay slot if the + // biased locking exit case failed. + void biased_locking_exit(Address mark_addr, Register temp_reg, Label& done, bool allow_delay_slot_filling = false); + + // allocation + void eden_allocate( + Register obj, // result: pointer to object after successful allocation + Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise + int con_size_in_bytes, // object size in bytes if known at compile time + Register t1, // temp register + Register t2, // temp register + Label& slow_case // continuation point if fast allocation fails + ); + void tlab_allocate( + Register obj, // result: pointer to object after successful allocation + Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise + int con_size_in_bytes, // object size in bytes if known at compile time + Register t1, // temp register + Label& slow_case // continuation point if fast allocation fails + ); + void tlab_refill(Label& retry_tlab, Label& try_eden, Label& slow_case); + void incr_allocated_bytes(RegisterOrConstant size_in_bytes, + Register t1, Register t2); + + // interface method calling + void lookup_interface_method(Register recv_klass, + Register intf_klass, + RegisterOrConstant itable_index, + Register method_result, + Register temp_reg, Register temp2_reg, + Label& no_such_interface); + + // virtual method calling + void lookup_virtual_method(Register recv_klass, + RegisterOrConstant vtable_index, + Register method_result); + + // Test sub_klass against super_klass, with fast and slow paths. + + // The fast path produces a tri-state answer: yes / no / maybe-slow. + // One of the three labels can be NULL, meaning take the fall-through. + // If super_check_offset is -1, the value is loaded up from super_klass. + // No registers are killed, except temp_reg and temp2_reg. + // If super_check_offset is not -1, temp2_reg is not used and can be noreg. + void check_klass_subtype_fast_path(Register sub_klass, + Register super_klass, + Register temp_reg, + Register temp2_reg, + Label* L_success, + Label* L_failure, + Label* L_slow_path, + RegisterOrConstant super_check_offset = RegisterOrConstant(-1)); + + // The rest of the type check; must be wired to a corresponding fast path. + // It does not repeat the fast path logic, so don't use it standalone. + // The temp_reg can be noreg, if no temps are available. + // It can also be sub_klass or super_klass, meaning it's OK to kill that one. + // Updates the sub's secondary super cache as necessary. + void check_klass_subtype_slow_path(Register sub_klass, + Register super_klass, + Register temp_reg, + Register temp2_reg, + Register temp3_reg, + Register temp4_reg, + Label* L_success, + Label* L_failure); + + // Simplified, combined version, good for typical uses. + // Falls through on failure. + void check_klass_subtype(Register sub_klass, + Register super_klass, + Register temp_reg, + Register temp2_reg, + Label& L_success); + + // method handles (JSR 292) + // offset relative to Gargs of argument at tos[arg_slot]. + // (arg_slot == 0 means the last argument, not the first). + RegisterOrConstant argument_offset(RegisterOrConstant arg_slot, + Register temp_reg, + int extra_slot_offset = 0); + // Address of Gargs and argument_offset. + Address argument_address(RegisterOrConstant arg_slot, + Register temp_reg = noreg, + int extra_slot_offset = 0); + + // Stack overflow checking + + // Note: this clobbers G3_scratch + void bang_stack_with_offset(int offset) { + // stack grows down, caller passes positive offset + assert(offset > 0, "must bang with negative offset"); + set((-offset)+STACK_BIAS, G3_scratch); + st(G0, SP, G3_scratch); + } + + // Writes to stack successive pages until offset reached to check for + // stack overflow + shadow pages. Clobbers tsp and scratch registers. + void bang_stack_size(Register Rsize, Register Rtsp, Register Rscratch); + + virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr, Register tmp, int offset); + + void verify_tlab(); + + Condition negate_condition(Condition cond); + + // Helper functions for statistics gathering. + // Conditionally (non-atomically) increments passed counter address, preserving condition codes. + void cond_inc(Condition cond, address counter_addr, Register Rtemp1, Register Rtemp2); + // Unconditional increment. + void inc_counter(address counter_addr, Register Rtmp1, Register Rtmp2); + void inc_counter(int* counter_addr, Register Rtmp1, Register Rtmp2); + + // Compare char[] arrays aligned to 4 bytes. + void char_arrays_equals(Register ary1, Register ary2, + Register limit, Register result, + Register chr1, Register chr2, Label& Ldone); + // Use BIS for zeroing + void bis_zeroing(Register to, Register count, Register temp, Label& Ldone); + +#undef VIRTUAL +}; + +/** + * class SkipIfEqual: + * + * Instantiating this class will result in assembly code being output that will + * jump around any code emitted between the creation of the instance and it's + * automatic destruction at the end of a scope block, depending on the value of + * the flag passed to the constructor, which will be checked at run-time. + */ +class SkipIfEqual : public StackObj { + private: + MacroAssembler* _masm; + Label _label; + + public: + // 'temp' is a temp register that this object can use (and trash) + SkipIfEqual(MacroAssembler*, Register temp, + const bool* flag_addr, Assembler::Condition condition); + ~SkipIfEqual(); +}; + +#endif // CPU_SPARC_VM_MACROASSEMBLER_SPARC_HPP diff --git a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.inline.hpp b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.inline.hpp new file mode 100644 index 00000000000..e9bdaea79ad --- /dev/null +++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.inline.hpp @@ -0,0 +1,765 @@ +/* + * Copyright (c) 1997, 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 CPU_SPARC_VM_MACROASSEMBLER_SPARC_INLINE_HPP +#define CPU_SPARC_VM_MACROASSEMBLER_SPARC_INLINE_HPP + +#include "asm/assembler.inline.hpp" +#include "asm/macroAssembler.hpp" +#include "asm/codeBuffer.hpp" +#include "code/codeCache.hpp" + +inline bool Address::is_simm13(int offset) { return Assembler::is_simm13(disp() + offset); } + + +inline int AddressLiteral::low10() const { + return Assembler::low10(value()); +} + + +inline void MacroAssembler::pd_patch_instruction(address branch, address target) { + jint& stub_inst = *(jint*) branch; + stub_inst = patched_branch(target - branch, stub_inst, 0); +} + +#ifndef PRODUCT +inline void MacroAssembler::pd_print_patched_instruction(address branch) { + jint stub_inst = *(jint*) branch; + print_instruction(stub_inst); + ::tty->print("%s", " (unresolved)"); +} +#endif // PRODUCT + +// Use the right loads/stores for the platform +inline void MacroAssembler::ld_ptr( Register s1, Register s2, Register d ) { +#ifdef _LP64 + Assembler::ldx(s1, s2, d); +#else + ld( s1, s2, d); +#endif +} + +inline void MacroAssembler::ld_ptr( Register s1, int simm13a, Register d ) { +#ifdef _LP64 + Assembler::ldx(s1, simm13a, d); +#else + ld( s1, simm13a, d); +#endif +} + +#ifdef ASSERT +// ByteSize is only a class when ASSERT is defined, otherwise it's an int. +inline void MacroAssembler::ld_ptr( Register s1, ByteSize simm13a, Register d ) { + ld_ptr(s1, in_bytes(simm13a), d); +} +#endif + +inline void MacroAssembler::ld_ptr( Register s1, RegisterOrConstant s2, Register d ) { +#ifdef _LP64 + ldx(s1, s2, d); +#else + ld( s1, s2, d); +#endif +} + +inline void MacroAssembler::ld_ptr(const Address& a, Register d, int offset) { +#ifdef _LP64 + ldx(a, d, offset); +#else + ld( a, d, offset); +#endif +} + +inline void MacroAssembler::st_ptr( Register d, Register s1, Register s2 ) { +#ifdef _LP64 + Assembler::stx(d, s1, s2); +#else + st( d, s1, s2); +#endif +} + +inline void MacroAssembler::st_ptr( Register d, Register s1, int simm13a ) { +#ifdef _LP64 + Assembler::stx(d, s1, simm13a); +#else + st( d, s1, simm13a); +#endif +} + +#ifdef ASSERT +// ByteSize is only a class when ASSERT is defined, otherwise it's an int. +inline void MacroAssembler::st_ptr( Register d, Register s1, ByteSize simm13a ) { + st_ptr(d, s1, in_bytes(simm13a)); +} +#endif + +inline void MacroAssembler::st_ptr( Register d, Register s1, RegisterOrConstant s2 ) { +#ifdef _LP64 + stx(d, s1, s2); +#else + st( d, s1, s2); +#endif +} + +inline void MacroAssembler::st_ptr(Register d, const Address& a, int offset) { +#ifdef _LP64 + stx(d, a, offset); +#else + st( d, a, offset); +#endif +} + +// Use the right loads/stores for the platform +inline void MacroAssembler::ld_long( Register s1, Register s2, Register d ) { +#ifdef _LP64 + Assembler::ldx(s1, s2, d); +#else + Assembler::ldd(s1, s2, d); +#endif +} + +inline void MacroAssembler::ld_long( Register s1, int simm13a, Register d ) { +#ifdef _LP64 + Assembler::ldx(s1, simm13a, d); +#else + Assembler::ldd(s1, simm13a, d); +#endif +} + +inline void MacroAssembler::ld_long( Register s1, RegisterOrConstant s2, Register d ) { +#ifdef _LP64 + ldx(s1, s2, d); +#else + ldd(s1, s2, d); +#endif +} + +inline void MacroAssembler::ld_long(const Address& a, Register d, int offset) { +#ifdef _LP64 + ldx(a, d, offset); +#else + ldd(a, d, offset); +#endif +} + +inline void MacroAssembler::st_long( Register d, Register s1, Register s2 ) { +#ifdef _LP64 + Assembler::stx(d, s1, s2); +#else + Assembler::std(d, s1, s2); +#endif +} + +inline void MacroAssembler::st_long( Register d, Register s1, int simm13a ) { +#ifdef _LP64 + Assembler::stx(d, s1, simm13a); +#else + Assembler::std(d, s1, simm13a); +#endif +} + +inline void MacroAssembler::st_long( Register d, Register s1, RegisterOrConstant s2 ) { +#ifdef _LP64 + stx(d, s1, s2); +#else + std(d, s1, s2); +#endif +} + +inline void MacroAssembler::st_long( Register d, const Address& a, int offset ) { +#ifdef _LP64 + stx(d, a, offset); +#else + std(d, a, offset); +#endif +} + +// Functions for isolating 64 bit shifts for LP64 + +inline void MacroAssembler::sll_ptr( Register s1, Register s2, Register d ) { +#ifdef _LP64 + Assembler::sllx(s1, s2, d); +#else + Assembler::sll( s1, s2, d); +#endif +} + +inline void MacroAssembler::sll_ptr( Register s1, int imm6a, Register d ) { +#ifdef _LP64 + Assembler::sllx(s1, imm6a, d); +#else + Assembler::sll( s1, imm6a, d); +#endif +} + +inline void MacroAssembler::srl_ptr( Register s1, Register s2, Register d ) { +#ifdef _LP64 + Assembler::srlx(s1, s2, d); +#else + Assembler::srl( s1, s2, d); +#endif +} + +inline void MacroAssembler::srl_ptr( Register s1, int imm6a, Register d ) { +#ifdef _LP64 + Assembler::srlx(s1, imm6a, d); +#else + Assembler::srl( s1, imm6a, d); +#endif +} + +inline void MacroAssembler::sll_ptr( Register s1, RegisterOrConstant s2, Register d ) { + if (s2.is_register()) sll_ptr(s1, s2.as_register(), d); + else sll_ptr(s1, s2.as_constant(), d); +} + +// Use the right branch for the platform + +inline void MacroAssembler::br( Condition c, bool a, Predict p, address d, relocInfo::relocType rt ) { + if (VM_Version::v9_instructions_work()) + Assembler::bp(c, a, icc, p, d, rt); + else + Assembler::br(c, a, d, rt); +} + +inline void MacroAssembler::br( Condition c, bool a, Predict p, Label& L ) { + br(c, a, p, target(L)); +} + + +// Branch that tests either xcc or icc depending on the +// architecture compiled (LP64 or not) +inline void MacroAssembler::brx( Condition c, bool a, Predict p, address d, relocInfo::relocType rt ) { +#ifdef _LP64 + Assembler::bp(c, a, xcc, p, d, rt); +#else + MacroAssembler::br(c, a, p, d, rt); +#endif +} + +inline void MacroAssembler::brx( Condition c, bool a, Predict p, Label& L ) { + brx(c, a, p, target(L)); +} + +inline void MacroAssembler::ba( Label& L ) { + br(always, false, pt, L); +} + +// Warning: V9 only functions +inline void MacroAssembler::bp( Condition c, bool a, CC cc, Predict p, address d, relocInfo::relocType rt ) { + Assembler::bp(c, a, cc, p, d, rt); +} + +inline void MacroAssembler::bp( Condition c, bool a, CC cc, Predict p, Label& L ) { + Assembler::bp(c, a, cc, p, L); +} + +inline void MacroAssembler::fb( Condition c, bool a, Predict p, address d, relocInfo::relocType rt ) { + if (VM_Version::v9_instructions_work()) + fbp(c, a, fcc0, p, d, rt); + else + Assembler::fb(c, a, d, rt); +} + +inline void MacroAssembler::fb( Condition c, bool a, Predict p, Label& L ) { + fb(c, a, p, target(L)); +} + +inline void MacroAssembler::fbp( Condition c, bool a, CC cc, Predict p, address d, relocInfo::relocType rt ) { + Assembler::fbp(c, a, cc, p, d, rt); +} + +inline void MacroAssembler::fbp( Condition c, bool a, CC cc, Predict p, Label& L ) { + Assembler::fbp(c, a, cc, p, L); +} + +inline void MacroAssembler::jmp( Register s1, Register s2 ) { jmpl( s1, s2, G0 ); } +inline void MacroAssembler::jmp( Register s1, int simm13a, RelocationHolder const& rspec ) { jmpl( s1, simm13a, G0, rspec); } + +inline bool MacroAssembler::is_far_target(address d) { + if (ForceUnreachable) { + // References outside the code cache should be treated as far + return d < CodeCache::low_bound() || d > CodeCache::high_bound(); + } + return !is_in_wdisp30_range(d, CodeCache::low_bound()) || !is_in_wdisp30_range(d, CodeCache::high_bound()); +} + +// Call with a check to see if we need to deal with the added +// expense of relocation and if we overflow the displacement +// of the quick call instruction. +inline void MacroAssembler::call( address d, relocInfo::relocType rt ) { +#ifdef _LP64 + intptr_t disp; + // NULL is ok because it will be relocated later. + // Must change NULL to a reachable address in order to + // pass asserts here and in wdisp. + if ( d == NULL ) + d = pc(); + + // Is this address within range of the call instruction? + // If not, use the expensive instruction sequence + if (is_far_target(d)) { + relocate(rt); + AddressLiteral dest(d); + jumpl_to(dest, O7, O7); + } else { + Assembler::call(d, rt); + } +#else + Assembler::call( d, rt ); +#endif +} + +inline void MacroAssembler::call( Label& L, relocInfo::relocType rt ) { + MacroAssembler::call( target(L), rt); +} + + + +inline void MacroAssembler::callr( Register s1, Register s2 ) { jmpl( s1, s2, O7 ); } +inline void MacroAssembler::callr( Register s1, int simm13a, RelocationHolder const& rspec ) { jmpl( s1, simm13a, O7, rspec); } + +// prefetch instruction +inline void MacroAssembler::iprefetch( address d, relocInfo::relocType rt ) { + if (VM_Version::v9_instructions_work()) + Assembler::bp( never, true, xcc, pt, d, rt ); +} +inline void MacroAssembler::iprefetch( Label& L) { iprefetch( target(L) ); } + + +// clobbers o7 on V8!! +// returns delta from gotten pc to addr after +inline int MacroAssembler::get_pc( Register d ) { + int x = offset(); + if (VM_Version::v9_instructions_work()) + rdpc(d); + else { + Label lbl; + Assembler::call(lbl, relocInfo::none); // No relocation as this is call to pc+0x8 + if (d == O7) delayed()->nop(); + else delayed()->mov(O7, d); + bind(lbl); + } + return offset() - x; +} + + +// Note: All MacroAssembler::set_foo functions are defined out-of-line. + + +// Loads the current PC of the following instruction as an immediate value in +// 2 instructions. All PCs in the CodeCache are within 2 Gig of each other. +inline intptr_t MacroAssembler::load_pc_address( Register reg, int bytes_to_skip ) { + intptr_t thepc = (intptr_t)pc() + 2*BytesPerInstWord + bytes_to_skip; +#ifdef _LP64 + Unimplemented(); +#else + Assembler::sethi( thepc & ~0x3ff, reg, internal_word_Relocation::spec((address)thepc)); + add(reg, thepc & 0x3ff, reg, internal_word_Relocation::spec((address)thepc)); +#endif + return thepc; +} + + +inline void MacroAssembler::load_contents(const AddressLiteral& addrlit, Register d, int offset) { + assert_not_delayed(); + if (ForceUnreachable) { + patchable_sethi(addrlit, d); + } else { + sethi(addrlit, d); + } + ld(d, addrlit.low10() + offset, d); +} + + +inline void MacroAssembler::load_bool_contents(const AddressLiteral& addrlit, Register d, int offset) { + assert_not_delayed(); + if (ForceUnreachable) { + patchable_sethi(addrlit, d); + } else { + sethi(addrlit, d); + } + ldub(d, addrlit.low10() + offset, d); +} + + +inline void MacroAssembler::load_ptr_contents(const AddressLiteral& addrlit, Register d, int offset) { + assert_not_delayed(); + if (ForceUnreachable) { + patchable_sethi(addrlit, d); + } else { + sethi(addrlit, d); + } + ld_ptr(d, addrlit.low10() + offset, d); +} + + +inline void MacroAssembler::store_contents(Register s, const AddressLiteral& addrlit, Register temp, int offset) { + assert_not_delayed(); + if (ForceUnreachable) { + patchable_sethi(addrlit, temp); + } else { + sethi(addrlit, temp); + } + st(s, temp, addrlit.low10() + offset); +} + + +inline void MacroAssembler::store_ptr_contents(Register s, const AddressLiteral& addrlit, Register temp, int offset) { + assert_not_delayed(); + if (ForceUnreachable) { + patchable_sethi(addrlit, temp); + } else { + sethi(addrlit, temp); + } + st_ptr(s, temp, addrlit.low10() + offset); +} + + +// This code sequence is relocatable to any address, even on LP64. +inline void MacroAssembler::jumpl_to(const AddressLiteral& addrlit, Register temp, Register d, int offset) { + assert_not_delayed(); + // Force fixed length sethi because NativeJump and NativeFarCall don't handle + // variable length instruction streams. + patchable_sethi(addrlit, temp); + jmpl(temp, addrlit.low10() + offset, d); +} + + +inline void MacroAssembler::jump_to(const AddressLiteral& addrlit, Register temp, int offset) { + jumpl_to(addrlit, temp, G0, offset); +} + + +inline void MacroAssembler::jump_indirect_to(Address& a, Register temp, + int ld_offset, int jmp_offset) { + assert_not_delayed(); + //sethi(al); // sethi is caller responsibility for this one + ld_ptr(a, temp, ld_offset); + jmp(temp, jmp_offset); +} + + +inline void MacroAssembler::set_metadata(Metadata* obj, Register d) { + set_metadata(allocate_metadata_address(obj), d); +} + +inline void MacroAssembler::set_metadata_constant(Metadata* obj, Register d) { + set_metadata(constant_metadata_address(obj), d); +} + +inline void MacroAssembler::set_metadata(const AddressLiteral& obj_addr, Register d) { + assert(obj_addr.rspec().type() == relocInfo::metadata_type, "must be a metadata reloc"); + set(obj_addr, d); +} + +inline void MacroAssembler::set_oop(jobject obj, Register d) { + set_oop(allocate_oop_address(obj), d); +} + + +inline void MacroAssembler::set_oop_constant(jobject obj, Register d) { + set_oop(constant_oop_address(obj), d); +} + + +inline void MacroAssembler::set_oop(const AddressLiteral& obj_addr, Register d) { + assert(obj_addr.rspec().type() == relocInfo::oop_type, "must be an oop reloc"); + set(obj_addr, d); +} + + +inline void MacroAssembler::load_argument( Argument& a, Register d ) { + if (a.is_register()) + mov(a.as_register(), d); + else + ld (a.as_address(), d); +} + +inline void MacroAssembler::store_argument( Register s, Argument& a ) { + if (a.is_register()) + mov(s, a.as_register()); + else + st_ptr (s, a.as_address()); // ABI says everything is right justified. +} + +inline void MacroAssembler::store_ptr_argument( Register s, Argument& a ) { + if (a.is_register()) + mov(s, a.as_register()); + else + st_ptr (s, a.as_address()); +} + + +#ifdef _LP64 +inline void MacroAssembler::store_float_argument( FloatRegister s, Argument& a ) { + if (a.is_float_register()) +// V9 ABI has F1, F3, F5 are used to pass instead of O0, O1, O2 + fmov(FloatRegisterImpl::S, s, a.as_float_register() ); + else + // Floats are stored in the high half of the stack entry + // The low half is undefined per the ABI. + stf(FloatRegisterImpl::S, s, a.as_address(), sizeof(jfloat)); +} + +inline void MacroAssembler::store_double_argument( FloatRegister s, Argument& a ) { + if (a.is_float_register()) +// V9 ABI has D0, D2, D4 are used to pass instead of O0, O1, O2 + fmov(FloatRegisterImpl::D, s, a.as_double_register() ); + else + stf(FloatRegisterImpl::D, s, a.as_address()); +} + +inline void MacroAssembler::store_long_argument( Register s, Argument& a ) { + if (a.is_register()) + mov(s, a.as_register()); + else + stx(s, a.as_address()); +} +#endif + +inline void MacroAssembler::add(Register s1, int simm13a, Register d, relocInfo::relocType rtype) { + relocate(rtype); + add(s1, simm13a, d); +} +inline void MacroAssembler::add(Register s1, int simm13a, Register d, RelocationHolder const& rspec) { + relocate(rspec); + add(s1, simm13a, d); +} + +// form effective addresses this way: +inline void MacroAssembler::add(const Address& a, Register d, int offset) { + if (a.has_index()) add(a.base(), a.index(), d); + else { add(a.base(), a.disp() + offset, d, a.rspec(offset)); offset = 0; } + if (offset != 0) add(d, offset, d); +} +inline void MacroAssembler::add(Register s1, RegisterOrConstant s2, Register d, int offset) { + if (s2.is_register()) add(s1, s2.as_register(), d); + else { add(s1, s2.as_constant() + offset, d); offset = 0; } + if (offset != 0) add(d, offset, d); +} + +inline void MacroAssembler::andn(Register s1, RegisterOrConstant s2, Register d) { + if (s2.is_register()) andn(s1, s2.as_register(), d); + else andn(s1, s2.as_constant(), d); +} + +inline void MacroAssembler::clrb( Register s1, Register s2) { stb( G0, s1, s2 ); } +inline void MacroAssembler::clrh( Register s1, Register s2) { sth( G0, s1, s2 ); } +inline void MacroAssembler::clr( Register s1, Register s2) { stw( G0, s1, s2 ); } +inline void MacroAssembler::clrx( Register s1, Register s2) { stx( G0, s1, s2 ); } + +inline void MacroAssembler::clrb( Register s1, int simm13a) { stb( G0, s1, simm13a); } +inline void MacroAssembler::clrh( Register s1, int simm13a) { sth( G0, s1, simm13a); } +inline void MacroAssembler::clr( Register s1, int simm13a) { stw( G0, s1, simm13a); } +inline void MacroAssembler::clrx( Register s1, int simm13a) { stx( G0, s1, simm13a); } + +#ifdef _LP64 +// Make all 32 bit loads signed so 64 bit registers maintain proper sign +inline void MacroAssembler::ld( Register s1, Register s2, Register d) { ldsw( s1, s2, d); } +inline void MacroAssembler::ld( Register s1, int simm13a, Register d) { ldsw( s1, simm13a, d); } +#else +inline void MacroAssembler::ld( Register s1, Register s2, Register d) { lduw( s1, s2, d); } +inline void MacroAssembler::ld( Register s1, int simm13a, Register d) { lduw( s1, simm13a, d); } +#endif + +#ifdef ASSERT + // ByteSize is only a class when ASSERT is defined, otherwise it's an int. +# ifdef _LP64 +inline void MacroAssembler::ld(Register s1, ByteSize simm13a, Register d) { ldsw( s1, in_bytes(simm13a), d); } +# else +inline void MacroAssembler::ld(Register s1, ByteSize simm13a, Register d) { lduw( s1, in_bytes(simm13a), d); } +# endif +#endif + +inline void MacroAssembler::ld( const Address& a, Register d, int offset) { + if (a.has_index()) { assert(offset == 0, ""); ld( a.base(), a.index(), d); } + else { ld( a.base(), a.disp() + offset, d); } +} + +inline void MacroAssembler::ldsb(const Address& a, Register d, int offset) { + if (a.has_index()) { assert(offset == 0, ""); ldsb(a.base(), a.index(), d); } + else { ldsb(a.base(), a.disp() + offset, d); } +} +inline void MacroAssembler::ldsh(const Address& a, Register d, int offset) { + if (a.has_index()) { assert(offset == 0, ""); ldsh(a.base(), a.index(), d); } + else { ldsh(a.base(), a.disp() + offset, d); } +} +inline void MacroAssembler::ldsw(const Address& a, Register d, int offset) { + if (a.has_index()) { assert(offset == 0, ""); ldsw(a.base(), a.index(), d); } + else { ldsw(a.base(), a.disp() + offset, d); } +} +inline void MacroAssembler::ldub(const Address& a, Register d, int offset) { + if (a.has_index()) { assert(offset == 0, ""); ldub(a.base(), a.index(), d); } + else { ldub(a.base(), a.disp() + offset, d); } +} +inline void MacroAssembler::lduh(const Address& a, Register d, int offset) { + if (a.has_index()) { assert(offset == 0, ""); lduh(a.base(), a.index(), d); } + else { lduh(a.base(), a.disp() + offset, d); } +} +inline void MacroAssembler::lduw(const Address& a, Register d, int offset) { + if (a.has_index()) { assert(offset == 0, ""); lduw(a.base(), a.index(), d); } + else { lduw(a.base(), a.disp() + offset, d); } +} +inline void MacroAssembler::ldd( const Address& a, Register d, int offset) { + if (a.has_index()) { assert(offset == 0, ""); ldd( a.base(), a.index(), d); } + else { ldd( a.base(), a.disp() + offset, d); } +} +inline void MacroAssembler::ldx( const Address& a, Register d, int offset) { + if (a.has_index()) { assert(offset == 0, ""); ldx( a.base(), a.index(), d); } + else { ldx( a.base(), a.disp() + offset, d); } +} + +inline void MacroAssembler::ldub(Register s1, RegisterOrConstant s2, Register d) { ldub(Address(s1, s2), d); } +inline void MacroAssembler::ldsb(Register s1, RegisterOrConstant s2, Register d) { ldsb(Address(s1, s2), d); } +inline void MacroAssembler::lduh(Register s1, RegisterOrConstant s2, Register d) { lduh(Address(s1, s2), d); } +inline void MacroAssembler::ldsh(Register s1, RegisterOrConstant s2, Register d) { ldsh(Address(s1, s2), d); } +inline void MacroAssembler::lduw(Register s1, RegisterOrConstant s2, Register d) { lduw(Address(s1, s2), d); } +inline void MacroAssembler::ldsw(Register s1, RegisterOrConstant s2, Register d) { ldsw(Address(s1, s2), d); } +inline void MacroAssembler::ldx( Register s1, RegisterOrConstant s2, Register d) { ldx( Address(s1, s2), d); } +inline void MacroAssembler::ld( Register s1, RegisterOrConstant s2, Register d) { ld( Address(s1, s2), d); } +inline void MacroAssembler::ldd( Register s1, RegisterOrConstant s2, Register d) { ldd( Address(s1, s2), d); } + +inline void MacroAssembler::ldf(FloatRegisterImpl::Width w, Register s1, RegisterOrConstant s2, FloatRegister d) { + if (s2.is_register()) ldf(w, s1, s2.as_register(), d); + else ldf(w, s1, s2.as_constant(), d); +} + +inline void MacroAssembler::ldf(FloatRegisterImpl::Width w, const Address& a, FloatRegister d, int offset) { + relocate(a.rspec(offset)); + ldf(w, a.base(), a.disp() + offset, d); +} + +// returns if membar generates anything, obviously this code should mirror +// membar below. +inline bool MacroAssembler::membar_has_effect( Membar_mask_bits const7a ) { + if( !os::is_MP() ) return false; // Not needed on single CPU + if( VM_Version::v9_instructions_work() ) { + const Membar_mask_bits effective_mask = + Membar_mask_bits(const7a & ~(LoadLoad | LoadStore | StoreStore)); + return (effective_mask != 0); + } else { + return true; + } +} + +inline void MacroAssembler::membar( Membar_mask_bits const7a ) { + // Uniprocessors do not need memory barriers + if (!os::is_MP()) return; + // Weakened for current Sparcs and TSO. See the v9 manual, sections 8.4.3, + // 8.4.4.3, a.31 and a.50. + if( VM_Version::v9_instructions_work() ) { + // Under TSO, setting bit 3, 2, or 0 is redundant, so the only value + // of the mmask subfield of const7a that does anything that isn't done + // implicitly is StoreLoad. + const Membar_mask_bits effective_mask = + Membar_mask_bits(const7a & ~(LoadLoad | LoadStore | StoreStore)); + if ( effective_mask != 0 ) { + Assembler::membar( effective_mask ); + } + } else { + // stbar is the closest there is on v8. Equivalent to membar(StoreStore). We + // do not issue the stbar because to my knowledge all v8 machines implement TSO, + // which guarantees that all stores behave as if an stbar were issued just after + // each one of them. On these machines, stbar ought to be a nop. There doesn't + // appear to be an equivalent of membar(StoreLoad) on v8: TSO doesn't require it, + // it can't be specified by stbar, nor have I come up with a way to simulate it. + // + // Addendum. Dave says that ldstub guarantees a write buffer flush to coherent + // space. Put one here to be on the safe side. + Assembler::ldstub(SP, 0, G0); + } +} + +inline void MacroAssembler::prefetch(const Address& a, PrefetchFcn f, int offset) { + relocate(a.rspec(offset)); + assert(!a.has_index(), ""); + prefetch(a.base(), a.disp() + offset, f); +} + +inline void MacroAssembler::st(Register d, Register s1, Register s2) { stw(d, s1, s2); } +inline void MacroAssembler::st(Register d, Register s1, int simm13a) { stw(d, s1, simm13a); } + +#ifdef ASSERT +// ByteSize is only a class when ASSERT is defined, otherwise it's an int. +inline void MacroAssembler::st(Register d, Register s1, ByteSize simm13a) { stw(d, s1, in_bytes(simm13a)); } +#endif + +inline void MacroAssembler::st(Register d, const Address& a, int offset) { + if (a.has_index()) { assert(offset == 0, ""); st( d, a.base(), a.index() ); } + else { st( d, a.base(), a.disp() + offset); } +} + +inline void MacroAssembler::stb(Register d, const Address& a, int offset) { + if (a.has_index()) { assert(offset == 0, ""); stb(d, a.base(), a.index() ); } + else { stb(d, a.base(), a.disp() + offset); } +} +inline void MacroAssembler::sth(Register d, const Address& a, int offset) { + if (a.has_index()) { assert(offset == 0, ""); sth(d, a.base(), a.index() ); } + else { sth(d, a.base(), a.disp() + offset); } +} +inline void MacroAssembler::stw(Register d, const Address& a, int offset) { + if (a.has_index()) { assert(offset == 0, ""); stw(d, a.base(), a.index() ); } + else { stw(d, a.base(), a.disp() + offset); } +} +inline void MacroAssembler::std(Register d, const Address& a, int offset) { + if (a.has_index()) { assert(offset == 0, ""); std(d, a.base(), a.index() ); } + else { std(d, a.base(), a.disp() + offset); } +} +inline void MacroAssembler::stx(Register d, const Address& a, int offset) { + if (a.has_index()) { assert(offset == 0, ""); stx(d, a.base(), a.index() ); } + else { stx(d, a.base(), a.disp() + offset); } +} + +inline void MacroAssembler::stb(Register d, Register s1, RegisterOrConstant s2) { stb(d, Address(s1, s2)); } +inline void MacroAssembler::sth(Register d, Register s1, RegisterOrConstant s2) { sth(d, Address(s1, s2)); } +inline void MacroAssembler::stw(Register d, Register s1, RegisterOrConstant s2) { stw(d, Address(s1, s2)); } +inline void MacroAssembler::stx(Register d, Register s1, RegisterOrConstant s2) { stx(d, Address(s1, s2)); } +inline void MacroAssembler::std(Register d, Register s1, RegisterOrConstant s2) { std(d, Address(s1, s2)); } +inline void MacroAssembler::st( Register d, Register s1, RegisterOrConstant s2) { st( d, Address(s1, s2)); } + +inline void MacroAssembler::stf(FloatRegisterImpl::Width w, FloatRegister d, Register s1, RegisterOrConstant s2) { + if (s2.is_register()) stf(w, d, s1, s2.as_register()); + else stf(w, d, s1, s2.as_constant()); +} + +inline void MacroAssembler::stf(FloatRegisterImpl::Width w, FloatRegister d, const Address& a, int offset) { + relocate(a.rspec(offset)); + if (a.has_index()) { assert(offset == 0, ""); stf(w, d, a.base(), a.index() ); } + else { stf(w, d, a.base(), a.disp() + offset); } +} + +inline void MacroAssembler::sub(Register s1, RegisterOrConstant s2, Register d, int offset) { + if (s2.is_register()) sub(s1, s2.as_register(), d); + else { sub(s1, s2.as_constant() + offset, d); offset = 0; } + if (offset != 0) sub(d, offset, d); +} + +inline void MacroAssembler::swap(Address& a, Register d, int offset) { + relocate(a.rspec(offset)); + if (a.has_index()) { assert(offset == 0, ""); swap(a.base(), a.index(), d ); } + else { swap(a.base(), a.disp() + offset, d); } +} + +#endif // CPU_SPARC_VM_MACROASSEMBLER_SPARC_INLINE_HPP diff --git a/hotspot/src/cpu/sparc/vm/metaspaceShared_sparc.cpp b/hotspot/src/cpu/sparc/vm/metaspaceShared_sparc.cpp index 70ef0c78bb6..28f606be3b0 100644 --- a/hotspot/src/cpu/sparc/vm/metaspaceShared_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/metaspaceShared_sparc.cpp @@ -23,7 +23,8 @@ */ #include "precompiled.hpp" -#include "assembler_sparc.inline.hpp" +#include "asm/macroAssembler.inline.hpp" +#include "asm/codeBuffer.hpp" #include "memory/metaspaceShared.hpp" // Generate the self-patching vtable method: diff --git a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp index 9245f3b40ff..546cfaf08f1 100644 --- a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "asm/macroAssembler.hpp" #include "interpreter/interpreter.hpp" #include "memory/allocation.inline.hpp" #include "prims/methodHandles.hpp" @@ -170,7 +171,8 @@ void MethodHandles::jump_to_lambda_form(MacroAssembler* _masm, if (VerifyMethodHandles && !for_compiler_entry) { // make sure recv is already on stack - __ load_sized_value(Address(method_temp, Method::size_of_parameters_offset()), + __ ld_ptr(method_temp, in_bytes(Method::const_offset()), temp2); + __ load_sized_value(Address(temp2, ConstMethod::size_of_parameters_offset()), temp2, sizeof(u2), /*is_signed*/ false); // assert(sizeof(u2) == sizeof(Method::_size_of_parameters), ""); @@ -232,7 +234,8 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* int ref_kind = signature_polymorphic_intrinsic_ref_kind(iid); assert(ref_kind != 0 || iid == vmIntrinsics::_invokeBasic, "must be _invokeBasic or a linkTo intrinsic"); if (ref_kind == 0 || MethodHandles::ref_kind_has_receiver(ref_kind)) { - __ load_sized_value(Address(G5_method, Method::size_of_parameters_offset()), + __ ld_ptr(G5_method, in_bytes(Method::const_offset()), O4_param_size); + __ load_sized_value(Address(O4_param_size, ConstMethod::size_of_parameters_offset()), O4_param_size, sizeof(u2), /*is_signed*/ false); // assert(sizeof(u2) == sizeof(Method::_size_of_parameters), ""); diff --git a/hotspot/src/cpu/sparc/vm/nativeInst_sparc.cpp b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.cpp index 97108bfe82c..71a938e59fc 100644 --- a/hotspot/src/cpu/sparc/vm/nativeInst_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.cpp @@ -23,7 +23,7 @@ */ #include "precompiled.hpp" -#include "assembler_sparc.inline.hpp" +#include "asm/macroAssembler.hpp" #include "memory/resourceArea.hpp" #include "nativeInst_sparc.hpp" #include "oops/oop.inline.hpp" diff --git a/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp index 8617ec37e03..3c9a5e9b7a7 100644 --- a/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp @@ -25,7 +25,7 @@ #ifndef CPU_SPARC_VM_NATIVEINST_SPARC_HPP #define CPU_SPARC_VM_NATIVEINST_SPARC_HPP -#include "asm/assembler.hpp" +#include "asm/macroAssembler.hpp" #include "memory/allocation.hpp" #include "runtime/icache.hpp" #include "runtime/os.hpp" @@ -194,11 +194,10 @@ class NativeInstruction VALUE_OBJ_CLASS_SPEC { static int inv_simm( int x, int nbits ) { return Assembler::inv_simm(x, nbits); } static intptr_t inv_wdisp( int x, int nbits ) { return Assembler::inv_wdisp( x, 0, nbits); } static intptr_t inv_wdisp16( int x ) { return Assembler::inv_wdisp16(x, 0); } - static int branch_destination_offset(int x) { return Assembler::branch_destination(x, 0); } + static int branch_destination_offset(int x) { return MacroAssembler::branch_destination(x, 0); } static int patch_branch_destination_offset(int dest_offset, int x) { - return Assembler::patched_branch(dest_offset, x, 0); + return MacroAssembler::patched_branch(dest_offset, x, 0); } - void set_annul_bit() { set_long_at(0, long_at(0) | Assembler::annul(true)); } // utility for checking if x is either of 2 small constants static bool is_either(int x, int k1, int k2) { @@ -889,7 +888,6 @@ class NativeGeneralJump: public NativeInstruction { int patched_instr = patch_branch_destination_offset(dest - addr_at(0), long_at(0)); set_long_at(0, patched_instr); } - void set_annul() { set_annul_bit(); } NativeInstruction *delay_slot_instr() { return nativeInstruction_at(addr_at(4));} void fill_delay_slot(int instr) { set_long_at(4, instr);} Assembler::Condition condition() { diff --git a/hotspot/src/cpu/sparc/vm/relocInfo_sparc.cpp b/hotspot/src/cpu/sparc/vm/relocInfo_sparc.cpp index aeb2420c640..2a3516dcf6b 100644 --- a/hotspot/src/cpu/sparc/vm/relocInfo_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/relocInfo_sparc.cpp @@ -23,8 +23,7 @@ */ #include "precompiled.hpp" -#include "asm/assembler.inline.hpp" -#include "assembler_sparc.inline.hpp" +#include "asm/assembler.hpp" #include "code/relocInfo.hpp" #include "nativeInst_sparc.hpp" #include "oops/oop.inline.hpp" diff --git a/hotspot/src/cpu/sparc/vm/runtime_sparc.cpp b/hotspot/src/cpu/sparc/vm/runtime_sparc.cpp index ff04e6fef14..0e498d71285 100644 --- a/hotspot/src/cpu/sparc/vm/runtime_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/runtime_sparc.cpp @@ -24,8 +24,7 @@ #include "precompiled.hpp" #ifdef COMPILER2 -#include "asm/assembler.hpp" -#include "assembler_sparc.inline.hpp" +#include "asm/macroAssembler.inline.hpp" #include "classfile/systemDictionary.hpp" #include "code/vmreg.hpp" #include "interpreter/interpreter.hpp" diff --git a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp index ef8273f58f8..b6a338c34ee 100644 --- a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp @@ -23,8 +23,7 @@ */ #include "precompiled.hpp" -#include "asm/assembler.hpp" -#include "assembler_sparc.inline.hpp" +#include "asm/macroAssembler.inline.hpp" #include "code/debugInfoRec.hpp" #include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" diff --git a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp index e8e7499b5f9..3cd4ff2d3f5 100644 --- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp @@ -23,8 +23,7 @@ */ #include "precompiled.hpp" -#include "asm/assembler.hpp" -#include "assembler_sparc.inline.hpp" +#include "asm/macroAssembler.inline.hpp" #include "interpreter/interpreter.hpp" #include "nativeInst_sparc.hpp" #include "oops/instanceOop.hpp" diff --git a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp index d51b9e5bb0e..bd508561056 100644 --- a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp @@ -23,7 +23,7 @@ */ #include "precompiled.hpp" -#include "asm/assembler.hpp" +#include "asm/macroAssembler.hpp" #include "interpreter/bytecodeHistogram.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/interpreterGenerator.hpp" @@ -494,9 +494,6 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) { // (gri - 2/25/2000) - const Address size_of_parameters(G5_method, Method::size_of_parameters_offset()); - const Address size_of_locals (G5_method, Method::size_of_locals_offset()); - const Address constMethod (G5_method, Method::const_offset()); int rounded_vm_local_words = round_to( frame::interpreter_frame_vm_local_words, WordsPerLong ); const int extra_space = @@ -506,11 +503,15 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) { (native_call ? frame::interpreter_frame_extra_outgoing_argument_words : 0); const Register Glocals_size = G3; + const Register RconstMethod = Glocals_size; const Register Otmp1 = O3; const Register Otmp2 = O4; // Lscratch can't be used as a temporary because the call_stub uses // it to assert that the stack frame was setup correctly. + const Address constMethod (G5_method, Method::const_offset()); + const Address size_of_parameters(RconstMethod, ConstMethod::size_of_parameters_offset()); + __ ld_ptr( constMethod, RconstMethod ); __ lduh( size_of_parameters, Glocals_size); // Gargs points to first local + BytesPerWord @@ -530,6 +531,8 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) { // // Compute number of locals in method apart from incoming parameters // + const Address size_of_locals (Otmp1, ConstMethod::size_of_locals_offset()); + __ ld_ptr( constMethod, Otmp1 ); __ lduh( size_of_locals, Otmp1 ); __ sub( Otmp1, Glocals_size, Glocals_size ); __ round_to( Glocals_size, WordsPerLong ); @@ -1256,8 +1259,7 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) { // make sure registers are different! assert_different_registers(G2_thread, G5_method, Gargs, Gtmp1, Gtmp2); - const Address size_of_parameters(G5_method, Method::size_of_parameters_offset()); - const Address size_of_locals (G5_method, Method::size_of_locals_offset()); + const Address constMethod (G5_method, Method::const_offset()); // Seems like G5_method is live at the point this is used. So we could make this look consistent // and use in the asserts. const Address access_flags (Lmethod, Method::access_flags_offset()); @@ -1307,8 +1309,13 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) { init_value = G0; Label clear_loop; + const Register RconstMethod = O1; + const Address size_of_parameters(RconstMethod, ConstMethod::size_of_parameters_offset()); + const Address size_of_locals (RconstMethod, ConstMethod::size_of_locals_offset()); + // NOTE: If you change the frame layout, this code will need to // be updated! + __ ld_ptr( constMethod, RconstMethod ); __ lduh( size_of_locals, O2 ); __ lduh( size_of_parameters, O1 ); __ sll( O2, Interpreter::logStackElementSize, O2); @@ -1823,9 +1830,13 @@ void TemplateInterpreterGenerator::generate_throw_exception() { const Register Gtmp1 = G3_scratch; const Register Gtmp2 = G1_scratch; + const Register RconstMethod = Gtmp1; + const Address constMethod(Lmethod, Method::const_offset()); + const Address size_of_parameters(RconstMethod, ConstMethod::size_of_parameters_offset()); // Compute size of arguments for saving when returning to deoptimized caller - __ lduh(Lmethod, in_bytes(Method::size_of_parameters_offset()), Gtmp1); + __ ld_ptr(constMethod, RconstMethod); + __ lduh(size_of_parameters, Gtmp1); __ sll(Gtmp1, Interpreter::logStackElementSize, Gtmp1); __ sub(Llocals, Gtmp1, Gtmp2); __ add(Gtmp2, wordSize, Gtmp2); diff --git a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp index 5b1887dbbca..931342ded12 100644 --- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp @@ -3040,7 +3040,8 @@ void TemplateTable::invokevfinal_helper(Register Rscratch, Register Rret) { Register Rtemp = G4_scratch; // Load receiver from stack slot - __ lduh(G5_method, in_bytes(Method::size_of_parameters_offset()), G4_scratch); + __ ld_ptr(G5_method, in_bytes(Method::const_offset()), G4_scratch); + __ lduh(G4_scratch, in_bytes(ConstMethod::size_of_parameters_offset()), G4_scratch); __ load_receiver(G4_scratch, O0); // receiver NULL check diff --git a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp index aaa601fbbc9..7d3becef336 100644 --- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp @@ -23,7 +23,7 @@ */ #include "precompiled.hpp" -#include "assembler_sparc.inline.hpp" +#include "asm/macroAssembler.inline.hpp" #include "memory/resourceArea.hpp" #include "runtime/java.hpp" #include "runtime/stubCodeGenerator.hpp" diff --git a/hotspot/src/cpu/sparc/vm/vmreg_sparc.cpp b/hotspot/src/cpu/sparc/vm/vmreg_sparc.cpp index 470f354bf46..c261a5dd09f 100644 --- a/hotspot/src/cpu/sparc/vm/vmreg_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/vmreg_sparc.cpp @@ -23,7 +23,6 @@ */ #include "precompiled.hpp" -#include "asm/assembler.hpp" #include "code/vmreg.hpp" diff --git a/hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp b/hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp index 8e7021fa1a7..3c4f24c3867 100644 --- a/hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp @@ -23,8 +23,7 @@ */ #include "precompiled.hpp" -#include "asm/assembler.hpp" -#include "assembler_sparc.inline.hpp" +#include "asm/macroAssembler.inline.hpp" #include "code/vtableStubs.hpp" #include "interp_masm_sparc.hpp" #include "memory/resourceArea.hpp" diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.cpp b/hotspot/src/cpu/x86/vm/assembler_x86.cpp index 6b9677d30c5..0a51534ed24 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp @@ -23,7 +23,8 @@ */ #include "precompiled.hpp" -#include "assembler_x86.inline.hpp" +#include "asm/assembler.hpp" +#include "asm/assembler.inline.hpp" #include "gc_interface/collectedHeap.inline.hpp" #include "interpreter/interpreter.hpp" #include "memory/cardTableModRefBS.hpp" @@ -1154,7 +1155,7 @@ void Assembler::call_literal(address entry, RelocationHolder const& rspec) { assert(entry != NULL, "call most probably wrong"); InstructionMark im(this); emit_byte(0xE8); - intptr_t disp = entry - (_code_pos + sizeof(int32_t)); + intptr_t disp = entry - (pc() + sizeof(int32_t)); assert(is_simm32(disp), "must be 32bit offset (call2)"); // Technically, should use call32_operand, but this format is // implied by the fact that we're emitting a call instruction. @@ -1167,6 +1168,10 @@ void Assembler::cdql() { emit_byte(0x99); } +void Assembler::cld() { + emit_byte(0xfc); +} + void Assembler::cmovl(Condition cc, Register dst, Register src) { NOT_LP64(guarantee(VM_Version::supports_cmov(), "illegal instruction")); int encode = prefix_and_encode(dst->encoding(), src->encoding()); @@ -1260,6 +1265,11 @@ void Assembler::comiss(XMMRegister dst, XMMRegister src) { emit_simd_arith_nonds(0x2F, dst, src, VEX_SIMD_NONE); } +void Assembler::cpuid() { + emit_byte(0x0F); + emit_byte(0xA2); +} + void Assembler::cvtdq2pd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); emit_simd_arith_nonds(0xE6, dst, src, VEX_SIMD_F3); @@ -1417,7 +1427,7 @@ void Assembler::jcc(Condition cc, Label& L, bool maybe_short) { const int short_size = 2; const int long_size = 6; - intptr_t offs = (intptr_t)dst - (intptr_t)_code_pos; + intptr_t offs = (intptr_t)dst - (intptr_t)pc(); if (maybe_short && is8bit(offs - short_size)) { // 0111 tttn #8-bit disp emit_byte(0x70 | cc); @@ -1447,14 +1457,14 @@ void Assembler::jccb(Condition cc, Label& L) { const int short_size = 2; address entry = target(L); #ifdef ASSERT - intptr_t dist = (intptr_t)entry - ((intptr_t)_code_pos + short_size); + intptr_t dist = (intptr_t)entry - ((intptr_t)pc() + short_size); intptr_t delta = short_branch_delta(); if (delta != 0) { dist += (dist < 0 ? (-delta) :delta); } assert(is8bit(dist), "Dispacement too large for a short jmp"); #endif - intptr_t offs = (intptr_t)entry - (intptr_t)_code_pos; + intptr_t offs = (intptr_t)entry - (intptr_t)pc(); // 0111 tttn #8-bit disp emit_byte(0x70 | cc); emit_byte((offs - short_size) & 0xFF); @@ -1480,7 +1490,7 @@ void Assembler::jmp(Label& L, bool maybe_short) { InstructionMark im(this); const int short_size = 2; const int long_size = 5; - intptr_t offs = entry - _code_pos; + intptr_t offs = entry - pc(); if (maybe_short && is8bit(offs - short_size)) { emit_byte(0xEB); emit_byte((offs - short_size) & 0xFF); @@ -1510,7 +1520,7 @@ void Assembler::jmp_literal(address dest, RelocationHolder const& rspec) { InstructionMark im(this); emit_byte(0xE9); assert(dest != NULL, "must have a target"); - intptr_t disp = dest - (_code_pos + sizeof(int32_t)); + intptr_t disp = dest - (pc() + sizeof(int32_t)); assert(is_simm32(disp), "must be 32bit offset (jmp)"); emit_data(disp, rspec.reloc(), call32_operand); } @@ -1521,14 +1531,14 @@ void Assembler::jmpb(Label& L) { address entry = target(L); assert(entry != NULL, "jmp most probably wrong"); #ifdef ASSERT - intptr_t dist = (intptr_t)entry - ((intptr_t)_code_pos + short_size); + intptr_t dist = (intptr_t)entry - ((intptr_t)pc() + short_size); intptr_t delta = short_branch_delta(); if (delta != 0) { dist += (dist < 0 ? (-delta) :delta); } assert(is8bit(dist), "Dispacement too large for a short jmp"); #endif - intptr_t offs = entry - _code_pos; + intptr_t offs = entry - pc(); emit_byte(0xEB); emit_byte((offs - short_size) & 0xFF); } else { @@ -1558,6 +1568,12 @@ void Assembler::leal(Register dst, Address src) { emit_operand(dst, src); } +void Assembler::lfence() { + emit_byte(0x0F); + emit_byte(0xAE); + emit_byte(0xE8); +} + void Assembler::lock() { emit_byte(0xF0); } @@ -2671,6 +2687,10 @@ void Assembler::sqrtss(XMMRegister dst, XMMRegister src) { emit_simd_arith(0x51, dst, src, VEX_SIMD_F3); } +void Assembler::std() { + emit_byte(0xfd); +} + void Assembler::sqrtss(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); emit_simd_arith(0x51, dst, src, VEX_SIMD_F3); @@ -2816,6 +2836,12 @@ void Assembler::xchgl(Register dst, Register src) { emit_byte(0xc0 | encode); } +void Assembler::xgetbv() { + emit_byte(0x0F); + emit_byte(0x01); + emit_byte(0xD0); +} + void Assembler::xorl(Register dst, int32_t imm32) { prefix(dst); emit_arith(0x81, 0xF0, dst, imm32); @@ -4361,7 +4387,7 @@ bool Assembler::reachable(AddressLiteral adr) { disp = (int64_t)adr._target - ((int64_t)CodeCache::high_bound() + sizeof(int)); if (!is_simm32(disp)) return false; - disp = (int64_t)adr._target - ((int64_t)_code_pos + sizeof(int)); + disp = (int64_t)adr._target - ((int64_t)pc() + sizeof(int)); // Because rip relative is a disp + address_of_next_instruction and we // don't know the value of address_of_next_instruction we apply a fudge factor @@ -4392,7 +4418,7 @@ void Assembler::emit_data64(jlong data, relocInfo::relocType rtype, int format) { if (rtype == relocInfo::none) { - emit_long64(data); + emit_int64(data); } else { emit_data64(data, Relocation::spec_simple(rtype), format); } @@ -4410,7 +4436,7 @@ void Assembler::emit_data64(jlong data, #ifdef ASSERT check_relocation(rspec, format); #endif - emit_long64(data); + emit_int64(data); } int Assembler::prefix_and_encode(int reg_enc, bool byteinst) { @@ -4943,7 +4969,7 @@ void Assembler::mov64(Register dst, int64_t imm64) { InstructionMark im(this); int encode = prefixq_and_encode(dst->encoding()); emit_byte(0xB8 | encode); - emit_long64(imm64); + emit_int64(imm64); } void Assembler::mov_literal64(Register dst, intptr_t imm64, RelocationHolder const& rspec) { @@ -5417,6043 +5443,3 @@ void Assembler::xorq(Register dst, Address src) { } #endif // !LP64 - -static Assembler::Condition reverse[] = { - Assembler::noOverflow /* overflow = 0x0 */ , - Assembler::overflow /* noOverflow = 0x1 */ , - Assembler::aboveEqual /* carrySet = 0x2, below = 0x2 */ , - Assembler::below /* aboveEqual = 0x3, carryClear = 0x3 */ , - Assembler::notZero /* zero = 0x4, equal = 0x4 */ , - Assembler::zero /* notZero = 0x5, notEqual = 0x5 */ , - Assembler::above /* belowEqual = 0x6 */ , - Assembler::belowEqual /* above = 0x7 */ , - Assembler::positive /* negative = 0x8 */ , - Assembler::negative /* positive = 0x9 */ , - Assembler::noParity /* parity = 0xa */ , - Assembler::parity /* noParity = 0xb */ , - Assembler::greaterEqual /* less = 0xc */ , - Assembler::less /* greaterEqual = 0xd */ , - Assembler::greater /* lessEqual = 0xe */ , - Assembler::lessEqual /* greater = 0xf, */ - -}; - - -// Implementation of MacroAssembler - -// First all the versions that have distinct versions depending on 32/64 bit -// Unless the difference is trivial (1 line or so). - -#ifndef _LP64 - -// 32bit versions - -Address MacroAssembler::as_Address(AddressLiteral adr) { - return Address(adr.target(), adr.rspec()); -} - -Address MacroAssembler::as_Address(ArrayAddress adr) { - return Address::make_array(adr); -} - -int MacroAssembler::biased_locking_enter(Register lock_reg, - Register obj_reg, - Register swap_reg, - Register tmp_reg, - bool swap_reg_contains_mark, - Label& done, - Label* slow_case, - BiasedLockingCounters* counters) { - assert(UseBiasedLocking, "why call this otherwise?"); - assert(swap_reg == rax, "swap_reg must be rax, for cmpxchg"); - assert_different_registers(lock_reg, obj_reg, swap_reg); - - if (PrintBiasedLockingStatistics && counters == NULL) - counters = BiasedLocking::counters(); - - bool need_tmp_reg = false; - if (tmp_reg == noreg) { - need_tmp_reg = true; - tmp_reg = lock_reg; - } else { - assert_different_registers(lock_reg, obj_reg, swap_reg, tmp_reg); - } - assert(markOopDesc::age_shift == markOopDesc::lock_bits + markOopDesc::biased_lock_bits, "biased locking makes assumptions about bit layout"); - Address mark_addr (obj_reg, oopDesc::mark_offset_in_bytes()); - Address klass_addr (obj_reg, oopDesc::klass_offset_in_bytes()); - Address saved_mark_addr(lock_reg, 0); - - // Biased locking - // See whether the lock is currently biased toward our thread and - // whether the epoch is still valid - // Note that the runtime guarantees sufficient alignment of JavaThread - // pointers to allow age to be placed into low bits - // First check to see whether biasing is even enabled for this object - Label cas_label; - int null_check_offset = -1; - if (!swap_reg_contains_mark) { - null_check_offset = offset(); - movl(swap_reg, mark_addr); - } - if (need_tmp_reg) { - push(tmp_reg); - } - movl(tmp_reg, swap_reg); - andl(tmp_reg, markOopDesc::biased_lock_mask_in_place); - cmpl(tmp_reg, markOopDesc::biased_lock_pattern); - if (need_tmp_reg) { - pop(tmp_reg); - } - jcc(Assembler::notEqual, cas_label); - // The bias pattern is present in the object's header. Need to check - // whether the bias owner and the epoch are both still current. - // Note that because there is no current thread register on x86 we - // need to store off the mark word we read out of the object to - // avoid reloading it and needing to recheck invariants below. This - // store is unfortunate but it makes the overall code shorter and - // simpler. - movl(saved_mark_addr, swap_reg); - if (need_tmp_reg) { - push(tmp_reg); - } - get_thread(tmp_reg); - xorl(swap_reg, tmp_reg); - if (swap_reg_contains_mark) { - null_check_offset = offset(); - } - movl(tmp_reg, klass_addr); - xorl(swap_reg, Address(tmp_reg, Klass::prototype_header_offset())); - andl(swap_reg, ~((int) markOopDesc::age_mask_in_place)); - if (need_tmp_reg) { - pop(tmp_reg); - } - if (counters != NULL) { - cond_inc32(Assembler::zero, - ExternalAddress((address)counters->biased_lock_entry_count_addr())); - } - jcc(Assembler::equal, done); - - Label try_revoke_bias; - Label try_rebias; - - // At this point we know that the header has the bias pattern and - // that we are not the bias owner in the current epoch. We need to - // figure out more details about the state of the header in order to - // know what operations can be legally performed on the object's - // header. - - // If the low three bits in the xor result aren't clear, that means - // the prototype header is no longer biased and we have to revoke - // the bias on this object. - testl(swap_reg, markOopDesc::biased_lock_mask_in_place); - jcc(Assembler::notZero, try_revoke_bias); - - // Biasing is still enabled for this data type. See whether the - // epoch of the current bias is still valid, meaning that the epoch - // bits of the mark word are equal to the epoch bits of the - // prototype header. (Note that the prototype header's epoch bits - // only change at a safepoint.) If not, attempt to rebias the object - // toward the current thread. Note that we must be absolutely sure - // that the current epoch is invalid in order to do this because - // otherwise the manipulations it performs on the mark word are - // illegal. - testl(swap_reg, markOopDesc::epoch_mask_in_place); - jcc(Assembler::notZero, try_rebias); - - // The epoch of the current bias is still valid but we know nothing - // about the owner; it might be set or it might be clear. Try to - // acquire the bias of the object using an atomic operation. If this - // fails we will go in to the runtime to revoke the object's bias. - // Note that we first construct the presumed unbiased header so we - // don't accidentally blow away another thread's valid bias. - movl(swap_reg, saved_mark_addr); - andl(swap_reg, - markOopDesc::biased_lock_mask_in_place | markOopDesc::age_mask_in_place | markOopDesc::epoch_mask_in_place); - if (need_tmp_reg) { - push(tmp_reg); - } - get_thread(tmp_reg); - orl(tmp_reg, swap_reg); - if (os::is_MP()) { - lock(); - } - cmpxchgptr(tmp_reg, Address(obj_reg, 0)); - if (need_tmp_reg) { - pop(tmp_reg); - } - // If the biasing toward our thread failed, this means that - // another thread succeeded in biasing it toward itself and we - // need to revoke that bias. The revocation will occur in the - // interpreter runtime in the slow case. - if (counters != NULL) { - cond_inc32(Assembler::zero, - ExternalAddress((address)counters->anonymously_biased_lock_entry_count_addr())); - } - if (slow_case != NULL) { - jcc(Assembler::notZero, *slow_case); - } - jmp(done); - - bind(try_rebias); - // At this point we know the epoch has expired, meaning that the - // current "bias owner", if any, is actually invalid. Under these - // circumstances _only_, we are allowed to use the current header's - // value as the comparison value when doing the cas to acquire the - // bias in the current epoch. In other words, we allow transfer of - // the bias from one thread to another directly in this situation. - // - // FIXME: due to a lack of registers we currently blow away the age - // bits in this situation. Should attempt to preserve them. - if (need_tmp_reg) { - push(tmp_reg); - } - get_thread(tmp_reg); - movl(swap_reg, klass_addr); - orl(tmp_reg, Address(swap_reg, Klass::prototype_header_offset())); - movl(swap_reg, saved_mark_addr); - if (os::is_MP()) { - lock(); - } - cmpxchgptr(tmp_reg, Address(obj_reg, 0)); - if (need_tmp_reg) { - pop(tmp_reg); - } - // If the biasing toward our thread failed, then another thread - // succeeded in biasing it toward itself and we need to revoke that - // bias. The revocation will occur in the runtime in the slow case. - if (counters != NULL) { - cond_inc32(Assembler::zero, - ExternalAddress((address)counters->rebiased_lock_entry_count_addr())); - } - if (slow_case != NULL) { - jcc(Assembler::notZero, *slow_case); - } - jmp(done); - - bind(try_revoke_bias); - // The prototype mark in the klass doesn't have the bias bit set any - // more, indicating that objects of this data type are not supposed - // to be biased any more. We are going to try to reset the mark of - // this object to the prototype value and fall through to the - // CAS-based locking scheme. Note that if our CAS fails, it means - // that another thread raced us for the privilege of revoking the - // bias of this particular object, so it's okay to continue in the - // normal locking code. - // - // FIXME: due to a lack of registers we currently blow away the age - // bits in this situation. Should attempt to preserve them. - movl(swap_reg, saved_mark_addr); - if (need_tmp_reg) { - push(tmp_reg); - } - movl(tmp_reg, klass_addr); - movl(tmp_reg, Address(tmp_reg, Klass::prototype_header_offset())); - if (os::is_MP()) { - lock(); - } - cmpxchgptr(tmp_reg, Address(obj_reg, 0)); - if (need_tmp_reg) { - pop(tmp_reg); - } - // Fall through to the normal CAS-based lock, because no matter what - // the result of the above CAS, some thread must have succeeded in - // removing the bias bit from the object's header. - if (counters != NULL) { - cond_inc32(Assembler::zero, - ExternalAddress((address)counters->revoked_lock_entry_count_addr())); - } - - bind(cas_label); - - return null_check_offset; -} -void MacroAssembler::call_VM_leaf_base(address entry_point, - int number_of_arguments) { - call(RuntimeAddress(entry_point)); - increment(rsp, number_of_arguments * wordSize); -} - -void MacroAssembler::cmpklass(Address src1, Metadata* obj) { - cmp_literal32(src1, (int32_t)obj, metadata_Relocation::spec_for_immediate()); -} - -void MacroAssembler::cmpklass(Register src1, Metadata* obj) { - cmp_literal32(src1, (int32_t)obj, metadata_Relocation::spec_for_immediate()); -} - -void MacroAssembler::cmpoop(Address src1, jobject obj) { - cmp_literal32(src1, (int32_t)obj, oop_Relocation::spec_for_immediate()); -} - -void MacroAssembler::cmpoop(Register src1, jobject obj) { - cmp_literal32(src1, (int32_t)obj, oop_Relocation::spec_for_immediate()); -} - -void MacroAssembler::extend_sign(Register hi, Register lo) { - // According to Intel Doc. AP-526, "Integer Divide", p.18. - if (VM_Version::is_P6() && hi == rdx && lo == rax) { - cdql(); - } else { - movl(hi, lo); - sarl(hi, 31); - } -} - -void MacroAssembler::jC2(Register tmp, Label& L) { - // set parity bit if FPU flag C2 is set (via rax) - save_rax(tmp); - fwait(); fnstsw_ax(); - sahf(); - restore_rax(tmp); - // branch - jcc(Assembler::parity, L); -} - -void MacroAssembler::jnC2(Register tmp, Label& L) { - // set parity bit if FPU flag C2 is set (via rax) - save_rax(tmp); - fwait(); fnstsw_ax(); - sahf(); - restore_rax(tmp); - // branch - jcc(Assembler::noParity, L); -} - -// 32bit can do a case table jump in one instruction but we no longer allow the base -// to be installed in the Address class -void MacroAssembler::jump(ArrayAddress entry) { - jmp(as_Address(entry)); -} - -// Note: y_lo will be destroyed -void MacroAssembler::lcmp2int(Register x_hi, Register x_lo, Register y_hi, Register y_lo) { - // Long compare for Java (semantics as described in JVM spec.) - Label high, low, done; - - cmpl(x_hi, y_hi); - jcc(Assembler::less, low); - jcc(Assembler::greater, high); - // x_hi is the return register - xorl(x_hi, x_hi); - cmpl(x_lo, y_lo); - jcc(Assembler::below, low); - jcc(Assembler::equal, done); - - bind(high); - xorl(x_hi, x_hi); - increment(x_hi); - jmp(done); - - bind(low); - xorl(x_hi, x_hi); - decrementl(x_hi); - - bind(done); -} - -void MacroAssembler::lea(Register dst, AddressLiteral src) { - mov_literal32(dst, (int32_t)src.target(), src.rspec()); -} - -void MacroAssembler::lea(Address dst, AddressLiteral adr) { - // leal(dst, as_Address(adr)); - // see note in movl as to why we must use a move - mov_literal32(dst, (int32_t) adr.target(), adr.rspec()); -} - -void MacroAssembler::leave() { - mov(rsp, rbp); - pop(rbp); -} - -void MacroAssembler::lmul(int x_rsp_offset, int y_rsp_offset) { - // Multiplication of two Java long values stored on the stack - // as illustrated below. Result is in rdx:rax. - // - // rsp ---> [ ?? ] \ \ - // .... | y_rsp_offset | - // [ y_lo ] / (in bytes) | x_rsp_offset - // [ y_hi ] | (in bytes) - // .... | - // [ x_lo ] / - // [ x_hi ] - // .... - // - // Basic idea: lo(result) = lo(x_lo * y_lo) - // hi(result) = hi(x_lo * y_lo) + lo(x_hi * y_lo) + lo(x_lo * y_hi) - Address x_hi(rsp, x_rsp_offset + wordSize); Address x_lo(rsp, x_rsp_offset); - Address y_hi(rsp, y_rsp_offset + wordSize); Address y_lo(rsp, y_rsp_offset); - Label quick; - // load x_hi, y_hi and check if quick - // multiplication is possible - movl(rbx, x_hi); - movl(rcx, y_hi); - movl(rax, rbx); - orl(rbx, rcx); // rbx, = 0 <=> x_hi = 0 and y_hi = 0 - jcc(Assembler::zero, quick); // if rbx, = 0 do quick multiply - // do full multiplication - // 1st step - mull(y_lo); // x_hi * y_lo - movl(rbx, rax); // save lo(x_hi * y_lo) in rbx, - // 2nd step - movl(rax, x_lo); - mull(rcx); // x_lo * y_hi - addl(rbx, rax); // add lo(x_lo * y_hi) to rbx, - // 3rd step - bind(quick); // note: rbx, = 0 if quick multiply! - movl(rax, x_lo); - mull(y_lo); // x_lo * y_lo - addl(rdx, rbx); // correct hi(x_lo * y_lo) -} - -void MacroAssembler::lneg(Register hi, Register lo) { - negl(lo); - adcl(hi, 0); - negl(hi); -} - -void MacroAssembler::lshl(Register hi, Register lo) { - // Java shift left long support (semantics as described in JVM spec., p.305) - // (basic idea for shift counts s >= n: x << s == (x << n) << (s - n)) - // shift value is in rcx ! - assert(hi != rcx, "must not use rcx"); - assert(lo != rcx, "must not use rcx"); - const Register s = rcx; // shift count - const int n = BitsPerWord; - Label L; - andl(s, 0x3f); // s := s & 0x3f (s < 0x40) - cmpl(s, n); // if (s < n) - jcc(Assembler::less, L); // else (s >= n) - movl(hi, lo); // x := x << n - xorl(lo, lo); - // Note: subl(s, n) is not needed since the Intel shift instructions work rcx mod n! - bind(L); // s (mod n) < n - shldl(hi, lo); // x := x << s - shll(lo); -} - - -void MacroAssembler::lshr(Register hi, Register lo, bool sign_extension) { - // Java shift right long support (semantics as described in JVM spec., p.306 & p.310) - // (basic idea for shift counts s >= n: x >> s == (x >> n) >> (s - n)) - assert(hi != rcx, "must not use rcx"); - assert(lo != rcx, "must not use rcx"); - const Register s = rcx; // shift count - const int n = BitsPerWord; - Label L; - andl(s, 0x3f); // s := s & 0x3f (s < 0x40) - cmpl(s, n); // if (s < n) - jcc(Assembler::less, L); // else (s >= n) - movl(lo, hi); // x := x >> n - if (sign_extension) sarl(hi, 31); - else xorl(hi, hi); - // Note: subl(s, n) is not needed since the Intel shift instructions work rcx mod n! - bind(L); // s (mod n) < n - shrdl(lo, hi); // x := x >> s - if (sign_extension) sarl(hi); - else shrl(hi); -} - -void MacroAssembler::movoop(Register dst, jobject obj) { - mov_literal32(dst, (int32_t)obj, oop_Relocation::spec_for_immediate()); -} - -void MacroAssembler::movoop(Address dst, jobject obj) { - mov_literal32(dst, (int32_t)obj, oop_Relocation::spec_for_immediate()); -} - -void MacroAssembler::mov_metadata(Register dst, Metadata* obj) { - mov_literal32(dst, (int32_t)obj, metadata_Relocation::spec_for_immediate()); -} - -void MacroAssembler::mov_metadata(Address dst, Metadata* obj) { - mov_literal32(dst, (int32_t)obj, metadata_Relocation::spec_for_immediate()); -} - -void MacroAssembler::movptr(Register dst, AddressLiteral src) { - if (src.is_lval()) { - mov_literal32(dst, (intptr_t)src.target(), src.rspec()); - } else { - movl(dst, as_Address(src)); - } -} - -void MacroAssembler::movptr(ArrayAddress dst, Register src) { - movl(as_Address(dst), src); -} - -void MacroAssembler::movptr(Register dst, ArrayAddress src) { - movl(dst, as_Address(src)); -} - -// src should NEVER be a real pointer. Use AddressLiteral for true pointers -void MacroAssembler::movptr(Address dst, intptr_t src) { - movl(dst, src); -} - - -void MacroAssembler::pop_callee_saved_registers() { - pop(rcx); - pop(rdx); - pop(rdi); - pop(rsi); -} - -void MacroAssembler::pop_fTOS() { - fld_d(Address(rsp, 0)); - addl(rsp, 2 * wordSize); -} - -void MacroAssembler::push_callee_saved_registers() { - push(rsi); - push(rdi); - push(rdx); - push(rcx); -} - -void MacroAssembler::push_fTOS() { - subl(rsp, 2 * wordSize); - fstp_d(Address(rsp, 0)); -} - - -void MacroAssembler::pushoop(jobject obj) { - push_literal32((int32_t)obj, oop_Relocation::spec_for_immediate()); -} - -void MacroAssembler::pushklass(Metadata* obj) { - push_literal32((int32_t)obj, metadata_Relocation::spec_for_immediate()); -} - -void MacroAssembler::pushptr(AddressLiteral src) { - if (src.is_lval()) { - push_literal32((int32_t)src.target(), src.rspec()); - } else { - pushl(as_Address(src)); - } -} - -void MacroAssembler::set_word_if_not_zero(Register dst) { - xorl(dst, dst); - set_byte_if_not_zero(dst); -} - -static void pass_arg0(MacroAssembler* masm, Register arg) { - masm->push(arg); -} - -static void pass_arg1(MacroAssembler* masm, Register arg) { - masm->push(arg); -} - -static void pass_arg2(MacroAssembler* masm, Register arg) { - masm->push(arg); -} - -static void pass_arg3(MacroAssembler* masm, Register arg) { - masm->push(arg); -} - -#ifndef PRODUCT -extern "C" void findpc(intptr_t x); -#endif - -void MacroAssembler::debug32(int rdi, int rsi, int rbp, int rsp, int rbx, int rdx, int rcx, int rax, int eip, char* msg) { - // In order to get locks to work, we need to fake a in_VM state - JavaThread* thread = JavaThread::current(); - JavaThreadState saved_state = thread->thread_state(); - thread->set_thread_state(_thread_in_vm); - if (ShowMessageBoxOnError) { - JavaThread* thread = JavaThread::current(); - JavaThreadState saved_state = thread->thread_state(); - thread->set_thread_state(_thread_in_vm); - if (CountBytecodes || TraceBytecodes || StopInterpreterAt) { - ttyLocker ttyl; - BytecodeCounter::print(); - } - // To see where a verify_oop failed, get $ebx+40/X for this frame. - // This is the value of eip which points to where verify_oop will return. - if (os::message_box(msg, "Execution stopped, print registers?")) { - print_state32(rdi, rsi, rbp, rsp, rbx, rdx, rcx, rax, eip); - BREAKPOINT; - } - } else { - ttyLocker ttyl; - ::tty->print_cr("=============== DEBUG MESSAGE: %s ================\n", msg); - } - // Don't assert holding the ttyLock - assert(false, err_msg("DEBUG MESSAGE: %s", msg)); - ThreadStateTransition::transition(thread, _thread_in_vm, saved_state); -} - -void MacroAssembler::print_state32(int rdi, int rsi, int rbp, int rsp, int rbx, int rdx, int rcx, int rax, int eip) { - ttyLocker ttyl; - FlagSetting fs(Debugging, true); - tty->print_cr("eip = 0x%08x", eip); -#ifndef PRODUCT - if ((WizardMode || Verbose) && PrintMiscellaneous) { - tty->cr(); - findpc(eip); - tty->cr(); - } -#endif -#define PRINT_REG(rax) \ - { tty->print("%s = ", #rax); os::print_location(tty, rax); } - PRINT_REG(rax); - PRINT_REG(rbx); - PRINT_REG(rcx); - PRINT_REG(rdx); - PRINT_REG(rdi); - PRINT_REG(rsi); - PRINT_REG(rbp); - PRINT_REG(rsp); -#undef PRINT_REG - // Print some words near top of staack. - int* dump_sp = (int*) rsp; - for (int col1 = 0; col1 < 8; col1++) { - tty->print("(rsp+0x%03x) 0x%08x: ", (int)((intptr_t)dump_sp - (intptr_t)rsp), (intptr_t)dump_sp); - os::print_location(tty, *dump_sp++); - } - for (int row = 0; row < 16; row++) { - tty->print("(rsp+0x%03x) 0x%08x: ", (int)((intptr_t)dump_sp - (intptr_t)rsp), (intptr_t)dump_sp); - for (int col = 0; col < 8; col++) { - tty->print(" 0x%08x", *dump_sp++); - } - tty->cr(); - } - // Print some instructions around pc: - Disassembler::decode((address)eip-64, (address)eip); - tty->print_cr("--------"); - Disassembler::decode((address)eip, (address)eip+32); -} - -void MacroAssembler::stop(const char* msg) { - ExternalAddress message((address)msg); - // push address of message - pushptr(message.addr()); - { Label L; call(L, relocInfo::none); bind(L); } // push eip - pusha(); // push registers - call(RuntimeAddress(CAST_FROM_FN_PTR(address, MacroAssembler::debug32))); - hlt(); -} - -void MacroAssembler::warn(const char* msg) { - push_CPU_state(); - - ExternalAddress message((address) msg); - // push address of message - pushptr(message.addr()); - - call(RuntimeAddress(CAST_FROM_FN_PTR(address, warning))); - addl(rsp, wordSize); // discard argument - pop_CPU_state(); -} - -void MacroAssembler::print_state() { - { Label L; call(L, relocInfo::none); bind(L); } // push eip - pusha(); // push registers - - push_CPU_state(); - call(RuntimeAddress(CAST_FROM_FN_PTR(address, MacroAssembler::print_state32))); - pop_CPU_state(); - - popa(); - addl(rsp, wordSize); -} - -#else // _LP64 - -// 64 bit versions - -Address MacroAssembler::as_Address(AddressLiteral adr) { - // amd64 always does this as a pc-rel - // we can be absolute or disp based on the instruction type - // jmp/call are displacements others are absolute - assert(!adr.is_lval(), "must be rval"); - assert(reachable(adr), "must be"); - return Address((int32_t)(intptr_t)(adr.target() - pc()), adr.target(), adr.reloc()); - -} - -Address MacroAssembler::as_Address(ArrayAddress adr) { - AddressLiteral base = adr.base(); - lea(rscratch1, base); - Address index = adr.index(); - assert(index._disp == 0, "must not have disp"); // maybe it can? - Address array(rscratch1, index._index, index._scale, index._disp); - return array; -} - -int MacroAssembler::biased_locking_enter(Register lock_reg, - Register obj_reg, - Register swap_reg, - Register tmp_reg, - bool swap_reg_contains_mark, - Label& done, - Label* slow_case, - BiasedLockingCounters* counters) { - assert(UseBiasedLocking, "why call this otherwise?"); - assert(swap_reg == rax, "swap_reg must be rax for cmpxchgq"); - assert(tmp_reg != noreg, "tmp_reg must be supplied"); - assert_different_registers(lock_reg, obj_reg, swap_reg, tmp_reg); - assert(markOopDesc::age_shift == markOopDesc::lock_bits + markOopDesc::biased_lock_bits, "biased locking makes assumptions about bit layout"); - Address mark_addr (obj_reg, oopDesc::mark_offset_in_bytes()); - Address saved_mark_addr(lock_reg, 0); - - if (PrintBiasedLockingStatistics && counters == NULL) - counters = BiasedLocking::counters(); - - // Biased locking - // See whether the lock is currently biased toward our thread and - // whether the epoch is still valid - // Note that the runtime guarantees sufficient alignment of JavaThread - // pointers to allow age to be placed into low bits - // First check to see whether biasing is even enabled for this object - Label cas_label; - int null_check_offset = -1; - if (!swap_reg_contains_mark) { - null_check_offset = offset(); - movq(swap_reg, mark_addr); - } - movq(tmp_reg, swap_reg); - andq(tmp_reg, markOopDesc::biased_lock_mask_in_place); - cmpq(tmp_reg, markOopDesc::biased_lock_pattern); - jcc(Assembler::notEqual, cas_label); - // The bias pattern is present in the object's header. Need to check - // whether the bias owner and the epoch are both still current. - load_prototype_header(tmp_reg, obj_reg); - orq(tmp_reg, r15_thread); - xorq(tmp_reg, swap_reg); - andq(tmp_reg, ~((int) markOopDesc::age_mask_in_place)); - if (counters != NULL) { - cond_inc32(Assembler::zero, - ExternalAddress((address) counters->anonymously_biased_lock_entry_count_addr())); - } - jcc(Assembler::equal, done); - - Label try_revoke_bias; - Label try_rebias; - - // At this point we know that the header has the bias pattern and - // that we are not the bias owner in the current epoch. We need to - // figure out more details about the state of the header in order to - // know what operations can be legally performed on the object's - // header. - - // If the low three bits in the xor result aren't clear, that means - // the prototype header is no longer biased and we have to revoke - // the bias on this object. - testq(tmp_reg, markOopDesc::biased_lock_mask_in_place); - jcc(Assembler::notZero, try_revoke_bias); - - // Biasing is still enabled for this data type. See whether the - // epoch of the current bias is still valid, meaning that the epoch - // bits of the mark word are equal to the epoch bits of the - // prototype header. (Note that the prototype header's epoch bits - // only change at a safepoint.) If not, attempt to rebias the object - // toward the current thread. Note that we must be absolutely sure - // that the current epoch is invalid in order to do this because - // otherwise the manipulations it performs on the mark word are - // illegal. - testq(tmp_reg, markOopDesc::epoch_mask_in_place); - jcc(Assembler::notZero, try_rebias); - - // The epoch of the current bias is still valid but we know nothing - // about the owner; it might be set or it might be clear. Try to - // acquire the bias of the object using an atomic operation. If this - // fails we will go in to the runtime to revoke the object's bias. - // Note that we first construct the presumed unbiased header so we - // don't accidentally blow away another thread's valid bias. - andq(swap_reg, - markOopDesc::biased_lock_mask_in_place | markOopDesc::age_mask_in_place | markOopDesc::epoch_mask_in_place); - movq(tmp_reg, swap_reg); - orq(tmp_reg, r15_thread); - if (os::is_MP()) { - lock(); - } - cmpxchgq(tmp_reg, Address(obj_reg, 0)); - // If the biasing toward our thread failed, this means that - // another thread succeeded in biasing it toward itself and we - // need to revoke that bias. The revocation will occur in the - // interpreter runtime in the slow case. - if (counters != NULL) { - cond_inc32(Assembler::zero, - ExternalAddress((address) counters->anonymously_biased_lock_entry_count_addr())); - } - if (slow_case != NULL) { - jcc(Assembler::notZero, *slow_case); - } - jmp(done); - - bind(try_rebias); - // At this point we know the epoch has expired, meaning that the - // current "bias owner", if any, is actually invalid. Under these - // circumstances _only_, we are allowed to use the current header's - // value as the comparison value when doing the cas to acquire the - // bias in the current epoch. In other words, we allow transfer of - // the bias from one thread to another directly in this situation. - // - // FIXME: due to a lack of registers we currently blow away the age - // bits in this situation. Should attempt to preserve them. - load_prototype_header(tmp_reg, obj_reg); - orq(tmp_reg, r15_thread); - if (os::is_MP()) { - lock(); - } - cmpxchgq(tmp_reg, Address(obj_reg, 0)); - // If the biasing toward our thread failed, then another thread - // succeeded in biasing it toward itself and we need to revoke that - // bias. The revocation will occur in the runtime in the slow case. - if (counters != NULL) { - cond_inc32(Assembler::zero, - ExternalAddress((address) counters->rebiased_lock_entry_count_addr())); - } - if (slow_case != NULL) { - jcc(Assembler::notZero, *slow_case); - } - jmp(done); - - bind(try_revoke_bias); - // The prototype mark in the klass doesn't have the bias bit set any - // more, indicating that objects of this data type are not supposed - // to be biased any more. We are going to try to reset the mark of - // this object to the prototype value and fall through to the - // CAS-based locking scheme. Note that if our CAS fails, it means - // that another thread raced us for the privilege of revoking the - // bias of this particular object, so it's okay to continue in the - // normal locking code. - // - // FIXME: due to a lack of registers we currently blow away the age - // bits in this situation. Should attempt to preserve them. - load_prototype_header(tmp_reg, obj_reg); - if (os::is_MP()) { - lock(); - } - cmpxchgq(tmp_reg, Address(obj_reg, 0)); - // Fall through to the normal CAS-based lock, because no matter what - // the result of the above CAS, some thread must have succeeded in - // removing the bias bit from the object's header. - if (counters != NULL) { - cond_inc32(Assembler::zero, - ExternalAddress((address) counters->revoked_lock_entry_count_addr())); - } - - bind(cas_label); - - return null_check_offset; -} - -void MacroAssembler::call_VM_leaf_base(address entry_point, int num_args) { - Label L, E; - -#ifdef _WIN64 - // Windows always allocates space for it's register args - assert(num_args <= 4, "only register arguments supported"); - subq(rsp, frame::arg_reg_save_area_bytes); -#endif - - // Align stack if necessary - testl(rsp, 15); - jcc(Assembler::zero, L); - - subq(rsp, 8); - { - call(RuntimeAddress(entry_point)); - } - addq(rsp, 8); - jmp(E); - - bind(L); - { - call(RuntimeAddress(entry_point)); - } - - bind(E); - -#ifdef _WIN64 - // restore stack pointer - addq(rsp, frame::arg_reg_save_area_bytes); -#endif - -} - -void MacroAssembler::cmp64(Register src1, AddressLiteral src2) { - assert(!src2.is_lval(), "should use cmpptr"); - - if (reachable(src2)) { - cmpq(src1, as_Address(src2)); - } else { - lea(rscratch1, src2); - Assembler::cmpq(src1, Address(rscratch1, 0)); - } -} - -int MacroAssembler::corrected_idivq(Register reg) { - // Full implementation of Java ldiv and lrem; checks for special - // case as described in JVM spec., p.243 & p.271. The function - // returns the (pc) offset of the idivl instruction - may be needed - // for implicit exceptions. - // - // normal case special case - // - // input : rax: dividend min_long - // reg: divisor (may not be eax/edx) -1 - // - // output: rax: quotient (= rax idiv reg) min_long - // rdx: remainder (= rax irem reg) 0 - assert(reg != rax && reg != rdx, "reg cannot be rax or rdx register"); - static const int64_t min_long = 0x8000000000000000; - Label normal_case, special_case; - - // check for special case - cmp64(rax, ExternalAddress((address) &min_long)); - jcc(Assembler::notEqual, normal_case); - xorl(rdx, rdx); // prepare rdx for possible special case (where - // remainder = 0) - cmpq(reg, -1); - jcc(Assembler::equal, special_case); - - // handle normal case - bind(normal_case); - cdqq(); - int idivq_offset = offset(); - idivq(reg); - - // normal and special case exit - bind(special_case); - - return idivq_offset; -} - -void MacroAssembler::decrementq(Register reg, int value) { - if (value == min_jint) { subq(reg, value); return; } - if (value < 0) { incrementq(reg, -value); return; } - if (value == 0) { ; return; } - if (value == 1 && UseIncDec) { decq(reg) ; return; } - /* else */ { subq(reg, value) ; return; } -} - -void MacroAssembler::decrementq(Address dst, int value) { - if (value == min_jint) { subq(dst, value); return; } - if (value < 0) { incrementq(dst, -value); return; } - if (value == 0) { ; return; } - if (value == 1 && UseIncDec) { decq(dst) ; return; } - /* else */ { subq(dst, value) ; return; } -} - -void MacroAssembler::incrementq(Register reg, int value) { - if (value == min_jint) { addq(reg, value); return; } - if (value < 0) { decrementq(reg, -value); return; } - if (value == 0) { ; return; } - if (value == 1 && UseIncDec) { incq(reg) ; return; } - /* else */ { addq(reg, value) ; return; } -} - -void MacroAssembler::incrementq(Address dst, int value) { - if (value == min_jint) { addq(dst, value); return; } - if (value < 0) { decrementq(dst, -value); return; } - if (value == 0) { ; return; } - if (value == 1 && UseIncDec) { incq(dst) ; return; } - /* else */ { addq(dst, value) ; return; } -} - -// 32bit can do a case table jump in one instruction but we no longer allow the base -// to be installed in the Address class -void MacroAssembler::jump(ArrayAddress entry) { - lea(rscratch1, entry.base()); - Address dispatch = entry.index(); - assert(dispatch._base == noreg, "must be"); - dispatch._base = rscratch1; - jmp(dispatch); -} - -void MacroAssembler::lcmp2int(Register x_hi, Register x_lo, Register y_hi, Register y_lo) { - ShouldNotReachHere(); // 64bit doesn't use two regs - cmpq(x_lo, y_lo); -} - -void MacroAssembler::lea(Register dst, AddressLiteral src) { - mov_literal64(dst, (intptr_t)src.target(), src.rspec()); -} - -void MacroAssembler::lea(Address dst, AddressLiteral adr) { - mov_literal64(rscratch1, (intptr_t)adr.target(), adr.rspec()); - movptr(dst, rscratch1); -} - -void MacroAssembler::leave() { - // %%% is this really better? Why not on 32bit too? - emit_byte(0xC9); // LEAVE -} - -void MacroAssembler::lneg(Register hi, Register lo) { - ShouldNotReachHere(); // 64bit doesn't use two regs - negq(lo); -} - -void MacroAssembler::movoop(Register dst, jobject obj) { - mov_literal64(dst, (intptr_t)obj, oop_Relocation::spec_for_immediate()); -} - -void MacroAssembler::movoop(Address dst, jobject obj) { - mov_literal64(rscratch1, (intptr_t)obj, oop_Relocation::spec_for_immediate()); - movq(dst, rscratch1); -} - -void MacroAssembler::mov_metadata(Register dst, Metadata* obj) { - mov_literal64(dst, (intptr_t)obj, metadata_Relocation::spec_for_immediate()); -} - -void MacroAssembler::mov_metadata(Address dst, Metadata* obj) { - mov_literal64(rscratch1, (intptr_t)obj, metadata_Relocation::spec_for_immediate()); - movq(dst, rscratch1); -} - -void MacroAssembler::movptr(Register dst, AddressLiteral src) { - if (src.is_lval()) { - mov_literal64(dst, (intptr_t)src.target(), src.rspec()); - } else { - if (reachable(src)) { - movq(dst, as_Address(src)); - } else { - lea(rscratch1, src); - movq(dst, Address(rscratch1,0)); - } - } -} - -void MacroAssembler::movptr(ArrayAddress dst, Register src) { - movq(as_Address(dst), src); -} - -void MacroAssembler::movptr(Register dst, ArrayAddress src) { - movq(dst, as_Address(src)); -} - -// src should NEVER be a real pointer. Use AddressLiteral for true pointers -void MacroAssembler::movptr(Address dst, intptr_t src) { - mov64(rscratch1, src); - movq(dst, rscratch1); -} - -// These are mostly for initializing NULL -void MacroAssembler::movptr(Address dst, int32_t src) { - movslq(dst, src); -} - -void MacroAssembler::movptr(Register dst, int32_t src) { - mov64(dst, (intptr_t)src); -} - -void MacroAssembler::pushoop(jobject obj) { - movoop(rscratch1, obj); - push(rscratch1); -} - -void MacroAssembler::pushklass(Metadata* obj) { - mov_metadata(rscratch1, obj); - push(rscratch1); -} - -void MacroAssembler::pushptr(AddressLiteral src) { - lea(rscratch1, src); - if (src.is_lval()) { - push(rscratch1); - } else { - pushq(Address(rscratch1, 0)); - } -} - -void MacroAssembler::reset_last_Java_frame(bool clear_fp, - bool clear_pc) { - // we must set sp to zero to clear frame - movptr(Address(r15_thread, JavaThread::last_Java_sp_offset()), NULL_WORD); - // must clear fp, so that compiled frames are not confused; it is - // possible that we need it only for debugging - if (clear_fp) { - movptr(Address(r15_thread, JavaThread::last_Java_fp_offset()), NULL_WORD); - } - - if (clear_pc) { - movptr(Address(r15_thread, JavaThread::last_Java_pc_offset()), NULL_WORD); - } -} - -void MacroAssembler::set_last_Java_frame(Register last_java_sp, - Register last_java_fp, - address last_java_pc) { - // determine last_java_sp register - if (!last_java_sp->is_valid()) { - last_java_sp = rsp; - } - - // last_java_fp is optional - if (last_java_fp->is_valid()) { - movptr(Address(r15_thread, JavaThread::last_Java_fp_offset()), - last_java_fp); - } - - // last_java_pc is optional - if (last_java_pc != NULL) { - Address java_pc(r15_thread, - JavaThread::frame_anchor_offset() + JavaFrameAnchor::last_Java_pc_offset()); - lea(rscratch1, InternalAddress(last_java_pc)); - movptr(java_pc, rscratch1); - } - - movptr(Address(r15_thread, JavaThread::last_Java_sp_offset()), last_java_sp); -} - -static void pass_arg0(MacroAssembler* masm, Register arg) { - if (c_rarg0 != arg ) { - masm->mov(c_rarg0, arg); - } -} - -static void pass_arg1(MacroAssembler* masm, Register arg) { - if (c_rarg1 != arg ) { - masm->mov(c_rarg1, arg); - } -} - -static void pass_arg2(MacroAssembler* masm, Register arg) { - if (c_rarg2 != arg ) { - masm->mov(c_rarg2, arg); - } -} - -static void pass_arg3(MacroAssembler* masm, Register arg) { - if (c_rarg3 != arg ) { - masm->mov(c_rarg3, arg); - } -} - -void MacroAssembler::stop(const char* msg) { - address rip = pc(); - pusha(); // get regs on stack - lea(c_rarg0, ExternalAddress((address) msg)); - lea(c_rarg1, InternalAddress(rip)); - movq(c_rarg2, rsp); // pass pointer to regs array - andq(rsp, -16); // align stack as required by ABI - call(RuntimeAddress(CAST_FROM_FN_PTR(address, MacroAssembler::debug64))); - hlt(); -} - -void MacroAssembler::warn(const char* msg) { - push(rbp); - movq(rbp, rsp); - andq(rsp, -16); // align stack as required by push_CPU_state and call - push_CPU_state(); // keeps alignment at 16 bytes - lea(c_rarg0, ExternalAddress((address) msg)); - call_VM_leaf(CAST_FROM_FN_PTR(address, warning), c_rarg0); - pop_CPU_state(); - mov(rsp, rbp); - pop(rbp); -} - -void MacroAssembler::print_state() { - address rip = pc(); - pusha(); // get regs on stack - push(rbp); - movq(rbp, rsp); - andq(rsp, -16); // align stack as required by push_CPU_state and call - push_CPU_state(); // keeps alignment at 16 bytes - - lea(c_rarg0, InternalAddress(rip)); - lea(c_rarg1, Address(rbp, wordSize)); // pass pointer to regs array - call_VM_leaf(CAST_FROM_FN_PTR(address, MacroAssembler::print_state64), c_rarg0, c_rarg1); - - pop_CPU_state(); - mov(rsp, rbp); - pop(rbp); - popa(); -} - -#ifndef PRODUCT -extern "C" void findpc(intptr_t x); -#endif - -void MacroAssembler::debug64(char* msg, int64_t pc, int64_t regs[]) { - // In order to get locks to work, we need to fake a in_VM state - if (ShowMessageBoxOnError) { - JavaThread* thread = JavaThread::current(); - JavaThreadState saved_state = thread->thread_state(); - thread->set_thread_state(_thread_in_vm); -#ifndef PRODUCT - if (CountBytecodes || TraceBytecodes || StopInterpreterAt) { - ttyLocker ttyl; - BytecodeCounter::print(); - } -#endif - // To see where a verify_oop failed, get $ebx+40/X for this frame. - // XXX correct this offset for amd64 - // This is the value of eip which points to where verify_oop will return. - if (os::message_box(msg, "Execution stopped, print registers?")) { - print_state64(pc, regs); - BREAKPOINT; - assert(false, "start up GDB"); - } - ThreadStateTransition::transition(thread, _thread_in_vm, saved_state); - } else { - ttyLocker ttyl; - ::tty->print_cr("=============== DEBUG MESSAGE: %s ================\n", - msg); - assert(false, err_msg("DEBUG MESSAGE: %s", msg)); - } -} - -void MacroAssembler::print_state64(int64_t pc, int64_t regs[]) { - ttyLocker ttyl; - FlagSetting fs(Debugging, true); - tty->print_cr("rip = 0x%016lx", pc); -#ifndef PRODUCT - tty->cr(); - findpc(pc); - tty->cr(); -#endif -#define PRINT_REG(rax, value) \ - { tty->print("%s = ", #rax); os::print_location(tty, value); } - PRINT_REG(rax, regs[15]); - PRINT_REG(rbx, regs[12]); - PRINT_REG(rcx, regs[14]); - PRINT_REG(rdx, regs[13]); - PRINT_REG(rdi, regs[8]); - PRINT_REG(rsi, regs[9]); - PRINT_REG(rbp, regs[10]); - PRINT_REG(rsp, regs[11]); - PRINT_REG(r8 , regs[7]); - PRINT_REG(r9 , regs[6]); - PRINT_REG(r10, regs[5]); - PRINT_REG(r11, regs[4]); - PRINT_REG(r12, regs[3]); - PRINT_REG(r13, regs[2]); - PRINT_REG(r14, regs[1]); - PRINT_REG(r15, regs[0]); -#undef PRINT_REG - // Print some words near top of staack. - int64_t* rsp = (int64_t*) regs[11]; - int64_t* dump_sp = rsp; - for (int col1 = 0; col1 < 8; col1++) { - tty->print("(rsp+0x%03x) 0x%016lx: ", (int)((intptr_t)dump_sp - (intptr_t)rsp), (int64_t)dump_sp); - os::print_location(tty, *dump_sp++); - } - for (int row = 0; row < 25; row++) { - tty->print("(rsp+0x%03x) 0x%016lx: ", (int)((intptr_t)dump_sp - (intptr_t)rsp), (int64_t)dump_sp); - for (int col = 0; col < 4; col++) { - tty->print(" 0x%016lx", *dump_sp++); - } - tty->cr(); - } - // Print some instructions around pc: - Disassembler::decode((address)pc-64, (address)pc); - tty->print_cr("--------"); - Disassembler::decode((address)pc, (address)pc+32); -} - -#endif // _LP64 - -// Now versions that are common to 32/64 bit - -void MacroAssembler::addptr(Register dst, int32_t imm32) { - LP64_ONLY(addq(dst, imm32)) NOT_LP64(addl(dst, imm32)); -} - -void MacroAssembler::addptr(Register dst, Register src) { - LP64_ONLY(addq(dst, src)) NOT_LP64(addl(dst, src)); -} - -void MacroAssembler::addptr(Address dst, Register src) { - LP64_ONLY(addq(dst, src)) NOT_LP64(addl(dst, src)); -} - -void MacroAssembler::addsd(XMMRegister dst, AddressLiteral src) { - if (reachable(src)) { - Assembler::addsd(dst, as_Address(src)); - } else { - lea(rscratch1, src); - Assembler::addsd(dst, Address(rscratch1, 0)); - } -} - -void MacroAssembler::addss(XMMRegister dst, AddressLiteral src) { - if (reachable(src)) { - addss(dst, as_Address(src)); - } else { - lea(rscratch1, src); - addss(dst, Address(rscratch1, 0)); - } -} - -void MacroAssembler::align(int modulus) { - if (offset() % modulus != 0) { - nop(modulus - (offset() % modulus)); - } -} - -void MacroAssembler::andpd(XMMRegister dst, AddressLiteral src) { - // Used in sign-masking with aligned address. - assert((UseAVX > 0) || (((intptr_t)src.target() & 15) == 0), "SSE mode requires address alignment 16 bytes"); - if (reachable(src)) { - Assembler::andpd(dst, as_Address(src)); - } else { - lea(rscratch1, src); - Assembler::andpd(dst, Address(rscratch1, 0)); - } -} - -void MacroAssembler::andps(XMMRegister dst, AddressLiteral src) { - // Used in sign-masking with aligned address. - assert((UseAVX > 0) || (((intptr_t)src.target() & 15) == 0), "SSE mode requires address alignment 16 bytes"); - if (reachable(src)) { - Assembler::andps(dst, as_Address(src)); - } else { - lea(rscratch1, src); - Assembler::andps(dst, Address(rscratch1, 0)); - } -} - -void MacroAssembler::andptr(Register dst, int32_t imm32) { - LP64_ONLY(andq(dst, imm32)) NOT_LP64(andl(dst, imm32)); -} - -void MacroAssembler::atomic_incl(AddressLiteral counter_addr) { - pushf(); - if (os::is_MP()) - lock(); - incrementl(counter_addr); - popf(); -} - -// Writes to stack successive pages until offset reached to check for -// stack overflow + shadow pages. This clobbers tmp. -void MacroAssembler::bang_stack_size(Register size, Register tmp) { - movptr(tmp, rsp); - // Bang stack for total size given plus shadow page size. - // Bang one page at a time because large size can bang beyond yellow and - // red zones. - Label loop; - bind(loop); - movl(Address(tmp, (-os::vm_page_size())), size ); - subptr(tmp, os::vm_page_size()); - subl(size, os::vm_page_size()); - jcc(Assembler::greater, loop); - - // Bang down shadow pages too. - // The -1 because we already subtracted 1 page. - for (int i = 0; i< StackShadowPages-1; i++) { - // this could be any sized move but this is can be a debugging crumb - // so the bigger the better. - movptr(Address(tmp, (-i*os::vm_page_size())), size ); - } -} - -void MacroAssembler::biased_locking_exit(Register obj_reg, Register temp_reg, Label& done) { - assert(UseBiasedLocking, "why call this otherwise?"); - - // Check for biased locking unlock case, which is a no-op - // Note: we do not have to check the thread ID for two reasons. - // First, the interpreter checks for IllegalMonitorStateException at - // a higher level. Second, if the bias was revoked while we held the - // lock, the object could not be rebiased toward another thread, so - // the bias bit would be clear. - movptr(temp_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); - andptr(temp_reg, markOopDesc::biased_lock_mask_in_place); - cmpptr(temp_reg, markOopDesc::biased_lock_pattern); - jcc(Assembler::equal, done); -} - -void MacroAssembler::c2bool(Register x) { - // implements x == 0 ? 0 : 1 - // note: must only look at least-significant byte of x - // since C-style booleans are stored in one byte - // only! (was bug) - andl(x, 0xFF); - setb(Assembler::notZero, x); -} - -// Wouldn't need if AddressLiteral version had new name -void MacroAssembler::call(Label& L, relocInfo::relocType rtype) { - Assembler::call(L, rtype); -} - -void MacroAssembler::call(Register entry) { - Assembler::call(entry); -} - -void MacroAssembler::call(AddressLiteral entry) { - if (reachable(entry)) { - Assembler::call_literal(entry.target(), entry.rspec()); - } else { - lea(rscratch1, entry); - Assembler::call(rscratch1); - } -} - -void MacroAssembler::ic_call(address entry) { - RelocationHolder rh = virtual_call_Relocation::spec(pc()); - movptr(rax, (intptr_t)Universe::non_oop_word()); - call(AddressLiteral(entry, rh)); -} - -// Implementation of call_VM versions - -void MacroAssembler::call_VM(Register oop_result, - address entry_point, - bool check_exceptions) { - Label C, E; - call(C, relocInfo::none); - jmp(E); - - bind(C); - call_VM_helper(oop_result, entry_point, 0, check_exceptions); - ret(0); - - bind(E); -} - -void MacroAssembler::call_VM(Register oop_result, - address entry_point, - Register arg_1, - bool check_exceptions) { - Label C, E; - call(C, relocInfo::none); - jmp(E); - - bind(C); - pass_arg1(this, arg_1); - call_VM_helper(oop_result, entry_point, 1, check_exceptions); - ret(0); - - bind(E); -} - -void MacroAssembler::call_VM(Register oop_result, - address entry_point, - Register arg_1, - Register arg_2, - bool check_exceptions) { - Label C, E; - call(C, relocInfo::none); - jmp(E); - - bind(C); - - LP64_ONLY(assert(arg_1 != c_rarg2, "smashed arg")); - - pass_arg2(this, arg_2); - pass_arg1(this, arg_1); - call_VM_helper(oop_result, entry_point, 2, check_exceptions); - ret(0); - - bind(E); -} - -void MacroAssembler::call_VM(Register oop_result, - address entry_point, - Register arg_1, - Register arg_2, - Register arg_3, - bool check_exceptions) { - Label C, E; - call(C, relocInfo::none); - jmp(E); - - bind(C); - - LP64_ONLY(assert(arg_1 != c_rarg3, "smashed arg")); - LP64_ONLY(assert(arg_2 != c_rarg3, "smashed arg")); - pass_arg3(this, arg_3); - - LP64_ONLY(assert(arg_1 != c_rarg2, "smashed arg")); - pass_arg2(this, arg_2); - - pass_arg1(this, arg_1); - call_VM_helper(oop_result, entry_point, 3, check_exceptions); - ret(0); - - bind(E); -} - -void MacroAssembler::call_VM(Register oop_result, - Register last_java_sp, - address entry_point, - int number_of_arguments, - bool check_exceptions) { - Register thread = LP64_ONLY(r15_thread) NOT_LP64(noreg); - call_VM_base(oop_result, thread, last_java_sp, entry_point, number_of_arguments, check_exceptions); -} - -void MacroAssembler::call_VM(Register oop_result, - Register last_java_sp, - address entry_point, - Register arg_1, - bool check_exceptions) { - pass_arg1(this, arg_1); - call_VM(oop_result, last_java_sp, entry_point, 1, check_exceptions); -} - -void MacroAssembler::call_VM(Register oop_result, - Register last_java_sp, - address entry_point, - Register arg_1, - Register arg_2, - bool check_exceptions) { - - LP64_ONLY(assert(arg_1 != c_rarg2, "smashed arg")); - pass_arg2(this, arg_2); - pass_arg1(this, arg_1); - call_VM(oop_result, last_java_sp, entry_point, 2, check_exceptions); -} - -void MacroAssembler::call_VM(Register oop_result, - Register last_java_sp, - address entry_point, - Register arg_1, - Register arg_2, - Register arg_3, - bool check_exceptions) { - LP64_ONLY(assert(arg_1 != c_rarg3, "smashed arg")); - LP64_ONLY(assert(arg_2 != c_rarg3, "smashed arg")); - pass_arg3(this, arg_3); - LP64_ONLY(assert(arg_1 != c_rarg2, "smashed arg")); - pass_arg2(this, arg_2); - pass_arg1(this, arg_1); - call_VM(oop_result, last_java_sp, entry_point, 3, check_exceptions); -} - -void MacroAssembler::super_call_VM(Register oop_result, - Register last_java_sp, - address entry_point, - int number_of_arguments, - bool check_exceptions) { - Register thread = LP64_ONLY(r15_thread) NOT_LP64(noreg); - MacroAssembler::call_VM_base(oop_result, thread, last_java_sp, entry_point, number_of_arguments, check_exceptions); -} - -void MacroAssembler::super_call_VM(Register oop_result, - Register last_java_sp, - address entry_point, - Register arg_1, - bool check_exceptions) { - pass_arg1(this, arg_1); - super_call_VM(oop_result, last_java_sp, entry_point, 1, check_exceptions); -} - -void MacroAssembler::super_call_VM(Register oop_result, - Register last_java_sp, - address entry_point, - Register arg_1, - Register arg_2, - bool check_exceptions) { - - LP64_ONLY(assert(arg_1 != c_rarg2, "smashed arg")); - pass_arg2(this, arg_2); - pass_arg1(this, arg_1); - super_call_VM(oop_result, last_java_sp, entry_point, 2, check_exceptions); -} - -void MacroAssembler::super_call_VM(Register oop_result, - Register last_java_sp, - address entry_point, - Register arg_1, - Register arg_2, - Register arg_3, - bool check_exceptions) { - LP64_ONLY(assert(arg_1 != c_rarg3, "smashed arg")); - LP64_ONLY(assert(arg_2 != c_rarg3, "smashed arg")); - pass_arg3(this, arg_3); - LP64_ONLY(assert(arg_1 != c_rarg2, "smashed arg")); - pass_arg2(this, arg_2); - pass_arg1(this, arg_1); - super_call_VM(oop_result, last_java_sp, entry_point, 3, check_exceptions); -} - -void MacroAssembler::call_VM_base(Register oop_result, - Register java_thread, - Register last_java_sp, - address entry_point, - int number_of_arguments, - bool check_exceptions) { - // determine java_thread register - if (!java_thread->is_valid()) { -#ifdef _LP64 - java_thread = r15_thread; -#else - java_thread = rdi; - get_thread(java_thread); -#endif // LP64 - } - // determine last_java_sp register - if (!last_java_sp->is_valid()) { - last_java_sp = rsp; - } - // debugging support - assert(number_of_arguments >= 0 , "cannot have negative number of arguments"); - LP64_ONLY(assert(java_thread == r15_thread, "unexpected register")); -#ifdef ASSERT - // TraceBytecodes does not use r12 but saves it over the call, so don't verify - // r12 is the heapbase. - LP64_ONLY(if ((UseCompressedOops || UseCompressedKlassPointers) && !TraceBytecodes) verify_heapbase("call_VM_base: heap base corrupted?");) -#endif // ASSERT - - assert(java_thread != oop_result , "cannot use the same register for java_thread & oop_result"); - assert(java_thread != last_java_sp, "cannot use the same register for java_thread & last_java_sp"); - - // push java thread (becomes first argument of C function) - - NOT_LP64(push(java_thread); number_of_arguments++); - LP64_ONLY(mov(c_rarg0, r15_thread)); - - // set last Java frame before call - assert(last_java_sp != rbp, "can't use ebp/rbp"); - - // Only interpreter should have to set fp - set_last_Java_frame(java_thread, last_java_sp, rbp, NULL); - - // do the call, remove parameters - MacroAssembler::call_VM_leaf_base(entry_point, number_of_arguments); - - // restore the thread (cannot use the pushed argument since arguments - // may be overwritten by C code generated by an optimizing compiler); - // however can use the register value directly if it is callee saved. - if (LP64_ONLY(true ||) java_thread == rdi || java_thread == rsi) { - // rdi & rsi (also r15) are callee saved -> nothing to do -#ifdef ASSERT - guarantee(java_thread != rax, "change this code"); - push(rax); - { Label L; - get_thread(rax); - cmpptr(java_thread, rax); - jcc(Assembler::equal, L); - STOP("MacroAssembler::call_VM_base: rdi not callee saved?"); - bind(L); - } - pop(rax); -#endif - } else { - get_thread(java_thread); - } - // reset last Java frame - // Only interpreter should have to clear fp - reset_last_Java_frame(java_thread, true, false); - -#ifndef CC_INTERP - // C++ interp handles this in the interpreter - check_and_handle_popframe(java_thread); - check_and_handle_earlyret(java_thread); -#endif /* CC_INTERP */ - - if (check_exceptions) { - // check for pending exceptions (java_thread is set upon return) - cmpptr(Address(java_thread, Thread::pending_exception_offset()), (int32_t) NULL_WORD); -#ifndef _LP64 - jump_cc(Assembler::notEqual, - RuntimeAddress(StubRoutines::forward_exception_entry())); -#else - // This used to conditionally jump to forward_exception however it is - // possible if we relocate that the branch will not reach. So we must jump - // around so we can always reach - - Label ok; - jcc(Assembler::equal, ok); - jump(RuntimeAddress(StubRoutines::forward_exception_entry())); - bind(ok); -#endif // LP64 - } - - // get oop result if there is one and reset the value in the thread - if (oop_result->is_valid()) { - get_vm_result(oop_result, java_thread); - } -} - -void MacroAssembler::call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions) { - - // Calculate the value for last_Java_sp - // somewhat subtle. call_VM does an intermediate call - // which places a return address on the stack just under the - // stack pointer as the user finsihed with it. This allows - // use to retrieve last_Java_pc from last_Java_sp[-1]. - // On 32bit we then have to push additional args on the stack to accomplish - // the actual requested call. On 64bit call_VM only can use register args - // so the only extra space is the return address that call_VM created. - // This hopefully explains the calculations here. - -#ifdef _LP64 - // We've pushed one address, correct last_Java_sp - lea(rax, Address(rsp, wordSize)); -#else - lea(rax, Address(rsp, (1 + number_of_arguments) * wordSize)); -#endif // LP64 - - call_VM_base(oop_result, noreg, rax, entry_point, number_of_arguments, check_exceptions); - -} - -void MacroAssembler::call_VM_leaf(address entry_point, int number_of_arguments) { - call_VM_leaf_base(entry_point, number_of_arguments); -} - -void MacroAssembler::call_VM_leaf(address entry_point, Register arg_0) { - pass_arg0(this, arg_0); - call_VM_leaf(entry_point, 1); -} - -void MacroAssembler::call_VM_leaf(address entry_point, Register arg_0, Register arg_1) { - - LP64_ONLY(assert(arg_0 != c_rarg1, "smashed arg")); - pass_arg1(this, arg_1); - pass_arg0(this, arg_0); - call_VM_leaf(entry_point, 2); -} - -void MacroAssembler::call_VM_leaf(address entry_point, Register arg_0, Register arg_1, Register arg_2) { - LP64_ONLY(assert(arg_0 != c_rarg2, "smashed arg")); - LP64_ONLY(assert(arg_1 != c_rarg2, "smashed arg")); - pass_arg2(this, arg_2); - LP64_ONLY(assert(arg_0 != c_rarg1, "smashed arg")); - pass_arg1(this, arg_1); - pass_arg0(this, arg_0); - call_VM_leaf(entry_point, 3); -} - -void MacroAssembler::super_call_VM_leaf(address entry_point, Register arg_0) { - pass_arg0(this, arg_0); - MacroAssembler::call_VM_leaf_base(entry_point, 1); -} - -void MacroAssembler::super_call_VM_leaf(address entry_point, Register arg_0, Register arg_1) { - - LP64_ONLY(assert(arg_0 != c_rarg1, "smashed arg")); - pass_arg1(this, arg_1); - pass_arg0(this, arg_0); - MacroAssembler::call_VM_leaf_base(entry_point, 2); -} - -void MacroAssembler::super_call_VM_leaf(address entry_point, Register arg_0, Register arg_1, Register arg_2) { - LP64_ONLY(assert(arg_0 != c_rarg2, "smashed arg")); - LP64_ONLY(assert(arg_1 != c_rarg2, "smashed arg")); - pass_arg2(this, arg_2); - LP64_ONLY(assert(arg_0 != c_rarg1, "smashed arg")); - pass_arg1(this, arg_1); - pass_arg0(this, arg_0); - MacroAssembler::call_VM_leaf_base(entry_point, 3); -} - -void MacroAssembler::super_call_VM_leaf(address entry_point, Register arg_0, Register arg_1, Register arg_2, Register arg_3) { - LP64_ONLY(assert(arg_0 != c_rarg3, "smashed arg")); - LP64_ONLY(assert(arg_1 != c_rarg3, "smashed arg")); - LP64_ONLY(assert(arg_2 != c_rarg3, "smashed arg")); - pass_arg3(this, arg_3); - LP64_ONLY(assert(arg_0 != c_rarg2, "smashed arg")); - LP64_ONLY(assert(arg_1 != c_rarg2, "smashed arg")); - pass_arg2(this, arg_2); - LP64_ONLY(assert(arg_0 != c_rarg1, "smashed arg")); - pass_arg1(this, arg_1); - pass_arg0(this, arg_0); - MacroAssembler::call_VM_leaf_base(entry_point, 4); -} - -void MacroAssembler::get_vm_result(Register oop_result, Register java_thread) { - movptr(oop_result, Address(java_thread, JavaThread::vm_result_offset())); - movptr(Address(java_thread, JavaThread::vm_result_offset()), NULL_WORD); - verify_oop(oop_result, "broken oop in call_VM_base"); -} - -void MacroAssembler::get_vm_result_2(Register metadata_result, Register java_thread) { - movptr(metadata_result, Address(java_thread, JavaThread::vm_result_2_offset())); - movptr(Address(java_thread, JavaThread::vm_result_2_offset()), NULL_WORD); -} - -void MacroAssembler::check_and_handle_earlyret(Register java_thread) { -} - -void MacroAssembler::check_and_handle_popframe(Register java_thread) { -} - -void MacroAssembler::cmp32(AddressLiteral src1, int32_t imm) { - if (reachable(src1)) { - cmpl(as_Address(src1), imm); - } else { - lea(rscratch1, src1); - cmpl(Address(rscratch1, 0), imm); - } -} - -void MacroAssembler::cmp32(Register src1, AddressLiteral src2) { - assert(!src2.is_lval(), "use cmpptr"); - if (reachable(src2)) { - cmpl(src1, as_Address(src2)); - } else { - lea(rscratch1, src2); - cmpl(src1, Address(rscratch1, 0)); - } -} - -void MacroAssembler::cmp32(Register src1, int32_t imm) { - Assembler::cmpl(src1, imm); -} - -void MacroAssembler::cmp32(Register src1, Address src2) { - Assembler::cmpl(src1, src2); -} - -void MacroAssembler::cmpsd2int(XMMRegister opr1, XMMRegister opr2, Register dst, bool unordered_is_less) { - ucomisd(opr1, opr2); - - Label L; - if (unordered_is_less) { - movl(dst, -1); - jcc(Assembler::parity, L); - jcc(Assembler::below , L); - movl(dst, 0); - jcc(Assembler::equal , L); - increment(dst); - } else { // unordered is greater - movl(dst, 1); - jcc(Assembler::parity, L); - jcc(Assembler::above , L); - movl(dst, 0); - jcc(Assembler::equal , L); - decrementl(dst); - } - bind(L); -} - -void MacroAssembler::cmpss2int(XMMRegister opr1, XMMRegister opr2, Register dst, bool unordered_is_less) { - ucomiss(opr1, opr2); - - Label L; - if (unordered_is_less) { - movl(dst, -1); - jcc(Assembler::parity, L); - jcc(Assembler::below , L); - movl(dst, 0); - jcc(Assembler::equal , L); - increment(dst); - } else { // unordered is greater - movl(dst, 1); - jcc(Assembler::parity, L); - jcc(Assembler::above , L); - movl(dst, 0); - jcc(Assembler::equal , L); - decrementl(dst); - } - bind(L); -} - - -void MacroAssembler::cmp8(AddressLiteral src1, int imm) { - if (reachable(src1)) { - cmpb(as_Address(src1), imm); - } else { - lea(rscratch1, src1); - cmpb(Address(rscratch1, 0), imm); - } -} - -void MacroAssembler::cmpptr(Register src1, AddressLiteral src2) { -#ifdef _LP64 - if (src2.is_lval()) { - movptr(rscratch1, src2); - Assembler::cmpq(src1, rscratch1); - } else if (reachable(src2)) { - cmpq(src1, as_Address(src2)); - } else { - lea(rscratch1, src2); - Assembler::cmpq(src1, Address(rscratch1, 0)); - } -#else - if (src2.is_lval()) { - cmp_literal32(src1, (int32_t) src2.target(), src2.rspec()); - } else { - cmpl(src1, as_Address(src2)); - } -#endif // _LP64 -} - -void MacroAssembler::cmpptr(Address src1, AddressLiteral src2) { - assert(src2.is_lval(), "not a mem-mem compare"); -#ifdef _LP64 - // moves src2's literal address - movptr(rscratch1, src2); - Assembler::cmpq(src1, rscratch1); -#else - cmp_literal32(src1, (int32_t) src2.target(), src2.rspec()); -#endif // _LP64 -} - -void MacroAssembler::locked_cmpxchgptr(Register reg, AddressLiteral adr) { - if (reachable(adr)) { - if (os::is_MP()) - lock(); - cmpxchgptr(reg, as_Address(adr)); - } else { - lea(rscratch1, adr); - if (os::is_MP()) - lock(); - cmpxchgptr(reg, Address(rscratch1, 0)); - } -} - -void MacroAssembler::cmpxchgptr(Register reg, Address adr) { - LP64_ONLY(cmpxchgq(reg, adr)) NOT_LP64(cmpxchgl(reg, adr)); -} - -void MacroAssembler::comisd(XMMRegister dst, AddressLiteral src) { - if (reachable(src)) { - Assembler::comisd(dst, as_Address(src)); - } else { - lea(rscratch1, src); - Assembler::comisd(dst, Address(rscratch1, 0)); - } -} - -void MacroAssembler::comiss(XMMRegister dst, AddressLiteral src) { - if (reachable(src)) { - Assembler::comiss(dst, as_Address(src)); - } else { - lea(rscratch1, src); - Assembler::comiss(dst, Address(rscratch1, 0)); - } -} - - -void MacroAssembler::cond_inc32(Condition cond, AddressLiteral counter_addr) { - Condition negated_cond = negate_condition(cond); - Label L; - jcc(negated_cond, L); - atomic_incl(counter_addr); - bind(L); -} - -int MacroAssembler::corrected_idivl(Register reg) { - // Full implementation of Java idiv and irem; checks for - // special case as described in JVM spec., p.243 & p.271. - // The function returns the (pc) offset of the idivl - // instruction - may be needed for implicit exceptions. - // - // normal case special case - // - // input : rax,: dividend min_int - // reg: divisor (may not be rax,/rdx) -1 - // - // output: rax,: quotient (= rax, idiv reg) min_int - // rdx: remainder (= rax, irem reg) 0 - assert(reg != rax && reg != rdx, "reg cannot be rax, or rdx register"); - const int min_int = 0x80000000; - Label normal_case, special_case; - - // check for special case - cmpl(rax, min_int); - jcc(Assembler::notEqual, normal_case); - xorl(rdx, rdx); // prepare rdx for possible special case (where remainder = 0) - cmpl(reg, -1); - jcc(Assembler::equal, special_case); - - // handle normal case - bind(normal_case); - cdql(); - int idivl_offset = offset(); - idivl(reg); - - // normal and special case exit - bind(special_case); - - return idivl_offset; -} - - - -void MacroAssembler::decrementl(Register reg, int value) { - if (value == min_jint) {subl(reg, value) ; return; } - if (value < 0) { incrementl(reg, -value); return; } - if (value == 0) { ; return; } - if (value == 1 && UseIncDec) { decl(reg) ; return; } - /* else */ { subl(reg, value) ; return; } -} - -void MacroAssembler::decrementl(Address dst, int value) { - if (value == min_jint) {subl(dst, value) ; return; } - if (value < 0) { incrementl(dst, -value); return; } - if (value == 0) { ; return; } - if (value == 1 && UseIncDec) { decl(dst) ; return; } - /* else */ { subl(dst, value) ; return; } -} - -void MacroAssembler::division_with_shift (Register reg, int shift_value) { - assert (shift_value > 0, "illegal shift value"); - Label _is_positive; - testl (reg, reg); - jcc (Assembler::positive, _is_positive); - int offset = (1 << shift_value) - 1 ; - - if (offset == 1) { - incrementl(reg); - } else { - addl(reg, offset); - } - - bind (_is_positive); - sarl(reg, shift_value); -} - -void MacroAssembler::divsd(XMMRegister dst, AddressLiteral src) { - if (reachable(src)) { - Assembler::divsd(dst, as_Address(src)); - } else { - lea(rscratch1, src); - Assembler::divsd(dst, Address(rscratch1, 0)); - } -} - -void MacroAssembler::divss(XMMRegister dst, AddressLiteral src) { - if (reachable(src)) { - Assembler::divss(dst, as_Address(src)); - } else { - lea(rscratch1, src); - Assembler::divss(dst, Address(rscratch1, 0)); - } -} - -// !defined(COMPILER2) is because of stupid core builds -#if !defined(_LP64) || defined(COMPILER1) || !defined(COMPILER2) -void MacroAssembler::empty_FPU_stack() { - if (VM_Version::supports_mmx()) { - emms(); - } else { - for (int i = 8; i-- > 0; ) ffree(i); - } -} -#endif // !LP64 || C1 || !C2 - - -// Defines obj, preserves var_size_in_bytes -void MacroAssembler::eden_allocate(Register obj, - Register var_size_in_bytes, - int con_size_in_bytes, - Register t1, - Label& slow_case) { - assert(obj == rax, "obj must be in rax, for cmpxchg"); - assert_different_registers(obj, var_size_in_bytes, t1); - if (CMSIncrementalMode || !Universe::heap()->supports_inline_contig_alloc()) { - jmp(slow_case); - } else { - Register end = t1; - Label retry; - bind(retry); - ExternalAddress heap_top((address) Universe::heap()->top_addr()); - movptr(obj, heap_top); - if (var_size_in_bytes == noreg) { - lea(end, Address(obj, con_size_in_bytes)); - } else { - lea(end, Address(obj, var_size_in_bytes, Address::times_1)); - } - // if end < obj then we wrapped around => object too long => slow case - cmpptr(end, obj); - jcc(Assembler::below, slow_case); - cmpptr(end, ExternalAddress((address) Universe::heap()->end_addr())); - jcc(Assembler::above, slow_case); - // Compare obj with the top addr, and if still equal, store the new top addr in - // end at the address of the top addr pointer. Sets ZF if was equal, and clears - // it otherwise. Use lock prefix for atomicity on MPs. - locked_cmpxchgptr(end, heap_top); - jcc(Assembler::notEqual, retry); - } -} - -void MacroAssembler::enter() { - push(rbp); - mov(rbp, rsp); -} - -// A 5 byte nop that is safe for patching (see patch_verified_entry) -void MacroAssembler::fat_nop() { - if (UseAddressNop) { - addr_nop_5(); - } else { - emit_byte(0x26); // es: - emit_byte(0x2e); // cs: - emit_byte(0x64); // fs: - emit_byte(0x65); // gs: - emit_byte(0x90); - } -} - -void MacroAssembler::fcmp(Register tmp) { - fcmp(tmp, 1, true, true); -} - -void MacroAssembler::fcmp(Register tmp, int index, bool pop_left, bool pop_right) { - assert(!pop_right || pop_left, "usage error"); - if (VM_Version::supports_cmov()) { - assert(tmp == noreg, "unneeded temp"); - if (pop_left) { - fucomip(index); - } else { - fucomi(index); - } - if (pop_right) { - fpop(); - } - } else { - assert(tmp != noreg, "need temp"); - if (pop_left) { - if (pop_right) { - fcompp(); - } else { - fcomp(index); - } - } else { - fcom(index); - } - // convert FPU condition into eflags condition via rax, - save_rax(tmp); - fwait(); fnstsw_ax(); - sahf(); - restore_rax(tmp); - } - // condition codes set as follows: - // - // CF (corresponds to C0) if x < y - // PF (corresponds to C2) if unordered - // ZF (corresponds to C3) if x = y -} - -void MacroAssembler::fcmp2int(Register dst, bool unordered_is_less) { - fcmp2int(dst, unordered_is_less, 1, true, true); -} - -void MacroAssembler::fcmp2int(Register dst, bool unordered_is_less, int index, bool pop_left, bool pop_right) { - fcmp(VM_Version::supports_cmov() ? noreg : dst, index, pop_left, pop_right); - Label L; - if (unordered_is_less) { - movl(dst, -1); - jcc(Assembler::parity, L); - jcc(Assembler::below , L); - movl(dst, 0); - jcc(Assembler::equal , L); - increment(dst); - } else { // unordered is greater - movl(dst, 1); - jcc(Assembler::parity, L); - jcc(Assembler::above , L); - movl(dst, 0); - jcc(Assembler::equal , L); - decrementl(dst); - } - bind(L); -} - -void MacroAssembler::fld_d(AddressLiteral src) { - fld_d(as_Address(src)); -} - -void MacroAssembler::fld_s(AddressLiteral src) { - fld_s(as_Address(src)); -} - -void MacroAssembler::fld_x(AddressLiteral src) { - Assembler::fld_x(as_Address(src)); -} - -void MacroAssembler::fldcw(AddressLiteral src) { - Assembler::fldcw(as_Address(src)); -} - -void MacroAssembler::pow_exp_core_encoding() { - // kills rax, rcx, rdx - subptr(rsp,sizeof(jdouble)); - // computes 2^X. Stack: X ... - // f2xm1 computes 2^X-1 but only operates on -1<=X<=1. Get int(X) and - // keep it on the thread's stack to compute 2^int(X) later - // then compute 2^(X-int(X)) as (2^(X-int(X)-1+1) - // final result is obtained with: 2^X = 2^int(X) * 2^(X-int(X)) - fld_s(0); // Stack: X X ... - frndint(); // Stack: int(X) X ... - fsuba(1); // Stack: int(X) X-int(X) ... - fistp_s(Address(rsp,0)); // move int(X) as integer to thread's stack. Stack: X-int(X) ... - f2xm1(); // Stack: 2^(X-int(X))-1 ... - fld1(); // Stack: 1 2^(X-int(X))-1 ... - faddp(1); // Stack: 2^(X-int(X)) - // computes 2^(int(X)): add exponent bias (1023) to int(X), then - // shift int(X)+1023 to exponent position. - // Exponent is limited to 11 bits if int(X)+1023 does not fit in 11 - // bits, set result to NaN. 0x000 and 0x7FF are reserved exponent - // values so detect them and set result to NaN. - movl(rax,Address(rsp,0)); - movl(rcx, -2048); // 11 bit mask and valid NaN binary encoding - addl(rax, 1023); - movl(rdx,rax); - shll(rax,20); - // Check that 0 < int(X)+1023 < 2047. Otherwise set rax to NaN. - addl(rdx,1); - // Check that 1 < int(X)+1023+1 < 2048 - // in 3 steps: - // 1- (int(X)+1023+1)&-2048 == 0 => 0 <= int(X)+1023+1 < 2048 - // 2- (int(X)+1023+1)&-2048 != 0 - // 3- (int(X)+1023+1)&-2048 != 1 - // Do 2- first because addl just updated the flags. - cmov32(Assembler::equal,rax,rcx); - cmpl(rdx,1); - cmov32(Assembler::equal,rax,rcx); - testl(rdx,rcx); - cmov32(Assembler::notEqual,rax,rcx); - movl(Address(rsp,4),rax); - movl(Address(rsp,0),0); - fmul_d(Address(rsp,0)); // Stack: 2^X ... - addptr(rsp,sizeof(jdouble)); -} - -void MacroAssembler::increase_precision() { - subptr(rsp, BytesPerWord); - fnstcw(Address(rsp, 0)); - movl(rax, Address(rsp, 0)); - orl(rax, 0x300); - push(rax); - fldcw(Address(rsp, 0)); - pop(rax); -} - -void MacroAssembler::restore_precision() { - fldcw(Address(rsp, 0)); - addptr(rsp, BytesPerWord); -} - -void MacroAssembler::fast_pow() { - // computes X^Y = 2^(Y * log2(X)) - // if fast computation is not possible, result is NaN. Requires - // fallback from user of this macro. - // increase precision for intermediate steps of the computation - increase_precision(); - fyl2x(); // Stack: (Y*log2(X)) ... - pow_exp_core_encoding(); // Stack: exp(X) ... - restore_precision(); -} - -void MacroAssembler::fast_exp() { - // computes exp(X) = 2^(X * log2(e)) - // if fast computation is not possible, result is NaN. Requires - // fallback from user of this macro. - // increase precision for intermediate steps of the computation - increase_precision(); - fldl2e(); // Stack: log2(e) X ... - fmulp(1); // Stack: (X*log2(e)) ... - pow_exp_core_encoding(); // Stack: exp(X) ... - restore_precision(); -} - -void MacroAssembler::pow_or_exp(bool is_exp, int num_fpu_regs_in_use) { - // kills rax, rcx, rdx - // pow and exp needs 2 extra registers on the fpu stack. - Label slow_case, done; - Register tmp = noreg; - if (!VM_Version::supports_cmov()) { - // fcmp needs a temporary so preserve rdx, - tmp = rdx; - } - Register tmp2 = rax; - Register tmp3 = rcx; - - if (is_exp) { - // Stack: X - fld_s(0); // duplicate argument for runtime call. Stack: X X - fast_exp(); // Stack: exp(X) X - fcmp(tmp, 0, false, false); // Stack: exp(X) X - // exp(X) not equal to itself: exp(X) is NaN go to slow case. - jcc(Assembler::parity, slow_case); - // get rid of duplicate argument. Stack: exp(X) - if (num_fpu_regs_in_use > 0) { - fxch(); - fpop(); - } else { - ffree(1); - } - jmp(done); - } else { - // Stack: X Y - Label x_negative, y_odd; - - fldz(); // Stack: 0 X Y - fcmp(tmp, 1, true, false); // Stack: X Y - jcc(Assembler::above, x_negative); - - // X >= 0 - - fld_s(1); // duplicate arguments for runtime call. Stack: Y X Y - fld_s(1); // Stack: X Y X Y - fast_pow(); // Stack: X^Y X Y - fcmp(tmp, 0, false, false); // Stack: X^Y X Y - // X^Y not equal to itself: X^Y is NaN go to slow case. - jcc(Assembler::parity, slow_case); - // get rid of duplicate arguments. Stack: X^Y - if (num_fpu_regs_in_use > 0) { - fxch(); fpop(); - fxch(); fpop(); - } else { - ffree(2); - ffree(1); - } - jmp(done); - - // X <= 0 - bind(x_negative); - - fld_s(1); // Stack: Y X Y - frndint(); // Stack: int(Y) X Y - fcmp(tmp, 2, false, false); // Stack: int(Y) X Y - jcc(Assembler::notEqual, slow_case); - - subptr(rsp, 8); - - // For X^Y, when X < 0, Y has to be an integer and the final - // result depends on whether it's odd or even. We just checked - // that int(Y) == Y. We move int(Y) to gp registers as a 64 bit - // integer to test its parity. If int(Y) is huge and doesn't fit - // in the 64 bit integer range, the integer indefinite value will - // end up in the gp registers. Huge numbers are all even, the - // integer indefinite number is even so it's fine. - -#ifdef ASSERT - // Let's check we don't end up with an integer indefinite number - // when not expected. First test for huge numbers: check whether - // int(Y)+1 == int(Y) which is true for very large numbers and - // those are all even. A 64 bit integer is guaranteed to not - // overflow for numbers where y+1 != y (when precision is set to - // double precision). - Label y_not_huge; - - fld1(); // Stack: 1 int(Y) X Y - fadd(1); // Stack: 1+int(Y) int(Y) X Y - -#ifdef _LP64 - // trip to memory to force the precision down from double extended - // precision - fstp_d(Address(rsp, 0)); - fld_d(Address(rsp, 0)); -#endif - - fcmp(tmp, 1, true, false); // Stack: int(Y) X Y -#endif - - // move int(Y) as 64 bit integer to thread's stack - fistp_d(Address(rsp,0)); // Stack: X Y - -#ifdef ASSERT - jcc(Assembler::notEqual, y_not_huge); - - // Y is huge so we know it's even. It may not fit in a 64 bit - // integer and we don't want the debug code below to see the - // integer indefinite value so overwrite int(Y) on the thread's - // stack with 0. - movl(Address(rsp, 0), 0); - movl(Address(rsp, 4), 0); - - bind(y_not_huge); -#endif - - fld_s(1); // duplicate arguments for runtime call. Stack: Y X Y - fld_s(1); // Stack: X Y X Y - fabs(); // Stack: abs(X) Y X Y - fast_pow(); // Stack: abs(X)^Y X Y - fcmp(tmp, 0, false, false); // Stack: abs(X)^Y X Y - // abs(X)^Y not equal to itself: abs(X)^Y is NaN go to slow case. - - pop(tmp2); - NOT_LP64(pop(tmp3)); - jcc(Assembler::parity, slow_case); - -#ifdef ASSERT - // Check that int(Y) is not integer indefinite value (int - // overflow). Shouldn't happen because for values that would - // overflow, 1+int(Y)==Y which was tested earlier. -#ifndef _LP64 - { - Label integer; - testl(tmp2, tmp2); - jcc(Assembler::notZero, integer); - cmpl(tmp3, 0x80000000); - jcc(Assembler::notZero, integer); - STOP("integer indefinite value shouldn't be seen here"); - bind(integer); - } -#else - { - Label integer; - mov(tmp3, tmp2); // preserve tmp2 for parity check below - shlq(tmp3, 1); - jcc(Assembler::carryClear, integer); - jcc(Assembler::notZero, integer); - STOP("integer indefinite value shouldn't be seen here"); - bind(integer); - } -#endif -#endif - - // get rid of duplicate arguments. Stack: X^Y - if (num_fpu_regs_in_use > 0) { - fxch(); fpop(); - fxch(); fpop(); - } else { - ffree(2); - ffree(1); - } - - testl(tmp2, 1); - jcc(Assembler::zero, done); // X <= 0, Y even: X^Y = abs(X)^Y - // X <= 0, Y even: X^Y = -abs(X)^Y - - fchs(); // Stack: -abs(X)^Y Y - jmp(done); - } - - // slow case: runtime call - bind(slow_case); - - fpop(); // pop incorrect result or int(Y) - - fp_runtime_fallback(is_exp ? CAST_FROM_FN_PTR(address, SharedRuntime::dexp) : CAST_FROM_FN_PTR(address, SharedRuntime::dpow), - is_exp ? 1 : 2, num_fpu_regs_in_use); - - // Come here with result in F-TOS - bind(done); -} - -void MacroAssembler::fpop() { - ffree(); - fincstp(); -} - -void MacroAssembler::fremr(Register tmp) { - save_rax(tmp); - { Label L; - bind(L); - fprem(); - fwait(); fnstsw_ax(); -#ifdef _LP64 - testl(rax, 0x400); - jcc(Assembler::notEqual, L); -#else - sahf(); - jcc(Assembler::parity, L); -#endif // _LP64 - } - restore_rax(tmp); - // Result is in ST0. - // Note: fxch & fpop to get rid of ST1 - // (otherwise FPU stack could overflow eventually) - fxch(1); - fpop(); -} - - -void MacroAssembler::incrementl(AddressLiteral dst) { - if (reachable(dst)) { - incrementl(as_Address(dst)); - } else { - lea(rscratch1, dst); - incrementl(Address(rscratch1, 0)); - } -} - -void MacroAssembler::incrementl(ArrayAddress dst) { - incrementl(as_Address(dst)); -} - -void MacroAssembler::incrementl(Register reg, int value) { - if (value == min_jint) {addl(reg, value) ; return; } - if (value < 0) { decrementl(reg, -value); return; } - if (value == 0) { ; return; } - if (value == 1 && UseIncDec) { incl(reg) ; return; } - /* else */ { addl(reg, value) ; return; } -} - -void MacroAssembler::incrementl(Address dst, int value) { - if (value == min_jint) {addl(dst, value) ; return; } - if (value < 0) { decrementl(dst, -value); return; } - if (value == 0) { ; return; } - if (value == 1 && UseIncDec) { incl(dst) ; return; } - /* else */ { addl(dst, value) ; return; } -} - -void MacroAssembler::jump(AddressLiteral dst) { - if (reachable(dst)) { - jmp_literal(dst.target(), dst.rspec()); - } else { - lea(rscratch1, dst); - jmp(rscratch1); - } -} - -void MacroAssembler::jump_cc(Condition cc, AddressLiteral dst) { - if (reachable(dst)) { - InstructionMark im(this); - relocate(dst.reloc()); - const int short_size = 2; - const int long_size = 6; - int offs = (intptr_t)dst.target() - ((intptr_t)_code_pos); - if (dst.reloc() == relocInfo::none && is8bit(offs - short_size)) { - // 0111 tttn #8-bit disp - emit_byte(0x70 | cc); - emit_byte((offs - short_size) & 0xFF); - } else { - // 0000 1111 1000 tttn #32-bit disp - emit_byte(0x0F); - emit_byte(0x80 | cc); - emit_long(offs - long_size); - } - } else { -#ifdef ASSERT - warning("reversing conditional branch"); -#endif /* ASSERT */ - Label skip; - jccb(reverse[cc], skip); - lea(rscratch1, dst); - Assembler::jmp(rscratch1); - bind(skip); - } -} - -void MacroAssembler::ldmxcsr(AddressLiteral src) { - if (reachable(src)) { - Assembler::ldmxcsr(as_Address(src)); - } else { - lea(rscratch1, src); - Assembler::ldmxcsr(Address(rscratch1, 0)); - } -} - -int MacroAssembler::load_signed_byte(Register dst, Address src) { - int off; - if (LP64_ONLY(true ||) VM_Version::is_P6()) { - off = offset(); - movsbl(dst, src); // movsxb - } else { - off = load_unsigned_byte(dst, src); - shll(dst, 24); - sarl(dst, 24); - } - return off; -} - -// Note: load_signed_short used to be called load_signed_word. -// Although the 'w' in x86 opcodes refers to the term "word" in the assembler -// manual, which means 16 bits, that usage is found nowhere in HotSpot code. -// The term "word" in HotSpot means a 32- or 64-bit machine word. -int MacroAssembler::load_signed_short(Register dst, Address src) { - int off; - if (LP64_ONLY(true ||) VM_Version::is_P6()) { - // This is dubious to me since it seems safe to do a signed 16 => 64 bit - // version but this is what 64bit has always done. This seems to imply - // that users are only using 32bits worth. - off = offset(); - movswl(dst, src); // movsxw - } else { - off = load_unsigned_short(dst, src); - shll(dst, 16); - sarl(dst, 16); - } - return off; -} - -int MacroAssembler::load_unsigned_byte(Register dst, Address src) { - // According to Intel Doc. AP-526, "Zero-Extension of Short", p.16, - // and "3.9 Partial Register Penalties", p. 22). - int off; - if (LP64_ONLY(true || ) VM_Version::is_P6() || src.uses(dst)) { - off = offset(); - movzbl(dst, src); // movzxb - } else { - xorl(dst, dst); - off = offset(); - movb(dst, src); - } - return off; -} - -// Note: load_unsigned_short used to be called load_unsigned_word. -int MacroAssembler::load_unsigned_short(Register dst, Address src) { - // According to Intel Doc. AP-526, "Zero-Extension of Short", p.16, - // and "3.9 Partial Register Penalties", p. 22). - int off; - if (LP64_ONLY(true ||) VM_Version::is_P6() || src.uses(dst)) { - off = offset(); - movzwl(dst, src); // movzxw - } else { - xorl(dst, dst); - off = offset(); - movw(dst, src); - } - return off; -} - -void MacroAssembler::load_sized_value(Register dst, Address src, size_t size_in_bytes, bool is_signed, Register dst2) { - switch (size_in_bytes) { -#ifndef _LP64 - case 8: - assert(dst2 != noreg, "second dest register required"); - movl(dst, src); - movl(dst2, src.plus_disp(BytesPerInt)); - break; -#else - case 8: movq(dst, src); break; -#endif - case 4: movl(dst, src); break; - case 2: is_signed ? load_signed_short(dst, src) : load_unsigned_short(dst, src); break; - case 1: is_signed ? load_signed_byte( dst, src) : load_unsigned_byte( dst, src); break; - default: ShouldNotReachHere(); - } -} - -void MacroAssembler::store_sized_value(Address dst, Register src, size_t size_in_bytes, Register src2) { - switch (size_in_bytes) { -#ifndef _LP64 - case 8: - assert(src2 != noreg, "second source register required"); - movl(dst, src); - movl(dst.plus_disp(BytesPerInt), src2); - break; -#else - case 8: movq(dst, src); break; -#endif - case 4: movl(dst, src); break; - case 2: movw(dst, src); break; - case 1: movb(dst, src); break; - default: ShouldNotReachHere(); - } -} - -void MacroAssembler::mov32(AddressLiteral dst, Register src) { - if (reachable(dst)) { - movl(as_Address(dst), src); - } else { - lea(rscratch1, dst); - movl(Address(rscratch1, 0), src); - } -} - -void MacroAssembler::mov32(Register dst, AddressLiteral src) { - if (reachable(src)) { - movl(dst, as_Address(src)); - } else { - lea(rscratch1, src); - movl(dst, Address(rscratch1, 0)); - } -} - -// C++ bool manipulation - -void MacroAssembler::movbool(Register dst, Address src) { - if(sizeof(bool) == 1) - movb(dst, src); - else if(sizeof(bool) == 2) - movw(dst, src); - else if(sizeof(bool) == 4) - movl(dst, src); - else - // unsupported - ShouldNotReachHere(); -} - -void MacroAssembler::movbool(Address dst, bool boolconst) { - if(sizeof(bool) == 1) - movb(dst, (int) boolconst); - else if(sizeof(bool) == 2) - movw(dst, (int) boolconst); - else if(sizeof(bool) == 4) - movl(dst, (int) boolconst); - else - // unsupported - ShouldNotReachHere(); -} - -void MacroAssembler::movbool(Address dst, Register src) { - if(sizeof(bool) == 1) - movb(dst, src); - else if(sizeof(bool) == 2) - movw(dst, src); - else if(sizeof(bool) == 4) - movl(dst, src); - else - // unsupported - ShouldNotReachHere(); -} - -void MacroAssembler::movbyte(ArrayAddress dst, int src) { - movb(as_Address(dst), src); -} - -void MacroAssembler::movdl(XMMRegister dst, AddressLiteral src) { - if (reachable(src)) { - movdl(dst, as_Address(src)); - } else { - lea(rscratch1, src); - movdl(dst, Address(rscratch1, 0)); - } -} - -void MacroAssembler::movq(XMMRegister dst, AddressLiteral src) { - if (reachable(src)) { - movq(dst, as_Address(src)); - } else { - lea(rscratch1, src); - movq(dst, Address(rscratch1, 0)); - } -} - -void MacroAssembler::movdbl(XMMRegister dst, AddressLiteral src) { - if (reachable(src)) { - if (UseXmmLoadAndClearUpper) { - movsd (dst, as_Address(src)); - } else { - movlpd(dst, as_Address(src)); - } - } else { - lea(rscratch1, src); - if (UseXmmLoadAndClearUpper) { - movsd (dst, Address(rscratch1, 0)); - } else { - movlpd(dst, Address(rscratch1, 0)); - } - } -} - -void MacroAssembler::movflt(XMMRegister dst, AddressLiteral src) { - if (reachable(src)) { - movss(dst, as_Address(src)); - } else { - lea(rscratch1, src); - movss(dst, Address(rscratch1, 0)); - } -} - -void MacroAssembler::movptr(Register dst, Register src) { - LP64_ONLY(movq(dst, src)) NOT_LP64(movl(dst, src)); -} - -void MacroAssembler::movptr(Register dst, Address src) { - LP64_ONLY(movq(dst, src)) NOT_LP64(movl(dst, src)); -} - -// src should NEVER be a real pointer. Use AddressLiteral for true pointers -void MacroAssembler::movptr(Register dst, intptr_t src) { - LP64_ONLY(mov64(dst, src)) NOT_LP64(movl(dst, src)); -} - -void MacroAssembler::movptr(Address dst, Register src) { - LP64_ONLY(movq(dst, src)) NOT_LP64(movl(dst, src)); -} - -void MacroAssembler::movdqu(XMMRegister dst, AddressLiteral src) { - if (reachable(src)) { - Assembler::movdqu(dst, as_Address(src)); - } else { - lea(rscratch1, src); - Assembler::movdqu(dst, Address(rscratch1, 0)); - } -} - -void MacroAssembler::movsd(XMMRegister dst, AddressLiteral src) { - if (reachable(src)) { - Assembler::movsd(dst, as_Address(src)); - } else { - lea(rscratch1, src); - Assembler::movsd(dst, Address(rscratch1, 0)); - } -} - -void MacroAssembler::movss(XMMRegister dst, AddressLiteral src) { - if (reachable(src)) { - Assembler::movss(dst, as_Address(src)); - } else { - lea(rscratch1, src); - Assembler::movss(dst, Address(rscratch1, 0)); - } -} - -void MacroAssembler::mulsd(XMMRegister dst, AddressLiteral src) { - if (reachable(src)) { - Assembler::mulsd(dst, as_Address(src)); - } else { - lea(rscratch1, src); - Assembler::mulsd(dst, Address(rscratch1, 0)); - } -} - -void MacroAssembler::mulss(XMMRegister dst, AddressLiteral src) { - if (reachable(src)) { - Assembler::mulss(dst, as_Address(src)); - } else { - lea(rscratch1, src); - Assembler::mulss(dst, Address(rscratch1, 0)); - } -} - -void MacroAssembler::null_check(Register reg, int offset) { - if (needs_explicit_null_check(offset)) { - // provoke OS NULL exception if reg = NULL by - // accessing M[reg] w/o changing any (non-CC) registers - // NOTE: cmpl is plenty here to provoke a segv - cmpptr(rax, Address(reg, 0)); - // Note: should probably use testl(rax, Address(reg, 0)); - // may be shorter code (however, this version of - // testl needs to be implemented first) - } else { - // nothing to do, (later) access of M[reg + offset] - // will provoke OS NULL exception if reg = NULL - } -} - -void MacroAssembler::os_breakpoint() { - // instead of directly emitting a breakpoint, call os:breakpoint for better debugability - // (e.g., MSVC can't call ps() otherwise) - call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); -} - -void MacroAssembler::pop_CPU_state() { - pop_FPU_state(); - pop_IU_state(); -} - -void MacroAssembler::pop_FPU_state() { - NOT_LP64(frstor(Address(rsp, 0));) - LP64_ONLY(fxrstor(Address(rsp, 0));) - addptr(rsp, FPUStateSizeInWords * wordSize); -} - -void MacroAssembler::pop_IU_state() { - popa(); - LP64_ONLY(addq(rsp, 8)); - popf(); -} - -// Save Integer and Float state -// Warning: Stack must be 16 byte aligned (64bit) -void MacroAssembler::push_CPU_state() { - push_IU_state(); - push_FPU_state(); -} - -void MacroAssembler::push_FPU_state() { - subptr(rsp, FPUStateSizeInWords * wordSize); -#ifndef _LP64 - fnsave(Address(rsp, 0)); - fwait(); -#else - fxsave(Address(rsp, 0)); -#endif // LP64 -} - -void MacroAssembler::push_IU_state() { - // Push flags first because pusha kills them - pushf(); - // Make sure rsp stays 16-byte aligned - LP64_ONLY(subq(rsp, 8)); - pusha(); -} - -void MacroAssembler::reset_last_Java_frame(Register java_thread, bool clear_fp, bool clear_pc) { - // determine java_thread register - if (!java_thread->is_valid()) { - java_thread = rdi; - get_thread(java_thread); - } - // we must set sp to zero to clear frame - movptr(Address(java_thread, JavaThread::last_Java_sp_offset()), NULL_WORD); - if (clear_fp) { - movptr(Address(java_thread, JavaThread::last_Java_fp_offset()), NULL_WORD); - } - - if (clear_pc) - movptr(Address(java_thread, JavaThread::last_Java_pc_offset()), NULL_WORD); - -} - -void MacroAssembler::restore_rax(Register tmp) { - if (tmp == noreg) pop(rax); - else if (tmp != rax) mov(rax, tmp); -} - -void MacroAssembler::round_to(Register reg, int modulus) { - addptr(reg, modulus - 1); - andptr(reg, -modulus); -} - -void MacroAssembler::save_rax(Register tmp) { - if (tmp == noreg) push(rax); - else if (tmp != rax) mov(tmp, rax); -} - -// Write serialization page so VM thread can do a pseudo remote membar. -// We use the current thread pointer to calculate a thread specific -// offset to write to within the page. This minimizes bus traffic -// due to cache line collision. -void MacroAssembler::serialize_memory(Register thread, Register tmp) { - movl(tmp, thread); - shrl(tmp, os::get_serialize_page_shift_count()); - andl(tmp, (os::vm_page_size() - sizeof(int))); - - Address index(noreg, tmp, Address::times_1); - ExternalAddress page(os::get_memory_serialize_page()); - - // Size of store must match masking code above - movl(as_Address(ArrayAddress(page, index)), tmp); -} - -// Calls to C land -// -// When entering C land, the rbp, & rsp of the last Java frame have to be recorded -// in the (thread-local) JavaThread object. When leaving C land, the last Java fp -// has to be reset to 0. This is required to allow proper stack traversal. -void MacroAssembler::set_last_Java_frame(Register java_thread, - Register last_java_sp, - Register last_java_fp, - address last_java_pc) { - // determine java_thread register - if (!java_thread->is_valid()) { - java_thread = rdi; - get_thread(java_thread); - } - // determine last_java_sp register - if (!last_java_sp->is_valid()) { - last_java_sp = rsp; - } - - // last_java_fp is optional - - if (last_java_fp->is_valid()) { - movptr(Address(java_thread, JavaThread::last_Java_fp_offset()), last_java_fp); - } - - // last_java_pc is optional - - if (last_java_pc != NULL) { - lea(Address(java_thread, - JavaThread::frame_anchor_offset() + JavaFrameAnchor::last_Java_pc_offset()), - InternalAddress(last_java_pc)); - - } - movptr(Address(java_thread, JavaThread::last_Java_sp_offset()), last_java_sp); -} - -void MacroAssembler::shlptr(Register dst, int imm8) { - LP64_ONLY(shlq(dst, imm8)) NOT_LP64(shll(dst, imm8)); -} - -void MacroAssembler::shrptr(Register dst, int imm8) { - LP64_ONLY(shrq(dst, imm8)) NOT_LP64(shrl(dst, imm8)); -} - -void MacroAssembler::sign_extend_byte(Register reg) { - if (LP64_ONLY(true ||) (VM_Version::is_P6() && reg->has_byte_register())) { - movsbl(reg, reg); // movsxb - } else { - shll(reg, 24); - sarl(reg, 24); - } -} - -void MacroAssembler::sign_extend_short(Register reg) { - if (LP64_ONLY(true ||) VM_Version::is_P6()) { - movswl(reg, reg); // movsxw - } else { - shll(reg, 16); - sarl(reg, 16); - } -} - -void MacroAssembler::testl(Register dst, AddressLiteral src) { - assert(reachable(src), "Address should be reachable"); - testl(dst, as_Address(src)); -} - -void MacroAssembler::sqrtsd(XMMRegister dst, AddressLiteral src) { - if (reachable(src)) { - Assembler::sqrtsd(dst, as_Address(src)); - } else { - lea(rscratch1, src); - Assembler::sqrtsd(dst, Address(rscratch1, 0)); - } -} - -void MacroAssembler::sqrtss(XMMRegister dst, AddressLiteral src) { - if (reachable(src)) { - Assembler::sqrtss(dst, as_Address(src)); - } else { - lea(rscratch1, src); - Assembler::sqrtss(dst, Address(rscratch1, 0)); - } -} - -void MacroAssembler::subsd(XMMRegister dst, AddressLiteral src) { - if (reachable(src)) { - Assembler::subsd(dst, as_Address(src)); - } else { - lea(rscratch1, src); - Assembler::subsd(dst, Address(rscratch1, 0)); - } -} - -void MacroAssembler::subss(XMMRegister dst, AddressLiteral src) { - if (reachable(src)) { - Assembler::subss(dst, as_Address(src)); - } else { - lea(rscratch1, src); - Assembler::subss(dst, Address(rscratch1, 0)); - } -} - -void MacroAssembler::ucomisd(XMMRegister dst, AddressLiteral src) { - if (reachable(src)) { - Assembler::ucomisd(dst, as_Address(src)); - } else { - lea(rscratch1, src); - Assembler::ucomisd(dst, Address(rscratch1, 0)); - } -} - -void MacroAssembler::ucomiss(XMMRegister dst, AddressLiteral src) { - if (reachable(src)) { - Assembler::ucomiss(dst, as_Address(src)); - } else { - lea(rscratch1, src); - Assembler::ucomiss(dst, Address(rscratch1, 0)); - } -} - -void MacroAssembler::xorpd(XMMRegister dst, AddressLiteral src) { - // Used in sign-bit flipping with aligned address. - assert((UseAVX > 0) || (((intptr_t)src.target() & 15) == 0), "SSE mode requires address alignment 16 bytes"); - if (reachable(src)) { - Assembler::xorpd(dst, as_Address(src)); - } else { - lea(rscratch1, src); - Assembler::xorpd(dst, Address(rscratch1, 0)); - } -} - -void MacroAssembler::xorps(XMMRegister dst, AddressLiteral src) { - // Used in sign-bit flipping with aligned address. - assert((UseAVX > 0) || (((intptr_t)src.target() & 15) == 0), "SSE mode requires address alignment 16 bytes"); - if (reachable(src)) { - Assembler::xorps(dst, as_Address(src)); - } else { - lea(rscratch1, src); - Assembler::xorps(dst, Address(rscratch1, 0)); - } -} - -void MacroAssembler::pshufb(XMMRegister dst, AddressLiteral src) { - // Used in sign-bit flipping with aligned address. - assert((UseAVX > 0) || (((intptr_t)src.target() & 15) == 0), "SSE mode requires address alignment 16 bytes"); - if (reachable(src)) { - Assembler::pshufb(dst, as_Address(src)); - } else { - lea(rscratch1, src); - Assembler::pshufb(dst, Address(rscratch1, 0)); - } -} - -// AVX 3-operands instructions - -void MacroAssembler::vaddsd(XMMRegister dst, XMMRegister nds, AddressLiteral src) { - if (reachable(src)) { - vaddsd(dst, nds, as_Address(src)); - } else { - lea(rscratch1, src); - vaddsd(dst, nds, Address(rscratch1, 0)); - } -} - -void MacroAssembler::vaddss(XMMRegister dst, XMMRegister nds, AddressLiteral src) { - if (reachable(src)) { - vaddss(dst, nds, as_Address(src)); - } else { - lea(rscratch1, src); - vaddss(dst, nds, Address(rscratch1, 0)); - } -} - -void MacroAssembler::vandpd(XMMRegister dst, XMMRegister nds, AddressLiteral src, bool vector256) { - if (reachable(src)) { - vandpd(dst, nds, as_Address(src), vector256); - } else { - lea(rscratch1, src); - vandpd(dst, nds, Address(rscratch1, 0), vector256); - } -} - -void MacroAssembler::vandps(XMMRegister dst, XMMRegister nds, AddressLiteral src, bool vector256) { - if (reachable(src)) { - vandps(dst, nds, as_Address(src), vector256); - } else { - lea(rscratch1, src); - vandps(dst, nds, Address(rscratch1, 0), vector256); - } -} - -void MacroAssembler::vdivsd(XMMRegister dst, XMMRegister nds, AddressLiteral src) { - if (reachable(src)) { - vdivsd(dst, nds, as_Address(src)); - } else { - lea(rscratch1, src); - vdivsd(dst, nds, Address(rscratch1, 0)); - } -} - -void MacroAssembler::vdivss(XMMRegister dst, XMMRegister nds, AddressLiteral src) { - if (reachable(src)) { - vdivss(dst, nds, as_Address(src)); - } else { - lea(rscratch1, src); - vdivss(dst, nds, Address(rscratch1, 0)); - } -} - -void MacroAssembler::vmulsd(XMMRegister dst, XMMRegister nds, AddressLiteral src) { - if (reachable(src)) { - vmulsd(dst, nds, as_Address(src)); - } else { - lea(rscratch1, src); - vmulsd(dst, nds, Address(rscratch1, 0)); - } -} - -void MacroAssembler::vmulss(XMMRegister dst, XMMRegister nds, AddressLiteral src) { - if (reachable(src)) { - vmulss(dst, nds, as_Address(src)); - } else { - lea(rscratch1, src); - vmulss(dst, nds, Address(rscratch1, 0)); - } -} - -void MacroAssembler::vsubsd(XMMRegister dst, XMMRegister nds, AddressLiteral src) { - if (reachable(src)) { - vsubsd(dst, nds, as_Address(src)); - } else { - lea(rscratch1, src); - vsubsd(dst, nds, Address(rscratch1, 0)); - } -} - -void MacroAssembler::vsubss(XMMRegister dst, XMMRegister nds, AddressLiteral src) { - if (reachable(src)) { - vsubss(dst, nds, as_Address(src)); - } else { - lea(rscratch1, src); - vsubss(dst, nds, Address(rscratch1, 0)); - } -} - -void MacroAssembler::vxorpd(XMMRegister dst, XMMRegister nds, AddressLiteral src, bool vector256) { - if (reachable(src)) { - vxorpd(dst, nds, as_Address(src), vector256); - } else { - lea(rscratch1, src); - vxorpd(dst, nds, Address(rscratch1, 0), vector256); - } -} - -void MacroAssembler::vxorps(XMMRegister dst, XMMRegister nds, AddressLiteral src, bool vector256) { - if (reachable(src)) { - vxorps(dst, nds, as_Address(src), vector256); - } else { - lea(rscratch1, src); - vxorps(dst, nds, Address(rscratch1, 0), vector256); - } -} - - -////////////////////////////////////////////////////////////////////////////////// -#ifndef SERIALGC - -void MacroAssembler::g1_write_barrier_pre(Register obj, - Register pre_val, - Register thread, - Register tmp, - bool tosca_live, - bool expand_call) { - - // If expand_call is true then we expand the call_VM_leaf macro - // directly to skip generating the check by - // InterpreterMacroAssembler::call_VM_leaf_base that checks _last_sp. - -#ifdef _LP64 - assert(thread == r15_thread, "must be"); -#endif // _LP64 - - Label done; - Label runtime; - - assert(pre_val != noreg, "check this code"); - - if (obj != noreg) { - assert_different_registers(obj, pre_val, tmp); - assert(pre_val != rax, "check this code"); - } - - Address in_progress(thread, in_bytes(JavaThread::satb_mark_queue_offset() + - PtrQueue::byte_offset_of_active())); - Address index(thread, in_bytes(JavaThread::satb_mark_queue_offset() + - PtrQueue::byte_offset_of_index())); - Address buffer(thread, in_bytes(JavaThread::satb_mark_queue_offset() + - PtrQueue::byte_offset_of_buf())); - - - // Is marking active? - if (in_bytes(PtrQueue::byte_width_of_active()) == 4) { - cmpl(in_progress, 0); - } else { - assert(in_bytes(PtrQueue::byte_width_of_active()) == 1, "Assumption"); - cmpb(in_progress, 0); - } - jcc(Assembler::equal, done); - - // Do we need to load the previous value? - if (obj != noreg) { - load_heap_oop(pre_val, Address(obj, 0)); - } - - // Is the previous value null? - cmpptr(pre_val, (int32_t) NULL_WORD); - jcc(Assembler::equal, done); - - // Can we store original value in the thread's buffer? - // Is index == 0? - // (The index field is typed as size_t.) - - movptr(tmp, index); // tmp := *index_adr - cmpptr(tmp, 0); // tmp == 0? - jcc(Assembler::equal, runtime); // If yes, goto runtime - - subptr(tmp, wordSize); // tmp := tmp - wordSize - movptr(index, tmp); // *index_adr := tmp - addptr(tmp, buffer); // tmp := tmp + *buffer_adr - - // Record the previous value - movptr(Address(tmp, 0), pre_val); - jmp(done); - - bind(runtime); - // save the live input values - if(tosca_live) push(rax); - - if (obj != noreg && obj != rax) - push(obj); - - if (pre_val != rax) - push(pre_val); - - // Calling the runtime using the regular call_VM_leaf mechanism generates - // code (generated by InterpreterMacroAssember::call_VM_leaf_base) - // that checks that the *(ebp+frame::interpreter_frame_last_sp) == NULL. - // - // If we care generating the pre-barrier without a frame (e.g. in the - // intrinsified Reference.get() routine) then ebp might be pointing to - // the caller frame and so this check will most likely fail at runtime. - // - // Expanding the call directly bypasses the generation of the check. - // So when we do not have have a full interpreter frame on the stack - // expand_call should be passed true. - - NOT_LP64( push(thread); ) - - if (expand_call) { - LP64_ONLY( assert(pre_val != c_rarg1, "smashed arg"); ) - pass_arg1(this, thread); - pass_arg0(this, pre_val); - MacroAssembler::call_VM_leaf_base(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), 2); - } else { - call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), pre_val, thread); - } - - NOT_LP64( pop(thread); ) - - // save the live input values - if (pre_val != rax) - pop(pre_val); - - if (obj != noreg && obj != rax) - pop(obj); - - if(tosca_live) pop(rax); - - bind(done); -} - -void MacroAssembler::g1_write_barrier_post(Register store_addr, - Register new_val, - Register thread, - Register tmp, - Register tmp2) { -#ifdef _LP64 - assert(thread == r15_thread, "must be"); -#endif // _LP64 - - Address queue_index(thread, in_bytes(JavaThread::dirty_card_queue_offset() + - PtrQueue::byte_offset_of_index())); - Address buffer(thread, in_bytes(JavaThread::dirty_card_queue_offset() + - PtrQueue::byte_offset_of_buf())); - - BarrierSet* bs = Universe::heap()->barrier_set(); - CardTableModRefBS* ct = (CardTableModRefBS*)bs; - Label done; - Label runtime; - - // Does store cross heap regions? - - movptr(tmp, store_addr); - xorptr(tmp, new_val); - shrptr(tmp, HeapRegion::LogOfHRGrainBytes); - jcc(Assembler::equal, done); - - // crosses regions, storing NULL? - - cmpptr(new_val, (int32_t) NULL_WORD); - jcc(Assembler::equal, done); - - // storing region crossing non-NULL, is card already dirty? - - ExternalAddress cardtable((address) ct->byte_map_base); - assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code"); -#ifdef _LP64 - const Register card_addr = tmp; - - movq(card_addr, store_addr); - shrq(card_addr, CardTableModRefBS::card_shift); - - lea(tmp2, cardtable); - - // get the address of the card - addq(card_addr, tmp2); -#else - const Register card_index = tmp; - - movl(card_index, store_addr); - shrl(card_index, CardTableModRefBS::card_shift); - - Address index(noreg, card_index, Address::times_1); - const Register card_addr = tmp; - lea(card_addr, as_Address(ArrayAddress(cardtable, index))); -#endif - cmpb(Address(card_addr, 0), 0); - jcc(Assembler::equal, done); - - // storing a region crossing, non-NULL oop, card is clean. - // dirty card and log. - - movb(Address(card_addr, 0), 0); - - cmpl(queue_index, 0); - jcc(Assembler::equal, runtime); - subl(queue_index, wordSize); - movptr(tmp2, buffer); -#ifdef _LP64 - movslq(rscratch1, queue_index); - addq(tmp2, rscratch1); - movq(Address(tmp2, 0), card_addr); -#else - addl(tmp2, queue_index); - movl(Address(tmp2, 0), card_index); -#endif - jmp(done); - - bind(runtime); - // save the live input values - push(store_addr); - push(new_val); -#ifdef _LP64 - call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), card_addr, r15_thread); -#else - push(thread); - call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), card_addr, thread); - pop(thread); -#endif - pop(new_val); - pop(store_addr); - - bind(done); -} - -#endif // SERIALGC -////////////////////////////////////////////////////////////////////////////////// - - -void MacroAssembler::store_check(Register obj) { - // Does a store check for the oop in register obj. The content of - // register obj is destroyed afterwards. - store_check_part_1(obj); - store_check_part_2(obj); -} - -void MacroAssembler::store_check(Register obj, Address dst) { - store_check(obj); -} - - -// split the store check operation so that other instructions can be scheduled inbetween -void MacroAssembler::store_check_part_1(Register obj) { - BarrierSet* bs = Universe::heap()->barrier_set(); - assert(bs->kind() == BarrierSet::CardTableModRef, "Wrong barrier set kind"); - shrptr(obj, CardTableModRefBS::card_shift); -} - -void MacroAssembler::store_check_part_2(Register obj) { - BarrierSet* bs = Universe::heap()->barrier_set(); - assert(bs->kind() == BarrierSet::CardTableModRef, "Wrong barrier set kind"); - CardTableModRefBS* ct = (CardTableModRefBS*)bs; - assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code"); - - // The calculation for byte_map_base is as follows: - // byte_map_base = _byte_map - (uintptr_t(low_bound) >> card_shift); - // So this essentially converts an address to a displacement and - // it will never need to be relocated. On 64bit however the value may be too - // large for a 32bit displacement - - intptr_t disp = (intptr_t) ct->byte_map_base; - if (is_simm32(disp)) { - Address cardtable(noreg, obj, Address::times_1, disp); - movb(cardtable, 0); - } else { - // By doing it as an ExternalAddress disp could be converted to a rip-relative - // displacement and done in a single instruction given favorable mapping and - // a smarter version of as_Address. Worst case it is two instructions which - // is no worse off then loading disp into a register and doing as a simple - // Address() as above. - // We can't do as ExternalAddress as the only style since if disp == 0 we'll - // assert since NULL isn't acceptable in a reloci (see 6644928). In any case - // in some cases we'll get a single instruction version. - - ExternalAddress cardtable((address)disp); - Address index(noreg, obj, Address::times_1); - movb(as_Address(ArrayAddress(cardtable, index)), 0); - } -} - -void MacroAssembler::subptr(Register dst, int32_t imm32) { - LP64_ONLY(subq(dst, imm32)) NOT_LP64(subl(dst, imm32)); -} - -// Force generation of a 4 byte immediate value even if it fits into 8bit -void MacroAssembler::subptr_imm32(Register dst, int32_t imm32) { - LP64_ONLY(subq_imm32(dst, imm32)) NOT_LP64(subl_imm32(dst, imm32)); -} - -void MacroAssembler::subptr(Register dst, Register src) { - LP64_ONLY(subq(dst, src)) NOT_LP64(subl(dst, src)); -} - -// C++ bool manipulation -void MacroAssembler::testbool(Register dst) { - if(sizeof(bool) == 1) - testb(dst, 0xff); - else if(sizeof(bool) == 2) { - // testw implementation needed for two byte bools - ShouldNotReachHere(); - } else if(sizeof(bool) == 4) - testl(dst, dst); - else - // unsupported - ShouldNotReachHere(); -} - -void MacroAssembler::testptr(Register dst, Register src) { - LP64_ONLY(testq(dst, src)) NOT_LP64(testl(dst, src)); -} - -// Defines obj, preserves var_size_in_bytes, okay for t2 == var_size_in_bytes. -void MacroAssembler::tlab_allocate(Register obj, - Register var_size_in_bytes, - int con_size_in_bytes, - Register t1, - Register t2, - Label& slow_case) { - assert_different_registers(obj, t1, t2); - assert_different_registers(obj, var_size_in_bytes, t1); - Register end = t2; - Register thread = NOT_LP64(t1) LP64_ONLY(r15_thread); - - verify_tlab(); - - NOT_LP64(get_thread(thread)); - - movptr(obj, Address(thread, JavaThread::tlab_top_offset())); - if (var_size_in_bytes == noreg) { - lea(end, Address(obj, con_size_in_bytes)); - } else { - lea(end, Address(obj, var_size_in_bytes, Address::times_1)); - } - cmpptr(end, Address(thread, JavaThread::tlab_end_offset())); - jcc(Assembler::above, slow_case); - - // update the tlab top pointer - movptr(Address(thread, JavaThread::tlab_top_offset()), end); - - // recover var_size_in_bytes if necessary - if (var_size_in_bytes == end) { - subptr(var_size_in_bytes, obj); - } - verify_tlab(); -} - -// Preserves rbx, and rdx. -Register MacroAssembler::tlab_refill(Label& retry, - Label& try_eden, - Label& slow_case) { - Register top = rax; - Register t1 = rcx; - Register t2 = rsi; - Register thread_reg = NOT_LP64(rdi) LP64_ONLY(r15_thread); - assert_different_registers(top, thread_reg, t1, t2, /* preserve: */ rbx, rdx); - Label do_refill, discard_tlab; - - if (CMSIncrementalMode || !Universe::heap()->supports_inline_contig_alloc()) { - // No allocation in the shared eden. - jmp(slow_case); - } - - NOT_LP64(get_thread(thread_reg)); - - movptr(top, Address(thread_reg, in_bytes(JavaThread::tlab_top_offset()))); - movptr(t1, Address(thread_reg, in_bytes(JavaThread::tlab_end_offset()))); - - // calculate amount of free space - subptr(t1, top); - shrptr(t1, LogHeapWordSize); - - // Retain tlab and allocate object in shared space if - // the amount free in the tlab is too large to discard. - cmpptr(t1, Address(thread_reg, in_bytes(JavaThread::tlab_refill_waste_limit_offset()))); - jcc(Assembler::lessEqual, discard_tlab); - - // Retain - // %%% yuck as movptr... - movptr(t2, (int32_t) ThreadLocalAllocBuffer::refill_waste_limit_increment()); - addptr(Address(thread_reg, in_bytes(JavaThread::tlab_refill_waste_limit_offset())), t2); - if (TLABStats) { - // increment number of slow_allocations - addl(Address(thread_reg, in_bytes(JavaThread::tlab_slow_allocations_offset())), 1); - } - jmp(try_eden); - - bind(discard_tlab); - if (TLABStats) { - // increment number of refills - addl(Address(thread_reg, in_bytes(JavaThread::tlab_number_of_refills_offset())), 1); - // accumulate wastage -- t1 is amount free in tlab - addl(Address(thread_reg, in_bytes(JavaThread::tlab_fast_refill_waste_offset())), t1); - } - - // if tlab is currently allocated (top or end != null) then - // fill [top, end + alignment_reserve) with array object - testptr(top, top); - jcc(Assembler::zero, do_refill); - - // set up the mark word - movptr(Address(top, oopDesc::mark_offset_in_bytes()), (intptr_t)markOopDesc::prototype()->copy_set_hash(0x2)); - // set the length to the remaining space - subptr(t1, typeArrayOopDesc::header_size(T_INT)); - addptr(t1, (int32_t)ThreadLocalAllocBuffer::alignment_reserve()); - shlptr(t1, log2_intptr(HeapWordSize/sizeof(jint))); - movl(Address(top, arrayOopDesc::length_offset_in_bytes()), t1); - // set klass to intArrayKlass - // dubious reloc why not an oop reloc? - movptr(t1, ExternalAddress((address)Universe::intArrayKlassObj_addr())); - // store klass last. concurrent gcs assumes klass length is valid if - // klass field is not null. - store_klass(top, t1); - - movptr(t1, top); - subptr(t1, Address(thread_reg, in_bytes(JavaThread::tlab_start_offset()))); - incr_allocated_bytes(thread_reg, t1, 0); - - // refill the tlab with an eden allocation - bind(do_refill); - movptr(t1, Address(thread_reg, in_bytes(JavaThread::tlab_size_offset()))); - shlptr(t1, LogHeapWordSize); - // allocate new tlab, address returned in top - eden_allocate(top, t1, 0, t2, slow_case); - - // Check that t1 was preserved in eden_allocate. -#ifdef ASSERT - if (UseTLAB) { - Label ok; - Register tsize = rsi; - assert_different_registers(tsize, thread_reg, t1); - push(tsize); - movptr(tsize, Address(thread_reg, in_bytes(JavaThread::tlab_size_offset()))); - shlptr(tsize, LogHeapWordSize); - cmpptr(t1, tsize); - jcc(Assembler::equal, ok); - STOP("assert(t1 != tlab size)"); - should_not_reach_here(); - - bind(ok); - pop(tsize); - } -#endif - movptr(Address(thread_reg, in_bytes(JavaThread::tlab_start_offset())), top); - movptr(Address(thread_reg, in_bytes(JavaThread::tlab_top_offset())), top); - addptr(top, t1); - subptr(top, (int32_t)ThreadLocalAllocBuffer::alignment_reserve_in_bytes()); - movptr(Address(thread_reg, in_bytes(JavaThread::tlab_end_offset())), top); - verify_tlab(); - jmp(retry); - - return thread_reg; // for use by caller -} - -void MacroAssembler::incr_allocated_bytes(Register thread, - Register var_size_in_bytes, - int con_size_in_bytes, - Register t1) { - if (!thread->is_valid()) { -#ifdef _LP64 - thread = r15_thread; -#else - assert(t1->is_valid(), "need temp reg"); - thread = t1; - get_thread(thread); -#endif - } - -#ifdef _LP64 - if (var_size_in_bytes->is_valid()) { - addq(Address(thread, in_bytes(JavaThread::allocated_bytes_offset())), var_size_in_bytes); - } else { - addq(Address(thread, in_bytes(JavaThread::allocated_bytes_offset())), con_size_in_bytes); - } -#else - if (var_size_in_bytes->is_valid()) { - addl(Address(thread, in_bytes(JavaThread::allocated_bytes_offset())), var_size_in_bytes); - } else { - addl(Address(thread, in_bytes(JavaThread::allocated_bytes_offset())), con_size_in_bytes); - } - adcl(Address(thread, in_bytes(JavaThread::allocated_bytes_offset())+4), 0); -#endif -} - -void MacroAssembler::fp_runtime_fallback(address runtime_entry, int nb_args, int num_fpu_regs_in_use) { - pusha(); - - // if we are coming from c1, xmm registers may be live - int off = 0; - if (UseSSE == 1) { - subptr(rsp, sizeof(jdouble)*8); - movflt(Address(rsp,off++*sizeof(jdouble)),xmm0); - movflt(Address(rsp,off++*sizeof(jdouble)),xmm1); - movflt(Address(rsp,off++*sizeof(jdouble)),xmm2); - movflt(Address(rsp,off++*sizeof(jdouble)),xmm3); - movflt(Address(rsp,off++*sizeof(jdouble)),xmm4); - movflt(Address(rsp,off++*sizeof(jdouble)),xmm5); - movflt(Address(rsp,off++*sizeof(jdouble)),xmm6); - movflt(Address(rsp,off++*sizeof(jdouble)),xmm7); - } else if (UseSSE >= 2) { -#ifdef COMPILER2 - if (MaxVectorSize > 16) { - assert(UseAVX > 0, "256bit vectors are supported only with AVX"); - // Save upper half of YMM registes - subptr(rsp, 16 * LP64_ONLY(16) NOT_LP64(8)); - vextractf128h(Address(rsp, 0),xmm0); - vextractf128h(Address(rsp, 16),xmm1); - vextractf128h(Address(rsp, 32),xmm2); - vextractf128h(Address(rsp, 48),xmm3); - vextractf128h(Address(rsp, 64),xmm4); - vextractf128h(Address(rsp, 80),xmm5); - vextractf128h(Address(rsp, 96),xmm6); - vextractf128h(Address(rsp,112),xmm7); -#ifdef _LP64 - vextractf128h(Address(rsp,128),xmm8); - vextractf128h(Address(rsp,144),xmm9); - vextractf128h(Address(rsp,160),xmm10); - vextractf128h(Address(rsp,176),xmm11); - vextractf128h(Address(rsp,192),xmm12); - vextractf128h(Address(rsp,208),xmm13); - vextractf128h(Address(rsp,224),xmm14); - vextractf128h(Address(rsp,240),xmm15); -#endif - } -#endif - // Save whole 128bit (16 bytes) XMM regiters - subptr(rsp, 16 * LP64_ONLY(16) NOT_LP64(8)); - movdqu(Address(rsp,off++*16),xmm0); - movdqu(Address(rsp,off++*16),xmm1); - movdqu(Address(rsp,off++*16),xmm2); - movdqu(Address(rsp,off++*16),xmm3); - movdqu(Address(rsp,off++*16),xmm4); - movdqu(Address(rsp,off++*16),xmm5); - movdqu(Address(rsp,off++*16),xmm6); - movdqu(Address(rsp,off++*16),xmm7); -#ifdef _LP64 - movdqu(Address(rsp,off++*16),xmm8); - movdqu(Address(rsp,off++*16),xmm9); - movdqu(Address(rsp,off++*16),xmm10); - movdqu(Address(rsp,off++*16),xmm11); - movdqu(Address(rsp,off++*16),xmm12); - movdqu(Address(rsp,off++*16),xmm13); - movdqu(Address(rsp,off++*16),xmm14); - movdqu(Address(rsp,off++*16),xmm15); -#endif - } - - // Preserve registers across runtime call - int incoming_argument_and_return_value_offset = -1; - if (num_fpu_regs_in_use > 1) { - // Must preserve all other FPU regs (could alternatively convert - // SharedRuntime::dsin, dcos etc. into assembly routines known not to trash - // FPU state, but can not trust C compiler) - NEEDS_CLEANUP; - // NOTE that in this case we also push the incoming argument(s) to - // the stack and restore it later; we also use this stack slot to - // hold the return value from dsin, dcos etc. - for (int i = 0; i < num_fpu_regs_in_use; i++) { - subptr(rsp, sizeof(jdouble)); - fstp_d(Address(rsp, 0)); - } - incoming_argument_and_return_value_offset = sizeof(jdouble)*(num_fpu_regs_in_use-1); - for (int i = nb_args-1; i >= 0; i--) { - fld_d(Address(rsp, incoming_argument_and_return_value_offset-i*sizeof(jdouble))); - } - } - - subptr(rsp, nb_args*sizeof(jdouble)); - for (int i = 0; i < nb_args; i++) { - fstp_d(Address(rsp, i*sizeof(jdouble))); - } - -#ifdef _LP64 - if (nb_args > 0) { - movdbl(xmm0, Address(rsp, 0)); - } - if (nb_args > 1) { - movdbl(xmm1, Address(rsp, sizeof(jdouble))); - } - assert(nb_args <= 2, "unsupported number of args"); -#endif // _LP64 - - // NOTE: we must not use call_VM_leaf here because that requires a - // complete interpreter frame in debug mode -- same bug as 4387334 - // MacroAssembler::call_VM_leaf_base is perfectly safe and will - // do proper 64bit abi - - NEEDS_CLEANUP; - // Need to add stack banging before this runtime call if it needs to - // be taken; however, there is no generic stack banging routine at - // the MacroAssembler level - - MacroAssembler::call_VM_leaf_base(runtime_entry, 0); - -#ifdef _LP64 - movsd(Address(rsp, 0), xmm0); - fld_d(Address(rsp, 0)); -#endif // _LP64 - addptr(rsp, sizeof(jdouble) * nb_args); - if (num_fpu_regs_in_use > 1) { - // Must save return value to stack and then restore entire FPU - // stack except incoming arguments - fstp_d(Address(rsp, incoming_argument_and_return_value_offset)); - for (int i = 0; i < num_fpu_regs_in_use - nb_args; i++) { - fld_d(Address(rsp, 0)); - addptr(rsp, sizeof(jdouble)); - } - fld_d(Address(rsp, (nb_args-1)*sizeof(jdouble))); - addptr(rsp, sizeof(jdouble) * nb_args); - } - - off = 0; - if (UseSSE == 1) { - movflt(xmm0, Address(rsp,off++*sizeof(jdouble))); - movflt(xmm1, Address(rsp,off++*sizeof(jdouble))); - movflt(xmm2, Address(rsp,off++*sizeof(jdouble))); - movflt(xmm3, Address(rsp,off++*sizeof(jdouble))); - movflt(xmm4, Address(rsp,off++*sizeof(jdouble))); - movflt(xmm5, Address(rsp,off++*sizeof(jdouble))); - movflt(xmm6, Address(rsp,off++*sizeof(jdouble))); - movflt(xmm7, Address(rsp,off++*sizeof(jdouble))); - addptr(rsp, sizeof(jdouble)*8); - } else if (UseSSE >= 2) { - // Restore whole 128bit (16 bytes) XMM regiters - movdqu(xmm0, Address(rsp,off++*16)); - movdqu(xmm1, Address(rsp,off++*16)); - movdqu(xmm2, Address(rsp,off++*16)); - movdqu(xmm3, Address(rsp,off++*16)); - movdqu(xmm4, Address(rsp,off++*16)); - movdqu(xmm5, Address(rsp,off++*16)); - movdqu(xmm6, Address(rsp,off++*16)); - movdqu(xmm7, Address(rsp,off++*16)); -#ifdef _LP64 - movdqu(xmm8, Address(rsp,off++*16)); - movdqu(xmm9, Address(rsp,off++*16)); - movdqu(xmm10, Address(rsp,off++*16)); - movdqu(xmm11, Address(rsp,off++*16)); - movdqu(xmm12, Address(rsp,off++*16)); - movdqu(xmm13, Address(rsp,off++*16)); - movdqu(xmm14, Address(rsp,off++*16)); - movdqu(xmm15, Address(rsp,off++*16)); -#endif - addptr(rsp, 16 * LP64_ONLY(16) NOT_LP64(8)); -#ifdef COMPILER2 - if (MaxVectorSize > 16) { - // Restore upper half of YMM registes. - vinsertf128h(xmm0, Address(rsp, 0)); - vinsertf128h(xmm1, Address(rsp, 16)); - vinsertf128h(xmm2, Address(rsp, 32)); - vinsertf128h(xmm3, Address(rsp, 48)); - vinsertf128h(xmm4, Address(rsp, 64)); - vinsertf128h(xmm5, Address(rsp, 80)); - vinsertf128h(xmm6, Address(rsp, 96)); - vinsertf128h(xmm7, Address(rsp,112)); -#ifdef _LP64 - vinsertf128h(xmm8, Address(rsp,128)); - vinsertf128h(xmm9, Address(rsp,144)); - vinsertf128h(xmm10, Address(rsp,160)); - vinsertf128h(xmm11, Address(rsp,176)); - vinsertf128h(xmm12, Address(rsp,192)); - vinsertf128h(xmm13, Address(rsp,208)); - vinsertf128h(xmm14, Address(rsp,224)); - vinsertf128h(xmm15, Address(rsp,240)); -#endif - addptr(rsp, 16 * LP64_ONLY(16) NOT_LP64(8)); - } -#endif - } - popa(); -} - -static const double pi_4 = 0.7853981633974483; - -void MacroAssembler::trigfunc(char trig, int num_fpu_regs_in_use) { - // A hand-coded argument reduction for values in fabs(pi/4, pi/2) - // was attempted in this code; unfortunately it appears that the - // switch to 80-bit precision and back causes this to be - // unprofitable compared with simply performing a runtime call if - // the argument is out of the (-pi/4, pi/4) range. - - Register tmp = noreg; - if (!VM_Version::supports_cmov()) { - // fcmp needs a temporary so preserve rbx, - tmp = rbx; - push(tmp); - } - - Label slow_case, done; - - ExternalAddress pi4_adr = (address)&pi_4; - if (reachable(pi4_adr)) { - // x ?<= pi/4 - fld_d(pi4_adr); - fld_s(1); // Stack: X PI/4 X - fabs(); // Stack: |X| PI/4 X - fcmp(tmp); - jcc(Assembler::above, slow_case); - - // fastest case: -pi/4 <= x <= pi/4 - switch(trig) { - case 's': - fsin(); - break; - case 'c': - fcos(); - break; - case 't': - ftan(); - break; - default: - assert(false, "bad intrinsic"); - break; - } - jmp(done); - } - - // slow case: runtime call - bind(slow_case); - - switch(trig) { - case 's': - { - fp_runtime_fallback(CAST_FROM_FN_PTR(address, SharedRuntime::dsin), 1, num_fpu_regs_in_use); - } - break; - case 'c': - { - fp_runtime_fallback(CAST_FROM_FN_PTR(address, SharedRuntime::dcos), 1, num_fpu_regs_in_use); - } - break; - case 't': - { - fp_runtime_fallback(CAST_FROM_FN_PTR(address, SharedRuntime::dtan), 1, num_fpu_regs_in_use); - } - break; - default: - assert(false, "bad intrinsic"); - break; - } - - // Come here with result in F-TOS - bind(done); - - if (tmp != noreg) { - pop(tmp); - } -} - - -// Look up the method for a megamorphic invokeinterface call. -// The target method is determined by . -// The receiver klass is in recv_klass. -// On success, the result will be in method_result, and execution falls through. -// On failure, execution transfers to the given label. -void MacroAssembler::lookup_interface_method(Register recv_klass, - Register intf_klass, - RegisterOrConstant itable_index, - Register method_result, - Register scan_temp, - Label& L_no_such_interface) { - assert_different_registers(recv_klass, intf_klass, method_result, scan_temp); - assert(itable_index.is_constant() || itable_index.as_register() == method_result, - "caller must use same register for non-constant itable index as for method"); - - // Compute start of first itableOffsetEntry (which is at the end of the vtable) - int vtable_base = InstanceKlass::vtable_start_offset() * wordSize; - int itentry_off = itableMethodEntry::method_offset_in_bytes(); - int scan_step = itableOffsetEntry::size() * wordSize; - int vte_size = vtableEntry::size() * wordSize; - Address::ScaleFactor times_vte_scale = Address::times_ptr; - assert(vte_size == wordSize, "else adjust times_vte_scale"); - - movl(scan_temp, Address(recv_klass, InstanceKlass::vtable_length_offset() * wordSize)); - - // %%% Could store the aligned, prescaled offset in the klassoop. - lea(scan_temp, Address(recv_klass, scan_temp, times_vte_scale, vtable_base)); - if (HeapWordsPerLong > 1) { - // Round up to align_object_offset boundary - // see code for InstanceKlass::start_of_itable! - round_to(scan_temp, BytesPerLong); - } - - // Adjust recv_klass by scaled itable_index, so we can free itable_index. - assert(itableMethodEntry::size() * wordSize == wordSize, "adjust the scaling in the code below"); - lea(recv_klass, Address(recv_klass, itable_index, Address::times_ptr, itentry_off)); - - // for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) { - // if (scan->interface() == intf) { - // result = (klass + scan->offset() + itable_index); - // } - // } - Label search, found_method; - - for (int peel = 1; peel >= 0; peel--) { - movptr(method_result, Address(scan_temp, itableOffsetEntry::interface_offset_in_bytes())); - cmpptr(intf_klass, method_result); - - if (peel) { - jccb(Assembler::equal, found_method); - } else { - jccb(Assembler::notEqual, search); - // (invert the test to fall through to found_method...) - } - - if (!peel) break; - - bind(search); - - // Check that the previous entry is non-null. A null entry means that - // the receiver class doesn't implement the interface, and wasn't the - // same as when the caller was compiled. - testptr(method_result, method_result); - jcc(Assembler::zero, L_no_such_interface); - addptr(scan_temp, scan_step); - } - - bind(found_method); - - // Got a hit. - movl(scan_temp, Address(scan_temp, itableOffsetEntry::offset_offset_in_bytes())); - movptr(method_result, Address(recv_klass, scan_temp, Address::times_1)); -} - - -// virtual method calling -void MacroAssembler::lookup_virtual_method(Register recv_klass, - RegisterOrConstant vtable_index, - Register method_result) { - const int base = InstanceKlass::vtable_start_offset() * wordSize; - assert(vtableEntry::size() * wordSize == wordSize, "else adjust the scaling in the code below"); - Address vtable_entry_addr(recv_klass, - vtable_index, Address::times_ptr, - base + vtableEntry::method_offset_in_bytes()); - movptr(method_result, vtable_entry_addr); -} - - -void MacroAssembler::check_klass_subtype(Register sub_klass, - Register super_klass, - Register temp_reg, - Label& L_success) { - Label L_failure; - check_klass_subtype_fast_path(sub_klass, super_klass, temp_reg, &L_success, &L_failure, NULL); - check_klass_subtype_slow_path(sub_klass, super_klass, temp_reg, noreg, &L_success, NULL); - bind(L_failure); -} - - -void MacroAssembler::check_klass_subtype_fast_path(Register sub_klass, - Register super_klass, - Register temp_reg, - Label* L_success, - Label* L_failure, - Label* L_slow_path, - RegisterOrConstant super_check_offset) { - assert_different_registers(sub_klass, super_klass, temp_reg); - bool must_load_sco = (super_check_offset.constant_or_zero() == -1); - if (super_check_offset.is_register()) { - assert_different_registers(sub_klass, super_klass, - super_check_offset.as_register()); - } else if (must_load_sco) { - assert(temp_reg != noreg, "supply either a temp or a register offset"); - } - - Label L_fallthrough; - int label_nulls = 0; - if (L_success == NULL) { L_success = &L_fallthrough; label_nulls++; } - if (L_failure == NULL) { L_failure = &L_fallthrough; label_nulls++; } - if (L_slow_path == NULL) { L_slow_path = &L_fallthrough; label_nulls++; } - assert(label_nulls <= 1, "at most one NULL in the batch"); - - int sc_offset = in_bytes(Klass::secondary_super_cache_offset()); - int sco_offset = in_bytes(Klass::super_check_offset_offset()); - Address super_check_offset_addr(super_klass, sco_offset); - - // Hacked jcc, which "knows" that L_fallthrough, at least, is in - // range of a jccb. If this routine grows larger, reconsider at - // least some of these. -#define local_jcc(assembler_cond, label) \ - if (&(label) == &L_fallthrough) jccb(assembler_cond, label); \ - else jcc( assembler_cond, label) /*omit semi*/ - - // Hacked jmp, which may only be used just before L_fallthrough. -#define final_jmp(label) \ - if (&(label) == &L_fallthrough) { /*do nothing*/ } \ - else jmp(label) /*omit semi*/ - - // If the pointers are equal, we are done (e.g., String[] elements). - // This self-check enables sharing of secondary supertype arrays among - // non-primary types such as array-of-interface. Otherwise, each such - // type would need its own customized SSA. - // We move this check to the front of the fast path because many - // type checks are in fact trivially successful in this manner, - // so we get a nicely predicted branch right at the start of the check. - cmpptr(sub_klass, super_klass); - local_jcc(Assembler::equal, *L_success); - - // Check the supertype display: - if (must_load_sco) { - // Positive movl does right thing on LP64. - movl(temp_reg, super_check_offset_addr); - super_check_offset = RegisterOrConstant(temp_reg); - } - Address super_check_addr(sub_klass, super_check_offset, Address::times_1, 0); - cmpptr(super_klass, super_check_addr); // load displayed supertype - - // This check has worked decisively for primary supers. - // Secondary supers are sought in the super_cache ('super_cache_addr'). - // (Secondary supers are interfaces and very deeply nested subtypes.) - // This works in the same check above because of a tricky aliasing - // between the super_cache and the primary super display elements. - // (The 'super_check_addr' can address either, as the case requires.) - // Note that the cache is updated below if it does not help us find - // what we need immediately. - // So if it was a primary super, we can just fail immediately. - // Otherwise, it's the slow path for us (no success at this point). - - if (super_check_offset.is_register()) { - local_jcc(Assembler::equal, *L_success); - cmpl(super_check_offset.as_register(), sc_offset); - if (L_failure == &L_fallthrough) { - local_jcc(Assembler::equal, *L_slow_path); - } else { - local_jcc(Assembler::notEqual, *L_failure); - final_jmp(*L_slow_path); - } - } else if (super_check_offset.as_constant() == sc_offset) { - // Need a slow path; fast failure is impossible. - if (L_slow_path == &L_fallthrough) { - local_jcc(Assembler::equal, *L_success); - } else { - local_jcc(Assembler::notEqual, *L_slow_path); - final_jmp(*L_success); - } - } else { - // No slow path; it's a fast decision. - if (L_failure == &L_fallthrough) { - local_jcc(Assembler::equal, *L_success); - } else { - local_jcc(Assembler::notEqual, *L_failure); - final_jmp(*L_success); - } - } - - bind(L_fallthrough); - -#undef local_jcc -#undef final_jmp -} - - -void MacroAssembler::check_klass_subtype_slow_path(Register sub_klass, - Register super_klass, - Register temp_reg, - Register temp2_reg, - Label* L_success, - Label* L_failure, - bool set_cond_codes) { - assert_different_registers(sub_klass, super_klass, temp_reg); - if (temp2_reg != noreg) - assert_different_registers(sub_klass, super_klass, temp_reg, temp2_reg); -#define IS_A_TEMP(reg) ((reg) == temp_reg || (reg) == temp2_reg) - - Label L_fallthrough; - int label_nulls = 0; - if (L_success == NULL) { L_success = &L_fallthrough; label_nulls++; } - if (L_failure == NULL) { L_failure = &L_fallthrough; label_nulls++; } - assert(label_nulls <= 1, "at most one NULL in the batch"); - - // a couple of useful fields in sub_klass: - int ss_offset = in_bytes(Klass::secondary_supers_offset()); - int sc_offset = in_bytes(Klass::secondary_super_cache_offset()); - Address secondary_supers_addr(sub_klass, ss_offset); - Address super_cache_addr( sub_klass, sc_offset); - - // Do a linear scan of the secondary super-klass chain. - // This code is rarely used, so simplicity is a virtue here. - // The repne_scan instruction uses fixed registers, which we must spill. - // Don't worry too much about pre-existing connections with the input regs. - - assert(sub_klass != rax, "killed reg"); // killed by mov(rax, super) - assert(sub_klass != rcx, "killed reg"); // killed by lea(rcx, &pst_counter) - - // Get super_klass value into rax (even if it was in rdi or rcx). - bool pushed_rax = false, pushed_rcx = false, pushed_rdi = false; - if (super_klass != rax || UseCompressedOops) { - if (!IS_A_TEMP(rax)) { push(rax); pushed_rax = true; } - mov(rax, super_klass); - } - if (!IS_A_TEMP(rcx)) { push(rcx); pushed_rcx = true; } - if (!IS_A_TEMP(rdi)) { push(rdi); pushed_rdi = true; } - -#ifndef PRODUCT - int* pst_counter = &SharedRuntime::_partial_subtype_ctr; - ExternalAddress pst_counter_addr((address) pst_counter); - NOT_LP64( incrementl(pst_counter_addr) ); - LP64_ONLY( lea(rcx, pst_counter_addr) ); - LP64_ONLY( incrementl(Address(rcx, 0)) ); -#endif //PRODUCT - - // We will consult the secondary-super array. - movptr(rdi, secondary_supers_addr); - // Load the array length. (Positive movl does right thing on LP64.) - movl(rcx, Address(rdi, Array::length_offset_in_bytes())); - // Skip to start of data. - addptr(rdi, Array::base_offset_in_bytes()); - - // Scan RCX words at [RDI] for an occurrence of RAX. - // Set NZ/Z based on last compare. - // Z flag value will not be set by 'repne' if RCX == 0 since 'repne' does - // not change flags (only scas instruction which is repeated sets flags). - // Set Z = 0 (not equal) before 'repne' to indicate that class was not found. - - testptr(rax,rax); // Set Z = 0 - repne_scan(); - - // Unspill the temp. registers: - if (pushed_rdi) pop(rdi); - if (pushed_rcx) pop(rcx); - if (pushed_rax) pop(rax); - - if (set_cond_codes) { - // Special hack for the AD files: rdi is guaranteed non-zero. - assert(!pushed_rdi, "rdi must be left non-NULL"); - // Also, the condition codes are properly set Z/NZ on succeed/failure. - } - - if (L_failure == &L_fallthrough) - jccb(Assembler::notEqual, *L_failure); - else jcc(Assembler::notEqual, *L_failure); - - // Success. Cache the super we found and proceed in triumph. - movptr(super_cache_addr, super_klass); - - if (L_success != &L_fallthrough) { - jmp(*L_success); - } - -#undef IS_A_TEMP - - bind(L_fallthrough); -} - - -void MacroAssembler::cmov32(Condition cc, Register dst, Address src) { - if (VM_Version::supports_cmov()) { - cmovl(cc, dst, src); - } else { - Label L; - jccb(negate_condition(cc), L); - movl(dst, src); - bind(L); - } -} - -void MacroAssembler::cmov32(Condition cc, Register dst, Register src) { - if (VM_Version::supports_cmov()) { - cmovl(cc, dst, src); - } else { - Label L; - jccb(negate_condition(cc), L); - movl(dst, src); - bind(L); - } -} - -void MacroAssembler::verify_oop(Register reg, const char* s) { - if (!VerifyOops) return; - - // Pass register number to verify_oop_subroutine - char* b = new char[strlen(s) + 50]; - sprintf(b, "verify_oop: %s: %s", reg->name(), s); - BLOCK_COMMENT("verify_oop {"); -#ifdef _LP64 - push(rscratch1); // save r10, trashed by movptr() -#endif - push(rax); // save rax, - push(reg); // pass register argument - ExternalAddress buffer((address) b); - // avoid using pushptr, as it modifies scratch registers - // and our contract is not to modify anything - movptr(rax, buffer.addr()); - push(rax); - // call indirectly to solve generation ordering problem - movptr(rax, ExternalAddress(StubRoutines::verify_oop_subroutine_entry_address())); - call(rax); - // Caller pops the arguments (oop, message) and restores rax, r10 - BLOCK_COMMENT("} verify_oop"); -} - - -RegisterOrConstant MacroAssembler::delayed_value_impl(intptr_t* delayed_value_addr, - Register tmp, - int offset) { - intptr_t value = *delayed_value_addr; - if (value != 0) - return RegisterOrConstant(value + offset); - - // load indirectly to solve generation ordering problem - movptr(tmp, ExternalAddress((address) delayed_value_addr)); - -#ifdef ASSERT - { Label L; - testptr(tmp, tmp); - if (WizardMode) { - jcc(Assembler::notZero, L); - char* buf = new char[40]; - sprintf(buf, "DelayedValue="INTPTR_FORMAT, delayed_value_addr[1]); - STOP(buf); - } else { - jccb(Assembler::notZero, L); - hlt(); - } - bind(L); - } -#endif - - if (offset != 0) - addptr(tmp, offset); - - return RegisterOrConstant(tmp); -} - - -Address MacroAssembler::argument_address(RegisterOrConstant arg_slot, - int extra_slot_offset) { - // cf. TemplateTable::prepare_invoke(), if (load_receiver). - int stackElementSize = Interpreter::stackElementSize; - int offset = Interpreter::expr_offset_in_bytes(extra_slot_offset+0); -#ifdef ASSERT - int offset1 = Interpreter::expr_offset_in_bytes(extra_slot_offset+1); - assert(offset1 - offset == stackElementSize, "correct arithmetic"); -#endif - Register scale_reg = noreg; - Address::ScaleFactor scale_factor = Address::no_scale; - if (arg_slot.is_constant()) { - offset += arg_slot.as_constant() * stackElementSize; - } else { - scale_reg = arg_slot.as_register(); - scale_factor = Address::times(stackElementSize); - } - offset += wordSize; // return PC is on stack - return Address(rsp, scale_reg, scale_factor, offset); -} - - -void MacroAssembler::verify_oop_addr(Address addr, const char* s) { - if (!VerifyOops) return; - - // Address adjust(addr.base(), addr.index(), addr.scale(), addr.disp() + BytesPerWord); - // Pass register number to verify_oop_subroutine - char* b = new char[strlen(s) + 50]; - sprintf(b, "verify_oop_addr: %s", s); - -#ifdef _LP64 - push(rscratch1); // save r10, trashed by movptr() -#endif - push(rax); // save rax, - // addr may contain rsp so we will have to adjust it based on the push - // we just did (and on 64 bit we do two pushes) - // NOTE: 64bit seemed to have had a bug in that it did movq(addr, rax); which - // stores rax into addr which is backwards of what was intended. - if (addr.uses(rsp)) { - lea(rax, addr); - pushptr(Address(rax, LP64_ONLY(2 *) BytesPerWord)); - } else { - pushptr(addr); - } - - ExternalAddress buffer((address) b); - // pass msg argument - // avoid using pushptr, as it modifies scratch registers - // and our contract is not to modify anything - movptr(rax, buffer.addr()); - push(rax); - - // call indirectly to solve generation ordering problem - movptr(rax, ExternalAddress(StubRoutines::verify_oop_subroutine_entry_address())); - call(rax); - // Caller pops the arguments (addr, message) and restores rax, r10. -} - -void MacroAssembler::verify_tlab() { -#ifdef ASSERT - if (UseTLAB && VerifyOops) { - Label next, ok; - Register t1 = rsi; - Register thread_reg = NOT_LP64(rbx) LP64_ONLY(r15_thread); - - push(t1); - NOT_LP64(push(thread_reg)); - NOT_LP64(get_thread(thread_reg)); - - movptr(t1, Address(thread_reg, in_bytes(JavaThread::tlab_top_offset()))); - cmpptr(t1, Address(thread_reg, in_bytes(JavaThread::tlab_start_offset()))); - jcc(Assembler::aboveEqual, next); - STOP("assert(top >= start)"); - should_not_reach_here(); - - bind(next); - movptr(t1, Address(thread_reg, in_bytes(JavaThread::tlab_end_offset()))); - cmpptr(t1, Address(thread_reg, in_bytes(JavaThread::tlab_top_offset()))); - jcc(Assembler::aboveEqual, ok); - STOP("assert(top <= end)"); - should_not_reach_here(); - - bind(ok); - NOT_LP64(pop(thread_reg)); - pop(t1); - } -#endif -} - -class ControlWord { - public: - int32_t _value; - - int rounding_control() const { return (_value >> 10) & 3 ; } - int precision_control() const { return (_value >> 8) & 3 ; } - bool precision() const { return ((_value >> 5) & 1) != 0; } - bool underflow() const { return ((_value >> 4) & 1) != 0; } - bool overflow() const { return ((_value >> 3) & 1) != 0; } - bool zero_divide() const { return ((_value >> 2) & 1) != 0; } - bool denormalized() const { return ((_value >> 1) & 1) != 0; } - bool invalid() const { return ((_value >> 0) & 1) != 0; } - - void print() const { - // rounding control - const char* rc; - switch (rounding_control()) { - case 0: rc = "round near"; break; - case 1: rc = "round down"; break; - case 2: rc = "round up "; break; - case 3: rc = "chop "; break; - }; - // precision control - const char* pc; - switch (precision_control()) { - case 0: pc = "24 bits "; break; - case 1: pc = "reserved"; break; - case 2: pc = "53 bits "; break; - case 3: pc = "64 bits "; break; - }; - // flags - char f[9]; - f[0] = ' '; - f[1] = ' '; - f[2] = (precision ()) ? 'P' : 'p'; - f[3] = (underflow ()) ? 'U' : 'u'; - f[4] = (overflow ()) ? 'O' : 'o'; - f[5] = (zero_divide ()) ? 'Z' : 'z'; - f[6] = (denormalized()) ? 'D' : 'd'; - f[7] = (invalid ()) ? 'I' : 'i'; - f[8] = '\x0'; - // output - printf("%04x masks = %s, %s, %s", _value & 0xFFFF, f, rc, pc); - } - -}; - -class StatusWord { - public: - int32_t _value; - - bool busy() const { return ((_value >> 15) & 1) != 0; } - bool C3() const { return ((_value >> 14) & 1) != 0; } - bool C2() const { return ((_value >> 10) & 1) != 0; } - bool C1() const { return ((_value >> 9) & 1) != 0; } - bool C0() const { return ((_value >> 8) & 1) != 0; } - int top() const { return (_value >> 11) & 7 ; } - bool error_status() const { return ((_value >> 7) & 1) != 0; } - bool stack_fault() const { return ((_value >> 6) & 1) != 0; } - bool precision() const { return ((_value >> 5) & 1) != 0; } - bool underflow() const { return ((_value >> 4) & 1) != 0; } - bool overflow() const { return ((_value >> 3) & 1) != 0; } - bool zero_divide() const { return ((_value >> 2) & 1) != 0; } - bool denormalized() const { return ((_value >> 1) & 1) != 0; } - bool invalid() const { return ((_value >> 0) & 1) != 0; } - - void print() const { - // condition codes - char c[5]; - c[0] = (C3()) ? '3' : '-'; - c[1] = (C2()) ? '2' : '-'; - c[2] = (C1()) ? '1' : '-'; - c[3] = (C0()) ? '0' : '-'; - c[4] = '\x0'; - // flags - char f[9]; - f[0] = (error_status()) ? 'E' : '-'; - f[1] = (stack_fault ()) ? 'S' : '-'; - f[2] = (precision ()) ? 'P' : '-'; - f[3] = (underflow ()) ? 'U' : '-'; - f[4] = (overflow ()) ? 'O' : '-'; - f[5] = (zero_divide ()) ? 'Z' : '-'; - f[6] = (denormalized()) ? 'D' : '-'; - f[7] = (invalid ()) ? 'I' : '-'; - f[8] = '\x0'; - // output - printf("%04x flags = %s, cc = %s, top = %d", _value & 0xFFFF, f, c, top()); - } - -}; - -class TagWord { - public: - int32_t _value; - - int tag_at(int i) const { return (_value >> (i*2)) & 3; } - - void print() const { - printf("%04x", _value & 0xFFFF); - } - -}; - -class FPU_Register { - public: - int32_t _m0; - int32_t _m1; - int16_t _ex; - - bool is_indefinite() const { - return _ex == -1 && _m1 == (int32_t)0xC0000000 && _m0 == 0; - } - - void print() const { - char sign = (_ex < 0) ? '-' : '+'; - const char* kind = (_ex == 0x7FFF || _ex == (int16_t)-1) ? "NaN" : " "; - printf("%c%04hx.%08x%08x %s", sign, _ex, _m1, _m0, kind); - }; - -}; - -class FPU_State { - public: - enum { - register_size = 10, - number_of_registers = 8, - register_mask = 7 - }; - - ControlWord _control_word; - StatusWord _status_word; - TagWord _tag_word; - int32_t _error_offset; - int32_t _error_selector; - int32_t _data_offset; - int32_t _data_selector; - int8_t _register[register_size * number_of_registers]; - - int tag_for_st(int i) const { return _tag_word.tag_at((_status_word.top() + i) & register_mask); } - FPU_Register* st(int i) const { return (FPU_Register*)&_register[register_size * i]; } - - const char* tag_as_string(int tag) const { - switch (tag) { - case 0: return "valid"; - case 1: return "zero"; - case 2: return "special"; - case 3: return "empty"; - } - ShouldNotReachHere(); - return NULL; - } - - void print() const { - // print computation registers - { int t = _status_word.top(); - for (int i = 0; i < number_of_registers; i++) { - int j = (i - t) & register_mask; - printf("%c r%d = ST%d = ", (j == 0 ? '*' : ' '), i, j); - st(j)->print(); - printf(" %s\n", tag_as_string(_tag_word.tag_at(i))); - } - } - printf("\n"); - // print control registers - printf("ctrl = "); _control_word.print(); printf("\n"); - printf("stat = "); _status_word .print(); printf("\n"); - printf("tags = "); _tag_word .print(); printf("\n"); - } - -}; - -class Flag_Register { - public: - int32_t _value; - - bool overflow() const { return ((_value >> 11) & 1) != 0; } - bool direction() const { return ((_value >> 10) & 1) != 0; } - bool sign() const { return ((_value >> 7) & 1) != 0; } - bool zero() const { return ((_value >> 6) & 1) != 0; } - bool auxiliary_carry() const { return ((_value >> 4) & 1) != 0; } - bool parity() const { return ((_value >> 2) & 1) != 0; } - bool carry() const { return ((_value >> 0) & 1) != 0; } - - void print() const { - // flags - char f[8]; - f[0] = (overflow ()) ? 'O' : '-'; - f[1] = (direction ()) ? 'D' : '-'; - f[2] = (sign ()) ? 'S' : '-'; - f[3] = (zero ()) ? 'Z' : '-'; - f[4] = (auxiliary_carry()) ? 'A' : '-'; - f[5] = (parity ()) ? 'P' : '-'; - f[6] = (carry ()) ? 'C' : '-'; - f[7] = '\x0'; - // output - printf("%08x flags = %s", _value, f); - } - -}; - -class IU_Register { - public: - int32_t _value; - - void print() const { - printf("%08x %11d", _value, _value); - } - -}; - -class IU_State { - public: - Flag_Register _eflags; - IU_Register _rdi; - IU_Register _rsi; - IU_Register _rbp; - IU_Register _rsp; - IU_Register _rbx; - IU_Register _rdx; - IU_Register _rcx; - IU_Register _rax; - - void print() const { - // computation registers - printf("rax, = "); _rax.print(); printf("\n"); - printf("rbx, = "); _rbx.print(); printf("\n"); - printf("rcx = "); _rcx.print(); printf("\n"); - printf("rdx = "); _rdx.print(); printf("\n"); - printf("rdi = "); _rdi.print(); printf("\n"); - printf("rsi = "); _rsi.print(); printf("\n"); - printf("rbp, = "); _rbp.print(); printf("\n"); - printf("rsp = "); _rsp.print(); printf("\n"); - printf("\n"); - // control registers - printf("flgs = "); _eflags.print(); printf("\n"); - } -}; - - -class CPU_State { - public: - FPU_State _fpu_state; - IU_State _iu_state; - - void print() const { - printf("--------------------------------------------------\n"); - _iu_state .print(); - printf("\n"); - _fpu_state.print(); - printf("--------------------------------------------------\n"); - } - -}; - - -static void _print_CPU_state(CPU_State* state) { - state->print(); -}; - - -void MacroAssembler::print_CPU_state() { - push_CPU_state(); - push(rsp); // pass CPU state - call(RuntimeAddress(CAST_FROM_FN_PTR(address, _print_CPU_state))); - addptr(rsp, wordSize); // discard argument - pop_CPU_state(); -} - - -static bool _verify_FPU(int stack_depth, char* s, CPU_State* state) { - static int counter = 0; - FPU_State* fs = &state->_fpu_state; - counter++; - // For leaf calls, only verify that the top few elements remain empty. - // We only need 1 empty at the top for C2 code. - if( stack_depth < 0 ) { - if( fs->tag_for_st(7) != 3 ) { - printf("FPR7 not empty\n"); - state->print(); - assert(false, "error"); - return false; - } - return true; // All other stack states do not matter - } - - assert((fs->_control_word._value & 0xffff) == StubRoutines::_fpu_cntrl_wrd_std, - "bad FPU control word"); - - // compute stack depth - int i = 0; - while (i < FPU_State::number_of_registers && fs->tag_for_st(i) < 3) i++; - int d = i; - while (i < FPU_State::number_of_registers && fs->tag_for_st(i) == 3) i++; - // verify findings - if (i != FPU_State::number_of_registers) { - // stack not contiguous - printf("%s: stack not contiguous at ST%d\n", s, i); - state->print(); - assert(false, "error"); - return false; - } - // check if computed stack depth corresponds to expected stack depth - if (stack_depth < 0) { - // expected stack depth is -stack_depth or less - if (d > -stack_depth) { - // too many elements on the stack - printf("%s: <= %d stack elements expected but found %d\n", s, -stack_depth, d); - state->print(); - assert(false, "error"); - return false; - } - } else { - // expected stack depth is stack_depth - if (d != stack_depth) { - // wrong stack depth - printf("%s: %d stack elements expected but found %d\n", s, stack_depth, d); - state->print(); - assert(false, "error"); - return false; - } - } - // everything is cool - return true; -} - - -void MacroAssembler::verify_FPU(int stack_depth, const char* s) { - if (!VerifyFPU) return; - push_CPU_state(); - push(rsp); // pass CPU state - ExternalAddress msg((address) s); - // pass message string s - pushptr(msg.addr()); - push(stack_depth); // pass stack depth - call(RuntimeAddress(CAST_FROM_FN_PTR(address, _verify_FPU))); - addptr(rsp, 3 * wordSize); // discard arguments - // check for error - { Label L; - testl(rax, rax); - jcc(Assembler::notZero, L); - int3(); // break if error condition - bind(L); - } - pop_CPU_state(); -} - -void MacroAssembler::load_klass(Register dst, Register src) { -#ifdef _LP64 - if (UseCompressedKlassPointers) { - movl(dst, Address(src, oopDesc::klass_offset_in_bytes())); - decode_klass_not_null(dst); - } else -#endif - movptr(dst, Address(src, oopDesc::klass_offset_in_bytes())); -} - -void MacroAssembler::load_prototype_header(Register dst, Register src) { -#ifdef _LP64 - if (UseCompressedKlassPointers) { - assert (Universe::heap() != NULL, "java heap should be initialized"); - movl(dst, Address(src, oopDesc::klass_offset_in_bytes())); - if (Universe::narrow_klass_shift() != 0) { - assert(LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong"); - assert(LogKlassAlignmentInBytes == Address::times_8, "klass not aligned on 64bits?"); - movq(dst, Address(r12_heapbase, dst, Address::times_8, Klass::prototype_header_offset())); - } else { - movq(dst, Address(dst, Klass::prototype_header_offset())); - } - } else -#endif - { - movptr(dst, Address(src, oopDesc::klass_offset_in_bytes())); - movptr(dst, Address(dst, Klass::prototype_header_offset())); - } -} - -void MacroAssembler::store_klass(Register dst, Register src) { -#ifdef _LP64 - if (UseCompressedKlassPointers) { - encode_klass_not_null(src); - movl(Address(dst, oopDesc::klass_offset_in_bytes()), src); - } else -#endif - movptr(Address(dst, oopDesc::klass_offset_in_bytes()), src); -} - -void MacroAssembler::load_heap_oop(Register dst, Address src) { -#ifdef _LP64 - // FIXME: Must change all places where we try to load the klass. - if (UseCompressedOops) { - movl(dst, src); - decode_heap_oop(dst); - } else -#endif - movptr(dst, src); -} - -// Doesn't do verfication, generates fixed size code -void MacroAssembler::load_heap_oop_not_null(Register dst, Address src) { -#ifdef _LP64 - if (UseCompressedOops) { - movl(dst, src); - decode_heap_oop_not_null(dst); - } else -#endif - movptr(dst, src); -} - -void MacroAssembler::store_heap_oop(Address dst, Register src) { -#ifdef _LP64 - if (UseCompressedOops) { - assert(!dst.uses(src), "not enough registers"); - encode_heap_oop(src); - movl(dst, src); - } else -#endif - movptr(dst, src); -} - -void MacroAssembler::cmp_heap_oop(Register src1, Address src2, Register tmp) { - assert_different_registers(src1, tmp); -#ifdef _LP64 - if (UseCompressedOops) { - bool did_push = false; - if (tmp == noreg) { - tmp = rax; - push(tmp); - did_push = true; - assert(!src2.uses(rsp), "can't push"); - } - load_heap_oop(tmp, src2); - cmpptr(src1, tmp); - if (did_push) pop(tmp); - } else -#endif - cmpptr(src1, src2); -} - -// Used for storing NULLs. -void MacroAssembler::store_heap_oop_null(Address dst) { -#ifdef _LP64 - if (UseCompressedOops) { - movl(dst, (int32_t)NULL_WORD); - } else { - movslq(dst, (int32_t)NULL_WORD); - } -#else - movl(dst, (int32_t)NULL_WORD); -#endif -} - -#ifdef _LP64 -void MacroAssembler::store_klass_gap(Register dst, Register src) { - if (UseCompressedKlassPointers) { - // Store to klass gap in destination - movl(Address(dst, oopDesc::klass_gap_offset_in_bytes()), src); - } -} - -#ifdef ASSERT -void MacroAssembler::verify_heapbase(const char* msg) { - assert (UseCompressedOops || UseCompressedKlassPointers, "should be compressed"); - assert (Universe::heap() != NULL, "java heap should be initialized"); - if (CheckCompressedOops) { - Label ok; - push(rscratch1); // cmpptr trashes rscratch1 - cmpptr(r12_heapbase, ExternalAddress((address)Universe::narrow_ptrs_base_addr())); - jcc(Assembler::equal, ok); - STOP(msg); - bind(ok); - pop(rscratch1); - } -} -#endif - -// Algorithm must match oop.inline.hpp encode_heap_oop. -void MacroAssembler::encode_heap_oop(Register r) { -#ifdef ASSERT - verify_heapbase("MacroAssembler::encode_heap_oop: heap base corrupted?"); -#endif - verify_oop(r, "broken oop in encode_heap_oop"); - if (Universe::narrow_oop_base() == NULL) { - if (Universe::narrow_oop_shift() != 0) { - assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); - shrq(r, LogMinObjAlignmentInBytes); - } - return; - } - testq(r, r); - cmovq(Assembler::equal, r, r12_heapbase); - subq(r, r12_heapbase); - shrq(r, LogMinObjAlignmentInBytes); -} - -void MacroAssembler::encode_heap_oop_not_null(Register r) { -#ifdef ASSERT - verify_heapbase("MacroAssembler::encode_heap_oop_not_null: heap base corrupted?"); - if (CheckCompressedOops) { - Label ok; - testq(r, r); - jcc(Assembler::notEqual, ok); - STOP("null oop passed to encode_heap_oop_not_null"); - bind(ok); - } -#endif - verify_oop(r, "broken oop in encode_heap_oop_not_null"); - if (Universe::narrow_oop_base() != NULL) { - subq(r, r12_heapbase); - } - if (Universe::narrow_oop_shift() != 0) { - assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); - shrq(r, LogMinObjAlignmentInBytes); - } -} - -void MacroAssembler::encode_heap_oop_not_null(Register dst, Register src) { -#ifdef ASSERT - verify_heapbase("MacroAssembler::encode_heap_oop_not_null2: heap base corrupted?"); - if (CheckCompressedOops) { - Label ok; - testq(src, src); - jcc(Assembler::notEqual, ok); - STOP("null oop passed to encode_heap_oop_not_null2"); - bind(ok); - } -#endif - verify_oop(src, "broken oop in encode_heap_oop_not_null2"); - if (dst != src) { - movq(dst, src); - } - if (Universe::narrow_oop_base() != NULL) { - subq(dst, r12_heapbase); - } - if (Universe::narrow_oop_shift() != 0) { - assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); - shrq(dst, LogMinObjAlignmentInBytes); - } -} - -void MacroAssembler::decode_heap_oop(Register r) { -#ifdef ASSERT - verify_heapbase("MacroAssembler::decode_heap_oop: heap base corrupted?"); -#endif - if (Universe::narrow_oop_base() == NULL) { - if (Universe::narrow_oop_shift() != 0) { - assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); - shlq(r, LogMinObjAlignmentInBytes); - } - } else { - Label done; - shlq(r, LogMinObjAlignmentInBytes); - jccb(Assembler::equal, done); - addq(r, r12_heapbase); - bind(done); - } - verify_oop(r, "broken oop in decode_heap_oop"); -} - -void MacroAssembler::decode_heap_oop_not_null(Register r) { - // Note: it will change flags - assert (UseCompressedOops, "should only be used for compressed headers"); - assert (Universe::heap() != NULL, "java heap should be initialized"); - // Cannot assert, unverified entry point counts instructions (see .ad file) - // vtableStubs also counts instructions in pd_code_size_limit. - // Also do not verify_oop as this is called by verify_oop. - if (Universe::narrow_oop_shift() != 0) { - assert(LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); - shlq(r, LogMinObjAlignmentInBytes); - if (Universe::narrow_oop_base() != NULL) { - addq(r, r12_heapbase); - } - } else { - assert (Universe::narrow_oop_base() == NULL, "sanity"); - } -} - -void MacroAssembler::decode_heap_oop_not_null(Register dst, Register src) { - // Note: it will change flags - assert (UseCompressedOops, "should only be used for compressed headers"); - assert (Universe::heap() != NULL, "java heap should be initialized"); - // Cannot assert, unverified entry point counts instructions (see .ad file) - // vtableStubs also counts instructions in pd_code_size_limit. - // Also do not verify_oop as this is called by verify_oop. - if (Universe::narrow_oop_shift() != 0) { - assert(LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); - if (LogMinObjAlignmentInBytes == Address::times_8) { - leaq(dst, Address(r12_heapbase, src, Address::times_8, 0)); - } else { - if (dst != src) { - movq(dst, src); - } - shlq(dst, LogMinObjAlignmentInBytes); - if (Universe::narrow_oop_base() != NULL) { - addq(dst, r12_heapbase); - } - } - } else { - assert (Universe::narrow_oop_base() == NULL, "sanity"); - if (dst != src) { - movq(dst, src); - } - } -} - -void MacroAssembler::encode_klass_not_null(Register r) { - assert(Metaspace::is_initialized(), "metaspace should be initialized"); -#ifdef ASSERT - verify_heapbase("MacroAssembler::encode_klass_not_null: heap base corrupted?"); -#endif - if (Universe::narrow_klass_base() != NULL) { - subq(r, r12_heapbase); - } - if (Universe::narrow_klass_shift() != 0) { - assert (LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong"); - shrq(r, LogKlassAlignmentInBytes); - } -} - -void MacroAssembler::encode_klass_not_null(Register dst, Register src) { - assert(Metaspace::is_initialized(), "metaspace should be initialized"); -#ifdef ASSERT - verify_heapbase("MacroAssembler::encode_klass_not_null2: heap base corrupted?"); -#endif - if (dst != src) { - movq(dst, src); - } - if (Universe::narrow_klass_base() != NULL) { - subq(dst, r12_heapbase); - } - if (Universe::narrow_klass_shift() != 0) { - assert (LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong"); - shrq(dst, LogKlassAlignmentInBytes); - } -} - -void MacroAssembler::decode_klass_not_null(Register r) { - assert(Metaspace::is_initialized(), "metaspace should be initialized"); - // Note: it will change flags - assert (UseCompressedKlassPointers, "should only be used for compressed headers"); - // Cannot assert, unverified entry point counts instructions (see .ad file) - // vtableStubs also counts instructions in pd_code_size_limit. - // Also do not verify_oop as this is called by verify_oop. - if (Universe::narrow_klass_shift() != 0) { - assert(LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong"); - shlq(r, LogKlassAlignmentInBytes); - if (Universe::narrow_klass_base() != NULL) { - addq(r, r12_heapbase); - } - } else { - assert (Universe::narrow_klass_base() == NULL, "sanity"); - } -} - -void MacroAssembler::decode_klass_not_null(Register dst, Register src) { - assert(Metaspace::is_initialized(), "metaspace should be initialized"); - // Note: it will change flags - assert (UseCompressedKlassPointers, "should only be used for compressed headers"); - // Cannot assert, unverified entry point counts instructions (see .ad file) - // vtableStubs also counts instructions in pd_code_size_limit. - // Also do not verify_oop as this is called by verify_oop. - if (Universe::narrow_klass_shift() != 0) { - assert(LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong"); - assert(LogKlassAlignmentInBytes == Address::times_8, "klass not aligned on 64bits?"); - leaq(dst, Address(r12_heapbase, src, Address::times_8, 0)); - } else { - assert (Universe::narrow_klass_base() == NULL, "sanity"); - if (dst != src) { - movq(dst, src); - } - } -} - -void MacroAssembler::set_narrow_oop(Register dst, jobject obj) { - assert (UseCompressedOops, "should only be used for compressed headers"); - assert (Universe::heap() != NULL, "java heap should be initialized"); - assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); - int oop_index = oop_recorder()->find_index(obj); - RelocationHolder rspec = oop_Relocation::spec(oop_index); - mov_narrow_oop(dst, oop_index, rspec); -} - -void MacroAssembler::set_narrow_oop(Address dst, jobject obj) { - assert (UseCompressedOops, "should only be used for compressed headers"); - assert (Universe::heap() != NULL, "java heap should be initialized"); - assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); - int oop_index = oop_recorder()->find_index(obj); - RelocationHolder rspec = oop_Relocation::spec(oop_index); - mov_narrow_oop(dst, oop_index, rspec); -} - -void MacroAssembler::set_narrow_klass(Register dst, Klass* k) { - assert (UseCompressedKlassPointers, "should only be used for compressed headers"); - assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); - int klass_index = oop_recorder()->find_index(k); - RelocationHolder rspec = metadata_Relocation::spec(klass_index); - mov_narrow_oop(dst, oopDesc::encode_klass(k), rspec); -} - -void MacroAssembler::set_narrow_klass(Address dst, Klass* k) { - assert (UseCompressedKlassPointers, "should only be used for compressed headers"); - assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); - int klass_index = oop_recorder()->find_index(k); - RelocationHolder rspec = metadata_Relocation::spec(klass_index); - mov_narrow_oop(dst, oopDesc::encode_klass(k), rspec); -} - -void MacroAssembler::cmp_narrow_oop(Register dst, jobject obj) { - assert (UseCompressedOops, "should only be used for compressed headers"); - assert (Universe::heap() != NULL, "java heap should be initialized"); - assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); - int oop_index = oop_recorder()->find_index(obj); - RelocationHolder rspec = oop_Relocation::spec(oop_index); - Assembler::cmp_narrow_oop(dst, oop_index, rspec); -} - -void MacroAssembler::cmp_narrow_oop(Address dst, jobject obj) { - assert (UseCompressedOops, "should only be used for compressed headers"); - assert (Universe::heap() != NULL, "java heap should be initialized"); - assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); - int oop_index = oop_recorder()->find_index(obj); - RelocationHolder rspec = oop_Relocation::spec(oop_index); - Assembler::cmp_narrow_oop(dst, oop_index, rspec); -} - -void MacroAssembler::cmp_narrow_klass(Register dst, Klass* k) { - assert (UseCompressedKlassPointers, "should only be used for compressed headers"); - assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); - int klass_index = oop_recorder()->find_index(k); - RelocationHolder rspec = metadata_Relocation::spec(klass_index); - Assembler::cmp_narrow_oop(dst, oopDesc::encode_klass(k), rspec); -} - -void MacroAssembler::cmp_narrow_klass(Address dst, Klass* k) { - assert (UseCompressedKlassPointers, "should only be used for compressed headers"); - assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); - int klass_index = oop_recorder()->find_index(k); - RelocationHolder rspec = metadata_Relocation::spec(klass_index); - Assembler::cmp_narrow_oop(dst, oopDesc::encode_klass(k), rspec); -} - -void MacroAssembler::reinit_heapbase() { - if (UseCompressedOops || UseCompressedKlassPointers) { - movptr(r12_heapbase, ExternalAddress((address)Universe::narrow_ptrs_base_addr())); - } -} -#endif // _LP64 - - -// C2 compiled method's prolog code. -void MacroAssembler::verified_entry(int framesize, bool stack_bang, bool fp_mode_24b) { - - // WARNING: Initial instruction MUST be 5 bytes or longer so that - // NativeJump::patch_verified_entry will be able to patch out the entry - // code safely. The push to verify stack depth is ok at 5 bytes, - // the frame allocation can be either 3 or 6 bytes. So if we don't do - // stack bang then we must use the 6 byte frame allocation even if - // we have no frame. :-( - - assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); - // Remove word for return addr - framesize -= wordSize; - - // Calls to C2R adapters often do not accept exceptional returns. - // We require that their callers must bang for them. But be careful, because - // some VM calls (such as call site linkage) can use several kilobytes of - // stack. But the stack safety zone should account for that. - // See bugs 4446381, 4468289, 4497237. - if (stack_bang) { - generate_stack_overflow_check(framesize); - - // We always push rbp, so that on return to interpreter rbp, will be - // restored correctly and we can correct the stack. - push(rbp); - // Remove word for ebp - framesize -= wordSize; - - // Create frame - if (framesize) { - subptr(rsp, framesize); - } - } else { - // Create frame (force generation of a 4 byte immediate value) - subptr_imm32(rsp, framesize); - - // Save RBP register now. - framesize -= wordSize; - movptr(Address(rsp, framesize), rbp); - } - - if (VerifyStackAtCalls) { // Majik cookie to verify stack depth - framesize -= wordSize; - movptr(Address(rsp, framesize), (int32_t)0xbadb100d); - } - -#ifndef _LP64 - // If method sets FPU control word do it now - if (fp_mode_24b) { - fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_24())); - } - if (UseSSE >= 2 && VerifyFPU) { - verify_FPU(0, "FPU stack must be clean on entry"); - } -#endif - -#ifdef ASSERT - if (VerifyStackAtCalls) { - Label L; - push(rax); - mov(rax, rsp); - andptr(rax, StackAlignmentInBytes-1); - cmpptr(rax, StackAlignmentInBytes-wordSize); - pop(rax); - jcc(Assembler::equal, L); - STOP("Stack is not properly aligned!"); - bind(L); - } -#endif - -} - - -// IndexOf for constant substrings with size >= 8 chars -// which don't need to be loaded through stack. -void MacroAssembler::string_indexofC8(Register str1, Register str2, - Register cnt1, Register cnt2, - int int_cnt2, Register result, - XMMRegister vec, Register tmp) { - ShortBranchVerifier sbv(this); - assert(UseSSE42Intrinsics, "SSE4.2 is required"); - - // This method uses pcmpestri inxtruction with bound registers - // inputs: - // xmm - substring - // rax - substring length (elements count) - // mem - scanned string - // rdx - string length (elements count) - // 0xd - mode: 1100 (substring search) + 01 (unsigned shorts) - // outputs: - // rcx - matched index in string - assert(cnt1 == rdx && cnt2 == rax && tmp == rcx, "pcmpestri"); - - Label RELOAD_SUBSTR, SCAN_TO_SUBSTR, SCAN_SUBSTR, - RET_FOUND, RET_NOT_FOUND, EXIT, FOUND_SUBSTR, - MATCH_SUBSTR_HEAD, RELOAD_STR, FOUND_CANDIDATE; - - // Note, inline_string_indexOf() generates checks: - // if (substr.count > string.count) return -1; - // if (substr.count == 0) return 0; - assert(int_cnt2 >= 8, "this code isused only for cnt2 >= 8 chars"); - - // Load substring. - movdqu(vec, Address(str2, 0)); - movl(cnt2, int_cnt2); - movptr(result, str1); // string addr - - if (int_cnt2 > 8) { - jmpb(SCAN_TO_SUBSTR); - - // Reload substr for rescan, this code - // is executed only for large substrings (> 8 chars) - bind(RELOAD_SUBSTR); - movdqu(vec, Address(str2, 0)); - negptr(cnt2); // Jumped here with negative cnt2, convert to positive - - bind(RELOAD_STR); - // We came here after the beginning of the substring was - // matched but the rest of it was not so we need to search - // again. Start from the next element after the previous match. - - // cnt2 is number of substring reminding elements and - // cnt1 is number of string reminding elements when cmp failed. - // Restored cnt1 = cnt1 - cnt2 + int_cnt2 - subl(cnt1, cnt2); - addl(cnt1, int_cnt2); - movl(cnt2, int_cnt2); // Now restore cnt2 - - decrementl(cnt1); // Shift to next element - cmpl(cnt1, cnt2); - jccb(Assembler::negative, RET_NOT_FOUND); // Left less then substring - - addptr(result, 2); - - } // (int_cnt2 > 8) - - // Scan string for start of substr in 16-byte vectors - bind(SCAN_TO_SUBSTR); - pcmpestri(vec, Address(result, 0), 0x0d); - jccb(Assembler::below, FOUND_CANDIDATE); // CF == 1 - subl(cnt1, 8); - jccb(Assembler::lessEqual, RET_NOT_FOUND); // Scanned full string - cmpl(cnt1, cnt2); - jccb(Assembler::negative, RET_NOT_FOUND); // Left less then substring - addptr(result, 16); - jmpb(SCAN_TO_SUBSTR); - - // Found a potential substr - bind(FOUND_CANDIDATE); - // Matched whole vector if first element matched (tmp(rcx) == 0). - if (int_cnt2 == 8) { - jccb(Assembler::overflow, RET_FOUND); // OF == 1 - } else { // int_cnt2 > 8 - jccb(Assembler::overflow, FOUND_SUBSTR); - } - // After pcmpestri tmp(rcx) contains matched element index - // Compute start addr of substr - lea(result, Address(result, tmp, Address::times_2)); - - // Make sure string is still long enough - subl(cnt1, tmp); - cmpl(cnt1, cnt2); - if (int_cnt2 == 8) { - jccb(Assembler::greaterEqual, SCAN_TO_SUBSTR); - } else { // int_cnt2 > 8 - jccb(Assembler::greaterEqual, MATCH_SUBSTR_HEAD); - } - // Left less then substring. - - bind(RET_NOT_FOUND); - movl(result, -1); - jmpb(EXIT); - - if (int_cnt2 > 8) { - // This code is optimized for the case when whole substring - // is matched if its head is matched. - bind(MATCH_SUBSTR_HEAD); - pcmpestri(vec, Address(result, 0), 0x0d); - // Reload only string if does not match - jccb(Assembler::noOverflow, RELOAD_STR); // OF == 0 - - Label CONT_SCAN_SUBSTR; - // Compare the rest of substring (> 8 chars). - bind(FOUND_SUBSTR); - // First 8 chars are already matched. - negptr(cnt2); - addptr(cnt2, 8); - - bind(SCAN_SUBSTR); - subl(cnt1, 8); - cmpl(cnt2, -8); // Do not read beyond substring - jccb(Assembler::lessEqual, CONT_SCAN_SUBSTR); - // Back-up strings to avoid reading beyond substring: - // cnt1 = cnt1 - cnt2 + 8 - addl(cnt1, cnt2); // cnt2 is negative - addl(cnt1, 8); - movl(cnt2, 8); negptr(cnt2); - bind(CONT_SCAN_SUBSTR); - if (int_cnt2 < (int)G) { - movdqu(vec, Address(str2, cnt2, Address::times_2, int_cnt2*2)); - pcmpestri(vec, Address(result, cnt2, Address::times_2, int_cnt2*2), 0x0d); - } else { - // calculate index in register to avoid integer overflow (int_cnt2*2) - movl(tmp, int_cnt2); - addptr(tmp, cnt2); - movdqu(vec, Address(str2, tmp, Address::times_2, 0)); - pcmpestri(vec, Address(result, tmp, Address::times_2, 0), 0x0d); - } - // Need to reload strings pointers if not matched whole vector - jcc(Assembler::noOverflow, RELOAD_SUBSTR); // OF == 0 - addptr(cnt2, 8); - jcc(Assembler::negative, SCAN_SUBSTR); - // Fall through if found full substring - - } // (int_cnt2 > 8) - - bind(RET_FOUND); - // Found result if we matched full small substring. - // Compute substr offset - subptr(result, str1); - shrl(result, 1); // index - bind(EXIT); - -} // string_indexofC8 - -// Small strings are loaded through stack if they cross page boundary. -void MacroAssembler::string_indexof(Register str1, Register str2, - Register cnt1, Register cnt2, - int int_cnt2, Register result, - XMMRegister vec, Register tmp) { - ShortBranchVerifier sbv(this); - assert(UseSSE42Intrinsics, "SSE4.2 is required"); - // - // int_cnt2 is length of small (< 8 chars) constant substring - // or (-1) for non constant substring in which case its length - // is in cnt2 register. - // - // Note, inline_string_indexOf() generates checks: - // if (substr.count > string.count) return -1; - // if (substr.count == 0) return 0; - // - assert(int_cnt2 == -1 || (0 < int_cnt2 && int_cnt2 < 8), "should be != 0"); - - // This method uses pcmpestri inxtruction with bound registers - // inputs: - // xmm - substring - // rax - substring length (elements count) - // mem - scanned string - // rdx - string length (elements count) - // 0xd - mode: 1100 (substring search) + 01 (unsigned shorts) - // outputs: - // rcx - matched index in string - assert(cnt1 == rdx && cnt2 == rax && tmp == rcx, "pcmpestri"); - - Label RELOAD_SUBSTR, SCAN_TO_SUBSTR, SCAN_SUBSTR, ADJUST_STR, - RET_FOUND, RET_NOT_FOUND, CLEANUP, FOUND_SUBSTR, - FOUND_CANDIDATE; - - { //======================================================== - // We don't know where these strings are located - // and we can't read beyond them. Load them through stack. - Label BIG_STRINGS, CHECK_STR, COPY_SUBSTR, COPY_STR; - - movptr(tmp, rsp); // save old SP - - if (int_cnt2 > 0) { // small (< 8 chars) constant substring - if (int_cnt2 == 1) { // One char - load_unsigned_short(result, Address(str2, 0)); - movdl(vec, result); // move 32 bits - } else if (int_cnt2 == 2) { // Two chars - movdl(vec, Address(str2, 0)); // move 32 bits - } else if (int_cnt2 == 4) { // Four chars - movq(vec, Address(str2, 0)); // move 64 bits - } else { // cnt2 = { 3, 5, 6, 7 } - // Array header size is 12 bytes in 32-bit VM - // + 6 bytes for 3 chars == 18 bytes, - // enough space to load vec and shift. - assert(HeapWordSize*TypeArrayKlass::header_size() >= 12,"sanity"); - movdqu(vec, Address(str2, (int_cnt2*2)-16)); - psrldq(vec, 16-(int_cnt2*2)); - } - } else { // not constant substring - cmpl(cnt2, 8); - jccb(Assembler::aboveEqual, BIG_STRINGS); // Both strings are big enough - - // We can read beyond string if srt+16 does not cross page boundary - // since heaps are aligned and mapped by pages. - assert(os::vm_page_size() < (int)G, "default page should be small"); - movl(result, str2); // We need only low 32 bits - andl(result, (os::vm_page_size()-1)); - cmpl(result, (os::vm_page_size()-16)); - jccb(Assembler::belowEqual, CHECK_STR); - - // Move small strings to stack to allow load 16 bytes into vec. - subptr(rsp, 16); - int stk_offset = wordSize-2; - push(cnt2); - - bind(COPY_SUBSTR); - load_unsigned_short(result, Address(str2, cnt2, Address::times_2, -2)); - movw(Address(rsp, cnt2, Address::times_2, stk_offset), result); - decrement(cnt2); - jccb(Assembler::notZero, COPY_SUBSTR); - - pop(cnt2); - movptr(str2, rsp); // New substring address - } // non constant - - bind(CHECK_STR); - cmpl(cnt1, 8); - jccb(Assembler::aboveEqual, BIG_STRINGS); - - // Check cross page boundary. - movl(result, str1); // We need only low 32 bits - andl(result, (os::vm_page_size()-1)); - cmpl(result, (os::vm_page_size()-16)); - jccb(Assembler::belowEqual, BIG_STRINGS); - - subptr(rsp, 16); - int stk_offset = -2; - if (int_cnt2 < 0) { // not constant - push(cnt2); - stk_offset += wordSize; - } - movl(cnt2, cnt1); - - bind(COPY_STR); - load_unsigned_short(result, Address(str1, cnt2, Address::times_2, -2)); - movw(Address(rsp, cnt2, Address::times_2, stk_offset), result); - decrement(cnt2); - jccb(Assembler::notZero, COPY_STR); - - if (int_cnt2 < 0) { // not constant - pop(cnt2); - } - movptr(str1, rsp); // New string address - - bind(BIG_STRINGS); - // Load substring. - if (int_cnt2 < 0) { // -1 - movdqu(vec, Address(str2, 0)); - push(cnt2); // substr count - push(str2); // substr addr - push(str1); // string addr - } else { - // Small (< 8 chars) constant substrings are loaded already. - movl(cnt2, int_cnt2); - } - push(tmp); // original SP - - } // Finished loading - - //======================================================== - // Start search - // - - movptr(result, str1); // string addr - - if (int_cnt2 < 0) { // Only for non constant substring - jmpb(SCAN_TO_SUBSTR); - - // SP saved at sp+0 - // String saved at sp+1*wordSize - // Substr saved at sp+2*wordSize - // Substr count saved at sp+3*wordSize - - // Reload substr for rescan, this code - // is executed only for large substrings (> 8 chars) - bind(RELOAD_SUBSTR); - movptr(str2, Address(rsp, 2*wordSize)); - movl(cnt2, Address(rsp, 3*wordSize)); - movdqu(vec, Address(str2, 0)); - // We came here after the beginning of the substring was - // matched but the rest of it was not so we need to search - // again. Start from the next element after the previous match. - subptr(str1, result); // Restore counter - shrl(str1, 1); - addl(cnt1, str1); - decrementl(cnt1); // Shift to next element - cmpl(cnt1, cnt2); - jccb(Assembler::negative, RET_NOT_FOUND); // Left less then substring - - addptr(result, 2); - } // non constant - - // Scan string for start of substr in 16-byte vectors - bind(SCAN_TO_SUBSTR); - assert(cnt1 == rdx && cnt2 == rax && tmp == rcx, "pcmpestri"); - pcmpestri(vec, Address(result, 0), 0x0d); - jccb(Assembler::below, FOUND_CANDIDATE); // CF == 1 - subl(cnt1, 8); - jccb(Assembler::lessEqual, RET_NOT_FOUND); // Scanned full string - cmpl(cnt1, cnt2); - jccb(Assembler::negative, RET_NOT_FOUND); // Left less then substring - addptr(result, 16); - - bind(ADJUST_STR); - cmpl(cnt1, 8); // Do not read beyond string - jccb(Assembler::greaterEqual, SCAN_TO_SUBSTR); - // Back-up string to avoid reading beyond string. - lea(result, Address(result, cnt1, Address::times_2, -16)); - movl(cnt1, 8); - jmpb(SCAN_TO_SUBSTR); - - // Found a potential substr - bind(FOUND_CANDIDATE); - // After pcmpestri tmp(rcx) contains matched element index - - // Make sure string is still long enough - subl(cnt1, tmp); - cmpl(cnt1, cnt2); - jccb(Assembler::greaterEqual, FOUND_SUBSTR); - // Left less then substring. - - bind(RET_NOT_FOUND); - movl(result, -1); - jmpb(CLEANUP); - - bind(FOUND_SUBSTR); - // Compute start addr of substr - lea(result, Address(result, tmp, Address::times_2)); - - if (int_cnt2 > 0) { // Constant substring - // Repeat search for small substring (< 8 chars) - // from new point without reloading substring. - // Have to check that we don't read beyond string. - cmpl(tmp, 8-int_cnt2); - jccb(Assembler::greater, ADJUST_STR); - // Fall through if matched whole substring. - } else { // non constant - assert(int_cnt2 == -1, "should be != 0"); - - addl(tmp, cnt2); - // Found result if we matched whole substring. - cmpl(tmp, 8); - jccb(Assembler::lessEqual, RET_FOUND); - - // Repeat search for small substring (<= 8 chars) - // from new point 'str1' without reloading substring. - cmpl(cnt2, 8); - // Have to check that we don't read beyond string. - jccb(Assembler::lessEqual, ADJUST_STR); - - Label CHECK_NEXT, CONT_SCAN_SUBSTR, RET_FOUND_LONG; - // Compare the rest of substring (> 8 chars). - movptr(str1, result); - - cmpl(tmp, cnt2); - // First 8 chars are already matched. - jccb(Assembler::equal, CHECK_NEXT); - - bind(SCAN_SUBSTR); - pcmpestri(vec, Address(str1, 0), 0x0d); - // Need to reload strings pointers if not matched whole vector - jcc(Assembler::noOverflow, RELOAD_SUBSTR); // OF == 0 - - bind(CHECK_NEXT); - subl(cnt2, 8); - jccb(Assembler::lessEqual, RET_FOUND_LONG); // Found full substring - addptr(str1, 16); - addptr(str2, 16); - subl(cnt1, 8); - cmpl(cnt2, 8); // Do not read beyond substring - jccb(Assembler::greaterEqual, CONT_SCAN_SUBSTR); - // Back-up strings to avoid reading beyond substring. - lea(str2, Address(str2, cnt2, Address::times_2, -16)); - lea(str1, Address(str1, cnt2, Address::times_2, -16)); - subl(cnt1, cnt2); - movl(cnt2, 8); - addl(cnt1, 8); - bind(CONT_SCAN_SUBSTR); - movdqu(vec, Address(str2, 0)); - jmpb(SCAN_SUBSTR); - - bind(RET_FOUND_LONG); - movptr(str1, Address(rsp, wordSize)); - } // non constant - - bind(RET_FOUND); - // Compute substr offset - subptr(result, str1); - shrl(result, 1); // index - - bind(CLEANUP); - pop(rsp); // restore SP - -} // string_indexof - -// Compare strings. -void MacroAssembler::string_compare(Register str1, Register str2, - Register cnt1, Register cnt2, Register result, - XMMRegister vec1) { - ShortBranchVerifier sbv(this); - Label LENGTH_DIFF_LABEL, POP_LABEL, DONE_LABEL, WHILE_HEAD_LABEL; - - // Compute the minimum of the string lengths and the - // difference of the string lengths (stack). - // Do the conditional move stuff - movl(result, cnt1); - subl(cnt1, cnt2); - push(cnt1); - cmov32(Assembler::lessEqual, cnt2, result); - - // Is the minimum length zero? - testl(cnt2, cnt2); - jcc(Assembler::zero, LENGTH_DIFF_LABEL); - - // Load first characters - load_unsigned_short(result, Address(str1, 0)); - load_unsigned_short(cnt1, Address(str2, 0)); - - // Compare first characters - subl(result, cnt1); - jcc(Assembler::notZero, POP_LABEL); - decrementl(cnt2); - jcc(Assembler::zero, LENGTH_DIFF_LABEL); - - { - // Check after comparing first character to see if strings are equivalent - Label LSkip2; - // Check if the strings start at same location - cmpptr(str1, str2); - jccb(Assembler::notEqual, LSkip2); - - // Check if the length difference is zero (from stack) - cmpl(Address(rsp, 0), 0x0); - jcc(Assembler::equal, LENGTH_DIFF_LABEL); - - // Strings might not be equivalent - bind(LSkip2); - } - - Address::ScaleFactor scale = Address::times_2; - int stride = 8; - - // Advance to next element - addptr(str1, 16/stride); - addptr(str2, 16/stride); - - if (UseSSE42Intrinsics) { - Label COMPARE_WIDE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_TAIL; - int pcmpmask = 0x19; - // Setup to compare 16-byte vectors - movl(result, cnt2); - andl(cnt2, ~(stride - 1)); // cnt2 holds the vector count - jccb(Assembler::zero, COMPARE_TAIL); - - lea(str1, Address(str1, result, scale)); - lea(str2, Address(str2, result, scale)); - negptr(result); - - // pcmpestri - // inputs: - // vec1- substring - // rax - negative string length (elements count) - // mem - scaned string - // rdx - string length (elements count) - // pcmpmask - cmp mode: 11000 (string compare with negated result) - // + 00 (unsigned bytes) or + 01 (unsigned shorts) - // outputs: - // rcx - first mismatched element index - assert(result == rax && cnt2 == rdx && cnt1 == rcx, "pcmpestri"); - - bind(COMPARE_WIDE_VECTORS); - movdqu(vec1, Address(str1, result, scale)); - pcmpestri(vec1, Address(str2, result, scale), pcmpmask); - // After pcmpestri cnt1(rcx) contains mismatched element index - - jccb(Assembler::below, VECTOR_NOT_EQUAL); // CF==1 - addptr(result, stride); - subptr(cnt2, stride); - jccb(Assembler::notZero, COMPARE_WIDE_VECTORS); - - // compare wide vectors tail - testl(result, result); - jccb(Assembler::zero, LENGTH_DIFF_LABEL); - - movl(cnt2, stride); - movl(result, stride); - negptr(result); - movdqu(vec1, Address(str1, result, scale)); - pcmpestri(vec1, Address(str2, result, scale), pcmpmask); - jccb(Assembler::aboveEqual, LENGTH_DIFF_LABEL); - - // Mismatched characters in the vectors - bind(VECTOR_NOT_EQUAL); - addptr(result, cnt1); - movptr(cnt2, result); - load_unsigned_short(result, Address(str1, cnt2, scale)); - load_unsigned_short(cnt1, Address(str2, cnt2, scale)); - subl(result, cnt1); - jmpb(POP_LABEL); - - bind(COMPARE_TAIL); // limit is zero - movl(cnt2, result); - // Fallthru to tail compare - } - - // Shift str2 and str1 to the end of the arrays, negate min - lea(str1, Address(str1, cnt2, scale, 0)); - lea(str2, Address(str2, cnt2, scale, 0)); - negptr(cnt2); - - // Compare the rest of the elements - bind(WHILE_HEAD_LABEL); - load_unsigned_short(result, Address(str1, cnt2, scale, 0)); - load_unsigned_short(cnt1, Address(str2, cnt2, scale, 0)); - subl(result, cnt1); - jccb(Assembler::notZero, POP_LABEL); - increment(cnt2); - jccb(Assembler::notZero, WHILE_HEAD_LABEL); - - // Strings are equal up to min length. Return the length difference. - bind(LENGTH_DIFF_LABEL); - pop(result); - jmpb(DONE_LABEL); - - // Discard the stored length difference - bind(POP_LABEL); - pop(cnt1); - - // That's it - bind(DONE_LABEL); -} - -// Compare char[] arrays aligned to 4 bytes or substrings. -void MacroAssembler::char_arrays_equals(bool is_array_equ, Register ary1, Register ary2, - Register limit, Register result, Register chr, - XMMRegister vec1, XMMRegister vec2) { - ShortBranchVerifier sbv(this); - Label TRUE_LABEL, FALSE_LABEL, DONE, COMPARE_VECTORS, COMPARE_CHAR; - - int length_offset = arrayOopDesc::length_offset_in_bytes(); - int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); - - // Check the input args - cmpptr(ary1, ary2); - jcc(Assembler::equal, TRUE_LABEL); - - if (is_array_equ) { - // Need additional checks for arrays_equals. - testptr(ary1, ary1); - jcc(Assembler::zero, FALSE_LABEL); - testptr(ary2, ary2); - jcc(Assembler::zero, FALSE_LABEL); - - // Check the lengths - movl(limit, Address(ary1, length_offset)); - cmpl(limit, Address(ary2, length_offset)); - jcc(Assembler::notEqual, FALSE_LABEL); - } - - // count == 0 - testl(limit, limit); - jcc(Assembler::zero, TRUE_LABEL); - - if (is_array_equ) { - // Load array address - lea(ary1, Address(ary1, base_offset)); - lea(ary2, Address(ary2, base_offset)); - } - - shll(limit, 1); // byte count != 0 - movl(result, limit); // copy - - if (UseSSE42Intrinsics) { - // With SSE4.2, use double quad vector compare - Label COMPARE_WIDE_VECTORS, COMPARE_TAIL; - - // Compare 16-byte vectors - andl(result, 0x0000000e); // tail count (in bytes) - andl(limit, 0xfffffff0); // vector count (in bytes) - jccb(Assembler::zero, COMPARE_TAIL); - - lea(ary1, Address(ary1, limit, Address::times_1)); - lea(ary2, Address(ary2, limit, Address::times_1)); - negptr(limit); - - bind(COMPARE_WIDE_VECTORS); - movdqu(vec1, Address(ary1, limit, Address::times_1)); - movdqu(vec2, Address(ary2, limit, Address::times_1)); - pxor(vec1, vec2); - - ptest(vec1, vec1); - jccb(Assembler::notZero, FALSE_LABEL); - addptr(limit, 16); - jcc(Assembler::notZero, COMPARE_WIDE_VECTORS); - - testl(result, result); - jccb(Assembler::zero, TRUE_LABEL); - - movdqu(vec1, Address(ary1, result, Address::times_1, -16)); - movdqu(vec2, Address(ary2, result, Address::times_1, -16)); - pxor(vec1, vec2); - - ptest(vec1, vec1); - jccb(Assembler::notZero, FALSE_LABEL); - jmpb(TRUE_LABEL); - - bind(COMPARE_TAIL); // limit is zero - movl(limit, result); - // Fallthru to tail compare - } - - // Compare 4-byte vectors - andl(limit, 0xfffffffc); // vector count (in bytes) - jccb(Assembler::zero, COMPARE_CHAR); - - lea(ary1, Address(ary1, limit, Address::times_1)); - lea(ary2, Address(ary2, limit, Address::times_1)); - negptr(limit); - - bind(COMPARE_VECTORS); - movl(chr, Address(ary1, limit, Address::times_1)); - cmpl(chr, Address(ary2, limit, Address::times_1)); - jccb(Assembler::notEqual, FALSE_LABEL); - addptr(limit, 4); - jcc(Assembler::notZero, COMPARE_VECTORS); - - // Compare trailing char (final 2 bytes), if any - bind(COMPARE_CHAR); - testl(result, 0x2); // tail char - jccb(Assembler::zero, TRUE_LABEL); - load_unsigned_short(chr, Address(ary1, 0)); - load_unsigned_short(limit, Address(ary2, 0)); - cmpl(chr, limit); - jccb(Assembler::notEqual, FALSE_LABEL); - - bind(TRUE_LABEL); - movl(result, 1); // return true - jmpb(DONE); - - bind(FALSE_LABEL); - xorl(result, result); // return false - - // That's it - bind(DONE); -} - -void MacroAssembler::generate_fill(BasicType t, bool aligned, - Register to, Register value, Register count, - Register rtmp, XMMRegister xtmp) { - ShortBranchVerifier sbv(this); - assert_different_registers(to, value, count, rtmp); - Label L_exit, L_skip_align1, L_skip_align2, L_fill_byte; - Label L_fill_2_bytes, L_fill_4_bytes; - - int shift = -1; - switch (t) { - case T_BYTE: - shift = 2; - break; - case T_SHORT: - shift = 1; - break; - case T_INT: - shift = 0; - break; - default: ShouldNotReachHere(); - } - - if (t == T_BYTE) { - andl(value, 0xff); - movl(rtmp, value); - shll(rtmp, 8); - orl(value, rtmp); - } - if (t == T_SHORT) { - andl(value, 0xffff); - } - if (t == T_BYTE || t == T_SHORT) { - movl(rtmp, value); - shll(rtmp, 16); - orl(value, rtmp); - } - - cmpl(count, 2<= 2, "supported cpu only" ); - Label L_fill_32_bytes_loop, L_check_fill_8_bytes, L_fill_8_bytes_loop, L_fill_8_bytes; - // Fill 32-byte chunks - movdl(xtmp, value); - pshufd(xtmp, xtmp, 0); - - subl(count, 8 << shift); - jcc(Assembler::less, L_check_fill_8_bytes); - align(16); - - BIND(L_fill_32_bytes_loop); - - if (UseUnalignedLoadStores) { - movdqu(Address(to, 0), xtmp); - movdqu(Address(to, 16), xtmp); - } else { - movq(Address(to, 0), xtmp); - movq(Address(to, 8), xtmp); - movq(Address(to, 16), xtmp); - movq(Address(to, 24), xtmp); - } - - addptr(to, 32); - subl(count, 8 << shift); - jcc(Assembler::greaterEqual, L_fill_32_bytes_loop); - BIND(L_check_fill_8_bytes); - addl(count, 8 << shift); - jccb(Assembler::zero, L_exit); - jmpb(L_fill_8_bytes); - - // - // length is too short, just fill qwords - // - BIND(L_fill_8_bytes_loop); - movq(Address(to, 0), xtmp); - addptr(to, 8); - BIND(L_fill_8_bytes); - subl(count, 1 << (shift + 1)); - jcc(Assembler::greaterEqual, L_fill_8_bytes_loop); - } - } - // fill trailing 4 bytes - BIND(L_fill_4_bytes); - testl(count, 1<cmp8(ExternalAddress((address)flag_addr), value); - _masm->jcc(Assembler::equal, _label); -} - -SkipIfEqual::~SkipIfEqual() { - _masm->bind(_label); -} diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.hpp b/hotspot/src/cpu/x86/vm/assembler_x86.hpp index 8a9bbaf424e..a48aeda8dd3 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp @@ -25,6 +25,8 @@ #ifndef CPU_X86_VM_ASSEMBLER_X86_HPP #define CPU_X86_VM_ASSEMBLER_X86_HPP +#include "asm/register.hpp" + class BiasedLockingCounters; // Contains all the definitions needed for x86 assembly code generation. @@ -706,8 +708,6 @@ private: void check_relocation(RelocationHolder const& rspec, int format); #endif - inline void emit_long64(jlong x); - void emit_data(jint data, relocInfo::relocType rtype, int format); void emit_data(jint data, RelocationHolder const& rspec, int format); void emit_data64(jlong data, relocInfo::relocType rtype, int format = 0); @@ -916,7 +916,7 @@ private: void cdqq(); - void cld() { emit_byte(0xfc); } + void cld(); void clflush(Address adr); @@ -963,10 +963,7 @@ private: void comiss(XMMRegister dst, XMMRegister src); // Identify processor type and features - void cpuid() { - emit_byte(0x0F); - emit_byte(0xA2); - } + void cpuid(); // Convert Scalar Double-Precision Floating-Point Value to Scalar Single-Precision Floating-Point Value void cvtsd2ss(XMMRegister dst, XMMRegister src); @@ -1211,11 +1208,7 @@ private: void leaq(Register dst, Address src); - void lfence() { - emit_byte(0x0F); - emit_byte(0xAE); - emit_byte(0xE8); - } + void lfence(); void lock(); @@ -1523,7 +1516,7 @@ private: void sqrtss(XMMRegister dst, Address src); void sqrtss(XMMRegister dst, XMMRegister src); - void std() { emit_byte(0xfd); } + void std(); void stmxcsr( Address dst ); @@ -1580,11 +1573,7 @@ private: void xchgq(Register dst, Register src); // Get Value of Extended Control Register - void xgetbv() { - emit_byte(0x0F); - emit_byte(0x01); - emit_byte(0xD0); - } + void xgetbv(); void xorl(Register dst, int32_t imm32); void xorl(Register dst, Address src); @@ -1781,1114 +1770,4 @@ private: }; - -// MacroAssembler extends Assembler by frequently used macros. -// -// Instructions for which a 'better' code sequence exists depending -// on arguments should also go in here. - -class MacroAssembler: public Assembler { - friend class LIR_Assembler; - friend class Runtime1; // as_Address() - - protected: - - Address as_Address(AddressLiteral adr); - Address as_Address(ArrayAddress adr); - - // Support for VM calls - // - // This is the base routine called by the different versions of call_VM_leaf. The interpreter - // may customize this version by overriding it for its purposes (e.g., to save/restore - // additional registers when doing a VM call). -#ifdef CC_INTERP - // c++ interpreter never wants to use interp_masm version of call_VM - #define VIRTUAL -#else - #define VIRTUAL virtual -#endif - - VIRTUAL void call_VM_leaf_base( - address entry_point, // the entry point - int number_of_arguments // the number of arguments to pop after the call - ); - - // This is the base routine called by the different versions of call_VM. The interpreter - // may customize this version by overriding it for its purposes (e.g., to save/restore - // additional registers when doing a VM call). - // - // If no java_thread register is specified (noreg) than rdi will be used instead. call_VM_base - // returns the register which contains the thread upon return. If a thread register has been - // specified, the return value will correspond to that register. If no last_java_sp is specified - // (noreg) than rsp will be used instead. - VIRTUAL void call_VM_base( // returns the register containing the thread upon return - Register oop_result, // where an oop-result ends up if any; use noreg otherwise - Register java_thread, // the thread if computed before ; use noreg otherwise - Register last_java_sp, // to set up last_Java_frame in stubs; use noreg otherwise - address entry_point, // the entry point - int number_of_arguments, // the number of arguments (w/o thread) to pop after the call - bool check_exceptions // whether to check for pending exceptions after return - ); - - // These routines should emit JVMTI PopFrame and ForceEarlyReturn handling code. - // The implementation is only non-empty for the InterpreterMacroAssembler, - // as only the interpreter handles PopFrame and ForceEarlyReturn requests. - virtual void check_and_handle_popframe(Register java_thread); - virtual void check_and_handle_earlyret(Register java_thread); - - void call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions = true); - - // helpers for FPU flag access - // tmp is a temporary register, if none is available use noreg - void save_rax (Register tmp); - void restore_rax(Register tmp); - - public: - MacroAssembler(CodeBuffer* code) : Assembler(code) {} - - // Support for NULL-checks - // - // Generates code that causes a NULL OS exception if the content of reg is NULL. - // If the accessed location is M[reg + offset] and the offset is known, provide the - // offset. No explicit code generation is needed if the offset is within a certain - // range (0 <= offset <= page_size). - - void null_check(Register reg, int offset = -1); - static bool needs_explicit_null_check(intptr_t offset); - - // Required platform-specific helpers for Label::patch_instructions. - // They _shadow_ the declarations in AbstractAssembler, which are undefined. - void pd_patch_instruction(address branch, address target); -#ifndef PRODUCT - static void pd_print_patched_instruction(address branch); -#endif - - // The following 4 methods return the offset of the appropriate move instruction - - // Support for fast byte/short loading with zero extension (depending on particular CPU) - int load_unsigned_byte(Register dst, Address src); - int load_unsigned_short(Register dst, Address src); - - // Support for fast byte/short loading with sign extension (depending on particular CPU) - int load_signed_byte(Register dst, Address src); - int load_signed_short(Register dst, Address src); - - // Support for sign-extension (hi:lo = extend_sign(lo)) - void extend_sign(Register hi, Register lo); - - // Load and store values by size and signed-ness - void load_sized_value(Register dst, Address src, size_t size_in_bytes, bool is_signed, Register dst2 = noreg); - void store_sized_value(Address dst, Register src, size_t size_in_bytes, Register src2 = noreg); - - // Support for inc/dec with optimal instruction selection depending on value - - void increment(Register reg, int value = 1) { LP64_ONLY(incrementq(reg, value)) NOT_LP64(incrementl(reg, value)) ; } - void decrement(Register reg, int value = 1) { LP64_ONLY(decrementq(reg, value)) NOT_LP64(decrementl(reg, value)) ; } - - void decrementl(Address dst, int value = 1); - void decrementl(Register reg, int value = 1); - - void decrementq(Register reg, int value = 1); - void decrementq(Address dst, int value = 1); - - void incrementl(Address dst, int value = 1); - void incrementl(Register reg, int value = 1); - - void incrementq(Register reg, int value = 1); - void incrementq(Address dst, int value = 1); - - - // Support optimal SSE move instructions. - void movflt(XMMRegister dst, XMMRegister src) { - if (UseXmmRegToRegMoveAll) { movaps(dst, src); return; } - else { movss (dst, src); return; } - } - void movflt(XMMRegister dst, Address src) { movss(dst, src); } - void movflt(XMMRegister dst, AddressLiteral src); - void movflt(Address dst, XMMRegister src) { movss(dst, src); } - - void movdbl(XMMRegister dst, XMMRegister src) { - if (UseXmmRegToRegMoveAll) { movapd(dst, src); return; } - else { movsd (dst, src); return; } - } - - void movdbl(XMMRegister dst, AddressLiteral src); - - void movdbl(XMMRegister dst, Address src) { - if (UseXmmLoadAndClearUpper) { movsd (dst, src); return; } - else { movlpd(dst, src); return; } - } - void movdbl(Address dst, XMMRegister src) { movsd(dst, src); } - - void incrementl(AddressLiteral dst); - void incrementl(ArrayAddress dst); - - // Alignment - void align(int modulus); - - // A 5 byte nop that is safe for patching (see patch_verified_entry) - void fat_nop(); - - // Stack frame creation/removal - void enter(); - void leave(); - - // Support for getting the JavaThread pointer (i.e.; a reference to thread-local information) - // The pointer will be loaded into the thread register. - void get_thread(Register thread); - - - // Support for VM calls - // - // It is imperative that all calls into the VM are handled via the call_VM macros. - // They make sure that the stack linkage is setup correctly. call_VM's correspond - // to ENTRY/ENTRY_X entry points while call_VM_leaf's correspond to LEAF entry points. - - - void call_VM(Register oop_result, - address entry_point, - bool check_exceptions = true); - void call_VM(Register oop_result, - address entry_point, - Register arg_1, - bool check_exceptions = true); - void call_VM(Register oop_result, - address entry_point, - Register arg_1, Register arg_2, - bool check_exceptions = true); - void call_VM(Register oop_result, - address entry_point, - Register arg_1, Register arg_2, Register arg_3, - bool check_exceptions = true); - - // Overloadings with last_Java_sp - void call_VM(Register oop_result, - Register last_java_sp, - address entry_point, - int number_of_arguments = 0, - bool check_exceptions = true); - void call_VM(Register oop_result, - Register last_java_sp, - address entry_point, - Register arg_1, bool - check_exceptions = true); - void call_VM(Register oop_result, - Register last_java_sp, - address entry_point, - Register arg_1, Register arg_2, - bool check_exceptions = true); - void call_VM(Register oop_result, - Register last_java_sp, - address entry_point, - Register arg_1, Register arg_2, Register arg_3, - bool check_exceptions = true); - - void get_vm_result (Register oop_result, Register thread); - void get_vm_result_2(Register metadata_result, Register thread); - - // These always tightly bind to MacroAssembler::call_VM_base - // bypassing the virtual implementation - void super_call_VM(Register oop_result, Register last_java_sp, address entry_point, int number_of_arguments = 0, bool check_exceptions = true); - void super_call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, bool check_exceptions = true); - void super_call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, Register arg_2, bool check_exceptions = true); - void super_call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, Register arg_2, Register arg_3, bool check_exceptions = true); - void super_call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, Register arg_2, Register arg_3, Register arg_4, bool check_exceptions = true); - - void call_VM_leaf(address entry_point, - int number_of_arguments = 0); - void call_VM_leaf(address entry_point, - Register arg_1); - void call_VM_leaf(address entry_point, - Register arg_1, Register arg_2); - void call_VM_leaf(address entry_point, - Register arg_1, Register arg_2, Register arg_3); - - // These always tightly bind to MacroAssembler::call_VM_leaf_base - // bypassing the virtual implementation - void super_call_VM_leaf(address entry_point); - void super_call_VM_leaf(address entry_point, Register arg_1); - void super_call_VM_leaf(address entry_point, Register arg_1, Register arg_2); - void super_call_VM_leaf(address entry_point, Register arg_1, Register arg_2, Register arg_3); - void super_call_VM_leaf(address entry_point, Register arg_1, Register arg_2, Register arg_3, Register arg_4); - - // last Java Frame (fills frame anchor) - void set_last_Java_frame(Register thread, - Register last_java_sp, - Register last_java_fp, - address last_java_pc); - - // thread in the default location (r15_thread on 64bit) - void set_last_Java_frame(Register last_java_sp, - Register last_java_fp, - address last_java_pc); - - void reset_last_Java_frame(Register thread, bool clear_fp, bool clear_pc); - - // thread in the default location (r15_thread on 64bit) - void reset_last_Java_frame(bool clear_fp, bool clear_pc); - - // Stores - void store_check(Register obj); // store check for obj - register is destroyed afterwards - void store_check(Register obj, Address dst); // same as above, dst is exact store location (reg. is destroyed) - -#ifndef SERIALGC - - void g1_write_barrier_pre(Register obj, - Register pre_val, - Register thread, - Register tmp, - bool tosca_live, - bool expand_call); - - void g1_write_barrier_post(Register store_addr, - Register new_val, - Register thread, - Register tmp, - Register tmp2); - -#endif // SERIALGC - - // split store_check(Register obj) to enhance instruction interleaving - void store_check_part_1(Register obj); - void store_check_part_2(Register obj); - - // C 'boolean' to Java boolean: x == 0 ? 0 : 1 - void c2bool(Register x); - - // C++ bool manipulation - - void movbool(Register dst, Address src); - void movbool(Address dst, bool boolconst); - void movbool(Address dst, Register src); - void testbool(Register dst); - - // oop manipulations - void load_klass(Register dst, Register src); - void store_klass(Register dst, Register src); - - void load_heap_oop(Register dst, Address src); - void load_heap_oop_not_null(Register dst, Address src); - void store_heap_oop(Address dst, Register src); - void cmp_heap_oop(Register src1, Address src2, Register tmp = noreg); - - // Used for storing NULL. All other oop constants should be - // stored using routines that take a jobject. - void store_heap_oop_null(Address dst); - - void load_prototype_header(Register dst, Register src); - -#ifdef _LP64 - void store_klass_gap(Register dst, Register src); - - // This dummy is to prevent a call to store_heap_oop from - // converting a zero (like NULL) into a Register by giving - // the compiler two choices it can't resolve - - void store_heap_oop(Address dst, void* dummy); - - void encode_heap_oop(Register r); - void decode_heap_oop(Register r); - void encode_heap_oop_not_null(Register r); - void decode_heap_oop_not_null(Register r); - void encode_heap_oop_not_null(Register dst, Register src); - void decode_heap_oop_not_null(Register dst, Register src); - - void set_narrow_oop(Register dst, jobject obj); - void set_narrow_oop(Address dst, jobject obj); - void cmp_narrow_oop(Register dst, jobject obj); - void cmp_narrow_oop(Address dst, jobject obj); - - void encode_klass_not_null(Register r); - void decode_klass_not_null(Register r); - void encode_klass_not_null(Register dst, Register src); - void decode_klass_not_null(Register dst, Register src); - void set_narrow_klass(Register dst, Klass* k); - void set_narrow_klass(Address dst, Klass* k); - void cmp_narrow_klass(Register dst, Klass* k); - void cmp_narrow_klass(Address dst, Klass* k); - - // if heap base register is used - reinit it with the correct value - void reinit_heapbase(); - - DEBUG_ONLY(void verify_heapbase(const char* msg);) - -#endif // _LP64 - - // Int division/remainder for Java - // (as idivl, but checks for special case as described in JVM spec.) - // returns idivl instruction offset for implicit exception handling - int corrected_idivl(Register reg); - - // Long division/remainder for Java - // (as idivq, but checks for special case as described in JVM spec.) - // returns idivq instruction offset for implicit exception handling - int corrected_idivq(Register reg); - - void int3(); - - // Long operation macros for a 32bit cpu - // Long negation for Java - void lneg(Register hi, Register lo); - - // Long multiplication for Java - // (destroys contents of eax, ebx, ecx and edx) - void lmul(int x_rsp_offset, int y_rsp_offset); // rdx:rax = x * y - - // Long shifts for Java - // (semantics as described in JVM spec.) - void lshl(Register hi, Register lo); // hi:lo << (rcx & 0x3f) - void lshr(Register hi, Register lo, bool sign_extension = false); // hi:lo >> (rcx & 0x3f) - - // Long compare for Java - // (semantics as described in JVM spec.) - void lcmp2int(Register x_hi, Register x_lo, Register y_hi, Register y_lo); // x_hi = lcmp(x, y) - - - // misc - - // Sign extension - void sign_extend_short(Register reg); - void sign_extend_byte(Register reg); - - // Division by power of 2, rounding towards 0 - void division_with_shift(Register reg, int shift_value); - - // Compares the top-most stack entries on the FPU stack and sets the eflags as follows: - // - // CF (corresponds to C0) if x < y - // PF (corresponds to C2) if unordered - // ZF (corresponds to C3) if x = y - // - // The arguments are in reversed order on the stack (i.e., top of stack is first argument). - // tmp is a temporary register, if none is available use noreg (only matters for non-P6 code) - void fcmp(Register tmp); - // Variant of the above which allows y to be further down the stack - // and which only pops x and y if specified. If pop_right is - // specified then pop_left must also be specified. - void fcmp(Register tmp, int index, bool pop_left, bool pop_right); - - // Floating-point comparison for Java - // Compares the top-most stack entries on the FPU stack and stores the result in dst. - // The arguments are in reversed order on the stack (i.e., top of stack is first argument). - // (semantics as described in JVM spec.) - void fcmp2int(Register dst, bool unordered_is_less); - // Variant of the above which allows y to be further down the stack - // and which only pops x and y if specified. If pop_right is - // specified then pop_left must also be specified. - void fcmp2int(Register dst, bool unordered_is_less, int index, bool pop_left, bool pop_right); - - // Floating-point remainder for Java (ST0 = ST0 fremr ST1, ST1 is empty afterwards) - // tmp is a temporary register, if none is available use noreg - void fremr(Register tmp); - - - // same as fcmp2int, but using SSE2 - void cmpss2int(XMMRegister opr1, XMMRegister opr2, Register dst, bool unordered_is_less); - void cmpsd2int(XMMRegister opr1, XMMRegister opr2, Register dst, bool unordered_is_less); - - // Inlined sin/cos generator for Java; must not use CPU instruction - // directly on Intel as it does not have high enough precision - // outside of the range [-pi/4, pi/4]. Extra argument indicate the - // number of FPU stack slots in use; all but the topmost will - // require saving if a slow case is necessary. Assumes argument is - // on FP TOS; result is on FP TOS. No cpu registers are changed by - // this code. - void trigfunc(char trig, int num_fpu_regs_in_use = 1); - - // branch to L if FPU flag C2 is set/not set - // tmp is a temporary register, if none is available use noreg - void jC2 (Register tmp, Label& L); - void jnC2(Register tmp, Label& L); - - // Pop ST (ffree & fincstp combined) - void fpop(); - - // pushes double TOS element of FPU stack on CPU stack; pops from FPU stack - void push_fTOS(); - - // pops double TOS element from CPU stack and pushes on FPU stack - void pop_fTOS(); - - void empty_FPU_stack(); - - void push_IU_state(); - void pop_IU_state(); - - void push_FPU_state(); - void pop_FPU_state(); - - void push_CPU_state(); - void pop_CPU_state(); - - // Round up to a power of two - void round_to(Register reg, int modulus); - - // Callee saved registers handling - void push_callee_saved_registers(); - void pop_callee_saved_registers(); - - // allocation - void eden_allocate( - Register obj, // result: pointer to object after successful allocation - Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise - int con_size_in_bytes, // object size in bytes if known at compile time - Register t1, // temp register - Label& slow_case // continuation point if fast allocation fails - ); - void tlab_allocate( - Register obj, // result: pointer to object after successful allocation - Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise - int con_size_in_bytes, // object size in bytes if known at compile time - Register t1, // temp register - Register t2, // temp register - Label& slow_case // continuation point if fast allocation fails - ); - Register tlab_refill(Label& retry_tlab, Label& try_eden, Label& slow_case); // returns TLS address - void incr_allocated_bytes(Register thread, - Register var_size_in_bytes, int con_size_in_bytes, - Register t1 = noreg); - - // interface method calling - void lookup_interface_method(Register recv_klass, - Register intf_klass, - RegisterOrConstant itable_index, - Register method_result, - Register scan_temp, - Label& no_such_interface); - - // virtual method calling - void lookup_virtual_method(Register recv_klass, - RegisterOrConstant vtable_index, - Register method_result); - - // Test sub_klass against super_klass, with fast and slow paths. - - // The fast path produces a tri-state answer: yes / no / maybe-slow. - // One of the three labels can be NULL, meaning take the fall-through. - // If super_check_offset is -1, the value is loaded up from super_klass. - // No registers are killed, except temp_reg. - void check_klass_subtype_fast_path(Register sub_klass, - Register super_klass, - Register temp_reg, - Label* L_success, - Label* L_failure, - Label* L_slow_path, - RegisterOrConstant super_check_offset = RegisterOrConstant(-1)); - - // The rest of the type check; must be wired to a corresponding fast path. - // It does not repeat the fast path logic, so don't use it standalone. - // The temp_reg and temp2_reg can be noreg, if no temps are available. - // Updates the sub's secondary super cache as necessary. - // If set_cond_codes, condition codes will be Z on success, NZ on failure. - void check_klass_subtype_slow_path(Register sub_klass, - Register super_klass, - Register temp_reg, - Register temp2_reg, - Label* L_success, - Label* L_failure, - bool set_cond_codes = false); - - // Simplified, combined version, good for typical uses. - // Falls through on failure. - void check_klass_subtype(Register sub_klass, - Register super_klass, - Register temp_reg, - Label& L_success); - - // method handles (JSR 292) - Address argument_address(RegisterOrConstant arg_slot, int extra_slot_offset = 0); - - //---- - void set_word_if_not_zero(Register reg); // sets reg to 1 if not zero, otherwise 0 - - // Debugging - - // only if +VerifyOops - // TODO: Make these macros with file and line like sparc version! - void verify_oop(Register reg, const char* s = "broken oop"); - void verify_oop_addr(Address addr, const char * s = "broken oop addr"); - - // TODO: verify method and klass metadata (compare against vptr?) - void _verify_method_ptr(Register reg, const char * msg, const char * file, int line) {} - void _verify_klass_ptr(Register reg, const char * msg, const char * file, int line){} - -#define verify_method_ptr(reg) _verify_method_ptr(reg, "broken method " #reg, __FILE__, __LINE__) -#define verify_klass_ptr(reg) _verify_klass_ptr(reg, "broken klass " #reg, __FILE__, __LINE__) - - // only if +VerifyFPU - void verify_FPU(int stack_depth, const char* s = "illegal FPU state"); - - // prints msg, dumps registers and stops execution - void stop(const char* msg); - - // prints msg and continues - void warn(const char* msg); - - // dumps registers and other state - void print_state(); - - static void debug32(int rdi, int rsi, int rbp, int rsp, int rbx, int rdx, int rcx, int rax, int eip, char* msg); - static void debug64(char* msg, int64_t pc, int64_t regs[]); - static void print_state32(int rdi, int rsi, int rbp, int rsp, int rbx, int rdx, int rcx, int rax, int eip); - static void print_state64(int64_t pc, int64_t regs[]); - - void os_breakpoint(); - - void untested() { stop("untested"); } - - void unimplemented(const char* what = "") { char* b = new char[1024]; jio_snprintf(b, 1024, "unimplemented: %s", what); stop(b); } - - void should_not_reach_here() { stop("should not reach here"); } - - void print_CPU_state(); - - // Stack overflow checking - void bang_stack_with_offset(int offset) { - // stack grows down, caller passes positive offset - assert(offset > 0, "must bang with negative offset"); - movl(Address(rsp, (-offset)), rax); - } - - // Writes to stack successive pages until offset reached to check for - // stack overflow + shadow pages. Also, clobbers tmp - void bang_stack_size(Register size, Register tmp); - - virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr, - Register tmp, - int offset); - - // Support for serializing memory accesses between threads - void serialize_memory(Register thread, Register tmp); - - void verify_tlab(); - - // Biased locking support - // lock_reg and obj_reg must be loaded up with the appropriate values. - // swap_reg must be rax, and is killed. - // tmp_reg is optional. If it is supplied (i.e., != noreg) it will - // be killed; if not supplied, push/pop will be used internally to - // allocate a temporary (inefficient, avoid if possible). - // Optional slow case is for implementations (interpreter and C1) which branch to - // slow case directly. Leaves condition codes set for C2's Fast_Lock node. - // Returns offset of first potentially-faulting instruction for null - // check info (currently consumed only by C1). If - // swap_reg_contains_mark is true then returns -1 as it is assumed - // the calling code has already passed any potential faults. - int biased_locking_enter(Register lock_reg, Register obj_reg, - Register swap_reg, Register tmp_reg, - bool swap_reg_contains_mark, - Label& done, Label* slow_case = NULL, - BiasedLockingCounters* counters = NULL); - void biased_locking_exit (Register obj_reg, Register temp_reg, Label& done); - - - Condition negate_condition(Condition cond); - - // Instructions that use AddressLiteral operands. These instruction can handle 32bit/64bit - // operands. In general the names are modified to avoid hiding the instruction in Assembler - // so that we don't need to implement all the varieties in the Assembler with trivial wrappers - // here in MacroAssembler. The major exception to this rule is call - - // Arithmetics - - - void addptr(Address dst, int32_t src) { LP64_ONLY(addq(dst, src)) NOT_LP64(addl(dst, src)) ; } - void addptr(Address dst, Register src); - - void addptr(Register dst, Address src) { LP64_ONLY(addq(dst, src)) NOT_LP64(addl(dst, src)); } - void addptr(Register dst, int32_t src); - void addptr(Register dst, Register src); - void addptr(Register dst, RegisterOrConstant src) { - if (src.is_constant()) addptr(dst, (int) src.as_constant()); - else addptr(dst, src.as_register()); - } - - void andptr(Register dst, int32_t src); - void andptr(Register src1, Register src2) { LP64_ONLY(andq(src1, src2)) NOT_LP64(andl(src1, src2)) ; } - - void cmp8(AddressLiteral src1, int imm); - - // renamed to drag out the casting of address to int32_t/intptr_t - void cmp32(Register src1, int32_t imm); - - void cmp32(AddressLiteral src1, int32_t imm); - // compare reg - mem, or reg - &mem - void cmp32(Register src1, AddressLiteral src2); - - void cmp32(Register src1, Address src2); - -#ifndef _LP64 - void cmpklass(Address dst, Metadata* obj); - void cmpklass(Register dst, Metadata* obj); - void cmpoop(Address dst, jobject obj); - void cmpoop(Register dst, jobject obj); -#endif // _LP64 - - // NOTE src2 must be the lval. This is NOT an mem-mem compare - void cmpptr(Address src1, AddressLiteral src2); - - void cmpptr(Register src1, AddressLiteral src2); - - void cmpptr(Register src1, Register src2) { LP64_ONLY(cmpq(src1, src2)) NOT_LP64(cmpl(src1, src2)) ; } - void cmpptr(Register src1, Address src2) { LP64_ONLY(cmpq(src1, src2)) NOT_LP64(cmpl(src1, src2)) ; } - // void cmpptr(Address src1, Register src2) { LP64_ONLY(cmpq(src1, src2)) NOT_LP64(cmpl(src1, src2)) ; } - - void cmpptr(Register src1, int32_t src2) { LP64_ONLY(cmpq(src1, src2)) NOT_LP64(cmpl(src1, src2)) ; } - void cmpptr(Address src1, int32_t src2) { LP64_ONLY(cmpq(src1, src2)) NOT_LP64(cmpl(src1, src2)) ; } - - // cmp64 to avoild hiding cmpq - void cmp64(Register src1, AddressLiteral src); - - void cmpxchgptr(Register reg, Address adr); - - void locked_cmpxchgptr(Register reg, AddressLiteral adr); - - - void imulptr(Register dst, Register src) { LP64_ONLY(imulq(dst, src)) NOT_LP64(imull(dst, src)); } - - - void negptr(Register dst) { LP64_ONLY(negq(dst)) NOT_LP64(negl(dst)); } - - void notptr(Register dst) { LP64_ONLY(notq(dst)) NOT_LP64(notl(dst)); } - - void shlptr(Register dst, int32_t shift); - void shlptr(Register dst) { LP64_ONLY(shlq(dst)) NOT_LP64(shll(dst)); } - - void shrptr(Register dst, int32_t shift); - void shrptr(Register dst) { LP64_ONLY(shrq(dst)) NOT_LP64(shrl(dst)); } - - void sarptr(Register dst) { LP64_ONLY(sarq(dst)) NOT_LP64(sarl(dst)); } - void sarptr(Register dst, int32_t src) { LP64_ONLY(sarq(dst, src)) NOT_LP64(sarl(dst, src)); } - - void subptr(Address dst, int32_t src) { LP64_ONLY(subq(dst, src)) NOT_LP64(subl(dst, src)); } - - void subptr(Register dst, Address src) { LP64_ONLY(subq(dst, src)) NOT_LP64(subl(dst, src)); } - void subptr(Register dst, int32_t src); - // Force generation of a 4 byte immediate value even if it fits into 8bit - void subptr_imm32(Register dst, int32_t src); - void subptr(Register dst, Register src); - void subptr(Register dst, RegisterOrConstant src) { - if (src.is_constant()) subptr(dst, (int) src.as_constant()); - else subptr(dst, src.as_register()); - } - - void sbbptr(Address dst, int32_t src) { LP64_ONLY(sbbq(dst, src)) NOT_LP64(sbbl(dst, src)); } - void sbbptr(Register dst, int32_t src) { LP64_ONLY(sbbq(dst, src)) NOT_LP64(sbbl(dst, src)); } - - void xchgptr(Register src1, Register src2) { LP64_ONLY(xchgq(src1, src2)) NOT_LP64(xchgl(src1, src2)) ; } - void xchgptr(Register src1, Address src2) { LP64_ONLY(xchgq(src1, src2)) NOT_LP64(xchgl(src1, src2)) ; } - - void xaddptr(Address src1, Register src2) { LP64_ONLY(xaddq(src1, src2)) NOT_LP64(xaddl(src1, src2)) ; } - - - - // Helper functions for statistics gathering. - // Conditionally (atomically, on MPs) increments passed counter address, preserving condition codes. - void cond_inc32(Condition cond, AddressLiteral counter_addr); - // Unconditional atomic increment. - void atomic_incl(AddressLiteral counter_addr); - - void lea(Register dst, AddressLiteral adr); - void lea(Address dst, AddressLiteral adr); - void lea(Register dst, Address adr) { Assembler::lea(dst, adr); } - - void leal32(Register dst, Address src) { leal(dst, src); } - - // Import other testl() methods from the parent class or else - // they will be hidden by the following overriding declaration. - using Assembler::testl; - void testl(Register dst, AddressLiteral src); - - void orptr(Register dst, Address src) { LP64_ONLY(orq(dst, src)) NOT_LP64(orl(dst, src)); } - void orptr(Register dst, Register src) { LP64_ONLY(orq(dst, src)) NOT_LP64(orl(dst, src)); } - void orptr(Register dst, int32_t src) { LP64_ONLY(orq(dst, src)) NOT_LP64(orl(dst, src)); } - - void testptr(Register src, int32_t imm32) { LP64_ONLY(testq(src, imm32)) NOT_LP64(testl(src, imm32)); } - void testptr(Register src1, Register src2); - - void xorptr(Register dst, Register src) { LP64_ONLY(xorq(dst, src)) NOT_LP64(xorl(dst, src)); } - void xorptr(Register dst, Address src) { LP64_ONLY(xorq(dst, src)) NOT_LP64(xorl(dst, src)); } - - // Calls - - void call(Label& L, relocInfo::relocType rtype); - void call(Register entry); - - // NOTE: this call tranfers to the effective address of entry NOT - // the address contained by entry. This is because this is more natural - // for jumps/calls. - void call(AddressLiteral entry); - - // Emit the CompiledIC call idiom - void ic_call(address entry); - - // Jumps - - // NOTE: these jumps tranfer to the effective address of dst NOT - // the address contained by dst. This is because this is more natural - // for jumps/calls. - void jump(AddressLiteral dst); - void jump_cc(Condition cc, AddressLiteral dst); - - // 32bit can do a case table jump in one instruction but we no longer allow the base - // to be installed in the Address class. This jump will tranfers to the address - // contained in the location described by entry (not the address of entry) - void jump(ArrayAddress entry); - - // Floating - - void andpd(XMMRegister dst, Address src) { Assembler::andpd(dst, src); } - void andpd(XMMRegister dst, AddressLiteral src); - - void andps(XMMRegister dst, XMMRegister src) { Assembler::andps(dst, src); } - void andps(XMMRegister dst, Address src) { Assembler::andps(dst, src); } - void andps(XMMRegister dst, AddressLiteral src); - - void comiss(XMMRegister dst, XMMRegister src) { Assembler::comiss(dst, src); } - void comiss(XMMRegister dst, Address src) { Assembler::comiss(dst, src); } - void comiss(XMMRegister dst, AddressLiteral src); - - void comisd(XMMRegister dst, XMMRegister src) { Assembler::comisd(dst, src); } - void comisd(XMMRegister dst, Address src) { Assembler::comisd(dst, src); } - void comisd(XMMRegister dst, AddressLiteral src); - - void fadd_s(Address src) { Assembler::fadd_s(src); } - void fadd_s(AddressLiteral src) { Assembler::fadd_s(as_Address(src)); } - - void fldcw(Address src) { Assembler::fldcw(src); } - void fldcw(AddressLiteral src); - - void fld_s(int index) { Assembler::fld_s(index); } - void fld_s(Address src) { Assembler::fld_s(src); } - void fld_s(AddressLiteral src); - - void fld_d(Address src) { Assembler::fld_d(src); } - void fld_d(AddressLiteral src); - - void fld_x(Address src) { Assembler::fld_x(src); } - void fld_x(AddressLiteral src); - - void fmul_s(Address src) { Assembler::fmul_s(src); } - void fmul_s(AddressLiteral src) { Assembler::fmul_s(as_Address(src)); } - - void ldmxcsr(Address src) { Assembler::ldmxcsr(src); } - void ldmxcsr(AddressLiteral src); - - // compute pow(x,y) and exp(x) with x86 instructions. Don't cover - // all corner cases and may result in NaN and require fallback to a - // runtime call. - void fast_pow(); - void fast_exp(); - void increase_precision(); - void restore_precision(); - - // computes exp(x). Fallback to runtime call included. - void exp_with_fallback(int num_fpu_regs_in_use) { pow_or_exp(true, num_fpu_regs_in_use); } - // computes pow(x,y). Fallback to runtime call included. - void pow_with_fallback(int num_fpu_regs_in_use) { pow_or_exp(false, num_fpu_regs_in_use); } - -private: - - // call runtime as a fallback for trig functions and pow/exp. - void fp_runtime_fallback(address runtime_entry, int nb_args, int num_fpu_regs_in_use); - - // computes 2^(Ylog2X); Ylog2X in ST(0) - void pow_exp_core_encoding(); - - // computes pow(x,y) or exp(x). Fallback to runtime call included. - void pow_or_exp(bool is_exp, int num_fpu_regs_in_use); - - // these are private because users should be doing movflt/movdbl - - void movss(Address dst, XMMRegister src) { Assembler::movss(dst, src); } - void movss(XMMRegister dst, XMMRegister src) { Assembler::movss(dst, src); } - void movss(XMMRegister dst, Address src) { Assembler::movss(dst, src); } - void movss(XMMRegister dst, AddressLiteral src); - - void movlpd(XMMRegister dst, Address src) {Assembler::movlpd(dst, src); } - void movlpd(XMMRegister dst, AddressLiteral src); - -public: - - void addsd(XMMRegister dst, XMMRegister src) { Assembler::addsd(dst, src); } - void addsd(XMMRegister dst, Address src) { Assembler::addsd(dst, src); } - void addsd(XMMRegister dst, AddressLiteral src); - - void addss(XMMRegister dst, XMMRegister src) { Assembler::addss(dst, src); } - void addss(XMMRegister dst, Address src) { Assembler::addss(dst, src); } - void addss(XMMRegister dst, AddressLiteral src); - - void divsd(XMMRegister dst, XMMRegister src) { Assembler::divsd(dst, src); } - void divsd(XMMRegister dst, Address src) { Assembler::divsd(dst, src); } - void divsd(XMMRegister dst, AddressLiteral src); - - void divss(XMMRegister dst, XMMRegister src) { Assembler::divss(dst, src); } - void divss(XMMRegister dst, Address src) { Assembler::divss(dst, src); } - void divss(XMMRegister dst, AddressLiteral src); - - // Move Unaligned Double Quadword - void movdqu(Address dst, XMMRegister src) { Assembler::movdqu(dst, src); } - void movdqu(XMMRegister dst, Address src) { Assembler::movdqu(dst, src); } - void movdqu(XMMRegister dst, XMMRegister src) { Assembler::movdqu(dst, src); } - void movdqu(XMMRegister dst, AddressLiteral src); - - void movsd(XMMRegister dst, XMMRegister src) { Assembler::movsd(dst, src); } - void movsd(Address dst, XMMRegister src) { Assembler::movsd(dst, src); } - void movsd(XMMRegister dst, Address src) { Assembler::movsd(dst, src); } - void movsd(XMMRegister dst, AddressLiteral src); - - void mulsd(XMMRegister dst, XMMRegister src) { Assembler::mulsd(dst, src); } - void mulsd(XMMRegister dst, Address src) { Assembler::mulsd(dst, src); } - void mulsd(XMMRegister dst, AddressLiteral src); - - void mulss(XMMRegister dst, XMMRegister src) { Assembler::mulss(dst, src); } - void mulss(XMMRegister dst, Address src) { Assembler::mulss(dst, src); } - void mulss(XMMRegister dst, AddressLiteral src); - - 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); - - void sqrtss(XMMRegister dst, XMMRegister src) { Assembler::sqrtss(dst, src); } - void sqrtss(XMMRegister dst, Address src) { Assembler::sqrtss(dst, src); } - void sqrtss(XMMRegister dst, AddressLiteral src); - - void subsd(XMMRegister dst, XMMRegister src) { Assembler::subsd(dst, src); } - void subsd(XMMRegister dst, Address src) { Assembler::subsd(dst, src); } - void subsd(XMMRegister dst, AddressLiteral src); - - void subss(XMMRegister dst, XMMRegister src) { Assembler::subss(dst, src); } - void subss(XMMRegister dst, Address src) { Assembler::subss(dst, src); } - void subss(XMMRegister dst, AddressLiteral src); - - void ucomiss(XMMRegister dst, XMMRegister src) { Assembler::ucomiss(dst, src); } - void ucomiss(XMMRegister dst, Address src) { Assembler::ucomiss(dst, src); } - void ucomiss(XMMRegister dst, AddressLiteral src); - - void ucomisd(XMMRegister dst, XMMRegister src) { Assembler::ucomisd(dst, src); } - void ucomisd(XMMRegister dst, Address src) { Assembler::ucomisd(dst, src); } - void ucomisd(XMMRegister dst, AddressLiteral src); - - // Bitwise Logical XOR of Packed Double-Precision Floating-Point Values - void xorpd(XMMRegister dst, XMMRegister src) { Assembler::xorpd(dst, src); } - void xorpd(XMMRegister dst, Address src) { Assembler::xorpd(dst, src); } - void xorpd(XMMRegister dst, AddressLiteral src); - - // Bitwise Logical XOR of Packed Single-Precision Floating-Point Values - void xorps(XMMRegister dst, XMMRegister src) { Assembler::xorps(dst, src); } - void xorps(XMMRegister dst, Address src) { Assembler::xorps(dst, src); } - void xorps(XMMRegister dst, AddressLiteral src); - - // Shuffle Bytes - void pshufb(XMMRegister dst, XMMRegister src) { Assembler::pshufb(dst, src); } - void pshufb(XMMRegister dst, Address src) { Assembler::pshufb(dst, src); } - void pshufb(XMMRegister dst, AddressLiteral src); - // AVX 3-operands instructions - - void vaddsd(XMMRegister dst, XMMRegister nds, XMMRegister src) { Assembler::vaddsd(dst, nds, src); } - void vaddsd(XMMRegister dst, XMMRegister nds, Address src) { Assembler::vaddsd(dst, nds, src); } - void vaddsd(XMMRegister dst, XMMRegister nds, AddressLiteral src); - - void vaddss(XMMRegister dst, XMMRegister nds, XMMRegister src) { Assembler::vaddss(dst, nds, src); } - void vaddss(XMMRegister dst, XMMRegister nds, Address src) { Assembler::vaddss(dst, nds, src); } - void vaddss(XMMRegister dst, XMMRegister nds, AddressLiteral src); - - void vandpd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { Assembler::vandpd(dst, nds, src, vector256); } - void vandpd(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { Assembler::vandpd(dst, nds, src, vector256); } - void vandpd(XMMRegister dst, XMMRegister nds, AddressLiteral src, bool vector256); - - void vandps(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { Assembler::vandps(dst, nds, src, vector256); } - void vandps(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { Assembler::vandps(dst, nds, src, vector256); } - void vandps(XMMRegister dst, XMMRegister nds, AddressLiteral src, bool vector256); - - void vdivsd(XMMRegister dst, XMMRegister nds, XMMRegister src) { Assembler::vdivsd(dst, nds, src); } - void vdivsd(XMMRegister dst, XMMRegister nds, Address src) { Assembler::vdivsd(dst, nds, src); } - void vdivsd(XMMRegister dst, XMMRegister nds, AddressLiteral src); - - void vdivss(XMMRegister dst, XMMRegister nds, XMMRegister src) { Assembler::vdivss(dst, nds, src); } - void vdivss(XMMRegister dst, XMMRegister nds, Address src) { Assembler::vdivss(dst, nds, src); } - void vdivss(XMMRegister dst, XMMRegister nds, AddressLiteral src); - - void vmulsd(XMMRegister dst, XMMRegister nds, XMMRegister src) { Assembler::vmulsd(dst, nds, src); } - void vmulsd(XMMRegister dst, XMMRegister nds, Address src) { Assembler::vmulsd(dst, nds, src); } - void vmulsd(XMMRegister dst, XMMRegister nds, AddressLiteral src); - - void vmulss(XMMRegister dst, XMMRegister nds, XMMRegister src) { Assembler::vmulss(dst, nds, src); } - void vmulss(XMMRegister dst, XMMRegister nds, Address src) { Assembler::vmulss(dst, nds, src); } - void vmulss(XMMRegister dst, XMMRegister nds, AddressLiteral src); - - void vsubsd(XMMRegister dst, XMMRegister nds, XMMRegister src) { Assembler::vsubsd(dst, nds, src); } - void vsubsd(XMMRegister dst, XMMRegister nds, Address src) { Assembler::vsubsd(dst, nds, src); } - void vsubsd(XMMRegister dst, XMMRegister nds, AddressLiteral src); - - void vsubss(XMMRegister dst, XMMRegister nds, XMMRegister src) { Assembler::vsubss(dst, nds, src); } - void vsubss(XMMRegister dst, XMMRegister nds, Address src) { Assembler::vsubss(dst, nds, src); } - void vsubss(XMMRegister dst, XMMRegister nds, AddressLiteral src); - - // AVX Vector instructions - - void vxorpd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { Assembler::vxorpd(dst, nds, src, vector256); } - void vxorpd(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { Assembler::vxorpd(dst, nds, src, vector256); } - void vxorpd(XMMRegister dst, XMMRegister nds, AddressLiteral src, bool vector256); - - void vxorps(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { Assembler::vxorps(dst, nds, src, vector256); } - void vxorps(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { Assembler::vxorps(dst, nds, src, vector256); } - void vxorps(XMMRegister dst, XMMRegister nds, AddressLiteral src, bool vector256); - - void vpxor(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { - if (UseAVX > 1 || !vector256) // vpxor 256 bit is available only in AVX2 - Assembler::vpxor(dst, nds, src, vector256); - else - Assembler::vxorpd(dst, nds, src, vector256); - } - void vpxor(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { - if (UseAVX > 1 || !vector256) // vpxor 256 bit is available only in AVX2 - Assembler::vpxor(dst, nds, src, vector256); - else - Assembler::vxorpd(dst, nds, src, vector256); - } - - // Move packed integer values from low 128 bit to hign 128 bit in 256 bit vector. - void vinserti128h(XMMRegister dst, XMMRegister nds, XMMRegister src) { - if (UseAVX > 1) // vinserti128h is available only in AVX2 - Assembler::vinserti128h(dst, nds, src); - else - Assembler::vinsertf128h(dst, nds, src); - } - - // Data - - void cmov32( Condition cc, Register dst, Address src); - void cmov32( Condition cc, Register dst, Register src); - - void cmov( Condition cc, Register dst, Register src) { cmovptr(cc, dst, src); } - - void cmovptr(Condition cc, Register dst, Address src) { LP64_ONLY(cmovq(cc, dst, src)) NOT_LP64(cmov32(cc, dst, src)); } - void cmovptr(Condition cc, Register dst, Register src) { LP64_ONLY(cmovq(cc, dst, src)) NOT_LP64(cmov32(cc, dst, src)); } - - void movoop(Register dst, jobject obj); - void movoop(Address dst, jobject obj); - - void mov_metadata(Register dst, Metadata* obj); - void mov_metadata(Address dst, Metadata* obj); - - void movptr(ArrayAddress dst, Register src); - // can this do an lea? - void movptr(Register dst, ArrayAddress src); - - void movptr(Register dst, Address src); - - void movptr(Register dst, AddressLiteral src); - - void movptr(Register dst, intptr_t src); - void movptr(Register dst, Register src); - void movptr(Address dst, intptr_t src); - - void movptr(Address dst, Register src); - - void movptr(Register dst, RegisterOrConstant src) { - if (src.is_constant()) movptr(dst, src.as_constant()); - else movptr(dst, src.as_register()); - } - -#ifdef _LP64 - // Generally the next two are only used for moving NULL - // Although there are situations in initializing the mark word where - // they could be used. They are dangerous. - - // They only exist on LP64 so that int32_t and intptr_t are not the same - // and we have ambiguous declarations. - - void movptr(Address dst, int32_t imm32); - void movptr(Register dst, int32_t imm32); -#endif // _LP64 - - // to avoid hiding movl - void mov32(AddressLiteral dst, Register src); - void mov32(Register dst, AddressLiteral src); - - // to avoid hiding movb - void movbyte(ArrayAddress dst, int src); - - // Import other mov() methods from the parent class or else - // they will be hidden by the following overriding declaration. - using Assembler::movdl; - using Assembler::movq; - void movdl(XMMRegister dst, AddressLiteral src); - void movq(XMMRegister dst, AddressLiteral src); - - // Can push value or effective address - void pushptr(AddressLiteral src); - - void pushptr(Address src) { LP64_ONLY(pushq(src)) NOT_LP64(pushl(src)); } - void popptr(Address src) { LP64_ONLY(popq(src)) NOT_LP64(popl(src)); } - - void pushoop(jobject obj); - void pushklass(Metadata* obj); - - // sign extend as need a l to ptr sized element - void movl2ptr(Register dst, Address src) { LP64_ONLY(movslq(dst, src)) NOT_LP64(movl(dst, src)); } - void movl2ptr(Register dst, Register src) { LP64_ONLY(movslq(dst, src)) NOT_LP64(if (dst != src) movl(dst, src)); } - - // C2 compiled method's prolog code. - void verified_entry(int framesize, bool stack_bang, bool fp_mode_24b); - - // IndexOf strings. - // Small strings are loaded through stack if they cross page boundary. - void string_indexof(Register str1, Register str2, - Register cnt1, Register cnt2, - int int_cnt2, Register result, - XMMRegister vec, Register tmp); - - // IndexOf for constant substrings with size >= 8 elements - // which don't need to be loaded through stack. - void string_indexofC8(Register str1, Register str2, - Register cnt1, Register cnt2, - int int_cnt2, Register result, - XMMRegister vec, Register tmp); - - // Smallest code: we don't need to load through stack, - // check string tail. - - // Compare strings. - void string_compare(Register str1, Register str2, - Register cnt1, Register cnt2, Register result, - XMMRegister vec1); - - // Compare char[] arrays. - void char_arrays_equals(bool is_array_equ, Register ary1, Register ary2, - Register limit, Register result, Register chr, - XMMRegister vec1, XMMRegister vec2); - - // Fill primitive arrays - void generate_fill(BasicType t, bool aligned, - Register to, Register value, Register count, - Register rtmp, XMMRegister xtmp); - -#undef VIRTUAL - -}; - -/** - * class SkipIfEqual: - * - * Instantiating this class will result in assembly code being output that will - * jump around any code emitted between the creation of the instance and it's - * automatic destruction at the end of a scope block, depending on the value of - * the flag passed to the constructor, which will be checked at run-time. - */ -class SkipIfEqual { - private: - MacroAssembler* _masm; - Label _label; - - public: - SkipIfEqual(MacroAssembler*, const bool* flag_addr, bool value); - ~SkipIfEqual(); -}; - -#ifdef ASSERT -inline bool AbstractAssembler::pd_check_instruction_mark() { return true; } -#endif - #endif // CPU_X86_VM_ASSEMBLER_X86_HPP diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.inline.hpp b/hotspot/src/cpu/x86/vm/assembler_x86.inline.hpp index bf299c6da8c..7dbb0950712 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.inline.hpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.inline.hpp @@ -28,48 +28,6 @@ #include "asm/assembler.inline.hpp" #include "asm/codeBuffer.hpp" #include "code/codeCache.hpp" -#include "runtime/handles.inline.hpp" - -inline void MacroAssembler::pd_patch_instruction(address branch, address target) { - unsigned char op = branch[0]; - assert(op == 0xE8 /* call */ || - op == 0xE9 /* jmp */ || - op == 0xEB /* short jmp */ || - (op & 0xF0) == 0x70 /* short jcc */ || - op == 0x0F && (branch[1] & 0xF0) == 0x80 /* jcc */, - "Invalid opcode at patch point"); - - if (op == 0xEB || (op & 0xF0) == 0x70) { - // short offset operators (jmp and jcc) - char* disp = (char*) &branch[1]; - int imm8 = target - (address) &disp[1]; - guarantee(this->is8bit(imm8), "Short forward jump exceeds 8-bit offset"); - *disp = imm8; - } else { - int* disp = (int*) &branch[(op == 0x0F)? 2: 1]; - int imm32 = target - (address) &disp[1]; - *disp = imm32; - } -} - -#ifndef PRODUCT -inline void MacroAssembler::pd_print_patched_instruction(address branch) { - const char* s; - unsigned char op = branch[0]; - if (op == 0xE8) { - s = "call"; - } else if (op == 0xE9 || op == 0xEB) { - s = "jmp"; - } else if ((op & 0xF0) == 0x70) { - s = "jcc"; - } else if (op == 0x0F) { - s = "jcc"; - } else { - s = "????"; - } - tty->print("%s (unresolved)", s); -} -#endif // ndef PRODUCT #ifndef _LP64 inline int Assembler::prefix_and_encode(int reg_enc, bool byteinst) { return reg_enc; } @@ -87,12 +45,6 @@ inline void Assembler::prefixq(Address adr, Register reg) {} inline void Assembler::prefix(Address adr, XMMRegister reg) {} inline void Assembler::prefixq(Address adr, XMMRegister reg) {} -#else -inline void Assembler::emit_long64(jlong x) { - *(jlong*) _code_pos = x; - _code_pos += sizeof(jlong); - code_section()->set_end(_code_pos); -} #endif // _LP64 #endif // CPU_X86_VM_ASSEMBLER_X86_INLINE_HPP diff --git a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp index 684ae866e9c..83146761cd2 100644 --- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp @@ -23,7 +23,8 @@ */ #include "precompiled.hpp" -#include "asm/assembler.hpp" +#include "asm/macroAssembler.hpp" +#include "asm/macroAssembler.inline.hpp" #include "c1/c1_Compilation.hpp" #include "c1/c1_LIRAssembler.hpp" #include "c1/c1_MacroAssembler.hpp" diff --git a/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp b/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp index 64a9463f868..9c3a2f31aeb 100644 --- a/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp +++ b/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp @@ -23,7 +23,7 @@ */ #include "precompiled.hpp" -#include "asm/assembler.hpp" +#include "asm/macroAssembler.hpp" #include "interpreter/bytecodeHistogram.hpp" #include "interpreter/cppInterpreter.hpp" #include "interpreter/interpreter.hpp" @@ -611,8 +611,6 @@ void InterpreterGenerator::generate_counter_overflow(Label* do_continue) { // C++ interpreter only // rsi/r13 - previous interpreter state pointer - const Address size_of_parameters(rbx, Method::size_of_parameters_offset()); - // InterpreterRuntime::frequency_counter_overflow takes one argument // indicating if the counter overflow occurs at a backwards branch (non-NULL bcp). // The call returns the address of the verified entry point for the method or NULL @@ -977,15 +975,16 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) { // to save/restore. address entry_point = __ pc(); - const Address size_of_parameters(rbx, Method::size_of_parameters_offset()); - const Address size_of_locals (rbx, Method::size_of_locals_offset()); + const Address constMethod (rbx, Method::const_offset()); const Address invocation_counter(rbx, Method::invocation_counter_offset() + InvocationCounter::counter_offset()); const Address access_flags (rbx, Method::access_flags_offset()); + const Address size_of_parameters(rcx, ConstMethod::size_of_parameters_offset()); // rsi/r13 == state/locals rdi == prevstate const Register locals = rdi; // get parameter size (always needed) + __ movptr(rcx, constMethod); __ load_unsigned_short(rcx, size_of_parameters); // rbx: Method* @@ -994,6 +993,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) { // for natives the size of locals is zero // compute beginning of parameters /locals + __ lea(locals, Address(rsp, rcx, Address::times_ptr, -wordSize)); // initialize fixed part of activation frame @@ -1107,11 +1107,14 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) { const Register method = rbx; const Register thread = LP64_ONLY(r15_thread) NOT_LP64(rdi); const Register t = InterpreterRuntime::SignatureHandlerGenerator::temp(); // rcx|rscratch1 + const Address constMethod (method, Method::const_offset()); + const Address size_of_parameters(t, ConstMethod::size_of_parameters_offset()); // allocate space for parameters __ movptr(method, STATE(_method)); __ verify_method_ptr(method); - __ load_unsigned_short(t, Address(method, Method::size_of_parameters_offset())); + __ movptr(t, constMethod); + __ load_unsigned_short(t, size_of_parameters); __ shll(t, 2); #ifdef _LP64 __ subptr(rsp, t); @@ -1700,15 +1703,17 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) { // save sender sp __ push(rcx); - const Address size_of_parameters(rbx, Method::size_of_parameters_offset()); - const Address size_of_locals (rbx, Method::size_of_locals_offset()); + const Address constMethod (rbx, Method::const_offset()); const Address access_flags (rbx, Method::access_flags_offset()); + const Address size_of_parameters(rdx, ConstMethod::size_of_parameters_offset()); + const Address size_of_locals (rdx, ConstMethod::size_of_locals_offset()); // const Address monitor_block_top (rbp, frame::interpreter_frame_monitor_block_top_offset * wordSize); // const Address monitor_block_bot (rbp, frame::interpreter_frame_initial_sp_offset * wordSize); // const Address monitor(rbp, frame::interpreter_frame_initial_sp_offset * wordSize - (int)sizeof(BasicObjectLock)); // get parameter size (always needed) + __ movptr(rdx, constMethod); __ load_unsigned_short(rcx, size_of_parameters); // rbx: Method* @@ -1989,7 +1994,9 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) { __ movptr(rbx, STATE(_result._to_call._callee)); // callee left args on top of expression stack, remove them - __ load_unsigned_short(rcx, Address(rbx, Method::size_of_parameters_offset())); + __ movptr(rcx, constMethod); + __ load_unsigned_short(rcx, Address(rcx, ConstMethod::size_of_parameters_offset())); + __ lea(rsp, Address(rsp, rcx, Address::times_ptr)); __ movl(rcx, Address(rbx, Method::result_index_offset())); @@ -2159,7 +2166,9 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) { // Make it look like call_stub calling conventions // Get (potential) receiver - __ load_unsigned_short(rcx, size_of_parameters); // get size of parameters in words + // get size of parameters in words + __ movptr(rcx, constMethod); + __ load_unsigned_short(rcx, Address(rcx, ConstMethod::size_of_parameters_offset())); ExternalAddress recursive(CAST_FROM_FN_PTR(address, RecursiveInterpreterActivation)); __ pushptr(recursive.addr()); // make it look good in the debugger diff --git a/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp b/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp index 55459c09d54..ea8111b9fd7 100644 --- a/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp +++ b/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp @@ -25,6 +25,8 @@ #ifndef CPU_X86_VM_FRAME_X86_INLINE_HPP #define CPU_X86_VM_FRAME_X86_INLINE_HPP +#include "code/codeCache.hpp" + // Inline functions for Intel frames: // Constructors: diff --git a/hotspot/src/cpu/x86/vm/icBuffer_x86.cpp b/hotspot/src/cpu/x86/vm/icBuffer_x86.cpp index ede401d4d9e..62ecc447a13 100644 --- a/hotspot/src/cpu/x86/vm/icBuffer_x86.cpp +++ b/hotspot/src/cpu/x86/vm/icBuffer_x86.cpp @@ -23,8 +23,8 @@ */ #include "precompiled.hpp" -#include "asm/assembler.hpp" -#include "assembler_x86.inline.hpp" +#include "asm/macroAssembler.hpp" +#include "asm/macroAssembler.inline.hpp" #include "code/icBuffer.hpp" #include "gc_interface/collectedHeap.inline.hpp" #include "interpreter/bytecodes.hpp" diff --git a/hotspot/src/cpu/x86/vm/icache_x86.cpp b/hotspot/src/cpu/x86/vm/icache_x86.cpp index 91d4f4da1c1..b9ec2f6d186 100644 --- a/hotspot/src/cpu/x86/vm/icache_x86.cpp +++ b/hotspot/src/cpu/x86/vm/icache_x86.cpp @@ -23,7 +23,7 @@ */ #include "precompiled.hpp" -#include "assembler_x86.inline.hpp" +#include "asm/macroAssembler.hpp" #include "runtime/icache.hpp" #define __ _masm-> diff --git a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.hpp b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.hpp index 7f8463a9a32..6dada56de0d 100644 --- a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.hpp +++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.hpp @@ -25,8 +25,10 @@ #ifndef CPU_X86_VM_INTERP_MASM_X86_32_HPP #define CPU_X86_VM_INTERP_MASM_X86_32_HPP -#include "assembler_x86.inline.hpp" +#include "asm/macroAssembler.hpp" +#include "asm/macroAssembler.inline.hpp" #include "interpreter/invocationCounter.hpp" +#include "runtime/frame.hpp" // This file specializes the assember with interpreter-specific macros diff --git a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.hpp b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.hpp index eb8c4f0a453..66a001366ff 100644 --- a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.hpp +++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.hpp @@ -25,8 +25,10 @@ #ifndef CPU_X86_VM_INTERP_MASM_X86_64_HPP #define CPU_X86_VM_INTERP_MASM_X86_64_HPP -#include "assembler_x86.inline.hpp" +#include "asm/macroAssembler.hpp" +#include "asm/macroAssembler.inline.hpp" #include "interpreter/invocationCounter.hpp" +#include "runtime/frame.hpp" // This file specializes the assember with interpreter-specific macros diff --git a/hotspot/src/cpu/x86/vm/interpreter_x86_32.cpp b/hotspot/src/cpu/x86/vm/interpreter_x86_32.cpp index bed8137e4d5..865801e3de7 100644 --- a/hotspot/src/cpu/x86/vm/interpreter_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/interpreter_x86_32.cpp @@ -23,7 +23,7 @@ */ #include "precompiled.hpp" -#include "asm/assembler.hpp" +#include "asm/macroAssembler.hpp" #include "interpreter/bytecodeHistogram.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/interpreterGenerator.hpp" diff --git a/hotspot/src/cpu/x86/vm/interpreter_x86_64.cpp b/hotspot/src/cpu/x86/vm/interpreter_x86_64.cpp index 3b0a6b445ea..bc5229b997d 100644 --- a/hotspot/src/cpu/x86/vm/interpreter_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/interpreter_x86_64.cpp @@ -23,7 +23,7 @@ */ #include "precompiled.hpp" -#include "asm/assembler.hpp" +#include "asm/macroAssembler.hpp" #include "interpreter/bytecodeHistogram.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/interpreterGenerator.hpp" diff --git a/hotspot/src/cpu/x86/vm/jniFastGetField_x86_32.cpp b/hotspot/src/cpu/x86/vm/jniFastGetField_x86_32.cpp index 57edd9b195b..e4fb943a925 100644 --- a/hotspot/src/cpu/x86/vm/jniFastGetField_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/jniFastGetField_x86_32.cpp @@ -23,7 +23,7 @@ */ #include "precompiled.hpp" -#include "assembler_x86.inline.hpp" +#include "asm/macroAssembler.hpp" #include "memory/resourceArea.hpp" #include "prims/jniFastGetField.hpp" #include "prims/jvm_misc.hpp" diff --git a/hotspot/src/cpu/x86/vm/jniFastGetField_x86_64.cpp b/hotspot/src/cpu/x86/vm/jniFastGetField_x86_64.cpp index 8b0d2e6fa6f..1f523c7621d 100644 --- a/hotspot/src/cpu/x86/vm/jniFastGetField_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/jniFastGetField_x86_64.cpp @@ -23,7 +23,7 @@ */ #include "precompiled.hpp" -#include "assembler_x86.inline.hpp" +#include "asm/macroAssembler.hpp" #include "memory/resourceArea.hpp" #include "prims/jniFastGetField.hpp" #include "prims/jvm_misc.hpp" diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp new file mode 100644 index 00000000000..fa2d7fa4376 --- /dev/null +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp @@ -0,0 +1,6099 @@ +/* + * Copyright (c) 1997, 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. + * + */ + +#include "precompiled.hpp" +#include "asm/assembler.hpp" +#include "asm/assembler.inline.hpp" +#include "compiler/disassembler.hpp" +#include "gc_interface/collectedHeap.inline.hpp" +#include "interpreter/interpreter.hpp" +#include "memory/cardTableModRefBS.hpp" +#include "memory/resourceArea.hpp" +#include "prims/methodHandles.hpp" +#include "runtime/biasedLocking.hpp" +#include "runtime/interfaceSupport.hpp" +#include "runtime/objectMonitor.hpp" +#include "runtime/os.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" +#ifndef SERIALGC +#include "gc_implementation/g1/g1CollectedHeap.inline.hpp" +#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" +#include "gc_implementation/g1/heapRegion.hpp" +#endif + +#ifdef PRODUCT +#define BLOCK_COMMENT(str) /* nothing */ +#define STOP(error) stop(error) +#else +#define BLOCK_COMMENT(str) block_comment(str) +#define STOP(error) block_comment(error); stop(error) +#endif + +#define BIND(label) bind(label); BLOCK_COMMENT(#label ":") + + +#ifdef ASSERT +bool AbstractAssembler::pd_check_instruction_mark() { return true; } +#endif + +static Assembler::Condition reverse[] = { + Assembler::noOverflow /* overflow = 0x0 */ , + Assembler::overflow /* noOverflow = 0x1 */ , + Assembler::aboveEqual /* carrySet = 0x2, below = 0x2 */ , + Assembler::below /* aboveEqual = 0x3, carryClear = 0x3 */ , + Assembler::notZero /* zero = 0x4, equal = 0x4 */ , + Assembler::zero /* notZero = 0x5, notEqual = 0x5 */ , + Assembler::above /* belowEqual = 0x6 */ , + Assembler::belowEqual /* above = 0x7 */ , + Assembler::positive /* negative = 0x8 */ , + Assembler::negative /* positive = 0x9 */ , + Assembler::noParity /* parity = 0xa */ , + Assembler::parity /* noParity = 0xb */ , + Assembler::greaterEqual /* less = 0xc */ , + Assembler::less /* greaterEqual = 0xd */ , + Assembler::greater /* lessEqual = 0xe */ , + Assembler::lessEqual /* greater = 0xf, */ + +}; + + +// Implementation of MacroAssembler + +// First all the versions that have distinct versions depending on 32/64 bit +// Unless the difference is trivial (1 line or so). + +#ifndef _LP64 + +// 32bit versions + +Address MacroAssembler::as_Address(AddressLiteral adr) { + return Address(adr.target(), adr.rspec()); +} + +Address MacroAssembler::as_Address(ArrayAddress adr) { + return Address::make_array(adr); +} + +int MacroAssembler::biased_locking_enter(Register lock_reg, + Register obj_reg, + Register swap_reg, + Register tmp_reg, + bool swap_reg_contains_mark, + Label& done, + Label* slow_case, + BiasedLockingCounters* counters) { + assert(UseBiasedLocking, "why call this otherwise?"); + assert(swap_reg == rax, "swap_reg must be rax, for cmpxchg"); + assert_different_registers(lock_reg, obj_reg, swap_reg); + + if (PrintBiasedLockingStatistics && counters == NULL) + counters = BiasedLocking::counters(); + + bool need_tmp_reg = false; + if (tmp_reg == noreg) { + need_tmp_reg = true; + tmp_reg = lock_reg; + } else { + assert_different_registers(lock_reg, obj_reg, swap_reg, tmp_reg); + } + assert(markOopDesc::age_shift == markOopDesc::lock_bits + markOopDesc::biased_lock_bits, "biased locking makes assumptions about bit layout"); + Address mark_addr (obj_reg, oopDesc::mark_offset_in_bytes()); + Address klass_addr (obj_reg, oopDesc::klass_offset_in_bytes()); + Address saved_mark_addr(lock_reg, 0); + + // Biased locking + // See whether the lock is currently biased toward our thread and + // whether the epoch is still valid + // Note that the runtime guarantees sufficient alignment of JavaThread + // pointers to allow age to be placed into low bits + // First check to see whether biasing is even enabled for this object + Label cas_label; + int null_check_offset = -1; + if (!swap_reg_contains_mark) { + null_check_offset = offset(); + movl(swap_reg, mark_addr); + } + if (need_tmp_reg) { + push(tmp_reg); + } + movl(tmp_reg, swap_reg); + andl(tmp_reg, markOopDesc::biased_lock_mask_in_place); + cmpl(tmp_reg, markOopDesc::biased_lock_pattern); + if (need_tmp_reg) { + pop(tmp_reg); + } + jcc(Assembler::notEqual, cas_label); + // The bias pattern is present in the object's header. Need to check + // whether the bias owner and the epoch are both still current. + // Note that because there is no current thread register on x86 we + // need to store off the mark word we read out of the object to + // avoid reloading it and needing to recheck invariants below. This + // store is unfortunate but it makes the overall code shorter and + // simpler. + movl(saved_mark_addr, swap_reg); + if (need_tmp_reg) { + push(tmp_reg); + } + get_thread(tmp_reg); + xorl(swap_reg, tmp_reg); + if (swap_reg_contains_mark) { + null_check_offset = offset(); + } + movl(tmp_reg, klass_addr); + xorl(swap_reg, Address(tmp_reg, Klass::prototype_header_offset())); + andl(swap_reg, ~((int) markOopDesc::age_mask_in_place)); + if (need_tmp_reg) { + pop(tmp_reg); + } + if (counters != NULL) { + cond_inc32(Assembler::zero, + ExternalAddress((address)counters->biased_lock_entry_count_addr())); + } + jcc(Assembler::equal, done); + + Label try_revoke_bias; + Label try_rebias; + + // At this point we know that the header has the bias pattern and + // that we are not the bias owner in the current epoch. We need to + // figure out more details about the state of the header in order to + // know what operations can be legally performed on the object's + // header. + + // If the low three bits in the xor result aren't clear, that means + // the prototype header is no longer biased and we have to revoke + // the bias on this object. + testl(swap_reg, markOopDesc::biased_lock_mask_in_place); + jcc(Assembler::notZero, try_revoke_bias); + + // Biasing is still enabled for this data type. See whether the + // epoch of the current bias is still valid, meaning that the epoch + // bits of the mark word are equal to the epoch bits of the + // prototype header. (Note that the prototype header's epoch bits + // only change at a safepoint.) If not, attempt to rebias the object + // toward the current thread. Note that we must be absolutely sure + // that the current epoch is invalid in order to do this because + // otherwise the manipulations it performs on the mark word are + // illegal. + testl(swap_reg, markOopDesc::epoch_mask_in_place); + jcc(Assembler::notZero, try_rebias); + + // The epoch of the current bias is still valid but we know nothing + // about the owner; it might be set or it might be clear. Try to + // acquire the bias of the object using an atomic operation. If this + // fails we will go in to the runtime to revoke the object's bias. + // Note that we first construct the presumed unbiased header so we + // don't accidentally blow away another thread's valid bias. + movl(swap_reg, saved_mark_addr); + andl(swap_reg, + markOopDesc::biased_lock_mask_in_place | markOopDesc::age_mask_in_place | markOopDesc::epoch_mask_in_place); + if (need_tmp_reg) { + push(tmp_reg); + } + get_thread(tmp_reg); + orl(tmp_reg, swap_reg); + if (os::is_MP()) { + lock(); + } + cmpxchgptr(tmp_reg, Address(obj_reg, 0)); + if (need_tmp_reg) { + pop(tmp_reg); + } + // If the biasing toward our thread failed, this means that + // another thread succeeded in biasing it toward itself and we + // need to revoke that bias. The revocation will occur in the + // interpreter runtime in the slow case. + if (counters != NULL) { + cond_inc32(Assembler::zero, + ExternalAddress((address)counters->anonymously_biased_lock_entry_count_addr())); + } + if (slow_case != NULL) { + jcc(Assembler::notZero, *slow_case); + } + jmp(done); + + bind(try_rebias); + // At this point we know the epoch has expired, meaning that the + // current "bias owner", if any, is actually invalid. Under these + // circumstances _only_, we are allowed to use the current header's + // value as the comparison value when doing the cas to acquire the + // bias in the current epoch. In other words, we allow transfer of + // the bias from one thread to another directly in this situation. + // + // FIXME: due to a lack of registers we currently blow away the age + // bits in this situation. Should attempt to preserve them. + if (need_tmp_reg) { + push(tmp_reg); + } + get_thread(tmp_reg); + movl(swap_reg, klass_addr); + orl(tmp_reg, Address(swap_reg, Klass::prototype_header_offset())); + movl(swap_reg, saved_mark_addr); + if (os::is_MP()) { + lock(); + } + cmpxchgptr(tmp_reg, Address(obj_reg, 0)); + if (need_tmp_reg) { + pop(tmp_reg); + } + // If the biasing toward our thread failed, then another thread + // succeeded in biasing it toward itself and we need to revoke that + // bias. The revocation will occur in the runtime in the slow case. + if (counters != NULL) { + cond_inc32(Assembler::zero, + ExternalAddress((address)counters->rebiased_lock_entry_count_addr())); + } + if (slow_case != NULL) { + jcc(Assembler::notZero, *slow_case); + } + jmp(done); + + bind(try_revoke_bias); + // The prototype mark in the klass doesn't have the bias bit set any + // more, indicating that objects of this data type are not supposed + // to be biased any more. We are going to try to reset the mark of + // this object to the prototype value and fall through to the + // CAS-based locking scheme. Note that if our CAS fails, it means + // that another thread raced us for the privilege of revoking the + // bias of this particular object, so it's okay to continue in the + // normal locking code. + // + // FIXME: due to a lack of registers we currently blow away the age + // bits in this situation. Should attempt to preserve them. + movl(swap_reg, saved_mark_addr); + if (need_tmp_reg) { + push(tmp_reg); + } + movl(tmp_reg, klass_addr); + movl(tmp_reg, Address(tmp_reg, Klass::prototype_header_offset())); + if (os::is_MP()) { + lock(); + } + cmpxchgptr(tmp_reg, Address(obj_reg, 0)); + if (need_tmp_reg) { + pop(tmp_reg); + } + // Fall through to the normal CAS-based lock, because no matter what + // the result of the above CAS, some thread must have succeeded in + // removing the bias bit from the object's header. + if (counters != NULL) { + cond_inc32(Assembler::zero, + ExternalAddress((address)counters->revoked_lock_entry_count_addr())); + } + + bind(cas_label); + + return null_check_offset; +} +void MacroAssembler::call_VM_leaf_base(address entry_point, + int number_of_arguments) { + call(RuntimeAddress(entry_point)); + increment(rsp, number_of_arguments * wordSize); +} + +void MacroAssembler::cmpklass(Address src1, Metadata* obj) { + cmp_literal32(src1, (int32_t)obj, metadata_Relocation::spec_for_immediate()); +} + +void MacroAssembler::cmpklass(Register src1, Metadata* obj) { + cmp_literal32(src1, (int32_t)obj, metadata_Relocation::spec_for_immediate()); +} + +void MacroAssembler::cmpoop(Address src1, jobject obj) { + cmp_literal32(src1, (int32_t)obj, oop_Relocation::spec_for_immediate()); +} + +void MacroAssembler::cmpoop(Register src1, jobject obj) { + cmp_literal32(src1, (int32_t)obj, oop_Relocation::spec_for_immediate()); +} + +void MacroAssembler::extend_sign(Register hi, Register lo) { + // According to Intel Doc. AP-526, "Integer Divide", p.18. + if (VM_Version::is_P6() && hi == rdx && lo == rax) { + cdql(); + } else { + movl(hi, lo); + sarl(hi, 31); + } +} + +void MacroAssembler::jC2(Register tmp, Label& L) { + // set parity bit if FPU flag C2 is set (via rax) + save_rax(tmp); + fwait(); fnstsw_ax(); + sahf(); + restore_rax(tmp); + // branch + jcc(Assembler::parity, L); +} + +void MacroAssembler::jnC2(Register tmp, Label& L) { + // set parity bit if FPU flag C2 is set (via rax) + save_rax(tmp); + fwait(); fnstsw_ax(); + sahf(); + restore_rax(tmp); + // branch + jcc(Assembler::noParity, L); +} + +// 32bit can do a case table jump in one instruction but we no longer allow the base +// to be installed in the Address class +void MacroAssembler::jump(ArrayAddress entry) { + jmp(as_Address(entry)); +} + +// Note: y_lo will be destroyed +void MacroAssembler::lcmp2int(Register x_hi, Register x_lo, Register y_hi, Register y_lo) { + // Long compare for Java (semantics as described in JVM spec.) + Label high, low, done; + + cmpl(x_hi, y_hi); + jcc(Assembler::less, low); + jcc(Assembler::greater, high); + // x_hi is the return register + xorl(x_hi, x_hi); + cmpl(x_lo, y_lo); + jcc(Assembler::below, low); + jcc(Assembler::equal, done); + + bind(high); + xorl(x_hi, x_hi); + increment(x_hi); + jmp(done); + + bind(low); + xorl(x_hi, x_hi); + decrementl(x_hi); + + bind(done); +} + +void MacroAssembler::lea(Register dst, AddressLiteral src) { + mov_literal32(dst, (int32_t)src.target(), src.rspec()); +} + +void MacroAssembler::lea(Address dst, AddressLiteral adr) { + // leal(dst, as_Address(adr)); + // see note in movl as to why we must use a move + mov_literal32(dst, (int32_t) adr.target(), adr.rspec()); +} + +void MacroAssembler::leave() { + mov(rsp, rbp); + pop(rbp); +} + +void MacroAssembler::lmul(int x_rsp_offset, int y_rsp_offset) { + // Multiplication of two Java long values stored on the stack + // as illustrated below. Result is in rdx:rax. + // + // rsp ---> [ ?? ] \ \ + // .... | y_rsp_offset | + // [ y_lo ] / (in bytes) | x_rsp_offset + // [ y_hi ] | (in bytes) + // .... | + // [ x_lo ] / + // [ x_hi ] + // .... + // + // Basic idea: lo(result) = lo(x_lo * y_lo) + // hi(result) = hi(x_lo * y_lo) + lo(x_hi * y_lo) + lo(x_lo * y_hi) + Address x_hi(rsp, x_rsp_offset + wordSize); Address x_lo(rsp, x_rsp_offset); + Address y_hi(rsp, y_rsp_offset + wordSize); Address y_lo(rsp, y_rsp_offset); + Label quick; + // load x_hi, y_hi and check if quick + // multiplication is possible + movl(rbx, x_hi); + movl(rcx, y_hi); + movl(rax, rbx); + orl(rbx, rcx); // rbx, = 0 <=> x_hi = 0 and y_hi = 0 + jcc(Assembler::zero, quick); // if rbx, = 0 do quick multiply + // do full multiplication + // 1st step + mull(y_lo); // x_hi * y_lo + movl(rbx, rax); // save lo(x_hi * y_lo) in rbx, + // 2nd step + movl(rax, x_lo); + mull(rcx); // x_lo * y_hi + addl(rbx, rax); // add lo(x_lo * y_hi) to rbx, + // 3rd step + bind(quick); // note: rbx, = 0 if quick multiply! + movl(rax, x_lo); + mull(y_lo); // x_lo * y_lo + addl(rdx, rbx); // correct hi(x_lo * y_lo) +} + +void MacroAssembler::lneg(Register hi, Register lo) { + negl(lo); + adcl(hi, 0); + negl(hi); +} + +void MacroAssembler::lshl(Register hi, Register lo) { + // Java shift left long support (semantics as described in JVM spec., p.305) + // (basic idea for shift counts s >= n: x << s == (x << n) << (s - n)) + // shift value is in rcx ! + assert(hi != rcx, "must not use rcx"); + assert(lo != rcx, "must not use rcx"); + const Register s = rcx; // shift count + const int n = BitsPerWord; + Label L; + andl(s, 0x3f); // s := s & 0x3f (s < 0x40) + cmpl(s, n); // if (s < n) + jcc(Assembler::less, L); // else (s >= n) + movl(hi, lo); // x := x << n + xorl(lo, lo); + // Note: subl(s, n) is not needed since the Intel shift instructions work rcx mod n! + bind(L); // s (mod n) < n + shldl(hi, lo); // x := x << s + shll(lo); +} + + +void MacroAssembler::lshr(Register hi, Register lo, bool sign_extension) { + // Java shift right long support (semantics as described in JVM spec., p.306 & p.310) + // (basic idea for shift counts s >= n: x >> s == (x >> n) >> (s - n)) + assert(hi != rcx, "must not use rcx"); + assert(lo != rcx, "must not use rcx"); + const Register s = rcx; // shift count + const int n = BitsPerWord; + Label L; + andl(s, 0x3f); // s := s & 0x3f (s < 0x40) + cmpl(s, n); // if (s < n) + jcc(Assembler::less, L); // else (s >= n) + movl(lo, hi); // x := x >> n + if (sign_extension) sarl(hi, 31); + else xorl(hi, hi); + // Note: subl(s, n) is not needed since the Intel shift instructions work rcx mod n! + bind(L); // s (mod n) < n + shrdl(lo, hi); // x := x >> s + if (sign_extension) sarl(hi); + else shrl(hi); +} + +void MacroAssembler::movoop(Register dst, jobject obj) { + mov_literal32(dst, (int32_t)obj, oop_Relocation::spec_for_immediate()); +} + +void MacroAssembler::movoop(Address dst, jobject obj) { + mov_literal32(dst, (int32_t)obj, oop_Relocation::spec_for_immediate()); +} + +void MacroAssembler::mov_metadata(Register dst, Metadata* obj) { + mov_literal32(dst, (int32_t)obj, metadata_Relocation::spec_for_immediate()); +} + +void MacroAssembler::mov_metadata(Address dst, Metadata* obj) { + mov_literal32(dst, (int32_t)obj, metadata_Relocation::spec_for_immediate()); +} + +void MacroAssembler::movptr(Register dst, AddressLiteral src) { + if (src.is_lval()) { + mov_literal32(dst, (intptr_t)src.target(), src.rspec()); + } else { + movl(dst, as_Address(src)); + } +} + +void MacroAssembler::movptr(ArrayAddress dst, Register src) { + movl(as_Address(dst), src); +} + +void MacroAssembler::movptr(Register dst, ArrayAddress src) { + movl(dst, as_Address(src)); +} + +// src should NEVER be a real pointer. Use AddressLiteral for true pointers +void MacroAssembler::movptr(Address dst, intptr_t src) { + movl(dst, src); +} + + +void MacroAssembler::pop_callee_saved_registers() { + pop(rcx); + pop(rdx); + pop(rdi); + pop(rsi); +} + +void MacroAssembler::pop_fTOS() { + fld_d(Address(rsp, 0)); + addl(rsp, 2 * wordSize); +} + +void MacroAssembler::push_callee_saved_registers() { + push(rsi); + push(rdi); + push(rdx); + push(rcx); +} + +void MacroAssembler::push_fTOS() { + subl(rsp, 2 * wordSize); + fstp_d(Address(rsp, 0)); +} + + +void MacroAssembler::pushoop(jobject obj) { + push_literal32((int32_t)obj, oop_Relocation::spec_for_immediate()); +} + +void MacroAssembler::pushklass(Metadata* obj) { + push_literal32((int32_t)obj, metadata_Relocation::spec_for_immediate()); +} + +void MacroAssembler::pushptr(AddressLiteral src) { + if (src.is_lval()) { + push_literal32((int32_t)src.target(), src.rspec()); + } else { + pushl(as_Address(src)); + } +} + +void MacroAssembler::set_word_if_not_zero(Register dst) { + xorl(dst, dst); + set_byte_if_not_zero(dst); +} + +static void pass_arg0(MacroAssembler* masm, Register arg) { + masm->push(arg); +} + +static void pass_arg1(MacroAssembler* masm, Register arg) { + masm->push(arg); +} + +static void pass_arg2(MacroAssembler* masm, Register arg) { + masm->push(arg); +} + +static void pass_arg3(MacroAssembler* masm, Register arg) { + masm->push(arg); +} + +#ifndef PRODUCT +extern "C" void findpc(intptr_t x); +#endif + +void MacroAssembler::debug32(int rdi, int rsi, int rbp, int rsp, int rbx, int rdx, int rcx, int rax, int eip, char* msg) { + // In order to get locks to work, we need to fake a in_VM state + JavaThread* thread = JavaThread::current(); + JavaThreadState saved_state = thread->thread_state(); + thread->set_thread_state(_thread_in_vm); + if (ShowMessageBoxOnError) { + JavaThread* thread = JavaThread::current(); + JavaThreadState saved_state = thread->thread_state(); + thread->set_thread_state(_thread_in_vm); + if (CountBytecodes || TraceBytecodes || StopInterpreterAt) { + ttyLocker ttyl; + BytecodeCounter::print(); + } + // To see where a verify_oop failed, get $ebx+40/X for this frame. + // This is the value of eip which points to where verify_oop will return. + if (os::message_box(msg, "Execution stopped, print registers?")) { + print_state32(rdi, rsi, rbp, rsp, rbx, rdx, rcx, rax, eip); + BREAKPOINT; + } + } else { + ttyLocker ttyl; + ::tty->print_cr("=============== DEBUG MESSAGE: %s ================\n", msg); + } + // Don't assert holding the ttyLock + assert(false, err_msg("DEBUG MESSAGE: %s", msg)); + ThreadStateTransition::transition(thread, _thread_in_vm, saved_state); +} + +void MacroAssembler::print_state32(int rdi, int rsi, int rbp, int rsp, int rbx, int rdx, int rcx, int rax, int eip) { + ttyLocker ttyl; + FlagSetting fs(Debugging, true); + tty->print_cr("eip = 0x%08x", eip); +#ifndef PRODUCT + if ((WizardMode || Verbose) && PrintMiscellaneous) { + tty->cr(); + findpc(eip); + tty->cr(); + } +#endif +#define PRINT_REG(rax) \ + { tty->print("%s = ", #rax); os::print_location(tty, rax); } + PRINT_REG(rax); + PRINT_REG(rbx); + PRINT_REG(rcx); + PRINT_REG(rdx); + PRINT_REG(rdi); + PRINT_REG(rsi); + PRINT_REG(rbp); + PRINT_REG(rsp); +#undef PRINT_REG + // Print some words near top of staack. + int* dump_sp = (int*) rsp; + for (int col1 = 0; col1 < 8; col1++) { + tty->print("(rsp+0x%03x) 0x%08x: ", (int)((intptr_t)dump_sp - (intptr_t)rsp), (intptr_t)dump_sp); + os::print_location(tty, *dump_sp++); + } + for (int row = 0; row < 16; row++) { + tty->print("(rsp+0x%03x) 0x%08x: ", (int)((intptr_t)dump_sp - (intptr_t)rsp), (intptr_t)dump_sp); + for (int col = 0; col < 8; col++) { + tty->print(" 0x%08x", *dump_sp++); + } + tty->cr(); + } + // Print some instructions around pc: + Disassembler::decode((address)eip-64, (address)eip); + tty->print_cr("--------"); + Disassembler::decode((address)eip, (address)eip+32); +} + +void MacroAssembler::stop(const char* msg) { + ExternalAddress message((address)msg); + // push address of message + pushptr(message.addr()); + { Label L; call(L, relocInfo::none); bind(L); } // push eip + pusha(); // push registers + call(RuntimeAddress(CAST_FROM_FN_PTR(address, MacroAssembler::debug32))); + hlt(); +} + +void MacroAssembler::warn(const char* msg) { + push_CPU_state(); + + ExternalAddress message((address) msg); + // push address of message + pushptr(message.addr()); + + call(RuntimeAddress(CAST_FROM_FN_PTR(address, warning))); + addl(rsp, wordSize); // discard argument + pop_CPU_state(); +} + +void MacroAssembler::print_state() { + { Label L; call(L, relocInfo::none); bind(L); } // push eip + pusha(); // push registers + + push_CPU_state(); + call(RuntimeAddress(CAST_FROM_FN_PTR(address, MacroAssembler::print_state32))); + pop_CPU_state(); + + popa(); + addl(rsp, wordSize); +} + +#else // _LP64 + +// 64 bit versions + +Address MacroAssembler::as_Address(AddressLiteral adr) { + // amd64 always does this as a pc-rel + // we can be absolute or disp based on the instruction type + // jmp/call are displacements others are absolute + assert(!adr.is_lval(), "must be rval"); + assert(reachable(adr), "must be"); + return Address((int32_t)(intptr_t)(adr.target() - pc()), adr.target(), adr.reloc()); + +} + +Address MacroAssembler::as_Address(ArrayAddress adr) { + AddressLiteral base = adr.base(); + lea(rscratch1, base); + Address index = adr.index(); + assert(index._disp == 0, "must not have disp"); // maybe it can? + Address array(rscratch1, index._index, index._scale, index._disp); + return array; +} + +int MacroAssembler::biased_locking_enter(Register lock_reg, + Register obj_reg, + Register swap_reg, + Register tmp_reg, + bool swap_reg_contains_mark, + Label& done, + Label* slow_case, + BiasedLockingCounters* counters) { + assert(UseBiasedLocking, "why call this otherwise?"); + assert(swap_reg == rax, "swap_reg must be rax for cmpxchgq"); + assert(tmp_reg != noreg, "tmp_reg must be supplied"); + assert_different_registers(lock_reg, obj_reg, swap_reg, tmp_reg); + assert(markOopDesc::age_shift == markOopDesc::lock_bits + markOopDesc::biased_lock_bits, "biased locking makes assumptions about bit layout"); + Address mark_addr (obj_reg, oopDesc::mark_offset_in_bytes()); + Address saved_mark_addr(lock_reg, 0); + + if (PrintBiasedLockingStatistics && counters == NULL) + counters = BiasedLocking::counters(); + + // Biased locking + // See whether the lock is currently biased toward our thread and + // whether the epoch is still valid + // Note that the runtime guarantees sufficient alignment of JavaThread + // pointers to allow age to be placed into low bits + // First check to see whether biasing is even enabled for this object + Label cas_label; + int null_check_offset = -1; + if (!swap_reg_contains_mark) { + null_check_offset = offset(); + movq(swap_reg, mark_addr); + } + movq(tmp_reg, swap_reg); + andq(tmp_reg, markOopDesc::biased_lock_mask_in_place); + cmpq(tmp_reg, markOopDesc::biased_lock_pattern); + jcc(Assembler::notEqual, cas_label); + // The bias pattern is present in the object's header. Need to check + // whether the bias owner and the epoch are both still current. + load_prototype_header(tmp_reg, obj_reg); + orq(tmp_reg, r15_thread); + xorq(tmp_reg, swap_reg); + andq(tmp_reg, ~((int) markOopDesc::age_mask_in_place)); + if (counters != NULL) { + cond_inc32(Assembler::zero, + ExternalAddress((address) counters->anonymously_biased_lock_entry_count_addr())); + } + jcc(Assembler::equal, done); + + Label try_revoke_bias; + Label try_rebias; + + // At this point we know that the header has the bias pattern and + // that we are not the bias owner in the current epoch. We need to + // figure out more details about the state of the header in order to + // know what operations can be legally performed on the object's + // header. + + // If the low three bits in the xor result aren't clear, that means + // the prototype header is no longer biased and we have to revoke + // the bias on this object. + testq(tmp_reg, markOopDesc::biased_lock_mask_in_place); + jcc(Assembler::notZero, try_revoke_bias); + + // Biasing is still enabled for this data type. See whether the + // epoch of the current bias is still valid, meaning that the epoch + // bits of the mark word are equal to the epoch bits of the + // prototype header. (Note that the prototype header's epoch bits + // only change at a safepoint.) If not, attempt to rebias the object + // toward the current thread. Note that we must be absolutely sure + // that the current epoch is invalid in order to do this because + // otherwise the manipulations it performs on the mark word are + // illegal. + testq(tmp_reg, markOopDesc::epoch_mask_in_place); + jcc(Assembler::notZero, try_rebias); + + // The epoch of the current bias is still valid but we know nothing + // about the owner; it might be set or it might be clear. Try to + // acquire the bias of the object using an atomic operation. If this + // fails we will go in to the runtime to revoke the object's bias. + // Note that we first construct the presumed unbiased header so we + // don't accidentally blow away another thread's valid bias. + andq(swap_reg, + markOopDesc::biased_lock_mask_in_place | markOopDesc::age_mask_in_place | markOopDesc::epoch_mask_in_place); + movq(tmp_reg, swap_reg); + orq(tmp_reg, r15_thread); + if (os::is_MP()) { + lock(); + } + cmpxchgq(tmp_reg, Address(obj_reg, 0)); + // If the biasing toward our thread failed, this means that + // another thread succeeded in biasing it toward itself and we + // need to revoke that bias. The revocation will occur in the + // interpreter runtime in the slow case. + if (counters != NULL) { + cond_inc32(Assembler::zero, + ExternalAddress((address) counters->anonymously_biased_lock_entry_count_addr())); + } + if (slow_case != NULL) { + jcc(Assembler::notZero, *slow_case); + } + jmp(done); + + bind(try_rebias); + // At this point we know the epoch has expired, meaning that the + // current "bias owner", if any, is actually invalid. Under these + // circumstances _only_, we are allowed to use the current header's + // value as the comparison value when doing the cas to acquire the + // bias in the current epoch. In other words, we allow transfer of + // the bias from one thread to another directly in this situation. + // + // FIXME: due to a lack of registers we currently blow away the age + // bits in this situation. Should attempt to preserve them. + load_prototype_header(tmp_reg, obj_reg); + orq(tmp_reg, r15_thread); + if (os::is_MP()) { + lock(); + } + cmpxchgq(tmp_reg, Address(obj_reg, 0)); + // If the biasing toward our thread failed, then another thread + // succeeded in biasing it toward itself and we need to revoke that + // bias. The revocation will occur in the runtime in the slow case. + if (counters != NULL) { + cond_inc32(Assembler::zero, + ExternalAddress((address) counters->rebiased_lock_entry_count_addr())); + } + if (slow_case != NULL) { + jcc(Assembler::notZero, *slow_case); + } + jmp(done); + + bind(try_revoke_bias); + // The prototype mark in the klass doesn't have the bias bit set any + // more, indicating that objects of this data type are not supposed + // to be biased any more. We are going to try to reset the mark of + // this object to the prototype value and fall through to the + // CAS-based locking scheme. Note that if our CAS fails, it means + // that another thread raced us for the privilege of revoking the + // bias of this particular object, so it's okay to continue in the + // normal locking code. + // + // FIXME: due to a lack of registers we currently blow away the age + // bits in this situation. Should attempt to preserve them. + load_prototype_header(tmp_reg, obj_reg); + if (os::is_MP()) { + lock(); + } + cmpxchgq(tmp_reg, Address(obj_reg, 0)); + // Fall through to the normal CAS-based lock, because no matter what + // the result of the above CAS, some thread must have succeeded in + // removing the bias bit from the object's header. + if (counters != NULL) { + cond_inc32(Assembler::zero, + ExternalAddress((address) counters->revoked_lock_entry_count_addr())); + } + + bind(cas_label); + + return null_check_offset; +} + +void MacroAssembler::call_VM_leaf_base(address entry_point, int num_args) { + Label L, E; + +#ifdef _WIN64 + // Windows always allocates space for it's register args + assert(num_args <= 4, "only register arguments supported"); + subq(rsp, frame::arg_reg_save_area_bytes); +#endif + + // Align stack if necessary + testl(rsp, 15); + jcc(Assembler::zero, L); + + subq(rsp, 8); + { + call(RuntimeAddress(entry_point)); + } + addq(rsp, 8); + jmp(E); + + bind(L); + { + call(RuntimeAddress(entry_point)); + } + + bind(E); + +#ifdef _WIN64 + // restore stack pointer + addq(rsp, frame::arg_reg_save_area_bytes); +#endif + +} + +void MacroAssembler::cmp64(Register src1, AddressLiteral src2) { + assert(!src2.is_lval(), "should use cmpptr"); + + if (reachable(src2)) { + cmpq(src1, as_Address(src2)); + } else { + lea(rscratch1, src2); + Assembler::cmpq(src1, Address(rscratch1, 0)); + } +} + +int MacroAssembler::corrected_idivq(Register reg) { + // Full implementation of Java ldiv and lrem; checks for special + // case as described in JVM spec., p.243 & p.271. The function + // returns the (pc) offset of the idivl instruction - may be needed + // for implicit exceptions. + // + // normal case special case + // + // input : rax: dividend min_long + // reg: divisor (may not be eax/edx) -1 + // + // output: rax: quotient (= rax idiv reg) min_long + // rdx: remainder (= rax irem reg) 0 + assert(reg != rax && reg != rdx, "reg cannot be rax or rdx register"); + static const int64_t min_long = 0x8000000000000000; + Label normal_case, special_case; + + // check for special case + cmp64(rax, ExternalAddress((address) &min_long)); + jcc(Assembler::notEqual, normal_case); + xorl(rdx, rdx); // prepare rdx for possible special case (where + // remainder = 0) + cmpq(reg, -1); + jcc(Assembler::equal, special_case); + + // handle normal case + bind(normal_case); + cdqq(); + int idivq_offset = offset(); + idivq(reg); + + // normal and special case exit + bind(special_case); + + return idivq_offset; +} + +void MacroAssembler::decrementq(Register reg, int value) { + if (value == min_jint) { subq(reg, value); return; } + if (value < 0) { incrementq(reg, -value); return; } + if (value == 0) { ; return; } + if (value == 1 && UseIncDec) { decq(reg) ; return; } + /* else */ { subq(reg, value) ; return; } +} + +void MacroAssembler::decrementq(Address dst, int value) { + if (value == min_jint) { subq(dst, value); return; } + if (value < 0) { incrementq(dst, -value); return; } + if (value == 0) { ; return; } + if (value == 1 && UseIncDec) { decq(dst) ; return; } + /* else */ { subq(dst, value) ; return; } +} + +void MacroAssembler::incrementq(Register reg, int value) { + if (value == min_jint) { addq(reg, value); return; } + if (value < 0) { decrementq(reg, -value); return; } + if (value == 0) { ; return; } + if (value == 1 && UseIncDec) { incq(reg) ; return; } + /* else */ { addq(reg, value) ; return; } +} + +void MacroAssembler::incrementq(Address dst, int value) { + if (value == min_jint) { addq(dst, value); return; } + if (value < 0) { decrementq(dst, -value); return; } + if (value == 0) { ; return; } + if (value == 1 && UseIncDec) { incq(dst) ; return; } + /* else */ { addq(dst, value) ; return; } +} + +// 32bit can do a case table jump in one instruction but we no longer allow the base +// to be installed in the Address class +void MacroAssembler::jump(ArrayAddress entry) { + lea(rscratch1, entry.base()); + Address dispatch = entry.index(); + assert(dispatch._base == noreg, "must be"); + dispatch._base = rscratch1; + jmp(dispatch); +} + +void MacroAssembler::lcmp2int(Register x_hi, Register x_lo, Register y_hi, Register y_lo) { + ShouldNotReachHere(); // 64bit doesn't use two regs + cmpq(x_lo, y_lo); +} + +void MacroAssembler::lea(Register dst, AddressLiteral src) { + mov_literal64(dst, (intptr_t)src.target(), src.rspec()); +} + +void MacroAssembler::lea(Address dst, AddressLiteral adr) { + mov_literal64(rscratch1, (intptr_t)adr.target(), adr.rspec()); + movptr(dst, rscratch1); +} + +void MacroAssembler::leave() { + // %%% is this really better? Why not on 32bit too? + emit_byte(0xC9); // LEAVE +} + +void MacroAssembler::lneg(Register hi, Register lo) { + ShouldNotReachHere(); // 64bit doesn't use two regs + negq(lo); +} + +void MacroAssembler::movoop(Register dst, jobject obj) { + mov_literal64(dst, (intptr_t)obj, oop_Relocation::spec_for_immediate()); +} + +void MacroAssembler::movoop(Address dst, jobject obj) { + mov_literal64(rscratch1, (intptr_t)obj, oop_Relocation::spec_for_immediate()); + movq(dst, rscratch1); +} + +void MacroAssembler::mov_metadata(Register dst, Metadata* obj) { + mov_literal64(dst, (intptr_t)obj, metadata_Relocation::spec_for_immediate()); +} + +void MacroAssembler::mov_metadata(Address dst, Metadata* obj) { + mov_literal64(rscratch1, (intptr_t)obj, metadata_Relocation::spec_for_immediate()); + movq(dst, rscratch1); +} + +void MacroAssembler::movptr(Register dst, AddressLiteral src) { + if (src.is_lval()) { + mov_literal64(dst, (intptr_t)src.target(), src.rspec()); + } else { + if (reachable(src)) { + movq(dst, as_Address(src)); + } else { + lea(rscratch1, src); + movq(dst, Address(rscratch1,0)); + } + } +} + +void MacroAssembler::movptr(ArrayAddress dst, Register src) { + movq(as_Address(dst), src); +} + +void MacroAssembler::movptr(Register dst, ArrayAddress src) { + movq(dst, as_Address(src)); +} + +// src should NEVER be a real pointer. Use AddressLiteral for true pointers +void MacroAssembler::movptr(Address dst, intptr_t src) { + mov64(rscratch1, src); + movq(dst, rscratch1); +} + +// These are mostly for initializing NULL +void MacroAssembler::movptr(Address dst, int32_t src) { + movslq(dst, src); +} + +void MacroAssembler::movptr(Register dst, int32_t src) { + mov64(dst, (intptr_t)src); +} + +void MacroAssembler::pushoop(jobject obj) { + movoop(rscratch1, obj); + push(rscratch1); +} + +void MacroAssembler::pushklass(Metadata* obj) { + mov_metadata(rscratch1, obj); + push(rscratch1); +} + +void MacroAssembler::pushptr(AddressLiteral src) { + lea(rscratch1, src); + if (src.is_lval()) { + push(rscratch1); + } else { + pushq(Address(rscratch1, 0)); + } +} + +void MacroAssembler::reset_last_Java_frame(bool clear_fp, + bool clear_pc) { + // we must set sp to zero to clear frame + movptr(Address(r15_thread, JavaThread::last_Java_sp_offset()), NULL_WORD); + // must clear fp, so that compiled frames are not confused; it is + // possible that we need it only for debugging + if (clear_fp) { + movptr(Address(r15_thread, JavaThread::last_Java_fp_offset()), NULL_WORD); + } + + if (clear_pc) { + movptr(Address(r15_thread, JavaThread::last_Java_pc_offset()), NULL_WORD); + } +} + +void MacroAssembler::set_last_Java_frame(Register last_java_sp, + Register last_java_fp, + address last_java_pc) { + // determine last_java_sp register + if (!last_java_sp->is_valid()) { + last_java_sp = rsp; + } + + // last_java_fp is optional + if (last_java_fp->is_valid()) { + movptr(Address(r15_thread, JavaThread::last_Java_fp_offset()), + last_java_fp); + } + + // last_java_pc is optional + if (last_java_pc != NULL) { + Address java_pc(r15_thread, + JavaThread::frame_anchor_offset() + JavaFrameAnchor::last_Java_pc_offset()); + lea(rscratch1, InternalAddress(last_java_pc)); + movptr(java_pc, rscratch1); + } + + movptr(Address(r15_thread, JavaThread::last_Java_sp_offset()), last_java_sp); +} + +static void pass_arg0(MacroAssembler* masm, Register arg) { + if (c_rarg0 != arg ) { + masm->mov(c_rarg0, arg); + } +} + +static void pass_arg1(MacroAssembler* masm, Register arg) { + if (c_rarg1 != arg ) { + masm->mov(c_rarg1, arg); + } +} + +static void pass_arg2(MacroAssembler* masm, Register arg) { + if (c_rarg2 != arg ) { + masm->mov(c_rarg2, arg); + } +} + +static void pass_arg3(MacroAssembler* masm, Register arg) { + if (c_rarg3 != arg ) { + masm->mov(c_rarg3, arg); + } +} + +void MacroAssembler::stop(const char* msg) { + address rip = pc(); + pusha(); // get regs on stack + lea(c_rarg0, ExternalAddress((address) msg)); + lea(c_rarg1, InternalAddress(rip)); + movq(c_rarg2, rsp); // pass pointer to regs array + andq(rsp, -16); // align stack as required by ABI + call(RuntimeAddress(CAST_FROM_FN_PTR(address, MacroAssembler::debug64))); + hlt(); +} + +void MacroAssembler::warn(const char* msg) { + push(rbp); + movq(rbp, rsp); + andq(rsp, -16); // align stack as required by push_CPU_state and call + push_CPU_state(); // keeps alignment at 16 bytes + lea(c_rarg0, ExternalAddress((address) msg)); + call_VM_leaf(CAST_FROM_FN_PTR(address, warning), c_rarg0); + pop_CPU_state(); + mov(rsp, rbp); + pop(rbp); +} + +void MacroAssembler::print_state() { + address rip = pc(); + pusha(); // get regs on stack + push(rbp); + movq(rbp, rsp); + andq(rsp, -16); // align stack as required by push_CPU_state and call + push_CPU_state(); // keeps alignment at 16 bytes + + lea(c_rarg0, InternalAddress(rip)); + lea(c_rarg1, Address(rbp, wordSize)); // pass pointer to regs array + call_VM_leaf(CAST_FROM_FN_PTR(address, MacroAssembler::print_state64), c_rarg0, c_rarg1); + + pop_CPU_state(); + mov(rsp, rbp); + pop(rbp); + popa(); +} + +#ifndef PRODUCT +extern "C" void findpc(intptr_t x); +#endif + +void MacroAssembler::debug64(char* msg, int64_t pc, int64_t regs[]) { + // In order to get locks to work, we need to fake a in_VM state + if (ShowMessageBoxOnError) { + JavaThread* thread = JavaThread::current(); + JavaThreadState saved_state = thread->thread_state(); + thread->set_thread_state(_thread_in_vm); +#ifndef PRODUCT + if (CountBytecodes || TraceBytecodes || StopInterpreterAt) { + ttyLocker ttyl; + BytecodeCounter::print(); + } +#endif + // To see where a verify_oop failed, get $ebx+40/X for this frame. + // XXX correct this offset for amd64 + // This is the value of eip which points to where verify_oop will return. + if (os::message_box(msg, "Execution stopped, print registers?")) { + print_state64(pc, regs); + BREAKPOINT; + assert(false, "start up GDB"); + } + ThreadStateTransition::transition(thread, _thread_in_vm, saved_state); + } else { + ttyLocker ttyl; + ::tty->print_cr("=============== DEBUG MESSAGE: %s ================\n", + msg); + assert(false, err_msg("DEBUG MESSAGE: %s", msg)); + } +} + +void MacroAssembler::print_state64(int64_t pc, int64_t regs[]) { + ttyLocker ttyl; + FlagSetting fs(Debugging, true); + tty->print_cr("rip = 0x%016lx", pc); +#ifndef PRODUCT + tty->cr(); + findpc(pc); + tty->cr(); +#endif +#define PRINT_REG(rax, value) \ + { tty->print("%s = ", #rax); os::print_location(tty, value); } + PRINT_REG(rax, regs[15]); + PRINT_REG(rbx, regs[12]); + PRINT_REG(rcx, regs[14]); + PRINT_REG(rdx, regs[13]); + PRINT_REG(rdi, regs[8]); + PRINT_REG(rsi, regs[9]); + PRINT_REG(rbp, regs[10]); + PRINT_REG(rsp, regs[11]); + PRINT_REG(r8 , regs[7]); + PRINT_REG(r9 , regs[6]); + PRINT_REG(r10, regs[5]); + PRINT_REG(r11, regs[4]); + PRINT_REG(r12, regs[3]); + PRINT_REG(r13, regs[2]); + PRINT_REG(r14, regs[1]); + PRINT_REG(r15, regs[0]); +#undef PRINT_REG + // Print some words near top of staack. + int64_t* rsp = (int64_t*) regs[11]; + int64_t* dump_sp = rsp; + for (int col1 = 0; col1 < 8; col1++) { + tty->print("(rsp+0x%03x) 0x%016lx: ", (int)((intptr_t)dump_sp - (intptr_t)rsp), (int64_t)dump_sp); + os::print_location(tty, *dump_sp++); + } + for (int row = 0; row < 25; row++) { + tty->print("(rsp+0x%03x) 0x%016lx: ", (int)((intptr_t)dump_sp - (intptr_t)rsp), (int64_t)dump_sp); + for (int col = 0; col < 4; col++) { + tty->print(" 0x%016lx", *dump_sp++); + } + tty->cr(); + } + // Print some instructions around pc: + Disassembler::decode((address)pc-64, (address)pc); + tty->print_cr("--------"); + Disassembler::decode((address)pc, (address)pc+32); +} + +#endif // _LP64 + +// Now versions that are common to 32/64 bit + +void MacroAssembler::addptr(Register dst, int32_t imm32) { + LP64_ONLY(addq(dst, imm32)) NOT_LP64(addl(dst, imm32)); +} + +void MacroAssembler::addptr(Register dst, Register src) { + LP64_ONLY(addq(dst, src)) NOT_LP64(addl(dst, src)); +} + +void MacroAssembler::addptr(Address dst, Register src) { + LP64_ONLY(addq(dst, src)) NOT_LP64(addl(dst, src)); +} + +void MacroAssembler::addsd(XMMRegister dst, AddressLiteral src) { + if (reachable(src)) { + Assembler::addsd(dst, as_Address(src)); + } else { + lea(rscratch1, src); + Assembler::addsd(dst, Address(rscratch1, 0)); + } +} + +void MacroAssembler::addss(XMMRegister dst, AddressLiteral src) { + if (reachable(src)) { + addss(dst, as_Address(src)); + } else { + lea(rscratch1, src); + addss(dst, Address(rscratch1, 0)); + } +} + +void MacroAssembler::align(int modulus) { + if (offset() % modulus != 0) { + nop(modulus - (offset() % modulus)); + } +} + +void MacroAssembler::andpd(XMMRegister dst, AddressLiteral src) { + // Used in sign-masking with aligned address. + assert((UseAVX > 0) || (((intptr_t)src.target() & 15) == 0), "SSE mode requires address alignment 16 bytes"); + if (reachable(src)) { + Assembler::andpd(dst, as_Address(src)); + } else { + lea(rscratch1, src); + Assembler::andpd(dst, Address(rscratch1, 0)); + } +} + +void MacroAssembler::andps(XMMRegister dst, AddressLiteral src) { + // Used in sign-masking with aligned address. + assert((UseAVX > 0) || (((intptr_t)src.target() & 15) == 0), "SSE mode requires address alignment 16 bytes"); + if (reachable(src)) { + Assembler::andps(dst, as_Address(src)); + } else { + lea(rscratch1, src); + Assembler::andps(dst, Address(rscratch1, 0)); + } +} + +void MacroAssembler::andptr(Register dst, int32_t imm32) { + LP64_ONLY(andq(dst, imm32)) NOT_LP64(andl(dst, imm32)); +} + +void MacroAssembler::atomic_incl(AddressLiteral counter_addr) { + pushf(); + if (os::is_MP()) + lock(); + incrementl(counter_addr); + popf(); +} + +// Writes to stack successive pages until offset reached to check for +// stack overflow + shadow pages. This clobbers tmp. +void MacroAssembler::bang_stack_size(Register size, Register tmp) { + movptr(tmp, rsp); + // Bang stack for total size given plus shadow page size. + // Bang one page at a time because large size can bang beyond yellow and + // red zones. + Label loop; + bind(loop); + movl(Address(tmp, (-os::vm_page_size())), size ); + subptr(tmp, os::vm_page_size()); + subl(size, os::vm_page_size()); + jcc(Assembler::greater, loop); + + // Bang down shadow pages too. + // The -1 because we already subtracted 1 page. + for (int i = 0; i< StackShadowPages-1; i++) { + // this could be any sized move but this is can be a debugging crumb + // so the bigger the better. + movptr(Address(tmp, (-i*os::vm_page_size())), size ); + } +} + +void MacroAssembler::biased_locking_exit(Register obj_reg, Register temp_reg, Label& done) { + assert(UseBiasedLocking, "why call this otherwise?"); + + // Check for biased locking unlock case, which is a no-op + // Note: we do not have to check the thread ID for two reasons. + // First, the interpreter checks for IllegalMonitorStateException at + // a higher level. Second, if the bias was revoked while we held the + // lock, the object could not be rebiased toward another thread, so + // the bias bit would be clear. + movptr(temp_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); + andptr(temp_reg, markOopDesc::biased_lock_mask_in_place); + cmpptr(temp_reg, markOopDesc::biased_lock_pattern); + jcc(Assembler::equal, done); +} + +void MacroAssembler::c2bool(Register x) { + // implements x == 0 ? 0 : 1 + // note: must only look at least-significant byte of x + // since C-style booleans are stored in one byte + // only! (was bug) + andl(x, 0xFF); + setb(Assembler::notZero, x); +} + +// Wouldn't need if AddressLiteral version had new name +void MacroAssembler::call(Label& L, relocInfo::relocType rtype) { + Assembler::call(L, rtype); +} + +void MacroAssembler::call(Register entry) { + Assembler::call(entry); +} + +void MacroAssembler::call(AddressLiteral entry) { + if (reachable(entry)) { + Assembler::call_literal(entry.target(), entry.rspec()); + } else { + lea(rscratch1, entry); + Assembler::call(rscratch1); + } +} + +void MacroAssembler::ic_call(address entry) { + RelocationHolder rh = virtual_call_Relocation::spec(pc()); + movptr(rax, (intptr_t)Universe::non_oop_word()); + call(AddressLiteral(entry, rh)); +} + +// Implementation of call_VM versions + +void MacroAssembler::call_VM(Register oop_result, + address entry_point, + bool check_exceptions) { + Label C, E; + call(C, relocInfo::none); + jmp(E); + + bind(C); + call_VM_helper(oop_result, entry_point, 0, check_exceptions); + ret(0); + + bind(E); +} + +void MacroAssembler::call_VM(Register oop_result, + address entry_point, + Register arg_1, + bool check_exceptions) { + Label C, E; + call(C, relocInfo::none); + jmp(E); + + bind(C); + pass_arg1(this, arg_1); + call_VM_helper(oop_result, entry_point, 1, check_exceptions); + ret(0); + + bind(E); +} + +void MacroAssembler::call_VM(Register oop_result, + address entry_point, + Register arg_1, + Register arg_2, + bool check_exceptions) { + Label C, E; + call(C, relocInfo::none); + jmp(E); + + bind(C); + + LP64_ONLY(assert(arg_1 != c_rarg2, "smashed arg")); + + pass_arg2(this, arg_2); + pass_arg1(this, arg_1); + call_VM_helper(oop_result, entry_point, 2, check_exceptions); + ret(0); + + bind(E); +} + +void MacroAssembler::call_VM(Register oop_result, + address entry_point, + Register arg_1, + Register arg_2, + Register arg_3, + bool check_exceptions) { + Label C, E; + call(C, relocInfo::none); + jmp(E); + + bind(C); + + LP64_ONLY(assert(arg_1 != c_rarg3, "smashed arg")); + LP64_ONLY(assert(arg_2 != c_rarg3, "smashed arg")); + pass_arg3(this, arg_3); + + LP64_ONLY(assert(arg_1 != c_rarg2, "smashed arg")); + pass_arg2(this, arg_2); + + pass_arg1(this, arg_1); + call_VM_helper(oop_result, entry_point, 3, check_exceptions); + ret(0); + + bind(E); +} + +void MacroAssembler::call_VM(Register oop_result, + Register last_java_sp, + address entry_point, + int number_of_arguments, + bool check_exceptions) { + Register thread = LP64_ONLY(r15_thread) NOT_LP64(noreg); + call_VM_base(oop_result, thread, last_java_sp, entry_point, number_of_arguments, check_exceptions); +} + +void MacroAssembler::call_VM(Register oop_result, + Register last_java_sp, + address entry_point, + Register arg_1, + bool check_exceptions) { + pass_arg1(this, arg_1); + call_VM(oop_result, last_java_sp, entry_point, 1, check_exceptions); +} + +void MacroAssembler::call_VM(Register oop_result, + Register last_java_sp, + address entry_point, + Register arg_1, + Register arg_2, + bool check_exceptions) { + + LP64_ONLY(assert(arg_1 != c_rarg2, "smashed arg")); + pass_arg2(this, arg_2); + pass_arg1(this, arg_1); + call_VM(oop_result, last_java_sp, entry_point, 2, check_exceptions); +} + +void MacroAssembler::call_VM(Register oop_result, + Register last_java_sp, + address entry_point, + Register arg_1, + Register arg_2, + Register arg_3, + bool check_exceptions) { + LP64_ONLY(assert(arg_1 != c_rarg3, "smashed arg")); + LP64_ONLY(assert(arg_2 != c_rarg3, "smashed arg")); + pass_arg3(this, arg_3); + LP64_ONLY(assert(arg_1 != c_rarg2, "smashed arg")); + pass_arg2(this, arg_2); + pass_arg1(this, arg_1); + call_VM(oop_result, last_java_sp, entry_point, 3, check_exceptions); +} + +void MacroAssembler::super_call_VM(Register oop_result, + Register last_java_sp, + address entry_point, + int number_of_arguments, + bool check_exceptions) { + Register thread = LP64_ONLY(r15_thread) NOT_LP64(noreg); + MacroAssembler::call_VM_base(oop_result, thread, last_java_sp, entry_point, number_of_arguments, check_exceptions); +} + +void MacroAssembler::super_call_VM(Register oop_result, + Register last_java_sp, + address entry_point, + Register arg_1, + bool check_exceptions) { + pass_arg1(this, arg_1); + super_call_VM(oop_result, last_java_sp, entry_point, 1, check_exceptions); +} + +void MacroAssembler::super_call_VM(Register oop_result, + Register last_java_sp, + address entry_point, + Register arg_1, + Register arg_2, + bool check_exceptions) { + + LP64_ONLY(assert(arg_1 != c_rarg2, "smashed arg")); + pass_arg2(this, arg_2); + pass_arg1(this, arg_1); + super_call_VM(oop_result, last_java_sp, entry_point, 2, check_exceptions); +} + +void MacroAssembler::super_call_VM(Register oop_result, + Register last_java_sp, + address entry_point, + Register arg_1, + Register arg_2, + Register arg_3, + bool check_exceptions) { + LP64_ONLY(assert(arg_1 != c_rarg3, "smashed arg")); + LP64_ONLY(assert(arg_2 != c_rarg3, "smashed arg")); + pass_arg3(this, arg_3); + LP64_ONLY(assert(arg_1 != c_rarg2, "smashed arg")); + pass_arg2(this, arg_2); + pass_arg1(this, arg_1); + super_call_VM(oop_result, last_java_sp, entry_point, 3, check_exceptions); +} + +void MacroAssembler::call_VM_base(Register oop_result, + Register java_thread, + Register last_java_sp, + address entry_point, + int number_of_arguments, + bool check_exceptions) { + // determine java_thread register + if (!java_thread->is_valid()) { +#ifdef _LP64 + java_thread = r15_thread; +#else + java_thread = rdi; + get_thread(java_thread); +#endif // LP64 + } + // determine last_java_sp register + if (!last_java_sp->is_valid()) { + last_java_sp = rsp; + } + // debugging support + assert(number_of_arguments >= 0 , "cannot have negative number of arguments"); + LP64_ONLY(assert(java_thread == r15_thread, "unexpected register")); +#ifdef ASSERT + // TraceBytecodes does not use r12 but saves it over the call, so don't verify + // r12 is the heapbase. + LP64_ONLY(if ((UseCompressedOops || UseCompressedKlassPointers) && !TraceBytecodes) verify_heapbase("call_VM_base: heap base corrupted?");) +#endif // ASSERT + + assert(java_thread != oop_result , "cannot use the same register for java_thread & oop_result"); + assert(java_thread != last_java_sp, "cannot use the same register for java_thread & last_java_sp"); + + // push java thread (becomes first argument of C function) + + NOT_LP64(push(java_thread); number_of_arguments++); + LP64_ONLY(mov(c_rarg0, r15_thread)); + + // set last Java frame before call + assert(last_java_sp != rbp, "can't use ebp/rbp"); + + // Only interpreter should have to set fp + set_last_Java_frame(java_thread, last_java_sp, rbp, NULL); + + // do the call, remove parameters + MacroAssembler::call_VM_leaf_base(entry_point, number_of_arguments); + + // restore the thread (cannot use the pushed argument since arguments + // may be overwritten by C code generated by an optimizing compiler); + // however can use the register value directly if it is callee saved. + if (LP64_ONLY(true ||) java_thread == rdi || java_thread == rsi) { + // rdi & rsi (also r15) are callee saved -> nothing to do +#ifdef ASSERT + guarantee(java_thread != rax, "change this code"); + push(rax); + { Label L; + get_thread(rax); + cmpptr(java_thread, rax); + jcc(Assembler::equal, L); + STOP("MacroAssembler::call_VM_base: rdi not callee saved?"); + bind(L); + } + pop(rax); +#endif + } else { + get_thread(java_thread); + } + // reset last Java frame + // Only interpreter should have to clear fp + reset_last_Java_frame(java_thread, true, false); + +#ifndef CC_INTERP + // C++ interp handles this in the interpreter + check_and_handle_popframe(java_thread); + check_and_handle_earlyret(java_thread); +#endif /* CC_INTERP */ + + if (check_exceptions) { + // check for pending exceptions (java_thread is set upon return) + cmpptr(Address(java_thread, Thread::pending_exception_offset()), (int32_t) NULL_WORD); +#ifndef _LP64 + jump_cc(Assembler::notEqual, + RuntimeAddress(StubRoutines::forward_exception_entry())); +#else + // This used to conditionally jump to forward_exception however it is + // possible if we relocate that the branch will not reach. So we must jump + // around so we can always reach + + Label ok; + jcc(Assembler::equal, ok); + jump(RuntimeAddress(StubRoutines::forward_exception_entry())); + bind(ok); +#endif // LP64 + } + + // get oop result if there is one and reset the value in the thread + if (oop_result->is_valid()) { + get_vm_result(oop_result, java_thread); + } +} + +void MacroAssembler::call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions) { + + // Calculate the value for last_Java_sp + // somewhat subtle. call_VM does an intermediate call + // which places a return address on the stack just under the + // stack pointer as the user finsihed with it. This allows + // use to retrieve last_Java_pc from last_Java_sp[-1]. + // On 32bit we then have to push additional args on the stack to accomplish + // the actual requested call. On 64bit call_VM only can use register args + // so the only extra space is the return address that call_VM created. + // This hopefully explains the calculations here. + +#ifdef _LP64 + // We've pushed one address, correct last_Java_sp + lea(rax, Address(rsp, wordSize)); +#else + lea(rax, Address(rsp, (1 + number_of_arguments) * wordSize)); +#endif // LP64 + + call_VM_base(oop_result, noreg, rax, entry_point, number_of_arguments, check_exceptions); + +} + +void MacroAssembler::call_VM_leaf(address entry_point, int number_of_arguments) { + call_VM_leaf_base(entry_point, number_of_arguments); +} + +void MacroAssembler::call_VM_leaf(address entry_point, Register arg_0) { + pass_arg0(this, arg_0); + call_VM_leaf(entry_point, 1); +} + +void MacroAssembler::call_VM_leaf(address entry_point, Register arg_0, Register arg_1) { + + LP64_ONLY(assert(arg_0 != c_rarg1, "smashed arg")); + pass_arg1(this, arg_1); + pass_arg0(this, arg_0); + call_VM_leaf(entry_point, 2); +} + +void MacroAssembler::call_VM_leaf(address entry_point, Register arg_0, Register arg_1, Register arg_2) { + LP64_ONLY(assert(arg_0 != c_rarg2, "smashed arg")); + LP64_ONLY(assert(arg_1 != c_rarg2, "smashed arg")); + pass_arg2(this, arg_2); + LP64_ONLY(assert(arg_0 != c_rarg1, "smashed arg")); + pass_arg1(this, arg_1); + pass_arg0(this, arg_0); + call_VM_leaf(entry_point, 3); +} + +void MacroAssembler::super_call_VM_leaf(address entry_point, Register arg_0) { + pass_arg0(this, arg_0); + MacroAssembler::call_VM_leaf_base(entry_point, 1); +} + +void MacroAssembler::super_call_VM_leaf(address entry_point, Register arg_0, Register arg_1) { + + LP64_ONLY(assert(arg_0 != c_rarg1, "smashed arg")); + pass_arg1(this, arg_1); + pass_arg0(this, arg_0); + MacroAssembler::call_VM_leaf_base(entry_point, 2); +} + +void MacroAssembler::super_call_VM_leaf(address entry_point, Register arg_0, Register arg_1, Register arg_2) { + LP64_ONLY(assert(arg_0 != c_rarg2, "smashed arg")); + LP64_ONLY(assert(arg_1 != c_rarg2, "smashed arg")); + pass_arg2(this, arg_2); + LP64_ONLY(assert(arg_0 != c_rarg1, "smashed arg")); + pass_arg1(this, arg_1); + pass_arg0(this, arg_0); + MacroAssembler::call_VM_leaf_base(entry_point, 3); +} + +void MacroAssembler::super_call_VM_leaf(address entry_point, Register arg_0, Register arg_1, Register arg_2, Register arg_3) { + LP64_ONLY(assert(arg_0 != c_rarg3, "smashed arg")); + LP64_ONLY(assert(arg_1 != c_rarg3, "smashed arg")); + LP64_ONLY(assert(arg_2 != c_rarg3, "smashed arg")); + pass_arg3(this, arg_3); + LP64_ONLY(assert(arg_0 != c_rarg2, "smashed arg")); + LP64_ONLY(assert(arg_1 != c_rarg2, "smashed arg")); + pass_arg2(this, arg_2); + LP64_ONLY(assert(arg_0 != c_rarg1, "smashed arg")); + pass_arg1(this, arg_1); + pass_arg0(this, arg_0); + MacroAssembler::call_VM_leaf_base(entry_point, 4); +} + +void MacroAssembler::get_vm_result(Register oop_result, Register java_thread) { + movptr(oop_result, Address(java_thread, JavaThread::vm_result_offset())); + movptr(Address(java_thread, JavaThread::vm_result_offset()), NULL_WORD); + verify_oop(oop_result, "broken oop in call_VM_base"); +} + +void MacroAssembler::get_vm_result_2(Register metadata_result, Register java_thread) { + movptr(metadata_result, Address(java_thread, JavaThread::vm_result_2_offset())); + movptr(Address(java_thread, JavaThread::vm_result_2_offset()), NULL_WORD); +} + +void MacroAssembler::check_and_handle_earlyret(Register java_thread) { +} + +void MacroAssembler::check_and_handle_popframe(Register java_thread) { +} + +void MacroAssembler::cmp32(AddressLiteral src1, int32_t imm) { + if (reachable(src1)) { + cmpl(as_Address(src1), imm); + } else { + lea(rscratch1, src1); + cmpl(Address(rscratch1, 0), imm); + } +} + +void MacroAssembler::cmp32(Register src1, AddressLiteral src2) { + assert(!src2.is_lval(), "use cmpptr"); + if (reachable(src2)) { + cmpl(src1, as_Address(src2)); + } else { + lea(rscratch1, src2); + cmpl(src1, Address(rscratch1, 0)); + } +} + +void MacroAssembler::cmp32(Register src1, int32_t imm) { + Assembler::cmpl(src1, imm); +} + +void MacroAssembler::cmp32(Register src1, Address src2) { + Assembler::cmpl(src1, src2); +} + +void MacroAssembler::cmpsd2int(XMMRegister opr1, XMMRegister opr2, Register dst, bool unordered_is_less) { + ucomisd(opr1, opr2); + + Label L; + if (unordered_is_less) { + movl(dst, -1); + jcc(Assembler::parity, L); + jcc(Assembler::below , L); + movl(dst, 0); + jcc(Assembler::equal , L); + increment(dst); + } else { // unordered is greater + movl(dst, 1); + jcc(Assembler::parity, L); + jcc(Assembler::above , L); + movl(dst, 0); + jcc(Assembler::equal , L); + decrementl(dst); + } + bind(L); +} + +void MacroAssembler::cmpss2int(XMMRegister opr1, XMMRegister opr2, Register dst, bool unordered_is_less) { + ucomiss(opr1, opr2); + + Label L; + if (unordered_is_less) { + movl(dst, -1); + jcc(Assembler::parity, L); + jcc(Assembler::below , L); + movl(dst, 0); + jcc(Assembler::equal , L); + increment(dst); + } else { // unordered is greater + movl(dst, 1); + jcc(Assembler::parity, L); + jcc(Assembler::above , L); + movl(dst, 0); + jcc(Assembler::equal , L); + decrementl(dst); + } + bind(L); +} + + +void MacroAssembler::cmp8(AddressLiteral src1, int imm) { + if (reachable(src1)) { + cmpb(as_Address(src1), imm); + } else { + lea(rscratch1, src1); + cmpb(Address(rscratch1, 0), imm); + } +} + +void MacroAssembler::cmpptr(Register src1, AddressLiteral src2) { +#ifdef _LP64 + if (src2.is_lval()) { + movptr(rscratch1, src2); + Assembler::cmpq(src1, rscratch1); + } else if (reachable(src2)) { + cmpq(src1, as_Address(src2)); + } else { + lea(rscratch1, src2); + Assembler::cmpq(src1, Address(rscratch1, 0)); + } +#else + if (src2.is_lval()) { + cmp_literal32(src1, (int32_t) src2.target(), src2.rspec()); + } else { + cmpl(src1, as_Address(src2)); + } +#endif // _LP64 +} + +void MacroAssembler::cmpptr(Address src1, AddressLiteral src2) { + assert(src2.is_lval(), "not a mem-mem compare"); +#ifdef _LP64 + // moves src2's literal address + movptr(rscratch1, src2); + Assembler::cmpq(src1, rscratch1); +#else + cmp_literal32(src1, (int32_t) src2.target(), src2.rspec()); +#endif // _LP64 +} + +void MacroAssembler::locked_cmpxchgptr(Register reg, AddressLiteral adr) { + if (reachable(adr)) { + if (os::is_MP()) + lock(); + cmpxchgptr(reg, as_Address(adr)); + } else { + lea(rscratch1, adr); + if (os::is_MP()) + lock(); + cmpxchgptr(reg, Address(rscratch1, 0)); + } +} + +void MacroAssembler::cmpxchgptr(Register reg, Address adr) { + LP64_ONLY(cmpxchgq(reg, adr)) NOT_LP64(cmpxchgl(reg, adr)); +} + +void MacroAssembler::comisd(XMMRegister dst, AddressLiteral src) { + if (reachable(src)) { + Assembler::comisd(dst, as_Address(src)); + } else { + lea(rscratch1, src); + Assembler::comisd(dst, Address(rscratch1, 0)); + } +} + +void MacroAssembler::comiss(XMMRegister dst, AddressLiteral src) { + if (reachable(src)) { + Assembler::comiss(dst, as_Address(src)); + } else { + lea(rscratch1, src); + Assembler::comiss(dst, Address(rscratch1, 0)); + } +} + + +void MacroAssembler::cond_inc32(Condition cond, AddressLiteral counter_addr) { + Condition negated_cond = negate_condition(cond); + Label L; + jcc(negated_cond, L); + atomic_incl(counter_addr); + bind(L); +} + +int MacroAssembler::corrected_idivl(Register reg) { + // Full implementation of Java idiv and irem; checks for + // special case as described in JVM spec., p.243 & p.271. + // The function returns the (pc) offset of the idivl + // instruction - may be needed for implicit exceptions. + // + // normal case special case + // + // input : rax,: dividend min_int + // reg: divisor (may not be rax,/rdx) -1 + // + // output: rax,: quotient (= rax, idiv reg) min_int + // rdx: remainder (= rax, irem reg) 0 + assert(reg != rax && reg != rdx, "reg cannot be rax, or rdx register"); + const int min_int = 0x80000000; + Label normal_case, special_case; + + // check for special case + cmpl(rax, min_int); + jcc(Assembler::notEqual, normal_case); + xorl(rdx, rdx); // prepare rdx for possible special case (where remainder = 0) + cmpl(reg, -1); + jcc(Assembler::equal, special_case); + + // handle normal case + bind(normal_case); + cdql(); + int idivl_offset = offset(); + idivl(reg); + + // normal and special case exit + bind(special_case); + + return idivl_offset; +} + + + +void MacroAssembler::decrementl(Register reg, int value) { + if (value == min_jint) {subl(reg, value) ; return; } + if (value < 0) { incrementl(reg, -value); return; } + if (value == 0) { ; return; } + if (value == 1 && UseIncDec) { decl(reg) ; return; } + /* else */ { subl(reg, value) ; return; } +} + +void MacroAssembler::decrementl(Address dst, int value) { + if (value == min_jint) {subl(dst, value) ; return; } + if (value < 0) { incrementl(dst, -value); return; } + if (value == 0) { ; return; } + if (value == 1 && UseIncDec) { decl(dst) ; return; } + /* else */ { subl(dst, value) ; return; } +} + +void MacroAssembler::division_with_shift (Register reg, int shift_value) { + assert (shift_value > 0, "illegal shift value"); + Label _is_positive; + testl (reg, reg); + jcc (Assembler::positive, _is_positive); + int offset = (1 << shift_value) - 1 ; + + if (offset == 1) { + incrementl(reg); + } else { + addl(reg, offset); + } + + bind (_is_positive); + sarl(reg, shift_value); +} + +void MacroAssembler::divsd(XMMRegister dst, AddressLiteral src) { + if (reachable(src)) { + Assembler::divsd(dst, as_Address(src)); + } else { + lea(rscratch1, src); + Assembler::divsd(dst, Address(rscratch1, 0)); + } +} + +void MacroAssembler::divss(XMMRegister dst, AddressLiteral src) { + if (reachable(src)) { + Assembler::divss(dst, as_Address(src)); + } else { + lea(rscratch1, src); + Assembler::divss(dst, Address(rscratch1, 0)); + } +} + +// !defined(COMPILER2) is because of stupid core builds +#if !defined(_LP64) || defined(COMPILER1) || !defined(COMPILER2) +void MacroAssembler::empty_FPU_stack() { + if (VM_Version::supports_mmx()) { + emms(); + } else { + for (int i = 8; i-- > 0; ) ffree(i); + } +} +#endif // !LP64 || C1 || !C2 + + +// Defines obj, preserves var_size_in_bytes +void MacroAssembler::eden_allocate(Register obj, + Register var_size_in_bytes, + int con_size_in_bytes, + Register t1, + Label& slow_case) { + assert(obj == rax, "obj must be in rax, for cmpxchg"); + assert_different_registers(obj, var_size_in_bytes, t1); + if (CMSIncrementalMode || !Universe::heap()->supports_inline_contig_alloc()) { + jmp(slow_case); + } else { + Register end = t1; + Label retry; + bind(retry); + ExternalAddress heap_top((address) Universe::heap()->top_addr()); + movptr(obj, heap_top); + if (var_size_in_bytes == noreg) { + lea(end, Address(obj, con_size_in_bytes)); + } else { + lea(end, Address(obj, var_size_in_bytes, Address::times_1)); + } + // if end < obj then we wrapped around => object too long => slow case + cmpptr(end, obj); + jcc(Assembler::below, slow_case); + cmpptr(end, ExternalAddress((address) Universe::heap()->end_addr())); + jcc(Assembler::above, slow_case); + // Compare obj with the top addr, and if still equal, store the new top addr in + // end at the address of the top addr pointer. Sets ZF if was equal, and clears + // it otherwise. Use lock prefix for atomicity on MPs. + locked_cmpxchgptr(end, heap_top); + jcc(Assembler::notEqual, retry); + } +} + +void MacroAssembler::enter() { + push(rbp); + mov(rbp, rsp); +} + +// A 5 byte nop that is safe for patching (see patch_verified_entry) +void MacroAssembler::fat_nop() { + if (UseAddressNop) { + addr_nop_5(); + } else { + emit_byte(0x26); // es: + emit_byte(0x2e); // cs: + emit_byte(0x64); // fs: + emit_byte(0x65); // gs: + emit_byte(0x90); + } +} + +void MacroAssembler::fcmp(Register tmp) { + fcmp(tmp, 1, true, true); +} + +void MacroAssembler::fcmp(Register tmp, int index, bool pop_left, bool pop_right) { + assert(!pop_right || pop_left, "usage error"); + if (VM_Version::supports_cmov()) { + assert(tmp == noreg, "unneeded temp"); + if (pop_left) { + fucomip(index); + } else { + fucomi(index); + } + if (pop_right) { + fpop(); + } + } else { + assert(tmp != noreg, "need temp"); + if (pop_left) { + if (pop_right) { + fcompp(); + } else { + fcomp(index); + } + } else { + fcom(index); + } + // convert FPU condition into eflags condition via rax, + save_rax(tmp); + fwait(); fnstsw_ax(); + sahf(); + restore_rax(tmp); + } + // condition codes set as follows: + // + // CF (corresponds to C0) if x < y + // PF (corresponds to C2) if unordered + // ZF (corresponds to C3) if x = y +} + +void MacroAssembler::fcmp2int(Register dst, bool unordered_is_less) { + fcmp2int(dst, unordered_is_less, 1, true, true); +} + +void MacroAssembler::fcmp2int(Register dst, bool unordered_is_less, int index, bool pop_left, bool pop_right) { + fcmp(VM_Version::supports_cmov() ? noreg : dst, index, pop_left, pop_right); + Label L; + if (unordered_is_less) { + movl(dst, -1); + jcc(Assembler::parity, L); + jcc(Assembler::below , L); + movl(dst, 0); + jcc(Assembler::equal , L); + increment(dst); + } else { // unordered is greater + movl(dst, 1); + jcc(Assembler::parity, L); + jcc(Assembler::above , L); + movl(dst, 0); + jcc(Assembler::equal , L); + decrementl(dst); + } + bind(L); +} + +void MacroAssembler::fld_d(AddressLiteral src) { + fld_d(as_Address(src)); +} + +void MacroAssembler::fld_s(AddressLiteral src) { + fld_s(as_Address(src)); +} + +void MacroAssembler::fld_x(AddressLiteral src) { + Assembler::fld_x(as_Address(src)); +} + +void MacroAssembler::fldcw(AddressLiteral src) { + Assembler::fldcw(as_Address(src)); +} + +void MacroAssembler::pow_exp_core_encoding() { + // kills rax, rcx, rdx + subptr(rsp,sizeof(jdouble)); + // computes 2^X. Stack: X ... + // f2xm1 computes 2^X-1 but only operates on -1<=X<=1. Get int(X) and + // keep it on the thread's stack to compute 2^int(X) later + // then compute 2^(X-int(X)) as (2^(X-int(X)-1+1) + // final result is obtained with: 2^X = 2^int(X) * 2^(X-int(X)) + fld_s(0); // Stack: X X ... + frndint(); // Stack: int(X) X ... + fsuba(1); // Stack: int(X) X-int(X) ... + fistp_s(Address(rsp,0)); // move int(X) as integer to thread's stack. Stack: X-int(X) ... + f2xm1(); // Stack: 2^(X-int(X))-1 ... + fld1(); // Stack: 1 2^(X-int(X))-1 ... + faddp(1); // Stack: 2^(X-int(X)) + // computes 2^(int(X)): add exponent bias (1023) to int(X), then + // shift int(X)+1023 to exponent position. + // Exponent is limited to 11 bits if int(X)+1023 does not fit in 11 + // bits, set result to NaN. 0x000 and 0x7FF are reserved exponent + // values so detect them and set result to NaN. + movl(rax,Address(rsp,0)); + movl(rcx, -2048); // 11 bit mask and valid NaN binary encoding + addl(rax, 1023); + movl(rdx,rax); + shll(rax,20); + // Check that 0 < int(X)+1023 < 2047. Otherwise set rax to NaN. + addl(rdx,1); + // Check that 1 < int(X)+1023+1 < 2048 + // in 3 steps: + // 1- (int(X)+1023+1)&-2048 == 0 => 0 <= int(X)+1023+1 < 2048 + // 2- (int(X)+1023+1)&-2048 != 0 + // 3- (int(X)+1023+1)&-2048 != 1 + // Do 2- first because addl just updated the flags. + cmov32(Assembler::equal,rax,rcx); + cmpl(rdx,1); + cmov32(Assembler::equal,rax,rcx); + testl(rdx,rcx); + cmov32(Assembler::notEqual,rax,rcx); + movl(Address(rsp,4),rax); + movl(Address(rsp,0),0); + fmul_d(Address(rsp,0)); // Stack: 2^X ... + addptr(rsp,sizeof(jdouble)); +} + +void MacroAssembler::increase_precision() { + subptr(rsp, BytesPerWord); + fnstcw(Address(rsp, 0)); + movl(rax, Address(rsp, 0)); + orl(rax, 0x300); + push(rax); + fldcw(Address(rsp, 0)); + pop(rax); +} + +void MacroAssembler::restore_precision() { + fldcw(Address(rsp, 0)); + addptr(rsp, BytesPerWord); +} + +void MacroAssembler::fast_pow() { + // computes X^Y = 2^(Y * log2(X)) + // if fast computation is not possible, result is NaN. Requires + // fallback from user of this macro. + // increase precision for intermediate steps of the computation + increase_precision(); + fyl2x(); // Stack: (Y*log2(X)) ... + pow_exp_core_encoding(); // Stack: exp(X) ... + restore_precision(); +} + +void MacroAssembler::fast_exp() { + // computes exp(X) = 2^(X * log2(e)) + // if fast computation is not possible, result is NaN. Requires + // fallback from user of this macro. + // increase precision for intermediate steps of the computation + increase_precision(); + fldl2e(); // Stack: log2(e) X ... + fmulp(1); // Stack: (X*log2(e)) ... + pow_exp_core_encoding(); // Stack: exp(X) ... + restore_precision(); +} + +void MacroAssembler::pow_or_exp(bool is_exp, int num_fpu_regs_in_use) { + // kills rax, rcx, rdx + // pow and exp needs 2 extra registers on the fpu stack. + Label slow_case, done; + Register tmp = noreg; + if (!VM_Version::supports_cmov()) { + // fcmp needs a temporary so preserve rdx, + tmp = rdx; + } + Register tmp2 = rax; + Register tmp3 = rcx; + + if (is_exp) { + // Stack: X + fld_s(0); // duplicate argument for runtime call. Stack: X X + fast_exp(); // Stack: exp(X) X + fcmp(tmp, 0, false, false); // Stack: exp(X) X + // exp(X) not equal to itself: exp(X) is NaN go to slow case. + jcc(Assembler::parity, slow_case); + // get rid of duplicate argument. Stack: exp(X) + if (num_fpu_regs_in_use > 0) { + fxch(); + fpop(); + } else { + ffree(1); + } + jmp(done); + } else { + // Stack: X Y + Label x_negative, y_odd; + + fldz(); // Stack: 0 X Y + fcmp(tmp, 1, true, false); // Stack: X Y + jcc(Assembler::above, x_negative); + + // X >= 0 + + fld_s(1); // duplicate arguments for runtime call. Stack: Y X Y + fld_s(1); // Stack: X Y X Y + fast_pow(); // Stack: X^Y X Y + fcmp(tmp, 0, false, false); // Stack: X^Y X Y + // X^Y not equal to itself: X^Y is NaN go to slow case. + jcc(Assembler::parity, slow_case); + // get rid of duplicate arguments. Stack: X^Y + if (num_fpu_regs_in_use > 0) { + fxch(); fpop(); + fxch(); fpop(); + } else { + ffree(2); + ffree(1); + } + jmp(done); + + // X <= 0 + bind(x_negative); + + fld_s(1); // Stack: Y X Y + frndint(); // Stack: int(Y) X Y + fcmp(tmp, 2, false, false); // Stack: int(Y) X Y + jcc(Assembler::notEqual, slow_case); + + subptr(rsp, 8); + + // For X^Y, when X < 0, Y has to be an integer and the final + // result depends on whether it's odd or even. We just checked + // that int(Y) == Y. We move int(Y) to gp registers as a 64 bit + // integer to test its parity. If int(Y) is huge and doesn't fit + // in the 64 bit integer range, the integer indefinite value will + // end up in the gp registers. Huge numbers are all even, the + // integer indefinite number is even so it's fine. + +#ifdef ASSERT + // Let's check we don't end up with an integer indefinite number + // when not expected. First test for huge numbers: check whether + // int(Y)+1 == int(Y) which is true for very large numbers and + // those are all even. A 64 bit integer is guaranteed to not + // overflow for numbers where y+1 != y (when precision is set to + // double precision). + Label y_not_huge; + + fld1(); // Stack: 1 int(Y) X Y + fadd(1); // Stack: 1+int(Y) int(Y) X Y + +#ifdef _LP64 + // trip to memory to force the precision down from double extended + // precision + fstp_d(Address(rsp, 0)); + fld_d(Address(rsp, 0)); +#endif + + fcmp(tmp, 1, true, false); // Stack: int(Y) X Y +#endif + + // move int(Y) as 64 bit integer to thread's stack + fistp_d(Address(rsp,0)); // Stack: X Y + +#ifdef ASSERT + jcc(Assembler::notEqual, y_not_huge); + + // Y is huge so we know it's even. It may not fit in a 64 bit + // integer and we don't want the debug code below to see the + // integer indefinite value so overwrite int(Y) on the thread's + // stack with 0. + movl(Address(rsp, 0), 0); + movl(Address(rsp, 4), 0); + + bind(y_not_huge); +#endif + + fld_s(1); // duplicate arguments for runtime call. Stack: Y X Y + fld_s(1); // Stack: X Y X Y + fabs(); // Stack: abs(X) Y X Y + fast_pow(); // Stack: abs(X)^Y X Y + fcmp(tmp, 0, false, false); // Stack: abs(X)^Y X Y + // abs(X)^Y not equal to itself: abs(X)^Y is NaN go to slow case. + + pop(tmp2); + NOT_LP64(pop(tmp3)); + jcc(Assembler::parity, slow_case); + +#ifdef ASSERT + // Check that int(Y) is not integer indefinite value (int + // overflow). Shouldn't happen because for values that would + // overflow, 1+int(Y)==Y which was tested earlier. +#ifndef _LP64 + { + Label integer; + testl(tmp2, tmp2); + jcc(Assembler::notZero, integer); + cmpl(tmp3, 0x80000000); + jcc(Assembler::notZero, integer); + STOP("integer indefinite value shouldn't be seen here"); + bind(integer); + } +#else + { + Label integer; + mov(tmp3, tmp2); // preserve tmp2 for parity check below + shlq(tmp3, 1); + jcc(Assembler::carryClear, integer); + jcc(Assembler::notZero, integer); + STOP("integer indefinite value shouldn't be seen here"); + bind(integer); + } +#endif +#endif + + // get rid of duplicate arguments. Stack: X^Y + if (num_fpu_regs_in_use > 0) { + fxch(); fpop(); + fxch(); fpop(); + } else { + ffree(2); + ffree(1); + } + + testl(tmp2, 1); + jcc(Assembler::zero, done); // X <= 0, Y even: X^Y = abs(X)^Y + // X <= 0, Y even: X^Y = -abs(X)^Y + + fchs(); // Stack: -abs(X)^Y Y + jmp(done); + } + + // slow case: runtime call + bind(slow_case); + + fpop(); // pop incorrect result or int(Y) + + fp_runtime_fallback(is_exp ? CAST_FROM_FN_PTR(address, SharedRuntime::dexp) : CAST_FROM_FN_PTR(address, SharedRuntime::dpow), + is_exp ? 1 : 2, num_fpu_regs_in_use); + + // Come here with result in F-TOS + bind(done); +} + +void MacroAssembler::fpop() { + ffree(); + fincstp(); +} + +void MacroAssembler::fremr(Register tmp) { + save_rax(tmp); + { Label L; + bind(L); + fprem(); + fwait(); fnstsw_ax(); +#ifdef _LP64 + testl(rax, 0x400); + jcc(Assembler::notEqual, L); +#else + sahf(); + jcc(Assembler::parity, L); +#endif // _LP64 + } + restore_rax(tmp); + // Result is in ST0. + // Note: fxch & fpop to get rid of ST1 + // (otherwise FPU stack could overflow eventually) + fxch(1); + fpop(); +} + + +void MacroAssembler::incrementl(AddressLiteral dst) { + if (reachable(dst)) { + incrementl(as_Address(dst)); + } else { + lea(rscratch1, dst); + incrementl(Address(rscratch1, 0)); + } +} + +void MacroAssembler::incrementl(ArrayAddress dst) { + incrementl(as_Address(dst)); +} + +void MacroAssembler::incrementl(Register reg, int value) { + if (value == min_jint) {addl(reg, value) ; return; } + if (value < 0) { decrementl(reg, -value); return; } + if (value == 0) { ; return; } + if (value == 1 && UseIncDec) { incl(reg) ; return; } + /* else */ { addl(reg, value) ; return; } +} + +void MacroAssembler::incrementl(Address dst, int value) { + if (value == min_jint) {addl(dst, value) ; return; } + if (value < 0) { decrementl(dst, -value); return; } + if (value == 0) { ; return; } + if (value == 1 && UseIncDec) { incl(dst) ; return; } + /* else */ { addl(dst, value) ; return; } +} + +void MacroAssembler::jump(AddressLiteral dst) { + if (reachable(dst)) { + jmp_literal(dst.target(), dst.rspec()); + } else { + lea(rscratch1, dst); + jmp(rscratch1); + } +} + +void MacroAssembler::jump_cc(Condition cc, AddressLiteral dst) { + if (reachable(dst)) { + InstructionMark im(this); + relocate(dst.reloc()); + const int short_size = 2; + const int long_size = 6; + int offs = (intptr_t)dst.target() - ((intptr_t)pc()); + if (dst.reloc() == relocInfo::none && is8bit(offs - short_size)) { + // 0111 tttn #8-bit disp + emit_byte(0x70 | cc); + emit_byte((offs - short_size) & 0xFF); + } else { + // 0000 1111 1000 tttn #32-bit disp + emit_byte(0x0F); + emit_byte(0x80 | cc); + emit_long(offs - long_size); + } + } else { +#ifdef ASSERT + warning("reversing conditional branch"); +#endif /* ASSERT */ + Label skip; + jccb(reverse[cc], skip); + lea(rscratch1, dst); + Assembler::jmp(rscratch1); + bind(skip); + } +} + +void MacroAssembler::ldmxcsr(AddressLiteral src) { + if (reachable(src)) { + Assembler::ldmxcsr(as_Address(src)); + } else { + lea(rscratch1, src); + Assembler::ldmxcsr(Address(rscratch1, 0)); + } +} + +int MacroAssembler::load_signed_byte(Register dst, Address src) { + int off; + if (LP64_ONLY(true ||) VM_Version::is_P6()) { + off = offset(); + movsbl(dst, src); // movsxb + } else { + off = load_unsigned_byte(dst, src); + shll(dst, 24); + sarl(dst, 24); + } + return off; +} + +// Note: load_signed_short used to be called load_signed_word. +// Although the 'w' in x86 opcodes refers to the term "word" in the assembler +// manual, which means 16 bits, that usage is found nowhere in HotSpot code. +// The term "word" in HotSpot means a 32- or 64-bit machine word. +int MacroAssembler::load_signed_short(Register dst, Address src) { + int off; + if (LP64_ONLY(true ||) VM_Version::is_P6()) { + // This is dubious to me since it seems safe to do a signed 16 => 64 bit + // version but this is what 64bit has always done. This seems to imply + // that users are only using 32bits worth. + off = offset(); + movswl(dst, src); // movsxw + } else { + off = load_unsigned_short(dst, src); + shll(dst, 16); + sarl(dst, 16); + } + return off; +} + +int MacroAssembler::load_unsigned_byte(Register dst, Address src) { + // According to Intel Doc. AP-526, "Zero-Extension of Short", p.16, + // and "3.9 Partial Register Penalties", p. 22). + int off; + if (LP64_ONLY(true || ) VM_Version::is_P6() || src.uses(dst)) { + off = offset(); + movzbl(dst, src); // movzxb + } else { + xorl(dst, dst); + off = offset(); + movb(dst, src); + } + return off; +} + +// Note: load_unsigned_short used to be called load_unsigned_word. +int MacroAssembler::load_unsigned_short(Register dst, Address src) { + // According to Intel Doc. AP-526, "Zero-Extension of Short", p.16, + // and "3.9 Partial Register Penalties", p. 22). + int off; + if (LP64_ONLY(true ||) VM_Version::is_P6() || src.uses(dst)) { + off = offset(); + movzwl(dst, src); // movzxw + } else { + xorl(dst, dst); + off = offset(); + movw(dst, src); + } + return off; +} + +void MacroAssembler::load_sized_value(Register dst, Address src, size_t size_in_bytes, bool is_signed, Register dst2) { + switch (size_in_bytes) { +#ifndef _LP64 + case 8: + assert(dst2 != noreg, "second dest register required"); + movl(dst, src); + movl(dst2, src.plus_disp(BytesPerInt)); + break; +#else + case 8: movq(dst, src); break; +#endif + case 4: movl(dst, src); break; + case 2: is_signed ? load_signed_short(dst, src) : load_unsigned_short(dst, src); break; + case 1: is_signed ? load_signed_byte( dst, src) : load_unsigned_byte( dst, src); break; + default: ShouldNotReachHere(); + } +} + +void MacroAssembler::store_sized_value(Address dst, Register src, size_t size_in_bytes, Register src2) { + switch (size_in_bytes) { +#ifndef _LP64 + case 8: + assert(src2 != noreg, "second source register required"); + movl(dst, src); + movl(dst.plus_disp(BytesPerInt), src2); + break; +#else + case 8: movq(dst, src); break; +#endif + case 4: movl(dst, src); break; + case 2: movw(dst, src); break; + case 1: movb(dst, src); break; + default: ShouldNotReachHere(); + } +} + +void MacroAssembler::mov32(AddressLiteral dst, Register src) { + if (reachable(dst)) { + movl(as_Address(dst), src); + } else { + lea(rscratch1, dst); + movl(Address(rscratch1, 0), src); + } +} + +void MacroAssembler::mov32(Register dst, AddressLiteral src) { + if (reachable(src)) { + movl(dst, as_Address(src)); + } else { + lea(rscratch1, src); + movl(dst, Address(rscratch1, 0)); + } +} + +// C++ bool manipulation + +void MacroAssembler::movbool(Register dst, Address src) { + if(sizeof(bool) == 1) + movb(dst, src); + else if(sizeof(bool) == 2) + movw(dst, src); + else if(sizeof(bool) == 4) + movl(dst, src); + else + // unsupported + ShouldNotReachHere(); +} + +void MacroAssembler::movbool(Address dst, bool boolconst) { + if(sizeof(bool) == 1) + movb(dst, (int) boolconst); + else if(sizeof(bool) == 2) + movw(dst, (int) boolconst); + else if(sizeof(bool) == 4) + movl(dst, (int) boolconst); + else + // unsupported + ShouldNotReachHere(); +} + +void MacroAssembler::movbool(Address dst, Register src) { + if(sizeof(bool) == 1) + movb(dst, src); + else if(sizeof(bool) == 2) + movw(dst, src); + else if(sizeof(bool) == 4) + movl(dst, src); + else + // unsupported + ShouldNotReachHere(); +} + +void MacroAssembler::movbyte(ArrayAddress dst, int src) { + movb(as_Address(dst), src); +} + +void MacroAssembler::movdl(XMMRegister dst, AddressLiteral src) { + if (reachable(src)) { + movdl(dst, as_Address(src)); + } else { + lea(rscratch1, src); + movdl(dst, Address(rscratch1, 0)); + } +} + +void MacroAssembler::movq(XMMRegister dst, AddressLiteral src) { + if (reachable(src)) { + movq(dst, as_Address(src)); + } else { + lea(rscratch1, src); + movq(dst, Address(rscratch1, 0)); + } +} + +void MacroAssembler::movdbl(XMMRegister dst, AddressLiteral src) { + if (reachable(src)) { + if (UseXmmLoadAndClearUpper) { + movsd (dst, as_Address(src)); + } else { + movlpd(dst, as_Address(src)); + } + } else { + lea(rscratch1, src); + if (UseXmmLoadAndClearUpper) { + movsd (dst, Address(rscratch1, 0)); + } else { + movlpd(dst, Address(rscratch1, 0)); + } + } +} + +void MacroAssembler::movflt(XMMRegister dst, AddressLiteral src) { + if (reachable(src)) { + movss(dst, as_Address(src)); + } else { + lea(rscratch1, src); + movss(dst, Address(rscratch1, 0)); + } +} + +void MacroAssembler::movptr(Register dst, Register src) { + LP64_ONLY(movq(dst, src)) NOT_LP64(movl(dst, src)); +} + +void MacroAssembler::movptr(Register dst, Address src) { + LP64_ONLY(movq(dst, src)) NOT_LP64(movl(dst, src)); +} + +// src should NEVER be a real pointer. Use AddressLiteral for true pointers +void MacroAssembler::movptr(Register dst, intptr_t src) { + LP64_ONLY(mov64(dst, src)) NOT_LP64(movl(dst, src)); +} + +void MacroAssembler::movptr(Address dst, Register src) { + LP64_ONLY(movq(dst, src)) NOT_LP64(movl(dst, src)); +} + +void MacroAssembler::movdqu(XMMRegister dst, AddressLiteral src) { + if (reachable(src)) { + Assembler::movdqu(dst, as_Address(src)); + } else { + lea(rscratch1, src); + Assembler::movdqu(dst, Address(rscratch1, 0)); + } +} + +void MacroAssembler::movsd(XMMRegister dst, AddressLiteral src) { + if (reachable(src)) { + Assembler::movsd(dst, as_Address(src)); + } else { + lea(rscratch1, src); + Assembler::movsd(dst, Address(rscratch1, 0)); + } +} + +void MacroAssembler::movss(XMMRegister dst, AddressLiteral src) { + if (reachable(src)) { + Assembler::movss(dst, as_Address(src)); + } else { + lea(rscratch1, src); + Assembler::movss(dst, Address(rscratch1, 0)); + } +} + +void MacroAssembler::mulsd(XMMRegister dst, AddressLiteral src) { + if (reachable(src)) { + Assembler::mulsd(dst, as_Address(src)); + } else { + lea(rscratch1, src); + Assembler::mulsd(dst, Address(rscratch1, 0)); + } +} + +void MacroAssembler::mulss(XMMRegister dst, AddressLiteral src) { + if (reachable(src)) { + Assembler::mulss(dst, as_Address(src)); + } else { + lea(rscratch1, src); + Assembler::mulss(dst, Address(rscratch1, 0)); + } +} + +void MacroAssembler::null_check(Register reg, int offset) { + if (needs_explicit_null_check(offset)) { + // provoke OS NULL exception if reg = NULL by + // accessing M[reg] w/o changing any (non-CC) registers + // NOTE: cmpl is plenty here to provoke a segv + cmpptr(rax, Address(reg, 0)); + // Note: should probably use testl(rax, Address(reg, 0)); + // may be shorter code (however, this version of + // testl needs to be implemented first) + } else { + // nothing to do, (later) access of M[reg + offset] + // will provoke OS NULL exception if reg = NULL + } +} + +void MacroAssembler::os_breakpoint() { + // instead of directly emitting a breakpoint, call os:breakpoint for better debugability + // (e.g., MSVC can't call ps() otherwise) + call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); +} + +void MacroAssembler::pop_CPU_state() { + pop_FPU_state(); + pop_IU_state(); +} + +void MacroAssembler::pop_FPU_state() { + NOT_LP64(frstor(Address(rsp, 0));) + LP64_ONLY(fxrstor(Address(rsp, 0));) + addptr(rsp, FPUStateSizeInWords * wordSize); +} + +void MacroAssembler::pop_IU_state() { + popa(); + LP64_ONLY(addq(rsp, 8)); + popf(); +} + +// Save Integer and Float state +// Warning: Stack must be 16 byte aligned (64bit) +void MacroAssembler::push_CPU_state() { + push_IU_state(); + push_FPU_state(); +} + +void MacroAssembler::push_FPU_state() { + subptr(rsp, FPUStateSizeInWords * wordSize); +#ifndef _LP64 + fnsave(Address(rsp, 0)); + fwait(); +#else + fxsave(Address(rsp, 0)); +#endif // LP64 +} + +void MacroAssembler::push_IU_state() { + // Push flags first because pusha kills them + pushf(); + // Make sure rsp stays 16-byte aligned + LP64_ONLY(subq(rsp, 8)); + pusha(); +} + +void MacroAssembler::reset_last_Java_frame(Register java_thread, bool clear_fp, bool clear_pc) { + // determine java_thread register + if (!java_thread->is_valid()) { + java_thread = rdi; + get_thread(java_thread); + } + // we must set sp to zero to clear frame + movptr(Address(java_thread, JavaThread::last_Java_sp_offset()), NULL_WORD); + if (clear_fp) { + movptr(Address(java_thread, JavaThread::last_Java_fp_offset()), NULL_WORD); + } + + if (clear_pc) + movptr(Address(java_thread, JavaThread::last_Java_pc_offset()), NULL_WORD); + +} + +void MacroAssembler::restore_rax(Register tmp) { + if (tmp == noreg) pop(rax); + else if (tmp != rax) mov(rax, tmp); +} + +void MacroAssembler::round_to(Register reg, int modulus) { + addptr(reg, modulus - 1); + andptr(reg, -modulus); +} + +void MacroAssembler::save_rax(Register tmp) { + if (tmp == noreg) push(rax); + else if (tmp != rax) mov(tmp, rax); +} + +// Write serialization page so VM thread can do a pseudo remote membar. +// We use the current thread pointer to calculate a thread specific +// offset to write to within the page. This minimizes bus traffic +// due to cache line collision. +void MacroAssembler::serialize_memory(Register thread, Register tmp) { + movl(tmp, thread); + shrl(tmp, os::get_serialize_page_shift_count()); + andl(tmp, (os::vm_page_size() - sizeof(int))); + + Address index(noreg, tmp, Address::times_1); + ExternalAddress page(os::get_memory_serialize_page()); + + // Size of store must match masking code above + movl(as_Address(ArrayAddress(page, index)), tmp); +} + +// Calls to C land +// +// When entering C land, the rbp, & rsp of the last Java frame have to be recorded +// in the (thread-local) JavaThread object. When leaving C land, the last Java fp +// has to be reset to 0. This is required to allow proper stack traversal. +void MacroAssembler::set_last_Java_frame(Register java_thread, + Register last_java_sp, + Register last_java_fp, + address last_java_pc) { + // determine java_thread register + if (!java_thread->is_valid()) { + java_thread = rdi; + get_thread(java_thread); + } + // determine last_java_sp register + if (!last_java_sp->is_valid()) { + last_java_sp = rsp; + } + + // last_java_fp is optional + + if (last_java_fp->is_valid()) { + movptr(Address(java_thread, JavaThread::last_Java_fp_offset()), last_java_fp); + } + + // last_java_pc is optional + + if (last_java_pc != NULL) { + lea(Address(java_thread, + JavaThread::frame_anchor_offset() + JavaFrameAnchor::last_Java_pc_offset()), + InternalAddress(last_java_pc)); + + } + movptr(Address(java_thread, JavaThread::last_Java_sp_offset()), last_java_sp); +} + +void MacroAssembler::shlptr(Register dst, int imm8) { + LP64_ONLY(shlq(dst, imm8)) NOT_LP64(shll(dst, imm8)); +} + +void MacroAssembler::shrptr(Register dst, int imm8) { + LP64_ONLY(shrq(dst, imm8)) NOT_LP64(shrl(dst, imm8)); +} + +void MacroAssembler::sign_extend_byte(Register reg) { + if (LP64_ONLY(true ||) (VM_Version::is_P6() && reg->has_byte_register())) { + movsbl(reg, reg); // movsxb + } else { + shll(reg, 24); + sarl(reg, 24); + } +} + +void MacroAssembler::sign_extend_short(Register reg) { + if (LP64_ONLY(true ||) VM_Version::is_P6()) { + movswl(reg, reg); // movsxw + } else { + shll(reg, 16); + sarl(reg, 16); + } +} + +void MacroAssembler::testl(Register dst, AddressLiteral src) { + assert(reachable(src), "Address should be reachable"); + testl(dst, as_Address(src)); +} + +void MacroAssembler::sqrtsd(XMMRegister dst, AddressLiteral src) { + if (reachable(src)) { + Assembler::sqrtsd(dst, as_Address(src)); + } else { + lea(rscratch1, src); + Assembler::sqrtsd(dst, Address(rscratch1, 0)); + } +} + +void MacroAssembler::sqrtss(XMMRegister dst, AddressLiteral src) { + if (reachable(src)) { + Assembler::sqrtss(dst, as_Address(src)); + } else { + lea(rscratch1, src); + Assembler::sqrtss(dst, Address(rscratch1, 0)); + } +} + +void MacroAssembler::subsd(XMMRegister dst, AddressLiteral src) { + if (reachable(src)) { + Assembler::subsd(dst, as_Address(src)); + } else { + lea(rscratch1, src); + Assembler::subsd(dst, Address(rscratch1, 0)); + } +} + +void MacroAssembler::subss(XMMRegister dst, AddressLiteral src) { + if (reachable(src)) { + Assembler::subss(dst, as_Address(src)); + } else { + lea(rscratch1, src); + Assembler::subss(dst, Address(rscratch1, 0)); + } +} + +void MacroAssembler::ucomisd(XMMRegister dst, AddressLiteral src) { + if (reachable(src)) { + Assembler::ucomisd(dst, as_Address(src)); + } else { + lea(rscratch1, src); + Assembler::ucomisd(dst, Address(rscratch1, 0)); + } +} + +void MacroAssembler::ucomiss(XMMRegister dst, AddressLiteral src) { + if (reachable(src)) { + Assembler::ucomiss(dst, as_Address(src)); + } else { + lea(rscratch1, src); + Assembler::ucomiss(dst, Address(rscratch1, 0)); + } +} + +void MacroAssembler::xorpd(XMMRegister dst, AddressLiteral src) { + // Used in sign-bit flipping with aligned address. + assert((UseAVX > 0) || (((intptr_t)src.target() & 15) == 0), "SSE mode requires address alignment 16 bytes"); + if (reachable(src)) { + Assembler::xorpd(dst, as_Address(src)); + } else { + lea(rscratch1, src); + Assembler::xorpd(dst, Address(rscratch1, 0)); + } +} + +void MacroAssembler::xorps(XMMRegister dst, AddressLiteral src) { + // Used in sign-bit flipping with aligned address. + assert((UseAVX > 0) || (((intptr_t)src.target() & 15) == 0), "SSE mode requires address alignment 16 bytes"); + if (reachable(src)) { + Assembler::xorps(dst, as_Address(src)); + } else { + lea(rscratch1, src); + Assembler::xorps(dst, Address(rscratch1, 0)); + } +} + +void MacroAssembler::pshufb(XMMRegister dst, AddressLiteral src) { + // Used in sign-bit flipping with aligned address. + assert((UseAVX > 0) || (((intptr_t)src.target() & 15) == 0), "SSE mode requires address alignment 16 bytes"); + if (reachable(src)) { + Assembler::pshufb(dst, as_Address(src)); + } else { + lea(rscratch1, src); + Assembler::pshufb(dst, Address(rscratch1, 0)); + } +} + +// AVX 3-operands instructions + +void MacroAssembler::vaddsd(XMMRegister dst, XMMRegister nds, AddressLiteral src) { + if (reachable(src)) { + vaddsd(dst, nds, as_Address(src)); + } else { + lea(rscratch1, src); + vaddsd(dst, nds, Address(rscratch1, 0)); + } +} + +void MacroAssembler::vaddss(XMMRegister dst, XMMRegister nds, AddressLiteral src) { + if (reachable(src)) { + vaddss(dst, nds, as_Address(src)); + } else { + lea(rscratch1, src); + vaddss(dst, nds, Address(rscratch1, 0)); + } +} + +void MacroAssembler::vandpd(XMMRegister dst, XMMRegister nds, AddressLiteral src, bool vector256) { + if (reachable(src)) { + vandpd(dst, nds, as_Address(src), vector256); + } else { + lea(rscratch1, src); + vandpd(dst, nds, Address(rscratch1, 0), vector256); + } +} + +void MacroAssembler::vandps(XMMRegister dst, XMMRegister nds, AddressLiteral src, bool vector256) { + if (reachable(src)) { + vandps(dst, nds, as_Address(src), vector256); + } else { + lea(rscratch1, src); + vandps(dst, nds, Address(rscratch1, 0), vector256); + } +} + +void MacroAssembler::vdivsd(XMMRegister dst, XMMRegister nds, AddressLiteral src) { + if (reachable(src)) { + vdivsd(dst, nds, as_Address(src)); + } else { + lea(rscratch1, src); + vdivsd(dst, nds, Address(rscratch1, 0)); + } +} + +void MacroAssembler::vdivss(XMMRegister dst, XMMRegister nds, AddressLiteral src) { + if (reachable(src)) { + vdivss(dst, nds, as_Address(src)); + } else { + lea(rscratch1, src); + vdivss(dst, nds, Address(rscratch1, 0)); + } +} + +void MacroAssembler::vmulsd(XMMRegister dst, XMMRegister nds, AddressLiteral src) { + if (reachable(src)) { + vmulsd(dst, nds, as_Address(src)); + } else { + lea(rscratch1, src); + vmulsd(dst, nds, Address(rscratch1, 0)); + } +} + +void MacroAssembler::vmulss(XMMRegister dst, XMMRegister nds, AddressLiteral src) { + if (reachable(src)) { + vmulss(dst, nds, as_Address(src)); + } else { + lea(rscratch1, src); + vmulss(dst, nds, Address(rscratch1, 0)); + } +} + +void MacroAssembler::vsubsd(XMMRegister dst, XMMRegister nds, AddressLiteral src) { + if (reachable(src)) { + vsubsd(dst, nds, as_Address(src)); + } else { + lea(rscratch1, src); + vsubsd(dst, nds, Address(rscratch1, 0)); + } +} + +void MacroAssembler::vsubss(XMMRegister dst, XMMRegister nds, AddressLiteral src) { + if (reachable(src)) { + vsubss(dst, nds, as_Address(src)); + } else { + lea(rscratch1, src); + vsubss(dst, nds, Address(rscratch1, 0)); + } +} + +void MacroAssembler::vxorpd(XMMRegister dst, XMMRegister nds, AddressLiteral src, bool vector256) { + if (reachable(src)) { + vxorpd(dst, nds, as_Address(src), vector256); + } else { + lea(rscratch1, src); + vxorpd(dst, nds, Address(rscratch1, 0), vector256); + } +} + +void MacroAssembler::vxorps(XMMRegister dst, XMMRegister nds, AddressLiteral src, bool vector256) { + if (reachable(src)) { + vxorps(dst, nds, as_Address(src), vector256); + } else { + lea(rscratch1, src); + vxorps(dst, nds, Address(rscratch1, 0), vector256); + } +} + + +////////////////////////////////////////////////////////////////////////////////// +#ifndef SERIALGC + +void MacroAssembler::g1_write_barrier_pre(Register obj, + Register pre_val, + Register thread, + Register tmp, + bool tosca_live, + bool expand_call) { + + // If expand_call is true then we expand the call_VM_leaf macro + // directly to skip generating the check by + // InterpreterMacroAssembler::call_VM_leaf_base that checks _last_sp. + +#ifdef _LP64 + assert(thread == r15_thread, "must be"); +#endif // _LP64 + + Label done; + Label runtime; + + assert(pre_val != noreg, "check this code"); + + if (obj != noreg) { + assert_different_registers(obj, pre_val, tmp); + assert(pre_val != rax, "check this code"); + } + + Address in_progress(thread, in_bytes(JavaThread::satb_mark_queue_offset() + + PtrQueue::byte_offset_of_active())); + Address index(thread, in_bytes(JavaThread::satb_mark_queue_offset() + + PtrQueue::byte_offset_of_index())); + Address buffer(thread, in_bytes(JavaThread::satb_mark_queue_offset() + + PtrQueue::byte_offset_of_buf())); + + + // Is marking active? + if (in_bytes(PtrQueue::byte_width_of_active()) == 4) { + cmpl(in_progress, 0); + } else { + assert(in_bytes(PtrQueue::byte_width_of_active()) == 1, "Assumption"); + cmpb(in_progress, 0); + } + jcc(Assembler::equal, done); + + // Do we need to load the previous value? + if (obj != noreg) { + load_heap_oop(pre_val, Address(obj, 0)); + } + + // Is the previous value null? + cmpptr(pre_val, (int32_t) NULL_WORD); + jcc(Assembler::equal, done); + + // Can we store original value in the thread's buffer? + // Is index == 0? + // (The index field is typed as size_t.) + + movptr(tmp, index); // tmp := *index_adr + cmpptr(tmp, 0); // tmp == 0? + jcc(Assembler::equal, runtime); // If yes, goto runtime + + subptr(tmp, wordSize); // tmp := tmp - wordSize + movptr(index, tmp); // *index_adr := tmp + addptr(tmp, buffer); // tmp := tmp + *buffer_adr + + // Record the previous value + movptr(Address(tmp, 0), pre_val); + jmp(done); + + bind(runtime); + // save the live input values + if(tosca_live) push(rax); + + if (obj != noreg && obj != rax) + push(obj); + + if (pre_val != rax) + push(pre_val); + + // Calling the runtime using the regular call_VM_leaf mechanism generates + // code (generated by InterpreterMacroAssember::call_VM_leaf_base) + // that checks that the *(ebp+frame::interpreter_frame_last_sp) == NULL. + // + // If we care generating the pre-barrier without a frame (e.g. in the + // intrinsified Reference.get() routine) then ebp might be pointing to + // the caller frame and so this check will most likely fail at runtime. + // + // Expanding the call directly bypasses the generation of the check. + // So when we do not have have a full interpreter frame on the stack + // expand_call should be passed true. + + NOT_LP64( push(thread); ) + + if (expand_call) { + LP64_ONLY( assert(pre_val != c_rarg1, "smashed arg"); ) + pass_arg1(this, thread); + pass_arg0(this, pre_val); + MacroAssembler::call_VM_leaf_base(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), 2); + } else { + call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), pre_val, thread); + } + + NOT_LP64( pop(thread); ) + + // save the live input values + if (pre_val != rax) + pop(pre_val); + + if (obj != noreg && obj != rax) + pop(obj); + + if(tosca_live) pop(rax); + + bind(done); +} + +void MacroAssembler::g1_write_barrier_post(Register store_addr, + Register new_val, + Register thread, + Register tmp, + Register tmp2) { +#ifdef _LP64 + assert(thread == r15_thread, "must be"); +#endif // _LP64 + + Address queue_index(thread, in_bytes(JavaThread::dirty_card_queue_offset() + + PtrQueue::byte_offset_of_index())); + Address buffer(thread, in_bytes(JavaThread::dirty_card_queue_offset() + + PtrQueue::byte_offset_of_buf())); + + BarrierSet* bs = Universe::heap()->barrier_set(); + CardTableModRefBS* ct = (CardTableModRefBS*)bs; + Label done; + Label runtime; + + // Does store cross heap regions? + + movptr(tmp, store_addr); + xorptr(tmp, new_val); + shrptr(tmp, HeapRegion::LogOfHRGrainBytes); + jcc(Assembler::equal, done); + + // crosses regions, storing NULL? + + cmpptr(new_val, (int32_t) NULL_WORD); + jcc(Assembler::equal, done); + + // storing region crossing non-NULL, is card already dirty? + + ExternalAddress cardtable((address) ct->byte_map_base); + assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code"); +#ifdef _LP64 + const Register card_addr = tmp; + + movq(card_addr, store_addr); + shrq(card_addr, CardTableModRefBS::card_shift); + + lea(tmp2, cardtable); + + // get the address of the card + addq(card_addr, tmp2); +#else + const Register card_index = tmp; + + movl(card_index, store_addr); + shrl(card_index, CardTableModRefBS::card_shift); + + Address index(noreg, card_index, Address::times_1); + const Register card_addr = tmp; + lea(card_addr, as_Address(ArrayAddress(cardtable, index))); +#endif + cmpb(Address(card_addr, 0), 0); + jcc(Assembler::equal, done); + + // storing a region crossing, non-NULL oop, card is clean. + // dirty card and log. + + movb(Address(card_addr, 0), 0); + + cmpl(queue_index, 0); + jcc(Assembler::equal, runtime); + subl(queue_index, wordSize); + movptr(tmp2, buffer); +#ifdef _LP64 + movslq(rscratch1, queue_index); + addq(tmp2, rscratch1); + movq(Address(tmp2, 0), card_addr); +#else + addl(tmp2, queue_index); + movl(Address(tmp2, 0), card_index); +#endif + jmp(done); + + bind(runtime); + // save the live input values + push(store_addr); + push(new_val); +#ifdef _LP64 + call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), card_addr, r15_thread); +#else + push(thread); + call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), card_addr, thread); + pop(thread); +#endif + pop(new_val); + pop(store_addr); + + bind(done); +} + +#endif // SERIALGC +////////////////////////////////////////////////////////////////////////////////// + + +void MacroAssembler::store_check(Register obj) { + // Does a store check for the oop in register obj. The content of + // register obj is destroyed afterwards. + store_check_part_1(obj); + store_check_part_2(obj); +} + +void MacroAssembler::store_check(Register obj, Address dst) { + store_check(obj); +} + + +// split the store check operation so that other instructions can be scheduled inbetween +void MacroAssembler::store_check_part_1(Register obj) { + BarrierSet* bs = Universe::heap()->barrier_set(); + assert(bs->kind() == BarrierSet::CardTableModRef, "Wrong barrier set kind"); + shrptr(obj, CardTableModRefBS::card_shift); +} + +void MacroAssembler::store_check_part_2(Register obj) { + BarrierSet* bs = Universe::heap()->barrier_set(); + assert(bs->kind() == BarrierSet::CardTableModRef, "Wrong barrier set kind"); + CardTableModRefBS* ct = (CardTableModRefBS*)bs; + assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code"); + + // The calculation for byte_map_base is as follows: + // byte_map_base = _byte_map - (uintptr_t(low_bound) >> card_shift); + // So this essentially converts an address to a displacement and + // it will never need to be relocated. On 64bit however the value may be too + // large for a 32bit displacement + + intptr_t disp = (intptr_t) ct->byte_map_base; + if (is_simm32(disp)) { + Address cardtable(noreg, obj, Address::times_1, disp); + movb(cardtable, 0); + } else { + // By doing it as an ExternalAddress disp could be converted to a rip-relative + // displacement and done in a single instruction given favorable mapping and + // a smarter version of as_Address. Worst case it is two instructions which + // is no worse off then loading disp into a register and doing as a simple + // Address() as above. + // We can't do as ExternalAddress as the only style since if disp == 0 we'll + // assert since NULL isn't acceptable in a reloci (see 6644928). In any case + // in some cases we'll get a single instruction version. + + ExternalAddress cardtable((address)disp); + Address index(noreg, obj, Address::times_1); + movb(as_Address(ArrayAddress(cardtable, index)), 0); + } +} + +void MacroAssembler::subptr(Register dst, int32_t imm32) { + LP64_ONLY(subq(dst, imm32)) NOT_LP64(subl(dst, imm32)); +} + +// Force generation of a 4 byte immediate value even if it fits into 8bit +void MacroAssembler::subptr_imm32(Register dst, int32_t imm32) { + LP64_ONLY(subq_imm32(dst, imm32)) NOT_LP64(subl_imm32(dst, imm32)); +} + +void MacroAssembler::subptr(Register dst, Register src) { + LP64_ONLY(subq(dst, src)) NOT_LP64(subl(dst, src)); +} + +// C++ bool manipulation +void MacroAssembler::testbool(Register dst) { + if(sizeof(bool) == 1) + testb(dst, 0xff); + else if(sizeof(bool) == 2) { + // testw implementation needed for two byte bools + ShouldNotReachHere(); + } else if(sizeof(bool) == 4) + testl(dst, dst); + else + // unsupported + ShouldNotReachHere(); +} + +void MacroAssembler::testptr(Register dst, Register src) { + LP64_ONLY(testq(dst, src)) NOT_LP64(testl(dst, src)); +} + +// Defines obj, preserves var_size_in_bytes, okay for t2 == var_size_in_bytes. +void MacroAssembler::tlab_allocate(Register obj, + Register var_size_in_bytes, + int con_size_in_bytes, + Register t1, + Register t2, + Label& slow_case) { + assert_different_registers(obj, t1, t2); + assert_different_registers(obj, var_size_in_bytes, t1); + Register end = t2; + Register thread = NOT_LP64(t1) LP64_ONLY(r15_thread); + + verify_tlab(); + + NOT_LP64(get_thread(thread)); + + movptr(obj, Address(thread, JavaThread::tlab_top_offset())); + if (var_size_in_bytes == noreg) { + lea(end, Address(obj, con_size_in_bytes)); + } else { + lea(end, Address(obj, var_size_in_bytes, Address::times_1)); + } + cmpptr(end, Address(thread, JavaThread::tlab_end_offset())); + jcc(Assembler::above, slow_case); + + // update the tlab top pointer + movptr(Address(thread, JavaThread::tlab_top_offset()), end); + + // recover var_size_in_bytes if necessary + if (var_size_in_bytes == end) { + subptr(var_size_in_bytes, obj); + } + verify_tlab(); +} + +// Preserves rbx, and rdx. +Register MacroAssembler::tlab_refill(Label& retry, + Label& try_eden, + Label& slow_case) { + Register top = rax; + Register t1 = rcx; + Register t2 = rsi; + Register thread_reg = NOT_LP64(rdi) LP64_ONLY(r15_thread); + assert_different_registers(top, thread_reg, t1, t2, /* preserve: */ rbx, rdx); + Label do_refill, discard_tlab; + + if (CMSIncrementalMode || !Universe::heap()->supports_inline_contig_alloc()) { + // No allocation in the shared eden. + jmp(slow_case); + } + + NOT_LP64(get_thread(thread_reg)); + + movptr(top, Address(thread_reg, in_bytes(JavaThread::tlab_top_offset()))); + movptr(t1, Address(thread_reg, in_bytes(JavaThread::tlab_end_offset()))); + + // calculate amount of free space + subptr(t1, top); + shrptr(t1, LogHeapWordSize); + + // Retain tlab and allocate object in shared space if + // the amount free in the tlab is too large to discard. + cmpptr(t1, Address(thread_reg, in_bytes(JavaThread::tlab_refill_waste_limit_offset()))); + jcc(Assembler::lessEqual, discard_tlab); + + // Retain + // %%% yuck as movptr... + movptr(t2, (int32_t) ThreadLocalAllocBuffer::refill_waste_limit_increment()); + addptr(Address(thread_reg, in_bytes(JavaThread::tlab_refill_waste_limit_offset())), t2); + if (TLABStats) { + // increment number of slow_allocations + addl(Address(thread_reg, in_bytes(JavaThread::tlab_slow_allocations_offset())), 1); + } + jmp(try_eden); + + bind(discard_tlab); + if (TLABStats) { + // increment number of refills + addl(Address(thread_reg, in_bytes(JavaThread::tlab_number_of_refills_offset())), 1); + // accumulate wastage -- t1 is amount free in tlab + addl(Address(thread_reg, in_bytes(JavaThread::tlab_fast_refill_waste_offset())), t1); + } + + // if tlab is currently allocated (top or end != null) then + // fill [top, end + alignment_reserve) with array object + testptr(top, top); + jcc(Assembler::zero, do_refill); + + // set up the mark word + movptr(Address(top, oopDesc::mark_offset_in_bytes()), (intptr_t)markOopDesc::prototype()->copy_set_hash(0x2)); + // set the length to the remaining space + subptr(t1, typeArrayOopDesc::header_size(T_INT)); + addptr(t1, (int32_t)ThreadLocalAllocBuffer::alignment_reserve()); + shlptr(t1, log2_intptr(HeapWordSize/sizeof(jint))); + movl(Address(top, arrayOopDesc::length_offset_in_bytes()), t1); + // set klass to intArrayKlass + // dubious reloc why not an oop reloc? + movptr(t1, ExternalAddress((address)Universe::intArrayKlassObj_addr())); + // store klass last. concurrent gcs assumes klass length is valid if + // klass field is not null. + store_klass(top, t1); + + movptr(t1, top); + subptr(t1, Address(thread_reg, in_bytes(JavaThread::tlab_start_offset()))); + incr_allocated_bytes(thread_reg, t1, 0); + + // refill the tlab with an eden allocation + bind(do_refill); + movptr(t1, Address(thread_reg, in_bytes(JavaThread::tlab_size_offset()))); + shlptr(t1, LogHeapWordSize); + // allocate new tlab, address returned in top + eden_allocate(top, t1, 0, t2, slow_case); + + // Check that t1 was preserved in eden_allocate. +#ifdef ASSERT + if (UseTLAB) { + Label ok; + Register tsize = rsi; + assert_different_registers(tsize, thread_reg, t1); + push(tsize); + movptr(tsize, Address(thread_reg, in_bytes(JavaThread::tlab_size_offset()))); + shlptr(tsize, LogHeapWordSize); + cmpptr(t1, tsize); + jcc(Assembler::equal, ok); + STOP("assert(t1 != tlab size)"); + should_not_reach_here(); + + bind(ok); + pop(tsize); + } +#endif + movptr(Address(thread_reg, in_bytes(JavaThread::tlab_start_offset())), top); + movptr(Address(thread_reg, in_bytes(JavaThread::tlab_top_offset())), top); + addptr(top, t1); + subptr(top, (int32_t)ThreadLocalAllocBuffer::alignment_reserve_in_bytes()); + movptr(Address(thread_reg, in_bytes(JavaThread::tlab_end_offset())), top); + verify_tlab(); + jmp(retry); + + return thread_reg; // for use by caller +} + +void MacroAssembler::incr_allocated_bytes(Register thread, + Register var_size_in_bytes, + int con_size_in_bytes, + Register t1) { + if (!thread->is_valid()) { +#ifdef _LP64 + thread = r15_thread; +#else + assert(t1->is_valid(), "need temp reg"); + thread = t1; + get_thread(thread); +#endif + } + +#ifdef _LP64 + if (var_size_in_bytes->is_valid()) { + addq(Address(thread, in_bytes(JavaThread::allocated_bytes_offset())), var_size_in_bytes); + } else { + addq(Address(thread, in_bytes(JavaThread::allocated_bytes_offset())), con_size_in_bytes); + } +#else + if (var_size_in_bytes->is_valid()) { + addl(Address(thread, in_bytes(JavaThread::allocated_bytes_offset())), var_size_in_bytes); + } else { + addl(Address(thread, in_bytes(JavaThread::allocated_bytes_offset())), con_size_in_bytes); + } + adcl(Address(thread, in_bytes(JavaThread::allocated_bytes_offset())+4), 0); +#endif +} + +void MacroAssembler::fp_runtime_fallback(address runtime_entry, int nb_args, int num_fpu_regs_in_use) { + pusha(); + + // if we are coming from c1, xmm registers may be live + int off = 0; + if (UseSSE == 1) { + subptr(rsp, sizeof(jdouble)*8); + movflt(Address(rsp,off++*sizeof(jdouble)),xmm0); + movflt(Address(rsp,off++*sizeof(jdouble)),xmm1); + movflt(Address(rsp,off++*sizeof(jdouble)),xmm2); + movflt(Address(rsp,off++*sizeof(jdouble)),xmm3); + movflt(Address(rsp,off++*sizeof(jdouble)),xmm4); + movflt(Address(rsp,off++*sizeof(jdouble)),xmm5); + movflt(Address(rsp,off++*sizeof(jdouble)),xmm6); + movflt(Address(rsp,off++*sizeof(jdouble)),xmm7); + } else if (UseSSE >= 2) { +#ifdef COMPILER2 + if (MaxVectorSize > 16) { + assert(UseAVX > 0, "256bit vectors are supported only with AVX"); + // Save upper half of YMM registes + subptr(rsp, 16 * LP64_ONLY(16) NOT_LP64(8)); + vextractf128h(Address(rsp, 0),xmm0); + vextractf128h(Address(rsp, 16),xmm1); + vextractf128h(Address(rsp, 32),xmm2); + vextractf128h(Address(rsp, 48),xmm3); + vextractf128h(Address(rsp, 64),xmm4); + vextractf128h(Address(rsp, 80),xmm5); + vextractf128h(Address(rsp, 96),xmm6); + vextractf128h(Address(rsp,112),xmm7); +#ifdef _LP64 + vextractf128h(Address(rsp,128),xmm8); + vextractf128h(Address(rsp,144),xmm9); + vextractf128h(Address(rsp,160),xmm10); + vextractf128h(Address(rsp,176),xmm11); + vextractf128h(Address(rsp,192),xmm12); + vextractf128h(Address(rsp,208),xmm13); + vextractf128h(Address(rsp,224),xmm14); + vextractf128h(Address(rsp,240),xmm15); +#endif + } +#endif + // Save whole 128bit (16 bytes) XMM regiters + subptr(rsp, 16 * LP64_ONLY(16) NOT_LP64(8)); + movdqu(Address(rsp,off++*16),xmm0); + movdqu(Address(rsp,off++*16),xmm1); + movdqu(Address(rsp,off++*16),xmm2); + movdqu(Address(rsp,off++*16),xmm3); + movdqu(Address(rsp,off++*16),xmm4); + movdqu(Address(rsp,off++*16),xmm5); + movdqu(Address(rsp,off++*16),xmm6); + movdqu(Address(rsp,off++*16),xmm7); +#ifdef _LP64 + movdqu(Address(rsp,off++*16),xmm8); + movdqu(Address(rsp,off++*16),xmm9); + movdqu(Address(rsp,off++*16),xmm10); + movdqu(Address(rsp,off++*16),xmm11); + movdqu(Address(rsp,off++*16),xmm12); + movdqu(Address(rsp,off++*16),xmm13); + movdqu(Address(rsp,off++*16),xmm14); + movdqu(Address(rsp,off++*16),xmm15); +#endif + } + + // Preserve registers across runtime call + int incoming_argument_and_return_value_offset = -1; + if (num_fpu_regs_in_use > 1) { + // Must preserve all other FPU regs (could alternatively convert + // SharedRuntime::dsin, dcos etc. into assembly routines known not to trash + // FPU state, but can not trust C compiler) + NEEDS_CLEANUP; + // NOTE that in this case we also push the incoming argument(s) to + // the stack and restore it later; we also use this stack slot to + // hold the return value from dsin, dcos etc. + for (int i = 0; i < num_fpu_regs_in_use; i++) { + subptr(rsp, sizeof(jdouble)); + fstp_d(Address(rsp, 0)); + } + incoming_argument_and_return_value_offset = sizeof(jdouble)*(num_fpu_regs_in_use-1); + for (int i = nb_args-1; i >= 0; i--) { + fld_d(Address(rsp, incoming_argument_and_return_value_offset-i*sizeof(jdouble))); + } + } + + subptr(rsp, nb_args*sizeof(jdouble)); + for (int i = 0; i < nb_args; i++) { + fstp_d(Address(rsp, i*sizeof(jdouble))); + } + +#ifdef _LP64 + if (nb_args > 0) { + movdbl(xmm0, Address(rsp, 0)); + } + if (nb_args > 1) { + movdbl(xmm1, Address(rsp, sizeof(jdouble))); + } + assert(nb_args <= 2, "unsupported number of args"); +#endif // _LP64 + + // NOTE: we must not use call_VM_leaf here because that requires a + // complete interpreter frame in debug mode -- same bug as 4387334 + // MacroAssembler::call_VM_leaf_base is perfectly safe and will + // do proper 64bit abi + + NEEDS_CLEANUP; + // Need to add stack banging before this runtime call if it needs to + // be taken; however, there is no generic stack banging routine at + // the MacroAssembler level + + MacroAssembler::call_VM_leaf_base(runtime_entry, 0); + +#ifdef _LP64 + movsd(Address(rsp, 0), xmm0); + fld_d(Address(rsp, 0)); +#endif // _LP64 + addptr(rsp, sizeof(jdouble) * nb_args); + if (num_fpu_regs_in_use > 1) { + // Must save return value to stack and then restore entire FPU + // stack except incoming arguments + fstp_d(Address(rsp, incoming_argument_and_return_value_offset)); + for (int i = 0; i < num_fpu_regs_in_use - nb_args; i++) { + fld_d(Address(rsp, 0)); + addptr(rsp, sizeof(jdouble)); + } + fld_d(Address(rsp, (nb_args-1)*sizeof(jdouble))); + addptr(rsp, sizeof(jdouble) * nb_args); + } + + off = 0; + if (UseSSE == 1) { + movflt(xmm0, Address(rsp,off++*sizeof(jdouble))); + movflt(xmm1, Address(rsp,off++*sizeof(jdouble))); + movflt(xmm2, Address(rsp,off++*sizeof(jdouble))); + movflt(xmm3, Address(rsp,off++*sizeof(jdouble))); + movflt(xmm4, Address(rsp,off++*sizeof(jdouble))); + movflt(xmm5, Address(rsp,off++*sizeof(jdouble))); + movflt(xmm6, Address(rsp,off++*sizeof(jdouble))); + movflt(xmm7, Address(rsp,off++*sizeof(jdouble))); + addptr(rsp, sizeof(jdouble)*8); + } else if (UseSSE >= 2) { + // Restore whole 128bit (16 bytes) XMM regiters + movdqu(xmm0, Address(rsp,off++*16)); + movdqu(xmm1, Address(rsp,off++*16)); + movdqu(xmm2, Address(rsp,off++*16)); + movdqu(xmm3, Address(rsp,off++*16)); + movdqu(xmm4, Address(rsp,off++*16)); + movdqu(xmm5, Address(rsp,off++*16)); + movdqu(xmm6, Address(rsp,off++*16)); + movdqu(xmm7, Address(rsp,off++*16)); +#ifdef _LP64 + movdqu(xmm8, Address(rsp,off++*16)); + movdqu(xmm9, Address(rsp,off++*16)); + movdqu(xmm10, Address(rsp,off++*16)); + movdqu(xmm11, Address(rsp,off++*16)); + movdqu(xmm12, Address(rsp,off++*16)); + movdqu(xmm13, Address(rsp,off++*16)); + movdqu(xmm14, Address(rsp,off++*16)); + movdqu(xmm15, Address(rsp,off++*16)); +#endif + addptr(rsp, 16 * LP64_ONLY(16) NOT_LP64(8)); +#ifdef COMPILER2 + if (MaxVectorSize > 16) { + // Restore upper half of YMM registes. + vinsertf128h(xmm0, Address(rsp, 0)); + vinsertf128h(xmm1, Address(rsp, 16)); + vinsertf128h(xmm2, Address(rsp, 32)); + vinsertf128h(xmm3, Address(rsp, 48)); + vinsertf128h(xmm4, Address(rsp, 64)); + vinsertf128h(xmm5, Address(rsp, 80)); + vinsertf128h(xmm6, Address(rsp, 96)); + vinsertf128h(xmm7, Address(rsp,112)); +#ifdef _LP64 + vinsertf128h(xmm8, Address(rsp,128)); + vinsertf128h(xmm9, Address(rsp,144)); + vinsertf128h(xmm10, Address(rsp,160)); + vinsertf128h(xmm11, Address(rsp,176)); + vinsertf128h(xmm12, Address(rsp,192)); + vinsertf128h(xmm13, Address(rsp,208)); + vinsertf128h(xmm14, Address(rsp,224)); + vinsertf128h(xmm15, Address(rsp,240)); +#endif + addptr(rsp, 16 * LP64_ONLY(16) NOT_LP64(8)); + } +#endif + } + popa(); +} + +static const double pi_4 = 0.7853981633974483; + +void MacroAssembler::trigfunc(char trig, int num_fpu_regs_in_use) { + // A hand-coded argument reduction for values in fabs(pi/4, pi/2) + // was attempted in this code; unfortunately it appears that the + // switch to 80-bit precision and back causes this to be + // unprofitable compared with simply performing a runtime call if + // the argument is out of the (-pi/4, pi/4) range. + + Register tmp = noreg; + if (!VM_Version::supports_cmov()) { + // fcmp needs a temporary so preserve rbx, + tmp = rbx; + push(tmp); + } + + Label slow_case, done; + + ExternalAddress pi4_adr = (address)&pi_4; + if (reachable(pi4_adr)) { + // x ?<= pi/4 + fld_d(pi4_adr); + fld_s(1); // Stack: X PI/4 X + fabs(); // Stack: |X| PI/4 X + fcmp(tmp); + jcc(Assembler::above, slow_case); + + // fastest case: -pi/4 <= x <= pi/4 + switch(trig) { + case 's': + fsin(); + break; + case 'c': + fcos(); + break; + case 't': + ftan(); + break; + default: + assert(false, "bad intrinsic"); + break; + } + jmp(done); + } + + // slow case: runtime call + bind(slow_case); + + switch(trig) { + case 's': + { + fp_runtime_fallback(CAST_FROM_FN_PTR(address, SharedRuntime::dsin), 1, num_fpu_regs_in_use); + } + break; + case 'c': + { + fp_runtime_fallback(CAST_FROM_FN_PTR(address, SharedRuntime::dcos), 1, num_fpu_regs_in_use); + } + break; + case 't': + { + fp_runtime_fallback(CAST_FROM_FN_PTR(address, SharedRuntime::dtan), 1, num_fpu_regs_in_use); + } + break; + default: + assert(false, "bad intrinsic"); + break; + } + + // Come here with result in F-TOS + bind(done); + + if (tmp != noreg) { + pop(tmp); + } +} + + +// Look up the method for a megamorphic invokeinterface call. +// The target method is determined by . +// The receiver klass is in recv_klass. +// On success, the result will be in method_result, and execution falls through. +// On failure, execution transfers to the given label. +void MacroAssembler::lookup_interface_method(Register recv_klass, + Register intf_klass, + RegisterOrConstant itable_index, + Register method_result, + Register scan_temp, + Label& L_no_such_interface) { + assert_different_registers(recv_klass, intf_klass, method_result, scan_temp); + assert(itable_index.is_constant() || itable_index.as_register() == method_result, + "caller must use same register for non-constant itable index as for method"); + + // Compute start of first itableOffsetEntry (which is at the end of the vtable) + int vtable_base = InstanceKlass::vtable_start_offset() * wordSize; + int itentry_off = itableMethodEntry::method_offset_in_bytes(); + int scan_step = itableOffsetEntry::size() * wordSize; + int vte_size = vtableEntry::size() * wordSize; + Address::ScaleFactor times_vte_scale = Address::times_ptr; + assert(vte_size == wordSize, "else adjust times_vte_scale"); + + movl(scan_temp, Address(recv_klass, InstanceKlass::vtable_length_offset() * wordSize)); + + // %%% Could store the aligned, prescaled offset in the klassoop. + lea(scan_temp, Address(recv_klass, scan_temp, times_vte_scale, vtable_base)); + if (HeapWordsPerLong > 1) { + // Round up to align_object_offset boundary + // see code for InstanceKlass::start_of_itable! + round_to(scan_temp, BytesPerLong); + } + + // Adjust recv_klass by scaled itable_index, so we can free itable_index. + assert(itableMethodEntry::size() * wordSize == wordSize, "adjust the scaling in the code below"); + lea(recv_klass, Address(recv_klass, itable_index, Address::times_ptr, itentry_off)); + + // for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) { + // if (scan->interface() == intf) { + // result = (klass + scan->offset() + itable_index); + // } + // } + Label search, found_method; + + for (int peel = 1; peel >= 0; peel--) { + movptr(method_result, Address(scan_temp, itableOffsetEntry::interface_offset_in_bytes())); + cmpptr(intf_klass, method_result); + + if (peel) { + jccb(Assembler::equal, found_method); + } else { + jccb(Assembler::notEqual, search); + // (invert the test to fall through to found_method...) + } + + if (!peel) break; + + bind(search); + + // Check that the previous entry is non-null. A null entry means that + // the receiver class doesn't implement the interface, and wasn't the + // same as when the caller was compiled. + testptr(method_result, method_result); + jcc(Assembler::zero, L_no_such_interface); + addptr(scan_temp, scan_step); + } + + bind(found_method); + + // Got a hit. + movl(scan_temp, Address(scan_temp, itableOffsetEntry::offset_offset_in_bytes())); + movptr(method_result, Address(recv_klass, scan_temp, Address::times_1)); +} + + +// virtual method calling +void MacroAssembler::lookup_virtual_method(Register recv_klass, + RegisterOrConstant vtable_index, + Register method_result) { + const int base = InstanceKlass::vtable_start_offset() * wordSize; + assert(vtableEntry::size() * wordSize == wordSize, "else adjust the scaling in the code below"); + Address vtable_entry_addr(recv_klass, + vtable_index, Address::times_ptr, + base + vtableEntry::method_offset_in_bytes()); + movptr(method_result, vtable_entry_addr); +} + + +void MacroAssembler::check_klass_subtype(Register sub_klass, + Register super_klass, + Register temp_reg, + Label& L_success) { + Label L_failure; + check_klass_subtype_fast_path(sub_klass, super_klass, temp_reg, &L_success, &L_failure, NULL); + check_klass_subtype_slow_path(sub_klass, super_klass, temp_reg, noreg, &L_success, NULL); + bind(L_failure); +} + + +void MacroAssembler::check_klass_subtype_fast_path(Register sub_klass, + Register super_klass, + Register temp_reg, + Label* L_success, + Label* L_failure, + Label* L_slow_path, + RegisterOrConstant super_check_offset) { + assert_different_registers(sub_klass, super_klass, temp_reg); + bool must_load_sco = (super_check_offset.constant_or_zero() == -1); + if (super_check_offset.is_register()) { + assert_different_registers(sub_klass, super_klass, + super_check_offset.as_register()); + } else if (must_load_sco) { + assert(temp_reg != noreg, "supply either a temp or a register offset"); + } + + Label L_fallthrough; + int label_nulls = 0; + if (L_success == NULL) { L_success = &L_fallthrough; label_nulls++; } + if (L_failure == NULL) { L_failure = &L_fallthrough; label_nulls++; } + if (L_slow_path == NULL) { L_slow_path = &L_fallthrough; label_nulls++; } + assert(label_nulls <= 1, "at most one NULL in the batch"); + + int sc_offset = in_bytes(Klass::secondary_super_cache_offset()); + int sco_offset = in_bytes(Klass::super_check_offset_offset()); + Address super_check_offset_addr(super_klass, sco_offset); + + // Hacked jcc, which "knows" that L_fallthrough, at least, is in + // range of a jccb. If this routine grows larger, reconsider at + // least some of these. +#define local_jcc(assembler_cond, label) \ + if (&(label) == &L_fallthrough) jccb(assembler_cond, label); \ + else jcc( assembler_cond, label) /*omit semi*/ + + // Hacked jmp, which may only be used just before L_fallthrough. +#define final_jmp(label) \ + if (&(label) == &L_fallthrough) { /*do nothing*/ } \ + else jmp(label) /*omit semi*/ + + // If the pointers are equal, we are done (e.g., String[] elements). + // This self-check enables sharing of secondary supertype arrays among + // non-primary types such as array-of-interface. Otherwise, each such + // type would need its own customized SSA. + // We move this check to the front of the fast path because many + // type checks are in fact trivially successful in this manner, + // so we get a nicely predicted branch right at the start of the check. + cmpptr(sub_klass, super_klass); + local_jcc(Assembler::equal, *L_success); + + // Check the supertype display: + if (must_load_sco) { + // Positive movl does right thing on LP64. + movl(temp_reg, super_check_offset_addr); + super_check_offset = RegisterOrConstant(temp_reg); + } + Address super_check_addr(sub_klass, super_check_offset, Address::times_1, 0); + cmpptr(super_klass, super_check_addr); // load displayed supertype + + // This check has worked decisively for primary supers. + // Secondary supers are sought in the super_cache ('super_cache_addr'). + // (Secondary supers are interfaces and very deeply nested subtypes.) + // This works in the same check above because of a tricky aliasing + // between the super_cache and the primary super display elements. + // (The 'super_check_addr' can address either, as the case requires.) + // Note that the cache is updated below if it does not help us find + // what we need immediately. + // So if it was a primary super, we can just fail immediately. + // Otherwise, it's the slow path for us (no success at this point). + + if (super_check_offset.is_register()) { + local_jcc(Assembler::equal, *L_success); + cmpl(super_check_offset.as_register(), sc_offset); + if (L_failure == &L_fallthrough) { + local_jcc(Assembler::equal, *L_slow_path); + } else { + local_jcc(Assembler::notEqual, *L_failure); + final_jmp(*L_slow_path); + } + } else if (super_check_offset.as_constant() == sc_offset) { + // Need a slow path; fast failure is impossible. + if (L_slow_path == &L_fallthrough) { + local_jcc(Assembler::equal, *L_success); + } else { + local_jcc(Assembler::notEqual, *L_slow_path); + final_jmp(*L_success); + } + } else { + // No slow path; it's a fast decision. + if (L_failure == &L_fallthrough) { + local_jcc(Assembler::equal, *L_success); + } else { + local_jcc(Assembler::notEqual, *L_failure); + final_jmp(*L_success); + } + } + + bind(L_fallthrough); + +#undef local_jcc +#undef final_jmp +} + + +void MacroAssembler::check_klass_subtype_slow_path(Register sub_klass, + Register super_klass, + Register temp_reg, + Register temp2_reg, + Label* L_success, + Label* L_failure, + bool set_cond_codes) { + assert_different_registers(sub_klass, super_klass, temp_reg); + if (temp2_reg != noreg) + assert_different_registers(sub_klass, super_klass, temp_reg, temp2_reg); +#define IS_A_TEMP(reg) ((reg) == temp_reg || (reg) == temp2_reg) + + Label L_fallthrough; + int label_nulls = 0; + if (L_success == NULL) { L_success = &L_fallthrough; label_nulls++; } + if (L_failure == NULL) { L_failure = &L_fallthrough; label_nulls++; } + assert(label_nulls <= 1, "at most one NULL in the batch"); + + // a couple of useful fields in sub_klass: + int ss_offset = in_bytes(Klass::secondary_supers_offset()); + int sc_offset = in_bytes(Klass::secondary_super_cache_offset()); + Address secondary_supers_addr(sub_klass, ss_offset); + Address super_cache_addr( sub_klass, sc_offset); + + // Do a linear scan of the secondary super-klass chain. + // This code is rarely used, so simplicity is a virtue here. + // The repne_scan instruction uses fixed registers, which we must spill. + // Don't worry too much about pre-existing connections with the input regs. + + assert(sub_klass != rax, "killed reg"); // killed by mov(rax, super) + assert(sub_klass != rcx, "killed reg"); // killed by lea(rcx, &pst_counter) + + // Get super_klass value into rax (even if it was in rdi or rcx). + bool pushed_rax = false, pushed_rcx = false, pushed_rdi = false; + if (super_klass != rax || UseCompressedOops) { + if (!IS_A_TEMP(rax)) { push(rax); pushed_rax = true; } + mov(rax, super_klass); + } + if (!IS_A_TEMP(rcx)) { push(rcx); pushed_rcx = true; } + if (!IS_A_TEMP(rdi)) { push(rdi); pushed_rdi = true; } + +#ifndef PRODUCT + int* pst_counter = &SharedRuntime::_partial_subtype_ctr; + ExternalAddress pst_counter_addr((address) pst_counter); + NOT_LP64( incrementl(pst_counter_addr) ); + LP64_ONLY( lea(rcx, pst_counter_addr) ); + LP64_ONLY( incrementl(Address(rcx, 0)) ); +#endif //PRODUCT + + // We will consult the secondary-super array. + movptr(rdi, secondary_supers_addr); + // Load the array length. (Positive movl does right thing on LP64.) + movl(rcx, Address(rdi, Array::length_offset_in_bytes())); + // Skip to start of data. + addptr(rdi, Array::base_offset_in_bytes()); + + // Scan RCX words at [RDI] for an occurrence of RAX. + // Set NZ/Z based on last compare. + // Z flag value will not be set by 'repne' if RCX == 0 since 'repne' does + // not change flags (only scas instruction which is repeated sets flags). + // Set Z = 0 (not equal) before 'repne' to indicate that class was not found. + + testptr(rax,rax); // Set Z = 0 + repne_scan(); + + // Unspill the temp. registers: + if (pushed_rdi) pop(rdi); + if (pushed_rcx) pop(rcx); + if (pushed_rax) pop(rax); + + if (set_cond_codes) { + // Special hack for the AD files: rdi is guaranteed non-zero. + assert(!pushed_rdi, "rdi must be left non-NULL"); + // Also, the condition codes are properly set Z/NZ on succeed/failure. + } + + if (L_failure == &L_fallthrough) + jccb(Assembler::notEqual, *L_failure); + else jcc(Assembler::notEqual, *L_failure); + + // Success. Cache the super we found and proceed in triumph. + movptr(super_cache_addr, super_klass); + + if (L_success != &L_fallthrough) { + jmp(*L_success); + } + +#undef IS_A_TEMP + + bind(L_fallthrough); +} + + +void MacroAssembler::cmov32(Condition cc, Register dst, Address src) { + if (VM_Version::supports_cmov()) { + cmovl(cc, dst, src); + } else { + Label L; + jccb(negate_condition(cc), L); + movl(dst, src); + bind(L); + } +} + +void MacroAssembler::cmov32(Condition cc, Register dst, Register src) { + if (VM_Version::supports_cmov()) { + cmovl(cc, dst, src); + } else { + Label L; + jccb(negate_condition(cc), L); + movl(dst, src); + bind(L); + } +} + +void MacroAssembler::verify_oop(Register reg, const char* s) { + if (!VerifyOops) return; + + // Pass register number to verify_oop_subroutine + char* b = new char[strlen(s) + 50]; + sprintf(b, "verify_oop: %s: %s", reg->name(), s); + BLOCK_COMMENT("verify_oop {"); +#ifdef _LP64 + push(rscratch1); // save r10, trashed by movptr() +#endif + push(rax); // save rax, + push(reg); // pass register argument + ExternalAddress buffer((address) b); + // avoid using pushptr, as it modifies scratch registers + // and our contract is not to modify anything + movptr(rax, buffer.addr()); + push(rax); + // call indirectly to solve generation ordering problem + movptr(rax, ExternalAddress(StubRoutines::verify_oop_subroutine_entry_address())); + call(rax); + // Caller pops the arguments (oop, message) and restores rax, r10 + BLOCK_COMMENT("} verify_oop"); +} + + +RegisterOrConstant MacroAssembler::delayed_value_impl(intptr_t* delayed_value_addr, + Register tmp, + int offset) { + intptr_t value = *delayed_value_addr; + if (value != 0) + return RegisterOrConstant(value + offset); + + // load indirectly to solve generation ordering problem + movptr(tmp, ExternalAddress((address) delayed_value_addr)); + +#ifdef ASSERT + { Label L; + testptr(tmp, tmp); + if (WizardMode) { + jcc(Assembler::notZero, L); + char* buf = new char[40]; + sprintf(buf, "DelayedValue="INTPTR_FORMAT, delayed_value_addr[1]); + STOP(buf); + } else { + jccb(Assembler::notZero, L); + hlt(); + } + bind(L); + } +#endif + + if (offset != 0) + addptr(tmp, offset); + + return RegisterOrConstant(tmp); +} + + +Address MacroAssembler::argument_address(RegisterOrConstant arg_slot, + int extra_slot_offset) { + // cf. TemplateTable::prepare_invoke(), if (load_receiver). + int stackElementSize = Interpreter::stackElementSize; + int offset = Interpreter::expr_offset_in_bytes(extra_slot_offset+0); +#ifdef ASSERT + int offset1 = Interpreter::expr_offset_in_bytes(extra_slot_offset+1); + assert(offset1 - offset == stackElementSize, "correct arithmetic"); +#endif + Register scale_reg = noreg; + Address::ScaleFactor scale_factor = Address::no_scale; + if (arg_slot.is_constant()) { + offset += arg_slot.as_constant() * stackElementSize; + } else { + scale_reg = arg_slot.as_register(); + scale_factor = Address::times(stackElementSize); + } + offset += wordSize; // return PC is on stack + return Address(rsp, scale_reg, scale_factor, offset); +} + + +void MacroAssembler::verify_oop_addr(Address addr, const char* s) { + if (!VerifyOops) return; + + // Address adjust(addr.base(), addr.index(), addr.scale(), addr.disp() + BytesPerWord); + // Pass register number to verify_oop_subroutine + char* b = new char[strlen(s) + 50]; + sprintf(b, "verify_oop_addr: %s", s); + +#ifdef _LP64 + push(rscratch1); // save r10, trashed by movptr() +#endif + push(rax); // save rax, + // addr may contain rsp so we will have to adjust it based on the push + // we just did (and on 64 bit we do two pushes) + // NOTE: 64bit seemed to have had a bug in that it did movq(addr, rax); which + // stores rax into addr which is backwards of what was intended. + if (addr.uses(rsp)) { + lea(rax, addr); + pushptr(Address(rax, LP64_ONLY(2 *) BytesPerWord)); + } else { + pushptr(addr); + } + + ExternalAddress buffer((address) b); + // pass msg argument + // avoid using pushptr, as it modifies scratch registers + // and our contract is not to modify anything + movptr(rax, buffer.addr()); + push(rax); + + // call indirectly to solve generation ordering problem + movptr(rax, ExternalAddress(StubRoutines::verify_oop_subroutine_entry_address())); + call(rax); + // Caller pops the arguments (addr, message) and restores rax, r10. +} + +void MacroAssembler::verify_tlab() { +#ifdef ASSERT + if (UseTLAB && VerifyOops) { + Label next, ok; + Register t1 = rsi; + Register thread_reg = NOT_LP64(rbx) LP64_ONLY(r15_thread); + + push(t1); + NOT_LP64(push(thread_reg)); + NOT_LP64(get_thread(thread_reg)); + + movptr(t1, Address(thread_reg, in_bytes(JavaThread::tlab_top_offset()))); + cmpptr(t1, Address(thread_reg, in_bytes(JavaThread::tlab_start_offset()))); + jcc(Assembler::aboveEqual, next); + STOP("assert(top >= start)"); + should_not_reach_here(); + + bind(next); + movptr(t1, Address(thread_reg, in_bytes(JavaThread::tlab_end_offset()))); + cmpptr(t1, Address(thread_reg, in_bytes(JavaThread::tlab_top_offset()))); + jcc(Assembler::aboveEqual, ok); + STOP("assert(top <= end)"); + should_not_reach_here(); + + bind(ok); + NOT_LP64(pop(thread_reg)); + pop(t1); + } +#endif +} + +class ControlWord { + public: + int32_t _value; + + int rounding_control() const { return (_value >> 10) & 3 ; } + int precision_control() const { return (_value >> 8) & 3 ; } + bool precision() const { return ((_value >> 5) & 1) != 0; } + bool underflow() const { return ((_value >> 4) & 1) != 0; } + bool overflow() const { return ((_value >> 3) & 1) != 0; } + bool zero_divide() const { return ((_value >> 2) & 1) != 0; } + bool denormalized() const { return ((_value >> 1) & 1) != 0; } + bool invalid() const { return ((_value >> 0) & 1) != 0; } + + void print() const { + // rounding control + const char* rc; + switch (rounding_control()) { + case 0: rc = "round near"; break; + case 1: rc = "round down"; break; + case 2: rc = "round up "; break; + case 3: rc = "chop "; break; + }; + // precision control + const char* pc; + switch (precision_control()) { + case 0: pc = "24 bits "; break; + case 1: pc = "reserved"; break; + case 2: pc = "53 bits "; break; + case 3: pc = "64 bits "; break; + }; + // flags + char f[9]; + f[0] = ' '; + f[1] = ' '; + f[2] = (precision ()) ? 'P' : 'p'; + f[3] = (underflow ()) ? 'U' : 'u'; + f[4] = (overflow ()) ? 'O' : 'o'; + f[5] = (zero_divide ()) ? 'Z' : 'z'; + f[6] = (denormalized()) ? 'D' : 'd'; + f[7] = (invalid ()) ? 'I' : 'i'; + f[8] = '\x0'; + // output + printf("%04x masks = %s, %s, %s", _value & 0xFFFF, f, rc, pc); + } + +}; + +class StatusWord { + public: + int32_t _value; + + bool busy() const { return ((_value >> 15) & 1) != 0; } + bool C3() const { return ((_value >> 14) & 1) != 0; } + bool C2() const { return ((_value >> 10) & 1) != 0; } + bool C1() const { return ((_value >> 9) & 1) != 0; } + bool C0() const { return ((_value >> 8) & 1) != 0; } + int top() const { return (_value >> 11) & 7 ; } + bool error_status() const { return ((_value >> 7) & 1) != 0; } + bool stack_fault() const { return ((_value >> 6) & 1) != 0; } + bool precision() const { return ((_value >> 5) & 1) != 0; } + bool underflow() const { return ((_value >> 4) & 1) != 0; } + bool overflow() const { return ((_value >> 3) & 1) != 0; } + bool zero_divide() const { return ((_value >> 2) & 1) != 0; } + bool denormalized() const { return ((_value >> 1) & 1) != 0; } + bool invalid() const { return ((_value >> 0) & 1) != 0; } + + void print() const { + // condition codes + char c[5]; + c[0] = (C3()) ? '3' : '-'; + c[1] = (C2()) ? '2' : '-'; + c[2] = (C1()) ? '1' : '-'; + c[3] = (C0()) ? '0' : '-'; + c[4] = '\x0'; + // flags + char f[9]; + f[0] = (error_status()) ? 'E' : '-'; + f[1] = (stack_fault ()) ? 'S' : '-'; + f[2] = (precision ()) ? 'P' : '-'; + f[3] = (underflow ()) ? 'U' : '-'; + f[4] = (overflow ()) ? 'O' : '-'; + f[5] = (zero_divide ()) ? 'Z' : '-'; + f[6] = (denormalized()) ? 'D' : '-'; + f[7] = (invalid ()) ? 'I' : '-'; + f[8] = '\x0'; + // output + printf("%04x flags = %s, cc = %s, top = %d", _value & 0xFFFF, f, c, top()); + } + +}; + +class TagWord { + public: + int32_t _value; + + int tag_at(int i) const { return (_value >> (i*2)) & 3; } + + void print() const { + printf("%04x", _value & 0xFFFF); + } + +}; + +class FPU_Register { + public: + int32_t _m0; + int32_t _m1; + int16_t _ex; + + bool is_indefinite() const { + return _ex == -1 && _m1 == (int32_t)0xC0000000 && _m0 == 0; + } + + void print() const { + char sign = (_ex < 0) ? '-' : '+'; + const char* kind = (_ex == 0x7FFF || _ex == (int16_t)-1) ? "NaN" : " "; + printf("%c%04hx.%08x%08x %s", sign, _ex, _m1, _m0, kind); + }; + +}; + +class FPU_State { + public: + enum { + register_size = 10, + number_of_registers = 8, + register_mask = 7 + }; + + ControlWord _control_word; + StatusWord _status_word; + TagWord _tag_word; + int32_t _error_offset; + int32_t _error_selector; + int32_t _data_offset; + int32_t _data_selector; + int8_t _register[register_size * number_of_registers]; + + int tag_for_st(int i) const { return _tag_word.tag_at((_status_word.top() + i) & register_mask); } + FPU_Register* st(int i) const { return (FPU_Register*)&_register[register_size * i]; } + + const char* tag_as_string(int tag) const { + switch (tag) { + case 0: return "valid"; + case 1: return "zero"; + case 2: return "special"; + case 3: return "empty"; + } + ShouldNotReachHere(); + return NULL; + } + + void print() const { + // print computation registers + { int t = _status_word.top(); + for (int i = 0; i < number_of_registers; i++) { + int j = (i - t) & register_mask; + printf("%c r%d = ST%d = ", (j == 0 ? '*' : ' '), i, j); + st(j)->print(); + printf(" %s\n", tag_as_string(_tag_word.tag_at(i))); + } + } + printf("\n"); + // print control registers + printf("ctrl = "); _control_word.print(); printf("\n"); + printf("stat = "); _status_word .print(); printf("\n"); + printf("tags = "); _tag_word .print(); printf("\n"); + } + +}; + +class Flag_Register { + public: + int32_t _value; + + bool overflow() const { return ((_value >> 11) & 1) != 0; } + bool direction() const { return ((_value >> 10) & 1) != 0; } + bool sign() const { return ((_value >> 7) & 1) != 0; } + bool zero() const { return ((_value >> 6) & 1) != 0; } + bool auxiliary_carry() const { return ((_value >> 4) & 1) != 0; } + bool parity() const { return ((_value >> 2) & 1) != 0; } + bool carry() const { return ((_value >> 0) & 1) != 0; } + + void print() const { + // flags + char f[8]; + f[0] = (overflow ()) ? 'O' : '-'; + f[1] = (direction ()) ? 'D' : '-'; + f[2] = (sign ()) ? 'S' : '-'; + f[3] = (zero ()) ? 'Z' : '-'; + f[4] = (auxiliary_carry()) ? 'A' : '-'; + f[5] = (parity ()) ? 'P' : '-'; + f[6] = (carry ()) ? 'C' : '-'; + f[7] = '\x0'; + // output + printf("%08x flags = %s", _value, f); + } + +}; + +class IU_Register { + public: + int32_t _value; + + void print() const { + printf("%08x %11d", _value, _value); + } + +}; + +class IU_State { + public: + Flag_Register _eflags; + IU_Register _rdi; + IU_Register _rsi; + IU_Register _rbp; + IU_Register _rsp; + IU_Register _rbx; + IU_Register _rdx; + IU_Register _rcx; + IU_Register _rax; + + void print() const { + // computation registers + printf("rax, = "); _rax.print(); printf("\n"); + printf("rbx, = "); _rbx.print(); printf("\n"); + printf("rcx = "); _rcx.print(); printf("\n"); + printf("rdx = "); _rdx.print(); printf("\n"); + printf("rdi = "); _rdi.print(); printf("\n"); + printf("rsi = "); _rsi.print(); printf("\n"); + printf("rbp, = "); _rbp.print(); printf("\n"); + printf("rsp = "); _rsp.print(); printf("\n"); + printf("\n"); + // control registers + printf("flgs = "); _eflags.print(); printf("\n"); + } +}; + + +class CPU_State { + public: + FPU_State _fpu_state; + IU_State _iu_state; + + void print() const { + printf("--------------------------------------------------\n"); + _iu_state .print(); + printf("\n"); + _fpu_state.print(); + printf("--------------------------------------------------\n"); + } + +}; + + +static void _print_CPU_state(CPU_State* state) { + state->print(); +}; + + +void MacroAssembler::print_CPU_state() { + push_CPU_state(); + push(rsp); // pass CPU state + call(RuntimeAddress(CAST_FROM_FN_PTR(address, _print_CPU_state))); + addptr(rsp, wordSize); // discard argument + pop_CPU_state(); +} + + +static bool _verify_FPU(int stack_depth, char* s, CPU_State* state) { + static int counter = 0; + FPU_State* fs = &state->_fpu_state; + counter++; + // For leaf calls, only verify that the top few elements remain empty. + // We only need 1 empty at the top for C2 code. + if( stack_depth < 0 ) { + if( fs->tag_for_st(7) != 3 ) { + printf("FPR7 not empty\n"); + state->print(); + assert(false, "error"); + return false; + } + return true; // All other stack states do not matter + } + + assert((fs->_control_word._value & 0xffff) == StubRoutines::_fpu_cntrl_wrd_std, + "bad FPU control word"); + + // compute stack depth + int i = 0; + while (i < FPU_State::number_of_registers && fs->tag_for_st(i) < 3) i++; + int d = i; + while (i < FPU_State::number_of_registers && fs->tag_for_st(i) == 3) i++; + // verify findings + if (i != FPU_State::number_of_registers) { + // stack not contiguous + printf("%s: stack not contiguous at ST%d\n", s, i); + state->print(); + assert(false, "error"); + return false; + } + // check if computed stack depth corresponds to expected stack depth + if (stack_depth < 0) { + // expected stack depth is -stack_depth or less + if (d > -stack_depth) { + // too many elements on the stack + printf("%s: <= %d stack elements expected but found %d\n", s, -stack_depth, d); + state->print(); + assert(false, "error"); + return false; + } + } else { + // expected stack depth is stack_depth + if (d != stack_depth) { + // wrong stack depth + printf("%s: %d stack elements expected but found %d\n", s, stack_depth, d); + state->print(); + assert(false, "error"); + return false; + } + } + // everything is cool + return true; +} + + +void MacroAssembler::verify_FPU(int stack_depth, const char* s) { + if (!VerifyFPU) return; + push_CPU_state(); + push(rsp); // pass CPU state + ExternalAddress msg((address) s); + // pass message string s + pushptr(msg.addr()); + push(stack_depth); // pass stack depth + call(RuntimeAddress(CAST_FROM_FN_PTR(address, _verify_FPU))); + addptr(rsp, 3 * wordSize); // discard arguments + // check for error + { Label L; + testl(rax, rax); + jcc(Assembler::notZero, L); + int3(); // break if error condition + bind(L); + } + pop_CPU_state(); +} + +void MacroAssembler::load_klass(Register dst, Register src) { +#ifdef _LP64 + if (UseCompressedKlassPointers) { + movl(dst, Address(src, oopDesc::klass_offset_in_bytes())); + decode_klass_not_null(dst); + } else +#endif + movptr(dst, Address(src, oopDesc::klass_offset_in_bytes())); +} + +void MacroAssembler::load_prototype_header(Register dst, Register src) { +#ifdef _LP64 + if (UseCompressedKlassPointers) { + assert (Universe::heap() != NULL, "java heap should be initialized"); + movl(dst, Address(src, oopDesc::klass_offset_in_bytes())); + if (Universe::narrow_klass_shift() != 0) { + assert(LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong"); + assert(LogKlassAlignmentInBytes == Address::times_8, "klass not aligned on 64bits?"); + movq(dst, Address(r12_heapbase, dst, Address::times_8, Klass::prototype_header_offset())); + } else { + movq(dst, Address(dst, Klass::prototype_header_offset())); + } + } else +#endif + { + movptr(dst, Address(src, oopDesc::klass_offset_in_bytes())); + movptr(dst, Address(dst, Klass::prototype_header_offset())); + } +} + +void MacroAssembler::store_klass(Register dst, Register src) { +#ifdef _LP64 + if (UseCompressedKlassPointers) { + encode_klass_not_null(src); + movl(Address(dst, oopDesc::klass_offset_in_bytes()), src); + } else +#endif + movptr(Address(dst, oopDesc::klass_offset_in_bytes()), src); +} + +void MacroAssembler::load_heap_oop(Register dst, Address src) { +#ifdef _LP64 + // FIXME: Must change all places where we try to load the klass. + if (UseCompressedOops) { + movl(dst, src); + decode_heap_oop(dst); + } else +#endif + movptr(dst, src); +} + +// Doesn't do verfication, generates fixed size code +void MacroAssembler::load_heap_oop_not_null(Register dst, Address src) { +#ifdef _LP64 + if (UseCompressedOops) { + movl(dst, src); + decode_heap_oop_not_null(dst); + } else +#endif + movptr(dst, src); +} + +void MacroAssembler::store_heap_oop(Address dst, Register src) { +#ifdef _LP64 + if (UseCompressedOops) { + assert(!dst.uses(src), "not enough registers"); + encode_heap_oop(src); + movl(dst, src); + } else +#endif + movptr(dst, src); +} + +void MacroAssembler::cmp_heap_oop(Register src1, Address src2, Register tmp) { + assert_different_registers(src1, tmp); +#ifdef _LP64 + if (UseCompressedOops) { + bool did_push = false; + if (tmp == noreg) { + tmp = rax; + push(tmp); + did_push = true; + assert(!src2.uses(rsp), "can't push"); + } + load_heap_oop(tmp, src2); + cmpptr(src1, tmp); + if (did_push) pop(tmp); + } else +#endif + cmpptr(src1, src2); +} + +// Used for storing NULLs. +void MacroAssembler::store_heap_oop_null(Address dst) { +#ifdef _LP64 + if (UseCompressedOops) { + movl(dst, (int32_t)NULL_WORD); + } else { + movslq(dst, (int32_t)NULL_WORD); + } +#else + movl(dst, (int32_t)NULL_WORD); +#endif +} + +#ifdef _LP64 +void MacroAssembler::store_klass_gap(Register dst, Register src) { + if (UseCompressedKlassPointers) { + // Store to klass gap in destination + movl(Address(dst, oopDesc::klass_gap_offset_in_bytes()), src); + } +} + +#ifdef ASSERT +void MacroAssembler::verify_heapbase(const char* msg) { + assert (UseCompressedOops || UseCompressedKlassPointers, "should be compressed"); + assert (Universe::heap() != NULL, "java heap should be initialized"); + if (CheckCompressedOops) { + Label ok; + push(rscratch1); // cmpptr trashes rscratch1 + cmpptr(r12_heapbase, ExternalAddress((address)Universe::narrow_ptrs_base_addr())); + jcc(Assembler::equal, ok); + STOP(msg); + bind(ok); + pop(rscratch1); + } +} +#endif + +// Algorithm must match oop.inline.hpp encode_heap_oop. +void MacroAssembler::encode_heap_oop(Register r) { +#ifdef ASSERT + verify_heapbase("MacroAssembler::encode_heap_oop: heap base corrupted?"); +#endif + verify_oop(r, "broken oop in encode_heap_oop"); + if (Universe::narrow_oop_base() == NULL) { + if (Universe::narrow_oop_shift() != 0) { + assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); + shrq(r, LogMinObjAlignmentInBytes); + } + return; + } + testq(r, r); + cmovq(Assembler::equal, r, r12_heapbase); + subq(r, r12_heapbase); + shrq(r, LogMinObjAlignmentInBytes); +} + +void MacroAssembler::encode_heap_oop_not_null(Register r) { +#ifdef ASSERT + verify_heapbase("MacroAssembler::encode_heap_oop_not_null: heap base corrupted?"); + if (CheckCompressedOops) { + Label ok; + testq(r, r); + jcc(Assembler::notEqual, ok); + STOP("null oop passed to encode_heap_oop_not_null"); + bind(ok); + } +#endif + verify_oop(r, "broken oop in encode_heap_oop_not_null"); + if (Universe::narrow_oop_base() != NULL) { + subq(r, r12_heapbase); + } + if (Universe::narrow_oop_shift() != 0) { + assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); + shrq(r, LogMinObjAlignmentInBytes); + } +} + +void MacroAssembler::encode_heap_oop_not_null(Register dst, Register src) { +#ifdef ASSERT + verify_heapbase("MacroAssembler::encode_heap_oop_not_null2: heap base corrupted?"); + if (CheckCompressedOops) { + Label ok; + testq(src, src); + jcc(Assembler::notEqual, ok); + STOP("null oop passed to encode_heap_oop_not_null2"); + bind(ok); + } +#endif + verify_oop(src, "broken oop in encode_heap_oop_not_null2"); + if (dst != src) { + movq(dst, src); + } + if (Universe::narrow_oop_base() != NULL) { + subq(dst, r12_heapbase); + } + if (Universe::narrow_oop_shift() != 0) { + assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); + shrq(dst, LogMinObjAlignmentInBytes); + } +} + +void MacroAssembler::decode_heap_oop(Register r) { +#ifdef ASSERT + verify_heapbase("MacroAssembler::decode_heap_oop: heap base corrupted?"); +#endif + if (Universe::narrow_oop_base() == NULL) { + if (Universe::narrow_oop_shift() != 0) { + assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); + shlq(r, LogMinObjAlignmentInBytes); + } + } else { + Label done; + shlq(r, LogMinObjAlignmentInBytes); + jccb(Assembler::equal, done); + addq(r, r12_heapbase); + bind(done); + } + verify_oop(r, "broken oop in decode_heap_oop"); +} + +void MacroAssembler::decode_heap_oop_not_null(Register r) { + // Note: it will change flags + assert (UseCompressedOops, "should only be used for compressed headers"); + assert (Universe::heap() != NULL, "java heap should be initialized"); + // Cannot assert, unverified entry point counts instructions (see .ad file) + // vtableStubs also counts instructions in pd_code_size_limit. + // Also do not verify_oop as this is called by verify_oop. + if (Universe::narrow_oop_shift() != 0) { + assert(LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); + shlq(r, LogMinObjAlignmentInBytes); + if (Universe::narrow_oop_base() != NULL) { + addq(r, r12_heapbase); + } + } else { + assert (Universe::narrow_oop_base() == NULL, "sanity"); + } +} + +void MacroAssembler::decode_heap_oop_not_null(Register dst, Register src) { + // Note: it will change flags + assert (UseCompressedOops, "should only be used for compressed headers"); + assert (Universe::heap() != NULL, "java heap should be initialized"); + // Cannot assert, unverified entry point counts instructions (see .ad file) + // vtableStubs also counts instructions in pd_code_size_limit. + // Also do not verify_oop as this is called by verify_oop. + if (Universe::narrow_oop_shift() != 0) { + assert(LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); + if (LogMinObjAlignmentInBytes == Address::times_8) { + leaq(dst, Address(r12_heapbase, src, Address::times_8, 0)); + } else { + if (dst != src) { + movq(dst, src); + } + shlq(dst, LogMinObjAlignmentInBytes); + if (Universe::narrow_oop_base() != NULL) { + addq(dst, r12_heapbase); + } + } + } else { + assert (Universe::narrow_oop_base() == NULL, "sanity"); + if (dst != src) { + movq(dst, src); + } + } +} + +void MacroAssembler::encode_klass_not_null(Register r) { + assert(Metaspace::is_initialized(), "metaspace should be initialized"); +#ifdef ASSERT + verify_heapbase("MacroAssembler::encode_klass_not_null: heap base corrupted?"); +#endif + if (Universe::narrow_klass_base() != NULL) { + subq(r, r12_heapbase); + } + if (Universe::narrow_klass_shift() != 0) { + assert (LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong"); + shrq(r, LogKlassAlignmentInBytes); + } +} + +void MacroAssembler::encode_klass_not_null(Register dst, Register src) { + assert(Metaspace::is_initialized(), "metaspace should be initialized"); +#ifdef ASSERT + verify_heapbase("MacroAssembler::encode_klass_not_null2: heap base corrupted?"); +#endif + if (dst != src) { + movq(dst, src); + } + if (Universe::narrow_klass_base() != NULL) { + subq(dst, r12_heapbase); + } + if (Universe::narrow_klass_shift() != 0) { + assert (LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong"); + shrq(dst, LogKlassAlignmentInBytes); + } +} + +void MacroAssembler::decode_klass_not_null(Register r) { + assert(Metaspace::is_initialized(), "metaspace should be initialized"); + // Note: it will change flags + assert (UseCompressedKlassPointers, "should only be used for compressed headers"); + // Cannot assert, unverified entry point counts instructions (see .ad file) + // vtableStubs also counts instructions in pd_code_size_limit. + // Also do not verify_oop as this is called by verify_oop. + if (Universe::narrow_klass_shift() != 0) { + assert(LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong"); + shlq(r, LogKlassAlignmentInBytes); + if (Universe::narrow_klass_base() != NULL) { + addq(r, r12_heapbase); + } + } else { + assert (Universe::narrow_klass_base() == NULL, "sanity"); + } +} + +void MacroAssembler::decode_klass_not_null(Register dst, Register src) { + assert(Metaspace::is_initialized(), "metaspace should be initialized"); + // Note: it will change flags + assert (UseCompressedKlassPointers, "should only be used for compressed headers"); + // Cannot assert, unverified entry point counts instructions (see .ad file) + // vtableStubs also counts instructions in pd_code_size_limit. + // Also do not verify_oop as this is called by verify_oop. + if (Universe::narrow_klass_shift() != 0) { + assert(LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong"); + assert(LogKlassAlignmentInBytes == Address::times_8, "klass not aligned on 64bits?"); + leaq(dst, Address(r12_heapbase, src, Address::times_8, 0)); + } else { + assert (Universe::narrow_klass_base() == NULL, "sanity"); + if (dst != src) { + movq(dst, src); + } + } +} + +void MacroAssembler::set_narrow_oop(Register dst, jobject obj) { + assert (UseCompressedOops, "should only be used for compressed headers"); + assert (Universe::heap() != NULL, "java heap should be initialized"); + assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); + int oop_index = oop_recorder()->find_index(obj); + RelocationHolder rspec = oop_Relocation::spec(oop_index); + mov_narrow_oop(dst, oop_index, rspec); +} + +void MacroAssembler::set_narrow_oop(Address dst, jobject obj) { + assert (UseCompressedOops, "should only be used for compressed headers"); + assert (Universe::heap() != NULL, "java heap should be initialized"); + assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); + int oop_index = oop_recorder()->find_index(obj); + RelocationHolder rspec = oop_Relocation::spec(oop_index); + mov_narrow_oop(dst, oop_index, rspec); +} + +void MacroAssembler::set_narrow_klass(Register dst, Klass* k) { + assert (UseCompressedKlassPointers, "should only be used for compressed headers"); + assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); + int klass_index = oop_recorder()->find_index(k); + RelocationHolder rspec = metadata_Relocation::spec(klass_index); + mov_narrow_oop(dst, oopDesc::encode_klass(k), rspec); +} + +void MacroAssembler::set_narrow_klass(Address dst, Klass* k) { + assert (UseCompressedKlassPointers, "should only be used for compressed headers"); + assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); + int klass_index = oop_recorder()->find_index(k); + RelocationHolder rspec = metadata_Relocation::spec(klass_index); + mov_narrow_oop(dst, oopDesc::encode_klass(k), rspec); +} + +void MacroAssembler::cmp_narrow_oop(Register dst, jobject obj) { + assert (UseCompressedOops, "should only be used for compressed headers"); + assert (Universe::heap() != NULL, "java heap should be initialized"); + assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); + int oop_index = oop_recorder()->find_index(obj); + RelocationHolder rspec = oop_Relocation::spec(oop_index); + Assembler::cmp_narrow_oop(dst, oop_index, rspec); +} + +void MacroAssembler::cmp_narrow_oop(Address dst, jobject obj) { + assert (UseCompressedOops, "should only be used for compressed headers"); + assert (Universe::heap() != NULL, "java heap should be initialized"); + assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); + int oop_index = oop_recorder()->find_index(obj); + RelocationHolder rspec = oop_Relocation::spec(oop_index); + Assembler::cmp_narrow_oop(dst, oop_index, rspec); +} + +void MacroAssembler::cmp_narrow_klass(Register dst, Klass* k) { + assert (UseCompressedKlassPointers, "should only be used for compressed headers"); + assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); + int klass_index = oop_recorder()->find_index(k); + RelocationHolder rspec = metadata_Relocation::spec(klass_index); + Assembler::cmp_narrow_oop(dst, oopDesc::encode_klass(k), rspec); +} + +void MacroAssembler::cmp_narrow_klass(Address dst, Klass* k) { + assert (UseCompressedKlassPointers, "should only be used for compressed headers"); + assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); + int klass_index = oop_recorder()->find_index(k); + RelocationHolder rspec = metadata_Relocation::spec(klass_index); + Assembler::cmp_narrow_oop(dst, oopDesc::encode_klass(k), rspec); +} + +void MacroAssembler::reinit_heapbase() { + if (UseCompressedOops || UseCompressedKlassPointers) { + movptr(r12_heapbase, ExternalAddress((address)Universe::narrow_ptrs_base_addr())); + } +} +#endif // _LP64 + + +// C2 compiled method's prolog code. +void MacroAssembler::verified_entry(int framesize, bool stack_bang, bool fp_mode_24b) { + + // WARNING: Initial instruction MUST be 5 bytes or longer so that + // NativeJump::patch_verified_entry will be able to patch out the entry + // code safely. The push to verify stack depth is ok at 5 bytes, + // the frame allocation can be either 3 or 6 bytes. So if we don't do + // stack bang then we must use the 6 byte frame allocation even if + // we have no frame. :-( + + assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); + // Remove word for return addr + framesize -= wordSize; + + // Calls to C2R adapters often do not accept exceptional returns. + // We require that their callers must bang for them. But be careful, because + // some VM calls (such as call site linkage) can use several kilobytes of + // stack. But the stack safety zone should account for that. + // See bugs 4446381, 4468289, 4497237. + if (stack_bang) { + generate_stack_overflow_check(framesize); + + // We always push rbp, so that on return to interpreter rbp, will be + // restored correctly and we can correct the stack. + push(rbp); + // Remove word for ebp + framesize -= wordSize; + + // Create frame + if (framesize) { + subptr(rsp, framesize); + } + } else { + // Create frame (force generation of a 4 byte immediate value) + subptr_imm32(rsp, framesize); + + // Save RBP register now. + framesize -= wordSize; + movptr(Address(rsp, framesize), rbp); + } + + if (VerifyStackAtCalls) { // Majik cookie to verify stack depth + framesize -= wordSize; + movptr(Address(rsp, framesize), (int32_t)0xbadb100d); + } + +#ifndef _LP64 + // If method sets FPU control word do it now + if (fp_mode_24b) { + fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_24())); + } + if (UseSSE >= 2 && VerifyFPU) { + verify_FPU(0, "FPU stack must be clean on entry"); + } +#endif + +#ifdef ASSERT + if (VerifyStackAtCalls) { + Label L; + push(rax); + mov(rax, rsp); + andptr(rax, StackAlignmentInBytes-1); + cmpptr(rax, StackAlignmentInBytes-wordSize); + pop(rax); + jcc(Assembler::equal, L); + STOP("Stack is not properly aligned!"); + bind(L); + } +#endif + +} + + +// IndexOf for constant substrings with size >= 8 chars +// which don't need to be loaded through stack. +void MacroAssembler::string_indexofC8(Register str1, Register str2, + Register cnt1, Register cnt2, + int int_cnt2, Register result, + XMMRegister vec, Register tmp) { + ShortBranchVerifier sbv(this); + assert(UseSSE42Intrinsics, "SSE4.2 is required"); + + // This method uses pcmpestri inxtruction with bound registers + // inputs: + // xmm - substring + // rax - substring length (elements count) + // mem - scanned string + // rdx - string length (elements count) + // 0xd - mode: 1100 (substring search) + 01 (unsigned shorts) + // outputs: + // rcx - matched index in string + assert(cnt1 == rdx && cnt2 == rax && tmp == rcx, "pcmpestri"); + + Label RELOAD_SUBSTR, SCAN_TO_SUBSTR, SCAN_SUBSTR, + RET_FOUND, RET_NOT_FOUND, EXIT, FOUND_SUBSTR, + MATCH_SUBSTR_HEAD, RELOAD_STR, FOUND_CANDIDATE; + + // Note, inline_string_indexOf() generates checks: + // if (substr.count > string.count) return -1; + // if (substr.count == 0) return 0; + assert(int_cnt2 >= 8, "this code isused only for cnt2 >= 8 chars"); + + // Load substring. + movdqu(vec, Address(str2, 0)); + movl(cnt2, int_cnt2); + movptr(result, str1); // string addr + + if (int_cnt2 > 8) { + jmpb(SCAN_TO_SUBSTR); + + // Reload substr for rescan, this code + // is executed only for large substrings (> 8 chars) + bind(RELOAD_SUBSTR); + movdqu(vec, Address(str2, 0)); + negptr(cnt2); // Jumped here with negative cnt2, convert to positive + + bind(RELOAD_STR); + // We came here after the beginning of the substring was + // matched but the rest of it was not so we need to search + // again. Start from the next element after the previous match. + + // cnt2 is number of substring reminding elements and + // cnt1 is number of string reminding elements when cmp failed. + // Restored cnt1 = cnt1 - cnt2 + int_cnt2 + subl(cnt1, cnt2); + addl(cnt1, int_cnt2); + movl(cnt2, int_cnt2); // Now restore cnt2 + + decrementl(cnt1); // Shift to next element + cmpl(cnt1, cnt2); + jccb(Assembler::negative, RET_NOT_FOUND); // Left less then substring + + addptr(result, 2); + + } // (int_cnt2 > 8) + + // Scan string for start of substr in 16-byte vectors + bind(SCAN_TO_SUBSTR); + pcmpestri(vec, Address(result, 0), 0x0d); + jccb(Assembler::below, FOUND_CANDIDATE); // CF == 1 + subl(cnt1, 8); + jccb(Assembler::lessEqual, RET_NOT_FOUND); // Scanned full string + cmpl(cnt1, cnt2); + jccb(Assembler::negative, RET_NOT_FOUND); // Left less then substring + addptr(result, 16); + jmpb(SCAN_TO_SUBSTR); + + // Found a potential substr + bind(FOUND_CANDIDATE); + // Matched whole vector if first element matched (tmp(rcx) == 0). + if (int_cnt2 == 8) { + jccb(Assembler::overflow, RET_FOUND); // OF == 1 + } else { // int_cnt2 > 8 + jccb(Assembler::overflow, FOUND_SUBSTR); + } + // After pcmpestri tmp(rcx) contains matched element index + // Compute start addr of substr + lea(result, Address(result, tmp, Address::times_2)); + + // Make sure string is still long enough + subl(cnt1, tmp); + cmpl(cnt1, cnt2); + if (int_cnt2 == 8) { + jccb(Assembler::greaterEqual, SCAN_TO_SUBSTR); + } else { // int_cnt2 > 8 + jccb(Assembler::greaterEqual, MATCH_SUBSTR_HEAD); + } + // Left less then substring. + + bind(RET_NOT_FOUND); + movl(result, -1); + jmpb(EXIT); + + if (int_cnt2 > 8) { + // This code is optimized for the case when whole substring + // is matched if its head is matched. + bind(MATCH_SUBSTR_HEAD); + pcmpestri(vec, Address(result, 0), 0x0d); + // Reload only string if does not match + jccb(Assembler::noOverflow, RELOAD_STR); // OF == 0 + + Label CONT_SCAN_SUBSTR; + // Compare the rest of substring (> 8 chars). + bind(FOUND_SUBSTR); + // First 8 chars are already matched. + negptr(cnt2); + addptr(cnt2, 8); + + bind(SCAN_SUBSTR); + subl(cnt1, 8); + cmpl(cnt2, -8); // Do not read beyond substring + jccb(Assembler::lessEqual, CONT_SCAN_SUBSTR); + // Back-up strings to avoid reading beyond substring: + // cnt1 = cnt1 - cnt2 + 8 + addl(cnt1, cnt2); // cnt2 is negative + addl(cnt1, 8); + movl(cnt2, 8); negptr(cnt2); + bind(CONT_SCAN_SUBSTR); + if (int_cnt2 < (int)G) { + movdqu(vec, Address(str2, cnt2, Address::times_2, int_cnt2*2)); + pcmpestri(vec, Address(result, cnt2, Address::times_2, int_cnt2*2), 0x0d); + } else { + // calculate index in register to avoid integer overflow (int_cnt2*2) + movl(tmp, int_cnt2); + addptr(tmp, cnt2); + movdqu(vec, Address(str2, tmp, Address::times_2, 0)); + pcmpestri(vec, Address(result, tmp, Address::times_2, 0), 0x0d); + } + // Need to reload strings pointers if not matched whole vector + jcc(Assembler::noOverflow, RELOAD_SUBSTR); // OF == 0 + addptr(cnt2, 8); + jcc(Assembler::negative, SCAN_SUBSTR); + // Fall through if found full substring + + } // (int_cnt2 > 8) + + bind(RET_FOUND); + // Found result if we matched full small substring. + // Compute substr offset + subptr(result, str1); + shrl(result, 1); // index + bind(EXIT); + +} // string_indexofC8 + +// Small strings are loaded through stack if they cross page boundary. +void MacroAssembler::string_indexof(Register str1, Register str2, + Register cnt1, Register cnt2, + int int_cnt2, Register result, + XMMRegister vec, Register tmp) { + ShortBranchVerifier sbv(this); + assert(UseSSE42Intrinsics, "SSE4.2 is required"); + // + // int_cnt2 is length of small (< 8 chars) constant substring + // or (-1) for non constant substring in which case its length + // is in cnt2 register. + // + // Note, inline_string_indexOf() generates checks: + // if (substr.count > string.count) return -1; + // if (substr.count == 0) return 0; + // + assert(int_cnt2 == -1 || (0 < int_cnt2 && int_cnt2 < 8), "should be != 0"); + + // This method uses pcmpestri inxtruction with bound registers + // inputs: + // xmm - substring + // rax - substring length (elements count) + // mem - scanned string + // rdx - string length (elements count) + // 0xd - mode: 1100 (substring search) + 01 (unsigned shorts) + // outputs: + // rcx - matched index in string + assert(cnt1 == rdx && cnt2 == rax && tmp == rcx, "pcmpestri"); + + Label RELOAD_SUBSTR, SCAN_TO_SUBSTR, SCAN_SUBSTR, ADJUST_STR, + RET_FOUND, RET_NOT_FOUND, CLEANUP, FOUND_SUBSTR, + FOUND_CANDIDATE; + + { //======================================================== + // We don't know where these strings are located + // and we can't read beyond them. Load them through stack. + Label BIG_STRINGS, CHECK_STR, COPY_SUBSTR, COPY_STR; + + movptr(tmp, rsp); // save old SP + + if (int_cnt2 > 0) { // small (< 8 chars) constant substring + if (int_cnt2 == 1) { // One char + load_unsigned_short(result, Address(str2, 0)); + movdl(vec, result); // move 32 bits + } else if (int_cnt2 == 2) { // Two chars + movdl(vec, Address(str2, 0)); // move 32 bits + } else if (int_cnt2 == 4) { // Four chars + movq(vec, Address(str2, 0)); // move 64 bits + } else { // cnt2 = { 3, 5, 6, 7 } + // Array header size is 12 bytes in 32-bit VM + // + 6 bytes for 3 chars == 18 bytes, + // enough space to load vec and shift. + assert(HeapWordSize*TypeArrayKlass::header_size() >= 12,"sanity"); + movdqu(vec, Address(str2, (int_cnt2*2)-16)); + psrldq(vec, 16-(int_cnt2*2)); + } + } else { // not constant substring + cmpl(cnt2, 8); + jccb(Assembler::aboveEqual, BIG_STRINGS); // Both strings are big enough + + // We can read beyond string if srt+16 does not cross page boundary + // since heaps are aligned and mapped by pages. + assert(os::vm_page_size() < (int)G, "default page should be small"); + movl(result, str2); // We need only low 32 bits + andl(result, (os::vm_page_size()-1)); + cmpl(result, (os::vm_page_size()-16)); + jccb(Assembler::belowEqual, CHECK_STR); + + // Move small strings to stack to allow load 16 bytes into vec. + subptr(rsp, 16); + int stk_offset = wordSize-2; + push(cnt2); + + bind(COPY_SUBSTR); + load_unsigned_short(result, Address(str2, cnt2, Address::times_2, -2)); + movw(Address(rsp, cnt2, Address::times_2, stk_offset), result); + decrement(cnt2); + jccb(Assembler::notZero, COPY_SUBSTR); + + pop(cnt2); + movptr(str2, rsp); // New substring address + } // non constant + + bind(CHECK_STR); + cmpl(cnt1, 8); + jccb(Assembler::aboveEqual, BIG_STRINGS); + + // Check cross page boundary. + movl(result, str1); // We need only low 32 bits + andl(result, (os::vm_page_size()-1)); + cmpl(result, (os::vm_page_size()-16)); + jccb(Assembler::belowEqual, BIG_STRINGS); + + subptr(rsp, 16); + int stk_offset = -2; + if (int_cnt2 < 0) { // not constant + push(cnt2); + stk_offset += wordSize; + } + movl(cnt2, cnt1); + + bind(COPY_STR); + load_unsigned_short(result, Address(str1, cnt2, Address::times_2, -2)); + movw(Address(rsp, cnt2, Address::times_2, stk_offset), result); + decrement(cnt2); + jccb(Assembler::notZero, COPY_STR); + + if (int_cnt2 < 0) { // not constant + pop(cnt2); + } + movptr(str1, rsp); // New string address + + bind(BIG_STRINGS); + // Load substring. + if (int_cnt2 < 0) { // -1 + movdqu(vec, Address(str2, 0)); + push(cnt2); // substr count + push(str2); // substr addr + push(str1); // string addr + } else { + // Small (< 8 chars) constant substrings are loaded already. + movl(cnt2, int_cnt2); + } + push(tmp); // original SP + + } // Finished loading + + //======================================================== + // Start search + // + + movptr(result, str1); // string addr + + if (int_cnt2 < 0) { // Only for non constant substring + jmpb(SCAN_TO_SUBSTR); + + // SP saved at sp+0 + // String saved at sp+1*wordSize + // Substr saved at sp+2*wordSize + // Substr count saved at sp+3*wordSize + + // Reload substr for rescan, this code + // is executed only for large substrings (> 8 chars) + bind(RELOAD_SUBSTR); + movptr(str2, Address(rsp, 2*wordSize)); + movl(cnt2, Address(rsp, 3*wordSize)); + movdqu(vec, Address(str2, 0)); + // We came here after the beginning of the substring was + // matched but the rest of it was not so we need to search + // again. Start from the next element after the previous match. + subptr(str1, result); // Restore counter + shrl(str1, 1); + addl(cnt1, str1); + decrementl(cnt1); // Shift to next element + cmpl(cnt1, cnt2); + jccb(Assembler::negative, RET_NOT_FOUND); // Left less then substring + + addptr(result, 2); + } // non constant + + // Scan string for start of substr in 16-byte vectors + bind(SCAN_TO_SUBSTR); + assert(cnt1 == rdx && cnt2 == rax && tmp == rcx, "pcmpestri"); + pcmpestri(vec, Address(result, 0), 0x0d); + jccb(Assembler::below, FOUND_CANDIDATE); // CF == 1 + subl(cnt1, 8); + jccb(Assembler::lessEqual, RET_NOT_FOUND); // Scanned full string + cmpl(cnt1, cnt2); + jccb(Assembler::negative, RET_NOT_FOUND); // Left less then substring + addptr(result, 16); + + bind(ADJUST_STR); + cmpl(cnt1, 8); // Do not read beyond string + jccb(Assembler::greaterEqual, SCAN_TO_SUBSTR); + // Back-up string to avoid reading beyond string. + lea(result, Address(result, cnt1, Address::times_2, -16)); + movl(cnt1, 8); + jmpb(SCAN_TO_SUBSTR); + + // Found a potential substr + bind(FOUND_CANDIDATE); + // After pcmpestri tmp(rcx) contains matched element index + + // Make sure string is still long enough + subl(cnt1, tmp); + cmpl(cnt1, cnt2); + jccb(Assembler::greaterEqual, FOUND_SUBSTR); + // Left less then substring. + + bind(RET_NOT_FOUND); + movl(result, -1); + jmpb(CLEANUP); + + bind(FOUND_SUBSTR); + // Compute start addr of substr + lea(result, Address(result, tmp, Address::times_2)); + + if (int_cnt2 > 0) { // Constant substring + // Repeat search for small substring (< 8 chars) + // from new point without reloading substring. + // Have to check that we don't read beyond string. + cmpl(tmp, 8-int_cnt2); + jccb(Assembler::greater, ADJUST_STR); + // Fall through if matched whole substring. + } else { // non constant + assert(int_cnt2 == -1, "should be != 0"); + + addl(tmp, cnt2); + // Found result if we matched whole substring. + cmpl(tmp, 8); + jccb(Assembler::lessEqual, RET_FOUND); + + // Repeat search for small substring (<= 8 chars) + // from new point 'str1' without reloading substring. + cmpl(cnt2, 8); + // Have to check that we don't read beyond string. + jccb(Assembler::lessEqual, ADJUST_STR); + + Label CHECK_NEXT, CONT_SCAN_SUBSTR, RET_FOUND_LONG; + // Compare the rest of substring (> 8 chars). + movptr(str1, result); + + cmpl(tmp, cnt2); + // First 8 chars are already matched. + jccb(Assembler::equal, CHECK_NEXT); + + bind(SCAN_SUBSTR); + pcmpestri(vec, Address(str1, 0), 0x0d); + // Need to reload strings pointers if not matched whole vector + jcc(Assembler::noOverflow, RELOAD_SUBSTR); // OF == 0 + + bind(CHECK_NEXT); + subl(cnt2, 8); + jccb(Assembler::lessEqual, RET_FOUND_LONG); // Found full substring + addptr(str1, 16); + addptr(str2, 16); + subl(cnt1, 8); + cmpl(cnt2, 8); // Do not read beyond substring + jccb(Assembler::greaterEqual, CONT_SCAN_SUBSTR); + // Back-up strings to avoid reading beyond substring. + lea(str2, Address(str2, cnt2, Address::times_2, -16)); + lea(str1, Address(str1, cnt2, Address::times_2, -16)); + subl(cnt1, cnt2); + movl(cnt2, 8); + addl(cnt1, 8); + bind(CONT_SCAN_SUBSTR); + movdqu(vec, Address(str2, 0)); + jmpb(SCAN_SUBSTR); + + bind(RET_FOUND_LONG); + movptr(str1, Address(rsp, wordSize)); + } // non constant + + bind(RET_FOUND); + // Compute substr offset + subptr(result, str1); + shrl(result, 1); // index + + bind(CLEANUP); + pop(rsp); // restore SP + +} // string_indexof + +// Compare strings. +void MacroAssembler::string_compare(Register str1, Register str2, + Register cnt1, Register cnt2, Register result, + XMMRegister vec1) { + ShortBranchVerifier sbv(this); + Label LENGTH_DIFF_LABEL, POP_LABEL, DONE_LABEL, WHILE_HEAD_LABEL; + + // Compute the minimum of the string lengths and the + // difference of the string lengths (stack). + // Do the conditional move stuff + movl(result, cnt1); + subl(cnt1, cnt2); + push(cnt1); + cmov32(Assembler::lessEqual, cnt2, result); + + // Is the minimum length zero? + testl(cnt2, cnt2); + jcc(Assembler::zero, LENGTH_DIFF_LABEL); + + // Load first characters + load_unsigned_short(result, Address(str1, 0)); + load_unsigned_short(cnt1, Address(str2, 0)); + + // Compare first characters + subl(result, cnt1); + jcc(Assembler::notZero, POP_LABEL); + decrementl(cnt2); + jcc(Assembler::zero, LENGTH_DIFF_LABEL); + + { + // Check after comparing first character to see if strings are equivalent + Label LSkip2; + // Check if the strings start at same location + cmpptr(str1, str2); + jccb(Assembler::notEqual, LSkip2); + + // Check if the length difference is zero (from stack) + cmpl(Address(rsp, 0), 0x0); + jcc(Assembler::equal, LENGTH_DIFF_LABEL); + + // Strings might not be equivalent + bind(LSkip2); + } + + Address::ScaleFactor scale = Address::times_2; + int stride = 8; + + // Advance to next element + addptr(str1, 16/stride); + addptr(str2, 16/stride); + + if (UseSSE42Intrinsics) { + Label COMPARE_WIDE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_TAIL; + int pcmpmask = 0x19; + // Setup to compare 16-byte vectors + movl(result, cnt2); + andl(cnt2, ~(stride - 1)); // cnt2 holds the vector count + jccb(Assembler::zero, COMPARE_TAIL); + + lea(str1, Address(str1, result, scale)); + lea(str2, Address(str2, result, scale)); + negptr(result); + + // pcmpestri + // inputs: + // vec1- substring + // rax - negative string length (elements count) + // mem - scaned string + // rdx - string length (elements count) + // pcmpmask - cmp mode: 11000 (string compare with negated result) + // + 00 (unsigned bytes) or + 01 (unsigned shorts) + // outputs: + // rcx - first mismatched element index + assert(result == rax && cnt2 == rdx && cnt1 == rcx, "pcmpestri"); + + bind(COMPARE_WIDE_VECTORS); + movdqu(vec1, Address(str1, result, scale)); + pcmpestri(vec1, Address(str2, result, scale), pcmpmask); + // After pcmpestri cnt1(rcx) contains mismatched element index + + jccb(Assembler::below, VECTOR_NOT_EQUAL); // CF==1 + addptr(result, stride); + subptr(cnt2, stride); + jccb(Assembler::notZero, COMPARE_WIDE_VECTORS); + + // compare wide vectors tail + testl(result, result); + jccb(Assembler::zero, LENGTH_DIFF_LABEL); + + movl(cnt2, stride); + movl(result, stride); + negptr(result); + movdqu(vec1, Address(str1, result, scale)); + pcmpestri(vec1, Address(str2, result, scale), pcmpmask); + jccb(Assembler::aboveEqual, LENGTH_DIFF_LABEL); + + // Mismatched characters in the vectors + bind(VECTOR_NOT_EQUAL); + addptr(result, cnt1); + movptr(cnt2, result); + load_unsigned_short(result, Address(str1, cnt2, scale)); + load_unsigned_short(cnt1, Address(str2, cnt2, scale)); + subl(result, cnt1); + jmpb(POP_LABEL); + + bind(COMPARE_TAIL); // limit is zero + movl(cnt2, result); + // Fallthru to tail compare + } + + // Shift str2 and str1 to the end of the arrays, negate min + lea(str1, Address(str1, cnt2, scale, 0)); + lea(str2, Address(str2, cnt2, scale, 0)); + negptr(cnt2); + + // Compare the rest of the elements + bind(WHILE_HEAD_LABEL); + load_unsigned_short(result, Address(str1, cnt2, scale, 0)); + load_unsigned_short(cnt1, Address(str2, cnt2, scale, 0)); + subl(result, cnt1); + jccb(Assembler::notZero, POP_LABEL); + increment(cnt2); + jccb(Assembler::notZero, WHILE_HEAD_LABEL); + + // Strings are equal up to min length. Return the length difference. + bind(LENGTH_DIFF_LABEL); + pop(result); + jmpb(DONE_LABEL); + + // Discard the stored length difference + bind(POP_LABEL); + pop(cnt1); + + // That's it + bind(DONE_LABEL); +} + +// Compare char[] arrays aligned to 4 bytes or substrings. +void MacroAssembler::char_arrays_equals(bool is_array_equ, Register ary1, Register ary2, + Register limit, Register result, Register chr, + XMMRegister vec1, XMMRegister vec2) { + ShortBranchVerifier sbv(this); + Label TRUE_LABEL, FALSE_LABEL, DONE, COMPARE_VECTORS, COMPARE_CHAR; + + int length_offset = arrayOopDesc::length_offset_in_bytes(); + int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); + + // Check the input args + cmpptr(ary1, ary2); + jcc(Assembler::equal, TRUE_LABEL); + + if (is_array_equ) { + // Need additional checks for arrays_equals. + testptr(ary1, ary1); + jcc(Assembler::zero, FALSE_LABEL); + testptr(ary2, ary2); + jcc(Assembler::zero, FALSE_LABEL); + + // Check the lengths + movl(limit, Address(ary1, length_offset)); + cmpl(limit, Address(ary2, length_offset)); + jcc(Assembler::notEqual, FALSE_LABEL); + } + + // count == 0 + testl(limit, limit); + jcc(Assembler::zero, TRUE_LABEL); + + if (is_array_equ) { + // Load array address + lea(ary1, Address(ary1, base_offset)); + lea(ary2, Address(ary2, base_offset)); + } + + shll(limit, 1); // byte count != 0 + movl(result, limit); // copy + + if (UseSSE42Intrinsics) { + // With SSE4.2, use double quad vector compare + Label COMPARE_WIDE_VECTORS, COMPARE_TAIL; + + // Compare 16-byte vectors + andl(result, 0x0000000e); // tail count (in bytes) + andl(limit, 0xfffffff0); // vector count (in bytes) + jccb(Assembler::zero, COMPARE_TAIL); + + lea(ary1, Address(ary1, limit, Address::times_1)); + lea(ary2, Address(ary2, limit, Address::times_1)); + negptr(limit); + + bind(COMPARE_WIDE_VECTORS); + movdqu(vec1, Address(ary1, limit, Address::times_1)); + movdqu(vec2, Address(ary2, limit, Address::times_1)); + pxor(vec1, vec2); + + ptest(vec1, vec1); + jccb(Assembler::notZero, FALSE_LABEL); + addptr(limit, 16); + jcc(Assembler::notZero, COMPARE_WIDE_VECTORS); + + testl(result, result); + jccb(Assembler::zero, TRUE_LABEL); + + movdqu(vec1, Address(ary1, result, Address::times_1, -16)); + movdqu(vec2, Address(ary2, result, Address::times_1, -16)); + pxor(vec1, vec2); + + ptest(vec1, vec1); + jccb(Assembler::notZero, FALSE_LABEL); + jmpb(TRUE_LABEL); + + bind(COMPARE_TAIL); // limit is zero + movl(limit, result); + // Fallthru to tail compare + } + + // Compare 4-byte vectors + andl(limit, 0xfffffffc); // vector count (in bytes) + jccb(Assembler::zero, COMPARE_CHAR); + + lea(ary1, Address(ary1, limit, Address::times_1)); + lea(ary2, Address(ary2, limit, Address::times_1)); + negptr(limit); + + bind(COMPARE_VECTORS); + movl(chr, Address(ary1, limit, Address::times_1)); + cmpl(chr, Address(ary2, limit, Address::times_1)); + jccb(Assembler::notEqual, FALSE_LABEL); + addptr(limit, 4); + jcc(Assembler::notZero, COMPARE_VECTORS); + + // Compare trailing char (final 2 bytes), if any + bind(COMPARE_CHAR); + testl(result, 0x2); // tail char + jccb(Assembler::zero, TRUE_LABEL); + load_unsigned_short(chr, Address(ary1, 0)); + load_unsigned_short(limit, Address(ary2, 0)); + cmpl(chr, limit); + jccb(Assembler::notEqual, FALSE_LABEL); + + bind(TRUE_LABEL); + movl(result, 1); // return true + jmpb(DONE); + + bind(FALSE_LABEL); + xorl(result, result); // return false + + // That's it + bind(DONE); +} + +void MacroAssembler::generate_fill(BasicType t, bool aligned, + Register to, Register value, Register count, + Register rtmp, XMMRegister xtmp) { + ShortBranchVerifier sbv(this); + assert_different_registers(to, value, count, rtmp); + Label L_exit, L_skip_align1, L_skip_align2, L_fill_byte; + Label L_fill_2_bytes, L_fill_4_bytes; + + int shift = -1; + switch (t) { + case T_BYTE: + shift = 2; + break; + case T_SHORT: + shift = 1; + break; + case T_INT: + shift = 0; + break; + default: ShouldNotReachHere(); + } + + if (t == T_BYTE) { + andl(value, 0xff); + movl(rtmp, value); + shll(rtmp, 8); + orl(value, rtmp); + } + if (t == T_SHORT) { + andl(value, 0xffff); + } + if (t == T_BYTE || t == T_SHORT) { + movl(rtmp, value); + shll(rtmp, 16); + orl(value, rtmp); + } + + cmpl(count, 2<= 2, "supported cpu only" ); + Label L_fill_32_bytes_loop, L_check_fill_8_bytes, L_fill_8_bytes_loop, L_fill_8_bytes; + // Fill 32-byte chunks + movdl(xtmp, value); + pshufd(xtmp, xtmp, 0); + + subl(count, 8 << shift); + jcc(Assembler::less, L_check_fill_8_bytes); + align(16); + + BIND(L_fill_32_bytes_loop); + + if (UseUnalignedLoadStores) { + movdqu(Address(to, 0), xtmp); + movdqu(Address(to, 16), xtmp); + } else { + movq(Address(to, 0), xtmp); + movq(Address(to, 8), xtmp); + movq(Address(to, 16), xtmp); + movq(Address(to, 24), xtmp); + } + + addptr(to, 32); + subl(count, 8 << shift); + jcc(Assembler::greaterEqual, L_fill_32_bytes_loop); + BIND(L_check_fill_8_bytes); + addl(count, 8 << shift); + jccb(Assembler::zero, L_exit); + jmpb(L_fill_8_bytes); + + // + // length is too short, just fill qwords + // + BIND(L_fill_8_bytes_loop); + movq(Address(to, 0), xtmp); + addptr(to, 8); + BIND(L_fill_8_bytes); + subl(count, 1 << (shift + 1)); + jcc(Assembler::greaterEqual, L_fill_8_bytes_loop); + } + } + // fill trailing 4 bytes + BIND(L_fill_4_bytes); + testl(count, 1<cmp8(ExternalAddress((address)flag_addr), value); + _masm->jcc(Assembler::equal, _label); +} + +SkipIfEqual::~SkipIfEqual() { + _masm->bind(_label); +} diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp new file mode 100644 index 00000000000..36d4d231155 --- /dev/null +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp @@ -0,0 +1,1172 @@ +/* + * Copyright (c) 1997, 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 CPU_X86_VM_MACROASSEMBLER_X86_HPP +#define CPU_X86_VM_MACROASSEMBLER_X86_HPP + +#include "asm/assembler.hpp" + + +// MacroAssembler extends Assembler by frequently used macros. +// +// Instructions for which a 'better' code sequence exists depending +// on arguments should also go in here. + +class MacroAssembler: public Assembler { + friend class LIR_Assembler; + friend class Runtime1; // as_Address() + + protected: + + Address as_Address(AddressLiteral adr); + Address as_Address(ArrayAddress adr); + + // Support for VM calls + // + // This is the base routine called by the different versions of call_VM_leaf. The interpreter + // may customize this version by overriding it for its purposes (e.g., to save/restore + // additional registers when doing a VM call). +#ifdef CC_INTERP + // c++ interpreter never wants to use interp_masm version of call_VM + #define VIRTUAL +#else + #define VIRTUAL virtual +#endif + + VIRTUAL void call_VM_leaf_base( + address entry_point, // the entry point + int number_of_arguments // the number of arguments to pop after the call + ); + + // This is the base routine called by the different versions of call_VM. The interpreter + // may customize this version by overriding it for its purposes (e.g., to save/restore + // additional registers when doing a VM call). + // + // If no java_thread register is specified (noreg) than rdi will be used instead. call_VM_base + // returns the register which contains the thread upon return. If a thread register has been + // specified, the return value will correspond to that register. If no last_java_sp is specified + // (noreg) than rsp will be used instead. + VIRTUAL void call_VM_base( // returns the register containing the thread upon return + Register oop_result, // where an oop-result ends up if any; use noreg otherwise + Register java_thread, // the thread if computed before ; use noreg otherwise + Register last_java_sp, // to set up last_Java_frame in stubs; use noreg otherwise + address entry_point, // the entry point + int number_of_arguments, // the number of arguments (w/o thread) to pop after the call + bool check_exceptions // whether to check for pending exceptions after return + ); + + // These routines should emit JVMTI PopFrame and ForceEarlyReturn handling code. + // The implementation is only non-empty for the InterpreterMacroAssembler, + // as only the interpreter handles PopFrame and ForceEarlyReturn requests. + virtual void check_and_handle_popframe(Register java_thread); + virtual void check_and_handle_earlyret(Register java_thread); + + void call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions = true); + + // helpers for FPU flag access + // tmp is a temporary register, if none is available use noreg + void save_rax (Register tmp); + void restore_rax(Register tmp); + + public: + MacroAssembler(CodeBuffer* code) : Assembler(code) {} + + // Support for NULL-checks + // + // Generates code that causes a NULL OS exception if the content of reg is NULL. + // If the accessed location is M[reg + offset] and the offset is known, provide the + // offset. No explicit code generation is needed if the offset is within a certain + // range (0 <= offset <= page_size). + + void null_check(Register reg, int offset = -1); + static bool needs_explicit_null_check(intptr_t offset); + + // Required platform-specific helpers for Label::patch_instructions. + // They _shadow_ the declarations in AbstractAssembler, which are undefined. + void pd_patch_instruction(address branch, address target) { + unsigned char op = branch[0]; + assert(op == 0xE8 /* call */ || + op == 0xE9 /* jmp */ || + op == 0xEB /* short jmp */ || + (op & 0xF0) == 0x70 /* short jcc */ || + op == 0x0F && (branch[1] & 0xF0) == 0x80 /* jcc */, + "Invalid opcode at patch point"); + + if (op == 0xEB || (op & 0xF0) == 0x70) { + // short offset operators (jmp and jcc) + char* disp = (char*) &branch[1]; + int imm8 = target - (address) &disp[1]; + guarantee(this->is8bit(imm8), "Short forward jump exceeds 8-bit offset"); + *disp = imm8; + } else { + int* disp = (int*) &branch[(op == 0x0F)? 2: 1]; + int imm32 = target - (address) &disp[1]; + *disp = imm32; + } + } + +#ifndef PRODUCT + static void pd_print_patched_instruction(address branch) { + const char* s; + unsigned char op = branch[0]; + if (op == 0xE8) { + s = "call"; + } else if (op == 0xE9 || op == 0xEB) { + s = "jmp"; + } else if ((op & 0xF0) == 0x70) { + s = "jcc"; + } else if (op == 0x0F) { + s = "jcc"; + } else { + s = "????"; + } + tty->print("%s (unresolved)", s); + } +#endif + + // The following 4 methods return the offset of the appropriate move instruction + + // Support for fast byte/short loading with zero extension (depending on particular CPU) + int load_unsigned_byte(Register dst, Address src); + int load_unsigned_short(Register dst, Address src); + + // Support for fast byte/short loading with sign extension (depending on particular CPU) + int load_signed_byte(Register dst, Address src); + int load_signed_short(Register dst, Address src); + + // Support for sign-extension (hi:lo = extend_sign(lo)) + void extend_sign(Register hi, Register lo); + + // Load and store values by size and signed-ness + void load_sized_value(Register dst, Address src, size_t size_in_bytes, bool is_signed, Register dst2 = noreg); + void store_sized_value(Address dst, Register src, size_t size_in_bytes, Register src2 = noreg); + + // Support for inc/dec with optimal instruction selection depending on value + + void increment(Register reg, int value = 1) { LP64_ONLY(incrementq(reg, value)) NOT_LP64(incrementl(reg, value)) ; } + void decrement(Register reg, int value = 1) { LP64_ONLY(decrementq(reg, value)) NOT_LP64(decrementl(reg, value)) ; } + + void decrementl(Address dst, int value = 1); + void decrementl(Register reg, int value = 1); + + void decrementq(Register reg, int value = 1); + void decrementq(Address dst, int value = 1); + + void incrementl(Address dst, int value = 1); + void incrementl(Register reg, int value = 1); + + void incrementq(Register reg, int value = 1); + void incrementq(Address dst, int value = 1); + + + // Support optimal SSE move instructions. + void movflt(XMMRegister dst, XMMRegister src) { + if (UseXmmRegToRegMoveAll) { movaps(dst, src); return; } + else { movss (dst, src); return; } + } + void movflt(XMMRegister dst, Address src) { movss(dst, src); } + void movflt(XMMRegister dst, AddressLiteral src); + void movflt(Address dst, XMMRegister src) { movss(dst, src); } + + void movdbl(XMMRegister dst, XMMRegister src) { + if (UseXmmRegToRegMoveAll) { movapd(dst, src); return; } + else { movsd (dst, src); return; } + } + + void movdbl(XMMRegister dst, AddressLiteral src); + + void movdbl(XMMRegister dst, Address src) { + if (UseXmmLoadAndClearUpper) { movsd (dst, src); return; } + else { movlpd(dst, src); return; } + } + void movdbl(Address dst, XMMRegister src) { movsd(dst, src); } + + void incrementl(AddressLiteral dst); + void incrementl(ArrayAddress dst); + + // Alignment + void align(int modulus); + + // A 5 byte nop that is safe for patching (see patch_verified_entry) + void fat_nop(); + + // Stack frame creation/removal + void enter(); + void leave(); + + // Support for getting the JavaThread pointer (i.e.; a reference to thread-local information) + // The pointer will be loaded into the thread register. + void get_thread(Register thread); + + + // Support for VM calls + // + // It is imperative that all calls into the VM are handled via the call_VM macros. + // They make sure that the stack linkage is setup correctly. call_VM's correspond + // to ENTRY/ENTRY_X entry points while call_VM_leaf's correspond to LEAF entry points. + + + void call_VM(Register oop_result, + address entry_point, + bool check_exceptions = true); + void call_VM(Register oop_result, + address entry_point, + Register arg_1, + bool check_exceptions = true); + void call_VM(Register oop_result, + address entry_point, + Register arg_1, Register arg_2, + bool check_exceptions = true); + void call_VM(Register oop_result, + address entry_point, + Register arg_1, Register arg_2, Register arg_3, + bool check_exceptions = true); + + // Overloadings with last_Java_sp + void call_VM(Register oop_result, + Register last_java_sp, + address entry_point, + int number_of_arguments = 0, + bool check_exceptions = true); + void call_VM(Register oop_result, + Register last_java_sp, + address entry_point, + Register arg_1, bool + check_exceptions = true); + void call_VM(Register oop_result, + Register last_java_sp, + address entry_point, + Register arg_1, Register arg_2, + bool check_exceptions = true); + void call_VM(Register oop_result, + Register last_java_sp, + address entry_point, + Register arg_1, Register arg_2, Register arg_3, + bool check_exceptions = true); + + void get_vm_result (Register oop_result, Register thread); + void get_vm_result_2(Register metadata_result, Register thread); + + // These always tightly bind to MacroAssembler::call_VM_base + // bypassing the virtual implementation + void super_call_VM(Register oop_result, Register last_java_sp, address entry_point, int number_of_arguments = 0, bool check_exceptions = true); + void super_call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, bool check_exceptions = true); + void super_call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, Register arg_2, bool check_exceptions = true); + void super_call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, Register arg_2, Register arg_3, bool check_exceptions = true); + void super_call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, Register arg_2, Register arg_3, Register arg_4, bool check_exceptions = true); + + void call_VM_leaf(address entry_point, + int number_of_arguments = 0); + void call_VM_leaf(address entry_point, + Register arg_1); + void call_VM_leaf(address entry_point, + Register arg_1, Register arg_2); + void call_VM_leaf(address entry_point, + Register arg_1, Register arg_2, Register arg_3); + + // These always tightly bind to MacroAssembler::call_VM_leaf_base + // bypassing the virtual implementation + void super_call_VM_leaf(address entry_point); + void super_call_VM_leaf(address entry_point, Register arg_1); + void super_call_VM_leaf(address entry_point, Register arg_1, Register arg_2); + void super_call_VM_leaf(address entry_point, Register arg_1, Register arg_2, Register arg_3); + void super_call_VM_leaf(address entry_point, Register arg_1, Register arg_2, Register arg_3, Register arg_4); + + // last Java Frame (fills frame anchor) + void set_last_Java_frame(Register thread, + Register last_java_sp, + Register last_java_fp, + address last_java_pc); + + // thread in the default location (r15_thread on 64bit) + void set_last_Java_frame(Register last_java_sp, + Register last_java_fp, + address last_java_pc); + + void reset_last_Java_frame(Register thread, bool clear_fp, bool clear_pc); + + // thread in the default location (r15_thread on 64bit) + void reset_last_Java_frame(bool clear_fp, bool clear_pc); + + // Stores + void store_check(Register obj); // store check for obj - register is destroyed afterwards + void store_check(Register obj, Address dst); // same as above, dst is exact store location (reg. is destroyed) + +#ifndef SERIALGC + + void g1_write_barrier_pre(Register obj, + Register pre_val, + Register thread, + Register tmp, + bool tosca_live, + bool expand_call); + + void g1_write_barrier_post(Register store_addr, + Register new_val, + Register thread, + Register tmp, + Register tmp2); + +#endif // SERIALGC + + // split store_check(Register obj) to enhance instruction interleaving + void store_check_part_1(Register obj); + void store_check_part_2(Register obj); + + // C 'boolean' to Java boolean: x == 0 ? 0 : 1 + void c2bool(Register x); + + // C++ bool manipulation + + void movbool(Register dst, Address src); + void movbool(Address dst, bool boolconst); + void movbool(Address dst, Register src); + void testbool(Register dst); + + // oop manipulations + void load_klass(Register dst, Register src); + void store_klass(Register dst, Register src); + + void load_heap_oop(Register dst, Address src); + void load_heap_oop_not_null(Register dst, Address src); + void store_heap_oop(Address dst, Register src); + void cmp_heap_oop(Register src1, Address src2, Register tmp = noreg); + + // Used for storing NULL. All other oop constants should be + // stored using routines that take a jobject. + void store_heap_oop_null(Address dst); + + void load_prototype_header(Register dst, Register src); + +#ifdef _LP64 + void store_klass_gap(Register dst, Register src); + + // This dummy is to prevent a call to store_heap_oop from + // converting a zero (like NULL) into a Register by giving + // the compiler two choices it can't resolve + + void store_heap_oop(Address dst, void* dummy); + + void encode_heap_oop(Register r); + void decode_heap_oop(Register r); + void encode_heap_oop_not_null(Register r); + void decode_heap_oop_not_null(Register r); + void encode_heap_oop_not_null(Register dst, Register src); + void decode_heap_oop_not_null(Register dst, Register src); + + void set_narrow_oop(Register dst, jobject obj); + void set_narrow_oop(Address dst, jobject obj); + void cmp_narrow_oop(Register dst, jobject obj); + void cmp_narrow_oop(Address dst, jobject obj); + + void encode_klass_not_null(Register r); + void decode_klass_not_null(Register r); + void encode_klass_not_null(Register dst, Register src); + void decode_klass_not_null(Register dst, Register src); + void set_narrow_klass(Register dst, Klass* k); + void set_narrow_klass(Address dst, Klass* k); + void cmp_narrow_klass(Register dst, Klass* k); + void cmp_narrow_klass(Address dst, Klass* k); + + // if heap base register is used - reinit it with the correct value + void reinit_heapbase(); + + DEBUG_ONLY(void verify_heapbase(const char* msg);) + +#endif // _LP64 + + // Int division/remainder for Java + // (as idivl, but checks for special case as described in JVM spec.) + // returns idivl instruction offset for implicit exception handling + int corrected_idivl(Register reg); + + // Long division/remainder for Java + // (as idivq, but checks for special case as described in JVM spec.) + // returns idivq instruction offset for implicit exception handling + int corrected_idivq(Register reg); + + void int3(); + + // Long operation macros for a 32bit cpu + // Long negation for Java + void lneg(Register hi, Register lo); + + // Long multiplication for Java + // (destroys contents of eax, ebx, ecx and edx) + void lmul(int x_rsp_offset, int y_rsp_offset); // rdx:rax = x * y + + // Long shifts for Java + // (semantics as described in JVM spec.) + void lshl(Register hi, Register lo); // hi:lo << (rcx & 0x3f) + void lshr(Register hi, Register lo, bool sign_extension = false); // hi:lo >> (rcx & 0x3f) + + // Long compare for Java + // (semantics as described in JVM spec.) + void lcmp2int(Register x_hi, Register x_lo, Register y_hi, Register y_lo); // x_hi = lcmp(x, y) + + + // misc + + // Sign extension + void sign_extend_short(Register reg); + void sign_extend_byte(Register reg); + + // Division by power of 2, rounding towards 0 + void division_with_shift(Register reg, int shift_value); + + // Compares the top-most stack entries on the FPU stack and sets the eflags as follows: + // + // CF (corresponds to C0) if x < y + // PF (corresponds to C2) if unordered + // ZF (corresponds to C3) if x = y + // + // The arguments are in reversed order on the stack (i.e., top of stack is first argument). + // tmp is a temporary register, if none is available use noreg (only matters for non-P6 code) + void fcmp(Register tmp); + // Variant of the above which allows y to be further down the stack + // and which only pops x and y if specified. If pop_right is + // specified then pop_left must also be specified. + void fcmp(Register tmp, int index, bool pop_left, bool pop_right); + + // Floating-point comparison for Java + // Compares the top-most stack entries on the FPU stack and stores the result in dst. + // The arguments are in reversed order on the stack (i.e., top of stack is first argument). + // (semantics as described in JVM spec.) + void fcmp2int(Register dst, bool unordered_is_less); + // Variant of the above which allows y to be further down the stack + // and which only pops x and y if specified. If pop_right is + // specified then pop_left must also be specified. + void fcmp2int(Register dst, bool unordered_is_less, int index, bool pop_left, bool pop_right); + + // Floating-point remainder for Java (ST0 = ST0 fremr ST1, ST1 is empty afterwards) + // tmp is a temporary register, if none is available use noreg + void fremr(Register tmp); + + + // same as fcmp2int, but using SSE2 + void cmpss2int(XMMRegister opr1, XMMRegister opr2, Register dst, bool unordered_is_less); + void cmpsd2int(XMMRegister opr1, XMMRegister opr2, Register dst, bool unordered_is_less); + + // Inlined sin/cos generator for Java; must not use CPU instruction + // directly on Intel as it does not have high enough precision + // outside of the range [-pi/4, pi/4]. Extra argument indicate the + // number of FPU stack slots in use; all but the topmost will + // require saving if a slow case is necessary. Assumes argument is + // on FP TOS; result is on FP TOS. No cpu registers are changed by + // this code. + void trigfunc(char trig, int num_fpu_regs_in_use = 1); + + // branch to L if FPU flag C2 is set/not set + // tmp is a temporary register, if none is available use noreg + void jC2 (Register tmp, Label& L); + void jnC2(Register tmp, Label& L); + + // Pop ST (ffree & fincstp combined) + void fpop(); + + // pushes double TOS element of FPU stack on CPU stack; pops from FPU stack + void push_fTOS(); + + // pops double TOS element from CPU stack and pushes on FPU stack + void pop_fTOS(); + + void empty_FPU_stack(); + + void push_IU_state(); + void pop_IU_state(); + + void push_FPU_state(); + void pop_FPU_state(); + + void push_CPU_state(); + void pop_CPU_state(); + + // Round up to a power of two + void round_to(Register reg, int modulus); + + // Callee saved registers handling + void push_callee_saved_registers(); + void pop_callee_saved_registers(); + + // allocation + void eden_allocate( + Register obj, // result: pointer to object after successful allocation + Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise + int con_size_in_bytes, // object size in bytes if known at compile time + Register t1, // temp register + Label& slow_case // continuation point if fast allocation fails + ); + void tlab_allocate( + Register obj, // result: pointer to object after successful allocation + Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise + int con_size_in_bytes, // object size in bytes if known at compile time + Register t1, // temp register + Register t2, // temp register + Label& slow_case // continuation point if fast allocation fails + ); + Register tlab_refill(Label& retry_tlab, Label& try_eden, Label& slow_case); // returns TLS address + void incr_allocated_bytes(Register thread, + Register var_size_in_bytes, int con_size_in_bytes, + Register t1 = noreg); + + // interface method calling + void lookup_interface_method(Register recv_klass, + Register intf_klass, + RegisterOrConstant itable_index, + Register method_result, + Register scan_temp, + Label& no_such_interface); + + // virtual method calling + void lookup_virtual_method(Register recv_klass, + RegisterOrConstant vtable_index, + Register method_result); + + // Test sub_klass against super_klass, with fast and slow paths. + + // The fast path produces a tri-state answer: yes / no / maybe-slow. + // One of the three labels can be NULL, meaning take the fall-through. + // If super_check_offset is -1, the value is loaded up from super_klass. + // No registers are killed, except temp_reg. + void check_klass_subtype_fast_path(Register sub_klass, + Register super_klass, + Register temp_reg, + Label* L_success, + Label* L_failure, + Label* L_slow_path, + RegisterOrConstant super_check_offset = RegisterOrConstant(-1)); + + // The rest of the type check; must be wired to a corresponding fast path. + // It does not repeat the fast path logic, so don't use it standalone. + // The temp_reg and temp2_reg can be noreg, if no temps are available. + // Updates the sub's secondary super cache as necessary. + // If set_cond_codes, condition codes will be Z on success, NZ on failure. + void check_klass_subtype_slow_path(Register sub_klass, + Register super_klass, + Register temp_reg, + Register temp2_reg, + Label* L_success, + Label* L_failure, + bool set_cond_codes = false); + + // Simplified, combined version, good for typical uses. + // Falls through on failure. + void check_klass_subtype(Register sub_klass, + Register super_klass, + Register temp_reg, + Label& L_success); + + // method handles (JSR 292) + Address argument_address(RegisterOrConstant arg_slot, int extra_slot_offset = 0); + + //---- + void set_word_if_not_zero(Register reg); // sets reg to 1 if not zero, otherwise 0 + + // Debugging + + // only if +VerifyOops + // TODO: Make these macros with file and line like sparc version! + void verify_oop(Register reg, const char* s = "broken oop"); + void verify_oop_addr(Address addr, const char * s = "broken oop addr"); + + // TODO: verify method and klass metadata (compare against vptr?) + void _verify_method_ptr(Register reg, const char * msg, const char * file, int line) {} + void _verify_klass_ptr(Register reg, const char * msg, const char * file, int line){} + +#define verify_method_ptr(reg) _verify_method_ptr(reg, "broken method " #reg, __FILE__, __LINE__) +#define verify_klass_ptr(reg) _verify_klass_ptr(reg, "broken klass " #reg, __FILE__, __LINE__) + + // only if +VerifyFPU + void verify_FPU(int stack_depth, const char* s = "illegal FPU state"); + + // prints msg, dumps registers and stops execution + void stop(const char* msg); + + // prints msg and continues + void warn(const char* msg); + + // dumps registers and other state + void print_state(); + + static void debug32(int rdi, int rsi, int rbp, int rsp, int rbx, int rdx, int rcx, int rax, int eip, char* msg); + static void debug64(char* msg, int64_t pc, int64_t regs[]); + static void print_state32(int rdi, int rsi, int rbp, int rsp, int rbx, int rdx, int rcx, int rax, int eip); + static void print_state64(int64_t pc, int64_t regs[]); + + void os_breakpoint(); + + void untested() { stop("untested"); } + + void unimplemented(const char* what = "") { char* b = new char[1024]; jio_snprintf(b, 1024, "unimplemented: %s", what); stop(b); } + + void should_not_reach_here() { stop("should not reach here"); } + + void print_CPU_state(); + + // Stack overflow checking + void bang_stack_with_offset(int offset) { + // stack grows down, caller passes positive offset + assert(offset > 0, "must bang with negative offset"); + movl(Address(rsp, (-offset)), rax); + } + + // Writes to stack successive pages until offset reached to check for + // stack overflow + shadow pages. Also, clobbers tmp + void bang_stack_size(Register size, Register tmp); + + virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr, + Register tmp, + int offset); + + // Support for serializing memory accesses between threads + void serialize_memory(Register thread, Register tmp); + + void verify_tlab(); + + // Biased locking support + // lock_reg and obj_reg must be loaded up with the appropriate values. + // swap_reg must be rax, and is killed. + // tmp_reg is optional. If it is supplied (i.e., != noreg) it will + // be killed; if not supplied, push/pop will be used internally to + // allocate a temporary (inefficient, avoid if possible). + // Optional slow case is for implementations (interpreter and C1) which branch to + // slow case directly. Leaves condition codes set for C2's Fast_Lock node. + // Returns offset of first potentially-faulting instruction for null + // check info (currently consumed only by C1). If + // swap_reg_contains_mark is true then returns -1 as it is assumed + // the calling code has already passed any potential faults. + int biased_locking_enter(Register lock_reg, Register obj_reg, + Register swap_reg, Register tmp_reg, + bool swap_reg_contains_mark, + Label& done, Label* slow_case = NULL, + BiasedLockingCounters* counters = NULL); + void biased_locking_exit (Register obj_reg, Register temp_reg, Label& done); + + + Condition negate_condition(Condition cond); + + // Instructions that use AddressLiteral operands. These instruction can handle 32bit/64bit + // operands. In general the names are modified to avoid hiding the instruction in Assembler + // so that we don't need to implement all the varieties in the Assembler with trivial wrappers + // here in MacroAssembler. The major exception to this rule is call + + // Arithmetics + + + void addptr(Address dst, int32_t src) { LP64_ONLY(addq(dst, src)) NOT_LP64(addl(dst, src)) ; } + void addptr(Address dst, Register src); + + void addptr(Register dst, Address src) { LP64_ONLY(addq(dst, src)) NOT_LP64(addl(dst, src)); } + void addptr(Register dst, int32_t src); + void addptr(Register dst, Register src); + void addptr(Register dst, RegisterOrConstant src) { + if (src.is_constant()) addptr(dst, (int) src.as_constant()); + else addptr(dst, src.as_register()); + } + + void andptr(Register dst, int32_t src); + void andptr(Register src1, Register src2) { LP64_ONLY(andq(src1, src2)) NOT_LP64(andl(src1, src2)) ; } + + void cmp8(AddressLiteral src1, int imm); + + // renamed to drag out the casting of address to int32_t/intptr_t + void cmp32(Register src1, int32_t imm); + + void cmp32(AddressLiteral src1, int32_t imm); + // compare reg - mem, or reg - &mem + void cmp32(Register src1, AddressLiteral src2); + + void cmp32(Register src1, Address src2); + +#ifndef _LP64 + void cmpklass(Address dst, Metadata* obj); + void cmpklass(Register dst, Metadata* obj); + void cmpoop(Address dst, jobject obj); + void cmpoop(Register dst, jobject obj); +#endif // _LP64 + + // NOTE src2 must be the lval. This is NOT an mem-mem compare + void cmpptr(Address src1, AddressLiteral src2); + + void cmpptr(Register src1, AddressLiteral src2); + + void cmpptr(Register src1, Register src2) { LP64_ONLY(cmpq(src1, src2)) NOT_LP64(cmpl(src1, src2)) ; } + void cmpptr(Register src1, Address src2) { LP64_ONLY(cmpq(src1, src2)) NOT_LP64(cmpl(src1, src2)) ; } + // void cmpptr(Address src1, Register src2) { LP64_ONLY(cmpq(src1, src2)) NOT_LP64(cmpl(src1, src2)) ; } + + void cmpptr(Register src1, int32_t src2) { LP64_ONLY(cmpq(src1, src2)) NOT_LP64(cmpl(src1, src2)) ; } + void cmpptr(Address src1, int32_t src2) { LP64_ONLY(cmpq(src1, src2)) NOT_LP64(cmpl(src1, src2)) ; } + + // cmp64 to avoild hiding cmpq + void cmp64(Register src1, AddressLiteral src); + + void cmpxchgptr(Register reg, Address adr); + + void locked_cmpxchgptr(Register reg, AddressLiteral adr); + + + void imulptr(Register dst, Register src) { LP64_ONLY(imulq(dst, src)) NOT_LP64(imull(dst, src)); } + + + void negptr(Register dst) { LP64_ONLY(negq(dst)) NOT_LP64(negl(dst)); } + + void notptr(Register dst) { LP64_ONLY(notq(dst)) NOT_LP64(notl(dst)); } + + void shlptr(Register dst, int32_t shift); + void shlptr(Register dst) { LP64_ONLY(shlq(dst)) NOT_LP64(shll(dst)); } + + void shrptr(Register dst, int32_t shift); + void shrptr(Register dst) { LP64_ONLY(shrq(dst)) NOT_LP64(shrl(dst)); } + + void sarptr(Register dst) { LP64_ONLY(sarq(dst)) NOT_LP64(sarl(dst)); } + void sarptr(Register dst, int32_t src) { LP64_ONLY(sarq(dst, src)) NOT_LP64(sarl(dst, src)); } + + void subptr(Address dst, int32_t src) { LP64_ONLY(subq(dst, src)) NOT_LP64(subl(dst, src)); } + + void subptr(Register dst, Address src) { LP64_ONLY(subq(dst, src)) NOT_LP64(subl(dst, src)); } + void subptr(Register dst, int32_t src); + // Force generation of a 4 byte immediate value even if it fits into 8bit + void subptr_imm32(Register dst, int32_t src); + void subptr(Register dst, Register src); + void subptr(Register dst, RegisterOrConstant src) { + if (src.is_constant()) subptr(dst, (int) src.as_constant()); + else subptr(dst, src.as_register()); + } + + void sbbptr(Address dst, int32_t src) { LP64_ONLY(sbbq(dst, src)) NOT_LP64(sbbl(dst, src)); } + void sbbptr(Register dst, int32_t src) { LP64_ONLY(sbbq(dst, src)) NOT_LP64(sbbl(dst, src)); } + + void xchgptr(Register src1, Register src2) { LP64_ONLY(xchgq(src1, src2)) NOT_LP64(xchgl(src1, src2)) ; } + void xchgptr(Register src1, Address src2) { LP64_ONLY(xchgq(src1, src2)) NOT_LP64(xchgl(src1, src2)) ; } + + void xaddptr(Address src1, Register src2) { LP64_ONLY(xaddq(src1, src2)) NOT_LP64(xaddl(src1, src2)) ; } + + + + // Helper functions for statistics gathering. + // Conditionally (atomically, on MPs) increments passed counter address, preserving condition codes. + void cond_inc32(Condition cond, AddressLiteral counter_addr); + // Unconditional atomic increment. + void atomic_incl(AddressLiteral counter_addr); + + void lea(Register dst, AddressLiteral adr); + void lea(Address dst, AddressLiteral adr); + void lea(Register dst, Address adr) { Assembler::lea(dst, adr); } + + void leal32(Register dst, Address src) { leal(dst, src); } + + // Import other testl() methods from the parent class or else + // they will be hidden by the following overriding declaration. + using Assembler::testl; + void testl(Register dst, AddressLiteral src); + + void orptr(Register dst, Address src) { LP64_ONLY(orq(dst, src)) NOT_LP64(orl(dst, src)); } + void orptr(Register dst, Register src) { LP64_ONLY(orq(dst, src)) NOT_LP64(orl(dst, src)); } + void orptr(Register dst, int32_t src) { LP64_ONLY(orq(dst, src)) NOT_LP64(orl(dst, src)); } + + void testptr(Register src, int32_t imm32) { LP64_ONLY(testq(src, imm32)) NOT_LP64(testl(src, imm32)); } + void testptr(Register src1, Register src2); + + void xorptr(Register dst, Register src) { LP64_ONLY(xorq(dst, src)) NOT_LP64(xorl(dst, src)); } + void xorptr(Register dst, Address src) { LP64_ONLY(xorq(dst, src)) NOT_LP64(xorl(dst, src)); } + + // Calls + + void call(Label& L, relocInfo::relocType rtype); + void call(Register entry); + + // NOTE: this call tranfers to the effective address of entry NOT + // the address contained by entry. This is because this is more natural + // for jumps/calls. + void call(AddressLiteral entry); + + // Emit the CompiledIC call idiom + void ic_call(address entry); + + // Jumps + + // NOTE: these jumps tranfer to the effective address of dst NOT + // the address contained by dst. This is because this is more natural + // for jumps/calls. + void jump(AddressLiteral dst); + void jump_cc(Condition cc, AddressLiteral dst); + + // 32bit can do a case table jump in one instruction but we no longer allow the base + // to be installed in the Address class. This jump will tranfers to the address + // contained in the location described by entry (not the address of entry) + void jump(ArrayAddress entry); + + // Floating + + void andpd(XMMRegister dst, Address src) { Assembler::andpd(dst, src); } + void andpd(XMMRegister dst, AddressLiteral src); + + void andps(XMMRegister dst, XMMRegister src) { Assembler::andps(dst, src); } + void andps(XMMRegister dst, Address src) { Assembler::andps(dst, src); } + void andps(XMMRegister dst, AddressLiteral src); + + void comiss(XMMRegister dst, XMMRegister src) { Assembler::comiss(dst, src); } + void comiss(XMMRegister dst, Address src) { Assembler::comiss(dst, src); } + void comiss(XMMRegister dst, AddressLiteral src); + + void comisd(XMMRegister dst, XMMRegister src) { Assembler::comisd(dst, src); } + void comisd(XMMRegister dst, Address src) { Assembler::comisd(dst, src); } + void comisd(XMMRegister dst, AddressLiteral src); + + void fadd_s(Address src) { Assembler::fadd_s(src); } + void fadd_s(AddressLiteral src) { Assembler::fadd_s(as_Address(src)); } + + void fldcw(Address src) { Assembler::fldcw(src); } + void fldcw(AddressLiteral src); + + void fld_s(int index) { Assembler::fld_s(index); } + void fld_s(Address src) { Assembler::fld_s(src); } + void fld_s(AddressLiteral src); + + void fld_d(Address src) { Assembler::fld_d(src); } + void fld_d(AddressLiteral src); + + void fld_x(Address src) { Assembler::fld_x(src); } + void fld_x(AddressLiteral src); + + void fmul_s(Address src) { Assembler::fmul_s(src); } + void fmul_s(AddressLiteral src) { Assembler::fmul_s(as_Address(src)); } + + void ldmxcsr(Address src) { Assembler::ldmxcsr(src); } + void ldmxcsr(AddressLiteral src); + + // compute pow(x,y) and exp(x) with x86 instructions. Don't cover + // all corner cases and may result in NaN and require fallback to a + // runtime call. + void fast_pow(); + void fast_exp(); + void increase_precision(); + void restore_precision(); + + // computes exp(x). Fallback to runtime call included. + void exp_with_fallback(int num_fpu_regs_in_use) { pow_or_exp(true, num_fpu_regs_in_use); } + // computes pow(x,y). Fallback to runtime call included. + void pow_with_fallback(int num_fpu_regs_in_use) { pow_or_exp(false, num_fpu_regs_in_use); } + +private: + + // call runtime as a fallback for trig functions and pow/exp. + void fp_runtime_fallback(address runtime_entry, int nb_args, int num_fpu_regs_in_use); + + // computes 2^(Ylog2X); Ylog2X in ST(0) + void pow_exp_core_encoding(); + + // computes pow(x,y) or exp(x). Fallback to runtime call included. + void pow_or_exp(bool is_exp, int num_fpu_regs_in_use); + + // these are private because users should be doing movflt/movdbl + + void movss(Address dst, XMMRegister src) { Assembler::movss(dst, src); } + void movss(XMMRegister dst, XMMRegister src) { Assembler::movss(dst, src); } + void movss(XMMRegister dst, Address src) { Assembler::movss(dst, src); } + void movss(XMMRegister dst, AddressLiteral src); + + void movlpd(XMMRegister dst, Address src) {Assembler::movlpd(dst, src); } + void movlpd(XMMRegister dst, AddressLiteral src); + +public: + + void addsd(XMMRegister dst, XMMRegister src) { Assembler::addsd(dst, src); } + void addsd(XMMRegister dst, Address src) { Assembler::addsd(dst, src); } + void addsd(XMMRegister dst, AddressLiteral src); + + void addss(XMMRegister dst, XMMRegister src) { Assembler::addss(dst, src); } + void addss(XMMRegister dst, Address src) { Assembler::addss(dst, src); } + void addss(XMMRegister dst, AddressLiteral src); + + void divsd(XMMRegister dst, XMMRegister src) { Assembler::divsd(dst, src); } + void divsd(XMMRegister dst, Address src) { Assembler::divsd(dst, src); } + void divsd(XMMRegister dst, AddressLiteral src); + + void divss(XMMRegister dst, XMMRegister src) { Assembler::divss(dst, src); } + void divss(XMMRegister dst, Address src) { Assembler::divss(dst, src); } + void divss(XMMRegister dst, AddressLiteral src); + + // Move Unaligned Double Quadword + void movdqu(Address dst, XMMRegister src) { Assembler::movdqu(dst, src); } + void movdqu(XMMRegister dst, Address src) { Assembler::movdqu(dst, src); } + void movdqu(XMMRegister dst, XMMRegister src) { Assembler::movdqu(dst, src); } + void movdqu(XMMRegister dst, AddressLiteral src); + + void movsd(XMMRegister dst, XMMRegister src) { Assembler::movsd(dst, src); } + void movsd(Address dst, XMMRegister src) { Assembler::movsd(dst, src); } + void movsd(XMMRegister dst, Address src) { Assembler::movsd(dst, src); } + void movsd(XMMRegister dst, AddressLiteral src); + + void mulsd(XMMRegister dst, XMMRegister src) { Assembler::mulsd(dst, src); } + void mulsd(XMMRegister dst, Address src) { Assembler::mulsd(dst, src); } + void mulsd(XMMRegister dst, AddressLiteral src); + + void mulss(XMMRegister dst, XMMRegister src) { Assembler::mulss(dst, src); } + void mulss(XMMRegister dst, Address src) { Assembler::mulss(dst, src); } + void mulss(XMMRegister dst, AddressLiteral src); + + 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); + + void sqrtss(XMMRegister dst, XMMRegister src) { Assembler::sqrtss(dst, src); } + void sqrtss(XMMRegister dst, Address src) { Assembler::sqrtss(dst, src); } + void sqrtss(XMMRegister dst, AddressLiteral src); + + void subsd(XMMRegister dst, XMMRegister src) { Assembler::subsd(dst, src); } + void subsd(XMMRegister dst, Address src) { Assembler::subsd(dst, src); } + void subsd(XMMRegister dst, AddressLiteral src); + + void subss(XMMRegister dst, XMMRegister src) { Assembler::subss(dst, src); } + void subss(XMMRegister dst, Address src) { Assembler::subss(dst, src); } + void subss(XMMRegister dst, AddressLiteral src); + + void ucomiss(XMMRegister dst, XMMRegister src) { Assembler::ucomiss(dst, src); } + void ucomiss(XMMRegister dst, Address src) { Assembler::ucomiss(dst, src); } + void ucomiss(XMMRegister dst, AddressLiteral src); + + void ucomisd(XMMRegister dst, XMMRegister src) { Assembler::ucomisd(dst, src); } + void ucomisd(XMMRegister dst, Address src) { Assembler::ucomisd(dst, src); } + void ucomisd(XMMRegister dst, AddressLiteral src); + + // Bitwise Logical XOR of Packed Double-Precision Floating-Point Values + void xorpd(XMMRegister dst, XMMRegister src) { Assembler::xorpd(dst, src); } + void xorpd(XMMRegister dst, Address src) { Assembler::xorpd(dst, src); } + void xorpd(XMMRegister dst, AddressLiteral src); + + // Bitwise Logical XOR of Packed Single-Precision Floating-Point Values + void xorps(XMMRegister dst, XMMRegister src) { Assembler::xorps(dst, src); } + void xorps(XMMRegister dst, Address src) { Assembler::xorps(dst, src); } + void xorps(XMMRegister dst, AddressLiteral src); + + // Shuffle Bytes + void pshufb(XMMRegister dst, XMMRegister src) { Assembler::pshufb(dst, src); } + void pshufb(XMMRegister dst, Address src) { Assembler::pshufb(dst, src); } + void pshufb(XMMRegister dst, AddressLiteral src); + // AVX 3-operands instructions + + void vaddsd(XMMRegister dst, XMMRegister nds, XMMRegister src) { Assembler::vaddsd(dst, nds, src); } + void vaddsd(XMMRegister dst, XMMRegister nds, Address src) { Assembler::vaddsd(dst, nds, src); } + void vaddsd(XMMRegister dst, XMMRegister nds, AddressLiteral src); + + void vaddss(XMMRegister dst, XMMRegister nds, XMMRegister src) { Assembler::vaddss(dst, nds, src); } + void vaddss(XMMRegister dst, XMMRegister nds, Address src) { Assembler::vaddss(dst, nds, src); } + void vaddss(XMMRegister dst, XMMRegister nds, AddressLiteral src); + + void vandpd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { Assembler::vandpd(dst, nds, src, vector256); } + void vandpd(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { Assembler::vandpd(dst, nds, src, vector256); } + void vandpd(XMMRegister dst, XMMRegister nds, AddressLiteral src, bool vector256); + + void vandps(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { Assembler::vandps(dst, nds, src, vector256); } + void vandps(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { Assembler::vandps(dst, nds, src, vector256); } + void vandps(XMMRegister dst, XMMRegister nds, AddressLiteral src, bool vector256); + + void vdivsd(XMMRegister dst, XMMRegister nds, XMMRegister src) { Assembler::vdivsd(dst, nds, src); } + void vdivsd(XMMRegister dst, XMMRegister nds, Address src) { Assembler::vdivsd(dst, nds, src); } + void vdivsd(XMMRegister dst, XMMRegister nds, AddressLiteral src); + + void vdivss(XMMRegister dst, XMMRegister nds, XMMRegister src) { Assembler::vdivss(dst, nds, src); } + void vdivss(XMMRegister dst, XMMRegister nds, Address src) { Assembler::vdivss(dst, nds, src); } + void vdivss(XMMRegister dst, XMMRegister nds, AddressLiteral src); + + void vmulsd(XMMRegister dst, XMMRegister nds, XMMRegister src) { Assembler::vmulsd(dst, nds, src); } + void vmulsd(XMMRegister dst, XMMRegister nds, Address src) { Assembler::vmulsd(dst, nds, src); } + void vmulsd(XMMRegister dst, XMMRegister nds, AddressLiteral src); + + void vmulss(XMMRegister dst, XMMRegister nds, XMMRegister src) { Assembler::vmulss(dst, nds, src); } + void vmulss(XMMRegister dst, XMMRegister nds, Address src) { Assembler::vmulss(dst, nds, src); } + void vmulss(XMMRegister dst, XMMRegister nds, AddressLiteral src); + + void vsubsd(XMMRegister dst, XMMRegister nds, XMMRegister src) { Assembler::vsubsd(dst, nds, src); } + void vsubsd(XMMRegister dst, XMMRegister nds, Address src) { Assembler::vsubsd(dst, nds, src); } + void vsubsd(XMMRegister dst, XMMRegister nds, AddressLiteral src); + + void vsubss(XMMRegister dst, XMMRegister nds, XMMRegister src) { Assembler::vsubss(dst, nds, src); } + void vsubss(XMMRegister dst, XMMRegister nds, Address src) { Assembler::vsubss(dst, nds, src); } + void vsubss(XMMRegister dst, XMMRegister nds, AddressLiteral src); + + // AVX Vector instructions + + void vxorpd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { Assembler::vxorpd(dst, nds, src, vector256); } + void vxorpd(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { Assembler::vxorpd(dst, nds, src, vector256); } + void vxorpd(XMMRegister dst, XMMRegister nds, AddressLiteral src, bool vector256); + + void vxorps(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { Assembler::vxorps(dst, nds, src, vector256); } + void vxorps(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { Assembler::vxorps(dst, nds, src, vector256); } + void vxorps(XMMRegister dst, XMMRegister nds, AddressLiteral src, bool vector256); + + void vpxor(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { + if (UseAVX > 1 || !vector256) // vpxor 256 bit is available only in AVX2 + Assembler::vpxor(dst, nds, src, vector256); + else + Assembler::vxorpd(dst, nds, src, vector256); + } + void vpxor(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + if (UseAVX > 1 || !vector256) // vpxor 256 bit is available only in AVX2 + Assembler::vpxor(dst, nds, src, vector256); + else + Assembler::vxorpd(dst, nds, src, vector256); + } + + // Move packed integer values from low 128 bit to hign 128 bit in 256 bit vector. + void vinserti128h(XMMRegister dst, XMMRegister nds, XMMRegister src) { + if (UseAVX > 1) // vinserti128h is available only in AVX2 + Assembler::vinserti128h(dst, nds, src); + else + Assembler::vinsertf128h(dst, nds, src); + } + + // Data + + void cmov32( Condition cc, Register dst, Address src); + void cmov32( Condition cc, Register dst, Register src); + + void cmov( Condition cc, Register dst, Register src) { cmovptr(cc, dst, src); } + + void cmovptr(Condition cc, Register dst, Address src) { LP64_ONLY(cmovq(cc, dst, src)) NOT_LP64(cmov32(cc, dst, src)); } + void cmovptr(Condition cc, Register dst, Register src) { LP64_ONLY(cmovq(cc, dst, src)) NOT_LP64(cmov32(cc, dst, src)); } + + void movoop(Register dst, jobject obj); + void movoop(Address dst, jobject obj); + + void mov_metadata(Register dst, Metadata* obj); + void mov_metadata(Address dst, Metadata* obj); + + void movptr(ArrayAddress dst, Register src); + // can this do an lea? + void movptr(Register dst, ArrayAddress src); + + void movptr(Register dst, Address src); + + void movptr(Register dst, AddressLiteral src); + + void movptr(Register dst, intptr_t src); + void movptr(Register dst, Register src); + void movptr(Address dst, intptr_t src); + + void movptr(Address dst, Register src); + + void movptr(Register dst, RegisterOrConstant src) { + if (src.is_constant()) movptr(dst, src.as_constant()); + else movptr(dst, src.as_register()); + } + +#ifdef _LP64 + // Generally the next two are only used for moving NULL + // Although there are situations in initializing the mark word where + // they could be used. They are dangerous. + + // They only exist on LP64 so that int32_t and intptr_t are not the same + // and we have ambiguous declarations. + + void movptr(Address dst, int32_t imm32); + void movptr(Register dst, int32_t imm32); +#endif // _LP64 + + // to avoid hiding movl + void mov32(AddressLiteral dst, Register src); + void mov32(Register dst, AddressLiteral src); + + // to avoid hiding movb + void movbyte(ArrayAddress dst, int src); + + // Import other mov() methods from the parent class or else + // they will be hidden by the following overriding declaration. + using Assembler::movdl; + using Assembler::movq; + void movdl(XMMRegister dst, AddressLiteral src); + void movq(XMMRegister dst, AddressLiteral src); + + // Can push value or effective address + void pushptr(AddressLiteral src); + + void pushptr(Address src) { LP64_ONLY(pushq(src)) NOT_LP64(pushl(src)); } + void popptr(Address src) { LP64_ONLY(popq(src)) NOT_LP64(popl(src)); } + + void pushoop(jobject obj); + void pushklass(Metadata* obj); + + // sign extend as need a l to ptr sized element + void movl2ptr(Register dst, Address src) { LP64_ONLY(movslq(dst, src)) NOT_LP64(movl(dst, src)); } + void movl2ptr(Register dst, Register src) { LP64_ONLY(movslq(dst, src)) NOT_LP64(if (dst != src) movl(dst, src)); } + + // C2 compiled method's prolog code. + void verified_entry(int framesize, bool stack_bang, bool fp_mode_24b); + + // IndexOf strings. + // Small strings are loaded through stack if they cross page boundary. + void string_indexof(Register str1, Register str2, + Register cnt1, Register cnt2, + int int_cnt2, Register result, + XMMRegister vec, Register tmp); + + // IndexOf for constant substrings with size >= 8 elements + // which don't need to be loaded through stack. + void string_indexofC8(Register str1, Register str2, + Register cnt1, Register cnt2, + int int_cnt2, Register result, + XMMRegister vec, Register tmp); + + // Smallest code: we don't need to load through stack, + // check string tail. + + // Compare strings. + void string_compare(Register str1, Register str2, + Register cnt1, Register cnt2, Register result, + XMMRegister vec1); + + // Compare char[] arrays. + void char_arrays_equals(bool is_array_equ, Register ary1, Register ary2, + Register limit, Register result, Register chr, + XMMRegister vec1, XMMRegister vec2); + + // Fill primitive arrays + void generate_fill(BasicType t, bool aligned, + Register to, Register value, Register count, + Register rtmp, XMMRegister xtmp); + +#undef VIRTUAL + +}; + +/** + * class SkipIfEqual: + * + * Instantiating this class will result in assembly code being output that will + * jump around any code emitted between the creation of the instance and it's + * automatic destruction at the end of a scope block, depending on the value of + * the flag passed to the constructor, which will be checked at run-time. + */ +class SkipIfEqual { + private: + MacroAssembler* _masm; + Label _label; + + public: + SkipIfEqual(MacroAssembler*, const bool* flag_addr, bool value); + ~SkipIfEqual(); +}; + +#endif // CPU_X86_VM_MACROASSEMBLER_X86_HPP diff --git a/hotspot/src/cpu/x86/vm/metaspaceShared_x86_32.cpp b/hotspot/src/cpu/x86/vm/metaspaceShared_x86_32.cpp index a43fafdd31b..c2956a52a54 100644 --- a/hotspot/src/cpu/x86/vm/metaspaceShared_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/metaspaceShared_x86_32.cpp @@ -23,7 +23,8 @@ */ #include "precompiled.hpp" -#include "assembler_x86.inline.hpp" +#include "asm/macroAssembler.hpp" +#include "asm/codeBuffer.hpp" #include "memory/metaspaceShared.hpp" // Generate the self-patching vtable method: diff --git a/hotspot/src/cpu/x86/vm/metaspaceShared_x86_64.cpp b/hotspot/src/cpu/x86/vm/metaspaceShared_x86_64.cpp index 2ef2abf6a75..4ff6cc955d7 100644 --- a/hotspot/src/cpu/x86/vm/metaspaceShared_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/metaspaceShared_x86_64.cpp @@ -23,7 +23,8 @@ */ #include "precompiled.hpp" -#include "assembler_x86.inline.hpp" +#include "asm/macroAssembler.hpp" +#include "asm/codeBuffer.hpp" #include "memory/metaspaceShared.hpp" // Generate the self-patching vtable method: diff --git a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp index 88ec6b71965..95d5123f406 100644 --- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp +++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "asm/macroAssembler.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/interpreterRuntime.hpp" #include "memory/allocation.inline.hpp" @@ -168,8 +169,9 @@ void MethodHandles::jump_to_lambda_form(MacroAssembler* _masm, if (VerifyMethodHandles && !for_compiler_entry) { // make sure recv is already on stack + __ movptr(temp2, Address(method_temp, Method::const_offset())); __ load_sized_value(temp2, - Address(method_temp, Method::size_of_parameters_offset()), + Address(temp2, ConstMethod::size_of_parameters_offset()), sizeof(u2), /*is_signed*/ false); // assert(sizeof(u2) == sizeof(Method::_size_of_parameters), ""); Label L; @@ -233,8 +235,9 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* int ref_kind = signature_polymorphic_intrinsic_ref_kind(iid); assert(ref_kind != 0 || iid == vmIntrinsics::_invokeBasic, "must be _invokeBasic or a linkTo intrinsic"); if (ref_kind == 0 || MethodHandles::ref_kind_has_receiver(ref_kind)) { + __ movptr(rdx_argp, Address(rbx_method, Method::const_offset())); __ load_sized_value(rdx_argp, - Address(rbx_method, Method::size_of_parameters_offset()), + Address(rdx_argp, ConstMethod::size_of_parameters_offset()), sizeof(u2), /*is_signed*/ false); // assert(sizeof(u2) == sizeof(Method::_size_of_parameters), ""); rdx_first_arg_addr = __ argument_address(rdx_argp, -1); diff --git a/hotspot/src/cpu/x86/vm/nativeInst_x86.cpp b/hotspot/src/cpu/x86/vm/nativeInst_x86.cpp index 1cf509992ca..dccd7e0b7cd 100644 --- a/hotspot/src/cpu/x86/vm/nativeInst_x86.cpp +++ b/hotspot/src/cpu/x86/vm/nativeInst_x86.cpp @@ -23,7 +23,7 @@ */ #include "precompiled.hpp" -#include "assembler_x86.inline.hpp" +#include "asm/macroAssembler.hpp" #include "memory/resourceArea.hpp" #include "nativeInst_x86.hpp" #include "oops/oop.inline.hpp" diff --git a/hotspot/src/cpu/x86/vm/relocInfo_x86.cpp b/hotspot/src/cpu/x86/vm/relocInfo_x86.cpp index 1023695e853..d4a929613ab 100644 --- a/hotspot/src/cpu/x86/vm/relocInfo_x86.cpp +++ b/hotspot/src/cpu/x86/vm/relocInfo_x86.cpp @@ -23,8 +23,7 @@ */ #include "precompiled.hpp" -#include "asm/assembler.inline.hpp" -#include "assembler_x86.inline.hpp" +#include "asm/macroAssembler.hpp" #include "code/relocInfo.hpp" #include "nativeInst_x86.hpp" #include "oops/oop.inline.hpp" diff --git a/hotspot/src/cpu/x86/vm/runtime_x86_32.cpp b/hotspot/src/cpu/x86/vm/runtime_x86_32.cpp index c932f9fa2d1..1cc10d76622 100644 --- a/hotspot/src/cpu/x86/vm/runtime_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/runtime_x86_32.cpp @@ -24,12 +24,11 @@ #include "precompiled.hpp" #ifdef COMPILER2 -#include "asm/assembler.hpp" -#include "assembler_x86.inline.hpp" +#include "asm/macroAssembler.hpp" +#include "asm/macroAssembler.inline.hpp" #include "classfile/systemDictionary.hpp" #include "code/vmreg.hpp" #include "interpreter/interpreter.hpp" -#include "nativeInst_x86.hpp" #include "opto/runtime.hpp" #include "runtime/interfaceSupport.hpp" #include "runtime/sharedRuntime.hpp" diff --git a/hotspot/src/cpu/x86/vm/runtime_x86_64.cpp b/hotspot/src/cpu/x86/vm/runtime_x86_64.cpp index 8f53518bb4b..0c39aea845f 100644 --- a/hotspot/src/cpu/x86/vm/runtime_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/runtime_x86_64.cpp @@ -24,12 +24,11 @@ #include "precompiled.hpp" #ifdef COMPILER2 -#include "asm/assembler.hpp" -#include "assembler_x86.inline.hpp" +#include "asm/macroAssembler.hpp" +#include "asm/macroAssembler.inline.hpp" #include "classfile/systemDictionary.hpp" #include "code/vmreg.hpp" #include "interpreter/interpreter.hpp" -#include "nativeInst_x86.hpp" #include "opto/runtime.hpp" #include "runtime/interfaceSupport.hpp" #include "runtime/sharedRuntime.hpp" diff --git a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp index 7c3116a489c..dc705421ca9 100644 --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp @@ -23,8 +23,8 @@ */ #include "precompiled.hpp" -#include "asm/assembler.hpp" -#include "assembler_x86.inline.hpp" +#include "asm/macroAssembler.hpp" +#include "asm/macroAssembler.inline.hpp" #include "code/debugInfoRec.hpp" #include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" diff --git a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp index 271a045fb6d..50255eeef0e 100644 --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp @@ -23,8 +23,8 @@ */ #include "precompiled.hpp" -#include "asm/assembler.hpp" -#include "assembler_x86.inline.hpp" +#include "asm/macroAssembler.hpp" +#include "asm/macroAssembler.inline.hpp" #include "code/debugInfoRec.hpp" #include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp index bcb408b5bc8..52e3f4169af 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp @@ -23,8 +23,8 @@ */ #include "precompiled.hpp" -#include "asm/assembler.hpp" -#include "assembler_x86.inline.hpp" +#include "asm/macroAssembler.hpp" +#include "asm/macroAssembler.inline.hpp" #include "interpreter/interpreter.hpp" #include "nativeInst_x86.hpp" #include "oops/instanceOop.hpp" diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp index d205f963926..48f4af8dc17 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp @@ -23,8 +23,8 @@ */ #include "precompiled.hpp" -#include "asm/assembler.hpp" -#include "assembler_x86.inline.hpp" +#include "asm/macroAssembler.hpp" +#include "asm/macroAssembler.inline.hpp" #include "interpreter/interpreter.hpp" #include "nativeInst_x86.hpp" #include "oops/instanceOop.hpp" diff --git a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp index 4aff1d9663f..aabc3dbbacd 100644 --- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp @@ -23,7 +23,7 @@ */ #include "precompiled.hpp" -#include "asm/assembler.hpp" +#include "asm/macroAssembler.hpp" #include "interpreter/bytecodeHistogram.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/interpreterGenerator.hpp" @@ -424,8 +424,6 @@ void InterpreterGenerator::generate_counter_overflow(Label* do_continue) { // C++ interpreter only // rsi - previous interpreter state pointer - const Address size_of_parameters(rbx, Method::size_of_parameters_offset()); - // InterpreterRuntime::frequency_counter_overflow takes one argument // indicating if the counter overflow occurs at a backwards branch (non-NULL bcp). // The call returns the address of the verified entry point for the method or NULL @@ -868,12 +866,13 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) { // rsi: previous interpreter state (C++ interpreter) must preserve address entry_point = __ pc(); - - const Address size_of_parameters(rbx, Method::size_of_parameters_offset()); + const Address constMethod (rbx, Method::const_offset()); const Address invocation_counter(rbx, Method::invocation_counter_offset() + InvocationCounter::counter_offset()); const Address access_flags (rbx, Method::access_flags_offset()); + const Address size_of_parameters(rcx, ConstMethod::size_of_parameters_offset()); // get parameter size (always needed) + __ movptr(rcx, constMethod); __ load_unsigned_short(rcx, size_of_parameters); // native calls don't need the stack size check since they have no expression stack @@ -988,7 +987,9 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) { // allocate space for parameters __ get_method(method); - __ load_unsigned_short(t, Address(method, Method::size_of_parameters_offset())); + __ movptr(t, Address(method, Method::const_offset())); + __ load_unsigned_short(t, Address(t, ConstMethod::size_of_parameters_offset())); + __ shlptr(t, Interpreter::logStackElementSize); __ addptr(t, 2*wordSize); // allocate two more slots for JNIEnv and possible mirror __ subptr(rsp, t); @@ -1297,13 +1298,14 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) { // rsi: sender sp address entry_point = __ pc(); - - const Address size_of_parameters(rbx, Method::size_of_parameters_offset()); - const Address size_of_locals (rbx, Method::size_of_locals_offset()); + const Address constMethod (rbx, Method::const_offset()); const Address invocation_counter(rbx, Method::invocation_counter_offset() + InvocationCounter::counter_offset()); const Address access_flags (rbx, Method::access_flags_offset()); + const Address size_of_parameters(rdx, ConstMethod::size_of_parameters_offset()); + const Address size_of_locals (rdx, ConstMethod::size_of_locals_offset()); // get parameter size (always needed) + __ movptr(rdx, constMethod); __ load_unsigned_short(rcx, size_of_parameters); // rbx,: Method* @@ -1734,7 +1736,8 @@ void TemplateInterpreterGenerator::generate_throw_exception() { // Compute size of arguments for saving when returning to deoptimized caller __ get_method(rax); - __ load_unsigned_short(rax, Address(rax, in_bytes(Method::size_of_parameters_offset()))); + __ movptr(rax, Address(rax, Method::const_offset())); + __ load_unsigned_short(rax, Address(rax, ConstMethod::size_of_parameters_offset())); __ shlptr(rax, Interpreter::logStackElementSize); __ restore_locals(); __ subptr(rdi, rax); diff --git a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp index 75318ab42c8..3e3cc0fc1f5 100644 --- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp @@ -23,7 +23,7 @@ */ #include "precompiled.hpp" -#include "asm/assembler.hpp" +#include "asm/macroAssembler.hpp" #include "interpreter/bytecodeHistogram.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/interpreterGenerator.hpp" @@ -369,9 +369,6 @@ void InterpreterGenerator::generate_counter_overflow(Label* do_continue) { // Everything as it was on entry // rdx is not restored. Doesn't appear to really be set. - const Address size_of_parameters(rbx, - Method::size_of_parameters_offset()); - // InterpreterRuntime::frequency_counter_overflow takes two // arguments, the first (thread) is passed by call_VM, the second // indicates if the counter overflow occurs at a backwards branch @@ -844,14 +841,17 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) { address entry_point = __ pc(); - const Address size_of_parameters(rbx, Method:: - size_of_parameters_offset()); + const Address constMethod (rbx, Method::const_offset()); const Address invocation_counter(rbx, Method:: invocation_counter_offset() + InvocationCounter::counter_offset()); const Address access_flags (rbx, Method::access_flags_offset()); + const Address size_of_parameters(rcx, ConstMethod:: + size_of_parameters_offset()); + // get parameter size (always needed) + __ movptr(rcx, constMethod); __ load_unsigned_short(rcx, size_of_parameters); // native calls don't need the stack size check since they have no @@ -967,9 +967,8 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) { // allocate space for parameters __ get_method(method); - __ load_unsigned_short(t, - Address(method, - Method::size_of_parameters_offset())); + __ movptr(t, Address(method, Method::const_offset())); + __ load_unsigned_short(t, Address(t, ConstMethod::size_of_parameters_offset())); __ shll(t, Interpreter::logStackElementSize); __ subptr(rsp, t); @@ -1302,15 +1301,18 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) { // r13: sender sp address entry_point = __ pc(); - const Address size_of_parameters(rbx, - Method::size_of_parameters_offset()); - const Address size_of_locals(rbx, Method::size_of_locals_offset()); + const Address constMethod(rbx, Method::const_offset()); const Address invocation_counter(rbx, Method::invocation_counter_offset() + InvocationCounter::counter_offset()); const Address access_flags(rbx, Method::access_flags_offset()); + const Address size_of_parameters(rdx, + ConstMethod::size_of_parameters_offset()); + const Address size_of_locals(rdx, ConstMethod::size_of_locals_offset()); + // get parameter size (always needed) + __ movptr(rdx, constMethod); __ load_unsigned_short(rcx, size_of_parameters); // rbx: Method* @@ -1752,7 +1754,8 @@ void TemplateInterpreterGenerator::generate_throw_exception() { // Compute size of arguments for saving when returning to // deoptimized caller __ get_method(rax); - __ load_unsigned_short(rax, Address(rax, in_bytes(Method:: + __ movptr(rax, Address(rax, Method::const_offset())); + __ load_unsigned_short(rax, Address(rax, in_bytes(ConstMethod:: size_of_parameters_offset()))); __ shll(rax, Interpreter::logStackElementSize); __ restore_locals(); // XXX do we need this? diff --git a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp index 24d138e4917..e2a20531f82 100644 --- a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp @@ -23,7 +23,7 @@ */ #include "precompiled.hpp" -#include "asm/assembler.hpp" +#include "asm/macroAssembler.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/interpreterRuntime.hpp" #include "interpreter/templateTable.hpp" diff --git a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp index bb9b86f2473..eedab0b4b22 100644 --- a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "asm/macroAssembler.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/interpreterRuntime.hpp" #include "interpreter/templateTable.hpp" diff --git a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp index 21bb57335ff..f48e66012a8 100644 --- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp +++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp @@ -23,7 +23,8 @@ */ #include "precompiled.hpp" -#include "assembler_x86.inline.hpp" +#include "asm/macroAssembler.hpp" +#include "asm/macroAssembler.inline.hpp" #include "memory/resourceArea.hpp" #include "runtime/java.hpp" #include "runtime/stubCodeGenerator.hpp" diff --git a/hotspot/src/cpu/x86/vm/vtableStubs_x86_32.cpp b/hotspot/src/cpu/x86/vm/vtableStubs_x86_32.cpp index edf1ab1bfff..c470004ebc8 100644 --- a/hotspot/src/cpu/x86/vm/vtableStubs_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/vtableStubs_x86_32.cpp @@ -23,8 +23,7 @@ */ #include "precompiled.hpp" -#include "asm/assembler.hpp" -#include "assembler_x86.inline.hpp" +#include "asm/macroAssembler.hpp" #include "code/vtableStubs.hpp" #include "interp_masm_x86_32.hpp" #include "memory/resourceArea.hpp" diff --git a/hotspot/src/cpu/x86/vm/vtableStubs_x86_64.cpp b/hotspot/src/cpu/x86/vm/vtableStubs_x86_64.cpp index 867ebfa152f..0dc056cdbaf 100644 --- a/hotspot/src/cpu/x86/vm/vtableStubs_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/vtableStubs_x86_64.cpp @@ -23,8 +23,7 @@ */ #include "precompiled.hpp" -#include "asm/assembler.hpp" -#include "assembler_x86.inline.hpp" +#include "asm/macroAssembler.hpp" #include "code/vtableStubs.hpp" #include "interp_masm_x86_64.hpp" #include "memory/resourceArea.hpp" diff --git a/hotspot/src/cpu/zero/vm/assembler_zero.cpp b/hotspot/src/cpu/zero/vm/assembler_zero.cpp index a3e36276415..e37938c1fa7 100644 --- a/hotspot/src/cpu/zero/vm/assembler_zero.cpp +++ b/hotspot/src/cpu/zero/vm/assembler_zero.cpp @@ -46,6 +46,12 @@ int AbstractAssembler::code_fill_byte() { return 0; } +#ifdef ASSERT +bool AbstractAssembler::pd_check_instruction_mark() { + ShouldNotCallThis(); +} +#endif + void Assembler::pd_patch_instruction(address branch, address target) { ShouldNotCallThis(); } @@ -80,6 +86,11 @@ void MacroAssembler::store_oop(jobject obj) { emit_address((address) obj); } +void MacroAssembler::store_Metadata(Metadata* md) { + code_section()->relocate(pc(), metadata_Relocation::spec_for_immediate()); + emit_address((address) md); +} + static void should_not_call() { report_should_not_call(__FILE__, __LINE__); } diff --git a/hotspot/src/cpu/zero/vm/assembler_zero.hpp b/hotspot/src/cpu/zero/vm/assembler_zero.hpp index 2cc25a73aa0..724153982ac 100644 --- a/hotspot/src/cpu/zero/vm/assembler_zero.hpp +++ b/hotspot/src/cpu/zero/vm/assembler_zero.hpp @@ -55,14 +55,9 @@ class MacroAssembler : public Assembler { public: void advance(int bytes); void store_oop(jobject obj); + void store_Metadata(Metadata* obj); }; -#ifdef ASSERT -inline bool AbstractAssembler::pd_check_instruction_mark() { - ShouldNotCallThis(); -} -#endif - address ShouldNotCallThisStub(); address ShouldNotCallThisEntry(); diff --git a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp index ee855a9efbc..c6f82cd74a8 100644 --- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp +++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp @@ -1015,11 +1015,7 @@ int AbstractInterpreter::size_top_interpreter_activation(Method* method) { // Helper for figuring out if frames are interpreter frames bool CppInterpreter::contains(address pc) { -#ifdef PRODUCT - ShouldNotCallThis(); -#else return false; // make frame::print_value_on work -#endif // !PRODUCT } // Result handlers and convertors diff --git a/hotspot/src/cpu/zero/vm/globals_zero.hpp b/hotspot/src/cpu/zero/vm/globals_zero.hpp index 7e0ae86b3be..a3c7d244173 100644 --- a/hotspot/src/cpu/zero/vm/globals_zero.hpp +++ b/hotspot/src/cpu/zero/vm/globals_zero.hpp @@ -52,11 +52,7 @@ define_pd_global(intx, StackShadowPages, 5 LP64_ONLY(+1) DEBUG_ONLY(+3)); define_pd_global(bool, RewriteBytecodes, true); define_pd_global(bool, RewriteFrequentPairs, true); -#ifdef _ALLBSD_SOURCE define_pd_global(bool, UseMembar, true); -#else -define_pd_global(bool, UseMembar, false); -#endif // GC Ergo Flags define_pd_global(intx, CMSYoungGenPerWorker, 16*M); // default max size of CMS young gen, per GC worker thread diff --git a/hotspot/src/os/bsd/vm/osThread_bsd.cpp b/hotspot/src/os/bsd/vm/osThread_bsd.cpp index 98a3f2f6340..92c6d0c4dac 100644 --- a/hotspot/src/os/bsd/vm/osThread_bsd.cpp +++ b/hotspot/src/os/bsd/vm/osThread_bsd.cpp @@ -23,29 +23,10 @@ */ // no precompiled headers -#include "runtime/atomic.hpp" -#include "runtime/handles.inline.hpp" #include "runtime/mutexLocker.hpp" -#include "runtime/os.hpp" #include "runtime/osThread.hpp" -#include "runtime/safepoint.hpp" -#include "runtime/vmThread.hpp" -#ifdef TARGET_ARCH_x86 -# include "assembler_x86.inline.hpp" -#endif -#ifdef TARGET_ARCH_sparc -# include "assembler_sparc.inline.hpp" -#endif -#ifdef TARGET_ARCH_zero -# include "assembler_zero.inline.hpp" -#endif -#ifdef TARGET_ARCH_arm -# include "assembler_arm.inline.hpp" -#endif -#ifdef TARGET_ARCH_ppc -# include "assembler_ppc.inline.hpp" -#endif +#include void OSThread::pd_initialize() { assert(this != NULL, "check"); diff --git a/hotspot/src/os/bsd/vm/os_bsd.cpp b/hotspot/src/os/bsd/vm/os_bsd.cpp index b77f2f0d770..81b4c9d0caf 100644 --- a/hotspot/src/os/bsd/vm/os_bsd.cpp +++ b/hotspot/src/os/bsd/vm/os_bsd.cpp @@ -29,6 +29,7 @@ #include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" #include "compiler/compileBroker.hpp" +#include "compiler/disassembler.hpp" #include "interpreter/interpreter.hpp" #include "jvm_bsd.h" #include "memory/allocation.inline.hpp" @@ -62,26 +63,6 @@ #include "utilities/events.hpp" #include "utilities/growableArray.hpp" #include "utilities/vmError.hpp" -#ifdef TARGET_ARCH_x86 -# include "assembler_x86.inline.hpp" -# include "nativeInst_x86.hpp" -#endif -#ifdef TARGET_ARCH_sparc -# include "assembler_sparc.inline.hpp" -# include "nativeInst_sparc.hpp" -#endif -#ifdef TARGET_ARCH_zero -# include "assembler_zero.inline.hpp" -# include "nativeInst_zero.hpp" -#endif -#ifdef TARGET_ARCH_arm -# include "assembler_arm.inline.hpp" -# include "nativeInst_arm.hpp" -#endif -#ifdef TARGET_ARCH_ppc -# include "assembler_ppc.inline.hpp" -# include "nativeInst_ppc.hpp" -#endif // put OS-includes here # include diff --git a/hotspot/src/os/bsd/vm/os_bsd.inline.hpp b/hotspot/src/os/bsd/vm/os_bsd.inline.hpp index 651059fbe8a..6a7cdc08b5f 100644 --- a/hotspot/src/os/bsd/vm/os_bsd.inline.hpp +++ b/hotspot/src/os/bsd/vm/os_bsd.inline.hpp @@ -26,13 +26,13 @@ #define OS_BSD_VM_OS_BSD_INLINE_HPP #include "runtime/atomic.hpp" +#include "runtime/atomic.inline.hpp" #include "runtime/os.hpp" + #ifdef TARGET_OS_ARCH_bsd_x86 -# include "atomic_bsd_x86.inline.hpp" # include "orderAccess_bsd_x86.inline.hpp" #endif #ifdef TARGET_OS_ARCH_bsd_zero -# include "atomic_bsd_zero.inline.hpp" # include "orderAccess_bsd_zero.inline.hpp" #endif diff --git a/hotspot/src/os/linux/vm/osThread_linux.cpp b/hotspot/src/os/linux/vm/osThread_linux.cpp index 8ff88a9e34f..8d27b5651bc 100644 --- a/hotspot/src/os/linux/vm/osThread_linux.cpp +++ b/hotspot/src/os/linux/vm/osThread_linux.cpp @@ -23,29 +23,10 @@ */ // no precompiled headers -#include "runtime/atomic.hpp" -#include "runtime/handles.inline.hpp" -#include "runtime/mutexLocker.hpp" -#include "runtime/os.hpp" +#include "runtime/mutex.hpp" #include "runtime/osThread.hpp" -#include "runtime/safepoint.hpp" -#include "runtime/vmThread.hpp" -#ifdef TARGET_ARCH_x86 -# include "assembler_x86.inline.hpp" -#endif -#ifdef TARGET_ARCH_sparc -# include "assembler_sparc.inline.hpp" -#endif -#ifdef TARGET_ARCH_zero -# include "assembler_zero.inline.hpp" -#endif -#ifdef TARGET_ARCH_arm -# include "assembler_arm.inline.hpp" -#endif -#ifdef TARGET_ARCH_ppc -# include "assembler_ppc.inline.hpp" -#endif +#include void OSThread::pd_initialize() { assert(this != NULL, "check"); diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index 09d821423da..45dea5e95a8 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -29,6 +29,7 @@ #include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" #include "compiler/compileBroker.hpp" +#include "compiler/disassembler.hpp" #include "interpreter/interpreter.hpp" #include "jvm_linux.h" #include "memory/allocation.inline.hpp" @@ -62,26 +63,6 @@ #include "utilities/events.hpp" #include "utilities/growableArray.hpp" #include "utilities/vmError.hpp" -#ifdef TARGET_ARCH_x86 -# include "assembler_x86.inline.hpp" -# include "nativeInst_x86.hpp" -#endif -#ifdef TARGET_ARCH_sparc -# include "assembler_sparc.inline.hpp" -# include "nativeInst_sparc.hpp" -#endif -#ifdef TARGET_ARCH_zero -# include "assembler_zero.inline.hpp" -# include "nativeInst_zero.hpp" -#endif -#ifdef TARGET_ARCH_arm -# include "assembler_arm.inline.hpp" -# include "nativeInst_arm.hpp" -#endif -#ifdef TARGET_ARCH_ppc -# include "assembler_ppc.inline.hpp" -# include "nativeInst_ppc.hpp" -#endif // put OS-includes here # include diff --git a/hotspot/src/os/linux/vm/os_linux.inline.hpp b/hotspot/src/os/linux/vm/os_linux.inline.hpp index ba56240dc8e..c779f8a6aa5 100644 --- a/hotspot/src/os/linux/vm/os_linux.inline.hpp +++ b/hotspot/src/os/linux/vm/os_linux.inline.hpp @@ -26,25 +26,22 @@ #define OS_LINUX_VM_OS_LINUX_INLINE_HPP #include "runtime/atomic.hpp" +#include "runtime/atomic.inline.hpp" #include "runtime/os.hpp" + #ifdef TARGET_OS_ARCH_linux_x86 -# include "atomic_linux_x86.inline.hpp" # include "orderAccess_linux_x86.inline.hpp" #endif #ifdef TARGET_OS_ARCH_linux_sparc -# include "atomic_linux_sparc.inline.hpp" # include "orderAccess_linux_sparc.inline.hpp" #endif #ifdef TARGET_OS_ARCH_linux_zero -# include "atomic_linux_zero.inline.hpp" # include "orderAccess_linux_zero.inline.hpp" #endif #ifdef TARGET_OS_ARCH_linux_arm -# include "atomic_linux_arm.inline.hpp" # include "orderAccess_linux_arm.inline.hpp" #endif #ifdef TARGET_OS_ARCH_linux_ppc -# include "atomic_linux_ppc.inline.hpp" # include "orderAccess_linux_ppc.inline.hpp" #endif diff --git a/hotspot/src/os/solaris/vm/osThread_solaris.cpp b/hotspot/src/os/solaris/vm/osThread_solaris.cpp index 937ae5cbbcf..6310471f5e0 100644 --- a/hotspot/src/os/solaris/vm/osThread_solaris.cpp +++ b/hotspot/src/os/solaris/vm/osThread_solaris.cpp @@ -30,14 +30,8 @@ #include "runtime/osThread.hpp" #include "runtime/safepoint.hpp" #include "runtime/vmThread.hpp" -#ifdef TARGET_ARCH_x86 -# include "assembler_x86.inline.hpp" -#endif -#ifdef TARGET_ARCH_sparc -# include "assembler_sparc.inline.hpp" -#endif -# include +#include // *************************************************************** // Platform dependent initialization and cleanup diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index d25c2714b46..05b2ec0a58a 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -29,6 +29,7 @@ #include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" #include "compiler/compileBroker.hpp" +#include "compiler/disassembler.hpp" #include "interpreter/interpreter.hpp" #include "jvm_solaris.h" #include "memory/allocation.inline.hpp" @@ -63,14 +64,6 @@ #include "utilities/events.hpp" #include "utilities/growableArray.hpp" #include "utilities/vmError.hpp" -#ifdef TARGET_ARCH_x86 -# include "assembler_x86.inline.hpp" -# include "nativeInst_x86.hpp" -#endif -#ifdef TARGET_ARCH_sparc -# include "assembler_sparc.inline.hpp" -# include "nativeInst_sparc.hpp" -#endif // put OS-includes here # include diff --git a/hotspot/src/os/solaris/vm/os_solaris.inline.hpp b/hotspot/src/os/solaris/vm/os_solaris.inline.hpp index 3454f6d7ba4..a3f09d01d32 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.inline.hpp +++ b/hotspot/src/os/solaris/vm/os_solaris.inline.hpp @@ -26,13 +26,13 @@ #define OS_SOLARIS_VM_OS_SOLARIS_INLINE_HPP #include "runtime/atomic.hpp" +#include "runtime/atomic.inline.hpp" #include "runtime/os.hpp" + #ifdef TARGET_OS_ARCH_solaris_x86 -# include "atomic_solaris_x86.inline.hpp" # include "orderAccess_solaris_x86.inline.hpp" #endif #ifdef TARGET_OS_ARCH_solaris_sparc -# include "atomic_solaris_sparc.inline.hpp" # include "orderAccess_solaris_sparc.inline.hpp" #endif diff --git a/hotspot/src/os/windows/vm/osThread_windows.cpp b/hotspot/src/os/windows/vm/osThread_windows.cpp index 005643aa67a..d65d0d6f557 100644 --- a/hotspot/src/os/windows/vm/osThread_windows.cpp +++ b/hotspot/src/os/windows/vm/osThread_windows.cpp @@ -30,9 +30,6 @@ #include "runtime/osThread.hpp" #include "runtime/safepoint.hpp" #include "runtime/vmThread.hpp" -#ifdef TARGET_ARCH_x86 -# include "assembler_x86.inline.hpp" -#endif void OSThread::pd_initialize() { set_thread_handle(NULL); diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index 8e1685ae9cb..ddd3a79bfe2 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -32,6 +32,7 @@ #include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" #include "compiler/compileBroker.hpp" +#include "compiler/disassembler.hpp" #include "interpreter/interpreter.hpp" #include "jvm_windows.h" #include "memory/allocation.inline.hpp" @@ -65,10 +66,6 @@ #include "utilities/events.hpp" #include "utilities/growableArray.hpp" #include "utilities/vmError.hpp" -#ifdef TARGET_ARCH_x86 -# include "assembler_x86.inline.hpp" -# include "nativeInst_x86.hpp" -#endif #ifdef _DEBUG #include diff --git a/hotspot/src/os/windows/vm/os_windows.inline.hpp b/hotspot/src/os/windows/vm/os_windows.inline.hpp index cee281fada7..8f8c3c72fd2 100644 --- a/hotspot/src/os/windows/vm/os_windows.inline.hpp +++ b/hotspot/src/os/windows/vm/os_windows.inline.hpp @@ -26,9 +26,10 @@ #define OS_WINDOWS_VM_OS_WINDOWS_INLINE_HPP #include "runtime/atomic.hpp" +#include "runtime/atomic.inline.hpp" #include "runtime/os.hpp" + #ifdef TARGET_OS_ARCH_windows_x86 -# include "atomic_windows_x86.inline.hpp" # include "orderAccess_windows_x86.inline.hpp" #endif diff --git a/hotspot/src/os_cpu/bsd_x86/vm/assembler_bsd_x86.cpp b/hotspot/src/os_cpu/bsd_x86/vm/assembler_bsd_x86.cpp index 5cd94107507..18bed6b0a6c 100644 --- a/hotspot/src/os_cpu/bsd_x86/vm/assembler_bsd_x86.cpp +++ b/hotspot/src/os_cpu/bsd_x86/vm/assembler_bsd_x86.cpp @@ -23,8 +23,8 @@ */ #include "precompiled.hpp" -#include "asm/assembler.hpp" -#include "assembler_x86.inline.hpp" +#include "asm/macroAssembler.hpp" +#include "asm/macroAssembler.inline.hpp" #include "runtime/os.hpp" #include "runtime/threadLocalStorage.hpp" diff --git a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp index 4b67b60c7e1..fc55e4ec71e 100644 --- a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp +++ b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp @@ -23,7 +23,7 @@ */ // no precompiled headers -#include "assembler_x86.inline.hpp" +#include "asm/macroAssembler.hpp" #include "classfile/classLoader.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" @@ -33,7 +33,6 @@ #include "jvm_bsd.h" #include "memory/allocation.inline.hpp" #include "mutex_bsd.inline.hpp" -#include "nativeInst_x86.hpp" #include "os_share_bsd.hpp" #include "prims/jniFastGetField.hpp" #include "prims/jvm.h" diff --git a/hotspot/src/os_cpu/linux_sparc/vm/assembler_linux_sparc.cpp b/hotspot/src/os_cpu/linux_sparc/vm/assembler_linux_sparc.cpp index 20a5c5886dc..e13dc36700e 100644 --- a/hotspot/src/os_cpu/linux_sparc/vm/assembler_linux_sparc.cpp +++ b/hotspot/src/os_cpu/linux_sparc/vm/assembler_linux_sparc.cpp @@ -23,8 +23,7 @@ */ #include "precompiled.hpp" -#include "asm/assembler.hpp" -#include "assembler_sparc.inline.hpp" +#include "asm/macroAssembler.hpp" #include "runtime/os.hpp" #include "runtime/threadLocalStorage.hpp" diff --git a/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp b/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp index 97aeaa334fc..81c013301d2 100644 --- a/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp +++ b/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp @@ -23,7 +23,7 @@ */ // no precompiled headers -#include "assembler_sparc.inline.hpp" +#include "asm/macroAssembler.hpp" #include "classfile/classLoader.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" diff --git a/hotspot/src/os_cpu/linux_x86/vm/assembler_linux_x86.cpp b/hotspot/src/os_cpu/linux_x86/vm/assembler_linux_x86.cpp index 12275f55d07..5c0c07a0c91 100644 --- a/hotspot/src/os_cpu/linux_x86/vm/assembler_linux_x86.cpp +++ b/hotspot/src/os_cpu/linux_x86/vm/assembler_linux_x86.cpp @@ -23,8 +23,8 @@ */ #include "precompiled.hpp" -#include "asm/assembler.hpp" -#include "assembler_x86.inline.hpp" +#include "asm/macroAssembler.hpp" +#include "asm/macroAssembler.inline.hpp" #include "runtime/os.hpp" #include "runtime/threadLocalStorage.hpp" diff --git a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp index eabe912053d..907395bb22a 100644 --- a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp +++ b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp @@ -23,7 +23,7 @@ */ // no precompiled headers -#include "assembler_x86.inline.hpp" +#include "asm/macroAssembler.hpp" #include "classfile/classLoader.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" @@ -33,7 +33,6 @@ #include "jvm_linux.h" #include "memory/allocation.inline.hpp" #include "mutex_linux.inline.hpp" -#include "nativeInst_x86.hpp" #include "os_share_linux.hpp" #include "prims/jniFastGetField.hpp" #include "prims/jvm.h" diff --git a/hotspot/src/os_cpu/solaris_sparc/vm/assembler_solaris_sparc.cpp b/hotspot/src/os_cpu/solaris_sparc/vm/assembler_solaris_sparc.cpp index 5e9eaa12a31..c9e4c2cc0d0 100644 --- a/hotspot/src/os_cpu/solaris_sparc/vm/assembler_solaris_sparc.cpp +++ b/hotspot/src/os_cpu/solaris_sparc/vm/assembler_solaris_sparc.cpp @@ -23,8 +23,7 @@ */ #include "precompiled.hpp" -#include "asm/assembler.hpp" -#include "assembler_sparc.inline.hpp" +#include "asm/macroAssembler.inline.hpp" #include "runtime/os.hpp" #include "runtime/threadLocalStorage.hpp" diff --git a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp index dc75ff06f33..f0db469941a 100644 --- a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp +++ b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp @@ -23,7 +23,7 @@ */ // no precompiled headers -#include "assembler_sparc.inline.hpp" +#include "asm/macroAssembler.hpp" #include "classfile/classLoader.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" diff --git a/hotspot/src/os_cpu/solaris_x86/vm/assembler_solaris_x86.cpp b/hotspot/src/os_cpu/solaris_x86/vm/assembler_solaris_x86.cpp index d1cd12f2803..ed25848bca8 100644 --- a/hotspot/src/os_cpu/solaris_x86/vm/assembler_solaris_x86.cpp +++ b/hotspot/src/os_cpu/solaris_x86/vm/assembler_solaris_x86.cpp @@ -23,8 +23,8 @@ */ #include "precompiled.hpp" -#include "asm/assembler.hpp" -#include "assembler_x86.inline.hpp" +#include "asm/macroAssembler.hpp" +#include "asm/macroAssembler.inline.hpp" #include "runtime/os.hpp" #include "runtime/threadLocalStorage.hpp" diff --git a/hotspot/src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp b/hotspot/src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp index 223e69e5cde..5b5445da512 100644 --- a/hotspot/src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp +++ b/hotspot/src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp @@ -27,6 +27,7 @@ #include "runtime/atomic.hpp" #include "runtime/orderAccess.hpp" +#include "runtime/os.hpp" #include "vm_version_x86.hpp" // Implementation of class OrderAccess. diff --git a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp index e51bae1796f..d954063c296 100644 --- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp +++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp @@ -23,7 +23,7 @@ */ // no precompiled headers -#include "assembler_x86.inline.hpp" +#include "asm/macroAssembler.hpp" #include "classfile/classLoader.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" @@ -33,7 +33,6 @@ #include "jvm_solaris.h" #include "memory/allocation.inline.hpp" #include "mutex_solaris.inline.hpp" -#include "nativeInst_x86.hpp" #include "os_share_solaris.hpp" #include "prims/jniFastGetField.hpp" #include "prims/jvm.h" diff --git a/hotspot/src/os_cpu/windows_x86/vm/assembler_windows_x86.cpp b/hotspot/src/os_cpu/windows_x86/vm/assembler_windows_x86.cpp index 55e5053387d..ce629e20762 100644 --- a/hotspot/src/os_cpu/windows_x86/vm/assembler_windows_x86.cpp +++ b/hotspot/src/os_cpu/windows_x86/vm/assembler_windows_x86.cpp @@ -23,8 +23,8 @@ */ #include "precompiled.hpp" -#include "asm/assembler.hpp" -#include "assembler_x86.inline.hpp" +#include "asm/macroAssembler.hpp" +#include "asm/macroAssembler.inline.hpp" #include "runtime/os.hpp" #include "runtime/threadLocalStorage.hpp" diff --git a/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp b/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp index 4caf927cf7c..e8bd38dc13e 100644 --- a/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp +++ b/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp @@ -23,7 +23,7 @@ */ // no precompiled headers -#include "assembler_x86.inline.hpp" +#include "asm/macroAssembler.hpp" #include "classfile/classLoader.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" diff --git a/hotspot/src/share/tools/LogCompilation/README b/hotspot/src/share/tools/LogCompilation/README index ed3cbbc8121..90dc3b893bb 100644 --- a/hotspot/src/share/tools/LogCompilation/README +++ b/hotspot/src/share/tools/LogCompilation/README @@ -13,6 +13,6 @@ Adding the -i option with also report inlining like PrintInlining. More information about the LogCompilation output can be found at -http://wikis.sun.com/display/HotSpotInternals/LogCompilation+overview -http://wikis.sun.com/display/HotSpotInternals/PrintCompilation -http://wikis.sun.com/display/HotSpotInternals/LogCompilation+tool +https://wikis.oracle.com/display/HotSpotInternals/LogCompilation+overview +https://wikis.oracle.com/display/HotSpotInternals/PrintCompilation +https://wikis.oracle.com/display/HotSpotInternals/LogCompilation+tool diff --git a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java index 354b32a99d7..4870dffec2e 100644 --- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java +++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java @@ -38,6 +38,7 @@ public class CallSite { private String reason; private List calls; private int endNodes; + private int endLiveNodes; private double timeStamp; CallSite() { @@ -106,7 +107,7 @@ public class CallSite { } } if (getEndNodes() > 0) { - stream.printf(" (end time: %6.4f nodes: %d)", getTimeStamp(), getEndNodes()); + stream.printf(" (end time: %6.4f nodes: %d live: %d)", getTimeStamp(), getEndNodes(), getEndLiveNodes()); } stream.println(""); if (getReceiver() != null) { @@ -195,6 +196,14 @@ public class CallSite { return endNodes; } + void setEndLiveNodes(int n) { + endLiveNodes = n; + } + + public int getEndLiveNodes() { + return endLiveNodes; + } + void setTimeStamp(double time) { timeStamp = time; } diff --git a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCompilation.java b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCompilation.java index 12689b0d3cc..46991bc8da6 100644 --- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCompilation.java +++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogCompilation.java @@ -37,13 +37,13 @@ import org.xml.sax.helpers.*; public class LogCompilation extends DefaultHandler implements ErrorHandler, Constants { public static void usage(int exitcode) { - System.out.println("Usage: LogCompilation [ -v ] [ -c ] [ -s ] [ -e | -N ] file1 ..."); + System.out.println("Usage: LogCompilation [ -v ] [ -c ] [ -s ] [ -e | -n ] file1 ..."); System.out.println(" -c: clean up malformed 1.5 xml"); System.out.println(" -i: print inlining decisions"); System.out.println(" -S: print compilation statistics"); System.out.println(" -s: sort events by start time"); System.out.println(" -e: sort events by elapsed time"); - System.out.println(" -N: sort events by name and start"); + System.out.println(" -n: sort events by name and start"); System.exit(exitcode); } @@ -137,7 +137,11 @@ public class LogCompilation extends DefaultHandler implements ErrorHandler, Cons v2 = Integer.valueOf(0); } phaseNodes.put(phase.getName(), Integer.valueOf(v2.intValue() + phase.getNodes())); - out.printf("\t%s %6.4f %d %d\n", phase.getName(), phase.getElapsedTime(), phase.getStartNodes(), phase.getNodes()); + /* Print phase name, elapsed time, nodes at the start of the phase, + nodes created in the phase, live nodes at the start of the phase, + live nodes added in the phase. + */ + out.printf("\t%s %6.4f %d %d %d %d\n", phase.getName(), phase.getElapsedTime(), phase.getStartNodes(), phase.getNodes(), phase.getStartLiveNodes(), phase.getLiveNodes()); } } else if (e instanceof MakeNotEntrantEvent) { MakeNotEntrantEvent mne = (MakeNotEntrantEvent) e; diff --git a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java index dc0b7ab3429..80a00364cc3 100644 --- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java +++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java @@ -224,7 +224,6 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants throw new InternalError("can't find " + name); } int indent = 0; - String compile_id; String type(String id) { String result = types.get(id); @@ -268,12 +267,18 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants if (qname.equals("phase")) { Phase p = new Phase(search(atts, "name"), Double.parseDouble(search(atts, "stamp")), - Integer.parseInt(search(atts, "nodes"))); + Integer.parseInt(search(atts, "nodes", "0")), + Integer.parseInt(search(atts, "live"))); phaseStack.push(p); } else if (qname.equals("phase_done")) { Phase p = phaseStack.pop(); - p.setEndNodes(Integer.parseInt(search(atts, "nodes"))); + if (! p.getId().equals(search(atts, "name"))) { + System.out.println("phase: " + p.getId()); + throw new InternalError("phase name mismatch"); + } p.setEnd(Double.parseDouble(search(atts, "stamp"))); + p.setEndNodes(Integer.parseInt(search(atts, "nodes", "0"))); + p.setEndLiveNodes(Integer.parseInt(search(atts, "live"))); compile.getPhases().add(p); } else if (qname.equals("task")) { compile = new Compilation(Integer.parseInt(search(atts, "compile_id", "-1"))); @@ -317,13 +322,16 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants m.setName(search(atts, "name")); m.setReturnType(type(search(atts, "return"))); m.setArguments(search(atts, "arguments", "void")); - m.setBytes(search(atts, "bytes")); - m.setIICount(search(atts, "iicount")); - m.setFlags(search(atts, "flags")); + + if (search(atts, "unloaded", "0").equals("0")) { + m.setBytes(search(atts, "bytes")); + m.setIICount(search(atts, "iicount")); + m.setFlags(search(atts, "flags")); + } methods.put(id, m); } else if (qname.equals("call")) { site = new CallSite(bci, method(search(atts, "method"))); - site.setCount(Integer.parseInt(search(atts, "count"))); + site.setCount(Integer.parseInt(search(atts, "count", "0"))); String receiver = atts.getValue("receiver"); if (receiver != null) { site.setReceiver(type(receiver)); @@ -406,6 +414,7 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants } else if (qname.equals("parse_done")) { CallSite call = scopes.pop(); call.setEndNodes(Integer.parseInt(search(atts, "nodes", "1"))); + call.setEndLiveNodes(Integer.parseInt(search(atts, "live", "1"))); call.setTimeStamp(Double.parseDouble(search(atts, "stamp"))); scopes.push(call); } diff --git a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Phase.java b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Phase.java index b448f457bee..af160abb81a 100644 --- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Phase.java +++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Phase.java @@ -30,10 +30,13 @@ public class Phase extends BasicLogEvent { private final int startNodes; private int endNodes; + private final int startLiveNodes; + private int endLiveNodes; - Phase(String n, double s, int nodes) { + Phase(String n, double s, int nodes, int live) { super(s, n); startNodes = nodes; + startLiveNodes = live; } int getNodes() { @@ -55,6 +58,22 @@ public class Phase extends BasicLogEvent { public int getEndNodes() { return endNodes; } + /* Number of live nodes added by the phase */ + int getLiveNodes() { + return getEndLiveNodes() - getStartLiveNodes(); + } + + void setEndLiveNodes(int n) { + endLiveNodes = n; + } + + public int getStartLiveNodes() { + return startLiveNodes; + } + + public int getEndLiveNodes() { + return endLiveNodes; + } @Override public void print(PrintStream stream) { diff --git a/hotspot/src/share/vm/adlc/main.cpp b/hotspot/src/share/vm/adlc/main.cpp index 3bfa0695e5b..8ecce63dd78 100644 --- a/hotspot/src/share/vm/adlc/main.cpp +++ b/hotspot/src/share/vm/adlc/main.cpp @@ -212,7 +212,7 @@ int main(int argc, char *argv[]) AD.addInclude(AD._CPP_file, "adfiles", get_basename(AD._VM_file._name)); AD.addInclude(AD._CPP_file, "adfiles", get_basename(AD._HPP_file._name)); AD.addInclude(AD._CPP_file, "memory/allocation.inline.hpp"); - AD.addInclude(AD._CPP_file, "asm/assembler.hpp"); + AD.addInclude(AD._CPP_file, "asm/macroAssembler.inline.hpp"); AD.addInclude(AD._CPP_file, "code/vmreg.hpp"); AD.addInclude(AD._CPP_file, "gc_interface/collectedHeap.inline.hpp"); AD.addInclude(AD._CPP_file, "oops/compiledICHolder.hpp"); @@ -231,17 +231,14 @@ int main(int argc, char *argv[]) AD.addInclude(AD._CPP_file, "runtime/stubRoutines.hpp"); AD.addInclude(AD._CPP_file, "utilities/growableArray.hpp"); #ifdef TARGET_ARCH_x86 - AD.addInclude(AD._CPP_file, "assembler_x86.inline.hpp"); AD.addInclude(AD._CPP_file, "nativeInst_x86.hpp"); AD.addInclude(AD._CPP_file, "vmreg_x86.inline.hpp"); #endif #ifdef TARGET_ARCH_sparc - AD.addInclude(AD._CPP_file, "assembler_sparc.inline.hpp"); AD.addInclude(AD._CPP_file, "nativeInst_sparc.hpp"); AD.addInclude(AD._CPP_file, "vmreg_sparc.inline.hpp"); #endif #ifdef TARGET_ARCH_arm - AD.addInclude(AD._CPP_file, "assembler_arm.inline.hpp"); AD.addInclude(AD._CPP_file, "nativeInst_arm.hpp"); AD.addInclude(AD._CPP_file, "vmreg_arm.inline.hpp"); #endif diff --git a/hotspot/src/share/vm/asm/assembler.cpp b/hotspot/src/share/vm/asm/assembler.cpp index 7f5dbf21ae4..6a34989ec7b 100644 --- a/hotspot/src/share/vm/asm/assembler.cpp +++ b/hotspot/src/share/vm/asm/assembler.cpp @@ -23,26 +23,13 @@ */ #include "precompiled.hpp" -#include "asm/assembler.hpp" -#include "asm/assembler.inline.hpp" +#include "asm/macroAssembler.hpp" +#include "asm/macroAssembler.inline.hpp" #include "asm/codeBuffer.hpp" +#include "runtime/atomic.hpp" +#include "runtime/atomic.inline.hpp" #include "runtime/icache.hpp" #include "runtime/os.hpp" -#ifdef TARGET_ARCH_x86 -# include "assembler_x86.inline.hpp" -#endif -#ifdef TARGET_ARCH_sparc -# include "assembler_sparc.inline.hpp" -#endif -#ifdef TARGET_ARCH_zero -# include "assembler_zero.inline.hpp" -#endif -#ifdef TARGET_ARCH_arm -# include "assembler_arm.inline.hpp" -#endif -#ifdef TARGET_ARCH_ppc -# include "assembler_ppc.inline.hpp" -#endif // Implementation of AbstractAssembler @@ -56,16 +43,13 @@ AbstractAssembler::AbstractAssembler(CodeBuffer* code) { if (code == NULL) return; CodeSection* cs = code->insts(); cs->clear_mark(); // new assembler kills old mark - _code_section = cs; - _code_begin = cs->start(); - _code_limit = cs->limit(); - _code_pos = cs->end(); - _oop_recorder= code->oop_recorder(); - DEBUG_ONLY( _short_branch_delta = 0; ) - if (_code_begin == NULL) { + if (cs->start() == NULL) { vm_exit_out_of_memory(0, err_msg("CodeCache: no room for %s", code->name())); } + _code_section = cs; + _oop_recorder= code->oop_recorder(); + DEBUG_ONLY( _short_branch_delta = 0; ) } void AbstractAssembler::set_code_section(CodeSection* cs) { @@ -73,9 +57,6 @@ void AbstractAssembler::set_code_section(CodeSection* cs) { assert(cs->is_allocated(), "need to pre-allocate this section"); cs->clear_mark(); // new assembly into this section kills old mark _code_section = cs; - _code_begin = cs->start(); - _code_limit = cs->limit(); - _code_pos = cs->end(); } // Inform CodeBuffer that incoming code and relocation will be for stubs @@ -83,7 +64,6 @@ address AbstractAssembler::start_a_stub(int required_space) { CodeBuffer* cb = code(); CodeSection* cs = cb->stubs(); assert(_code_section == cb->insts(), "not in insts?"); - sync(); if (cs->maybe_expand_to_ensure_remaining(required_space) && cb->blob() == NULL) { return NULL; @@ -96,7 +76,6 @@ address AbstractAssembler::start_a_stub(int required_space) { // Should not be called if start_a_stub() returned NULL void AbstractAssembler::end_a_stub() { assert(_code_section == code()->stubs(), "not in stubs?"); - sync(); set_code_section(code()->insts()); } @@ -104,8 +83,7 @@ void AbstractAssembler::end_a_stub() { address AbstractAssembler::start_a_const(int required_space, int required_align) { CodeBuffer* cb = code(); CodeSection* cs = cb->consts(); - assert(_code_section == cb->insts(), "not in insts?"); - sync(); + assert(_code_section == cb->insts() || _code_section == cb->stubs(), "not in insts/stubs?"); address end = cs->end(); int pad = -(intptr_t)end & (required_align-1); if (cs->maybe_expand_to_ensure_remaining(pad + required_space)) { @@ -121,16 +99,13 @@ address AbstractAssembler::start_a_const(int required_space, int required_align) } // Inform CodeBuffer that incoming code and relocation will be code -// Should not be called if start_a_const() returned NULL -void AbstractAssembler::end_a_const() { +// in section cs (insts or stubs). +void AbstractAssembler::end_a_const(CodeSection* cs) { assert(_code_section == code()->consts(), "not in consts?"); - sync(); - set_code_section(code()->insts()); + set_code_section(cs); } - void AbstractAssembler::flush() { - sync(); ICache::invalidate_range(addr_at(0), offset()); } diff --git a/hotspot/src/share/vm/asm/assembler.hpp b/hotspot/src/share/vm/asm/assembler.hpp index 897edb0a791..5de33dd503e 100644 --- a/hotspot/src/share/vm/asm/assembler.hpp +++ b/hotspot/src/share/vm/asm/assembler.hpp @@ -25,12 +25,14 @@ #ifndef SHARE_VM_ASM_ASSEMBLER_HPP #define SHARE_VM_ASM_ASSEMBLER_HPP +#include "asm/codeBuffer.hpp" #include "code/oopRecorder.hpp" #include "code/relocInfo.hpp" #include "memory/allocation.hpp" #include "utilities/debug.hpp" #include "utilities/growableArray.hpp" #include "utilities/top.hpp" + #ifdef TARGET_ARCH_x86 # include "register_x86.hpp" # include "vm_version_x86.hpp" @@ -54,7 +56,6 @@ // This file contains platform-independent assembler declarations. -class CodeBuffer; class MacroAssembler; class AbstractAssembler; class Label; @@ -122,7 +123,7 @@ class Label VALUE_OBJ_CLASS_SPEC { assert(_loc == -1, "already bound"); _loc = loc; } - void bind_loc(int pos, int sect); // = bind_loc(locator(pos, sect)) + void bind_loc(int pos, int sect) { bind_loc(CodeBuffer::locator(pos, sect)); } #ifndef PRODUCT // Iterates over all unresolved instructions for printing @@ -137,8 +138,8 @@ class Label VALUE_OBJ_CLASS_SPEC { assert(_loc >= 0, "unbound label"); return _loc; } - int loc_pos() const; // == locator_pos(loc()) - int loc_sect() const; // == locator_sect(loc()) + int loc_pos() const { return CodeBuffer::locator_pos(loc()); } + int loc_sect() const { return CodeBuffer::locator_sect(loc()); } bool is_bound() const { return _loc >= 0; } bool is_unbound() const { return _loc == -1 && _patch_index > 0; } @@ -201,26 +202,32 @@ class AbstractAssembler : public ResourceObj { protected: CodeSection* _code_section; // section within the code buffer - address _code_begin; // first byte of code buffer - address _code_limit; // first byte after code buffer - address _code_pos; // current code generation position OopRecorder* _oop_recorder; // support for relocInfo::oop_type // Code emission & accessing - address addr_at(int pos) const { return _code_begin + pos; } + address addr_at(int pos) const { return code_section()->start() + pos; } + // This routine is called with a label is used for an address. // Labels and displacements truck in offsets, but target must return a PC. - address target(Label& L); // return _code_section->target(L) + address target(Label& L) { return code_section()->target(L, pc()); } bool is8bit(int x) const { return -0x80 <= x && x < 0x80; } bool isByte(int x) const { return 0 <= x && x < 0x100; } bool isShiftCount(int x) const { return 0 <= x && x < 32; } - void emit_byte(int x); // emit a single byte - void emit_word(int x); // emit a 16-bit word (not a wordSize word!) - void emit_long(jint x); // emit a 32-bit word (not a longSize word!) - void emit_address(address x); // emit an address (not a longSize word!) + void emit_int8( int8_t x) { code_section()->emit_int8( x); } + void emit_int16( int16_t x) { code_section()->emit_int16( x); } + void emit_int32( int32_t x) { code_section()->emit_int32( x); } + void emit_int64( int64_t x) { code_section()->emit_int64( x); } + + void emit_float( jfloat x) { code_section()->emit_float( x); } + void emit_double( jdouble x) { code_section()->emit_double( x); } + void emit_address(address x) { code_section()->emit_address(x); } + + void emit_byte(int x) { emit_int8 (x); } // deprecated + void emit_word(int x) { emit_int16(x); } // deprecated + void emit_long(jint x) { emit_int32(x); } // deprecated // Instruction boundaries (required when emitting relocatable values). class InstructionMark: public StackObj { @@ -237,10 +244,10 @@ class AbstractAssembler : public ResourceObj { } }; friend class InstructionMark; - #ifdef ASSERT +#ifdef ASSERT // Make it return true on platforms which need to verify // instruction boundaries for some operations. - inline static bool pd_check_instruction_mark(); + static bool pd_check_instruction_mark(); // Add delta to short branch distance to verify that it still fit into imm8. int _short_branch_delta; @@ -262,13 +269,13 @@ class AbstractAssembler : public ResourceObj { _assm->clear_short_branch_delta(); } }; - #else +#else // Dummy in product. class ShortBranchVerifier: public StackObj { public: ShortBranchVerifier(AbstractAssembler* assm) {} }; - #endif +#endif // Label functions void print(Label& L); @@ -278,9 +285,6 @@ class AbstractAssembler : public ResourceObj { // Creation AbstractAssembler(CodeBuffer* code); - // save end pointer back to code buf. - void sync(); - // ensure buf contains all code (call this before using/copying the code) void flush(); @@ -308,26 +312,31 @@ class AbstractAssembler : public ResourceObj { static bool is_simm32(intptr_t x) { return is_simm(x, 32); } // Accessors - CodeBuffer* code() const; // _code_section->outer() CodeSection* code_section() const { return _code_section; } - int sect() const; // return _code_section->index() - address pc() const { return _code_pos; } - int offset() const { return _code_pos - _code_begin; } - int locator() const; // CodeBuffer::locator(offset(), sect()) + CodeBuffer* code() const { return code_section()->outer(); } + int sect() const { return code_section()->index(); } + address pc() const { return code_section()->end(); } + int offset() const { return code_section()->size(); } + int locator() const { return CodeBuffer::locator(offset(), sect()); } + OopRecorder* oop_recorder() const { return _oop_recorder; } void set_oop_recorder(OopRecorder* r) { _oop_recorder = r; } - address inst_mark() const; - void set_inst_mark(); - void clear_inst_mark(); + address inst_mark() const { return code_section()->mark(); } + void set_inst_mark() { code_section()->set_mark(); } + void clear_inst_mark() { code_section()->clear_mark(); } // Constants in code void a_byte(int x); void a_long(jint x); - void relocate(RelocationHolder const& rspec, int format = 0); + void relocate(RelocationHolder const& rspec, int format = 0) { + assert(!pd_check_instruction_mark() + || inst_mark() == NULL || inst_mark() == code_section()->end(), + "call relocate() between instructions"); + code_section()->relocate(code_section()->end(), rspec, format); + } void relocate( relocInfo::relocType rtype, int format = 0) { - if (rtype != relocInfo::none) - relocate(Relocation::spec_simple(rtype), format); + code_section()->relocate(code_section()->end(), rtype, format); } static int code_fill_byte(); // used to pad out odd-sized code buffers @@ -348,52 +357,55 @@ class AbstractAssembler : public ResourceObj { void end_a_stub(); // Ditto for constants. address start_a_const(int required_space, int required_align = sizeof(double)); - void end_a_const(); + void end_a_const(CodeSection* cs); // Pass the codesection to continue in (insts or stubs?). // constants support + // + // We must remember the code section (insts or stubs) in c1 + // so we can reset to the proper section in end_a_const(). address long_constant(jlong c) { + CodeSection* c1 = _code_section; address ptr = start_a_const(sizeof(c), sizeof(c)); if (ptr != NULL) { - *(jlong*)ptr = c; - _code_pos = ptr + sizeof(c); - end_a_const(); + emit_int64(c); + end_a_const(c1); } return ptr; } address double_constant(jdouble c) { + CodeSection* c1 = _code_section; address ptr = start_a_const(sizeof(c), sizeof(c)); if (ptr != NULL) { - *(jdouble*)ptr = c; - _code_pos = ptr + sizeof(c); - end_a_const(); + emit_double(c); + end_a_const(c1); } return ptr; } address float_constant(jfloat c) { + CodeSection* c1 = _code_section; address ptr = start_a_const(sizeof(c), sizeof(c)); if (ptr != NULL) { - *(jfloat*)ptr = c; - _code_pos = ptr + sizeof(c); - end_a_const(); + emit_float(c); + end_a_const(c1); } return ptr; } address address_constant(address c) { + CodeSection* c1 = _code_section; address ptr = start_a_const(sizeof(c), sizeof(c)); if (ptr != NULL) { - *(address*)ptr = c; - _code_pos = ptr + sizeof(c); - end_a_const(); + emit_address(c); + end_a_const(c1); } return ptr; } address address_constant(address c, RelocationHolder const& rspec) { + CodeSection* c1 = _code_section; address ptr = start_a_const(sizeof(c), sizeof(c)); if (ptr != NULL) { relocate(rspec); - *(address*)ptr = c; - _code_pos = ptr + sizeof(c); - end_a_const(); + emit_address(c); + end_a_const(c1); } return ptr; } diff --git a/hotspot/src/share/vm/asm/assembler.inline.hpp b/hotspot/src/share/vm/asm/assembler.inline.hpp index 6eede4445ca..2dcac0e2c17 100644 --- a/hotspot/src/share/vm/asm/assembler.inline.hpp +++ b/hotspot/src/share/vm/asm/assembler.inline.hpp @@ -26,92 +26,21 @@ #define SHARE_VM_ASM_ASSEMBLER_INLINE_HPP #include "asm/assembler.hpp" -#include "asm/codeBuffer.hpp" -#include "compiler/disassembler.hpp" -#include "runtime/threadLocalStorage.hpp" -inline void AbstractAssembler::sync() { - CodeSection* cs = code_section(); - guarantee(cs->start() == _code_begin, "must not shift code buffer"); - cs->set_end(_code_pos); -} - -inline void AbstractAssembler::emit_byte(int x) { - assert(isByte(x), "not a byte"); - *(unsigned char*)_code_pos = (unsigned char)x; - _code_pos += sizeof(unsigned char); - sync(); -} - - -inline void AbstractAssembler::emit_word(int x) { - *(short*)_code_pos = (short)x; - _code_pos += sizeof(short); - sync(); -} - - -inline void AbstractAssembler::emit_long(jint x) { - *(jint*)_code_pos = x; - _code_pos += sizeof(jint); - sync(); -} - -inline void AbstractAssembler::emit_address(address x) { - *(address*)_code_pos = x; - _code_pos += sizeof(address); - sync(); -} - -inline address AbstractAssembler::inst_mark() const { - return code_section()->mark(); -} - - -inline void AbstractAssembler::set_inst_mark() { - code_section()->set_mark(); -} - - -inline void AbstractAssembler::clear_inst_mark() { - code_section()->clear_mark(); -} - - -inline void AbstractAssembler::relocate(RelocationHolder const& rspec, int format) { - assert(!pd_check_instruction_mark() - || inst_mark() == NULL || inst_mark() == _code_pos, - "call relocate() between instructions"); - code_section()->relocate(_code_pos, rspec, format); -} - - -inline CodeBuffer* AbstractAssembler::code() const { - return code_section()->outer(); -} - -inline int AbstractAssembler::sect() const { - return code_section()->index(); -} - -inline int AbstractAssembler::locator() const { - return CodeBuffer::locator(offset(), sect()); -} - -inline address AbstractAssembler::target(Label& L) { - return code_section()->target(L, pc()); -} - -inline int Label::loc_pos() const { - return CodeBuffer::locator_pos(loc()); -} - -inline int Label::loc_sect() const { - return CodeBuffer::locator_sect(loc()); -} - -inline void Label::bind_loc(int pos, int sect) { - bind_loc(CodeBuffer::locator(pos, sect)); -} +#ifdef TARGET_ARCH_x86 +# include "assembler_x86.inline.hpp" +#endif +#ifdef TARGET_ARCH_sparc +# include "assembler_sparc.inline.hpp" +#endif +#ifdef TARGET_ARCH_zero +# include "assembler_zero.inline.hpp" +#endif +#ifdef TARGET_ARCH_arm +# include "assembler_arm.inline.hpp" +#endif +#ifdef TARGET_ARCH_ppc +# include "assembler_ppc.inline.hpp" +#endif #endif // SHARE_VM_ASM_ASSEMBLER_INLINE_HPP diff --git a/hotspot/src/share/vm/asm/codeBuffer.cpp b/hotspot/src/share/vm/asm/codeBuffer.cpp index 3fb1f179b0c..6b5548a1951 100644 --- a/hotspot/src/share/vm/asm/codeBuffer.cpp +++ b/hotspot/src/share/vm/asm/codeBuffer.cpp @@ -254,6 +254,10 @@ address CodeBuffer::locator_address(int locator) const { return start + locator_pos(locator); } +bool CodeBuffer::is_backward_branch(Label& L) { + return L.is_bound() && insts_end() <= locator_address(L.loc()); +} + address CodeBuffer::decode_begin() { address begin = _insts.start(); if (_decode_begin != NULL && _decode_begin > begin) @@ -758,7 +762,18 @@ void CodeBuffer::relocate_code_to(CodeBuffer* dest) const { // Make the new code copy use the old copy's relocations: dest_cs->initialize_locs_from(cs); + } + // Do relocation after all sections are copied. + // This is necessary if the code uses constants in stubs, which are + // relocated when the corresponding instruction in the code (e.g., a + // call) is relocated. Stubs are placed behind the main code + // section, so that section has to be copied before relocating. + for (int n = (int) SECT_FIRST; n < (int)SECT_LIMIT; n++) { + // pull code out of each section + const CodeSection* cs = code_section(n); + if (cs->is_empty()) continue; // skip trivial section + CodeSection* dest_cs = dest->code_section(n); { // Repair the pc relative information in the code after the move RelocIterator iter(dest_cs); while (iter.next()) { diff --git a/hotspot/src/share/vm/asm/codeBuffer.hpp b/hotspot/src/share/vm/asm/codeBuffer.hpp index 63dba2dbb0d..d13697ef46e 100644 --- a/hotspot/src/share/vm/asm/codeBuffer.hpp +++ b/hotspot/src/share/vm/asm/codeBuffer.hpp @@ -25,17 +25,15 @@ #ifndef SHARE_VM_ASM_CODEBUFFER_HPP #define SHARE_VM_ASM_CODEBUFFER_HPP -#include "asm/assembler.hpp" #include "code/oopRecorder.hpp" #include "code/relocInfo.hpp" -class CodeComments; -class AbstractAssembler; -class MacroAssembler; -class PhaseCFG; -class Compile; -class BufferBlob; -class CodeBuffer; +class CodeComments; +class PhaseCFG; +class Compile; +class BufferBlob; +class CodeBuffer; +class Label; class CodeOffsets: public StackObj { public: @@ -194,10 +192,14 @@ class CodeSection VALUE_OBJ_CLASS_SPEC { } // Code emission - void emit_int8 (int8_t x) { *((int8_t*) end()) = x; set_end(end() + 1); } - void emit_int16(int16_t x) { *((int16_t*) end()) = x; set_end(end() + 2); } - void emit_int32(int32_t x) { *((int32_t*) end()) = x; set_end(end() + 4); } - void emit_int64(int64_t x) { *((int64_t*) end()) = x; set_end(end() + 8); } + void emit_int8 ( int8_t x) { *((int8_t*) end()) = x; set_end(end() + sizeof(int8_t)); } + void emit_int16( int16_t x) { *((int16_t*) end()) = x; set_end(end() + sizeof(int16_t)); } + void emit_int32( int32_t x) { *((int32_t*) end()) = x; set_end(end() + sizeof(int32_t)); } + void emit_int64( int64_t x) { *((int64_t*) end()) = x; set_end(end() + sizeof(int64_t)); } + + void emit_float( jfloat x) { *((jfloat*) end()) = x; set_end(end() + sizeof(jfloat)); } + void emit_double(jdouble x) { *((jdouble*) end()) = x; set_end(end() + sizeof(jdouble)); } + void emit_address(address x) { *((address*) end()) = x; set_end(end() + sizeof(address)); } // Share a scratch buffer for relocinfo. (Hacky; saves a resource allocation.) void initialize_shared_locs(relocInfo* buf, int length); @@ -451,6 +453,9 @@ class CodeBuffer: public StackObj { int locator(address addr) const; address locator_address(int locator) const; + // Heuristic for pre-packing the taken/not-taken bit of a predicted branch. + bool is_backward_branch(Label& L); + // Properties const char* name() const { return _name; } CodeBuffer* before_expand() const { return _before_expand; } diff --git a/hotspot/src/share/vm/asm/macroAssembler.hpp b/hotspot/src/share/vm/asm/macroAssembler.hpp new file mode 100644 index 00000000000..92ecd138634 --- /dev/null +++ b/hotspot/src/share/vm/asm/macroAssembler.hpp @@ -0,0 +1,46 @@ +/* + * 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_ASM_MACROASSEMBLER_HPP +#define SHARE_VM_ASM_MACROASSEMBLER_HPP + +#include "asm/assembler.hpp" + +#ifdef TARGET_ARCH_x86 +# include "macroAssembler_x86.hpp" +#endif +#ifdef TARGET_ARCH_sparc +# include "macroAssembler_sparc.hpp" +#endif +#ifdef TARGET_ARCH_zero +# include "assembler_zero.hpp" +#endif +#ifdef TARGET_ARCH_arm +# include "assembler_arm.hpp" +#endif +#ifdef TARGET_ARCH_ppc +# include "assembler_ppc.hpp" +#endif + +#endif // SHARE_VM_ASM_MACROASSEMBLER_HPP diff --git a/hotspot/src/share/vm/asm/macroAssembler.inline.hpp b/hotspot/src/share/vm/asm/macroAssembler.inline.hpp new file mode 100644 index 00000000000..70a157c91a2 --- /dev/null +++ b/hotspot/src/share/vm/asm/macroAssembler.inline.hpp @@ -0,0 +1,46 @@ +/* + * 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_ASM_MACROASSEMBLER_INLINE_HPP +#define SHARE_VM_ASM_MACROASSEMBLER_INLINE_HPP + +#include "asm/macroAssembler.hpp" + +#ifdef TARGET_ARCH_x86 +// no macroAssembler_x86.inline.hpp +#endif +#ifdef TARGET_ARCH_sparc +# include "macroAssembler_sparc.inline.hpp" +#endif +#ifdef TARGET_ARCH_zero +# include "assembler_zero.inline.hpp" +#endif +#ifdef TARGET_ARCH_arm +# include "assembler_arm.inline.hpp" +#endif +#ifdef TARGET_ARCH_ppc +# include "assembler_ppc.inline.hpp" +#endif + +#endif // SHARE_VM_ASM_MACROASSEMBLER_INLINE_HPP diff --git a/hotspot/src/share/vm/asm/register.hpp b/hotspot/src/share/vm/asm/register.hpp index 128b6070b1f..5afecdeb116 100644 --- a/hotspot/src/share/vm/asm/register.hpp +++ b/hotspot/src/share/vm/asm/register.hpp @@ -93,6 +93,21 @@ enum { name##_##type##EnumValue = value##_##type##EnumValue } #define REGISTER_DEFINITION(type, name) \ const type name = ((type)name##_##type##EnumValue) +#ifdef TARGET_ARCH_x86 +# include "register_x86.hpp" +#endif +#ifdef TARGET_ARCH_sparc +# include "register_sparc.hpp" +#endif +#ifdef TARGET_ARCH_zero +# include "register_zero.hpp" +#endif +#ifdef TARGET_ARCH_arm +# include "register_arm.hpp" +#endif +#ifdef TARGET_ARCH_ppc +# include "register_ppc.hpp" +#endif // Debugging support diff --git a/hotspot/src/share/vm/c1/c1_Compilation.cpp b/hotspot/src/share/vm/c1/c1_Compilation.cpp index 68d3d2cc36b..cc268ef1450 100644 --- a/hotspot/src/share/vm/c1/c1_Compilation.cpp +++ b/hotspot/src/share/vm/c1/c1_Compilation.cpp @@ -129,7 +129,15 @@ void Compilation::build_hir() { CHECK_BAILOUT(); // setup ir + CompileLog* log = this->log(); + if (log != NULL) { + log->begin_head("parse method='%d' ", + log->identify(_method)); + log->stamp(); + log->end_head(); + } _hir = new IR(this, method(), osr_bci()); + if (log) log->done("parse"); if (!_hir->is_valid()) { bailout("invalid parsing"); return; diff --git a/hotspot/src/share/vm/c1/c1_MacroAssembler.hpp b/hotspot/src/share/vm/c1/c1_MacroAssembler.hpp index 3b6bbabdc34..f5e84bbe5f2 100644 --- a/hotspot/src/share/vm/c1/c1_MacroAssembler.hpp +++ b/hotspot/src/share/vm/c1/c1_MacroAssembler.hpp @@ -25,22 +25,8 @@ #ifndef SHARE_VM_C1_C1_MACROASSEMBLER_HPP #define SHARE_VM_C1_C1_MACROASSEMBLER_HPP -#include "asm/assembler.hpp" -#ifdef TARGET_ARCH_x86 -# include "assembler_x86.inline.hpp" -#endif -#ifdef TARGET_ARCH_sparc -# include "assembler_sparc.inline.hpp" -#endif -#ifdef TARGET_ARCH_zero -# include "assembler_zero.inline.hpp" -#endif -#ifdef TARGET_ARCH_arm -# include "assembler_arm.inline.hpp" -#endif -#ifdef TARGET_ARCH_ppc -# include "assembler_ppc.inline.hpp" -#endif +#include "asm/macroAssembler.hpp" +#include "asm/macroAssembler.inline.hpp" class CodeEmitInfo; diff --git a/hotspot/src/share/vm/ci/ciMethod.cpp b/hotspot/src/share/vm/ci/ciMethod.cpp index ed1f4b8b24d..8ad9ecb1199 100644 --- a/hotspot/src/share/vm/ci/ciMethod.cpp +++ b/hotspot/src/share/vm/ci/ciMethod.cpp @@ -741,6 +741,24 @@ int ciMethod::interpreter_call_site_count(int bci) { return -1; // unknown } +// ------------------------------------------------------------------ +// ciMethod::get_field_at_bci +ciField* ciMethod::get_field_at_bci(int bci, bool &will_link) { + ciBytecodeStream iter(this); + iter.reset_to_bci(bci); + iter.next(); + return iter.get_field(will_link); +} + +// ------------------------------------------------------------------ +// ciMethod::get_method_at_bci +ciMethod* ciMethod::get_method_at_bci(int bci, bool &will_link, ciSignature* *declared_signature) { + ciBytecodeStream iter(this); + iter.reset_to_bci(bci); + iter.next(); + return iter.get_method(will_link, declared_signature); +} + // ------------------------------------------------------------------ // Adjust a CounterData count to be commensurate with // interpreter_invocation_count. If the MDO exists for diff --git a/hotspot/src/share/vm/ci/ciMethod.hpp b/hotspot/src/share/vm/ci/ciMethod.hpp index cf8a622fa7c..193eb68de05 100644 --- a/hotspot/src/share/vm/ci/ciMethod.hpp +++ b/hotspot/src/share/vm/ci/ciMethod.hpp @@ -226,6 +226,9 @@ class ciMethod : public ciMetadata { ciCallProfile call_profile_at_bci(int bci); int interpreter_call_site_count(int bci); + ciField* get_field_at_bci( int bci, bool &will_link); + ciMethod* get_method_at_bci(int bci, bool &will_link, ciSignature* *declared_signature); + // Given a certain calling environment, find the monomorphic target // for the call. Return NULL if the call is not monomorphic in // its calling environment. diff --git a/hotspot/src/share/vm/ci/ciSignature.hpp b/hotspot/src/share/vm/ci/ciSignature.hpp index 37506c953b4..1d0f067c3bc 100644 --- a/hotspot/src/share/vm/ci/ciSignature.hpp +++ b/hotspot/src/share/vm/ci/ciSignature.hpp @@ -57,12 +57,14 @@ public: ciSymbol* as_symbol() const { return _symbol; } ciKlass* accessing_klass() const { return _accessing_klass; } - ciType* return_type() const; - ciType* type_at(int index) const; + ciType* return_type() const; + ciType* type_at(int index) const; int size() const { return _size; } int count() const { return _count; } + int arg_size_for_bc(Bytecodes::Code bc) { return size() + (Bytecodes::has_receiver(bc) ? 1 : 0); } + bool equals(ciSignature* that); void print_signature(); diff --git a/hotspot/src/share/vm/classfile/javaClasses.cpp b/hotspot/src/share/vm/classfile/javaClasses.cpp index 80b15fbd2d1..514e15b3fde 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.cpp +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp @@ -327,14 +327,14 @@ jchar* java_lang_String::as_unicode_string(oop java_string, int& length) { return result; } -unsigned int java_lang_String::to_hash(oop java_string) { +unsigned int java_lang_String::hash_code(oop java_string) { int length = java_lang_String::length(java_string); - // Zero length string will hash to zero with String.toHash() function. + // Zero length string will hash to zero with String.hashCode() function. if (length == 0) return 0; typeArrayOop value = java_lang_String::value(java_string); int offset = java_lang_String::offset(java_string); - return java_lang_String::to_hash(value->char_at_addr(offset), length); + return java_lang_String::hash_code(value->char_at_addr(offset), length); } char* java_lang_String::as_quoted_ascii(oop java_string) { diff --git a/hotspot/src/share/vm/classfile/javaClasses.hpp b/hotspot/src/share/vm/classfile/javaClasses.hpp index 9359d5b3c6e..a60872b365a 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.hpp +++ b/hotspot/src/share/vm/classfile/javaClasses.hpp @@ -166,8 +166,8 @@ class java_lang_String : AllStatic { // objects in the shared archive file. // hash P(31) from Kernighan & Ritchie // - // For this reason, THIS ALGORITHM MUST MATCH String.toHash(). - template static unsigned int to_hash(T* s, int len) { + // For this reason, THIS ALGORITHM MUST MATCH String.hashCode(). + template static unsigned int hash_code(T* s, int len) { unsigned int h = 0; while (len-- > 0) { h = 31*h + (unsigned int) *s; @@ -175,10 +175,10 @@ class java_lang_String : AllStatic { } return h; } - static unsigned int to_hash(oop java_string); + static unsigned int hash_code(oop java_string); // This is the string hash code used by the StringTable, which may be - // the same as String.toHash or an alternate hash code. + // the same as String.hashCode or an alternate hash code. static unsigned int hash_string(oop java_string); static bool equals(oop java_string, jchar* chars, int len); diff --git a/hotspot/src/share/vm/classfile/symbolTable.cpp b/hotspot/src/share/vm/classfile/symbolTable.cpp index 3c936620521..87de232d7a5 100644 --- a/hotspot/src/share/vm/classfile/symbolTable.cpp +++ b/hotspot/src/share/vm/classfile/symbolTable.cpp @@ -179,7 +179,7 @@ Symbol* SymbolTable::lookup(int index, const char* name, unsigned int SymbolTable::hash_symbol(const char* s, int len) { return use_alternate_hashcode() ? AltHashing::murmur3_32(seed(), (const jbyte*)s, len) : - java_lang_String::to_hash(s, len); + java_lang_String::hash_code(s, len); } @@ -617,7 +617,7 @@ bool StringTable::_needs_rehashing = false; // Pick hashing algorithm unsigned int StringTable::hash_string(const jchar* s, int len) { return use_alternate_hashcode() ? AltHashing::murmur3_32(seed(), s, len) : - java_lang_String::to_hash(s, len); + java_lang_String::hash_code(s, len); } oop StringTable::lookup(int index, jchar* name, diff --git a/hotspot/src/share/vm/code/icBuffer.cpp b/hotspot/src/share/vm/code/icBuffer.cpp index 8d5200ce901..81ef87ce200 100644 --- a/hotspot/src/share/vm/code/icBuffer.cpp +++ b/hotspot/src/share/vm/code/icBuffer.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "code/codeCache.hpp" #include "code/compiledIC.hpp" #include "code/icBuffer.hpp" #include "code/nmethod.hpp" @@ -37,21 +38,6 @@ #include "oops/oop.inline2.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/stubRoutines.hpp" -#ifdef TARGET_ARCH_x86 -# include "assembler_x86.inline.hpp" -#endif -#ifdef TARGET_ARCH_sparc -# include "assembler_sparc.inline.hpp" -#endif -#ifdef TARGET_ARCH_zero -# include "assembler_zero.inline.hpp" -#endif -#ifdef TARGET_ARCH_arm -# include "assembler_arm.inline.hpp" -#endif -#ifdef TARGET_ARCH_ppc -# include "assembler_ppc.inline.hpp" -#endif DEF_STUB_INTERFACE(ICStub); diff --git a/hotspot/src/share/vm/code/relocInfo.cpp b/hotspot/src/share/vm/code/relocInfo.cpp index fbe597ad5ce..679bc290ade 100644 --- a/hotspot/src/share/vm/code/relocInfo.cpp +++ b/hotspot/src/share/vm/code/relocInfo.cpp @@ -23,32 +23,13 @@ */ #include "precompiled.hpp" +#include "code/codeCache.hpp" #include "code/compiledIC.hpp" #include "code/nmethod.hpp" #include "code/relocInfo.hpp" #include "memory/resourceArea.hpp" #include "runtime/stubCodeGenerator.hpp" #include "utilities/copy.hpp" -#ifdef TARGET_ARCH_x86 -# include "assembler_x86.inline.hpp" -# include "nativeInst_x86.hpp" -#endif -#ifdef TARGET_ARCH_sparc -# include "assembler_sparc.inline.hpp" -# include "nativeInst_sparc.hpp" -#endif -#ifdef TARGET_ARCH_zero -# include "assembler_zero.inline.hpp" -# include "nativeInst_zero.hpp" -#endif -#ifdef TARGET_ARCH_arm -# include "assembler_arm.inline.hpp" -# include "nativeInst_arm.hpp" -#endif -#ifdef TARGET_ARCH_ppc -# include "assembler_ppc.inline.hpp" -# include "nativeInst_ppc.hpp" -#endif const RelocationHolder RelocationHolder::none; // its type is relocInfo::none diff --git a/hotspot/src/share/vm/code/vmreg.hpp b/hotspot/src/share/vm/code/vmreg.hpp index 23832a398c1..70b476de00e 100644 --- a/hotspot/src/share/vm/code/vmreg.hpp +++ b/hotspot/src/share/vm/code/vmreg.hpp @@ -27,21 +27,8 @@ #include "memory/allocation.hpp" #include "utilities/globalDefinitions.hpp" -#ifdef TARGET_ARCH_x86 -# include "register_x86.hpp" -#endif -#ifdef TARGET_ARCH_sparc -# include "register_sparc.hpp" -#endif -#ifdef TARGET_ARCH_zero -# include "register_zero.hpp" -#endif -#ifdef TARGET_ARCH_arm -# include "register_arm.hpp" -#endif -#ifdef TARGET_ARCH_ppc -# include "register_ppc.hpp" -#endif +#include "asm/register.hpp" + #ifdef COMPILER2 #include "opto/adlcVMDeps.hpp" #include "utilities/ostream.hpp" diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp index d3dc1eb7bb7..e03b2f41cfc 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp @@ -46,27 +46,11 @@ // Concurrent marking bit map wrapper -CMBitMapRO::CMBitMapRO(ReservedSpace rs, int shifter) : - _bm((uintptr_t*)NULL,0), +CMBitMapRO::CMBitMapRO(int shifter) : + _bm(), _shifter(shifter) { - _bmStartWord = (HeapWord*)(rs.base()); - _bmWordSize = rs.size()/HeapWordSize; // rs.size() is in bytes - ReservedSpace brs(ReservedSpace::allocation_align_size_up( - (_bmWordSize >> (_shifter + LogBitsPerByte)) + 1)); - - MemTracker::record_virtual_memory_type((address)brs.base(), mtGC); - - guarantee(brs.is_reserved(), "couldn't allocate concurrent marking bit map"); - // For now we'll just commit all of the bit map up fromt. - // Later on we'll try to be more parsimonious with swap. - guarantee(_virtual_space.initialize(brs, brs.size()), - "couldn't reseve backing store for concurrent marking bit map"); - assert(_virtual_space.committed_size() == brs.size(), - "didn't reserve backing store for all of concurrent marking bit map?"); - _bm.set_map((uintptr_t*)_virtual_space.low()); - assert(_virtual_space.committed_size() << (_shifter + LogBitsPerByte) >= - _bmWordSize, "inconsistency in bit map sizing"); - _bm.set_size(_bmWordSize >> _shifter); + _bmStartWord = 0; + _bmWordSize = 0; } HeapWord* CMBitMapRO::getNextMarkedWordAddress(HeapWord* addr, @@ -108,15 +92,40 @@ int CMBitMapRO::heapWordDiffToOffsetDiff(size_t diff) const { } #ifndef PRODUCT -bool CMBitMapRO::covers(ReservedSpace rs) const { +bool CMBitMapRO::covers(ReservedSpace heap_rs) const { // assert(_bm.map() == _virtual_space.low(), "map inconsistency"); assert(((size_t)_bm.size() * ((size_t)1 << _shifter)) == _bmWordSize, "size inconsistency"); - return _bmStartWord == (HeapWord*)(rs.base()) && - _bmWordSize == rs.size()>>LogHeapWordSize; + return _bmStartWord == (HeapWord*)(heap_rs.base()) && + _bmWordSize == heap_rs.size()>>LogHeapWordSize; } #endif +bool CMBitMap::allocate(ReservedSpace heap_rs) { + _bmStartWord = (HeapWord*)(heap_rs.base()); + _bmWordSize = heap_rs.size()/HeapWordSize; // heap_rs.size() is in bytes + ReservedSpace brs(ReservedSpace::allocation_align_size_up( + (_bmWordSize >> (_shifter + LogBitsPerByte)) + 1)); + if (!brs.is_reserved()) { + warning("ConcurrentMark marking bit map allocation failure"); + return false; + } + MemTracker::record_virtual_memory_type((address)brs.base(), mtGC); + // For now we'll just commit all of the bit map up front. + // Later on we'll try to be more parsimonious with swap. + if (!_virtual_space.initialize(brs, brs.size())) { + warning("ConcurrentMark marking bit map backing store failure"); + return false; + } + assert(_virtual_space.committed_size() == brs.size(), + "didn't reserve backing store for all of concurrent marking bit map?"); + _bm.set_map((uintptr_t*)_virtual_space.low()); + assert(_virtual_space.committed_size() << (_shifter + LogBitsPerByte) >= + _bmWordSize, "inconsistency in bit map sizing"); + _bm.set_size(_bmWordSize >> _shifter); + return true; +} + void CMBitMap::clearAll() { _bm.clear(); return; @@ -163,20 +172,79 @@ CMMarkStack::CMMarkStack(ConcurrentMark* cm) : #endif {} -void CMMarkStack::allocate(size_t size) { - _base = NEW_C_HEAP_ARRAY(oop, size, mtGC); - if (_base == NULL) { - vm_exit_during_initialization("Failed to allocate CM region mark stack"); +bool CMMarkStack::allocate(size_t capacity) { + // allocate a stack of the requisite depth + ReservedSpace rs(ReservedSpace::allocation_align_size_up(capacity * sizeof(oop))); + if (!rs.is_reserved()) { + warning("ConcurrentMark MarkStack allocation failure"); + return false; } - _index = 0; - _capacity = (jint) size; + MemTracker::record_virtual_memory_type((address)rs.base(), mtGC); + if (!_virtual_space.initialize(rs, rs.size())) { + warning("ConcurrentMark MarkStack backing store failure"); + // Release the virtual memory reserved for the marking stack + rs.release(); + return false; + } + assert(_virtual_space.committed_size() == rs.size(), + "Didn't reserve backing store for all of ConcurrentMark stack?"); + _base = (oop*) _virtual_space.low(); + setEmpty(); + _capacity = (jint) capacity; _saved_index = -1; NOT_PRODUCT(_max_depth = 0); + return true; +} + +void CMMarkStack::expand() { + // Called, during remark, if we've overflown the marking stack during marking. + assert(isEmpty(), "stack should been emptied while handling overflow"); + assert(_capacity <= (jint) MarkStackSizeMax, "stack bigger than permitted"); + // Clear expansion flag + _should_expand = false; + if (_capacity == (jint) MarkStackSizeMax) { + if (PrintGCDetails && Verbose) { + gclog_or_tty->print_cr(" (benign) Can't expand marking stack capacity, at max size limit"); + } + return; + } + // Double capacity if possible + jint new_capacity = MIN2(_capacity*2, (jint) MarkStackSizeMax); + // Do not give up existing stack until we have managed to + // get the double capacity that we desired. + ReservedSpace rs(ReservedSpace::allocation_align_size_up(new_capacity * + sizeof(oop))); + if (rs.is_reserved()) { + // Release the backing store associated with old stack + _virtual_space.release(); + // Reinitialize virtual space for new stack + if (!_virtual_space.initialize(rs, rs.size())) { + fatal("Not enough swap for expanded marking stack capacity"); + } + _base = (oop*)(_virtual_space.low()); + _index = 0; + _capacity = new_capacity; + } else { + if (PrintGCDetails && Verbose) { + // Failed to double capacity, continue; + gclog_or_tty->print(" (benign) Failed to expand marking stack capacity from " + SIZE_FORMAT"K to " SIZE_FORMAT"K", + _capacity / K, new_capacity / K); + } + } +} + +void CMMarkStack::set_should_expand() { + // If we're resetting the marking state because of an + // marking stack overflow, record that we should, if + // possible, expand the stack. + _should_expand = _cm->has_overflown(); } CMMarkStack::~CMMarkStack() { if (_base != NULL) { - FREE_C_HEAP_ARRAY(oop, _base, mtGC); + _base = NULL; + _virtual_space.release(); } } @@ -217,7 +285,7 @@ void CMMarkStack::par_adjoin_arr(oop* ptr_arr, int n) { jint res = Atomic::cmpxchg(next_index, &_index, index); if (res == index) { for (int i = 0; i < n; i++) { - int ind = index + i; + int ind = index + i; assert(ind < _capacity, "By overflow test above."); _base[ind] = ptr_arr[i]; } @@ -228,7 +296,6 @@ void CMMarkStack::par_adjoin_arr(oop* ptr_arr, int n) { } } - void CMMarkStack::par_push_arr(oop* ptr_arr, int n) { MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag); jint start = _index; @@ -244,9 +311,9 @@ void CMMarkStack::par_push_arr(oop* ptr_arr, int n) { assert(ind < _capacity, "By overflow test above."); _base[ind] = ptr_arr[i]; } + NOT_PRODUCT(_max_depth = MAX2(_max_depth, next_index)); } - bool CMMarkStack::par_pop_arr(oop* ptr_arr, int max, int* n) { MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag); jint index = _index; @@ -255,7 +322,7 @@ bool CMMarkStack::par_pop_arr(oop* ptr_arr, int max, int* n) { return false; } else { int k = MIN2(max, index); - jint new_ind = index - k; + jint new_ind = index - k; for (int j = 0; j < k; j++) { ptr_arr[j] = _base[new_ind + j]; } @@ -404,9 +471,10 @@ uint ConcurrentMark::scale_parallel_threads(uint n_par_threads) { return MAX2((n_par_threads + 2) / 4, 1U); } -ConcurrentMark::ConcurrentMark(ReservedSpace rs, uint max_regions) : - _markBitMap1(rs, MinObjAlignment - 1), - _markBitMap2(rs, MinObjAlignment - 1), +ConcurrentMark::ConcurrentMark(G1CollectedHeap* g1h, ReservedSpace heap_rs) : + _g1h(g1h), + _markBitMap1(MinObjAlignment - 1), + _markBitMap2(MinObjAlignment - 1), _parallel_marking_threads(0), _max_parallel_marking_threads(0), @@ -415,10 +483,10 @@ ConcurrentMark::ConcurrentMark(ReservedSpace rs, uint max_regions) : _cleanup_sleep_factor(0.0), _cleanup_task_overhead(1.0), _cleanup_list("Cleanup List"), - _region_bm((BitMap::idx_t) max_regions, false /* in_resource_area*/), - _card_bm((rs.size() + CardTableModRefBS::card_size - 1) >> - CardTableModRefBS::card_shift, - false /* in_resource_area*/), + _region_bm((BitMap::idx_t)(g1h->max_regions()), false /* in_resource_area*/), + _card_bm((heap_rs.size() + CardTableModRefBS::card_size - 1) >> + CardTableModRefBS::card_shift, + false /* in_resource_area*/), _prevMarkBitMap(&_markBitMap1), _nextMarkBitMap(&_markBitMap2), @@ -449,7 +517,8 @@ ConcurrentMark::ConcurrentMark(ReservedSpace rs, uint max_regions) : _parallel_workers(NULL), _count_card_bitmaps(NULL), - _count_marked_bytes(NULL) { + _count_marked_bytes(NULL), + _completed_initialization(false) { CMVerboseLevel verbose_level = (CMVerboseLevel) G1MarkingVerboseLevel; if (verbose_level < no_verbose) { verbose_level = no_verbose; @@ -464,61 +533,34 @@ ConcurrentMark::ConcurrentMark(ReservedSpace rs, uint max_regions) : "heap end = "PTR_FORMAT, _heap_start, _heap_end); } - _markStack.allocate(MarkStackSize); + if (!_markBitMap1.allocate(heap_rs)) { + warning("Failed to allocate first CM bit map"); + return; + } + if (!_markBitMap2.allocate(heap_rs)) { + warning("Failed to allocate second CM bit map"); + return; + } // Create & start a ConcurrentMark thread. _cmThread = new ConcurrentMarkThread(this); assert(cmThread() != NULL, "CM Thread should have been created"); assert(cmThread()->cm() != NULL, "CM Thread should refer to this cm"); - _g1h = G1CollectedHeap::heap(); assert(CGC_lock != NULL, "Where's the CGC_lock?"); - assert(_markBitMap1.covers(rs), "_markBitMap1 inconsistency"); - assert(_markBitMap2.covers(rs), "_markBitMap2 inconsistency"); + assert(_markBitMap1.covers(heap_rs), "_markBitMap1 inconsistency"); + assert(_markBitMap2.covers(heap_rs), "_markBitMap2 inconsistency"); SATBMarkQueueSet& satb_qs = JavaThread::satb_mark_queue_set(); satb_qs.set_buffer_size(G1SATBBufferSize); _root_regions.init(_g1h, this); - _tasks = NEW_C_HEAP_ARRAY(CMTask*, _max_worker_id, mtGC); - _accum_task_vtime = NEW_C_HEAP_ARRAY(double, _max_worker_id, mtGC); - - _count_card_bitmaps = NEW_C_HEAP_ARRAY(BitMap, _max_worker_id, mtGC); - _count_marked_bytes = NEW_C_HEAP_ARRAY(size_t*, _max_worker_id, mtGC); - - BitMap::idx_t card_bm_size = _card_bm.size(); - - // so that the assertion in MarkingTaskQueue::task_queue doesn't fail - _active_tasks = _max_worker_id; - for (uint i = 0; i < _max_worker_id; ++i) { - CMTaskQueue* task_queue = new CMTaskQueue(); - task_queue->initialize(); - _task_queues->register_queue(i, task_queue); - - _count_card_bitmaps[i] = BitMap(card_bm_size, false); - _count_marked_bytes[i] = NEW_C_HEAP_ARRAY(size_t, (size_t) max_regions, mtGC); - - _tasks[i] = new CMTask(i, this, - _count_marked_bytes[i], - &_count_card_bitmaps[i], - task_queue, _task_queues); - - _accum_task_vtime[i] = 0.0; - } - - // Calculate the card number for the bottom of the heap. Used - // in biasing indexes into the accounting card bitmaps. - _heap_bottom_card_num = - intptr_t(uintptr_t(_g1h->reserved_region().start()) >> - CardTableModRefBS::card_shift); - - // Clear all the liveness counting data - clear_all_count_data(); - if (ConcGCThreads > ParallelGCThreads) { - vm_exit_during_initialization("Can't have more ConcGCThreads " - "than ParallelGCThreads."); + warning("Can't have more ConcGCThreads (" UINT32_FORMAT ") " + "than ParallelGCThreads (" UINT32_FORMAT ").", + ConcGCThreads, ParallelGCThreads); + return; } if (ParallelGCThreads == 0) { // if we are not running with any parallel GC threads we will not @@ -590,9 +632,86 @@ ConcurrentMark::ConcurrentMark(ReservedSpace rs, uint max_regions) : } } + if (FLAG_IS_DEFAULT(MarkStackSize)) { + uintx mark_stack_size = + MIN2(MarkStackSizeMax, + MAX2(MarkStackSize, (uintx) (parallel_marking_threads() * TASKQUEUE_SIZE))); + // Verify that the calculated value for MarkStackSize is in range. + // It would be nice to use the private utility routine from Arguments. + if (!(mark_stack_size >= 1 && mark_stack_size <= MarkStackSizeMax)) { + warning("Invalid value calculated for MarkStackSize (" UINTX_FORMAT "): " + "must be between " UINTX_FORMAT " and " UINTX_FORMAT, + mark_stack_size, 1, MarkStackSizeMax); + return; + } + FLAG_SET_ERGO(uintx, MarkStackSize, mark_stack_size); + } else { + // Verify MarkStackSize is in range. + if (FLAG_IS_CMDLINE(MarkStackSize)) { + if (FLAG_IS_DEFAULT(MarkStackSizeMax)) { + if (!(MarkStackSize >= 1 && MarkStackSize <= MarkStackSizeMax)) { + warning("Invalid value specified for MarkStackSize (" UINTX_FORMAT "): " + "must be between " UINTX_FORMAT " and " UINTX_FORMAT, + MarkStackSize, 1, MarkStackSizeMax); + return; + } + } else if (FLAG_IS_CMDLINE(MarkStackSizeMax)) { + if (!(MarkStackSize >= 1 && MarkStackSize <= MarkStackSizeMax)) { + warning("Invalid value specified for MarkStackSize (" UINTX_FORMAT ")" + " or for MarkStackSizeMax (" UINTX_FORMAT ")", + MarkStackSize, MarkStackSizeMax); + return; + } + } + } + } + + if (!_markStack.allocate(MarkStackSize)) { + warning("Failed to allocate CM marking stack"); + return; + } + + _tasks = NEW_C_HEAP_ARRAY(CMTask*, _max_worker_id, mtGC); + _accum_task_vtime = NEW_C_HEAP_ARRAY(double, _max_worker_id, mtGC); + + _count_card_bitmaps = NEW_C_HEAP_ARRAY(BitMap, _max_worker_id, mtGC); + _count_marked_bytes = NEW_C_HEAP_ARRAY(size_t*, _max_worker_id, mtGC); + + BitMap::idx_t card_bm_size = _card_bm.size(); + + // so that the assertion in MarkingTaskQueue::task_queue doesn't fail + _active_tasks = _max_worker_id; + + size_t max_regions = (size_t) _g1h->max_regions(); + for (uint i = 0; i < _max_worker_id; ++i) { + CMTaskQueue* task_queue = new CMTaskQueue(); + task_queue->initialize(); + _task_queues->register_queue(i, task_queue); + + _count_card_bitmaps[i] = BitMap(card_bm_size, false); + _count_marked_bytes[i] = NEW_C_HEAP_ARRAY(size_t, max_regions, mtGC); + + _tasks[i] = new CMTask(i, this, + _count_marked_bytes[i], + &_count_card_bitmaps[i], + task_queue, _task_queues); + + _accum_task_vtime[i] = 0.0; + } + + // Calculate the card number for the bottom of the heap. Used + // in biasing indexes into the accounting card bitmaps. + _heap_bottom_card_num = + intptr_t(uintptr_t(_g1h->reserved_region().start()) >> + CardTableModRefBS::card_shift); + + // Clear all the liveness counting data + clear_all_count_data(); + // so that the call below can read a sensible value - _heap_start = (HeapWord*) rs.base(); + _heap_start = (HeapWord*) heap_rs.base(); set_non_marking_state(); + _completed_initialization = true; } void ConcurrentMark::update_g1_committed(bool force) { @@ -1165,6 +1284,11 @@ void ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) { assert(!restart_for_overflow(), "sanity"); } + // Expand the marking stack, if we have to and if we can. + if (_markStack.should_expand()) { + _markStack.expand(); + } + // Reset the marking state if marking completed if (!restart_for_overflow()) { set_non_marking_state(); @@ -2785,7 +2909,7 @@ void ConcurrentMark::verify_no_cset_oops(bool verify_stacks, // Verify entries on the task queues for (uint i = 0; i < _max_worker_id; i += 1) { cl.set_phase(VerifyNoCSetOopsQueues, i); - OopTaskQueue* queue = _task_queues->queue(i); + CMTaskQueue* queue = _task_queues->queue(i); queue->oops_do(&cl); } } @@ -2840,8 +2964,8 @@ void ConcurrentMark::verify_no_cset_oops(bool verify_stacks, #endif // PRODUCT void ConcurrentMark::clear_marking_state(bool clear_overflow) { - _markStack.setEmpty(); - _markStack.clear_overflow(); + _markStack.set_should_expand(); + _markStack.setEmpty(); // Also clears the _markStack overflow flag if (clear_overflow) { clear_has_overflown(); } else { @@ -2850,7 +2974,7 @@ void ConcurrentMark::clear_marking_state(bool clear_overflow) { _finger = _heap_start; for (uint i = 0; i < _max_worker_id; ++i) { - OopTaskQueue* queue = _task_queues->queue(i); + CMTaskQueue* queue = _task_queues->queue(i); queue->set_empty(); } } diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp index 5bac7a6b34d..8089c98294a 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp @@ -63,7 +63,7 @@ class CMBitMapRO VALUE_OBJ_CLASS_SPEC { public: // constructor - CMBitMapRO(ReservedSpace rs, int shifter); + CMBitMapRO(int shifter); enum { do_yield = true }; @@ -117,8 +117,11 @@ class CMBitMap : public CMBitMapRO { public: // constructor - CMBitMap(ReservedSpace rs, int shifter) : - CMBitMapRO(rs, shifter) {} + CMBitMap(int shifter) : + CMBitMapRO(shifter) {} + + // Allocates the back store for the marking bitmap + bool allocate(ReservedSpace heap_rs); // write marks void mark(HeapWord* addr) { @@ -155,17 +158,18 @@ class CMBitMap : public CMBitMapRO { MemRegion getAndClearMarkedRegion(HeapWord* addr, HeapWord* end_addr); }; -// Represents a marking stack used by the CM collector. -// Ideally this should be GrowableArray<> just like MSC's marking stack(s). +// Represents a marking stack used by ConcurrentMarking in the G1 collector. class CMMarkStack VALUE_OBJ_CLASS_SPEC { + VirtualSpace _virtual_space; // Underlying backing store for actual stack ConcurrentMark* _cm; oop* _base; // bottom of stack - jint _index; // one more than last occupied index - jint _capacity; // max #elements - jint _saved_index; // value of _index saved at start of GC - NOT_PRODUCT(jint _max_depth;) // max depth plumbed during run + jint _index; // one more than last occupied index + jint _capacity; // max #elements + jint _saved_index; // value of _index saved at start of GC + NOT_PRODUCT(jint _max_depth;) // max depth plumbed during run - bool _overflow; + bool _overflow; + bool _should_expand; DEBUG_ONLY(bool _drain_in_progress;) DEBUG_ONLY(bool _drain_in_progress_yields;) @@ -173,7 +177,13 @@ class CMMarkStack VALUE_OBJ_CLASS_SPEC { CMMarkStack(ConcurrentMark* cm); ~CMMarkStack(); - void allocate(size_t size); +#ifndef PRODUCT + jint max_depth() const { + return _max_depth; + } +#endif + + bool allocate(size_t capacity); oop pop() { if (!isEmpty()) { @@ -231,11 +241,17 @@ class CMMarkStack VALUE_OBJ_CLASS_SPEC { bool isEmpty() { return _index == 0; } bool isFull() { return _index == _capacity; } - int maxElems() { return _capacity; } + int maxElems() { return _capacity; } bool overflow() { return _overflow; } void clear_overflow() { _overflow = false; } + bool should_expand() const { return _should_expand; } + void set_should_expand(); + + // Expand the stack, typically in response to an overflow condition + void expand(); + int size() { return _index; } void setEmpty() { _index = 0; clear_overflow(); } @@ -344,6 +360,7 @@ public: class ConcurrentMarkThread; class ConcurrentMark: public CHeapObj { + friend class CMMarkStack; friend class ConcurrentMarkThread; friend class CMTask; friend class CMBitMapClosure; @@ -577,6 +594,9 @@ protected: // the card bitmaps. intptr_t _heap_bottom_card_num; + // Set to true when initialization is complete + bool _completed_initialization; + public: // Manipulation of the global mark stack. // Notice that the first mark_stack_push is CAS-based, whereas the @@ -636,7 +656,7 @@ public: return _task_queues->steal(worker_id, hash_seed, obj); } - ConcurrentMark(ReservedSpace rs, uint max_regions); + ConcurrentMark(G1CollectedHeap* g1h, ReservedSpace heap_rs); ~ConcurrentMark(); ConcurrentMarkThread* cmThread() { return _cmThread; } @@ -907,6 +927,11 @@ public: // Should *not* be called from parallel code. inline bool mark_and_count(oop obj); + // Returns true if initialization was successfully completed. + bool completed_initialization() const { + return _completed_initialization; + } + protected: // Clear all the per-task bitmaps and arrays used to store the // counting data. diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 471e638de19..448c5707787 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -2079,7 +2079,11 @@ jint G1CollectedHeap::initialize() { // Create the ConcurrentMark data structure and thread. // (Must do this late, so that "max_regions" is defined.) - _cm = new ConcurrentMark(heap_rs, max_regions()); + _cm = new ConcurrentMark(this, heap_rs); + if (_cm == NULL || !_cm->completed_initialization()) { + vm_shutdown_during_initialization("Could not create/initialize ConcurrentMark"); + return JNI_ENOMEM; + } _cmThread = _cm->cmThread(); // Initialize the from_card cache structure of HeapRegionRemSet. @@ -2087,7 +2091,7 @@ jint G1CollectedHeap::initialize() { // Now expand into the initial heap size. if (!expand(init_byte_size)) { - vm_exit_during_initialization("Failed to allocate initial heap."); + vm_shutdown_during_initialization("Failed to allocate initial heap."); return JNI_ENOMEM; } @@ -3690,6 +3694,7 @@ void G1CollectedHeap::log_gc_footer(double pause_time_sec) { g1_policy()->print_heap_transition(); gclog_or_tty->print_cr(", %3.7f secs]", pause_time_sec); } + gclog_or_tty->flush(); } bool @@ -4036,10 +4041,11 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { #endif gc_epilogue(false); - - log_gc_footer(os::elapsedTime() - pause_start_sec); } + // Print the remainder of the GC log output. + log_gc_footer(os::elapsedTime() - pause_start_sec); + // It is not yet to safe to tell the concurrent mark to // start as we have some optional output below. We don't want the // output from the concurrent mark thread interfering with this diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/adjoiningVirtualSpaces.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/adjoiningVirtualSpaces.cpp index e21f7a7a6e4..e5ca1f5c097 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/adjoiningVirtualSpaces.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/adjoiningVirtualSpaces.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "gc_implementation/parallelScavenge/adjoiningVirtualSpaces.hpp" +#include "memory/allocation.inline.hpp" #include "runtime/java.hpp" AdjoiningVirtualSpaces::AdjoiningVirtualSpaces(ReservedSpace rs, diff --git a/hotspot/src/share/vm/gc_implementation/shared/gcStats.cpp b/hotspot/src/share/vm/gc_implementation/shared/gcStats.cpp index faef280f632..745f8f3ab65 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/gcStats.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/gcStats.cpp @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "gc_implementation/shared/gcStats.hpp" #include "gc_implementation/shared/gcUtil.hpp" +#include "memory/allocation.inline.hpp" GCStats::GCStats() { _avg_promoted = new AdaptivePaddedNoZeroDevAverage( diff --git a/hotspot/src/share/vm/interpreter/bytecodes.hpp b/hotspot/src/share/vm/interpreter/bytecodes.hpp index b33df83d74a..707f210e8e0 100644 --- a/hotspot/src/share/vm/interpreter/bytecodes.hpp +++ b/hotspot/src/share/vm/interpreter/bytecodes.hpp @@ -423,7 +423,9 @@ class Bytecodes: AllStatic { static bool is_zero_const (Code code) { return (code == _aconst_null || code == _iconst_0 || code == _fconst_0 || code == _dconst_0); } static bool is_invoke (Code code) { return (_invokevirtual <= code && code <= _invokedynamic); } - + static bool has_receiver (Code code) { assert(is_invoke(code), ""); return code == _invokevirtual || + code == _invokespecial || + code == _invokeinterface; } static bool has_optional_appendix(Code code) { return code == _invokedynamic || code == _invokehandle; } static int compute_flags (const char* format, int more_flags = 0); // compute the flags diff --git a/hotspot/src/share/vm/interpreter/interpreter.cpp b/hotspot/src/share/vm/interpreter/interpreter.cpp index 4513eebb79c..24de109f39c 100644 --- a/hotspot/src/share/vm/interpreter/interpreter.cpp +++ b/hotspot/src/share/vm/interpreter/interpreter.cpp @@ -23,7 +23,9 @@ */ #include "precompiled.hpp" -#include "asm/assembler.hpp" +#include "asm/macroAssembler.hpp" +#include "asm/macroAssembler.inline.hpp" +#include "compiler/disassembler.hpp" #include "interpreter/bytecodeHistogram.hpp" #include "interpreter/bytecodeInterpreter.hpp" #include "interpreter/interpreter.hpp" diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp index 0b83ad21eab..682f70032e5 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp @@ -26,6 +26,7 @@ #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" #include "compiler/compileBroker.hpp" +#include "compiler/disassembler.hpp" #include "gc_interface/collectedHeap.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/interpreterRuntime.hpp" diff --git a/hotspot/src/share/vm/memory/metablock.cpp b/hotspot/src/share/vm/memory/metablock.cpp new file mode 100644 index 00000000000..8aa6a9f8372 --- /dev/null +++ b/hotspot/src/share/vm/memory/metablock.cpp @@ -0,0 +1,75 @@ +/* + * 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. + * + */ + +#include "precompiled.hpp" +#include "memory/allocation.hpp" +#include "memory/metablock.hpp" +#include "utilities/copy.hpp" +#include "utilities/debug.hpp" + +// Blocks of space for metadata are allocated out of Metachunks. +// +// Metachunk are allocated out of MetadataVirtualspaces and once +// allocated there is no explicit link between a Metachunk and +// the MetadataVirtualspaces from which it was allocated. +// +// Each SpaceManager maintains a +// list of the chunks it is using and the current chunk. The current +// chunk is the chunk from which allocations are done. Space freed in +// a chunk is placed on the free list of blocks (BlockFreelist) and +// reused from there. +// +// Future modification +// +// The Metachunk can conceivable be replaced by the Chunk in +// allocation.hpp. Note that the latter Chunk is the space for +// allocation (allocations from the chunk are out of the space in +// the Chunk after the header for the Chunk) where as Metachunks +// point to space in a VirtualSpace. To replace Metachunks with +// Chunks, change Chunks so that they can be allocated out of a VirtualSpace. +size_t Metablock::_min_block_byte_size = sizeof(Metablock); + +#ifdef ASSERT +size_t Metablock::_overhead = + Chunk::aligned_overhead_size(sizeof(Metablock)) / BytesPerWord; +#else +size_t Metablock::_overhead = 0; +#endif + +// New blocks returned by the Metaspace are zero initialized. +// We should fix the constructors to not assume this instead. +Metablock* Metablock::initialize(MetaWord* p, size_t word_size) { + if (p == NULL) { + return NULL; + } + + Metablock* result = (Metablock*) p; + + // Clear the memory + Copy::fill_to_aligned_words((HeapWord*)result, word_size); +#ifdef ASSERT + result->set_word_size(word_size); +#endif + return result; +} diff --git a/hotspot/src/share/vm/memory/metachunk.cpp b/hotspot/src/share/vm/memory/metachunk.cpp new file mode 100644 index 00000000000..3b71a1165ef --- /dev/null +++ b/hotspot/src/share/vm/memory/metachunk.cpp @@ -0,0 +1,117 @@ +/* + * 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. + * + */ + +#include "precompiled.hpp" +#include "memory/allocation.hpp" +#include "memory/metachunk.hpp" +#include "utilities/copy.hpp" +#include "utilities/debug.hpp" + +// +// Future modification +// +// The Metachunk can conceivable be replaced by the Chunk in +// allocation.hpp. Note that the latter Chunk is the space for +// allocation (allocations from the chunk are out of the space in +// the Chunk after the header for the Chunk) where as Metachunks +// point to space in a VirtualSpace. To replace Metachunks with +// Chunks, change Chunks so that they can be allocated out of a VirtualSpace. + +const size_t metadata_chunk_initialize = 0xf7f7f7f7; + +size_t Metachunk::_overhead = + Chunk::aligned_overhead_size(sizeof(Metachunk)) / BytesPerWord; + +// Metachunk methods + +Metachunk* Metachunk::initialize(MetaWord* ptr, size_t word_size) { + // Set bottom, top, and end. Allow space for the Metachunk itself + Metachunk* chunk = (Metachunk*) ptr; + + MetaWord* chunk_bottom = ptr + _overhead; + chunk->set_bottom(ptr); + chunk->set_top(chunk_bottom); + MetaWord* chunk_end = ptr + word_size; + assert(chunk_end > chunk_bottom, "Chunk must be too small"); + chunk->set_end(chunk_end); + chunk->set_next(NULL); + chunk->set_word_size(word_size); +#ifdef ASSERT + size_t data_word_size = pointer_delta(chunk_end, chunk_bottom, sizeof(MetaWord)); + Copy::fill_to_words((HeapWord*) chunk_bottom, data_word_size, metadata_chunk_initialize); +#endif + return chunk; +} + + +MetaWord* Metachunk::allocate(size_t word_size) { + MetaWord* result = NULL; + // If available, bump the pointer to allocate. + if (free_word_size() >= word_size) { + result = _top; + _top = _top + word_size; + } + return result; +} + +// _bottom points to the start of the chunk including the overhead. +size_t Metachunk::used_word_size() { + return pointer_delta(_top, _bottom, sizeof(MetaWord)); +} + +size_t Metachunk::free_word_size() { + return pointer_delta(_end, _top, sizeof(MetaWord)); +} + +size_t Metachunk::capacity_word_size() { + return pointer_delta(_end, _bottom, sizeof(MetaWord)); +} + +void Metachunk::print_on(outputStream* st) const { + st->print_cr("Metachunk:" + " bottom " PTR_FORMAT " top " PTR_FORMAT + " end " PTR_FORMAT " size " SIZE_FORMAT, + bottom(), top(), end(), word_size()); +} + +#ifndef PRODUCT +void Metachunk::mangle() { + // Mangle the payload of the chunk and not the links that + // maintain list of chunks. + HeapWord* start = (HeapWord*)(bottom() + overhead()); + size_t word_size = capacity_word_size() - overhead(); + Copy::fill_to_words(start, word_size, metadata_chunk_initialize); +} +#endif // PRODUCT + +void Metachunk::verify() { +#ifdef ASSERT + // Cannot walk through the blocks unless the blocks have + // headers with sizes. + assert(_bottom <= _top && + _top <= _end, + "Chunk has been smashed"); +#endif + return; +} diff --git a/hotspot/src/share/vm/memory/metaspace.cpp b/hotspot/src/share/vm/memory/metaspace.cpp index 1e83247adc1..42870cd0fda 100644 --- a/hotspot/src/share/vm/memory/metaspace.cpp +++ b/hotspot/src/share/vm/memory/metaspace.cpp @@ -52,7 +52,6 @@ const bool metaspace_slow_verify = false; const uint metadata_deallocate_a_lot_block = 10; const uint metadata_deallocate_a_lock_chunk = 3; size_t const allocation_from_dictionary_limit = 64 * K; -const size_t metadata_chunk_initialize = 0xf7f7f7f7; const size_t metadata_deallocate = 0xf5f5f5f5; MetaWord* last_allocated = 0; @@ -92,22 +91,6 @@ bool MetaspaceGC::_should_concurrent_collect = false; // chunk is the chunk from which allocations are done. Space freed in // a chunk is placed on the free list of blocks (BlockFreelist) and // reused from there. -// -// Future modification -// -// The Metachunk can conceivable be replaced by the Chunk in -// allocation.hpp. Note that the latter Chunk is the space for -// allocation (allocations from the chunk are out of the space in -// the Chunk after the header for the Chunk) where as Metachunks -// point to space in a VirtualSpace. To replace Metachunks with -// Chunks, change Chunks so that they can be allocated out of a VirtualSpace. -size_t Metablock::_min_block_byte_size = sizeof(Metablock); -#ifdef ASSERT - size_t Metablock::_overhead = - Chunk::aligned_overhead_size(sizeof(Metablock)) / BytesPerWord; -#else - size_t Metablock::_overhead = 0; -#endif // Pointer to list of Metachunks. class ChunkList VALUE_OBJ_CLASS_SPEC { @@ -623,6 +606,7 @@ class SpaceManager : public CHeapObj { void locked_print_chunks_in_use_on(outputStream* st) const; void verify(); + void verify_chunk_size(Metachunk* chunk); NOT_PRODUCT(void mangle_freed_chunks();) #ifdef ASSERT void verify_allocation_total(); @@ -631,8 +615,6 @@ class SpaceManager : public CHeapObj { uint const SpaceManager::_small_chunk_limit = 4; - - const char* SpaceManager::_expand_lock_name = "SpaceManager chunk allocation lock"; const int SpaceManager::_expand_lock_rank = Monitor::leaf - 1; @@ -641,103 +623,6 @@ Mutex* const SpaceManager::_expand_lock = SpaceManager::_expand_lock_name, Mutex::_allow_vm_block_flag); -size_t Metachunk::_overhead = - Chunk::aligned_overhead_size(sizeof(Metachunk)) / BytesPerWord; - -// New blocks returned by the Metaspace are zero initialized. -// We should fix the constructors to not assume this instead. -Metablock* Metablock::initialize(MetaWord* p, size_t word_size) { - if (p == NULL) { - return NULL; - } - - Metablock* result = (Metablock*) p; - - // Clear the memory - Copy::fill_to_aligned_words((HeapWord*)result, word_size); -#ifdef ASSERT - result->set_word_size(word_size); -#endif - return result; -} - -// Metachunk methods - -Metachunk* Metachunk::initialize(MetaWord* ptr, size_t word_size) { - // Set bottom, top, and end. Allow space for the Metachunk itself - Metachunk* chunk = (Metachunk*) ptr; - - MetaWord* chunk_bottom = ptr + _overhead; - chunk->set_bottom(ptr); - chunk->set_top(chunk_bottom); - MetaWord* chunk_end = ptr + word_size; - assert(chunk_end > chunk_bottom, "Chunk must be too small"); - chunk->set_end(chunk_end); - chunk->set_next(NULL); - chunk->set_word_size(word_size); -#ifdef ASSERT - size_t data_word_size = pointer_delta(chunk_end, chunk_bottom, sizeof(MetaWord)); - Copy::fill_to_words((HeapWord*) chunk_bottom, data_word_size, metadata_chunk_initialize); -#endif - return chunk; -} - - -MetaWord* Metachunk::allocate(size_t word_size) { - MetaWord* result = NULL; - // If available, bump the pointer to allocate. - if (free_word_size() >= word_size) { - result = _top; - _top = _top + word_size; - } - return result; -} - -// _bottom points to the start of the chunk including the overhead. -size_t Metachunk::used_word_size() { - return pointer_delta(_top, _bottom, sizeof(MetaWord)); -} - -size_t Metachunk::free_word_size() { - return pointer_delta(_end, _top, sizeof(MetaWord)); -} - -size_t Metachunk::capacity_word_size() { - return pointer_delta(_end, _bottom, sizeof(MetaWord)); -} - -void Metachunk::print_on(outputStream* st) const { - st->print_cr("Metachunk:" - " bottom " PTR_FORMAT " top " PTR_FORMAT - " end " PTR_FORMAT " size " SIZE_FORMAT, - bottom(), top(), end(), word_size()); -} - -#ifndef PRODUCT -void Metachunk::mangle() { - // Mangle the payload of the chunk and not the links that - // maintain list of chunks. - HeapWord* start = (HeapWord*)(bottom() + overhead()); - size_t word_size = capacity_word_size() - overhead(); - Copy::fill_to_words(start, word_size, metadata_chunk_initialize); -} -#endif // PRODUCT - -void Metachunk::verify() { -#ifdef ASSERT - // Cannot walk through the blocks unless the blocks have - // headers with sizes. - assert(_bottom <= _top && - _top <= _end, - "Chunk has been smashed"); - assert(SpaceManager::is_humongous(_word_size) || - _word_size == SpaceManager::MediumChunk || - _word_size == SpaceManager::SmallChunk, - "Chunk size is wrong"); -#endif - return; -} - // BlockFreelist methods BlockFreelist::BlockFreelist() : _dictionary(NULL) {} @@ -2214,12 +2099,21 @@ void SpaceManager::verify() { Metachunk* curr = chunks_in_use(i); while (curr != NULL) { curr->verify(); + verify_chunk_size(curr); curr = curr->next(); } } } } +void SpaceManager::verify_chunk_size(Metachunk* chunk) { + assert(is_humongous(chunk->word_size()) || + chunk->word_size() == MediumChunk || + chunk->word_size() == SmallChunk, + "Chunk size is wrong"); + return; +} + #ifdef ASSERT void SpaceManager::verify_allocation_total() { #if 0 diff --git a/hotspot/src/share/vm/oops/constMethod.hpp b/hotspot/src/share/vm/oops/constMethod.hpp index 771bf7b169c..2819b3e7756 100644 --- a/hotspot/src/share/vm/oops/constMethod.hpp +++ b/hotspot/src/share/vm/oops/constMethod.hpp @@ -46,6 +46,7 @@ // | interp_kind | flags | code_size | // | name index | signature index | // | method_idnum | max_stack | +// | max_locals | size_of_parameters | // |------------------------------------------------------| // | | // | byte codes | @@ -150,7 +151,8 @@ private: // initially corresponds to the index into the methods array. // but this may change with redefinition u2 _max_stack; // Maximum number of entries on the expression stack - + u2 _max_locals; // Number of local variables used by this method + u2 _size_of_parameters; // size of the parameter block (receiver + arguments) in words // Constructor ConstMethod(int byte_code_size, @@ -338,6 +340,11 @@ public: static ByteSize max_stack_offset() { return byte_offset_of(ConstMethod, _max_stack); } + static ByteSize size_of_locals_offset() + { return byte_offset_of(ConstMethod, _max_locals); } + static ByteSize size_of_parameters_offset() + { return byte_offset_of(ConstMethod, _size_of_parameters); } + // Unique id for the method static const u2 MAX_IDNUM; @@ -349,6 +356,14 @@ public: int max_stack() const { return _max_stack; } void set_max_stack(int size) { _max_stack = size; } + // max locals + int max_locals() const { return _max_locals; } + void set_max_locals(int size) { _max_locals = size; } + + // size of parameters + int size_of_parameters() const { return _size_of_parameters; } + void set_size_of_parameters(int size) { _size_of_parameters = size; } + // Deallocation for RedefineClasses void deallocate_contents(ClassLoaderData* loader_data); bool is_klass() const { return false; } diff --git a/hotspot/src/share/vm/oops/method.hpp b/hotspot/src/share/vm/oops/method.hpp index ff7bc0ee53d..9e5e3b9da6a 100644 --- a/hotspot/src/share/vm/oops/method.hpp +++ b/hotspot/src/share/vm/oops/method.hpp @@ -73,8 +73,7 @@ // |------------------------------------------------------| // | result_index (C++ interpreter only) | // |------------------------------------------------------| -// | method_size | max_locals | -// | size_of_parameters | intrinsic_id| flags | +// | method_size | intrinsic_id| flags | // |------------------------------------------------------| // | throwout_count | num_breakpoints | // |------------------------------------------------------| @@ -116,8 +115,6 @@ class Method : public Metadata { int _result_index; // C++ interpreter needs for converting results to/from stack #endif u2 _method_size; // size of this object - u2 _max_locals; // Number of local variables used by this method - u2 _size_of_parameters; // size of the parameter block (receiver + arguments) in words u1 _intrinsic_id; // vmSymbols::intrinsic_id (0 == _none) u1 _jfr_towrite : 1, // Flags _force_inline : 1, @@ -292,8 +289,8 @@ class Method : public Metadata { void set_max_stack(int size) { constMethod()->set_max_stack(size); } // max locals - int max_locals() const { return _max_locals; } - void set_max_locals(int size) { _max_locals = size; } + int max_locals() const { return constMethod()->max_locals(); } + void set_max_locals(int size) { constMethod()->set_max_locals(size); } int highest_comp_level() const; void set_highest_comp_level(int level); @@ -311,7 +308,8 @@ class Method : public Metadata { void set_interpreter_throwout_count(int count) { _interpreter_throwout_count = count; } // size of parameters - int size_of_parameters() const { return _size_of_parameters; } + int size_of_parameters() const { return constMethod()->size_of_parameters(); } + void set_size_of_parameters(int size) { constMethod()->set_size_of_parameters(size); } bool has_stackmap_table() const { return constMethod()->has_stackmap_table(); @@ -588,8 +586,6 @@ class Method : public Metadata { #ifdef CC_INTERP static ByteSize result_index_offset() { return byte_offset_of(Method, _result_index ); } #endif /* CC_INTERP */ - static ByteSize size_of_locals_offset() { return byte_offset_of(Method, _max_locals ); } - static ByteSize size_of_parameters_offset() { return byte_offset_of(Method, _size_of_parameters); } static ByteSize from_compiled_offset() { return byte_offset_of(Method, _from_compiled_entry); } static ByteSize code_offset() { return byte_offset_of(Method, _code); } static ByteSize invocation_counter_offset() { return byte_offset_of(Method, _invocation_counter); } @@ -796,9 +792,6 @@ class Method : public Metadata { Array* methods_default_annotations, bool idempotent = false); - // size of parameters - void set_size_of_parameters(int size) { _size_of_parameters = size; } - // Deallocation function for redefine classes or if an error occurs void deallocate_contents(ClassLoaderData* loader_data); diff --git a/hotspot/src/share/vm/opto/block.hpp b/hotspot/src/share/vm/opto/block.hpp index d0d67b7fcbf..a2e4615b8d0 100644 --- a/hotspot/src/share/vm/opto/block.hpp +++ b/hotspot/src/share/vm/opto/block.hpp @@ -292,7 +292,7 @@ class Block : public CFGElement { void needed_for_next_call(Node *this_call, VectorSet &next_call, Block_Array &bbs); bool schedule_local(PhaseCFG *cfg, Matcher &m, GrowableArray &ready_cnt, VectorSet &next_call); // Cleanup if any code lands between a Call and his Catch - void call_catch_cleanup(Block_Array &bbs); + void call_catch_cleanup(Block_Array &bbs, Compile *C); // Detect implicit-null-check opportunities. Basically, find NULL checks // with suitable memory ops nearby. Use the memory op to do the NULL check. // I can generate a memory op if there is not one nearby. diff --git a/hotspot/src/share/vm/opto/c2_globals.hpp b/hotspot/src/share/vm/opto/c2_globals.hpp index 4fdebf526cb..ba30d230cee 100644 --- a/hotspot/src/share/vm/opto/c2_globals.hpp +++ b/hotspot/src/share/vm/opto/c2_globals.hpp @@ -115,6 +115,12 @@ notproduct(bool, VerifyOpto, false, \ "Apply more time consuming verification during compilation") \ \ + notproduct(bool, VerifyIdealNodeCount, false, \ + "Verify that tracked dead ideal node count is accurate") \ + \ + notproduct(bool, PrintIdealNodeCount, false, \ + "Print liveness counts of ideal nodes") \ + \ notproduct(bool, VerifyOptoOopOffsets, false, \ "Check types of base addresses in field references") \ \ diff --git a/hotspot/src/share/vm/opto/callGenerator.cpp b/hotspot/src/share/vm/opto/callGenerator.cpp index 93f2b859ba0..33d8c0c6241 100644 --- a/hotspot/src/share/vm/opto/callGenerator.cpp +++ b/hotspot/src/share/vm/opto/callGenerator.cpp @@ -139,7 +139,7 @@ JVMState* DirectCallGenerator::generate(JVMState* jvms) { if (!is_static) { // Make an explicit receiver null_check as part of this call. // Since we share a map with the caller, his JVMS gets adjusted. - kit.null_check_receiver(method()); + kit.null_check_receiver_before_call(method()); if (kit.stopped()) { // And dump it back to the caller, decorated with any exceptions: return kit.transfer_exceptions_into_jvms(); @@ -207,7 +207,7 @@ JVMState* VirtualCallGenerator::generate(JVMState* jvms) { >= (uint)ImplicitNullCheckThreshold))) { // Make an explicit receiver null_check as part of this call. // Since we share a map with the caller, his JVMS gets adjusted. - receiver = kit.null_check_receiver(method()); + receiver = kit.null_check_receiver_before_call(method()); if (kit.stopped()) { // And dump it back to the caller, decorated with any exceptions: return kit.transfer_exceptions_into_jvms(); @@ -491,7 +491,7 @@ JVMState* PredictedCallGenerator::generate(JVMState* jvms) { jvms->bci(), log->identify(_predicted_receiver)); } - receiver = kit.null_check_receiver(method()); + receiver = kit.null_check_receiver_before_call(method()); if (kit.stopped()) { return kit.transfer_exceptions_into_jvms(); } @@ -597,7 +597,7 @@ CallGenerator* CallGenerator::for_method_handle_inline(JVMState* jvms, ciMethod* switch (iid) { case vmIntrinsics::_invokeBasic: { - // get MethodHandle receiver + // Get MethodHandle receiver: Node* receiver = kit.argument(0); if (receiver->Opcode() == Op_ConP) { const TypeOopPtr* oop_ptr = receiver->bottom_type()->is_oopptr(); @@ -618,7 +618,7 @@ CallGenerator* CallGenerator::for_method_handle_inline(JVMState* jvms, ciMethod* case vmIntrinsics::_linkToSpecial: case vmIntrinsics::_linkToInterface: { - // pop MemberName argument + // Get MemberName argument: Node* member_name = kit.argument(callee->arg_size() - 1); if (member_name->Opcode() == Op_ConP) { const TypeOopPtr* oop_ptr = member_name->bottom_type()->is_oopptr(); diff --git a/hotspot/src/share/vm/opto/callnode.hpp b/hotspot/src/share/vm/opto/callnode.hpp index a412e2b0d9f..f7f4faaa6e3 100644 --- a/hotspot/src/share/vm/opto/callnode.hpp +++ b/hotspot/src/share/vm/opto/callnode.hpp @@ -344,17 +344,26 @@ public: OopMap *oop_map() const { return _oop_map; } void set_oop_map(OopMap *om) { _oop_map = om; } + private: + void verify_input(JVMState* jvms, uint idx) const { + assert(verify_jvms(jvms), "jvms must match"); + Node* n = in(idx); + assert((!n->bottom_type()->isa_long() && !n->bottom_type()->isa_double()) || + in(idx + 1)->is_top(), "2nd half of long/double"); + } + + public: // Functionality from old debug nodes which has changed Node *local(JVMState* jvms, uint idx) const { - assert(verify_jvms(jvms), "jvms must match"); + verify_input(jvms, jvms->locoff() + idx); return in(jvms->locoff() + idx); } Node *stack(JVMState* jvms, uint idx) const { - assert(verify_jvms(jvms), "jvms must match"); + verify_input(jvms, jvms->stkoff() + idx); return in(jvms->stkoff() + idx); } Node *argument(JVMState* jvms, uint idx) const { - assert(verify_jvms(jvms), "jvms must match"); + verify_input(jvms, jvms->argoff() + idx); return in(jvms->argoff() + idx); } Node *monitor_box(JVMState* jvms, uint idx) const { diff --git a/hotspot/src/share/vm/opto/chaitin.cpp b/hotspot/src/share/vm/opto/chaitin.cpp index e626a10d875..0fbe723c44f 100644 --- a/hotspot/src/share/vm/opto/chaitin.cpp +++ b/hotspot/src/share/vm/opto/chaitin.cpp @@ -1495,7 +1495,7 @@ void PhaseChaitin::fixup_spills() { cisc->ins_req(1,src); // Requires a memory edge } b->_nodes.map(j,cisc); // Insert into basic block - n->subsume_by(cisc); // Correct graph + n->subsume_by(cisc, C); // Correct graph // ++_used_cisc_instructions; #ifndef PRODUCT diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp index c4da70ee32c..ffb7ed7b8d5 100644 --- a/hotspot/src/share/vm/opto/compile.cpp +++ b/hotspot/src/share/vm/opto/compile.cpp @@ -23,11 +23,13 @@ */ #include "precompiled.hpp" -#include "asm/assembler.hpp" +#include "asm/macroAssembler.hpp" +#include "asm/macroAssembler.inline.hpp" #include "classfile/systemDictionary.hpp" #include "code/exceptionHandlerTable.hpp" #include "code/nmethod.hpp" #include "compiler/compileLog.hpp" +#include "compiler/disassembler.hpp" #include "compiler/oopMap.hpp" #include "opto/addnode.hpp" #include "opto/block.hpp" @@ -316,7 +318,12 @@ void Compile::gvn_replace_by(Node* n, Node* nn) { } - +static inline bool not_a_node(const Node* n) { + if (n == NULL) return true; + if (((intptr_t)n & 1) != 0) return true; // uninitialized, etc. + if (*(address*)n == badAddress) return true; // kill by Node::destruct + return false; +} // Identify all nodes that are reachable from below, useful. // Use breadth-first pass that records state in a Unique_Node_List, @@ -337,12 +344,27 @@ void Compile::identify_useful_nodes(Unique_Node_List &useful) { uint max = n->len(); for( uint i = 0; i < max; ++i ) { Node *m = n->in(i); - if( m == NULL ) continue; + if (not_a_node(m)) continue; useful.push(m); } } } +// Update dead_node_list with any missing dead nodes using useful +// list. Consider all non-useful nodes to be useless i.e., dead nodes. +void Compile::update_dead_node_list(Unique_Node_List &useful) { + uint max_idx = unique(); + VectorSet& useful_node_set = useful.member_set(); + + for (uint node_idx = 0; node_idx < max_idx; node_idx++) { + // If node with index node_idx is not in useful set, + // mark it as dead in dead node list. + if (! useful_node_set.test(node_idx) ) { + record_dead_node(node_idx); + } + } +} + // Disconnect all useless nodes by disconnecting those at the boundary. void Compile::remove_useless_nodes(Unique_Node_List &useful) { uint next = 0; @@ -582,6 +604,8 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr _inner_loops(0), _scratch_const_size(-1), _in_scratch_emit_size(false), + _dead_node_list(comp_arena()), + _dead_node_count(0), #ifndef PRODUCT _trace_opto_output(TraceOptoOutput || method()->has_option("TraceOptoOutput")), _printer(IdealGraphPrinter::printer()), @@ -873,6 +897,8 @@ Compile::Compile( ciEnv* ci_env, _trace_opto_output(TraceOptoOutput), _printer(NULL), #endif + _dead_node_list(comp_arena()), + _dead_node_count(0), _congraph(NULL) { C = this; @@ -1069,6 +1095,72 @@ void Compile::set_cached_top_node(Node* tn) { assert(_top == NULL || top()->is_top(), ""); } +#ifdef ASSERT +uint Compile::count_live_nodes_by_graph_walk() { + Unique_Node_List useful(comp_arena()); + // Get useful node list by walking the graph. + identify_useful_nodes(useful); + return useful.size(); +} + +void Compile::print_missing_nodes() { + + // Return if CompileLog is NULL and PrintIdealNodeCount is false. + if ((_log == NULL) && (! PrintIdealNodeCount)) { + return; + } + + // This is an expensive function. It is executed only when the user + // specifies VerifyIdealNodeCount option or otherwise knows the + // additional work that needs to be done to identify reachable nodes + // by walking the flow graph and find the missing ones using + // _dead_node_list. + + Unique_Node_List useful(comp_arena()); + // Get useful node list by walking the graph. + identify_useful_nodes(useful); + + uint l_nodes = C->live_nodes(); + uint l_nodes_by_walk = useful.size(); + + if (l_nodes != l_nodes_by_walk) { + if (_log != NULL) { + _log->begin_head("mismatched_nodes count='%d'", abs((int) (l_nodes - l_nodes_by_walk))); + _log->stamp(); + _log->end_head(); + } + VectorSet& useful_member_set = useful.member_set(); + int last_idx = l_nodes_by_walk; + for (int i = 0; i < last_idx; i++) { + if (useful_member_set.test(i)) { + if (_dead_node_list.test(i)) { + if (_log != NULL) { + _log->elem("mismatched_node_info node_idx='%d' type='both live and dead'", i); + } + if (PrintIdealNodeCount) { + // Print the log message to tty + tty->print_cr("mismatched_node idx='%d' both live and dead'", i); + useful.at(i)->dump(); + } + } + } + else if (! _dead_node_list.test(i)) { + if (_log != NULL) { + _log->elem("mismatched_node_info node_idx='%d' type='neither live nor dead'", i); + } + if (PrintIdealNodeCount) { + // Print the log message to tty + tty->print_cr("mismatched_node idx='%d' type='neither live nor dead'", i); + } + } + } + if (_log != NULL) { + _log->tail("mismatched_nodes"); + } + } +} +#endif + #ifndef PRODUCT void Compile::verify_top(Node* tn) const { if (tn != NULL) { @@ -2087,7 +2179,7 @@ static bool oop_offset_is_sane(const TypeInstPtr* tp) { // Eliminate trivially redundant StoreCMs and accumulate their // precedence edges. -static void eliminate_redundant_card_marks(Node* n) { +void Compile::eliminate_redundant_card_marks(Node* n) { assert(n->Opcode() == Op_StoreCM, "expected StoreCM"); if (n->in(MemNode::Address)->outcnt() > 1) { // There are multiple users of the same address so it might be @@ -2122,7 +2214,7 @@ static void eliminate_redundant_card_marks(Node* n) { // Eliminate the previous StoreCM prev->set_req(MemNode::Memory, mem->in(MemNode::Memory)); assert(mem->outcnt() == 0, "should be dead"); - mem->disconnect_inputs(NULL); + mem->disconnect_inputs(NULL, this); } else { prev = mem; } @@ -2133,7 +2225,7 @@ static void eliminate_redundant_card_marks(Node* n) { //------------------------------final_graph_reshaping_impl---------------------- // Implement items 1-5 from final_graph_reshaping below. -static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) { +void Compile::final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc) { if ( n->outcnt() == 0 ) return; // dead node uint nop = n->Opcode(); @@ -2163,8 +2255,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) { #ifdef ASSERT if( n->is_Mem() ) { - Compile* C = Compile::current(); - int alias_idx = C->get_alias_index(n->as_Mem()->adr_type()); + int alias_idx = get_alias_index(n->as_Mem()->adr_type()); assert( n->in(0) != NULL || alias_idx != Compile::AliasIdxRaw || // oop will be recorded in oop map if load crosses safepoint n->is_Load() && (n->as_Load()->bottom_type()->isa_oopptr() || @@ -2213,7 +2304,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) { break; case Op_Opaque1: // Remove Opaque Nodes before matching case Op_Opaque2: // Remove Opaque Nodes before matching - n->subsume_by(n->in(1)); + n->subsume_by(n->in(1), this); break; case Op_CallStaticJava: case Op_CallJava: @@ -2337,8 +2428,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) { int op = t->isa_oopptr() ? Op_ConN : Op_ConNKlass; // Look for existing ConN node of the same exact type. - Compile* C = Compile::current(); - Node* r = C->root(); + Node* r = root(); uint cnt = r->outcnt(); for (uint i = 0; i < cnt; i++) { Node* m = r->raw_out(i); @@ -2352,14 +2442,14 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) { // Decode a narrow oop to match address // [R12 + narrow_oop_reg<<3 + offset] if (t->isa_oopptr()) { - nn = new (C) DecodeNNode(nn, t); + nn = new (this) DecodeNNode(nn, t); } else { - nn = new (C) DecodeNKlassNode(nn, t); + nn = new (this) DecodeNKlassNode(nn, t); } n->set_req(AddPNode::Base, nn); n->set_req(AddPNode::Address, nn); if (addp->outcnt() == 0) { - addp->disconnect_inputs(NULL); + addp->disconnect_inputs(NULL, this); } } } @@ -2371,7 +2461,6 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) { #ifdef _LP64 case Op_CastPP: if (n->in(1)->is_DecodeN() && Matcher::gen_narrow_oop_implicit_null_checks()) { - Compile* C = Compile::current(); Node* in1 = n->in(1); const Type* t = n->bottom_type(); Node* new_in1 = in1->clone(); @@ -2400,9 +2489,9 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) { new_in1->set_req(0, n->in(0)); } - n->subsume_by(new_in1); + n->subsume_by(new_in1, this); if (in1->outcnt() == 0) { - in1->disconnect_inputs(NULL); + in1->disconnect_inputs(NULL, this); } } break; @@ -2419,7 +2508,6 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) { } assert(in1->is_DecodeNarrowPtr(), "sanity"); - Compile* C = Compile::current(); Node* new_in2 = NULL; if (in2->is_DecodeNarrowPtr()) { assert(in2->Opcode() == in1->Opcode(), "must be same node type"); @@ -2432,7 +2520,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) { // 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(C, TypeNarrowOop::NULL_PTR); + new_in2 = ConNode::make(this, TypeNarrowOop::NULL_PTR); // // This transformation together with CastPP transformation above // will generated code for implicit NULL checks for compressed oops. @@ -2471,19 +2559,19 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) { // NullCheck base_reg // } else if (t->isa_oopptr()) { - new_in2 = ConNode::make(C, t->make_narrowoop()); + new_in2 = ConNode::make(this, t->make_narrowoop()); } else if (t->isa_klassptr()) { - new_in2 = ConNode::make(C, t->make_narrowklass()); + new_in2 = ConNode::make(this, t->make_narrowklass()); } } if (new_in2 != NULL) { - Node* cmpN = new (C) CmpNNode(in1->in(1), new_in2); - n->subsume_by( cmpN ); + Node* cmpN = new (this) CmpNNode(in1->in(1), new_in2); + n->subsume_by(cmpN, this); if (in1->outcnt() == 0) { - in1->disconnect_inputs(NULL); + in1->disconnect_inputs(NULL, this); } if (in2->outcnt() == 0) { - in2->disconnect_inputs(NULL); + in2->disconnect_inputs(NULL, this); } } } @@ -2501,21 +2589,20 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) { case Op_EncodePKlass: { Node* in1 = n->in(1); if (in1->is_DecodeNarrowPtr()) { - n->subsume_by(in1->in(1)); + n->subsume_by(in1->in(1), this); } else if (in1->Opcode() == Op_ConP) { - Compile* C = Compile::current(); const Type* t = in1->bottom_type(); if (t == TypePtr::NULL_PTR) { assert(t->isa_oopptr(), "null klass?"); - n->subsume_by(ConNode::make(C, TypeNarrowOop::NULL_PTR)); + n->subsume_by(ConNode::make(this, TypeNarrowOop::NULL_PTR), this); } else if (t->isa_oopptr()) { - n->subsume_by(ConNode::make(C, t->make_narrowoop())); + n->subsume_by(ConNode::make(this, t->make_narrowoop()), this); } else if (t->isa_klassptr()) { - n->subsume_by(ConNode::make(C, t->make_narrowklass())); + n->subsume_by(ConNode::make(this, t->make_narrowklass()), this); } } if (in1->outcnt() == 0) { - in1->disconnect_inputs(NULL); + in1->disconnect_inputs(NULL, this); } break; } @@ -2538,7 +2625,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) { } } assert(proj != NULL, "must be found"); - p->subsume_by(proj); + p->subsume_by(proj, this); } } break; @@ -2558,7 +2645,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) { unique_in = NULL; } if (unique_in != NULL) { - n->subsume_by(unique_in); + n->subsume_by(unique_in, this); } } break; @@ -2571,16 +2658,15 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) { Node* d = n->find_similar(Op_DivI); if (d) { // Replace them with a fused divmod if supported - Compile* C = Compile::current(); if (Matcher::has_match_rule(Op_DivModI)) { - DivModINode* divmod = DivModINode::make(C, n); - d->subsume_by(divmod->div_proj()); - n->subsume_by(divmod->mod_proj()); + DivModINode* divmod = DivModINode::make(this, n); + d->subsume_by(divmod->div_proj(), this); + n->subsume_by(divmod->mod_proj(), this); } else { // replace a%b with a-((a/b)*b) - Node* mult = new (C) MulINode(d, d->in(2)); - Node* sub = new (C) SubINode(d->in(1), mult); - n->subsume_by( sub ); + Node* mult = new (this) MulINode(d, d->in(2)); + Node* sub = new (this) SubINode(d->in(1), mult); + n->subsume_by(sub, this); } } } @@ -2592,16 +2678,15 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) { Node* d = n->find_similar(Op_DivL); if (d) { // Replace them with a fused divmod if supported - Compile* C = Compile::current(); if (Matcher::has_match_rule(Op_DivModL)) { - DivModLNode* divmod = DivModLNode::make(C, n); - d->subsume_by(divmod->div_proj()); - n->subsume_by(divmod->mod_proj()); + DivModLNode* divmod = DivModLNode::make(this, n); + d->subsume_by(divmod->div_proj(), this); + n->subsume_by(divmod->mod_proj(), this); } else { // replace a%b with a-((a/b)*b) - Node* mult = new (C) MulLNode(d, d->in(2)); - Node* sub = new (C) SubLNode(d->in(1), mult); - n->subsume_by( sub ); + Node* mult = new (this) MulLNode(d, d->in(2)); + Node* sub = new (this) SubLNode(d->in(1), mult); + n->subsume_by(sub, this); } } } @@ -2620,8 +2705,8 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) { 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(Compile::current(), 1, n->req()); - n->subsume_by(btp); + Node* btp = p->binary_tree_pack(this, 1, n->req()); + n->subsume_by(btp, this); } break; case Op_Loop: @@ -2645,18 +2730,16 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) { if (t != NULL && t->is_con()) { juint shift = t->get_con(); if (shift > mask) { // Unsigned cmp - Compile* C = Compile::current(); - n->set_req(2, ConNode::make(C, TypeInt::make(shift & mask))); + n->set_req(2, ConNode::make(this, TypeInt::make(shift & mask))); } } else { if (t == NULL || t->_lo < 0 || t->_hi > (int)mask) { - Compile* C = Compile::current(); - Node* shift = new (C) AndINode(in2, ConNode::make(C, TypeInt::make(mask))); + Node* shift = new (this) AndINode(in2, ConNode::make(this, TypeInt::make(mask))); n->set_req(2, shift); } } if (in2->outcnt() == 0) { // Remove dead node - in2->disconnect_inputs(NULL); + in2->disconnect_inputs(NULL, this); } } break; @@ -2674,7 +2757,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) { //------------------------------final_graph_reshaping_walk--------------------- // Replacing Opaque nodes with their input in final_graph_reshaping_impl(), // requires that the walk visits a node's inputs before visiting the node. -static void final_graph_reshaping_walk( Node_Stack &nstack, Node *root, Final_Reshape_Counts &frc ) { +void Compile::final_graph_reshaping_walk( Node_Stack &nstack, Node *root, Final_Reshape_Counts &frc ) { ResourceArea *area = Thread::current()->resource_area(); Unique_Node_List sfpt(area); @@ -2741,7 +2824,7 @@ static void final_graph_reshaping_walk( Node_Stack &nstack, Node *root, Final_Re n->set_req(j, in->in(1)); } if (in->outcnt() == 0) { - in->disconnect_inputs(NULL); + in->disconnect_inputs(NULL, this); } } } @@ -3014,7 +3097,8 @@ void Compile::record_failure(const char* reason) { } Compile::TracePhase::TracePhase(const char* name, elapsedTimer* accumulator, bool dolog) - : TraceTime(NULL, accumulator, false NOT_PRODUCT( || TimeCompiler ), false) + : TraceTime(NULL, accumulator, false NOT_PRODUCT( || TimeCompiler ), false), + _phase_name(name), _dolog(dolog) { if (dolog) { C = Compile::current(); @@ -3024,15 +3108,34 @@ Compile::TracePhase::TracePhase(const char* name, elapsedTimer* accumulator, boo _log = NULL; } if (_log != NULL) { - _log->begin_head("phase name='%s' nodes='%d'", name, C->unique()); + _log->begin_head("phase name='%s' nodes='%d' live='%d'", _phase_name, C->unique(), C->live_nodes()); _log->stamp(); _log->end_head(); } } Compile::TracePhase::~TracePhase() { + + C = Compile::current(); + if (_dolog) { + _log = C->log(); + } else { + _log = NULL; + } + +#ifdef ASSERT + if (PrintIdealNodeCount) { + tty->print_cr("phase name='%s' nodes='%d' live='%d' live_graph_walk='%d'", + _phase_name, C->unique(), C->live_nodes(), C->count_live_nodes_by_graph_walk()); + } + + if (VerifyIdealNodeCount) { + Compile::current()->print_missing_nodes(); + } +#endif + if (_log != NULL) { - _log->done("phase nodes='%d'", C->unique()); + _log->done("phase name='%s' nodes='%d' live='%d'", _phase_name, C->unique(), C->live_nodes()); } } diff --git a/hotspot/src/share/vm/opto/compile.hpp b/hotspot/src/share/vm/opto/compile.hpp index 44bf277689c..aacb72cbfb4 100644 --- a/hotspot/src/share/vm/opto/compile.hpp +++ b/hotspot/src/share/vm/opto/compile.hpp @@ -75,6 +75,8 @@ class TypeFunc; class Unique_Node_List; class nmethod; class WarmCallInfo; +class Node_Stack; +struct Final_Reshape_Counts; //------------------------------Compile---------------------------------------- // This class defines a top-level Compiler invocation. @@ -98,6 +100,8 @@ class Compile : public Phase { private: Compile* C; CompileLog* _log; + const char* _phase_name; + bool _dolog; public: TracePhase(const char* name, elapsedTimer* accumulator, bool dolog); ~TracePhase(); @@ -313,6 +317,9 @@ class Compile : public Phase { // Node management uint _unique; // Counter for unique Node indices + 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(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 @@ -534,7 +541,7 @@ class Compile : public Phase { ciEnv* env() const { return _env; } CompileLog* log() const { return _log; } bool failing() const { return _env->failing() || _failure_reason != NULL; } - const char* failure_reason() { return _failure_reason; } + const char* failure_reason() { return _failure_reason; } bool failure_reason_is(const char* r) { return (r==_failure_reason) || (r!=NULL && _failure_reason!=NULL && strcmp(r, _failure_reason)==0); } void record_failure(const char* reason); @@ -549,7 +556,7 @@ class Compile : public Phase { record_method_not_compilable(reason, true); } bool check_node_count(uint margin, const char* reason) { - if (unique() + margin > (uint)MaxNodeLimit) { + if (live_nodes() + margin > (uint)MaxNodeLimit) { record_method_not_compilable(reason); return true; } else { @@ -558,25 +565,41 @@ class Compile : public Phase { } // Node management - uint unique() const { return _unique; } - uint next_unique() { return _unique++; } - void set_unique(uint i) { _unique = i; } - static int debug_idx() { return debug_only(_debug_idx)+0; } - static void set_debug_idx(int i) { debug_only(_debug_idx = i); } - Arena* node_arena() { return &_node_arena; } - Arena* old_arena() { return &_old_arena; } - RootNode* root() const { return _root; } - void set_root(RootNode* r) { _root = r; } - StartNode* start() const; // (Derived from root.) + uint unique() const { return _unique; } + uint next_unique() { return _unique++; } + void set_unique(uint i) { _unique = i; } + static int debug_idx() { return debug_only(_debug_idx)+0; } + static void set_debug_idx(int i) { debug_only(_debug_idx = i); } + Arena* node_arena() { return &_node_arena; } + Arena* old_arena() { return &_old_arena; } + RootNode* root() const { return _root; } + void set_root(RootNode* r) { _root = r; } + StartNode* start() const; // (Derived from root.) void init_start(StartNode* s); - Node* immutable_memory(); + Node* immutable_memory(); - Node* recent_alloc_ctl() const { return _recent_alloc_ctl; } - Node* recent_alloc_obj() const { return _recent_alloc_obj; } - void set_recent_alloc(Node* ctl, Node* obj) { + Node* recent_alloc_ctl() const { return _recent_alloc_ctl; } + Node* recent_alloc_obj() const { return _recent_alloc_obj; } + void set_recent_alloc(Node* ctl, Node* obj) { _recent_alloc_ctl = ctl; _recent_alloc_obj = obj; - } + } + void record_dead_node(uint idx) { if (_dead_node_list.test_set(idx)) return; + _dead_node_count++; + } + uint dead_node_count() { return _dead_node_count; } + void reset_dead_node_list() { _dead_node_list.Reset(); + _dead_node_count = 0; + } + uint live_nodes() { + int val = _unique - _dead_node_count; + assert (val >= 0, err_msg_res("number of tracked dead nodes %d more than created nodes %d", _unique, _dead_node_count)); + return (uint) val; + } +#ifdef ASSERT + uint count_live_nodes_by_graph_walk(); + void print_missing_nodes(); +#endif // Constant table ConstantTable& constant_table() { return _constant_table; } @@ -678,6 +701,7 @@ class Compile : public Phase { void identify_useful_nodes(Unique_Node_List &useful); + void update_dead_node_list(Unique_Node_List &useful); void remove_useless_nodes (Unique_Node_List &useful); WarmCallInfo* warm_calls() const { return _warm_calls; } @@ -892,6 +916,11 @@ class Compile : public Phase { static juint _intrinsic_hist_count[vmIntrinsics::ID_LIMIT]; static jubyte _intrinsic_hist_flags[vmIntrinsics::ID_LIMIT]; #endif + // Function calls made by the public function final_graph_reshaping. + // No need to be made public as they are not called elsewhere. + void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc); + void final_graph_reshaping_walk( Node_Stack &nstack, Node *root, Final_Reshape_Counts &frc ); + void eliminate_redundant_card_marks(Node* n); public: diff --git a/hotspot/src/share/vm/opto/doCall.cpp b/hotspot/src/share/vm/opto/doCall.cpp index ba806d79c55..ca9a0a6d67e 100644 --- a/hotspot/src/share/vm/opto/doCall.cpp +++ b/hotspot/src/share/vm/opto/doCall.cpp @@ -350,7 +350,7 @@ void Parse::do_call() { // Set frequently used booleans const bool is_virtual = bc() == Bytecodes::_invokevirtual; const bool is_virtual_or_interface = is_virtual || bc() == Bytecodes::_invokeinterface; - const bool has_receiver = is_virtual_or_interface || bc() == Bytecodes::_invokespecial; + const bool has_receiver = Bytecodes::has_receiver(bc()); // Find target being called bool will_link; @@ -380,6 +380,8 @@ void Parse::do_call() { // Note: In the absence of miranda methods, an abstract class K can perform // an invokevirtual directly on an interface method I.m if K implements I. + // orig_callee is the resolved callee which's signature includes the + // appendix argument. const int nargs = orig_callee->arg_size(); // Push appendix argument (MethodType, CallSite, etc.), if one. @@ -572,7 +574,7 @@ void Parse::do_call() { } // If there is going to be a trap, put it at the next bytecode: set_bci(iter().next_bci()); - do_null_assert(peek(), T_OBJECT); + null_assert(peek()); set_bci(iter().cur_bci()); // put it back } } diff --git a/hotspot/src/share/vm/opto/escape.cpp b/hotspot/src/share/vm/opto/escape.cpp index 40acbdbe770..659828e509f 100644 --- a/hotspot/src/share/vm/opto/escape.cpp +++ b/hotspot/src/share/vm/opto/escape.cpp @@ -2320,7 +2320,7 @@ PhiNode *ConnectionGraph::create_split_phi(PhiNode *orig_phi, int alias_idx, Gro } } } - if ((int)C->unique() + 2*NodeLimitFudgeFactor > MaxNodeLimit) { + if ((int) (C->live_nodes() + 2*NodeLimitFudgeFactor) > MaxNodeLimit) { if (C->do_escape_analysis() == true && !C->failing()) { // Retry compilation without escape analysis. // If this is the first failure, the sentinel string will "stick" diff --git a/hotspot/src/share/vm/opto/gcm.cpp b/hotspot/src/share/vm/opto/gcm.cpp index 6cd2ecd237e..4fffeeb80d3 100644 --- a/hotspot/src/share/vm/opto/gcm.cpp +++ b/hotspot/src/share/vm/opto/gcm.cpp @@ -1359,7 +1359,7 @@ void PhaseCFG::GlobalCodeMotion( Matcher &matcher, uint unique, Node_List &proj_ // If we inserted any instructions between a Call and his CatchNode, // clone the instructions on all paths below the Catch. for( i=0; i < _num_blocks; i++ ) - _blocks[i]->call_catch_cleanup(_bbs); + _blocks[i]->call_catch_cleanup(_bbs, C); #ifndef PRODUCT if (trace_opto_pipelining()) { diff --git a/hotspot/src/share/vm/opto/graphKit.cpp b/hotspot/src/share/vm/opto/graphKit.cpp index 95d5357d7d3..ba7ec2caf77 100644 --- a/hotspot/src/share/vm/opto/graphKit.cpp +++ b/hotspot/src/share/vm/opto/graphKit.cpp @@ -93,6 +93,16 @@ JVMState* GraphKit::sync_jvms() const { return jvms; } +//--------------------------------sync_jvms_for_reexecute--------------------- +// Make sure our current jvms agrees with our parse state. This version +// uses the reexecute_sp for reexecuting bytecodes. +JVMState* GraphKit::sync_jvms_for_reexecute() { + JVMState* jvms = this->jvms(); + jvms->set_bci(bci()); // Record the new bci in the JVMState + jvms->set_sp(reexecute_sp()); // Record the new sp in the JVMState + return jvms; +} + #ifdef ASSERT bool GraphKit::jvms_in_sync() const { Parse* parse = is_Parse(); @@ -143,7 +153,7 @@ void GraphKit::verify_exception_state(SafePointNode* ex_map) { void GraphKit::stop_and_kill_map() { SafePointNode* dead_map = stop(); if (dead_map != NULL) { - dead_map->disconnect_inputs(NULL); // Mark the map as killed. + dead_map->disconnect_inputs(NULL, C); // Mark the map as killed. assert(dead_map->is_killed(), "must be so marked"); } } @@ -826,7 +836,16 @@ void GraphKit::add_safepoint_edges(SafePointNode* call, bool must_throw) { // Walk the inline list to fill in the correct set of JVMState's // Also fill in the associated edges for each JVMState. - JVMState* youngest_jvms = sync_jvms(); + // If the bytecode needs to be reexecuted we need to put + // the arguments back on the stack. + const bool should_reexecute = jvms()->should_reexecute(); + JVMState* youngest_jvms = should_reexecute ? sync_jvms_for_reexecute() : sync_jvms(); + + // NOTE: set_bci (called from sync_jvms) might reset the reexecute bit to + // undefined if the bci is different. This is normal for Parse but it + // should not happen for LibraryCallKit because only one bci is processed. + assert(!is_LibraryCallKit() || (jvms()->should_reexecute() == should_reexecute), + "in LibraryCallKit the reexecute bit should not change"); // If we are guaranteed to throw, we can prune everything but the // input to the current bytecode. @@ -860,7 +879,7 @@ void GraphKit::add_safepoint_edges(SafePointNode* call, bool must_throw) { } // Presize the call: - debug_only(uint non_debug_edges = call->req()); + DEBUG_ONLY(uint non_debug_edges = call->req()); call->add_req_batch(top(), youngest_jvms->debug_depth()); assert(call->req() == non_debug_edges + youngest_jvms->debug_depth(), ""); @@ -965,7 +984,7 @@ void GraphKit::add_safepoint_edges(SafePointNode* call, bool must_throw) { assert(call->jvms()->debug_depth() == call->req() - non_debug_edges, ""); } -bool GraphKit::compute_stack_effects(int& inputs, int& depth, bool for_parse) { +bool GraphKit::compute_stack_effects(int& inputs, int& depth) { Bytecodes::Code code = java_bc(); if (code == Bytecodes::_wide) { code = method()->java_code_at_bci(bci() + 1); @@ -1005,14 +1024,11 @@ bool GraphKit::compute_stack_effects(int& inputs, int& depth, bool for_parse) { case Bytecodes::_getfield: case Bytecodes::_putfield: { - bool is_get = (depth >= 0), is_static = (depth & 1); - ciBytecodeStream iter(method()); - iter.reset_to_bci(bci()); - iter.next(); bool ignored_will_link; - ciField* field = iter.get_field(ignored_will_link); + ciField* field = method()->get_field_at_bci(bci(), ignored_will_link); int size = field->type()->size(); - inputs = (is_static ? 0 : 1); + bool is_get = (depth >= 0), is_static = (depth & 1); + inputs = (is_static ? 0 : 1); if (is_get) { depth = size - inputs; } else { @@ -1028,26 +1044,11 @@ bool GraphKit::compute_stack_effects(int& inputs, int& depth, bool for_parse) { case Bytecodes::_invokedynamic: case Bytecodes::_invokeinterface: { - ciBytecodeStream iter(method()); - iter.reset_to_bci(bci()); - iter.next(); bool ignored_will_link; ciSignature* declared_signature = NULL; - ciMethod* callee = iter.get_method(ignored_will_link, &declared_signature); + ciMethod* ignored_callee = method()->get_method_at_bci(bci(), ignored_will_link, &declared_signature); assert(declared_signature != NULL, "cannot be null"); - // (Do not use ciMethod::arg_size(), because - // it might be an unloaded method, which doesn't - // know whether it is static or not.) - if (for_parse) { - // Case 1: When called from parse we are *before* the invoke (in the - // caller) and need to to adjust the inputs by an appendix - // argument that will be pushed implicitly. - inputs = callee->invoke_arg_size(code) - (iter.has_appendix() ? 1 : 0); - } else { - // Case 2: Here we are *after* the invoke (in the callee) and need to - // remove any appendix arguments that were popped. - inputs = callee->invoke_arg_size(code) - (callee->has_member_arg() ? 1 : 0); - } + inputs = declared_signature->arg_size_for_bc(code); int size = declared_signature->return_type()->size(); depth = size - inputs; } @@ -1178,7 +1179,7 @@ Node* GraphKit::null_check_common(Node* value, BasicType type, Node *chk = NULL; switch(type) { case T_LONG : chk = new (C) CmpLNode(value, _gvn.zerocon(T_LONG)); break; - case T_INT : chk = new (C) CmpINode( value, _gvn.intcon(0)); break; + case T_INT : chk = new (C) CmpINode(value, _gvn.intcon(0)); break; case T_ARRAY : // fall through type = T_OBJECT; // simplify further tests case T_OBJECT : { @@ -1229,7 +1230,8 @@ Node* GraphKit::null_check_common(Node* value, BasicType type, break; } - default : ShouldNotReachHere(); + default: + fatal(err_msg_res("unexpected type: %s", type2name(type))); } assert(chk != NULL, "sanity check"); chk = _gvn.transform(chk); @@ -1809,7 +1811,7 @@ void GraphKit::replace_call(CallNode* call, Node* result) { } // Disconnect the call from the graph - call->disconnect_inputs(NULL); + call->disconnect_inputs(NULL, C); C->gvn_replace_by(call, C->top()); // Clean up any MergeMems that feed other MergeMems since the @@ -1861,15 +1863,17 @@ void GraphKit::uncommon_trap(int trap_request, // occurs here, the runtime will make sure an MDO exists. There is // no need to call method()->ensure_method_data() at this point. + // Set the stack pointer to the right value for reexecution: + set_sp(reexecute_sp()); + #ifdef ASSERT if (!must_throw) { // Make sure the stack has at least enough depth to execute // the current bytecode. - int inputs, ignore; - if (compute_stack_effects(inputs, ignore)) { - assert(sp() >= inputs, "must have enough JVMS stack to execute"); - // It is a frequent error in library_call.cpp to issue an - // uncommon trap with the _sp value already popped. + int inputs, ignored_depth; + if (compute_stack_effects(inputs, ignored_depth)) { + assert(sp() >= inputs, err_msg_res("must have enough JVMS stack to execute %s: sp=%d, inputs=%d", + Bytecodes::name(java_bc()), sp(), inputs)); } } #endif @@ -1900,7 +1904,8 @@ void GraphKit::uncommon_trap(int trap_request, case Deoptimization::Action_make_not_compilable: break; default: - assert(false, "bad action"); + fatal(err_msg_res("unknown action %d: %s", action, Deoptimization::trap_action_name(action))); + break; #endif } @@ -2667,7 +2672,7 @@ Node* GraphKit::gen_checkcast(Node *obj, Node* superklass, case SSC_always_false: // It needs a null check because a null will *pass* the cast check. // A non-null value will always produce an exception. - return do_null_assert(obj, T_OBJECT); + return null_assert(obj); } } } @@ -2786,7 +2791,7 @@ Node* GraphKit::insert_mem_bar(int opcode, Node* precedent) { mb->init_req(TypeFunc::Control, control()); mb->init_req(TypeFunc::Memory, reset_memory()); Node* membar = _gvn.transform(mb); - set_control(_gvn.transform(new (C) ProjNode(membar,TypeFunc::Control) )); + set_control(_gvn.transform(new (C) ProjNode(membar, TypeFunc::Control))); set_all_memory_call(membar); return membar; } @@ -3148,7 +3153,7 @@ Node* GraphKit::new_array(Node* klass_node, // array klass (maybe variable) Node* cmp_lh = _gvn.transform( new(C) CmpINode(layout_val, intcon(layout_con)) ); Node* bol_lh = _gvn.transform( new(C) BoolNode(cmp_lh, BoolTest::eq) ); { BuildCutout unless(this, bol_lh, PROB_MAX); - _sp += nargs; + inc_sp(nargs); uncommon_trap(Deoptimization::Reason_class_check, Deoptimization::Action_maybe_recompile); } @@ -3391,7 +3396,7 @@ void GraphKit::add_predicate_impl(Deoptimization::DeoptReason reason, int nargs) { PreserveJVMState pjvms(this); set_control(iffalse); - _sp += nargs; + inc_sp(nargs); uncommon_trap(reason, Deoptimization::Action_maybe_recompile); } Node* iftrue = _gvn.transform(new (C) IfTrueNode(iff)); diff --git a/hotspot/src/share/vm/opto/graphKit.hpp b/hotspot/src/share/vm/opto/graphKit.hpp index ede5b92e68e..4d7d96178ae 100644 --- a/hotspot/src/share/vm/opto/graphKit.hpp +++ b/hotspot/src/share/vm/opto/graphKit.hpp @@ -41,6 +41,7 @@ class FastLockNode; class FastUnlockNode; class IdealKit; +class LibraryCallKit; class Parse; class RootNode; @@ -60,10 +61,12 @@ class GraphKit : public Phase { PhaseGVN &_gvn; // Some optimizations while parsing SafePointNode* _map; // Parser map from JVM to Nodes SafePointNode* _exceptions;// Parser map(s) for exception state(s) - int _sp; // JVM Expression Stack Pointer int _bci; // JVM Bytecode Pointer ciMethod* _method; // JVM Current Method + private: + int _sp; // JVM Expression Stack Pointer; don't modify directly! + private: SafePointNode* map_not_null() const { assert(_map != NULL, "must call stopped() to test for reset compiler map"); @@ -80,7 +83,8 @@ class GraphKit : public Phase { } #endif - virtual Parse* is_Parse() const { return NULL; } + virtual Parse* is_Parse() const { return NULL; } + virtual LibraryCallKit* is_LibraryCallKit() const { return NULL; } ciEnv* env() const { return _env; } PhaseGVN& gvn() const { return _gvn; } @@ -141,7 +145,7 @@ class GraphKit : public Phase { _bci = jvms->bci(); _method = jvms->has_method() ? jvms->method() : NULL; } void set_map(SafePointNode* m) { _map = m; debug_only(verify_map()); } - void set_sp(int i) { assert(i >= 0, "must be non-negative"); _sp = i; } + void set_sp(int sp) { assert(sp >= 0, err_msg_res("sp must be non-negative: %d", sp)); _sp = sp; } void clean_stack(int from_sp); // clear garbage beyond from_sp to top void inc_sp(int i) { set_sp(sp() + i); } @@ -149,7 +153,9 @@ class GraphKit : public Phase { void set_bci(int bci) { _bci = bci; } // Make sure jvms has current bci & sp. - JVMState* sync_jvms() const; + JVMState* sync_jvms() const; + JVMState* sync_jvms_for_reexecute(); + #ifdef ASSERT // Make sure JVMS has an updated copy of bci and sp. // Also sanity-check method, depth, and monitor depth. @@ -286,7 +292,7 @@ class GraphKit : public Phase { // How many stack inputs does the current BC consume? // And, how does the stack change after the bytecode? // Returns false if unknown. - bool compute_stack_effects(int& inputs, int& depth, bool for_parse = false); + bool compute_stack_effects(int& inputs, int& depth); // Add a fixed offset to a pointer Node* basic_plus_adr(Node* base, Node* ptr, intptr_t offset) { @@ -337,20 +343,37 @@ class GraphKit : public Phase { Node* load_object_klass(Node* object); // Find out the length of an array. Node* load_array_length(Node* array); + + // Helper function to do a NULL pointer check or ZERO check based on type. - Node* null_check_common(Node* value, BasicType type, - bool assert_null, Node* *null_control); // Throw an exception if a given value is null. // Return the value cast to not-null. // Be clever about equivalent dominating null checks. - Node* do_null_check(Node* value, BasicType type) { - return null_check_common(value, type, false, NULL); + Node* null_check_common(Node* value, BasicType type, + bool assert_null = false, Node* *null_control = NULL); + Node* null_check(Node* value, BasicType type = T_OBJECT) { + return null_check_common(value, type); + } + Node* null_check_receiver() { + assert(argument(0)->bottom_type()->isa_ptr(), "must be"); + return null_check(argument(0)); + } + Node* zero_check_int(Node* value) { + assert(value->bottom_type()->basic_type() == T_INT, + err_msg_res("wrong type: %s", type2name(value->bottom_type()->basic_type()))); + return null_check_common(value, T_INT); + } + Node* zero_check_long(Node* value) { + assert(value->bottom_type()->basic_type() == T_LONG, + err_msg_res("wrong type: %s", type2name(value->bottom_type()->basic_type()))); + return null_check_common(value, T_LONG); } // Throw an uncommon trap if a given value is __not__ null. // Return the value cast to null, and be clever about dominating checks. - Node* do_null_assert(Node* value, BasicType type) { - return null_check_common(value, type, true, NULL); + Node* null_assert(Node* value, BasicType type = T_OBJECT) { + return null_check_common(value, type, true); } + // Null check oop. Return null-path control into (*null_control). // Return a cast-not-null node which depends on the not-null control. // If never_see_null, use an uncommon trap (*null_control sees a top). @@ -371,9 +394,9 @@ class GraphKit : public Phase { // Replace all occurrences of one node by another. void replace_in_map(Node* old, Node* neww); - void push(Node* n) { map_not_null(); _map->set_stack(_map->_jvms, _sp++, n); } - Node* pop() { map_not_null(); return _map->stack( _map->_jvms, --_sp); } - Node* peek(int off = 0) { map_not_null(); return _map->stack( _map->_jvms, _sp - off - 1); } + void push(Node* n) { map_not_null(); _map->set_stack(_map->_jvms, _sp++ , n); } + Node* pop() { map_not_null(); return _map->stack( _map->_jvms, --_sp ); } + Node* peek(int off = 0) { map_not_null(); return _map->stack( _map->_jvms, _sp - off - 1 ); } void push_pair(Node* ldval) { push(ldval); @@ -580,19 +603,15 @@ class GraphKit : public Phase { //---------- help for generating calls -------------- - // Do a null check on the receiver, which is in argument(0). - Node* null_check_receiver(ciMethod* callee) { + // Do a null check on the receiver as it would happen before the call to + // callee (with all arguments still on the stack). + Node* null_check_receiver_before_call(ciMethod* callee) { assert(!callee->is_static(), "must be a virtual method"); - int nargs = 1 + callee->signature()->size(); - // Null check on self without removing any arguments. The argument - // null check technically happens in the wrong place, which can lead to - // invalid stack traces when the primitive is inlined into a method - // which handles NullPointerExceptions. - Node* receiver = argument(0); - _sp += nargs; - receiver = do_null_check(receiver, T_OBJECT); - _sp -= nargs; - return receiver; + const int nargs = callee->arg_size(); + inc_sp(nargs); + Node* n = null_check_receiver(); + dec_sp(nargs); + return n; } // Fill in argument edges for the call from argument(0), argument(1), ... @@ -645,6 +664,9 @@ class GraphKit : public Phase { klass, reason_string, must_throw, keep_exact_action); } + // SP when bytecode needs to be reexecuted. + virtual int reexecute_sp() { return sp(); } + // Report if there were too many traps at the current method and bci. // Report if a trap was recorded, and/or PerMethodTrapLimit was exceeded. // If there is no MDO at all, report no trap unless told to assume it. diff --git a/hotspot/src/share/vm/opto/ifg.cpp b/hotspot/src/share/vm/opto/ifg.cpp index 4827a17d8df..44828fa6ab8 100644 --- a/hotspot/src/share/vm/opto/ifg.cpp +++ b/hotspot/src/share/vm/opto/ifg.cpp @@ -573,7 +573,7 @@ uint PhaseChaitin::build_ifg_physical( ResourceArea *a ) { (n2lidx(def) && !liveout.member(n2lidx(def)) ) ) { b->_nodes.remove(j - 1); if( lrgs(r)._def == n ) lrgs(r)._def = 0; - n->disconnect_inputs(NULL); + n->disconnect_inputs(NULL, C); _cfg._bbs.map(n->_idx,NULL); n->replace_by(C->top()); // Since yanking a Node from block, high pressure moves up one diff --git a/hotspot/src/share/vm/opto/lcm.cpp b/hotspot/src/share/vm/opto/lcm.cpp index 24a6a3182d0..5ca4bae13d7 100644 --- a/hotspot/src/share/vm/opto/lcm.cpp +++ b/hotspot/src/share/vm/opto/lcm.cpp @@ -1006,7 +1006,7 @@ static void catch_cleanup_inter_block(Node *use, Block *use_blk, Node *def, Bloc //------------------------------call_catch_cleanup----------------------------- // If we inserted any instructions between a Call and his CatchNode, // clone the instructions on all paths below the Catch. -void Block::call_catch_cleanup(Block_Array &bbs) { +void Block::call_catch_cleanup(Block_Array &bbs, Compile* C) { // End of region to clone uint end = end_idx(); @@ -1068,7 +1068,7 @@ void Block::call_catch_cleanup(Block_Array &bbs) { // Remove the now-dead cloned ops for(uint i3 = beg; i3 < end; i3++ ) { - _nodes[beg]->disconnect_inputs(NULL); + _nodes[beg]->disconnect_inputs(NULL, C); _nodes.remove(beg); } @@ -1081,7 +1081,7 @@ void Block::call_catch_cleanup(Block_Array &bbs) { Node *n = sb->_nodes[j]; if (n->outcnt() == 0 && (!n->is_Proj() || n->as_Proj()->in(0)->outcnt() == 1) ){ - n->disconnect_inputs(NULL); + n->disconnect_inputs(NULL, C); sb->_nodes.remove(j); new_cnt--; } diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index 6b90061ff4f..43d4d05022e 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -67,30 +67,64 @@ class LibraryIntrinsic : public InlineCallGenerator { // Local helper class for LibraryIntrinsic: class LibraryCallKit : public GraphKit { private: - LibraryIntrinsic* _intrinsic; // the library intrinsic being called + LibraryIntrinsic* _intrinsic; // the library intrinsic being called + Node* _result; // the result node, if any + int _reexecute_sp; // the stack pointer when bytecode needs to be reexecuted const TypeOopPtr* sharpen_unsafe_type(Compile::AliasType* alias_type, const TypePtr *adr_type, bool is_native_ptr = false); public: - LibraryCallKit(JVMState* caller, LibraryIntrinsic* intrinsic) - : GraphKit(caller), - _intrinsic(intrinsic) + LibraryCallKit(JVMState* jvms, LibraryIntrinsic* intrinsic) + : GraphKit(jvms), + _intrinsic(intrinsic), + _result(NULL) { + // Check if this is a root compile. In that case we don't have a caller. + if (!jvms->has_method()) { + _reexecute_sp = sp(); + } else { + // Find out how many arguments the interpreter needs when deoptimizing + // and save the stack pointer value so it can used by uncommon_trap. + // We find the argument count by looking at the declared signature. + bool ignored_will_link; + ciSignature* declared_signature = NULL; + ciMethod* ignored_callee = caller()->get_method_at_bci(bci(), ignored_will_link, &declared_signature); + const int nargs = declared_signature->arg_size_for_bc(caller()->java_code_at_bci(bci())); + _reexecute_sp = sp() + nargs; // "push" arguments back on stack + } } + virtual LibraryCallKit* is_LibraryCallKit() const { return (LibraryCallKit*)this; } + ciMethod* caller() const { return jvms()->method(); } int bci() const { return jvms()->bci(); } LibraryIntrinsic* intrinsic() const { return _intrinsic; } vmIntrinsics::ID intrinsic_id() const { return _intrinsic->intrinsic_id(); } ciMethod* callee() const { return _intrinsic->method(); } - ciSignature* signature() const { return callee()->signature(); } - int arg_size() const { return callee()->arg_size(); } bool try_to_inline(); Node* try_to_predicate(); + void push_result() { + // Push the result onto the stack. + if (!stopped() && result() != NULL) { + BasicType bt = result()->bottom_type()->basic_type(); + push_node(bt, result()); + } + } + + private: + void fatal_unexpected_iid(vmIntrinsics::ID iid) { + fatal(err_msg_res("unexpected intrinsic %d: %s", iid, vmIntrinsics::name_at(iid))); + } + + void set_result(Node* n) { assert(_result == NULL, "only set once"); _result = n; } + void set_result(RegionNode* region, PhiNode* value); + Node* result() { return _result; } + + virtual int reexecute_sp() { return _reexecute_sp; } + // Helper functions to inline natives - void push_result(RegionNode* region, PhiNode* value); Node* generate_guard(Node* test, RegionNode* region, float true_prob); Node* generate_slow_guard(Node* test, RegionNode* region); Node* generate_fair_guard(Node* test, RegionNode* region); @@ -108,21 +142,19 @@ class LibraryCallKit : public GraphKit { bool disjoint_bases, const char* &name, bool dest_uninitialized); Node* load_mirror_from_klass(Node* klass); Node* load_klass_from_mirror_common(Node* mirror, bool never_see_null, - int nargs, RegionNode* region, int null_path, int offset); - Node* load_klass_from_mirror(Node* mirror, bool never_see_null, int nargs, + Node* load_klass_from_mirror(Node* mirror, bool never_see_null, RegionNode* region, int null_path) { int offset = java_lang_Class::klass_offset_in_bytes(); - return load_klass_from_mirror_common(mirror, never_see_null, nargs, + return load_klass_from_mirror_common(mirror, never_see_null, region, null_path, offset); } Node* load_array_klass_from_mirror(Node* mirror, bool never_see_null, - int nargs, RegionNode* region, int null_path) { int offset = java_lang_Class::array_klass_offset_in_bytes(); - return load_klass_from_mirror_common(mirror, never_see_null, nargs, + return load_klass_from_mirror_common(mirror, never_see_null, region, null_path, offset); } @@ -161,16 +193,14 @@ class LibraryCallKit : public GraphKit { bool inline_string_indexOf(); Node* string_indexOf(Node* string_object, ciTypeArray* target_array, jint offset, jint cache_i, jint md2_i); bool inline_string_equals(); - Node* pop_math_arg(); + Node* round_double_node(Node* n); bool runtime_math(const TypeFunc* call_type, address funcAddr, const char* funcName); bool inline_math_native(vmIntrinsics::ID id); bool inline_trig(vmIntrinsics::ID id); - bool inline_trans(vmIntrinsics::ID id); - bool inline_abs(vmIntrinsics::ID id); - bool inline_sqrt(vmIntrinsics::ID id); + bool inline_math(vmIntrinsics::ID id); + bool inline_exp(); + bool inline_pow(); void finish_pow_exp(Node* result, Node* x, Node* y, const TypeFunc* call_type, address funcAddr, const char* funcName); - bool inline_pow(vmIntrinsics::ID id); - bool inline_exp(vmIntrinsics::ID id); bool inline_min_max(vmIntrinsics::ID id); Node* generate_min_max(vmIntrinsics::ID id, Node* x, Node* y); // This returns Type::AnyPtr, RawPtr, or OopPtr. @@ -179,7 +209,7 @@ class LibraryCallKit : public GraphKit { // Helper for inline_unsafe_access. // Generates the guards that check whether the result of // Unsafe.getObject should be recorded in an SATB log buffer. - void insert_pre_barrier(Node* base_oop, Node* offset, Node* pre_val, int nargs, bool need_mem_bar); + void insert_pre_barrier(Node* base_oop, Node* offset, Node* pre_val, bool need_mem_bar); bool inline_unsafe_access(bool is_native_ptr, bool is_store, BasicType type, bool is_volatile); bool inline_unsafe_prefetch(bool is_native_ptr, bool is_store, bool is_static); bool inline_unsafe_allocate(); @@ -253,11 +283,7 @@ class LibraryCallKit : public GraphKit { bool inline_unsafe_load_store(BasicType type, LoadStoreKind kind); bool inline_unsafe_ordered_store(BasicType type); bool inline_fp_conversions(vmIntrinsics::ID id); - bool inline_numberOfLeadingZeros(vmIntrinsics::ID id); - bool inline_numberOfTrailingZeros(vmIntrinsics::ID id); - bool inline_bitCount(vmIntrinsics::ID id); - bool inline_reverseBytes(vmIntrinsics::ID id); - + bool inline_number_methods(vmIntrinsics::ID id); bool inline_reference_get(); bool inline_aescrypt_Block(vmIntrinsics::ID id); bool inline_cipherBlockChaining_AESCrypt(vmIntrinsics::ID id); @@ -321,15 +347,18 @@ CallGenerator* Compile::make_vm_intrinsic(ciMethod* m, bool is_virtual) { switch (id) { case vmIntrinsics::_compareTo: if (!SpecialStringCompareTo) return NULL; + if (!Matcher::match_rule_supported(Op_StrComp)) return NULL; break; case vmIntrinsics::_indexOf: if (!SpecialStringIndexOf) return NULL; break; case vmIntrinsics::_equals: if (!SpecialStringEquals) return NULL; + if (!Matcher::match_rule_supported(Op_StrEquals)) return NULL; break; case vmIntrinsics::_equalsC: if (!SpecialArraysEquals) return NULL; + if (!Matcher::match_rule_supported(Op_AryEq)) return NULL; break; case vmIntrinsics::_arraycopy: if (!InlineArrayCopy) return NULL; @@ -382,6 +411,19 @@ CallGenerator* Compile::make_vm_intrinsic(ciMethod* m, bool is_virtual) { if (!Matcher::match_rule_supported(Op_CountTrailingZerosL)) return NULL; break; + case vmIntrinsics::_reverseBytes_c: + if (!Matcher::match_rule_supported(Op_ReverseBytesUS)) return false; + break; + case vmIntrinsics::_reverseBytes_s: + if (!Matcher::match_rule_supported(Op_ReverseBytesS)) return false; + break; + case vmIntrinsics::_reverseBytes_i: + if (!Matcher::match_rule_supported(Op_ReverseBytesI)) return false; + break; + case vmIntrinsics::_reverseBytes_l: + if (!Matcher::match_rule_supported(Op_ReverseBytesL)) return false; + break; + case vmIntrinsics::_Reference_get: // Use the intrinsic version of Reference.get() so that the value in // the referent field can be registered by the G1 pre-barrier code. @@ -488,10 +530,13 @@ JVMState* LibraryIntrinsic::generate(JVMState* jvms) { tty->print_cr("Intrinsic %s", str); } #endif + ciMethod* callee = kit.callee(); + const int bci = kit.bci(); + // Try to inline the intrinsic. if (kit.try_to_inline()) { if (PrintIntrinsics || PrintInlining NOT_PRODUCT( || PrintOptoInlining) ) { - CompileTask::print_inlining(kit.callee(), jvms->depth() - 1, kit.bci(), is_virtual() ? "(intrinsic, virtual)" : "(intrinsic)"); + CompileTask::print_inlining(callee, jvms->depth() - 1, bci, is_virtual() ? "(intrinsic, virtual)" : "(intrinsic)"); } C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_worked); if (C->log()) { @@ -500,6 +545,8 @@ JVMState* LibraryIntrinsic::generate(JVMState* jvms) { (is_virtual() ? " virtual='1'" : ""), C->unique() - nodes); } + // Push the result from the inlined method onto the stack. + kit.push_result(); return kit.transfer_exceptions_into_jvms(); } @@ -508,12 +555,12 @@ JVMState* LibraryIntrinsic::generate(JVMState* jvms) { if (jvms->has_method()) { // Not a root compile. const char* msg = is_virtual() ? "failed to inline (intrinsic, virtual)" : "failed to inline (intrinsic)"; - CompileTask::print_inlining(kit.callee(), jvms->depth() - 1, kit.bci(), msg); + CompileTask::print_inlining(callee, jvms->depth() - 1, bci, msg); } else { // Root compile tty->print("Did not generate intrinsic %s%s at bci:%d in", vmIntrinsics::name_at(intrinsic_id()), - (is_virtual() ? " (virtual)" : ""), kit.bci()); + (is_virtual() ? " (virtual)" : ""), bci); } } C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_failed); @@ -532,9 +579,15 @@ Node* LibraryIntrinsic::generate_predicate(JVMState* jvms) { tty->print_cr("Predicate for intrinsic %s", str); } #endif + ciMethod* callee = kit.callee(); + const int bci = kit.bci(); Node* slow_ctl = kit.try_to_predicate(); if (!kit.failing()) { + if (PrintIntrinsics || PrintInlining NOT_PRODUCT( || PrintOptoInlining) ) { + CompileTask::print_inlining(callee, jvms->depth() - 1, bci, is_virtual() ? "(intrinsic, virtual)" : "(intrinsic)"); + } + C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_worked); if (C->log()) { C->log()->elem("predicate_intrinsic id='%s'%s nodes='%d'", vmIntrinsics::name_at(intrinsic_id()), @@ -549,12 +602,12 @@ Node* LibraryIntrinsic::generate_predicate(JVMState* jvms) { if (jvms->has_method()) { // Not a root compile. const char* msg = "failed to generate predicate for intrinsic"; - CompileTask::print_inlining(kit.callee(), jvms->depth() - 1, kit.bci(), msg); + CompileTask::print_inlining(kit.callee(), jvms->depth() - 1, bci, msg); } else { // Root compile tty->print("Did not generate predicate for intrinsic %s%s at bci:%d in", vmIntrinsics::name_at(intrinsic_id()), - (is_virtual() ? " (virtual)" : ""), kit.bci()); + (is_virtual() ? " (virtual)" : ""), bci); } } C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_failed); @@ -566,6 +619,7 @@ bool LibraryCallKit::try_to_inline() { const bool is_store = true; const bool is_native_ptr = true; const bool is_static = true; + const bool is_volatile = true; if (!jvms()->has_method()) { // Root JVMState has a null method. @@ -575,13 +629,11 @@ bool LibraryCallKit::try_to_inline() { } assert(merged_memory(), ""); + switch (intrinsic_id()) { - case vmIntrinsics::_hashCode: - return inline_native_hashcode(intrinsic()->is_virtual(), !is_static); - case vmIntrinsics::_identityHashCode: - return inline_native_hashcode(/*!virtual*/ false, is_static); - case vmIntrinsics::_getClass: - return inline_native_getClass(); + case vmIntrinsics::_hashCode: return inline_native_hashcode(intrinsic()->is_virtual(), !is_static); + case vmIntrinsics::_identityHashCode: return inline_native_hashcode(/*!virtual*/ false, is_static); + case vmIntrinsics::_getClass: return inline_native_getClass(); case vmIntrinsics::_dsin: case vmIntrinsics::_dcos: @@ -592,203 +644,114 @@ bool LibraryCallKit::try_to_inline() { case vmIntrinsics::_dexp: case vmIntrinsics::_dlog: case vmIntrinsics::_dlog10: - case vmIntrinsics::_dpow: - return inline_math_native(intrinsic_id()); + case vmIntrinsics::_dpow: return inline_math_native(intrinsic_id()); case vmIntrinsics::_min: - case vmIntrinsics::_max: - return inline_min_max(intrinsic_id()); + case vmIntrinsics::_max: return inline_min_max(intrinsic_id()); - case vmIntrinsics::_arraycopy: - return inline_arraycopy(); + case vmIntrinsics::_arraycopy: return inline_arraycopy(); - case vmIntrinsics::_compareTo: - return inline_string_compareTo(); - case vmIntrinsics::_indexOf: - return inline_string_indexOf(); - case vmIntrinsics::_equals: - return inline_string_equals(); + case vmIntrinsics::_compareTo: return inline_string_compareTo(); + case vmIntrinsics::_indexOf: return inline_string_indexOf(); + case vmIntrinsics::_equals: return inline_string_equals(); - case vmIntrinsics::_getObject: - return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, false); - case vmIntrinsics::_getBoolean: - return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, false); - case vmIntrinsics::_getByte: - return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, false); - case vmIntrinsics::_getShort: - return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, false); - case vmIntrinsics::_getChar: - return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, false); - case vmIntrinsics::_getInt: - return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, false); - case vmIntrinsics::_getLong: - return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, false); - case vmIntrinsics::_getFloat: - return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, false); - case vmIntrinsics::_getDouble: - return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE, false); + case vmIntrinsics::_getObject: return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, !is_volatile); + case vmIntrinsics::_getBoolean: return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, !is_volatile); + case vmIntrinsics::_getByte: return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, !is_volatile); + case vmIntrinsics::_getShort: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, !is_volatile); + case vmIntrinsics::_getChar: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, !is_volatile); + case vmIntrinsics::_getInt: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, !is_volatile); + case vmIntrinsics::_getLong: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, !is_volatile); + case vmIntrinsics::_getFloat: return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, !is_volatile); + case vmIntrinsics::_getDouble: return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE, !is_volatile); - case vmIntrinsics::_putObject: - return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, false); - case vmIntrinsics::_putBoolean: - return inline_unsafe_access(!is_native_ptr, is_store, T_BOOLEAN, false); - case vmIntrinsics::_putByte: - return inline_unsafe_access(!is_native_ptr, is_store, T_BYTE, false); - case vmIntrinsics::_putShort: - return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, false); - case vmIntrinsics::_putChar: - return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, false); - case vmIntrinsics::_putInt: - return inline_unsafe_access(!is_native_ptr, is_store, T_INT, false); - case vmIntrinsics::_putLong: - return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, false); - case vmIntrinsics::_putFloat: - return inline_unsafe_access(!is_native_ptr, is_store, T_FLOAT, false); - case vmIntrinsics::_putDouble: - return inline_unsafe_access(!is_native_ptr, is_store, T_DOUBLE, false); + case vmIntrinsics::_putObject: return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, !is_volatile); + case vmIntrinsics::_putBoolean: return inline_unsafe_access(!is_native_ptr, is_store, T_BOOLEAN, !is_volatile); + case vmIntrinsics::_putByte: return inline_unsafe_access(!is_native_ptr, is_store, T_BYTE, !is_volatile); + case vmIntrinsics::_putShort: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, !is_volatile); + case vmIntrinsics::_putChar: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, !is_volatile); + case vmIntrinsics::_putInt: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, !is_volatile); + case vmIntrinsics::_putLong: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, !is_volatile); + case vmIntrinsics::_putFloat: return inline_unsafe_access(!is_native_ptr, is_store, T_FLOAT, !is_volatile); + case vmIntrinsics::_putDouble: return inline_unsafe_access(!is_native_ptr, is_store, T_DOUBLE, !is_volatile); - case vmIntrinsics::_getByte_raw: - return inline_unsafe_access(is_native_ptr, !is_store, T_BYTE, false); - case vmIntrinsics::_getShort_raw: - return inline_unsafe_access(is_native_ptr, !is_store, T_SHORT, false); - case vmIntrinsics::_getChar_raw: - return inline_unsafe_access(is_native_ptr, !is_store, T_CHAR, false); - case vmIntrinsics::_getInt_raw: - return inline_unsafe_access(is_native_ptr, !is_store, T_INT, false); - case vmIntrinsics::_getLong_raw: - return inline_unsafe_access(is_native_ptr, !is_store, T_LONG, false); - case vmIntrinsics::_getFloat_raw: - return inline_unsafe_access(is_native_ptr, !is_store, T_FLOAT, false); - case vmIntrinsics::_getDouble_raw: - return inline_unsafe_access(is_native_ptr, !is_store, T_DOUBLE, false); - case vmIntrinsics::_getAddress_raw: - return inline_unsafe_access(is_native_ptr, !is_store, T_ADDRESS, false); + case vmIntrinsics::_getByte_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_BYTE, !is_volatile); + case vmIntrinsics::_getShort_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_SHORT, !is_volatile); + case vmIntrinsics::_getChar_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_CHAR, !is_volatile); + case vmIntrinsics::_getInt_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_INT, !is_volatile); + case vmIntrinsics::_getLong_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_LONG, !is_volatile); + case vmIntrinsics::_getFloat_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_FLOAT, !is_volatile); + case vmIntrinsics::_getDouble_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_DOUBLE, !is_volatile); + case vmIntrinsics::_getAddress_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_ADDRESS, !is_volatile); - case vmIntrinsics::_putByte_raw: - return inline_unsafe_access(is_native_ptr, is_store, T_BYTE, false); - case vmIntrinsics::_putShort_raw: - return inline_unsafe_access(is_native_ptr, is_store, T_SHORT, false); - case vmIntrinsics::_putChar_raw: - return inline_unsafe_access(is_native_ptr, is_store, T_CHAR, false); - case vmIntrinsics::_putInt_raw: - return inline_unsafe_access(is_native_ptr, is_store, T_INT, false); - case vmIntrinsics::_putLong_raw: - return inline_unsafe_access(is_native_ptr, is_store, T_LONG, false); - case vmIntrinsics::_putFloat_raw: - return inline_unsafe_access(is_native_ptr, is_store, T_FLOAT, false); - case vmIntrinsics::_putDouble_raw: - return inline_unsafe_access(is_native_ptr, is_store, T_DOUBLE, false); - case vmIntrinsics::_putAddress_raw: - return inline_unsafe_access(is_native_ptr, is_store, T_ADDRESS, false); + case vmIntrinsics::_putByte_raw: return inline_unsafe_access( is_native_ptr, is_store, T_BYTE, !is_volatile); + case vmIntrinsics::_putShort_raw: return inline_unsafe_access( is_native_ptr, is_store, T_SHORT, !is_volatile); + case vmIntrinsics::_putChar_raw: return inline_unsafe_access( is_native_ptr, is_store, T_CHAR, !is_volatile); + case vmIntrinsics::_putInt_raw: return inline_unsafe_access( is_native_ptr, is_store, T_INT, !is_volatile); + case vmIntrinsics::_putLong_raw: return inline_unsafe_access( is_native_ptr, is_store, T_LONG, !is_volatile); + case vmIntrinsics::_putFloat_raw: return inline_unsafe_access( is_native_ptr, is_store, T_FLOAT, !is_volatile); + case vmIntrinsics::_putDouble_raw: return inline_unsafe_access( is_native_ptr, is_store, T_DOUBLE, !is_volatile); + case vmIntrinsics::_putAddress_raw: return inline_unsafe_access( is_native_ptr, is_store, T_ADDRESS, !is_volatile); - case vmIntrinsics::_getObjectVolatile: - return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, true); - case vmIntrinsics::_getBooleanVolatile: - return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, true); - case vmIntrinsics::_getByteVolatile: - return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, true); - case vmIntrinsics::_getShortVolatile: - return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, true); - case vmIntrinsics::_getCharVolatile: - return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, true); - case vmIntrinsics::_getIntVolatile: - return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, true); - case vmIntrinsics::_getLongVolatile: - return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, true); - case vmIntrinsics::_getFloatVolatile: - return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, true); - case vmIntrinsics::_getDoubleVolatile: - return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE, true); + case vmIntrinsics::_getObjectVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, is_volatile); + case vmIntrinsics::_getBooleanVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, is_volatile); + case vmIntrinsics::_getByteVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, is_volatile); + case vmIntrinsics::_getShortVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, is_volatile); + case vmIntrinsics::_getCharVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, is_volatile); + case vmIntrinsics::_getIntVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, is_volatile); + case vmIntrinsics::_getLongVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, is_volatile); + case vmIntrinsics::_getFloatVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, is_volatile); + case vmIntrinsics::_getDoubleVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE, is_volatile); - case vmIntrinsics::_putObjectVolatile: - return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, true); - case vmIntrinsics::_putBooleanVolatile: - return inline_unsafe_access(!is_native_ptr, is_store, T_BOOLEAN, true); - case vmIntrinsics::_putByteVolatile: - return inline_unsafe_access(!is_native_ptr, is_store, T_BYTE, true); - case vmIntrinsics::_putShortVolatile: - return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, true); - case vmIntrinsics::_putCharVolatile: - return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, true); - case vmIntrinsics::_putIntVolatile: - return inline_unsafe_access(!is_native_ptr, is_store, T_INT, true); - case vmIntrinsics::_putLongVolatile: - return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, true); - case vmIntrinsics::_putFloatVolatile: - return inline_unsafe_access(!is_native_ptr, is_store, T_FLOAT, true); - case vmIntrinsics::_putDoubleVolatile: - return inline_unsafe_access(!is_native_ptr, is_store, T_DOUBLE, true); + case vmIntrinsics::_putObjectVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, is_volatile); + case vmIntrinsics::_putBooleanVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_BOOLEAN, is_volatile); + case vmIntrinsics::_putByteVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_BYTE, is_volatile); + case vmIntrinsics::_putShortVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, is_volatile); + case vmIntrinsics::_putCharVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, is_volatile); + case vmIntrinsics::_putIntVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, is_volatile); + case vmIntrinsics::_putLongVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, is_volatile); + case vmIntrinsics::_putFloatVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_FLOAT, is_volatile); + case vmIntrinsics::_putDoubleVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_DOUBLE, is_volatile); - case vmIntrinsics::_prefetchRead: - return inline_unsafe_prefetch(!is_native_ptr, !is_store, !is_static); - case vmIntrinsics::_prefetchWrite: - return inline_unsafe_prefetch(!is_native_ptr, is_store, !is_static); - case vmIntrinsics::_prefetchReadStatic: - return inline_unsafe_prefetch(!is_native_ptr, !is_store, is_static); - case vmIntrinsics::_prefetchWriteStatic: - return inline_unsafe_prefetch(!is_native_ptr, is_store, is_static); + case vmIntrinsics::_prefetchRead: return inline_unsafe_prefetch(!is_native_ptr, !is_store, !is_static); + case vmIntrinsics::_prefetchWrite: return inline_unsafe_prefetch(!is_native_ptr, is_store, !is_static); + case vmIntrinsics::_prefetchReadStatic: return inline_unsafe_prefetch(!is_native_ptr, !is_store, is_static); + case vmIntrinsics::_prefetchWriteStatic: return inline_unsafe_prefetch(!is_native_ptr, is_store, is_static); - case vmIntrinsics::_compareAndSwapObject: - return inline_unsafe_load_store(T_OBJECT, LS_cmpxchg); - case vmIntrinsics::_compareAndSwapInt: - return inline_unsafe_load_store(T_INT, LS_cmpxchg); - case vmIntrinsics::_compareAndSwapLong: - return inline_unsafe_load_store(T_LONG, LS_cmpxchg); + case vmIntrinsics::_compareAndSwapObject: return inline_unsafe_load_store(T_OBJECT, LS_cmpxchg); + case vmIntrinsics::_compareAndSwapInt: return inline_unsafe_load_store(T_INT, LS_cmpxchg); + case vmIntrinsics::_compareAndSwapLong: return inline_unsafe_load_store(T_LONG, LS_cmpxchg); - case vmIntrinsics::_putOrderedObject: - return inline_unsafe_ordered_store(T_OBJECT); - case vmIntrinsics::_putOrderedInt: - return inline_unsafe_ordered_store(T_INT); - case vmIntrinsics::_putOrderedLong: - return inline_unsafe_ordered_store(T_LONG); + case vmIntrinsics::_putOrderedObject: return inline_unsafe_ordered_store(T_OBJECT); + case vmIntrinsics::_putOrderedInt: return inline_unsafe_ordered_store(T_INT); + case vmIntrinsics::_putOrderedLong: return inline_unsafe_ordered_store(T_LONG); - case vmIntrinsics::_getAndAddInt: - return inline_unsafe_load_store(T_INT, LS_xadd); - case vmIntrinsics::_getAndAddLong: - return inline_unsafe_load_store(T_LONG, LS_xadd); - case vmIntrinsics::_getAndSetInt: - return inline_unsafe_load_store(T_INT, LS_xchg); - case vmIntrinsics::_getAndSetLong: - return inline_unsafe_load_store(T_LONG, LS_xchg); - case vmIntrinsics::_getAndSetObject: - return inline_unsafe_load_store(T_OBJECT, LS_xchg); + case vmIntrinsics::_getAndAddInt: return inline_unsafe_load_store(T_INT, LS_xadd); + case vmIntrinsics::_getAndAddLong: return inline_unsafe_load_store(T_LONG, LS_xadd); + case vmIntrinsics::_getAndSetInt: return inline_unsafe_load_store(T_INT, LS_xchg); + case vmIntrinsics::_getAndSetLong: return inline_unsafe_load_store(T_LONG, LS_xchg); + case vmIntrinsics::_getAndSetObject: return inline_unsafe_load_store(T_OBJECT, LS_xchg); - case vmIntrinsics::_currentThread: - return inline_native_currentThread(); - case vmIntrinsics::_isInterrupted: - return inline_native_isInterrupted(); + case vmIntrinsics::_currentThread: return inline_native_currentThread(); + case vmIntrinsics::_isInterrupted: return inline_native_isInterrupted(); #ifdef TRACE_HAVE_INTRINSICS - case vmIntrinsics::_classID: - return inline_native_classID(); - case vmIntrinsics::_threadID: - return inline_native_threadID(); - case vmIntrinsics::_counterTime: - return inline_native_time_funcs(CAST_FROM_FN_PTR(address, TRACE_TIME_METHOD), "counterTime"); + case vmIntrinsics::_classID: return inline_native_classID(); + case vmIntrinsics::_threadID: return inline_native_threadID(); + case vmIntrinsics::_counterTime: return inline_native_time_funcs(CAST_FROM_FN_PTR(address, TRACE_TIME_METHOD), "counterTime"); #endif - case vmIntrinsics::_currentTimeMillis: - return inline_native_time_funcs(CAST_FROM_FN_PTR(address, os::javaTimeMillis), "currentTimeMillis"); - case vmIntrinsics::_nanoTime: - return inline_native_time_funcs(CAST_FROM_FN_PTR(address, os::javaTimeNanos), "nanoTime"); - case vmIntrinsics::_allocateInstance: - return inline_unsafe_allocate(); - case vmIntrinsics::_copyMemory: - return inline_unsafe_copyMemory(); - case vmIntrinsics::_newArray: - return inline_native_newArray(); - case vmIntrinsics::_getLength: - return inline_native_getLength(); - case vmIntrinsics::_copyOf: - return inline_array_copyOf(false); - case vmIntrinsics::_copyOfRange: - return inline_array_copyOf(true); - case vmIntrinsics::_equalsC: - return inline_array_equals(); - case vmIntrinsics::_clone: - return inline_native_clone(intrinsic()->is_virtual()); + case vmIntrinsics::_currentTimeMillis: return inline_native_time_funcs(CAST_FROM_FN_PTR(address, os::javaTimeMillis), "currentTimeMillis"); + case vmIntrinsics::_nanoTime: return inline_native_time_funcs(CAST_FROM_FN_PTR(address, os::javaTimeNanos), "nanoTime"); + case vmIntrinsics::_allocateInstance: return inline_unsafe_allocate(); + case vmIntrinsics::_copyMemory: return inline_unsafe_copyMemory(); + case vmIntrinsics::_newArray: return inline_native_newArray(); + case vmIntrinsics::_getLength: return inline_native_getLength(); + case vmIntrinsics::_copyOf: return inline_array_copyOf(false); + case vmIntrinsics::_copyOfRange: return inline_array_copyOf(true); + case vmIntrinsics::_equalsC: return inline_array_equals(); + case vmIntrinsics::_clone: return inline_native_clone(intrinsic()->is_virtual()); - case vmIntrinsics::_isAssignableFrom: - return inline_native_subtype_check(); + case vmIntrinsics::_isAssignableFrom: return inline_native_subtype_check(); case vmIntrinsics::_isInstance: case vmIntrinsics::_getModifiers: @@ -797,44 +760,32 @@ bool LibraryCallKit::try_to_inline() { case vmIntrinsics::_isPrimitive: case vmIntrinsics::_getSuperclass: case vmIntrinsics::_getComponentType: - case vmIntrinsics::_getClassAccessFlags: - return inline_native_Class_query(intrinsic_id()); + case vmIntrinsics::_getClassAccessFlags: return inline_native_Class_query(intrinsic_id()); case vmIntrinsics::_floatToRawIntBits: case vmIntrinsics::_floatToIntBits: case vmIntrinsics::_intBitsToFloat: case vmIntrinsics::_doubleToRawLongBits: case vmIntrinsics::_doubleToLongBits: - case vmIntrinsics::_longBitsToDouble: - return inline_fp_conversions(intrinsic_id()); + case vmIntrinsics::_longBitsToDouble: return inline_fp_conversions(intrinsic_id()); case vmIntrinsics::_numberOfLeadingZeros_i: case vmIntrinsics::_numberOfLeadingZeros_l: - return inline_numberOfLeadingZeros(intrinsic_id()); - case vmIntrinsics::_numberOfTrailingZeros_i: case vmIntrinsics::_numberOfTrailingZeros_l: - return inline_numberOfTrailingZeros(intrinsic_id()); - case vmIntrinsics::_bitCount_i: case vmIntrinsics::_bitCount_l: - return inline_bitCount(intrinsic_id()); - case vmIntrinsics::_reverseBytes_i: case vmIntrinsics::_reverseBytes_l: case vmIntrinsics::_reverseBytes_s: - case vmIntrinsics::_reverseBytes_c: - return inline_reverseBytes((vmIntrinsics::ID) intrinsic_id()); + case vmIntrinsics::_reverseBytes_c: return inline_number_methods(intrinsic_id()); - case vmIntrinsics::_getCallerClass: - return inline_native_Reflection_getCallerClass(); + case vmIntrinsics::_getCallerClass: return inline_native_Reflection_getCallerClass(); - case vmIntrinsics::_Reference_get: - return inline_reference_get(); + case vmIntrinsics::_Reference_get: return inline_reference_get(); case vmIntrinsics::_aescrypt_encryptBlock: - case vmIntrinsics::_aescrypt_decryptBlock: - return inline_aescrypt_Block(intrinsic_id()); + case vmIntrinsics::_aescrypt_decryptBlock: return inline_aescrypt_Block(intrinsic_id()); case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt: case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt: @@ -883,13 +834,13 @@ Node* LibraryCallKit::try_to_predicate() { } } -//------------------------------push_result------------------------------ +//------------------------------set_result------------------------------- // Helper function for finishing intrinsics. -void LibraryCallKit::push_result(RegionNode* region, PhiNode* value) { +void LibraryCallKit::set_result(RegionNode* region, PhiNode* value) { record_for_igvn(region); set_control(_gvn.transform(region)); - BasicType value_type = value->type()->basic_type(); - push_node(value_type, _gvn.transform(value)); + set_result( _gvn.transform(value)); + assert(value->type()->basic_type() == result()->bottom_type()->basic_type(), "sanity"); } //------------------------------generate_guard--------------------------- @@ -1078,7 +1029,6 @@ Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1, Node* str2 // to Int nodes containing the lenghts of str1 and str2. // Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1_start, Node* cnt1, Node* str2_start, Node* cnt2) { - Node* result = NULL; switch (opcode) { case Op_StrIndexOf: @@ -1105,51 +1055,23 @@ Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1_start, Node } //------------------------------inline_string_compareTo------------------------ +// public int java.lang.String.compareTo(String anotherString); bool LibraryCallKit::inline_string_compareTo() { - - if (!Matcher::has_match_rule(Op_StrComp)) return false; - - _sp += 2; - Node *argument = pop(); // pop non-receiver first: it was pushed second - Node *receiver = pop(); - - // Null check on self without removing any arguments. The argument - // null check technically happens in the wrong place, which can lead to - // invalid stack traces when string compare is inlined into a method - // which handles NullPointerExceptions. - _sp += 2; - receiver = do_null_check(receiver, T_OBJECT); - argument = do_null_check(argument, T_OBJECT); - _sp -= 2; + Node* receiver = null_check(argument(0)); + Node* arg = null_check(argument(1)); if (stopped()) { return true; } - - Node* compare = make_string_method_node(Op_StrComp, receiver, argument); - push(compare); + set_result(make_string_method_node(Op_StrComp, receiver, arg)); return true; } //------------------------------inline_string_equals------------------------ bool LibraryCallKit::inline_string_equals() { - - if (!Matcher::has_match_rule(Op_StrEquals)) return false; - - int nargs = 2; - _sp += nargs; - Node* argument = pop(); // pop non-receiver first: it was pushed second - Node* receiver = pop(); - - // Null check on self without removing any arguments. The argument - // null check technically happens in the wrong place, which can lead to - // invalid stack traces when string compare is inlined into a method - // which handles NullPointerExceptions. - _sp += nargs; - receiver = do_null_check(receiver, T_OBJECT); - //should not do null check for argument for String.equals(), because spec - //allows to specify NULL as argument. - _sp -= nargs; - + Node* receiver = null_check_receiver(); + // NOTE: Do not null check argument for String.equals() because spec + // allows to specify NULL as argument. + Node* argument = this->argument(1); if (stopped()) { return true; } @@ -1173,9 +1095,7 @@ bool LibraryCallKit::inline_string_equals() { ciInstanceKlass* klass = env()->String_klass(); if (!stopped()) { - _sp += nargs; // gen_instanceof might do an uncommon trap Node* inst = gen_instanceof(argument, makecon(TypeKlassPtr::make(klass))); - _sp -= nargs; Node* cmp = _gvn.transform(new (C) CmpINode(inst, intcon(1))); Node* bol = _gvn.transform(new (C) BoolNode(cmp, BoolTest::ne)); @@ -1207,7 +1127,7 @@ bool LibraryCallKit::inline_string_equals() { Node* receiver_cnt = load_String_length(no_ctrl, receiver); // Get start addr of argument - Node* argument_val = load_String_value(no_ctrl, argument); + Node* argument_val = load_String_value(no_ctrl, argument); Node* argument_offset = load_String_offset(no_ctrl, argument); Node* argument_start = array_element_address(argument_val, argument_offset, T_CHAR); @@ -1236,24 +1156,15 @@ bool LibraryCallKit::inline_string_equals() { set_control(_gvn.transform(region)); record_for_igvn(region); - push(_gvn.transform(phi)); - + set_result(_gvn.transform(phi)); return true; } //------------------------------inline_array_equals---------------------------- bool LibraryCallKit::inline_array_equals() { - - if (!Matcher::has_match_rule(Op_AryEq)) return false; - - _sp += 2; - Node *argument2 = pop(); - Node *argument1 = pop(); - - Node* equals = - _gvn.transform(new (C) AryEqNode(control(), memory(TypeAryPtr::CHARS), - argument1, argument2) ); - push(equals); + Node* arg1 = argument(0); + Node* arg2 = argument(1); + set_result(_gvn.transform(new (C) AryEqNode(control(), memory(TypeAryPtr::CHARS), arg1, arg2))); return true; } @@ -1325,7 +1236,7 @@ Node* LibraryCallKit::string_indexOf(Node* string_object, ciTypeArray* target_ar float likely = PROB_LIKELY(0.9); float unlikely = PROB_UNLIKELY(0.9); - const int nargs = 2; // number of arguments to push back for uncommon trap in predicate + const int nargs = 0; // no arguments to push back for uncommon trap in predicate Node* source = load_String_value(no_ctrl, string_object); Node* sourceOffset = load_String_offset(no_ctrl, string_object); @@ -1396,10 +1307,8 @@ Node* LibraryCallKit::string_indexOf(Node* string_object, ciTypeArray* target_ar //------------------------------inline_string_indexOf------------------------ bool LibraryCallKit::inline_string_indexOf() { - - _sp += 2; - Node *argument = pop(); // pop non-receiver first: it was pushed second - Node *receiver = pop(); + Node* receiver = argument(0); + Node* arg = argument(1); Node* result; // Disable the use of pcmpestri until it can be guaranteed that @@ -1409,15 +1318,8 @@ bool LibraryCallKit::inline_string_indexOf() { // Generate SSE4.2 version of indexOf // We currently only have match rules that use SSE4.2 - // Null check on self without removing any arguments. The argument - // null check technically happens in the wrong place, which can lead to - // invalid stack traces when string compare is inlined into a method - // which handles NullPointerExceptions. - _sp += 2; - receiver = do_null_check(receiver, T_OBJECT); - argument = do_null_check(argument, T_OBJECT); - _sp -= 2; - + receiver = null_check(receiver); + arg = null_check(arg); if (stopped()) { return true; } @@ -1439,12 +1341,12 @@ bool LibraryCallKit::inline_string_indexOf() { Node* source_cnt = load_String_length(no_ctrl, receiver); // Get start addr of substring - Node* substr = load_String_value(no_ctrl, argument); - Node* substr_offset = load_String_offset(no_ctrl, argument); + Node* substr = load_String_value(no_ctrl, arg); + Node* substr_offset = load_String_offset(no_ctrl, arg); Node* substr_start = array_element_address(substr, substr_offset, T_CHAR); // Get length of source string - Node* substr_cnt = load_String_length(no_ctrl, argument); + Node* substr_cnt = load_String_length(no_ctrl, arg); // Check for substr count > string count Node* cmp = _gvn.transform( new(C) CmpINode(substr_cnt, source_cnt) ); @@ -1477,10 +1379,10 @@ bool LibraryCallKit::inline_string_indexOf() { } else { // Use LibraryCallKit::string_indexOf // don't intrinsify if argument isn't a constant string. - if (!argument->is_Con()) { + if (!arg->is_Con()) { return false; } - const TypeOopPtr* str_type = _gvn.type(argument)->isa_oopptr(); + const TypeOopPtr* str_type = _gvn.type(arg)->isa_oopptr(); if (str_type == NULL) { return false; } @@ -1511,21 +1413,15 @@ bool LibraryCallKit::inline_string_indexOf() { return false; } - // Null check on self without removing any arguments. The argument - // null check technically happens in the wrong place, which can lead to - // invalid stack traces when string compare is inlined into a method - // which handles NullPointerExceptions. - _sp += 2; - receiver = do_null_check(receiver, T_OBJECT); - // No null check on the argument is needed since it's a constant String oop. - _sp -= 2; + receiver = null_check(receiver, T_OBJECT); + // NOTE: No null check on the argument is needed since it's a constant String oop. if (stopped()) { return true; } // The null string as a pattern always returns 0 (match at beginning of string) if (c == 0) { - push(intcon(0)); + set_result(intcon(0)); return true; } @@ -1548,47 +1444,54 @@ bool LibraryCallKit::inline_string_indexOf() { result = string_indexOf(receiver, pat, o, cache, md2); } - - push(result); + set_result(result); return true; } -//--------------------------pop_math_arg-------------------------------- -// Pop a double argument to a math function from the stack -// rounding it if necessary. -Node * LibraryCallKit::pop_math_arg() { - Node *arg = pop_pair(); - if( Matcher::strict_fp_requires_explicit_rounding && UseSSE<=1 ) - arg = _gvn.transform( new (C) RoundDoubleNode(0, arg) ); - return arg; +//--------------------------round_double_node-------------------------------- +// Round a double node if necessary. +Node* LibraryCallKit::round_double_node(Node* n) { + if (Matcher::strict_fp_requires_explicit_rounding && UseSSE <= 1) + n = _gvn.transform(new (C) RoundDoubleNode(0, n)); + return n; +} + +//------------------------------inline_math----------------------------------- +// public static double Math.abs(double) +// public static double Math.sqrt(double) +// public static double Math.log(double) +// public static double Math.log10(double) +bool LibraryCallKit::inline_math(vmIntrinsics::ID id) { + Node* arg = round_double_node(argument(0)); + Node* n; + switch (id) { + case vmIntrinsics::_dabs: n = new (C) AbsDNode( arg); break; + case vmIntrinsics::_dsqrt: n = new (C) SqrtDNode(0, arg); break; + case vmIntrinsics::_dlog: n = new (C) LogDNode( arg); break; + case vmIntrinsics::_dlog10: n = new (C) Log10DNode( arg); break; + default: fatal_unexpected_iid(id); break; + } + set_result(_gvn.transform(n)); + return true; } //------------------------------inline_trig---------------------------------- // Inline sin/cos/tan instructions, if possible. If rounding is required, do // argument reduction which will turn into a fast/slow diamond. bool LibraryCallKit::inline_trig(vmIntrinsics::ID id) { - _sp += arg_size(); // restore stack pointer - Node* arg = pop_math_arg(); - Node* trig = NULL; + Node* arg = round_double_node(argument(0)); + Node* n = NULL; switch (id) { - case vmIntrinsics::_dsin: - trig = _gvn.transform((Node*)new (C) SinDNode(arg)); - break; - case vmIntrinsics::_dcos: - trig = _gvn.transform((Node*)new (C) CosDNode(arg)); - break; - case vmIntrinsics::_dtan: - trig = _gvn.transform((Node*)new (C) TanDNode(arg)); - break; - default: - assert(false, "bad intrinsic was passed in"); - return false; + case vmIntrinsics::_dsin: n = new (C) SinDNode(arg); break; + case vmIntrinsics::_dcos: n = new (C) CosDNode(arg); break; + case vmIntrinsics::_dtan: n = new (C) TanDNode(arg); break; + default: fatal_unexpected_iid(id); break; } + n = _gvn.transform(n); // Rounding required? Check for argument reduction! - if( Matcher::strict_fp_requires_explicit_rounding ) { - + if (Matcher::strict_fp_requires_explicit_rounding) { static const double pi_4 = 0.7853981633974483; static const double neg_pi_4 = -0.7853981633974483; // pi/2 in 80-bit extended precision @@ -1623,8 +1526,8 @@ bool LibraryCallKit::inline_trig(vmIntrinsics::ID id) { // probably do the math inside the SIN encoding. // Make the merge point - RegionNode *r = new (C) RegionNode(3); - Node *phi = new (C) PhiNode(r,Type::DOUBLE); + RegionNode* r = new (C) RegionNode(3); + Node* phi = new (C) PhiNode(r, Type::DOUBLE); // Flatten arg so we need only 1 test Node *abs = _gvn.transform(new (C) AbsDNode(arg)); @@ -1639,7 +1542,7 @@ bool LibraryCallKit::inline_trig(vmIntrinsics::ID id) { set_control(opt_iff(r,iff)); // Set fast path result - phi->init_req(2,trig); + phi->init_req(2, n); // Slow path - non-blocking leaf call Node* call = NULL; @@ -1661,37 +1564,18 @@ bool LibraryCallKit::inline_trig(vmIntrinsics::ID id) { break; } assert(control()->in(0) == call, ""); - Node* slow_result = _gvn.transform(new (C) ProjNode(call,TypeFunc::Parms)); - r->init_req(1,control()); - phi->init_req(1,slow_result); + Node* slow_result = _gvn.transform(new (C) ProjNode(call, TypeFunc::Parms)); + r->init_req(1, control()); + phi->init_req(1, slow_result); // Post-merge set_control(_gvn.transform(r)); record_for_igvn(r); - trig = _gvn.transform(phi); + n = _gvn.transform(phi); C->set_has_split_ifs(true); // Has chance for split-if optimization } - // Push result back on JVM stack - push_pair(trig); - return true; -} - -//------------------------------inline_sqrt------------------------------------- -// Inline square root instruction, if possible. -bool LibraryCallKit::inline_sqrt(vmIntrinsics::ID id) { - assert(id == vmIntrinsics::_dsqrt, "Not square root"); - _sp += arg_size(); // restore stack pointer - push_pair(_gvn.transform(new (C) SqrtDNode(0, pop_math_arg()))); - return true; -} - -//------------------------------inline_abs------------------------------------- -// Inline absolute value instruction, if possible. -bool LibraryCallKit::inline_abs(vmIntrinsics::ID id) { - assert(id == vmIntrinsics::_dabs, "Not absolute value"); - _sp += arg_size(); // restore stack pointer - push_pair(_gvn.transform(new (C) AbsDNode(pop_math_arg()))); + set_result(n); return true; } @@ -1700,24 +1584,18 @@ void LibraryCallKit::finish_pow_exp(Node* result, Node* x, Node* y, const TypeFu //result=(result.isNaN())? funcAddr():result; // Check: If isNaN() by checking result!=result? then either trap // or go to runtime - Node* cmpisnan = _gvn.transform(new (C) CmpDNode(result,result)); + Node* cmpisnan = _gvn.transform(new (C) CmpDNode(result, result)); // Build the boolean node - Node* bolisnum = _gvn.transform( new (C) BoolNode(cmpisnan, BoolTest::eq) ); + Node* bolisnum = _gvn.transform(new (C) BoolNode(cmpisnan, BoolTest::eq)); if (!too_many_traps(Deoptimization::Reason_intrinsic)) { - { - BuildCutout unless(this, bolisnum, PROB_STATIC_FREQUENT); - // End the current control-flow path - push_pair(x); - if (y != NULL) { - push_pair(y); - } + { BuildCutout unless(this, bolisnum, PROB_STATIC_FREQUENT); // The pow or exp intrinsic returned a NaN, which requires a call // to the runtime. Recompile with the runtime call. uncommon_trap(Deoptimization::Reason_intrinsic, Deoptimization::Action_make_not_entrant); } - push_pair(result); + set_result(result); } else { // If this inlining ever returned NaN in the past, we compile a call // to the runtime to properly handle corner cases @@ -1727,7 +1605,7 @@ void LibraryCallKit::finish_pow_exp(Node* result, Node* x, Node* y, const TypeFu Node* if_fast = _gvn.transform( new (C) IfTrueNode(iff) ); if (!if_slow->is_top()) { - RegionNode* result_region = new(C) RegionNode(3); + RegionNode* result_region = new (C) RegionNode(3); PhiNode* result_val = new (C) PhiNode(result_region, Type::DOUBLE); result_region->init_req(1, if_fast); @@ -1747,9 +1625,9 @@ void LibraryCallKit::finish_pow_exp(Node* result, Node* x, Node* y, const TypeFu result_region->init_req(2, control()); result_val->init_req(2, value); - push_result(result_region, result_val); + set_result(result_region, result_val); } else { - push_pair(result); + set_result(result); } } } @@ -1757,25 +1635,19 @@ void LibraryCallKit::finish_pow_exp(Node* result, Node* x, Node* y, const TypeFu //------------------------------inline_exp------------------------------------- // Inline exp instructions, if possible. The Intel hardware only misses // really odd corner cases (+/- Infinity). Just uncommon-trap them. -bool LibraryCallKit::inline_exp(vmIntrinsics::ID id) { - assert(id == vmIntrinsics::_dexp, "Not exp"); +bool LibraryCallKit::inline_exp() { + Node* arg = round_double_node(argument(0)); + Node* n = _gvn.transform(new (C) ExpDNode(0, arg)); - _sp += arg_size(); // restore stack pointer - Node *x = pop_math_arg(); - Node *result = _gvn.transform(new (C) ExpDNode(0,x)); - - finish_pow_exp(result, x, NULL, OptoRuntime::Math_D_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::dexp), "EXP"); + finish_pow_exp(n, arg, NULL, OptoRuntime::Math_D_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::dexp), "EXP"); C->set_has_split_ifs(true); // Has chance for split-if optimization - return true; } //------------------------------inline_pow------------------------------------- // Inline power instructions, if possible. -bool LibraryCallKit::inline_pow(vmIntrinsics::ID id) { - assert(id == vmIntrinsics::_dpow, "Not pow"); - +bool LibraryCallKit::inline_pow() { // Pseudocode for pow // if (x <= 0.0) { // long longy = (long)y; @@ -1793,15 +1665,14 @@ bool LibraryCallKit::inline_pow(vmIntrinsics::ID id) { // } // return result; - _sp += arg_size(); // restore stack pointer - Node* y = pop_math_arg(); - Node* x = pop_math_arg(); + Node* x = round_double_node(argument(0)); + Node* y = round_double_node(argument(2)); Node* result = NULL; if (!too_many_traps(Deoptimization::Reason_intrinsic)) { // Short form: skip the fancy tests and just check for NaN result. - result = _gvn.transform( new (C) PowDNode(0, x, y) ); + result = _gvn.transform(new (C) PowDNode(0, x, y)); } else { // If this inlining ever returned NaN in the past, include all // checks + call to the runtime. @@ -1919,55 +1790,23 @@ bool LibraryCallKit::inline_pow(vmIntrinsics::ID id) { // Post merge set_control(_gvn.transform(r)); record_for_igvn(r); - result=_gvn.transform(phi); + result = _gvn.transform(phi); } finish_pow_exp(result, x, y, OptoRuntime::Math_DD_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::dpow), "POW"); C->set_has_split_ifs(true); // Has chance for split-if optimization - - return true; -} - -//------------------------------inline_trans------------------------------------- -// Inline transcendental instructions, if possible. The Intel hardware gets -// these right, no funny corner cases missed. -bool LibraryCallKit::inline_trans(vmIntrinsics::ID id) { - _sp += arg_size(); // restore stack pointer - Node* arg = pop_math_arg(); - Node* trans = NULL; - - switch (id) { - case vmIntrinsics::_dlog: - trans = _gvn.transform((Node*)new (C) LogDNode(arg)); - break; - case vmIntrinsics::_dlog10: - trans = _gvn.transform((Node*)new (C) Log10DNode(arg)); - break; - default: - assert(false, "bad intrinsic was passed in"); - return false; - } - - // Push result back on JVM stack - push_pair(trans); return true; } //------------------------------runtime_math----------------------------- bool LibraryCallKit::runtime_math(const TypeFunc* call_type, address funcAddr, const char* funcName) { - Node* a = NULL; - Node* b = NULL; - assert(call_type == OptoRuntime::Math_DD_D_Type() || call_type == OptoRuntime::Math_D_D_Type(), "must be (DD)D or (D)D type"); // Inputs - _sp += arg_size(); // restore stack pointer - if (call_type == OptoRuntime::Math_DD_D_Type()) { - b = pop_math_arg(); - } - a = pop_math_arg(); + Node* a = round_double_node(argument(0)); + Node* b = (call_type == OptoRuntime::Math_DD_D_Type()) ? round_double_node(argument(2)) : NULL; const TypePtr* no_memory_effects = NULL; Node* trig = make_runtime_call(RC_LEAF, call_type, funcAddr, funcName, @@ -1979,43 +1818,43 @@ bool LibraryCallKit::runtime_math(const TypeFunc* call_type, address funcAddr, c assert(value_top == top(), "second value must be top"); #endif - push_pair(value); + set_result(value); return true; } //------------------------------inline_math_native----------------------------- bool LibraryCallKit::inline_math_native(vmIntrinsics::ID id) { +#define FN_PTR(f) CAST_FROM_FN_PTR(address, f) switch (id) { // These intrinsics are not properly supported on all hardware - case vmIntrinsics::_dcos: return Matcher::has_match_rule(Op_CosD) ? inline_trig(id) : - runtime_math(OptoRuntime::Math_D_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::dcos), "COS"); - case vmIntrinsics::_dsin: return Matcher::has_match_rule(Op_SinD) ? inline_trig(id) : - runtime_math(OptoRuntime::Math_D_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::dsin), "SIN"); - case vmIntrinsics::_dtan: return Matcher::has_match_rule(Op_TanD) ? inline_trig(id) : - runtime_math(OptoRuntime::Math_D_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::dtan), "TAN"); + case vmIntrinsics::_dcos: return Matcher::has_match_rule(Op_CosD) ? inline_trig(id) : + runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dcos), "COS"); + case vmIntrinsics::_dsin: return Matcher::has_match_rule(Op_SinD) ? inline_trig(id) : + runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dsin), "SIN"); + case vmIntrinsics::_dtan: return Matcher::has_match_rule(Op_TanD) ? inline_trig(id) : + runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dtan), "TAN"); - case vmIntrinsics::_dlog: return Matcher::has_match_rule(Op_LogD) ? inline_trans(id) : - runtime_math(OptoRuntime::Math_D_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::dlog), "LOG"); - case vmIntrinsics::_dlog10: return Matcher::has_match_rule(Op_Log10D) ? inline_trans(id) : - runtime_math(OptoRuntime::Math_D_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::dlog10), "LOG10"); + case vmIntrinsics::_dlog: return Matcher::has_match_rule(Op_LogD) ? inline_math(id) : + runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dlog), "LOG"); + case vmIntrinsics::_dlog10: return Matcher::has_match_rule(Op_Log10D) ? inline_math(id) : + runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dlog10), "LOG10"); // These intrinsics are supported on all hardware - case vmIntrinsics::_dsqrt: return Matcher::has_match_rule(Op_SqrtD) ? inline_sqrt(id) : false; - case vmIntrinsics::_dabs: return Matcher::has_match_rule(Op_AbsD) ? inline_abs(id) : false; + case vmIntrinsics::_dsqrt: return Matcher::has_match_rule(Op_SqrtD) ? inline_math(id) : false; + case vmIntrinsics::_dabs: return Matcher::has_match_rule(Op_AbsD) ? inline_math(id) : false; - case vmIntrinsics::_dexp: return - Matcher::has_match_rule(Op_ExpD) ? inline_exp(id) : - runtime_math(OptoRuntime::Math_D_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::dexp), "EXP"); - case vmIntrinsics::_dpow: return - Matcher::has_match_rule(Op_PowD) ? inline_pow(id) : - runtime_math(OptoRuntime::Math_DD_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::dpow), "POW"); + case vmIntrinsics::_dexp: return Matcher::has_match_rule(Op_ExpD) ? inline_exp() : + runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dexp), "EXP"); + case vmIntrinsics::_dpow: return Matcher::has_match_rule(Op_PowD) ? inline_pow() : + runtime_math(OptoRuntime::Math_DD_D_Type(), FN_PTR(SharedRuntime::dpow), "POW"); +#undef FN_PTR // These intrinsics are not yet correctly implemented case vmIntrinsics::_datan2: return false; default: - ShouldNotReachHere(); + fatal_unexpected_iid(id); return false; } } @@ -2030,8 +1869,7 @@ static bool is_simple_name(Node* n) { //----------------------------inline_min_max----------------------------------- bool LibraryCallKit::inline_min_max(vmIntrinsics::ID id) { - push(generate_min_max(id, argument(0), argument(1))); - + set_result(generate_min_max(id, argument(0), argument(1))); return true; } @@ -2254,99 +2092,37 @@ inline Node* LibraryCallKit::make_unsafe_address(Node* base, Node* offset) { } } -//-------------------inline_numberOfLeadingZeros_int/long----------------------- -// inline int Integer.numberOfLeadingZeros(int) -// inline int Long.numberOfLeadingZeros(long) -bool LibraryCallKit::inline_numberOfLeadingZeros(vmIntrinsics::ID id) { - assert(id == vmIntrinsics::_numberOfLeadingZeros_i || id == vmIntrinsics::_numberOfLeadingZeros_l, "not numberOfLeadingZeros"); - if (id == vmIntrinsics::_numberOfLeadingZeros_i && !Matcher::match_rule_supported(Op_CountLeadingZerosI)) return false; - if (id == vmIntrinsics::_numberOfLeadingZeros_l && !Matcher::match_rule_supported(Op_CountLeadingZerosL)) return false; - _sp += arg_size(); // restore stack pointer +//--------------------------inline_number_methods----------------------------- +// inline int Integer.numberOfLeadingZeros(int) +// inline int Long.numberOfLeadingZeros(long) +// +// inline int Integer.numberOfTrailingZeros(int) +// inline int Long.numberOfTrailingZeros(long) +// +// inline int Integer.bitCount(int) +// inline int Long.bitCount(long) +// +// inline char Character.reverseBytes(char) +// inline short Short.reverseBytes(short) +// inline int Integer.reverseBytes(int) +// inline long Long.reverseBytes(long) +bool LibraryCallKit::inline_number_methods(vmIntrinsics::ID id) { + Node* arg = argument(0); + Node* n; switch (id) { - case vmIntrinsics::_numberOfLeadingZeros_i: - push(_gvn.transform(new (C) CountLeadingZerosINode(pop()))); - break; - case vmIntrinsics::_numberOfLeadingZeros_l: - push(_gvn.transform(new (C) CountLeadingZerosLNode(pop_pair()))); - break; - default: - ShouldNotReachHere(); - } - return true; -} - -//-------------------inline_numberOfTrailingZeros_int/long---------------------- -// inline int Integer.numberOfTrailingZeros(int) -// inline int Long.numberOfTrailingZeros(long) -bool LibraryCallKit::inline_numberOfTrailingZeros(vmIntrinsics::ID id) { - assert(id == vmIntrinsics::_numberOfTrailingZeros_i || id == vmIntrinsics::_numberOfTrailingZeros_l, "not numberOfTrailingZeros"); - if (id == vmIntrinsics::_numberOfTrailingZeros_i && !Matcher::match_rule_supported(Op_CountTrailingZerosI)) return false; - if (id == vmIntrinsics::_numberOfTrailingZeros_l && !Matcher::match_rule_supported(Op_CountTrailingZerosL)) return false; - _sp += arg_size(); // restore stack pointer - switch (id) { - case vmIntrinsics::_numberOfTrailingZeros_i: - push(_gvn.transform(new (C) CountTrailingZerosINode(pop()))); - break; - case vmIntrinsics::_numberOfTrailingZeros_l: - push(_gvn.transform(new (C) CountTrailingZerosLNode(pop_pair()))); - break; - default: - ShouldNotReachHere(); - } - return true; -} - -//----------------------------inline_bitCount_int/long----------------------- -// inline int Integer.bitCount(int) -// inline int Long.bitCount(long) -bool LibraryCallKit::inline_bitCount(vmIntrinsics::ID id) { - assert(id == vmIntrinsics::_bitCount_i || id == vmIntrinsics::_bitCount_l, "not bitCount"); - if (id == vmIntrinsics::_bitCount_i && !Matcher::has_match_rule(Op_PopCountI)) return false; - if (id == vmIntrinsics::_bitCount_l && !Matcher::has_match_rule(Op_PopCountL)) return false; - _sp += arg_size(); // restore stack pointer - switch (id) { - case vmIntrinsics::_bitCount_i: - push(_gvn.transform(new (C) PopCountINode(pop()))); - break; - case vmIntrinsics::_bitCount_l: - push(_gvn.transform(new (C) PopCountLNode(pop_pair()))); - break; - default: - ShouldNotReachHere(); - } - return true; -} - -//----------------------------inline_reverseBytes_int/long/char/short------------------- -// inline Integer.reverseBytes(int) -// inline Long.reverseBytes(long) -// inline Character.reverseBytes(char) -// inline Short.reverseBytes(short) -bool LibraryCallKit::inline_reverseBytes(vmIntrinsics::ID id) { - assert(id == vmIntrinsics::_reverseBytes_i || id == vmIntrinsics::_reverseBytes_l || - id == vmIntrinsics::_reverseBytes_c || id == vmIntrinsics::_reverseBytes_s, - "not reverse Bytes"); - if (id == vmIntrinsics::_reverseBytes_i && !Matcher::has_match_rule(Op_ReverseBytesI)) return false; - if (id == vmIntrinsics::_reverseBytes_l && !Matcher::has_match_rule(Op_ReverseBytesL)) return false; - if (id == vmIntrinsics::_reverseBytes_c && !Matcher::has_match_rule(Op_ReverseBytesUS)) return false; - if (id == vmIntrinsics::_reverseBytes_s && !Matcher::has_match_rule(Op_ReverseBytesS)) return false; - _sp += arg_size(); // restore stack pointer - switch (id) { - case vmIntrinsics::_reverseBytes_i: - push(_gvn.transform(new (C) ReverseBytesINode(0, pop()))); - break; - case vmIntrinsics::_reverseBytes_l: - push_pair(_gvn.transform(new (C) ReverseBytesLNode(0, pop_pair()))); - break; - case vmIntrinsics::_reverseBytes_c: - push(_gvn.transform(new (C) ReverseBytesUSNode(0, pop()))); - break; - case vmIntrinsics::_reverseBytes_s: - push(_gvn.transform(new (C) ReverseBytesSNode(0, pop()))); - break; - default: - ; + case vmIntrinsics::_numberOfLeadingZeros_i: n = new (C) CountLeadingZerosINode( arg); break; + case vmIntrinsics::_numberOfLeadingZeros_l: n = new (C) CountLeadingZerosLNode( arg); break; + case vmIntrinsics::_numberOfTrailingZeros_i: n = new (C) CountTrailingZerosINode(arg); break; + case vmIntrinsics::_numberOfTrailingZeros_l: n = new (C) CountTrailingZerosLNode(arg); break; + case vmIntrinsics::_bitCount_i: n = new (C) PopCountINode( arg); break; + case vmIntrinsics::_bitCount_l: n = new (C) PopCountLNode( arg); break; + case vmIntrinsics::_reverseBytes_c: n = new (C) ReverseBytesUSNode(0, arg); break; + case vmIntrinsics::_reverseBytes_s: n = new (C) ReverseBytesSNode( 0, arg); break; + case vmIntrinsics::_reverseBytes_i: n = new (C) ReverseBytesINode( 0, arg); break; + case vmIntrinsics::_reverseBytes_l: n = new (C) ReverseBytesLNode( 0, arg); break; + default: fatal_unexpected_iid(id); break; } + set_result(_gvn.transform(n)); return true; } @@ -2356,7 +2132,7 @@ const static BasicType T_ADDRESS_HOLDER = T_LONG; // Helper that guards and inserts a pre-barrier. void LibraryCallKit::insert_pre_barrier(Node* base_oop, Node* offset, - Node* pre_val, int nargs, bool need_mem_bar) { + Node* pre_val, bool need_mem_bar) { // We could be accessing the referent field of a reference object. If so, when G1 // is enabled, we need to log the value in the referent field in an SATB buffer. // This routine performs some compile time filters and generates suitable @@ -2406,8 +2182,8 @@ void LibraryCallKit::insert_pre_barrier(Node* base_oop, Node* offset, // } // } - float likely = PROB_LIKELY(0.999); - float unlikely = PROB_UNLIKELY(0.999); + float likely = PROB_LIKELY( 0.999); + float unlikely = PROB_UNLIKELY(0.999); IdealKit ideal(this); #define __ ideal. @@ -2419,9 +2195,7 @@ void LibraryCallKit::insert_pre_barrier(Node* base_oop, Node* offset, sync_kit(ideal); Node* ref_klass_con = makecon(TypeKlassPtr::make(env()->Reference_klass())); - _sp += nargs; // gen_instanceof might do an uncommon trap Node* is_instof = gen_instanceof(base_oop, ref_klass_con); - _sp -= nargs; // Update IdealKit memory and control from graphKit. __ sync_kit(this); @@ -2505,7 +2279,7 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas { ResourceMark rm; // Check the signatures. - ciSignature* sig = signature(); + ciSignature* sig = callee()->signature(); #ifdef ASSERT if (!is_store) { // Object getObject(Object base, int/long offset), etc. @@ -2543,42 +2317,19 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas C->set_has_unsafe_access(true); // Mark eventual nmethod as "unsafe". - int type_words = type2size[ (type == T_ADDRESS) ? T_LONG : type ]; - - // Argument words: "this" plus (oop/offset) or (lo/hi) args plus maybe 1 or 2 value words - int nargs = 1 + (is_native_ptr ? 2 : 3) + (is_store ? type_words : 0); - assert(callee()->arg_size() == nargs, "must be"); - - debug_only(int saved_sp = _sp); - _sp += nargs; - - Node* val; - debug_only(val = (Node*)(uintptr_t)-1); - - - if (is_store) { - // Get the value being stored. (Pop it first; it was pushed last.) - switch (type) { - case T_DOUBLE: - case T_LONG: - case T_ADDRESS: - val = pop_pair(); - break; - default: - val = pop(); - } - } + Node* receiver = argument(0); // type: oop // Build address expression. See the code in inline_unsafe_prefetch. - Node *adr; - Node *heap_base_oop = top(); + Node* adr; + Node* heap_base_oop = top(); Node* offset = top(); + Node* val; if (!is_native_ptr) { - // The offset is a value produced by Unsafe.staticFieldOffset or Unsafe.objectFieldOffset - offset = pop_pair(); // The base is either a Java object or a value produced by Unsafe.staticFieldBase - Node* base = pop(); + Node* base = argument(1); // type: oop + // The offset is a value produced by Unsafe.staticFieldOffset or Unsafe.objectFieldOffset + offset = argument(2); // type: long // We currently rely on the cookies produced by Unsafe.xxxFieldOffset // to be plain byte offsets, which are also the same as those accepted // by oopDesc::field_base. @@ -2588,18 +2339,14 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas offset = ConvL2X(offset); adr = make_unsafe_address(base, offset); heap_base_oop = base; + val = is_store ? argument(4) : NULL; } else { - Node* ptr = pop_pair(); - // Adjust Java long to machine word: - ptr = ConvL2X(ptr); + Node* ptr = argument(1); // type: long + ptr = ConvL2X(ptr); // adjust Java long to machine word adr = make_unsafe_address(NULL, ptr); + val = is_store ? argument(3) : NULL; } - // Pop receiver last: it was pushed first. - Node *receiver = pop(); - - assert(saved_sp == _sp, "must have correct argument count"); - const TypePtr *adr_type = _gvn.type(adr)->isa_ptr(); // First guess at the value type. @@ -2633,13 +2380,7 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas } } - // Null check on self without removing any arguments. The argument - // null check technically happens in the wrong place, which can lead to - // invalid stack traces when the primitive is inlined into a method - // which handles NullPointerExceptions. - _sp += nargs; - do_null_check(receiver, T_OBJECT); - _sp -= nargs; + receiver = null_check(receiver); if (stopped()) { return true; } @@ -2671,34 +2412,36 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas if (!is_store) { Node* p = make_load(control(), adr, value_type, type, adr_type, is_volatile); - // load value and push onto stack + // load value switch (type) { case T_BOOLEAN: case T_CHAR: case T_BYTE: case T_SHORT: case T_INT: + case T_LONG: case T_FLOAT: - push(p); + case T_DOUBLE: break; case T_OBJECT: if (need_read_barrier) { - insert_pre_barrier(heap_base_oop, offset, p, nargs, !(is_volatile || need_mem_bar)); + insert_pre_barrier(heap_base_oop, offset, p, !(is_volatile || need_mem_bar)); } - push(p); break; case T_ADDRESS: // Cast to an int type. - p = _gvn.transform( new (C) CastP2XNode(NULL,p) ); + p = _gvn.transform(new (C) CastP2XNode(NULL, p)); p = ConvX2L(p); - push_pair(p); break; - case T_DOUBLE: - case T_LONG: - push_pair( p ); + default: + fatal(err_msg_res("unexpected type %d: %s", type, type2name(type))); break; - default: ShouldNotReachHere(); } + // The load node has the control of the preceding MemBarCPUOrder. All + // following nodes will have the control of the MemBarCPUOrder inserted at + // the end of this method. So, pushing the load onto the stack at a later + // point is fine. + set_result(p); } else { // place effect of store into memory switch (type) { @@ -2762,7 +2505,7 @@ bool LibraryCallKit::inline_unsafe_prefetch(bool is_native_ptr, bool is_store, b { ResourceMark rm; // Check the signatures. - ciSignature* sig = signature(); + ciSignature* sig = callee()->signature(); #ifdef ASSERT // Object getObject(Object base, int/long offset), etc. BasicType rtype = sig->return_type()->basic_type(); @@ -2780,19 +2523,21 @@ bool LibraryCallKit::inline_unsafe_prefetch(bool is_native_ptr, bool is_store, b C->set_has_unsafe_access(true); // Mark eventual nmethod as "unsafe". - // Argument words: "this" if not static, plus (oop/offset) or (lo/hi) args - int nargs = (is_static ? 0 : 1) + (is_native_ptr ? 2 : 3); - - debug_only(int saved_sp = _sp); - _sp += nargs; + const int idx = is_static ? 0 : 1; + if (!is_static) { + null_check_receiver(); + if (stopped()) { + return true; + } + } // Build address expression. See the code in inline_unsafe_access. Node *adr; if (!is_native_ptr) { - // The offset is a value produced by Unsafe.staticFieldOffset or Unsafe.objectFieldOffset - Node* offset = pop_pair(); // The base is either a Java object or a value produced by Unsafe.staticFieldBase - Node* base = pop(); + Node* base = argument(idx + 0); // type: oop + // The offset is a value produced by Unsafe.staticFieldOffset or Unsafe.objectFieldOffset + Node* offset = argument(idx + 1); // type: long // We currently rely on the cookies produced by Unsafe.xxxFieldOffset // to be plain byte offsets, which are also the same as those accepted // by oopDesc::field_base. @@ -2802,31 +2547,11 @@ bool LibraryCallKit::inline_unsafe_prefetch(bool is_native_ptr, bool is_store, b offset = ConvL2X(offset); adr = make_unsafe_address(base, offset); } else { - Node* ptr = pop_pair(); - // Adjust Java long to machine word: - ptr = ConvL2X(ptr); + Node* ptr = argument(idx + 0); // type: long + ptr = ConvL2X(ptr); // adjust Java long to machine word adr = make_unsafe_address(NULL, ptr); } - if (is_static) { - assert(saved_sp == _sp, "must have correct argument count"); - } else { - // Pop receiver last: it was pushed first. - Node *receiver = pop(); - assert(saved_sp == _sp, "must have correct argument count"); - - // Null check on self without removing any arguments. The argument - // null check technically happens in the wrong place, which can lead to - // invalid stack traces when the primitive is inlined into a method - // which handles NullPointerExceptions. - _sp += nargs; - do_null_check(receiver, T_OBJECT); - _sp -= nargs; - if (stopped()) { - return true; - } - } - // Generate the read or write prefetch Node *prefetch; if (is_store) { @@ -2841,7 +2566,22 @@ bool LibraryCallKit::inline_unsafe_prefetch(bool is_native_ptr, bool is_store, b } //----------------------------inline_unsafe_load_store---------------------------- - +// This method serves a couple of different customers (depending on LoadStoreKind): +// +// LS_cmpxchg: +// public final native boolean compareAndSwapObject(Object o, long offset, Object expected, Object x); +// public final native boolean compareAndSwapInt( Object o, long offset, int expected, int x); +// public final native boolean compareAndSwapLong( Object o, long offset, long expected, long x); +// +// LS_xadd: +// public int getAndAddInt( Object o, long offset, int delta) +// public long getAndAddLong(Object o, long offset, long delta) +// +// LS_xchg: +// int getAndSet(Object o, long offset, int newValue) +// long getAndSet(Object o, long offset, long newValue) +// Object getAndSet(Object o, long offset, Object newValue) +// bool LibraryCallKit::inline_unsafe_load_store(BasicType type, LoadStoreKind kind) { // This basic scheme here is the same as inline_unsafe_access, but // differs in enough details that combining them would make the code @@ -2856,7 +2596,8 @@ bool LibraryCallKit::inline_unsafe_load_store(BasicType type, LoadStoreKind kind BasicType rtype; { ResourceMark rm; - ciSignature* sig = signature(); + // Check the signatures. + ciSignature* sig = callee()->signature(); rtype = sig->return_type()->basic_type(); if (kind == LS_xadd || kind == LS_xchg) { // Check the signatures. @@ -2881,28 +2622,31 @@ bool LibraryCallKit::inline_unsafe_load_store(BasicType type, LoadStoreKind kind } #endif //PRODUCT - // number of stack slots per value argument (1 or 2) - int type_words = type2size[type]; - C->set_has_unsafe_access(true); // Mark eventual nmethod as "unsafe". - // Argument words: "this" plus oop plus offset (plus oldvalue) plus newvalue/delta; - int nargs = 1 + 1 + 2 + ((kind == LS_cmpxchg) ? type_words : 0) + type_words; + // Get arguments: + Node* receiver = NULL; + Node* base = NULL; + Node* offset = NULL; + Node* oldval = NULL; + Node* newval = NULL; + if (kind == LS_cmpxchg) { + const bool two_slot_type = type2size[type] == 2; + receiver = argument(0); // type: oop + base = argument(1); // type: oop + offset = argument(2); // type: long + oldval = argument(4); // type: oop, int, or long + newval = argument(two_slot_type ? 6 : 5); // type: oop, int, or long + } else if (kind == LS_xadd || kind == LS_xchg){ + receiver = argument(0); // type: oop + base = argument(1); // type: oop + offset = argument(2); // type: long + oldval = NULL; + newval = argument(4); // type: oop, int, or long + } - // pop arguments: newval, offset, base, and receiver - debug_only(int saved_sp = _sp); - _sp += nargs; - Node* newval = (type_words == 1) ? pop() : pop_pair(); - Node* oldval = (kind == LS_cmpxchg) ? ((type_words == 1) ? pop() : pop_pair()) : NULL; - Node *offset = pop_pair(); - Node *base = pop(); - Node *receiver = pop(); - assert(saved_sp == _sp, "must have correct argument count"); - - // Null check receiver. - _sp += nargs; - do_null_check(receiver, T_OBJECT); - _sp -= nargs; + // Null check receiver. + receiver = null_check(receiver); if (stopped()) { return true; } @@ -3008,7 +2752,7 @@ bool LibraryCallKit::inline_unsafe_load_store(BasicType type, LoadStoreKind kind post_barrier(control(), load_store, base, adr, alias_idx, newval, T_OBJECT, true); break; default: - ShouldNotReachHere(); + fatal(err_msg_res("unexpected type %d: %s", type, type2name(type))); break; } @@ -3029,10 +2773,14 @@ bool LibraryCallKit::inline_unsafe_load_store(BasicType type, LoadStoreKind kind #endif assert(type2size[load_store->bottom_type()->basic_type()] == type2size[rtype], "result type should match"); - push_node(load_store->bottom_type()->basic_type(), load_store); + set_result(load_store); return true; } +//----------------------------inline_unsafe_ordered_store---------------------- +// public native void sun.misc.Unsafe.putOrderedObject(Object o, long offset, Object x); +// public native void sun.misc.Unsafe.putOrderedInt(Object o, long offset, int x); +// public native void sun.misc.Unsafe.putOrderedLong(Object o, long offset, long x); bool LibraryCallKit::inline_unsafe_ordered_store(BasicType type) { // This is another variant of inline_unsafe_access, differing in // that it always issues store-store ("release") barrier and ensures @@ -3044,7 +2792,7 @@ bool LibraryCallKit::inline_unsafe_ordered_store(BasicType type) { { ResourceMark rm; // Check the signatures. - ciSignature* sig = signature(); + ciSignature* sig = callee()->signature(); #ifdef ASSERT BasicType rtype = sig->return_type()->basic_type(); assert(rtype == T_VOID, "must return void"); @@ -3055,27 +2803,16 @@ bool LibraryCallKit::inline_unsafe_ordered_store(BasicType type) { } #endif //PRODUCT - // number of stack slots per value argument (1 or 2) - int type_words = type2size[type]; - C->set_has_unsafe_access(true); // Mark eventual nmethod as "unsafe". - // Argument words: "this" plus oop plus offset plus value; - int nargs = 1 + 1 + 2 + type_words; + // Get arguments: + Node* receiver = argument(0); // type: oop + Node* base = argument(1); // type: oop + Node* offset = argument(2); // type: long + Node* val = argument(4); // type: oop, int, or long - // pop arguments: val, offset, base, and receiver - debug_only(int saved_sp = _sp); - _sp += nargs; - Node* val = (type_words == 1) ? pop() : pop_pair(); - Node *offset = pop_pair(); - Node *base = pop(); - Node *receiver = pop(); - assert(saved_sp == _sp, "must have correct argument count"); - - // Null check receiver. - _sp += nargs; - do_null_check(receiver, T_OBJECT); - _sp -= nargs; + // Null check receiver. + receiver = null_check(receiver); if (stopped()) { return true; } @@ -3092,7 +2829,7 @@ bool LibraryCallKit::inline_unsafe_ordered_store(BasicType type) { insert_mem_bar(Op_MemBarRelease); insert_mem_bar(Op_MemBarCPUOrder); // Ensure that the store is atomic for longs: - bool require_atomic_access = true; + const bool require_atomic_access = true; Node* store; if (type == T_OBJECT) // reference stores need a store barrier. store = store_oop_to_unknown(control(), base, adr, adr_type, val, type); @@ -3103,20 +2840,17 @@ bool LibraryCallKit::inline_unsafe_ordered_store(BasicType type) { return true; } +//----------------------------inline_unsafe_allocate--------------------------- +// public native Object sun.mics.Unsafe.allocateInstance(Class cls); bool LibraryCallKit::inline_unsafe_allocate() { if (callee()->is_static()) return false; // caller must have the capability! - int nargs = 1 + 1; - assert(signature()->size() == nargs-1, "alloc has 1 argument"); - null_check_receiver(callee()); // check then ignore argument(0) - _sp += nargs; // set original stack for use by uncommon_trap - Node* cls = do_null_check(argument(1), T_OBJECT); - _sp -= nargs; + + null_check_receiver(); // null-check, then ignore + Node* cls = null_check(argument(1)); if (stopped()) return true; - Node* kls = load_klass_from_mirror(cls, false, nargs, NULL, 0); - _sp += nargs; // set original stack for use by uncommon_trap - kls = do_null_check(kls, T_OBJECT); - _sp -= nargs; + Node* kls = load_klass_from_mirror(cls, false, NULL, 0); + kls = null_check(kls); if (stopped()) return true; // argument was like int.class // Note: The argument might still be an illegal value like @@ -3127,12 +2861,11 @@ bool LibraryCallKit::inline_unsafe_allocate() { // can generate code to load it as unsigned byte. Node* inst = make_load(NULL, insp, TypeInt::UBYTE, T_BOOLEAN); Node* bits = intcon(InstanceKlass::fully_initialized); - Node* test = _gvn.transform( new (C) SubINode(inst, bits) ); + Node* test = _gvn.transform(new (C) SubINode(inst, bits)); // The 'test' is non-zero if we need to take a slow path. Node* obj = new_instance(kls, test); - push(obj); - + set_result(obj); return true; } @@ -3143,15 +2876,10 @@ bool LibraryCallKit::inline_unsafe_allocate() { * return myklass->trace_id & ~0x3 */ bool LibraryCallKit::inline_native_classID() { - int nargs = 1 + 1; - null_check_receiver(callee()); // check then ignore argument(0) - _sp += nargs; - Node* cls = do_null_check(argument(1), T_OBJECT); - _sp -= nargs; - Node* kls = load_klass_from_mirror(cls, false, nargs, NULL, 0); - _sp += nargs; - kls = do_null_check(kls, T_OBJECT); - _sp -= nargs; + null_check_receiver(); // null-check, then ignore + Node* cls = null_check(argument(1), T_OBJECT); + Node* kls = load_klass_from_mirror(cls, false, NULL, 0); + kls = null_check(kls, T_OBJECT); ByteSize offset = TRACE_ID_OFFSET; Node* insp = basic_plus_adr(kls, in_bytes(offset)); Node* tvalue = make_load(NULL, insp, TypeLong::LONG, T_LONG); @@ -3162,7 +2890,7 @@ bool LibraryCallKit::inline_native_classID() { const TypePtr *adr_type = _gvn.type(insp)->isa_ptr(); store_to_memory(control(), insp, orl, T_LONG, adr_type); - push_pair(andl); + set_result(andl); return true; } @@ -3177,13 +2905,12 @@ bool LibraryCallKit::inline_native_threadID() { size_t thread_id_size = OSThread::thread_id_size(); if (thread_id_size == (size_t) BytesPerLong) { threadid = ConvL2I(make_load(control(), p, TypeLong::LONG, T_LONG)); - push(threadid); } else if (thread_id_size == (size_t) BytesPerInt) { threadid = make_load(control(), p, TypeInt::INT, T_INT); - push(threadid); } else { ShouldNotReachHere(); } + set_result(threadid); return true; } #endif @@ -3192,29 +2919,28 @@ bool LibraryCallKit::inline_native_threadID() { // inline code for System.currentTimeMillis() and System.nanoTime() // these have the same type and signature bool LibraryCallKit::inline_native_time_funcs(address funcAddr, const char* funcName) { - const TypeFunc *tf = OptoRuntime::void_long_Type(); + const TypeFunc* tf = OptoRuntime::void_long_Type(); const TypePtr* no_memory_effects = NULL; Node* time = make_runtime_call(RC_LEAF, tf, funcAddr, funcName, no_memory_effects); Node* value = _gvn.transform(new (C) ProjNode(time, TypeFunc::Parms+0)); #ifdef ASSERT - Node* value_top = _gvn.transform(new (C) ProjNode(time, TypeFunc::Parms + 1)); + Node* value_top = _gvn.transform(new (C) ProjNode(time, TypeFunc::Parms+1)); assert(value_top == top(), "second value must be top"); #endif - push_pair(value); + set_result(value); return true; } //------------------------inline_native_currentThread------------------ bool LibraryCallKit::inline_native_currentThread() { Node* junk = NULL; - push(generate_current_thread(junk)); + set_result(generate_current_thread(junk)); return true; } //------------------------inline_native_isInterrupted------------------ +// private native boolean java.lang.Thread.isInterrupted(boolean ClearInterrupted); bool LibraryCallKit::inline_native_isInterrupted() { - const int nargs = 1+1; // receiver + boolean - assert(nargs == arg_size(), "sanity"); // Add a fast path to t.isInterrupted(clear_int): // (t == Thread.current() && (!TLS._osthread._interrupted || !clear_int)) // ? TLS._osthread._interrupted : /*slow path:*/ t.isInterrupted(clear_int) @@ -3312,9 +3038,8 @@ bool LibraryCallKit::inline_native_isInterrupted() { set_i_o( _gvn.transform(io_phi) ); } - push_result(result_rgn, result_val); C->set_has_split_ifs(true); // Has chance for split-if optimization - + set_result(result_rgn, result_val); return true; } @@ -3334,7 +3059,6 @@ Node* LibraryCallKit::load_mirror_from_klass(Node* klass) { // If the region is NULL, force never_see_null = true. Node* LibraryCallKit::load_klass_from_mirror_common(Node* mirror, bool never_see_null, - int nargs, RegionNode* region, int null_path, int offset) { @@ -3342,7 +3066,6 @@ Node* LibraryCallKit::load_klass_from_mirror_common(Node* mirror, Node* p = basic_plus_adr(mirror, offset); const TypeKlassPtr* kls_type = TypeKlassPtr::OBJECT_OR_NULL; Node* kls = _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), p, TypeRawPtr::BOTTOM, kls_type) ); - _sp += nargs; // any deopt will start just before call to enclosing method Node* null_ctl = top(); kls = null_check_oop(kls, &null_ctl, never_see_null); if (region != NULL) { @@ -3351,7 +3074,6 @@ Node* LibraryCallKit::load_klass_from_mirror_common(Node* mirror, } else { assert(null_ctl == top(), "no loose ends"); } - _sp -= nargs; return kls; } @@ -3376,7 +3098,6 @@ Node* LibraryCallKit::generate_interface_guard(Node* kls, RegionNode* region) { //-------------------------inline_native_Class_query------------------- bool LibraryCallKit::inline_native_Class_query(vmIntrinsics::ID id) { - int nargs = 1+0; // just the Class mirror, in most cases const Type* return_type = TypeInt::BOOL; Node* prim_return_value = top(); // what happens if it's a primitive class? bool never_see_null = !too_many_traps(Deoptimization::Reason_null_check); @@ -3384,11 +3105,14 @@ bool LibraryCallKit::inline_native_Class_query(vmIntrinsics::ID id) { enum { _normal_path = 1, _prim_path = 2, PATH_LIMIT }; + Node* mirror = argument(0); + Node* obj = top(); + switch (id) { case vmIntrinsics::_isInstance: - nargs = 1+1; // the Class mirror, plus the object getting queried about // nothing is an instance of a primitive type prim_return_value = intcon(0); + obj = argument(1); break; case vmIntrinsics::_getModifiers: prim_return_value = intcon(JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC); @@ -3419,12 +3143,10 @@ bool LibraryCallKit::inline_native_Class_query(vmIntrinsics::ID id) { return_type = TypeInt::INT; // not bool! 6297094 break; default: - ShouldNotReachHere(); + fatal_unexpected_iid(id); + break; } - Node* mirror = argument(0); - Node* obj = (nargs <= 1)? top(): argument(1); - const TypeInstPtr* mirror_con = _gvn.type(mirror)->isa_instptr(); if (mirror_con == NULL) return false; // cannot happen? @@ -3451,9 +3173,7 @@ bool LibraryCallKit::inline_native_Class_query(vmIntrinsics::ID id) { // For Reflection.getClassAccessFlags(), the null check occurs in // the wrong place; see inline_unsafe_access(), above, for a similar // situation. - _sp += nargs; // set original stack for use by uncommon_trap - mirror = do_null_check(mirror, T_OBJECT); - _sp -= nargs; + mirror = null_check(mirror); // If mirror or obj is dead, only null-path is taken. if (stopped()) return true; @@ -3461,11 +3181,10 @@ bool LibraryCallKit::inline_native_Class_query(vmIntrinsics::ID id) { // Now load the mirror's klass metaobject, and null-check it. // Side-effects region with the control path if the klass is null. - Node* kls = load_klass_from_mirror(mirror, never_see_null, nargs, - region, _prim_path); + Node* kls = load_klass_from_mirror(mirror, never_see_null, region, _prim_path); // If kls is null, we have a primitive mirror. phi->init_req(_prim_path, prim_return_value); - if (stopped()) { push_result(region, phi); return true; } + if (stopped()) { set_result(region, phi); return true; } Node* p; // handy temp Node* null_ctl; @@ -3476,9 +3195,7 @@ bool LibraryCallKit::inline_native_Class_query(vmIntrinsics::ID id) { switch (id) { case vmIntrinsics::_isInstance: // nothing is an instance of a primitive type - _sp += nargs; // gen_instanceof might do an uncommon trap query_value = gen_instanceof(obj, kls); - _sp -= nargs; break; case vmIntrinsics::_getModifiers: @@ -3553,16 +3270,16 @@ bool LibraryCallKit::inline_native_Class_query(vmIntrinsics::ID id) { break; default: - ShouldNotReachHere(); + fatal_unexpected_iid(id); + break; } // Fall-through is the normal case of a query to a real class. phi->init_req(1, query_value); region->init_req(1, control()); - push_result(region, phi); C->set_has_split_ifs(true); // Has chance for split-if optimization - + set_result(region, phi); return true; } @@ -3570,8 +3287,6 @@ bool LibraryCallKit::inline_native_Class_query(vmIntrinsics::ID id) { // This intrinsic takes the JNI calls out of the heart of // UnsafeFieldAccessorImpl.set, which improves Field.set, readObject, etc. bool LibraryCallKit::inline_native_subtype_check() { - int nargs = 1+1; // the Class mirror, plus the other class getting examined - // Pull both arguments off the stack. Node* args[2]; // two java.lang.Class mirrors: superc, subc args[0] = argument(0); @@ -3602,9 +3317,7 @@ bool LibraryCallKit::inline_native_subtype_check() { int which_arg; for (which_arg = 0; which_arg <= 1; which_arg++) { Node* arg = args[which_arg]; - _sp += nargs; // set original stack for use by uncommon_trap - arg = do_null_check(arg, T_OBJECT); - _sp -= nargs; + arg = null_check(arg); if (stopped()) break; args[which_arg] = _gvn.transform(arg); @@ -3618,9 +3331,7 @@ bool LibraryCallKit::inline_native_subtype_check() { for (which_arg = 0; which_arg <= 1; which_arg++) { Node* kls = klasses[which_arg]; Node* null_ctl = top(); - _sp += nargs; // set original stack for use by uncommon_trap kls = null_check_oop(kls, &null_ctl, never_see_null); - _sp -= nargs; int prim_path = (which_arg == 0 ? _prim_0_path : _prim_1_path); region->init_req(prim_path, null_ctl); if (stopped()) break; @@ -3670,8 +3381,7 @@ bool LibraryCallKit::inline_native_subtype_check() { } set_control(_gvn.transform(region)); - push(_gvn.transform(phi)); - + set_result(_gvn.transform(phi)); return true; } @@ -3719,14 +3429,12 @@ Node* LibraryCallKit::generate_array_guard_common(Node* kls, RegionNode* region, //-----------------------inline_native_newArray-------------------------- +// private static native Object java.lang.reflect.newArray(Class componentType, int length); bool LibraryCallKit::inline_native_newArray() { - int nargs = 2; Node* mirror = argument(0); Node* count_val = argument(1); - _sp += nargs; // set original stack for use by uncommon_trap - mirror = do_null_check(mirror, T_OBJECT); - _sp -= nargs; + mirror = null_check(mirror); // If mirror or obj is dead, only null-path is taken. if (stopped()) return true; @@ -3740,7 +3448,6 @@ bool LibraryCallKit::inline_native_newArray() { bool never_see_null = !too_many_traps(Deoptimization::Reason_null_check); Node* klass_node = load_array_klass_from_mirror(mirror, never_see_null, - nargs, result_reg, _slow_path); Node* normal_ctl = control(); Node* no_array_ctl = result_reg->in(_slow_path); @@ -3767,7 +3474,7 @@ bool LibraryCallKit::inline_native_newArray() { // Normal case: The array type has been cached in the java.lang.Class. // The following call works fine even if the array type is polymorphic. // It could be a dynamic mix of int[], boolean[], Object[], etc. - Node* obj = new_array(klass_node, count_val, nargs); + Node* obj = new_array(klass_node, count_val, 0); // no arguments to push result_reg->init_req(_normal_path, control()); result_val->init_req(_normal_path, obj); result_io ->init_req(_normal_path, i_o()); @@ -3777,23 +3484,18 @@ bool LibraryCallKit::inline_native_newArray() { // Return the combined state. set_i_o( _gvn.transform(result_io) ); set_all_memory( _gvn.transform(result_mem) ); - push_result(result_reg, result_val); - C->set_has_split_ifs(true); // Has chance for split-if optimization + C->set_has_split_ifs(true); // Has chance for split-if optimization + set_result(result_reg, result_val); return true; } //----------------------inline_native_getLength-------------------------- +// public static native int java.lang.reflect.Array.getLength(Object array); bool LibraryCallKit::inline_native_getLength() { if (too_many_traps(Deoptimization::Reason_intrinsic)) return false; - int nargs = 1; - Node* array = argument(0); - - _sp += nargs; // set original stack for use by uncommon_trap - array = do_null_check(array, T_OBJECT); - _sp -= nargs; - + Node* array = null_check(argument(0)); // If array is dead, only null-path is taken. if (stopped()) return true; @@ -3803,7 +3505,6 @@ bool LibraryCallKit::inline_native_getLength() { if (non_array != NULL) { PreserveJVMState pjvms(this); set_control(non_array); - _sp += nargs; // push the arguments back on the stack uncommon_trap(Deoptimization::Reason_intrinsic, Deoptimization::Action_maybe_recompile); } @@ -3813,19 +3514,21 @@ bool LibraryCallKit::inline_native_getLength() { // The works fine even if the array type is polymorphic. // It could be a dynamic mix of int[], boolean[], Object[], etc. - push( load_array_length(array) ); - - C->set_has_split_ifs(true); // Has chance for split-if optimization + Node* result = load_array_length(array); + C->set_has_split_ifs(true); // Has chance for split-if optimization + set_result(result); return true; } //------------------------inline_array_copyOf---------------------------- +// public static T[] java.util.Arrays.copyOf( U[] original, int newLength, Class newType); +// public static T[] java.util.Arrays.copyOfRange(U[] original, int from, int to, Class newType); bool LibraryCallKit::inline_array_copyOf(bool is_copyOfRange) { + return false; if (too_many_traps(Deoptimization::Reason_intrinsic)) return false; - // Restore the stack and pop off the arguments. - int nargs = 3 + (is_copyOfRange? 1: 0); + // Get the arguments. Node* original = argument(0); Node* start = is_copyOfRange? argument(1): intcon(0); Node* end = is_copyOfRange? argument(2): argument(1); @@ -3833,23 +3536,21 @@ bool LibraryCallKit::inline_array_copyOf(bool is_copyOfRange) { Node* newcopy; - //set the original stack and the reexecute bit for the interpreter to reexecute - //the bytecode that invokes Arrays.copyOf if deoptimization happens + // Set the original stack and the reexecute bit for the interpreter to reexecute + // the bytecode that invokes Arrays.copyOf if deoptimization happens. { PreserveReexecuteState preexecs(this); - _sp += nargs; jvms()->set_should_reexecute(true); - array_type_mirror = do_null_check(array_type_mirror, T_OBJECT); - original = do_null_check(original, T_OBJECT); + array_type_mirror = null_check(array_type_mirror); + original = null_check(original); // Check if a null path was taken unconditionally. if (stopped()) return true; Node* orig_length = load_array_length(original); - Node* klass_node = load_klass_from_mirror(array_type_mirror, false, 0, - NULL, 0); - klass_node = do_null_check(klass_node, T_OBJECT); + Node* klass_node = load_klass_from_mirror(array_type_mirror, false, NULL, 0); + klass_node = null_check(klass_node); RegionNode* bailout = new (C) RegionNode(1); record_for_igvn(bailout); @@ -3872,7 +3573,7 @@ bool LibraryCallKit::inline_array_copyOf(bool is_copyOfRange) { Node* length = end; if (_gvn.type(start) != TypeInt::ZERO) { - length = _gvn.transform( new (C) SubINode(end, start) ); + length = _gvn.transform(new (C) SubINode(end, start)); } // Bail out if length is negative. @@ -3883,19 +3584,18 @@ bool LibraryCallKit::inline_array_copyOf(bool is_copyOfRange) { if (bailout->req() > 1) { PreserveJVMState pjvms(this); - set_control( _gvn.transform(bailout) ); + set_control(_gvn.transform(bailout)); uncommon_trap(Deoptimization::Reason_intrinsic, Deoptimization::Action_maybe_recompile); } if (!stopped()) { - // How many elements will we copy from the original? // The answer is MinI(orig_length - start, length). - Node* orig_tail = _gvn.transform( new(C) SubINode(orig_length, start) ); + Node* orig_tail = _gvn.transform(new (C) SubINode(orig_length, start)); Node* moved = generate_min_max(vmIntrinsics::_min, orig_tail, length); - newcopy = new_array(klass_node, length, 0); + newcopy = new_array(klass_node, length, 0); // no argments to push // Generate a direct call to the right arraycopy function(s). // We know the copy is disjoint but we might not know if the @@ -3910,14 +3610,12 @@ bool LibraryCallKit::inline_array_copyOf(bool is_copyOfRange) { original, start, newcopy, intcon(0), moved, disjoint_bases, length_never_negative); } - } //original reexecute and sp are set back here - - if(!stopped()) { - push(newcopy); - } + } // original reexecute is set back here C->set_has_split_ifs(true); // Has chance for split-if optimization - + if (!stopped()) { + set_result(newcopy); + } return true; } @@ -3969,7 +3667,7 @@ LibraryCallKit::generate_method_call(vmIntrinsics::ID method_id, bool is_virtual SharedRuntime::get_resolve_static_call_stub(), method, bci()); } else if (is_virtual) { - null_check_receiver(method); + null_check_receiver(); int vtable_index = Method::invalid_vtable_index; if (UseInlineCaches) { // Suppress the vtable call @@ -3983,7 +3681,7 @@ LibraryCallKit::generate_method_call(vmIntrinsics::ID method_id, bool is_virtual SharedRuntime::get_resolve_virtual_call_stub(), method, vtable_index, bci()); } else { // neither virtual nor static: opt_virtual - null_check_receiver(method); + null_check_receiver(); slow_call = new(C) CallStaticJavaNode(tf, SharedRuntime::get_resolve_opt_virtual_call_stub(), method, bci()); @@ -4012,7 +3710,7 @@ bool LibraryCallKit::inline_native_hashcode(bool is_virtual, bool is_static) { Node* obj = NULL; if (!is_static) { // Check for hashing null object - obj = null_check_receiver(callee()); + obj = null_check_receiver(); if (stopped()) return true; // unconditionally null result_reg->init_req(_null_path, top()); result_val->init_req(_null_path, top()); @@ -4028,9 +3726,9 @@ bool LibraryCallKit::inline_native_hashcode(bool is_virtual, bool is_static) { // Unconditionally null? Then return right away. if (stopped()) { - set_control( result_reg->in(_null_path) ); + set_control( result_reg->in(_null_path)); if (!stopped()) - push( result_val ->in(_null_path) ); + set_result(result_val->in(_null_path)); return true; } @@ -4103,8 +3801,7 @@ bool LibraryCallKit::inline_native_hashcode(bool is_virtual, bool is_static) { if (!stopped()) { // No need for PreserveJVMState, because we're using up the present state. set_all_memory(init_mem); - vmIntrinsics::ID hashCode_id = vmIntrinsics::_hashCode; - if (is_static) hashCode_id = vmIntrinsics::_identityHashCode; + vmIntrinsics::ID hashCode_id = is_static ? vmIntrinsics::_identityHashCode : vmIntrinsics::_hashCode; CallJavaNode* slow_call = generate_method_call(hashCode_id, is_virtual, is_static); Node* slow_result = set_results_for_java_call(slow_call); // this->control() comes from set_results_for_java_call @@ -4117,48 +3814,38 @@ bool LibraryCallKit::inline_native_hashcode(bool is_virtual, bool is_static) { // Return the combined state. set_i_o( _gvn.transform(result_io) ); set_all_memory( _gvn.transform(result_mem) ); - push_result(result_reg, result_val); + set_result(result_reg, result_val); return true; } //---------------------------inline_native_getClass---------------------------- +// public final native Class java.lang.Object.getClass(); +// // Build special case code for calls to getClass on an object. bool LibraryCallKit::inline_native_getClass() { - Node* obj = null_check_receiver(callee()); + Node* obj = null_check_receiver(); if (stopped()) return true; - push( load_mirror_from_klass(load_object_klass(obj)) ); + set_result(load_mirror_from_klass(load_object_klass(obj))); return true; } //-----------------inline_native_Reflection_getCallerClass--------------------- +// public static native Class sun.reflect.Reflection.getCallerClass(int realFramesToSkip); +// // In the presence of deep enough inlining, getCallerClass() becomes a no-op. // // NOTE that this code must perform the same logic as // vframeStream::security_get_caller_frame in that it must skip // Method.invoke() and auxiliary frames. - - - - bool LibraryCallKit::inline_native_Reflection_getCallerClass() { - ciMethod* method = callee(); - #ifndef PRODUCT if ((PrintIntrinsics || PrintInlining || PrintOptoInlining) && Verbose) { tty->print_cr("Attempting to inline sun.reflect.Reflection.getCallerClass"); } #endif - debug_only(int saved_sp = _sp); - - // Argument words: (int depth) - int nargs = 1; - - _sp += nargs; - Node* caller_depth_node = pop(); - - assert(saved_sp == _sp, "must have correct argument count"); + Node* caller_depth_node = argument(0); // The depth value must be a constant in order for the runtime call // to be eliminated. @@ -4230,7 +3917,8 @@ bool LibraryCallKit::inline_native_Reflection_getCallerClass() { tty->print_cr(" Bailing out because caller depth (%d) exceeded inlining depth (%d)", caller_depth_type->get_con(), _depth); tty->print_cr(" JVM state at this point:"); for (int i = _depth; i >= 1; i--) { - tty->print_cr(" %d) %s", i, jvms()->of_depth(i)->method()->name()->as_utf8()); + ciMethod* m = jvms()->of_depth(i)->method(); + tty->print_cr(" %d) %s.%s", i, m->holder()->name()->as_utf8(), m->name()->as_utf8()); } } #endif @@ -4240,14 +3928,17 @@ bool LibraryCallKit::inline_native_Reflection_getCallerClass() { // Acquire method holder as java.lang.Class ciInstanceKlass* caller_klass = caller_jvms->method()->holder(); ciInstance* caller_mirror = caller_klass->java_mirror(); + // Push this as a constant - push(makecon(TypeInstPtr::make(caller_mirror))); + set_result(makecon(TypeInstPtr::make(caller_mirror))); + #ifndef PRODUCT if ((PrintIntrinsics || PrintInlining || PrintOptoInlining) && Verbose) { tty->print_cr(" Succeeded: caller = %s.%s, caller depth = %d, depth = %d", caller_klass->name()->as_utf8(), caller_jvms->method()->name()->as_utf8(), caller_depth_type->get_con(), _depth); tty->print_cr(" JVM state at this point:"); for (int i = _depth; i >= 1; i--) { - tty->print_cr(" %d) %s", i, jvms()->of_depth(i)->method()->name()->as_utf8()); + ciMethod* m = jvms()->of_depth(i)->method(); + tty->print_cr(" %d) %s.%s", i, m->holder()->name()->as_utf8(), m->name()->as_utf8()); } } #endif @@ -4283,36 +3974,23 @@ bool LibraryCallKit::is_method_invoke_or_aux_frame(JVMState* jvms) { } bool LibraryCallKit::inline_fp_conversions(vmIntrinsics::ID id) { - // restore the arguments - _sp += arg_size(); + Node* arg = argument(0); + Node* result; switch (id) { - case vmIntrinsics::_floatToRawIntBits: - push(_gvn.transform( new (C) MoveF2INode(pop()))); - break; - - case vmIntrinsics::_intBitsToFloat: - push(_gvn.transform( new (C) MoveI2FNode(pop()))); - break; - - case vmIntrinsics::_doubleToRawLongBits: - push_pair(_gvn.transform( new (C) MoveD2LNode(pop_pair()))); - break; - - case vmIntrinsics::_longBitsToDouble: - push_pair(_gvn.transform( new (C) MoveL2DNode(pop_pair()))); - break; + case vmIntrinsics::_floatToRawIntBits: result = new (C) MoveF2INode(arg); break; + case vmIntrinsics::_intBitsToFloat: result = new (C) MoveI2FNode(arg); break; + case vmIntrinsics::_doubleToRawLongBits: result = new (C) MoveD2LNode(arg); break; + case vmIntrinsics::_longBitsToDouble: result = new (C) MoveL2DNode(arg); break; case vmIntrinsics::_doubleToLongBits: { - Node* value = pop_pair(); - // two paths (plus control) merge in a wood RegionNode *r = new (C) RegionNode(3); Node *phi = new (C) PhiNode(r, TypeLong::LONG); - Node *cmpisnan = _gvn.transform( new (C) CmpDNode(value, value)); + Node *cmpisnan = _gvn.transform(new (C) CmpDNode(arg, arg)); // Build the boolean node - Node *bolisnan = _gvn.transform( new (C) BoolNode( cmpisnan, BoolTest::ne ) ); + Node *bolisnan = _gvn.transform(new (C) BoolNode(cmpisnan, BoolTest::ne)); // Branch either way. // NaN case is less traveled, which makes all the difference. @@ -4330,35 +4008,30 @@ bool LibraryCallKit::inline_fp_conversions(vmIntrinsics::ID id) { r->init_req(1, iftrue); // Else fall through - Node *iffalse = _gvn.transform( new (C) IfFalseNode(opt_ifisnan) ); + Node *iffalse = _gvn.transform(new (C) IfFalseNode(opt_ifisnan)); set_control(iffalse); - phi->init_req(2, _gvn.transform( new (C) MoveD2LNode(value))); + phi->init_req(2, _gvn.transform(new (C) MoveD2LNode(arg))); r->init_req(2, iffalse); // Post merge set_control(_gvn.transform(r)); record_for_igvn(r); - Node* result = _gvn.transform(phi); - assert(result->bottom_type()->isa_long(), "must be"); - push_pair(result); - C->set_has_split_ifs(true); // Has chance for split-if optimization - + result = phi; + assert(result->bottom_type()->isa_long(), "must be"); break; } case vmIntrinsics::_floatToIntBits: { - Node* value = pop(); - // two paths (plus control) merge in a wood RegionNode *r = new (C) RegionNode(3); Node *phi = new (C) PhiNode(r, TypeInt::INT); - Node *cmpisnan = _gvn.transform( new (C) CmpFNode(value, value)); + Node *cmpisnan = _gvn.transform(new (C) CmpFNode(arg, arg)); // Build the boolean node - Node *bolisnan = _gvn.transform( new (C) BoolNode( cmpisnan, BoolTest::ne ) ); + Node *bolisnan = _gvn.transform(new (C) BoolNode(cmpisnan, BoolTest::ne)); // Branch either way. // NaN case is less traveled, which makes all the difference. @@ -4376,29 +4049,27 @@ bool LibraryCallKit::inline_fp_conversions(vmIntrinsics::ID id) { r->init_req(1, iftrue); // Else fall through - Node *iffalse = _gvn.transform( new (C) IfFalseNode(opt_ifisnan) ); + Node *iffalse = _gvn.transform(new (C) IfFalseNode(opt_ifisnan)); set_control(iffalse); - phi->init_req(2, _gvn.transform( new (C) MoveF2INode(value))); + phi->init_req(2, _gvn.transform(new (C) MoveF2INode(arg))); r->init_req(2, iffalse); // Post merge set_control(_gvn.transform(r)); record_for_igvn(r); - Node* result = _gvn.transform(phi); - assert(result->bottom_type()->isa_int(), "must be"); - push(result); - C->set_has_split_ifs(true); // Has chance for split-if optimization - + result = phi; + assert(result->bottom_type()->isa_int(), "must be"); break; } default: - ShouldNotReachHere(); + fatal_unexpected_iid(id); + break; } - + set_result(_gvn.transform(result)); return true; } @@ -4409,23 +4080,19 @@ bool LibraryCallKit::inline_fp_conversions(vmIntrinsics::ID id) { #endif //_LP64 //----------------------inline_unsafe_copyMemory------------------------- +// public native void sun.misc.Unsafe.copyMemory(Object srcBase, long srcOffset, Object destBase, long destOffset, long bytes); bool LibraryCallKit::inline_unsafe_copyMemory() { if (callee()->is_static()) return false; // caller must have the capability! - int nargs = 1 + 5 + 3; // 5 args: (src: ptr,off, dst: ptr,off, size) - assert(signature()->size() == nargs-1, "copy has 5 arguments"); - null_check_receiver(callee()); // check then ignore argument(0) + null_check_receiver(); // null-check receiver if (stopped()) return true; C->set_has_unsafe_access(true); // Mark eventual nmethod as "unsafe". - Node* src_ptr = argument(1); - Node* src_off = ConvL2X(argument(2)); - assert(argument(3)->is_top(), "2nd half of long"); - Node* dst_ptr = argument(4); - Node* dst_off = ConvL2X(argument(5)); - assert(argument(6)->is_top(), "2nd half of long"); - Node* size = ConvL2X(argument(7)); - assert(argument(8)->is_top(), "2nd half of long"); + Node* src_ptr = argument(1); // type: oop + Node* src_off = ConvL2X(argument(2)); // type: long + Node* dst_ptr = argument(4); // type: oop + Node* dst_off = ConvL2X(argument(5)); // type: long + Node* size = ConvL2X(argument(7)); // type: long assert(Unsafe_field_offset_to_byte_offset(11) == 11, "fieldOffset must be byte-scaled"); @@ -4545,6 +4212,8 @@ void LibraryCallKit::copy_to_clone(Node* obj, Node* alloc_obj, Node* obj_size, b } //------------------------inline_native_clone---------------------------- +// protected native Object java.lang.Object.clone(); +// // Here are the simple edge cases: // null receiver => normal trap // virtual and clone was overridden => slow path to out-of-line clone @@ -4561,20 +4230,16 @@ void LibraryCallKit::copy_to_clone(Node* obj, Node* alloc_obj, Node* obj_size, b // can be sharply typed as an object array, a type array, or an instance. // bool LibraryCallKit::inline_native_clone(bool is_virtual) { - int nargs = 1; PhiNode* result_val; - //set the original stack and the reexecute bit for the interpreter to reexecute - //the bytecode that invokes Object.clone if deoptimization happens + // Set the reexecute bit for the interpreter to reexecute + // the bytecode that invokes Object.clone if deoptimization happens. { PreserveReexecuteState preexecs(this); jvms()->set_should_reexecute(true); - //null_check_receiver will adjust _sp (push and pop) - Node* obj = null_check_receiver(callee()); + Node* obj = null_check_receiver(); if (stopped()) return true; - _sp += nargs; - Node* obj_klass = load_object_klass(obj); const TypeKlassPtr* tklass = _gvn.type(obj_klass)->isa_klassptr(); const TypeOopPtr* toop = ((tklass != NULL) @@ -4611,7 +4276,7 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) { set_control(array_ctl); Node* obj_length = load_array_length(obj); Node* obj_size = NULL; - Node* alloc_obj = new_array(obj_klass, obj_length, 0, &obj_size); + Node* alloc_obj = new_array(obj_klass, obj_length, 0, &obj_size); // no arguments to push if (!use_ReduceInitialCardMarks()) { // If it is an oop array, it requires very special treatment, @@ -4711,10 +4376,9 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) { set_control( _gvn.transform(result_reg) ); set_i_o( _gvn.transform(result_i_o) ); set_all_memory( _gvn.transform(result_mem) ); - } //original reexecute and sp are set back here - - push(_gvn.transform(result_val)); + } // original reexecute is set back here + set_result(_gvn.transform(result_val)); return true; } @@ -4755,25 +4419,25 @@ address LibraryCallKit::basictype2arraycopy(BasicType t, //------------------------------inline_arraycopy----------------------- +// public static native void java.lang.System.arraycopy(Object src, int srcPos, +// Object dest, int destPos, +// int length); bool LibraryCallKit::inline_arraycopy() { - // Restore the stack and pop off the arguments. - int nargs = 5; // 2 oops, 3 ints, no size_t or long - assert(callee()->signature()->size() == nargs, "copy has 5 arguments"); - - Node *src = argument(0); - Node *src_offset = argument(1); - Node *dest = argument(2); - Node *dest_offset = argument(3); - Node *length = argument(4); + // Get the arguments. + Node* src = argument(0); // type: oop + Node* src_offset = argument(1); // type: int + Node* dest = argument(2); // type: oop + Node* dest_offset = argument(3); // type: int + Node* length = argument(4); // type: int // Compile time checks. If any of these checks cannot be verified at compile time, // we do not make a fast path for this call. Instead, we let the call remain as it // is. The checks we choose to mandate at compile time are: // // (1) src and dest are arrays. - const Type* src_type = src->Value(&_gvn); + const Type* src_type = src->Value(&_gvn); const Type* dest_type = dest->Value(&_gvn); - const TypeAryPtr* top_src = src_type->isa_aryptr(); + const TypeAryPtr* top_src = src_type->isa_aryptr(); const TypeAryPtr* top_dest = dest_type->isa_aryptr(); if (top_src == NULL || top_src->klass() == NULL || top_dest == NULL || top_dest->klass() == NULL) { @@ -4828,15 +4492,13 @@ bool LibraryCallKit::inline_arraycopy() { record_for_igvn(slow_region); // (3) operands must not be null - // We currently perform our null checks with the do_null_check routine. + // We currently perform our null checks with the null_check routine. // This means that the null exceptions will be reported in the caller // rather than (correctly) reported inside of the native arraycopy call. // This should be corrected, given time. We do our null check with the // stack pointer restored. - _sp += nargs; - src = do_null_check(src, T_ARRAY); - dest = do_null_check(dest, T_ARRAY); - _sp -= nargs; + src = null_check(src, T_ARRAY); + dest = null_check(dest, T_ARRAY); // (4) src_offset must not be negative. generate_negative_guard(src_offset, slow_region); @@ -5179,7 +4841,7 @@ LibraryCallKit::generate_arraycopy(const TypePtr* adr_type, slow_control = top(); if (slow_region != NULL) slow_control = _gvn.transform(slow_region); - debug_only(slow_region = (RegionNode*)badAddress); + DEBUG_ONLY(slow_region = (RegionNode*)badAddress); set_control(checked_control); if (!stopped()) { @@ -5674,33 +5336,22 @@ LibraryCallKit::generate_unchecked_arraycopy(const TypePtr* adr_type, } //----------------------------inline_reference_get---------------------------- - +// public T java.lang.ref.Reference.get(); bool LibraryCallKit::inline_reference_get() { - const int nargs = 1; // self - - guarantee(java_lang_ref_Reference::referent_offset > 0, - "should have already been set"); - - int referent_offset = java_lang_ref_Reference::referent_offset; - - // Restore the stack and pop off the argument - _sp += nargs; - Node *reference_obj = pop(); - - // Null check on self without removing any arguments. - _sp += nargs; - reference_obj = do_null_check(reference_obj, T_OBJECT); - _sp -= nargs;; + const int referent_offset = java_lang_ref_Reference::referent_offset; + guarantee(referent_offset > 0, "should have already been set"); + // Get the argument: + Node* reference_obj = null_check_receiver(); if (stopped()) return true; - Node *adr = basic_plus_adr(reference_obj, reference_obj, referent_offset); + Node* adr = basic_plus_adr(reference_obj, reference_obj, referent_offset); ciInstanceKlass* klass = env()->Object_klass(); const TypeOopPtr* object_type = TypeOopPtr::make_from_klass(klass); Node* no_ctrl = NULL; - Node *result = make_load(no_ctrl, adr, object_type, T_OBJECT); + Node* result = make_load(no_ctrl, adr, object_type, T_OBJECT); // Use the pre-barrier to record the value in the referent field pre_barrier(false /* do_load */, @@ -5713,7 +5364,7 @@ bool LibraryCallKit::inline_reference_get() { // across safepoint since GC can change its value. insert_mem_bar(Op_MemBarCPUOrder); - push(result); + set_result(result); return true; } @@ -5770,15 +5421,11 @@ bool LibraryCallKit::inline_aescrypt_Block(vmIntrinsics::ID id) { } if (stubAddr == NULL) return false; - // Restore the stack and pop off the arguments. - int nargs = 5; // this + 2 oop/offset combos - assert(callee()->signature()->size() == nargs-1, "encryptBlock has 4 arguments"); - - Node *aescrypt_object = argument(0); - Node *src = argument(1); - Node *src_offset = argument(2); - Node *dest = argument(3); - Node *dest_offset = argument(4); + Node* aescrypt_object = argument(0); + Node* src = argument(1); + Node* src_offset = argument(2); + Node* dest = argument(3); + Node* dest_offset = argument(4); // (1) src and dest are arrays. const Type* src_type = src->Value(&_gvn); @@ -5829,16 +5476,12 @@ bool LibraryCallKit::inline_cipherBlockChaining_AESCrypt(vmIntrinsics::ID id) { } if (stubAddr == NULL) return false; - - // Restore the stack and pop off the arguments. - int nargs = 6; // this + oop/offset + len + oop/offset - assert(callee()->signature()->size() == nargs-1, "wrong number of arguments"); - Node *cipherBlockChaining_object = argument(0); - Node *src = argument(1); - Node *src_offset = argument(2); - Node *len = argument(3); - Node *dest = argument(4); - Node *dest_offset = argument(5); + Node* cipherBlockChaining_object = argument(0); + Node* src = argument(1); + Node* src_offset = argument(2); + Node* len = argument(3); + Node* dest = argument(4); + Node* dest_offset = argument(5); // (1) src and dest are arrays. const Type* src_type = src->Value(&_gvn); @@ -5920,11 +5563,8 @@ Node * LibraryCallKit::get_key_start_from_aescrypt_object(Node *aescrypt_object) // Node* LibraryCallKit::inline_cipherBlockChaining_AESCrypt_predicate(bool decrypting) { // First, check receiver for NULL since it is virtual method. - int nargs = arg_size(); Node* objCBC = argument(0); - _sp += nargs; - objCBC = do_null_check(objCBC, T_OBJECT); - _sp -= nargs; + objCBC = null_check(objCBC); if (stopped()) return NULL; // Always NULL @@ -5948,9 +5588,7 @@ Node* LibraryCallKit::inline_cipherBlockChaining_AESCrypt_predicate(bool decrypt } ciInstanceKlass* instklass_AESCrypt = klass_AESCrypt->as_instance_klass(); - _sp += nargs; // gen_instanceof might do an uncommon trap Node* instof = gen_instanceof(embeddedCipherObj, makecon(TypeKlassPtr::make(instklass_AESCrypt))); - _sp -= nargs; Node* cmp_instof = _gvn.transform(new (C) CmpINode(instof, intcon(1))); Node* bool_instof = _gvn.transform(new (C) BoolNode(cmp_instof, BoolTest::ne)); @@ -5966,7 +5604,7 @@ Node* LibraryCallKit::inline_cipherBlockChaining_AESCrypt_predicate(bool decrypt RegionNode* region = new(C) RegionNode(3); region->init_req(1, instof_false); Node* src = argument(1); - Node *dest = argument(4); + Node* dest = argument(4); Node* cmp_src_dest = _gvn.transform(new (C) CmpPNode(src, dest)); Node* bool_src_dest = _gvn.transform(new (C) BoolNode(cmp_src_dest, BoolTest::eq)); Node* src_dest_conjoint = generate_guard(bool_src_dest, NULL, PROB_MIN); @@ -5974,7 +5612,4 @@ Node* LibraryCallKit::inline_cipherBlockChaining_AESCrypt_predicate(bool decrypt record_for_igvn(region); return _gvn.transform(region); - } - - diff --git a/hotspot/src/share/vm/opto/locknode.cpp b/hotspot/src/share/vm/opto/locknode.cpp index 1e6a6c20c84..26c6291686b 100644 --- a/hotspot/src/share/vm/opto/locknode.cpp +++ b/hotspot/src/share/vm/opto/locknode.cpp @@ -165,7 +165,7 @@ void Parse::do_monitor_enter() { kill_dead_locals(); // Null check; get casted pointer. - Node *obj = do_null_check(peek(), T_OBJECT); + Node* obj = null_check(peek()); // Check for locking null object if (stopped()) return; diff --git a/hotspot/src/share/vm/opto/loopTransform.cpp b/hotspot/src/share/vm/opto/loopTransform.cpp index 53d0fffdc31..259e10a56df 100644 --- a/hotspot/src/share/vm/opto/loopTransform.cpp +++ b/hotspot/src/share/vm/opto/loopTransform.cpp @@ -269,10 +269,10 @@ void IdealLoopTree::reassociate_invariants(PhaseIdealLoop *phase) { bool IdealLoopTree::policy_peeling( PhaseIdealLoop *phase ) const { Node *test = ((IdealLoopTree*)this)->tail(); int body_size = ((IdealLoopTree*)this)->_body.size(); - int uniq = phase->C->unique(); + int live_node_count = phase->C->live_nodes(); // Peeling does loop cloning which can result in O(N^2) node construction if( body_size > 255 /* Prevent overflow for large body_size */ - || (body_size * body_size + uniq > MaxNodeLimit) ) { + || (body_size * body_size + live_node_count > MaxNodeLimit) ) { return false; // too large to safely clone } while( test != _head ) { // Scan till run off top of loop @@ -601,7 +601,7 @@ bool IdealLoopTree::policy_maximally_unroll( PhaseIdealLoop *phase ) const { return false; if (new_body_size > unroll_limit || // Unrolling can result in a large amount of node construction - new_body_size >= MaxNodeLimit - phase->C->unique()) { + new_body_size >= MaxNodeLimit - (uint) phase->C->live_nodes()) { return false; } @@ -2268,7 +2268,7 @@ bool IdealLoopTree::iteration_split_impl( PhaseIdealLoop *phase, Node_List &old_ // Skip next optimizations if running low on nodes. Note that // policy_unswitching and policy_maximally_unroll have this check. - uint nodes_left = MaxNodeLimit - phase->C->unique(); + uint nodes_left = MaxNodeLimit - (uint) phase->C->live_nodes(); if ((2 * _body.size()) > nodes_left) { return true; } diff --git a/hotspot/src/share/vm/opto/loopUnswitch.cpp b/hotspot/src/share/vm/opto/loopUnswitch.cpp index fc3380f4909..047c00e8021 100644 --- a/hotspot/src/share/vm/opto/loopUnswitch.cpp +++ b/hotspot/src/share/vm/opto/loopUnswitch.cpp @@ -59,7 +59,7 @@ bool IdealLoopTree::policy_unswitching( PhaseIdealLoop *phase ) const { if (!_head->is_Loop()) { return false; } - uint nodes_left = MaxNodeLimit - phase->C->unique(); + uint nodes_left = MaxNodeLimit - phase->C->live_nodes(); if (2 * _body.size() > nodes_left) { return false; // Too speculative if running low on nodes. } diff --git a/hotspot/src/share/vm/opto/loopopts.cpp b/hotspot/src/share/vm/opto/loopopts.cpp index 015a063a815..31f080dbf7b 100644 --- a/hotspot/src/share/vm/opto/loopopts.cpp +++ b/hotspot/src/share/vm/opto/loopopts.cpp @@ -729,7 +729,7 @@ static bool merge_point_too_heavy(Compile* C, Node* region) { for (DUIterator_Fast imax, i = region->fast_outs(imax); i < imax; i++) { weight += region->fast_out(i)->outcnt(); } - int nodes_left = MaxNodeLimit - C->unique(); + int nodes_left = MaxNodeLimit - C->live_nodes(); if (weight * 8 > nodes_left) { #ifndef PRODUCT if (PrintOpto) diff --git a/hotspot/src/share/vm/opto/macro.cpp b/hotspot/src/share/vm/opto/macro.cpp index 16987d97468..2c45140816e 100644 --- a/hotspot/src/share/vm/opto/macro.cpp +++ b/hotspot/src/share/vm/opto/macro.cpp @@ -2262,7 +2262,7 @@ void PhaseMacroExpand::expand_lock_node(LockNode *lock) { Node *slow_ctrl = _fallthroughproj->clone(); transform_later(slow_ctrl); _igvn.hash_delete(_fallthroughproj); - _fallthroughproj->disconnect_inputs(NULL); + _fallthroughproj->disconnect_inputs(NULL, C); region->init_req(1, slow_ctrl); // region inputs are now complete transform_later(region); @@ -2327,7 +2327,7 @@ void PhaseMacroExpand::expand_unlock_node(UnlockNode *unlock) { Node *slow_ctrl = _fallthroughproj->clone(); transform_later(slow_ctrl); _igvn.hash_delete(_fallthroughproj); - _fallthroughproj->disconnect_inputs(NULL); + _fallthroughproj->disconnect_inputs(NULL, C); region->init_req(1, slow_ctrl); // region inputs are now complete transform_later(region); diff --git a/hotspot/src/share/vm/opto/matcher.cpp b/hotspot/src/share/vm/opto/matcher.cpp index 53924d0c9a0..0c6f5ea8ec2 100644 --- a/hotspot/src/share/vm/opto/matcher.cpp +++ b/hotspot/src/share/vm/opto/matcher.cpp @@ -342,6 +342,7 @@ void Matcher::match( ) { // Reset node counter so MachNodes start with _idx at 0 int nodes = C->unique(); // save value C->set_unique(0); + C->reset_dead_node_list(); // Recursively match trees from old space into new space. // Correct leaves of new-space Nodes; they point to old-space. diff --git a/hotspot/src/share/vm/opto/node.cpp b/hotspot/src/share/vm/opto/node.cpp index cc35098e823..4c83d906003 100644 --- a/hotspot/src/share/vm/opto/node.cpp +++ b/hotspot/src/share/vm/opto/node.cpp @@ -57,7 +57,7 @@ void Node::verify_construction() { int new_debug_idx = old_debug_idx+1; if (new_debug_idx > 0) { // Arrange that the lowest five decimal digits of _debug_idx - // will repeat thos of _idx. In case this is somehow pathological, + // will repeat those of _idx. In case this is somehow pathological, // we continue to assign negative numbers (!) consecutively. const int mod = 100000; int bump = (int)(_idx - new_debug_idx) % mod; @@ -67,7 +67,7 @@ void Node::verify_construction() { } Compile::set_debug_idx(new_debug_idx); set_debug_idx( new_debug_idx ); - assert(Compile::current()->unique() < (uint)MaxNodeLimit, "Node limit exceeded"); + assert(Compile::current()->unique() < (UINT_MAX - 1), "Node limit exceeded UINT_MAX"); if (BreakAtNode != 0 && (_debug_idx == BreakAtNode || (int)_idx == BreakAtNode)) { tty->print_cr("BreakAtNode: _idx=%d _debug_idx=%d", _idx, _debug_idx); BREAKPOINT; @@ -802,7 +802,7 @@ int Node::replace_edge(Node* old, Node* neww) { //-------------------------disconnect_inputs----------------------------------- // NULL out all inputs to eliminate incoming Def-Use edges. // Return the number of edges between 'n' and 'this' -int Node::disconnect_inputs(Node *n) { +int Node::disconnect_inputs(Node *n, Compile* C) { int edges_to_n = 0; uint cnt = req(); @@ -824,6 +824,9 @@ int Node::disconnect_inputs(Node *n) { // Node::destruct requires all out edges be deleted first // debug_only(destruct();) // no reuse benefit expected + if (edges_to_n == 0) { + C->record_dead_node(_idx); + } return edges_to_n; } diff --git a/hotspot/src/share/vm/opto/node.hpp b/hotspot/src/share/vm/opto/node.hpp index f746f2e42af..f0c1df3a8b0 100644 --- a/hotspot/src/share/vm/opto/node.hpp +++ b/hotspot/src/share/vm/opto/node.hpp @@ -410,7 +410,7 @@ protected: int replace_edge(Node* old, Node* neww); // NULL out all inputs to eliminate incoming Def-Use edges. // Return the number of edges between 'n' and 'this' - int disconnect_inputs(Node *n); + int disconnect_inputs(Node *n, Compile *c); // Quickly, return true if and only if I am Compile::current()->top(). bool is_top() const { @@ -458,9 +458,9 @@ public: void replace_by(Node* new_node); // Globally replace this node by a given new node, updating all uses // and cutting input edges of old node. - void subsume_by(Node* new_node) { + void subsume_by(Node* new_node, Compile* c) { replace_by(new_node); - disconnect_inputs(NULL); + disconnect_inputs(NULL, c); } void set_req_X( uint i, Node *n, PhaseIterGVN *igvn ); // Find the one non-null required input. RegionNode only diff --git a/hotspot/src/share/vm/opto/output.cpp b/hotspot/src/share/vm/opto/output.cpp index f16bbc6fb55..b0d7a9948ea 100644 --- a/hotspot/src/share/vm/opto/output.cpp +++ b/hotspot/src/share/vm/opto/output.cpp @@ -513,7 +513,7 @@ void Compile::shorten_branches(uint* blk_starts, int& code_size, int& reloc_size } adjust_block_start += diff; b->_nodes.map(idx, replacement); - mach->subsume_by(replacement); + mach->subsume_by(replacement, C); mach = replacement; progress = true; @@ -1425,7 +1425,7 @@ void Compile::fill_buffer(CodeBuffer* cb, uint* blk_starts) { jmp_rule[i] = mach->rule(); #endif b->_nodes.map(j, replacement); - mach->subsume_by(replacement); + mach->subsume_by(replacement, C); n = replacement; mach = replacement; } diff --git a/hotspot/src/share/vm/opto/parse1.cpp b/hotspot/src/share/vm/opto/parse1.cpp index d0b52f554ec..7009352917f 100644 --- a/hotspot/src/share/vm/opto/parse1.cpp +++ b/hotspot/src/share/vm/opto/parse1.cpp @@ -601,8 +601,8 @@ Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses) set_map(entry_map); do_exits(); - if (log) log->done("parse nodes='%d' memory='%d'", - C->unique(), C->node_arena()->used()); + if (log) log->done("parse nodes='%d' live='%d' memory='%d'", + C->unique(), C->live_nodes(), C->node_arena()->used()); } //---------------------------do_all_blocks------------------------------------- @@ -1008,7 +1008,7 @@ SafePointNode* Parse::create_entry_map() { // If this is an inlined method, we may have to do a receiver null check. if (_caller->has_method() && is_normal_parse() && !method()->is_static()) { GraphKit kit(_caller); - kit.null_check_receiver(method()); + kit.null_check_receiver_before_call(method()); _caller = kit.transfer_exceptions_into_jvms(); if (kit.stopped()) { _exits.add_exception_states_from(_caller); @@ -1398,7 +1398,7 @@ void Parse::do_one_block() { #ifdef ASSERT int pre_bc_sp = sp(); int inputs, depth; - bool have_se = !stopped() && compute_stack_effects(inputs, depth, /*for_parse*/ true); + bool have_se = !stopped() && compute_stack_effects(inputs, depth); assert(!have_se || pre_bc_sp >= inputs, err_msg_res("have enough stack to execute this BC: pre_bc_sp=%d, inputs=%d", pre_bc_sp, inputs)); #endif //ASSERT diff --git a/hotspot/src/share/vm/opto/parse2.cpp b/hotspot/src/share/vm/opto/parse2.cpp index af91156dad3..9a14c9a58f9 100644 --- a/hotspot/src/share/vm/opto/parse2.cpp +++ b/hotspot/src/share/vm/opto/parse2.cpp @@ -48,7 +48,7 @@ void Parse::array_load(BasicType elem_type) { const Type* elem = Type::TOP; Node* adr = array_addressing(elem_type, 0, &elem); if (stopped()) return; // guaranteed null or range check - _sp -= 2; // Pop array and index + dec_sp(2); // Pop array and index const TypeAryPtr* adr_type = TypeAryPtr::get_array_body_type(elem_type); Node* ld = make_load(control(), adr, elem, elem_type, adr_type); push(ld); @@ -60,7 +60,7 @@ void Parse::array_store(BasicType elem_type) { Node* adr = array_addressing(elem_type, 1); if (stopped()) return; // guaranteed null or range check Node* val = pop(); - _sp -= 2; // Pop array and index + dec_sp(2); // Pop array and index const TypeAryPtr* adr_type = TypeAryPtr::get_array_body_type(elem_type); store_to_memory(control(), adr, val, elem_type, adr_type); } @@ -73,7 +73,7 @@ Node* Parse::array_addressing(BasicType type, int vals, const Type* *result2) { Node *ary = peek(1+vals); // in case of exception // Null check the array base, with correct stack contents - ary = do_null_check(ary, T_ARRAY); + ary = null_check(ary, T_ARRAY); // Compile-time detect of null-exception? if (stopped()) return top(); @@ -681,7 +681,7 @@ void Parse::l2f() { void Parse::do_irem() { // Must keep both values on the expression-stack during null-check - do_null_check(peek(), T_INT); + zero_check_int(peek()); // Compile-time detect of null-exception? if (stopped()) return; @@ -958,7 +958,7 @@ inline int Parse::repush_if_args() { DEBUG_ONLY(sync_jvms()); // argument(n) requires a synced jvms assert(argument(0) != NULL, "must exist"); assert(bc_depth == 1 || argument(1) != NULL, "two must exist"); - _sp += bc_depth; + inc_sp(bc_depth); return bc_depth; } @@ -1581,8 +1581,8 @@ void Parse::do_one_bytecode() { set_pair_local( iter().get_index(), dstore_rounding(pop_pair()) ); break; - case Bytecodes::_pop: _sp -= 1; break; - case Bytecodes::_pop2: _sp -= 2; break; + case Bytecodes::_pop: dec_sp(1); break; + case Bytecodes::_pop2: dec_sp(2); break; case Bytecodes::_swap: a = pop(); b = pop(); @@ -1650,7 +1650,7 @@ void Parse::do_one_bytecode() { case Bytecodes::_arraylength: { // Must do null-check with value on expression stack - Node *ary = do_null_check(peek(), T_ARRAY); + Node *ary = null_check(peek(), T_ARRAY); // Compile-time detect of null-exception? if (stopped()) return; a = pop(); @@ -1667,15 +1667,15 @@ void Parse::do_one_bytecode() { case Bytecodes::_laload: { a = array_addressing(T_LONG, 0); if (stopped()) return; // guaranteed null or range check - _sp -= 2; // Pop array and index - push_pair( make_load(control(), a, TypeLong::LONG, T_LONG, TypeAryPtr::LONGS)); + dec_sp(2); // Pop array and index + push_pair(make_load(control(), a, TypeLong::LONG, T_LONG, TypeAryPtr::LONGS)); break; } case Bytecodes::_daload: { a = array_addressing(T_DOUBLE, 0); if (stopped()) return; // guaranteed null or range check - _sp -= 2; // Pop array and index - push_pair( make_load(control(), a, Type::DOUBLE, T_DOUBLE, TypeAryPtr::DOUBLES)); + dec_sp(2); // Pop array and index + push_pair(make_load(control(), a, Type::DOUBLE, T_DOUBLE, TypeAryPtr::DOUBLES)); break; } case Bytecodes::_bastore: array_store(T_BYTE); break; @@ -1699,7 +1699,7 @@ void Parse::do_one_bytecode() { a = array_addressing(T_LONG, 2); if (stopped()) return; // guaranteed null or range check c = pop_pair(); - _sp -= 2; // Pop array and index + dec_sp(2); // Pop array and index store_to_memory(control(), a, c, T_LONG, TypeAryPtr::LONGS); break; } @@ -1707,7 +1707,7 @@ void Parse::do_one_bytecode() { a = array_addressing(T_DOUBLE, 2); if (stopped()) return; // guaranteed null or range check c = pop_pair(); - _sp -= 2; // Pop array and index + dec_sp(2); // Pop array and index c = dstore_rounding(c); store_to_memory(control(), a, c, T_DOUBLE, TypeAryPtr::DOUBLES); break; @@ -1733,7 +1733,7 @@ void Parse::do_one_bytecode() { break; case Bytecodes::_idiv: // Must keep both values on the expression-stack during null-check - do_null_check(peek(), T_INT); + zero_check_int(peek()); // Compile-time detect of null-exception? if (stopped()) return; b = pop(); @@ -2041,7 +2041,7 @@ void Parse::do_one_bytecode() { case Bytecodes::_lrem: // Must keep both values on the expression-stack during null-check assert(peek(0) == top(), "long word order"); - do_null_check(peek(1), T_LONG); + zero_check_long(peek(1)); // Compile-time detect of null-exception? if (stopped()) return; b = pop_pair(); @@ -2053,7 +2053,7 @@ void Parse::do_one_bytecode() { case Bytecodes::_ldiv: // Must keep both values on the expression-stack during null-check assert(peek(0) == top(), "long word order"); - do_null_check(peek(1), T_LONG); + zero_check_long(peek(1)); // Compile-time detect of null-exception? if (stopped()) return; b = pop_pair(); @@ -2175,7 +2175,7 @@ void Parse::do_one_bytecode() { case Bytecodes::_athrow: // null exception oop throws NULL pointer exception - do_null_check(peek(), T_OBJECT); + null_check(peek()); if (stopped()) return; // Hook the thrown exception directly to subsequent handlers. if (BailoutToInterpreterForThrows) { diff --git a/hotspot/src/share/vm/opto/parse3.cpp b/hotspot/src/share/vm/opto/parse3.cpp index 119fe7d1922..0f92b53f135 100644 --- a/hotspot/src/share/vm/opto/parse3.cpp +++ b/hotspot/src/share/vm/opto/parse3.cpp @@ -116,7 +116,7 @@ void Parse::do_field_access(bool is_get, bool is_field) { Node* obj; if (is_field) { int obj_depth = is_get ? 0 : field->type()->size(); - obj = do_null_check(peek(obj_depth), T_OBJECT); + obj = null_check(peek(obj_depth)); // Compile-time detect of null-exception? if (stopped()) return; @@ -126,11 +126,11 @@ void Parse::do_field_access(bool is_get, bool is_field) { #endif if (is_get) { - --_sp; // pop receiver before getting + (void) pop(); // pop receiver before getting do_get_xxx(obj, field, is_field); } else { do_put_xxx(obj, field, is_field); - --_sp; // pop receiver after putting + (void) pop(); // pop receiver after putting } } else { const TypeInstPtr* tip = TypeInstPtr::make(field_holder->java_mirror()); @@ -230,7 +230,7 @@ void Parse::do_get_xxx(Node* obj, ciField* field, bool is_field) { } // If there is going to be a trap, put it at the next bytecode: set_bci(iter().next_bci()); - do_null_assert(peek(), T_OBJECT); + null_assert(peek()); set_bci(iter().cur_bci()); // put it back } @@ -463,7 +463,7 @@ void Parse::do_multianewarray() { // Note: the reexecute bit will be set in GraphKit::add_safepoint_edges() // when AllocateArray node for newarray is created. { PreserveReexecuteState preexecs(this); - _sp += ndimensions; + inc_sp(ndimensions); // Pass 0 as nargs since uncommon trap code does not need to restore stack. obj = expand_multianewarray(array_klass, &length[0], ndimensions, 0); } //original reexecute and sp are set back here @@ -492,7 +492,7 @@ void Parse::do_multianewarray() { // Create a java array for dimension sizes Node* dims = NULL; { PreserveReexecuteState preexecs(this); - _sp += ndimensions; + inc_sp(ndimensions); Node* dims_array_klass = makecon(TypeKlassPtr::make(ciArrayKlass::make(ciType::make(T_INT)))); dims = new_array(dims_array_klass, intcon(ndimensions), 0); diff --git a/hotspot/src/share/vm/opto/parseHelper.cpp b/hotspot/src/share/vm/opto/parseHelper.cpp index 19b0f513366..f2a1bd2bef4 100644 --- a/hotspot/src/share/vm/opto/parseHelper.cpp +++ b/hotspot/src/share/vm/opto/parseHelper.cpp @@ -84,7 +84,7 @@ void Parse::do_checkcast() { C->log()->identify(tp->klass())); } } - do_null_assert(obj, T_OBJECT); + null_assert(obj); assert( stopped() || _gvn.type(peek())->higher_equal(TypePtr::NULL_PTR), "what's left behind is null" ); if (!stopped()) { profile_null_checkcast(); @@ -116,7 +116,7 @@ void Parse::do_instanceof() { C->log()->elem("assert_null reason='instanceof' klass='%d'", C->log()->identify(klass)); } - do_null_assert(peek(), T_OBJECT); + null_assert(peek()); assert( stopped() || _gvn.type(peek())->higher_equal(TypePtr::NULL_PTR), "what's left behind is null" ); if (!stopped()) { // The object is now known to be null. @@ -139,10 +139,10 @@ void Parse::do_instanceof() { // pull array from stack and check that the store is valid void Parse::array_store_check() { - // Shorthand access to array store elements - Node *obj = stack(_sp-1); - Node *idx = stack(_sp-2); - Node *ary = stack(_sp-3); + // Shorthand access to array store elements without popping them. + Node *obj = peek(0); + Node *idx = peek(1); + Node *ary = peek(2); if (_gvn.type(obj) == TypePtr::NULL_PTR) { // There's never a type check on null values. diff --git a/hotspot/src/share/vm/opto/phaseX.cpp b/hotspot/src/share/vm/opto/phaseX.cpp index 849327cf8bb..f2a44f0e7a7 100644 --- a/hotspot/src/share/vm/opto/phaseX.cpp +++ b/hotspot/src/share/vm/opto/phaseX.cpp @@ -383,6 +383,8 @@ PhaseRemoveUseless::PhaseRemoveUseless( PhaseGVN *gvn, Unique_Node_List *worklis // Identify nodes that are reachable from below, useful. C->identify_useful_nodes(_useful); + // Update dead node list + C->update_dead_node_list(_useful); // Remove all useless nodes from PhaseValues' recorded types // Must be done before disconnecting nodes to preserve hash-table-invariant @@ -1190,7 +1192,7 @@ void PhaseIterGVN::remove_globally_dead_node( Node *dead ) { } } } - + C->record_dead_node(dead->_idx); if (dead->is_macro()) { C->remove_macro_node(dead); } @@ -1199,6 +1201,11 @@ void PhaseIterGVN::remove_globally_dead_node( Node *dead ) { continue; } } + // 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 + // as dead to be conservative about the dead node count at any + // given time. } // Aggressively kill globally dead uses diff --git a/hotspot/src/share/vm/opto/postaloc.cpp b/hotspot/src/share/vm/opto/postaloc.cpp index 912e07704e7..a27145b5c7b 100644 --- a/hotspot/src/share/vm/opto/postaloc.cpp +++ b/hotspot/src/share/vm/opto/postaloc.cpp @@ -146,7 +146,7 @@ int PhaseChaitin::yank_if_dead_recurse(Node *old, Node *orig_old, Block *current } } // Disconnect control and remove precedence edges if any exist - old->disconnect_inputs(NULL); + old->disconnect_inputs(NULL, C); } return blk_adjust; } @@ -513,7 +513,7 @@ void PhaseChaitin::post_allocate_copy_removal() { b->_nodes.remove(j--); phi_dex--; _cfg._bbs.map(phi->_idx,NULL); phi->replace_by(u); - phi->disconnect_inputs(NULL); + phi->disconnect_inputs(NULL, C); continue; } // Note that if value[pidx] exists, then we merged no new values here diff --git a/hotspot/src/share/vm/opto/reg_split.cpp b/hotspot/src/share/vm/opto/reg_split.cpp index fe720e89334..1695dee6008 100644 --- a/hotspot/src/share/vm/opto/reg_split.cpp +++ b/hotspot/src/share/vm/opto/reg_split.cpp @@ -747,7 +747,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) { if( i >= cnt ) { // Found one unique input assert(Find_id(n) == Find_id(u), "should be the same lrg"); n->replace_by(u); // Then replace with unique input - n->disconnect_inputs(NULL); + n->disconnect_inputs(NULL, C); b->_nodes.remove(insidx); insidx--; b->_ihrp_index--; diff --git a/hotspot/src/share/vm/opto/stringopts.cpp b/hotspot/src/share/vm/opto/stringopts.cpp index 6be806acc12..c471887d881 100644 --- a/hotspot/src/share/vm/opto/stringopts.cpp +++ b/hotspot/src/share/vm/opto/stringopts.cpp @@ -241,13 +241,13 @@ class StringConcat : public ResourceObj { _stringopts->gvn()->transform(call); C->gvn_replace_by(uct, call); - uct->disconnect_inputs(NULL); + uct->disconnect_inputs(NULL, C); } } void cleanup() { // disconnect the hook node - _arguments->disconnect_inputs(NULL); + _arguments->disconnect_inputs(NULL, _stringopts->C); } }; @@ -358,7 +358,7 @@ void StringConcat::eliminate_initialize(InitializeNode* init) { C->gvn_replace_by(mem_proj, mem); } C->gvn_replace_by(init, C->top()); - init->disconnect_inputs(NULL); + init->disconnect_inputs(NULL, C); } Node_List PhaseStringOpts::collect_toString_calls() { @@ -1477,6 +1477,6 @@ void PhaseStringOpts::replace_string_concat(StringConcat* sc) { kit.replace_call(sc->end(), result); // Unhook any hook nodes - string_sizes->disconnect_inputs(NULL); + string_sizes->disconnect_inputs(NULL, C); sc->cleanup(); } diff --git a/hotspot/src/share/vm/opto/type.hpp b/hotspot/src/share/vm/opto/type.hpp index 39bbf0306a9..7868b2f7856 100644 --- a/hotspot/src/share/vm/opto/type.hpp +++ b/hotspot/src/share/vm/opto/type.hpp @@ -242,8 +242,10 @@ public: const TypeInt *isa_int() const; // Returns NULL if not an Int const TypeLong *is_long() const; const TypeLong *isa_long() const; // Returns NULL if not a Long + const TypeD *isa_double() const; // Returns NULL if not a Double{Top,Con,Bot} const TypeD *is_double_constant() const; // Asserts it is a DoubleCon const TypeD *isa_double_constant() const; // Returns NULL if not a DoubleCon + const TypeF *isa_float() const; // Returns NULL if not a Float{Top,Con,Bot} const TypeF *is_float_constant() const; // Asserts it is a FloatCon const TypeF *isa_float_constant() const; // Returns NULL if not a FloatCon const TypeTuple *is_tuple() const; // Collection of fields, NOT a pointer @@ -1320,24 +1322,6 @@ inline double Type::getd() const { return ((TypeD*)this)->_d; } -inline const TypeF *Type::is_float_constant() const { - assert( _base == FloatCon, "Not a Float" ); - return (TypeF*)this; -} - -inline const TypeF *Type::isa_float_constant() const { - return ( _base == FloatCon ? (TypeF*)this : NULL); -} - -inline const TypeD *Type::is_double_constant() const { - assert( _base == DoubleCon, "Not a Double" ); - return (TypeD*)this; -} - -inline const TypeD *Type::isa_double_constant() const { - return ( _base == DoubleCon ? (TypeD*)this : NULL); -} - inline const TypeInt *Type::is_int() const { assert( _base == Int, "Not an Int" ); return (TypeInt*)this; @@ -1356,6 +1340,36 @@ inline const TypeLong *Type::isa_long() const { return ( _base == Long ? (TypeLong*)this : NULL); } +inline const TypeF *Type::isa_float() const { + return ((_base == FloatTop || + _base == FloatCon || + _base == FloatBot) ? (TypeF*)this : NULL); +} + +inline const TypeF *Type::is_float_constant() const { + assert( _base == FloatCon, "Not a Float" ); + return (TypeF*)this; +} + +inline const TypeF *Type::isa_float_constant() const { + return ( _base == FloatCon ? (TypeF*)this : NULL); +} + +inline const TypeD *Type::isa_double() const { + return ((_base == DoubleTop || + _base == DoubleCon || + _base == DoubleBot) ? (TypeD*)this : NULL); +} + +inline const TypeD *Type::is_double_constant() const { + assert( _base == DoubleCon, "Not a Double" ); + return (TypeD*)this; +} + +inline const TypeD *Type::isa_double_constant() const { + return ( _base == DoubleCon ? (TypeD*)this : NULL); +} + inline const TypeTuple *Type::is_tuple() const { assert( _base == Tuple, "Not a Tuple" ); return (TypeTuple*)this; diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index f850e05cbab..21e5cce7b18 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -1499,13 +1499,12 @@ void Arguments::set_g1_gc_flags() { Abstract_VM_Version::parallel_worker_threads()); } - if (FLAG_IS_DEFAULT(MarkStackSize)) { - FLAG_SET_DEFAULT(MarkStackSize, 128 * TASKQUEUE_SIZE); - } - if (PrintGCDetails && Verbose) { - tty->print_cr("MarkStackSize: %uk MarkStackSizeMax: %uk", - MarkStackSize / K, MarkStackSizeMax / K); - tty->print_cr("ConcGCThreads: %u", ConcGCThreads); + // MarkStackSize will be set (if it hasn't been set by the user) + // when concurrent marking is initialized. + // Its value will be based upon the number of parallel marking threads. + // But we do set the maximum mark stack size here. + if (FLAG_IS_DEFAULT(MarkStackSizeMax)) { + FLAG_SET_DEFAULT(MarkStackSizeMax, 128 * TASKQUEUE_SIZE); } if (FLAG_IS_DEFAULT(GCTimeRatio) || GCTimeRatio == 0) { @@ -1517,6 +1516,12 @@ void Arguments::set_g1_gc_flags() { // is allocation). We might consider increase it further. FLAG_SET_DEFAULT(GCTimeRatio, 9); } + + if (PrintGCDetails && Verbose) { + tty->print_cr("MarkStackSize: %uk MarkStackSizeMax: %uk", + MarkStackSize / K, MarkStackSizeMax / K); + tty->print_cr("ConcGCThreads: %u", ConcGCThreads); + } } void Arguments::set_heap_size() { @@ -1980,6 +1985,9 @@ bool Arguments::check_vm_args_consistency() { status = status && verify_min_value(ClassMetaspaceSize, 1*M, "ClassMetaspaceSize"); + status = status && verify_interval(MarkStackSizeMax, + 1, (max_jint - 1), "MarkStackSizeMax"); + #ifdef SPARC if (UseConcMarkSweepGC || UseG1GC) { // Issue a stern warning if the user has explicitly set diff --git a/hotspot/src/share/vm/runtime/atomic.cpp b/hotspot/src/share/vm/runtime/atomic.cpp index 80780d78066..dbb66b2f63f 100644 --- a/hotspot/src/share/vm/runtime/atomic.cpp +++ b/hotspot/src/share/vm/runtime/atomic.cpp @@ -36,36 +36,8 @@ #ifdef TARGET_OS_FAMILY_bsd # include "os_bsd.inline.hpp" #endif -#ifdef TARGET_OS_ARCH_linux_x86 -# include "atomic_linux_x86.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_linux_sparc -# include "atomic_linux_sparc.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_linux_zero -# include "atomic_linux_zero.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_solaris_x86 -# include "atomic_solaris_x86.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_solaris_sparc -# include "atomic_solaris_sparc.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_windows_x86 -# include "atomic_windows_x86.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_linux_arm -# include "atomic_linux_arm.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_linux_ppc -# include "atomic_linux_ppc.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_bsd_x86 -# include "atomic_bsd_x86.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_bsd_zero -# include "atomic_bsd_zero.inline.hpp" -#endif + +#include "runtime/atomic.inline.hpp" jbyte Atomic::cmpxchg(jbyte exchange_value, volatile jbyte* dest, jbyte compare_value) { assert(sizeof(jbyte) == 1, "assumption."); diff --git a/hotspot/src/share/vm/runtime/atomic.hpp b/hotspot/src/share/vm/runtime/atomic.hpp index 1d5d721f4b1..0c96816d794 100644 --- a/hotspot/src/share/vm/runtime/atomic.hpp +++ b/hotspot/src/share/vm/runtime/atomic.hpp @@ -30,60 +30,59 @@ class Atomic : AllStatic { public: // Atomically store to a location - static void store (jbyte store_value, jbyte* dest); - static void store (jshort store_value, jshort* dest); - static void store (jint store_value, jint* dest); - static void store (jlong store_value, jlong* dest); - static void store_ptr(intptr_t store_value, intptr_t* dest); - static void store_ptr(void* store_value, void* dest); + inline static void store (jbyte store_value, jbyte* dest); + inline static void store (jshort store_value, jshort* dest); + inline static void store (jint store_value, jint* dest); + inline static void store (jlong store_value, jlong* dest); + inline static void store_ptr(intptr_t store_value, intptr_t* dest); + inline static void store_ptr(void* store_value, void* dest); - static void store (jbyte store_value, volatile jbyte* dest); - static void store (jshort store_value, volatile jshort* dest); - static void store (jint store_value, volatile jint* dest); - static void store (jlong store_value, volatile jlong* dest); - static void store_ptr(intptr_t store_value, volatile intptr_t* dest); - static void store_ptr(void* store_value, volatile void* dest); + inline static void store (jbyte store_value, volatile jbyte* dest); + inline static void store (jshort store_value, volatile jshort* dest); + inline static void store (jint store_value, volatile jint* dest); + inline static void store (jlong store_value, volatile jlong* dest); + inline static void store_ptr(intptr_t store_value, volatile intptr_t* dest); + inline static void store_ptr(void* store_value, volatile void* dest); - static jlong load(volatile jlong* src); + inline static jlong load(volatile jlong* src); // Atomically add to a location, return updated value - static jint add (jint add_value, volatile jint* dest); - static intptr_t add_ptr(intptr_t add_value, volatile intptr_t* dest); - static void* add_ptr(intptr_t add_value, volatile void* dest); + inline static jint add (jint add_value, volatile jint* dest); + inline static intptr_t add_ptr(intptr_t add_value, volatile intptr_t* dest); + inline static void* add_ptr(intptr_t add_value, volatile void* dest); - static jlong add (jlong add_value, volatile jlong* dest); + static jlong add (jlong add_value, volatile jlong* dest); // Atomically increment location - static void inc (volatile jint* dest); - static void inc_ptr(volatile intptr_t* dest); - static void inc_ptr(volatile void* dest); + inline static void inc (volatile jint* dest); + inline static void inc_ptr(volatile intptr_t* dest); + inline static void inc_ptr(volatile void* dest); // Atomically decrement a location - static void dec (volatile jint* dest); - static void dec_ptr(volatile intptr_t* dest); - static void dec_ptr(volatile void* dest); + inline static void dec (volatile jint* dest); + inline static void dec_ptr(volatile intptr_t* dest); + inline static void dec_ptr(volatile void* dest); // Performs atomic exchange of *dest with exchange_value. Returns old prior value of *dest. - static jint xchg(jint exchange_value, volatile jint* dest); - static unsigned int xchg(unsigned int exchange_value, - volatile unsigned int* dest); + inline static jint xchg(jint exchange_value, volatile jint* dest); + static unsigned int xchg(unsigned int exchange_value, volatile unsigned int* dest); - static intptr_t xchg_ptr(intptr_t exchange_value, volatile intptr_t* dest); - static void* xchg_ptr(void* exchange_value, volatile void* dest); + inline static intptr_t xchg_ptr(intptr_t exchange_value, volatile intptr_t* dest); + inline static void* xchg_ptr(void* exchange_value, volatile void* dest); // Performs atomic compare of *dest and compare_value, and exchanges *dest with exchange_value // if the comparison succeeded. Returns prior value of *dest. Guarantees a two-way memory // barrier across the cmpxchg. I.e., it's really a 'fence_cmpxchg_acquire'. - static jbyte cmpxchg (jbyte exchange_value, volatile jbyte* dest, jbyte compare_value); - static jint cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value); - static jlong cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value); + static jbyte cmpxchg (jbyte exchange_value, volatile jbyte* dest, jbyte compare_value); + inline static jint cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value); + inline static jlong cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value); - static unsigned int cmpxchg(unsigned int exchange_value, - volatile unsigned int* dest, - unsigned int compare_value); + static unsigned int cmpxchg(unsigned int exchange_value, + volatile unsigned int* dest, + unsigned int compare_value); - static intptr_t cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value); - static void* cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value); + inline static intptr_t cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value); + inline static void* cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value); }; #endif // SHARE_VM_RUNTIME_ATOMIC_HPP diff --git a/hotspot/src/share/vm/runtime/atomic.inline.hpp b/hotspot/src/share/vm/runtime/atomic.inline.hpp new file mode 100644 index 00000000000..e89bf0c0887 --- /dev/null +++ b/hotspot/src/share/vm/runtime/atomic.inline.hpp @@ -0,0 +1,68 @@ +/* + * 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_RUNTIME_ATOMIC_INLINE_HPP +#define SHARE_VM_RUNTIME_ATOMIC_INLINE_HPP + +#include "runtime/atomic.hpp" + +// Linux +#ifdef TARGET_OS_ARCH_linux_x86 +# include "atomic_linux_x86.inline.hpp" +#endif +#ifdef TARGET_OS_ARCH_linux_sparc +# include "atomic_linux_sparc.inline.hpp" +#endif +#ifdef TARGET_OS_ARCH_linux_zero +# include "atomic_linux_zero.inline.hpp" +#endif +#ifdef TARGET_OS_ARCH_linux_arm +# include "atomic_linux_arm.inline.hpp" +#endif +#ifdef TARGET_OS_ARCH_linux_ppc +# include "atomic_linux_ppc.inline.hpp" +#endif + +// Solaris +#ifdef TARGET_OS_ARCH_solaris_x86 +# include "atomic_solaris_x86.inline.hpp" +#endif +#ifdef TARGET_OS_ARCH_solaris_sparc +# include "atomic_solaris_sparc.inline.hpp" +#endif + +// Windows +#ifdef TARGET_OS_ARCH_windows_x86 +# include "atomic_windows_x86.inline.hpp" +#endif + +// BSD +#ifdef TARGET_OS_ARCH_bsd_x86 +# include "atomic_bsd_x86.inline.hpp" +#endif +#ifdef TARGET_OS_ARCH_bsd_zero +# include "atomic_bsd_zero.inline.hpp" +#endif + +#endif // SHARE_VM_RUNTIME_ATOMIC_INLINE_HPP diff --git a/hotspot/src/share/vm/runtime/deoptimization.cpp b/hotspot/src/share/vm/runtime/deoptimization.cpp index c761c0b337d..63df5aa5f88 100644 --- a/hotspot/src/share/vm/runtime/deoptimization.cpp +++ b/hotspot/src/share/vm/runtime/deoptimization.cpp @@ -1242,8 +1242,8 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* thread, jint tra nmethodLocker nl(fr.pc()); // Log a message - Events::log_deopt_message(thread, "Uncommon trap %d fr.pc " INTPTR_FORMAT, - trap_request, fr.pc()); + Events::log(thread, "Uncommon trap: trap_request=" PTR32_FORMAT " fr.pc=" INTPTR_FORMAT, + trap_request, fr.pc()); { ResourceMark rm; @@ -1274,6 +1274,11 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* thread, jint tra MethodData* trap_mdo = get_method_data(thread, trap_method, create_if_missing); + // Log a message + Events::log_deopt_message(thread, "Uncommon trap: reason=%s action=%s pc=" INTPTR_FORMAT " method=%s @ %d", + trap_reason_name(reason), trap_action_name(action), fr.pc(), + trap_method->name_and_sig_as_C_string(), trap_bci); + // Print a bunch of diagnostics, if requested. if (TraceDeoptimization || LogCompilation) { ResourceMark rm; diff --git a/hotspot/src/share/vm/runtime/frame.cpp b/hotspot/src/share/vm/runtime/frame.cpp index 1788d3d0de4..f20fca0154c 100644 --- a/hotspot/src/share/vm/runtime/frame.cpp +++ b/hotspot/src/share/vm/runtime/frame.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "compiler/disassembler.hpp" #include "gc_interface/collectedHeap.inline.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/oopMapCache.hpp" diff --git a/hotspot/src/share/vm/runtime/frame.hpp b/hotspot/src/share/vm/runtime/frame.hpp index 6e990dce73d..2e27430f7fb 100644 --- a/hotspot/src/share/vm/runtime/frame.hpp +++ b/hotspot/src/share/vm/runtime/frame.hpp @@ -25,7 +25,6 @@ #ifndef SHARE_VM_RUNTIME_FRAME_HPP #define SHARE_VM_RUNTIME_FRAME_HPP -#include "asm/assembler.hpp" #include "oops/method.hpp" #include "runtime/basicLock.hpp" #include "runtime/monitorChunk.hpp" diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.cpp b/hotspot/src/share/vm/runtime/sharedRuntime.cpp index 363f065bcd8..539235422d6 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp @@ -31,6 +31,7 @@ #include "compiler/abstractCompiler.hpp" #include "compiler/compileBroker.hpp" #include "compiler/compilerOracle.hpp" +#include "compiler/disassembler.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/interpreterRuntime.hpp" #include "memory/gcLocker.inline.hpp" diff --git a/hotspot/src/share/vm/runtime/stubCodeGenerator.cpp b/hotspot/src/share/vm/runtime/stubCodeGenerator.cpp index b6068a5d9c7..2ba8e159fec 100644 --- a/hotspot/src/share/vm/runtime/stubCodeGenerator.cpp +++ b/hotspot/src/share/vm/runtime/stubCodeGenerator.cpp @@ -23,25 +23,13 @@ */ #include "precompiled.hpp" +#include "asm/macroAssembler.hpp" +#include "asm/macroAssembler.inline.hpp" +#include "code/codeCache.hpp" #include "compiler/disassembler.hpp" #include "oops/oop.inline.hpp" #include "prims/forte.hpp" #include "runtime/stubCodeGenerator.hpp" -#ifdef TARGET_ARCH_x86 -# include "assembler_x86.inline.hpp" -#endif -#ifdef TARGET_ARCH_sparc -# include "assembler_sparc.inline.hpp" -#endif -#ifdef TARGET_ARCH_zero -# include "assembler_zero.inline.hpp" -#endif -#ifdef TARGET_ARCH_arm -# include "assembler_arm.inline.hpp" -#endif -#ifdef TARGET_ARCH_ppc -# include "assembler_ppc.inline.hpp" -#endif // Implementation of StubCodeDesc diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index 23b0bbf32ad..9ca52bec2cf 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -3667,7 +3667,7 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { } // initialize compiler(s) -#if defined(COMPILER1) || defined(COMPILER2) +#if defined(COMPILER1) || defined(COMPILER2) || defined(SHARK) CompileBroker::compilation_init(); #endif diff --git a/hotspot/src/share/vm/runtime/timer.cpp b/hotspot/src/share/vm/runtime/timer.cpp index 640fb50fefb..838262650e9 100644 --- a/hotspot/src/share/vm/runtime/timer.cpp +++ b/hotspot/src/share/vm/runtime/timer.cpp @@ -210,8 +210,9 @@ TraceCPUTime::~TraceCPUTime() { } else { _logfile->print("[Error in TraceCPUTime]"); } - if (_print_cr) { + if (_print_cr) { _logfile->print_cr(""); } + _logfile->flush(); } } diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index 9346d6c72a7..9ac10e26d4c 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -355,8 +355,6 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; nonstatic_field(Method, _access_flags, AccessFlags) \ nonstatic_field(Method, _vtable_index, int) \ nonstatic_field(Method, _method_size, u2) \ - nonstatic_field(Method, _max_locals, u2) \ - nonstatic_field(Method, _size_of_parameters, u2) \ nonstatic_field(Method, _interpreter_throwout_count, u2) \ nonstatic_field(Method, _number_of_breakpoints, u2) \ nonstatic_field(Method, _invocation_counter, InvocationCounter) \ @@ -378,6 +376,8 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; nonstatic_field(ConstMethod, _signature_index, u2) \ nonstatic_field(ConstMethod, _method_idnum, u2) \ nonstatic_field(ConstMethod, _max_stack, u2) \ + nonstatic_field(ConstMethod, _max_locals, u2) \ + nonstatic_field(ConstMethod, _size_of_parameters, u2) \ nonstatic_field(ObjArrayKlass, _element_klass, Klass*) \ nonstatic_field(ObjArrayKlass, _bottom_klass, Klass*) \ volatile_nonstatic_field(Symbol, _refcount, int) \ diff --git a/hotspot/src/share/vm/shark/llvmHeaders.hpp b/hotspot/src/share/vm/shark/llvmHeaders.hpp index ab05e027274..1f2c2c79778 100644 --- a/hotspot/src/share/vm/shark/llvmHeaders.hpp +++ b/hotspot/src/share/vm/shark/llvmHeaders.hpp @@ -35,6 +35,7 @@ #undef DEBUG #endif +#include #include #include #include @@ -42,29 +43,21 @@ #include #include #include -#if SHARK_LLVM_VERSION < 27 -#include -#endif +#if SHARK_LLVM_VERSION <= 31 #include -#if SHARK_LLVM_VERSION >= 29 -#include #else -#include +#include #endif -#include +#include +#include #include #include #include -#if SHARK_LLVM_VERSION >= 27 +#include #include #include #include -#if SHARK_LLVM_VERSION >= 29 #include -#else -#include -#endif -#endif #include diff --git a/hotspot/src/share/vm/shark/llvmValue.hpp b/hotspot/src/share/vm/shark/llvmValue.hpp index f7451ac715e..4eef6ef8142 100644 --- a/hotspot/src/share/vm/shark/llvmValue.hpp +++ b/hotspot/src/share/vm/shark/llvmValue.hpp @@ -56,6 +56,10 @@ class LLVMValue : public AllStatic { { return llvm::ConstantPointerNull::get(SharkType::oop_type()); } + static llvm::ConstantPointerNull* nullKlass() + { + return llvm::ConstantPointerNull::get(SharkType::klass_type()); + } public: static llvm::ConstantInt* bit_constant(int value) diff --git a/hotspot/src/share/vm/shark/sharkBlock.cpp b/hotspot/src/share/vm/shark/sharkBlock.cpp index 6c8bee378ba..b4e98365efc 100644 --- a/hotspot/src/share/vm/shark/sharkBlock.cpp +++ b/hotspot/src/share/vm/shark/sharkBlock.cpp @@ -170,10 +170,12 @@ void SharkBlock::parse_bytecode(int start, int limit) { case Bytecodes::_ldc: case Bytecodes::_ldc_w: - case Bytecodes::_ldc2_w: - push(SharkConstant::for_ldc(iter())->value(builder())); + case Bytecodes::_ldc2_w: { + SharkConstant* constant = SharkConstant::for_ldc(iter()); + assert(constant->is_loaded(), "trap should handle unloaded classes"); + push(constant->value(builder())); break; - + } case Bytecodes::_iload_0: case Bytecodes::_lload_0: case Bytecodes::_fload_0: @@ -1000,9 +1002,9 @@ void SharkBlock::do_div_or_rem(bool is_long, bool is_rem) { builder()->SetInsertPoint(done); PHINode *result; if (is_long) - result = builder()->CreatePHI(SharkType::jlong_type(), "result"); + result = builder()->CreatePHI(SharkType::jlong_type(), 0, "result"); else - result = builder()->CreatePHI(SharkType::jint_type(), "result"); + result = builder()->CreatePHI(SharkType::jint_type(), 0, "result"); result->addIncoming(special_result, special_case); result->addIncoming(general_result, general_case); @@ -1036,12 +1038,12 @@ void SharkBlock::do_field_access(bool is_get, bool is_field) { value = constant->value(builder()); } if (!is_get || value == NULL) { - if (!is_field) - object = builder()->CreateInlineOop(field->holder()); - + if (!is_field) { + object = builder()->CreateInlineOop(field->holder()->java_mirror()); + } BasicType basic_type = field->type()->basic_type(); - const Type *stack_type = SharkType::to_stackType(basic_type); - const Type *field_type = SharkType::to_arrayType(basic_type); + Type *stack_type = SharkType::to_stackType(basic_type); + Type *field_type = SharkType::to_arrayType(basic_type); Value *addr = builder()->CreateAddressOfStructEntry( object, in_ByteSize(field->offset_in_bytes()), @@ -1050,8 +1052,12 @@ void SharkBlock::do_field_access(bool is_get, bool is_field) { // Do the access if (is_get) { - Value *field_value = builder()->CreateLoad(addr); - + Value* field_value; + if (field->is_volatile()) { + field_value = builder()->CreateAtomicLoad(addr); + } else { + field_value = builder()->CreateLoad(addr); + } if (field_type != stack_type) { field_value = builder()->CreateIntCast( field_value, stack_type, basic_type != T_CHAR); @@ -1067,13 +1073,15 @@ void SharkBlock::do_field_access(bool is_get, bool is_field) { field_value, field_type, basic_type != T_CHAR); } - builder()->CreateStore(field_value, addr); + if (field->is_volatile()) { + builder()->CreateAtomicStore(field_value, addr); + } else { + builder()->CreateStore(field_value, addr); + } - if (!field->type()->is_primitive_type()) + if (!field->type()->is_primitive_type()) { builder()->CreateUpdateBarrierSet(oopDesc::bs(), addr); - - if (field->is_volatile()) - builder()->CreateMemoryBarrier(SharkBuilder::BARRIER_STORELOAD); + } } } @@ -1105,7 +1113,7 @@ void SharkBlock::do_lcmp() { builder()->CreateBr(done); builder()->SetInsertPoint(done); - PHINode *result = builder()->CreatePHI(SharkType::jint_type(), "result"); + PHINode *result = builder()->CreatePHI(SharkType::jint_type(), 0, "result"); result->addIncoming(LLVMValue::jint_constant(-1), lt); result->addIncoming(LLVMValue::jint_constant(0), eq); result->addIncoming(LLVMValue::jint_constant(1), gt); @@ -1152,7 +1160,7 @@ void SharkBlock::do_fcmp(bool is_double, bool unordered_is_greater) { builder()->CreateBr(done); builder()->SetInsertPoint(done); - PHINode *result = builder()->CreatePHI(SharkType::jint_type(), "result"); + PHINode *result = builder()->CreatePHI(SharkType::jint_type(), 0, "result"); result->addIncoming(LLVMValue::jint_constant(-1), lt); result->addIncoming(LLVMValue::jint_constant(0), eq); result->addIncoming(LLVMValue::jint_constant(1), gt); diff --git a/hotspot/src/share/vm/shark/sharkBuilder.cpp b/hotspot/src/share/vm/shark/sharkBuilder.cpp index f4908ff26fb..f9c22bd1696 100644 --- a/hotspot/src/share/vm/shark/sharkBuilder.cpp +++ b/hotspot/src/share/vm/shark/sharkBuilder.cpp @@ -47,14 +47,14 @@ SharkBuilder::SharkBuilder(SharkCodeBuffer* code_buffer) // Helpers for accessing structures Value* SharkBuilder::CreateAddressOfStructEntry(Value* base, ByteSize offset, - const Type* type, + Type* type, const char* name) { return CreateBitCast(CreateStructGEP(base, in_bytes(offset)), type, name); } LoadInst* SharkBuilder::CreateValueOfStructEntry(Value* base, ByteSize offset, - const Type* type, + Type* type, const char* name) { return CreateLoad( CreateAddressOfStructEntry( @@ -71,7 +71,7 @@ LoadInst* SharkBuilder::CreateArrayLength(Value* arrayoop) { } Value* SharkBuilder::CreateArrayAddress(Value* arrayoop, - const Type* element_type, + Type* element_type, int element_bytes, ByteSize base_offset, Value* index, @@ -114,7 +114,7 @@ Value* SharkBuilder::CreateArrayAddress(Value* arrayoop, // Helpers for creating intrinsics and external functions. -const Type* SharkBuilder::make_type(char type, bool void_ok) { +Type* SharkBuilder::make_type(char type, bool void_ok) { switch (type) { // Primitive types case 'c': @@ -146,6 +146,8 @@ const Type* SharkBuilder::make_type(char type, bool void_ok) { return PointerType::getUnqual(SharkType::monitor_type()); case 'O': return SharkType::oop_type(); + case 'K': + return SharkType::klass_type(); // Miscellaneous case 'v': @@ -159,14 +161,14 @@ const Type* SharkBuilder::make_type(char type, bool void_ok) { } } -const FunctionType* SharkBuilder::make_ftype(const char* params, +FunctionType* SharkBuilder::make_ftype(const char* params, const char* ret) { - std::vector param_types; + std::vector param_types; for (const char* c = params; *c; c++) param_types.push_back(make_type(*c, false)); assert(strlen(ret) == 1, "should be"); - const Type *return_type = make_type(*ret, true); + Type *return_type = make_type(*ret, true); return FunctionType::get(return_type, param_types, false); } @@ -274,7 +276,7 @@ Value* SharkBuilder::d2l() { } Value* SharkBuilder::is_subtype_of() { - return make_function((address) SharkRuntime::is_subtype_of, "OO", "c"); + return make_function((address) SharkRuntime::is_subtype_of, "KK", "c"); } Value* SharkBuilder::current_time_millis() { @@ -352,79 +354,14 @@ Value* SharkBuilder::check_special_condition_for_native_trans() { "T", "v"); } -// Low-level non-VM calls - -// The ARM-specific code here is to work around unimplemented -// atomic exchange and memory barrier intrinsics in LLVM. -// -// Delegating to external functions for these would normally -// incur a speed penalty, but Linux on ARM is a special case -// in that atomic operations on that platform are handled by -// external functions anyway. It would be *preferable* for -// the calls to be hidden away in LLVM, but it's not hurting -// performance so having the calls here is acceptable. -// -// If you are building Shark on a platform without atomic -// exchange and/or memory barrier intrinsics then it is only -// acceptable to mimic this approach if your platform cannot -// perform these operations without delegating to a function. - -#ifdef ARM -static jint zero_cmpxchg_int(volatile jint *ptr, jint oldval, jint newval) { - return Atomic::cmpxchg(newval, ptr, oldval); -} -#endif // ARM - -Value* SharkBuilder::cmpxchg_int() { - return make_function( -#ifdef ARM - (address) zero_cmpxchg_int, -#else - "llvm.atomic.cmp.swap.i32.p0i32", -#endif // ARM - "Iii", "i"); -} - -#ifdef ARM -static intptr_t zero_cmpxchg_ptr(volatile intptr_t* ptr, - intptr_t oldval, - intptr_t newval) { - return Atomic::cmpxchg_ptr(newval, ptr, oldval); -} -#endif // ARM - -Value* SharkBuilder::cmpxchg_ptr() { - return make_function( -#ifdef ARM - (address) zero_cmpxchg_ptr, -#else - "llvm.atomic.cmp.swap.i" LP64_ONLY("64") NOT_LP64("32") ".p0i" LP64_ONLY("64") NOT_LP64("32"), -#endif // ARM - "Xxx", "x"); -} - Value* SharkBuilder::frame_address() { return make_function("llvm.frameaddress", "i", "C"); } -Value* SharkBuilder::memory_barrier() { - return make_function( -#ifdef ARM - (address) 0xffff0fa0, // __kernel_dmb -#else - "llvm.memory.barrier", -#endif // ARM - "11111", "v"); -} - Value* SharkBuilder::memset() { -#if SHARK_LLVM_VERSION >= 28 // LLVM 2.8 added a fifth isVolatile field for memset // introduced with LLVM r100304 - return make_function("llvm.memset.i32", "Cciii", "v"); -#else - return make_function("llvm.memset.i32", "Ccii", "v"); -#endif + return make_function("llvm.memset.p0i8.i32", "Cciii", "v"); } Value* SharkBuilder::unimplemented() { @@ -441,43 +378,16 @@ Value* SharkBuilder::dump() { // Public interface to low-level non-VM calls -CallInst* SharkBuilder::CreateCmpxchgInt(Value* exchange_value, - Value* dst, - Value* compare_value) { - return CreateCall3(cmpxchg_int(), dst, compare_value, exchange_value); -} - -CallInst* SharkBuilder::CreateCmpxchgPtr(Value* exchange_value, - Value* dst, - Value* compare_value) { - return CreateCall3(cmpxchg_ptr(), dst, compare_value, exchange_value); -} - CallInst* SharkBuilder::CreateGetFrameAddress() { return CreateCall(frame_address(), LLVMValue::jint_constant(0)); } -CallInst *SharkBuilder::CreateMemoryBarrier(int flags) { - Value *args[] = { - LLVMValue::bit_constant((flags & BARRIER_LOADLOAD) ? 1 : 0), - LLVMValue::bit_constant((flags & BARRIER_LOADSTORE) ? 1 : 0), - LLVMValue::bit_constant((flags & BARRIER_STORELOAD) ? 1 : 0), - LLVMValue::bit_constant((flags & BARRIER_STORESTORE) ? 1 : 0), - LLVMValue::bit_constant(1)}; - - return CreateCall(memory_barrier(), args, args + 5); -} - CallInst* SharkBuilder::CreateMemset(Value* dst, Value* value, Value* len, Value* align) { -#if SHARK_LLVM_VERSION >= 28 return CreateCall5(memset(), dst, value, len, align, LLVMValue::jint_constant(0)); -#else - return CreateCall4(memset(), dst, value, len, align); -#endif } CallInst* SharkBuilder::CreateUnimplemented(const char* file, int line) { @@ -510,11 +420,7 @@ CallInst* SharkBuilder::CreateDump(Value* value) { if (isa(value->getType())) value = CreatePtrToInt(value, SharkType::intptr_type()); else if (value->getType()-> -#if SHARK_LLVM_VERSION >= 27 isIntegerTy() -#else - isInteger() -#endif ) value = CreateIntCast(value, SharkType::intptr_type(), false); else @@ -563,9 +469,19 @@ Value* SharkBuilder::CreateInlineOop(jobject object, const char* name) { name); } +Value* SharkBuilder::CreateInlineMetadata(Metadata* metadata, llvm::PointerType* type, const char* name) { + assert(metadata != NULL, "inlined metadata must not be NULL"); + assert(metadata->is_metadata(), "sanity check"); + return CreateLoad( + CreateIntToPtr( + code_buffer_address(code_buffer()->inline_Metadata(metadata)), + PointerType::getUnqual(type)), + name); +} + Value* SharkBuilder::CreateInlineData(void* data, size_t size, - const Type* type, + Type* type, const char* name) { return CreateIntToPtr( code_buffer_address(code_buffer()->inline_data(data, size)), @@ -600,3 +516,11 @@ BasicBlock* SharkBuilder::CreateBlock(BasicBlock* ip, const char* name) const { return BasicBlock::Create( SharkContext::current(), name, GetInsertBlock()->getParent(), ip); } + +LoadInst* SharkBuilder::CreateAtomicLoad(Value* ptr, unsigned align, AtomicOrdering ordering, SynchronizationScope synchScope, bool isVolatile, const char* name) { + return Insert(new LoadInst(ptr, name, isVolatile, align, ordering, synchScope), name); +} + +StoreInst* SharkBuilder::CreateAtomicStore(Value* val, Value* ptr, unsigned align, AtomicOrdering ordering, SynchronizationScope synchScope, bool isVolatile, const char* name) { + return Insert(new StoreInst(val, ptr, isVolatile, align, ordering, synchScope), name); +} diff --git a/hotspot/src/share/vm/shark/sharkBuilder.hpp b/hotspot/src/share/vm/shark/sharkBuilder.hpp index 226e23b242d..e594a196026 100644 --- a/hotspot/src/share/vm/shark/sharkBuilder.hpp +++ b/hotspot/src/share/vm/shark/sharkBuilder.hpp @@ -53,22 +53,37 @@ class SharkBuilder : public llvm::IRBuilder<> { return _code_buffer; } + public: + llvm::LoadInst* CreateAtomicLoad(llvm::Value* ptr, + unsigned align = HeapWordSize, + llvm::AtomicOrdering ordering = llvm::SequentiallyConsistent, + llvm::SynchronizationScope synchScope = llvm::CrossThread, + bool isVolatile = true, + const char *name = ""); + llvm::StoreInst* CreateAtomicStore(llvm::Value *val, + llvm::Value *ptr, + unsigned align = HeapWordSize, + llvm::AtomicOrdering ordering = llvm::SequentiallyConsistent, + llvm::SynchronizationScope SynchScope = llvm::CrossThread, + bool isVolatile = true, + const char *name = ""); + // Helpers for accessing structures. public: llvm::Value* CreateAddressOfStructEntry(llvm::Value* base, ByteSize offset, - const llvm::Type* type, + llvm::Type* type, const char *name = ""); llvm::LoadInst* CreateValueOfStructEntry(llvm::Value* base, ByteSize offset, - const llvm::Type* type, + llvm::Type* type, const char *name = ""); // Helpers for accessing arrays. public: llvm::LoadInst* CreateArrayLength(llvm::Value* arrayoop); llvm::Value* CreateArrayAddress(llvm::Value* arrayoop, - const llvm::Type* element_type, + llvm::Type* element_type, int element_bytes, ByteSize base_offset, llvm::Value* index, @@ -85,8 +100,8 @@ class SharkBuilder : public llvm::IRBuilder<> { // Helpers for creating intrinsics and external functions. private: - static const llvm::Type* make_type(char type, bool void_ok); - static const llvm::FunctionType* make_ftype(const char* params, + static llvm::Type* make_type(char type, bool void_ok); + static llvm::FunctionType* make_ftype(const char* params, const char* ret); llvm::Value* make_function(const char* name, const char* params, @@ -165,7 +180,6 @@ class SharkBuilder : public llvm::IRBuilder<> { llvm::Value* cmpxchg_int(); llvm::Value* cmpxchg_ptr(); llvm::Value* frame_address(); - llvm::Value* memory_barrier(); llvm::Value* memset(); llvm::Value* unimplemented(); llvm::Value* should_not_reach_here(); @@ -173,14 +187,7 @@ class SharkBuilder : public llvm::IRBuilder<> { // Public interface to low-level non-VM calls. public: - llvm::CallInst* CreateCmpxchgInt(llvm::Value* exchange_value, - llvm::Value* dst, - llvm::Value* compare_value); - llvm::CallInst* CreateCmpxchgPtr(llvm::Value* exchange_value, - llvm::Value* dst, - llvm::Value* compare_value); llvm::CallInst* CreateGetFrameAddress(); - llvm::CallInst* CreateMemoryBarrier(int flags); llvm::CallInst* CreateMemset(llvm::Value* dst, llvm::Value* value, llvm::Value* len, @@ -189,15 +196,6 @@ class SharkBuilder : public llvm::IRBuilder<> { llvm::CallInst* CreateShouldNotReachHere(const char* file, int line); NOT_PRODUCT(llvm::CallInst* CreateDump(llvm::Value* value)); - // Flags for CreateMemoryBarrier. - public: - enum BarrierFlags { - BARRIER_LOADLOAD = 1, - BARRIER_LOADSTORE = 2, - BARRIER_STORELOAD = 4, - BARRIER_STORESTORE = 8 - }; - // HotSpot memory barriers public: void CreateUpdateBarrierSet(BarrierSet* bs, llvm::Value* field); @@ -209,9 +207,14 @@ class SharkBuilder : public llvm::IRBuilder<> { llvm::Value* CreateInlineOop(ciObject* object, const char* name = "") { return CreateInlineOop(object->constant_encoding(), name); } + + llvm::Value* CreateInlineMetadata(Metadata* metadata, llvm::PointerType* type, const char* name = ""); + llvm::Value* CreateInlineMetadata(ciMetadata* metadata, llvm::PointerType* type, const char* name = "") { + return CreateInlineMetadata(metadata->constant_encoding(), type, name); + } llvm::Value* CreateInlineData(void* data, size_t size, - const llvm::Type* type, + llvm::Type* type, const char* name = ""); // Helpers for creating basic blocks. @@ -222,5 +225,4 @@ class SharkBuilder : public llvm::IRBuilder<> { llvm::BasicBlock* CreateBlock(llvm::BasicBlock* ip, const char* name="") const; }; - -#endif // SHARE_VM_SHARK_SHARKBUILDER_HPP + #endif // SHARE_VM_SHARK_SHARKBUILDER_HPP diff --git a/hotspot/src/share/vm/shark/sharkCacheDecache.cpp b/hotspot/src/share/vm/shark/sharkCacheDecache.cpp index 98c86a6c16a..809322f9d40 100644 --- a/hotspot/src/share/vm/shark/sharkCacheDecache.cpp +++ b/hotspot/src/share/vm/shark/sharkCacheDecache.cpp @@ -107,11 +107,10 @@ void SharkDecacher::process_oop_tmp_slot(Value** value, int offset) { void SharkDecacher::process_method_slot(Value** value, int offset) { // Decache the method pointer write_value_to_frame( - SharkType::Method*_type(), + SharkType::Method_type(), *value, offset); - oopmap()->set_oop(slot2reg(offset)); } void SharkDecacher::process_pc_slot(int offset) { @@ -205,7 +204,7 @@ void SharkCacher::process_oop_tmp_slot(Value** value, int offset) { void SharkCacher::process_method_slot(Value** value, int offset) { // Cache the method pointer - *value = read_value_from_frame(SharkType::Method*_type(), offset); + *value = read_value_from_frame(SharkType::Method_type(), offset); } void SharkFunctionEntryCacher::process_method_slot(Value** value, int offset) { @@ -230,7 +229,7 @@ void SharkCacher::process_local_slot(int index, } Value* SharkOSREntryCacher::CreateAddressOfOSRBufEntry(int offset, - const Type* type) { + Type* type) { Value *result = builder()->CreateStructGEP(osr_buf(), offset); if (type != SharkType::intptr_type()) result = builder()->CreateBitCast(result, PointerType::getUnqual(type)); @@ -254,12 +253,12 @@ void SharkOSREntryCacher::process_local_slot(int index, } } -void SharkDecacher::write_value_to_frame(const Type* type, +void SharkDecacher::write_value_to_frame(Type* type, Value* value, int offset) { builder()->CreateStore(value, stack()->slot_addr(offset, type)); } -Value* SharkCacher::read_value_from_frame(const Type* type, int offset) { +Value* SharkCacher::read_value_from_frame(Type* type, int offset) { return builder()->CreateLoad(stack()->slot_addr(offset, type)); } diff --git a/hotspot/src/share/vm/shark/sharkCacheDecache.hpp b/hotspot/src/share/vm/shark/sharkCacheDecache.hpp index 6432a58c299..bdc77a55dcc 100644 --- a/hotspot/src/share/vm/shark/sharkCacheDecache.hpp +++ b/hotspot/src/share/vm/shark/sharkCacheDecache.hpp @@ -192,7 +192,7 @@ class SharkDecacher : public SharkCacherDecacher { // Writer helper protected: - void write_value_to_frame(const llvm::Type* type, + void write_value_to_frame(llvm::Type* type, llvm::Value* value, int offset); }; @@ -321,7 +321,7 @@ class SharkCacher : public SharkCacherDecacher { // Writer helper protected: - llvm::Value* read_value_from_frame(const llvm::Type* type, int offset); + llvm::Value* read_value_from_frame(llvm::Type* type, int offset); }; class SharkJavaCallCacher : public SharkCacher { @@ -422,7 +422,7 @@ class SharkOSREntryCacher : public SharkFunctionEntryCacher { // Helper private: - llvm::Value* CreateAddressOfOSRBufEntry(int offset, const llvm::Type* type); + llvm::Value* CreateAddressOfOSRBufEntry(int offset, llvm::Type* type); }; #endif // SHARE_VM_SHARK_SHARKCACHEDECACHE_HPP diff --git a/hotspot/src/share/vm/shark/sharkCodeBuffer.hpp b/hotspot/src/share/vm/shark/sharkCodeBuffer.hpp index 745112012a6..68b2506dd75 100644 --- a/hotspot/src/share/vm/shark/sharkCodeBuffer.hpp +++ b/hotspot/src/share/vm/shark/sharkCodeBuffer.hpp @@ -81,6 +81,13 @@ class SharkCodeBuffer : public StackObj { return offset; } + int inline_Metadata(Metadata* metadata) const { + masm()->align(BytesPerWord); + int offset = masm()->offset(); + masm()->store_Metadata(metadata); + return offset; + } + // Inline a block of non-oop data into the buffer and return its offset. public: int inline_data(void *src, size_t size) const { diff --git a/hotspot/src/share/vm/shark/sharkCompiler.cpp b/hotspot/src/share/vm/shark/sharkCompiler.cpp index 53851770fc7..3438240ad00 100644 --- a/hotspot/src/share/vm/shark/sharkCompiler.cpp +++ b/hotspot/src/share/vm/shark/sharkCompiler.cpp @@ -48,7 +48,6 @@ using namespace llvm; -#if SHARK_LLVM_VERSION >= 27 namespace { cl::opt MCPU("mcpu"); @@ -57,7 +56,6 @@ namespace { MAttrs("mattr", cl::CommaSeparated); } -#endif SharkCompiler::SharkCompiler() : AbstractCompiler() { @@ -72,6 +70,9 @@ SharkCompiler::SharkCompiler() // Initialize the native target InitializeNativeTarget(); + // MCJIT require a native AsmPrinter + InitializeNativeTargetAsmPrinter(); + // Create the two contexts which we'll use _normal_context = new SharkContext("normal"); _native_context = new SharkContext("native"); @@ -79,7 +80,6 @@ SharkCompiler::SharkCompiler() // Create the memory manager _memory_manager = new SharkMemoryManager(); -#if SHARK_LLVM_VERSION >= 27 // Finetune LLVM for the current host CPU. StringMap Features; bool gotCpuFeatures = llvm::sys::getHostCPUFeatures(Features); @@ -113,6 +113,16 @@ SharkCompiler::SharkCompiler() builder.setJITMemoryManager(memory_manager()); builder.setEngineKind(EngineKind::JIT); builder.setErrorStr(&ErrorMsg); + if (! fnmatch(SharkOptimizationLevel, "None", 0)) { + tty->print_cr("Shark optimization level set to: None"); + builder.setOptLevel(llvm::CodeGenOpt::None); + } else if (! fnmatch(SharkOptimizationLevel, "Less", 0)) { + tty->print_cr("Shark optimization level set to: Less"); + builder.setOptLevel(llvm::CodeGenOpt::Less); + } else if (! fnmatch(SharkOptimizationLevel, "Aggressive", 0)) { + tty->print_cr("Shark optimization level set to: Aggressive"); + builder.setOptLevel(llvm::CodeGenOpt::Aggressive); + } // else Default is selected by, well, default :-) _execution_engine = builder.create(); if (!execution_engine()) { @@ -125,13 +135,6 @@ SharkCompiler::SharkCompiler() execution_engine()->addModule( _native_context->module()); -#else - _execution_engine = ExecutionEngine::createJIT( - _normal_context->module_provider(), - NULL, memory_manager(), CodeGenOpt::Default); - execution_engine()->addModuleProvider( - _native_context->module_provider()); -#endif // All done mark_initialized(); @@ -261,6 +264,12 @@ void SharkCompiler::generate_native_code(SharkEntry* entry, function->dump(); } + if (SharkVerifyFunction != NULL) { + if (!fnmatch(SharkVerifyFunction, name, 0)) { + verifyFunction(*function); + } + } + // Compile to native code address code = NULL; context()->add_function(function); @@ -268,33 +277,28 @@ void SharkCompiler::generate_native_code(SharkEntry* entry, MutexLocker locker(execution_engine_lock()); free_queued_methods(); - if (SharkPrintAsmOf != NULL) { -#if SHARK_LLVM_VERSION >= 27 #ifndef NDEBUG +#if SHARK_LLVM_VERSION <= 31 +#define setCurrentDebugType SetCurrentDebugType +#endif + if (SharkPrintAsmOf != NULL) { if (!fnmatch(SharkPrintAsmOf, name, 0)) { - llvm::SetCurrentDebugType(X86_ONLY("x86-emitter") NOT_X86("jit")); + llvm::setCurrentDebugType(X86_ONLY("x86-emitter") NOT_X86("jit")); llvm::DebugFlag = true; } else { - llvm::SetCurrentDebugType(""); + llvm::setCurrentDebugType(""); llvm::DebugFlag = false; } -#endif // !NDEBUG -#else - // NB you need to patch LLVM with http://tinyurl.com/yf3baln for this - std::vector args; - args.push_back(""); // program name - if (!fnmatch(SharkPrintAsmOf, name, 0)) - args.push_back("-debug-only=x86-emitter"); - else - args.push_back("-debug-only=none"); - args.push_back(0); // terminator - cl::ParseCommandLineOptions(args.size() - 1, (char **) &args[0]); -#endif // SHARK_LLVM_VERSION } +#ifdef setCurrentDebugType +#undef setCurrentDebugType +#endif +#endif // !NDEBUG memory_manager()->set_entry_for_function(function, entry); code = (address) execution_engine()->getPointerToFunction(function); } + assert(code != NULL, "code must be != NULL"); entry->set_entry_point(code); entry->set_function(function); entry->set_context(context()); @@ -319,8 +323,8 @@ void SharkCompiler::free_compiled_method(address code) { // finish with the exception of the VM thread, so we can consider // ourself the owner of the execution engine lock even though we // can't actually acquire it at this time. - assert(Thread::current()->is_VM_thread(), "must be called by VM thread"); - assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); + assert(Thread::current()->is_Compiler_thread(), "must be called by compiler thread"); + assert_locked_or_safepoint(CodeCache_lock); SharkEntry *entry = (SharkEntry *) code; entry->context()->push_to_free_queue(entry->function()); diff --git a/hotspot/src/share/vm/shark/sharkConstant.cpp b/hotspot/src/share/vm/shark/sharkConstant.cpp index 50923bd57aa..b45ec136e77 100644 --- a/hotspot/src/share/vm/shark/sharkConstant.cpp +++ b/hotspot/src/share/vm/shark/sharkConstant.cpp @@ -37,10 +37,8 @@ SharkConstant* SharkConstant::for_ldc(ciBytecodeStream *iter) { ciType *type = NULL; if (constant.basic_type() == T_OBJECT) { ciEnv *env = ciEnv::current(); - if (constant.as_object()->is_klass()) - type = env->Class_klass(); - else - type = env->String_klass(); + assert(constant.as_object()->klass() == env->String_klass() || constant.as_object()->klass() == env->Class_klass(), "should be"); + type = constant.as_object()->klass(); } return new SharkConstant(constant, type); } @@ -108,17 +106,16 @@ SharkConstant::SharkConstant(ciConstant constant, ciType *type) { // objects (which differ between ldc* and get*, thanks!) ciObject *object = constant.as_object(); assert(type != NULL, "shouldn't be"); - if (object->is_klass()) { - // The constant returned for a klass is the ciKlass - // for the entry, but we want the java_mirror. - ciKlass *klass = object->as_klass(); - if (!klass->is_loaded()) { + + if ((! object->is_null_object()) && object->klass() == ciEnv::current()->Class_klass()) { + ciKlass *klass = object->klass(); + if (! klass->is_loaded()) { _is_loaded = false; return; } - object = klass->java_mirror(); } - if (object->is_null_object() || !object->can_be_constant()) { + + if (object->is_null_object() || ! object->can_be_constant() || ! object->is_loaded()) { _is_loaded = false; return; } diff --git a/hotspot/src/share/vm/shark/sharkContext.cpp b/hotspot/src/share/vm/shark/sharkContext.cpp index 098abb8a5aa..0fc86f0b14c 100644 --- a/hotspot/src/share/vm/shark/sharkContext.cpp +++ b/hotspot/src/share/vm/shark/sharkContext.cpp @@ -29,6 +29,7 @@ #include "shark/llvmHeaders.hpp" #include "shark/sharkContext.hpp" #include "utilities/globalDefinitions.hpp" +#include "memory/allocation.hpp" using namespace llvm; @@ -52,6 +53,9 @@ SharkContext::SharkContext(const char* name) _itableOffsetEntry_type = PointerType::getUnqual( ArrayType::get(jbyte_type(), itableOffsetEntry::size() * wordSize)); + _Metadata_type = PointerType::getUnqual( + ArrayType::get(jbyte_type(), sizeof(Metadata))); + _klass_type = PointerType::getUnqual( ArrayType::get(jbyte_type(), sizeof(Klass))); @@ -61,7 +65,7 @@ SharkContext::SharkContext(const char* name) _jniHandleBlock_type = PointerType::getUnqual( ArrayType::get(jbyte_type(), sizeof(JNIHandleBlock))); - _Method*_type = PointerType::getUnqual( + _Method_type = PointerType::getUnqual( ArrayType::get(jbyte_type(), sizeof(Method))); _monitor_type = ArrayType::get( @@ -76,14 +80,14 @@ SharkContext::SharkContext(const char* name) _zeroStack_type = PointerType::getUnqual( ArrayType::get(jbyte_type(), sizeof(ZeroStack))); - std::vector params; - params.push_back(Method*_type()); + std::vector params; + params.push_back(Method_type()); params.push_back(intptr_type()); params.push_back(thread_type()); _entry_point_type = FunctionType::get(jint_type(), params, false); params.clear(); - params.push_back(Method*_type()); + params.push_back(Method_type()); params.push_back(PointerType::getUnqual(jbyte_type())); params.push_back(intptr_type()); params.push_back(thread_type()); @@ -150,7 +154,7 @@ SharkContext::SharkContext(const char* name) } } -class SharkFreeQueueItem : public CHeapObj { +class SharkFreeQueueItem : public CHeapObj { public: SharkFreeQueueItem(llvm::Function* function, SharkFreeQueueItem *next) : _function(function), _next(next) {} diff --git a/hotspot/src/share/vm/shark/sharkContext.hpp b/hotspot/src/share/vm/shark/sharkContext.hpp index 470b9114ac1..952cf13b7b7 100644 --- a/hotspot/src/share/vm/shark/sharkContext.hpp +++ b/hotspot/src/share/vm/shark/sharkContext.hpp @@ -42,11 +42,7 @@ class SharkContext : public llvm::LLVMContext { private: llvm::Module* _module; -#if SHARK_LLVM_VERSION >= 27 public: -#else - private: -#endif llvm::Module* module() const { return _module; } @@ -59,127 +55,126 @@ class SharkContext : public llvm::LLVMContext { // Module accessors public: -#if SHARK_LLVM_VERSION < 27 - llvm::ModuleProvider* module_provider() const { - return new llvm::ExistingModuleProvider(module()); - } -#endif void add_function(llvm::Function* function) const { module()->getFunctionList().push_back(function); } llvm::Constant* get_external(const char* name, - const llvm::FunctionType* sig) { + llvm::FunctionType* sig) { return module()->getOrInsertFunction(name, sig); } // Basic types private: - const llvm::Type* _void_type; - const llvm::IntegerType* _bit_type; - const llvm::IntegerType* _jbyte_type; - const llvm::IntegerType* _jshort_type; - const llvm::IntegerType* _jint_type; - const llvm::IntegerType* _jlong_type; - const llvm::Type* _jfloat_type; - const llvm::Type* _jdouble_type; + llvm::Type* _void_type; + llvm::IntegerType* _bit_type; + llvm::IntegerType* _jbyte_type; + llvm::IntegerType* _jshort_type; + llvm::IntegerType* _jint_type; + llvm::IntegerType* _jlong_type; + llvm::Type* _jfloat_type; + llvm::Type* _jdouble_type; public: - const llvm::Type* void_type() const { + llvm::Type* void_type() const { return _void_type; } - const llvm::IntegerType* bit_type() const { + llvm::IntegerType* bit_type() const { return _bit_type; } - const llvm::IntegerType* jbyte_type() const { + llvm::IntegerType* jbyte_type() const { return _jbyte_type; } - const llvm::IntegerType* jshort_type() const { + llvm::IntegerType* jshort_type() const { return _jshort_type; } - const llvm::IntegerType* jint_type() const { + llvm::IntegerType* jint_type() const { return _jint_type; } - const llvm::IntegerType* jlong_type() const { + llvm::IntegerType* jlong_type() const { return _jlong_type; } - const llvm::Type* jfloat_type() const { + llvm::Type* jfloat_type() const { return _jfloat_type; } - const llvm::Type* jdouble_type() const { + llvm::Type* jdouble_type() const { return _jdouble_type; } - const llvm::IntegerType* intptr_type() const { + llvm::IntegerType* intptr_type() const { return LP64_ONLY(jlong_type()) NOT_LP64(jint_type()); } // Compound types private: - const llvm::PointerType* _itableOffsetEntry_type; - const llvm::PointerType* _jniEnv_type; - const llvm::PointerType* _jniHandleBlock_type; - const llvm::PointerType* _klass_type; - const llvm::PointerType* _Method*_type; - const llvm::ArrayType* _monitor_type; - const llvm::PointerType* _oop_type; - const llvm::PointerType* _thread_type; - const llvm::PointerType* _zeroStack_type; - const llvm::FunctionType* _entry_point_type; - const llvm::FunctionType* _osr_entry_point_type; + llvm::PointerType* _itableOffsetEntry_type; + llvm::PointerType* _jniEnv_type; + llvm::PointerType* _jniHandleBlock_type; + llvm::PointerType* _Metadata_type; + llvm::PointerType* _klass_type; + llvm::PointerType* _Method_type; + llvm::ArrayType* _monitor_type; + llvm::PointerType* _oop_type; + llvm::PointerType* _thread_type; + llvm::PointerType* _zeroStack_type; + llvm::FunctionType* _entry_point_type; + llvm::FunctionType* _osr_entry_point_type; public: - const llvm::PointerType* itableOffsetEntry_type() const { + llvm::PointerType* itableOffsetEntry_type() const { return _itableOffsetEntry_type; } - const llvm::PointerType* jniEnv_type() const { + llvm::PointerType* jniEnv_type() const { return _jniEnv_type; } - const llvm::PointerType* jniHandleBlock_type() const { + llvm::PointerType* jniHandleBlock_type() const { return _jniHandleBlock_type; } - const llvm::PointerType* klass_type() const { + llvm::PointerType* Metadata_type() const { + return _Metadata_type; + } + llvm::PointerType* klass_type() const { return _klass_type; } - const llvm::PointerType* Method*_type() const { - return _Method*_type; + llvm::PointerType* Method_type() const { + return _Method_type; } - const llvm::ArrayType* monitor_type() const { + llvm::ArrayType* monitor_type() const { return _monitor_type; } - const llvm::PointerType* oop_type() const { + llvm::PointerType* oop_type() const { return _oop_type; } - const llvm::PointerType* thread_type() const { + llvm::PointerType* thread_type() const { return _thread_type; } - const llvm::PointerType* zeroStack_type() const { + llvm::PointerType* zeroStack_type() const { return _zeroStack_type; } - const llvm::FunctionType* entry_point_type() const { + llvm::FunctionType* entry_point_type() const { return _entry_point_type; } - const llvm::FunctionType* osr_entry_point_type() const { + llvm::FunctionType* osr_entry_point_type() const { return _osr_entry_point_type; } // Mappings private: - const llvm::Type* _to_stackType[T_CONFLICT]; - const llvm::Type* _to_arrayType[T_CONFLICT]; + llvm::Type* _to_stackType[T_CONFLICT]; + llvm::Type* _to_arrayType[T_CONFLICT]; private: - const llvm::Type* map_type(const llvm::Type* const* table, + llvm::Type* map_type(llvm::Type* const* table, BasicType type) const { assert(type >= 0 && type < T_CONFLICT, "unhandled type"); - const llvm::Type* result = table[type]; + llvm::Type* result = table[type]; assert(result != NULL, "unhandled type"); return result; } public: - const llvm::Type* to_stackType(BasicType type) const { + llvm::Type* to_stackType(BasicType type) const { return map_type(_to_stackType, type); } - const llvm::Type* to_arrayType(BasicType type) const { + llvm::Type* to_arrayType(BasicType type) const { return map_type(_to_arrayType, type); } diff --git a/hotspot/src/share/vm/shark/sharkFunction.hpp b/hotspot/src/share/vm/shark/sharkFunction.hpp index cc34a1fdc9b..47a480fa14f 100644 --- a/hotspot/src/share/vm/shark/sharkFunction.hpp +++ b/hotspot/src/share/vm/shark/sharkFunction.hpp @@ -91,7 +91,7 @@ class SharkFunction : public SharkTargetInvariants { bool is_osr() const { return flow()->is_osr_flow(); } - const llvm::FunctionType* entry_point_type() const { + llvm::FunctionType* entry_point_type() const { if (is_osr()) return SharkType::osr_entry_point_type(); else diff --git a/hotspot/src/share/vm/shark/sharkIntrinsics.cpp b/hotspot/src/share/vm/shark/sharkIntrinsics.cpp index 8efaa432e2e..9ad91c96d79 100644 --- a/hotspot/src/share/vm/shark/sharkIntrinsics.cpp +++ b/hotspot/src/share/vm/shark/sharkIntrinsics.cpp @@ -171,7 +171,7 @@ void SharkIntrinsics::do_Math_minmax(ICmpInst::Predicate p) { builder()->CreateBr(done); builder()->SetInsertPoint(done); - PHINode *phi = builder()->CreatePHI(a->getType(), "result"); + PHINode *phi = builder()->CreatePHI(a->getType(), 0, "result"); phi->addIncoming(a, return_a); phi->addIncoming(b, return_b); @@ -210,7 +210,7 @@ void SharkIntrinsics::do_Object_getClass() { Value *klass = builder()->CreateValueOfStructEntry( state()->pop()->jobject_value(), in_ByteSize(oopDesc::klass_offset_in_bytes()), - SharkType::oop_type(), + SharkType::klass_type(), "klass"); state()->push( @@ -265,8 +265,7 @@ void SharkIntrinsics::do_Unsafe_compareAndSwapInt() { "addr"); // Perform the operation - Value *result = builder()->CreateCmpxchgInt(x, addr, e); - + Value *result = builder()->CreateAtomicCmpXchg(addr, e, x, llvm::SequentiallyConsistent); // Push the result state()->push( SharkValue::create_jint( diff --git a/hotspot/src/share/vm/shark/sharkMemoryManager.cpp b/hotspot/src/share/vm/shark/sharkMemoryManager.cpp index cbcef22c2a3..20cb0e5ebfe 100644 --- a/hotspot/src/share/vm/shark/sharkMemoryManager.cpp +++ b/hotspot/src/share/vm/shark/sharkMemoryManager.cpp @@ -79,7 +79,6 @@ void SharkMemoryManager::setMemoryExecutable() { mm()->setMemoryExecutable(); } -#if SHARK_LLVM_VERSION >= 27 void SharkMemoryManager::deallocateExceptionTable(void *ptr) { mm()->deallocateExceptionTable(ptr); } @@ -87,26 +86,23 @@ void SharkMemoryManager::deallocateExceptionTable(void *ptr) { void SharkMemoryManager::deallocateFunctionBody(void *ptr) { mm()->deallocateFunctionBody(ptr); } -#else -void SharkMemoryManager::deallocateMemForFunction(const Function* F) { - return mm()->deallocateMemForFunction(F); -} -#endif uint8_t* SharkMemoryManager::allocateGlobal(uintptr_t Size, unsigned int Alignment) { return mm()->allocateGlobal(Size, Alignment); } -#if SHARK_LLVM_VERSION < 27 -void* SharkMemoryManager::getDlsymTable() const { - return mm()->getDlsymTable(); +void* SharkMemoryManager::getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure) { + return mm()->getPointerToNamedFunction(Name, AbortOnFailure); } -void SharkMemoryManager::SetDlsymTable(void *ptr) { - mm()->SetDlsymTable(ptr); +uint8_t* SharkMemoryManager::allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID) { + return mm()->allocateCodeSection(Size, Alignment, SectionID); +} + +uint8_t* SharkMemoryManager::allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID) { + return mm()->allocateDataSection(Size, Alignment, SectionID); } -#endif void SharkMemoryManager::setPoisonMemory(bool poison) { mm()->setPoisonMemory(poison); diff --git a/hotspot/src/share/vm/shark/sharkMemoryManager.hpp b/hotspot/src/share/vm/shark/sharkMemoryManager.hpp index 2da762afeda..fa725a14502 100644 --- a/hotspot/src/share/vm/shark/sharkMemoryManager.hpp +++ b/hotspot/src/share/vm/shark/sharkMemoryManager.hpp @@ -75,20 +75,15 @@ class SharkMemoryManager : public llvm::JITMemoryManager { unsigned char* TableStart, unsigned char* TableEnd, unsigned char* FrameRegister); -#if SHARK_LLVM_VERSION < 27 - void* getDlsymTable() const; - void SetDlsymTable(void *ptr); -#endif + void *getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure = true); + uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID); + uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID); void setPoisonMemory(bool); uint8_t* allocateGlobal(uintptr_t, unsigned int); void setMemoryWritable(); void setMemoryExecutable(); -#if SHARK_LLVM_VERSION >= 27 void deallocateExceptionTable(void *ptr); void deallocateFunctionBody(void *ptr); -#else - void deallocateMemForFunction(const llvm::Function* F); -#endif unsigned char *allocateSpace(intptr_t Size, unsigned int Alignment); }; diff --git a/hotspot/src/share/vm/shark/sharkNativeWrapper.cpp b/hotspot/src/share/vm/shark/sharkNativeWrapper.cpp index ef4337233f5..53fea3154b8 100644 --- a/hotspot/src/share/vm/shark/sharkNativeWrapper.cpp +++ b/hotspot/src/share/vm/shark/sharkNativeWrapper.cpp @@ -59,7 +59,6 @@ void SharkNativeWrapper::initialize(const char *name) { OopMap *oopmap = new OopMap( SharkStack::oopmap_slot_munge(stack()->oopmap_frame_size()), SharkStack::oopmap_slot_munge(arg_size())); - oopmap->set_oop(SharkStack::slot2reg(stack()->method_slot_offset())); // Set up the oop_tmp slot if required: // - For static methods we use it to handlize the class argument @@ -83,9 +82,9 @@ void SharkNativeWrapper::initialize(const char *name) { } // Start building the argument list - std::vector param_types; + std::vector param_types; std::vector param_values; - const PointerType *box_type = PointerType::getUnqual(SharkType::oop_type()); + PointerType *box_type = PointerType::getUnqual(SharkType::oop_type()); // First argument is the JNIEnv param_types.push_back(SharkType::jniEnv_type()); @@ -149,7 +148,7 @@ void SharkNativeWrapper::initialize(const char *name) { builder()->CreateBr(merge); builder()->SetInsertPoint(merge); - phi = builder()->CreatePHI(box_type, "boxed_object"); + phi = builder()->CreatePHI(box_type, 0, "boxed_object"); phi->addIncoming(ConstantPointerNull::get(box_type), null); phi->addIncoming(box, not_null); box = phi; @@ -170,7 +169,7 @@ void SharkNativeWrapper::initialize(const char *name) { // fall through default: - const Type *param_type = SharkType::to_stackType(arg_type(i)); + Type *param_type = SharkType::to_stackType(arg_type(i)); param_types.push_back(param_type); param_values.push_back( @@ -201,7 +200,7 @@ void SharkNativeWrapper::initialize(const char *name) { // Make the call BasicType result_type = target()->result_type(); - const Type* return_type; + Type* return_type; if (result_type == T_VOID) return_type = SharkType::void_type(); else if (is_returning_oop()) @@ -213,7 +212,7 @@ void SharkNativeWrapper::initialize(const char *name) { PointerType::getUnqual( FunctionType::get(return_type, param_types, false))); Value *result = builder()->CreateCall( - native_function, param_values.begin(), param_values.end()); + native_function, llvm::makeArrayRef(param_values)); // Start the transition back to _thread_in_Java CreateSetThreadState(_thread_in_native_trans); @@ -221,7 +220,7 @@ void SharkNativeWrapper::initialize(const char *name) { // Make sure new state is visible in the GC thread if (os::is_MP()) { if (UseMembar) - builder()->CreateMemoryBarrier(SharkBuilder::BARRIER_STORELOAD); + builder()->CreateFence(llvm::SequentiallyConsistent, llvm::CrossThread); else CreateWriteMemorySerializePage(); } @@ -305,7 +304,7 @@ void SharkNativeWrapper::initialize(const char *name) { builder()->CreateBr(merge); builder()->SetInsertPoint(merge); - PHINode *phi = builder()->CreatePHI(SharkType::oop_type(), "result"); + PHINode *phi = builder()->CreatePHI(SharkType::oop_type(), 0, "result"); phi->addIncoming(LLVMValue::null(), null); phi->addIncoming(unboxed_result, not_null); result = phi; diff --git a/hotspot/src/share/vm/shark/sharkStack.cpp b/hotspot/src/share/vm/shark/sharkStack.cpp index 6800d22e012..ce868d61d56 100644 --- a/hotspot/src/share/vm/shark/sharkStack.cpp +++ b/hotspot/src/share/vm/shark/sharkStack.cpp @@ -75,7 +75,7 @@ void SharkStack::initialize(Value* method) { _method_slot_offset = offset++; if (setup_sp_and_method) { builder()->CreateStore( - method, slot_addr(method_slot_offset(), SharkType::Method*_type())); + method, slot_addr(method_slot_offset(), SharkType::Method_type())); } // Unextended SP @@ -163,7 +163,7 @@ Value* SharkStack::CreatePopFrame(int result_slots) { } Value* SharkStack::slot_addr(int offset, - const Type* type, + Type* type, const char* name) const { bool needs_cast = type && type != SharkType::intptr_type(); diff --git a/hotspot/src/share/vm/shark/sharkStack.hpp b/hotspot/src/share/vm/shark/sharkStack.hpp index 78f694cee99..15e367f59bc 100644 --- a/hotspot/src/share/vm/shark/sharkStack.hpp +++ b/hotspot/src/share/vm/shark/sharkStack.hpp @@ -204,7 +204,7 @@ class SharkStack : public SharkCompileInvariants { // Addresses of things in the frame public: llvm::Value* slot_addr(int offset, - const llvm::Type* type = NULL, + llvm::Type* type = NULL, const char* name = "") const; llvm::Value* monitor_addr(int index) const { diff --git a/hotspot/src/share/vm/shark/sharkState.cpp b/hotspot/src/share/vm/shark/sharkState.cpp index d0bc19d9891..87a5d5c6a42 100644 --- a/hotspot/src/share/vm/shark/sharkState.cpp +++ b/hotspot/src/share/vm/shark/sharkState.cpp @@ -131,7 +131,7 @@ void SharkState::merge(SharkState* other, Value *this_method = this->method(); Value *other_method = other->method(); if (this_method != other_method) { - PHINode *phi = builder()->CreatePHI(SharkType::Method*_type(), "method"); + PHINode *phi = builder()->CreatePHI(SharkType::Method_type(), 0, "method"); phi->addIncoming(this_method, this_block); phi->addIncoming(other_method, other_block); set_method(phi); @@ -142,7 +142,7 @@ void SharkState::merge(SharkState* other, Value *other_oop_tmp = other->oop_tmp(); if (this_oop_tmp != other_oop_tmp) { assert(this_oop_tmp && other_oop_tmp, "can't merge NULL with non-NULL"); - PHINode *phi = builder()->CreatePHI(SharkType::oop_type(), "oop_tmp"); + PHINode *phi = builder()->CreatePHI(SharkType::oop_type(), 0, "oop_tmp"); phi->addIncoming(this_oop_tmp, this_block); phi->addIncoming(other_oop_tmp, other_block); set_oop_tmp(phi); @@ -243,7 +243,7 @@ SharkOSREntryState::SharkOSREntryState(SharkTopLevelBlock* block, Value* method, Value* osr_buf) : SharkState(block) { - assert(!block->stack_depth_at_entry(), "entry block shouldn't have stack"); + assert(block->stack_depth_at_entry() == 0, "entry block shouldn't have stack"); set_num_monitors(block->ciblock()->monitor_count()); // Local variables @@ -287,7 +287,7 @@ SharkPHIState::SharkPHIState(SharkTopLevelBlock* block) char name[18]; // Method - set_method(builder()->CreatePHI(SharkType::Method*_type(), "method")); + set_method(builder()->CreatePHI(SharkType::Method_type(), 0, "method")); // Local variables for (int i = 0; i < max_locals(); i++) { @@ -307,7 +307,7 @@ SharkPHIState::SharkPHIState(SharkTopLevelBlock* block) case T_ARRAY: snprintf(name, sizeof(name), "local_%d_", i); value = SharkValue::create_phi( - type, builder()->CreatePHI(SharkType::to_stackType(type), name)); + type, builder()->CreatePHI(SharkType::to_stackType(type), 0, name)); break; case T_ADDRESS: @@ -345,7 +345,7 @@ SharkPHIState::SharkPHIState(SharkTopLevelBlock* block) case T_ARRAY: snprintf(name, sizeof(name), "stack_%d_", i); value = SharkValue::create_phi( - type, builder()->CreatePHI(SharkType::to_stackType(type), name)); + type, builder()->CreatePHI(SharkType::to_stackType(type), 0, name)); break; case T_ADDRESS: diff --git a/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp b/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp index b66d70bdda8..fcd6906caad 100644 --- a/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp +++ b/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp @@ -65,6 +65,7 @@ void SharkTopLevelBlock::scan_for_traps() { switch (bc()) { case Bytecodes::_ldc: case Bytecodes::_ldc_w: + case Bytecodes::_ldc2_w: if (!SharkConstant::for_ldc(iter())->is_loaded()) { set_trap( Deoptimization::make_trap_request( @@ -109,7 +110,8 @@ void SharkTopLevelBlock::scan_for_traps() { case Bytecodes::_invokespecial: case Bytecodes::_invokevirtual: case Bytecodes::_invokeinterface: - method = iter()->get_method(will_link); + ciSignature* sig; + method = iter()->get_method(will_link, &sig); assert(will_link, "typeflow responsibility"); if (!method->holder()->is_linked()) { @@ -562,12 +564,12 @@ void SharkTopLevelBlock::marshal_exception_fast(int num_options) { Value *exception_klass = builder()->CreateValueOfStructEntry( xstack(0)->jobject_value(), in_ByteSize(oopDesc::klass_offset_in_bytes()), - SharkType::oop_type(), + SharkType::klass_type(), "exception_klass"); for (int i = 0; i < num_options; i++) { Value *check_klass = - builder()->CreateInlineOop(exc_handler(i)->catch_klass()); + builder()->CreateInlineMetadata(exc_handler(i)->catch_klass(), SharkType::klass_type()); BasicBlock *not_exact = function()->CreateBlock("not_exact"); BasicBlock *not_subtype = function()->CreateBlock("not_subtype"); @@ -823,7 +825,7 @@ void SharkTopLevelBlock::do_aload(BasicType basic_type) { builder()->CreateArrayAddress( array->jarray_value(), basic_type, index->jint_value())); - const Type *stack_type = SharkType::to_stackType(basic_type); + Type *stack_type = SharkType::to_stackType(basic_type); if (value->getType() != stack_type) value = builder()->CreateIntCast(value, stack_type, basic_type != T_CHAR); @@ -910,7 +912,7 @@ void SharkTopLevelBlock::do_astore(BasicType basic_type) { ShouldNotReachHere(); } - const Type *array_type = SharkType::to_arrayType(basic_type); + Type *array_type = SharkType::to_arrayType(basic_type); if (value->getType() != array_type) value = builder()->CreateIntCast(value, array_type, basic_type != T_CHAR); @@ -1102,9 +1104,9 @@ ciMethod* SharkTopLevelBlock::improve_virtual_call(ciMethod* caller, Value *SharkTopLevelBlock::get_direct_callee(ciMethod* method) { return builder()->CreateBitCast( - builder()->CreateInlineOop(method), - SharkType::Method*_type(), - "callee"); + builder()->CreateInlineMetadata(method, SharkType::Method_type()), + SharkType::Method_type(), + "callee"); } Value *SharkTopLevelBlock::get_virtual_callee(SharkValue* receiver, @@ -1118,7 +1120,7 @@ Value *SharkTopLevelBlock::get_virtual_callee(SharkValue* receiver, return builder()->CreateLoad( builder()->CreateArrayAddress( klass, - SharkType::Method*_type(), + SharkType::Method_type(), vtableEntry::size() * wordSize, in_ByteSize(InstanceKlass::vtable_start_offset() * wordSize), LLVMValue::intptr_constant(vtable_index)), @@ -1136,7 +1138,7 @@ Value* SharkTopLevelBlock::get_interface_callee(SharkValue *receiver, // Locate the receiver's itable Value *object_klass = builder()->CreateValueOfStructEntry( receiver->jobject_value(), in_ByteSize(oopDesc::klass_offset_in_bytes()), - SharkType::oop_type(), + SharkType::klass_type(), "object_klass"); Value *vtable_start = builder()->CreateAdd( @@ -1169,12 +1171,12 @@ Value* SharkTopLevelBlock::get_interface_callee(SharkValue *receiver, } // Locate this interface's entry in the table - Value *iklass = builder()->CreateInlineOop(method->holder()); + Value *iklass = builder()->CreateInlineMetadata(method->holder(), SharkType::klass_type()); BasicBlock *loop_entry = builder()->GetInsertBlock(); builder()->CreateBr(loop); builder()->SetInsertPoint(loop); PHINode *itable_entry_addr = builder()->CreatePHI( - SharkType::intptr_type(), "itable_entry_addr"); + SharkType::intptr_type(), 0, "itable_entry_addr"); itable_entry_addr->addIncoming(itable_start, loop_entry); Value *itable_entry = builder()->CreateIntToPtr( @@ -1183,11 +1185,11 @@ Value* SharkTopLevelBlock::get_interface_callee(SharkValue *receiver, Value *itable_iklass = builder()->CreateValueOfStructEntry( itable_entry, in_ByteSize(itableOffsetEntry::interface_offset_in_bytes()), - SharkType::oop_type(), + SharkType::klass_type(), "itable_iklass"); builder()->CreateCondBr( - builder()->CreateICmpEQ(itable_iklass, LLVMValue::null()), + builder()->CreateICmpEQ(itable_iklass, LLVMValue::nullKlass()), got_null, not_null); // A null entry means that the class doesn't implement the @@ -1231,7 +1233,7 @@ Value* SharkTopLevelBlock::get_interface_callee(SharkValue *receiver, method->itable_index() * itableMethodEntry::size() * wordSize)), LLVMValue::intptr_constant( itableMethodEntry::method_offset_in_bytes())), - PointerType::getUnqual(SharkType::Method*_type())), + PointerType::getUnqual(SharkType::Method_type())), "callee"); } @@ -1243,7 +1245,9 @@ void SharkTopLevelBlock::do_call() { // Find the method being called bool will_link; - ciMethod *dest_method = iter()->get_method(will_link); + ciSignature* sig; + ciMethod *dest_method = iter()->get_method(will_link, &sig); + assert(will_link, "typeflow responsibility"); assert(dest_method->is_static() == is_static, "must match bc"); @@ -1259,10 +1263,17 @@ void SharkTopLevelBlock::do_call() { assert(holder_klass->is_interface() || holder_klass->super() == NULL || !is_interface, "must match bc"); + + bool is_forced_virtual = is_interface && holder_klass == java_lang_Object_klass(); + ciKlass *holder = iter()->get_declared_method_holder(); ciInstanceKlass *klass = ciEnv::get_instance_klass_for_declared_method_holder(holder); + if (is_forced_virtual) { + klass = java_lang_Object_klass(); + } + // Find the receiver in the stack. We do this before // trying to inline because the inliner can only use // zero-checked values, not being able to perform the @@ -1294,7 +1305,7 @@ void SharkTopLevelBlock::do_call() { // Find the method we are calling Value *callee; if (call_is_virtual) { - if (is_virtual) { + if (is_virtual || is_forced_virtual) { assert(klass->is_linked(), "scan_for_traps responsibility"); int vtable_index = call_method->resolve_vtable_index( target()->holder(), klass); @@ -1490,12 +1501,12 @@ void SharkTopLevelBlock::do_full_instance_check(ciKlass* klass) { // Get the class we're checking against builder()->SetInsertPoint(not_null); - Value *check_klass = builder()->CreateInlineOop(klass); + Value *check_klass = builder()->CreateInlineMetadata(klass, SharkType::klass_type()); // Get the class of the object being tested Value *object_klass = builder()->CreateValueOfStructEntry( object, in_ByteSize(oopDesc::klass_offset_in_bytes()), - SharkType::oop_type(), + SharkType::klass_type(), "object_klass"); // Perform the check @@ -1520,7 +1531,7 @@ void SharkTopLevelBlock::do_full_instance_check(ciKlass* klass) { // First merge builder()->SetInsertPoint(merge1); PHINode *nonnull_result = builder()->CreatePHI( - SharkType::jint_type(), "nonnull_result"); + SharkType::jint_type(), 0, "nonnull_result"); nonnull_result->addIncoming( LLVMValue::jint_constant(IC_IS_INSTANCE), is_instance); nonnull_result->addIncoming( @@ -1531,7 +1542,7 @@ void SharkTopLevelBlock::do_full_instance_check(ciKlass* klass) { // Second merge builder()->SetInsertPoint(merge2); PHINode *result = builder()->CreatePHI( - SharkType::jint_type(), "result"); + SharkType::jint_type(), 0, "result"); result->addIncoming(LLVMValue::jint_constant(IC_IS_NULL), null_block); result->addIncoming(nonnull_result, nonnull_block); @@ -1698,7 +1709,7 @@ void SharkTopLevelBlock::do_new() { heap_object = builder()->CreateIntToPtr( old_top, SharkType::oop_type(), "heap_object"); - Value *check = builder()->CreateCmpxchgPtr(new_top, top_addr, old_top); + Value *check = builder()->CreateAtomicCmpXchg(top_addr, old_top, new_top, llvm::SequentiallyConsistent); builder()->CreateCondBr( builder()->CreateICmpEQ(old_top, check), initialize, retry); @@ -1707,7 +1718,7 @@ void SharkTopLevelBlock::do_new() { builder()->SetInsertPoint(initialize); if (tlab_object) { PHINode *phi = builder()->CreatePHI( - SharkType::oop_type(), "fast_object"); + SharkType::oop_type(), 0, "fast_object"); phi->addIncoming(tlab_object, got_tlab); phi->addIncoming(heap_object, got_heap); fast_object = phi; @@ -1730,7 +1741,7 @@ void SharkTopLevelBlock::do_new() { Value *klass_addr = builder()->CreateAddressOfStructEntry( fast_object, in_ByteSize(oopDesc::klass_offset_in_bytes()), - PointerType::getUnqual(SharkType::oop_type()), + PointerType::getUnqual(SharkType::klass_type()), "klass_addr"); // Set the mark @@ -1744,7 +1755,7 @@ void SharkTopLevelBlock::do_new() { builder()->CreateStore(LLVMValue::intptr_constant(mark), mark_addr); // Set the class - Value *rtklass = builder()->CreateInlineOop(klass); + Value *rtklass = builder()->CreateInlineMetadata(klass, SharkType::klass_type()); builder()->CreateStore(rtklass, klass_addr); got_fast = builder()->GetInsertBlock(); @@ -1767,7 +1778,7 @@ void SharkTopLevelBlock::do_new() { builder()->SetInsertPoint(push_object); } if (fast_object) { - PHINode *phi = builder()->CreatePHI(SharkType::oop_type(), "object"); + PHINode *phi = builder()->CreatePHI(SharkType::oop_type(), 0, "object"); phi->addIncoming(fast_object, got_fast); phi->addIncoming(slow_object, got_slow); object = phi; @@ -1849,8 +1860,9 @@ void SharkTopLevelBlock::do_multianewarray() { void SharkTopLevelBlock::acquire_method_lock() { Value *lockee; - if (target()->is_static()) + if (target()->is_static()) { lockee = builder()->CreateInlineOop(target()->holder()->java_mirror()); + } else lockee = local(0)->jobject_value(); @@ -1898,7 +1910,7 @@ void SharkTopLevelBlock::acquire_lock(Value *lockee, int exception_action) { Value *lock = builder()->CreatePtrToInt( monitor_header_addr, SharkType::intptr_type()); - Value *check = builder()->CreateCmpxchgPtr(lock, mark_addr, disp); + Value *check = builder()->CreateAtomicCmpXchg(mark_addr, disp, lock, llvm::Acquire); builder()->CreateCondBr( builder()->CreateICmpEQ(disp, check), acquired_fast, try_recursive); @@ -1983,7 +1995,7 @@ void SharkTopLevelBlock::release_lock(int exception_action) { PointerType::getUnqual(SharkType::intptr_type()), "mark_addr"); - Value *check = builder()->CreateCmpxchgPtr(disp, mark_addr, lock); + Value *check = builder()->CreateAtomicCmpXchg(mark_addr, lock, disp, llvm::Release); builder()->CreateCondBr( builder()->CreateICmpEQ(lock, check), released_fast, slow_path); diff --git a/hotspot/src/share/vm/shark/sharkTopLevelBlock.hpp b/hotspot/src/share/vm/shark/sharkTopLevelBlock.hpp index 067ea6285d1..a1306f30cb5 100644 --- a/hotspot/src/share/vm/shark/sharkTopLevelBlock.hpp +++ b/hotspot/src/share/vm/shark/sharkTopLevelBlock.hpp @@ -290,7 +290,7 @@ class SharkTopLevelBlock : public SharkBlock { int exception_action) { decache_for_VM_call(); stack()->CreateSetLastJavaFrame(); - llvm::CallInst *res = builder()->CreateCall(callee, args_start, args_end); + llvm::CallInst *res = builder()->CreateCall(callee, llvm::makeArrayRef(args_start, args_end)); stack()->CreateResetLastJavaFrame(); cache_after_VM_call(); if (exception_action & EAM_CHECK) { diff --git a/hotspot/src/share/vm/shark/sharkType.hpp b/hotspot/src/share/vm/shark/sharkType.hpp index c4e0d957518..719722bc79f 100644 --- a/hotspot/src/share/vm/shark/sharkType.hpp +++ b/hotspot/src/share/vm/shark/sharkType.hpp @@ -40,82 +40,85 @@ class SharkType : public AllStatic { // Basic types public: - static const llvm::Type* void_type() { + static llvm::Type* void_type() { return context().void_type(); } - static const llvm::IntegerType* bit_type() { + static llvm::IntegerType* bit_type() { return context().bit_type(); } - static const llvm::IntegerType* jbyte_type() { + static llvm::IntegerType* jbyte_type() { return context().jbyte_type(); } - static const llvm::IntegerType* jshort_type() { + static llvm::IntegerType* jshort_type() { return context().jshort_type(); } - static const llvm::IntegerType* jint_type() { + static llvm::IntegerType* jint_type() { return context().jint_type(); } - static const llvm::IntegerType* jlong_type() { + static llvm::IntegerType* jlong_type() { return context().jlong_type(); } - static const llvm::Type* jfloat_type() { + static llvm::Type* jfloat_type() { return context().jfloat_type(); } - static const llvm::Type* jdouble_type() { + static llvm::Type* jdouble_type() { return context().jdouble_type(); } - static const llvm::IntegerType* intptr_type() { + static llvm::IntegerType* intptr_type() { return context().intptr_type(); } // Compound types public: - static const llvm::PointerType* itableOffsetEntry_type() { + static llvm::PointerType* itableOffsetEntry_type() { return context().itableOffsetEntry_type(); } - static const llvm::PointerType* jniEnv_type() { + static llvm::PointerType* jniEnv_type() { return context().jniEnv_type(); } - static const llvm::PointerType* jniHandleBlock_type() { + static llvm::PointerType* jniHandleBlock_type() { return context().jniHandleBlock_type(); } - static const llvm::PointerType* klass_type() { + static llvm::PointerType* Metadata_type() { + return context().Metadata_type(); + } + static llvm::PointerType* klass_type() { return context().klass_type(); } - static const llvm::PointerType* Method*_type() { - return context().Method*_type(); + static llvm::PointerType* Method_type() { + return context().Method_type(); } - static const llvm::ArrayType* monitor_type() { + static llvm::ArrayType* monitor_type() { return context().monitor_type(); } - static const llvm::PointerType* oop_type() { + static llvm::PointerType* oop_type() { return context().oop_type(); } - static const llvm::PointerType* thread_type() { + static llvm::PointerType* thread_type() { return context().thread_type(); } - static const llvm::PointerType* zeroStack_type() { + static llvm::PointerType* zeroStack_type() { return context().zeroStack_type(); } - static const llvm::FunctionType* entry_point_type() { + static llvm::FunctionType* entry_point_type() { return context().entry_point_type(); } - static const llvm::FunctionType* osr_entry_point_type() { + static llvm::FunctionType* osr_entry_point_type() { return context().osr_entry_point_type(); } // Mappings public: - static const llvm::Type* to_stackType(BasicType type) { + static llvm::Type* to_stackType(BasicType type) { return context().to_stackType(type); } - static const llvm::Type* to_stackType(ciType* type) { + static llvm::Type* to_stackType(ciType* type) { return to_stackType(type->basic_type()); } - static const llvm::Type* to_arrayType(BasicType type) { + static llvm::Type* to_arrayType(BasicType type) { return context().to_arrayType(type); } - static const llvm::Type* to_arrayType(ciType* type) { + static llvm::Type* to_arrayType(ciType* type) { return to_arrayType(type->basic_type()); } }; diff --git a/hotspot/src/share/vm/shark/sharkValue.cpp b/hotspot/src/share/vm/shark/sharkValue.cpp index e9b17a5f35b..0c4ef006a61 100644 --- a/hotspot/src/share/vm/shark/sharkValue.cpp +++ b/hotspot/src/share/vm/shark/sharkValue.cpp @@ -233,7 +233,7 @@ SharkValue* SharkNormalValue::merge(SharkBuilder* builder, assert(type() == other->type(), "should be"); assert(zero_checked() == other->zero_checked(), "should be"); - PHINode *phi = builder->CreatePHI(SharkType::to_stackType(type()), name); + PHINode *phi = builder->CreatePHI(SharkType::to_stackType(type()), 0, name); phi->addIncoming(this->generic_value(), this_block); phi->addIncoming(other->generic_value(), other_block); return SharkValue::create_generic(type(), phi, zero_checked()); diff --git a/hotspot/src/share/vm/shark/shark_globals.hpp b/hotspot/src/share/vm/shark/shark_globals.hpp index deae2f3c0b3..9ab174d654b 100644 --- a/hotspot/src/share/vm/shark/shark_globals.hpp +++ b/hotspot/src/share/vm/shark/shark_globals.hpp @@ -40,6 +40,12 @@ product(intx, SharkMaxInlineSize, 32, \ "Maximum bytecode size of methods to inline when using Shark") \ \ + product(bool, EliminateNestedLocks, true, \ + "Eliminate nested locks of the same object when possible") \ + \ + product(ccstr, SharkOptimizationLevel, "Default", \ + "The optimization level passed to LLVM, possible values: None, Less, Default and Agressive") \ + \ /* compiler debugging */ \ develop(ccstr, SharkPrintTypeflowOf, NULL, \ "Print the typeflow of the specified method") \ @@ -58,6 +64,10 @@ \ diagnostic(bool, SharkPerformanceWarnings, false, \ "Warn about things that could be made faster") \ + \ + develop(ccstr, SharkVerifyFunction, NULL, \ + "Runs LLVM verify over LLVM IR") \ + SHARK_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_NOTPRODUCT_FLAG) diff --git a/hotspot/src/share/vm/utilities/events.hpp b/hotspot/src/share/vm/utilities/events.hpp index 74a804219fa..c2e543da976 100644 --- a/hotspot/src/share/vm/utilities/events.hpp +++ b/hotspot/src/share/vm/utilities/events.hpp @@ -135,11 +135,11 @@ template class EventLogBase : public EventLog { }; // A simple wrapper class for fixed size text messages. -class StringLogMessage : public FormatBuffer<132> { +class StringLogMessage : public FormatBuffer<256> { public: // Wrap this buffer in a stringStream. stringStream stream() { - return stringStream(_buf, sizeof(_buf)); + return stringStream(_buf, size()); } }; diff --git a/hotspot/test/compiler/6865265/StackOverflowBug.java b/hotspot/test/compiler/6865265/StackOverflowBug.java index d474814054f..295a6b41777 100644 --- a/hotspot/test/compiler/6865265/StackOverflowBug.java +++ b/hotspot/test/compiler/6865265/StackOverflowBug.java @@ -28,7 +28,7 @@ * @summary JVM crashes with "missing exception handler" error * @author volker.simonis@sap.com * - * @run main/othervm -XX:CompileThreshold=100 -Xbatch -Xss224k StackOverflowBug + * @run main/othervm -XX:CompileThreshold=100 -Xbatch -Xss248k StackOverflowBug */ diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 7e7e54dfed2..091f63750e3 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -188,3 +188,5 @@ af9e8b0f1900b631a8a0fcccff9f1514fe58c808 jdk8-b59 27ab79568c34abf80958d5fa8c04fd1740d243da jdk8-b64 5cf3c69a93d6d088a1cdfa28031d4f0f9438c0de jdk8-b65 e6af1ad464e3d9b1154b9f9ed9a5373b97d129fc jdk8-b66 +83df3493ca3cf0be077f1d0dd90119456f266f54 jdk8-b67 +b854e70084214e9dcf1b37373f6e4b1a68760e03 jdk8-b68 diff --git a/jaxws/.hgtags b/jaxws/.hgtags index b6557e7b588..575a13941ef 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -188,3 +188,5 @@ d265b9b4c0f55c23a1c9fda02a8052fd9df2eec5 jdk8-b62 5ded18a14bcc80b2a253f2b84da0073a0ecac665 jdk8-b64 fbe54291c9d337ea4dfef4d846f1d9a22f76249c jdk8-b65 3eb7f11cb4e000555c1b6f0f1a10fe2919633c8e jdk8-b66 +eb06aa51dfc225614dba2d89ae7ca6cedddff982 jdk8-b67 +d3fe408f3a9ad250bc9a4e9365bdfc3f28c1d3f4 jdk8-b68 diff --git a/jdk/.hgtags b/jdk/.hgtags index 0181b2d733a..d941bf4d50e 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -188,3 +188,5 @@ f117a3e06f78a258074674ad17601f99bcb1ce0d jdk8-b63 26dbd73fb7662a29b3e47179fdc88a0bfa4e231e jdk8-b64 130d3a54d28becaac0846137256c2684adb34c33 jdk8-b65 4d337fae2250135729ee9ed2bf8baf3c60da5d6d jdk8-b66 +ce9b02a3a17edd1983201002cfa0f364e4ab7524 jdk8-b67 +53fb43e4d614c92310e1fb00ec41d1960fd9facf jdk8-b68 diff --git a/jdk/make/com/sun/security/Makefile b/jdk/make/com/sun/security/Makefile index 3a6ae4386e2..85a919b1824 100644 --- a/jdk/make/com/sun/security/Makefile +++ b/jdk/make/com/sun/security/Makefile @@ -35,7 +35,7 @@ SUBDIRS_MAKEFLAGS += JAVAC_WARNINGS_FATAL=true include $(BUILDDIR)/common/Defs.gmk SUBDIRS = auth -SUBDIRS_misc = jgss sasl auth/module +SUBDIRS_misc = jgss sasl auth/module ntlm include $(BUILDDIR)/common/Subdirs.gmk all build clean clobber:: diff --git a/jdk/make/com/sun/security/ntlm/Makefile b/jdk/make/com/sun/security/ntlm/Makefile new file mode 100644 index 00000000000..547092b7a61 --- /dev/null +++ b/jdk/make/com/sun/security/ntlm/Makefile @@ -0,0 +1,39 @@ +# +# 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. 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. +# + +BUILDDIR = ../../../.. +PACKAGE = com.sun.security.ntlm +PRODUCT = sun +include $(BUILDDIR)/common/Defs.gmk + +# +# Files +# +AUTO_FILES_JAVA_DIRS = com/sun/security/ntlm + +# +# Rules +# +include $(BUILDDIR)/common/Classes.gmk diff --git a/jdk/make/docs/CORE_PKGS.gmk b/jdk/make/docs/CORE_PKGS.gmk index cdef9ebbc97..2c2b1774f32 100644 --- a/jdk/make/docs/CORE_PKGS.gmk +++ b/jdk/make/docs/CORE_PKGS.gmk @@ -131,6 +131,7 @@ CORE_PKGS = \ java.util.concurrent \ java.util.concurrent.atomic \ java.util.concurrent.locks \ + java.util.function \ java.util.jar \ java.util.logging \ java.util.prefs \ diff --git a/jdk/make/java/java/FILES_java.gmk b/jdk/make/java/java/FILES_java.gmk index c35bb29989c..33d35caeef5 100644 --- a/jdk/make/java/java/FILES_java.gmk +++ b/jdk/make/java/java/FILES_java.gmk @@ -147,6 +147,7 @@ JAVA_JAVA_java = \ java/lang/ref/PhantomReference.java \ java/lang/ref/ReferenceQueue.java \ java/lang/ref/Finalizer.java \ + java/util/Base64.java \ java/util/BitSet.java \ java/util/Calendar.java \ java/util/GregorianCalendar.java \ diff --git a/jdk/make/java/java/Makefile b/jdk/make/java/java/Makefile index b2d1c5ab091..54f4dbdebfa 100644 --- a/jdk/make/java/java/Makefile +++ b/jdk/make/java/java/Makefile @@ -37,6 +37,8 @@ SUBDIRS_MAKEFLAGS += JAVAC_WARNINGS_FATAL=true JAVAC_MAX_WARNINGS=true include $(BUILDDIR)/common/Defs.gmk +AUTO_FILES_JAVA_DIRS = java/util/function + # windows compiler flags ifeq ($(PLATFORM),windows) OTHER_CFLAGS = diff --git a/jdk/make/java/net/Makefile b/jdk/make/java/net/Makefile index 60f83869f74..d45c92087f4 100644 --- a/jdk/make/java/net/Makefile +++ b/jdk/make/java/net/Makefile @@ -77,6 +77,7 @@ ifeq ($(PLATFORM), windows) FILES_export += java/net/DualStackPlainSocketImpl.java FILES_export += java/net/TwoStacksPlainDatagramSocketImpl.java FILES_export += java/net/DualStackPlainDatagramSocketImpl.java + FILES_export += sun/net/www/protocol/http/ntlm/NTLMAuthSequence.java else FILES_export += java/net/PlainDatagramSocketImpl.java endif diff --git a/jdk/make/java/nio/Makefile b/jdk/make/java/nio/Makefile index 94a50dc4bcb..9eebd5cc4ea 100644 --- a/jdk/make/java/nio/Makefile +++ b/jdk/make/java/nio/Makefile @@ -69,6 +69,7 @@ FILES_java += \ sun/nio/ch/UnixAsynchronousSocketChannelImpl.java \ \ sun/nio/fs/GnomeFileTypeDetector.java \ + sun/nio/fs/MimeTypesFileTypeDetector.java \ sun/nio/fs/PollingWatchService.java \ sun/nio/fs/SolarisAclFileAttributeView.java \ sun/nio/fs/SolarisFileStore.java \ @@ -202,6 +203,8 @@ FILES_java += \ sun/nio/ch/UnixAsynchronousSocketChannelImpl.java \ \ sun/nio/fs/GnomeFileTypeDetector.java \ + sun/nio/fs/MagicFileTypeDetector.java \ + sun/nio/fs/MimeTypesFileTypeDetector.java \ sun/nio/fs/LinuxDosFileAttributeView.java \ sun/nio/fs/LinuxFileStore.java \ sun/nio/fs/LinuxFileSystem.java \ @@ -239,6 +242,7 @@ FILES_c += \ UnixAsynchronousSocketChannelImpl.c \ \ GnomeFileTypeDetector.c \ + MagicFileTypeDetector.c \ LinuxNativeDispatcher.c \ LinuxWatchService.c \ UnixCopyFile.c \ @@ -254,6 +258,7 @@ FILES_export += \ sun/nio/ch/UnixAsynchronousSocketChannelImpl.java \ \ sun/nio/fs/GnomeFileTypeDetector.java \ + sun/nio/fs/MagicFileTypeDetector.java \ sun/nio/fs/LinuxNativeDispatcher.java \ sun/nio/fs/LinuxWatchService.java \ sun/nio/fs/UnixCopyFile.java \ @@ -277,6 +282,7 @@ FILES_java += \ sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java \ sun/nio/ch/UnixAsynchronousSocketChannelImpl.java \ \ + sun/nio/fs/MimeTypesFileTypeDetector.java \ sun/nio/fs/BsdFileStore.java \ sun/nio/fs/BsdFileSystem.java \ sun/nio/fs/BsdFileSystemProvider.java \ diff --git a/jdk/make/java/nio/mapfile-linux b/jdk/make/java/nio/mapfile-linux index d78a74400b3..92c7d318894 100644 --- a/jdk/make/java/nio/mapfile-linux +++ b/jdk/make/java/nio/mapfile-linux @@ -130,6 +130,8 @@ SUNWprivate_1.1 { Java_sun_nio_fs_GnomeFileTypeDetector_probeUsingGio; Java_sun_nio_fs_GnomeFileTypeDetector_initializeGnomeVfs; Java_sun_nio_fs_GnomeFileTypeDetector_probeUsingGnomeVfs; + Java_sun_nio_fs_MagicFileTypeDetector_initialize0; + Java_sun_nio_fs_MagicFileTypeDetector_probe0; Java_sun_nio_fs_LinuxWatchService_eventSize; Java_sun_nio_fs_LinuxWatchService_eventOffsets; Java_sun_nio_fs_LinuxWatchService_inotifyInit; diff --git a/jdk/make/java/security/Makefile b/jdk/make/java/security/Makefile index d68d0a03510..bbb0ca4f757 100644 --- a/jdk/make/java/security/Makefile +++ b/jdk/make/java/security/Makefile @@ -40,7 +40,8 @@ AUTO_FILES_JAVA_DIRS = java/security # Directories # -PROPS_SRC = $(TOPDIR)/src/share/lib/security/java.security +# The default security properties file is for linux +PROPS_SRC = $(TOPDIR)/src/share/lib/security/java.security-linux ifeq ($(PLATFORM), solaris) PROPS_SRC = $(TOPDIR)/src/share/lib/security/java.security-solaris diff --git a/jdk/make/jprt.properties b/jdk/make/jprt.properties index cbf8540e02f..4bd2d4b84c6 100644 --- a/jdk/make/jprt.properties +++ b/jdk/make/jprt.properties @@ -86,7 +86,6 @@ jprt.make.rule.core.test.targets= \ ${jprt.my.test.target.set:TESTNAME=jdk_jmx}, \ ${jprt.my.test.target.set:TESTNAME=jdk_text}, \ ${jprt.my.test.target.set:TESTNAME=jdk_tools}, \ - ${jprt.my.test.target.set:TESTNAME=jdk_jdi}, \ ${jprt.my.test.target.set:TESTNAME=jdk_jfr}, \ ${jprt.my.test.target.set:TESTNAME=jdk_other} @@ -103,6 +102,7 @@ jprt.make.rule.all.test.targets= \ ${jprt.my.test.target.set:TESTNAME=jdk_beans1}, \ ${jprt.my.test.target.set:TESTNAME=jdk_beans2}, \ ${jprt.my.test.target.set:TESTNAME=jdk_beans3}, \ + ${jprt.my.test.target.set:TESTNAME=jdk_jdi}, \ ${jprt.my.test.target.set:TESTNAME=jdk_sound}, \ ${jprt.my.test.target.set:TESTNAME=jdk_swing} diff --git a/jdk/make/sun/security/Makefile b/jdk/make/sun/security/Makefile index 50720320121..9e9f8c50d36 100644 --- a/jdk/make/sun/security/Makefile +++ b/jdk/make/sun/security/Makefile @@ -38,10 +38,12 @@ SUBDIRS_MAKEFLAGS += JAVAC_MAX_WARNINGS=true SUBDIRS_MAKEFLAGS += JAVAC_WARNINGS_FATAL=true include $(BUILDDIR)/common/Defs.gmk -# build sun/security/jgss/wrapper on non-windows platform +# build sun/security/jgss/wrapper on non-windows non-macosx platforms JGSS_WRAPPER = ifneq ($(PLATFORM), windows) - JGSS_WRAPPER = jgss/wrapper + ifneq ($(PLATFORM), macosx) + JGSS_WRAPPER = jgss/wrapper + endif endif # Build PKCS#11 on all platforms diff --git a/jdk/make/tools/src/build/tools/cldrconverter/Bundle.java b/jdk/make/tools/src/build/tools/cldrconverter/Bundle.java index dc277ea684e..701ea4b057d 100644 --- a/jdk/make/tools/src/build/tools/cldrconverter/Bundle.java +++ b/jdk/make/tools/src/build/tools/cldrconverter/Bundle.java @@ -29,6 +29,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.EnumSet; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; @@ -86,7 +87,23 @@ class Bundle { private final static String[] ERA_KEYS = { "long.Eras", "Eras", - "short.Eras" + "narrow.Eras" + }; + + // Keys for individual time zone names + private final static String TZ_GEN_LONG_KEY = "timezone.displayname.generic.long"; + private final static String TZ_GEN_SHORT_KEY = "timezone.displayname.generic.short"; + private final static String TZ_STD_LONG_KEY = "timezone.displayname.standard.long"; + private final static String TZ_STD_SHORT_KEY = "timezone.displayname.standard.short"; + private final static String TZ_DST_LONG_KEY = "timezone.displayname.daylight.long"; + private final static String TZ_DST_SHORT_KEY = "timezone.displayname.daylight.short"; + private final static String[] ZONE_NAME_KEYS = { + TZ_STD_LONG_KEY, + TZ_STD_SHORT_KEY, + TZ_DST_LONG_KEY, + TZ_DST_SHORT_KEY, + TZ_GEN_LONG_KEY, + TZ_GEN_SHORT_KEY }; private final String id; @@ -98,6 +115,7 @@ class Bundle { return bundles.get(id); } + @SuppressWarnings("ConvertToStringSwitch") Bundle(String id, String cldrPath, String bundles, String currencies) { this.id = id; this.cldrPath = cldrPath; @@ -242,9 +260,12 @@ class Bundle { // handle multiple inheritance for month and day names handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "MonthNames"); handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "MonthAbbreviations"); + handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "MonthNarrows"); handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "DayNames"); handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "DayAbbreviations"); + handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "DayNarrows"); handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "AmPmMarkers"); + handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "narrow.AmPmMarkers"); adjustEraNames(myMap, calendarType); @@ -253,6 +274,99 @@ class Bundle { handleDateTimeFormatPatterns(DATETIME_PATTERN_KEYS, myMap, parentsMap, calendarType, "DateTimePatterns"); } + // if myMap has any empty timezone or metazone names, weed out them. + // Fill in any missing abbreviations if locale is "en". + for (Iterator it = myMap.keySet().iterator(); it.hasNext();) { + String key = it.next(); + if (key.startsWith(CLDRConverter.TIMEZONE_ID_PREFIX) + || key.startsWith(CLDRConverter.METAZONE_ID_PREFIX)) { + @SuppressWarnings("unchecked") + Map nameMap = (Map) myMap.get(key); + if (nameMap.isEmpty()) { + // Some zones have only exemplarCity, which become empty. + // Remove those from the map. + it.remove(); + continue; + } + + if (id.startsWith("en")) { + fillInAbbrs(key, nameMap); + } + } + } + for (Iterator it = myMap.keySet().iterator(); it.hasNext();) { + String key = it.next(); + if (key.startsWith(CLDRConverter.TIMEZONE_ID_PREFIX) + || key.startsWith(CLDRConverter.METAZONE_ID_PREFIX)) { + @SuppressWarnings("unchecked") + Map nameMap = (Map) myMap.get(key); + // Convert key/value pairs to an array. + String[] names = new String[ZONE_NAME_KEYS.length]; + int ix = 0; + for (String nameKey : ZONE_NAME_KEYS) { + String name = nameMap.get(nameKey); + if (name == null) { + @SuppressWarnings("unchecked") + Map parentNames = (Map) parentsMap.get(key); + if (parentNames != null) { + name = parentNames.get(nameKey); + } + } + names[ix++] = name; + } + if (hasNulls(names)) { + String metaKey = toMetaZoneKey(key); + if (metaKey != null) { + Object obj = myMap.get(metaKey); + if (obj instanceof String[]) { + String[] metaNames = (String[]) obj; + for (int i = 0; i < names.length; i++) { + if (names[i] == null) { + names[i] = metaNames[i]; + } + } + } else if (obj instanceof Map) { + @SuppressWarnings("unchecked") + Map m = (Map) obj; + for (int i = 0; i < names.length; i++) { + if (names[i] == null) { + names[i] = m.get(ZONE_NAME_KEYS[i]); + } + } + } + } + // If there are still any nulls, try filling in them from en data. + if (hasNulls(names) && !id.equals("en")) { + @SuppressWarnings("unchecked") + String[] enNames = (String[]) Bundle.getBundle("en").getTargetMap().get(key); + if (enNames == null) { + if (metaKey != null) { + @SuppressWarnings("unchecked") + String[] metaNames = (String[]) Bundle.getBundle("en").getTargetMap().get(metaKey); + enNames = metaNames; + } + } + if (enNames != null) { + for (int i = 0; i < names.length; i++) { + if (names[i] == null) { + names[i] = enNames[i]; + } + } + } + // If there are still nulls, give up names. + if (hasNulls(names)) { + names = null; + } + } + } + // replace the Map with the array + if (names != null) { + myMap.put(key, names); + } else { + it.remove(); + } + } + } return myMap; } @@ -352,20 +466,10 @@ class Bundle { realKeys[index] = realKey; eraNames[index++] = value; } - if (eraNames[0] != null) { - if (eraNames[1] != null) { - if (eraNames[2] == null) { - // Eras -> short.Eras - // long.Eras -> Eras - map.put(realKeys[2], map.get(realKeys[1])); - map.put(realKeys[1], map.get(realKeys[0])); - } - } else { - // long.Eras -> Eras - map.put(realKeys[1], map.get(realKeys[0])); + for (int i = 0; i < eraNames.length; i++) { + if (eraNames[i] == null) { + map.put(realKeys[i], null); } - // remove long.Eras - map.remove(realKeys[0]); } } @@ -473,6 +577,86 @@ class Bundle { return jrePattern.toString(); } + private String toMetaZoneKey(String tzKey) { + if (tzKey.startsWith(CLDRConverter.TIMEZONE_ID_PREFIX)) { + String tz = tzKey.substring(CLDRConverter.TIMEZONE_ID_PREFIX.length()); + String meta = CLDRConverter.handlerMetaZones.get(tz); + if (meta != null) { + return CLDRConverter.METAZONE_ID_PREFIX + meta; + } + } + return null; + } + + private void fillInAbbrs(String key, Map map) { + fillInAbbrs(TZ_STD_LONG_KEY, TZ_STD_SHORT_KEY, map); + fillInAbbrs(TZ_DST_LONG_KEY, TZ_DST_SHORT_KEY, map); + fillInAbbrs(TZ_GEN_LONG_KEY, TZ_GEN_SHORT_KEY, map); + + // If the standard std is "Standard Time" and daylight std is "Summer Time", + // replace the standard std with the generic std to avoid using + // the same abbrivation except for Australia time zone names. + String std = map.get(TZ_STD_SHORT_KEY); + String dst = map.get(TZ_DST_SHORT_KEY); + String gen = map.get(TZ_GEN_SHORT_KEY); + if (std != null) { + if (dst == null) { + // if dst is null, create long and short names from the standard + // std. ("Something Standard Time" to "Something Daylight Time", + // or "Something Time" to "Something Summer Time") + String name = map.get(TZ_STD_LONG_KEY); + if (name != null) { + if (name.contains("Standard Time")) { + name = name.replace("Standard Time", "Daylight Time"); + } else if (name.endsWith("Mean Time")) { + name = name.replace("Mean Time", "Summer Time"); + } else if (name.endsWith(" Time")) { + name = name.replace(" Time", " Summer Time"); + } + map.put(TZ_DST_LONG_KEY, name); + fillInAbbrs(TZ_DST_LONG_KEY, TZ_DST_SHORT_KEY, map); + } + } + if (gen == null) { + String name = map.get(TZ_STD_LONG_KEY); + if (name != null) { + if (name.endsWith("Standard Time")) { + name = name.replace("Standard Time", "Time"); + } else if (name.endsWith("Mean Time")) { + name = name.replace("Mean Time", "Time"); + } + map.put(TZ_GEN_LONG_KEY, name); + fillInAbbrs(TZ_GEN_LONG_KEY, TZ_GEN_SHORT_KEY, map); + } + } + } + } + + private void fillInAbbrs(String longKey, String shortKey, Map map) { + String abbr = map.get(shortKey); + if (abbr == null) { + String name = map.get(longKey); + if (name != null) { + abbr = toAbbr(name); + if (abbr != null) { + map.put(shortKey, abbr); + } + } + } + } + + private String toAbbr(String name) { + String[] substrs = name.split("\\s+"); + StringBuilder sb = new StringBuilder(); + for (String s : substrs) { + char c = s.charAt(0); + if (c >= 'A' && c <= 'Z') { + sb.append(c); + } + } + return sb.length() > 0 ? sb.toString() : null; + } + private void convert(CalendarType calendarType, char cldrLetter, int count, StringBuilder sb) { switch (cldrLetter) { case 'G': @@ -539,4 +723,13 @@ class Bundle { sb.append(c); } } + + private static boolean hasNulls(Object[] array) { + for (int i = 0; i < array.length; i++) { + if (array[i] == null) { + return true; + } + } + return false; + } } diff --git a/jdk/make/tools/src/build/tools/cldrconverter/BundleGenerator.java b/jdk/make/tools/src/build/tools/cldrconverter/BundleGenerator.java index f06a903a26e..14760bcbb4d 100644 --- a/jdk/make/tools/src/build/tools/cldrconverter/BundleGenerator.java +++ b/jdk/make/tools/src/build/tools/cldrconverter/BundleGenerator.java @@ -30,8 +30,27 @@ import java.util.Map; import java.util.SortedSet; public interface BundleGenerator { + static enum BundleType { + PLAIN("java.util.ListResourceBundle"), + OPEN("sun.util.resources.OpenListResourceBundle"), + TIMEZONE("sun.util.resources.TimeZoneNamesBundle"); + + private final String pathName, className; + private BundleType(String name) { + pathName = name; + int x = name.lastIndexOf('.'); + className = name.substring(x + 1); + } + String getPathName() { + return pathName; + } + String getClassName() { + return className; + } + }; + public void generateBundle(String packageName, String baseName, String localeID, - boolean useJava, Map map, boolean open) throws IOException; + boolean useJava, Map map, BundleType type) throws IOException; public void generateMetaInfo(Map> metaInfo) throws IOException; } diff --git a/jdk/make/tools/src/build/tools/cldrconverter/CLDRConverter.java b/jdk/make/tools/src/build/tools/cldrconverter/CLDRConverter.java index 106e3475a8e..1d5cd5e2d8f 100644 --- a/jdk/make/tools/src/build/tools/cldrconverter/CLDRConverter.java +++ b/jdk/make/tools/src/build/tools/cldrconverter/CLDRConverter.java @@ -25,6 +25,7 @@ package build.tools.cldrconverter; +import build.tools.cldrconverter.BundleGenerator.BundleType; import java.io.File; import java.nio.file.DirectoryStream; import java.nio.file.FileSystems; @@ -58,9 +59,8 @@ public class CLDRConverter { static final String CURRENCY_SYMBOL_PREFIX = "currency.symbol."; static final String CURRENCY_NAME_PREFIX = "currency.displayname."; static final String TIMEZONE_ID_PREFIX = "timezone.id."; - static final String TIMEZONE_NAME_PREFIX = "timezone.displayname."; + static final String ZONE_NAME_PREFIX = "timezone.displayname."; static final String METAZONE_ID_PREFIX = "metazone.id."; - static final String METAZONE_NAME_PREFIX = "metazone.displayname."; private static SupplementDataParseHandler handlerSuppl; static NumberingSystemsParseHandler handlerNumbering; @@ -236,7 +236,14 @@ public class CLDRConverter { if (sb.indexOf("root") == -1) { sb.append("root"); } - retList.add(new Bundle(id, sb.toString(), null, null)); + Bundle b = new Bundle(id, sb.toString(), null, null); + // Insert the bundle for en at the top so that it will get + // processed first. + if ("en".equals(id)) { + retList.add(0, b); + } else { + retList.add(b); + } } } } @@ -312,6 +319,7 @@ public class CLDRConverter { Map> metaInfo = new HashMap<>(); metaInfo.put("LocaleNames", new TreeSet()); metaInfo.put("CurrencyNames", new TreeSet()); + metaInfo.put("TimeZoneNames", new TreeSet()); metaInfo.put("CalendarData", new TreeSet()); metaInfo.put("FormatData", new TreeSet()); @@ -348,24 +356,28 @@ public class CLDRConverter { Map localeNamesMap = extractLocaleNames(targetMap, bundle.getID()); if (!localeNamesMap.isEmpty() || bundle.isRoot()) { metaInfo.get("LocaleNames").add(toLanguageTag(bundle.getID())); - bundleGenerator.generateBundle("util", "LocaleNames", bundle.getID(), true, localeNamesMap, true); + bundleGenerator.generateBundle("util", "LocaleNames", bundle.getID(), true, localeNamesMap, BundleType.OPEN); } } if (bundleTypes.contains(Bundle.Type.CURRENCYNAMES)) { Map currencyNamesMap = extractCurrencyNames(targetMap, bundle.getID(), bundle.getCurrencies()); if (!currencyNamesMap.isEmpty() || bundle.isRoot()) { metaInfo.get("CurrencyNames").add(toLanguageTag(bundle.getID())); - bundleGenerator.generateBundle("util", "CurrencyNames", bundle.getID(), true, currencyNamesMap, true); + bundleGenerator.generateBundle("util", "CurrencyNames", bundle.getID(), true, currencyNamesMap, BundleType.OPEN); } } if (bundleTypes.contains(Bundle.Type.TIMEZONENAMES)) { Map zoneNamesMap = extractZoneNames(targetMap, bundle.getID()); + if (!zoneNamesMap.isEmpty() || bundle.isRoot()) { + metaInfo.get("TimeZoneNames").add(toLanguageTag(bundle.getID())); + bundleGenerator.generateBundle("util", "TimeZoneNames", bundle.getID(), true, zoneNamesMap, BundleType.TIMEZONE); + } } if (bundleTypes.contains(Bundle.Type.CALENDARDATA)) { Map calendarDataMap = extractCalendarData(targetMap, bundle.getID()); if (!calendarDataMap.isEmpty() || bundle.isRoot()) { metaInfo.get("CalendarData").add(toLanguageTag(bundle.getID())); - bundleGenerator.generateBundle("util", "CalendarData", bundle.getID(), true, calendarDataMap, false); + bundleGenerator.generateBundle("util", "CalendarData", bundle.getID(), true, calendarDataMap, BundleType.PLAIN); } } if (bundleTypes.contains(Bundle.Type.FORMATDATA)) { @@ -373,9 +385,10 @@ public class CLDRConverter { // LocaleData.getAvailableLocales depends on having FormatData bundles around if (!formatDataMap.isEmpty() || bundle.isRoot()) { metaInfo.get("FormatData").add(toLanguageTag(bundle.getID())); - bundleGenerator.generateBundle("text", "FormatData", bundle.getID(), true, formatDataMap, false); + bundleGenerator.generateBundle("text", "FormatData", bundle.getID(), true, formatDataMap, BundleType.PLAIN); } } + // For testing SortedSet allLocales = new TreeSet<>(); allLocales.addAll(metaInfo.get("CurrencyNames")); @@ -431,6 +444,7 @@ public class CLDRConverter { private KeyComparator() { } + @Override public int compare(String o1, String o2) { int len1 = o1.length(); int len2 = o2.length(); @@ -476,7 +490,26 @@ public class CLDRConverter { } private static Map extractZoneNames(Map map, String id) { - return null; + Map names = new HashMap<>(); + for (String tzid : handlerMetaZones.keySet()) { + String tzKey = TIMEZONE_ID_PREFIX + tzid; + Object data = map.get(tzKey); + if (data instanceof String[]) { + names.put(tzid, data); + } else { + String meta = handlerMetaZones.get(tzid); + if (meta != null) { + String metaKey = METAZONE_ID_PREFIX + meta; + data = map.get(metaKey); + if (data instanceof String[]) { + // Keep the metazone prefix here. + names.put(metaKey, data); + names.put(tzid, meta); + } + } + } + } + return names; } private static Map extractCalendarData(Map map, String id) { @@ -494,11 +527,19 @@ public class CLDRConverter { copyIfPresent(map, prefix + "standalone.MonthNames", formatData); copyIfPresent(map, prefix + "MonthAbbreviations", formatData); copyIfPresent(map, prefix + "standalone.MonthAbbreviations", formatData); + copyIfPresent(map, prefix + "MonthNarrow", formatData); + copyIfPresent(map, prefix + "standalone.MonthNarrows", formatData); copyIfPresent(map, prefix + "DayNames", formatData); + copyIfPresent(map, prefix + "standalone.DayNames", formatData); copyIfPresent(map, prefix + "DayAbbreviations", formatData); + copyIfPresent(map, prefix + "standalone.DayAbbreviations", formatData); + copyIfPresent(map, prefix + "DayNarrows", formatData); + copyIfPresent(map, prefix + "standalone.DayNarrows", formatData); copyIfPresent(map, prefix + "AmPmMarkers", formatData); + copyIfPresent(map, prefix + "narrow.AmPmMarkers", formatData); + copyIfPresent(map, prefix + "long.Eras", formatData); copyIfPresent(map, prefix + "Eras", formatData); - copyIfPresent(map, prefix + "short.Eras", formatData); + copyIfPresent(map, prefix + "narrow.Eras", formatData); copyIfPresent(map, prefix + "TimePatterns", formatData); copyIfPresent(map, prefix + "DatePatterns", formatData); copyIfPresent(map, prefix + "DateTimePatterns", formatData); @@ -560,7 +601,6 @@ public class CLDRConverter { if (x == 0 || escapeSpace) { outBuffer.append('\\'); } - outBuffer.append(' '); break; case '\\': @@ -584,7 +624,7 @@ public class CLDRConverter { outBuffer.append('f'); break; default: - if (!USE_UTF8 && ((aChar < 0x0020) || (aChar > 0x007e))) { + if (aChar < 0x0020 || (!USE_UTF8 && aChar > 0x007e)) { formatter.format("\\u%04x", (int)aChar); } else { if (specialSaveChars.indexOf(aChar) != -1) { diff --git a/jdk/make/tools/src/build/tools/cldrconverter/LDMLParseHandler.java b/jdk/make/tools/src/build/tools/cldrconverter/LDMLParseHandler.java index 128eaf6ef57..812aab244fa 100644 --- a/jdk/make/tools/src/build/tools/cldrconverter/LDMLParseHandler.java +++ b/jdk/make/tools/src/build/tools/cldrconverter/LDMLParseHandler.java @@ -155,6 +155,9 @@ class LDMLParseHandler extends AbstractLDMLHandler { case "abbreviated": pushStringArrayEntry(qName, attributes, prefix + "MonthAbbreviations/" + getContainerKey(), 13); break; + case "narrow": + pushStringArrayEntry(qName, attributes, prefix + "MonthNarrows/" + getContainerKey(), 13); + break; default: pushIgnoredContainer(qName); break; @@ -191,6 +194,9 @@ class LDMLParseHandler extends AbstractLDMLHandler { case "abbreviated": pushStringArrayEntry(qName, attributes, prefix + "DayAbbreviations/" + getContainerKey(), 7); break; + case "narrow": + pushStringArrayEntry(qName, attributes, prefix + "DayNarrows/" + getContainerKey(), 7); + break; default: pushIgnoredContainer(qName); break; @@ -219,25 +225,36 @@ class LDMLParseHandler extends AbstractLDMLHandler { case "dayPeriodWidth": // for FormatData // create string array entry for am/pm. only keeping wide - if ("wide".equals(attributes.getValue("type"))) { + switch (attributes.getValue("type")) { + case "wide": pushStringArrayEntry(qName, attributes, "AmPmMarkers/" + getContainerKey(), 2); - } else { + break; + case "narrow": + pushStringArrayEntry(qName, attributes, "narrow.AmPmMarkers/" + getContainerKey(), 2); + break; + default: pushIgnoredContainer(qName); + break; } break; case "dayPeriod": // for FormatData // add to string array entry of AmPmMarkers element - switch (attributes.getValue("type")) { - case "am": - pushStringArrayElement(qName, attributes, 0); - break; - case "pm": - pushStringArrayElement(qName, attributes, 1); - break; - default: + if (attributes.getValue("alt") == null) { + switch (attributes.getValue("type")) { + case "am": + pushStringArrayElement(qName, attributes, 0); + break; + case "pm": + pushStringArrayElement(qName, attributes, 1); + break; + default: + pushIgnoredContainer(qName); + break; + } + } else { + // discard alt values pushIgnoredContainer(qName); - break; } break; case "eraNames": @@ -269,7 +286,7 @@ class LDMLParseHandler extends AbstractLDMLHandler { assert currentContainer instanceof IgnoredContainer; pushIgnoredContainer(qName); } else { - String key = currentCalendarType.keyElementName() + "short.Eras"; + String key = currentCalendarType.keyElementName() + "narrow.Eras"; pushStringArrayEntry(qName, attributes, key, currentCalendarType.getEraLength(qName)); } break; @@ -301,15 +318,15 @@ class LDMLParseHandler extends AbstractLDMLHandler { break; case "zone": { - String zone = attributes.getValue("type"); + String tzid = attributes.getValue("type"); // Olson tz id zonePrefix = CLDRConverter.TIMEZONE_ID_PREFIX; - put(zonePrefix + zone, new HashMap()); - pushKeyContainer(qName, attributes, zone); + put(zonePrefix + tzid, new HashMap()); + pushKeyContainer(qName, attributes, tzid); } break; case "metazone": { - String zone = attributes.getValue("type"); + String zone = attributes.getValue("type"); // LDML meta zone id zonePrefix = CLDRConverter.METAZONE_ID_PREFIX; put(zonePrefix + zone, new HashMap()); pushKeyContainer(qName, attributes, zone); @@ -323,16 +340,12 @@ class LDMLParseHandler extends AbstractLDMLHandler { zoneNameStyle = "short"; pushContainer(qName, attributes); break; - case "generic": // not used in JDK - pushIgnoredContainer(qName); + case "generic": // generic name + case "standard": // standard time name + case "daylight": // daylight saving (summer) time name + pushStringEntry(qName, attributes, CLDRConverter.ZONE_NAME_PREFIX + qName + "." + zoneNameStyle); break; - case "standard": // standard time - pushStringEntry(qName, attributes, CLDRConverter.TIMEZONE_NAME_PREFIX + "standard." + zoneNameStyle); - break; - case "daylight": - pushStringEntry(qName, attributes, CLDRConverter.TIMEZONE_NAME_PREFIX + "daylight." + zoneNameStyle); - break; - case "exemplarCity": + case "exemplarCity": // not used in JDK pushIgnoredContainer(qName); break; @@ -530,6 +543,7 @@ class LDMLParseHandler extends AbstractLDMLHandler { case "timeZoneNames": zonePrefix = null; break; + case "generic": case "standard": case "daylight": if (zonePrefix != null && (currentContainer instanceof Entry)) { diff --git a/jdk/make/tools/src/build/tools/cldrconverter/MetaZonesParseHandler.java b/jdk/make/tools/src/build/tools/cldrconverter/MetaZonesParseHandler.java index 5c6f50b4ae9..99be8cfd882 100644 --- a/jdk/make/tools/src/build/tools/cldrconverter/MetaZonesParseHandler.java +++ b/jdk/make/tools/src/build/tools/cldrconverter/MetaZonesParseHandler.java @@ -46,8 +46,9 @@ class MetaZonesParseHandler extends AbstractLDMLHandler { return null; } + // metaZone: ID -> metazone + // per locale: ID -> names, metazone -> names @Override - @SuppressWarnings("fallthrough") public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { switch (qName) { case "timezone": diff --git a/jdk/make/tools/src/build/tools/cldrconverter/ResourceBundleGenerator.java b/jdk/make/tools/src/build/tools/cldrconverter/ResourceBundleGenerator.java index 2d031fa8ba3..c7826a2519b 100644 --- a/jdk/make/tools/src/build/tools/cldrconverter/ResourceBundleGenerator.java +++ b/jdk/make/tools/src/build/tools/cldrconverter/ResourceBundleGenerator.java @@ -28,14 +28,16 @@ package build.tools.cldrconverter; import java.io.File; import java.io.IOException; import java.io.PrintWriter; +import java.util.Formatter; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import java.util.SortedSet; class ResourceBundleGenerator implements BundleGenerator { - @Override public void generateBundle(String packageName, String baseName, String localeID, boolean useJava, - Map map, boolean open) throws IOException { + Map map, BundleType type) throws IOException { String suffix = useJava ? ".java" : ".properties"; String lang = CLDRConverter.getLanguageCode(localeID); String dirName = CLDRConverter.DESTINATION_DIR + File.separator + "sun" + File.separator @@ -67,6 +69,28 @@ class ResourceBundleGenerator implements BundleGenerator { encoding = "iso-8859-1"; } + Formatter fmt = null; + if (type == BundleType.TIMEZONE) { + fmt = new Formatter(); + Set metaKeys = new HashSet<>(); + for (String key : map.keySet()) { + if (key.startsWith(CLDRConverter.METAZONE_ID_PREFIX)) { + String meta = key.substring(CLDRConverter.METAZONE_ID_PREFIX.length()); + String[] value; + value = (String[]) map.get(key); + fmt.format(" final String[] %s = new String[] {\n", meta); + for (String s : value) { + fmt.format(" \"%s\",\n", CLDRConverter.saveConvert(s, useJava)); + } + fmt.format(" };\n"); + metaKeys.add(key); + } + } + for (String key : metaKeys) { + map.remove(key); + } + } + try (PrintWriter out = new PrintWriter(file, encoding)) { // Output copyright headers out.println(CopyrightHeaders.getOpenJDKCopyright()); @@ -74,16 +98,15 @@ class ResourceBundleGenerator implements BundleGenerator { if (useJava) { out.println("package sun." + packageName + ";\n"); - if (open) { - out.println("import sun.util.resources.OpenListResourceBundle;\n"); - out.println("public class " + baseName + ("root".equals(localeID) ? "" : "_" + localeID) + " extends OpenListResourceBundle {"); - } else { - out.println("import java.util.ListResourceBundle;\n"); - out.println("public class " + baseName + ("root".equals(localeID) ? "" : "_" + localeID) + " extends ListResourceBundle {"); - } + out.printf("import %s;\n\n", type.getPathName()); + out.printf("public class %s%s extends %s {\n", baseName, "root".equals(localeID) ? "" : "_" + localeID, type.getClassName()); + out.println(" @Override\n" + - " protected final Object[][] getContents() {\n" + - " final Object[][] data = new Object[][] {"); + " protected final Object[][] getContents() {"); + if (fmt != null) { + out.print(fmt.toString()); + } + out.println(" final Object[][] data = new Object[][] {"); } for (String key : map.keySet()) { if (useJava) { @@ -91,7 +114,11 @@ class ResourceBundleGenerator implements BundleGenerator { if (value == null) { CLDRConverter.warning("null value for " + key); } else if (value instanceof String) { - out.println(" { \"" + key + "\", \"" + CLDRConverter.saveConvert((String) value, useJava) + "\" },"); + if (type == BundleType.TIMEZONE) { + out.printf(" { \"%s\", %s },\n", key, CLDRConverter.saveConvert((String) value, useJava)); + } else { + out.printf(" { \"%s\", \"%s\" },\n", key, CLDRConverter.saveConvert((String) value, useJava)); + } } else if (value instanceof String[]) { String[] values = (String[]) value; out.println(" { \"" + key + "\",\n new String[] {"); diff --git a/jdk/makefiles/CompileJavaClasses.gmk b/jdk/makefiles/CompileJavaClasses.gmk index 383cf0d4a9f..2a7f4def426 100644 --- a/jdk/makefiles/CompileJavaClasses.gmk +++ b/jdk/makefiles/CompileJavaClasses.gmk @@ -121,6 +121,7 @@ ifneq ($(OPENJDK_TARGET_OS),linux) sun/nio/fs/LinuxFileStore.java \ sun/nio/fs/LinuxFileSystem.java \ sun/nio/fs/LinuxFileSystemProvider.java \ + sun/nio/fs/MagicFileTypeDetector.java \ sun/nio/fs/LinuxNativeDispatcher.java \ sun/nio/fs/LinuxUserDefinedFileAttributeView.java \ sun/nio/fs/LinuxWatchService.java @@ -220,24 +221,10 @@ endif EXFILES+=-linux-arm.java \ -linux-ppc.java -# TODO: Is this necessary? ifeq ($(OPENJDK_TARGET_OS), windows) EXFILES+=sun/nio/ch/AbstractPollSelectorImpl.java \ - sun/nio/ch/DevPollArrayWrapper.java \ - sun/nio/ch/DevPollSelectorImpl.java \ - sun/nio/ch/DevPollSelectorProvider.java \ - sun/nio/ch/InheritedChannel.java \ sun/nio/ch/PollSelectorProvider.java \ - sun/nio/ch/PollSelectorImpl.java \ - sun/nio/ch/Port.java \ - sun/nio/ch/SimpleAsynchronousFileChannelImpl.java \ - sun/nio/ch/SolarisAsynchronousChannelProvider.java \ - sun/nio/ch/SolarisEventPort.java \ - sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java \ - sun/nio/ch/UnixAsynchronousSocketChannelImpl.java - EXFILES+=sun/net/sdp/SdpProvider.java -else - EXFILES+=sun/net/www/protocol/http/ntlm/NTLMAuthSequence.java + sun/nio/ch/SimpleAsynchronousFileChannelImpl.java endif # Exclude nimbus files from rt.jar diff --git a/jdk/makefiles/CompileNativeLibraries.gmk b/jdk/makefiles/CompileNativeLibraries.gmk index 23bf459ba2e..06abfab9406 100644 --- a/jdk/makefiles/CompileNativeLibraries.gmk +++ b/jdk/makefiles/CompileNativeLibraries.gmk @@ -125,7 +125,7 @@ endif LIBVERIFY_OPTIMIZATION:=HIGH ifneq ($(findstring $(OPENJDK_TARGET_OS),solaris linux),) - ifeq ($(ENABLE_DEBUG_SYMBOLS), yes) + ifeq ($(ENABLE_DEBUG_SYMBOLS), true) LIBVERIFY_OPTIMIZATION:=LOW endif endif @@ -1645,7 +1645,7 @@ endif LIBMANAGEMENT_OPTIMIZATION:=HIGH ifneq ($(findstring $(OPENJDK_TARGET_OS),solaris linux),) - ifeq ($(ENABLE_DEBUG_SYMBOLS), yes) + ifeq ($(ENABLE_DEBUG_SYMBOLS), true) LIBMANAGEMENT_OPTIMIZATION:=LOW endif endif @@ -1688,7 +1688,7 @@ BUILD_LIBHPROF_LDFLAGS:= LIBHPROF_OPTIMIZATION:=HIGHEST ifneq ($(findstring $(OPENJDK_TARGET_OS),solaris linux),) - ifeq ($(ENABLE_DEBUG_SYMBOLS), yes) + ifeq ($(ENABLE_DEBUG_SYMBOLS), true) LIBHPROF_OPTIMIZATION:=LOW endif endif @@ -1897,6 +1897,7 @@ ifeq ($(OPENJDK_TARGET_OS), linux) UnixAsynchronousServerSocketChannelImpl.c \ UnixAsynchronousSocketChannelImpl.c \ GnomeFileTypeDetector.c \ + MagicFileTypeDetector.c \ LinuxNativeDispatcher.c \ LinuxWatchService.c \ UnixCopyFile.c \ @@ -2235,7 +2236,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBKCMS,\ $(call SET_SHARED_LIBRARY_ORIGIN),\ LDFLAGS_SUFFIX_linux:=-lc -lpthread,\ LDFLAGS_SUFFIX_windows:=$(WIN_JAVA_LIB) advapi32.lib user32.lib version.lib, \ - LDFLAGS_SUFFIX:=-lm $(LDFLAGS_JDKLIB_SUFFIX),\ + LDFLAGS_SUFFIX_posix:=-lm -ljava -ljvm,\ VERSIONINFO_RESOURCE:=$(JDK_TOPDIR)/src/closed/share/native/sun/java2d/cmm/kcms/cmm.rc,\ VERSIONINFO_RESOURCE:=$(JDK_TOPDIR)/src/closed/share/native/sun/java2d/cmm/kcms/cmm.rc,\ RC_FLAGS:=$(RC_FLAGS)\ @@ -2539,6 +2540,7 @@ BUILD_LIBRARIES += $(BUILD_LIBJ2PCSC) ########################################################################################## ifneq ($(OPENJDK_TARGET_OS), windows) +ifneq ($(OPENJDK_TARGET_OS), macosx) $(eval $(call SetupNativeCompilation,BUILD_LIBJ2GSS,\ LIBRARY:=j2gss,\ OUTPUT_DIR:=$(INSTALL_LIBRARIES_HERE),\ @@ -2558,6 +2560,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJ2GSS,\ BUILD_LIBRARIES += $(BUILD_LIBJ2GSS) endif +endif ########################################################################################## diff --git a/jdk/makefiles/CopyFiles.gmk b/jdk/makefiles/CopyFiles.gmk index e0c8d620f2d..be24ab22819 100644 --- a/jdk/makefiles/CopyFiles.gmk +++ b/jdk/makefiles/CopyFiles.gmk @@ -356,21 +356,9 @@ COPY_FILES += $(JVMCFG) ########################################################################################## -PROPS_SRC := $(JDK_TOPDIR)/src/share/lib/security/java.security +PROPS_SRC := $(JDK_TOPDIR)/src/share/lib/security/java.security-$(OPENJDK_TARGET_OS) PROPS_DST := $(JDK_OUTPUTDIR)/lib/security/java.security -ifeq ($(OPENJDK_TARGET_OS), solaris) - PROPS_SRC := $(JDK_TOPDIR)/src/share/lib/security/java.security-solaris -endif - -ifeq ($(OPENJDK_TARGET_OS), windows) - PROPS_SRC := $(JDK_TOPDIR)/src/share/lib/security/java.security-windows -endif - -ifeq ($(OPENJDK_TARGET_OS), macosx) - PROPS_SRC := $(JDK_TOPDIR)/src/share/lib/security/java.security-macosx -endif - $(PROPS_DST): $(PROPS_SRC) $(MKDIR) -p $(@D) $(RM) $@ diff --git a/jdk/makefiles/CreateJars.gmk b/jdk/makefiles/CreateJars.gmk index cd5ec1fd258..2bfbd358af8 100644 --- a/jdk/makefiles/CreateJars.gmk +++ b/jdk/makefiles/CreateJars.gmk @@ -810,9 +810,8 @@ EXPORTED_PRIVATE_PKGS = com.sun.servicetag \ $(IMAGES_OUTPUTDIR)/symbols/_the.symbols: $(IMAGES_OUTPUTDIR)/lib/rt.jar $(RM) -r $(IMAGES_OUTPUTDIR)/symbols/META-INF/sym $(MKDIR) -p $(IMAGES_OUTPUTDIR)/symbols/META-INF/sym - $(JAVA) \ - -Xbootclasspath/a:$(JDK_OUTPUTDIR)/classes \ - $(JAVAC_JARS) \ + $(JAVA) $(JAVAC_JARS) \ + -bootclasspath $(JDK_OUTPUTDIR)/classes \ -XDprocess.packages -proc:only \ -processor com.sun.tools.javac.sym.CreateSymbols \ -Acom.sun.tools.javac.sym.Jar=$(IMAGES_OUTPUTDIR)/lib/rt.jar \ diff --git a/jdk/makefiles/mapfiles/libnio/mapfile-linux b/jdk/makefiles/mapfiles/libnio/mapfile-linux index d78a74400b3..92c7d318894 100644 --- a/jdk/makefiles/mapfiles/libnio/mapfile-linux +++ b/jdk/makefiles/mapfiles/libnio/mapfile-linux @@ -130,6 +130,8 @@ SUNWprivate_1.1 { Java_sun_nio_fs_GnomeFileTypeDetector_probeUsingGio; Java_sun_nio_fs_GnomeFileTypeDetector_initializeGnomeVfs; Java_sun_nio_fs_GnomeFileTypeDetector_probeUsingGnomeVfs; + Java_sun_nio_fs_MagicFileTypeDetector_initialize0; + Java_sun_nio_fs_MagicFileTypeDetector_probe0; Java_sun_nio_fs_LinuxWatchService_eventSize; Java_sun_nio_fs_LinuxWatchService_eventOffsets; Java_sun_nio_fs_LinuxWatchService_inotifyInit; diff --git a/jdk/src/macosx/classes/com/apple/laf/AquaLookAndFeel.java b/jdk/src/macosx/classes/com/apple/laf/AquaLookAndFeel.java index 3c872df2b26..4f108da2df0 100644 --- a/jdk/src/macosx/classes/com/apple/laf/AquaLookAndFeel.java +++ b/jdk/src/macosx/classes/com/apple/laf/AquaLookAndFeel.java @@ -714,7 +714,8 @@ public class AquaLookAndFeel extends BasicLookAndFeel { "PopupMenu.font", menuFont, "PopupMenu.background", menuBackgroundColor, - "PopupMenu.translucentBackground", translucentWhite, + // Fix for 7154516: make popups opaque + "PopupMenu.translucentBackground", white, "PopupMenu.foreground", menuForegroundColor, "PopupMenu.selectionBackground", menuSelectedBackgroundColor, "PopupMenu.selectionForeground", menuSelectedForegroundColor, diff --git a/jdk/src/macosx/classes/sun/awt/CGraphicsConfig.java b/jdk/src/macosx/classes/sun/awt/CGraphicsConfig.java index 01409a5bb0a..fb37d01209c 100644 --- a/jdk/src/macosx/classes/sun/awt/CGraphicsConfig.java +++ b/jdk/src/macosx/classes/sun/awt/CGraphicsConfig.java @@ -31,13 +31,16 @@ import java.awt.image.*; import sun.java2d.SurfaceData; import sun.java2d.opengl.CGLLayer; +import sun.lwawt.LWGraphicsConfig; import sun.lwawt.macosx.CPlatformView; -public class CGraphicsConfig extends GraphicsConfiguration { +public abstract class CGraphicsConfig extends GraphicsConfiguration + implements LWGraphicsConfig { + private final CGraphicsDevice device; private ColorModel colorModel; - public CGraphicsConfig(CGraphicsDevice device) { + protected CGraphicsConfig(CGraphicsDevice device) { this.device = device; } @@ -84,88 +87,20 @@ public class CGraphicsConfig extends GraphicsConfiguration { return new AffineTransform(xscale, 0.0, 0.0, yscale, 0.0, 0.0); } - - /** - * The following methods are invoked from CToolkit.java and - * LWWindowPeer.java rather than having the native - * implementations hardcoded in those classes. This way the appropriate - * actions are taken based on the peer's GraphicsConfig, whether it is - * an CGLGraphicsConfig or something else. - */ - /** * Creates a new SurfaceData that will be associated with the given * LWWindowPeer. */ - public SurfaceData createSurfaceData(CPlatformView pView) { - throw new UnsupportedOperationException("not implemented"); - } + public abstract SurfaceData createSurfaceData(CPlatformView pView); /** * Creates a new SurfaceData that will be associated with the given * CGLLayer. */ - public SurfaceData createSurfaceData(CGLLayer layer) { - throw new UnsupportedOperationException("not implemented"); - } - - /** - * Creates a new hidden-acceleration image of the given width and height - * that is associated with the target Component. - */ - public Image createAcceleratedImage(Component target, - int width, int height) - { - throw new UnsupportedOperationException("not implemented"); - } - - /** - * The following methods correspond to the multibuffering methods in - * LWWindowPeer.java... - */ - - /** - * Attempts to create a native backbuffer for the given peer. If - * the requested configuration is not natively supported, an AWTException - * is thrown. Otherwise, if the backbuffer creation is successful, a - * handle to the native backbuffer is returned. - */ - public long createBackBuffer(CPlatformView pView, - int numBuffers, BufferCapabilities caps) - throws AWTException - { - throw new UnsupportedOperationException("not implemented"); - } - - public void destroyBackBuffer(long backBuffer) - throws AWTException - { - throw new UnsupportedOperationException("not implemented"); - } - - /** - * Creates a VolatileImage that essentially wraps the target Component's - * backbuffer, using the provided backbuffer handle. - */ - public VolatileImage createBackBufferImage(Component target, - long backBuffer) - { - throw new UnsupportedOperationException("not implemented"); - } - - /** - * Performs the native flip operation for the given target Component. - */ - public void flip(CPlatformView delegate, - Component target, VolatileImage xBackBuffer, - int x1, int y1, int x2, int y2, - BufferCapabilities.FlipContents flipAction) - { - throw new UnsupportedOperationException("not implemented"); - } + public abstract SurfaceData createSurfaceData(CGLLayer layer); @Override - public boolean isTranslucencyCapable() { + public final boolean isTranslucencyCapable() { //we know for sure we have capable config :) return true; } diff --git a/jdk/src/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java b/jdk/src/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java index 8c36ddc6614..230f7057927 100644 --- a/jdk/src/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java +++ b/jdk/src/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java @@ -27,7 +27,6 @@ package sun.java2d.opengl; import java.awt.AWTException; import java.awt.BufferCapabilities; -import java.awt.Color; import java.awt.Component; import java.awt.Graphics; import java.awt.Graphics2D; @@ -48,13 +47,10 @@ import java.awt.image.WritableRaster; import sun.awt.CGraphicsConfig; import sun.awt.CGraphicsDevice; -import sun.awt.TextureSizeConstraining; import sun.awt.image.OffScreenImage; import sun.awt.image.SunVolatileImage; -import sun.awt.image.SurfaceManager; import sun.java2d.Disposer; import sun.java2d.DisposerRecord; -import sun.java2d.SunGraphics2D; import sun.java2d.Surface; import sun.java2d.SurfaceData; import sun.java2d.opengl.OGLContext.OGLContextCaps; @@ -63,18 +59,19 @@ import sun.java2d.pipe.hw.AccelTypedVolatileImage; import sun.java2d.pipe.hw.ContextCapabilities; import static sun.java2d.opengl.OGLSurfaceData.*; import static sun.java2d.opengl.OGLContext.OGLContextCaps.*; -import sun.java2d.opengl.CGLSurfaceData.CGLVSyncOffScreenSurfaceData; import sun.java2d.pipe.hw.AccelDeviceEventListener; import sun.java2d.pipe.hw.AccelDeviceEventNotifier; +import sun.lwawt.LWComponentPeer; import sun.lwawt.macosx.CPlatformView; -public class CGLGraphicsConfig extends CGraphicsConfig - implements OGLGraphicsConfig, TextureSizeConstraining +public final class CGLGraphicsConfig extends CGraphicsConfig + implements OGLGraphicsConfig { - //private static final int kOpenGLSwapInterval = RuntimeOptions.getCurrentOptions().OpenGLSwapInterval; + //private static final int kOpenGLSwapInterval = + // RuntimeOptions.getCurrentOptions().OpenGLSwapInterval; private static final int kOpenGLSwapInterval = 0; // TODO - protected static boolean cglAvailable; + private static boolean cglAvailable; private static ImageCapabilities imageCaps = new CGLImageCaps(); private int pixfmt; @@ -82,7 +79,7 @@ public class CGLGraphicsConfig extends CGraphicsConfig private long pConfigInfo; private ContextCapabilities oglCaps; private OGLContext context; - private Object disposerReferent = new Object(); + private final Object disposerReferent = new Object(); public static native int getDefaultPixFmt(int screennum); private static native boolean initCGL(); @@ -94,7 +91,7 @@ public class CGLGraphicsConfig extends CGraphicsConfig cglAvailable = initCGL(); } - protected CGLGraphicsConfig(CGraphicsDevice device, int pixfmt, + private CGLGraphicsConfig(CGraphicsDevice device, int pixfmt, long configInfo, ContextCapabilities oglCaps) { super(device); @@ -170,11 +167,13 @@ public class CGLGraphicsConfig extends CGraphicsConfig * Returns true if the provided capability bit is present for this config. * See OGLContext.java for a list of supported capabilities. */ - public final boolean isCapPresent(int cap) { + @Override + public boolean isCapPresent(int cap) { return ((oglCaps.getCaps() & cap) != 0); } - public final long getNativeConfigInfo() { + @Override + public long getNativeConfigInfo() { return pConfigInfo; } @@ -183,7 +182,8 @@ public class CGLGraphicsConfig extends CGraphicsConfig * * @see sun.java2d.pipe.hw.BufferedContextProvider#getContext */ - public final OGLContext getContext() { + @Override + public OGLContext getContext() { return context; } @@ -257,145 +257,83 @@ public class CGLGraphicsConfig extends CGraphicsConfig return ("CGLGraphicsConfig[dev="+screen+",pixfmt="+pixfmt+"]"); } - - /** - * The following methods are invoked from ComponentModel.java rather - * than having the Mac OS X-dependent implementations hardcoded in that - * class. This way the appropriate actions are taken based on the peer's - * GraphicsConfig, whether it is a CGraphicsConfig or a - * CGLGraphicsConfig. - */ - - /** - * Creates a new SurfaceData that will be associated with the given - * LWWindowPeer. - */ @Override public SurfaceData createSurfaceData(CPlatformView pView) { return CGLSurfaceData.createData(pView); } - /** - * Creates a new SurfaceData that will be associated with the given - * CGLLayer. - */ @Override public SurfaceData createSurfaceData(CGLLayer layer) { return CGLSurfaceData.createData(layer); } - /** - * Creates a new hidden-acceleration image of the given width and height - * that is associated with the target Component. - */ @Override public Image createAcceleratedImage(Component target, int width, int height) { ColorModel model = getColorModel(Transparency.OPAQUE); - WritableRaster wr = - model.createCompatibleWritableRaster(width, height); + WritableRaster wr = model.createCompatibleWritableRaster(width, height); return new OffScreenImage(target, model, wr, model.isAlphaPremultiplied()); } - /** - * The following methods correspond to the multibuffering methods in - * CWindowPeer.java... - */ - - /** - * Attempts to create a OGL-based backbuffer for the given peer. If - * the requested configuration is not natively supported, an AWTException - * is thrown. Otherwise, if the backbuffer creation is successful, a - * value of 1 is returned. - */ @Override - public long createBackBuffer(CPlatformView pView, - int numBuffers, BufferCapabilities caps) - throws AWTException - { - if (numBuffers > 2) { - throw new AWTException( - "Only double or single buffering is supported"); + public void assertOperationSupported(final int numBuffers, + final BufferCapabilities caps) + throws AWTException { + // Assume this method is never called with numBuffers != 2, as 0 is + // unsupported, and 1 corresponds to a SingleBufferStrategy which + // doesn't depend on the peer. Screen is considered as a separate + // "buffer". + if (numBuffers != 2) { + throw new AWTException("Only double buffering is supported"); } - BufferCapabilities configCaps = getBufferCapabilities(); + final BufferCapabilities configCaps = getBufferCapabilities(); if (!configCaps.isPageFlipping()) { throw new AWTException("Page flipping is not supported"); } if (caps.getFlipContents() == BufferCapabilities.FlipContents.PRIOR) { throw new AWTException("FlipContents.PRIOR is not supported"); } - - // non-zero return value means backbuffer creation was successful - // (checked in CPlatformWindow.flip(), etc.) - return 1; } - /** - * Destroys the backbuffer object represented by the given handle value. - */ @Override - public void destroyBackBuffer(long backBuffer) { + public Image createBackBuffer(final LWComponentPeer peer) { + final Rectangle r = peer.getBounds(); + // It is possible for the component to have size 0x0, adjust it to + // be at least 1x1 to avoid IAE + final int w = Math.max(1, r.width); + final int h = Math.max(1, r.height); + final int transparency = peer.isTranslucent() ? Transparency.TRANSLUCENT + : Transparency.OPAQUE; + return new SunVolatileImage(this, w, h, transparency, null); } - /** - * Creates a VolatileImage that essentially wraps the target Component's - * backbuffer (the provided backbuffer handle is essentially ignored). - */ @Override - public VolatileImage createBackBufferImage(Component target, - long backBuffer) - { - return new SunVolatileImage(target, - target.getWidth(), target.getHeight(), - Boolean.TRUE); - } - - /** - * Performs the native OGL flip operation for the given target Component. - */ - @Override - public void flip(CPlatformView pView, - Component target, VolatileImage xBackBuffer, - int x1, int y1, int x2, int y2, - BufferCapabilities.FlipContents flipAction) - { - if (flipAction == BufferCapabilities.FlipContents.COPIED) { - SurfaceManager vsm = SurfaceManager.getManager(xBackBuffer); - SurfaceData sd = vsm.getPrimarySurfaceData(); - - if (sd instanceof CGLVSyncOffScreenSurfaceData) { - CGLVSyncOffScreenSurfaceData vsd = - (CGLVSyncOffScreenSurfaceData)sd; - SurfaceData bbsd = vsd.getFlipSurface(); - Graphics2D bbg = - new SunGraphics2D(bbsd, Color.black, Color.white, null); - try { - bbg.drawImage(xBackBuffer, 0, 0, null); - } finally { - bbg.dispose(); - } - } else { - pView.drawImageOnPeer(xBackBuffer, x1, y1, x2, y2); - return; - } - } else if (flipAction == BufferCapabilities.FlipContents.PRIOR) { - // not supported by CGL... - return; + public void destroyBackBuffer(final Image backBuffer) { + if (backBuffer != null) { + backBuffer.flush(); } + } - OGLSurfaceData.swapBuffers(pView.getAWTView()); - + @Override + public void flip(final LWComponentPeer peer, final Image backBuffer, + final int x1, final int y1, final int x2, final int y2, + final BufferCapabilities.FlipContents flipAction) { + final Graphics g = peer.getGraphics(); + try { + g.drawImage(backBuffer, x1, y1, x2, y2, x1, y1, x2, y2, null); + } finally { + g.dispose(); + } if (flipAction == BufferCapabilities.FlipContents.BACKGROUND) { - Graphics g = xBackBuffer.getGraphics(); + final Graphics2D bg = (Graphics2D) backBuffer.getGraphics(); try { - g.setColor(target.getBackground()); - g.fillRect(0, 0, - xBackBuffer.getWidth(), - xBackBuffer.getHeight()); + bg.setBackground(peer.getBackground()); + bg.clearRect(0, 0, backBuffer.getWidth(null), + backBuffer.getHeight(null)); } finally { - g.dispose(); + bg.dispose(); } } } @@ -429,15 +367,10 @@ public class CGLGraphicsConfig extends CGraphicsConfig return imageCaps; } - /** - * {@inheritDoc} - * - * @see sun.java2d.pipe.hw.AccelGraphicsConfig#createCompatibleVolatileImage - */ - public VolatileImage - createCompatibleVolatileImage(int width, int height, - int transparency, int type) - { + @Override + public VolatileImage createCompatibleVolatileImage(int width, int height, + int transparency, + int type) { if (type == FLIP_BACKBUFFER || type == WINDOW || type == UNDEFINED || transparency == Transparency.BITMASK) { @@ -473,15 +406,18 @@ public class CGLGraphicsConfig extends CGraphicsConfig * * @see sun.java2d.pipe.hw.AccelGraphicsConfig#getContextCapabilities */ + @Override public ContextCapabilities getContextCapabilities() { return oglCaps; } + @Override public void addDeviceEventListener(AccelDeviceEventListener l) { int screen = getDevice().getCoreGraphicsScreen(); AccelDeviceEventNotifier.addListener(l, screen); } + @Override public void removeDeviceEventListener(AccelDeviceEventListener l) { AccelDeviceEventNotifier.removeListener(l); } diff --git a/jdk/src/macosx/classes/sun/lwawt/LWCanvasPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWCanvasPeer.java index f61b978d230..0c80ff0af0d 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWCanvasPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWCanvasPeer.java @@ -26,12 +26,9 @@ package sun.lwawt; -import java.awt.AWTException; -import java.awt.BufferCapabilities; import java.awt.Component; import java.awt.Dimension; import java.awt.GraphicsConfiguration; -import java.awt.Image; import java.awt.peer.CanvasPeer; import javax.swing.JComponent; @@ -42,35 +39,10 @@ class LWCanvasPeer LWCanvasPeer(final T target, final PlatformComponent platformComponent) { super(target, platformComponent); } - // ---- PEER METHODS ---- // - - @Override - public void createBuffers(int numBuffers, BufferCapabilities caps) - throws AWTException { - // TODO - } - - @Override - public Image getBackBuffer() { - // TODO - return null; - } - - @Override - public void flip(int x1, int y1, int x2, int y2, - BufferCapabilities.FlipContents flipAction) { - // TODO - } - - @Override - public void destroyBuffers() { - // TODO - } @Override public final GraphicsConfiguration getAppropriateGraphicsConfiguration( - GraphicsConfiguration gc) - { + final GraphicsConfiguration gc) { // TODO return gc; } diff --git a/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java index db6d2dd4430..55b4665a752 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java @@ -138,6 +138,11 @@ public abstract class LWComponentPeer */ static final char WIDE_CHAR = '0'; + /** + * The back buffer provide user with a BufferStrategy. + */ + private Image backBuffer; + private final class DelegateContainer extends Container { { enableEvents(0xFFFFFFFF); @@ -389,6 +394,7 @@ public abstract class LWComponentPeer } protected void disposeImpl() { + destroyBuffers(); LWContainerPeer cp = getContainerPeer(); if (cp != null) { cp.removeChildPeer(this); @@ -415,6 +421,12 @@ public abstract class LWComponentPeer return getWindowPeer().getGraphicsConfiguration(); } + + // Just a helper method + public final LWGraphicsConfig getLWGC() { + return (LWGraphicsConfig) getGraphicsConfiguration(); + } + /* * Overridden in LWWindowPeer to replace its surface * data and back buffer. @@ -506,31 +518,45 @@ public abstract class LWComponentPeer return getGraphicsConfiguration().getColorModel(); } + public boolean isTranslucent() { + // Translucent windows of the top level are supported only + return false; + } + @Override - public void createBuffers(int numBuffers, BufferCapabilities caps) + public final void createBuffers(int numBuffers, BufferCapabilities caps) throws AWTException { - throw new AWTException("Back buffers are only supported for " + - "Window or Canvas components."); - } - - /* - * To be overridden in LWWindowPeer and LWCanvasPeer. - */ - @Override - public Image getBackBuffer() { - // Return null or throw AWTException? - return null; + getLWGC().assertOperationSupported(numBuffers, caps); + final Image buffer = getLWGC().createBackBuffer(this); + synchronized (getStateLock()) { + backBuffer = buffer; + } } @Override - public void flip(int x1, int y1, int x2, int y2, + public final Image getBackBuffer() { + synchronized (getStateLock()) { + if (backBuffer != null) { + return backBuffer; + } + } + throw new IllegalStateException("Buffers have not been created"); + } + + @Override + public final void flip(int x1, int y1, int x2, int y2, BufferCapabilities.FlipContents flipAction) { - // Skip silently or throw AWTException? + getLWGC().flip(this, getBackBuffer(), x1, y1, x2, y2, flipAction); } @Override - public void destroyBuffers() { - // Do nothing + public final void destroyBuffers() { + final Image oldBB; + synchronized (getStateLock()) { + oldBB = backBuffer; + backBuffer = null; + } + getLWGC().destroyBackBuffer(oldBB); } // Helper method @@ -642,7 +668,7 @@ public abstract class LWComponentPeer } } - protected final Color getBackground() { + public final Color getBackground() { synchronized (getStateLock()) { return background; } @@ -982,19 +1008,17 @@ public abstract class LWComponentPeer } @Override - public Image createImage(ImageProducer producer) { + public final Image createImage(final ImageProducer producer) { return new ToolkitImage(producer); } @Override - public Image createImage(int w, int h) { - CGraphicsConfig gc = (CGraphicsConfig)getGraphicsConfiguration(); - return gc.createAcceleratedImage(getTarget(), w, h); + public final Image createImage(final int width, final int height) { + return getLWGC().createAcceleratedImage(getTarget(), width, height); } @Override - public VolatileImage createVolatileImage(int w, int h) { - // TODO: is it a right/complete implementation? + public final VolatileImage createVolatileImage(final int w, final int h) { return new SunVolatileImage(getTarget(), w, h); } @@ -1105,8 +1129,6 @@ public abstract class LWComponentPeer * of target.setLocation() or as a result of user actions (window is * dragged with mouse). * - * To be overridden in LWWindowPeer to update its GraphicsConfig. - * * This method could be called on the toolkit thread. */ protected final void handleMove(final int x, final int y, @@ -1122,13 +1144,19 @@ public abstract class LWComponentPeer * Called when this peer's size has been changed either as a result of * target.setSize() or as a result of user actions (window is resized). * - * To be overridden in LWWindowPeer to update its SurfaceData and - * GraphicsConfig. - * * This method could be called on the toolkit thread. */ protected final void handleResize(final int w, final int h, final boolean updateTarget) { + Image oldBB = null; + synchronized (getStateLock()) { + if (backBuffer != null) { + oldBB = backBuffer; + backBuffer = getLWGC().createBackBuffer(this); + } + } + getLWGC().destroyBackBuffer(oldBB); + if (updateTarget) { AWTAccessor.getComponentAccessor().setSize(getTarget(), w, h); } diff --git a/jdk/src/macosx/classes/sun/lwawt/LWGraphicsConfig.java b/jdk/src/macosx/classes/sun/lwawt/LWGraphicsConfig.java new file mode 100644 index 00000000000..d556ea75995 --- /dev/null +++ b/jdk/src/macosx/classes/sun/lwawt/LWGraphicsConfig.java @@ -0,0 +1,97 @@ +/* + * 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. 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 sun.lwawt; + +import java.awt.AWTException; +import java.awt.BufferCapabilities; +import java.awt.Component; +import java.awt.Image; + +/** + * As lwawt can be used on different platforms with different graphic + * configurations, the general set of methods is necessary. This interface + * collects the methods that should be provided by GraphicsConfiguration, + * simplifying use by the LWAWT. + * + * @author Sergey Bylokhov + */ +public interface LWGraphicsConfig { + + /* + * A GraphicsConfiguration must implements following methods to indicate + * that it imposes certain limitations on the maximum size of supported + * textures. + */ + + /** + * Returns the maximum width of any texture image. By default return {@code + * Integer.MAX_VALUE}. + */ + int getMaxTextureWidth(); + + /** + * Returns the maximum height of any texture image. By default return {@code + * Integer.MAX_VALUE}. + */ + int getMaxTextureHeight(); + + /* + * The following methods correspond to the multi-buffering methods in + * LWComponentPeer.java. + */ + + /** + * Checks that the requested configuration is natively supported; if not, an + * AWTException is thrown. + */ + void assertOperationSupported(int numBuffers, BufferCapabilities caps) + throws AWTException; + + /** + * Creates a back buffer for the given peer and returns the image wrapper. + */ + Image createBackBuffer(LWComponentPeer peer); + + /** + * Destroys the back buffer object. + */ + void destroyBackBuffer(Image backBuffer); + + /** + * Performs the native flip operation for the given target Component. Our + * flip is implemented through normal drawImage() to the graphic object, + * because of our components uses a graphic object of the container(in this + * case we also apply necessary constrains) + */ + void flip(LWComponentPeer peer, Image backBuffer, int x1, int y1, + int x2, int y2, BufferCapabilities.FlipContents flipAction); + + /** + * Creates a new hidden-acceleration image of the given width and height + * that is associated with the target Component. + */ + Image createAcceleratedImage(Component target, int width, int height); +} diff --git a/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java b/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java index cba6cec9c9f..57a8642b6d0 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java @@ -210,9 +210,9 @@ public abstract class LWToolkit extends SunToolkit implements Runnable { * and DialogPeer interfaces. */ private LWWindowPeer createDelegatedPeer(Window target, PlatformComponent platformComponent, - PlatformWindow platformWindow) + PlatformWindow platformWindow, LWWindowPeer.PeerType peerType) { - LWWindowPeer peer = new LWWindowPeer(target, platformComponent, platformWindow); + LWWindowPeer peer = new LWWindowPeer(target, platformComponent, platformWindow, peerType); targetCreatedPeer(target, peer); peer.initialize(); return peer; @@ -222,22 +222,29 @@ public abstract class LWToolkit extends SunToolkit implements Runnable { public WindowPeer createWindow(Window target) { PlatformComponent platformComponent = createPlatformComponent(); PlatformWindow platformWindow = createPlatformWindow(LWWindowPeer.PeerType.SIMPLEWINDOW); - return createDelegatedPeer(target, platformComponent, platformWindow); + return createDelegatedPeer(target, platformComponent, platformWindow, LWWindowPeer.PeerType.SIMPLEWINDOW); } @Override public FramePeer createFrame(Frame target) { PlatformComponent platformComponent = createPlatformComponent(); PlatformWindow platformWindow = createPlatformWindow(LWWindowPeer.PeerType.FRAME); - return createDelegatedPeer(target, platformComponent, platformWindow); + return createDelegatedPeer(target, platformComponent, platformWindow, LWWindowPeer.PeerType.FRAME); } public LWWindowPeer createEmbeddedFrame(CEmbeddedFrame target) { PlatformComponent platformComponent = createPlatformComponent(); - PlatformWindow platformWindow = createPlatformWindow(LWWindowPeer.PeerType.EMBEDDEDFRAME); - return createDelegatedPeer(target, platformComponent, platformWindow); + PlatformWindow platformWindow = createPlatformWindow(LWWindowPeer.PeerType.EMBEDDED_FRAME); + return createDelegatedPeer(target, platformComponent, platformWindow, LWWindowPeer.PeerType.EMBEDDED_FRAME); } + public LWWindowPeer createEmbeddedFrame(CViewEmbeddedFrame target) { + PlatformComponent platformComponent = createPlatformComponent(); + PlatformWindow platformWindow = createPlatformWindow(LWWindowPeer.PeerType.VIEW_EMBEDDED_FRAME); + return createDelegatedPeer(target, platformComponent, platformWindow, LWWindowPeer.PeerType.VIEW_EMBEDDED_FRAME); + } + + CPrinterDialogPeer createCPrinterDialog(CPrinterDialog target) { PlatformComponent platformComponent = createPlatformComponent(); PlatformWindow platformWindow = createPlatformWindow(LWWindowPeer.PeerType.DIALOG); @@ -254,7 +261,7 @@ public abstract class LWToolkit extends SunToolkit implements Runnable { PlatformComponent platformComponent = createPlatformComponent(); PlatformWindow platformWindow = createPlatformWindow(LWWindowPeer.PeerType.DIALOG); - return createDelegatedPeer(target, platformComponent, platformWindow); + return createDelegatedPeer(target, platformComponent, platformWindow, LWWindowPeer.PeerType.DIALOG); } @Override diff --git a/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java index 5d3c88295e4..9d583e65749 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java @@ -27,7 +27,6 @@ package sun.lwawt; import java.awt.*; import java.awt.event.*; -import java.awt.image.BufferedImage; import java.awt.peer.*; import java.util.List; @@ -48,7 +47,8 @@ public class LWWindowPeer SIMPLEWINDOW, FRAME, DIALOG, - EMBEDDEDFRAME + EMBEDDED_FRAME, + VIEW_EMBEDDED_FRAME } private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.lwawt.focus.LWWindowPeer"); @@ -75,17 +75,6 @@ public class LWWindowPeer private SurfaceData surfaceData; private final Object surfaceDataLock = new Object(); - private int backBufferCount; - private BufferCapabilities backBufferCaps; - - // The back buffer is used for two purposes: - // 1. To render all the lightweight peers - // 2. To provide user with a BufferStrategy - // Need to check if a single back buffer can be used for both -// TODO: VolatileImage -// private VolatileImage backBuffer; - private volatile BufferedImage backBuffer; - private volatile int windowState = Frame.NORMAL; // check that the mouse is over the window @@ -120,6 +109,8 @@ public class LWWindowPeer private volatile boolean textured; + private final PeerType peerType; + /** * Current modal blocker or null. * @@ -128,10 +119,11 @@ public class LWWindowPeer private LWWindowPeer blocker; public LWWindowPeer(Window target, PlatformComponent platformComponent, - PlatformWindow platformWindow) + PlatformWindow platformWindow, PeerType peerType) { super(target, platformComponent); this.platformWindow = platformWindow; + this.peerType = peerType; Window owner = target.getOwner(); LWWindowPeer ownerPeer = (owner != null) ? (LWWindowPeer)owner.getPeer() : null; @@ -227,7 +219,6 @@ public class LWWindowPeer if (isGrabbing()) { ungrab(); } - destroyBuffers(); platformWindow.dispose(); super.disposeImpl(); } @@ -258,8 +249,10 @@ public class LWWindowPeer } @Override - public GraphicsConfiguration getGraphicsConfiguration() { - return graphicsConfig; + public final GraphicsConfiguration getGraphicsConfiguration() { + synchronized (getStateLock()) { + return graphicsConfig; + } } @Override @@ -284,50 +277,13 @@ public class LWWindowPeer return platformWindow.transformGraphics(new SunGraphics2D(getSurfaceData(), fg, bg, f)); } - @Override - public void createBuffers(int numBuffers, BufferCapabilities caps) - throws AWTException - { - try { - // Assume this method is never called with numBuffers <= 1, as 0 is - // unsupported, and 1 corresponds to a SingleBufferStrategy which - // doesn't depend on the peer. Screen is considered as a separate - // "buffer", that's why numBuffers - 1 - assert numBuffers > 1; - - replaceSurfaceData(numBuffers - 1, caps, false); - } catch (InvalidPipeException z) { - throw new AWTException(z.toString()); - } - } - - @Override - public final Image getBackBuffer() { - synchronized (getStateLock()) { - return backBuffer; - } - } - - @Override - public void flip(int x1, int y1, int x2, int y2, - BufferCapabilities.FlipContents flipAction) - { - platformWindow.flip(x1, y1, x2, y2, flipAction); - } - - @Override - public final void destroyBuffers() { - final Image oldBB = getBackBuffer(); - synchronized (getStateLock()) { - backBuffer = null; - } - if (oldBB != null) { - oldBB.flush(); - } - } - @Override public void setBounds(int x, int y, int w, int h, int op) { + + if((op & NO_EMBEDDED_CHECK) == 0 && getPeerType() == PeerType.VIEW_EMBEDDED_FRAME) { + return; + } + if ((op & SET_CLIENT_SIZE) != 0) { // SET_CLIENT_SIZE is only applicable to window peers, so handle it here // instead of pulling 'insets' field up to LWComponentPeer @@ -343,16 +299,14 @@ public class LWWindowPeer h = MINIMUM_HEIGHT; } - if (graphicsConfig instanceof TextureSizeConstraining) { - final int maxW = ((TextureSizeConstraining)graphicsConfig).getMaxTextureWidth(); - final int maxH = ((TextureSizeConstraining)graphicsConfig).getMaxTextureHeight(); + final int maxW = getLWGC().getMaxTextureWidth(); + final int maxH = getLWGC().getMaxTextureHeight(); - if (w > maxW) { - w = maxW; - } - if (h > maxH) { - h = maxH; - } + if (w > maxW) { + w = maxW; + } + if (h > maxH) { + h = maxH; } // Don't post ComponentMoved/Resized and Paint events @@ -431,21 +385,14 @@ public class LWWindowPeer min = new Dimension(MINIMUM_WIDTH, MINIMUM_HEIGHT); } - final int maxW, maxH; - if (graphicsConfig instanceof TextureSizeConstraining) { - maxW = ((TextureSizeConstraining)graphicsConfig).getMaxTextureWidth(); - maxH = ((TextureSizeConstraining)graphicsConfig).getMaxTextureHeight(); - } else { - maxW = maxH = Integer.MAX_VALUE; - } - final Dimension max; if (getTarget().isMaximumSizeSet()) { max = getTarget().getMaximumSize(); - max.width = Math.min(max.width, maxW); - max.height = Math.min(max.height, maxH); + max.width = Math.min(max.width, getLWGC().getMaxTextureWidth()); + max.height = Math.min(max.height, getLWGC().getMaxTextureHeight()); } else { - max = new Dimension(maxW, maxH); + max = new Dimension(getLWGC().getMaxTextureWidth(), + getLWGC().getMaxTextureHeight()); } platformWindow.setSizeConstraints(min.width, min.height, max.width, max.height); @@ -1014,21 +961,10 @@ public class LWWindowPeer replaceSurfaceData(true); } - private void replaceSurfaceData(boolean blit) { - replaceSurfaceData(backBufferCount, backBufferCaps, blit); - } - - private void replaceSurfaceData(int newBackBufferCount, - BufferCapabilities newBackBufferCaps, - boolean blit) { + private void replaceSurfaceData(final boolean blit) { synchronized (surfaceDataLock) { final SurfaceData oldData = getSurfaceData(); surfaceData = platformWindow.replaceSurfaceData(); - // TODO: volatile image - // VolatileImage oldBB = backBuffer; - BufferedImage oldBB = backBuffer; - backBufferCount = newBackBufferCount; - backBufferCaps = newBackBufferCaps; final Rectangle size = getSize(); if (getSurfaceData() != null && oldData != getSurfaceData()) { clearBackground(size.width, size.height); @@ -1043,35 +979,6 @@ public class LWWindowPeer // This can only happen when this peer is being created oldData.flush(); } - - // TODO: volatile image - // backBuffer = (VolatileImage)delegate.createBackBuffer(); - backBuffer = (BufferedImage) platformWindow.createBackBuffer(); - if (backBuffer != null) { - Graphics g = backBuffer.getGraphics(); - try { - Rectangle r = getBounds(); - if (g instanceof Graphics2D) { - ((Graphics2D) g).setComposite(AlphaComposite.Src); - } - g.setColor(nonOpaqueBackground); - g.fillRect(0, 0, r.width, r.height); - if (g instanceof SunGraphics2D) { - SG2DConstraint((SunGraphics2D) g, getRegion()); - } - if (!isTextured()) { - g.setColor(getBackground()); - g.fillRect(0, 0, r.width, r.height); - } - if (oldBB != null) { - // Draw the old back buffer to the new one - g.drawImage(oldBB, 0, 0, null); - oldBB.flush(); - } - } finally { - g.dispose(); - } - } } } @@ -1092,14 +999,6 @@ public class LWWindowPeer } } - public int getBackBufferCount() { - return backBufferCount; - } - - public BufferCapabilities getBackBufferCaps() { - return backBufferCaps; - } - /* * Request the window insets from the delegate and compares it * with the current one. This method is mostly called by the @@ -1320,6 +1219,10 @@ public class LWWindowPeer return this == grabbingWindow; } + public PeerType getPeerType() { + return peerType; + } + @Override public String toString() { return super.toString() + " [target is " + getTarget() + "]"; diff --git a/jdk/src/macosx/classes/sun/lwawt/PlatformWindow.java b/jdk/src/macosx/classes/sun/lwawt/PlatformWindow.java index d4a470de5cf..0527281814a 100644 --- a/jdk/src/macosx/classes/sun/lwawt/PlatformWindow.java +++ b/jdk/src/macosx/classes/sun/lwawt/PlatformWindow.java @@ -97,17 +97,6 @@ public interface PlatformWindow { */ public SurfaceData replaceSurfaceData(); - /* - * Creates a new image to serve as a back buffer. - */ - public Image createBackBuffer(); - - /* - * Move the given part of the back buffer to the front buffer. - */ - public void flip(int x1, int y1, int x2, int y2, - BufferCapabilities.FlipContents flipAction); - public void setModalBlocked(boolean blocked); public void toFront(); @@ -162,4 +151,6 @@ public interface PlatformWindow { public long getLayerPtr(); public LWWindowPeer getPeer(); + + public boolean isUnderMouse(); } diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CMouseInfoPeer.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CMouseInfoPeer.java index 8651aa3ac36..8ee580108dc 100644 --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CMouseInfoPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CMouseInfoPeer.java @@ -26,7 +26,6 @@ package sun.lwawt.macosx; import java.awt.Window; - import sun.lwawt.LWMouseInfoPeer; import sun.lwawt.LWWindowPeer; @@ -41,10 +40,6 @@ public class CMouseInfoPeer extends LWMouseInfoPeer return false; } - LWWindowPeer peer = (LWWindowPeer)w.getPeer(); - CPlatformWindow platformWindow = (CPlatformWindow)peer.getPlatformWindow(); - return nativeIsWindowUnderMouse(platformWindow.getNSWindowPtr()); + return ((LWWindowPeer)w.getPeer()).getPlatformWindow().isUnderMouse(); } - - private static native boolean nativeIsWindowUnderMouse(long ptr); } diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java index e93f1ec4b9f..e06cc6f49aa 100644 --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java @@ -25,19 +25,13 @@ package sun.lwawt.macosx; -import sun.lwawt.PlatformWindow; -import sun.lwawt.LWWindowPeer; - -import sun.java2d.opengl.CGLLayer; -import sun.java2d.SurfaceData; - -import sun.awt.CGraphicsConfig; -import sun.awt.CGraphicsDevice; -import sun.awt.CausedFocusEvent; - import java.awt.*; -import java.awt.BufferCapabilities.FlipContents; - +import sun.awt.CausedFocusEvent; +import sun.java2d.SurfaceData; +import sun.java2d.opengl.CGLLayer; +import sun.lwawt.LWWindowPeer; +import sun.lwawt.LWWindowPeer.PeerType; +import sun.lwawt.PlatformWindow; import sun.util.logging.PlatformLogger; /* @@ -112,22 +106,6 @@ public class CPlatformEmbeddedFrame implements PlatformWindow { return windowLayer.replaceSurfaceData(); } - @Override - public Image createBackBuffer() { - Rectangle r = peer.getBounds(); - Image im = null; - if (!r.isEmpty()) { - int transparency = peer.isTranslucent() ? Transparency.TRANSLUCENT : Transparency.OPAQUE; - im = peer.getGraphicsConfiguration().createCompatibleImage(r.width, r.height, transparency); - } - return im; - } - - @Override - public void flip(int x1, int y1, int x2, int y2, FlipContents flipAction) { - throw new RuntimeException("Not implemented"); - } - @Override public void setVisible(boolean visible) {} @@ -153,6 +131,7 @@ public class CPlatformEmbeddedFrame implements PlatformWindow { // This method should be properly implemented for applets. // It returns null just as a stub. + @Override public PlatformWindow getTopmostPlatformWindowUnderMouse() { return null; } @Override @@ -211,4 +190,13 @@ public class CPlatformEmbeddedFrame implements PlatformWindow { @Override public void setModalBlocked(boolean blocked) {} + + /* + * The method could not be implemented due to CALayer restrictions. + * The exeption enforce clients not to use it. + */ + @Override + public boolean isUnderMouse() { + throw new RuntimeException("Not implemented"); + } } diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java index 1fc247f1c3e..4972301e780 100644 --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java @@ -26,9 +26,11 @@ package sun.lwawt.macosx; import java.awt.*; +import java.awt.geom.Rectangle2D; import java.awt.image.VolatileImage; import sun.awt.CGraphicsConfig; +import sun.awt.CGraphicsEnvironment; import sun.lwawt.LWWindowPeer; import sun.lwawt.macosx.event.NSEvent; @@ -38,6 +40,10 @@ import sun.java2d.opengl.CGLSurfaceData; public class CPlatformView extends CFRetainedResource { private native long nativeCreateView(int x, int y, int width, int height, long windowLayerPtr); + private static native void nativeSetAutoResizable(long awtView, boolean toResize); + private static native int nativeGetNSViewDisplayID(long awtView); + private static native Rectangle2D nativeGetLocationOnScreen(long awtView); + private static native boolean nativeIsViewUnderMouse(long ptr); private LWWindowPeer peer; private SurfaceData surfaceData; @@ -60,7 +66,7 @@ public class CPlatformView extends CFRetainedResource { public long getAWTView() { return ptr; - } + } public boolean isOpaque() { return !peer.isTranslucent(); @@ -115,26 +121,6 @@ public class CPlatformView extends CFRetainedResource { // ---------------------------------------------------------------------- // PAINTING METHODS // ---------------------------------------------------------------------- - - public void drawImageOnPeer(VolatileImage xBackBuffer, int x1, int y1, int x2, int y2) { - Graphics g = peer.getGraphics(); - try { - g.drawImage(xBackBuffer, x1, y1, x2, y2, x1, y1, x2, y2, null); - } finally { - g.dispose(); - } - } - - public Image createBackBuffer() { - Rectangle r = peer.getBounds(); - Image im = null; - if (!r.isEmpty()) { - int transparency = (isOpaque() ? Transparency.OPAQUE : Transparency.TRANSLUCENT); - im = peer.getGraphicsConfiguration().createCompatibleImage(r.width, r.height, transparency); - } - return im; - } - public SurfaceData replaceSurfaceData() { if (!LWCToolkit.getSunAwtDisableCALayers()) { surfaceData = windowLayer.replaceSurfaceData(); @@ -179,10 +165,46 @@ public class CPlatformView extends CFRetainedResource { } } + public void setAutoResizable(boolean toResize) { + nativeSetAutoResizable(this.getAWTView(), toResize); + } + + public boolean isUnderMouse() { + return nativeIsViewUnderMouse(getAWTView()); + } + + public GraphicsDevice getGraphicsDevice() { + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + CGraphicsEnvironment cge = (CGraphicsEnvironment)ge; + int displayID = nativeGetNSViewDisplayID(getAWTView()); + GraphicsDevice gd = cge.getScreenDevice(displayID); + if (gd == null) { + // this could possibly happen during device removal + // use the default screen device in this case + gd = ge.getDefaultScreenDevice(); + } + return gd; + } + + public Point getLocationOnScreen() { + Rectangle r = nativeGetLocationOnScreen(this.getAWTView()).getBounds(); + return new Point(r.x, r.y); + } + // ---------------------------------------------------------------------- // NATIVE CALLBACKS // ---------------------------------------------------------------------- + /* + * The callback is called only in the embedded case when the view is + * automatically resized by the superview. + * In normal mode this method is never called. + */ + private void deliverResize(int x, int y, int w, int h) { + peer.notifyReshape(x, y, w, h); + } + + private void deliverMouseEvent(NSEvent event) { int x = event.getX(); int y = getBounds().height - event.getY(); diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java index 7fbc64c4f8d..b489eae96b6 100644 --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java @@ -25,7 +25,6 @@ package sun.lwawt.macosx; -import java.awt.BufferCapabilities.FlipContents; import java.awt.*; import java.awt.Dialog.ModalityType; import java.awt.event.*; @@ -65,8 +64,6 @@ public final class CPlatformWindow extends CFRetainedResource implements Platfor private static native void nativeDispose(long nsWindowPtr); private static native CPlatformWindow nativeGetTopmostPlatformWindowUnderMouse(); - private static native int nativeGetNSWindowDisplayID(long nsWindowPtr); - // Loger to report issues happened during execution but that do not affect functionality private static final PlatformLogger logger = PlatformLogger.getLogger("sun.lwawt.macosx.CPlatformWindow"); private static final PlatformLogger focusLogger = PlatformLogger.getLogger("sun.lwawt.macosx.focus.CPlatformWindow"); @@ -212,9 +209,8 @@ public final class CPlatformWindow extends CFRetainedResource implements Platfor private CPlatformResponder responder; private volatile boolean zoomed = false; // from native perspective - public CPlatformWindow(final PeerType peerType) { + public CPlatformWindow() { super(0, true); - assert (peerType == PeerType.SIMPLEWINDOW || peerType == PeerType.DIALOG || peerType == PeerType.FRAME); } /* @@ -258,7 +254,7 @@ public final class CPlatformWindow extends CFRetainedResource implements Platfor validateSurface(); } - protected int getInitialStyleBits() { + private int getInitialStyleBits() { // defaults style bits int styleBits = DECORATED | HAS_SHADOW | CLOSEABLE | MINIMIZABLE | ZOOMABLE | RESIZABLE; @@ -285,7 +281,6 @@ public final class CPlatformWindow extends CFRetainedResource implements Platfor final boolean resizable = isFrame ? ((Frame)target).isResizable() : (isDialog ? ((Dialog)target).isResizable() : false); styleBits = SET(styleBits, RESIZABLE, resizable); if (!resizable) { - styleBits = SET(styleBits, RESIZABLE, false); styleBits = SET(styleBits, ZOOMABLE, false); } } @@ -380,7 +375,7 @@ public final class CPlatformWindow extends CFRetainedResource implements Platfor } // this is the counter-point to -[CWindow _nativeSetStyleBit:] - protected void setStyleBits(final int mask, final boolean value) { + private void setStyleBits(final int mask, final boolean value) { nativeSetNSWindowStyleBits(getNSWindowPtr(), mask, value ? mask : 0); } @@ -401,11 +396,6 @@ public final class CPlatformWindow extends CFRetainedResource implements Platfor } } - @Override // PlatformWindow - public Image createBackBuffer() { - return contentView.createBackBuffer(); - } - @Override // PlatformWindow public void dispose() { if (owner != null) { @@ -416,12 +406,6 @@ public final class CPlatformWindow extends CFRetainedResource implements Platfor CPlatformWindow.super.dispose(); } - @Override // PlatformWindow - public void flip(int x1, int y1, int x2, int y2, FlipContents flipAction) { - // TODO: not implemented - (new RuntimeException("unimplemented")).printStackTrace(); - } - @Override // PlatformWindow public FontMetrics getFontMetrics(Font f) { // TODO: not implemented @@ -442,16 +426,7 @@ public final class CPlatformWindow extends CFRetainedResource implements Platfor @Override public GraphicsDevice getGraphicsDevice() { - GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); - CGraphicsEnvironment cge = (CGraphicsEnvironment)ge; - int displayID = nativeGetNSWindowDisplayID(getNSWindowPtr()); - GraphicsDevice gd = cge.getScreenDevice(displayID); - if (gd == null) { - // this could possibly happen during device removal - // use the default screen device in this case - gd = ge.getDefaultScreenDevice(); - } - return gd; + return contentView.getGraphicsDevice(); } @Override // PlatformWindow @@ -668,15 +643,8 @@ public final class CPlatformWindow extends CFRetainedResource implements Platfor } @Override - public void setResizable(boolean resizable) { + public void setResizable(final boolean resizable) { setStyleBits(RESIZABLE, resizable); - - // Re-apply the size constraints and the size to ensure the space - // occupied by the grow box is counted properly - peer.updateMinimumSize(); - - Rectangle bounds = peer.getBounds(); - setBounds(bounds.x, bounds.y, bounds.width, bounds.height); } @Override @@ -853,6 +821,11 @@ public final class CPlatformWindow extends CFRetainedResource implements Platfor return peer; } + @Override + public boolean isUnderMouse() { + return contentView.isUnderMouse(); + } + public CPlatformView getContentView() { return contentView; } @@ -889,7 +862,8 @@ public final class CPlatformWindow extends CFRetainedResource implements Platfor responder.handleWindowFocusEvent(gained, oppositePeer); } - private void deliverMoveResizeEvent(int x, int y, int width, int height) { + private void deliverMoveResizeEvent(int x, int y, int width, int height, + boolean byUser) { // when the content view enters the full-screen mode, the native // move/resize notifications contain a bounds smaller than // the whole screen and therefore we ignore the native notifications @@ -901,7 +875,7 @@ public final class CPlatformWindow extends CFRetainedResource implements Platfor final Rectangle oldB = nativeBounds; nativeBounds = new Rectangle(x, y, width, height); peer.notifyReshape(x, y, width, height); - if (!oldB.getSize().equals(nativeBounds.getSize()) ) { + if (byUser && !oldB.getSize().equals(nativeBounds.getSize())) { flushBuffers(); } //TODO validateSurface already called from notifyReshape diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CPrinterDialogPeer.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CPrinterDialogPeer.java index f50f2869d9e..1ca65e7faae 100644 --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPrinterDialogPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPrinterDialogPeer.java @@ -41,7 +41,7 @@ public class CPrinterDialogPeer extends LWWindowPeer { public CPrinterDialogPeer(CPrinterDialog target, PlatformComponent platformComponent, PlatformWindow platformWindow) { - super(target, platformComponent, platformWindow); + super(target, platformComponent, platformWindow, LWWindowPeer.PeerType.DIALOG); //super(target); fTarget = target; super.initialize(); diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CViewEmbeddedFrame.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CViewEmbeddedFrame.java new file mode 100644 index 00000000000..306cfb1e12e --- /dev/null +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CViewEmbeddedFrame.java @@ -0,0 +1,102 @@ +/* + * 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. 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 sun.lwawt.macosx; + +import java.awt.AWTKeyStroke; +import java.awt.Toolkit; +import java.lang.reflect.InvocationTargetException; +import sun.awt.EmbeddedFrame; +import sun.lwawt.LWToolkit; +import sun.lwawt.LWWindowPeer; +/* + * The CViewEmbeddedFrame class is used in the SWT_AWT bridge. + * This is a part of public API and should not be renamed or moved + */ +public class CViewEmbeddedFrame extends EmbeddedFrame { + + private final long nsViewPtr; + + private boolean isActive = false; + + public CViewEmbeddedFrame(long nsViewPtr) { + this.nsViewPtr = nsViewPtr; + } + + @SuppressWarnings("deprecation") + @Override + public void addNotify() { + if (getPeer() == null) { + LWToolkit toolkit = (LWToolkit) Toolkit.getDefaultToolkit(); + setPeer(toolkit.createEmbeddedFrame(this)); + } + super.addNotify(); + } + + public long getEmbedderHandle() { + return nsViewPtr; + } + + @Override + public void registerAccelerator(AWTKeyStroke awtks) { + } + + @Override + public void unregisterAccelerator(AWTKeyStroke awtks) { + } + + public boolean isParentWindowActive() { + return isActive; + } + + /* + * Synthetic event delivery for focus management + */ + @Override + public void synthesizeWindowActivation(boolean activated) { + if (isActive != activated) { + isActive = activated; + ((LWWindowPeer)getPeer()).notifyActivation(activated, null); + } + } + + /* + * Initializes the embedded frame bounds and validates a component. + * Designed to be called from the main thread + * This method should be called once from the initialization of the SWT_AWT Bridge + */ + @SuppressWarnings("deprecation") + public void validateWithBounds(final int x, final int y, final int width, final int height) { + try { + LWCToolkit.invokeAndWait(new Runnable() { + @Override + public void run() { + ((LWWindowPeer) getPeer()).setBoundsPrivate(0, 0, width, height); + validate(); + setVisible(true); + } + }, null); + } catch (InterruptedException | InvocationTargetException ex) {} + } +} diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CViewPlatformEmbeddedFrame.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CViewPlatformEmbeddedFrame.java new file mode 100644 index 00000000000..adc3c034b74 --- /dev/null +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CViewPlatformEmbeddedFrame.java @@ -0,0 +1,211 @@ +/* + * 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. 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 sun.lwawt.macosx; + +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.GraphicsDevice; +import java.awt.Insets; +import java.awt.MenuBar; +import java.awt.Point; +import java.awt.Window; +import sun.awt.CausedFocusEvent.Cause; +import sun.java2d.SurfaceData; +import sun.lwawt.LWWindowPeer; +import sun.lwawt.PlatformWindow; + +public class CViewPlatformEmbeddedFrame implements PlatformWindow { + + private CPlatformView view; + private LWWindowPeer peer; + private CViewEmbeddedFrame target; + private CPlatformResponder responder; + + @Override // PlatformWindow + public void initialize(Window target, final LWWindowPeer peer, PlatformWindow owner) { + this.peer = peer; + this.target = (CViewEmbeddedFrame) target; + responder = new CPlatformResponder(peer, false); + + view = new CPlatformView(); + view.initialize(peer, responder); + + CWrapper.NSView.addSubview(this.target.getEmbedderHandle(), view.getAWTView()); + view.setAutoResizable(true); + } + + public long getNSViewPtr() { + return view.getAWTView(); + } + + @Override + public long getLayerPtr() { + return view.getWindowLayerPtr(); + } + + @Override + public LWWindowPeer getPeer() { + return peer; + } + + @Override + public void dispose() { + CWrapper.NSView.removeFromSuperview(view.getAWTView()); + view.dispose(); + } + + @Override + public void setVisible(boolean visible) { + CWrapper.NSView.setHidden(view.getAWTView(), !visible); + } + + @Override + public void setTitle(String title) { + } + + @Override + public void setBounds(int x, int y, int w, int h) { + view.setBounds(x, y, w, h); + peer.notifyReshape(x, y, w, h); + } + + @Override + public GraphicsDevice getGraphicsDevice() { + return view.getGraphicsDevice(); + } + + @Override + public Point getLocationOnScreen() { + return view.getLocationOnScreen(); + } + + @Override + public Insets getInsets() { + return new Insets(0, 0, 0, 0); + } + + @Override + public FontMetrics getFontMetrics(Font f) { + throw new RuntimeException("Not implemented"); + } + + @Override + public SurfaceData getScreenSurface() { + return view.getSurfaceData(); + } + + @Override + public SurfaceData replaceSurfaceData() { + return view.replaceSurfaceData(); + } + + @Override + public void setModalBlocked(boolean blocked) { + } + + @Override + public void toFront() { + } + + @Override + public void toBack() { + } + + @Override + public void setMenuBar(MenuBar mb) { + } + + @Override + public void setAlwaysOnTop(boolean value) { + } + + @Override + public PlatformWindow getTopmostPlatformWindowUnderMouse() { + return null; + } + + @Override + public void updateFocusableWindowState() { + } + + @Override + public boolean rejectFocusRequest(Cause cause) { + return false; + } + + @Override + public boolean requestWindowFocus() { + return true; + } + + @Override + public boolean isActive() { + return target.isParentWindowActive(); + } + + @Override + public void setResizable(boolean resizable) { + } + + @Override + public void setSizeConstraints(int minW, int minH, int maxW, int maxH) { + } + + @Override + public Graphics transformGraphics(Graphics g) { + return g; + } + + @Override + public void updateIconImages() { + } + + @Override + public void setOpacity(float opacity) { + } + + @Override + public void setOpaque(boolean isOpaque) { + } + + @Override + public void enterFullScreenMode() { + } + + @Override + public void exitFullScreenMode() { + } + + @Override + public void setWindowState(int windowState) { + } + + @Override + public boolean isUnderMouse() { + return view.isUnderMouse(); + } +} diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CWrapper.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CWrapper.java index 385259e352e..52aa16ce829 100644 --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CWrapper.java +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CWrapper.java @@ -85,6 +85,8 @@ public final class CWrapper { public static native void enterFullScreenMode(long view); public static native void exitFullScreenMode(long view); + + public static native void setHidden(long view, boolean hidden); } public static final class NSObject { diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java b/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java index 29e4f7b0c2e..ae6a4f77662 100644 --- a/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java @@ -156,10 +156,13 @@ public final class LWCToolkit extends LWToolkit { @Override protected PlatformWindow createPlatformWindow(PeerType peerType) { - if (peerType == PeerType.EMBEDDEDFRAME) { + if (peerType == PeerType.EMBEDDED_FRAME) { return new CPlatformEmbeddedFrame(); + } else if (peerType == PeerType.VIEW_EMBEDDED_FRAME) { + return new CViewPlatformEmbeddedFrame(); } else { - return new CPlatformWindow(peerType); + assert (peerType == PeerType.SIMPLEWINDOW || peerType == PeerType.DIALOG || peerType == PeerType.FRAME); + return new CPlatformWindow(); } } diff --git a/jdk/src/macosx/native/sun/awt/AWTSurfaceLayers.m b/jdk/src/macosx/native/sun/awt/AWTSurfaceLayers.m index 74b0855ffa2..c6fec1fc392 100644 --- a/jdk/src/macosx/native/sun/awt/AWTSurfaceLayers.m +++ b/jdk/src/macosx/native/sun/awt/AWTSurfaceLayers.m @@ -99,17 +99,16 @@ Java_sun_lwawt_macosx_CPlatformComponent_nativeCreateComponent __block AWTSurfaceLayers *surfaceLayers = nil; JNF_COCOA_ENTER(env); -AWT_ASSERT_NOT_APPKIT_THREAD; - [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ - AWT_ASSERT_APPKIT_THREAD; - - CALayer *windowLayer = jlong_to_ptr(windowLayerPtr); - surfaceLayers = [[AWTSurfaceLayers alloc] initWithWindowLayer: windowLayer]; - CFRetain(surfaceLayers); - [surfaceLayers release]; + [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ + AWT_ASSERT_APPKIT_THREAD; + + CALayer *windowLayer = jlong_to_ptr(windowLayerPtr); + surfaceLayers = [[AWTSurfaceLayers alloc] initWithWindowLayer: windowLayer]; + CFRetain(surfaceLayers); + [surfaceLayers release]; }]; - + JNF_COCOA_EXIT(env); return ptr_to_jlong(surfaceLayers); @@ -126,12 +125,13 @@ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformComponent_nativeSetBounds JNF_COCOA_ENTER(env); AWTSurfaceLayers *surfaceLayers = OBJC(surfaceLayersPtr); - [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){ + + [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ AWT_ASSERT_APPKIT_THREAD; CGRect rect = CGRectMake(x, y, width, height); [surfaceLayers setBounds: rect]; - }]; + }]; JNF_COCOA_EXIT(env); } diff --git a/jdk/src/macosx/native/sun/awt/AWTView.m b/jdk/src/macosx/native/sun/awt/AWTView.m index 0f896a44300..3770287a32a 100644 --- a/jdk/src/macosx/native/sun/awt/AWTView.m +++ b/jdk/src/macosx/native/sun/awt/AWTView.m @@ -83,6 +83,7 @@ AWT_ASSERT_APPKIT_THREAD; mouseIsOver = NO; [self resetTrackingArea]; + [self setAutoresizesSubviews:NO]; if (windowLayer != nil) { self.cglLayer = windowLayer; @@ -174,6 +175,11 @@ AWT_ASSERT_APPKIT_THREAD; * Automatically triggered functions. */ +- (void)resizeWithOldSuperviewSize:(NSSize)oldBoundsSize { + [super resizeWithOldSuperviewSize: oldBoundsSize]; + [self deliverResize: [self frame]]; +} + /* * MouseEvents support */ @@ -437,6 +443,18 @@ AWT_ASSERT_APPKIT_THREAD; } } +-(void) deliverResize: (NSRect) rect { + jint x = (jint) rect.origin.x; + jint y = (jint) rect.origin.y; + jint w = (jint) rect.size.width; + jint h = (jint) rect.size.height; + JNIEnv *env = [ThreadUtilities getJNIEnv]; + static JNF_CLASS_CACHE(jc_PlatformView, "sun/lwawt/macosx/CPlatformView"); + static JNF_MEMBER_CACHE(jm_deliverResize, jc_PlatformView, "deliverResize", "(IIII)V"); + JNFCallVoidMethod(env, m_cPlatformView, jm_deliverResize, x,y,w,h); +} + + - (void) drawRect:(NSRect)dirtyRect { AWT_ASSERT_APPKIT_THREAD; @@ -1220,21 +1238,19 @@ Java_sun_lwawt_macosx_CPlatformView_nativeCreateView __block AWTView *newView = nil; JNF_COCOA_ENTER(env); -AWT_ASSERT_NOT_APPKIT_THREAD; NSRect rect = NSMakeRect(originX, originY, width, height); jobject cPlatformView = (*env)->NewGlobalRef(env, obj); - [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ + [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ AWT_ASSERT_APPKIT_THREAD; - + CALayer *windowLayer = jlong_to_ptr(windowLayerPtr); AWTView *view = [[AWTView alloc] initWithRect:rect platformView:cPlatformView windowLayer:windowLayer]; CFRetain(view); [view release]; // GC - newView = view; }]; @@ -1242,3 +1258,125 @@ JNF_COCOA_EXIT(env); return ptr_to_jlong(newView); } + +/* + * Class: sun_lwawt_macosx_CPlatformView + * Method: nativeSetAutoResizable + * Signature: (JZ)V; + */ + +JNIEXPORT void JNICALL +Java_sun_lwawt_macosx_CPlatformView_nativeSetAutoResizable +(JNIEnv *env, jclass cls, jlong viewPtr, jboolean toResize) +{ +JNF_COCOA_ENTER(env); + + NSView *view = (NSView *)jlong_to_ptr(viewPtr); + + [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ + AWT_ASSERT_APPKIT_THREAD; + + if (toResize) { + [view setAutoresizingMask: NSViewHeightSizable | NSViewWidthSizable]; + } else { + [view setAutoresizingMask: NSViewMinYMargin | NSViewMaxXMargin]; + } + + if ([view superview] != nil) { + [[view superview] setAutoresizesSubviews:(BOOL)toResize]; + } + + }]; +JNF_COCOA_EXIT(env); +} + +/* + * Class: sun_lwawt_macosx_CPlatformView + * Method: nativeGetNSViewDisplayID + * Signature: (J)I; + */ + +JNIEXPORT jint JNICALL +Java_sun_lwawt_macosx_CPlatformView_nativeGetNSViewDisplayID +(JNIEnv *env, jclass cls, jlong viewPtr) +{ + __block jint ret; //CGDirectDisplayID + +JNF_COCOA_ENTER(env); + + NSView *view = (NSView *)jlong_to_ptr(viewPtr); + NSWindow *window = [view window]; + + [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ + AWT_ASSERT_APPKIT_THREAD; + + ret = (jint)[[AWTWindow getNSWindowDisplayID_AppKitThread: window] intValue]; + }]; + +JNF_COCOA_EXIT(env); + + return ret; +} + +/* + * Class: sun_lwawt_macosx_CPlatformView + * Method: nativeGetLocationOnScreen + * Signature: (J)Ljava/awt/Rectangle; + */ + +JNIEXPORT jobject JNICALL +Java_sun_lwawt_macosx_CPlatformView_nativeGetLocationOnScreen +(JNIEnv *env, jclass cls, jlong viewPtr) +{ + jobject jRect = NULL; + +JNF_COCOA_ENTER(env); + + __block NSRect rect = NSZeroRect; + + NSView *view = (NSView *)jlong_to_ptr(viewPtr); + [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ + AWT_ASSERT_APPKIT_THREAD; + + NSRect viewBounds = [view bounds]; + NSRect frameInWindow = [view convertRect:viewBounds toView:nil]; + rect = [[view window] convertRectToScreen:frameInWindow]; + NSRect screenRect = [[NSScreen mainScreen] frame]; + //Convert coordinates to top-left corner origin + rect.origin.y = screenRect.size.height - rect.origin.y - viewBounds.size.height; + }]; + jRect = NSToJavaRect(env, rect); + +JNF_COCOA_EXIT(env); + + return jRect; +} + +/* + * Class: sun_lwawt_macosx_CPlatformView + * Method: nativeIsViewUnderMouse + * Signature: (J)Z; + */ + +JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_CPlatformView_nativeIsViewUnderMouse +(JNIEnv *env, jclass clazz, jlong viewPtr) +{ + __block jboolean underMouse = JNI_FALSE; + +JNF_COCOA_ENTER(env); + + NSView *nsView = OBJC(viewPtr); + [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ + AWT_ASSERT_APPKIT_THREAD; + + NSPoint ptWindowCoords = [[nsView window] mouseLocationOutsideOfEventStream]; + NSPoint ptViewCoords = [nsView convertPoint:ptWindowCoords fromView:nil]; + underMouse = [nsView hitTest:ptViewCoords] != nil; + }]; + +JNF_COCOA_EXIT(env); + + return underMouse; +} + + diff --git a/jdk/src/macosx/native/sun/awt/AWTWindow.m b/jdk/src/macosx/native/sun/awt/AWTWindow.m index 3e25a6cb63c..fa27a3bf761 100644 --- a/jdk/src/macosx/native/sun/awt/AWTWindow.m +++ b/jdk/src/macosx/native/sun/awt/AWTWindow.m @@ -160,6 +160,10 @@ AWT_NS_WINDOW_IMPLEMENTATION BOOL resizable = IS(bits, RESIZABLE); [self updateMinMaxSize:resizable]; [self.nsWindow setShowsResizeIndicator:resizable]; + // Zoom button should be disabled, if the window is not resizable, + // otherwise button should be restored to initial state. + BOOL zoom = resizable && IS(bits, ZOOMABLE); + [[self.nsWindow standardWindowButton:NSWindowZoomButton] setEnabled:zoom]; } if (IS(mask, HAS_SHADOW)) { @@ -445,12 +449,13 @@ AWT_ASSERT_APPKIT_THREAD; NSRect frame = ConvertNSScreenRect(env, [self.nsWindow frame]); - static JNF_MEMBER_CACHE(jm_deliverMoveResizeEvent, jc_CPlatformWindow, "deliverMoveResizeEvent", "(IIII)V"); + static JNF_MEMBER_CACHE(jm_deliverMoveResizeEvent, jc_CPlatformWindow, "deliverMoveResizeEvent", "(IIIIZ)V"); JNFCallVoidMethod(env, platformWindow, jm_deliverMoveResizeEvent, (jint)frame.origin.x, (jint)frame.origin.y, (jint)frame.size.width, - (jint)frame.size.height); + (jint)frame.size.height, + (jboolean)[self.nsWindow inLiveResize]); (*env)->DeleteLocalRef(env, platformWindow); } @@ -784,7 +789,7 @@ AWT_ASSERT_NOT_APPKIT_THREAD; // calls methods on NSWindow to change other properties, based on the mask if (mask & MASK(_METHOD_PROP_BITMASK)) { - [window setPropertiesForStyleBits:bits mask:mask]; + [window setPropertiesForStyleBits:newBits mask:mask]; } window.styleBits = newBits; @@ -1149,34 +1154,6 @@ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSynthesizeMou JNF_COCOA_EXIT(env); } -/* - * Class: sun_lwawt_macosx_CPlatformWindow - * Method: nativeGetDisplayID_AppKitThread - * Signature: (J)I - */ -JNIEXPORT jint JNICALL -Java_sun_lwawt_macosx_CPlatformWindow_nativeGetNSWindowDisplayID -(JNIEnv *env, jclass clazz, jlong windowPtr) -{ - __block jint ret; // CGDirectDisplayID - -JNF_COCOA_ENTER(env); - - NSWindow *window = OBJC(windowPtr); - - if ([NSThread isMainThread]) { - ret = (jint)[[AWTWindow getNSWindowDisplayID_AppKitThread: window] intValue]; - } else { - [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ - ret = (jint)[[AWTWindow getNSWindowDisplayID_AppKitThread: window] intValue]; - }]; - } - -JNF_COCOA_EXIT(env); - - return ret; -} - /* * Class: sun_lwawt_macosx_CPlatformWindow * Method: _toggleFullScreenMode @@ -1198,27 +1175,6 @@ JNF_COCOA_ENTER(env); JNF_COCOA_EXIT(env); } -JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_CMouseInfoPeer_nativeIsWindowUnderMouse -(JNIEnv *env, jclass clazz, jlong windowPtr) -{ - __block jboolean underMouse = JNI_FALSE; - -JNF_COCOA_ENTER(env); -AWT_ASSERT_NOT_APPKIT_THREAD; - - NSWindow *nsWindow = OBJC(windowPtr); - [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^() { - AWT_ASSERT_APPKIT_THREAD; - - NSPoint pt = [nsWindow mouseLocationOutsideOfEventStream]; - underMouse = [[nsWindow contentView] hitTest:pt] != nil; - }]; - -JNF_COCOA_EXIT(env); - - return underMouse; -} - JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetEnabled (JNIEnv *env, jclass clazz, jlong windowPtr, jboolean isEnabled) { diff --git a/jdk/src/macosx/native/sun/awt/CCursorManager.m b/jdk/src/macosx/native/sun/awt/CCursorManager.m index e7378d3929a..601ea91e782 100644 --- a/jdk/src/macosx/native/sun/awt/CCursorManager.m +++ b/jdk/src/macosx/native/sun/awt/CCursorManager.m @@ -123,14 +123,15 @@ Java_sun_lwawt_macosx_CCursorManager_nativeGetCursorPosition jobject jpt = NULL; JNF_COCOA_ENTER(env); -AWT_ASSERT_NOT_APPKIT_THREAD; __block NSPoint pt = NSZeroPoint; - [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ - AWT_ASSERT_APPKIT_THREAD; - - pt = ConvertNSScreenPoint(env, [NSEvent mouseLocation]); + + [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ + AWT_ASSERT_APPKIT_THREAD; + + pt = ConvertNSScreenPoint(env, [NSEvent mouseLocation]); }]; + jpt = NSToJavaPoint(env, pt); JNF_COCOA_EXIT(env); diff --git a/jdk/src/macosx/native/sun/awt/CWrapper.m b/jdk/src/macosx/native/sun/awt/CWrapper.m index 139ea4bef71..eb047c5bc82 100644 --- a/jdk/src/macosx/native/sun/awt/CWrapper.m +++ b/jdk/src/macosx/native/sun/awt/CWrapper.m @@ -650,6 +650,26 @@ JNF_COCOA_EXIT(env); return windowPtr; } +/* + * Class: sun_lwawt_macosx_CWrapper$NSView + * Method: setHidden + * Signature: (JZ)V + */ +JNIEXPORT jlong JNICALL +Java_sun_lwawt_macosx_CWrapper_00024NSView_setHidden +(JNIEnv *env, jclass cls, jlong viewPtr, jboolean toHide) +{ + JNF_COCOA_ENTER(env); + + NSView *view = (NSView *)jlong_to_ptr(viewPtr); + [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){ + [view setHidden:(BOOL)toHide]; + }]; + + JNF_COCOA_EXIT(env); +} + + /* * Class: sun_lwawt_macosx_CWrapper$NSScreen * Method: frame diff --git a/jdk/src/macosx/native/sun/awt/awt.m b/jdk/src/macosx/native/sun/awt/awt.m index d183d1bc026..8ca56bd117c 100644 --- a/jdk/src/macosx/native/sun/awt/awt.m +++ b/jdk/src/macosx/native/sun/awt/awt.m @@ -95,7 +95,7 @@ AWT_ASSERT_APPKIT_THREAD; CFRelease(busyObserver); CFRelease(notBusyObserver); - + if (!headless) setBusy(YES); // Set the java name of the AppKit main thread appropriately. @@ -367,7 +367,8 @@ AWT_ASSERT_APPKIT_THREAD; CFRunLoopRef runLoop = [[NSRunLoop currentRunLoop] getCFRunLoop]; CFRunLoopRemoveObserver(runLoop, busyObserver, kCFRunLoopDefaultMode); CFRunLoopRemoveObserver(runLoop, notBusyObserver, kCFRunLoopDefaultMode); - + // We don't track if the runloop is busy, so set it free to let AWT finish when it needs + setBusy(NO); busyObserver = NULL; notBusyObserver = NULL; } else { diff --git a/jdk/src/macosx/native/sun/java2d/opengl/CGLLayer.m b/jdk/src/macosx/native/sun/java2d/opengl/CGLLayer.m index 76d6820a9ab..66838984aba 100644 --- a/jdk/src/macosx/native/sun/java2d/opengl/CGLLayer.m +++ b/jdk/src/macosx/native/sun/java2d/opengl/CGLLayer.m @@ -151,16 +151,15 @@ Java_sun_java2d_opengl_CGLLayer_nativeCreateLayer __block CGLLayer *layer = nil; JNF_COCOA_ENTER(env); -AWT_ASSERT_NOT_APPKIT_THREAD; JNFJObjectWrapper *javaLayer = [JNFJObjectWrapper wrapperWithJObject:obj withEnv:env]; - [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ - AWT_ASSERT_APPKIT_THREAD; - - layer = [[CGLLayer alloc] initWithJavaLayer: javaLayer]; + [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ + AWT_ASSERT_APPKIT_THREAD; + + layer = [[CGLLayer alloc] initWithJavaLayer: javaLayer]; }]; - + JNF_COCOA_EXIT(env); return ptr_to_jlong(layer); diff --git a/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.h b/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.h index f213a163e0c..0acde2f9aa6 100644 --- a/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.h +++ b/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.h @@ -139,7 +139,7 @@ __attribute__((visibility("default"))) + (JNIEnv*)getJNIEnvUncached; + (void)performOnMainThread:(SEL)aSelector onObject:(id)target withObject:(id)arg waitUntilDone:(BOOL)wait awtMode:(BOOL)inAWT; - ++ (void)performOnMainThreadWaiting:(BOOL)wait block:(void (^)())block; @end void OSXAPP_SetJavaVM(JavaVM *vm); diff --git a/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.m b/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.m index 788a06dccd1..0e40fc1a52b 100644 --- a/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.m +++ b/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.m @@ -245,6 +245,14 @@ AWT_ASSERT_APPKIT_THREAD; } } ++ (void)performOnMainThreadWaiting:(BOOL)wait block:(void (^)())block { + if ([NSThread isMainThread] && wait == YES) { + block(); + } else { + [JNFRunLoop performOnMainThreadWaiting:wait withBlock:block]; + } +} + @end diff --git a/jdk/src/share/back/debugInit.c b/jdk/src/share/back/debugInit.c index 490099b06c5..25ffbffc91a 100644 --- a/jdk/src/share/back/debugInit.c +++ b/jdk/src/share/back/debugInit.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -37,6 +37,7 @@ #include "debugLoop.h" #include "bag.h" #include "invoker.h" +#include "sys.h" /* How the options get to OnLoad: */ #define XDEBUG "-Xdebug" @@ -201,6 +202,8 @@ Agent_OnLoad(JavaVM *vm, char *options, void *reserved) jint jvmtiCompileTimeMajorVersion; jint jvmtiCompileTimeMinorVersion; jint jvmtiCompileTimeMicroVersion; + char *boot_path = NULL; + char npt_lib[MAXPATHLEN]; /* See if it's already loaded */ if ( gdata!=NULL && gdata->isLoaded==JNI_TRUE ) { @@ -227,18 +230,6 @@ Agent_OnLoad(JavaVM *vm, char *options, void *reserved) vmInitialized = JNI_FALSE; gdata->vmDead = JNI_FALSE; - /* Npt and Utf function init */ - NPT_INITIALIZE(&(gdata->npt), NPT_VERSION, NULL); - if (gdata->npt == NULL) { - ERROR_MESSAGE(("JDWP: unable to initialize NPT library")); - return JNI_ERR; - } - gdata->npt->utf = (gdata->npt->utfInitialize)(NULL); - if (gdata->npt->utf == NULL) { - ERROR_MESSAGE(("JDWP: UTF function initialization failed")); - return JNI_ERR; - } - /* Get the JVMTI Env, IMPORTANT: Do this first! For jvmtiAllocate(). */ error = JVM_FUNC_PTR(vm,GetEnv) (vm, (void **)&(gdata->jvmti), JVMTI_VERSION_1); @@ -277,6 +268,24 @@ Agent_OnLoad(JavaVM *vm, char *options, void *reserved) forceExit(1); /* Kill entire process, no core dump wanted */ } + JVMTI_FUNC_PTR(gdata->jvmti, GetSystemProperty) + (gdata->jvmti, (const char *)"sun.boot.library.path", + &boot_path); + + dbgsysBuildLibName(npt_lib, sizeof(npt_lib), boot_path, NPT_LIBNAME); + /* Npt and Utf function init */ + NPT_INITIALIZE(npt_lib, &(gdata->npt), NPT_VERSION, NULL); + jvmtiDeallocate(boot_path); + if (gdata->npt == NULL) { + ERROR_MESSAGE(("JDWP: unable to initialize NPT library")); + return JNI_ERR; + } + gdata->npt->utf = (gdata->npt->utfInitialize)(NULL); + if (gdata->npt->utf == NULL) { + ERROR_MESSAGE(("JDWP: UTF function initialization failed")); + return JNI_ERR; + } + /* Parse input options */ if (!parseOptions(options)) { /* No message necessary, should have been printed out already */ diff --git a/jdk/src/share/back/error_messages.c b/jdk/src/share/back/error_messages.c index 13a04b5173a..2ec5bbfa2e5 100644 --- a/jdk/src/share/back/error_messages.c +++ b/jdk/src/share/back/error_messages.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -70,8 +70,13 @@ vprint_message(FILE *fp, const char *prefix, const char *suffix, len = (int)strlen((char*)utf8buf); /* Convert to platform encoding (ignore errors, dangerous area) */ - (void)(gdata->npt->utf8ToPlatform)(gdata->npt->utf, - utf8buf, len, pbuf, MAX_MESSAGE_LEN); + if (gdata->npt != NULL) { + (void)(gdata->npt->utf8ToPlatform)(gdata->npt->utf, + utf8buf, len, pbuf, MAX_MESSAGE_LEN); + } else { + /* May be called before NPT is initialized so don't fault */ + strncpy(pbuf, (char*)utf8buf, len); + } (void)fprintf(fp, "%s%s%s", prefix, pbuf, suffix); } diff --git a/jdk/src/share/back/transport.c b/jdk/src/share/back/transport.c index b3154941729..40608b31239 100644 --- a/jdk/src/share/back/transport.c +++ b/jdk/src/share/back/transport.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -144,7 +144,9 @@ loadTransport(char *name, jdwpTransportEnv **transportPtr) /* First, look in sun.boot.library.path. This should find the standard * dt_socket and dt_shmem transport libraries, or any library * that was delivered with the J2SE. - * Note: Java property sun.boot.library.path contains a single directory. + * Note: Since 6819213 fixed, Java property sun.boot.library.path can + * contain multiple paths. Dll_dir is the first entry and + * -Dsun.boot.library.path entries are appended. */ libdir = gdata->property_sun_boot_library_path; if (libdir == NULL) { diff --git a/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFImageReader.java b/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFImageReader.java index 36c78a4ede1..d281e11c8c8 100644 --- a/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFImageReader.java +++ b/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFImageReader.java @@ -30,14 +30,10 @@ import java.awt.Rectangle; import java.awt.image.BufferedImage; import java.awt.image.DataBuffer; import java.awt.image.WritableRaster; -import java.io.BufferedInputStream; -import java.io.DataInputStream; import java.io.EOFException; -import java.io.InputStream; import java.io.IOException; import java.nio.ByteOrder; import java.util.ArrayList; -import java.util.Arrays; import java.util.Iterator; import java.util.List; import javax.imageio.IIOException; @@ -48,6 +44,11 @@ import javax.imageio.metadata.IIOMetadata; import javax.imageio.spi.ImageReaderSpi; import javax.imageio.stream.ImageInputStream; import com.sun.imageio.plugins.common.ReaderUtil; +import java.awt.image.ColorModel; +import java.awt.image.IndexColorModel; +import java.awt.image.MultiPixelPackedSampleModel; +import java.awt.image.PixelInterleavedSampleModel; +import java.awt.image.SampleModel; public class GIFImageReader extends ImageReader { @@ -194,6 +195,36 @@ public class GIFImageReader extends ImageReader { return imageMetadata.imageHeight; } + // We don't check all parameters as ImageTypeSpecifier.createIndexed do + // since this method is private and we pass consistent data here + private ImageTypeSpecifier createIndexed(byte[] r, byte[] g, byte[] b, + int bits) { + ColorModel colorModel; + if (imageMetadata.transparentColorFlag) { + // Some files erroneously have a transparent color index + // of 255 even though there are fewer than 256 colors. + int idx = Math.min(imageMetadata.transparentColorIndex, + r.length - 1); + colorModel = new IndexColorModel(bits, r.length, r, g, b, idx); + } else { + colorModel = new IndexColorModel(bits, r.length, r, g, b); + } + + SampleModel sampleModel; + if (bits == 8) { + int[] bandOffsets = {0}; + sampleModel = + new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE, + 1, 1, 1, 1, + bandOffsets); + } else { + sampleModel = + new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE, + 1, 1, bits); + } + return new ImageTypeSpecifier(colorModel, sampleModel); + } + public Iterator getImageTypes(int imageIndex) throws IIOException { checkIndex(imageIndex); @@ -239,22 +270,7 @@ public class GIFImageReader extends ImageReader { b[i] = colorTable[rgbIndex++]; } - byte[] a = null; - if (imageMetadata.transparentColorFlag) { - a = new byte[lutLength]; - Arrays.fill(a, (byte)255); - - // Some files erroneously have a transparent color index - // of 255 even though there are fewer than 256 colors. - int idx = Math.min(imageMetadata.transparentColorIndex, - lutLength - 1); - a[idx] = (byte)0; - } - - int[] bitsPerSample = new int[1]; - bitsPerSample[0] = bits; - l.add(ImageTypeSpecifier.createIndexed(r, g, b, a, bits, - DataBuffer.TYPE_BYTE)); + l.add(createIndexed(r, g, b, bits)); return l.iterator(); } diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/PropMap.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/PropMap.java index e1a385546c9..6199c77b51d 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/PropMap.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/PropMap.java @@ -25,8 +25,6 @@ package com.sun.java.util.jar.pack; -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeEvent; import java.io.IOException; import java.io.InputStream; import java.io.PrintStream; @@ -42,40 +40,39 @@ import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; import java.util.jar.Pack200; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + /** * Control block for publishing Pack200 options to the other classes. */ final class PropMap implements SortedMap { private final TreeMap theMap = new TreeMap<>();; - private final List listenerList = new ArrayList<>(1); - void addListener(PropertyChangeListener listener) { + // type is erased, elements are of type java.beans.PropertyChangeListener + private final List listenerList = new ArrayList<>(1); + + void addListener(Object listener) { + assert Beans.isPropertyChangeListener(listener); listenerList.add(listener); } - void removeListener(PropertyChangeListener listener) { + void removeListener(Object listener) { + assert Beans.isPropertyChangeListener(listener); listenerList.remove(listener); } - void addListeners(ArrayList listeners) { - listenerList.addAll(listeners); - } - - void removeListeners(ArrayList listeners) { - listenerList.removeAll(listeners); - } - // Override: public String put(String key, String value) { String oldValue = theMap.put(key, value); if (value != oldValue && !listenerList.isEmpty()) { + assert Beans.isBeansPresent(); // Post the property change event. - PropertyChangeEvent event = - new PropertyChangeEvent(this, key, - oldValue, value); - for (PropertyChangeListener listener : listenerList) { - listener.propertyChange(event); + Object event = Beans.newPropertyChangeEvent(this, key, oldValue, value); + for (Object listener : listenerList) { + Beans.invokePropertyChange(listener, event); } } return oldValue; @@ -339,4 +336,113 @@ final class PropMap implements SortedMap { public String lastKey() { return theMap.lastKey(); } + + /** + * A class that provides access to the java.beans.PropertyChangeListener + * and java.beans.PropertyChangeEvent without creating a static dependency + * on java.beans. This class can be removed once the addPropertyChangeListener + * and removePropertyChangeListener methods are removed from Packer and + * Unpacker. + */ + private static class Beans { + private static final Class propertyChangeListenerClass = + getClass("java.beans.PropertyChangeListener"); + + private static final Class propertyChangeEventClass = + getClass("java.beans.PropertyChangeEvent"); + + private static final Method propertyChangeMethod = + getMethod(propertyChangeListenerClass, + "propertyChange", + propertyChangeEventClass); + + private static final Constructor propertyEventCtor = + getConstructor(propertyChangeEventClass, + Object.class, + String.class, + Object.class, + Object.class); + + private static Class getClass(String name) { + try { + return Class.forName(name, true, Beans.class.getClassLoader()); + } catch (ClassNotFoundException e) { + return null; + } + } + private static Constructor getConstructor(Class c, Class... types) { + try { + return (c == null) ? null : c.getDeclaredConstructor(types); + } catch (NoSuchMethodException x) { + throw new AssertionError(x); + } + } + + private static Method getMethod(Class c, String name, Class... types) { + try { + return (c == null) ? null : c.getMethod(name, types); + } catch (NoSuchMethodException e) { + throw new AssertionError(e); + } + } + + /** + * Returns {@code true} if java.beans is present. + */ + static boolean isBeansPresent() { + return propertyChangeListenerClass != null && + propertyChangeEventClass != null; + } + + /** + * Returns {@code true} if the given object is a PropertyChangeListener + */ + static boolean isPropertyChangeListener(Object obj) { + if (propertyChangeListenerClass == null) { + return false; + } else { + return propertyChangeListenerClass.isInstance(obj); + } + } + + /** + * Returns a new PropertyChangeEvent with the given source, property + * name, old and new values. + */ + static Object newPropertyChangeEvent(Object source, String prop, + Object oldValue, Object newValue) + { + try { + return propertyEventCtor.newInstance(source, prop, oldValue, newValue); + } catch (InstantiationException | IllegalAccessException x) { + throw new AssertionError(x); + } catch (InvocationTargetException x) { + Throwable cause = x.getCause(); + if (cause instanceof Error) + throw (Error)cause; + if (cause instanceof RuntimeException) + throw (RuntimeException)cause; + throw new AssertionError(x); + } + } + + /** + * Invokes the given PropertyChangeListener's propertyChange method + * with the given event. + */ + static void invokePropertyChange(Object listener, Object ev) { + try { + propertyChangeMethod.invoke(listener, ev); + } catch (IllegalAccessException x) { + throw new AssertionError(x); + } catch (InvocationTargetException x) { + Throwable cause = x.getCause(); + if (cause instanceof Error) + throw (Error)cause; + if (cause instanceof RuntimeException) + throw (RuntimeException)cause; + throw new AssertionError(x); + } + } + } } diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/EnumRowStatus.java b/jdk/src/share/classes/com/sun/jmx/snmp/EnumRowStatus.java index d92dd968f28..74a05ae1b96 100644 --- a/jdk/src/share/classes/com/sun/jmx/snmp/EnumRowStatus.java +++ b/jdk/src/share/classes/com/sun/jmx/snmp/EnumRowStatus.java @@ -28,10 +28,6 @@ package com.sun.jmx.snmp; import java.io.Serializable; import java.util.Hashtable; -import com.sun.jmx.snmp.SnmpValue; -import com.sun.jmx.snmp.SnmpInt; - -import com.sun.jmx.snmp.Enumerated; /** * This class is an internal class which is used to represent RowStatus @@ -263,30 +259,30 @@ public class EnumRowStatus extends Enumerated implements Serializable { // Documented in Enumerated // - protected Hashtable getIntTable() { + @Override + protected Hashtable getIntTable() { return EnumRowStatus.getRSIntTable(); } // Documented in Enumerated // - protected Hashtable getStringTable() { + @Override + protected Hashtable getStringTable() { return EnumRowStatus.getRSStringTable(); } - static final Hashtable getRSIntTable() { + static Hashtable getRSIntTable() { return intTable ; } - static final Hashtable getRSStringTable() { + static Hashtable getRSStringTable() { return stringTable ; } // Initialize the mapping tables. // - final static Hashtable intTable = - new Hashtable(); - final static Hashtable stringTable = - new Hashtable(); + final static Hashtable intTable = new Hashtable<>(); + final static Hashtable stringTable = new Hashtable<>(); static { intTable.put(new Integer(0), "unspecified"); intTable.put(new Integer(3), "notReady"); diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/Enumerated.java b/jdk/src/share/classes/com/sun/jmx/snmp/Enumerated.java index a4bca4e7053..7cde19bc20b 100644 --- a/jdk/src/share/classes/com/sun/jmx/snmp/Enumerated.java +++ b/jdk/src/share/classes/com/sun/jmx/snmp/Enumerated.java @@ -54,9 +54,9 @@ abstract public class Enumerated implements Serializable { * @exception IllegalArgumentException One of the arguments passed to the method is illegal or inappropriate. */ public Enumerated() throws IllegalArgumentException { - Enumeration e =getIntTable().keys() ; + Enumeration e =getIntTable().keys(); if (e.hasMoreElements()) { - value = ((Integer)e.nextElement()).intValue() ; + value = e.nextElement().intValue() ; } else { throw new IllegalArgumentException() ; @@ -100,7 +100,7 @@ abstract public class Enumerated implements Serializable { * to the method is illegal or inappropriate. */ public Enumerated(String valueString) throws IllegalArgumentException { - Integer index = (Integer)getStringTable().get(valueString) ; + Integer index = getStringTable().get(valueString) ; if (index == null) { throw new IllegalArgumentException() ; } @@ -127,7 +127,7 @@ abstract public class Enumerated implements Serializable { * @return An enumeration of Integer instances */ - public Enumeration valueIndexes() { + public Enumeration valueIndexes() { return getIntTable().keys() ; } @@ -138,7 +138,7 @@ abstract public class Enumerated implements Serializable { * @return An enumeration of String instances */ - public Enumeration valueStrings() { + public Enumeration valueStrings() { return getStringTable().keys() ; } @@ -153,6 +153,7 @@ abstract public class Enumerated implements Serializable { * * @return True if this and obj are the same; false otherwise */ + @Override public boolean equals(Object obj) { return ((obj != null) && @@ -166,6 +167,7 @@ abstract public class Enumerated implements Serializable { * * @return A hash code value for this object. */ + @Override public int hashCode() { String hashString = getClass().getName() + String.valueOf(value) ; return hashString.hashCode() ; @@ -177,9 +179,9 @@ abstract public class Enumerated implements Serializable { * * @return The string for for this object. */ - + @Override public String toString() { - return (String)getIntTable().get(new Integer(value)) ; + return getIntTable().get(new Integer(value)) ; } @@ -193,7 +195,7 @@ abstract public class Enumerated implements Serializable { * @return An hashtable for read-only purpose */ - protected abstract Hashtable getIntTable() ; + protected abstract Hashtable getIntTable() ; @@ -207,12 +209,12 @@ abstract public class Enumerated implements Serializable { * @return An hashtable for read-only purpose */ - protected abstract Hashtable getStringTable() ; + protected abstract Hashtable getStringTable() ; /** * This variable keeps the integer form of the enumerated. - * The string form is retreived using getIntTable(). + * The string form is retrieved using getIntTable(). */ protected int value ; diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/IPAcl/AclImpl.java b/jdk/src/share/classes/com/sun/jmx/snmp/IPAcl/AclImpl.java index 353514c689e..b78c9ff7c03 100644 --- a/jdk/src/share/classes/com/sun/jmx/snmp/IPAcl/AclImpl.java +++ b/jdk/src/share/classes/com/sun/jmx/snmp/IPAcl/AclImpl.java @@ -66,7 +66,7 @@ class AclImpl extends OwnerImpl implements Acl, Serializable { */ public AclImpl (PrincipalImpl owner, String name) { super(owner); - entryList = new Vector(); + entryList = new Vector<>(); aclName = name; } @@ -81,6 +81,7 @@ class AclImpl extends OwnerImpl implements Acl, Serializable { * of this ACL. * @see java.security.Principal */ + @Override public void setName(Principal caller, String name) throws NotOwnerException { if (!isOwner(caller)) @@ -93,6 +94,7 @@ class AclImpl extends OwnerImpl implements Acl, Serializable { * * @return the name of this ACL. */ + @Override public String getName(){ return aclName; } @@ -113,6 +115,7 @@ class AclImpl extends OwnerImpl implements Acl, Serializable { * this ACL. * @see java.security.Principal */ + @Override public boolean addEntry(Principal caller, AclEntry entry) throws NotOwnerException { if (!isOwner(caller)) @@ -144,6 +147,7 @@ class AclImpl extends OwnerImpl implements Acl, Serializable { * @see java.security.Principal * @see java.security.acl.AclEntry */ + @Override public boolean removeEntry(Principal caller, AclEntry entry) throws NotOwnerException { if (!isOwner(caller)) @@ -185,8 +189,9 @@ class AclImpl extends OwnerImpl implements Acl, Serializable { * is allowed. * @see java.security.Principal */ + @Override public Enumeration getPermissions(Principal user){ - Vector empty = new Vector(); + Vector empty = new Vector<>(); for (Enumeration e = entryList.elements();e.hasMoreElements();){ AclEntry ent = e.nextElement(); if (ent.getPrincipal().equals(user)) @@ -201,6 +206,7 @@ class AclImpl extends OwnerImpl implements Acl, Serializable { * * @return an enumeration of the entries in this ACL. */ + @Override public Enumeration entries(){ return entryList.elements(); } @@ -221,10 +227,11 @@ class AclImpl extends OwnerImpl implements Acl, Serializable { * @see java.security.Principal * @see java.security.Permission */ + @Override public boolean checkPermission(Principal user, java.security.acl.Permission perm) { - for (Enumeration e = entryList.elements();e.hasMoreElements();){ - AclEntry ent = (AclEntry) e.nextElement(); + for (Enumeration e = entryList.elements();e.hasMoreElements();){ + AclEntry ent = e.nextElement(); if (ent.getPrincipal().equals(user)) if (ent.checkPermission(perm)) return true; } @@ -250,7 +257,7 @@ class AclImpl extends OwnerImpl implements Acl, Serializable { */ public boolean checkPermission(Principal user, String community, java.security.acl.Permission perm) { - for (Enumeration e = entryList.elements();e.hasMoreElements();){ + for (Enumeration e = entryList.elements();e.hasMoreElements();){ AclEntryImpl ent = (AclEntryImpl) e.nextElement(); if (ent.getPrincipal().equals(user)) if (ent.checkPermission(perm) && ent.checkCommunity(community)) return true; @@ -269,7 +276,7 @@ class AclImpl extends OwnerImpl implements Acl, Serializable { * @see java.security.Permission */ public boolean checkCommunity(String community) { - for (Enumeration e = entryList.elements();e.hasMoreElements();){ + for (Enumeration e = entryList.elements();e.hasMoreElements();){ AclEntryImpl ent = (AclEntryImpl) e.nextElement(); if (ent.checkCommunity(community)) return true; } @@ -281,6 +288,7 @@ class AclImpl extends OwnerImpl implements Acl, Serializable { * * @return a string representation of the ACL contents. */ + @Override public String toString(){ return ("AclImpl: "+ getName()); } diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/IPAcl/JDMAclBlock.java b/jdk/src/share/classes/com/sun/jmx/snmp/IPAcl/JDMAclBlock.java index a48039fabd4..ca5720ef9a0 100644 --- a/jdk/src/share/classes/com/sun/jmx/snmp/IPAcl/JDMAclBlock.java +++ b/jdk/src/share/classes/com/sun/jmx/snmp/IPAcl/JDMAclBlock.java @@ -28,7 +28,9 @@ package com.sun.jmx.snmp.IPAcl; +import java.net.InetAddress; import java.util.Hashtable; +import java.util.Vector; class JDMAclBlock extends SimpleNode { JDMAclBlock(int id) { @@ -51,11 +53,13 @@ class JDMAclBlock extends SimpleNode { * Do no need to go through this part of the tree for * building TrapEntry. */ - public void buildTrapEntries(Hashtable dest) {} + @Override + public void buildTrapEntries(Hashtable> dest) {} /** * Do no need to go through this part of the tree for * building InformEntry. */ - public void buildInformEntries(Hashtable dest) {} + @Override + public void buildInformEntries(Hashtable> dest) {} } diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/IPAcl/JDMInformBlock.java b/jdk/src/share/classes/com/sun/jmx/snmp/IPAcl/JDMInformBlock.java index 6f54a6178d9..02a4550f1ce 100644 --- a/jdk/src/share/classes/com/sun/jmx/snmp/IPAcl/JDMInformBlock.java +++ b/jdk/src/share/classes/com/sun/jmx/snmp/IPAcl/JDMInformBlock.java @@ -27,7 +27,9 @@ package com.sun.jmx.snmp.IPAcl; +import java.net.InetAddress; import java.util.Hashtable; +import java.util.Vector; class JDMInformBlock extends SimpleNode { JDMInformBlock(int id) { @@ -50,11 +52,13 @@ class JDMInformBlock extends SimpleNode { * Do no need to go through this part of the tree for * building AclEntry. */ + @Override public void buildAclEntries(PrincipalImpl owner, AclImpl acl) {} /** * Do no need to go through this part of the tree for * building TrapEntry. */ - public void buildTrapEntries(Hashtable dest) {} + @Override + public void buildTrapEntries(Hashtable> dest) {} } diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/IPAcl/JDMTrapBlock.java b/jdk/src/share/classes/com/sun/jmx/snmp/IPAcl/JDMTrapBlock.java index d14d3d76fe7..ab3c5295865 100644 --- a/jdk/src/share/classes/com/sun/jmx/snmp/IPAcl/JDMTrapBlock.java +++ b/jdk/src/share/classes/com/sun/jmx/snmp/IPAcl/JDMTrapBlock.java @@ -28,7 +28,9 @@ package com.sun.jmx.snmp.IPAcl; +import java.net.InetAddress; import java.util.Hashtable; +import java.util.Vector; class JDMTrapBlock extends SimpleNode { JDMTrapBlock(int id) { @@ -51,11 +53,13 @@ class JDMTrapBlock extends SimpleNode { * Do no need to go through this part of the tree for * building AclEntry. */ + @Override public void buildAclEntries(PrincipalImpl owner, AclImpl acl) {} /** * Do no need to go through this part of the tree for * building InformEntry. */ - public void buildInformEntries(Hashtable dest) {} + @Override + public void buildInformEntries(Hashtable> dest) {} } diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/IPAcl/JJTParserState.java b/jdk/src/share/classes/com/sun/jmx/snmp/IPAcl/JJTParserState.java index 83adecd9755..f68c13cf260 100644 --- a/jdk/src/share/classes/com/sun/jmx/snmp/IPAcl/JJTParserState.java +++ b/jdk/src/share/classes/com/sun/jmx/snmp/IPAcl/JJTParserState.java @@ -27,18 +27,17 @@ package com.sun.jmx.snmp.IPAcl; -@SuppressWarnings("unchecked") // generated code, not worth fixing class JJTParserState { - private java.util.Stack nodes; - private java.util.Stack marks; + private java.util.Stack nodes; + private java.util.Stack marks; private int sp; // number of nodes on stack private int mk; // current mark private boolean node_created; JJTParserState() { - nodes = new java.util.Stack(); - marks = new java.util.Stack(); + nodes = new java.util.Stack<>(); + marks = new java.util.Stack<>(); sp = 0; mk = 0; } @@ -62,7 +61,7 @@ class JJTParserState { /* Returns the root node of the AST. It only makes sense to call this after a successful parse. */ Node rootNode() { - return (Node)nodes.elementAt(0); + return nodes.elementAt(0); } /* Pushes a node on to the stack. */ @@ -75,14 +74,14 @@ class JJTParserState { stack. */ Node popNode() { if (--sp < mk) { - mk = ((Integer)marks.pop()).intValue(); + mk = marks.pop().intValue(); } - return (Node)nodes.pop(); + return nodes.pop(); } /* Returns the node currently on the top of the stack. */ Node peekNode() { - return (Node)nodes.peek(); + return nodes.peek(); } /* Returns the number of children on the stack in the current node @@ -96,7 +95,7 @@ class JJTParserState { while (sp > mk) { popNode(); } - mk = ((Integer)marks.pop()).intValue(); + mk = marks.pop().intValue(); } @@ -112,7 +111,7 @@ class JJTParserState { made the children of the definite node. Then the definite node is pushed on to the stack. */ void closeNodeScope(Node n, int num) { - mk = ((Integer)marks.pop()).intValue(); + mk = marks.pop().intValue(); while (num-- > 0) { Node c = popNode(); c.jjtSetParent(n); @@ -132,7 +131,7 @@ class JJTParserState { void closeNodeScope(Node n, boolean condition) { if (condition) { int a = nodeArity(); - mk = ((Integer)marks.pop()).intValue(); + mk = marks.pop().intValue(); while (a-- > 0) { Node c = popNode(); c.jjtSetParent(n); @@ -142,7 +141,7 @@ class JJTParserState { pushNode(n); node_created = true; } else { - mk = ((Integer)marks.pop()).intValue(); + mk = marks.pop().intValue(); node_created = false; } } diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/IPAcl/Parser.java b/jdk/src/share/classes/com/sun/jmx/snmp/IPAcl/Parser.java index b2fe5f5d157..f6ba9e029e1 100644 --- a/jdk/src/share/classes/com/sun/jmx/snmp/IPAcl/Parser.java +++ b/jdk/src/share/classes/com/sun/jmx/snmp/IPAcl/Parser.java @@ -1168,7 +1168,7 @@ jjtree.openNodeScope(jjtn000);Token t; return (jj_ntk = jj_nt.kind); } - private java.util.Vector jj_expentries = new java.util.Vector(); + private java.util.Vector jj_expentries = new java.util.Vector<>(); private int[] jj_expentry; private int jj_kind = -1; private int[] jj_lasttokens = new int[100]; @@ -1184,8 +1184,8 @@ jjtree.openNodeScope(jjtn000);Token t; jj_expentry[i] = jj_lasttokens[i]; } boolean exists = false; - for (java.util.Enumeration enumv = jj_expentries.elements(); enumv.hasMoreElements();) { - int[] oldentry = (int[])(enumv.nextElement()); + for (java.util.Enumeration enumv = jj_expentries.elements(); enumv.hasMoreElements();) { + int[] oldentry = enumv.nextElement(); if (oldentry.length == jj_expentry.length) { exists = true; for (int i = 0; i < jj_expentry.length; i++) { @@ -1236,7 +1236,7 @@ jjtree.openNodeScope(jjtn000);Token t; jj_add_error_token(0, 0); int[][] exptokseq = new int[jj_expentries.size()][]; for (int i = 0; i < jj_expentries.size(); i++) { - exptokseq[i] = (int[])jj_expentries.elementAt(i); + exptokseq[i] = jj_expentries.elementAt(i); } return new ParseException(token, exptokseq, tokenImage); } diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/IPAcl/SnmpAcl.java b/jdk/src/share/classes/com/sun/jmx/snmp/IPAcl/SnmpAcl.java index 59f39969338..ae5b7cf9386 100644 --- a/jdk/src/share/classes/com/sun/jmx/snmp/IPAcl/SnmpAcl.java +++ b/jdk/src/share/classes/com/sun/jmx/snmp/IPAcl/SnmpAcl.java @@ -126,7 +126,7 @@ public class SnmpAcl implements InetAddressAcl, Serializable { * * @return An enumeration of the entries in this ACL. */ - public Enumeration entries() { + public Enumeration entries() { return acl.entries(); } @@ -137,11 +137,11 @@ public class SnmpAcl implements InetAddressAcl, Serializable { public Enumeration communities() { HashSet set = new HashSet(); Vector res = new Vector(); - for (Enumeration e = acl.entries() ; e.hasMoreElements() ;) { + for (Enumeration e = acl.entries() ; e.hasMoreElements() ;) { AclEntryImpl entry = (AclEntryImpl) e.nextElement(); - for (Enumeration cs = entry.communities(); + for (Enumeration cs = entry.communities(); cs.hasMoreElements() ;) { - set.add((String) cs.nextElement()); + set.add(cs.nextElement()); } } String[] objs = set.toArray(new String[0]); @@ -316,7 +316,7 @@ public class SnmpAcl implements InetAddressAcl, Serializable { * * @return An enumeration of the trap destinations (enumeration of InetAddress). */ - public Enumeration getTrapDestinations() { + public Enumeration getTrapDestinations() { return trapDestList.keys(); } @@ -327,16 +327,16 @@ public class SnmpAcl implements InetAddressAcl, Serializable { * * @return An enumeration of trap communities for a given host (enumeration of String). */ - public Enumeration getTrapCommunities(InetAddress i) { - Vector list = null; - if ((list = (Vector)trapDestList.get(i)) != null ) { + public Enumeration getTrapCommunities(InetAddress i) { + Vector list = null; + if ((list = trapDestList.get(i)) != null ) { if (SNMP_LOGGER.isLoggable(Level.FINER)) { SNMP_LOGGER.logp(Level.FINER, SnmpAcl.class.getName(), "getTrapCommunities", "["+i.toString()+"] is in list"); } return list.elements(); } else { - list = new Vector(); + list = new Vector<>(); if (SNMP_LOGGER.isLoggable(Level.FINER)) { SNMP_LOGGER.logp(Level.FINER, SnmpAcl.class.getName(), "getTrapCommunities", "["+i.toString()+"] is not in list"); @@ -350,7 +350,7 @@ public class SnmpAcl implements InetAddressAcl, Serializable { * * @return An enumeration of the inform destinations (enumeration of InetAddress). */ - public Enumeration getInformDestinations() { + public Enumeration getInformDestinations() { return informDestList.keys(); } @@ -361,16 +361,16 @@ public class SnmpAcl implements InetAddressAcl, Serializable { * * @return An enumeration of inform communities for a given host (enumeration of String). */ - public Enumeration getInformCommunities(InetAddress i) { - Vector list = null; - if ((list = (Vector)informDestList.get(i)) != null ) { + public Enumeration getInformCommunities(InetAddress i) { + Vector list = null; + if ((list = informDestList.get(i)) != null ) { if (SNMP_LOGGER.isLoggable(Level.FINER)) { SNMP_LOGGER.logp(Level.FINER, SnmpAcl.class.getName(), "getInformCommunities", "["+i.toString()+"] is in list"); } return list.elements(); } else { - list = new Vector(); + list = new Vector<>(); if (SNMP_LOGGER.isLoggable(Level.FINER)) { SNMP_LOGGER.logp(Level.FINER, SnmpAcl.class.getName(), "getInformCommunities", "["+i.toString()+"] is not in list"); @@ -426,15 +426,15 @@ public class SnmpAcl implements InetAddressAcl, Serializable { throw new IllegalArgumentException(err.getMessage()); } - for(Enumeration e = acl.entries(); e.hasMoreElements();) { + for(Enumeration e = acl.entries(); e.hasMoreElements();) { AclEntryImpl aa = (AclEntryImpl) e.nextElement(); if (SNMP_LOGGER.isLoggable(Level.FINER)) { SNMP_LOGGER.logp(Level.FINER, SnmpAcl.class.getName(), "readAuthorizedListFile", "===> " + aa.getPrincipal().toString()); } - for (Enumeration eee = aa.permissions();eee.hasMoreElements();) { - java.security.acl.Permission perm = (java.security.acl.Permission)eee.nextElement(); + for (Enumeration eee = aa.permissions();eee.hasMoreElements();) { + java.security.acl.Permission perm = eee.nextElement(); if (SNMP_LOGGER.isLoggable(Level.FINER)) { SNMP_LOGGER.logp(Level.FINER, SnmpAcl.class.getName(), "readAuthorizedListFile", "perm = " + perm); diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/InetAddressAcl.java b/jdk/src/share/classes/com/sun/jmx/snmp/InetAddressAcl.java index 99800e1ba89..690b933829a 100644 --- a/jdk/src/share/classes/com/sun/jmx/snmp/InetAddressAcl.java +++ b/jdk/src/share/classes/com/sun/jmx/snmp/InetAddressAcl.java @@ -99,7 +99,7 @@ public interface InetAddressAcl { * * @return An enumeration of the trap destinations (enumeration of InetAddress). */ - public Enumeration getTrapDestinations(); + public Enumeration getTrapDestinations(); /** * Returns an enumeration of trap communities for a given host. @@ -108,14 +108,14 @@ public interface InetAddressAcl { * * @return An enumeration of trap communities for a given host (enumeration of String). */ - public Enumeration getTrapCommunities(InetAddress address); + public Enumeration getTrapCommunities(InetAddress address); /** * Returns an enumeration of inform destinations. * * @return An enumeration of the inform destinations (enumeration of InetAddress). */ - public Enumeration getInformDestinations(); + public Enumeration getInformDestinations(); /** * Returns an enumeration of inform communities for a given host. @@ -124,5 +124,5 @@ public interface InetAddressAcl { * * @return An enumeration of inform communities for a given host (enumeration of String). */ - public Enumeration getInformCommunities(InetAddress address); + public Enumeration getInformCommunities(InetAddress address); } diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpErrorHandlerAgent.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpErrorHandlerAgent.java index 35c2fb8d986..ffa64b2f524 100644 --- a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpErrorHandlerAgent.java +++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpErrorHandlerAgent.java @@ -59,6 +59,7 @@ public class SnmpErrorHandlerAgent extends SnmpMibAgent * @exception IllegalAccessException The MIB cannot be initialized. */ + @Override public void init() throws IllegalAccessException { } @@ -74,6 +75,7 @@ public class SnmpErrorHandlerAgent extends SnmpMibAgent * @exception java.lang.Exception */ + @Override public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception { return name; @@ -87,6 +89,7 @@ public class SnmpErrorHandlerAgent extends SnmpMibAgent * @return The returned oid is null. */ + @Override public long[] getRootOid() { return null; } @@ -99,6 +102,7 @@ public class SnmpErrorHandlerAgent extends SnmpMibAgent * @exception SnmpStatusException An error occured during the operation. */ + @Override public void get(SnmpMibRequest inRequest) throws SnmpStatusException { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, @@ -108,9 +112,9 @@ public class SnmpErrorHandlerAgent extends SnmpMibAgent if(inRequest.getVersion() == SnmpDefinitions.snmpVersionOne) throw new SnmpStatusException(SnmpStatusException.noSuchName); - Enumeration l = inRequest.getElements(); + Enumeration l = inRequest.getElements(); while(l.hasMoreElements()) { - SnmpVarBind varbind = (SnmpVarBind) l.nextElement(); + SnmpVarBind varbind = l.nextElement(); varbind.setNoSuchObject(); } } @@ -128,6 +132,7 @@ public class SnmpErrorHandlerAgent extends SnmpMibAgent * cannot be performed. */ + @Override public void check(SnmpMibRequest inRequest) throws SnmpStatusException { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, @@ -145,6 +150,7 @@ public class SnmpErrorHandlerAgent extends SnmpMibAgent * @exception SnmpStatusException An error occured during the operation. */ + @Override public void set(SnmpMibRequest inRequest) throws SnmpStatusException { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, @@ -162,6 +168,7 @@ public class SnmpErrorHandlerAgent extends SnmpMibAgent * @exception SnmpStatusException An error occured during the operation. */ + @Override public void getNext(SnmpMibRequest inRequest) throws SnmpStatusException { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, @@ -171,9 +178,9 @@ public class SnmpErrorHandlerAgent extends SnmpMibAgent if(inRequest.getVersion() == SnmpDefinitions.snmpVersionOne) throw new SnmpStatusException(SnmpStatusException.noSuchName); - Enumeration l = inRequest.getElements(); + Enumeration l = inRequest.getElements(); while(l.hasMoreElements()) { - SnmpVarBind varbind = (SnmpVarBind) l.nextElement(); + SnmpVarBind varbind = l.nextElement(); varbind.setEndOfMibView(); } } @@ -186,6 +193,7 @@ public class SnmpErrorHandlerAgent extends SnmpMibAgent * @exception SnmpStatusException An error occured during the operation. */ + @Override public void getBulk(SnmpMibRequest inRequest, int nonRepeat, int maxRepeat) throws SnmpStatusException { @@ -196,9 +204,9 @@ public class SnmpErrorHandlerAgent extends SnmpMibAgent if(inRequest.getVersion() == SnmpDefinitions.snmpVersionOne) throw new SnmpStatusException(SnmpDefinitions.snmpRspGenErr, 0); - Enumeration l = inRequest.getElements(); + Enumeration l = inRequest.getElements(); while(l.hasMoreElements()) { - SnmpVarBind varbind = (SnmpVarBind) l.nextElement(); + SnmpVarBind varbind = l.nextElement(); varbind.setEndOfMibView(); } } diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpGenericObjectServer.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpGenericObjectServer.java index 547c8ca21bc..689e08505a2 100644 --- a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpGenericObjectServer.java +++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpGenericObjectServer.java @@ -28,7 +28,6 @@ package com.sun.jmx.snmp.agent; // java imports // -import java.util.Vector; import java.util.Enumeration; import java.util.Iterator; @@ -149,8 +148,8 @@ public class SnmpGenericObjectServer { final long[] idList = new long[size]; int i = 0; - for (Enumeration e=req.getElements(); e.hasMoreElements();) { - final SnmpVarBind var= (SnmpVarBind) e.nextElement(); + for (Enumeration e=req.getElements(); e.hasMoreElements();) { + final SnmpVarBind var= e.nextElement(); try { final long id = var.oid.getOidArc(depth); nameList[i] = meta.getAttributeName(id); @@ -190,7 +189,7 @@ public class SnmpGenericObjectServer { } - final Iterator it = result.iterator(); + final Iterator it = result.iterator(); for (int j=0; j < i; j++) { if (!it.hasNext()) { @@ -312,8 +311,8 @@ public class SnmpGenericObjectServer { final long[] idList = new long[size]; int i = 0; - for (Enumeration e=req.getElements(); e.hasMoreElements();) { - final SnmpVarBind var= (SnmpVarBind) e.nextElement(); + for (Enumeration e=req.getElements(); e.hasMoreElements();) { + final SnmpVarBind var= e.nextElement(); try { final long id = var.oid.getOidArc(depth); final String attname = meta.getAttributeName(id); @@ -330,7 +329,7 @@ public class SnmpGenericObjectServer { } } - AttributeList result = null; + AttributeList result; int errorCode = SnmpStatusException.noAccess; try { @@ -345,7 +344,7 @@ public class SnmpGenericObjectServer { result = new AttributeList(); } - final Iterator it = result.iterator(); + final Iterator it = result.iterator(); for (int j=0; j < i; j++) { if (!it.hasNext()) { @@ -469,8 +468,8 @@ public class SnmpGenericObjectServer { final Object data = req.getUserData(); - for (Enumeration e=req.getElements(); e.hasMoreElements();) { - final SnmpVarBind var= (SnmpVarBind) e.nextElement(); + for (Enumeration e=req.getElements(); e.hasMoreElements();) { + final SnmpVarBind var= e.nextElement(); try { final long id = var.oid.getOidArc(depth); // call meta.check() here, and meta.check will call check() diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpIndex.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpIndex.java index d41e2e35865..483a79618a8 100644 --- a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpIndex.java +++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpIndex.java @@ -164,11 +164,12 @@ public class SnmpIndex implements Serializable { * * @return A string representation of the index. */ + @Override public String toString() { - StringBuffer msg= new StringBuffer(); - for(Enumeration e= oids.elements(); e.hasMoreElements(); ) { - SnmpOid val= (SnmpOid) e.nextElement(); - msg.append( "//" + val.toString()); + final StringBuilder msg= new StringBuilder(); + for(Enumeration e= oids.elements(); e.hasMoreElements(); ) { + SnmpOid val= e.nextElement(); + msg.append("//").append( val.toString()); } return msg.toString(); } @@ -180,7 +181,7 @@ public class SnmpIndex implements Serializable { * The list of OIDs. * @serial */ - private Vector oids = new Vector(); + private Vector oids = new Vector<>(); /** * The number of elements in the index. diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMib.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMib.java index 13ae08c9cbe..df7587404ef 100644 --- a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMib.java +++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMib.java @@ -42,10 +42,6 @@ import com.sun.jmx.snmp.SnmpOid; import com.sun.jmx.snmp.SnmpVarBind; import com.sun.jmx.snmp.SnmpDefinitions; import com.sun.jmx.snmp.SnmpStatusException; -import com.sun.jmx.snmp.SnmpEngine; -import com.sun.jmx.snmp.SnmpUnknownModelException; -import com.sun.jmx.snmp.internal.SnmpAccessControlModel; -import com.sun.jmx.snmp.internal.SnmpEngineImpl; /** * Abstract class for representing an SNMP MIB. @@ -241,6 +237,7 @@ public abstract class SnmpMib extends SnmpMibAgent implements Serializable { // Implements the method defined in SnmpMibAgent. See SnmpMibAgent // for java-doc // + @Override public void get(SnmpMibRequest req) throws SnmpStatusException { // Builds the request tree: creation is not allowed, operation @@ -259,8 +256,8 @@ public abstract class SnmpMib extends SnmpMibAgent implements Serializable { // For each sub-request stored in the request-tree, invoke the // get() method. - for (Enumeration eh=handlers.getHandlers();eh.hasMoreElements();) { - h = (SnmpRequestTree.Handler) eh.nextElement(); + for (Enumeration eh=handlers.getHandlers();eh.hasMoreElements();) { + h = eh.nextElement(); // Gets the Meta node. It can be either a Group Meta or a // Table Meta. @@ -270,11 +267,11 @@ public abstract class SnmpMib extends SnmpMibAgent implements Serializable { // Gets the depth of the Meta node in the OID tree final int depth = handlers.getOidDepth(h); - for (Enumeration rqs=handlers.getSubRequests(h); + for (Enumeration rqs=handlers.getSubRequests(h); rqs.hasMoreElements();) { // Invoke the get() operation. - meta.get((SnmpMibSubRequest)rqs.nextElement(),depth); + meta.get(rqs.nextElement(),depth); } } } @@ -286,6 +283,7 @@ public abstract class SnmpMib extends SnmpMibAgent implements Serializable { // Implements the method defined in SnmpMibAgent. See SnmpMibAgent // for java-doc // + @Override public void set(SnmpMibRequest req) throws SnmpStatusException { SnmpRequestTree handlers = null; @@ -307,8 +305,8 @@ public abstract class SnmpMib extends SnmpMibAgent implements Serializable { handlers.switchCreationFlag(false); handlers.setPduType(reqType); - SnmpRequestTree.Handler h = null; - SnmpMibNode meta = null; + SnmpRequestTree.Handler h; + SnmpMibNode meta; if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpMib.class.getName(), @@ -317,8 +315,8 @@ public abstract class SnmpMib extends SnmpMibAgent implements Serializable { // For each sub-request stored in the request-tree, invoke the // get() method. - for (Enumeration eh=handlers.getHandlers();eh.hasMoreElements();) { - h = (SnmpRequestTree.Handler) eh.nextElement(); + for (Enumeration eh=handlers.getHandlers();eh.hasMoreElements();) { + h = eh.nextElement(); // Gets the Meta node. It can be either a Group Meta or a // Table Meta. @@ -328,11 +326,11 @@ public abstract class SnmpMib extends SnmpMibAgent implements Serializable { // Gets the depth of the Meta node in the OID tree final int depth = handlers.getOidDepth(h); - for (Enumeration rqs=handlers.getSubRequests(h); + for (Enumeration rqs=handlers.getSubRequests(h); rqs.hasMoreElements();) { // Invoke the set() operation - meta.set((SnmpMibSubRequest)rqs.nextElement(),depth); + meta.set(rqs.nextElement(),depth); } } } @@ -346,6 +344,7 @@ public abstract class SnmpMib extends SnmpMibAgent implements Serializable { // Implements the method defined in SnmpMibAgent. See SnmpMibAgent // for java-doc // + @Override public void check(SnmpMibRequest req) throws SnmpStatusException { final int reqType = SnmpDefinitions.pduWalkRequest; @@ -353,8 +352,8 @@ public abstract class SnmpMib extends SnmpMibAgent implements Serializable { // is atomic. SnmpRequestTree handlers = getHandlers(req,true,true,reqType); - SnmpRequestTree.Handler h = null; - SnmpMibNode meta = null; + SnmpRequestTree.Handler h; + SnmpMibNode meta; if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpMib.class.getName(), @@ -363,8 +362,8 @@ public abstract class SnmpMib extends SnmpMibAgent implements Serializable { // For each sub-request stored in the request-tree, invoke the // check() method. - for (Enumeration eh=handlers.getHandlers();eh.hasMoreElements();) { - h = (SnmpRequestTree.Handler) eh.nextElement(); + for (Enumeration eh=handlers.getHandlers();eh.hasMoreElements();) { + h = eh.nextElement(); // Gets the Meta node. It can be either a Group Meta or a // Table Meta. @@ -374,11 +373,11 @@ public abstract class SnmpMib extends SnmpMibAgent implements Serializable { // Gets the depth of the Meta node in the OID tree final int depth = handlers.getOidDepth(h); - for (Enumeration rqs=handlers.getSubRequests(h); + for (Enumeration rqs=handlers.getSubRequests(h); rqs.hasMoreElements();) { // Invoke the check() operation - meta.check((SnmpMibSubRequest)rqs.nextElement(),depth); + meta.check(rqs.nextElement(),depth); } } @@ -398,13 +397,14 @@ public abstract class SnmpMib extends SnmpMibAgent implements Serializable { // Implements the method defined in SnmpMibAgent. See SnmpMibAgent // for java-doc // + @Override public void getNext(SnmpMibRequest req) throws SnmpStatusException { // Build the request tree for the operation // The subrequest stored in the request tree are valid GET requests SnmpRequestTree handlers = getGetNextHandlers(req); - SnmpRequestTree.Handler h = null; - SnmpMibNode meta = null; + SnmpRequestTree.Handler h; + SnmpMibNode meta; if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpMib.class.getName(), @@ -412,8 +412,8 @@ public abstract class SnmpMib extends SnmpMibAgent implements Serializable { } // Now invoke get() for each subrequest of the request tree. - for (Enumeration eh=handlers.getHandlers();eh.hasMoreElements();) { - h = (SnmpRequestTree.Handler) eh.nextElement(); + for (Enumeration eh=handlers.getHandlers();eh.hasMoreElements();) { + h = eh.nextElement(); // Gets the Meta node. It can be either a Group Meta or a // Table Meta. @@ -423,11 +423,11 @@ public abstract class SnmpMib extends SnmpMibAgent implements Serializable { // Gets the depth of the Meta node in the OID tree int depth = handlers.getOidDepth(h); - for (Enumeration rqs=handlers.getSubRequests(h); + for (Enumeration rqs=handlers.getSubRequests(h); rqs.hasMoreElements();) { // Invoke the get() operation - meta.get((SnmpMibSubRequest)rqs.nextElement(),depth); + meta.get(rqs.nextElement(),depth); } } } @@ -442,6 +442,7 @@ public abstract class SnmpMib extends SnmpMibAgent implements Serializable { // Implements the method defined in SnmpMibAgent. See SnmpMibAgent // for java-doc // + @Override public void getBulk(SnmpMibRequest req, int nonRepeat, int maxRepeat) throws SnmpStatusException { @@ -456,10 +457,11 @@ public abstract class SnmpMib extends SnmpMibAgent implements Serializable { * * @return The root object identifier. */ + @Override public long[] getRootOid() { if( rootOid == null) { - Vector list= new Vector(10); + Vector list= new Vector<>(10); // Ask the tree to do the job ! // @@ -507,13 +509,13 @@ public abstract class SnmpMib extends SnmpMibAgent implements Serializable { new SnmpRequestTree(req,createflag,type); int index=0; - SnmpVarBind var = null; + SnmpVarBind var; final int ver= req.getVersion(); // For each varbind in the list finds its handling node. - for (Enumeration e= req.getElements(); e.hasMoreElements(); index++) { + for (Enumeration e= req.getElements(); e.hasMoreElements(); index++) { - var= (SnmpVarBind) e.nextElement(); + var= e.nextElement(); try { // Find the handling node for this varbind. @@ -657,10 +659,10 @@ public abstract class SnmpMib extends SnmpMibAgent implements Serializable { // request into a valid GET request, replacing the OIDs in the // original GET-NEXT request with the OID of the first leaf that // follows. - for (Enumeration e= req.getElements(); e.hasMoreElements(); index++) { + for (Enumeration e= req.getElements(); e.hasMoreElements(); index++) { - var = (SnmpVarBind) e.nextElement(); - SnmpOid result = null; + var = e.nextElement(); + SnmpOid result; try { // Find the node handling the OID that follows the varbind // OID. `result' contains this next leaf OID. diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibAgent.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibAgent.java index e0ba715d6e9..451fa859df4 100644 --- a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibAgent.java +++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibAgent.java @@ -33,14 +33,12 @@ package com.sun.jmx.snmp.agent; import java.io.Serializable; import java.util.Vector; import java.util.Enumeration; -import java.util.Set; // jmx imports // import javax.management.MBeanServer; import javax.management.MBeanRegistration; import javax.management.ObjectName; -import javax.management.MalformedObjectNameException; import javax.management.InstanceNotFoundException; import javax.management.ServiceNotFoundException; import javax.management.ReflectionException; @@ -94,6 +92,7 @@ public abstract class SnmpMibAgent * * @exception java.lang.Exception */ + @Override public abstract ObjectName preRegister(MBeanServer server, ObjectName name) throws java.lang.Exception; @@ -101,18 +100,21 @@ public abstract class SnmpMibAgent /** * Not used in this context. */ + @Override public void postRegister (Boolean registrationDone) { } /** * Not used in this context. */ + @Override public void preDeregister() throws java.lang.Exception { } /** * Not used in this context. */ + @Override public void postDeregister() { } @@ -127,6 +129,7 @@ public abstract class SnmpMibAgent * * @exception SnmpStatusException An error occured during the operation. */ + @Override public abstract void get(SnmpMibRequest req) throws SnmpStatusException; @@ -141,6 +144,7 @@ public abstract class SnmpMibAgent * * @exception SnmpStatusException An error occured during the operation. */ + @Override public abstract void getNext(SnmpMibRequest req) throws SnmpStatusException; @@ -164,6 +168,7 @@ public abstract class SnmpMibAgent * * @exception SnmpStatusException An error occured during the operation. */ + @Override public abstract void getBulk(SnmpMibRequest req, int nonRepeat, int maxRepeat) throws SnmpStatusException; @@ -185,6 +190,7 @@ public abstract class SnmpMibAgent * the exception is thrown in the {@link #check(SnmpMibRequest)} * method instead. */ + @Override public abstract void set(SnmpMibRequest req) throws SnmpStatusException; @@ -203,6 +209,7 @@ public abstract class SnmpMibAgent * @exception SnmpStatusException The set operation * cannot be performed. */ + @Override public abstract void check(SnmpMibRequest req) throws SnmpStatusException; @@ -226,6 +233,7 @@ public abstract class SnmpMibAgent * @return The MBean server or null if the MIB is not registered in any * MBean server. */ + @Override public MBeanServer getMBeanServer() { return server; } @@ -236,6 +244,7 @@ public abstract class SnmpMibAgent * * @return The SNMP MIB handler. */ + @Override public SnmpMibHandler getSnmpAdaptor() { return adaptor; } @@ -246,6 +255,7 @@ public abstract class SnmpMibAgent * * @param stack The SNMP MIB handler. */ + @Override public void setSnmpAdaptor(SnmpMibHandler stack) { if (adaptor != null) { adaptor.removeMib(this); @@ -266,6 +276,7 @@ public abstract class SnmpMibAgent * * @since 1.5 */ + @Override public void setSnmpAdaptor(SnmpMibHandler stack, SnmpOid[] oids) { if (adaptor != null) { adaptor.removeMib(this); @@ -288,6 +299,7 @@ public abstract class SnmpMibAgent * * @since 1.5 */ + @Override public void setSnmpAdaptor(SnmpMibHandler stack, String contextName) { if (adaptor != null) { adaptor.removeMib(this, contextName); @@ -309,6 +321,7 @@ public abstract class SnmpMibAgent * * @since 1.5 */ + @Override public void setSnmpAdaptor(SnmpMibHandler stack, String contextName, SnmpOid[] oids) { @@ -327,6 +340,7 @@ public abstract class SnmpMibAgent * * @return The name of the SNMP protocol adaptor. */ + @Override public ObjectName getSnmpAdaptorName() { return adaptorName; } @@ -344,6 +358,7 @@ public abstract class SnmpMibAgent * @exception ServiceNotFoundException This SNMP MIB is not registered * in the MBean server or the requested service is not supported. */ + @Override public void setSnmpAdaptorName(ObjectName name) throws InstanceNotFoundException, ServiceNotFoundException { @@ -389,6 +404,7 @@ public abstract class SnmpMibAgent * * @since 1.5 */ + @Override public void setSnmpAdaptorName(ObjectName name, SnmpOid[] oids) throws InstanceNotFoundException, ServiceNotFoundException { @@ -434,6 +450,7 @@ public abstract class SnmpMibAgent * * @since 1.5 */ + @Override public void setSnmpAdaptorName(ObjectName name, String contextName) throws InstanceNotFoundException, ServiceNotFoundException { @@ -481,6 +498,7 @@ public abstract class SnmpMibAgent * * @since 1.5 */ + @Override public void setSnmpAdaptorName(ObjectName name, String contextName, SnmpOid[] oids) throws InstanceNotFoundException, ServiceNotFoundException { @@ -522,6 +540,7 @@ public abstract class SnmpMibAgent * @return true if the MIB module is bound, * false otherwise. */ + @Override public boolean getBindingState() { if (adaptor == null) return false; @@ -534,6 +553,7 @@ public abstract class SnmpMibAgent * * @return The MIB name. */ + @Override public String getMibName() { return mibName; } @@ -681,7 +701,7 @@ public abstract class SnmpMibAgent private Vector splitFrom(Vector original, int limit) { int max= original.size(); - Vector result= new Vector(max - limit); + Vector result= new Vector<>(max - limit); int i= limit; // Ok the loop looks a bit strange. But in order to improve the @@ -697,21 +717,12 @@ public abstract class SnmpMibAgent return result; } - private void concatVector(SnmpMibRequest req, Vector source) { - for(Enumeration e= source.elements(); e.hasMoreElements(); ) { - SnmpVarBind var= (SnmpVarBind) e.nextElement(); - // We need to duplicate the SnmpVarBind otherwise it is going - // to be overloaded by the next get Next ... - req.addVarBind(new SnmpVarBind(var.oid, var.value)); - } - } - - private void concatVector(Vector target, Vector source) { + private void concatVector(SnmpMibRequest req, Vector source) { for(Enumeration e= source.elements(); e.hasMoreElements(); ) { SnmpVarBind var= e.nextElement(); // We need to duplicate the SnmpVarBind otherwise it is going // to be overloaded by the next get Next ... - target.addElement(new SnmpVarBind(var.oid, var.value)); + req.addVarBind(new SnmpVarBind(var.oid, var.value)); } } diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibGroup.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibGroup.java index b34e0009481..29882ce01d4 100644 --- a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibGroup.java +++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibGroup.java @@ -29,20 +29,13 @@ package com.sun.jmx.snmp.agent; // import java.io.Serializable; import java.util.Hashtable; -import java.util.Enumeration; import java.util.Vector; // jmx imports // -import com.sun.jmx.snmp.SnmpOid; -import com.sun.jmx.snmp.SnmpValue; import com.sun.jmx.snmp.SnmpVarBind; import com.sun.jmx.snmp.SnmpStatusException; -// SNMP Runtime imports -// -import com.sun.jmx.snmp.agent.SnmpMibOid; -import com.sun.jmx.snmp.agent.SnmpMibNode; /** * Represents a node in an SNMP MIB which corresponds to a group. @@ -174,6 +167,7 @@ public abstract class SnmpMibGroup extends SnmpMibOid * @exception SnmpStatusException An error occurred while accessing * the MIB node. */ + @Override abstract public void get(SnmpMibSubRequest req, int depth) throws SnmpStatusException; @@ -203,6 +197,7 @@ public abstract class SnmpMibGroup extends SnmpMibOid * @exception SnmpStatusException An error occurred while accessing * the MIB node. */ + @Override abstract public void set(SnmpMibSubRequest req, int depth) throws SnmpStatusException; @@ -234,6 +229,7 @@ public abstract class SnmpMibGroup extends SnmpMibOid * @exception SnmpStatusException An error occurred while accessing * the MIB node. */ + @Override abstract public void check(SnmpMibSubRequest req, int depth) throws SnmpStatusException; @@ -241,8 +237,8 @@ public abstract class SnmpMibGroup extends SnmpMibOid // If we reach this node, we are below the root OID, so we just // return. // -------------------------------------------------------------------- - public void getRootOid(Vector result) { - return; + @Override + public void getRootOid(Vector result) { } // ------------------------------------------------------------------- @@ -264,7 +260,7 @@ public abstract class SnmpMibGroup extends SnmpMibOid */ void registerNestedArc(long arc) { Long obj = new Long(arc); - if (subgroups == null) subgroups = new Hashtable(); + if (subgroups == null) subgroups = new Hashtable<>(); // registers the arc in the hashtable. subgroups.put(obj,obj); } @@ -312,6 +308,7 @@ public abstract class SnmpMibGroup extends SnmpMibOid * @param node The node being registered. * */ + @Override void registerNode(long[] oid, int cursor ,SnmpMibNode node) throws IllegalAccessException { super.registerNode(oid,cursor,node); @@ -325,13 +322,13 @@ public abstract class SnmpMibGroup extends SnmpMibOid // ------------------------------------------------------------------- // see comments in SnmpMibNode // ------------------------------------------------------------------- + @Override void findHandlingNode(SnmpVarBind varbind, long[] oid, int depth, SnmpRequestTree handlers) throws SnmpStatusException { int length = oid.length; - SnmpMibNode node = null; if (handlers == null) throw new SnmpStatusException(SnmpStatusException.snmpRspGenErr); @@ -349,7 +346,6 @@ public abstract class SnmpMibGroup extends SnmpMibOid // This arc leads to a subgroup: delegates the search to the // method defined in SnmpMibOid super.findHandlingNode(varbind,oid,depth,handlers); - return; } else if (isTable(arc)) { // This arc leads to a table: forward the search to the table. @@ -384,6 +380,7 @@ public abstract class SnmpMibGroup extends SnmpMibOid // ------------------------------------------------------------------- // See comments in SnmpMibNode. // ------------------------------------------------------------------- + @Override long[] findNextHandlingNode(SnmpVarBind varbind, long[] oid, int pos, int depth, SnmpRequestTree handlers, AcmChecker checker) diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibOid.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibOid.java index a9411b9d176..f3965bce637 100644 --- a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibOid.java +++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibOid.java @@ -37,7 +37,6 @@ import java.util.Enumeration; // jmx imports // import com.sun.jmx.snmp.SnmpOid; -import com.sun.jmx.snmp.SnmpValue; import com.sun.jmx.snmp.SnmpVarBind; import com.sun.jmx.snmp.SnmpStatusException; @@ -79,10 +78,11 @@ public class SnmpMibOid extends SnmpMibNode implements Serializable { * @exception SnmpStatusException The default implementation (if not * overridden) is to generate a SnmpStatusException. */ + @Override public void get(SnmpMibSubRequest req, int depth) throws SnmpStatusException { - for (Enumeration e= req.getElements(); e.hasMoreElements();) { - SnmpVarBind var= (SnmpVarBind) e.nextElement(); + for (Enumeration e= req.getElements(); e.hasMoreElements();) { + SnmpVarBind var= e.nextElement(); SnmpStatusException x = new SnmpStatusException(SnmpStatusException.noSuchObject); req.registerGetException(var,x); @@ -102,10 +102,11 @@ public class SnmpMibOid extends SnmpMibNode implements Serializable { * @exception SnmpStatusException The default implementation (if not * overridden) is to generate a SnmpStatusException. */ + @Override public void set(SnmpMibSubRequest req, int depth) throws SnmpStatusException { - for (Enumeration e= req.getElements(); e.hasMoreElements();) { - SnmpVarBind var= (SnmpVarBind) e.nextElement(); + for (Enumeration e= req.getElements(); e.hasMoreElements();) { + SnmpVarBind var= e.nextElement(); SnmpStatusException x = new SnmpStatusException(SnmpStatusException.noAccess); req.registerSetException(var,x); @@ -123,12 +124,13 @@ public class SnmpMibOid extends SnmpMibNode implements Serializable { * @param depth The depth reached in the OID tree. * * @exception SnmpStatusException The default implementation (if not - * overriden) is to generate a SnmpStatusException. + * overridden) is to generate a SnmpStatusException. */ + @Override public void check(SnmpMibSubRequest req, int depth) throws SnmpStatusException { - for (Enumeration e= req.getElements(); e.hasMoreElements();) { - SnmpVarBind var= (SnmpVarBind) e.nextElement(); + for (Enumeration e= req.getElements(); e.hasMoreElements();) { + SnmpVarBind var= e.nextElement(); SnmpStatusException x = new SnmpStatusException(SnmpStatusException.noAccess); req.registerCheckException(var,x); @@ -143,6 +145,7 @@ public class SnmpMibOid extends SnmpMibNode implements Serializable { // // --------------------------------------------------------------------- // + @Override void findHandlingNode(SnmpVarBind varbind, long[] oid, int depth, SnmpRequestTree handlers) @@ -191,6 +194,7 @@ public class SnmpMibOid extends SnmpMibNode implements Serializable { // // --------------------------------------------------------------------- // + @Override long[] findNextHandlingNode(SnmpVarBind varbind, long[] oid, int pos, int depth, SnmpRequestTree handlers, @@ -267,6 +271,7 @@ public class SnmpMibOid extends SnmpMibNode implements Serializable { /** * Computes the root OID of the MIB. */ + @Override public void getRootOid(Vector result) { // If a node has several children, let assume that we are one step to @@ -359,7 +364,6 @@ public class SnmpMibOid extends SnmpMibNode implements Serializable { // String.valueOf(var) + " position= " + cursor); children.insertElementAt(child, newPos); child.registerNode(oid, cursor + 1, node); - return; } else { // The node is already registered @@ -404,7 +408,6 @@ public class SnmpMibOid extends SnmpMibNode implements Serializable { } } children.setElementAt(node,pos); - return; } else { if (child == null) throw new IllegalAccessException(); @@ -469,7 +472,7 @@ public class SnmpMibOid extends SnmpMibNode implements Serializable { int max= varList.length -1 ; int curr= low + (max-low)/2; - int elmt= 0; + int elmt; while (low <= max) { elmt= varList[curr]; if (cursor == elmt) { @@ -494,7 +497,7 @@ public class SnmpMibOid extends SnmpMibNode implements Serializable { if (varList == null) return -1; int max= varList.length -1 ; - int elmt=0; + int elmt; //final int[] v = varList; //if (index > a[max]) @@ -528,7 +531,7 @@ public class SnmpMibOid extends SnmpMibNode implements Serializable { /** * Contains the list of sub nodes. */ - private NonSyncVector children = new NonSyncVector(1); + private NonSyncVector children = new NonSyncVector<>(1); /** * The number of sub nodes. diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibRequest.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibRequest.java index b45a8bca877..e117bf2a8cd 100644 --- a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibRequest.java +++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibRequest.java @@ -50,7 +50,7 @@ public interface SnmpMibRequest { * @return The element of the enumeration are instances of * {@link com.sun.jmx.snmp.SnmpVarBind} */ - public Enumeration getElements(); + public Enumeration getElements(); /** * Returns the vector of varbind to be handled by the SNMP mib node. diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibRequestImpl.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibRequestImpl.java index dfd9f4645e9..5f204bcba58 100644 --- a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibRequestImpl.java +++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibRequestImpl.java @@ -87,6 +87,7 @@ final class SnmpMibRequestImpl implements SnmpMibRequest { * Returns the local engine. This parameter is returned only if SnmpV3AdaptorServer is the adaptor receiving this request. Otherwise null is returned. * @return the local engine. */ + @Override public SnmpEngine getEngine() { return engine; } @@ -95,6 +96,7 @@ final class SnmpMibRequestImpl implements SnmpMibRequest { * Gets the incoming request principal. This parameter is returned only if SnmpV3AdaptorServer is the adaptor receiving this request. Otherwise null is returned. * @return The request principal. **/ + @Override public String getPrincipal() { return principal; } @@ -103,6 +105,7 @@ final class SnmpMibRequestImpl implements SnmpMibRequest { * Gets the incoming request security level. This level is defined in {@link com.sun.jmx.snmp.SnmpEngine SnmpEngine}. This parameter is returned only if SnmpV3AdaptorServer is the adaptor receiving this request. Otherwise -1 is returned. * @return The security level. */ + @Override public int getSecurityLevel() { return securityLevel; } @@ -110,6 +113,7 @@ final class SnmpMibRequestImpl implements SnmpMibRequest { * Gets the incoming request security model. This parameter is returned only if SnmpV3AdaptorServer is the adaptor receiving this request. Otherwise -1 is returned. * @return The security model. */ + @Override public int getSecurityModel() { return securityModel; } @@ -117,6 +121,7 @@ final class SnmpMibRequestImpl implements SnmpMibRequest { * Gets the incoming request context name. This parameter is returned only if SnmpV3AdaptorServer is the adaptor receiving this request. Otherwise null is returned. * @return The context name. */ + @Override public byte[] getContextName() { return contextName; } @@ -125,6 +130,7 @@ final class SnmpMibRequestImpl implements SnmpMibRequest { * Gets the incoming request context name used by Access Control Model in order to allow or deny the access to OIDs. This parameter is returned only if SnmpV3AdaptorServer is the adaptor receiving this request. Otherwise null is returned. * @return The checked context. */ + @Override public byte[] getAccessContextName() { return accessContextName; } @@ -133,6 +139,7 @@ final class SnmpMibRequestImpl implements SnmpMibRequest { // Implements the method defined in SnmpMibRequest interface. // See SnmpMibRequest for the java doc. // ------------------------------------------------------------------- + @Override public final SnmpPdu getPdu() { return reqPdu; } @@ -141,18 +148,21 @@ final class SnmpMibRequestImpl implements SnmpMibRequest { // Implements the method defined in SnmpMibRequest interface. // See SnmpMibRequest for the java doc. // ------------------------------------------------------------------- - public final Enumeration getElements() {return varbinds.elements();} + @Override + public final Enumeration getElements() {return varbinds.elements();} // ------------------------------------------------------------------- // Implements the method defined in SnmpMibRequest interface. // See SnmpMibRequest for the java doc. // ------------------------------------------------------------------- + @Override public final Vector getSubList() {return varbinds;} // ------------------------------------------------------------------- // Implements the method defined in SnmpMibRequest interface. // See SnmpMibRequest for the java doc. // ------------------------------------------------------------------- + @Override public final int getSize() { if (varbinds == null) return 0; return varbinds.size(); @@ -162,24 +172,28 @@ final class SnmpMibRequestImpl implements SnmpMibRequest { // Implements the method defined in SnmpMibRequest interface. // See SnmpMibRequest for the java doc. // ------------------------------------------------------------------- + @Override public final int getVersion() {return version;} // ------------------------------------------------------------------- // Implements the method defined in SnmpMibRequest interface. // See SnmpMibRequest for the java doc. // ------------------------------------------------------------------- + @Override public final int getRequestPduVersion() {return reqPdu.version;} // ------------------------------------------------------------------- // Implements the method defined in SnmpMibRequest interface. // See SnmpMibRequest for the java doc. // ------------------------------------------------------------------- + @Override public final Object getUserData() {return data;} // ------------------------------------------------------------------- // Implements the method defined in SnmpMibRequest interface. // See SnmpMibRequest for the java doc. // ------------------------------------------------------------------- + @Override public final int getVarIndex(SnmpVarBind varbind) { return varbinds.indexOf(varbind); } @@ -188,6 +202,7 @@ final class SnmpMibRequestImpl implements SnmpMibRequest { // Implements the method defined in SnmpMibRequest interface. // See SnmpMibRequest for the java doc. // ------------------------------------------------------------------- + @Override public void addVarBind(SnmpVarBind varbind) { varbinds.addElement(varbind); } @@ -218,7 +233,7 @@ final class SnmpMibRequestImpl implements SnmpMibRequest { // Returns the underlying vector of SNMP varbinds (used for algorithm // optimization). // ------------------------------------------------------------------- - final Vector getVarbinds() {return varbinds;} + final Vector getVarbinds() {return varbinds;} // ------------------------------------------------------------------- // Private variables diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibSubRequest.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibSubRequest.java index cd72847945a..76aa168b454 100644 --- a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibSubRequest.java +++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibSubRequest.java @@ -65,7 +65,8 @@ public interface SnmpMibSubRequest extends SnmpMibRequest { * @return The elements of the enumeration are instances of * {@link com.sun.jmx.snmp.SnmpVarBind} */ - public Enumeration getElements(); + @Override + public Enumeration getElements(); /** * Return the list of varbind to be handled by the SNMP MIB node. @@ -85,6 +86,7 @@ public interface SnmpMibSubRequest extends SnmpMibRequest { * @return The elements of the vector are instances of * {@link com.sun.jmx.snmp.SnmpVarBind} */ + @Override public Vector getSubList(); /** diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibTable.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibTable.java index 7b6631afc05..e0282c6cec0 100644 --- a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibTable.java +++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpMibTable.java @@ -266,6 +266,7 @@ public abstract class SnmpMibTable extends SnmpMibNode *

* */ + @Override public void get(SnmpMibSubRequest req, int depth) throws SnmpStatusException { @@ -276,9 +277,9 @@ public abstract class SnmpMibTable extends SnmpMibNode // each varbind involved (nb: should not happen, the error // should have been registered earlier) if (isnew) { - SnmpVarBind var = null; - for (Enumeration e= r.getElements(); e.hasMoreElements();) { - var = (SnmpVarBind) e.nextElement(); + SnmpVarBind var; + for (Enumeration e= r.getElements(); e.hasMoreElements();) { + var = e.nextElement(); r.registerGetException(var,noSuchInstanceException); } } @@ -329,6 +330,7 @@ public abstract class SnmpMibTable extends SnmpMibNode *

* */ + @Override public void check(SnmpMibSubRequest req, int depth) throws SnmpStatusException { final SnmpOid oid = req.getEntryOid(); @@ -389,6 +391,7 @@ public abstract class SnmpMibTable extends SnmpMibNode *

* */ + @Override public void set(SnmpMibSubRequest req, int depth) throws SnmpStatusException { @@ -755,6 +758,7 @@ public abstract class SnmpMibTable extends SnmpMibNode * * @exception IllegalArgumentException Listener parameter is null. */ + @Override public synchronized void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) { @@ -768,13 +772,11 @@ public abstract class SnmpMibTable extends SnmpMibNode // looking for listener in handbackTable // - Vector handbackList = - handbackTable.get(listener) ; - Vector filterList = - filterTable.get(listener) ; + Vector handbackList = handbackTable.get(listener) ; + Vector filterList = filterTable.get(listener) ; if ( handbackList == null ) { - handbackList = new Vector() ; - filterList = new Vector() ; + handbackList = new Vector<>() ; + filterList = new Vector<>() ; handbackTable.put(listener, handbackList) ; filterTable.put(listener, filterList) ; } @@ -797,16 +799,14 @@ public abstract class SnmpMibTable extends SnmpMibNode * @exception ListenerNotFoundException The listener is not registered * in the MBean. */ + @Override public synchronized void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException { // looking for listener in handbackTable // - java.util.Vector handbackList = - (java.util.Vector) handbackTable.get(listener) ; - java.util.Vector filterList = - (java.util.Vector) filterTable.get(listener) ; + java.util.Vector handbackList = handbackTable.get(listener) ; if ( handbackList == null ) { throw new ListenerNotFoundException("listener"); } @@ -822,6 +822,7 @@ public abstract class SnmpMibTable extends SnmpMibNode * notification class and the notification type sent by the * SnmpMibTable. */ + @Override public MBeanNotificationInfo[] getNotificationInfo() { String[] types = {SnmpTableEntryNotification.SNMP_ENTRY_ADDED, @@ -1813,9 +1814,9 @@ public abstract class SnmpMibTable extends SnmpMibNode // // --------------------------------------------------------------------- - final static void checkRowStatusFail(SnmpMibSubRequest req, - int errorStatus) + static void checkRowStatusFail(SnmpMibSubRequest req, int errorStatus) throws SnmpStatusException { + final SnmpVarBind statusvb = req.getRowStatusVarBind(); final SnmpStatusException x = new SnmpStatusException(errorStatus); req.registerCheckException(statusvb,x); @@ -1827,9 +1828,9 @@ public abstract class SnmpMibTable extends SnmpMibNode // // --------------------------------------------------------------------- - final static void setRowStatusFail(SnmpMibSubRequest req, - int errorStatus) + static void setRowStatusFail(SnmpMibSubRequest req, int errorStatus) throws SnmpStatusException { + final SnmpVarBind statusvb = req.getRowStatusVarBind(); final SnmpStatusException x = new SnmpStatusException(errorStatus); req.registerSetException(statusvb,x); @@ -1840,6 +1841,7 @@ public abstract class SnmpMibTable extends SnmpMibNode // Implements the method defined in SnmpMibNode. // // --------------------------------------------------------------------- + @Override final synchronized void findHandlingNode(SnmpVarBind varbind, long[] oid, int depth, SnmpRequestTree handlers) @@ -1909,11 +1911,15 @@ public abstract class SnmpMibTable extends SnmpMibNode // largely inspired from the original getNext() method. // // --------------------------------------------------------------------- + @Override final synchronized long[] findNextHandlingNode(SnmpVarBind varbind, - long[] oid, int pos, int depth, - SnmpRequestTree handlers, - AcmChecker checker) + long[] oid, + int pos, + int depth, + SnmpRequestTree handlers, + AcmChecker checker) throws SnmpStatusException { + int length = oid.length; if (handlers == null) @@ -1974,7 +1980,7 @@ public abstract class SnmpMibTable extends SnmpMibNode } // Now that we've got everything right we can begin. - SnmpOid entryoid = null ; + SnmpOid entryoid; if (pos == (length - 1)) { // pos points to the last arc in the oid, and this arc is @@ -2200,28 +2206,25 @@ public abstract class SnmpMibTable extends SnmpMibNode // loop on listener // - for(java.util.Enumeration k = handbackTable.keys(); + for(java.util.Enumeration k = handbackTable.keys(); k.hasMoreElements(); ) { - NotificationListener listener = - (NotificationListener) k.nextElement(); + NotificationListener listener = k.nextElement(); // Get the associated handback list and the associated filter list // - java.util.Vector handbackList = - (java.util.Vector) handbackTable.get(listener) ; - java.util.Vector filterList = - (java.util.Vector) filterTable.get(listener) ; + java.util.Vector handbackList = handbackTable.get(listener) ; + java.util.Vector filterList = + filterTable.get(listener) ; // loop on handback // - java.util.Enumeration f = filterList.elements(); - for(java.util.Enumeration h = handbackList.elements(); + java.util.Enumeration f = filterList.elements(); + for(java.util.Enumeration h = handbackList.elements(); h.hasMoreElements(); ) { Object handback = h.nextElement(); - NotificationFilter filter = - (NotificationFilter)f.nextElement(); + NotificationFilter filter = f.nextElement(); if ((filter == null) || (filter.isNotificationEnabled(notification))) { @@ -2300,7 +2303,7 @@ public abstract class SnmpMibTable extends SnmpMibNode * OID was not found. * **/ - private final int findObject(SnmpOid oid) { + private int findObject(SnmpOid oid) { int low= 0; int max= size - 1; SnmpOid pos; @@ -2332,25 +2335,6 @@ public abstract class SnmpMibTable extends SnmpMibNode return -1; } - /** - * Search the position at which the given oid should be inserted - * in the OID table (tableoids). - * - *

- * @param oid The OID we would like to insert. - * - * @return The position at which the OID should be inserted in - * the table. - * - * @exception SnmpStatusException if the OID is already present in the - * table. - * - **/ - private final int getInsertionPoint(SnmpOid oid) - throws SnmpStatusException { - return getInsertionPoint(oid, true); - } - /** * Search the position at which the given oid should be inserted * in the OID table (tableoids). @@ -2371,7 +2355,7 @@ public abstract class SnmpMibTable extends SnmpMibNode * table and fail is true. * **/ - private final int getInsertionPoint(SnmpOid oid, boolean fail) + private int getInsertionPoint(SnmpOid oid, boolean fail) throws SnmpStatusException { final int failStatus = SnmpStatusException.snmpRspNotWritable; @@ -2413,7 +2397,7 @@ public abstract class SnmpMibTable extends SnmpMibNode * @param pos The position at which the OID to be removed is located. * **/ - private final void removeOid(int pos) { + private void removeOid(int pos) { if (pos >= tablecount) return; if (pos < 0) return; final int l1 = --tablecount-pos; @@ -2431,7 +2415,7 @@ public abstract class SnmpMibTable extends SnmpMibNode * @param pos The position at which the OID to be added is located. * **/ - private final void insertOid(int pos, SnmpOid oid) { + private void insertOid(int pos, SnmpOid oid) { if (pos >= tablesize || tablecount == tablesize) { // Vector must be enlarged @@ -2534,13 +2518,13 @@ public abstract class SnmpMibTable extends SnmpMibNode * The list of entries. * @serial */ - private final Vector entries= new Vector(); + private final Vector entries= new Vector<>(); /** * The list of object names. * @serial */ - private final Vector entrynames= new Vector(); + private final Vector entrynames= new Vector<>(); /** * Callback handlers @@ -2548,17 +2532,16 @@ public abstract class SnmpMibTable extends SnmpMibNode // final Vector callbacks = new Vector(); /** - * Listener hastable containing the hand-back objects. + * Listener hashtable containing the hand-back objects. */ private Hashtable> handbackTable = - new Hashtable>(); + new Hashtable<>(); /** - * Listener hastable containing the filter objects. + * Listener hashtable containing the filter objects. */ private Hashtable> - filterTable = - new Hashtable>(); + filterTable = new Hashtable<>(); // PACKAGE VARIABLES //------------------ diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpRequestTree.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpRequestTree.java index c401a73f77e..dbcca12d9ef 100644 --- a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpRequestTree.java +++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpRequestTree.java @@ -25,11 +25,9 @@ package com.sun.jmx.snmp.agent; import java.util.Vector; -import java.util.ArrayList; import java.util.Hashtable; import java.util.Enumeration; import java.util.Iterator; -import java.util.List; import java.util.NoSuchElementException; import java.util.Arrays; import java.util.logging.Level; @@ -77,7 +75,7 @@ final class SnmpRequestTree { this.request = req; this.version = req.getVersion(); this.creationflag = creationflag; - this.hashtable = new Hashtable(); + this.hashtable = new Hashtable<>(); setPduType(pdutype); } @@ -191,7 +189,7 @@ final class SnmpRequestTree { // SnmSubRequest associated with an Handler node. //------------------------------------------------------------------- - static final class Enum implements Enumeration { + static final class Enum implements Enumeration { Enum(SnmpRequestTree hlist,Handler h) { handler = h; this.hlist = hlist; @@ -203,11 +201,13 @@ final class SnmpRequestTree { private int iter = 0; private int size = 0; + @Override public boolean hasMoreElements() { return iter < size; } - public Object nextElement() throws NoSuchElementException { + @Override + public SnmpMibSubRequest nextElement() throws NoSuchElementException { if (iter == 0) { if (handler.sublist != null) { iter++; @@ -216,7 +216,7 @@ final class SnmpRequestTree { } iter ++; if (iter > size) throw new NoSuchElementException(); - Object result = hlist.getSubRequest(handler,entry); + SnmpMibSubRequest result = hlist.getSubRequest(handler,entry); entry++; return result; } @@ -252,7 +252,8 @@ final class SnmpRequestTree { // Implements the method defined in SnmpMibRequest interface. // See SnmpMibRequest for the java doc. // ------------------------------------------------------------- - public Enumeration getElements() { + @Override + public Enumeration getElements() { return varbinds.elements(); } @@ -260,6 +261,7 @@ final class SnmpRequestTree { // Implements the method defined in SnmpMibRequest interface. // See SnmpMibRequest for the java doc. // ------------------------------------------------------------- + @Override public Vector getSubList() { return varbinds; } @@ -268,6 +270,7 @@ final class SnmpRequestTree { // Implements the method defined in SnmpMibRequest interface. // See SnmpMibRequest for the java doc. // ------------------------------------------------------------- + @Override public final int getSize() { if (varbinds == null) return 0; return varbinds.size(); @@ -277,6 +280,7 @@ final class SnmpRequestTree { // Implements the method defined in SnmpMibRequest interface. // See SnmpMibRequest for the java doc. // ------------------------------------------------------------- + @Override public void addVarBind(SnmpVarBind varbind) { // XXX not sure we must also add the varbind in the global // request? or whether we should raise an exception: @@ -289,6 +293,7 @@ final class SnmpRequestTree { // Implements the method defined in SnmpMibSubRequest interface. // See SnmpMibSubRequest for the java doc. // ------------------------------------------------------------- + @Override public boolean isNewEntry() { return isnew; } @@ -297,6 +302,7 @@ final class SnmpRequestTree { // Implements the method defined in SnmpMibSubRequest interface. // See SnmpMibSubRequest for the java doc. // ------------------------------------------------------------- + @Override public SnmpOid getEntryOid() { return entryoid; } @@ -305,6 +311,7 @@ final class SnmpRequestTree { // Implements the method defined in SnmpMibRequest interface. // See SnmpMibRequest for the java doc. // ------------------------------------------------------------- + @Override public int getVarIndex(SnmpVarBind varbind) { if (varbind == null) return 0; return global.getVarIndex(varbind); @@ -314,6 +321,7 @@ final class SnmpRequestTree { // Implements the method defined in SnmpMibRequest interface. // See SnmpMibRequest for the java doc. // ------------------------------------------------------------- + @Override public Object getUserData() { return global.getUserData(); } @@ -322,6 +330,7 @@ final class SnmpRequestTree { // See SnmpMibSubRequest for the java doc. // ------------------------------------------------------------- + @Override public void registerGetException(SnmpVarBind var, SnmpStatusException exception) throws SnmpStatusException { @@ -364,6 +373,7 @@ final class SnmpRequestTree { // Implements the method defined in SnmpMibSubRequest interface. // See SnmpMibSubRequest for the java doc. // ------------------------------------------------------------- + @Override public void registerSetException(SnmpVarBind var, SnmpStatusException exception) throws SnmpStatusException { @@ -387,6 +397,7 @@ final class SnmpRequestTree { // Implements the method defined in SnmpMibSubRequest interface. // See SnmpMibSubRequest for the java doc. // ------------------------------------------------------------- + @Override public void registerCheckException(SnmpVarBind var, SnmpStatusException exception) throws SnmpStatusException { @@ -410,42 +421,52 @@ final class SnmpRequestTree { // Implements the method defined in SnmpMibRequest interface. // See SnmpMibRequest for the java doc. // ------------------------------------------------------------- + @Override public int getVersion() { return version; } + @Override public SnmpVarBind getRowStatusVarBind() { return statusvb; } + @Override public SnmpPdu getPdu() { return global.getPdu(); } + @Override public int getRequestPduVersion() { return global.getRequestPduVersion(); } + @Override public SnmpEngine getEngine() { return global.getEngine(); } + @Override public String getPrincipal() { return global.getPrincipal(); } + @Override public int getSecurityLevel() { return global.getSecurityLevel(); } + @Override public int getSecurityModel() { return global.getSecurityModel(); } + @Override public byte[] getContextName() { return global.getContextName(); } + @Override public byte[] getAccessContextName() { return global.getAccessContextName(); } @@ -485,7 +506,7 @@ final class SnmpRequestTree { * Adds a varbind in this node sublist. */ public void addVarbind(SnmpVarBind varbind) { - if (sublist == null) sublist = new Vector(); + if (sublist == null) sublist = new Vector<>(); sublist.addElement(varbind); } @@ -503,7 +524,7 @@ final class SnmpRequestTree { // Vectors are null: Allocate new vectors entryoids = new SnmpOid[Delta]; - entrylists = new Vector[Delta]; + entrylists = (Vector[])new Vector[Delta]; isentrynew = new boolean[Delta]; rowstatus = new SnmpVarBind[Delta]; entrysize = Delta; @@ -521,7 +542,7 @@ final class SnmpRequestTree { // Allocate larger vectors entrysize += Delta; entryoids = new SnmpOid[entrysize]; - entrylists = new Vector[entrysize]; + entrylists = (Vector[])new Vector[entrysize]; isentrynew = new boolean[entrysize]; rowstatus = new SnmpVarBind[entrysize]; @@ -595,7 +616,7 @@ final class SnmpRequestTree { // entryoids = new ArrayList(); // entrylists = new ArrayList(); // isentrynew = new ArrayList(); - v = new Vector(); + v = new Vector<>(); // entryoids.add(entryoid); // entrylists.add(v); // isentrynew.add(new Boolean(isnew)); @@ -614,7 +635,7 @@ final class SnmpRequestTree { // if (pos == -1 || pos >= entrycount ) { // pos = getInsertionPoint(entryoids,entryoid); // pos = getInsertionPoint(entryoids,entrycount,entryoid); - v = new Vector(); + v = new Vector<>(); // entryoids.add(pos,entryoid); // entrylists.add(pos,v); // isentrynew.add(pos,new Boolean(isnew)); @@ -775,7 +796,7 @@ final class SnmpRequestTree { // If it is a table, there will be one subrequest per entry involved. //------------------------------------------------------------------- - public Enumeration getSubRequests(Handler handler) { + public Enumeration getSubRequests(Handler handler) { return new Enum(this,handler); } @@ -783,7 +804,7 @@ final class SnmpRequestTree { // returns an enumeration of the Handlers stored in the Hashtable. //------------------------------------------------------------------- - public Enumeration getHandlers() { + public Enumeration getHandlers() { return hashtable.elements(); } @@ -1048,7 +1069,6 @@ final class SnmpRequestTree { handler.addVarbind(varbind); else handler.addVarbind(varbind,entryoid,isnew,statusvb); - return ; } diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpStandardObjectServer.java b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpStandardObjectServer.java index 5b2fbcfbb04..f0369468126 100644 --- a/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpStandardObjectServer.java +++ b/jdk/src/share/classes/com/sun/jmx/snmp/agent/SnmpStandardObjectServer.java @@ -27,14 +27,7 @@ package com.sun.jmx.snmp.agent; // java imports // import java.io.Serializable; -import java.util.Hashtable; import java.util.Enumeration; -import java.util.Vector; - -// jmx imports -// -import com.sun.jmx.snmp.SnmpOid; -import com.sun.jmx.snmp.SnmpValue; import com.sun.jmx.snmp.SnmpVarBind; import com.sun.jmx.snmp.SnmpStatusException; @@ -121,8 +114,8 @@ public class SnmpStandardObjectServer implements Serializable { final Object data = req.getUserData(); - for (Enumeration e= req.getElements(); e.hasMoreElements();) { - final SnmpVarBind var= (SnmpVarBind) e.nextElement(); + for (Enumeration e= req.getElements(); e.hasMoreElements();) { + final SnmpVarBind var= e.nextElement(); try { final long id = var.oid.getOidArc(depth); var.value = meta.get(id, data); @@ -182,9 +175,8 @@ public class SnmpStandardObjectServer implements Serializable { final Object data = req.getUserData(); - for (Enumeration e= req.getElements(); e.hasMoreElements();) { - SnmpVarBind var = null; - var = (SnmpVarBind) e.nextElement(); + for (Enumeration e= req.getElements(); e.hasMoreElements();) { + SnmpVarBind var = e.nextElement(); try { // This method will generate a SnmpStatusException // if `depth' is out of bounds. @@ -248,8 +240,8 @@ public class SnmpStandardObjectServer implements Serializable { final Object data = req.getUserData(); - for (Enumeration e= req.getElements(); e.hasMoreElements();) { - final SnmpVarBind var = (SnmpVarBind) e.nextElement(); + for (Enumeration e= req.getElements(); e.hasMoreElements();) { + final SnmpVarBind var = e.nextElement(); try { // This method will generate a SnmpStatusException // if `depth' is out of bounds. diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/daemon/CommunicatorServer.java b/jdk/src/share/classes/com/sun/jmx/snmp/daemon/CommunicatorServer.java index 4b576b60fa2..b2634d8eee1 100644 --- a/jdk/src/share/classes/com/sun/jmx/snmp/daemon/CommunicatorServer.java +++ b/jdk/src/share/classes/com/sun/jmx/snmp/daemon/CommunicatorServer.java @@ -33,7 +33,6 @@ package com.sun.jmx.snmp.daemon; import java.io.ObjectInputStream; import java.io.IOException; import java.net.InetAddress; -import java.util.Enumeration; import java.util.logging.Level; import java.util.Vector; import java.util.NoSuchElementException; @@ -50,8 +49,6 @@ import javax.management.NotificationBroadcasterSupport; import javax.management.MBeanNotificationInfo; import javax.management.AttributeChangeNotification; import javax.management.ListenerNotFoundException; -import javax.management.loading.ClassLoaderRepository; -import javax.management.MBeanServerFactory; import static com.sun.jmx.defaults.JmxProperties.SNMP_ADAPTOR_LOGGER; @@ -225,9 +222,8 @@ public abstract class CommunicatorServer private transient Object stateLock = new Object(); private transient Vector - clientHandlerVector = new Vector() ; + clientHandlerVector = new Vector<>() ; - private transient Thread fatherThread = Thread.currentThread() ; private transient Thread mainThread = null ; private volatile boolean stopRequested = false ; @@ -328,6 +324,7 @@ public abstract class CommunicatorServer * Has no effect if this CommunicatorServer is * ONLINE or STOPPING. */ + @Override public void start() { try { start(0); @@ -346,6 +343,7 @@ public abstract class CommunicatorServer * Has no effect if this CommunicatorServer is * OFFLINE or STOPPING. */ + @Override public void stop() { synchronized (stateLock) { if (state == OFFLINE || state == STOPPING) { @@ -393,6 +391,7 @@ public abstract class CommunicatorServer * * @return True if connector is ONLINE; false otherwise. */ + @Override public boolean isActive() { synchronized (stateLock) { return (state == ONLINE); @@ -431,6 +430,7 @@ public abstract class CommunicatorServer * @return true if the value of this MBean's State attribute is the * same as the wantedState parameter; false otherwise. */ + @Override public boolean waitState(int wantedState, long timeOut) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, @@ -595,6 +595,7 @@ public abstract class CommunicatorServer * @return ONLINE, OFFLINE, * STARTING or STOPPING. */ + @Override public int getState() { synchronized (stateLock) { return state ; @@ -607,6 +608,7 @@ public abstract class CommunicatorServer * @return One of the strings "ONLINE", "OFFLINE", "STARTING" or * "STOPPING". */ + @Override public String getStateString() { return getStringForState(state) ; } @@ -616,6 +618,7 @@ public abstract class CommunicatorServer * * @return The host name used by this CommunicatorServer. */ + @Override public String getHost() { try { host = InetAddress.getLocalHost().getHostName(); @@ -630,6 +633,7 @@ public abstract class CommunicatorServer * * @return The port number used by this CommunicatorServer. */ + @Override public int getPort() { synchronized (stateLock) { return port ; @@ -645,6 +649,7 @@ public abstract class CommunicatorServer * @exception java.lang.IllegalStateException This method has been invoked * while the communicator was ONLINE or STARTING. */ + @Override public void setPort(int port) throws java.lang.IllegalStateException { synchronized (stateLock) { if ((state == ONLINE) || (state == STARTING)) @@ -659,7 +664,8 @@ public abstract class CommunicatorServer * Gets the protocol being used by this CommunicatorServer. * @return The protocol as a string. */ - public abstract String getProtocol() ; + @Override + public abstract String getProtocol(); /** * Gets the number of clients that have been processed by this @@ -754,6 +760,7 @@ public abstract class CommunicatorServer *

* The run method executed by this connector's main thread. */ + @Override public void run() { // Fix jaw.00667.B @@ -851,7 +858,7 @@ public abstract class CommunicatorServer } finally { synchronized (stateLock) { interrupted = true; - Thread.currentThread().interrupted(); + Thread.interrupted(); } // ---------------------- @@ -970,7 +977,7 @@ public abstract class CommunicatorServer "MBeanServer argument must be MBean server where this " + "server is registered, or an MBeanServerForwarder " + "leading to that server"; - Vector seenMBS = new Vector(); + Vector seenMBS = new Vector<>(); for (MBeanServer mbs = newMBS; mbs != bottomMBS; mbs = ((MBeanServerForwarder) mbs).getMBeanServer()) { @@ -1153,8 +1160,7 @@ public abstract class CommunicatorServer state = OFFLINE; stopRequested = false; servedClientCount = 0; - clientHandlerVector = new Vector(); - fatherThread = Thread.currentThread(); + clientHandlerVector = new Vector<>(); mainThread = null; notifCount = 0; notifInfos = null; @@ -1184,6 +1190,7 @@ public abstract class CommunicatorServer * * @exception IllegalArgumentException Listener parameter is null. */ + @Override public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) @@ -1207,6 +1214,7 @@ public abstract class CommunicatorServer * * @exception ListenerNotFoundException The listener is not registered. */ + @Override public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException { @@ -1225,6 +1233,7 @@ public abstract class CommunicatorServer * sent when the State attribute of this CommunicatorServer * changes. */ + @Override public MBeanNotificationInfo[] getNotificationInfo() { // Initialize notifInfos on first call to getNotificationInfo() @@ -1304,6 +1313,7 @@ public abstract class CommunicatorServer * the MBeanServer and re-thrown * as an MBeanRegistrationException. */ + @Override public ObjectName preRegister(MBeanServer server, ObjectName name) throws java.lang.Exception { objectName = name; @@ -1325,6 +1335,7 @@ public abstract class CommunicatorServer * successfully registered in the MBeanServer. * The value false means that the registration phase has failed. */ + @Override public void postRegister(Boolean registrationDone) { if (!registrationDone.booleanValue()) { synchronized (this) { @@ -1340,6 +1351,7 @@ public abstract class CommunicatorServer * the MBeanServer and re-thrown * as an MBeanRegistrationException. */ + @Override public void preDeregister() throws java.lang.Exception { synchronized (this) { topMBS = bottomMBS = null; @@ -1354,22 +1366,8 @@ public abstract class CommunicatorServer /** * Do nothing. */ + @Override public void postDeregister(){ } - /** - * Load a class using the default loader repository - **/ - Class loadClass(String className) - throws ClassNotFoundException { - try { - return Class.forName(className); - } catch (ClassNotFoundException e) { - final ClassLoaderRepository clr = - MBeanServerFactory.getClassLoaderRepository(bottomMBS); - if (clr == null) throw new ClassNotFoundException(className); - return clr.loadClass(className); - } - } - } diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/daemon/SnmpAdaptorServer.java b/jdk/src/share/classes/com/sun/jmx/snmp/daemon/SnmpAdaptorServer.java index 03822a091fa..612d4c57437 100644 --- a/jdk/src/share/classes/com/sun/jmx/snmp/daemon/SnmpAdaptorServer.java +++ b/jdk/src/share/classes/com/sun/jmx/snmp/daemon/SnmpAdaptorServer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -47,7 +47,6 @@ import java.io.InterruptedIOException; import javax.management.MBeanServer; import javax.management.MBeanRegistration; import javax.management.ObjectName; -import javax.management.InstanceAlreadyExistsException; import static com.sun.jmx.defaults.JmxProperties.SNMP_ADAPTOR_LOGGER; import com.sun.jmx.snmp.SnmpIpAddress; import com.sun.jmx.snmp.SnmpMessage; @@ -157,7 +156,7 @@ public class SnmpAdaptorServer extends CommunicatorServer /** * The IP address based ACL used by this SNMP protocol adaptor. */ - private Object ipacl = null; + private InetAddressAcl ipacl = null; /** * The factory object. @@ -199,7 +198,7 @@ public class SnmpAdaptorServer extends CommunicatorServer transient DatagramSocket trapSocket = null; private transient SnmpSession informSession = null; private transient DatagramPacket packet = null; - transient Vector mibs = new Vector(); + transient Vector mibs = new Vector<>(); private transient SnmpMibTree root; /** @@ -482,8 +481,7 @@ public class SnmpAdaptorServer extends CommunicatorServer // if (acl == null && forceAcl) { try { - acl = (InetAddressAcl) - new SnmpAcl("SNMP protocol adaptor IP ACL"); + acl = new SnmpAcl("SNMP protocol adaptor IP ACL"); } catch (UnknownHostException e) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, @@ -508,6 +506,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * since its creation. This counter is not reset by the stop * method. */ + @Override public int getServedClientCount() { return super.getServedClientCount(); } @@ -519,6 +518,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * @return The number of managers currently being processed by this * SNMP protocol adaptor. */ + @Override public int getActiveClientCount() { return super.getActiveClientCount(); } @@ -530,6 +530,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * @return The maximum number of managers that this SNMP protocol adaptor * can process concurrently. */ + @Override public int getMaxActiveClientCount() { return super.getMaxActiveClientCount(); } @@ -543,6 +544,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * @exception java.lang.IllegalStateException This method has been invoked * while the communicator was ONLINE or STARTING. */ + @Override public void setMaxActiveClientCount(int c) throws java.lang.IllegalStateException { super.setMaxActiveClientCount(c); @@ -554,8 +556,9 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @since 1.5 */ + @Override public InetAddressAcl getInetAddressAcl() { - return (InetAddressAcl)ipacl; + return ipacl; } /** @@ -564,6 +567,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @return The port number for sending SNMP traps. */ + @Override public Integer getTrapPort() { return new Integer(trapPort) ; } @@ -573,6 +577,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @param port The port number for sending SNMP traps. */ + @Override public void setTrapPort(Integer port) { setTrapPort(port.intValue()); } @@ -595,6 +600,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @return The port number for sending SNMP inform requests. */ + @Override public int getInformPort() { return informPort; } @@ -605,6 +611,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @param port The port number for sending SNMP inform requests. */ + @Override public void setInformPort(int port) { if (port < 0) throw new IllegalArgumentException("Inform request port "+ @@ -617,6 +624,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @return The string "snmp". */ + @Override public String getProtocol() { return "snmp"; } @@ -629,6 +637,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @return The buffer size. */ + @Override public Integer getBufferSize() { return new Integer(bufferSize) ; } @@ -643,6 +652,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * @exception java.lang.IllegalStateException This method has been invoked * while the communicator was ONLINE or STARTING. */ + @Override public void setBufferSize(Integer s) throws java.lang.IllegalStateException { if ((state == ONLINE) || (state == STARTING)) { @@ -658,6 +668,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * By default, a maximum of 3 tries is used. * @return The maximun number of tries. */ + @Override final public int getMaxTries() { return maxTries; } @@ -667,6 +678,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * request before giving up. * @param newMaxTries The maximun number of tries. */ + @Override final public synchronized void setMaxTries(int newMaxTries) { if (newMaxTries < 0) throw new IllegalArgumentException(); @@ -678,6 +690,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * By default, a timeout of 3 seconds is used. * @return The value of the timeout property. */ + @Override final public int getTimeout() { return timeout; } @@ -686,6 +699,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * Changes the timeout to wait for an inform response from the manager. * @param newTimeout The timeout (in milliseconds). */ + @Override final public synchronized void setTimeout(int newTimeout) { if (newTimeout < 0) throw new IllegalArgumentException(); @@ -697,6 +711,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @return The factory object. */ + @Override public SnmpPduFactory getPduFactory() { return pduFactory ; } @@ -706,6 +721,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @param factory The factory object (null means the default factory). */ + @Override public void setPduFactory(SnmpPduFactory factory) { if (factory == null) pduFactory = new SnmpPduFactoryBER() ; @@ -719,6 +735,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * @param factory The factory object (null means no factory). * @see com.sun.jmx.snmp.agent.SnmpUserDataFactory */ + @Override public void setUserDataFactory(SnmpUserDataFactory factory) { userDataFactory = factory ; } @@ -729,6 +746,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * @return The factory object (null means no factory). * @see com.sun.jmx.snmp.agent.SnmpUserDataFactory */ + @Override public SnmpUserDataFactory getUserDataFactory() { return userDataFactory; } @@ -745,6 +763,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * @return true if authentication traps are enabled, * false otherwise. */ + @Override public boolean getAuthTrapEnabled() { return authTrapEnabled ; } @@ -755,6 +774,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @param enabled Flag indicating if traps need to be sent. */ + @Override public void setAuthTrapEnabled(boolean enabled) { authTrapEnabled = enabled ; } @@ -772,6 +792,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @return true if responses are sent. */ + @Override public boolean getAuthRespEnabled() { return authRespEnabled ; } @@ -782,6 +803,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @param enabled Flag indicating if responses need to be sent. */ + @Override public void setAuthRespEnabled(boolean enabled) { authRespEnabled = enabled ; } @@ -793,6 +815,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @return The OID in string format "x.x.x.x". */ + @Override public String getEnterpriseOid() { return enterpriseOid.toString() ; } @@ -804,6 +827,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @exception IllegalArgumentException The string format is incorrect */ + @Override public void setEnterpriseOid(String oid) throws IllegalArgumentException { enterpriseOid = new SnmpOid(oid) ; } @@ -813,11 +837,12 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @return An array of MIB names. */ + @Override public String[] getMibs() { String[] result = new String[mibs.size()] ; int i = 0 ; - for (Enumeration e = mibs.elements() ; e.hasMoreElements() ;) { - SnmpMibAgent mib = (SnmpMibAgent)e.nextElement() ; + for (Enumeration e = mibs.elements() ; e.hasMoreElements() ;) { + SnmpMibAgent mib = e.nextElement() ; result[i++] = mib.getMibName(); } return result ; @@ -831,6 +856,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @return The snmpOutTraps value. */ + @Override public Long getSnmpOutTraps() { return new Long(snmpOutTraps); } @@ -840,6 +866,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @return The snmpOutGetResponses value. */ + @Override public Long getSnmpOutGetResponses() { return new Long(snmpOutGetResponses); } @@ -849,6 +876,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @return The snmpOutGenErrs value. */ + @Override public Long getSnmpOutGenErrs() { return new Long(snmpOutGenErrs); } @@ -858,6 +886,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @return The snmpOutBadValues value. */ + @Override public Long getSnmpOutBadValues() { return new Long(snmpOutBadValues); } @@ -867,6 +896,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @return The snmpOutNoSuchNames value. */ + @Override public Long getSnmpOutNoSuchNames() { return new Long(snmpOutNoSuchNames); } @@ -876,6 +906,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @return The snmpOutTooBigs value. */ + @Override public Long getSnmpOutTooBigs() { return new Long(snmpOutTooBigs); } @@ -885,6 +916,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @return The snmpInASNParseErrs value. */ + @Override public Long getSnmpInASNParseErrs() { return new Long(snmpInASNParseErrs); } @@ -894,6 +926,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @return The snmpInBadCommunityUses value. */ + @Override public Long getSnmpInBadCommunityUses() { return new Long(snmpInBadCommunityUses); } @@ -904,6 +937,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @return The snmpInBadCommunityNames value. */ + @Override public Long getSnmpInBadCommunityNames() { return new Long(snmpInBadCommunityNames); } @@ -913,6 +947,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @return The snmpInBadVersions value. */ + @Override public Long getSnmpInBadVersions() { return new Long(snmpInBadVersions); } @@ -922,6 +957,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @return The snmpOutPkts value. */ + @Override public Long getSnmpOutPkts() { return new Long(snmpOutPkts); } @@ -931,6 +967,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @return The snmpInPkts value. */ + @Override public Long getSnmpInPkts() { return new Long(snmpInPkts); } @@ -940,6 +977,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @return The snmpInGetRequests value. */ + @Override public Long getSnmpInGetRequests() { return new Long(snmpInGetRequests); } @@ -949,6 +987,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @return The snmpInGetNexts value. */ + @Override public Long getSnmpInGetNexts() { return new Long(snmpInGetNexts); } @@ -958,6 +997,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @return The snmpInSetRequests value. */ + @Override public Long getSnmpInSetRequests() { return new Long(snmpInSetRequests); } @@ -967,6 +1007,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @return The snmpInTotalSetVars value. */ + @Override public Long getSnmpInTotalSetVars() { return new Long(snmpInTotalSetVars); } @@ -976,6 +1017,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @return The snmpInTotalReqVars value. */ + @Override public Long getSnmpInTotalReqVars() { return new Long(snmpInTotalReqVars); } @@ -988,6 +1030,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @since 1.5 */ + @Override public Long getSnmpSilentDrops() { return new Long(snmpSilentDrops); } @@ -1000,6 +1043,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @since 1.5 */ + @Override public Long getSnmpProxyDrops() { return new Long(0); } @@ -1027,6 +1071,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @exception java.lang.Exception */ + @Override public ObjectName preRegister(MBeanServer server, ObjectName name) throws java.lang.Exception { @@ -1040,6 +1085,7 @@ public class SnmpAdaptorServer extends CommunicatorServer /** * Not used in this context. */ + @Override public void postRegister (Boolean registrationDone) { super.postRegister(registrationDone); } @@ -1047,6 +1093,7 @@ public class SnmpAdaptorServer extends CommunicatorServer /** * Not used in this context. */ + @Override public void preDeregister() throws java.lang.Exception { super.preDeregister(); } @@ -1054,6 +1101,7 @@ public class SnmpAdaptorServer extends CommunicatorServer /** * Not used in this context. */ + @Override public void postDeregister() { super.postDeregister(); } @@ -1067,6 +1115,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @exception IllegalArgumentException If the parameter is null. */ + @Override public SnmpMibHandler addMib(SnmpMibAgent mib) throws IllegalArgumentException { if (mib == null) { @@ -1097,6 +1146,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @since 1.5 */ + @Override public SnmpMibHandler addMib(SnmpMibAgent mib, SnmpOid[] oids) throws IllegalArgumentException { if (mib == null) { @@ -1129,6 +1179,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @since 1.5 */ + @Override public SnmpMibHandler addMib(SnmpMibAgent mib, String contextName) throws IllegalArgumentException { return addMib(mib); @@ -1150,10 +1201,12 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @since 1.5 */ + @Override public SnmpMibHandler addMib(SnmpMibAgent mib, String contextName, SnmpOid[] oids) throws IllegalArgumentException { + return addMib(mib, oids); } @@ -1171,6 +1224,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @since 1.5 */ + @Override public boolean removeMib(SnmpMibAgent mib, String contextName) { return removeMib(mib); } @@ -1183,6 +1237,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * @return true if the specified mib was a MIB * included in the SNMP MIB handler, false otherwise. */ + @Override public boolean removeMib(SnmpMibAgent mib) { root.unregister(mib); return (mibs.removeElement(mib)) ; @@ -1199,6 +1254,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @since 1.5 */ + @Override public boolean removeMib(SnmpMibAgent mib, SnmpOid[] oids) { root.unregister(mib, oids); return (mibs.removeElement(mib)) ; @@ -1216,6 +1272,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @since 1.5 */ + @Override public boolean removeMib(SnmpMibAgent mib, String contextName, SnmpOid[] oids) { @@ -1228,6 +1285,7 @@ public class SnmpAdaptorServer extends CommunicatorServer /** * Creates the datagram socket. */ + @Override protected void doBind() throws CommunicationException, InterruptedException { @@ -1255,6 +1313,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * that port number was 0. * @return the actual port to which the adaptor is bound. **/ + @Override public int getPort() { synchronized (this) { if (socket != null) return socket.getLocalPort(); @@ -1265,6 +1324,7 @@ public class SnmpAdaptorServer extends CommunicatorServer /** * Closes the datagram socket. */ + @Override protected void doUnbind() throws CommunicationException, InterruptedException { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { @@ -1282,12 +1342,17 @@ public class SnmpAdaptorServer extends CommunicatorServer closeInformSocketIfNeeded() ; } - void createSnmpRequestHandler(SnmpAdaptorServer server, int id, - DatagramSocket s, DatagramPacket p, - SnmpMibTree tree, Vector m, Object a, - SnmpPduFactory factory, - SnmpUserDataFactory dataFactory, - MBeanServer f, ObjectName n) { + private void createSnmpRequestHandler(SnmpAdaptorServer server, + int id, + DatagramSocket s, + DatagramPacket p, + SnmpMibTree tree, + Vector m, + InetAddressAcl a, + SnmpPduFactory factory, + SnmpUserDataFactory dataFactory, + MBeanServer f, + ObjectName n) { final SnmpRequestHandler handler = new SnmpRequestHandler(this, id, s, p, tree, m, a, factory, dataFactory, f, n); @@ -1298,6 +1363,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * Reads a packet from the datagram socket and creates a request * handler which decodes and processes the request. */ + @Override protected void doReceive() throws CommunicationException, InterruptedException { @@ -1339,13 +1405,14 @@ public class SnmpAdaptorServer extends CommunicatorServer } } + @Override protected void doError(Exception e) throws CommunicationException { - return; } /** * Not used in this context. */ + @Override protected void doProcess() throws CommunicationException, InterruptedException { } @@ -1357,6 +1424,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * We attempt only once... * @return 1 **/ + @Override protected int getBindTries() { return 1; } @@ -1368,6 +1436,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * Has no effect if this SNMP protocol adaptor is OFFLINE or * STOPPING. */ + @Override public void stop(){ final int port = getPort(); @@ -1424,6 +1493,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * @exception SnmpStatusException If the trap exceeds the limit defined * by bufferSize. */ + @Override public void snmpV1Trap(int generic, int specific, SnmpVarBindList varBindList) throws IOException, SnmpStatusException { @@ -1499,6 +1569,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * @exception SnmpStatusException If the trap exceeds the limit defined * by bufferSize. */ + @Override public void snmpV1Trap(InetAddress addr, String cs, int generic, int specific, SnmpVarBindList varBindList) throws IOException, SnmpStatusException { @@ -1617,6 +1688,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @since 1.5 */ + @Override public void snmpV1Trap(SnmpPeer peer, SnmpIpAddress agentAddr, SnmpOid enterpOid, @@ -1625,6 +1697,7 @@ public class SnmpAdaptorServer extends CommunicatorServer SnmpVarBindList varBindList, SnmpTimeticks time) throws IOException, SnmpStatusException { + SnmpParameters p = (SnmpParameters) peer.getParams(); snmpV1Trap(peer.getDestAddr(), peer.getDestPort(), @@ -1745,11 +1818,13 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @since 1.5 */ + @Override public void snmpV2Trap(SnmpPeer peer, SnmpOid trapOid, SnmpVarBindList varBindList, SnmpTimeticks time) throws IOException, SnmpStatusException { + SnmpParameters p = (SnmpParameters) peer.getParams(); snmpV2Trap(peer.getDestAddr(), peer.getDestPort(), @@ -1781,6 +1856,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * @exception SnmpStatusException If the trap exceeds the limit defined * by bufferSize. */ + @Override public void snmpV2Trap(SnmpOid trapOid, SnmpVarBindList varBindList) throws IOException, SnmpStatusException { @@ -1801,7 +1877,7 @@ public class SnmpAdaptorServer extends CommunicatorServer SnmpVarBindList fullVbl ; if (varBindList != null) - fullVbl = (SnmpVarBindList)varBindList.clone() ; + fullVbl = varBindList.clone() ; else fullVbl = new SnmpVarBindList(2) ; SnmpTimeticks sysUpTimeValue = new SnmpTimeticks(getSysUpTime()) ; @@ -1840,6 +1916,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * @exception SnmpStatusException If the trap exceeds the limit * defined by bufferSize. */ + @Override public void snmpV2Trap(InetAddress addr, String cs, SnmpOid trapOid, SnmpVarBindList varBindList) throws IOException, SnmpStatusException { @@ -1865,7 +1942,7 @@ public class SnmpAdaptorServer extends CommunicatorServer SnmpVarBindList fullVbl ; if (varBindList != null) - fullVbl = (SnmpVarBindList)varBindList.clone() ; + fullVbl = varBindList.clone() ; else fullVbl = new SnmpVarBindList(2) ; SnmpTimeticks sysUpTimeValue = new SnmpTimeticks(getSysUpTime()) ; @@ -1964,12 +2041,12 @@ public class SnmpAdaptorServer extends CommunicatorServer SnmpVarBindList fullVbl ; if (varBindList != null) - fullVbl = (SnmpVarBindList)varBindList.clone() ; + fullVbl = varBindList.clone() ; else fullVbl = new SnmpVarBindList(2) ; // Only difference with other - SnmpTimeticks sysUpTimeValue = null; + SnmpTimeticks sysUpTimeValue; if(time != null) sysUpTimeValue = time; else @@ -2002,6 +2079,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @since 1.5 */ + @Override public void snmpPduTrap(InetAddress address, SnmpPduPacket pdu) throws IOException, SnmpStatusException { @@ -2021,6 +2099,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * by bufferSize. * @since 1.5 */ + @Override public void snmpPduTrap(SnmpPeer peer, SnmpPduPacket pdu) throws IOException, SnmpStatusException { @@ -2066,13 +2145,12 @@ public class SnmpAdaptorServer extends CommunicatorServer int sendingCount = 0 ; openTrapSocketIfNeeded() ; if (ipacl != null) { - Enumeration ed = ((InetAddressAcl)ipacl).getTrapDestinations() ; + Enumeration ed = ipacl.getTrapDestinations() ; while (ed.hasMoreElements()) { - msg.address = (InetAddress)ed.nextElement() ; - Enumeration ec = ((InetAddressAcl)ipacl). - getTrapCommunities(msg.address) ; + msg.address = ed.nextElement() ; + Enumeration ec = ipacl.getTrapCommunities(msg.address) ; while (ec.hasMoreElements()) { - msg.community = ((String)ec.nextElement()).getBytes() ; + msg.community = ec.nextElement().getBytes() ; try { sendTrapMessage(msg) ; sendingCount++ ; @@ -2164,6 +2242,7 @@ public class SnmpAdaptorServer extends CommunicatorServer */ private void sendTrapMessage(SnmpMessage msg) throws IOException, SnmpTooBigException { + byte[] buffer = new byte[bufferSize] ; DatagramPacket packet = new DatagramPacket(buffer, buffer.length) ; int encodingLength = msg.encodeMessage(buffer) ; @@ -2245,8 +2324,10 @@ public class SnmpAdaptorServer extends CommunicatorServer * @exception SnmpStatusException If the inform request exceeds the * limit defined by bufferSize. */ - public Vector snmpInformRequest(SnmpInformHandler cb, SnmpOid trapOid, - SnmpVarBindList varBindList) + @Override + public Vector snmpInformRequest(SnmpInformHandler cb, + SnmpOid trapOid, + SnmpVarBindList varBindList) throws IllegalStateException, IOException, SnmpStatusException { if (!isActive()) { @@ -2263,7 +2344,7 @@ public class SnmpAdaptorServer extends CommunicatorServer // SnmpVarBindList fullVbl ; if (varBindList != null) - fullVbl = (SnmpVarBindList)varBindList.clone() ; + fullVbl = varBindList.clone() ; else fullVbl = new SnmpVarBindList(2) ; SnmpTimeticks sysUpTimeValue = new SnmpTimeticks(getSysUpTime()) ; @@ -2277,17 +2358,16 @@ public class SnmpAdaptorServer extends CommunicatorServer // Now send the SNMP message to each destination // - Vector informReqList = new Vector(); - InetAddress addr = null; - String cs = null; + Vector informReqList = new Vector<>(); + InetAddress addr; + String cs; if (ipacl != null) { - Enumeration ed = ((InetAddressAcl)ipacl).getInformDestinations() ; + Enumeration ed = ipacl.getInformDestinations() ; while (ed.hasMoreElements()) { - addr = (InetAddress)ed.nextElement() ; - Enumeration ec = ((InetAddressAcl)ipacl). - getInformCommunities(addr) ; + addr = ed.nextElement() ; + Enumeration ec = ipacl.getInformCommunities(addr) ; while (ec.hasMoreElements()) { - cs = (String)ec.nextElement() ; + cs = ec.nextElement() ; informReqList.addElement( informSession.makeAsyncRequest(addr, cs, cb, fullVbl,getInformPort())) ; @@ -2330,6 +2410,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * @exception SnmpStatusException If the inform request exceeds the * limit defined by bufferSize. */ + @Override public SnmpInformRequest snmpInformRequest(InetAddress addr, String cs, SnmpInformHandler cb, @@ -2380,11 +2461,13 @@ public class SnmpAdaptorServer extends CommunicatorServer * * @since 1.5 */ + @Override public SnmpInformRequest snmpInformRequest(SnmpPeer peer, SnmpInformHandler cb, SnmpOid trapOid, SnmpVarBindList varBindList) throws IllegalStateException, IOException, SnmpStatusException { + SnmpParameters p = (SnmpParameters) peer.getParams(); return snmpInformRequest(peer.getDestAddr(), peer.getDestPort(), @@ -2401,9 +2484,9 @@ public class SnmpAdaptorServer extends CommunicatorServer * @param protocolVersion The protocol version. * @param reqPduType The pdu type. */ - public static final int mapErrorStatus(int errorStatus, - int protocolVersion, - int reqPduType) { + public static int mapErrorStatus(int errorStatus, + int protocolVersion, + int reqPduType) { return SnmpSubRequestHandler.mapErrorStatus(errorStatus, protocolVersion, reqPduType); @@ -2416,6 +2499,7 @@ public class SnmpAdaptorServer extends CommunicatorServer SnmpOid trapOid, SnmpVarBindList varBindList) throws IllegalStateException, IOException, SnmpStatusException { + if (!isActive()) { throw new IllegalStateException( "Start SNMP adaptor server before carrying out this operation"); @@ -2430,7 +2514,7 @@ public class SnmpAdaptorServer extends CommunicatorServer // SnmpVarBindList fullVbl ; if (varBindList != null) - fullVbl = (SnmpVarBindList)varBindList.clone() ; + fullVbl = varBindList.clone() ; else fullVbl = new SnmpVarBindList(2) ; SnmpTimeticks sysUpTimeValue = new SnmpTimeticks(getSysUpTime()) ; @@ -2489,6 +2573,7 @@ public class SnmpAdaptorServer extends CommunicatorServer * references to the object. *

Closes the datagram socket associated to this SNMP protocol adaptor. */ + @Override protected void finalize() { try { if (socket != null) { @@ -2511,6 +2596,7 @@ public class SnmpAdaptorServer extends CommunicatorServer /** * Returns the string used in debug traces. */ + @Override String makeDebugTag() { return "SnmpAdaptorServer["+ getProtocol() + ":" + getPort() + "]"; } @@ -2615,13 +2701,13 @@ public class SnmpAdaptorServer extends CommunicatorServer // This is for transient structures to be initialized to specific // default values. // - mibs = new Vector() ; + mibs = new Vector<>() ; } /** * Common initializations. */ - private void init(Object acl, int p, InetAddress a) { + private void init(InetAddressAcl acl, int p, InetAddress a) { root= new SnmpMibTree(); @@ -2650,6 +2736,7 @@ public class SnmpAdaptorServer extends CommunicatorServer return root.getAgentMib(oid); } + @Override protected Thread createMainThread() { final Thread t = super.createMainThread(); t.setDaemon(true); diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/daemon/SnmpAdaptorServerMBean.java b/jdk/src/share/classes/com/sun/jmx/snmp/daemon/SnmpAdaptorServerMBean.java index e2d86b68a36..1b42ed4f043 100644 --- a/jdk/src/share/classes/com/sun/jmx/snmp/daemon/SnmpAdaptorServerMBean.java +++ b/jdk/src/share/classes/com/sun/jmx/snmp/daemon/SnmpAdaptorServerMBean.java @@ -140,6 +140,7 @@ public interface SnmpAdaptorServerMBean extends CommunicatorServerMBean { * * @return The string "snmp". */ + @Override public String getProtocol(); /** @@ -636,7 +637,8 @@ public interface SnmpAdaptorServerMBean extends CommunicatorServerMBean { * @exception IOException An I/O error occurred while sending the inform request. * @exception SnmpStatusException If the inform request exceeds the limit defined by bufferSize. */ - public Vector snmpInformRequest(SnmpInformHandler cb, SnmpOid trapOid, SnmpVarBindList varBindList) + public Vector snmpInformRequest(SnmpInformHandler cb, SnmpOid trapOid, + SnmpVarBindList varBindList) throws IllegalStateException, IOException, SnmpStatusException; /** diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/daemon/SnmpMibTree.java b/jdk/src/share/classes/com/sun/jmx/snmp/daemon/SnmpMibTree.java index 66fe5f8a313..c6f67700f48 100644 --- a/jdk/src/share/classes/com/sun/jmx/snmp/daemon/SnmpMibTree.java +++ b/jdk/src/share/classes/com/sun/jmx/snmp/daemon/SnmpMibTree.java @@ -125,7 +125,7 @@ final class SnmpMibTree { TreeNode node= retrieveChild(oid, cursor); if (node == null) return this; - if (children.size() == 0) { + if (children.isEmpty()) { // In this case, the node does not have any children. So no point to // continue the search ... return node; @@ -149,24 +149,24 @@ final class SnmpMibTree { public void printTree(String ident) { - StringBuffer buff= new StringBuffer(); + StringBuilder buff= new StringBuilder(); if (agents == null) { return; } - for(Enumeration e= agents.elements(); e.hasMoreElements(); ) { - SnmpMibAgent mib= (SnmpMibAgent) e.nextElement(); + for(Enumeration e= agents.elements(); e.hasMoreElements(); ) { + SnmpMibAgent mib= e.nextElement(); if (mib == null) buff.append("empty "); else - buff.append(mib.getMibName() + " "); + buff.append(mib.getMibName()).append(" "); } ident+= " "; if (children == null) { return; } - for(Enumeration e= children.elements(); e.hasMoreElements(); ) { - TreeNode node= (TreeNode) e.nextElement(); + for(Enumeration e= children.elements(); e.hasMoreElements(); ) { + TreeNode node= e.nextElement(); node.printTree(ident); } } @@ -185,7 +185,7 @@ final class SnmpMibTree { } private void removeAgentFully(SnmpMibAgent agent) { - Vector v = new Vector(); + Vector v = new Vector<>(); for(Enumeration e= children.elements(); e.hasMoreElements(); ) { @@ -212,9 +212,9 @@ final class SnmpMibTree { } - private void setAgent(SnmpMibAgent agent) { - this.agent = agent; - } + private void setAgent(SnmpMibAgent agent) { + this.agent = agent; + } private void registerNode(long[] oid, int cursor, SnmpMibAgent agent) { @@ -247,20 +247,20 @@ final class SnmpMibTree { private TreeNode retrieveChild(long[] oid, int current) { long theValue= oid[current]; - for(Enumeration e= children.elements(); e.hasMoreElements(); ) { - TreeNode node= (TreeNode) e.nextElement(); + for(Enumeration e= children.elements(); e.hasMoreElements(); ) { + TreeNode node= e.nextElement(); if (node.match(theValue)) return node; } return null; } - final private boolean match(long value) { + private boolean match(long value) { return (nodeValue == value) ? true : false; } - private Vector children= new Vector(); - private Vector agents= new Vector(); + private Vector children= new Vector<>(); + private Vector agents= new Vector<>(); private long nodeValue; private SnmpMibAgent agent; private TreeNode parent; diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/daemon/SnmpRequestHandler.java b/jdk/src/share/classes/com/sun/jmx/snmp/daemon/SnmpRequestHandler.java index f56b189b48e..0b60e802270 100644 --- a/jdk/src/share/classes/com/sun/jmx/snmp/daemon/SnmpRequestHandler.java +++ b/jdk/src/share/classes/com/sun/jmx/snmp/daemon/SnmpRequestHandler.java @@ -71,9 +71,9 @@ import com.sun.jmx.snmp.InetAddressAcl; class SnmpRequestHandler extends ClientHandler implements SnmpDefinitions { - private transient DatagramSocket socket = null ; - private transient DatagramPacket packet = null ; - private transient Vector mibs = null ; + private transient DatagramSocket socket = null ; + private transient DatagramPacket packet = null ; + private transient Vector mibs = null ; /** * Contains the list of sub-requests associated to the current request. @@ -85,7 +85,7 @@ class SnmpRequestHandler extends ClientHandler implements SnmpDefinitions { */ private transient SnmpMibTree root; - private transient Object ipacl = null ; + private transient InetAddressAcl ipacl = null ; private transient SnmpPduFactory pduFactory = null ; private transient SnmpUserDataFactory userDataFactory = null ; private transient SnmpAdaptorServer adaptor = null; @@ -94,7 +94,8 @@ class SnmpRequestHandler extends ClientHandler implements SnmpDefinitions { */ public SnmpRequestHandler(SnmpAdaptorServer server, int id, DatagramSocket s, DatagramPacket p, - SnmpMibTree tree, Vector m, Object a, + SnmpMibTree tree, Vector m, + InetAddressAcl a, SnmpPduFactory factory, SnmpUserDataFactory dataFactory, MBeanServer f, ObjectName n) @@ -108,8 +109,8 @@ class SnmpRequestHandler extends ClientHandler implements SnmpDefinitions { socket = s; packet = p; root= tree; - mibs = (Vector) m.clone(); - subs= new Hashtable(mibs.size()); + mibs = new Vector<>(m); + subs= new Hashtable<>(mibs.size()); ipacl = a; pduFactory = factory ; userDataFactory = dataFactory ; @@ -121,6 +122,7 @@ class SnmpRequestHandler extends ClientHandler implements SnmpDefinitions { * back to the client. * Note: we overwrite 'packet' with the response bytes. */ + @Override public void doRun() { // Trace the input packet @@ -243,7 +245,7 @@ class SnmpRequestHandler extends ClientHandler implements SnmpDefinitions { // Transform the request message into a request pdu // - SnmpPduPacket reqPdu = null ; + SnmpPduPacket reqPdu; Object userData = null; try { reqPdu = (SnmpPduPacket)pduFactory.decodeSnmpPdu(reqMsg) ; @@ -306,7 +308,7 @@ class SnmpRequestHandler extends ClientHandler implements SnmpDefinitions { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "makeResponseMessage", "fail on element" + pos); } - int old= 0; + int old; while (true) { try { respPdu = reduceResponsePdu(reqPdu, respPdu, pos) ; @@ -580,20 +582,18 @@ class SnmpRequestHandler extends ClientHandler implements SnmpDefinitions { Object userData) { int errorStatus = SnmpDefinitions.snmpRspNoError ; - int nbSubRequest= subs.size(); - int i=0; + int i; // If it's a set request, we must first check any varBind // if (req.type == pduSetRequestPdu) { i=0; - for(Enumeration e= subs.elements(); e.hasMoreElements() ; i++) { + for(Enumeration e= subs.elements(); e.hasMoreElements() ; i++) { // Indicate to the sub request that a check must be invoked ... // OK we should have defined out own tag for that ! // - SnmpSubRequestHandler sub= (SnmpSubRequestHandler) - e.nextElement(); + SnmpSubRequestHandler sub= e.nextElement(); sub.setUserData(userData); sub.type= pduWalkRequest; @@ -618,8 +618,8 @@ class SnmpRequestHandler extends ClientHandler implements SnmpDefinitions { // Let's start the sub-requests. // i=0; - for(Enumeration e= subs.elements(); e.hasMoreElements() ;i++) { - SnmpSubRequestHandler sub= (SnmpSubRequestHandler) e.nextElement(); + for(Enumeration e= subs.elements(); e.hasMoreElements() ;i++) { + SnmpSubRequestHandler sub= e.nextElement(); /* NPCTE fix for bugId 4492741, esc 0, 16-August 2001 */ sub.setUserData(userData); /* end of NPCTE fix for bugId 4492741 */ @@ -650,7 +650,7 @@ class SnmpRequestHandler extends ClientHandler implements SnmpDefinitions { private SnmpPduPacket turboProcessingGetSet(SnmpPduRequest req, Object userData) { - int errorStatus = SnmpDefinitions.snmpRspNoError ; + int errorStatus; SnmpSubRequestHandler sub = subs.elements().nextElement(); sub.setUserData(userData); @@ -707,7 +707,7 @@ class SnmpRequestHandler extends ClientHandler implements SnmpDefinitions { private SnmpPduPacket makeGetBulkResponsePdu(SnmpPduBulk req, Object userData) { - SnmpVarBind[] respVarBindList = null ; + SnmpVarBind[] respVarBindList; // RFC 1905, Section 4.2.3, p14 int L = req.varBindList.length ; @@ -761,7 +761,7 @@ class SnmpRequestHandler extends ClientHandler implements SnmpDefinitions { */ private boolean checkPduType(SnmpPduPacket pdu) { - boolean result = true ; + boolean result; switch(pdu.type) { @@ -798,8 +798,7 @@ class SnmpRequestHandler extends ClientHandler implements SnmpDefinitions { // if (ipacl != null) { if (pdu.type == SnmpDefinitions.pduSetRequestPdu) { - if (!((InetAddressAcl)ipacl). - checkWritePermission(pdu.address, community)) { + if (!ipacl.checkWritePermission(pdu.address, community)) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, "checkAcl", "sender is " + pdu.address + @@ -820,7 +819,7 @@ class SnmpRequestHandler extends ClientHandler implements SnmpDefinitions { } } else { - if (!((InetAddressAcl)ipacl).checkReadPermission(pdu.address, community)) { + if (!ipacl.checkReadPermission(pdu.address, community)) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, "checkAcl", "sender is " + pdu.address + @@ -854,7 +853,7 @@ class SnmpRequestHandler extends ClientHandler implements SnmpDefinitions { if (response != null) { SnmpAdaptorServer snmpServer = (SnmpAdaptorServer)adaptorServer ; snmpServer.incSnmpInBadCommunityUses(1) ; - if (((InetAddressAcl)ipacl).checkCommunity(community) == false) + if (ipacl.checkCommunity(community) == false) snmpServer.incSnmpInBadCommunityNames(1) ; } @@ -873,7 +872,7 @@ class SnmpRequestHandler extends ClientHandler implements SnmpDefinitions { result.port = reqPdu.port ; result.version = reqPdu.version ; result.community = reqPdu.community ; - result.type = result.pduGetResponsePdu ; + result.type = SnmpPduRequest.pduGetResponsePdu ; result.requestId = reqPdu.requestId ; result.errorStatus = SnmpDefinitions.snmpRspNoError ; result.errorIndex = 0 ; @@ -904,7 +903,7 @@ class SnmpRequestHandler extends ClientHandler implements SnmpDefinitions { private SnmpMessage newTooBigMessage(SnmpMessage reqMsg) throws SnmpTooBigException { SnmpMessage result = null ; - SnmpPduPacket reqPdu = null ; + SnmpPduPacket reqPdu; try { reqPdu = (SnmpPduPacket)pduFactory.decodeSnmpPdu(reqMsg) ; @@ -941,7 +940,7 @@ class SnmpRequestHandler extends ClientHandler implements SnmpDefinitions { // Reduction can be attempted only on bulk response // - if (req.type != req.pduGetBulkRequestPdu) { + if (req.type != SnmpPduPacket.pduGetBulkRequestPdu) { if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "reduceResponsePdu", "cannot remove anything"); @@ -961,7 +960,7 @@ class SnmpRequestHandler extends ClientHandler implements SnmpDefinitions { // * when it is 0 (in fact, acceptedVbCount is not available), // we split the varbindlist by 2. // - int vbCount = resp.varBindList.length ; + int vbCount; if (acceptedVbCount >= 3) vbCount = Math.min(acceptedVbCount - 1, resp.varBindList.length) ; else if (acceptedVbCount == 1) @@ -998,7 +997,7 @@ class SnmpRequestHandler extends ClientHandler implements SnmpDefinitions { private void splitRequest(SnmpPduRequest req) { int nbAgents= mibs.size(); - SnmpMibAgent agent= (SnmpMibAgent) mibs.firstElement(); + SnmpMibAgent agent = mibs.firstElement(); if (nbAgents == 1) { // Take all the oids contained in the request and // @@ -1010,8 +1009,8 @@ class SnmpRequestHandler extends ClientHandler implements SnmpDefinitions { // to all agents // if (req.type == pduGetNextRequestPdu) { - for(Enumeration e= mibs.elements(); e.hasMoreElements(); ) { - SnmpMibAgent ag= (SnmpMibAgent) e.nextElement(); + for(Enumeration e= mibs.elements(); e.hasMoreElements(); ) { + final SnmpMibAgent ag= e.nextElement(); subs.put(ag, new SnmpSubNextRequestHandler(adaptor, ag, req)); } return; @@ -1047,8 +1046,8 @@ class SnmpRequestHandler extends ClientHandler implements SnmpDefinitions { int R) { // Send the getBulk to all agents // - for(Enumeration e= mibs.elements(); e.hasMoreElements(); ) { - SnmpMibAgent agent = (SnmpMibAgent) e.nextElement(); + for(Enumeration e= mibs.elements(); e.hasMoreElements(); ) { + final SnmpMibAgent agent = e.nextElement(); if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, @@ -1064,7 +1063,6 @@ class SnmpRequestHandler extends ClientHandler implements SnmpDefinitions { maxRepetitions, R)); } - return; } private SnmpPduPacket mergeResponses(SnmpPduRequest req) { @@ -1078,8 +1076,8 @@ class SnmpRequestHandler extends ClientHandler implements SnmpDefinitions { // Go through the list of subrequests and concatenate. // Hopefully, by now all the sub-requests should be finished // - for(Enumeration e= subs.elements(); e.hasMoreElements();) { - SnmpSubRequestHandler sub= (SnmpSubRequestHandler) e.nextElement(); + for(Enumeration e= subs.elements(); e.hasMoreElements();) { + SnmpSubRequestHandler sub= e.nextElement(); sub.updateResult(result); } return newValidResponsePdu(req,result); @@ -1092,8 +1090,8 @@ class SnmpRequestHandler extends ClientHandler implements SnmpDefinitions { // Go through the list of subrequests and concatenate. // Hopefully, by now all the sub-requests should be finished // - for(Enumeration e= subs.elements(); e.hasMoreElements();) { - SnmpSubRequestHandler sub= (SnmpSubRequestHandler) e.nextElement(); + for(Enumeration e= subs.elements(); e.hasMoreElements();) { + SnmpSubRequestHandler sub= e.nextElement(); sub.updateResult(result); } @@ -1127,19 +1125,21 @@ class SnmpRequestHandler extends ClientHandler implements SnmpDefinitions { // Go through the list of subrequests and concatenate. // Hopefully, by now all the sub-requests should be finished // - for(Enumeration e= subs.elements(); e.hasMoreElements();) { - SnmpSubRequestHandler sub= (SnmpSubRequestHandler) e.nextElement(); + for(Enumeration e= subs.elements(); e.hasMoreElements();) { + SnmpSubRequestHandler sub= e.nextElement(); sub.updateResult(result); } return result; } + @Override protected String makeDebugTag() { return "SnmpRequestHandler[" + adaptorServer.getProtocol() + ":" + adaptorServer.getPort() + "]"; } + @Override Thread createThread(Runnable r) { return null; } diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/daemon/SnmpSubBulkRequestHandler.java b/jdk/src/share/classes/com/sun/jmx/snmp/daemon/SnmpSubBulkRequestHandler.java index f662e374fbe..2754975082f 100644 --- a/jdk/src/share/classes/com/sun/jmx/snmp/daemon/SnmpSubBulkRequestHandler.java +++ b/jdk/src/share/classes/com/sun/jmx/snmp/daemon/SnmpSubBulkRequestHandler.java @@ -31,7 +31,6 @@ package com.sun.jmx.snmp.daemon; // java import // import java.util.Enumeration; -import java.util.Vector; import java.util.logging.Level; // jmx imports // @@ -46,9 +45,6 @@ import com.sun.jmx.snmp.SnmpEngine; // import static com.sun.jmx.defaults.JmxProperties.SNMP_ADAPTOR_LOGGER; import com.sun.jmx.snmp.agent.SnmpMibAgent; -import com.sun.jmx.snmp.agent.SnmpMibRequest; -import com.sun.jmx.snmp.ThreadContext; -import com.sun.jmx.snmp.daemon.SnmpAdaptorServer; import com.sun.jmx.snmp.internal.SnmpIncomingRequest; import com.sun.jmx.snmp.ThreadContext; @@ -85,6 +81,7 @@ class SnmpSubBulkRequestHandler extends SnmpSubRequestHandler { init(server, req, nonRepeat, maxRepeat, R); } + @Override public void run() { size= varBind.size(); @@ -259,11 +256,12 @@ class SnmpSubBulkRequestHandler extends SnmpSubRequestHandler { * successful. As such the method getErrorIndex or getErrorStatus should be * called. */ + @Override protected void updateResult(SnmpVarBind[] result) { // we can assume that the run method is over ... // - final Enumeration e= varBind.elements(); + final Enumeration e= varBind.elements(); final int max= result.length; // First go through all the values once ... @@ -284,7 +282,7 @@ class SnmpSubBulkRequestHandler extends SnmpSubRequestHandler { continue; } - final SnmpVarBind element= (SnmpVarBind) e.nextElement(); + final SnmpVarBind element= e.nextElement(); if (element == null) continue; if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { @@ -309,7 +307,7 @@ class SnmpSubBulkRequestHandler extends SnmpSubRequestHandler { return; if (e.hasMoreElements() ==false) return; - final SnmpVarBind element= (SnmpVarBind) e.nextElement(); + final SnmpVarBind element= e.nextElement(); if (element == null) continue; if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/defaults/SnmpProperties.java b/jdk/src/share/classes/com/sun/jmx/snmp/defaults/SnmpProperties.java index 675c15b32aa..f17c68208d5 100644 --- a/jdk/src/share/classes/com/sun/jmx/snmp/defaults/SnmpProperties.java +++ b/jdk/src/share/classes/com/sun/jmx/snmp/defaults/SnmpProperties.java @@ -60,7 +60,7 @@ public class SnmpProperties { InputStream is = new FileInputStream(file); props.load(is); is.close(); - for (final Enumeration e = props.keys(); e.hasMoreElements() ; ) { + for (final Enumeration e = props.keys(); e.hasMoreElements() ; ) { final String key = (String) e.nextElement(); System.setProperty(key,props.getProperty(key)); } diff --git a/jdk/src/share/classes/com/sun/jmx/snmp/tasks/ThreadService.java b/jdk/src/share/classes/com/sun/jmx/snmp/tasks/ThreadService.java index b1c053448bd..6b45ee36072 100644 --- a/jdk/src/share/classes/com/sun/jmx/snmp/tasks/ThreadService.java +++ b/jdk/src/share/classes/com/sun/jmx/snmp/tasks/ThreadService.java @@ -199,7 +199,7 @@ public class ThreadService implements TaskServer { // re-init this.setPriority(priority); - this.interrupted(); + Thread.interrupted(); this.setContextClassLoader(cloader); } } diff --git a/jdk/src/share/classes/com/sun/net/ssl/KeyManagerFactory.java b/jdk/src/share/classes/com/sun/net/ssl/KeyManagerFactory.java index 36041d804d1..30e941a89d5 100644 --- a/jdk/src/share/classes/com/sun/net/ssl/KeyManagerFactory.java +++ b/jdk/src/share/classes/com/sun/net/ssl/KeyManagerFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -53,12 +53,13 @@ public class KeyManagerFactory { /** *

The default KeyManager can be changed by setting the value of the - * "sun.ssl.keymanager.type" security property (in the Java security - * properties file) to the desired name. + * {@code sun.ssl.keymanager.type} security property to the desired name. * - * @return the default type as specified in the - * Java security properties file, or an implementation-specific default - * if no such property exists. + * @return the default type as specified by the + * {@code sun.ssl.keymanager.type} security property, or an + * implementation-specific default if no such property exists. + * + * @see java.security.Security security properties */ public final static String getDefaultAlgorithm() { String type; diff --git a/jdk/src/share/classes/com/sun/net/ssl/SSLPermission.java b/jdk/src/share/classes/com/sun/net/ssl/SSLPermission.java index 101dcc7af6c..2bf9233051b 100644 --- a/jdk/src/share/classes/com/sun/net/ssl/SSLPermission.java +++ b/jdk/src/share/classes/com/sun/net/ssl/SSLPermission.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -46,8 +46,8 @@ import java.lang.SecurityManager; * convention follows the hierarchical property naming convention. * Also, an asterisk * may appear at the end of the name, following a ".", or by itself, to - * signify a wildcard match. For example: "foo.*" or "*" is valid, - * "*foo" or "a*b" is not valid. + * signify a wildcard match. For example: "foo.*" and "*" signify a wildcard + * match, while "*foo" and "a*b" do not. *

* The following table lists all the possible SSLPermission target names, * and for each provides a description of what the permission allows diff --git a/jdk/src/share/classes/com/sun/net/ssl/TrustManagerFactory.java b/jdk/src/share/classes/com/sun/net/ssl/TrustManagerFactory.java index e3e9b64b6b5..b9ef566a0e7 100644 --- a/jdk/src/share/classes/com/sun/net/ssl/TrustManagerFactory.java +++ b/jdk/src/share/classes/com/sun/net/ssl/TrustManagerFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -53,12 +53,13 @@ public class TrustManagerFactory { /** *

The default TrustManager can be changed by setting the value of the - * "sun.ssl.trustmanager.type" security property - * (in the Java security properties file) to the desired name. + * {@code sun.ssl.trustmanager.type} security property to the desired name. * - * @return the default type as specified in the - * Java security properties file, or an implementation-specific default - * if no such property exists. + * @return the default type as specified by the + * {@code sun.ssl.trustmanager.type} security property, or an + * implementation-specific default if no such property exists. + * + * @see java.security.Security security properties */ public final static String getDefaultAlgorithm() { String type; diff --git a/jdk/src/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java b/jdk/src/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java index 8824f8c0f0a..db14e424b29 100644 --- a/jdk/src/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java +++ b/jdk/src/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java @@ -264,7 +264,7 @@ public class CachedRowSetWriter implements TransactionalWriter, Serializable { * false otherwise */ public boolean writeData(RowSetInternal caller) throws SQLException { - boolean conflict = false; + long conflicts = 0; boolean showDel = false; PreparedStatement pstmtIns = null; iChangedValsInDbAndCRS = 0; @@ -337,8 +337,9 @@ public class CachedRowSetWriter implements TransactionalWriter, Serializable { while (crs.next()) { if (crs.rowDeleted()) { // The row has been deleted. - if (conflict = (deleteOriginalRow(crs, this.crsResolve)) == true) { + if (deleteOriginalRow(crs, this.crsResolve)) { status.add(rows, SyncResolver.DELETE_ROW_CONFLICT); + conflicts++; } else { // delete happened without any occurrence of conflicts // so update status accordingly @@ -349,8 +350,9 @@ public class CachedRowSetWriter implements TransactionalWriter, Serializable { // The row has been inserted. pstmtIns = con.prepareStatement(insertCmd); - if ( (conflict = insertNewRow(crs, pstmtIns, this.crsResolve)) == true) { + if (insertNewRow(crs, pstmtIns, this.crsResolve)) { status.add(rows, SyncResolver.INSERT_ROW_CONFLICT); + conflicts++; } else { // insert happened without any occurrence of conflicts // so update status accordingly @@ -358,8 +360,9 @@ public class CachedRowSetWriter implements TransactionalWriter, Serializable { } } else if (crs.rowUpdated()) { // The row has been updated. - if ( conflict = (updateOriginalRow(crs)) == true) { + if (updateOriginalRow(crs)) { status.add(rows, SyncResolver.UPDATE_ROW_CONFLICT); + conflicts++; } else { // update happened without any occurrence of conflicts // so update status accordingly @@ -395,21 +398,12 @@ public class CachedRowSetWriter implements TransactionalWriter, Serializable { // reset crs.setShowDeleted(showDel); - boolean boolConf = false; - for (int j=1;j *

  • - * Loop through the java.security.Security properties, + * Loop through the security properties, * auth.policy.url.1, auth.policy.url.2, ..., - * auth.policy.url.X". These properties are set - * in the Java security properties file, which is located in the file named - * <JAVA_HOME>/lib/security/java.security. - * <JAVA_HOME> refers to the value of the java.home system property, - * and specifies the directory where the JRE is installed. + * auth.policy.url.X". * Each property value specifies a URL pointing to a * policy file to be loaded. Read in and load each policy. * @@ -235,6 +231,7 @@ import sun.security.util.PropertyExpander; * @see java.security.CodeSource * @see java.security.Permissions * @see java.security.ProtectionDomain + * @see java.security.Security security properties */ @Deprecated public class PolicyFile extends javax.security.auth.Policy { diff --git a/jdk/src/share/classes/com/sun/security/auth/login/ConfigFile.java b/jdk/src/share/classes/com/sun/security/auth/login/ConfigFile.java index c4b3acdc834..8299b13f0bb 100644 --- a/jdk/src/share/classes/com/sun/security/auth/login/ConfigFile.java +++ b/jdk/src/share/classes/com/sun/security/auth/login/ConfigFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -49,13 +49,9 @@ import sun.security.util.PropertyExpander; * *
      *
    1. - * Loop through the java.security.Security properties, + * Loop through the security properties, * login.config.url.1, login.config.url.2, ..., - * login.config.url.X. These properties are set - * in the Java security properties file, which is located in the file named - * <JAVA_HOME>/lib/security/java.security. - * <JAVA_HOME> refers to the value of the java.home system property, - * and specifies the directory where the JRE is installed. + * login.config.url.X. * Each property value specifies a URL pointing to a * login configuration file to be loaded. Read in and load * each configuration. @@ -87,6 +83,7 @@ import sun.security.util.PropertyExpander; * javax.security.auth.login.Configuration class. * * @see javax.security.auth.login.LoginContext + * @see java.security.Security security properties */ public class ConfigFile extends javax.security.auth.login.Configuration { diff --git a/jdk/src/share/classes/com/sun/security/auth/module/Krb5LoginModule.java b/jdk/src/share/classes/com/sun/security/auth/module/Krb5LoginModule.java index 5779da791e5..3d1744ba172 100644 --- a/jdk/src/share/classes/com/sun/security/auth/module/Krb5LoginModule.java +++ b/jdk/src/share/classes/com/sun/security/auth/module/Krb5LoginModule.java @@ -1067,10 +1067,6 @@ public class Krb5LoginModule implements LoginModule { if (ktab != null) { if (!privCredSet.contains(ktab)) { privCredSet.add(ktab); - // Compatibility; also add keys to privCredSet - for (KerberosKey key: ktab.getKeys(kerbClientPrinc)) { - privCredSet.add(new Krb5Util.KeysFromKeyTab(key)); - } } } else { succeeded = false; diff --git a/jdk/src/share/classes/java/awt/color/ICC_Profile.java b/jdk/src/share/classes/java/awt/color/ICC_Profile.java index 6a785805b5a..321db6ca664 100644 --- a/jdk/src/share/classes/java/awt/color/ICC_Profile.java +++ b/jdk/src/share/classes/java/awt/color/ICC_Profile.java @@ -1435,7 +1435,15 @@ public class ICC_Profile implements Serializable { int renderingIntent = intFromBigEndian(theHeader, icHdrRenderingIntent); /* set the rendering intent */ - return renderingIntent; + + /* According to ICC spec, only the least-significant 16 bits shall be + * used to encode the rendering intent. The most significant 16 bits + * shall be set to zero. Thus, we are ignoring two most significant + * bytes here. + * + * See http://www.color.org/ICC1v42_2006-05.pdf, section 7.2.15. + */ + return (0xffff & renderingIntent); } diff --git a/jdk/src/share/classes/java/awt/image/ColorConvertOp.java b/jdk/src/share/classes/java/awt/image/ColorConvertOp.java index 3f25ebbefde..7ba11582be9 100644 --- a/jdk/src/share/classes/java/awt/image/ColorConvertOp.java +++ b/jdk/src/share/classes/java/awt/image/ColorConvertOp.java @@ -732,10 +732,16 @@ public class ColorConvertOp implements BufferedImageOp, RasterOp { private int getRenderingIntent (ICC_Profile profile) { byte[] header = profile.getData(ICC_Profile.icSigHead); int index = ICC_Profile.icHdrRenderingIntent; - return (((header[index] & 0xff) << 24) | - ((header[index+1] & 0xff) << 16) | - ((header[index+2] & 0xff) << 8) | - (header[index+3] & 0xff)); + + /* According to ICC spec, only the least-significant 16 bits shall be + * used to encode the rendering intent. The most significant 16 bits + * shall be set to zero. Thus, we are ignoring two most significant + * bytes here. + * + * See http://www.color.org/ICC1v42_2006-05.pdf, section 7.2.15. + */ + return ((header[index+2] & 0xff) << 8) | + (header[index+3] & 0xff); } /** diff --git a/jdk/src/share/classes/java/lang/AbstractStringBuilder.java b/jdk/src/share/classes/java/lang/AbstractStringBuilder.java index b87ebd73d9a..fc513f55efe 100644 --- a/jdk/src/share/classes/java/lang/AbstractStringBuilder.java +++ b/jdk/src/share/classes/java/lang/AbstractStringBuilder.java @@ -177,11 +177,10 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { ensureCapacityInternal(newLength); if (count < newLength) { - for (; count < newLength; count++) - value[count] = '\0'; - } else { - count = newLength; + Arrays.fill(value, count, newLength, '\0'); } + + count = newLength; } /** @@ -1308,8 +1307,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { * {@code null}. */ public int indexOf(String str, int fromIndex) { - return String.indexOf(value, 0, count, - str.toCharArray(), 0, str.length(), fromIndex); + return String.indexOf(value, 0, count, str, fromIndex); } /** @@ -1352,8 +1350,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { * {@code null}. */ public int lastIndexOf(String str, int fromIndex) { - return String.lastIndexOf(value, 0, count, - str.toCharArray(), 0, str.length(), fromIndex); + return String.lastIndexOf(value, 0, count, str, fromIndex); } /** diff --git a/jdk/src/share/classes/java/lang/Class.java b/jdk/src/share/classes/java/lang/Class.java index 2da316afbd3..17665ed7b28 100644 --- a/jdk/src/share/classes/java/lang/Class.java +++ b/jdk/src/share/classes/java/lang/Class.java @@ -48,6 +48,7 @@ import java.util.List; import java.util.Set; import java.util.Map; import java.util.HashMap; +import java.util.Objects; import sun.misc.Unsafe; import sun.reflect.ConstantPool; import sun.reflect.Reflection; @@ -3044,34 +3045,62 @@ public final * @throws NullPointerException {@inheritDoc} * @since 1.5 */ - @SuppressWarnings("unchecked") public A getAnnotation(Class annotationClass) { - if (annotationClass == null) - throw new NullPointerException(); + Objects.requireNonNull(annotationClass); initAnnotationsIfNecessary(); - return (A) annotations.get(annotationClass); + return AnnotationSupport.getOneAnnotation(annotations, annotationClass); } /** * @throws NullPointerException {@inheritDoc} * @since 1.5 */ - public boolean isAnnotationPresent( - Class annotationClass) { - if (annotationClass == null) - throw new NullPointerException(); + public boolean isAnnotationPresent(Class annotationClass) { + Objects.requireNonNull(annotationClass); return getAnnotation(annotationClass) != null; } + /** + * @throws NullPointerException {@inheritDoc} + * @since 1.8 + */ + public A[] getAnnotations(Class annotationClass) { + Objects.requireNonNull(annotationClass); + + initAnnotationsIfNecessary(); + return AnnotationSupport.getMultipleAnnotations(annotations, annotationClass); + } /** * @since 1.5 */ public Annotation[] getAnnotations() { initAnnotationsIfNecessary(); - return AnnotationParser.toArray(annotations); + return AnnotationSupport.unpackToArray(annotations); + } + + /** + * @throws NullPointerException {@inheritDoc} + * @since 1.8 + */ + public A getDeclaredAnnotation(Class annotationClass) { + Objects.requireNonNull(annotationClass); + + initAnnotationsIfNecessary(); + return AnnotationSupport.getOneAnnotation(declaredAnnotations, annotationClass); + } + + /** + * @throws NullPointerException {@inheritDoc} + * @since 1.8 + */ + public A[] getDeclaredAnnotations(Class annotationClass) { + Objects.requireNonNull(annotationClass); + + initAnnotationsIfNecessary(); + return AnnotationSupport.getMultipleAnnotations(declaredAnnotations, annotationClass); } /** @@ -3079,7 +3108,17 @@ public final */ public Annotation[] getDeclaredAnnotations() { initAnnotationsIfNecessary(); - return AnnotationParser.toArray(declaredAnnotations); + return AnnotationSupport.unpackToArray(declaredAnnotations); + } + + /** Returns one "directly" present annotation or null */ + A getDirectDeclaredAnnotation(Class annotationClass) { + Objects.requireNonNull(annotationClass); + + initAnnotationsIfNecessary(); + @SuppressWarnings("unchecked") // TODO check safe + A ret = (A)declaredAnnotations.get(annotationClass); + return ret; } // Annotations cache diff --git a/jdk/src/share/classes/java/lang/Package.java b/jdk/src/share/classes/java/lang/Package.java index f1f31b7acbe..744a292d6ee 100644 --- a/jdk/src/share/classes/java/lang/Package.java +++ b/jdk/src/share/classes/java/lang/Package.java @@ -394,6 +394,14 @@ public class Package implements java.lang.reflect.AnnotatedElement { return getPackageInfo().isAnnotationPresent(annotationClass); } + /** + * @throws NullPointerException {@inheritDoc} + * @since 1.8 + */ + public A[] getAnnotations(Class annotationClass) { + return getPackageInfo().getAnnotations(annotationClass); + } + /** * @since 1.5 */ @@ -401,6 +409,22 @@ public class Package implements java.lang.reflect.AnnotatedElement { return getPackageInfo().getAnnotations(); } + /** + * @throws NullPointerException {@inheritDoc} + * @since 1.8 + */ + public A getDeclaredAnnotation(Class annotationClass) { + return getPackageInfo().getDeclaredAnnotation(annotationClass); + } + + /** + * @throws NullPointerException {@inheritDoc} + * @since 1.8 + */ + public A[] getDeclaredAnnotations(Class annotationClass) { + return getPackageInfo().getDeclaredAnnotations(annotationClass); + } + /** * @since 1.5 */ diff --git a/jdk/src/share/classes/java/lang/RuntimePermission.java b/jdk/src/share/classes/java/lang/RuntimePermission.java index eeef0b5244b..6dcbc275e9e 100644 --- a/jdk/src/share/classes/java/lang/RuntimePermission.java +++ b/jdk/src/share/classes/java/lang/RuntimePermission.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -41,8 +41,8 @@ import java.util.StringTokenizer; * naming convention follows the hierarchical property naming convention. * Also, an asterisk * may appear at the end of the name, following a ".", or by itself, to - * signify a wildcard match. For example: "loadLibrary.*" or "*" is valid, - * "*loadLibrary" or "a*b" is not valid. + * signify a wildcard match. For example: "loadLibrary.*" and "*" signify a + * wildcard match, while "*loadLibrary" and "a*b" do not. *

      * The following table lists all the possible RuntimePermission target names, * and for each provides a description of what the permission allows diff --git a/jdk/src/share/classes/java/lang/String.java b/jdk/src/share/classes/java/lang/String.java index f9550874c9e..d73a2f7c2e9 100644 --- a/jdk/src/share/classes/java/lang/String.java +++ b/jdk/src/share/classes/java/lang/String.java @@ -1705,6 +1705,24 @@ public final class String str.value, 0, str.value.length, fromIndex); } + /** + * Code shared by String and AbstractStringBuilder to do searches. The + * source is the character array being searched, and the target + * is the string being searched for. + * + * @param source the characters being searched. + * @param sourceOffset offset of the source string. + * @param sourceCount count of the source string. + * @param target the characters being searched for. + * @param fromIndex the index to begin searching from. + */ + static int indexOf(char[] source, int sourceOffset, int sourceCount, + String target, int fromIndex) { + return indexOf(source, sourceOffset, sourceCount, + target.value, 0, target.value.length, + fromIndex); + } + /** * Code shared by String and StringBuffer to do searches. The * source is the character array being searched, and the target @@ -1796,6 +1814,24 @@ public final class String str.value, 0, str.value.length, fromIndex); } + /** + * Code shared by String and AbstractStringBuilder to do searches. The + * source is the character array being searched, and the target + * is the string being searched for. + * + * @param source the characters being searched. + * @param sourceOffset offset of the source string. + * @param sourceCount count of the source string. + * @param target the characters being searched for. + * @param fromIndex the index to begin searching from. + */ + static int lastIndexOf(char[] source, int sourceOffset, int sourceCount, + String target, int fromIndex) { + return lastIndexOf(source, sourceOffset, sourceCount, + target.value, 0, target.value.length, + fromIndex); + } + /** * Code shared by String and StringBuffer to do searches. The * source is the character array being searched, and the target diff --git a/jdk/src/share/classes/java/lang/System.java b/jdk/src/share/classes/java/lang/System.java index fde6aa36e6c..a6206e60391 100644 --- a/jdk/src/share/classes/java/lang/System.java +++ b/jdk/src/share/classes/java/lang/System.java @@ -25,6 +25,7 @@ package java.lang; import java.io.*; +import java.lang.annotation.Annotation; import java.util.Properties; import java.util.PropertyPermission; import java.util.StringTokenizer; @@ -1195,6 +1196,9 @@ public final class System { public AnnotationType getAnnotationType(Class klass) { return klass.getAnnotationType(); } + public A getDirectDeclaredAnnotation(Class klass, Class anno) { + return klass.getDirectDeclaredAnnotation(anno); + } public > E[] getEnumConstantsShared(Class klass) { return klass.getEnumConstantsShared(); diff --git a/jdk/src/share/classes/java/lang/ThreadLocal.java b/jdk/src/share/classes/java/lang/ThreadLocal.java index ac2254f88dc..b337fc5f2e6 100644 --- a/jdk/src/share/classes/java/lang/ThreadLocal.java +++ b/jdk/src/share/classes/java/lang/ThreadLocal.java @@ -25,19 +25,21 @@ package java.lang; import java.lang.ref.*; +import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Supplier; /** * This class provides thread-local variables. These variables differ from * their normal counterparts in that each thread that accesses one (via its - * get or set method) has its own, independently initialized - * copy of the variable. ThreadLocal instances are typically private + * {@code get} or {@code set} method) has its own, independently initialized + * copy of the variable. {@code ThreadLocal} instances are typically private * static fields in classes that wish to associate state with a thread (e.g., * a user ID or Transaction ID). * *

      For example, the class below generates unique identifiers local to each * thread. - * A thread's id is assigned the first time it invokes ThreadId.get() + * A thread's id is assigned the first time it invokes {@code ThreadId.get()} * and remains unchanged on subsequent calls. *

        * import java.util.concurrent.atomic.AtomicInteger;
      @@ -61,7 +63,7 @@ import java.util.concurrent.atomic.AtomicInteger;
        * }
        * 
      *

      Each thread holds an implicit reference to its copy of a thread-local - * variable as long as the thread is alive and the ThreadLocal + * variable as long as the thread is alive and the {@code ThreadLocal} * instance is accessible; after a thread goes away, all of its copies of * thread-local instances are subject to garbage collection (unless other * references to these copies exist). @@ -108,14 +110,14 @@ public class ThreadLocal { * thread-local variable. This method will be invoked the first * time a thread accesses the variable with the {@link #get} * method, unless the thread previously invoked the {@link #set} - * method, in which case the initialValue method will not + * method, in which case the {@code initialValue} method will not * be invoked for the thread. Normally, this method is invoked at * most once per thread, but it may be invoked again in case of * subsequent invocations of {@link #remove} followed by {@link #get}. * - *

      This implementation simply returns null; if the + *

      This implementation simply returns {@code null}; if the * programmer desires thread-local variables to have an initial - * value other than null, ThreadLocal must be + * value other than {@code null}, {@code ThreadLocal} must be * subclassed, and this method overridden. Typically, an * anonymous inner class will be used. * @@ -125,8 +127,22 @@ public class ThreadLocal { return null; } + /** + * Creates a thread local variable. The initial value of the variable is + * determined by invoking the {@code get} method on the {@code Supplier}. + * + * @param supplier the supplier to be used to determine the initial value + * @return a new thread local variable + * @throws NullPointerException if the specified supplier is null + * @since 1.8 + */ + public static ThreadLocal withInitial(Supplier supplier) { + return new SuppliedThreadLocal<>(supplier); + } + /** * Creates a thread local variable. + * @see #withInitial(java.util.function.Supplier) */ public ThreadLocal() { } @@ -195,7 +211,7 @@ public class ThreadLocal { * reinitialized by invoking its {@link #initialValue} method, * unless its value is {@linkplain #set set} by the current thread * in the interim. This may result in multiple invocations of the - * initialValue method in the current thread. + * {@code initialValue} method in the current thread. * * @since 1.5 */ @@ -250,6 +266,24 @@ public class ThreadLocal { throw new UnsupportedOperationException(); } + /** + * An extension of ThreadLocal that obtains its initial value from + * the specified {@code Supplier}. + */ + static final class SuppliedThreadLocal extends ThreadLocal { + + private final Supplier supplier; + + SuppliedThreadLocal(Supplier supplier) { + this.supplier = Objects.requireNonNull(supplier); + } + + @Override + protected T initialValue() { + return supplier.get(); + } + } + /** * ThreadLocalMap is a customized hash map suitable only for * maintaining thread local values. No operations are exported @@ -599,9 +633,9 @@ public class ThreadLocal { * @param i a position known NOT to hold a stale entry. The * scan starts at the element after i. * - * @param n scan control: log2(n) cells are scanned, + * @param n scan control: {@code log2(n)} cells are scanned, * unless a stale entry is found, in which case - * log2(table.length)-1 additional cells are scanned. + * {@code log2(table.length)-1} additional cells are scanned. * When called from insertions, this parameter is the number * of elements, but when from replaceStaleEntry, it is the * table length. (Note: all this could be changed to be either diff --git a/jdk/src/share/classes/java/lang/annotation/ContainedBy.java b/jdk/src/share/classes/java/lang/annotation/ContainedBy.java index 2449519d9ca..4f032863791 100644 --- a/jdk/src/share/classes/java/lang/annotation/ContainedBy.java +++ b/jdk/src/share/classes/java/lang/annotation/ContainedBy.java @@ -26,10 +26,35 @@ package java.lang.annotation; /** - * A meta-annotation to indicate which annotation type should be used - * as a container for repeated values of the annotation type modified - * by the {@code ContainedBy} annotation. + * The annotation type {@code java.lang.annotation.ContainedBy} is + * used to indicate that the annotation type whose declaration it + * (meta-)annotates is repeatable. The value of + * {@code @ContainedBy} indicates the containing annotation + * type for the repeatable annotation type. * + *

      The pair of annotation types {@code @ContainedBy} and + * {@link java.lang.annotation.ContainerFor @ContainerFor} are used to + * indicate that annotation types are repeatable. Specifically: + * + *

        + *
      • The annotation type {@code @ContainedBy} is used on the + * declaration of a repeatable annotation type (JLS 9.6) to indicate + * its containing annotation type. + * + *
      • The annotation type {@code @ContainerFor} is used on the + * declaration of a containing annotation type (JLS 9.6) to indicate + * the repeatable annotation type for which it serves as the + * containing annotation type. + *
      + * + *

      + * An inconsistent pair of {@code @ContainedBy} and + * {@code @ContainerFor} annotations on a repeatable annotation type + * and its containing annotation type (JLS 9.6) will lead to + * compile-time errors and runtime exceptions when using reflection to + * read annotations of a repeatable type. + * + * @see java.lang.annotation.ContainerFor * @since 1.8 * @jls 9.6 Annotation Types * @jls 9.7 Annotations @@ -39,8 +64,8 @@ package java.lang.annotation; @Target(ElementType.ANNOTATION_TYPE) public @interface ContainedBy { /** - * The annotation type to use to store repeated values of another - * annotation. + * Indicates the containing annotation type for the + * repeatable annotation type. */ Class value(); } diff --git a/jdk/src/share/classes/java/lang/annotation/ContainerFor.java b/jdk/src/share/classes/java/lang/annotation/ContainerFor.java index dd13bf99fcb..62f3446e021 100644 --- a/jdk/src/share/classes/java/lang/annotation/ContainerFor.java +++ b/jdk/src/share/classes/java/lang/annotation/ContainerFor.java @@ -26,10 +26,36 @@ package java.lang.annotation; /** - * Indicates that an annotation type is a container for repeated - * instances of annotations of the type of the value of the - * {@code ContainerFor}'s value element. + * The annotation type {@code java.lang.annotation.ContainerFor} is + * used to indicate that the annotation type whose declaration it + * (meta-)annotates is a containing annotation type. The + * value of {@code @ContainerFor} indicates the repeatable + * annotation type for the containing annotation type. * + *

      The pair of annotation types {@link + * java.lang.annotation.ContainedBy @ContainedBy} and + * {@code @ContainerFor} are used to indicate that annotation types + * are repeatable. Specifically: + * + *

        + *
      • The annotation type {@code @ContainedBy} is used on the + * declaration of a repeatable annotation type (JLS 9.6) to indicate + * its containing annotation type. + * + *
      • The annotation type {@code @ContainerFor} is used on the + * declaration of a containing annotation type (JLS 9.6) to indicate + * the repeatable annotation type for which it serves as the + * containing annotation type. + *
      + * + *

      + * An inconsistent pair of {@code @ContainedBy} and + * {@code @ContainerFor} annotations on a repeatable annotation type + * and its containing annotation type (JLS 9.6) will lead to + * compile-time errors and runtime exceptions when using reflection to + * read annotations of a repeatable type. + * + * @see java.lang.annotation.ContainedBy * @since 1.8 * @jls 9.6 Annotation Types * @jls 9.7 Annotations @@ -38,9 +64,10 @@ package java.lang.annotation; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface ContainerFor { + /** - * The repeating annotation type that the annotation type - * annotated with this annotation is a container for. + * Indicates the repeatable annotation type for the containing + * annotation type. */ Class value(); } diff --git a/jdk/src/share/classes/java/lang/annotation/InvalidContainerAnnotationError.java b/jdk/src/share/classes/java/lang/annotation/InvalidContainerAnnotationError.java new file mode 100644 index 00000000000..b24e3034179 --- /dev/null +++ b/jdk/src/share/classes/java/lang/annotation/InvalidContainerAnnotationError.java @@ -0,0 +1,129 @@ +/* + * 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. 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 java.lang.annotation; + +import java.util.Objects; + +/** + * Thrown to indicate that an annotation type whose declaration is + * (meta-)annotated with a {@link ContainerFor} annotation is not, in + * fact, the containing annotation type of the type named by {@link + * ContainerFor}. + * + * @see java.lang.reflect.AnnotatedElement + * @since 1.8 + * @jls 9.6 Annotation Types + * @jls 9.7 Annotations + */ +public class InvalidContainerAnnotationError extends AnnotationFormatError { + private static final long serialVersionUID = 5023L; + + /** + * The instance of the erroneous container. + */ + private transient Annotation container; + + /** + * The type of the annotation that should be contained in the + * container. + */ + private transient Class annotationType; + + /** + * Constructs a new InvalidContainerAnnotationError with the + * specified detail message. + * + * @param message the detail message. + */ + public InvalidContainerAnnotationError(String message) { + super(message); + } + + /** + * Constructs a new InvalidContainerAnnotationError with the specified + * detail message and cause. Note that the detail message associated + * with {@code cause} is not automatically incorporated in + * this error's detail message. + * + * @param message the detail message + * @param cause the cause, may be {@code null} + */ + public InvalidContainerAnnotationError(String message, Throwable cause) { + super(message, cause); + } + + /** + * Constructs a new InvalidContainerAnnotationError with the + * specified cause and a detail message of {@code (cause == null ? + * null : cause.toString())} (which typically contains the class + * and detail message of {@code cause}). + * + * @param cause the cause, may be {@code null} + */ + public InvalidContainerAnnotationError(Throwable cause) { + super(cause); + } + + /** + * Constructs InvalidContainerAnnotationError for the specified + * container instance and contained annotation type. + * + * @param message the detail message + * @param cause the cause, may be {@code null} + * @param container the erroneous container instance, may be + * {@code null} + * @param annotationType the annotation type intended to be + * contained, may be {@code null} + */ + public InvalidContainerAnnotationError(String message, + Throwable cause, + Annotation container, + Class annotationType) { + super(message, cause); + this.container = container; + this.annotationType = annotationType; + } + + /** + * Returns the erroneous container. + * + * @return the erroneous container, may return {@code null} + */ + public Annotation getContainer() { + return container; + } + + /** + * Returns the annotation type intended to be contained. Returns + * {@code null} if the annotation type intended to be contained + * could not be determined. + * + * @return the annotation type intended to be contained, or {@code + * null} if unknown + */ + public Class getAnnotationType() { + return annotationType; + } +} diff --git a/jdk/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java b/jdk/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java index d41a62d3952..13999001cdc 100644 --- a/jdk/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java +++ b/jdk/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java @@ -25,16 +25,15 @@ package java.lang.invoke; -import java.io.FileOutputStream; -import java.io.IOException; +import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.security.ProtectionDomain; import java.util.concurrent.atomic.AtomicInteger; -import java.util.logging.Level; -import java.util.logging.Logger; import jdk.internal.org.objectweb.asm.*; import static jdk.internal.org.objectweb.asm.Opcodes.*; import sun.misc.Unsafe; +import java.security.AccessController; +import java.security.PrivilegedAction; /** * InnerClassLambdaMetafactory @@ -121,13 +120,34 @@ import sun.misc.Unsafe; * * @return a CallSite, which, when invoked, will return an instance of the * functional interface - * @throws ReflectiveOperationException + * @throws ReflectiveOperationException, LambdaConversionException */ @Override CallSite buildCallSite() throws ReflectiveOperationException, LambdaConversionException { final Class innerClass = spinInnerClass(); if (invokedType.parameterCount() == 0) { - return new ConstantCallSite(MethodHandles.constant(samBase, innerClass.newInstance())); + final Constructor[] ctrs = AccessController.doPrivileged( + new PrivilegedAction() { + @Override + public Constructor[] run() { + return innerClass.getDeclaredConstructors(); + } + }); + if (ctrs.length != 1) { + throw new ReflectiveOperationException("Expected one lambda constructor for " + + innerClass.getCanonicalName() + ", got " + ctrs.length); + } + // The lambda implementing inner class constructor is private, set + // it accessible (by us) before creating the constant sole instance + AccessController.doPrivileged(new PrivilegedAction() { + @Override + public Void run() { + ctrs[0].setAccessible(true); + return null; + } + }); + Object inst = ctrs[0].newInstance(); + return new ConstantCallSite(MethodHandles.constant(samBase, inst)); } else { return new ConstantCallSite( MethodHandles.Lookup.IMPL_LOOKUP @@ -145,7 +165,7 @@ import sun.misc.Unsafe; private Class spinInnerClass() throws LambdaConversionException { String samName = samBase.getName().replace('.', '/'); - cw.visit(CLASSFILE_VERSION, ACC_PUBLIC + ACC_SUPER, lambdaClassName, null, NAME_MAGIC_ACCESSOR_IMPL, + cw.visit(CLASSFILE_VERSION, ACC_SUPER, lambdaClassName, null, NAME_MAGIC_ACCESSOR_IMPL, isSerializable ? new String[]{samName, NAME_SERIALIZABLE} : new String[]{samName}); // Generate final fields to be filled in by constructor @@ -187,17 +207,27 @@ import sun.misc.Unsafe; final byte[] classBytes = cw.toByteArray(); - if (System.getProperty("debug.dump.generated") != null) { + /*** Uncomment to dump the generated file System.out.printf("Loaded: %s (%d bytes) %n", lambdaClassName, classBytes.length); try (FileOutputStream fos = new FileOutputStream(lambdaClassName.replace('/', '.') + ".class")) { fos.write(classBytes); } catch (IOException ex) { Logger.getLogger(InnerClassLambdaMetafactory.class.getName()).log(Level.SEVERE, null, ex); } - } + ***/ ClassLoader loader = targetClass.getClassLoader(); - ProtectionDomain pd = (loader == null) ? null : targetClass.getProtectionDomain(); + ProtectionDomain pd = (loader == null) + ? null + : AccessController.doPrivileged( + new PrivilegedAction() { + @Override + public ProtectionDomain run() { + return targetClass.getProtectionDomain(); + } + } + ); + return (Class) Unsafe.getUnsafe().defineClass(lambdaClassName, classBytes, 0, classBytes.length, loader, pd); } @@ -206,7 +236,7 @@ import sun.misc.Unsafe; */ private void generateConstructor() { // Generate constructor - MethodVisitor ctor = cw.visitMethod(ACC_PUBLIC, NAME_CTOR, constructorDesc, null, null); + MethodVisitor ctor = cw.visitMethod(ACC_PRIVATE, NAME_CTOR, constructorDesc, null, null); ctor.visitCode(); ctor.visitVarInsn(ALOAD, 0); ctor.visitMethodInsn(INVOKESPECIAL, NAME_MAGIC_ACCESSOR_IMPL, NAME_CTOR, METHOD_DESCRIPTOR_VOID); diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java b/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java index 06a9ba20e69..fcc928a327d 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java @@ -448,7 +448,7 @@ class MethodHandleNatives { case "getDriver": case "getDrivers": case "deregisterDriver": - return defc == java.sql.DriverManager.class; + return defc == getClass("java.sql.DriverManager"); case "newUpdater": if (defc == java.util.concurrent.atomic.AtomicIntegerFieldUpdater.class) return true; if (defc == java.util.concurrent.atomic.AtomicLongFieldUpdater.class) return true; @@ -482,4 +482,14 @@ class MethodHandleNatives { } return false; } + + // avoid static dependency to a class in other modules + private static Class getClass(String cn) { + try { + return Class.forName(cn, false, + MethodHandleNatives.class.getClassLoader()); + } catch (ClassNotFoundException e) { + throw new InternalError(e); + } + } } diff --git a/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java b/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java index adbf8dbe76b..baaec298a85 100644 --- a/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java +++ b/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -184,11 +184,18 @@ public class AccessibleObject implements AnnotatedElement { * @throws NullPointerException {@inheritDoc} * @since 1.5 */ - public boolean isAnnotationPresent( - Class annotationClass) { + public boolean isAnnotationPresent(Class annotationClass) { return getAnnotation(annotationClass) != null; } + /** + * @throws NullPointerException {@inheritDoc} + * @since 1.8 + */ + public T[] getAnnotations(Class annotationClass) { + throw new AssertionError("All subclasses should override this method"); + } + /** * @since 1.5 */ @@ -196,6 +203,28 @@ public class AccessibleObject implements AnnotatedElement { return getDeclaredAnnotations(); } + /** + * @throws NullPointerException {@inheritDoc} + * @since 1.8 + */ + public T getDeclaredAnnotation(Class annotationClass) { + // Only annotations on classes are inherited, for all other + // objects getDeclaredAnnotation is the same as + // getAnnotation. + return getAnnotation(annotationClass); + } + + /** + * @throws NullPointerException {@inheritDoc} + * @since 1.8 + */ + public T[] getDeclaredAnnotations(Class annotationClass) { + // Only annotations on classes are inherited, for all other + // objects getDeclaredAnnotations is the same as + // getAnnotations. + return getAnnotations(annotationClass); + } + /** * @since 1.5 */ diff --git a/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java b/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java index dc244831676..58a07350f36 100644 --- a/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java +++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -45,6 +45,11 @@ import java.lang.annotation.Annotation; * a {@link EnumConstantNotPresentException} if the enum constant in the * annotation is no longer present in the enum type. * + *

      Attempting to read annotations of a repeatable annotation type T + * that are contained in an annotation whose type is not, in fact, the + * containing annotation type of T will result in an + * InvalidContainerAnnotationError. + * *

      Finally, Attempting to read a member whose definition has evolved * incompatibly will result in a {@link * java.lang.annotation.AnnotationTypeMismatchException} or an @@ -55,6 +60,7 @@ import java.lang.annotation.Annotation; * @see java.lang.annotation.AnnotationFormatError * @see java.lang.annotation.AnnotationTypeMismatchException * @see java.lang.annotation.IncompleteAnnotationException + * @see java.lang.annotation.InvalidContainerAnnotationError * @since 1.5 * @author Josh Bloch */ @@ -86,6 +92,23 @@ public interface AnnotatedElement { */ T getAnnotation(Class annotationClass); + /** + * Returns an array of all this element's annotations for the + * specified type if one or more of such annotation is present, + * else an array of length zero. + * + * The caller of this method is free to modify the returned array; + * it will have no effect on the arrays returned to other callers. + * + * @param annotationClass the Class object corresponding to the + * annotation type + * @return all this element's annotations for the specified annotation type if + * present on this element, else an array of length zero + * @throws NullPointerException if the given annotation class is null + * @since 1.8 + */ + T[] getAnnotations(Class annotationClass); + /** * Returns all annotations present on this element. (Returns an array * of length zero if this element has no annotations.) The caller of @@ -97,13 +120,49 @@ public interface AnnotatedElement { */ Annotation[] getAnnotations(); + /** + * Returns this element's annotation for the specified type if + * such an annotation is present, else null. + * + * This method ignores inherited annotations. (Returns null if no + * annotations are directly present on this element.) + * + * @param annotationClass the Class object corresponding to the + * annotation type + * @return this element's annotation for the specified annotation type if + * present on this element, else null + * @throws NullPointerException if the given annotation class is null + * @since 1.8 + */ + T getDeclaredAnnotation(Class annotationClass); + + /** + * Returns an array of all this element's annotations for the + * specified type if one or more of such annotation is directly + * present, else an array of length zero. + * + * This method ignores inherited annotations. (Returns + * an array of length zero if no annotations are directly present + * on this element.) The caller of this method is free to modify + * the returned array; it will have no effect on the arrays + * returned to other callers. + * + * @param annotationClass the Class object corresponding to the + * annotation type + * @return all this element's annotations for the specified annotation type if + * present on this element, else an array of length zero + * @throws NullPointerException if the given annotation class is null + * @since 1.8 + */ + T[] getDeclaredAnnotations(Class annotationClass); + /** * Returns all annotations that are directly present on this - * element. Unlike the other methods in this interface, this method - * ignores inherited annotations. (Returns an array of length zero if - * no annotations are directly present on this element.) The caller of - * this method is free to modify the returned array; it will have no - * effect on the arrays returned to other callers. + * element. This method ignores inherited annotations. (Returns + * an array of length zero if no annotations are directly present + * on this element.) The caller of this method is free to modify + * the returned array; it will have no effect on the arrays + * returned to other callers. * * @return All annotations directly present on this element * @since 1.5 diff --git a/jdk/src/share/classes/java/lang/reflect/Executable.java b/jdk/src/share/classes/java/lang/reflect/Executable.java index bec1a72a1e7..6948d96e8a0 100644 --- a/jdk/src/share/classes/java/lang/reflect/Executable.java +++ b/jdk/src/share/classes/java/lang/reflect/Executable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -26,8 +26,11 @@ package java.lang.reflect; import java.lang.annotation.*; +import java.util.Collections; import java.util.Map; +import java.util.Objects; import sun.reflect.annotation.AnnotationParser; +import sun.reflect.annotation.AnnotationSupport; import sun.reflect.generics.repository.ConstructorRepository; /** @@ -363,19 +366,28 @@ public abstract class Executable extends AccessibleObject * {@inheritDoc} * @throws NullPointerException {@inheritDoc} */ - @SuppressWarnings("unchecked") public T getAnnotation(Class annotationClass) { - if (annotationClass == null) - throw new NullPointerException(); + Objects.requireNonNull(annotationClass); - return (T) declaredAnnotations().get(annotationClass); + return AnnotationSupport.getOneAnnotation(declaredAnnotations(), annotationClass); + } + + /** + * {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + * @since 1.8 + */ + public T[] getAnnotations(Class annotationClass) { + Objects.requireNonNull(annotationClass); + + return AnnotationSupport.getMultipleAnnotations(declaredAnnotations(), annotationClass); } /** * {@inheritDoc} */ public Annotation[] getDeclaredAnnotations() { - return AnnotationParser.toArray(declaredAnnotations()); + return AnnotationSupport.unpackToArray(declaredAnnotations()); } private transient Map, Annotation> declaredAnnotations; diff --git a/jdk/src/share/classes/java/lang/reflect/Field.java b/jdk/src/share/classes/java/lang/reflect/Field.java index 5e24f228f84..ded3689c419 100644 --- a/jdk/src/share/classes/java/lang/reflect/Field.java +++ b/jdk/src/share/classes/java/lang/reflect/Field.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -33,7 +33,9 @@ import sun.reflect.generics.factory.GenericsFactory; import sun.reflect.generics.scope.ClassScope; import java.lang.annotation.Annotation; import java.util.Map; +import java.util.Objects; import sun.reflect.annotation.AnnotationParser; +import sun.reflect.annotation.AnnotationSupport; /** @@ -1012,19 +1014,28 @@ class Field extends AccessibleObject implements Member { * @throws NullPointerException {@inheritDoc} * @since 1.5 */ - @SuppressWarnings("unchecked") public T getAnnotation(Class annotationClass) { - if (annotationClass == null) - throw new NullPointerException(); + Objects.requireNonNull(annotationClass); - return (T) declaredAnnotations().get(annotationClass); + return AnnotationSupport.getOneAnnotation(declaredAnnotations(), annotationClass); } /** - * @since 1.5 + * {@inheritDoc} + * @throws NullPointerException {@inheritDoc} + * @since 1.8 + */ + public T[] getAnnotations(Class annotationClass) { + Objects.requireNonNull(annotationClass); + + return AnnotationSupport.getMultipleAnnotations(declaredAnnotations(), annotationClass); + } + + /** + * {@inheritDoc} */ public Annotation[] getDeclaredAnnotations() { - return AnnotationParser.toArray(declaredAnnotations()); + return AnnotationSupport.unpackToArray(declaredAnnotations()); } private transient Map, Annotation> declaredAnnotations; diff --git a/jdk/src/share/classes/java/net/AbstractPlainSocketImpl.java b/jdk/src/share/classes/java/net/AbstractPlainSocketImpl.java index b649b18ae90..be9ac509731 100644 --- a/jdk/src/share/classes/java/net/AbstractPlainSocketImpl.java +++ b/jdk/src/share/classes/java/net/AbstractPlainSocketImpl.java @@ -411,14 +411,13 @@ abstract class AbstractPlainSocketImpl extends SocketImpl * Gets an InputStream for this socket. */ protected synchronized InputStream getInputStream() throws IOException { - if (isClosedOrPending()) { - throw new IOException("Socket Closed"); - } - if (shut_rd) { - throw new IOException("Socket input is shutdown"); - } - if (socketInputStream == null) { - socketInputStream = new SocketInputStream(this); + synchronized (fdLock) { + if (isClosedOrPending()) + throw new IOException("Socket Closed"); + if (shut_rd) + throw new IOException("Socket input is shutdown"); + if (socketInputStream == null) + socketInputStream = new SocketInputStream(this); } return socketInputStream; } @@ -431,14 +430,13 @@ abstract class AbstractPlainSocketImpl extends SocketImpl * Gets an OutputStream for this socket. */ protected synchronized OutputStream getOutputStream() throws IOException { - if (isClosedOrPending()) { - throw new IOException("Socket Closed"); - } - if (shut_wr) { - throw new IOException("Socket output is shutdown"); - } - if (socketOutputStream == null) { - socketOutputStream = new SocketOutputStream(this); + synchronized (fdLock) { + if (isClosedOrPending()) + throw new IOException("Socket Closed"); + if (shut_wr) + throw new IOException("Socket output is shutdown"); + if (socketOutputStream == null) + socketOutputStream = new SocketOutputStream(this); } return socketOutputStream; } diff --git a/jdk/src/share/classes/java/net/HttpCookie.java b/jdk/src/share/classes/java/net/HttpCookie.java index fe4edc6ac12..d5a36df507f 100644 --- a/jdk/src/share/classes/java/net/HttpCookie.java +++ b/jdk/src/share/classes/java/net/HttpCookie.java @@ -30,6 +30,8 @@ import java.util.StringTokenizer; import java.util.NoSuchElementException; import java.text.SimpleDateFormat; import java.util.TimeZone; +import java.util.Calendar; +import java.util.GregorianCalendar; import java.util.Date; import java.util.Locale; import java.util.Objects; @@ -89,7 +91,10 @@ public final class HttpCookie implements Cloneable { private final static String[] COOKIE_DATE_FORMATS = { "EEE',' dd-MMM-yyyy HH:mm:ss 'GMT'", "EEE',' dd MMM yyyy HH:mm:ss 'GMT'", - "EEE MMM dd yyyy HH:mm:ss 'GMT'Z" + "EEE MMM dd yyyy HH:mm:ss 'GMT'Z", + "EEE',' dd-MMM-yy HH:mm:ss 'GMT'", + "EEE',' dd MMM yy HH:mm:ss 'GMT'", + "EEE MMM dd yy HH:mm:ss 'GMT'Z" }; // constant strings represent set-cookie header token @@ -1025,13 +1030,29 @@ public final class HttpCookie implements Cloneable { * specified by dateString */ private long expiryDate2DeltaSeconds(String dateString) { + Calendar cal = new GregorianCalendar(GMT); for (int i = 0; i < COOKIE_DATE_FORMATS.length; i++) { SimpleDateFormat df = new SimpleDateFormat(COOKIE_DATE_FORMATS[i], Locale.US); + cal.set(1970, 0, 1, 0, 0, 0); df.setTimeZone(GMT); + df.setLenient(false); + df.set2DigitYearStart(cal.getTime()); try { - Date date = df.parse(dateString); - return (date.getTime() - whenCreated) / 1000; + cal.setTime(df.parse(dateString)); + if (!COOKIE_DATE_FORMATS[i].contains("yyyy")) { + // 2-digit years following the standard set + // out it rfc 6265 + int year = cal.get(Calendar.YEAR); + year %= 100; + if (year < 70) { + year += 2000; + } else { + year += 1900; + } + cal.set(Calendar.YEAR, year); + } + return (cal.getTimeInMillis() - whenCreated) / 1000; } catch (Exception e) { // Ignore, try the next date format } diff --git a/jdk/src/share/classes/java/net/Inet6Address.java b/jdk/src/share/classes/java/net/Inet6Address.java index 77e7cf80314..7329b2de687 100644 --- a/jdk/src/share/classes/java/net/Inet6Address.java +++ b/jdk/src/share/classes/java/net/Inet6Address.java @@ -25,9 +25,9 @@ package java.net; -import java.io.ObjectInputStream; import java.io.IOException; import java.io.InvalidObjectException; +import java.io.ObjectInputStream; import java.util.Enumeration; /** @@ -116,7 +116,8 @@ import java.util.Enumeration; *

      Special IPv6 address

      * *
      - * + *
      IPv4-mapped address
      + * * *
      IPv4-mapped addressOf the form::ffff:w.x.y.z, this IPv6 address is used to * represent an IPv4 address. It allows the native program to * use the same address data structure and also the same @@ -130,35 +131,40 @@ import java.util.Enumeration; * address.
      *

      - *

      Textual representation of IPv6 scoped addresses

      - *

      - * The textual representation of IPv6 addresses as described above can be extended - * to specify IPv6 scoped addresses. This extension to the basic addressing architecture - * is described in [draft-ietf-ipngwg-scoping-arch-04.txt]. - *

      - * Because link-local and site-local addresses are non-global, it is possible that different hosts - * may have the same destination address and may be reachable through different interfaces on the - * same originating system. In this case, the originating system is said to be connected - * to multiple zones of the same scope. In order to disambiguate which is the intended destination - * zone, it is possible to append a zone identifier (or scope_id) to an IPv6 address. - *

      - * The general format for specifying the scope_id is the following: + *

      Textual representation of IPv6 scoped addresses

      + * + *

      The textual representation of IPv6 addresses as described above can be + * extended to specify IPv6 scoped addresses. This extension to the basic + * addressing architecture is described in [draft-ietf-ipngwg-scoping-arch-04.txt]. + * + *

      Because link-local and site-local addresses are non-global, it is possible + * that different hosts may have the same destination address and may be + * reachable through different interfaces on the same originating system. In + * this case, the originating system is said to be connected to multiple zones + * of the same scope. In order to disambiguate which is the intended destination + * zone, it is possible to append a zone identifier (or scope_id) to an + * IPv6 address. + * + *

      The general format for specifying the scope_id is the following: + * *

      IPv6-address%scope_id
      *

      The IPv6-address is a literal IPv6 address as described above. - * The scope_id refers to an interface on the local system, and it can be specified - * in two ways. - *

      1. As a numeric identifier. This must be a positive integer that identifies the - * particular interface and scope as understood by the system. Usually, the numeric - * values can be determined through administration tools on the system. Each interface may - * have multiple values, one for each scope. If the scope is unspecified, then the default value - * used is zero.
      2. - *

      3. As a string. This must be the exact string that is returned by - * {@link java.net.NetworkInterface#getName()} for the particular interface in question. - * When an Inet6Address is created in this way, the numeric scope-id is determined at the time - * the object is created by querying the relevant NetworkInterface.
      4. - *

      - * Note also, that the numeric scope_id can be retrieved from Inet6Address instances returned from the - * NetworkInterface class. This can be used to find out the current scope ids configured on the system. + * The scope_id refers to an interface on the local system, and it can be + * specified in two ways. + *

      1. As a numeric identifier. This must be a positive integer + * that identifies the particular interface and scope as understood by the + * system. Usually, the numeric values can be determined through administration + * tools on the system. Each interface may have multiple values, one for each + * scope. If the scope is unspecified, then the default value used is zero.
      2. + *

      3. As a string. This must be the exact string that is returned by + * {@link java.net.NetworkInterface#getName()} for the particular interface in + * question. When an Inet6Address is created in this way, the numeric scope-id + * is determined at the time the object is created by querying the relevant + * NetworkInterface.
      + * + *

      Note also, that the numeric scope_id can be retrieved from + * Inet6Address instances returned from the NetworkInterface class. This can be + * used to find out the current scope ids configured on the system. * @since 1.4 */ @@ -169,7 +175,7 @@ class Inet6Address extends InetAddress { /* * cached scope_id - for link-local address use only. */ - private transient int cached_scope_id = 0; + private transient int cached_scope_id; // 0 /** * Holds a 128-bit (16 bytes) IPv6 address. @@ -179,37 +185,28 @@ class Inet6Address extends InetAddress { byte[] ipaddress; /** - * scope_id. The scope specified when the object is created. If the object is created - * with an interface name, then the scope_id is not determined until the time it is needed. + * scope_id. The scope specified when the object is created. If the object + * is created with an interface name, then the scope_id is not determined + * until the time it is needed. */ - private int scope_id = 0; + private int scope_id; // 0 /** * This will be set to true when the scope_id field contains a valid * integer scope_id. */ - private boolean scope_id_set = false; + private boolean scope_id_set; // false /** * scoped interface. scope_id is derived from this as the scope_id of the first * address whose scope is the same as this address for the named interface. */ - private transient NetworkInterface scope_ifname = null; - - /** - * set if the object is constructed with a scoped interface instead of a - * numeric scope id. - */ - private boolean scope_ifname_set = false; + private transient NetworkInterface scope_ifname; // null private static final long serialVersionUID = 6880410070516793377L; - /* - * Perform initializations. - */ - static { - init(); - } + // Perform native initialization + static { init(); } Inet6Address() { super(); @@ -239,19 +236,24 @@ class Inet6Address extends InetAddress { } catch (UnknownHostException e) {} /* cant happen if ifname is null */ } - Inet6Address (String hostName, byte addr[], NetworkInterface nif) throws UnknownHostException { + Inet6Address (String hostName, byte addr[], NetworkInterface nif) + throws UnknownHostException + { initif (hostName, addr, nif); } - Inet6Address (String hostName, byte addr[], String ifname) throws UnknownHostException { + Inet6Address (String hostName, byte addr[], String ifname) + throws UnknownHostException + { initstr (hostName, addr, ifname); } /** - * Create an Inet6Address in the exact manner of {@link InetAddress#getByAddress(String,byte[])} - * except that the IPv6 scope_id is set to the value corresponding to the given interface - * for the address type specified in addr. - * The call will fail with an UnknownHostException if the given interface does not have a numeric + * Create an Inet6Address in the exact manner of {@link + * InetAddress#getByAddress(String,byte[])} except that the IPv6 scope_id is + * set to the value corresponding to the given interface for the address + * type specified in addr. The call will fail with an + * UnknownHostException if the given interface does not have a numeric * scope_id assigned for the given address type (eg. link-local or site-local). * See here for a description of IPv6 * scoped addresses. @@ -260,14 +262,16 @@ class Inet6Address extends InetAddress { * @param addr the raw IP address in network byte order * @param nif an interface this address must be associated with. * @return an Inet6Address object created from the raw IP address. - * @exception UnknownHostException if IP address is of illegal length, or if the interface - * does not have a numeric scope_id assigned for the given address type. + * @throws UnknownHostException + * if IP address is of illegal length, or if the interface does not + * have a numeric scope_id assigned for the given address type. * * @since 1.5 */ - - public static Inet6Address getByAddress(String host, byte[] addr, NetworkInterface nif) - throws UnknownHostException { + public static Inet6Address getByAddress(String host, byte[] addr, + NetworkInterface nif) + throws UnknownHostException + { if (host != null && host.length() > 0 && host.charAt(0) == '[') { if (host.charAt(host.length()-1) == ']') { host = host.substring(1, host.length() -1); @@ -282,9 +286,10 @@ class Inet6Address extends InetAddress { } /** - * Create an Inet6Address in the exact manner of {@link InetAddress#getByAddress(String,byte[])} - * except that the IPv6 scope_id is set to the given numeric value. - * The scope_id is not checked to determine if it corresponds to any interface on the system. + * Create an Inet6Address in the exact manner of {@link + * InetAddress#getByAddress(String,byte[])} except that the IPv6 scope_id is + * set to the given numeric value. The scope_id is not checked to determine + * if it corresponds to any interface on the system. * See here for a description of IPv6 * scoped addresses. * @@ -292,13 +297,14 @@ class Inet6Address extends InetAddress { * @param addr the raw IP address in network byte order * @param scope_id the numeric scope_id for the address. * @return an Inet6Address object created from the raw IP address. - * @exception UnknownHostException if IP address is of illegal length. + * @throws UnknownHostException if IP address is of illegal length. * * @since 1.5 */ - - public static Inet6Address getByAddress(String host, byte[] addr, int scope_id) - throws UnknownHostException { + public static Inet6Address getByAddress(String host, byte[] addr, + int scope_id) + throws UnknownHostException + { if (host != null && host.length() > 0 && host.charAt(0) == '[') { if (host.charAt(host.length()-1) == ']') { host = host.substring(1, host.length() -1); @@ -312,7 +318,9 @@ class Inet6Address extends InetAddress { throw new UnknownHostException("addr is of illegal length"); } - private void initstr (String hostName, byte addr[], String ifname) throws UnknownHostException { + private void initstr(String hostName, byte addr[], String ifname) + throws UnknownHostException + { try { NetworkInterface nif = NetworkInterface.getByName (ifname); if (nif == null) { @@ -324,16 +332,17 @@ class Inet6Address extends InetAddress { } } - private void initif(String hostName, byte addr[],NetworkInterface nif) throws UnknownHostException { + private void initif(String hostName, byte addr[],NetworkInterface nif) + throws UnknownHostException + { this.hostName = hostName; if (addr.length == INADDRSZ) { // normal IPv6 address family = IPv6; ipaddress = addr.clone(); } if (nif != null) { - this.scope_ifname = nif; - scope_ifname_set = true; - scope_id = deriveNumericScope (nif); + scope_ifname = nif; + scope_id = deriveNumericScope(nif); scope_id_set = true; } } @@ -344,17 +353,16 @@ class Inet6Address extends InetAddress { * return true otherwise. */ private boolean differentLocalAddressTypes(Inet6Address other) { - - if (isLinkLocalAddress() && !other.isLinkLocalAddress()) { + if (isLinkLocalAddress() && !other.isLinkLocalAddress()) return false; - } - if (isSiteLocalAddress() && !other.isSiteLocalAddress()) { + if (isSiteLocalAddress() && !other.isSiteLocalAddress()) return false; - } return true; } - private int deriveNumericScope (NetworkInterface ifc) throws UnknownHostException { + private int deriveNumericScope(NetworkInterface ifc) + throws UnknownHostException + { Enumeration addresses = ifc.getInetAddresses(); while (addresses.hasMoreElements()) { InetAddress addr = addresses.nextElement(); @@ -373,16 +381,17 @@ class Inet6Address extends InetAddress { throw new UnknownHostException ("no scope_id found"); } - private int deriveNumericScope (String ifname) throws UnknownHostException { + private int deriveNumericScope(String ifname) throws UnknownHostException { Enumeration en; try { en = NetworkInterface.getNetworkInterfaces(); } catch (SocketException e) { - throw new UnknownHostException ("could not enumerate local network interfaces"); + throw new UnknownHostException( + "could not enumerate local network interfaces"); } while (en.hasMoreElements()) { NetworkInterface ifc = en.nextElement(); - if (ifc.getName().equals (ifname)) { + if (ifc.getName().equals(ifname)) { Enumeration addresses = ifc.getInetAddresses(); while (addresses.hasMoreElements()) { InetAddress addr = addresses.nextElement(); @@ -400,7 +409,8 @@ class Inet6Address extends InetAddress { } } } - throw new UnknownHostException ("No matching address found for interface : " +ifname); + throw new UnknownHostException( + "No matching address found for interface : " +ifname); } /** @@ -410,22 +420,14 @@ class Inet6Address extends InetAddress { */ private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { - scope_ifname = null; - scope_ifname_set = false; s.defaultReadObject(); - if (ifname != null && !"".equals (ifname)) { + if (ifname != null && !ifname.equals("")) { try { scope_ifname = NetworkInterface.getByName(ifname); - if (scope_ifname == null) { - /* the interface does not exist on this system, so we clear - * the scope information completely */ - scope_id_set = false; - scope_ifname_set = false; - scope_id = 0; - } else { + if (scope_ifname != null) { try { - scope_id = deriveNumericScope (scope_ifname); + scope_id = deriveNumericScope(scope_ifname); } catch (UnknownHostException e) { // typically should not happen, but it may be that // the machine being used for deserialization has @@ -455,8 +457,9 @@ class Inet6Address extends InetAddress { * address. 11111111 at the start of the address identifies the * address as being a multicast address. * - * @return a boolean indicating if the InetAddress is - * an IP multicast address + * @return a {@code boolean} indicating if the InetAddress is an IP + * multicast address + * * @since JDK1.1 */ @Override @@ -466,8 +469,10 @@ class Inet6Address extends InetAddress { /** * Utility routine to check if the InetAddress in a wildcard address. - * @return a boolean indicating if the Inetaddress is + * + * @return a {@code boolean} indicating if the Inetaddress is * a wildcard address. + * * @since 1.4 */ @Override @@ -482,8 +487,9 @@ class Inet6Address extends InetAddress { /** * Utility routine to check if the InetAddress is a loopback address. * - * @return a boolean indicating if the InetAddress is - * a loopback address; or false otherwise. + * @return a {@code boolean} indicating if the InetAddress is a loopback + * address; or false otherwise. + * * @since 1.4 */ @Override @@ -498,8 +504,9 @@ class Inet6Address extends InetAddress { /** * Utility routine to check if the InetAddress is an link local address. * - * @return a boolean indicating if the InetAddress is - * a link local address; or false if address is not a link local unicast address. + * @return a {@code boolean} indicating if the InetAddress is a link local + * address; or false if address is not a link local unicast address. + * * @since 1.4 */ @Override @@ -511,8 +518,9 @@ class Inet6Address extends InetAddress { /** * Utility routine to check if the InetAddress is a site local address. * - * @return a boolean indicating if the InetAddress is - * a site local address; or false if address is not a site local unicast address. + * @return a {@code boolean} indicating if the InetAddress is a site local + * address; or false if address is not a site local unicast address. + * * @since 1.4 */ @Override @@ -524,9 +532,10 @@ class Inet6Address extends InetAddress { /** * Utility routine to check if the multicast address has global scope. * - * @return a boolean indicating if the address has - * is a multicast address of global scope, false if it is not - * of global scope or it is not a multicast address + * @return a {@code boolean} indicating if the address has is a multicast + * address of global scope, false if it is not of global scope or + * it is not a multicast address + * * @since 1.4 */ @Override @@ -538,9 +547,10 @@ class Inet6Address extends InetAddress { /** * Utility routine to check if the multicast address has node scope. * - * @return a boolean indicating if the address has - * is a multicast address of node-local scope, false if it is not - * of node-local scope or it is not a multicast address + * @return a {@code boolean} indicating if the address has is a multicast + * address of node-local scope, false if it is not of node-local + * scope or it is not a multicast address + * * @since 1.4 */ @Override @@ -552,9 +562,10 @@ class Inet6Address extends InetAddress { /** * Utility routine to check if the multicast address has link scope. * - * @return a boolean indicating if the address has - * is a multicast address of link-local scope, false if it is not - * of link-local scope or it is not a multicast address + * @return a {@code boolean} indicating if the address has is a multicast + * address of link-local scope, false if it is not of link-local + * scope or it is not a multicast address + * * @since 1.4 */ @Override @@ -566,9 +577,10 @@ class Inet6Address extends InetAddress { /** * Utility routine to check if the multicast address has site scope. * - * @return a boolean indicating if the address has - * is a multicast address of site-local scope, false if it is not - * of site-local scope or it is not a multicast address + * @return a {@code boolean} indicating if the address has is a multicast + * address of site-local scope, false if it is not of site-local + * scope or it is not a multicast address + * * @since 1.4 */ @Override @@ -580,10 +592,10 @@ class Inet6Address extends InetAddress { /** * Utility routine to check if the multicast address has organization scope. * - * @return a boolean indicating if the address has - * is a multicast address of organization-local scope, - * false if it is not of organization-local scope - * or it is not a multicast address + * @return a {@code boolean} indicating if the address has is a multicast + * address of organization-local scope, false if it is not of + * organization-local scope or it is not a multicast address + * * @since 1.4 */ @Override @@ -593,9 +605,9 @@ class Inet6Address extends InetAddress { } /** - * Returns the raw IP address of this InetAddress - * object. The result is in network byte order: the highest order - * byte of the address is in getAddress()[0]. + * Returns the raw IP address of this {@code InetAddress} object. The result + * is in network byte order: the highest order byte of the address is in + * {@code getAddress()[0]}. * * @return the raw IP address of this object. */ @@ -609,9 +621,10 @@ class Inet6Address extends InetAddress { * an interface. If no scoped_id is set, the returned value is zero. * * @return the scopeId, or zero if not set. + * * @since 1.5 */ - public int getScopeId () { + public int getScopeId() { return scope_id; } @@ -622,22 +635,23 @@ class Inet6Address extends InetAddress { * @return the scoped interface, or null if not set. * @since 1.5 */ - public NetworkInterface getScopedInterface () { + public NetworkInterface getScopedInterface() { return scope_ifname; } /** - * Returns the IP address string in textual presentation. If the instance was created - * specifying a scope identifier then the scope id is appended to the IP address preceded by - * a "%" (per-cent) character. This can be either a numeric value or a string, depending on which - * was used to createthe instance. + * Returns the IP address string in textual presentation. If the instance + * was created specifying a scope identifier then the scope id is appended + * to the IP address preceded by a "%" (per-cent) character. This can be + * either a numeric value or a string, depending on which was used to create + * the instance. * * @return the raw IP address in a string format. */ @Override public String getHostAddress() { String s = numericToTextFormat(ipaddress); - if (scope_ifname_set) { /* must check this first */ + if (scope_ifname != null) { /* must check this first */ s = s + "%" + scope_ifname.getName(); } else if (scope_id_set) { s = s + "%" + scope_id; @@ -674,29 +688,27 @@ class Inet6Address extends InetAddress { } /** - * Compares this object against the specified object. - * The result is true if and only if the argument is - * not null and it represents the same IP address as - * this object. - *

      - * Two instances of InetAddress represent the same IP - * address if the length of the byte arrays returned by - * getAddress is the same for both, and each of the - * array components is the same for the byte arrays. + * Compares this object against the specified object. The result is {@code + * true} if and only if the argument is not {@code null} and it represents + * the same IP address as this object. + * + *

      Two instances of {@code InetAddress} represent the same IP address + * if the length of the byte arrays returned by {@code getAddress} is the + * same for both, and each of the array components is the same for the byte + * arrays. * * @param obj the object to compare against. - * @return true if the objects are the same; - * false otherwise. + * + * @return {@code true} if the objects are the same; {@code false} otherwise. + * * @see java.net.InetAddress#getAddress() */ @Override public boolean equals(Object obj) { - if (obj == null || - !(obj instanceof Inet6Address)) + if (obj == null || !(obj instanceof Inet6Address)) return false; Inet6Address inetAddr = (Inet6Address)obj; - for (int i = 0; i < INADDRSZ; i++) { if (ipaddress[i] != inetAddr.ipaddress[i]) return false; @@ -709,8 +721,9 @@ class Inet6Address extends InetAddress { * Utility routine to check if the InetAddress is an * IPv4 compatible IPv6 address. * - * @return a boolean indicating if the InetAddress is - * an IPv4 compatible IPv6 address; or false if address is IPv4 address. + * @return a {@code boolean} indicating if the InetAddress is an IPv4 + * compatible IPv6 address; or false if address is IPv4 address. + * * @since 1.4 */ public boolean isIPv4CompatibleAddress() { @@ -727,6 +740,7 @@ class Inet6Address extends InetAddress { // Utilities private final static int INT16SZ = 2; + /* * Convert IPv6 binary address into presentation (printable) format. * @@ -735,9 +749,8 @@ class Inet6Address extends InetAddress { * textual representation format * @since 1.4 */ - static String numericToTextFormat(byte[] src) - { - StringBuffer sb = new StringBuffer(39); + static String numericToTextFormat(byte[] src) { + StringBuilder sb = new StringBuilder(39); for (int i = 0; i < (INADDRSZ / INT16SZ); i++) { sb.append(Integer.toHexString(((src[i<<1]<<8) & 0xff00) | (src[(i<<1)+1] & 0xff))); @@ -766,9 +779,8 @@ class Inet6Address extends InetAddress { private synchronized void writeObject(java.io.ObjectOutputStream s) throws IOException { - if (scope_ifname_set) { + if (scope_ifname != null) ifname = scope_ifname.getName(); - } s.defaultWriteObject(); } } diff --git a/jdk/src/share/classes/java/net/NetPermission.java b/jdk/src/share/classes/java/net/NetPermission.java index f22e04f717a..f11337e5b9e 100644 --- a/jdk/src/share/classes/java/net/NetPermission.java +++ b/jdk/src/share/classes/java/net/NetPermission.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -40,8 +40,8 @@ import java.util.StringTokenizer; * convention follows the hierarchical property naming convention. * Also, an asterisk * may appear at the end of the name, following a ".", or by itself, to - * signify a wildcard match. For example: "foo.*" or "*" is valid, - * "*foo" or "a*b" is not valid. + * signify a wildcard match. For example: "foo.*" and "*" signify a wildcard + * match, while "*foo" and "a*b" do not. *

      * The following table lists all the possible NetPermission target names, * and for each provides a description of what the permission allows diff --git a/jdk/src/share/classes/java/net/doc-files/net-properties.html b/jdk/src/share/classes/java/net/doc-files/net-properties.html index 37cbc930a12..5aac0c8e3bd 100644 --- a/jdk/src/share/classes/java/net/doc-files/net-properties.html +++ b/jdk/src/share/classes/java/net/doc-files/net-properties.html @@ -1,5 +1,5 @@ $ADDR" # IPv4 reverse lookup echo '' -OUT1=`$JAVA -Djava.net.preferIPv4Stack=true Lookup -q=PTR $ADDR` +OUT1=`$JAVA ${TESTVMOPTS} -Djava.net.preferIPv4Stack=true Lookup -q=PTR $ADDR` echo "(IPv4) $ADDR --> $OUT1" # reverse lookup (default) echo '' -OUT2=`$JAVA Lookup -q=PTR $ADDR` +OUT2=`$JAVA ${TESTVMOPTS} Lookup -q=PTR $ADDR` echo "(default) $ADDR --> $OUT2" diff --git a/jdk/test/java/net/ResponseCache/Test.java b/jdk/test/java/net/ResponseCache/Test.java new file mode 100644 index 00000000000..59951a49897 --- /dev/null +++ b/jdk/test/java/net/ResponseCache/Test.java @@ -0,0 +1,80 @@ +/* + * 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. + */ + +/* @test + * @summary Fixed a potential NullPointerException when setting a ResponseCache that returns a null CacheRequest + * @bug 4837267 + * @author Michael McMahon + */ + +import com.sun.net.httpserver.*; +import java.net.*; +import java.io.*; +import java.util.*; + +public class Test +{ + + static class MyHandler implements HttpHandler { + public void handle(HttpExchange t) throws IOException { + byte[] b = new byte[1024]; + int r = 0; + InputStream is = t.getRequestBody(); + while (is.read(b) != -1) ; + String response = "This is the response"; + t.sendResponseHeaders(200, response.length()); + OutputStream os = t.getResponseBody(); + os.write(response.getBytes()); + os.close(); + } + } + + public static void main(String args[]) throws Exception { + HttpServer server = HttpServer.create(new InetSocketAddress(0), 0); + server.createContext("/", new MyHandler()); + server.start(); + ResponseCache bak = ResponseCache.getDefault(); + + try { + ResponseCache.setDefault (new ResponseCache() { + public CacheResponse get (URI uri, String rqstMethod, Map> rqstHeaders) + throws IOException { + return null; + } + public CacheRequest put(URI uri, URLConnection conn) throws IOException + { + return null; + } + }); + + URL url = new URL ("http://localhost:" + server.getAddress().getPort() + "/"); + URLConnection urlc = url.openConnection (); + InputStream is = urlc.getInputStream(); + while (is.read() != -1) ; + is.close(); + } finally { + ResponseCache.setDefault(bak); + server.stop(0); + } + } +} diff --git a/jdk/test/java/net/ServerSocket/AcceptCauseFileDescriptorLeak.sh b/jdk/test/java/net/ServerSocket/AcceptCauseFileDescriptorLeak.sh index 5b039487286..df85f49feb7 100644 --- a/jdk/test/java/net/ServerSocket/AcceptCauseFileDescriptorLeak.sh +++ b/jdk/test/java/net/ServerSocket/AcceptCauseFileDescriptorLeak.sh @@ -45,4 +45,4 @@ if [ "$NOFILES" = "unlimited" ] || [ $NOFILES -ge 1024 ]; then ulimit -n 1024 fi -${TESTJAVA}/bin/java AcceptCauseFileDescriptorLeak +${TESTJAVA}/bin/java ${TESTVMOPTS} AcceptCauseFileDescriptorLeak diff --git a/jdk/test/java/net/Socket/B6210227.java b/jdk/test/java/net/Socket/B6210227.java new file mode 100644 index 00000000000..d8f4909604e --- /dev/null +++ b/jdk/test/java/net/Socket/B6210227.java @@ -0,0 +1,58 @@ +/* + * 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. + */ + +/** + * @test + * @bug 6210227 + * @summary REGRESSION: Socket.getLocalAddress() returns address of 0.0.0.0 on outbound TCP + */ + +import java.util.*; +import java.net.*; + +public class B6210227 { + public static void main(String[] args) throws Exception + { + ServerSocket ss = new ServerSocket(0); + int port = ss.getLocalPort(); + + byte[] bad = {0,0,0,0}; + try { + InetSocketAddress isa = new InetSocketAddress(InetAddress.getLocalHost(), port); + Socket s = new Socket(); + s.connect( isa, 1000 ); + InetAddress iaLocal = s.getLocalAddress(); // if this comes back as 0.0. 0.0 this would demonstrate issue + String sLocalHostname = iaLocal.getHostName(); + if (Arrays.equals (iaLocal.getAddress(), bad)) { + throw new RuntimeException ("0.0.0.0 returned"); + } + System.out.println("local hostname is "+sLocalHostname ); + } catch(Exception e) { + System.out.println("Exception happened"); + throw e; + } finally { + ss.close(); + } + } +} + diff --git a/jdk/test/java/net/Socket/OldSocketImpl.sh b/jdk/test/java/net/Socket/OldSocketImpl.sh index 5f429d1e4ee..bbe055fa2ea 100644 --- a/jdk/test/java/net/Socket/OldSocketImpl.sh +++ b/jdk/test/java/net/Socket/OldSocketImpl.sh @@ -50,7 +50,7 @@ esac # with 1.3 and in OldStyleImpl.jar # run -${TESTJAVA}${FS}bin${FS}java -cp ${TESTSRC}${FS}OldSocketImpl.jar OldSocketImpl +${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -cp ${TESTSRC}${FS}OldSocketImpl.jar OldSocketImpl result=$? if [ "$result" -ne "0" ]; then exit 1 diff --git a/jdk/test/java/net/Socket/Streams.java b/jdk/test/java/net/Socket/Streams.java new file mode 100644 index 00000000000..e3cae93c341 --- /dev/null +++ b/jdk/test/java/net/Socket/Streams.java @@ -0,0 +1,113 @@ +/* + * 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. + */ + +/* + * @test + * @bug 8003833 + * @summary Spurious NPE from Socket.getIn/OutputStream + */ + +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.concurrent.Phaser; + +// Racey test, will not always fail, but if it does then there is a problem. + +public class Streams { + static final int NUM_THREADS = 100; + static volatile boolean failed; + static final Phaser startingGate = new Phaser(NUM_THREADS + 1); + + public static void main(String[] args) throws Exception { + + try (ServerSocket ss = new ServerSocket(0)) { + runTest(OutputStreamGetter.class, ss); + runTest(InputStreamGetter.class, ss); + } + + if (failed) + throw new RuntimeException("Failed, check output"); + } + + static void runTest(Class klass, ServerSocket ss) + throws Exception + { + final int port = ss.getLocalPort(); + Socket[] sockets = new Socket[NUM_THREADS]; + for (int i=0; i ctr = klass.getConstructor(Socket.class); + + Thread[] threads = new Thread[NUM_THREADS]; + for (int i=0; i ${TMP1} 2>&1 cat ${TMP1} cat ${TMP1} | grep -s "Unrecognized VM option: \'MaxDirectMemorySize=" diff --git a/jdk/test/java/nio/channels/AsynchronousChannelGroup/run_any_task.sh b/jdk/test/java/nio/channels/AsynchronousChannelGroup/run_any_task.sh index 6849315e69a..8136634d205 100644 --- a/jdk/test/java/nio/channels/AsynchronousChannelGroup/run_any_task.sh +++ b/jdk/test/java/nio/channels/AsynchronousChannelGroup/run_any_task.sh @@ -46,7 +46,7 @@ $JAR -cf "${TESTCLASSES}/Privileged.jar" \ -C "${TESTCLASSES}" Attack.class echo "Running test ..." -$JAVA -XX:-UseVMInterruptibleIO \ - -Xbootclasspath/a:"${TESTCLASSES}/Privileged.jar" \ - -classpath "${TESTCLASSES}" \ - AsExecutor +$JAVA ${TESTVMOPTS} \ + -Xbootclasspath/a:"${TESTCLASSES}/Privileged.jar" \ + -classpath "${TESTCLASSES}" \ + AsExecutor diff --git a/jdk/test/java/nio/channels/spi/AsynchronousChannelProvider/custom_provider.sh b/jdk/test/java/nio/channels/spi/AsynchronousChannelProvider/custom_provider.sh index c334192a231..bf8246501e9 100644 --- a/jdk/test/java/nio/channels/spi/AsynchronousChannelProvider/custom_provider.sh +++ b/jdk/test/java/nio/channels/spi/AsynchronousChannelProvider/custom_provider.sh @@ -51,7 +51,7 @@ failures=0 go() { echo '' - $JAVA $1 $2 $3 2>&1 + $JAVA ${TESTVMOPTS} $1 $2 $3 2>&1 if [ $? != 0 ]; then failures=`expr $failures + 1`; fi } diff --git a/jdk/test/java/nio/charset/Charset/default.sh b/jdk/test/java/nio/charset/Charset/default.sh index 5a91ea10c18..c93aa71bdef 100644 --- a/jdk/test/java/nio/charset/Charset/default.sh +++ b/jdk/test/java/nio/charset/Charset/default.sh @@ -64,7 +64,7 @@ go() { ecs="$1"; shift echo -n "$L: " - cs="`LC_ALL=$L $JAVA -cp $TESTCLASSES Default`" + cs="`LC_ALL=$L $JAVA ${TESTVMOPTS} -cp $TESTCLASSES Default`" if [ $? != 0 ]; then exit 1 elif [ "`tolower $cs`" != "`tolower $ecs`" ]; then diff --git a/jdk/test/java/nio/charset/coders/CheckSJISMappingProp.sh b/jdk/test/java/nio/charset/coders/CheckSJISMappingProp.sh index 49caa0dfebb..fd76d5a5031 100644 --- a/jdk/test/java/nio/charset/coders/CheckSJISMappingProp.sh +++ b/jdk/test/java/nio/charset/coders/CheckSJISMappingProp.sh @@ -51,7 +51,7 @@ expectPass() { } -JAVA="${TESTJAVA}/bin/java -cp ${TESTCLASSES}" +JAVA="${TESTJAVA}/bin/java ${TESTVMOPTS} -cp ${TESTCLASSES}" runTest() { echo "Testing:" ${1} LC_ALL="$1" ; export LC_ALL diff --git a/jdk/test/java/nio/charset/spi/basic.sh b/jdk/test/java/nio/charset/spi/basic.sh index c1bdd45dd02..e4f89c5823c 100644 --- a/jdk/test/java/nio/charset/spi/basic.sh +++ b/jdk/test/java/nio/charset/spi/basic.sh @@ -116,7 +116,7 @@ for where in ext app; do av="$av -Djava.security.manager -Djava.security.policy==$TESTSRC/charsetProvider.sp";; esac - if (set -x; $JAVA $av Test $css) 2>&1; then + if (set -x; $JAVA ${TESTVMOPTS} $av Test $css) 2>&1; then continue; else failures=`expr $failures + 1` diff --git a/jdk/test/java/nio/file/Files/delete_on_close.sh b/jdk/test/java/nio/file/Files/delete_on_close.sh index 7ffa009a817..f6a58683be6 100644 --- a/jdk/test/java/nio/file/Files/delete_on_close.sh +++ b/jdk/test/java/nio/file/Files/delete_on_close.sh @@ -51,7 +51,7 @@ export CLASSPATH TMPFILE="$$.tmp" touch $TMPFILE -$JAVA DeleteOnClose $TMPFILE 2>&1 +$JAVA ${TESTVMOPTS} DeleteOnClose $TMPFILE 2>&1 if [ $? != 0 ]; then exit 1; fi if [ -f $TMPFILE ]; then echo "$TMPFILE was not deleted" diff --git a/jdk/test/java/nio/file/Files/walkFileTree/walk_file_tree.sh b/jdk/test/java/nio/file/Files/walkFileTree/walk_file_tree.sh index dee0dd06f71..6c9d7dc89d3 100644 --- a/jdk/test/java/nio/file/Files/walkFileTree/walk_file_tree.sh +++ b/jdk/test/java/nio/file/Files/walkFileTree/walk_file_tree.sh @@ -56,7 +56,7 @@ if [ $? != 0 ]; then exit 1; fi failures=0 # print the file tree and compare output with find(1) -$JAVA PrintFileTree "$ROOT" > out1 +$JAVA ${TESTVMOPTS} PrintFileTree "$ROOT" > out1 find "$ROOT" > out2 diff out1 out2 if [ $? != 0 ]; then failures=`expr $failures + 1`; fi @@ -66,26 +66,26 @@ if [ $? != 0 ]; then failures=`expr $failures + 1`; fi # not. For that reason we run PrintFileTree with the -printCycles # option when the output without this option differs to find(1). find "$ROOT" -follow > out1 -$JAVA PrintFileTree -follow "$ROOT" > out2 +$JAVA ${TESTVMOPTS} PrintFileTree -follow "$ROOT" > out2 diff out1 out2 if [ $? != 0 ]; then # re-run printing cycles to stdout - $JAVA PrintFileTree -follow -printCycles "$ROOT" > out2 + $JAVA ${TESTVMOPTS} PrintFileTree -follow -printCycles "$ROOT" > out2 diff out1 out2 if [ $? != 0 ]; then failures=`expr $failures + 1`; fi fi # test SKIP_SIBLINGS -$JAVA SkipSiblings "$ROOT" +$JAVA ${TESTVMOPTS} SkipSiblings "$ROOT" if [ $? != 0 ]; then failures=`expr $failures + 1`; fi # test TERMINATE -$JAVA TerminateWalk "$ROOT" +$JAVA ${TESTVMOPTS} TerminateWalk "$ROOT" if [ $? != 0 ]; then failures=`expr $failures + 1`; fi # test maxDepth -$JAVA MaxDepth "$ROOT" +$JAVA ${TESTVMOPTS} MaxDepth "$ROOT" if [ $? != 0 ]; then failures=`expr $failures + 1`; fi # clean-up diff --git a/jdk/test/java/nio/file/Path/MacPathTest.sh b/jdk/test/java/nio/file/Path/MacPathTest.sh index e81c62ae906..e5d410bd112 100644 --- a/jdk/test/java/nio/file/Path/MacPathTest.sh +++ b/jdk/test/java/nio/file/Path/MacPathTest.sh @@ -36,4 +36,4 @@ if [ "x$TESTJAVA" = x ]; then TESTCLASSES=. fi -export LC_ALL=en_US.UTF-8; ${TESTJAVA}/bin/java -cp ${TESTCLASSES} MacPathTest +export LC_ALL=en_US.UTF-8; ${TESTJAVA}/bin/java ${TESTVMOPTS} -cp ${TESTCLASSES} MacPathTest diff --git a/jdk/test/java/rmi/MarshalledObject/compare/Compare.java b/jdk/test/java/rmi/MarshalledObject/compare/Compare.java index 96ea46f76db..20322646920 100644 --- a/jdk/test/java/rmi/MarshalledObject/compare/Compare.java +++ b/jdk/test/java/rmi/MarshalledObject/compare/Compare.java @@ -29,7 +29,6 @@ * not involved in location should be compared. * @author Ken Arnold * - * @build Compare * @run main Compare 11 annotatedRef */ diff --git a/jdk/test/java/rmi/MarshalledObject/compare/HashCode.java b/jdk/test/java/rmi/MarshalledObject/compare/HashCode.java index 6a0266b927b..768e418ae5b 100644 --- a/jdk/test/java/rmi/MarshalledObject/compare/HashCode.java +++ b/jdk/test/java/rmi/MarshalledObject/compare/HashCode.java @@ -27,7 +27,6 @@ * @summary MarshalledObject with null throws NullPointerException * @author Ken Arnold * - * @build HashCode * @run main HashCode 11 annotatedRef */ diff --git a/jdk/test/java/rmi/MarshalledObject/compare/NullReference.java b/jdk/test/java/rmi/MarshalledObject/compare/NullReference.java index f8ff9a1a4fa..5210e948b51 100644 --- a/jdk/test/java/rmi/MarshalledObject/compare/NullReference.java +++ b/jdk/test/java/rmi/MarshalledObject/compare/NullReference.java @@ -27,7 +27,6 @@ * @summary MarshalledObject with null throws NullPointerException * @author Ken Arnold * - * @build NullReference * @run main NullReference */ diff --git a/jdk/test/java/rmi/Naming/DefaultRegistryPort.java b/jdk/test/java/rmi/Naming/DefaultRegistryPort.java index 4290bf563be..a4c49792536 100644 --- a/jdk/test/java/rmi/Naming/DefaultRegistryPort.java +++ b/jdk/test/java/rmi/Naming/DefaultRegistryPort.java @@ -28,7 +28,6 @@ * @author Dana Burns * @library ../testlibrary * @build TestLibrary - * @build DefaultRegistryPort * @run main DefaultRegistryPort */ diff --git a/jdk/test/java/rmi/Naming/LookupIPv6.java b/jdk/test/java/rmi/Naming/LookupIPv6.java index ebdd9f3efae..da6c62cbc83 100644 --- a/jdk/test/java/rmi/Naming/LookupIPv6.java +++ b/jdk/test/java/rmi/Naming/LookupIPv6.java @@ -22,12 +22,11 @@ */ /* @test + * @summary Ensure that java.rmi.Naming.lookup can handle URLs containing + * IPv6 addresses. * @bug 4402708 * * @run main/othervm -Djava.net.preferIPv6Addresses=true LookupIPv6 - * - * @summary Ensure that java.rmi.Naming.lookup can handle URLs containing - * IPv6 addresses. */ import java.net.InetAddress; diff --git a/jdk/test/java/rmi/Naming/RmiIsNoScheme.java b/jdk/test/java/rmi/Naming/RmiIsNoScheme.java index 865a07c995d..fe6d1ab4031 100644 --- a/jdk/test/java/rmi/Naming/RmiIsNoScheme.java +++ b/jdk/test/java/rmi/Naming/RmiIsNoScheme.java @@ -30,7 +30,6 @@ * * @library ../testlibrary * @build TestLibrary - * @build RmiIsNoScheme * @run main/othervm RmiIsNoScheme */ diff --git a/jdk/test/java/rmi/Naming/UnderscoreHost.java b/jdk/test/java/rmi/Naming/UnderscoreHost.java index 0d7375693c4..b88ca628e9a 100644 --- a/jdk/test/java/rmi/Naming/UnderscoreHost.java +++ b/jdk/test/java/rmi/Naming/UnderscoreHost.java @@ -29,8 +29,7 @@ * @author Vinod Johnson * * @library ../testlibrary - * @build TestLibrary - * @build UnderscoreHost UnderscoreHost_Stub + * @build TestLibrary UnderscoreHost_Stub * @run main/othervm UnderscoreHost */ diff --git a/jdk/test/java/rmi/Naming/legalRegistryNames/LegalRegistryNames.java b/jdk/test/java/rmi/Naming/legalRegistryNames/LegalRegistryNames.java index 0d367974b2e..725d9ca6c7a 100644 --- a/jdk/test/java/rmi/Naming/legalRegistryNames/LegalRegistryNames.java +++ b/jdk/test/java/rmi/Naming/legalRegistryNames/LegalRegistryNames.java @@ -21,14 +21,13 @@ * questions. */ -/** +/* * @test * @bug 4254808 * @summary Naming assumes '/' is present in relative URL; change in URL causes regression * @author Dana Burns * @library ../../testlibrary - * @build TestLibrary - * @build Legal LegalRegistryNames LegalRegistryNames_Stub + * @build TestLibrary Legal LegalRegistryNames_Stub * @run main LegalRegistryNames */ diff --git a/jdk/test/java/rmi/RMISecurityManager/checkPackageAccess/CheckPackageAccess.java b/jdk/test/java/rmi/RMISecurityManager/checkPackageAccess/CheckPackageAccess.java index 648708869ad..32cbe5ff481 100644 --- a/jdk/test/java/rmi/RMISecurityManager/checkPackageAccess/CheckPackageAccess.java +++ b/jdk/test/java/rmi/RMISecurityManager/checkPackageAccess/CheckPackageAccess.java @@ -28,10 +28,9 @@ * as when the default java.lang.SecurityManager is set, which with the * default "java.security" file in the JDK means that access to packages in * the sun.* package hierarchy is denied (without explicit runtime permission - * "accessClassInPackge.*"). + * "accessClassInPackage.*"). * @author Peter Jones * - * @build CheckPackageAccess * @run main/othervm CheckPackageAccess */ diff --git a/jdk/test/java/rmi/activation/Activatable/checkActivateRef/CheckActivateRef.java b/jdk/test/java/rmi/activation/Activatable/checkActivateRef/CheckActivateRef.java index 9bd8475a44b..fce32f9f06a 100644 --- a/jdk/test/java/rmi/activation/Activatable/checkActivateRef/CheckActivateRef.java +++ b/jdk/test/java/rmi/activation/Activatable/checkActivateRef/CheckActivateRef.java @@ -36,8 +36,7 @@ * functionality is in place * * @library ../../../testlibrary - * @build TestLibrary RMID - * @build ActivateMe CheckActivateRef_Stub CheckActivateRef + * @build TestLibrary RMID ActivateMe CheckActivateRef_Stub * @run main/othervm/policy=security.policy/timeout=240 -Djava.rmi.server.ignoreStubClasses=true CheckActivateRef * @run main/othervm/policy=security.policy/timeout=240 -Djava.rmi.server.ignoreStubClasses=false CheckActivateRef */ diff --git a/jdk/test/java/rmi/activation/Activatable/checkAnnotations/CheckAnnotations.java b/jdk/test/java/rmi/activation/Activatable/checkAnnotations/CheckAnnotations.java index ae7b843b1a9..b6e4abd433c 100644 --- a/jdk/test/java/rmi/activation/Activatable/checkAnnotations/CheckAnnotations.java +++ b/jdk/test/java/rmi/activation/Activatable/checkAnnotations/CheckAnnotations.java @@ -28,10 +28,7 @@ * @author Laird Dornin; code borrowed from Ann Wollrath * * @library ../../../testlibrary - * @build TestLibrary RMID JavaVM StreamPipe - * @build MyRMI - * @build CheckAnnotations - * @build CheckAnnotations_Stub + * @build TestLibrary RMID MyRMI CheckAnnotations_Stub * @run main/othervm/policy=security.policy/timeout=480 CheckAnnotations */ diff --git a/jdk/test/java/rmi/activation/Activatable/checkImplClassLoader/CheckImplClassLoader.java b/jdk/test/java/rmi/activation/Activatable/checkImplClassLoader/CheckImplClassLoader.java index e3a1467ceee..3d0694107e9 100644 --- a/jdk/test/java/rmi/activation/Activatable/checkImplClassLoader/CheckImplClassLoader.java +++ b/jdk/test/java/rmi/activation/Activatable/checkImplClassLoader/CheckImplClassLoader.java @@ -24,14 +24,11 @@ /* @test * @bug 4289544 * @summary ActivationGroupImpl.newInstance does not set context classloader for impl - * * @author Laird Dornin; code borrowed from Ann Wollrath * * @library ../../../testlibrary - * @build TestLibrary RMID JavaVM StreamPipe - * @build MyRMI - * @build CheckImplClassLoader ActivatableImpl - * @build ActivatableImpl ActivatableImpl_Stub + * @build TestLibrary RMID + * MyRMI ActivatableImpl ActivatableImpl ActivatableImpl_Stub * @run main/othervm/policy=security.policy/timeout=150 CheckImplClassLoader */ diff --git a/jdk/test/java/rmi/activation/Activatable/checkRegisterInLog/CheckRegisterInLog.java b/jdk/test/java/rmi/activation/Activatable/checkRegisterInLog/CheckRegisterInLog.java index 59f5c99dc77..b46142f1a2a 100644 --- a/jdk/test/java/rmi/activation/Activatable/checkRegisterInLog/CheckRegisterInLog.java +++ b/jdk/test/java/rmi/activation/Activatable/checkRegisterInLog/CheckRegisterInLog.java @@ -27,8 +27,8 @@ * @author Ann Wollrath * * @library ../../../testlibrary - * @build RMID ActivationLibrary TestLibrary - * @build ActivateMe CheckRegisterInLog CheckRegisterInLog_Stub + * @build TestLibrary RMID ActivationLibrary + * ActivateMe CheckRegisterInLog_Stub * @run main/othervm/policy=security.policy/timeout=240 CheckRegisterInLog */ diff --git a/jdk/test/java/rmi/activation/Activatable/createPrivateActivable/CreatePrivateActivatable.java b/jdk/test/java/rmi/activation/Activatable/createPrivateActivable/CreatePrivateActivatable.java index 4d4d0736722..41a28868ecd 100644 --- a/jdk/test/java/rmi/activation/Activatable/createPrivateActivable/CreatePrivateActivatable.java +++ b/jdk/test/java/rmi/activation/Activatable/createPrivateActivable/CreatePrivateActivatable.java @@ -22,14 +22,12 @@ */ /* @test - * @author Laird Dornin * @bug 4164971 * @summary allow non-public activatable class and/or constructor + * @author Laird Dornin * * @library ../../../testlibrary - * @build TestLibrary RMID - * @build ActivateMe - * @build CreatePrivateActivatable + * @build TestLibrary RMID ActivateMe * @run main/othervm/policy=security.policy/timeout=240 CreatePrivateActivatable */ diff --git a/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/DownloadParameterClass.java b/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/DownloadParameterClass.java index 1bb909a79bf..42d309b34d9 100644 --- a/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/DownloadParameterClass.java +++ b/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/DownloadParameterClass.java @@ -32,11 +32,7 @@ * * @library ../../../testlibrary * @build TestLibrary RMID ActivationLibrary - * @build DownloadParameterClass - * @build Foo - * @build FooReceiverImpl - * @build FooReceiverImpl_Stub - * @build Bar + * Foo FooReceiverImpl FooReceiverImpl_Stub Bar * @run main/othervm/policy=security.policy/timeout=240 DownloadParameterClass */ diff --git a/jdk/test/java/rmi/activation/Activatable/elucidateNoSuchMethod/ElucidateNoSuchMethod.java b/jdk/test/java/rmi/activation/Activatable/elucidateNoSuchMethod/ElucidateNoSuchMethod.java index 3d82bfb86af..7ee451d7328 100644 --- a/jdk/test/java/rmi/activation/Activatable/elucidateNoSuchMethod/ElucidateNoSuchMethod.java +++ b/jdk/test/java/rmi/activation/Activatable/elucidateNoSuchMethod/ElucidateNoSuchMethod.java @@ -23,14 +23,11 @@ /* @test * @bug 4128620 - * * @summary synopsis: NoSuchMethodError should be elucidated - * * @author Laird Dornin * * @library ../../../testlibrary - * @build TestLibrary RMID - * @build ActivateMe ElucidateNoSuchMethod ElucidateNoSuchMethod_Stub + * @build TestLibrary RMID ActivateMe ElucidateNoSuchMethod_Stub * @run main/othervm/policy=security.policy/timeout=240 ElucidateNoSuchMethod */ diff --git a/jdk/test/java/rmi/activation/Activatable/extLoadedImpl/ext.sh b/jdk/test/java/rmi/activation/Activatable/extLoadedImpl/ext.sh index 7d15638cdb1..4f758b410c4 100644 --- a/jdk/test/java/rmi/activation/Activatable/extLoadedImpl/ext.sh +++ b/jdk/test/java/rmi/activation/Activatable/extLoadedImpl/ext.sh @@ -51,5 +51,5 @@ rm classes/ExtLoadedImpl.class classes/ExtLoadedImpl_Stub.class classes/CheckLoa mkdir -p ext $TESTJAVA/bin/jar cf ext/ext.jar -C $TESTCLASSES ExtLoadedImpl.class -C $TESTCLASSES ExtLoadedImpl_Stub.class -C $TESTCLASSES CheckLoader.class -$TESTJAVA/bin/java -cp classes -Dtest.src=$TESTSRC -Dtest.classes=$TESTCLASSES -Djava.security.policy=$TESTSRC/security.policy -Djava.ext.dirs=ext ExtLoadedImplTest +$TESTJAVA/bin/java ${TESTVMOPTS} -cp classes -Dtest.src=$TESTSRC -Dtest.classes=$TESTCLASSES -Djava.security.policy=$TESTSRC/security.policy -Djava.ext.dirs=ext ExtLoadedImplTest diff --git a/jdk/test/java/rmi/activation/Activatable/forceLogSnapshot/ForceLogSnapshot.java b/jdk/test/java/rmi/activation/Activatable/forceLogSnapshot/ForceLogSnapshot.java index 679114806ff..9af0bf31600 100644 --- a/jdk/test/java/rmi/activation/Activatable/forceLogSnapshot/ForceLogSnapshot.java +++ b/jdk/test/java/rmi/activation/Activatable/forceLogSnapshot/ForceLogSnapshot.java @@ -27,9 +27,8 @@ * @author Laird Dornin * * @library ../../../testlibrary - * @build ActivateMe - * @build ForceLogSnapshot - * @build ForceLogSnapshot_Stub + * @build TestLibrary RMID ActivationLibrary + * ActivateMe ForceLogSnapshot_Stub * @run main/othervm/policy=security.policy/timeout=640 ForceLogSnapshot */ diff --git a/jdk/test/java/rmi/activation/Activatable/inactiveGroup/InactiveGroup.java b/jdk/test/java/rmi/activation/Activatable/inactiveGroup/InactiveGroup.java index a1b02b1eab4..238d3473a9e 100644 --- a/jdk/test/java/rmi/activation/Activatable/inactiveGroup/InactiveGroup.java +++ b/jdk/test/java/rmi/activation/Activatable/inactiveGroup/InactiveGroup.java @@ -29,10 +29,7 @@ * @author Ann Wollrath * * @library ../../../testlibrary - * @build TestLibrary RMID ActivationLibrary - * @build ActivateMe - * @build InactiveGroup - * @build InactiveGroup_Stub + * @build TestLibrary RMID ActivationLibrary ActivateMe InactiveGroup_Stub * @run main/othervm/policy=security.policy/timeout=240 InactiveGroup */ diff --git a/jdk/test/java/rmi/activation/Activatable/lookupActivationSystem/LookupActivationSystem.java b/jdk/test/java/rmi/activation/Activatable/lookupActivationSystem/LookupActivationSystem.java index eee264f2985..ce154c4ca99 100644 --- a/jdk/test/java/rmi/activation/Activatable/lookupActivationSystem/LookupActivationSystem.java +++ b/jdk/test/java/rmi/activation/Activatable/lookupActivationSystem/LookupActivationSystem.java @@ -24,14 +24,12 @@ /* * @test * @bug 6245733 - * * @summary synopsis: rmid's registry's list operation doesn't include * activation system * @author Ann Wollrath * * @library ../../../testlibrary * @build TestLibrary RMID ActivationLibrary - * @build LookupActivationSystem * @run main/othervm/timeout=240 LookupActivationSystem */ diff --git a/jdk/test/java/rmi/activation/Activatable/nestedActivate/NestedActivate.java b/jdk/test/java/rmi/activation/Activatable/nestedActivate/NestedActivate.java index 9ad2d5482dc..2cd5a634534 100644 --- a/jdk/test/java/rmi/activation/Activatable/nestedActivate/NestedActivate.java +++ b/jdk/test/java/rmi/activation/Activatable/nestedActivate/NestedActivate.java @@ -23,15 +23,11 @@ /* @test * @bug 4138056 - * * @summary synopsis: Activating objects from an Activatable constructor causes deadlock * @author Ann Wollrath * * @library ../../../testlibrary - * @build TestLibrary RMID ActivationLibrary - * @build ActivateMe - * @build NestedActivate - * @build NestedActivate_Stub + * @build TestLibrary RMID ActivationLibrary ActivateMe NestedActivate_Stub * @run main/othervm/policy=security.policy/timeout=240 NestedActivate */ diff --git a/jdk/test/java/rmi/activation/Activatable/nonExistentActivatable/NonExistentActivatable.java b/jdk/test/java/rmi/activation/Activatable/nonExistentActivatable/NonExistentActivatable.java index 76d68e9970a..625661ba432 100644 --- a/jdk/test/java/rmi/activation/Activatable/nonExistentActivatable/NonExistentActivatable.java +++ b/jdk/test/java/rmi/activation/Activatable/nonExistentActivatable/NonExistentActivatable.java @@ -23,16 +23,13 @@ /* @test * @bug 4115296 - * * @summary synopsis: NoSuchObjectException not thrown for non-existent * activatable objects * @author Ann Wollrath * * @library ../../../testlibrary * @build TestLibrary RMID ActivationLibrary - * @build ActivateMe - * @build NonExistentActivatable - * @build NonExistentActivatable_Stub + * ActivateMe NonExistentActivatable_Stub * @run main/othervm/policy=security.policy/timeout=240 NonExistentActivatable */ diff --git a/jdk/test/java/rmi/activation/Activatable/restartCrashedService/RestartCrashedService.java b/jdk/test/java/rmi/activation/Activatable/restartCrashedService/RestartCrashedService.java index 164a84209bb..b403c28441b 100644 --- a/jdk/test/java/rmi/activation/Activatable/restartCrashedService/RestartCrashedService.java +++ b/jdk/test/java/rmi/activation/Activatable/restartCrashedService/RestartCrashedService.java @@ -28,10 +28,7 @@ * @author Ann Wollrath * * @library ../../../testlibrary - * @build TestLibrary RMID JavaVM StreamPipe - * @build ActivateMe - * @build RestartCrashedService - * @build RestartCrashedService_Stub + * @build TestLibrary RMID ActivateMe RestartCrashedService_Stub * @run main/othervm/policy=security.policy/timeout=240 RestartCrashedService */ diff --git a/jdk/test/java/rmi/activation/Activatable/restartLatecomer/RestartLatecomer.java b/jdk/test/java/rmi/activation/Activatable/restartLatecomer/RestartLatecomer.java index 31750985e6d..c53053e7315 100644 --- a/jdk/test/java/rmi/activation/Activatable/restartLatecomer/RestartLatecomer.java +++ b/jdk/test/java/rmi/activation/Activatable/restartLatecomer/RestartLatecomer.java @@ -28,8 +28,7 @@ * * @library ../../../testlibrary * @build TestLibrary RMID ActivationLibrary - * @build RestartLatecomer - * @build RestartLatecomer_Stub + * RestartLatecomer RestartLatecomer_Stub * @run main/othervm/policy=security.policy/timeout=240 RestartLatecomer */ diff --git a/jdk/test/java/rmi/activation/Activatable/restartService/RestartService.java b/jdk/test/java/rmi/activation/Activatable/restartService/RestartService.java index a98ce832a2b..973916f083e 100644 --- a/jdk/test/java/rmi/activation/Activatable/restartService/RestartService.java +++ b/jdk/test/java/rmi/activation/Activatable/restartService/RestartService.java @@ -23,15 +23,11 @@ /* @test * @bug 4095165 4321151 - * @summary synopsis: activator should restart daemon services * @author Ann Wollrath * * @library ../../../testlibrary - * @build TestLibrary RMID ActivationLibrary - * @build ActivateMe - * @build RestartService - * @build RestartService_Stub + * @build TestLibrary RMID ActivationLibrary ActivateMe RestartService_Stub * @run main/othervm/policy=security.policy/timeout=240 RestartService */ diff --git a/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/ShutdownGracefully.java b/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/ShutdownGracefully.java index 162eb3861e4..64233bfd6f1 100644 --- a/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/ShutdownGracefully.java +++ b/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/ShutdownGracefully.java @@ -28,11 +28,8 @@ * @author Laird Dornin; code borrowed from Ann Wollrath * * @library ../../../testlibrary - * @build TestLibrary RMID JavaVM StreamPipe - * @build TestSecurityManager - * @build RegisteringActivatable - * @build ShutdownGracefully - * @build ShutdownGracefully_Stub + * @build TestLibrary RMID + * TestSecurityManager RegisteringActivatable ShutdownGracefully_Stub * @run main/othervm/policy=security.policy/timeout=700 ShutdownGracefully */ diff --git a/jdk/test/java/rmi/activation/Activatable/unregisterInactive/UnregisterInactive.java b/jdk/test/java/rmi/activation/Activatable/unregisterInactive/UnregisterInactive.java index 5d8c50c5641..412901ea742 100644 --- a/jdk/test/java/rmi/activation/Activatable/unregisterInactive/UnregisterInactive.java +++ b/jdk/test/java/rmi/activation/Activatable/unregisterInactive/UnregisterInactive.java @@ -23,16 +23,12 @@ /* @test * @bug 4115331 - * @summary synopsis: activatable object fails to go inactive after * unregister/inactive sequence. * @author Ann Wollrath * * @library ../../../testlibrary - * @build TestLibrary RMID ActivationLibrary - * @build ActivateMe - * @build UnregisterInactive - * @build UnregisterInactive_Stub + * @build TestLibrary RMID ActivationLibrary ActivateMe UnregisterInactive_Stub * @run main/othervm/policy=security.policy/timeout=240 UnregisterInactive */ diff --git a/jdk/test/java/rmi/activation/ActivateFailedException/activateFails/ActivateFails.java b/jdk/test/java/rmi/activation/ActivateFailedException/activateFails/ActivateFails.java index a5a5b0d374d..a7d7643977b 100644 --- a/jdk/test/java/rmi/activation/ActivateFailedException/activateFails/ActivateFails.java +++ b/jdk/test/java/rmi/activation/ActivateFailedException/activateFails/ActivateFails.java @@ -31,11 +31,8 @@ * @author Ann Wollrath * * @library ../../../testlibrary - * @build TestLibrary RMID JavaVM StreamPipe - * @build ActivateMe - * @build ActivateFails - * @build ActivateFails_Stub - * @build ShutdownThread + * @build TestLibrary RMID ActivationLibrary + * ActivateMe ActivateFails_Stub ShutdownThread * @run main/othervm/policy=security.policy/timeout=240 ActivateFails */ diff --git a/jdk/test/java/rmi/activation/ActivationGroup/downloadActivationGroup/DownloadActivationGroup.java b/jdk/test/java/rmi/activation/ActivationGroup/downloadActivationGroup/DownloadActivationGroup.java index f7f8643333c..880f1e8a8a6 100644 --- a/jdk/test/java/rmi/activation/ActivationGroup/downloadActivationGroup/DownloadActivationGroup.java +++ b/jdk/test/java/rmi/activation/ActivationGroup/downloadActivationGroup/DownloadActivationGroup.java @@ -33,9 +33,7 @@ * * @library ../../../testlibrary * @build TestLibrary RMID ActivationLibrary - * @build MyActivationGroupImpl - * @build DownloadActivationGroup - * @build DownloadActivationGroup_Stub + * DownloadActivationGroup MyActivationGroupImpl DownloadActivationGroup_Stub * @run main/othervm/policy=security.policy/timeout=240 DownloadActivationGroup */ diff --git a/jdk/test/java/rmi/activation/ActivationGroupDesc/checkDefaultGroupName/CheckDefaultGroupName.java b/jdk/test/java/rmi/activation/ActivationGroupDesc/checkDefaultGroupName/CheckDefaultGroupName.java index bd475029687..f37cbaeb79f 100644 --- a/jdk/test/java/rmi/activation/ActivationGroupDesc/checkDefaultGroupName/CheckDefaultGroupName.java +++ b/jdk/test/java/rmi/activation/ActivationGroupDesc/checkDefaultGroupName/CheckDefaultGroupName.java @@ -21,16 +21,15 @@ * questions. */ -/** +/* * @test * @bug 4252236 * @summary ActivationGroupDesc should not do early binding of default classname - * @library ../../../testlibrary - * - * @build CheckDefaultGroupName - * - * @run main CheckDefaultGroupName * @author Laird Dornin + * + * @library ../../../testlibrary + * @build TestLibrary + * @run main CheckDefaultGroupName */ import java.rmi.activation.*; diff --git a/jdk/test/java/rmi/activation/ActivationSystem/activeGroup/IdempotentActiveGroup.java b/jdk/test/java/rmi/activation/ActivationSystem/activeGroup/IdempotentActiveGroup.java index 41670ee1eb2..391a86273b1 100644 --- a/jdk/test/java/rmi/activation/ActivationSystem/activeGroup/IdempotentActiveGroup.java +++ b/jdk/test/java/rmi/activation/ActivationSystem/activeGroup/IdempotentActiveGroup.java @@ -23,15 +23,13 @@ /* @test * @bug 4720528 - * * @summary synopsis: (spec) ActivationSystem.activeGroup spec should be * relaxed (duplicate call to activeGroup with same instantiator and * incarnation should not throw ActivationException; it should succeed) * @author Ann Wollrath * * @library ../../../testlibrary - * @build TestLibrary RMID - * @build IdempotentActiveGroup + * @build TestLibrary RMID ActivationLibrary * @run main/othervm/policy=security.policy/timeout=480 IdempotentActiveGroup */ diff --git a/jdk/test/java/rmi/activation/ActivationSystem/modifyDescriptor/ModifyDescriptor.java b/jdk/test/java/rmi/activation/ActivationSystem/modifyDescriptor/ModifyDescriptor.java index 4f3d51e4646..19034e511a6 100644 --- a/jdk/test/java/rmi/activation/ActivationSystem/modifyDescriptor/ModifyDescriptor.java +++ b/jdk/test/java/rmi/activation/ActivationSystem/modifyDescriptor/ModifyDescriptor.java @@ -29,9 +29,8 @@ * @author Ann Wollrath * * @library ../../../testlibrary - * @build ActivateMe - * @build ModifyDescriptor - * @build ModifyDescriptor_Stub + * @build TestLibrary RMID ActivationLibrary + * ActivateMe ModifyDescriptor_Stub * @run main/othervm/policy=security.policy/timeout=240 ModifyDescriptor */ diff --git a/jdk/test/java/rmi/activation/ActivationSystem/stubClassesPermitted/StubClassesPermitted.java b/jdk/test/java/rmi/activation/ActivationSystem/stubClassesPermitted/StubClassesPermitted.java index cc7810407eb..d987f93b238 100644 --- a/jdk/test/java/rmi/activation/ActivationSystem/stubClassesPermitted/StubClassesPermitted.java +++ b/jdk/test/java/rmi/activation/ActivationSystem/stubClassesPermitted/StubClassesPermitted.java @@ -24,14 +24,11 @@ /* @test * @bug 4179055 * @summary Some java apps need to have access to read "accessClassInPackage.sun.rmi.server" - * * @author Laird Dornin * * @library ../../../testlibrary - * @build TestLibrary RMID JavaVM StreamPipe ActivationLibrary - * @build CanCreateStubs - * @build StubClassesPermitted - * @build StubClassesPermitted_Stub + * @build TestLibrary RMID ActivationLibrary + * CanCreateStubs StubClassesPermitted_Stub * @run main/othervm/policy=security.policy/secure=java.lang.SecurityManager/timeout=240 StubClassesPermitted */ diff --git a/jdk/test/java/rmi/activation/ActivationSystem/unregisterGroup/UnregisterGroup.java b/jdk/test/java/rmi/activation/ActivationSystem/unregisterGroup/UnregisterGroup.java index a2b4076495a..59fee9da723 100644 --- a/jdk/test/java/rmi/activation/ActivationSystem/unregisterGroup/UnregisterGroup.java +++ b/jdk/test/java/rmi/activation/ActivationSystem/unregisterGroup/UnregisterGroup.java @@ -24,16 +24,12 @@ /* @test * @bug 4134233 * @bug 4213186 - * * @summary synopsis: ActivationSystem.unregisterGroup should unregister objects in group * @author Ann Wollrath * * @library ../../../testlibrary - * @build TestLibrary RMID JavaVM StreamPipe - * @build ActivateMe CallbackInterface - * @build UnregisterGroup - * @build UnregisterGroup_Stub - * @build Callback_Stub + * @build TestLibrary RMID ActivationLibrary + * ActivateMe CallbackInterface UnregisterGroup_Stub Callback_Stub * @run main/othervm/policy=security.policy/timeout=480 UnregisterGroup */ diff --git a/jdk/test/java/rmi/activation/CommandEnvironment/NullOptions.java b/jdk/test/java/rmi/activation/CommandEnvironment/NullOptions.java index 3ef97e8d77c..a1ec946c21b 100644 --- a/jdk/test/java/rmi/activation/CommandEnvironment/NullOptions.java +++ b/jdk/test/java/rmi/activation/CommandEnvironment/NullOptions.java @@ -27,7 +27,6 @@ * ActivationGroupDesc.CommandEnvironment * @author Ann Wollrath * - * @build NullOptions * @run main/othervm/timeout=240 NullOptions */ diff --git a/jdk/test/java/rmi/activation/CommandEnvironment/SetChildEnv.java b/jdk/test/java/rmi/activation/CommandEnvironment/SetChildEnv.java index d89450d6151..7b1a9688ad4 100644 --- a/jdk/test/java/rmi/activation/CommandEnvironment/SetChildEnv.java +++ b/jdk/test/java/rmi/activation/CommandEnvironment/SetChildEnv.java @@ -35,9 +35,10 @@ * @author Adrian Colley * * @library ../../testlibrary - * @build TestLibrary RMID JavaVM StreamPipe - * @build Eliza Retireable Doctor Doctor_Stub SetChildEnv - * @run main/othervm/timeout=240/policy=security.policy -Djava.compiler=NONE SetChildEnv + * @build TestLibrary RMID ActivationLibrary + * Eliza Retireable Doctor Doctor_Stub + * @run main/othervm/timeout=240/policy=security.policy + * -Djava.compiler=NONE SetChildEnv */ import java.rmi.*; import java.util.Properties; diff --git a/jdk/test/java/rmi/activation/checkusage/CheckUsage.java b/jdk/test/java/rmi/activation/checkusage/CheckUsage.java index 66ff7ad9445..2b514e1f370 100644 --- a/jdk/test/java/rmi/activation/checkusage/CheckUsage.java +++ b/jdk/test/java/rmi/activation/checkusage/CheckUsage.java @@ -25,7 +25,7 @@ * @bug 4259564 * * @library ../../testlibrary - * @build TestLibrary JavaVM CheckUsage + * @build TestLibrary JavaVM * @run main/othervm CheckUsage */ diff --git a/jdk/test/java/rmi/activation/log/LogTest.java b/jdk/test/java/rmi/activation/log/LogTest.java index 2e503b916a4..53efeb49ced 100644 --- a/jdk/test/java/rmi/activation/log/LogTest.java +++ b/jdk/test/java/rmi/activation/log/LogTest.java @@ -29,7 +29,6 @@ * boundaries * @author Ann Wollrath * - * @build LogTest * @run main/othervm/timeout=240 LogTest */ diff --git a/jdk/test/java/rmi/activation/rmidViaInheritedChannel/InheritedChannelNotServerSocket.java b/jdk/test/java/rmi/activation/rmidViaInheritedChannel/InheritedChannelNotServerSocket.java index 345aca33a60..4611a83bda5 100644 --- a/jdk/test/java/rmi/activation/rmidViaInheritedChannel/InheritedChannelNotServerSocket.java +++ b/jdk/test/java/rmi/activation/rmidViaInheritedChannel/InheritedChannelNotServerSocket.java @@ -29,8 +29,7 @@ * @author Peter Jones * * @library ../../testlibrary - * @build RMID ActivationLibrary - * @build InheritedChannelNotServerSocket + * @build TestLibrary RMID ActivationLibrary * @run main/othervm/timeout=240 InheritedChannelNotServerSocket */ diff --git a/jdk/test/java/rmi/activation/rmidViaInheritedChannel/RmidViaInheritedChannel.java b/jdk/test/java/rmi/activation/rmidViaInheritedChannel/RmidViaInheritedChannel.java index 008b391acc4..be9234d2fb9 100644 --- a/jdk/test/java/rmi/activation/rmidViaInheritedChannel/RmidViaInheritedChannel.java +++ b/jdk/test/java/rmi/activation/rmidViaInheritedChannel/RmidViaInheritedChannel.java @@ -27,9 +27,7 @@ * @author Ann Wollrath * * @library ../../testlibrary - * @build RMID ActivationLibrary - * @build RmidViaInheritedChannel - * @build TestLibrary + * @build TestLibrary RMID ActivationLibrary * @run main/othervm/timeout=240 RmidViaInheritedChannel */ diff --git a/jdk/test/java/rmi/dgc/VMID/CheckVMID.java b/jdk/test/java/rmi/dgc/VMID/CheckVMID.java index dcdc9fd2ccf..0b69ff4cc30 100644 --- a/jdk/test/java/rmi/dgc/VMID/CheckVMID.java +++ b/jdk/test/java/rmi/dgc/VMID/CheckVMID.java @@ -30,7 +30,7 @@ * @author Ann Wollrath * * @library ../../testlibrary - * @build CheckVMID + * @build TestLibrary * @run main/othervm/policy=security.policy CheckVMID */ diff --git a/jdk/test/java/rmi/dgc/dgcAckFailure/DGCAckFailure.java b/jdk/test/java/rmi/dgc/dgcAckFailure/DGCAckFailure.java index c416063113a..6a47245dec9 100644 --- a/jdk/test/java/rmi/dgc/dgcAckFailure/DGCAckFailure.java +++ b/jdk/test/java/rmi/dgc/dgcAckFailure/DGCAckFailure.java @@ -30,8 +30,7 @@ * rather than pinning it indefinitely. * @author Peter Jones * - * @build DGCAckFailure - * @build DGCAckFailure_Stub + * @build DGCAckFailure DGCAckFailure_Stub * @run main/othervm DGCAckFailure */ diff --git a/jdk/test/java/rmi/dgc/dgcImplInsulation/DGCImplInsulation.java b/jdk/test/java/rmi/dgc/dgcImplInsulation/DGCImplInsulation.java index 246c2b541a3..4043268838d 100644 --- a/jdk/test/java/rmi/dgc/dgcImplInsulation/DGCImplInsulation.java +++ b/jdk/test/java/rmi/dgc/dgcImplInsulation/DGCImplInsulation.java @@ -31,9 +31,7 @@ * @author Peter Jones * * @library ../../testlibrary - * @build TestLibrary - * @build DGCImplInsulation - * @build DGCImplInsulation_Stub + * @build TestLibrary DGCImplInsulation_Stub * @run main/othervm/policy=security.policy DGCImplInsulation */ diff --git a/jdk/test/java/rmi/dgc/retryDirtyCalls/RetryDirtyCalls.java b/jdk/test/java/rmi/dgc/retryDirtyCalls/RetryDirtyCalls.java index 10cb15f30eb..b2f0af6506b 100644 --- a/jdk/test/java/rmi/dgc/retryDirtyCalls/RetryDirtyCalls.java +++ b/jdk/test/java/rmi/dgc/retryDirtyCalls/RetryDirtyCalls.java @@ -29,8 +29,7 @@ * renewing that lease at all after the first failure. * @author Peter Jones (inspired by Adrian Colley's test case in 4268258) * - * @build RetryDirtyCalls - * @build RetryDirtyCalls_Stub + * @build RetryDirtyCalls RetryDirtyCalls_Stub * @run main/othervm RetryDirtyCalls */ diff --git a/jdk/test/java/rmi/invalidName/InvalidName.java b/jdk/test/java/rmi/invalidName/InvalidName.java index 8d522f51592..74da1a5d53d 100644 --- a/jdk/test/java/rmi/invalidName/InvalidName.java +++ b/jdk/test/java/rmi/invalidName/InvalidName.java @@ -32,7 +32,7 @@ * @author Laird Dornin * * @library ../testlibrary - * @build InvalidName + * @build TestLibrary * @run main/othervm InvalidName */ diff --git a/jdk/test/java/rmi/registry/altSecurityManager/AltSecurityManager.java b/jdk/test/java/rmi/registry/altSecurityManager/AltSecurityManager.java index 15b98fc851b..08d030ec876 100644 --- a/jdk/test/java/rmi/registry/altSecurityManager/AltSecurityManager.java +++ b/jdk/test/java/rmi/registry/altSecurityManager/AltSecurityManager.java @@ -27,8 +27,7 @@ * @author Laird Dornin * * @library ../../testlibrary - * @build StreamPipe TestParams TestLibrary JavaVM RMID - * @build AltSecurityManager TestSecurityManager + * @build TestLibrary JavaVM RMID TestSecurityManager * @run main/othervm AltSecurityManager */ diff --git a/jdk/test/java/rmi/registry/checkusage/CheckUsage.java b/jdk/test/java/rmi/registry/checkusage/CheckUsage.java index 71deb55ad99..19dac5b600a 100644 --- a/jdk/test/java/rmi/registry/checkusage/CheckUsage.java +++ b/jdk/test/java/rmi/registry/checkusage/CheckUsage.java @@ -27,7 +27,7 @@ * @author Laird Dornin * * @library ../../testlibrary - * @build TestLibrary JavaVM CheckUsage + * @build TestLibrary JavaVM * @run main/othervm CheckUsage */ diff --git a/jdk/test/java/rmi/registry/classPathCodebase/ClassPathCodebase.java b/jdk/test/java/rmi/registry/classPathCodebase/ClassPathCodebase.java index 9e8cbba8bf6..99ac5f091a6 100644 --- a/jdk/test/java/rmi/registry/classPathCodebase/ClassPathCodebase.java +++ b/jdk/test/java/rmi/registry/classPathCodebase/ClassPathCodebase.java @@ -30,7 +30,7 @@ * @author Peter Jones * * @library ../../testlibrary - * @build ClassPathCodebase Dummy TestLibrary + * @build TestLibrary Dummy * @run main/othervm/policy=security.policy ClassPathCodebase */ diff --git a/jdk/test/java/rmi/registry/interfaceHash/InterfaceHash.java b/jdk/test/java/rmi/registry/interfaceHash/InterfaceHash.java index 77824125719..2eba1d6ac1a 100644 --- a/jdk/test/java/rmi/registry/interfaceHash/InterfaceHash.java +++ b/jdk/test/java/rmi/registry/interfaceHash/InterfaceHash.java @@ -36,9 +36,7 @@ * * @author Peter Jones * @library ../../testlibrary - * @build InterfaceHash - * @build ReferenceRegistryStub - * @build TestLibrary + * @build TestLibrary ReferenceRegistryStub * @run main/othervm InterfaceHash */ diff --git a/jdk/test/java/rmi/registry/multipleRegistries/MultipleRegistries.java b/jdk/test/java/rmi/registry/multipleRegistries/MultipleRegistries.java index e75a60989d7..1945ebe8db3 100644 --- a/jdk/test/java/rmi/registry/multipleRegistries/MultipleRegistries.java +++ b/jdk/test/java/rmi/registry/multipleRegistries/MultipleRegistries.java @@ -28,7 +28,6 @@ * * @library ../../testlibrary * @build TestLibrary - * @build MultipleRegistries * @run main/othervm/timeout=240 MultipleRegistries */ diff --git a/jdk/test/java/rmi/registry/readTest/readTest.sh b/jdk/test/java/rmi/registry/readTest/readTest.sh index d7f1568f62c..5fda0a5a314 100644 --- a/jdk/test/java/rmi/registry/readTest/readTest.sh +++ b/jdk/test/java/rmi/registry/readTest/readTest.sh @@ -76,7 +76,7 @@ case "$OS" in ;; esac # trailing / after code base is important for rmi codebase property. -${TESTJAVA}${FS}bin${FS}java -cp $TEST_CLASSPATH -Djava.rmi.server.codebase=${FILEURL}$CODEBASE/ readTest > OUT.TXT 2>&1 & +${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -cp $TEST_CLASSPATH -Djava.rmi.server.codebase=${FILEURL}$CODEBASE/ readTest > OUT.TXT 2>&1 & TEST_PID=$! #bulk of testcase - let it run for a while sleep 5 diff --git a/jdk/test/java/rmi/registry/reexport/Reexport.java b/jdk/test/java/rmi/registry/reexport/Reexport.java index 042088e65af..c209f7c55b8 100644 --- a/jdk/test/java/rmi/registry/reexport/Reexport.java +++ b/jdk/test/java/rmi/registry/reexport/Reexport.java @@ -25,9 +25,7 @@ * @bug 4120329 * @summary RMI registry creation is impossible if first attempt fails. * @library ../../testlibrary - * @build StreamPipe TestParams TestLibrary JavaVM - * @build RegistryRunner RegistryRunner_Stub - * @build Reexport + * @build TestLibrary JavaVM RegistryRunner RegistryRunner_Stub * @run main/othervm Reexport */ diff --git a/jdk/test/java/rmi/reliability/benchmark/runRmiBench.sh b/jdk/test/java/rmi/reliability/benchmark/runRmiBench.sh index cfa23f77811..98a31d1ddd1 100644 --- a/jdk/test/java/rmi/reliability/benchmark/runRmiBench.sh +++ b/jdk/test/java/rmi/reliability/benchmark/runRmiBench.sh @@ -27,20 +27,20 @@ # used to run the test under JTREG. # # @build bench.BenchInfo bench.HtmlReporter bench.Util bench.Benchmark -# @build bench.Reporter bench.XmlReporter bench.ConfigFormatException -# @build bench.Harness bench.TextReporter bench.rmi.BenchServer -# @build bench.rmi.DoubleArrayCalls bench.rmi.LongCalls bench.rmi.ShortCalls -# @build bench.rmi.BenchServerImpl bench.rmi.DoubleCalls -# @build bench.rmi.Main bench.rmi.SmallObjTreeCalls -# @build bench.rmi.BooleanArrayCalls bench.rmi.ExceptionCalls -# @build bench.rmi.NullCalls bench.rmi.BooleanCalls bench.rmi.ExportObjs -# @build bench.rmi.ObjArrayCalls bench.rmi.ByteArrayCalls -# @build bench.rmi.FloatArrayCalls bench.rmi.ObjTreeCalls -# @build bench.rmi.ByteCalls bench.rmi.FloatCalls bench.rmi.ProxyArrayCalls -# @build bench.rmi.CharArrayCalls bench.rmi.IntArrayCalls -# @build bench.rmi.RemoteObjArrayCalls bench.rmi.CharCalls bench.rmi.IntCalls -# @build bench.rmi.ClassLoading bench.rmi.LongArrayCalls -# @build bench.rmi.ShortArrayCalls bench.rmi.altroot.Node +# bench.Reporter bench.XmlReporter bench.ConfigFormatException +# bench.Harness bench.TextReporter bench.rmi.BenchServer +# bench.rmi.DoubleArrayCalls bench.rmi.LongCalls bench.rmi.ShortCalls +# bench.rmi.BenchServerImpl bench.rmi.DoubleCalls +# bench.rmi.Main bench.rmi.SmallObjTreeCalls +# bench.rmi.BooleanArrayCalls bench.rmi.ExceptionCalls +# bench.rmi.NullCalls bench.rmi.BooleanCalls bench.rmi.ExportObjs +# bench.rmi.ObjArrayCalls bench.rmi.ByteArrayCalls +# bench.rmi.FloatArrayCalls bench.rmi.ObjTreeCalls +# bench.rmi.ByteCalls bench.rmi.FloatCalls bench.rmi.ProxyArrayCalls +# bench.rmi.CharArrayCalls bench.rmi.IntArrayCalls +# bench.rmi.RemoteObjArrayCalls bench.rmi.CharCalls bench.rmi.IntCalls +# bench.rmi.ClassLoading bench.rmi.LongArrayCalls +# bench.rmi.ShortArrayCalls bench.rmi.altroot.Node # # @run shell/timeout=1800 runRmiBench.sh # diff --git a/jdk/test/java/rmi/reliability/benchmark/runSerialBench.sh b/jdk/test/java/rmi/reliability/benchmark/runSerialBench.sh index aac0d3ff768..82a2837bcff 100644 --- a/jdk/test/java/rmi/reliability/benchmark/runSerialBench.sh +++ b/jdk/test/java/rmi/reliability/benchmark/runSerialBench.sh @@ -51,7 +51,7 @@ echo "Starting serialization benchmark " $TESTJAVA/bin/java \ - -server \ + ${TESTVMOPTS} \ -cp $TESTCLASSES \ bench.serial.Main \ -c $TESTSRC/bench/serial/jtreg-config & diff --git a/jdk/test/java/rmi/reliability/juicer/AppleUserImpl.java b/jdk/test/java/rmi/reliability/juicer/AppleUserImpl.java index 2ed30c65ab8..70b187e25bc 100644 --- a/jdk/test/java/rmi/reliability/juicer/AppleUserImpl.java +++ b/jdk/test/java/rmi/reliability/juicer/AppleUserImpl.java @@ -55,11 +55,10 @@ * has been reached. * * @library ../../testlibrary - * - * @build Apple AppleEvent AppleImpl AppleUserImpl - * @build Orange OrangeEcho OrangeEchoImpl OrangeImpl - * @build ApplicationServer * @build TestLibrary + * Apple AppleEvent AppleImpl + * Orange OrangeEcho OrangeEchoImpl OrangeImpl + * ApplicationServer * * @run main/othervm/policy=security.policy AppleUserImpl -seconds 30 * diff --git a/jdk/test/java/rmi/server/ObjID/randomIDs/RandomIDs.java b/jdk/test/java/rmi/server/ObjID/randomIDs/RandomIDs.java index 9c20ab40dfb..ebe7192f382 100644 --- a/jdk/test/java/rmi/server/ObjID/randomIDs/RandomIDs.java +++ b/jdk/test/java/rmi/server/ObjID/randomIDs/RandomIDs.java @@ -30,7 +30,6 @@ * ObjID() should still generate sequential object numbers. * @author Peter Jones * - * @build RandomIDs * @run main/othervm RandomIDs random * @run main/othervm -Djava.rmi.server.randomIDs=true RandomIDs random * @run main/othervm -Djava.rmi.server.randomIDs=false RandomIDs sequential diff --git a/jdk/test/java/rmi/server/RMIClassLoader/delegateBeforePermissionCheck/DelegateBeforePermissionCheck.java b/jdk/test/java/rmi/server/RMIClassLoader/delegateBeforePermissionCheck/DelegateBeforePermissionCheck.java index fba4939a35c..6187f0cb17e 100644 --- a/jdk/test/java/rmi/server/RMIClassLoader/delegateBeforePermissionCheck/DelegateBeforePermissionCheck.java +++ b/jdk/test/java/rmi/server/RMIClassLoader/delegateBeforePermissionCheck/DelegateBeforePermissionCheck.java @@ -33,9 +33,7 @@ * @author Peter Jones * * @library ../../../testlibrary - * @build TestLibrary - * @build DelegateBeforePermissionCheck - * @build Foo + * @build TestLibrary Foo * @run main/othervm DelegateBeforePermissionCheck */ diff --git a/jdk/test/java/rmi/server/RMIClassLoader/delegateToContextLoader/DelegateToContextLoader.java b/jdk/test/java/rmi/server/RMIClassLoader/delegateToContextLoader/DelegateToContextLoader.java index 51b5bd4f88f..7ae4c5ee9ba 100644 --- a/jdk/test/java/rmi/server/RMIClassLoader/delegateToContextLoader/DelegateToContextLoader.java +++ b/jdk/test/java/rmi/server/RMIClassLoader/delegateToContextLoader/DelegateToContextLoader.java @@ -29,7 +29,7 @@ * @author Peter Jones * * @library ../../../testlibrary - * @build DelegateToContextLoader Dummy + * @build TestLibrary Dummy * @run main/othervm/policy=security.policy/timeout=120 DelegateToContextLoader */ diff --git a/jdk/test/java/rmi/server/RMIClassLoader/downloadArrayClass/DownloadArrayClass.java b/jdk/test/java/rmi/server/RMIClassLoader/downloadArrayClass/DownloadArrayClass.java index 34a21bd4651..9df187ab3a3 100644 --- a/jdk/test/java/rmi/server/RMIClassLoader/downloadArrayClass/DownloadArrayClass.java +++ b/jdk/test/java/rmi/server/RMIClassLoader/downloadArrayClass/DownloadArrayClass.java @@ -31,11 +31,7 @@ * @author Peter Jones * * @library ../../../testlibrary - * @build TestLibrary - * @build Receiver - * @build DownloadArrayClass - * @build DownloadArrayClass_Stub - * @build Foo + * @build TestLibrary Receiver DownloadArrayClass_Stub Foo * @run main/othervm/policy=security.policy DownloadArrayClass */ diff --git a/jdk/test/java/rmi/server/RMIClassLoader/getClassAnnotation/NullClass.java b/jdk/test/java/rmi/server/RMIClassLoader/getClassAnnotation/NullClass.java index 0a0cfb70e67..5167fc40c2b 100644 --- a/jdk/test/java/rmi/server/RMIClassLoader/getClassAnnotation/NullClass.java +++ b/jdk/test/java/rmi/server/RMIClassLoader/getClassAnnotation/NullClass.java @@ -29,7 +29,6 @@ * * @library ../../../testlibrary * @build TestLibrary - * @build NullClass * @run main/othervm NullClass */ diff --git a/jdk/test/java/rmi/server/RMIClassLoader/getClassLoader/GetClassLoader.java b/jdk/test/java/rmi/server/RMIClassLoader/getClassLoader/GetClassLoader.java index f54a5cf0b9e..10a9cc9b4ac 100644 --- a/jdk/test/java/rmi/server/RMIClassLoader/getClassLoader/GetClassLoader.java +++ b/jdk/test/java/rmi/server/RMIClassLoader/getClassLoader/GetClassLoader.java @@ -29,9 +29,7 @@ * @author Ann Wollrath * * @library ../../../testlibrary - * @build TestLibrary - * @build GetClassLoader - * @build Foo + * @build TestLibrary Foo * @run main/othervm/policy=security.policy GetClassLoader */ diff --git a/jdk/test/java/rmi/server/RMIClassLoader/loadProxyClasses/LoadProxyClasses.java b/jdk/test/java/rmi/server/RMIClassLoader/loadProxyClasses/LoadProxyClasses.java index 4feed266e96..6d29cb2468f 100644 --- a/jdk/test/java/rmi/server/RMIClassLoader/loadProxyClasses/LoadProxyClasses.java +++ b/jdk/test/java/rmi/server/RMIClassLoader/loadProxyClasses/LoadProxyClasses.java @@ -30,8 +30,8 @@ * @author Laird Dornin * * @library ../../../testlibrary - * @build TestLibrary FnnClass FnnUnmarshal LoadProxyClasses NonpublicInterface - * @build NonpublicInterface1 PublicInterface PublicInterface1 + * @build TestLibrary FnnClass FnnUnmarshal NonpublicInterface + * NonpublicInterface1 PublicInterface PublicInterface1 * @run main/othervm/policy=security.policy LoadProxyClasses */ diff --git a/jdk/test/java/rmi/server/RMIClassLoader/noSecurityManager/NoSecurityManager.java b/jdk/test/java/rmi/server/RMIClassLoader/noSecurityManager/NoSecurityManager.java index 182db1c69cb..93a33b91dd2 100644 --- a/jdk/test/java/rmi/server/RMIClassLoader/noSecurityManager/NoSecurityManager.java +++ b/jdk/test/java/rmi/server/RMIClassLoader/noSecurityManager/NoSecurityManager.java @@ -30,7 +30,7 @@ * been used for the RMI class loader instance. * @author Peter Jones * - * @build NoSecurityManager Dummy LocalDummy + * @build Dummy LocalDummy * @run main/othervm/timeout=120 NoSecurityManager */ diff --git a/jdk/test/java/rmi/server/RMIClassLoader/spi/ContextInsulation.java b/jdk/test/java/rmi/server/RMIClassLoader/spi/ContextInsulation.java index 56cd08d2bc1..de3d79b60f6 100644 --- a/jdk/test/java/rmi/server/RMIClassLoader/spi/ContextInsulation.java +++ b/jdk/test/java/rmi/server/RMIClassLoader/spi/ContextInsulation.java @@ -30,11 +30,7 @@ * @author Peter Jones * * @library ../../../testlibrary - * @build TestLibrary - * @build ContextInsulation - * @build ServiceConfiguration - * @build TestProvider - * @build TestProvider2 + * @build TestLibrary ServiceConfiguration TestProvider TestProvider2 * @run main/othervm/policy=security.policy ContextInsulation */ diff --git a/jdk/test/java/rmi/server/RMIClassLoader/spi/DefaultProperty.java b/jdk/test/java/rmi/server/RMIClassLoader/spi/DefaultProperty.java index 4cb8169ab8a..f91ef3d1893 100644 --- a/jdk/test/java/rmi/server/RMIClassLoader/spi/DefaultProperty.java +++ b/jdk/test/java/rmi/server/RMIClassLoader/spi/DefaultProperty.java @@ -29,10 +29,7 @@ * @author Peter Jones * * @library ../../../testlibrary - * @build TestLibrary - * @build DefaultProperty - * @build ServiceConfiguration - * @build Foo + * @build TestLibrary ServiceConfiguration Foo * @run main/othervm/policy=security.policy DefaultProperty */ diff --git a/jdk/test/java/rmi/server/RMIClassLoader/spi/Installed.java b/jdk/test/java/rmi/server/RMIClassLoader/spi/Installed.java index 23ce956b334..d32a8af596d 100644 --- a/jdk/test/java/rmi/server/RMIClassLoader/spi/Installed.java +++ b/jdk/test/java/rmi/server/RMIClassLoader/spi/Installed.java @@ -29,11 +29,7 @@ * @author Peter Jones * * @library ../../../testlibrary - * @build TestLibrary - * @build Installed - * @build ServiceConfiguration - * @build TestProvider - * @build TestProvider2 + * @build TestLibrary ServiceConfiguration TestProvider TestProvider2 * @run main/othervm/policy=security.policy Installed */ diff --git a/jdk/test/java/rmi/server/RMIClassLoader/spi/InvalidProperty.java b/jdk/test/java/rmi/server/RMIClassLoader/spi/InvalidProperty.java index e7b157c6480..d41cef1d924 100644 --- a/jdk/test/java/rmi/server/RMIClassLoader/spi/InvalidProperty.java +++ b/jdk/test/java/rmi/server/RMIClassLoader/spi/InvalidProperty.java @@ -29,9 +29,7 @@ * @author Peter Jones * * @library ../../../testlibrary - * @build TestLibrary - * @build InvalidProperty - * @build ServiceConfiguration + * @build TestLibrary ServiceConfiguration * @run main/othervm/policy=security.policy InvalidProperty */ diff --git a/jdk/test/java/rmi/server/RMIClassLoader/spi/Property.java b/jdk/test/java/rmi/server/RMIClassLoader/spi/Property.java index 427e5a3160e..6113a6ecb7b 100644 --- a/jdk/test/java/rmi/server/RMIClassLoader/spi/Property.java +++ b/jdk/test/java/rmi/server/RMIClassLoader/spi/Property.java @@ -29,10 +29,7 @@ * @author Peter Jones * * @library ../../../testlibrary - * @build TestLibrary - * @build Property - * @build ServiceConfiguration - * @build TestProvider + * @build TestLibrary ServiceConfiguration TestProvider * @run main/othervm/policy=security.policy Property */ diff --git a/jdk/test/java/rmi/server/RMIClassLoader/useCodebaseOnly/UseCodebaseOnly.java b/jdk/test/java/rmi/server/RMIClassLoader/useCodebaseOnly/UseCodebaseOnly.java index cd79782c46e..dc808370526 100644 --- a/jdk/test/java/rmi/server/RMIClassLoader/useCodebaseOnly/UseCodebaseOnly.java +++ b/jdk/test/java/rmi/server/RMIClassLoader/useCodebaseOnly/UseCodebaseOnly.java @@ -31,12 +31,7 @@ * @author Peter Jones * * @library ../../../testlibrary - * @build TestLibrary - * @build Receiver - * @build UseCodebaseOnly - * @build UseCodebaseOnly_Stub - * @build Foo - * @build Bar + * @build TestLibrary Receiver UseCodebaseOnly_Stub Foo Bar * @run main/othervm/policy=security.policy UseCodebaseOnly */ diff --git a/jdk/test/java/rmi/server/RMIClassLoader/useGetURLs/UseGetURLs.java b/jdk/test/java/rmi/server/RMIClassLoader/useGetURLs/UseGetURLs.java index 295b9944a77..d80907e0a2b 100644 --- a/jdk/test/java/rmi/server/RMIClassLoader/useGetURLs/UseGetURLs.java +++ b/jdk/test/java/rmi/server/RMIClassLoader/useGetURLs/UseGetURLs.java @@ -30,8 +30,7 @@ * @author Peter Jones * * @library ../../../testlibrary - * @build TestLibrary - * @build UseGetURLs Dummy + * @build TestLibrary Dummy * @run main/othervm/policy=security.policy/timeout=120 UseGetURLs */ diff --git a/jdk/test/java/rmi/server/RMISocketFactory/useSocketFactory/activatable/UseCustomSocketFactory.java b/jdk/test/java/rmi/server/RMISocketFactory/useSocketFactory/activatable/UseCustomSocketFactory.java index 5868c583b28..5f032ec58cf 100644 --- a/jdk/test/java/rmi/server/RMISocketFactory/useSocketFactory/activatable/UseCustomSocketFactory.java +++ b/jdk/test/java/rmi/server/RMISocketFactory/useSocketFactory/activatable/UseCustomSocketFactory.java @@ -28,11 +28,7 @@ * @author Ann Wollrath * * @library ../../../../testlibrary - * @build Echo - * @build EchoImpl - * @build EchoImpl_Stub - * @build UseCustomSocketFactory - * @build TestLibrary + * @build TestLibrary Echo EchoImpl EchoImpl_Stub * @run main/othervm/policy=security.policy/timeout=360 UseCustomSocketFactory */ diff --git a/jdk/test/java/rmi/server/RMISocketFactory/useSocketFactory/registry/UseCustomSocketFactory.java b/jdk/test/java/rmi/server/RMISocketFactory/useSocketFactory/registry/UseCustomSocketFactory.java index ba610688369..774e823e857 100644 --- a/jdk/test/java/rmi/server/RMISocketFactory/useSocketFactory/registry/UseCustomSocketFactory.java +++ b/jdk/test/java/rmi/server/RMISocketFactory/useSocketFactory/registry/UseCustomSocketFactory.java @@ -29,12 +29,7 @@ * @author Laird Dornin; code borrowed from Ann Wollrath * * @library ../../../../testlibrary - * @build Hello - * @build HelloImpl - * @build HelloImpl_Stub - * @build TestLibrary - * @build UseCustomSocketFactory - * @build Compress + * @build TestLibrary Compress Hello HelloImpl HelloImpl_Stub * @run main/othervm/policy=security.policy/timeout=240 UseCustomSocketFactory */ diff --git a/jdk/test/java/rmi/server/RMISocketFactory/useSocketFactory/unicast/UseCustomSocketFactory.java b/jdk/test/java/rmi/server/RMISocketFactory/useSocketFactory/unicast/UseCustomSocketFactory.java index 13766abd848..06571df79c1 100644 --- a/jdk/test/java/rmi/server/RMISocketFactory/useSocketFactory/unicast/UseCustomSocketFactory.java +++ b/jdk/test/java/rmi/server/RMISocketFactory/useSocketFactory/unicast/UseCustomSocketFactory.java @@ -29,11 +29,7 @@ * @author Ann Wollrath * * @library ../../../../testlibrary - * @build TestLibrary RMID JavaVM StreamPipe - * @build Echo - * @build EchoImpl - * @build EchoImpl_Stub - * @build UseCustomSocketFactory + * @build TestLibrary RMID JavaVM Echo EchoImpl EchoImpl_Stub * @run main/othervm/policy=security.policy/timeout=120 UseCustomSocketFactory */ diff --git a/jdk/test/java/rmi/server/RemoteObject/notExtending/NotExtending.java b/jdk/test/java/rmi/server/RemoteObject/notExtending/NotExtending.java index 0023fc5f0c1..ef524a4dd8a 100644 --- a/jdk/test/java/rmi/server/RemoteObject/notExtending/NotExtending.java +++ b/jdk/test/java/rmi/server/RemoteObject/notExtending/NotExtending.java @@ -29,9 +29,7 @@ * (specifically: stubs) that contain the instance's RemoteRef. * @author Peter Jones * - * @build NotExtending - * @build NotExtending_Stub - * @build NotExtending_Skel + * @build NotExtending_Stub NotExtending_Skel * @run main/othervm/timeout=240 NotExtending */ diff --git a/jdk/test/java/rmi/server/RemoteObject/verifyRemoteEquals/VerifyRemoteEquals.java b/jdk/test/java/rmi/server/RemoteObject/verifyRemoteEquals/VerifyRemoteEquals.java index 8b6bccab9a8..b89e3625e3d 100644 --- a/jdk/test/java/rmi/server/RemoteObject/verifyRemoteEquals/VerifyRemoteEquals.java +++ b/jdk/test/java/rmi/server/RemoteObject/verifyRemoteEquals/VerifyRemoteEquals.java @@ -21,16 +21,16 @@ * questions. */ -/** +/* * @test * @bug 4251010 * @summary equals does not works on stub objects created with * custom socket AndFactory - * @library ../../../testlibrary - * - * @build VerifyRemoteEquals - * @run main/othervm/timeout=40 VerifyRemoteEquals * @author Laird Dornin + * + * @library ../../../testlibrary + * @build TestLibrary + * @run main/othervm/timeout=40 VerifyRemoteEquals */ import java.io.*; diff --git a/jdk/test/java/rmi/server/RemoteServer/AddrInUse.java b/jdk/test/java/rmi/server/RemoteServer/AddrInUse.java index 9ab8e50d65b..34e343b6193 100644 --- a/jdk/test/java/rmi/server/RemoteServer/AddrInUse.java +++ b/jdk/test/java/rmi/server/RemoteServer/AddrInUse.java @@ -26,8 +26,6 @@ * @summary retryServerSocket should not retry on BindException * @author Ann Wollrath * - * @library ../../testlibrary - * @build AddrInUse * @run main/othervm AddrInUse */ diff --git a/jdk/test/java/rmi/server/UnicastRemoteObject/changeHostName/ChangeHostName.java b/jdk/test/java/rmi/server/UnicastRemoteObject/changeHostName/ChangeHostName.java index 0716c1a9b1e..523c3a08f4a 100644 --- a/jdk/test/java/rmi/server/UnicastRemoteObject/changeHostName/ChangeHostName.java +++ b/jdk/test/java/rmi/server/UnicastRemoteObject/changeHostName/ChangeHostName.java @@ -31,8 +31,7 @@ * * @author Ann Wollrath * - * @build ChangeHostName - * @build ChangeHostName_Stub + * @build ChangeHostName ChangeHostName_Stub * @run main/othervm ChangeHostName */ diff --git a/jdk/test/java/rmi/server/UnicastRemoteObject/exportObject/GcDuringExport.java b/jdk/test/java/rmi/server/UnicastRemoteObject/exportObject/GcDuringExport.java index 59663db7dea..def2806964d 100644 --- a/jdk/test/java/rmi/server/UnicastRemoteObject/exportObject/GcDuringExport.java +++ b/jdk/test/java/rmi/server/UnicastRemoteObject/exportObject/GcDuringExport.java @@ -30,6 +30,7 @@ * @bug 6597112 * @summary GC'ing objects whilst being exported to RMI should not cause exceptions * @author Neil Richards , + * @run main GcDuringExport */ import java.rmi.Remote; diff --git a/jdk/test/java/rmi/server/UnicastRemoteObject/keepAliveDuringCall/KeepAliveDuringCall.java b/jdk/test/java/rmi/server/UnicastRemoteObject/keepAliveDuringCall/KeepAliveDuringCall.java index dbe2ffe2157..780e7e5c7f1 100644 --- a/jdk/test/java/rmi/server/UnicastRemoteObject/keepAliveDuringCall/KeepAliveDuringCall.java +++ b/jdk/test/java/rmi/server/UnicastRemoteObject/keepAliveDuringCall/KeepAliveDuringCall.java @@ -32,14 +32,8 @@ * @author Peter Jones * * @library ../../../testlibrary - * @build TestLibrary - * @build JavaVM - * @build KeepAliveDuringCall - * @build KeepAliveDuringCall_Stub - * @build ShutdownMonitor - * @build Shutdown - * @build ShutdownImpl - * @build ShutdownImpl_Stub + * @build TestLibrary JavaVM KeepAliveDuringCall_Stub + * ShutdownMonitor Shutdown ShutdownImpl ShutdownImpl_Stub * @run main/othervm KeepAliveDuringCall */ diff --git a/jdk/test/java/rmi/server/UnicastRemoteObject/marshalAfterUnexport/MarshalAfterUnexport.java b/jdk/test/java/rmi/server/UnicastRemoteObject/marshalAfterUnexport/MarshalAfterUnexport.java index 743d4611f5f..a165dd81783 100644 --- a/jdk/test/java/rmi/server/UnicastRemoteObject/marshalAfterUnexport/MarshalAfterUnexport.java +++ b/jdk/test/java/rmi/server/UnicastRemoteObject/marshalAfterUnexport/MarshalAfterUnexport.java @@ -31,8 +31,7 @@ * IOException (see fix for bugid 4017232). * @author Peter Jones * - * @build MarshalAfterUnexport - * @build MarshalAfterUnexport_Stub + * @build MarshalAfterUnexport MarshalAfterUnexport_Stub * @run main/othervm MarshalAfterUnexport */ diff --git a/jdk/test/java/rmi/server/UnicastRemoteObject/marshalAfterUnexport/MarshalAfterUnexport2.java b/jdk/test/java/rmi/server/UnicastRemoteObject/marshalAfterUnexport/MarshalAfterUnexport2.java index ea1e482fc39..b72efa456cf 100644 --- a/jdk/test/java/rmi/server/UnicastRemoteObject/marshalAfterUnexport/MarshalAfterUnexport2.java +++ b/jdk/test/java/rmi/server/UnicastRemoteObject/marshalAfterUnexport/MarshalAfterUnexport2.java @@ -33,8 +33,7 @@ * @author Peter Jones * @author Ann Wollrath * - * @build MarshalAfterUnexport2 - * @build MarshalAfterUnexport2_Stub + * @build MarshalAfterUnexport2 MarshalAfterUnexport2_Stub * @run main/othervm MarshalAfterUnexport2 */ diff --git a/jdk/test/java/rmi/server/UnicastRemoteObject/unexportObject/UnexportLeak.java b/jdk/test/java/rmi/server/UnicastRemoteObject/unexportObject/UnexportLeak.java index 60325dcaa1e..62804feb6e0 100644 --- a/jdk/test/java/rmi/server/UnicastRemoteObject/unexportObject/UnexportLeak.java +++ b/jdk/test/java/rmi/server/UnicastRemoteObject/unexportObject/UnexportLeak.java @@ -29,10 +29,7 @@ * @author Ann Wollrath * * @library ../../../testlibrary - * @build UnexportLeak - * @build UnexportLeak_Stub - * @build TestLibrary - * @build Ping + * @build TestLibrary UnexportLeak_Stub Ping * @run main/othervm UnexportLeak */ diff --git a/jdk/test/java/rmi/server/Unmarshal/PrimitiveClasses.java b/jdk/test/java/rmi/server/Unmarshal/PrimitiveClasses.java index 8d7b30dbf66..b9dfb0c300e 100644 --- a/jdk/test/java/rmi/server/Unmarshal/PrimitiveClasses.java +++ b/jdk/test/java/rmi/server/Unmarshal/PrimitiveClasses.java @@ -25,6 +25,7 @@ * @bug 4442373 * @summary Verify that RMI can successfully unmarshal Class objects for * primitive types. + * @run main PrimitiveClasses */ import java.rmi.MarshalledObject; diff --git a/jdk/test/java/rmi/server/Unmarshal/checkUnmarshalOnStopThread/CheckUnmarshall.java b/jdk/test/java/rmi/server/Unmarshal/checkUnmarshalOnStopThread/CheckUnmarshal.java similarity index 100% rename from jdk/test/java/rmi/server/Unmarshal/checkUnmarshalOnStopThread/CheckUnmarshall.java rename to jdk/test/java/rmi/server/Unmarshal/checkUnmarshalOnStopThread/CheckUnmarshal.java diff --git a/jdk/test/java/rmi/server/Unmarshal/checkUnmarshalOnStopThread/CheckUnmarshalOnStopThread.java b/jdk/test/java/rmi/server/Unmarshal/checkUnmarshalOnStopThread/CheckUnmarshalOnStopThread.java index 60dce669c51..95dee537d21 100644 --- a/jdk/test/java/rmi/server/Unmarshal/checkUnmarshalOnStopThread/CheckUnmarshalOnStopThread.java +++ b/jdk/test/java/rmi/server/Unmarshal/checkUnmarshalOnStopThread/CheckUnmarshalOnStopThread.java @@ -31,10 +31,8 @@ * @author Laird Dornin * * @library ../../../testlibrary - * @build TestLibrary RMID JavaVM StreamPipe - * @build CheckUnmarshall PoisonPill RuntimeExceptionParameter - * @build CheckUnmarshalOnStopThread - * @build CheckUnmarshalOnStopThread_Stub + * @build TestLibrary CheckUnmarshal CheckUnmarshalOnStopThread_Stub + * PoisonPill RuntimeExceptionParameter * @run main/othervm/timeout=480 CheckUnmarshalOnStopThread */ diff --git a/jdk/test/java/rmi/server/Unreferenced/finiteGCLatency/FiniteGCLatency.java b/jdk/test/java/rmi/server/Unreferenced/finiteGCLatency/FiniteGCLatency.java index 7b7317a8d9b..f15883ca806 100644 --- a/jdk/test/java/rmi/server/Unreferenced/finiteGCLatency/FiniteGCLatency.java +++ b/jdk/test/java/rmi/server/Unreferenced/finiteGCLatency/FiniteGCLatency.java @@ -35,9 +35,7 @@ * @author Peter Jones * * @library ../../../testlibrary - * @build FiniteGCLatency - * @build FiniteGCLatency_Stub - * @build TestLibrary + * @build TestLibrary FiniteGCLatency_Stub * @run main/othervm/timeout=120 FiniteGCLatency */ diff --git a/jdk/test/java/rmi/server/Unreferenced/leaseCheckInterval/LeaseCheckInterval.java b/jdk/test/java/rmi/server/Unreferenced/leaseCheckInterval/LeaseCheckInterval.java index c1d5c579624..b488e762f9a 100644 --- a/jdk/test/java/rmi/server/Unreferenced/leaseCheckInterval/LeaseCheckInterval.java +++ b/jdk/test/java/rmi/server/Unreferenced/leaseCheckInterval/LeaseCheckInterval.java @@ -37,11 +37,7 @@ * @author Peter Jones * * @library ../../../testlibrary - * @build TestLibrary - * @build JavaVM - * @build LeaseCheckInterval - * @build LeaseCheckInterval_Stub - * @build SelfTerminator + * @build TestLibrary JavaVM LeaseCheckInterval_Stub SelfTerminator * @run main/othervm LeaseCheckInterval */ diff --git a/jdk/test/java/rmi/server/Unreferenced/marshalledObjectGet/MarshalledObjectGet.java b/jdk/test/java/rmi/server/Unreferenced/marshalledObjectGet/MarshalledObjectGet.java index 8170168d9d8..0ae059b95b2 100644 --- a/jdk/test/java/rmi/server/Unreferenced/marshalledObjectGet/MarshalledObjectGet.java +++ b/jdk/test/java/rmi/server/Unreferenced/marshalledObjectGet/MarshalledObjectGet.java @@ -30,8 +30,6 @@ * invoked. * @author Peter Jones * - * @library ../../../testlibrary - * @build MarshalledObjectGet * @build MarshalledObjectGet_Stub * @run main/othervm/timeout=120 MarshalledObjectGet */ diff --git a/jdk/test/java/rmi/server/Unreferenced/unreferencedContext/UnreferencedContext.java b/jdk/test/java/rmi/server/Unreferenced/unreferencedContext/UnreferencedContext.java index eb9d1928773..05be7aed087 100644 --- a/jdk/test/java/rmi/server/Unreferenced/unreferencedContext/UnreferencedContext.java +++ b/jdk/test/java/rmi/server/Unreferenced/unreferencedContext/UnreferencedContext.java @@ -39,9 +39,7 @@ * @author Laird Dornin * * @library ../../../testlibrary - * @build UnreferencedContext - * @build UnreferencedContext_Stub - * @build TestLibrary + * @build TestLibrary UnreferencedContext_Stub * @run main/othervm/timeout=120 UnreferencedContext */ diff --git a/jdk/test/java/rmi/server/clientStackTrace/ClientStackTrace.java b/jdk/test/java/rmi/server/clientStackTrace/ClientStackTrace.java index 41a2103be30..d6855575942 100644 --- a/jdk/test/java/rmi/server/clientStackTrace/ClientStackTrace.java +++ b/jdk/test/java/rmi/server/clientStackTrace/ClientStackTrace.java @@ -28,7 +28,7 @@ * @author Laird Dornin * * @library ../../testlibrary - * @build ClientStackTrace MyRemoteObject_Stub TestLibrary TestParams + * @build TestLibrary ClientStackTrace MyRemoteObject_Stub * @run main/othervm/policy=security.policy/timeout=120 ClientStackTrace */ diff --git a/jdk/test/java/rmi/server/getRemoteClass/GetRemoteClass.java b/jdk/test/java/rmi/server/getRemoteClass/GetRemoteClass.java index 8fa471006cc..b6f21b46ef5 100644 --- a/jdk/test/java/rmi/server/getRemoteClass/GetRemoteClass.java +++ b/jdk/test/java/rmi/server/getRemoteClass/GetRemoteClass.java @@ -28,7 +28,7 @@ * @author Laird Dornin * * @library ../../testlibrary - * @build GetRemoteClass TestLibrary TestParams + * @build TestLibrary * @run main/othervm GetRemoteClass */ diff --git a/jdk/test/java/rmi/server/serverStackTrace/ServerStackTrace.java b/jdk/test/java/rmi/server/serverStackTrace/ServerStackTrace.java index 6cc9b2da119..43504affe28 100644 --- a/jdk/test/java/rmi/server/serverStackTrace/ServerStackTrace.java +++ b/jdk/test/java/rmi/server/serverStackTrace/ServerStackTrace.java @@ -29,8 +29,7 @@ * serialized with the Throwable from the server. * @author Peter Jones * - * @build ServerStackTrace - * @build ServerStackTrace_Stub + * @build ServerStackTrace ServerStackTrace_Stub * @run main/othervm ServerStackTrace */ diff --git a/jdk/test/java/rmi/server/serverStackTrace/SuppressStackTraces.java b/jdk/test/java/rmi/server/serverStackTrace/SuppressStackTraces.java index 243d3223f0a..9606d12f9d8 100644 --- a/jdk/test/java/rmi/server/serverStackTrace/SuppressStackTraces.java +++ b/jdk/test/java/rmi/server/serverStackTrace/SuppressStackTraces.java @@ -36,10 +36,7 @@ * for reasons of performance or confidentiality requirements. * @author Peter Jones * - * @build SuppressStackTraces - * @build Impl2_Stub - * @build Impl1_Stub - * @build Impl1_Skel + * @build SuppressStackTraces Impl2_Stub Impl1_Stub Impl1_Skel * @run main/othervm SuppressStackTraces */ diff --git a/jdk/test/java/rmi/server/useCustomRef/UseCustomRef.java b/jdk/test/java/rmi/server/useCustomRef/UseCustomRef.java index 059c9a849c3..23d784706ca 100644 --- a/jdk/test/java/rmi/server/useCustomRef/UseCustomRef.java +++ b/jdk/test/java/rmi/server/useCustomRef/UseCustomRef.java @@ -31,11 +31,7 @@ * 4180392 * * @library ../../testlibrary - * @build UseCustomRef - * @build Ping - * @build UseCustomRef_Stub - * @build UseCustomRef_Skel - * @build TestLibrary + * @build TestLibrary Ping UseCustomRef_Stub UseCustomRef_Skel * @run main/othervm/policy=security.policy/secure=java.rmi.RMISecurityManager/timeout=120 UseCustomRef * * This test was failing to run because the synthetic access diff --git a/jdk/test/java/rmi/testlibrary/TestLibrary.java b/jdk/test/java/rmi/testlibrary/TestLibrary.java index 734d8050918..07ed308355c 100644 --- a/jdk/test/java/rmi/testlibrary/TestLibrary.java +++ b/jdk/test/java/rmi/testlibrary/TestLibrary.java @@ -54,6 +54,7 @@ import java.rmi.server.RemoteRef; import java.rmi.server.UnicastRemoteObject; import java.util.Enumeration; import java.util.Properties; + import sun.rmi.registry.RegistryImpl; import sun.rmi.server.UnicastServerRef; import sun.rmi.transport.Endpoint; @@ -92,6 +93,7 @@ public class TestLibrary { public final static int INHERITEDCHANNELNOTSERVERSOCKET_ACTIVATION_PORT = 64003; public final static int INHERITEDCHANNELNOTSERVERSOCKET_REGISTRY_PORT = 64004; public final static int READTEST_REGISTRY_PORT = 64005; + private final static int MAX_SERVER_SOCKET_TRIES = 10; static void mesg(Object mesg) { System.err.println("TEST_LIBRARY: " + mesg.toString()); @@ -125,36 +127,15 @@ public class TestLibrary { bomb(null, e); } - /** - * Property accessors - */ - private static boolean getBoolean(String name) { - return (new Boolean(getProperty(name, "false")).booleanValue()); - } - private static Integer getInteger(String name) { - int val = 0; - Integer value = null; - - String propVal = getProperty(name, null); - if (propVal == null) { - return null; - } - - try { - value = new Integer(Integer.parseInt(propVal)); - } catch (NumberFormatException nfe) { - } - return value; - } public static String getProperty(String property, String defaultVal) { final String prop = property; final String def = defaultVal; - return ((String) java.security.AccessController.doPrivileged - (new java.security.PrivilegedAction() { - public Object run() { + return java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public String run() { return System.getProperty(prop, def); } - })); + }); } /** @@ -169,9 +150,9 @@ public class TestLibrary { public static void setProperty(String property, String value) { final String prop = property; final String val = value; - java.security.AccessController.doPrivileged - (new java.security.PrivilegedAction() { - public Object run() { + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Void run() { System.setProperty(prop, val); return null; } @@ -188,7 +169,7 @@ public class TestLibrary { out.println("-------------------Test environment----------" + "---------"); - for(Enumeration keys = System.getProperties().keys(); + for(Enumeration keys = System.getProperties().keys(); keys.hasMoreElements();) { String property = (String) keys.nextElement(); @@ -252,7 +233,7 @@ public class TestLibrary { /* * Obtain the URL for the codebase. */ - URL codebaseURL = dstDir.toURL(); + URL codebaseURL = dstDir.toURI().toURL(); /* * Specify where we will copy the class definition from, if @@ -407,26 +388,46 @@ public class TestLibrary { */ public static int getUnusedRandomPort() { int numTries = 0; - int unusedRandomPort = FIXED_PORT_MIN; - Exception ex = null; + IOException ex = null; - while (numTries++ < 10) { + while (numTries++ < MAX_SERVER_SOCKET_TRIES) { + int unusedRandomPort = -1; ex = null; //reset try (ServerSocket ss = new ServerSocket(0)) { unusedRandomPort = ss.getLocalPort(); - } catch (Exception e) { + } catch (IOException e) { ex = e; + // temporarily print stack trace here until we find out why + // tests are failing. + System.err.println("TestLibrary.getUnusedRandomPort() caught " + + "exception on iteration " + numTries + + (numTries==MAX_SERVER_SOCKET_TRIES ? " (the final try)." + : ".")); + ex.printStackTrace(); } - if (!isReservedPort(unusedRandomPort)) { - return unusedRandomPort; + if (unusedRandomPort >= 0) { + if (isReservedPort(unusedRandomPort)) { + System.out.println("INFO: On try # " + numTries + + (numTries==MAX_SERVER_SOCKET_TRIES ? ", the final try, ": ",") + + " ServerSocket(0) returned the reserved port " + + unusedRandomPort + + " in TestLibrary.getUnusedRandomPort() "); + } else { + return unusedRandomPort; + } } } // If we're here, then either an exception was thrown or the port is // a reserved port. - throw new RuntimeException("Error getting unused random port.", ex); + if (ex==null) { + throw new RuntimeException("Error getting unused random port. The" + +" last port returned by ServerSocket(0) was a reserved port"); + } else { + throw new RuntimeException("Error getting unused random port.", ex); + } } /** diff --git a/jdk/test/java/rmi/transport/acceptLoop/CloseServerSocketOnTermination.java b/jdk/test/java/rmi/transport/acceptLoop/CloseServerSocketOnTermination.java index a2361373644..b4d86c4ccd2 100644 --- a/jdk/test/java/rmi/transport/acceptLoop/CloseServerSocketOnTermination.java +++ b/jdk/test/java/rmi/transport/acceptLoop/CloseServerSocketOnTermination.java @@ -31,7 +31,6 @@ * exception for which it doesn't even consult the RMIFailureHandler. * @author Peter Jones * - * @build CloseServerSocketOnTermination * @run main/othervm CloseServerSocketOnTermination */ diff --git a/jdk/test/java/rmi/transport/checkFQDN/CheckFQDN.java b/jdk/test/java/rmi/transport/checkFQDN/CheckFQDN.java index 006de5b6c89..9660f532c39 100644 --- a/jdk/test/java/rmi/transport/checkFQDN/CheckFQDN.java +++ b/jdk/test/java/rmi/transport/checkFQDN/CheckFQDN.java @@ -33,8 +33,7 @@ * @author Laird Dornin * * @library ../../testlibrary - * @build CheckFQDN CheckFQDNClient CheckFQDN_Stub TellServerName - * @build TestLibrary + * @build TestLibrary CheckFQDNClient CheckFQDN_Stub TellServerName * @run main/othervm/timeout=120 CheckFQDN */ diff --git a/jdk/test/java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java b/jdk/test/java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java index 0ab00577dc8..52fd7df9295 100644 --- a/jdk/test/java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java +++ b/jdk/test/java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java @@ -28,8 +28,7 @@ * @author Laird Dornin * * @library ../../testlibrary - * @build CheckLeaseLeak CheckLeaseLeak_Stub LeaseLeakClient LeaseLeak - * @build TestLibrary + * @build TestLibrary CheckLeaseLeak_Stub LeaseLeakClient LeaseLeak * @run main/othervm/timeout=240 CheckLeaseLeak * */ diff --git a/jdk/test/java/rmi/transport/closeServerSocket/CloseServerSocket.java b/jdk/test/java/rmi/transport/closeServerSocket/CloseServerSocket.java index 69c51de8074..2b1f1eeba99 100644 --- a/jdk/test/java/rmi/transport/closeServerSocket/CloseServerSocket.java +++ b/jdk/test/java/rmi/transport/closeServerSocket/CloseServerSocket.java @@ -31,7 +31,7 @@ * @author Peter Jones * * @library ../../testlibrary - * @build CloseServerSocket TestLibrary + * @build TestLibrary * @run main/othervm CloseServerSocket */ diff --git a/jdk/test/java/rmi/transport/dgcDeadLock/DGCDeadLock.java b/jdk/test/java/rmi/transport/dgcDeadLock/DGCDeadLock.java index 97ad31dc99d..bcd58a0a6a5 100644 --- a/jdk/test/java/rmi/transport/dgcDeadLock/DGCDeadLock.java +++ b/jdk/test/java/rmi/transport/dgcDeadLock/DGCDeadLock.java @@ -28,11 +28,7 @@ * @author Laird Dornin * * @library ../../testlibrary - * @build DGCDeadLock - * @build Test - * @build TestImpl - * @build TestImpl_Stub - * @build TestLibrary + * @build TestLibrary Test TestImpl TestImpl_Stub * @run main/othervm/policy=security.policy/timeout=360 DGCDeadLock */ diff --git a/jdk/test/java/rmi/transport/handshakeFailure/HandshakeFailure.java b/jdk/test/java/rmi/transport/handshakeFailure/HandshakeFailure.java index df04070f138..ed1ba8e0715 100644 --- a/jdk/test/java/rmi/transport/handshakeFailure/HandshakeFailure.java +++ b/jdk/test/java/rmi/transport/handshakeFailure/HandshakeFailure.java @@ -31,7 +31,7 @@ * @author Peter Jones * * @library ../../testlibrary - * @build HandshakeFailure TestLibrary + * @build TestLibrary * @run main/othervm HandshakeFailure */ diff --git a/jdk/test/java/rmi/transport/handshakeTimeout/HandshakeTimeout.java b/jdk/test/java/rmi/transport/handshakeTimeout/HandshakeTimeout.java index 304c175772b..ba492f4194d 100644 --- a/jdk/test/java/rmi/transport/handshakeTimeout/HandshakeTimeout.java +++ b/jdk/test/java/rmi/transport/handshakeTimeout/HandshakeTimeout.java @@ -34,7 +34,7 @@ * @author Peter Jones * * @library ../../testlibrary - * @build HandshakeTimeout TestLibrary + * @build TestLibrary * @run main/othervm HandshakeTimeout */ diff --git a/jdk/test/java/rmi/transport/httpSocket/HttpSocketTest.java b/jdk/test/java/rmi/transport/httpSocket/HttpSocketTest.java index 1004bfb86ed..032c4cdc532 100644 --- a/jdk/test/java/rmi/transport/httpSocket/HttpSocketTest.java +++ b/jdk/test/java/rmi/transport/httpSocket/HttpSocketTest.java @@ -27,7 +27,7 @@ * @author Dana Burns * * @library ../../testlibrary - * @build HttpSocketTest HttpSocketTest_Stub TestLibrary + * @build TestLibrary HttpSocketTest HttpSocketTest_Stub * @run main/othervm/policy=security.policy HttpSocketTest */ diff --git a/jdk/test/java/rmi/transport/rapidExportUnexport/RapidExportUnexport.java b/jdk/test/java/rmi/transport/rapidExportUnexport/RapidExportUnexport.java index 5b21da8680a..4080bfa7e74 100644 --- a/jdk/test/java/rmi/transport/rapidExportUnexport/RapidExportUnexport.java +++ b/jdk/test/java/rmi/transport/rapidExportUnexport/RapidExportUnexport.java @@ -32,7 +32,7 @@ * @author Peter Jones * * @library ../../testlibrary - * @build TestLibrary RapidExportUnexport + * @build TestLibrary * @run main/othervm RapidExportUnexport */ diff --git a/jdk/test/java/rmi/transport/readTimeout/ReadTimeoutTest.java b/jdk/test/java/rmi/transport/readTimeout/ReadTimeoutTest.java index f72fea3164a..3a0bfa1cafa 100644 --- a/jdk/test/java/rmi/transport/readTimeout/ReadTimeoutTest.java +++ b/jdk/test/java/rmi/transport/readTimeout/ReadTimeoutTest.java @@ -27,12 +27,9 @@ * @summary Incoming connections should be subject to timeout * @author Adrian Colley * - * @library ../../testlibrary - * @build TestIface - * @build TestImpl - * @build TestImpl_Stub - * @build ReadTimeoutTest - * @run main/othervm/policy=security.policy/timeout=60 -Dsun.rmi.transport.tcp.readTimeout=5000 ReadTimeoutTest + * @build TestIface TestImpl TestImpl_Stub + * @run main/othervm/policy=security.policy/timeout=60 + * -Dsun.rmi.transport.tcp.readTimeout=5000 ReadTimeoutTest */ /* This test sets a very short read timeout, exports an object, and then diff --git a/jdk/test/java/rmi/transport/reuseDefaultPort/ReuseDefaultPort.java b/jdk/test/java/rmi/transport/reuseDefaultPort/ReuseDefaultPort.java index decec588d01..e5e7d80b49f 100644 --- a/jdk/test/java/rmi/transport/reuseDefaultPort/ReuseDefaultPort.java +++ b/jdk/test/java/rmi/transport/reuseDefaultPort/ReuseDefaultPort.java @@ -34,7 +34,7 @@ * @author Peter Jones * * @library ../../testlibrary - * @build ReuseDefaultPort TestLibrary + * @build TestLibrary * @run main/othervm ReuseDefaultPort */ diff --git a/jdk/test/java/rmi/transport/runtimeThreadInheritanceLeak/RuntimeThreadInheritanceLeak.java b/jdk/test/java/rmi/transport/runtimeThreadInheritanceLeak/RuntimeThreadInheritanceLeak.java index 04a931daf9b..ac480776229 100644 --- a/jdk/test/java/rmi/transport/runtimeThreadInheritanceLeak/RuntimeThreadInheritanceLeak.java +++ b/jdk/test/java/rmi/transport/runtimeThreadInheritanceLeak/RuntimeThreadInheritanceLeak.java @@ -38,7 +38,6 @@ * subsystems also not holding on to the loader in their daemon threads.] * @author Peter Jones * - * @build RuntimeThreadInheritanceLeak * @build RuntimeThreadInheritanceLeak_Stub * @run main/othervm RuntimeThreadInheritanceLeak */ diff --git a/jdk/test/java/security/BasicPermission/Wildcard.java b/jdk/test/java/security/BasicPermission/Wildcard.java new file mode 100644 index 00000000000..3b6d1c58eea --- /dev/null +++ b/jdk/test/java/security/BasicPermission/Wildcard.java @@ -0,0 +1,54 @@ +/* + * 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. + */ + +import java.lang.RuntimePermission; +import java.net.NetPermission; +import java.sql.SQLPermission; +import java.util.PropertyPermission; +import javax.net.ssl.SSLPermission; + +/* + * @test + * @bug 7167056 + * @summary Check that BasicPermission subclasses don't throw exception if name + * contains wildcard character ("*") but does not signify a + * wildcard match + */ + +public class Wildcard { + + public static void main(String[] args) throws Exception { + wildcard("*java"); + wildcard("java*"); + wildcard("ja*va"); + } + + private static void wildcard(String wildcard) throws Exception { + new RuntimePermission(wildcard); + new NetPermission(wildcard); + new SQLPermission(wildcard); + new PropertyPermission(wildcard, "read"); + new SSLPermission(wildcard); + new com.sun.net.ssl.SSLPermission(wildcard); + } +} diff --git a/jdk/test/java/security/Security/ClassLoaderDeadlock/ClassLoaderDeadlock.sh b/jdk/test/java/security/Security/ClassLoaderDeadlock/ClassLoaderDeadlock.sh index a503697dc73..a62cba4ec3a 100644 --- a/jdk/test/java/security/Security/ClassLoaderDeadlock/ClassLoaderDeadlock.sh +++ b/jdk/test/java/security/Security/ClassLoaderDeadlock/ClassLoaderDeadlock.sh @@ -87,7 +87,7 @@ ${TESTJAVA}${FILESEP}bin${FILESEP}javac \ ${TESTSRC}${FILESEP}provider${FILESEP}HashProvider.java # run the test -${TESTJAVA}${FILESEP}bin${FILESEP}java \ +${TESTJAVA}${FILESEP}bin${FILESEP}java ${TESTVMOPTS} \ -classpath "${TESTCLASSES}${PATHSEP}${TESTSRC}${FILESEP}Deadlock.jar" \ -Djava.awt.headless=true \ ClassLoaderDeadlock diff --git a/jdk/test/java/security/Security/ClassLoaderDeadlock/Deadlock.sh b/jdk/test/java/security/Security/ClassLoaderDeadlock/Deadlock.sh index 53555ee26ff..e1ed14425fa 100644 --- a/jdk/test/java/security/Security/ClassLoaderDeadlock/Deadlock.sh +++ b/jdk/test/java/security/Security/ClassLoaderDeadlock/Deadlock.sh @@ -62,5 +62,5 @@ esac JAVA="${TESTJAVA}${FILESEP}bin${FILESEP}java" -${JAVA} -cp "${TESTCLASSES}${PATHSEP}${TESTSRC}${FILESEP}Deadlock.jar" Deadlock +${JAVA} ${TESTVMOPTS} -cp "${TESTCLASSES}${PATHSEP}${TESTSRC}${FILESEP}Deadlock.jar" Deadlock diff --git a/jdk/test/java/security/Security/ClassLoaderDeadlock/Deadlock2.sh b/jdk/test/java/security/Security/ClassLoaderDeadlock/Deadlock2.sh index 1109496c723..acf8ff21033 100644 --- a/jdk/test/java/security/Security/ClassLoaderDeadlock/Deadlock2.sh +++ b/jdk/test/java/security/Security/ClassLoaderDeadlock/Deadlock2.sh @@ -100,8 +100,8 @@ ${TESTJAVA}${FILESEP}bin${FILESEP}jar \ rm Deadlock2*.class # create serialized object and run the test -${TESTJAVA}${FILESEP}bin${FILESEP}java CreateSerialized -${TESTJAVA}${FILESEP}bin${FILESEP}java -Djava.ext.dirs=${TESTCLASSES}${FILESEP}testlib Deadlock2 +${TESTJAVA}${FILESEP}bin${FILESEP}java ${TESTVMOPTS} CreateSerialized +${TESTJAVA}${FILESEP}bin${FILESEP}java ${TESTVMOPTS} -Djava.ext.dirs=${TESTCLASSES}${FILESEP}testlib Deadlock2 STATUS=$? # clean up diff --git a/jdk/test/java/security/Security/signedfirst/Dyn.sh b/jdk/test/java/security/Security/signedfirst/Dyn.sh index d87e5ff0139..64d0dd3f775 100644 --- a/jdk/test/java/security/Security/signedfirst/Dyn.sh +++ b/jdk/test/java/security/Security/signedfirst/Dyn.sh @@ -83,7 +83,7 @@ ${TESTJAVA}${FILESEP}bin${FILESEP}javac \ ${TESTSRC}${FILESEP}DynSignedProvFirst.java # run the test -${TESTJAVA}${FILESEP}bin${FILESEP}java \ +${TESTJAVA}${FILESEP}bin${FILESEP}java ${TESTVMOPTS} \ -classpath "${TESTCLASSES}${PATHSEP}${TESTSRC}${FILESEP}exp.jar" \ DynSignedProvFirst diff --git a/jdk/test/java/security/Security/signedfirst/Static.sh b/jdk/test/java/security/Security/signedfirst/Static.sh index 6b41adf31ad..544a3b1a3ff 100644 --- a/jdk/test/java/security/Security/signedfirst/Static.sh +++ b/jdk/test/java/security/Security/signedfirst/Static.sh @@ -84,7 +84,7 @@ ${TESTJAVA}${FILESEP}bin${FILESEP}javac \ # run the test cd ${TESTSRC}${FILESEP} -${TESTJAVA}${FILESEP}bin${FILESEP}java \ +${TESTJAVA}${FILESEP}bin${FILESEP}java ${TESTVMOPTS} \ -classpath "${TESTCLASSES}${PATHSEP}${TESTSRC}${FILESEP}exp.jar" \ -Djava.security.properties=file:${TESTSRC}${FILESEP}Static.props \ StaticSignedProvFirst diff --git a/jdk/test/java/security/cert/CertificateFactory/slowstream.sh b/jdk/test/java/security/cert/CertificateFactory/slowstream.sh index fbca87e46a3..72d3fcf6c8c 100644 --- a/jdk/test/java/security/cert/CertificateFactory/slowstream.sh +++ b/jdk/test/java/security/cert/CertificateFactory/slowstream.sh @@ -46,5 +46,5 @@ case "$OS" in esac ${TESTJAVA}${FS}bin${FS}javac -d . ${TESTSRC}${FS}SlowStream.java -${TESTJAVA}${FS}bin${FS}java -Dtest.src=${TESTSRC} SlowStreamWriter | \ - ${TESTJAVA}${FS}bin${FS}java SlowStreamReader +${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -Dtest.src=${TESTSRC} SlowStreamWriter | \ + ${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} SlowStreamReader diff --git a/jdk/test/java/util/Base64/TestBase64.java b/jdk/test/java/util/Base64/TestBase64.java new file mode 100644 index 00000000000..6b37772d7f6 --- /dev/null +++ b/jdk/test/java/util/Base64/TestBase64.java @@ -0,0 +1,532 @@ +/* + * 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. + */ + +/** + * @test 4235519 8004212 + * @summary tests java.util.Base64 + */ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.Base64; +import java.util.Random; + +public class TestBase64 { + + public static void main(String args[]) throws Throwable { + int numRuns = 10; + int numBytes = 200; + if (args.length > 1) { + numRuns = Integer.parseInt(args[0]); + numBytes = Integer.parseInt(args[1]); + } + + test(Base64.getEncoder(), Base64.getDecoder(), + numRuns, numBytes); + test(Base64.getUrlEncoder(), Base64.getUrlDecoder(), + numRuns, numBytes); + test(Base64.getMimeEncoder(), Base64.getMimeDecoder(), + numRuns, numBytes); + + Random rnd = new java.util.Random(); + byte[] nl_1 = new byte[] {'\n'}; + byte[] nl_2 = new byte[] {'\n', '\r'}; + byte[] nl_3 = new byte[] {'\n', '\r', '\n'}; + for (int i = 0; i < 10; i++) { + int len = rnd.nextInt(200) + 4; + test(Base64.getEncoder(len, nl_1), + Base64.getMimeDecoder(), + numRuns, numBytes); + test(Base64.getEncoder(len, nl_2), + Base64.getMimeDecoder(), + numRuns, numBytes); + test(Base64.getEncoder(len, nl_3), + Base64.getMimeDecoder(), + numRuns, numBytes); + } + + testNull(Base64.getEncoder()); + testNull(Base64.getUrlEncoder()); + testNull(Base64.getMimeEncoder()); + testNull(Base64.getEncoder(10, new byte[]{'\n'})); + testNull(Base64.getDecoder()); + testNull(Base64.getUrlDecoder()); + testNull(Base64.getMimeDecoder()); + checkNull(new Runnable() { public void run() { Base64.getEncoder(10, null); }}); + + testIOE(Base64.getEncoder()); + testIOE(Base64.getUrlEncoder()); + testIOE(Base64.getMimeEncoder()); + testIOE(Base64.getEncoder(10, new byte[]{'\n'})); + + byte[] src = new byte[1024]; + new Random().nextBytes(src); + final byte[] decoded = Base64.getEncoder().encode(src); + testIOE(Base64.getDecoder(), decoded); + testIOE(Base64.getMimeDecoder(), decoded); + testIOE(Base64.getUrlDecoder(), Base64.getUrlEncoder().encode(src)); + + // illegal line separator + checkIAE(new Runnable() { public void run() { Base64.getEncoder(10, new byte[]{'\r', 'N'}); }}); + + // illegal base64 character + decoded[2] = (byte)0xe0; + checkIAE(new Runnable() { + public void run() { Base64.getDecoder().decode(decoded); }}); + checkIAE(new Runnable() { + public void run() { Base64.getDecoder().decode(decoded, new byte[1024]); }}); + checkIAE(new Runnable() { public void run() { + Base64.getDecoder().decode(ByteBuffer.wrap(decoded)); }}); + checkIAE(new Runnable() { public void run() { + Base64.getDecoder().decode(ByteBuffer.wrap(decoded), ByteBuffer.allocate(1024)); }}); + checkIAE(new Runnable() { public void run() { + Base64.getDecoder().decode(ByteBuffer.wrap(decoded), ByteBuffer.allocateDirect(1024)); }}); + + // test return value from decode(ByteBuffer, ByteBuffer) + testDecBufRet(); + } + + private static sun.misc.BASE64Encoder sunmisc = new sun.misc.BASE64Encoder(); + + private static void test(Base64.Encoder enc, Base64.Decoder dec, + int numRuns, int numBytes) throws Throwable { + Random rnd = new java.util.Random(); + + enc.encode(new byte[0]); + dec.decode(new byte[0]); + + for (int i=0; i + * @summary tests java.util.Base64 + */ + +import java.io.BufferedReader; +import java.io.FileReader; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Base64; +import java.util.Base64.Decoder; +import java.util.Base64.Encoder; +import java.util.Objects; +import java.util.Random; + +import sun.misc.BASE64Decoder; +import sun.misc.BASE64Encoder; + +public class TestBase64Golden { + + public static void main(String[] args) throws Exception { + test0(Base64Type.BASIC, Base64.getEncoder(), Base64.getDecoder(), + "plain.txt", "baseEncode.txt"); + + test0(Base64Type.URLSAFE, Base64.getUrlEncoder(), Base64.getUrlDecoder(), + "plain.txt", "urlEncode.txt"); + + test0(Base64Type.MIME, Base64.getMimeEncoder(), Base64.getMimeDecoder(), + "plain.txt", "mimeEncode.txt"); + test1(); + test2(); + } + + public static void test0(Base64Type type, Encoder encoder, Decoder decoder, + String srcFile, String encodedFile) throws Exception { + + String[] srcLns = Files.readAllLines(Paths.get(SRCDIR, srcFile), DEF_CHARSET) + .toArray(new String[0]); + String[] encodedLns = Files.readAllLines(Paths.get(SRCDIR, encodedFile), + DEF_CHARSET) + .toArray(new String[0]); + int lns = 0; + for (String srcStr : srcLns) { + String encodedStr = null; + if (type != Base64Type.MIME) { + encodedStr = encodedLns[lns++]; + } else { + while (lns < encodedLns.length) { + String s = encodedLns[lns++]; + if (s.length() == 0) + break; + if (encodedStr != null) { + encodedStr += DEFAULT_CRLF + s; + } else { + encodedStr = s; + } + } + if (encodedStr == null && srcStr.length() == 0) { + encodedStr = ""; + } + } + System.out.printf("%n src[%d]: %s%n", srcStr.length(), srcStr); + System.out.printf("encoded[%d]: %s%n", encodedStr.length(), encodedStr); + + byte[] srcArr = srcStr.getBytes(DEF_CHARSET); + byte[] encodedArr = encodedStr.getBytes(DEF_CHARSET); + + ByteBuffer srcBuf = ByteBuffer.wrap(srcArr); + ByteBuffer encodedBuf = ByteBuffer.wrap(encodedArr); + byte[] resArr = new byte[encodedArr.length]; + + // test int encode(byte[], byte[]) + int len = encoder.encode(srcArr, resArr); + assertEqual(len, encodedArr.length); + assertEqual(resArr, encodedArr); + + // test byte[] encode(byte[]) + resArr = encoder.encode(srcArr); + assertEqual(resArr, encodedArr); + + // test ByteBuffer encode(ByteBuffer) + int limit = srcBuf.limit(); + ByteBuffer resBuf = encoder.encode(srcBuf); + assertEqual(srcBuf.position(), limit); + assertEqual(srcBuf.limit(), limit); + assertEqual(resBuf, encodedBuf); + srcBuf.rewind(); // reset for next test + + // test encode(ByteBuffer, ByteBuffer, bytesOut) + resBuf.clear(); + len = encoder.encode(srcBuf, resBuf, 0); + assertEqual(len, encodedArr.length); + assertEqual(srcBuf.position(), limit); + assertEqual(srcBuf.limit(), limit); + assertEqual(resBuf.position(), len); + resBuf.flip(); + assertEqual(resBuf, encodedBuf); + srcBuf.rewind(); + + // test encode(ByteBuffer, ByteBuffer, bytesOut)[direct] + ByteBuffer resBuf_d = ByteBuffer.allocateDirect(encodedArr.length); + len = encoder.encode(srcBuf, resBuf_d, 0); + assertEqual(len, encodedArr.length); + assertEqual(srcBuf.position(), limit); + assertEqual(srcBuf.limit(), limit); + assertEqual(resBuf_d.position(), len); + resBuf_d.flip(); + assertEqual(resBuf_d, encodedBuf); + srcBuf.rewind(); + + // test String encodeToString(byte[]) + String resEncodeStr = encoder.encodeToString(srcArr); + assertEqual(resEncodeStr, encodedStr); + + // test int decode(byte[], byte[]) + resArr = new byte[srcArr.length]; + len = decoder.decode(encodedArr, resArr); + assertEqual(len, srcArr.length); + assertEqual(resArr, srcArr); + + // test byte[] decode(byte[]) + resArr = decoder.decode(encodedArr); + assertEqual(resArr, srcArr); + + // test ByteBuffer decode(ByteBuffer) + limit = encodedBuf.limit(); + resBuf = decoder.decode(encodedBuf); + assertEqual(encodedBuf.position(), limit); + assertEqual(encodedBuf.limit(), limit); + assertEqual(resBuf, srcBuf); + encodedBuf.rewind(); // reset for next test + + // test int decode(ByteBuffer, ByteBuffer) + resBuf.clear(); + len = decoder.decode(encodedBuf, resBuf); + assertEqual(len, srcArr.length); + assertEqual(encodedBuf.position(), limit); + assertEqual(encodedBuf.limit(), limit); + assertEqual(resBuf.position(), len); + resBuf.flip(); + assertEqual(resBuf, srcBuf); + encodedBuf.rewind(); // reset for next test + + // test int decode(ByteBuffer, ByteBuffer)[direct] + resBuf_d = ByteBuffer.allocateDirect(srcArr.length); + len = decoder.decode(encodedBuf, resBuf_d); + assertEqual(len, srcArr.length); + assertEqual(encodedBuf.position(), limit); + assertEqual(encodedBuf.limit(), limit); + assertEqual(resBuf_d.position(), len); + resBuf_d.flip(); + assertEqual(resBuf_d, srcBuf); + encodedBuf.rewind(); // reset for next test + + // test byte[] decode(String) + resArr = decoder.decode(encodedStr); + assertEqual(resArr, srcArr); + + // test compatible with sun.misc.Base64Encoder + if (type == Base64Type.MIME) { + sun.misc.BASE64Encoder miscEncoder = new BASE64Encoder(); + sun.misc.BASE64Decoder miscDecoder = new BASE64Decoder(); + resArr = decoder.decode(miscEncoder.encode(srcArr)); + assertEqual(resArr, srcArr); + + resArr = encoder.encode(miscDecoder.decodeBuffer(encodedStr)); + assertEqual(new String(resArr, DEF_CHARSET), encodedStr); + } + } + } + + private static void test1() throws Exception { + byte[] src = new byte[6]; + new Random().nextBytes(src); + + ByteBuffer srcBuf = ByteBuffer.allocate(10); + srcBuf.position(2); + srcBuf.mark(); + srcBuf.limit(8); + srcBuf.put(src); + srcBuf.reset(); + + ByteBuffer dstBuf = ByteBuffer.allocate((src.length + 2) / 3 * 4); + Base64.getEncoder().encode(srcBuf, dstBuf, 0); + dstBuf.rewind(); + byte[] dst = new byte[dstBuf.limit()]; + dstBuf.get(dst); + System.out.printf("%n src[%d]: %s%n", src.length, new String(src)); + System.out.printf("encoded[%d]: %s%n", dst.length, new String(dst)); + assertEqual(src, Base64.getDecoder().decode(dst)); + + dstBuf = ByteBuffer.allocateDirect((src.length + 2) / 3 * 4); + srcBuf.reset(); + Base64.getEncoder().encode(srcBuf, dstBuf, 0); + dstBuf.rewind(); + dst = new byte[dstBuf.limit()]; + dstBuf.get(dst); + assertEqual(src, Base64.getDecoder().decode(dst)); + } + + private static void test2() throws Exception { + byte[] src = new byte[] { + 46, -97, -35, -44, 127, -60, -39, -4, -112, 34, -57, 47, -14, 67, + 40, 18, 90, -59, 68, 112, 23, 121, -91, 94, 35, 49, 104, 17, 30, + -80, -104, -3, -53, 27, 38, -72, -47, 113, -52, 18, 5, -126 }; + Encoder encoder = Base64.getEncoder(49, new byte[] { 0x7e }); + byte[] encoded = encoder.encode(src); + Decoder decoder = Base64.getMimeDecoder(); + byte[] decoded = decoder.decode(encoded); + if (!Objects.deepEquals(src, decoded)) { + throw new RuntimeException(); + } + } + + // helper + enum Base64Type { + BASIC, URLSAFE, MIME + } + + private static final String SRCDIR = System.getProperty("test.src", "."); + private static final Charset DEF_CHARSET = StandardCharsets.US_ASCII; + private static final String DEF_EXCEPTION_MSG = + "Assertion failed! The result is not same as expected"; + private static final String DEFAULT_CRLF = "\r\n"; + + private static void assertEqual(Object result, Object expect) { + if (!Objects.deepEquals(result, expect)) { + String resultStr = result.toString(); + String expectStr = expect.toString(); + if (result instanceof byte[]) { + resultStr = new String((byte[]) result, DEF_CHARSET); + } + if (expect instanceof byte[]) { + expectStr = new String((byte[]) expect, DEF_CHARSET); + } + throw new RuntimeException(DEF_EXCEPTION_MSG + + " result: " + resultStr + " expected: " + expectStr); + } + } +} diff --git a/jdk/test/java/util/Base64/baseEncode.txt b/jdk/test/java/util/Base64/baseEncode.txt new file mode 100644 index 00000000000..0f71ef0d926 --- /dev/null +++ b/jdk/test/java/util/Base64/baseEncode.txt @@ -0,0 +1,183 @@ +VGhpcyB0ZXN0IGRhdGEgaXMgcGFydCBvZiByZmMyMDQ1IHdoaWNoIGluY2x1ZGVzIGFsbCBjaGFyYWN0ZXJzIGF+eiBBflosIDB+OSBhbmQgYWxsIHN5bWJvbHMs +SXQgaXMgdXNlZCB0byB0ZXN0IGphdmEudXRpbC5CYXNlNjQuRW5jb2RlciwgYW5kIHdpbGwgYmUgZW5jb2RlZCBieSBvcmcuYXBhY2hlLmNvbW1vbnMuY29kZWMuYmluYXJ5LkJhc2U2NC5qYXZh +dG8gdGVzdCBqYXZhLnV0aWwuQmFzZTY0LkRlY29kZXI7 + +RnJlZWQgJiBCb3JlbnN0ZWluICAgICAgICAgIFN0YW5kYXJkcyBUcmFjayAgICAgICAgICAgICAgICAgICAgIFtQYWdlIDFd +UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAgICBOb3ZlbWJlciAxOTk2 + +ICAgVGhlc2UgZG9jdW1lbnRzIGFyZSByZXZpc2lvbnMgb2YgUkZDcyAxNTIxLCAxNTIyLCBhbmQgMTU5MCwgd2hpY2g= +ICAgdGhlbXNlbHZlcyB3ZXJlIHJldmlzaW9ucyBvZiBSRkNzIDEzNDEgYW5kIDEzNDIuICBBbiBhcHBlbmRpeCBpbiBSRkM= +ICAgMjA0OSBkZXNjcmliZXMgZGlmZmVyZW5jZXMgYW5kIGNoYW5nZXMgZnJvbSBwcmV2aW91cyB2ZXJzaW9ucy4= + +VGFibGUgb2YgQ29udGVudHM= + +ICAgMS4gSW50cm9kdWN0aW9uIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgIDM= +ICAgMi4gRGVmaW5pdGlvbnMsIENvbnZlbnRpb25zLCBhbmQgR2VuZXJpYyBCTkYgR3JhbW1hciAuLi4uICAgIDU= +ICAgMy4gTUlNRSBIZWFkZXIgRmllbGRzIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgIDg= +ICAgNC4gTUlNRS1WZXJzaW9uIEhlYWRlciBGaWVsZCAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgIDg= +ICAgNS4gQ29udGVudC1UeXBlIEhlYWRlciBGaWVsZCAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMTA= +ICAgNi4gQ29udGVudC1UcmFuc2Zlci1FbmNvZGluZyBIZWFkZXIgRmllbGQgLi4uLi4uLi4uLi4uLi4uICAgMTQ= +ICAgNy4gQ29udGVudC1JRCBIZWFkZXIgRmllbGQgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjY= +ICAgOC4gQ29udGVudC1EZXNjcmlwdGlvbiBIZWFkZXIgRmllbGQgLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjc= +ICAgOS4gQWRkaXRpb25hbCBNSU1FIEhlYWRlciBGaWVsZHMgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjc= +ICAgMTAuIFN1bW1hcnkgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjc= +ICAgMTEuIFNlY3VyaXR5IENvbnNpZGVyYXRpb25zIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjc= +ICAgMTIuIEF1dGhvcnMnIEFkZHJlc3NlcyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjg= +ICAgQS4gQ29sbGVjdGVkIEdyYW1tYXIgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjk= + +RnJlZWQgJiBCb3JlbnN0ZWluICAgICAgICAgIFN0YW5kYXJkcyBUcmFjayAgICAgICAgICAgICAgICAgICAgIFtQYWdlIDdd +UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAgICBOb3ZlbWJlciAxOTk2 + +My4gIE1JTUUgSGVhZGVyIEZpZWxkcw== + +ICAgTUlNRSBkZWZpbmVzIGEgbnVtYmVyIG9mIG5ldyBSRkMgODIyIGhlYWRlciBmaWVsZHMgdGhhdCBhcmUgdXNlZCB0bw== +ICAgZGVzY3JpYmUgdGhlIGNvbnRlbnQgb2YgYSBNSU1FIGVudGl0eS4gIFRoZXNlIGhlYWRlciBmaWVsZHMgb2NjdXIgaW4= +ICAgYXQgbGVhc3QgdHdvIGNvbnRleHRzOg== + +ICAgICgxKSAgIEFzIHBhcnQgb2YgYSByZWd1bGFyIFJGQyA4MjIgbWVzc2FnZSBoZWFkZXIu + +ICAgICgyKSAgIEluIGEgTUlNRSBib2R5IHBhcnQgaGVhZGVyIHdpdGhpbiBhIG11bHRpcGFydA== +ICAgICAgICAgIGNvbnN0cnVjdC4= + +ICAgVGhlIGZvcm1hbCBkZWZpbml0aW9uIG9mIHRoZXNlIGhlYWRlciBmaWVsZHMgaXMgYXMgZm9sbG93czo= + +ICAgICBNSU1FLW1lc3NhZ2UtaGVhZGVycyA6PSBlbnRpdHktaGVhZGVycw== +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWVsZHM= +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2ZXJzaW9uIENSTEY= +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICA7IFRoZSBvcmRlcmluZyBvZiB0aGUgaGVhZGVy +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICA7IGZpZWxkcyBpbXBsaWVkIGJ5IHRoaXMgQk5G +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICA7IGRlZmluaXRpb24gc2hvdWxkIGJlIGlnbm9yZWQu + +ICAgICBNSU1FLXBhcnQtaGVhZGVycyA6PSBlbnRpdHktaGVhZGVycw== +ICAgICAgICAgICAgICAgICAgICAgICAgICBbIGZpZWxkcyBd +ICAgICAgICAgICAgICAgICAgICAgICAgICA7IEFueSBmaWVsZCBub3QgYmVnaW5uaW5nIHdpdGg= +ICAgICAgICAgICAgICAgICAgICAgICAgICA7ICJjb250ZW50LSIgY2FuIGhhdmUgbm8gZGVmaW5lZA== +ICAgICAgICAgICAgICAgICAgICAgICAgICA7IG1lYW5pbmcgYW5kIG1heSBiZSBpZ25vcmVkLg== +ICAgICAgICAgICAgICAgICAgICAgICAgICA7IFRoZSBvcmRlcmluZyBvZiB0aGUgaGVhZGVy +ICAgICAgICAgICAgICAgICAgICAgICAgICA7IGZpZWxkcyBpbXBsaWVkIGJ5IHRoaXMgQk5G +ICAgICAgICAgICAgICAgICAgICAgICAgICA7IGRlZmluaXRpb24gc2hvdWxkIGJlIGlnbm9yZWQu + +ICAgVGhlIHN5bnRheCBvZiB0aGUgdmFyaW91cyBzcGVjaWZpYyBNSU1FIGhlYWRlciBmaWVsZHMgd2lsbCBiZQ== +ICAgZGVzY3JpYmVkIGluIHRoZSBmb2xsb3dpbmcgc2VjdGlvbnMu + +RnJlZWQgJiBCb3JlbnN0ZWluICAgICAgICAgIFN0YW5kYXJkcyBUcmFjayAgICAgICAgICAgICAgICAgICAgW1BhZ2UgMTFd +UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAgICBOb3ZlbWJlciAxOTk2 + +NS4xLiAgU3ludGF4IG9mIHRoZSBDb250ZW50LVR5cGUgSGVhZGVyIEZpZWxk + +ICAgSW4gdGhlIEF1Z21lbnRlZCBCTkYgbm90YXRpb24gb2YgUkZDIDgyMiwgYSBDb250ZW50LVR5cGUgaGVhZGVyIGZpZWxk +ICAgdmFsdWUgaXMgZGVmaW5lZCBhcyBmb2xsb3dzOg== + +ICAgICBjb250ZW50IDo9ICJDb250ZW50LVR5cGUiICI6IiB0eXBlICIvIiBzdWJ0eXBl +ICAgICAgICAgICAgICAgICooIjsiIHBhcmFtZXRlcik= +ICAgICAgICAgICAgICAgIDsgTWF0Y2hpbmcgb2YgbWVkaWEgdHlwZSBhbmQgc3VidHlwZQ== +ICAgICAgICAgICAgICAgIDsgaXMgQUxXQVlTIGNhc2UtaW5zZW5zaXRpdmUu + +ICAgICB0eXBlIDo9IGRpc2NyZXRlLXR5cGUgLyBjb21wb3NpdGUtdHlwZQ== + +ICAgICBkaXNjcmV0ZS10eXBlIDo9ICJ0ZXh0IiAvICJpbWFnZSIgLyAiYXVkaW8iIC8gInZpZGVvIiAv +ICAgICAgICAgICAgICAgICAgICAgICJhcHBsaWNhdGlvbiIgLyBleHRlbnNpb24tdG9rZW4= + +ICAgICBjb21wb3NpdGUtdHlwZSA6PSAibWVzc2FnZSIgLyAibXVsdGlwYXJ0IiAvIGV4dGVuc2lvbi10b2tlbg== + +ICAgICBleHRlbnNpb24tdG9rZW4gOj0gaWV0Zi10b2tlbiAvIHgtdG9rZW4= + +ICAgICBpZXRmLXRva2VuIDo9IDxBbiBleHRlbnNpb24gdG9rZW4gZGVmaW5lZCBieSBh +ICAgICAgICAgICAgICAgICAgICBzdGFuZGFyZHMtdHJhY2sgUkZDIGFuZCByZWdpc3RlcmVk +ICAgICAgICAgICAgICAgICAgICB3aXRoIElBTkEuPg== + +ICAgICB4LXRva2VuIDo9IDxUaGUgdHdvIGNoYXJhY3RlcnMgIlgtIiBvciAieC0iIGZvbGxvd2VkLCB3aXRo +ICAgICAgICAgICAgICAgICBubyBpbnRlcnZlbmluZyB3aGl0ZSBzcGFjZSwgYnkgYW55IHRva2VuPg== + +ICAgICBzdWJ0eXBlIDo9IGV4dGVuc2lvbi10b2tlbiAvIGlhbmEtdG9rZW4= + +ICAgICBpYW5hLXRva2VuIDo9IDxBIHB1YmxpY2x5LWRlZmluZWQgZXh0ZW5zaW9uIHRva2VuLiBUb2tlbnM= +ICAgICAgICAgICAgICAgICAgICBvZiB0aGlzIGZvcm0gbXVzdCBiZSByZWdpc3RlcmVkIHdpdGggSUFOQQ== +ICAgICAgICAgICAgICAgICAgICBhcyBzcGVjaWZpZWQgaW4gUkZDIDIwNDguPg== + +ICAgICBwYXJhbWV0ZXIgOj0gYXR0cmlidXRlICI9IiB2YWx1ZQ== + +ICAgICBhdHRyaWJ1dGUgOj0gdG9rZW4= +ICAgICAgICAgICAgICAgICAgOyBNYXRjaGluZyBvZiBhdHRyaWJ1dGVz +ICAgICAgICAgICAgICAgICAgOyBpcyBBTFdBWVMgY2FzZS1pbnNlbnNpdGl2ZS4= + +ICAgICB2YWx1ZSA6PSB0b2tlbiAvIHF1b3RlZC1zdHJpbmc= + +ICAgICB0b2tlbiA6PSAxKjxhbnkgKFVTLUFTQ0lJKSBDSEFSIGV4Y2VwdCBTUEFDRSwgQ1RMcyw= +ICAgICAgICAgICAgICAgICBvciB0c3BlY2lhbHM+ + +ICAgICB0c3BlY2lhbHMgOj0gICIoIiAvICIpIiAvICI8IiAvICI+IiAvICJAIiAv +ICAgICAgICAgICAgICAgICAgICIsIiAvICI7IiAvICI6IiAvICJcIiAvIDwiPg== +ICAgICAgICAgICAgICAgICAgICIvIiAvICJbIiAvICJdIiAvICI/IiAvICI9Ig== +ICAgICAgICAgICAgICAgICAgIDsgTXVzdCBiZSBpbiBxdW90ZWQtc3RyaW5nLA== +ICAgICAgICAgICAgICAgICAgIDsgdG8gdXNlIHdpdGhpbiBwYXJhbWV0ZXIgdmFsdWVz + +ICAgICBkZXNjcmlwdGlvbiA6PSAiQ29udGVudC1EZXNjcmlwdGlvbiIgIjoiICp0ZXh0 + +ICAgICBlbmNvZGluZyA6PSAiQ29udGVudC1UcmFuc2Zlci1FbmNvZGluZyIgIjoiIG1lY2hhbmlzbQ== + +ICAgICBlbnRpdHktaGVhZGVycyA6PSBbIGNvbnRlbnQgQ1JMRiBd +ICAgICAgICAgICAgICAgICAgICBbIGVuY29kaW5nIENSTEYgXQ== +ICAgICAgICAgICAgICAgICAgICBbIGlkIENSTEYgXQ== +ICAgICAgICAgICAgICAgICAgICBbIGRlc2NyaXB0aW9uIENSTEYgXQ== +ICAgICAgICAgICAgICAgICAgICAqKCBNSU1FLWV4dGVuc2lvbi1maWVsZCBDUkxGICk= + +ICAgICBoZXgtb2N0ZXQgOj0gIj0iIDIoRElHSVQgLyAiQSIgLyAiQiIgLyAiQyIgLyAiRCIgLyAiRSIgLyAiRiIp +ICAgICAgICAgICAgICAgOyBPY3RldCBtdXN0IGJlIHVzZWQgZm9yIGNoYXJhY3RlcnMgPiAxMjcsID0s +ICAgICAgICAgICAgICAgOyBTUEFDRXMgb3IgVEFCcyBhdCB0aGUgZW5kcyBvZiBsaW5lcywgYW5kIGlz +ICAgICAgICAgICAgICAgOyByZWNvbW1lbmRlZCBmb3IgYW55IGNoYXJhY3RlciBub3QgbGlzdGVkIGlu +ICAgICAgICAgICAgICAgOyBSRkMgMjA0OSBhcyAibWFpbC1zYWZlIi4= + +UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAgICBOb3ZlbWJlciAxOTk2 + +ICAgICAgICAgIG11c3QgYmUgdXNlZC4gIEFuIGVxdWFsIHNpZ24gYXMgdGhlIGxhc3QgY2hhcmFjdGVyIG9uIGE= +ICAgICAgICAgIGVuY29kZWQgbGluZSBpbmRpY2F0ZXMgc3VjaCBhIG5vbi1zaWduaWZpY2FudCAoInNvZnQiKQ== +ICAgICAgICAgIGxpbmUgYnJlYWsgaW4gdGhlIGVuY29kZWQgdGV4dC4= + +ICAgVGh1cyBpZiB0aGUgInJhdyIgZm9ybSBvZiB0aGUgbGluZSBpcyBhIHNpbmdsZSB1bmVuY29kZWQgbGluZSB0aGF0 +ICAgc2F5czo= + +ICAgICBOb3cncyB0aGUgdGltZSBmb3IgYWxsIGZvbGsgdG8gY29tZSB0byB0aGUgYWlkIG9mIHRoZWlyIGNvdW50cnku + +ICAgVGhpcyBjYW4gYmUgcmVwcmVzZW50ZWQsIGluIHRoZSBRdW90ZWQtUHJpbnRhYmxlIGVuY29kaW5nLCBhczo= + +ICAgICBOb3cncyB0aGUgdGltZSA9 +ICAgICBmb3IgYWxsIGZvbGsgdG8gY29tZT0= +ICAgICAgdG8gdGhlIGFpZCBvZiB0aGVpciBjb3VudHJ5Lg== + +ICAgU2luY2UgdGhlIGh5cGhlbiBjaGFyYWN0ZXIgKCItIikgbWF5IGJlIHJlcHJlc2VudGVkIGFzIGl0c2VsZiBpbiB0aGU= +ICAgUXVvdGVkLVByaW50YWJsZSBlbmNvZGluZywgY2FyZSBtdXN0IGJlIHRha2VuLCB3aGVuIGVuY2Fwc3VsYXRpbmcgYQ== +ICAgcXVvdGVkLXByaW50YWJsZSBlbmNvZGVkIGJvZHkgaW5zaWRlIG9uZSBvciBtb3JlIG11bHRpcGFydCBlbnRpdGllcyw= +ICAgdG8gZW5zdXJlIHRoYXQgdGhlIGJvdW5kYXJ5IGRlbGltaXRlciBkb2VzIG5vdCBhcHBlYXIgYW55d2hlcmUgaW4gdGhl +ICAgZW5jb2RlZCBib2R5LiAgKEEgZ29vZCBzdHJhdGVneSBpcyB0byBjaG9vc2UgYSBib3VuZGFyeSB0aGF0IGluY2x1ZGVz +ICAgYSBjaGFyYWN0ZXIgc2VxdWVuY2Ugc3VjaCBhcyAiPV8iIHdoaWNoIGNhbiBuZXZlciBhcHBlYXIgaW4gYQ== +ICAgcXVvdGVkLXByaW50YWJsZSBib2R5LiAgU2VlIHRoZSBkZWZpbml0aW9uIG9mIG11bHRpcGFydCBtZXNzYWdlcyBpbg== +ICAgUkZDIDIwNDYuKQ== + +ICAgICAhIiMkQFtcXV5ge3x9fiU= + +RnJlZWQgJiBCb3JlbnN0ZWluICAgICAgICAgIFN0YW5kYXJkcyBUcmFjayAgICAgICAgICAgICAgICAgICAgW1BhZ2UgMjRd + +UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAgICBOb3ZlbWJlciAxOTk2 + + +ICAgICAgICAgICAgICAgICAgICBUYWJsZSAxOiBUaGUgQmFzZTY0IEFscGhhYmV0 + +ICAgICBWYWx1ZSBFbmNvZGluZyAgVmFsdWUgRW5jb2RpbmcgIFZhbHVlIEVuY29kaW5nICBWYWx1ZSBFbmNvZGluZw== +ICAgICAgICAgMCBBICAgICAgICAgICAgMTcgUiAgICAgICAgICAgIDM0IGkgICAgICAgICAgICA1MSB6 +ICAgICAgICAgMSBCICAgICAgICAgICAgMTggUyAgICAgICAgICAgIDM1IGogICAgICAgICAgICA1MiAw +ICAgICAgICAgMiBDICAgICAgICAgICAgMTkgVCAgICAgICAgICAgIDM2IGsgICAgICAgICAgICA1MyAx +ICAgICAgICAgMyBEICAgICAgICAgICAgMjAgVSAgICAgICAgICAgIDM3IGwgICAgICAgICAgICA1NCAy +ICAgICAgICAgNCBFICAgICAgICAgICAgMjEgViAgICAgICAgICAgIDM4IG0gICAgICAgICAgICA1NSAz +ICAgICAgICAgNSBGICAgICAgICAgICAgMjIgVyAgICAgICAgICAgIDM5IG4gICAgICAgICAgICA1NiA0 +ICAgICAgICAgNiBHICAgICAgICAgICAgMjMgWCAgICAgICAgICAgIDQwIG8gICAgICAgICAgICA1NyA1 +ICAgICAgICAgNyBIICAgICAgICAgICAgMjQgWSAgICAgICAgICAgIDQxIHAgICAgICAgICAgICA1OCA2 +ICAgICAgICAgOCBJICAgICAgICAgICAgMjUgWiAgICAgICAgICAgIDQyIHEgICAgICAgICAgICA1OSA3 +ICAgICAgICAgOSBKICAgICAgICAgICAgMjYgYSAgICAgICAgICAgIDQzIHIgICAgICAgICAgICA2MCA4 +ICAgICAgICAxMCBLICAgICAgICAgICAgMjcgYiAgICAgICAgICAgIDQ0IHMgICAgICAgICAgICA2MSA5 +ICAgICAgICAxMSBMICAgICAgICAgICAgMjggYyAgICAgICAgICAgIDQ1IHQgICAgICAgICAgICA2MiAr +ICAgICAgICAxMiBNICAgICAgICAgICAgMjkgZCAgICAgICAgICAgIDQ2IHUgICAgICAgICAgICA2MyAv +ICAgICAgICAxMyBOICAgICAgICAgICAgMzAgZSAgICAgICAgICAgIDQ3IHY= +ICAgICAgICAxNCBPICAgICAgICAgICAgMzEgZiAgICAgICAgICAgIDQ4IHcgICAgICAgICAocGFkKSA9 +ICAgICAgICAxNSBQICAgICAgICAgICAgMzIgZyAgICAgICAgICAgIDQ5IHg= +ICAgICAgICAxNiBRICAgICAgICAgICAgMzMgaCAgICAgICAgICAgIDUwIHk= diff --git a/jdk/test/java/util/Base64/mimeEncode.txt b/jdk/test/java/util/Base64/mimeEncode.txt new file mode 100644 index 00000000000..b107fa82a9e --- /dev/null +++ b/jdk/test/java/util/Base64/mimeEncode.txt @@ -0,0 +1,391 @@ +VGhpcyB0ZXN0IGRhdGEgaXMgcGFydCBvZiByZmMyMDQ1IHdoaWNoIGluY2x1ZGVzIGFsbCBjaGFy +YWN0ZXJzIGF+eiBBflosIDB+OSBhbmQgYWxsIHN5bWJvbHMs + +SXQgaXMgdXNlZCB0byB0ZXN0IGphdmEudXRpbC5CYXNlNjQuRW5jb2RlciwgYW5kIHdpbGwgYmUg +ZW5jb2RlZCBieSBvcmcuYXBhY2hlLmNvbW1vbnMuY29kZWMuYmluYXJ5LkJhc2U2NC5qYXZh + +dG8gdGVzdCBqYXZhLnV0aWwuQmFzZTY0LkRlY29kZXI7 + + +RnJlZWQgJiBCb3JlbnN0ZWluICAgICAgICAgIFN0YW5kYXJkcyBUcmFjayAgICAgICAgICAgICAg +ICAgICAgIFtQYWdlIDFd + +UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAg +ICBOb3ZlbWJlciAxOTk2 + + +ICAgVGhlc2UgZG9jdW1lbnRzIGFyZSByZXZpc2lvbnMgb2YgUkZDcyAxNTIxLCAxNTIyLCBhbmQg +MTU5MCwgd2hpY2g= + +ICAgdGhlbXNlbHZlcyB3ZXJlIHJldmlzaW9ucyBvZiBSRkNzIDEzNDEgYW5kIDEzNDIuICBBbiBh +cHBlbmRpeCBpbiBSRkM= + +ICAgMjA0OSBkZXNjcmliZXMgZGlmZmVyZW5jZXMgYW5kIGNoYW5nZXMgZnJvbSBwcmV2aW91cyB2 +ZXJzaW9ucy4= + + +VGFibGUgb2YgQ29udGVudHM= + + +ICAgMS4gSW50cm9kdWN0aW9uIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u +Li4uICAgIDM= + +ICAgMi4gRGVmaW5pdGlvbnMsIENvbnZlbnRpb25zLCBhbmQgR2VuZXJpYyBCTkYgR3JhbW1hciAu +Li4uICAgIDU= + +ICAgMy4gTUlNRSBIZWFkZXIgRmllbGRzIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u +Li4uICAgIDg= + +ICAgNC4gTUlNRS1WZXJzaW9uIEhlYWRlciBGaWVsZCAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u +Li4uICAgIDg= + +ICAgNS4gQ29udGVudC1UeXBlIEhlYWRlciBGaWVsZCAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u +Li4uICAgMTA= + +ICAgNi4gQ29udGVudC1UcmFuc2Zlci1FbmNvZGluZyBIZWFkZXIgRmllbGQgLi4uLi4uLi4uLi4u +Li4uICAgMTQ= + +ICAgNy4gQ29udGVudC1JRCBIZWFkZXIgRmllbGQgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u +Li4uICAgMjY= + +ICAgOC4gQ29udGVudC1EZXNjcmlwdGlvbiBIZWFkZXIgRmllbGQgLi4uLi4uLi4uLi4uLi4uLi4u +Li4uICAgMjc= + +ICAgOS4gQWRkaXRpb25hbCBNSU1FIEhlYWRlciBGaWVsZHMgLi4uLi4uLi4uLi4uLi4uLi4uLi4u +Li4uICAgMjc= + +ICAgMTAuIFN1bW1hcnkgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u +Li4uICAgMjc= + +ICAgMTEuIFNlY3VyaXR5IENvbnNpZGVyYXRpb25zIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u +Li4uICAgMjc= + +ICAgMTIuIEF1dGhvcnMnIEFkZHJlc3NlcyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u +Li4uICAgMjg= + +ICAgQS4gQ29sbGVjdGVkIEdyYW1tYXIgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u +Li4uICAgMjk= + + +RnJlZWQgJiBCb3JlbnN0ZWluICAgICAgICAgIFN0YW5kYXJkcyBUcmFjayAgICAgICAgICAgICAg +ICAgICAgIFtQYWdlIDdd + +UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAg +ICBOb3ZlbWJlciAxOTk2 + + +My4gIE1JTUUgSGVhZGVyIEZpZWxkcw== + + +ICAgTUlNRSBkZWZpbmVzIGEgbnVtYmVyIG9mIG5ldyBSRkMgODIyIGhlYWRlciBmaWVsZHMgdGhh +dCBhcmUgdXNlZCB0bw== + +ICAgZGVzY3JpYmUgdGhlIGNvbnRlbnQgb2YgYSBNSU1FIGVudGl0eS4gIFRoZXNlIGhlYWRlciBm +aWVsZHMgb2NjdXIgaW4= + +ICAgYXQgbGVhc3QgdHdvIGNvbnRleHRzOg== + + +ICAgICgxKSAgIEFzIHBhcnQgb2YgYSByZWd1bGFyIFJGQyA4MjIgbWVzc2FnZSBoZWFkZXIu + + +ICAgICgyKSAgIEluIGEgTUlNRSBib2R5IHBhcnQgaGVhZGVyIHdpdGhpbiBhIG11bHRpcGFydA== + +ICAgICAgICAgIGNvbnN0cnVjdC4= + + +ICAgVGhlIGZvcm1hbCBkZWZpbml0aW9uIG9mIHRoZXNlIGhlYWRlciBmaWVsZHMgaXMgYXMgZm9s +bG93czo= + + +ICAgICBNSU1FLW1lc3NhZ2UtaGVhZGVycyA6PSBlbnRpdHktaGVhZGVycw== + +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWVsZHM= + +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2ZXJzaW9uIENSTEY= + +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICA7IFRoZSBvcmRlcmluZyBvZiB0aGUgaGVhZGVy + +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICA7IGZpZWxkcyBpbXBsaWVkIGJ5IHRoaXMgQk5G + +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICA7IGRlZmluaXRpb24gc2hvdWxkIGJlIGlnbm9y +ZWQu + + +ICAgICBNSU1FLXBhcnQtaGVhZGVycyA6PSBlbnRpdHktaGVhZGVycw== + +ICAgICAgICAgICAgICAgICAgICAgICAgICBbIGZpZWxkcyBd + +ICAgICAgICAgICAgICAgICAgICAgICAgICA7IEFueSBmaWVsZCBub3QgYmVnaW5uaW5nIHdpdGg= + +ICAgICAgICAgICAgICAgICAgICAgICAgICA7ICJjb250ZW50LSIgY2FuIGhhdmUgbm8gZGVmaW5l +ZA== + +ICAgICAgICAgICAgICAgICAgICAgICAgICA7IG1lYW5pbmcgYW5kIG1heSBiZSBpZ25vcmVkLg== + +ICAgICAgICAgICAgICAgICAgICAgICAgICA7IFRoZSBvcmRlcmluZyBvZiB0aGUgaGVhZGVy + +ICAgICAgICAgICAgICAgICAgICAgICAgICA7IGZpZWxkcyBpbXBsaWVkIGJ5IHRoaXMgQk5G + +ICAgICAgICAgICAgICAgICAgICAgICAgICA7IGRlZmluaXRpb24gc2hvdWxkIGJlIGlnbm9yZWQu + + +ICAgVGhlIHN5bnRheCBvZiB0aGUgdmFyaW91cyBzcGVjaWZpYyBNSU1FIGhlYWRlciBmaWVsZHMg +d2lsbCBiZQ== + +ICAgZGVzY3JpYmVkIGluIHRoZSBmb2xsb3dpbmcgc2VjdGlvbnMu + + +RnJlZWQgJiBCb3JlbnN0ZWluICAgICAgICAgIFN0YW5kYXJkcyBUcmFjayAgICAgICAgICAgICAg +ICAgICAgW1BhZ2UgMTFd + +UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAg +ICBOb3ZlbWJlciAxOTk2 + + +NS4xLiAgU3ludGF4IG9mIHRoZSBDb250ZW50LVR5cGUgSGVhZGVyIEZpZWxk + + +ICAgSW4gdGhlIEF1Z21lbnRlZCBCTkYgbm90YXRpb24gb2YgUkZDIDgyMiwgYSBDb250ZW50LVR5 +cGUgaGVhZGVyIGZpZWxk + +ICAgdmFsdWUgaXMgZGVmaW5lZCBhcyBmb2xsb3dzOg== + + +ICAgICBjb250ZW50IDo9ICJDb250ZW50LVR5cGUiICI6IiB0eXBlICIvIiBzdWJ0eXBl + +ICAgICAgICAgICAgICAgICooIjsiIHBhcmFtZXRlcik= + +ICAgICAgICAgICAgICAgIDsgTWF0Y2hpbmcgb2YgbWVkaWEgdHlwZSBhbmQgc3VidHlwZQ== + +ICAgICAgICAgICAgICAgIDsgaXMgQUxXQVlTIGNhc2UtaW5zZW5zaXRpdmUu + + +ICAgICB0eXBlIDo9IGRpc2NyZXRlLXR5cGUgLyBjb21wb3NpdGUtdHlwZQ== + + +ICAgICBkaXNjcmV0ZS10eXBlIDo9ICJ0ZXh0IiAvICJpbWFnZSIgLyAiYXVkaW8iIC8gInZpZGVv +IiAv + +ICAgICAgICAgICAgICAgICAgICAgICJhcHBsaWNhdGlvbiIgLyBleHRlbnNpb24tdG9rZW4= + + +ICAgICBjb21wb3NpdGUtdHlwZSA6PSAibWVzc2FnZSIgLyAibXVsdGlwYXJ0IiAvIGV4dGVuc2lv +bi10b2tlbg== + + +ICAgICBleHRlbnNpb24tdG9rZW4gOj0gaWV0Zi10b2tlbiAvIHgtdG9rZW4= + + +ICAgICBpZXRmLXRva2VuIDo9IDxBbiBleHRlbnNpb24gdG9rZW4gZGVmaW5lZCBieSBh + +ICAgICAgICAgICAgICAgICAgICBzdGFuZGFyZHMtdHJhY2sgUkZDIGFuZCByZWdpc3RlcmVk + +ICAgICAgICAgICAgICAgICAgICB3aXRoIElBTkEuPg== + + +ICAgICB4LXRva2VuIDo9IDxUaGUgdHdvIGNoYXJhY3RlcnMgIlgtIiBvciAieC0iIGZvbGxvd2Vk +LCB3aXRo + +ICAgICAgICAgICAgICAgICBubyBpbnRlcnZlbmluZyB3aGl0ZSBzcGFjZSwgYnkgYW55IHRva2Vu +Pg== + + +ICAgICBzdWJ0eXBlIDo9IGV4dGVuc2lvbi10b2tlbiAvIGlhbmEtdG9rZW4= + + +ICAgICBpYW5hLXRva2VuIDo9IDxBIHB1YmxpY2x5LWRlZmluZWQgZXh0ZW5zaW9uIHRva2VuLiBU +b2tlbnM= + +ICAgICAgICAgICAgICAgICAgICBvZiB0aGlzIGZvcm0gbXVzdCBiZSByZWdpc3RlcmVkIHdpdGgg +SUFOQQ== + +ICAgICAgICAgICAgICAgICAgICBhcyBzcGVjaWZpZWQgaW4gUkZDIDIwNDguPg== + + +ICAgICBwYXJhbWV0ZXIgOj0gYXR0cmlidXRlICI9IiB2YWx1ZQ== + + +ICAgICBhdHRyaWJ1dGUgOj0gdG9rZW4= + +ICAgICAgICAgICAgICAgICAgOyBNYXRjaGluZyBvZiBhdHRyaWJ1dGVz + +ICAgICAgICAgICAgICAgICAgOyBpcyBBTFdBWVMgY2FzZS1pbnNlbnNpdGl2ZS4= + + +ICAgICB2YWx1ZSA6PSB0b2tlbiAvIHF1b3RlZC1zdHJpbmc= + + +ICAgICB0b2tlbiA6PSAxKjxhbnkgKFVTLUFTQ0lJKSBDSEFSIGV4Y2VwdCBTUEFDRSwgQ1RMcyw= + +ICAgICAgICAgICAgICAgICBvciB0c3BlY2lhbHM+ + + +ICAgICB0c3BlY2lhbHMgOj0gICIoIiAvICIpIiAvICI8IiAvICI+IiAvICJAIiAv + +ICAgICAgICAgICAgICAgICAgICIsIiAvICI7IiAvICI6IiAvICJcIiAvIDwiPg== + +ICAgICAgICAgICAgICAgICAgICIvIiAvICJbIiAvICJdIiAvICI/IiAvICI9Ig== + +ICAgICAgICAgICAgICAgICAgIDsgTXVzdCBiZSBpbiBxdW90ZWQtc3RyaW5nLA== + +ICAgICAgICAgICAgICAgICAgIDsgdG8gdXNlIHdpdGhpbiBwYXJhbWV0ZXIgdmFsdWVz + + +ICAgICBkZXNjcmlwdGlvbiA6PSAiQ29udGVudC1EZXNjcmlwdGlvbiIgIjoiICp0ZXh0 + + +ICAgICBlbmNvZGluZyA6PSAiQ29udGVudC1UcmFuc2Zlci1FbmNvZGluZyIgIjoiIG1lY2hhbmlz +bQ== + + +ICAgICBlbnRpdHktaGVhZGVycyA6PSBbIGNvbnRlbnQgQ1JMRiBd + +ICAgICAgICAgICAgICAgICAgICBbIGVuY29kaW5nIENSTEYgXQ== + +ICAgICAgICAgICAgICAgICAgICBbIGlkIENSTEYgXQ== + +ICAgICAgICAgICAgICAgICAgICBbIGRlc2NyaXB0aW9uIENSTEYgXQ== + +ICAgICAgICAgICAgICAgICAgICAqKCBNSU1FLWV4dGVuc2lvbi1maWVsZCBDUkxGICk= + + +ICAgICBoZXgtb2N0ZXQgOj0gIj0iIDIoRElHSVQgLyAiQSIgLyAiQiIgLyAiQyIgLyAiRCIgLyAi +RSIgLyAiRiIp + +ICAgICAgICAgICAgICAgOyBPY3RldCBtdXN0IGJlIHVzZWQgZm9yIGNoYXJhY3RlcnMgPiAxMjcs +ID0s + +ICAgICAgICAgICAgICAgOyBTUEFDRXMgb3IgVEFCcyBhdCB0aGUgZW5kcyBvZiBsaW5lcywgYW5k +IGlz + +ICAgICAgICAgICAgICAgOyByZWNvbW1lbmRlZCBmb3IgYW55IGNoYXJhY3RlciBub3QgbGlzdGVk +IGlu + +ICAgICAgICAgICAgICAgOyBSRkMgMjA0OSBhcyAibWFpbC1zYWZlIi4= + + +UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAg +ICBOb3ZlbWJlciAxOTk2 + + +ICAgICAgICAgIG11c3QgYmUgdXNlZC4gIEFuIGVxdWFsIHNpZ24gYXMgdGhlIGxhc3QgY2hhcmFj +dGVyIG9uIGE= + +ICAgICAgICAgIGVuY29kZWQgbGluZSBpbmRpY2F0ZXMgc3VjaCBhIG5vbi1zaWduaWZpY2FudCAo +InNvZnQiKQ== + +ICAgICAgICAgIGxpbmUgYnJlYWsgaW4gdGhlIGVuY29kZWQgdGV4dC4= + + +ICAgVGh1cyBpZiB0aGUgInJhdyIgZm9ybSBvZiB0aGUgbGluZSBpcyBhIHNpbmdsZSB1bmVuY29k +ZWQgbGluZSB0aGF0 + +ICAgc2F5czo= + + +ICAgICBOb3cncyB0aGUgdGltZSBmb3IgYWxsIGZvbGsgdG8gY29tZSB0byB0aGUgYWlkIG9mIHRo +ZWlyIGNvdW50cnku + + +ICAgVGhpcyBjYW4gYmUgcmVwcmVzZW50ZWQsIGluIHRoZSBRdW90ZWQtUHJpbnRhYmxlIGVuY29k +aW5nLCBhczo= + + +ICAgICBOb3cncyB0aGUgdGltZSA9 + +ICAgICBmb3IgYWxsIGZvbGsgdG8gY29tZT0= + +ICAgICAgdG8gdGhlIGFpZCBvZiB0aGVpciBjb3VudHJ5Lg== + + +ICAgU2luY2UgdGhlIGh5cGhlbiBjaGFyYWN0ZXIgKCItIikgbWF5IGJlIHJlcHJlc2VudGVkIGFz +IGl0c2VsZiBpbiB0aGU= + +ICAgUXVvdGVkLVByaW50YWJsZSBlbmNvZGluZywgY2FyZSBtdXN0IGJlIHRha2VuLCB3aGVuIGVu +Y2Fwc3VsYXRpbmcgYQ== + +ICAgcXVvdGVkLXByaW50YWJsZSBlbmNvZGVkIGJvZHkgaW5zaWRlIG9uZSBvciBtb3JlIG11bHRp +cGFydCBlbnRpdGllcyw= + +ICAgdG8gZW5zdXJlIHRoYXQgdGhlIGJvdW5kYXJ5IGRlbGltaXRlciBkb2VzIG5vdCBhcHBlYXIg +YW55d2hlcmUgaW4gdGhl + +ICAgZW5jb2RlZCBib2R5LiAgKEEgZ29vZCBzdHJhdGVneSBpcyB0byBjaG9vc2UgYSBib3VuZGFy +eSB0aGF0IGluY2x1ZGVz + +ICAgYSBjaGFyYWN0ZXIgc2VxdWVuY2Ugc3VjaCBhcyAiPV8iIHdoaWNoIGNhbiBuZXZlciBhcHBl +YXIgaW4gYQ== + +ICAgcXVvdGVkLXByaW50YWJsZSBib2R5LiAgU2VlIHRoZSBkZWZpbml0aW9uIG9mIG11bHRpcGFy +dCBtZXNzYWdlcyBpbg== + +ICAgUkZDIDIwNDYuKQ== + + +ICAgICAhIiMkQFtcXV5ge3x9fiU= + + +RnJlZWQgJiBCb3JlbnN0ZWluICAgICAgICAgIFN0YW5kYXJkcyBUcmFjayAgICAgICAgICAgICAg +ICAgICAgW1BhZ2UgMjRd + + +UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAg +ICBOb3ZlbWJlciAxOTk2 + + + +ICAgICAgICAgICAgICAgICAgICBUYWJsZSAxOiBUaGUgQmFzZTY0IEFscGhhYmV0 + + +ICAgICBWYWx1ZSBFbmNvZGluZyAgVmFsdWUgRW5jb2RpbmcgIFZhbHVlIEVuY29kaW5nICBWYWx1 +ZSBFbmNvZGluZw== + +ICAgICAgICAgMCBBICAgICAgICAgICAgMTcgUiAgICAgICAgICAgIDM0IGkgICAgICAgICAgICA1 +MSB6 + +ICAgICAgICAgMSBCICAgICAgICAgICAgMTggUyAgICAgICAgICAgIDM1IGogICAgICAgICAgICA1 +MiAw + +ICAgICAgICAgMiBDICAgICAgICAgICAgMTkgVCAgICAgICAgICAgIDM2IGsgICAgICAgICAgICA1 +MyAx + +ICAgICAgICAgMyBEICAgICAgICAgICAgMjAgVSAgICAgICAgICAgIDM3IGwgICAgICAgICAgICA1 +NCAy + +ICAgICAgICAgNCBFICAgICAgICAgICAgMjEgViAgICAgICAgICAgIDM4IG0gICAgICAgICAgICA1 +NSAz + +ICAgICAgICAgNSBGICAgICAgICAgICAgMjIgVyAgICAgICAgICAgIDM5IG4gICAgICAgICAgICA1 +NiA0 + +ICAgICAgICAgNiBHICAgICAgICAgICAgMjMgWCAgICAgICAgICAgIDQwIG8gICAgICAgICAgICA1 +NyA1 + +ICAgICAgICAgNyBIICAgICAgICAgICAgMjQgWSAgICAgICAgICAgIDQxIHAgICAgICAgICAgICA1 +OCA2 + +ICAgICAgICAgOCBJICAgICAgICAgICAgMjUgWiAgICAgICAgICAgIDQyIHEgICAgICAgICAgICA1 +OSA3 + +ICAgICAgICAgOSBKICAgICAgICAgICAgMjYgYSAgICAgICAgICAgIDQzIHIgICAgICAgICAgICA2 +MCA4 + +ICAgICAgICAxMCBLICAgICAgICAgICAgMjcgYiAgICAgICAgICAgIDQ0IHMgICAgICAgICAgICA2 +MSA5 + +ICAgICAgICAxMSBMICAgICAgICAgICAgMjggYyAgICAgICAgICAgIDQ1IHQgICAgICAgICAgICA2 +MiAr + +ICAgICAgICAxMiBNICAgICAgICAgICAgMjkgZCAgICAgICAgICAgIDQ2IHUgICAgICAgICAgICA2 +MyAv + +ICAgICAgICAxMyBOICAgICAgICAgICAgMzAgZSAgICAgICAgICAgIDQ3IHY= + +ICAgICAgICAxNCBPICAgICAgICAgICAgMzEgZiAgICAgICAgICAgIDQ4IHcgICAgICAgICAocGFk +KSA9 + +ICAgICAgICAxNSBQICAgICAgICAgICAgMzIgZyAgICAgICAgICAgIDQ5IHg= + +ICAgICAgICAxNiBRICAgICAgICAgICAgMzMgaCAgICAgICAgICAgIDUwIHk= + diff --git a/jdk/test/java/util/Base64/plain.txt b/jdk/test/java/util/Base64/plain.txt new file mode 100644 index 00000000000..804a19a50c9 --- /dev/null +++ b/jdk/test/java/util/Base64/plain.txt @@ -0,0 +1,183 @@ +This test data is part of rfc2045 which includes all characters a~z A~Z, 0~9 and all symbols, +It is used to test java.util.Base64.Encoder, and will be encoded by org.apache.commons.codec.binary.Base64.java +to test java.util.Base64.Decoder; + +Freed & Borenstein Standards Track [Page 1] +RFC 2045 Internet Message Bodies November 1996 + + These documents are revisions of RFCs 1521, 1522, and 1590, which + themselves were revisions of RFCs 1341 and 1342. An appendix in RFC + 2049 describes differences and changes from previous versions. + +Table of Contents + + 1. Introduction ......................................... 3 + 2. Definitions, Conventions, and Generic BNF Grammar .... 5 + 3. MIME Header Fields ................................... 8 + 4. MIME-Version Header Field ............................ 8 + 5. Content-Type Header Field ............................ 10 + 6. Content-Transfer-Encoding Header Field ............... 14 + 7. Content-ID Header Field .............................. 26 + 8. Content-Description Header Field ..................... 27 + 9. Additional MIME Header Fields ........................ 27 + 10. Summary ............................................. 27 + 11. Security Considerations ............................. 27 + 12. Authors' Addresses .................................. 28 + A. Collected Grammar .................................... 29 + +Freed & Borenstein Standards Track [Page 7] +RFC 2045 Internet Message Bodies November 1996 + +3. MIME Header Fields + + MIME defines a number of new RFC 822 header fields that are used to + describe the content of a MIME entity. These header fields occur in + at least two contexts: + + (1) As part of a regular RFC 822 message header. + + (2) In a MIME body part header within a multipart + construct. + + The formal definition of these header fields is as follows: + + MIME-message-headers := entity-headers + fields + version CRLF + ; The ordering of the header + ; fields implied by this BNF + ; definition should be ignored. + + MIME-part-headers := entity-headers + [ fields ] + ; Any field not beginning with + ; "content-" can have no defined + ; meaning and may be ignored. + ; The ordering of the header + ; fields implied by this BNF + ; definition should be ignored. + + The syntax of the various specific MIME header fields will be + described in the following sections. + +Freed & Borenstein Standards Track [Page 11] +RFC 2045 Internet Message Bodies November 1996 + +5.1. Syntax of the Content-Type Header Field + + In the Augmented BNF notation of RFC 822, a Content-Type header field + value is defined as follows: + + content := "Content-Type" ":" type "/" subtype + *(";" parameter) + ; Matching of media type and subtype + ; is ALWAYS case-insensitive. + + type := discrete-type / composite-type + + discrete-type := "text" / "image" / "audio" / "video" / + "application" / extension-token + + composite-type := "message" / "multipart" / extension-token + + extension-token := ietf-token / x-token + + ietf-token := + + x-token := + + subtype := extension-token / iana-token + + iana-token := + + parameter := attribute "=" value + + attribute := token + ; Matching of attributes + ; is ALWAYS case-insensitive. + + value := token / quoted-string + + token := 1* + + tspecials := "(" / ")" / "<" / ">" / "@" / + "," / ";" / ":" / "\" / <"> + "/" / "[" / "]" / "?" / "=" + ; Must be in quoted-string, + ; to use within parameter values + + description := "Content-Description" ":" *text + + encoding := "Content-Transfer-Encoding" ":" mechanism + + entity-headers := [ content CRLF ] + [ encoding CRLF ] + [ id CRLF ] + [ description CRLF ] + *( MIME-extension-field CRLF ) + + hex-octet := "=" 2(DIGIT / "A" / "B" / "C" / "D" / "E" / "F") + ; Octet must be used for characters > 127, =, + ; SPACEs or TABs at the ends of lines, and is + ; recommended for any character not listed in + ; RFC 2049 as "mail-safe". + +RFC 2045 Internet Message Bodies November 1996 + + must be used. An equal sign as the last character on a + encoded line indicates such a non-significant ("soft") + line break in the encoded text. + + Thus if the "raw" form of the line is a single unencoded line that + says: + + Now's the time for all folk to come to the aid of their country. + + This can be represented, in the Quoted-Printable encoding, as: + + Now's the time = + for all folk to come= + to the aid of their country. + + Since the hyphen character ("-") may be represented as itself in the + Quoted-Printable encoding, care must be taken, when encapsulating a + quoted-printable encoded body inside one or more multipart entities, + to ensure that the boundary delimiter does not appear anywhere in the + encoded body. (A good strategy is to choose a boundary that includes + a character sequence such as "=_" which can never appear in a + quoted-printable body. See the definition of multipart messages in + RFC 2046.) + + !"#$@[\]^`{|}~% + +Freed & Borenstein Standards Track [Page 24] + +RFC 2045 Internet Message Bodies November 1996 + + + Table 1: The Base64 Alphabet + + Value Encoding Value Encoding Value Encoding Value Encoding + 0 A 17 R 34 i 51 z + 1 B 18 S 35 j 52 0 + 2 C 19 T 36 k 53 1 + 3 D 20 U 37 l 54 2 + 4 E 21 V 38 m 55 3 + 5 F 22 W 39 n 56 4 + 6 G 23 X 40 o 57 5 + 7 H 24 Y 41 p 58 6 + 8 I 25 Z 42 q 59 7 + 9 J 26 a 43 r 60 8 + 10 K 27 b 44 s 61 9 + 11 L 28 c 45 t 62 + + 12 M 29 d 46 u 63 / + 13 N 30 e 47 v + 14 O 31 f 48 w (pad) = + 15 P 32 g 49 x + 16 Q 33 h 50 y diff --git a/jdk/test/java/util/Base64/urlEncode.txt b/jdk/test/java/util/Base64/urlEncode.txt new file mode 100644 index 00000000000..a55c4ddf194 --- /dev/null +++ b/jdk/test/java/util/Base64/urlEncode.txt @@ -0,0 +1,183 @@ +VGhpcyB0ZXN0IGRhdGEgaXMgcGFydCBvZiByZmMyMDQ1IHdoaWNoIGluY2x1ZGVzIGFsbCBjaGFyYWN0ZXJzIGF-eiBBflosIDB-OSBhbmQgYWxsIHN5bWJvbHMs +SXQgaXMgdXNlZCB0byB0ZXN0IGphdmEudXRpbC5CYXNlNjQuRW5jb2RlciwgYW5kIHdpbGwgYmUgZW5jb2RlZCBieSBvcmcuYXBhY2hlLmNvbW1vbnMuY29kZWMuYmluYXJ5LkJhc2U2NC5qYXZh +dG8gdGVzdCBqYXZhLnV0aWwuQmFzZTY0LkRlY29kZXI7 + +RnJlZWQgJiBCb3JlbnN0ZWluICAgICAgICAgIFN0YW5kYXJkcyBUcmFjayAgICAgICAgICAgICAgICAgICAgIFtQYWdlIDFd +UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAgICBOb3ZlbWJlciAxOTk2 + +ICAgVGhlc2UgZG9jdW1lbnRzIGFyZSByZXZpc2lvbnMgb2YgUkZDcyAxNTIxLCAxNTIyLCBhbmQgMTU5MCwgd2hpY2g= +ICAgdGhlbXNlbHZlcyB3ZXJlIHJldmlzaW9ucyBvZiBSRkNzIDEzNDEgYW5kIDEzNDIuICBBbiBhcHBlbmRpeCBpbiBSRkM= +ICAgMjA0OSBkZXNjcmliZXMgZGlmZmVyZW5jZXMgYW5kIGNoYW5nZXMgZnJvbSBwcmV2aW91cyB2ZXJzaW9ucy4= + +VGFibGUgb2YgQ29udGVudHM= + +ICAgMS4gSW50cm9kdWN0aW9uIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgIDM= +ICAgMi4gRGVmaW5pdGlvbnMsIENvbnZlbnRpb25zLCBhbmQgR2VuZXJpYyBCTkYgR3JhbW1hciAuLi4uICAgIDU= +ICAgMy4gTUlNRSBIZWFkZXIgRmllbGRzIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgIDg= +ICAgNC4gTUlNRS1WZXJzaW9uIEhlYWRlciBGaWVsZCAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgIDg= +ICAgNS4gQ29udGVudC1UeXBlIEhlYWRlciBGaWVsZCAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMTA= +ICAgNi4gQ29udGVudC1UcmFuc2Zlci1FbmNvZGluZyBIZWFkZXIgRmllbGQgLi4uLi4uLi4uLi4uLi4uICAgMTQ= +ICAgNy4gQ29udGVudC1JRCBIZWFkZXIgRmllbGQgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjY= +ICAgOC4gQ29udGVudC1EZXNjcmlwdGlvbiBIZWFkZXIgRmllbGQgLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjc= +ICAgOS4gQWRkaXRpb25hbCBNSU1FIEhlYWRlciBGaWVsZHMgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjc= +ICAgMTAuIFN1bW1hcnkgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjc= +ICAgMTEuIFNlY3VyaXR5IENvbnNpZGVyYXRpb25zIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjc= +ICAgMTIuIEF1dGhvcnMnIEFkZHJlc3NlcyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjg= +ICAgQS4gQ29sbGVjdGVkIEdyYW1tYXIgLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uICAgMjk= + +RnJlZWQgJiBCb3JlbnN0ZWluICAgICAgICAgIFN0YW5kYXJkcyBUcmFjayAgICAgICAgICAgICAgICAgICAgIFtQYWdlIDdd +UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAgICBOb3ZlbWJlciAxOTk2 + +My4gIE1JTUUgSGVhZGVyIEZpZWxkcw== + +ICAgTUlNRSBkZWZpbmVzIGEgbnVtYmVyIG9mIG5ldyBSRkMgODIyIGhlYWRlciBmaWVsZHMgdGhhdCBhcmUgdXNlZCB0bw== +ICAgZGVzY3JpYmUgdGhlIGNvbnRlbnQgb2YgYSBNSU1FIGVudGl0eS4gIFRoZXNlIGhlYWRlciBmaWVsZHMgb2NjdXIgaW4= +ICAgYXQgbGVhc3QgdHdvIGNvbnRleHRzOg== + +ICAgICgxKSAgIEFzIHBhcnQgb2YgYSByZWd1bGFyIFJGQyA4MjIgbWVzc2FnZSBoZWFkZXIu + +ICAgICgyKSAgIEluIGEgTUlNRSBib2R5IHBhcnQgaGVhZGVyIHdpdGhpbiBhIG11bHRpcGFydA== +ICAgICAgICAgIGNvbnN0cnVjdC4= + +ICAgVGhlIGZvcm1hbCBkZWZpbml0aW9uIG9mIHRoZXNlIGhlYWRlciBmaWVsZHMgaXMgYXMgZm9sbG93czo= + +ICAgICBNSU1FLW1lc3NhZ2UtaGVhZGVycyA6PSBlbnRpdHktaGVhZGVycw== +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWVsZHM= +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2ZXJzaW9uIENSTEY= +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICA7IFRoZSBvcmRlcmluZyBvZiB0aGUgaGVhZGVy +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICA7IGZpZWxkcyBpbXBsaWVkIGJ5IHRoaXMgQk5G +ICAgICAgICAgICAgICAgICAgICAgICAgICAgICA7IGRlZmluaXRpb24gc2hvdWxkIGJlIGlnbm9yZWQu + +ICAgICBNSU1FLXBhcnQtaGVhZGVycyA6PSBlbnRpdHktaGVhZGVycw== +ICAgICAgICAgICAgICAgICAgICAgICAgICBbIGZpZWxkcyBd +ICAgICAgICAgICAgICAgICAgICAgICAgICA7IEFueSBmaWVsZCBub3QgYmVnaW5uaW5nIHdpdGg= +ICAgICAgICAgICAgICAgICAgICAgICAgICA7ICJjb250ZW50LSIgY2FuIGhhdmUgbm8gZGVmaW5lZA== +ICAgICAgICAgICAgICAgICAgICAgICAgICA7IG1lYW5pbmcgYW5kIG1heSBiZSBpZ25vcmVkLg== +ICAgICAgICAgICAgICAgICAgICAgICAgICA7IFRoZSBvcmRlcmluZyBvZiB0aGUgaGVhZGVy +ICAgICAgICAgICAgICAgICAgICAgICAgICA7IGZpZWxkcyBpbXBsaWVkIGJ5IHRoaXMgQk5G +ICAgICAgICAgICAgICAgICAgICAgICAgICA7IGRlZmluaXRpb24gc2hvdWxkIGJlIGlnbm9yZWQu + +ICAgVGhlIHN5bnRheCBvZiB0aGUgdmFyaW91cyBzcGVjaWZpYyBNSU1FIGhlYWRlciBmaWVsZHMgd2lsbCBiZQ== +ICAgZGVzY3JpYmVkIGluIHRoZSBmb2xsb3dpbmcgc2VjdGlvbnMu + +RnJlZWQgJiBCb3JlbnN0ZWluICAgICAgICAgIFN0YW5kYXJkcyBUcmFjayAgICAgICAgICAgICAgICAgICAgW1BhZ2UgMTFd +UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAgICBOb3ZlbWJlciAxOTk2 + +NS4xLiAgU3ludGF4IG9mIHRoZSBDb250ZW50LVR5cGUgSGVhZGVyIEZpZWxk + +ICAgSW4gdGhlIEF1Z21lbnRlZCBCTkYgbm90YXRpb24gb2YgUkZDIDgyMiwgYSBDb250ZW50LVR5cGUgaGVhZGVyIGZpZWxk +ICAgdmFsdWUgaXMgZGVmaW5lZCBhcyBmb2xsb3dzOg== + +ICAgICBjb250ZW50IDo9ICJDb250ZW50LVR5cGUiICI6IiB0eXBlICIvIiBzdWJ0eXBl +ICAgICAgICAgICAgICAgICooIjsiIHBhcmFtZXRlcik= +ICAgICAgICAgICAgICAgIDsgTWF0Y2hpbmcgb2YgbWVkaWEgdHlwZSBhbmQgc3VidHlwZQ== +ICAgICAgICAgICAgICAgIDsgaXMgQUxXQVlTIGNhc2UtaW5zZW5zaXRpdmUu + +ICAgICB0eXBlIDo9IGRpc2NyZXRlLXR5cGUgLyBjb21wb3NpdGUtdHlwZQ== + +ICAgICBkaXNjcmV0ZS10eXBlIDo9ICJ0ZXh0IiAvICJpbWFnZSIgLyAiYXVkaW8iIC8gInZpZGVvIiAv +ICAgICAgICAgICAgICAgICAgICAgICJhcHBsaWNhdGlvbiIgLyBleHRlbnNpb24tdG9rZW4= + +ICAgICBjb21wb3NpdGUtdHlwZSA6PSAibWVzc2FnZSIgLyAibXVsdGlwYXJ0IiAvIGV4dGVuc2lvbi10b2tlbg== + +ICAgICBleHRlbnNpb24tdG9rZW4gOj0gaWV0Zi10b2tlbiAvIHgtdG9rZW4= + +ICAgICBpZXRmLXRva2VuIDo9IDxBbiBleHRlbnNpb24gdG9rZW4gZGVmaW5lZCBieSBh +ICAgICAgICAgICAgICAgICAgICBzdGFuZGFyZHMtdHJhY2sgUkZDIGFuZCByZWdpc3RlcmVk +ICAgICAgICAgICAgICAgICAgICB3aXRoIElBTkEuPg== + +ICAgICB4LXRva2VuIDo9IDxUaGUgdHdvIGNoYXJhY3RlcnMgIlgtIiBvciAieC0iIGZvbGxvd2VkLCB3aXRo +ICAgICAgICAgICAgICAgICBubyBpbnRlcnZlbmluZyB3aGl0ZSBzcGFjZSwgYnkgYW55IHRva2VuPg== + +ICAgICBzdWJ0eXBlIDo9IGV4dGVuc2lvbi10b2tlbiAvIGlhbmEtdG9rZW4= + +ICAgICBpYW5hLXRva2VuIDo9IDxBIHB1YmxpY2x5LWRlZmluZWQgZXh0ZW5zaW9uIHRva2VuLiBUb2tlbnM= +ICAgICAgICAgICAgICAgICAgICBvZiB0aGlzIGZvcm0gbXVzdCBiZSByZWdpc3RlcmVkIHdpdGggSUFOQQ== +ICAgICAgICAgICAgICAgICAgICBhcyBzcGVjaWZpZWQgaW4gUkZDIDIwNDguPg== + +ICAgICBwYXJhbWV0ZXIgOj0gYXR0cmlidXRlICI9IiB2YWx1ZQ== + +ICAgICBhdHRyaWJ1dGUgOj0gdG9rZW4= +ICAgICAgICAgICAgICAgICAgOyBNYXRjaGluZyBvZiBhdHRyaWJ1dGVz +ICAgICAgICAgICAgICAgICAgOyBpcyBBTFdBWVMgY2FzZS1pbnNlbnNpdGl2ZS4= + +ICAgICB2YWx1ZSA6PSB0b2tlbiAvIHF1b3RlZC1zdHJpbmc= + +ICAgICB0b2tlbiA6PSAxKjxhbnkgKFVTLUFTQ0lJKSBDSEFSIGV4Y2VwdCBTUEFDRSwgQ1RMcyw= +ICAgICAgICAgICAgICAgICBvciB0c3BlY2lhbHM- + +ICAgICB0c3BlY2lhbHMgOj0gICIoIiAvICIpIiAvICI8IiAvICI-IiAvICJAIiAv +ICAgICAgICAgICAgICAgICAgICIsIiAvICI7IiAvICI6IiAvICJcIiAvIDwiPg== +ICAgICAgICAgICAgICAgICAgICIvIiAvICJbIiAvICJdIiAvICI_IiAvICI9Ig== +ICAgICAgICAgICAgICAgICAgIDsgTXVzdCBiZSBpbiBxdW90ZWQtc3RyaW5nLA== +ICAgICAgICAgICAgICAgICAgIDsgdG8gdXNlIHdpdGhpbiBwYXJhbWV0ZXIgdmFsdWVz + +ICAgICBkZXNjcmlwdGlvbiA6PSAiQ29udGVudC1EZXNjcmlwdGlvbiIgIjoiICp0ZXh0 + +ICAgICBlbmNvZGluZyA6PSAiQ29udGVudC1UcmFuc2Zlci1FbmNvZGluZyIgIjoiIG1lY2hhbmlzbQ== + +ICAgICBlbnRpdHktaGVhZGVycyA6PSBbIGNvbnRlbnQgQ1JMRiBd +ICAgICAgICAgICAgICAgICAgICBbIGVuY29kaW5nIENSTEYgXQ== +ICAgICAgICAgICAgICAgICAgICBbIGlkIENSTEYgXQ== +ICAgICAgICAgICAgICAgICAgICBbIGRlc2NyaXB0aW9uIENSTEYgXQ== +ICAgICAgICAgICAgICAgICAgICAqKCBNSU1FLWV4dGVuc2lvbi1maWVsZCBDUkxGICk= + +ICAgICBoZXgtb2N0ZXQgOj0gIj0iIDIoRElHSVQgLyAiQSIgLyAiQiIgLyAiQyIgLyAiRCIgLyAiRSIgLyAiRiIp +ICAgICAgICAgICAgICAgOyBPY3RldCBtdXN0IGJlIHVzZWQgZm9yIGNoYXJhY3RlcnMgPiAxMjcsID0s +ICAgICAgICAgICAgICAgOyBTUEFDRXMgb3IgVEFCcyBhdCB0aGUgZW5kcyBvZiBsaW5lcywgYW5kIGlz +ICAgICAgICAgICAgICAgOyByZWNvbW1lbmRlZCBmb3IgYW55IGNoYXJhY3RlciBub3QgbGlzdGVkIGlu +ICAgICAgICAgICAgICAgOyBSRkMgMjA0OSBhcyAibWFpbC1zYWZlIi4= + +UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAgICBOb3ZlbWJlciAxOTk2 + +ICAgICAgICAgIG11c3QgYmUgdXNlZC4gIEFuIGVxdWFsIHNpZ24gYXMgdGhlIGxhc3QgY2hhcmFjdGVyIG9uIGE= +ICAgICAgICAgIGVuY29kZWQgbGluZSBpbmRpY2F0ZXMgc3VjaCBhIG5vbi1zaWduaWZpY2FudCAoInNvZnQiKQ== +ICAgICAgICAgIGxpbmUgYnJlYWsgaW4gdGhlIGVuY29kZWQgdGV4dC4= + +ICAgVGh1cyBpZiB0aGUgInJhdyIgZm9ybSBvZiB0aGUgbGluZSBpcyBhIHNpbmdsZSB1bmVuY29kZWQgbGluZSB0aGF0 +ICAgc2F5czo= + +ICAgICBOb3cncyB0aGUgdGltZSBmb3IgYWxsIGZvbGsgdG8gY29tZSB0byB0aGUgYWlkIG9mIHRoZWlyIGNvdW50cnku + +ICAgVGhpcyBjYW4gYmUgcmVwcmVzZW50ZWQsIGluIHRoZSBRdW90ZWQtUHJpbnRhYmxlIGVuY29kaW5nLCBhczo= + +ICAgICBOb3cncyB0aGUgdGltZSA9 +ICAgICBmb3IgYWxsIGZvbGsgdG8gY29tZT0= +ICAgICAgdG8gdGhlIGFpZCBvZiB0aGVpciBjb3VudHJ5Lg== + +ICAgU2luY2UgdGhlIGh5cGhlbiBjaGFyYWN0ZXIgKCItIikgbWF5IGJlIHJlcHJlc2VudGVkIGFzIGl0c2VsZiBpbiB0aGU= +ICAgUXVvdGVkLVByaW50YWJsZSBlbmNvZGluZywgY2FyZSBtdXN0IGJlIHRha2VuLCB3aGVuIGVuY2Fwc3VsYXRpbmcgYQ== +ICAgcXVvdGVkLXByaW50YWJsZSBlbmNvZGVkIGJvZHkgaW5zaWRlIG9uZSBvciBtb3JlIG11bHRpcGFydCBlbnRpdGllcyw= +ICAgdG8gZW5zdXJlIHRoYXQgdGhlIGJvdW5kYXJ5IGRlbGltaXRlciBkb2VzIG5vdCBhcHBlYXIgYW55d2hlcmUgaW4gdGhl +ICAgZW5jb2RlZCBib2R5LiAgKEEgZ29vZCBzdHJhdGVneSBpcyB0byBjaG9vc2UgYSBib3VuZGFyeSB0aGF0IGluY2x1ZGVz +ICAgYSBjaGFyYWN0ZXIgc2VxdWVuY2Ugc3VjaCBhcyAiPV8iIHdoaWNoIGNhbiBuZXZlciBhcHBlYXIgaW4gYQ== +ICAgcXVvdGVkLXByaW50YWJsZSBib2R5LiAgU2VlIHRoZSBkZWZpbml0aW9uIG9mIG11bHRpcGFydCBtZXNzYWdlcyBpbg== +ICAgUkZDIDIwNDYuKQ== + +ICAgICAhIiMkQFtcXV5ge3x9fiU= + +RnJlZWQgJiBCb3JlbnN0ZWluICAgICAgICAgIFN0YW5kYXJkcyBUcmFjayAgICAgICAgICAgICAgICAgICAgW1BhZ2UgMjRd + +UkZDIDIwNDUgICAgICAgICAgICAgICAgSW50ZXJuZXQgTWVzc2FnZSBCb2RpZXMgICAgICAgICAgICBOb3ZlbWJlciAxOTk2 + + +ICAgICAgICAgICAgICAgICAgICBUYWJsZSAxOiBUaGUgQmFzZTY0IEFscGhhYmV0 + +ICAgICBWYWx1ZSBFbmNvZGluZyAgVmFsdWUgRW5jb2RpbmcgIFZhbHVlIEVuY29kaW5nICBWYWx1ZSBFbmNvZGluZw== +ICAgICAgICAgMCBBICAgICAgICAgICAgMTcgUiAgICAgICAgICAgIDM0IGkgICAgICAgICAgICA1MSB6 +ICAgICAgICAgMSBCICAgICAgICAgICAgMTggUyAgICAgICAgICAgIDM1IGogICAgICAgICAgICA1MiAw +ICAgICAgICAgMiBDICAgICAgICAgICAgMTkgVCAgICAgICAgICAgIDM2IGsgICAgICAgICAgICA1MyAx +ICAgICAgICAgMyBEICAgICAgICAgICAgMjAgVSAgICAgICAgICAgIDM3IGwgICAgICAgICAgICA1NCAy +ICAgICAgICAgNCBFICAgICAgICAgICAgMjEgViAgICAgICAgICAgIDM4IG0gICAgICAgICAgICA1NSAz +ICAgICAgICAgNSBGICAgICAgICAgICAgMjIgVyAgICAgICAgICAgIDM5IG4gICAgICAgICAgICA1NiA0 +ICAgICAgICAgNiBHICAgICAgICAgICAgMjMgWCAgICAgICAgICAgIDQwIG8gICAgICAgICAgICA1NyA1 +ICAgICAgICAgNyBIICAgICAgICAgICAgMjQgWSAgICAgICAgICAgIDQxIHAgICAgICAgICAgICA1OCA2 +ICAgICAgICAgOCBJICAgICAgICAgICAgMjUgWiAgICAgICAgICAgIDQyIHEgICAgICAgICAgICA1OSA3 +ICAgICAgICAgOSBKICAgICAgICAgICAgMjYgYSAgICAgICAgICAgIDQzIHIgICAgICAgICAgICA2MCA4 +ICAgICAgICAxMCBLICAgICAgICAgICAgMjcgYiAgICAgICAgICAgIDQ0IHMgICAgICAgICAgICA2MSA5 +ICAgICAgICAxMSBMICAgICAgICAgICAgMjggYyAgICAgICAgICAgIDQ1IHQgICAgICAgICAgICA2MiAr +ICAgICAgICAxMiBNICAgICAgICAgICAgMjkgZCAgICAgICAgICAgIDQ2IHUgICAgICAgICAgICA2MyAv +ICAgICAgICAxMyBOICAgICAgICAgICAgMzAgZSAgICAgICAgICAgIDQ3IHY= +ICAgICAgICAxNCBPICAgICAgICAgICAgMzEgZiAgICAgICAgICAgIDQ4IHcgICAgICAgICAocGFkKSA9 +ICAgICAgICAxNSBQICAgICAgICAgICAgMzIgZyAgICAgICAgICAgIDQ5IHg= +ICAgICAgICAxNiBRICAgICAgICAgICAgMzMgaCAgICAgICAgICAgIDUwIHk= diff --git a/jdk/test/java/util/Calendar/GenericTimeZoneNamesTest.java b/jdk/test/java/util/Calendar/GenericTimeZoneNamesTest.java new file mode 100644 index 00000000000..f2dcbe5cfd5 --- /dev/null +++ b/jdk/test/java/util/Calendar/GenericTimeZoneNamesTest.java @@ -0,0 +1,57 @@ +/* + * 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. + */ + +import java.util.*; +import sun.util.locale.provider.TimeZoneNameUtility; + +public class GenericTimeZoneNamesTest { + private static final String[] PT = { + "America/Los_Angeles", "US/Pacific", "PST" + }; + + private static int errors = 0; + + public static void main(String[] args) { + for (String tag : args) { + Locale locale = Locale.forLanguageTag(tag); + for (String tzid : PT) { + test(tzid, TimeZone.LONG, locale, "Pacific Time"); + test(tzid, TimeZone.SHORT, locale, "PT"); + } + } + + if (errors != 0) { + throw new RuntimeException("test failed"); + } + } + + private static void test(String tzid, int style, Locale locale, String expected) { + // No public API to get generic time zone names (JDK 8) + String got = TimeZoneNameUtility.retrieveGenericDisplayName(tzid, style, locale); + if (!expected.equals(got)) { + System.err.printf("test: tzid=%s, locale=%s, style=%d, got=\"%s\", expected=\"%s\"%n", + tzid, locale, style, got, expected); + errors++; + } + } +} diff --git a/jdk/test/java/util/Calendar/GenericTimeZoneNamesTest.sh b/jdk/test/java/util/Calendar/GenericTimeZoneNamesTest.sh new file mode 100644 index 00000000000..a5491891bbb --- /dev/null +++ b/jdk/test/java/util/Calendar/GenericTimeZoneNamesTest.sh @@ -0,0 +1,47 @@ +# +# 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. +# + +# @test +# @bug 8003267 +# @summary Unit test for generic time zone names support +# @compile -XDignore.symbol.file GenericTimeZoneNamesTest.java +# @run shell GenericTimeZoneNamesTest.sh + +# This test is locale data-dependent and assumes that both JRE and CLDR +# have the same geneic time zone names in English. + +STATUS=0 +echo "Locale providers: default" +# TODO: The purpose of ja-JP is to make sure the fallback for generic +# names works. Remove ja-JP when adding generic names to localized +# resources. +if ! ${TESTJAVA}/bin/java -esa -cp "${TESTCLASSES}" GenericTimeZoneNamesTest en-US ja-JP; then + STATUS=1 +fi + +echo "Locale providers: CLDR" +if ! ${TESTJAVA}/bin/java -esa -cp "${TESTCLASSES}" -Djava.locale.providers=CLDR GenericTimeZoneNamesTest en-US; then + STATUS=1 +fi +exit ${STATUS} + diff --git a/jdk/test/java/util/Calendar/NarrowNamesTest.java b/jdk/test/java/util/Calendar/NarrowNamesTest.java new file mode 100644 index 00000000000..7338792abd3 --- /dev/null +++ b/jdk/test/java/util/Calendar/NarrowNamesTest.java @@ -0,0 +1,172 @@ +/* + * 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. + */ + +import java.util.*; +import static java.util.GregorianCalendar.*; + +public class NarrowNamesTest { + private static final Locale US = Locale.US; + private static final Locale JAJPJP = new Locale("ja", "JP", "JP"); + private static final Locale THTH = new Locale("th", "TH"); + + private static final String RESET_INDEX = "RESET_INDEX"; + + private static int errors = 0; + + // This test is locale data-dependent. + public static void main(String[] args) { + test(US, ERA, "B", + ERA, BC, YEAR, 1); + test(US, ERA, "A", + ERA, AD, YEAR, 2012); + test(US, DAY_OF_WEEK, "S", + YEAR, 2012, MONTH, DECEMBER, DAY_OF_MONTH, 23); + test(US, AM_PM, "a", + HOUR_OF_DAY, 10); + test(US, AM_PM, "p", + HOUR_OF_DAY, 23); + test(JAJPJP, DAY_OF_WEEK, "\u65e5", + YEAR, 24, MONTH, DECEMBER, DAY_OF_MONTH, 23); + test(THTH, MONTH, NARROW_STANDALONE, "\u0e18.\u0e04.", + YEAR, 2555, MONTH, DECEMBER, DAY_OF_MONTH, 5); + test(THTH, DAY_OF_WEEK, "\u0e1e", + YEAR, 2555, MONTH, DECEMBER, DAY_OF_MONTH, 5); + + testMap(US, DAY_OF_WEEK, ALL_STYLES, // shouldn't include any narrow names + "", // 1-based indexing for DAY_OF_WEEK + "Sunday", // Sunday + "Monday", // Monday + "Tuesday", // Tuesday + "Wednesday", // Wednesday + "Thursday", // Thursday + "Friday", // Friday + "Saturday", // Saturday + RESET_INDEX, + "", // 1-based indexing for DAY_OF_WEEK + "Sun", // abb Sunday + "Mon", // abb Monday + "Tue", // abb Tuesday + "Wed", // abb Wednesday + "Thu", // abb Thursday + "Fri", // abb Friday + "Sat" // abb Saturday + ); + testMap(US, DAY_OF_WEEK, NARROW_FORMAT); // expect null + testMap(US, AM_PM, ALL_STYLES, + "AM", "PM", + RESET_INDEX, + "a", "p"); + testMap(JAJPJP, DAY_OF_WEEK, NARROW_STANDALONE); // expect null + testMap(JAJPJP, DAY_OF_WEEK, NARROW_FORMAT, + "", // 1-based indexing for DAY_OF_WEEK + "\u65e5", + "\u6708", + "\u706b", + "\u6c34", + "\u6728", + "\u91d1", + "\u571f"); + testMap(THTH, MONTH, NARROW_FORMAT); // expect null + testMap(THTH, MONTH, NARROW_STANDALONE, + "\u0e21.\u0e04.", + "\u0e01.\u0e1e.", + "\u0e21\u0e35.\u0e04.", + "\u0e40\u0e21.\u0e22.", + "\u0e1e.\u0e04.", + "\u0e21\u0e34.\u0e22.", + "\u0e01.\u0e04.", + "\u0e2a.\u0e04.", + "\u0e01.\u0e22.", + "\u0e15.\u0e04.", + "\u0e1e.\u0e22.", + "\u0e18.\u0e04."); + + if (errors != 0) { + throw new RuntimeException("test failed"); + } + } + + private static void test(Locale locale, int field, String expected, int... data) { + test(locale, field, NARROW_FORMAT, expected, data); + } + + private static void test(Locale locale, int field, int style, String expected, int... fieldValuePairs) { + Calendar cal = Calendar.getInstance(locale); + cal.clear(); + for (int i = 0; i < fieldValuePairs.length;) { + int f = fieldValuePairs[i++]; + int v = fieldValuePairs[i++]; + cal.set(f, v); + } + String got = cal.getDisplayName(field, style, locale); + if (!expected.equals(got)) { + System.err.printf("test: locale=%s, field=%d, value=%d, style=%d, got=\"%s\", expected=\"%s\"%n", + locale, field, cal.get(field), style, got, expected); + errors++; + } + } + + private static void testMap(Locale locale, int field, int style, String... expected) { + Map expectedMap = null; + if (expected.length > 0) { + expectedMap = new TreeMap<>(LengthBasedComparator.INSTANCE); + int index = 0; + for (int i = 0; i < expected.length; i++) { + if (expected[i].isEmpty()) { + index++; + continue; + } + if (expected[i] == RESET_INDEX) { + index = 0; + continue; + } + expectedMap.put(expected[i], index++); + } + } + Calendar cal = Calendar.getInstance(locale); + Map got = cal.getDisplayNames(field, style, locale); + if (!(expectedMap == null && got == null) + && !expectedMap.equals(got)) { + System.err.printf("testMap: locale=%s, field=%d, style=%d, expected=%s, got=%s%n", + locale, field, style, expectedMap, got); + errors++; + } + } + + /** + * Comparator implementation for TreeMap which iterates keys from longest + * to shortest. + */ + private static class LengthBasedComparator implements Comparator { + private static final LengthBasedComparator INSTANCE = new LengthBasedComparator(); + + private LengthBasedComparator() { + } + + @Override + public int compare(String o1, String o2) { + int n = o2.length() - o1.length(); + return (n == 0) ? o1.compareTo(o2) : n; + } + } +} diff --git a/jdk/test/java/util/Calendar/NarrowNamesTest.sh b/jdk/test/java/util/Calendar/NarrowNamesTest.sh new file mode 100644 index 00000000000..742e35ac291 --- /dev/null +++ b/jdk/test/java/util/Calendar/NarrowNamesTest.sh @@ -0,0 +1,41 @@ +# +# 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. +# + +# @test +# @bug 8000983 +# @summary Unit test for narrow names support +# @build NarrowNamesTest +# @run shell NarrowNamesTest.sh + +# This test is locale data-dependent and assumes that both JRE and CLDR +# have the same narrow names. + +STATUS=0 +for P in "JRE,SPI" "CLDR" +do + echo "Locale providers: $P" + if ! ${TESTJAVA}/bin/java -esa -cp "${TESTCLASSES}" -Djava.locale.providers="${P}" NarrowNamesTest; then + STATUS=1 + fi +done +exit ${STATUS} diff --git a/jdk/test/java/util/Currency/PropertiesTest.java b/jdk/test/java/util/Currency/PropertiesTest.java index ab78ec08f3a..4b84e06584e 100644 --- a/jdk/test/java/util/Currency/PropertiesTest.java +++ b/jdk/test/java/util/Currency/PropertiesTest.java @@ -27,22 +27,15 @@ import java.util.*; import java.util.regex.*; public class PropertiesTest { - public static void main(String[] s) throws Exception { - for (int i = 0; i < s.length; i ++) { - if ("-d".equals(s[i])) { - i++; - if (i == s.length) { - throw new RuntimeException("-d needs output file name"); - } else { - dump(s[i]); - } - } else if ("-c".equals(s[i])) { - if (i+2 == s.length) { - throw new RuntimeException("-d needs two file name arguments, before and after respectively"); - } else { - compare(s[++i], s[++i]); - } - } + public static void main(String[] args) throws Exception { + if (args.length == 2 && args[0].equals("-d")) { + dump(args[1]); + } else if (args.length == 4 && args[0].equals("-c")) { + compare(args[1], args[2], args[3]); + } else { + System.err.println("Usage: java PropertiesTest -d "); + System.err.println(" java PropertiesTest -c "); + System.exit(-1); } } @@ -77,15 +70,17 @@ public class PropertiesTest { pw.close(); } - private static void compare(String beforeFile, String afterFile) throws Exception { + private static void compare(String beforeFile, String afterFile, String propsFile) + throws IOException + { // load file contents Properties before = new Properties(); + try (Reader reader = new FileReader(beforeFile)) { + before.load(reader); + } Properties after = new Properties(); - try { - before.load(new FileReader(beforeFile)); - after.load(new FileReader(afterFile)); - } catch (IOException ioe) { - throw new RuntimeException(ioe); + try (Reader reader = new FileReader(afterFile)) { + after.load(reader); } // remove the same contents from the 'after' properties @@ -103,13 +98,9 @@ public class PropertiesTest { } // now look at the currency.properties - String propFileName = System.getProperty("java.home") + File.separator + - "lib" + File.separator + "currency.properties"; Properties p = new Properties(); - try { - p.load(new FileReader(propFileName)); - } catch (IOException ioe) { - throw new RuntimeException(ioe); + try (Reader reader = new FileReader(propsFile)) { + p.load(reader); } // test each replacements diff --git a/jdk/test/java/util/Currency/PropertiesTest.sh b/jdk/test/java/util/Currency/PropertiesTest.sh index f016eed3d81..6c16851062e 100644 --- a/jdk/test/java/util/Currency/PropertiesTest.sh +++ b/jdk/test/java/util/Currency/PropertiesTest.sh @@ -1,7 +1,29 @@ #!/bin/sh + +# Copyright (c) 2007, 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. +# + # @test -# @bug 6332666 7180362 +# @bug 6332666 7180362 8003846 # @summary tests the capability of replacing the currency data with user # specified currency properties file # @build PropertiesTest @@ -36,7 +58,7 @@ case "$OS" in ;; Windows* | CYGWIN* ) PS=";" - FS="\\" + FS="/" ;; * ) echo "Unrecognized system!" @@ -44,23 +66,31 @@ case "$OS" in ;; esac -# Currency dump path #1. Just dump currencies with the bare JRE +failures=0 -# run -RUNCMD="${TESTJAVA}${FS}bin${FS}java -classpath ${TESTCLASSES} PropertiesTest -d dump1" +run() { + echo '' + sh -xc "${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -cp ${TESTCLASSES} $*" 2>&1 + if [ $? != 0 ]; then failures=`expr $failures + 1`; fi +} -echo ${RUNCMD} -${RUNCMD} -result=$? +PROPS=${TESTSRC}${FS}currency.properties -if [ $result -eq 0 ] -then - echo "Execution successful" -else - echo "Execution of the test case failed." -fi -# Currency dump path #2. Dump currencies using the JRE with replacement currencies +# Dump built-in currency data + +run PropertiesTest -d dump1 + + +# Dump built-in currency data + overrides in properties file specified +# by system property. + +run -Djava.util.currency.data=${PROPS} PropertiesTest -d dump2 +run PropertiesTest -c dump1 dump2 ${PROPS} + + +# Dump built-in currency data + overrides in properties file copied into +# JRE image. # copy the test properties file COPIED=0 @@ -79,44 +109,27 @@ then else PROPLOCATION=${WRITABLEJDK}${FS}lib fi -cp ${TESTSRC}${FS}currency.properties $PROPLOCATION +cp ${PROPS} $PROPLOCATION # run -RUNCMD="${WRITABLEJDK}${FS}bin${FS}java -classpath ${TESTCLASSES} PropertiesTest -d dump2" - -echo ${RUNCMD} -${RUNCMD} -result=$? - -if [ $result -eq 0 ] -then - echo "Execution successful" -else - echo "Execution of the test case failed." -fi - -# Now compare the two dump files - -RUNCMD="${WRITABLEJDK}${FS}bin${FS}java -classpath ${TESTCLASSES} PropertiesTest -c dump1 dump2" - -echo ${RUNCMD} -${RUNCMD} -result=$? - -if [ $result -eq 0 ] -then - echo "Execution successful" -else - echo "Execution of the test case failed." -fi +echo '' +sh -xc "${WRITABLEJDK}${FS}bin${FS}java ${TESTVMOPTS} -cp ${TESTCLASSES} PropertiesTest -d dump3" +if [ $? != 0 ]; then failures=`expr $failures + 1`; fi # Cleanup -rm -f dump1 -rm -f dump2 rm -f ${PROPLOCATION}${FS}currency.properties if [ $COPIED -eq 1 ] then rm -rf $WRITABLEJDK fi -exit $result +# compare the two dump files +run PropertiesTest -c dump1 dump3 ${PROPS} + + +# Results +echo '' +if [ $failures -gt 0 ]; + then echo "$failures tests failed"; + else echo "All tests passed"; fi +exit $failures diff --git a/jdk/test/java/util/Locale/LocaleCategory.sh b/jdk/test/java/util/Locale/LocaleCategory.sh index 34becd35a98..84b6119ec3d 100644 --- a/jdk/test/java/util/Locale/LocaleCategory.sh +++ b/jdk/test/java/util/Locale/LocaleCategory.sh @@ -69,7 +69,7 @@ esac # test user.xxx.display user.xxx.format properties # run -RUNCMD="${TESTJAVA}${FS}bin${FS}java -classpath ${TESTCLASSES} -Duser.language.display=ja -Duser.language.format=zh LocaleCategory" +RUNCMD="${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -classpath ${TESTCLASSES} -Duser.language.display=ja -Duser.language.format=zh LocaleCategory" echo ${RUNCMD} ${RUNCMD} @@ -85,7 +85,7 @@ fi # test user.xxx properties overriding user.xxx.display/format # run -RUNCMD="${TESTJAVA}${FS}bin${FS}java -classpath ${TESTCLASSES} -Duser.language=en -Duser.language.display=ja -Duser.language.format=zh LocaleCategory" +RUNCMD="${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -classpath ${TESTCLASSES} -Duser.language=en -Duser.language.display=ja -Duser.language.format=zh LocaleCategory" echo ${RUNCMD} ${RUNCMD} diff --git a/jdk/test/java/util/Locale/LocaleProviders.sh b/jdk/test/java/util/Locale/LocaleProviders.sh index 59e43fcff76..3cf0d4e7c69 100644 --- a/jdk/test/java/util/Locale/LocaleProviders.sh +++ b/jdk/test/java/util/Locale/LocaleProviders.sh @@ -96,12 +96,12 @@ ${TESTJAVA}${FS}bin${FS}javac -d ${SPIDIR}${FS}dest ${SPIDIR}${FS}src${FS}tznp.j ${TESTJAVA}${FS}bin${FS}jar cvf ${SPIDIR}${FS}tznp.jar -C ${SPIDIR}${FS}dest . # get the platform default locales -PLATDEF=`${TESTJAVA}${FS}bin${FS}java -classpath ${TESTCLASSES} LocaleProviders getPlatformLocale display` +PLATDEF=`${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -classpath ${TESTCLASSES} LocaleProviders getPlatformLocale display` DEFLANG=`echo ${PLATDEF} | sed -e "s/,.*//"` DEFCTRY=`echo ${PLATDEF} | sed -e "s/.*,//"` echo "DEFLANG=${DEFLANG}" echo "DEFCTRY=${DEFCTRY}" -PLATDEF=`${TESTJAVA}${FS}bin${FS}java -classpath ${TESTCLASSES} LocaleProviders getPlatformLocale format` +PLATDEF=`${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -classpath ${TESTCLASSES} LocaleProviders getPlatformLocale format` DEFFMTLANG=`echo ${PLATDEF} | sed -e "s/,.*//"` DEFFMTCTRY=`echo ${PLATDEF} | sed -e "s/.*,//"` echo "DEFFMTLANG=${DEFFMTLANG}" @@ -109,7 +109,7 @@ echo "DEFFMTCTRY=${DEFFMTCTRY}" runTest() { - RUNCMD="${TESTJAVA}${FS}bin${FS}java -classpath ${TESTCLASSES} -Djava.locale.providers=$PREFLIST LocaleProviders $METHODNAME $PARAM1 $PARAM2 $PARAM3" + RUNCMD="${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -classpath ${TESTCLASSES} -Djava.locale.providers=$PREFLIST LocaleProviders $METHODNAME $PARAM1 $PARAM2 $PARAM3" echo ${RUNCMD} ${RUNCMD} result=$? diff --git a/jdk/test/java/util/PluggableLocale/ExecTest.sh b/jdk/test/java/util/PluggableLocale/ExecTest.sh index 18bd8d16f61..c01e9e82742 100644 --- a/jdk/test/java/util/PluggableLocale/ExecTest.sh +++ b/jdk/test/java/util/PluggableLocale/ExecTest.sh @@ -119,9 +119,9 @@ fi # run if [ "$3" = "true" ] then - RUNCMD="${TESTJAVA}${FS}bin${FS}java -Djava.ext.dirs=${EXTDIRS} $2 " + RUNCMD="${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -Djava.ext.dirs=${EXTDIRS} $2 " else - RUNCMD="${TESTJAVA}${FS}bin${FS}java -classpath ${CLASSPATHARG} $2 " + RUNCMD="${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -classpath ${CLASSPATHARG} $2 " fi echo ${RUNCMD} diff --git a/jdk/test/java/util/PluggableLocale/GenericTest.java b/jdk/test/java/util/PluggableLocale/GenericTest.java index 8be74cdca91..eee0f95ff3a 100644 --- a/jdk/test/java/util/PluggableLocale/GenericTest.java +++ b/jdk/test/java/util/PluggableLocale/GenericTest.java @@ -41,6 +41,7 @@ public class GenericTest { com.bar.CurrencyNameProviderImpl2 currencyNP2 = new com.bar.CurrencyNameProviderImpl2(); com.bar.LocaleNameProviderImpl localeNP = new com.bar.LocaleNameProviderImpl(); com.bar.TimeZoneNameProviderImpl tzNP = new com.bar.TimeZoneNameProviderImpl(); + com.bar.GenericTimeZoneNameProviderImpl tzGenNP = new com.bar.GenericTimeZoneNameProviderImpl(); com.bar.CalendarDataProviderImpl calDataP = new com.bar.CalendarDataProviderImpl(); com.bar.CalendarNameProviderImpl calNameP = new com.bar.CalendarNameProviderImpl(); @@ -73,6 +74,7 @@ public class GenericTest { expected.addAll(Arrays.asList(currencyNP2.getAvailableLocales())); expected.addAll(Arrays.asList(localeNP.getAvailableLocales())); expected.addAll(Arrays.asList(tzNP.getAvailableLocales())); + expected.addAll(Arrays.asList(tzGenNP.getAvailableLocales())); expected.addAll(Arrays.asList(calDataP.getAvailableLocales())); expected.addAll(Arrays.asList(calNameP.getAvailableLocales())); if (!result.equals(expected)) { diff --git a/jdk/test/java/util/PluggableLocale/TimeZoneNameProviderTest.java b/jdk/test/java/util/PluggableLocale/TimeZoneNameProviderTest.java index cc71e6c6543..7ed2fc11429 100644 --- a/jdk/test/java/util/PluggableLocale/TimeZoneNameProviderTest.java +++ b/jdk/test/java/util/PluggableLocale/TimeZoneNameProviderTest.java @@ -40,6 +40,7 @@ public class TimeZoneNameProviderTest extends ProviderTest { TimeZoneNameProviderTest() { test1(); test2(); + test3(); aliasTest(); } @@ -92,6 +93,7 @@ public class TimeZoneNameProviderTest extends ProviderTest { final String pattern = "z"; final Locale OSAKA = new Locale("ja", "JP", "osaka"); final Locale KYOTO = new Locale("ja", "JP", "kyoto"); + final Locale GENERIC = new Locale("ja", "JP", "generic"); final String[] TIMEZONES = { "GMT", "America/Los_Angeles", "SystemV/PST8", @@ -157,6 +159,29 @@ public class TimeZoneNameProviderTest extends ProviderTest { } } + void test3() { + final String[] TZNAMES = { + LATIME, PST, PST8PDT, US_PACIFIC, + TOKYOTIME, JST, JAPAN, + }; + for (String tzname : TZNAMES) { + TimeZone tz = TimeZone.getTimeZone(tzname); + for (int style : new int[] { TimeZone.LONG, TimeZone.SHORT }) { + String osakaStd = tz.getDisplayName(false, style, OSAKA); + if (osakaStd != null) { + // No API for getting generic time zone names + String generic = TimeZoneNameUtility.retrieveGenericDisplayName(tzname, + style, GENERIC); + String expected = "Generic " + osakaStd; + if (!expected.equals(generic)) { + throw new RuntimeException("Wrong generic name: got=\"" + generic + + "\", expected=\"" + expected + "\""); + } + } + } + } + } + final String LATIME = "America/Los_Angeles"; final String PST = "PST"; final String PST8PDT = "PST8PDT"; diff --git a/jdk/test/java/util/PluggableLocale/TimeZoneNameProviderTest.sh b/jdk/test/java/util/PluggableLocale/TimeZoneNameProviderTest.sh index 76a08e6e83e..4e34ae09814 100644 --- a/jdk/test/java/util/PluggableLocale/TimeZoneNameProviderTest.sh +++ b/jdk/test/java/util/PluggableLocale/TimeZoneNameProviderTest.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2007, 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 @@ -23,6 +23,6 @@ #!/bin/sh # # @test -# @bug 4052440 +# @bug 4052440 8003267 # @summary TimeZoneNameProvider tests # @run shell ExecTest.sh bar TimeZoneNameProviderTest true diff --git a/jdk/test/java/util/PluggableLocale/barprovider.jar b/jdk/test/java/util/PluggableLocale/barprovider.jar index deed5facccb..3a6f37a9458 100644 Binary files a/jdk/test/java/util/PluggableLocale/barprovider.jar and b/jdk/test/java/util/PluggableLocale/barprovider.jar differ diff --git a/jdk/test/java/util/PluggableLocale/providersrc/GenericTimeZoneNameProviderImpl.java b/jdk/test/java/util/PluggableLocale/providersrc/GenericTimeZoneNameProviderImpl.java new file mode 100644 index 00000000000..b005b1a8b15 --- /dev/null +++ b/jdk/test/java/util/PluggableLocale/providersrc/GenericTimeZoneNameProviderImpl.java @@ -0,0 +1,58 @@ +/* + * 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. + */ +/* + * + */ + +package com.bar; + +import java.util.*; +import java.util.spi.*; + +import com.foobar.Utils; + +/** + * Implementation class for getGenericTimeZoneName which returns "Generic "+. + */ +public class GenericTimeZoneNameProviderImpl extends TimeZoneNameProviderImpl { + static final Locale jaJPGeneric = new Locale("ja", "JP", "generic"); + static final Locale OSAKA = new Locale("ja", "JP", "osaka"); + + static Locale[] avail = { + jaJPGeneric + }; + + @Override + public Locale[] getAvailableLocales() { + return avail; + } + + @Override + public String getGenericDisplayName(String id, int style, Locale locale) { + if (!jaJPGeneric.equals(locale)) { + return null; + } + String std = super.getDisplayName(id, false, style, OSAKA); + return (std != null) ? "Generic " + std : null; + } +} diff --git a/jdk/test/java/util/PluggableLocale/providersrc/Makefile b/jdk/test/java/util/PluggableLocale/providersrc/Makefile index 2af60665a36..916fed91e62 100644 --- a/jdk/test/java/util/PluggableLocale/providersrc/Makefile +++ b/jdk/test/java/util/PluggableLocale/providersrc/Makefile @@ -38,6 +38,7 @@ BARFILES_JAVA = \ CurrencyNameProviderImpl.java \ CurrencyNameProviderImpl2.java \ TimeZoneNameProviderImpl.java \ + GenericTimeZoneNameProviderImpl.java \ LocaleNameProviderImpl.java \ CalendarDataProviderImpl.java \ CalendarNameProviderImpl.java \ diff --git a/jdk/test/java/util/PluggableLocale/providersrc/java.util.spi.TimeZoneNameProvider b/jdk/test/java/util/PluggableLocale/providersrc/java.util.spi.TimeZoneNameProvider index c435e04e133..a72cb416c33 100644 --- a/jdk/test/java/util/PluggableLocale/providersrc/java.util.spi.TimeZoneNameProvider +++ b/jdk/test/java/util/PluggableLocale/providersrc/java.util.spi.TimeZoneNameProvider @@ -5,3 +5,4 @@ # implementation class # com.bar.TimeZoneNameProviderImpl +com.bar.GenericTimeZoneNameProviderImpl diff --git a/jdk/test/java/util/ResourceBundle/Bug6299235Test.sh b/jdk/test/java/util/ResourceBundle/Bug6299235Test.sh index ef17b412172..8bcb74f102d 100644 --- a/jdk/test/java/util/ResourceBundle/Bug6299235Test.sh +++ b/jdk/test/java/util/ResourceBundle/Bug6299235Test.sh @@ -75,7 +75,7 @@ echo "NEW_EXT_DIR=${NEW_EXT_DIR}" cd ${TESTSRC} -${TESTJAVA}/bin/java -cp ${TESTCLASSES} -Djava.ext.dirs=${NEW_EXT_DIR} Bug6299235Test +${TESTJAVA}/bin/java ${TESTVMOPTS} -cp ${TESTCLASSES} -Djava.ext.dirs=${NEW_EXT_DIR} Bug6299235Test if [ $? -ne 0 ] then diff --git a/jdk/test/java/util/ResourceBundle/Control/MissingResourceCauseTest.sh b/jdk/test/java/util/ResourceBundle/Control/MissingResourceCauseTest.sh index 7bb77326a78..d23ada5c9b6 100644 --- a/jdk/test/java/util/ResourceBundle/Control/MissingResourceCauseTest.sh +++ b/jdk/test/java/util/ResourceBundle/Control/MissingResourceCauseTest.sh @@ -50,7 +50,7 @@ chmod 000 $UNREADABLE : ${TESTCLASS:=.} : ${TESTSRC:=.} -${TESTJAVA}/bin/java -esa -cp ${TESTCLASS}${DEL}${TESTSRC} MissingResourceCauseTest +${TESTJAVA}/bin/java ${TESTVMOPTS} -esa -cp ${TESTCLASS}${DEL}${TESTSRC} MissingResourceCauseTest STATUS=$? chmod 666 $UNREADABLE rm -f $UNREADABLE diff --git a/jdk/test/java/util/ServiceLoader/basic.sh b/jdk/test/java/util/ServiceLoader/basic.sh index 259b2e15636..72d68fab7ae 100644 --- a/jdk/test/java/util/ServiceLoader/basic.sh +++ b/jdk/test/java/util/ServiceLoader/basic.sh @@ -94,7 +94,7 @@ go() { cp="$1"; shift if [ -z "$cp" ]; then cp="$TESTCLASSES"; else cp="$TESTCLASSES$SEP$cp"; fi vmargs="$1"; shift - sh -xc "'$JAVA' -cp $cp $vmargs $T $*" 2>&1 + sh -xc "'$JAVA' ${TESTVMOPTS} -cp $cp $vmargs $T $*" 2>&1 if [ $? != 0 ]; then failures=`expr $failures + 1`; fi } diff --git a/jdk/test/java/util/TimeZone/Bug6912560.java b/jdk/test/java/util/TimeZone/Bug6912560.java index c641f3329c6..e88ffb04c19 100644 --- a/jdk/test/java/util/TimeZone/Bug6912560.java +++ b/jdk/test/java/util/TimeZone/Bug6912560.java @@ -40,6 +40,9 @@ public class Bug6912560 { // set the user.timezone property String tzname = "Asia/Tokyo"; System.setProperty("user.timezone", tzname); + // make sure the timezone will be initialized by + // the next call to TimeZone.getDefault() + TimeZone.setDefault(null); System.setSecurityManager(new SecurityManager()); TimeZone tz = TimeZone.getDefault(); diff --git a/jdk/test/java/util/TimeZone/OldIDMappingTest.sh b/jdk/test/java/util/TimeZone/OldIDMappingTest.sh index 0f776e4e1fe..f7d67ba17e4 100644 --- a/jdk/test/java/util/TimeZone/OldIDMappingTest.sh +++ b/jdk/test/java/util/TimeZone/OldIDMappingTest.sh @@ -40,7 +40,7 @@ do if [ x"$I" != x ]; then D="-Dsun.timezone.ids.oldmapping=${I}" fi - if ! ${JAVA} ${D} -cp ${TESTCLASSES} OldIDMappingTest -new; then + if ! ${JAVA} ${D} ${TESTVMOPTS} -cp ${TESTCLASSES} OldIDMappingTest -new; then STATUS=1 fi done @@ -51,7 +51,7 @@ do if [ "x$I" != x ]; then D="-Dsun.timezone.ids.oldmapping=${I}" fi - if ! ${JAVA} ${D} -cp ${TESTCLASSES} OldIDMappingTest -old; then + if ! ${JAVA} ${D} ${TESTVMOPTS} -cp ${TESTCLASSES} OldIDMappingTest -old; then STATUS=1 fi done diff --git a/jdk/test/java/util/TimeZone/TimeZoneDatePermissionCheck.sh b/jdk/test/java/util/TimeZone/TimeZoneDatePermissionCheck.sh index 226228f1754..4a295ce532f 100644 --- a/jdk/test/java/util/TimeZone/TimeZoneDatePermissionCheck.sh +++ b/jdk/test/java/util/TimeZone/TimeZoneDatePermissionCheck.sh @@ -53,6 +53,6 @@ ${TESTJAVA}/bin/jarsigner \ # run it with the security manager on, plus accesscontroller debugging # will go into infinite recursion trying to get enough permissions for # printing Date of failing certificate unless fix is applied. -${TESTJAVA}/bin/java -Djava.security.manager \ +${TESTJAVA}/bin/java ${TESTVMOPTS} -Djava.security.manager \ -Djava.security.debug=access,failure,policy \ -cp ${TESTCLASSES}/timezonedatetest.jar TimeZoneDatePermissionCheck diff --git a/jdk/test/java/util/TreeMap/Clone.java b/jdk/test/java/util/TreeMap/Clone.java new file mode 100644 index 00000000000..efffa6a9633 --- /dev/null +++ b/jdk/test/java/util/TreeMap/Clone.java @@ -0,0 +1,58 @@ +/* + * 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. + */ + +/** + * @test + * @bug 7198904 + * @summary Verify that cloned TreeMap gets new keyset + * @author david.buck@oracle.com + * @run main/othervm Clone + * @run main/othervm -XX:+AggressiveOpts Clone + */ + +import java.util.TreeMap; + +public class Clone { + + public static void main(String[] args) throws Exception { + TreeMap m1 = new TreeMap(); + m1.put( "one", 1 ); + m1.keySet(); + TreeMap m2 = (TreeMap)m1.clone(); + m1.put( "two", 2 ); + m2.put( "three", 3 ); + // iterate over the clone (m2) and we should get "one" and "three" + for( final String key : m2.keySet() ) { + if( !"one".equals( key ) && !"three".equals( key ) ) { + throw new IllegalStateException( "Unexpected key: " + key ); + } + } + // iterate over the original (m1) and we should get "one" and "two" + for( final String key : m1.keySet() ) { + if( !"one".equals( key ) && !"two".equals( key ) ) { + throw new IllegalStateException( "Unexpected key: " + key ); + } + } + } + +} diff --git a/jdk/test/java/util/logging/CheckLockLocationTest.java b/jdk/test/java/util/logging/CheckLockLocationTest.java index 0eb98c0d4a0..956621ae6e4 100644 --- a/jdk/test/java/util/logging/CheckLockLocationTest.java +++ b/jdk/test/java/util/logging/CheckLockLocationTest.java @@ -30,7 +30,6 @@ * @run main/othervm CheckLockLocationTest */ import java.io.File; -import java.io.FileNotFoundException; import java.io.IOException; import java.nio.file.AccessDeniedException; import java.nio.file.FileSystemException; @@ -42,17 +41,22 @@ public class CheckLockLocationTest { private static final String NOT_A_DIR = "not-a-dir"; private static final String WRITABLE_DIR = "writable-dir"; private static final String NON_EXISTENT_DIR = "non-existent-dir"; + private static boolean runNonWritableDirTest; public static void main(String... args) throws IOException { // we'll base all file creation attempts on the system temp directory, // %t and also try specifying non-existent directories and plain files // that should be directories, and non-writable directories, // to exercise all code paths of checking the lock location + // Note that on platforms like Windows that don't support + // setWritable() on a directory, we'll skip the non-writable + // directory test if setWritable(false) returns false. + // File writableDir = setup(); // we now have three files/directories to work with: // writableDir // notAdir - // nonWritableDir + // nonWritableDir (may not be possible on some platforms) // nonExistentDir (which doesn't exist) runTests(writableDir); } @@ -79,15 +83,18 @@ public class CheckLockLocationTest { } // Test 2: creating FileHandler in non-writable directory should fail - try { - new FileHandler("%t/" + NON_WRITABLE_DIR + "/log.log"); - throw new RuntimeException("Test failed: should not have been able" - + " to create FileHandler for " + "%t/" + NON_WRITABLE_DIR - + "/log.log in non-writable directory."); - } catch (IOException ex) { - // check for the right exception - if (!(ex instanceof AccessDeniedException)) { - throw new RuntimeException("Test failed: Expected exception was not an AccessDeniedException", ex); + if (runNonWritableDirTest) { + try { + new FileHandler("%t/" + NON_WRITABLE_DIR + "/log.log"); + throw new RuntimeException("Test failed: should not have been able" + + " to create FileHandler for " + "%t/" + NON_WRITABLE_DIR + + "/log.log in non-writable directory."); + } catch (AccessDeniedException ex) { + // the right exception was thrown, so continue. + } catch (IOException ex) { + throw new RuntimeException( + "Test failed: Expected exception was not an " + + "AccessDeniedException", ex); } } @@ -97,11 +104,11 @@ public class CheckLockLocationTest { throw new RuntimeException("Test failed: should not have been able" + " to create FileHandler for " + "%t/" + NOT_A_DIR + "/log.log in non-directory."); + } catch (FileSystemException ex) { + // the right exception was thrown, so continue. } catch (IOException ex) { - // check for the right exception - if (!(ex instanceof FileSystemException && ex.getMessage().contains("Not a directory"))) { - throw new RuntimeException("Test failed: Expected exception was not a FileSystemException", ex); - } + throw new RuntimeException("Test failed: exception thrown was not a " + + "FileSystemException", ex); } // Test 4: make sure we can't create a FileHandler in a non-existent dir @@ -110,11 +117,11 @@ public class CheckLockLocationTest { throw new RuntimeException("Test failed: should not have been able" + " to create FileHandler for " + "%t/" + NON_EXISTENT_DIR + "/log.log in a non-existent directory."); + } catch (NoSuchFileException ex) { + // the right exception was thrown, so continue. } catch (IOException ex) { - // check for the right exception - if (!(ex instanceof NoSuchFileException)) { - throw new RuntimeException("Test failed: Expected exception was not a NoSuchFileException", ex); - } + throw new RuntimeException("Test failed: Expected exception " + + "was not a NoSuchFileException", ex); } } @@ -162,10 +169,14 @@ public class CheckLockLocationTest { nonWritableDir.deleteOnExit(); // make it non-writable - if (!nonWritableDir.setWritable(false)) { - throw new RuntimeException("Test setup failed: unable to make" + if (nonWritableDir.setWritable(false)) { + runNonWritableDirTest = true; + } else { + runNonWritableDirTest = false; + System.out.println( "Test Setup WARNING: unable to make" + " working directory " + nonWritableDir.getAbsolutePath() - + " non-writable."); + + " non-writable on platform " + System.getProperty("os.name")); + } // make sure non-existent directory really doesn't exist @@ -199,12 +210,14 @@ public class CheckLockLocationTest { /* * Recursively delete all files starting at specified file */ - private static void delete(File f) throws IOException { + private static void delete(File f) { if (f != null && f.isDirectory()) { for (File c : f.listFiles()) delete(c); } if (!f.delete()) - throw new FileNotFoundException("Failed to delete file: " + f); - } + System.err.println( + "WARNING: unable to delete/cleanup writable test directory: " + + f ); + } } diff --git a/jdk/test/java/util/logging/ClassLoaderLeakTest.java b/jdk/test/java/util/logging/ClassLoaderLeakTest.java index a1c56fa6abe..f2957dba7b8 100644 --- a/jdk/test/java/util/logging/ClassLoaderLeakTest.java +++ b/jdk/test/java/util/logging/ClassLoaderLeakTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -40,7 +40,6 @@ import java.net.URL; import java.net.URLClassLoader; import java.util.concurrent.CountDownLatch; import java.util.logging.Logger; -import java.util.logging.Logger; public class ClassLoaderLeakTest { @@ -59,11 +58,11 @@ public class ClassLoaderLeakTest { try { ClassLoader cl = Thread.currentThread().getContextClassLoader(); - Class appMain = cl.loadClass("AppTest"); + Class appMain = cl.loadClass("AppTest"); Method launch = appMain.getDeclaredMethod("launch", doneSignal.getClass()); - Constructor c = appMain.getConstructor(); + Constructor c = appMain.getConstructor(); Object o = c.newInstance(); @@ -80,8 +79,7 @@ public class ClassLoaderLeakTest { /* prepare test class loader */ URL pwd = null; try { - - pwd = new File(System.getProperty("test.classes",".")).toURL(); + pwd = new File(System.getProperty("test.classes",".")).toURI().toURL(); } catch (MalformedURLException e) { throw new RuntimeException("Test failed.", e); } @@ -139,7 +137,7 @@ public class ClassLoaderLeakTest { uniqClassName = uniq; } - public Class loadClass(String name) throws ClassNotFoundException { + public Class loadClass(String name) throws ClassNotFoundException { if (verbose) { System.out.printf("%s: load class %s\n", uniqClassName, name); } diff --git a/jdk/test/java/util/logging/Listeners.java b/jdk/test/java/util/logging/Listeners.java index 265fdced588..86383ef065b 100644 --- a/jdk/test/java/util/logging/Listeners.java +++ b/jdk/test/java/util/logging/Listeners.java @@ -88,6 +88,7 @@ public class Listeners { } } + @SuppressWarnings("deprecation") public static void main(String[] args) throws Exception { LogManager logman = LogManager.getLogManager(); diff --git a/jdk/test/java/util/logging/ListenersWithSM.java b/jdk/test/java/util/logging/ListenersWithSM.java index 41af3299bd1..49eba235dc6 100644 --- a/jdk/test/java/util/logging/ListenersWithSM.java +++ b/jdk/test/java/util/logging/ListenersWithSM.java @@ -35,6 +35,7 @@ import java.beans.PropertyChangeEvent; public class ListenersWithSM { + @SuppressWarnings("deprecation") public static void main(String[] args) throws Exception { boolean granted = args[0].equals("grant"); diff --git a/jdk/test/java/util/logging/LoggerResourceBundleRace.java b/jdk/test/java/util/logging/LoggerResourceBundleRace.java index c7976d7cced..e159a2ddeb9 100644 --- a/jdk/test/java/util/logging/LoggerResourceBundleRace.java +++ b/jdk/test/java/util/logging/LoggerResourceBundleRace.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -30,11 +30,10 @@ * @run main LoggerResourceBundleRace */ -import java.util.concurrent.atomic.AtomicInteger; import java.util.ListResourceBundle; -import java.util.logging.Logger; import java.util.MissingResourceException; -import java.util.ResourceBundle; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.logging.Logger; public class LoggerResourceBundleRace extends RacingThreadsTest { diff --git a/jdk/test/java/util/logging/LoggingDeadlock2.java b/jdk/test/java/util/logging/LoggingDeadlock2.java index 611ec2ae8da..8c83ae90cee 100644 --- a/jdk/test/java/util/logging/LoggingDeadlock2.java +++ b/jdk/test/java/util/logging/LoggingDeadlock2.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -103,7 +103,7 @@ public class LoggingDeadlock2 { // This may or may not result in a first call to // Runtime.addShutdownHook after shutdown has already // commenced. - LogManager log = LogManager.getLogManager(); + LogManager.getLogManager(); if (dojoin) { exiter.join(); @@ -148,7 +148,6 @@ public class LoggingDeadlock2 { public String out() { return out; } public String err() { return err; } public int exitValue() { return exitValue; } - public Throwable throwable() { return throwable; } public String toString() { StringBuilder sb = new StringBuilder(); diff --git a/jdk/test/java/util/logging/LoggingDeadlock3.java b/jdk/test/java/util/logging/LoggingDeadlock3.java index 1b94d0316d0..73162d58b6b 100644 --- a/jdk/test/java/util/logging/LoggingDeadlock3.java +++ b/jdk/test/java/util/logging/LoggingDeadlock3.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -61,7 +61,7 @@ public class LoggingDeadlock3 { public static class GetLogger implements Runnable { public void run() { for (int cnt = 0; cnt < ITER_CNT * 8; cnt++) { - Logger logger = Logger.getLogger("com.sun.Hello"+cnt/10); + Logger.getLogger("com.sun.Hello"+cnt/10); if (cnt % 1000 == 0) out.print("1"); if (cnt % 10000 == 0) out.println(); } diff --git a/jdk/test/java/util/logging/LoggingDeadlock4.java b/jdk/test/java/util/logging/LoggingDeadlock4.java index f52d74b1277..65846979fb9 100644 --- a/jdk/test/java/util/logging/LoggingDeadlock4.java +++ b/jdk/test/java/util/logging/LoggingDeadlock4.java @@ -30,7 +30,6 @@ * @run main/othervm/timeout=15 -Djava.awt.headless=true LoggingDeadlock4 */ -import java.awt.Container; import java.util.concurrent.CountDownLatch; import java.util.logging.LogManager; import java.util.logging.Logger; @@ -68,7 +67,7 @@ public class LoggingDeadlock4 { } catch (InterruptedException e) { } - LogManager manager = LogManager.getLogManager(); + LogManager.getLogManager(); } }; lmThread.start(); @@ -86,7 +85,7 @@ public class LoggingDeadlock4 { } catch (InterruptedException e) { } - Logger foo = Logger.getLogger("foo logger"); + Logger.getLogger("foo logger"); } }; logThread.start(); diff --git a/jdk/test/java/util/logging/LoggingMXBeanTest.java b/jdk/test/java/util/logging/LoggingMXBeanTest.java index a01e57c1357..a023aeeb0e7 100644 --- a/jdk/test/java/util/logging/LoggingMXBeanTest.java +++ b/jdk/test/java/util/logging/LoggingMXBeanTest.java @@ -208,7 +208,7 @@ public class LoggingMXBeanTest String levelName = (String) mbs.invoke( objectName, "getLoggerLevel", params, signature ); l = Level.parse(levelName); System.out.print(" Logger1: " ); - if ( l.equals( l.ALL ) ) { + if ( l.equals( Level.ALL ) ) { System.out.println("Level Set to ALL: PASSED" ); log1 = true; } @@ -226,7 +226,7 @@ public class LoggingMXBeanTest levelName = (String) mbs.invoke( objectName, "getLoggerLevel", params, signature ); l = Level.parse(levelName); System.out.print(" Logger2: " ); - if ( l.equals( l.FINER ) ) { + if ( l.equals( Level.FINER ) ) { System.out.println("Level Set to FINER: PASSED" ); log2 = true; } @@ -247,6 +247,6 @@ public class LoggingMXBeanTest } public static void main(String[] argv) throws Exception { - LoggingMXBeanTest p = new LoggingMXBeanTest(); + new LoggingMXBeanTest(); } } diff --git a/jdk/test/java/util/logging/LoggingMXBeanTest2.java b/jdk/test/java/util/logging/LoggingMXBeanTest2.java index 005ed72e03a..3791e80b242 100644 --- a/jdk/test/java/util/logging/LoggingMXBeanTest2.java +++ b/jdk/test/java/util/logging/LoggingMXBeanTest2.java @@ -37,7 +37,6 @@ import java.util.ListIterator; public class LoggingMXBeanTest2 { - static LoggingMXBean mbean = LogManager.getLoggingMXBean(); static String LOGGER_NAME_1 = "com.sun.management.Logger"; static String LOGGER_NAME_2 = "com.sun.management.Logger.Logger2"; @@ -57,14 +56,14 @@ public class LoggingMXBeanTest2 */ System.out.println("Test Logger Name retrieval (getLoggerNames)"); boolean log1 = false, log2 = false; - List loggers = mbean.getLoggerNames(); + List loggers = mbean.getLoggerNames(); if (loggers == null || loggers.size() < 2) { throw new RuntimeException( "Could not Detect the presense of the new Loggers"); } - for (ListIterator iter = loggers.listIterator(); iter.hasNext(); ) { - String logger = (String) iter.next(); + for (ListIterator iter = loggers.listIterator(); iter.hasNext(); ) { + String logger = iter.next(); if (logger.equals(LOGGER_NAME_1)) { log1 = true; System.out.println(" : Found new Logger : " + logger); @@ -187,6 +186,6 @@ public class LoggingMXBeanTest2 } public static void main(String[] argv) throws Exception { - LoggingMXBeanTest2 p = new LoggingMXBeanTest2(); + new LoggingMXBeanTest2(); } } diff --git a/jdk/test/java/util/logging/MemoryHandlerTest.java b/jdk/test/java/util/logging/MemoryHandlerTest.java index 026e571859f..ee80ef7864b 100644 --- a/jdk/test/java/util/logging/MemoryHandlerTest.java +++ b/jdk/test/java/util/logging/MemoryHandlerTest.java @@ -48,7 +48,7 @@ public class MemoryHandlerTest { File fname = new File(tstSrc, LM_PROP_FNAME); String prop = fname.getCanonicalPath(); System.setProperty(CFG_FILE_PROP, prop); - LogManager logMgr = LogManager.getLogManager(); + LogManager.getLogManager(); // create a logger logger = Logger.getLogger(MemoryHandlerTest.class.getName()); // don't have parent handlers get log messages diff --git a/jdk/test/java/util/logging/ParentLoggersTest.java b/jdk/test/java/util/logging/ParentLoggersTest.java index 3dc4bfcc25b..72d5ddadc0f 100644 --- a/jdk/test/java/util/logging/ParentLoggersTest.java +++ b/jdk/test/java/util/logging/ParentLoggersTest.java @@ -1,3 +1,26 @@ +/* + * 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. + */ + /* * @test * @bug 6498300 @@ -86,12 +109,12 @@ public class ParentLoggersTest { Vector expectedLoggerNames = new Vector(getDefaultLoggerNames()); // Create the logger LOGGER_NAME_1 - Logger logger1 = Logger.getLogger(LOGGER_NAME_1); + Logger.getLogger(LOGGER_NAME_1); expectedLoggerNames.addElement(PARENT_NAME_1); expectedLoggerNames.addElement(LOGGER_NAME_1); // Create the logger LOGGER_NAME_2 - Logger logger2 = Logger.getLogger(LOGGER_NAME_2); + Logger.getLogger(LOGGER_NAME_2); expectedLoggerNames.addElement(PARENT_NAME_2); expectedLoggerNames.addElement(LOGGER_NAME_2); diff --git a/jdk/test/java/util/logging/SimpleFormatterFormat.java b/jdk/test/java/util/logging/SimpleFormatterFormat.java index fc786a0f092..4fafba3b778 100644 --- a/jdk/test/java/util/logging/SimpleFormatterFormat.java +++ b/jdk/test/java/util/logging/SimpleFormatterFormat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -92,8 +92,9 @@ public class SimpleFormatterFormat { System.out.println("Checking log records in file: " + log); Pattern p = Pattern.compile("([\\.a-zA-Z:]+) (.*) \\[.*\\] source: (.*)"); - try (FileInputStream in = new FileInputStream(log)) { - BufferedReader reader = new BufferedReader(new InputStreamReader(in)); + try (FileInputStream in = new FileInputStream(log); + BufferedReader reader = new BufferedReader(new InputStreamReader(in)); + ) { String line; int i = 0; while (i < messages.length && diff --git a/jdk/test/java/util/prefs/AddNodeChangeListener.java b/jdk/test/java/util/prefs/AddNodeChangeListener.java index 8b506dc7e18..761ed2b48cf 100644 --- a/jdk/test/java/util/prefs/AddNodeChangeListener.java +++ b/jdk/test/java/util/prefs/AddNodeChangeListener.java @@ -24,9 +24,10 @@ */ /* @test - * @bug 7160252 + * @bug 7160252 7197662 * @summary Checks if events are delivered to a listener * when a child node is added or removed + * @run main/othervm -Djava.util.prefs.userRoot=. AddNodeChangeListener */ import java.util.prefs.*; diff --git a/jdk/test/java/util/prefs/CheckUserPrefsStorage.sh b/jdk/test/java/util/prefs/CheckUserPrefsStorage.sh index 71ded594cb2..28210696b39 100644 --- a/jdk/test/java/util/prefs/CheckUserPrefsStorage.sh +++ b/jdk/test/java/util/prefs/CheckUserPrefsStorage.sh @@ -22,10 +22,10 @@ # # @test -# @bug 7198073 +# @bug 7198073 7197662 # @build CheckUserPrefFirst CheckUserPrefLater # @run shell CheckUserPrefsStorage.sh -# @summary Tests that user preferences are stored in the +# @summary Tests that user preferences are stored in the # permanent storage # @@ -50,14 +50,14 @@ case "$OS" in esac # run CheckUserPrefFirst - creates and stores a user pref -${TESTJAVA}${FS}bin${FS}java -cp ${TESTCLASSES} CheckUserPrefFirst +${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -cp ${TESTCLASSES} -Djava.util.prefs.userRoot=. CheckUserPrefFirst result=$? if [ "$result" -ne "0" ]; then exit 1 fi # run CheckUserPrefLater - Looks for the stored pref -${TESTJAVA}${FS}bin${FS}java -cp ${TESTCLASSES} CheckUserPrefLater +${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -cp ${TESTCLASSES} -Djava.util.prefs.userRoot=. CheckUserPrefLater result=$? if [ "$result" -ne "0" ]; then exit 1 diff --git a/jdk/test/java/util/prefs/CommentsInXml.java b/jdk/test/java/util/prefs/CommentsInXml.java index bf8cdb9f7de..47011af880b 100644 --- a/jdk/test/java/util/prefs/CommentsInXml.java +++ b/jdk/test/java/util/prefs/CommentsInXml.java @@ -23,8 +23,9 @@ /* * @test - * @bug 4619564 + * @bug 4619564 7197662 * @summary XMl Comments in Preferences File lead to ClassCastException + * @run main/othervm -Djava.util.prefs.userRoot=. CommentsInXml * @author kladko */ diff --git a/jdk/test/java/util/prefs/ConflictInFlush.java b/jdk/test/java/util/prefs/ConflictInFlush.java index 290bab7d5e8..1f13ca736ef 100644 --- a/jdk/test/java/util/prefs/ConflictInFlush.java +++ b/jdk/test/java/util/prefs/ConflictInFlush.java @@ -23,8 +23,9 @@ /* * @test - * @bug 4703132 + * @bug 4703132 7197662 * @summary flush() throws an IllegalStateException on a removed node + * @run main/othervm -Djava.util.prefs.userRoot=. ConflictInFlush * @author Sucheta Dambalkar */ diff --git a/jdk/test/java/util/prefs/ExportNode.java b/jdk/test/java/util/prefs/ExportNode.java index 5ecab0ffd41..601b18920b3 100644 --- a/jdk/test/java/util/prefs/ExportNode.java +++ b/jdk/test/java/util/prefs/ExportNode.java @@ -24,9 +24,10 @@ /* * @test - * @bug 4387136 4947349 + * @bug 4387136 4947349 7197662 * @summary Due to a bug in XMLSupport.putPreferencesInXml(...), * node's keys would not get exported. + * @run main/othervm -Djava.util.prefs.userRoot=. ExportNode * @author Konstantin Kladko */ import java.util.prefs.*; diff --git a/jdk/test/java/util/prefs/ExportSubtree.java b/jdk/test/java/util/prefs/ExportSubtree.java index 36bfe79d53f..f1e632c6b4e 100644 --- a/jdk/test/java/util/prefs/ExportSubtree.java +++ b/jdk/test/java/util/prefs/ExportSubtree.java @@ -23,9 +23,10 @@ /* @test - @bug 6203576 4700020 - @summary checks if the output of exportSubtree() is identical to - the output from previous release. + * @bug 6203576 4700020 7197662 + * @summary checks if the output of exportSubtree() is identical to + * the output from previous release. + * @run main/othervm -Djava.util.prefs.userRoot=. ExportSubtree */ import java.io.*; diff --git a/jdk/test/java/util/prefs/PrefsSpi.sh b/jdk/test/java/util/prefs/PrefsSpi.sh index 10a0ded018f..877522e3f91 100644 --- a/jdk/test/java/util/prefs/PrefsSpi.sh +++ b/jdk/test/java/util/prefs/PrefsSpi.sh @@ -24,7 +24,7 @@ # # @test -# @bug 4991526 6514993 +# @bug 4991526 6514993 7197662 # @summary Unit test for Preferences jar providers # # @build PrefsSpi @@ -87,14 +87,18 @@ Sys "$javac" -d jarDir StubPreferencesFactory.java StubPreferences.java case "`uname`" in Windows*|CYGWIN* ) CPS=';';; *) CPS=':';; esac -Sys "$java" "-cp" "$TESTCLASSES${CPS}extDir/PrefsSpi.jar" \ +Sys "$java" "${TESTVMOPTS}" "-cp" "$TESTCLASSES${CPS}extDir/PrefsSpi.jar" \ -Djava.util.prefs.PreferencesFactory=StubPreferencesFactory \ + -Djava.util.prefs.userRoot=. \ PrefsSpi "StubPreferences" -Sys "$java" "-cp" "$TESTCLASSES" \ +Sys "$java" "${TESTVMOPTS}" "-cp" "$TESTCLASSES" \ + -Djava.util.prefs.userRoot=. \ PrefsSpi "java.util.prefs.*" -Sys "$java" "-cp" "$TESTCLASSES${CPS}extDir/PrefsSpi.jar" \ +Sys "$java" "${TESTVMOPTS}" "-cp" "$TESTCLASSES${CPS}extDir/PrefsSpi.jar" \ + -Djava.util.prefs.userRoot=. \ PrefsSpi "StubPreferences" -Sys "$java" "-cp" "$TESTCLASSES" "-Djava.ext.dirs=extDir" \ +Sys "$java" "${TESTVMOPTS}" "-cp" "$TESTCLASSES" "-Djava.ext.dirs=extDir" \ + -Djava.util.prefs.userRoot=. \ PrefsSpi "StubPreferences" rm -rf jarDir extDir diff --git a/jdk/test/java/util/prefs/RemoveNullKeyCheck.java b/jdk/test/java/util/prefs/RemoveNullKeyCheck.java index c74f0d82d37..eac63d5ead8 100644 --- a/jdk/test/java/util/prefs/RemoveNullKeyCheck.java +++ b/jdk/test/java/util/prefs/RemoveNullKeyCheck.java @@ -22,9 +22,10 @@ */ /* @test - * @bug 7160242 7165118 + * @bug 7160242 7165118 7197662 * @summary Check if NullPointerException is thrown if the key passed * to remove() is null. + * @run main/othervm -Djava.util.prefs.userRoot=. RemoveNullKeyCheck */ import java.util.prefs.Preferences; diff --git a/jdk/test/java/util/prefs/RemoveReadOnlyNode.java b/jdk/test/java/util/prefs/RemoveReadOnlyNode.java index 501a337b757..ca7684fc0f9 100644 --- a/jdk/test/java/util/prefs/RemoveReadOnlyNode.java +++ b/jdk/test/java/util/prefs/RemoveReadOnlyNode.java @@ -23,10 +23,11 @@ /* @test - @bug 6178148 - @summary check if wrong exception gets thrown if one of the child - nodes is readonly on underlying filesystem when node is - being removed. + * @bug 6178148 7197662 + * @summary check if wrong exception gets thrown if one of the child + * nodes is readonly on underlying filesystem when node is + * being removed. + * @run main/othervm -Djava.util.prefs.userRoot=. RemoveReadOnlyNode */ import java.io.*; diff --git a/jdk/test/java/util/prefs/RemoveUnregedListener.java b/jdk/test/java/util/prefs/RemoveUnregedListener.java index 901dde3e0a0..126a7d79f1e 100644 --- a/jdk/test/java/util/prefs/RemoveUnregedListener.java +++ b/jdk/test/java/util/prefs/RemoveUnregedListener.java @@ -23,9 +23,10 @@ /* @test - * @bug 4705094 + * @bug 4705094 7197662 * @summary Checks if correct exception gets thrown when removing an * unregistered NodeChangeListener . + * @run main/othervm -Djava.util.prefs.userRoot=. RemoveUnregedListener */ import java.util.prefs.*; diff --git a/jdk/test/java/util/spi/ResourceBundleControlProvider/UserDefaultControlTest.sh b/jdk/test/java/util/spi/ResourceBundleControlProvider/UserDefaultControlTest.sh index c6b91235609..538142606a0 100644 --- a/jdk/test/java/util/spi/ResourceBundleControlProvider/UserDefaultControlTest.sh +++ b/jdk/test/java/util/spi/ResourceBundleControlProvider/UserDefaultControlTest.sh @@ -21,4 +21,5 @@ # questions. # -${TESTJAVA}/bin/java -Djava.ext.dirs=${TESTSRC} -cp ${TESTCLASSES} UserDefaultControlTest \ No newline at end of file +${TESTJAVA}/bin/java ${TESTVMOPTS} -Djava.ext.dirs=${TESTSRC} -cp ${TESTCLASSES} UserDefaultControlTest + diff --git a/jdk/test/java/util/zip/3GBZipFiles.sh b/jdk/test/java/util/zip/3GBZipFiles.sh index 9caf109000c..65db4e296ea 100644 --- a/jdk/test/java/util/zip/3GBZipFiles.sh +++ b/jdk/test/java/util/zip/3GBZipFiles.sh @@ -1,4 +1,3 @@ -# # Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # @@ -83,7 +82,7 @@ buildFile () huge-*) filesize_="$hugeSize" ;; tiny-*) filesize_="$tinySize" ;; esac - sys "$JAVA" "-cp" "$TESTCLASSES" "FileBuilder" \ + sys "$JAVA" ${TESTVMOPTS} "-cp" "$TESTCLASSES" "FileBuilder" \ "$filetype_" "$filename_" "$filesize_" } diff --git a/jdk/test/java/util/zip/ZipFile/deletetempjar.sh b/jdk/test/java/util/zip/ZipFile/deletetempjar.sh index afa47feb91d..bad1a0f1e4b 100644 --- a/jdk/test/java/util/zip/ZipFile/deletetempjar.sh +++ b/jdk/test/java/util/zip/ZipFile/deletetempjar.sh @@ -30,7 +30,7 @@ if [ "x$TESTJAVA" = x ]; then TESTCLASSES=. fi -tmpfile=`$TESTJAVA/bin/java -classpath $TESTCLASSES DeleteTempJar` +tmpfile=`$TESTJAVA/bin/java ${TESTVMOPTS} -classpath $TESTCLASSES DeleteTempJar` rc=$? if [ $rc != 0 ]; then echo Unexpected failure with exit status $rc diff --git a/jdk/test/javax/crypto/SecretKeyFactory/FailOverTest.sh b/jdk/test/javax/crypto/SecretKeyFactory/FailOverTest.sh index b23e2bd99a2..ab8bb0ed8c9 100644 --- a/jdk/test/javax/crypto/SecretKeyFactory/FailOverTest.sh +++ b/jdk/test/javax/crypto/SecretKeyFactory/FailOverTest.sh @@ -82,6 +82,7 @@ if [ $? -ne 0 ]; then fi ${TESTJAVA}${FS}bin${FS}java \ + ${TESTVMOPTS} \ -classpath "${TESTSRC}${FS}P1.jar${PS}${TESTSRC}${FS}P2.jar${PS}." \ FailOverTest result=$? diff --git a/jdk/test/javax/print/applet/AppletPrintLookup.sh b/jdk/test/javax/print/applet/AppletPrintLookup.sh index c49b9f09c1f..06afe6ffd54 100644 --- a/jdk/test/javax/print/applet/AppletPrintLookup.sh +++ b/jdk/test/javax/print/applet/AppletPrintLookup.sh @@ -82,7 +82,7 @@ cp ${TESTSRC}${SEP}AppletPrintLookup.html ${TESTCLASSES} ${TESTJAVA}${SEP}bin${SEP}appletviewer ${TESTCLASSES}${SEP}AppletPrintLookup.html & cd ${TESTCLASSES} -${TESTJAVA}${SEP}bin${SEP}java YesNo +${TESTJAVA}${SEP}bin${SEP}java ${TESTVMOPTS} YesNo if [ $? -ne 0 ] then echo "Test fails!" diff --git a/jdk/test/javax/rmi/ssl/SocketFactoryTest.java b/jdk/test/javax/rmi/ssl/SocketFactoryTest.java index cf88fd746a0..76bf51a1c77 100644 --- a/jdk/test/javax/rmi/ssl/SocketFactoryTest.java +++ b/jdk/test/javax/rmi/ssl/SocketFactoryTest.java @@ -26,8 +26,7 @@ * @bug 4932837 6582235 * @summary Test SslRMI[Client|Server]SocketFactory equals() and hashCode(). * @author Daniel Fuchs - * @run clean SocketFactoryTest - * @run build SocketFactoryTest + * * @run main SocketFactoryTest */ diff --git a/jdk/test/javax/script/ProviderTest.sh b/jdk/test/javax/script/ProviderTest.sh index 5221d00d5fd..c39a9333914 100644 --- a/jdk/test/javax/script/ProviderTest.sh +++ b/jdk/test/javax/script/ProviderTest.sh @@ -45,6 +45,6 @@ $JAR -cf ${TESTCLASSES}/dummy.jar \ echo "Running test ..." -$JAVA -classpath \ +$JAVA ${TESTVMOPTS} -classpath \ "${TESTCLASSES}${PS}${TESTCLASSES}/dummy.jar" \ ProviderTest diff --git a/jdk/test/javax/security/auth/Subject/doAs/Test.sh b/jdk/test/javax/security/auth/Subject/doAs/Test.sh index cbf94e031f0..65ef4531e26 100644 --- a/jdk/test/javax/security/auth/Subject/doAs/Test.sh +++ b/jdk/test/javax/security/auth/Subject/doAs/Test.sh @@ -71,7 +71,7 @@ WD=`pwd` cd ${TESTSRC}${FS} cd $WD echo $WD -${TESTJAVA}${FS}bin${FS}java -classpath "${TESTCLASSES}${FS}" \ +${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -classpath "${TESTCLASSES}${FS}" \ -Djava.security.manager \ -Djava.security.policy=${TESTSRC}${FS}policy \ Test diff --git a/jdk/test/javax/swing/JInternalFrame/5066752/bug5066752.java b/jdk/test/javax/swing/JInternalFrame/5066752/bug5066752.java new file mode 100644 index 00000000000..09a8a7bd28f --- /dev/null +++ b/jdk/test/javax/swing/JInternalFrame/5066752/bug5066752.java @@ -0,0 +1,78 @@ +/* + * 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. + */ +/* + @test + @bug 5066752 + @summary Transparent JDesktopPane impossible because isOpaque() returns true + @author mb50250: area=JDesktopPane + @library ../../regtesthelpers + @build Util + @run main bug5066752 +*/ + +import java.awt.*; +import javax.swing.*; +import sun.awt.*; + +public class bug5066752 +{ + private static JFrame frame; + + public static void main(String[] args) throws Exception { + SunToolkit tk = (SunToolkit)Toolkit.getDefaultToolkit(); + Robot r = new Robot(); + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + createAndShowGUI(); + } + }); + tk.realSync(); + + r.delay(600); + + Point p = Util.getCenterPoint(frame); + Color color = r.getPixelColor((int) p.getX(), (int) p.getY()); + if (!color.equals(Color.RED)) { + throw new Exception("Test failed: JDesktopPane isn't transparent. Expected color is (red color): " + Color.RED + ", actual color is: " + color); + } + } + + private static void createAndShowGUI() { + frame = new JFrame(); + + frame.setLayout(new BorderLayout()); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + JPanel panel = new JPanel(); + panel.setLayout(new BorderLayout()); + panel.setBackground(Color.RED); + frame.add(panel, BorderLayout.CENTER); + + JDesktopPane dp = new JDesktopPane(); + dp.setOpaque(false); + panel.add(dp, BorderLayout.CENTER); + + frame.setBounds(200, 200, 300, 200); + frame.setVisible(true); + } +} diff --git a/jdk/test/javax/swing/JTree/8003830/bug8003830.java b/jdk/test/javax/swing/JTree/8003830/bug8003830.java new file mode 100644 index 00000000000..78515462496 --- /dev/null +++ b/jdk/test/javax/swing/JTree/8003830/bug8003830.java @@ -0,0 +1,66 @@ +/* + * 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. + */ + +import java.awt.EventQueue; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import javax.swing.JTree; +import javax.swing.plaf.basic.BasicTreeUI; +import javax.swing.tree.TreePath; + + +/* Originally reported as NetBeans bug 222081. + * + * @test + * @bug 8003830 + * @summary NullPointerException in BasicTreeUI.Actions when getPathBounds returns null + * @author Jaroslav Tulach + * @run main bug8003830 + */ + +public class bug8003830 implements Runnable { + public static void main(String[] args) throws Exception { + EventQueue.invokeAndWait(new bug8003830()); + } + @Override + public void run() { + testNPEAtActionsPage(); + } + + public void testNPEAtActionsPage() { + JTree tree = new JTree(); + BasicTreeUI ui = new NullReturningTreeUI(); + tree.setUI(ui); + BasicTreeUI.TreePageAction tpa = ui.new TreePageAction(0, "down"); + tpa.actionPerformed(new ActionEvent(tree, 0, "")); + } + + private static final class NullReturningTreeUI extends BasicTreeUI { + @Override + public Rectangle getPathBounds(JTree tree, TreePath path) { + // the method can return null and callers have to be ready for + // that. Simulate the case by returning null for unknown reason. + return null; + } + } +} diff --git a/jdk/test/javax/swing/RepaintManager/IconifyTest/IconifyTest.java b/jdk/test/javax/swing/RepaintManager/IconifyTest/IconifyTest.java new file mode 100644 index 00000000000..cbe6d2230de --- /dev/null +++ b/jdk/test/javax/swing/RepaintManager/IconifyTest/IconifyTest.java @@ -0,0 +1,80 @@ +/* + * 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. + */ +/* + * @test + * @bug 4665214 + * @summary Makes sure that RepaintManager doesn't attempt to repaint + * a frame when it is iconified. + * @author Scott Violet + * @run main IconifyTest + */ +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import sun.awt.*; + +public class IconifyTest { + private static volatile boolean windowIconifiedIsCalled = false; + private static volatile boolean frameIsRepainted = false; + static JFrame frame; + static JButton button; + + public static void main(String[] args) throws Throwable { + SunToolkit toolkit = (SunToolkit) SunToolkit.getDefaultToolkit(); + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame = new JFrame(); + button = new JButton("HI"); + frame.getContentPane().add(button); + frame.addWindowListener(new WindowAdapter() { + public void windowIconified(WindowEvent e) { + windowIconifiedIsCalled = true; + RepaintManager rm = RepaintManager.currentManager(null); + rm.paintDirtyRegions(); + button.repaint(); + if (!rm.getDirtyRegion(button).isEmpty()) { + frameIsRepainted = true; + } + } + }); + frame.pack(); + frame.setVisible(true); + } + }); + toolkit.realSync(); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setExtendedState(Frame.ICONIFIED); + } + }); + toolkit.realSync(); + + if (!windowIconifiedIsCalled) { + throw new Exception("Test failed: window was not iconified."); + } + if (frameIsRepainted) { + throw new Exception("Test failed: frame was repainted when window was iconified."); + } + } +} diff --git a/jdk/test/javax/swing/dnd/7171812/JListWithScroll.java b/jdk/test/javax/swing/dnd/7171812/JListWithScroll.java new file mode 100644 index 00000000000..4e11ce841b4 --- /dev/null +++ b/jdk/test/javax/swing/dnd/7171812/JListWithScroll.java @@ -0,0 +1,81 @@ +/* + * 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. + */ + +import javax.swing.*; +import java.awt.*; +import java.awt.dnd.Autoscroll; + +public class JListWithScroll extends JList implements Autoscroll { + private Insets scrollInsets; + + public JListWithScroll(E[] listData) { + super(listData); + scrollInsets = new Insets(50, 50, 50, 50); + } + + @Override + public Insets getAutoscrollInsets() { + return scrollInsets; + } + + @Override + public void autoscroll(Point cursorLoc) { + JViewport viewport = getViewport(); + + if (viewport == null) { + return; + } + + Point viewPos = viewport.getViewPosition(); + int viewHeight = viewport.getExtentSize().height; + int viewWidth = viewport.getExtentSize().width; + + if ((cursorLoc.y - viewPos.y) < scrollInsets.top) { + viewport.setViewPosition(new Point(viewPos.x, Math.max(viewPos.y - scrollInsets.top, 0))); + } else if (((viewPos.y + viewHeight) - cursorLoc.y) < scrollInsets.bottom) { + viewport.setViewPosition( + new Point(viewPos.x, Math.min(viewPos.y + scrollInsets.bottom, this.getHeight() - viewHeight)) + ); + } else if ((cursorLoc.x - viewPos.x) < scrollInsets.left) { + viewport.setViewPosition(new Point(Math.max(viewPos.x - scrollInsets.left, 0), viewPos.y)); + } else if (((viewPos.x + viewWidth) - cursorLoc.x) < scrollInsets.right) { + viewport.setViewPosition( + new Point(Math.min(viewPos.x + scrollInsets.right, this.getWidth() - viewWidth), viewPos.y) + ); + } + + } + + public JViewport getViewport() { + Component curComp = this; + + while (!(curComp instanceof JViewport) && (curComp != null)) { + curComp = curComp.getParent(); + } + if(curComp instanceof JViewport) { + return (JViewport) curComp; + } else { + return null; + } + } +} diff --git a/jdk/test/javax/swing/dnd/7171812/bug7171812.java b/jdk/test/javax/swing/dnd/7171812/bug7171812.java new file mode 100644 index 00000000000..a550d5e3cf9 --- /dev/null +++ b/jdk/test/javax/swing/dnd/7171812/bug7171812.java @@ -0,0 +1,123 @@ +/* + * 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. + */ + +/* @test + @bug 7171812 + @summary [macosx] Views keep scrolling back to the drag position after DnD + @author Alexander Zuev + @run main bug7171812 + */ + +import sun.awt.SunToolkit; + +import java.awt.*; +import java.awt.dnd.*; +import java.awt.event.InputEvent; +import javax.swing.*; + +public class bug7171812 { + static JFrame mainFrame; + static String listData[]; + static JListWithScroll list; + static JScrollPane scrollPane; + + /** + * @param args the command line arguments + */ + public static void main(String[] args) throws Exception{ + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + setupGUI(); + } + }); + toolkit.realSync(); + + Robot robot = new Robot(); + robot.setAutoDelay(10); + robot.mouseMove(scrollPane.getLocationOnScreen().x + 5, scrollPane.getLocationOnScreen().y + 5); + robot.mousePress(InputEvent.BUTTON1_MASK); + for(int offset = 5; offset < scrollPane.getHeight()-20; offset++) { + robot.mouseMove(scrollPane.getLocationOnScreen().x+5, scrollPane.getLocationOnScreen().y+offset); + } + for(int offset = 5; offset < 195; offset++) { + robot.mouseMove(scrollPane.getLocationOnScreen().x+offset, scrollPane.getLocationOnScreen().y+scrollPane.getHeight()-20); + } + robot.mouseRelease(InputEvent.BUTTON1_MASK); + try { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + if(scrollPane.getViewport().getViewPosition().getY() < 30) { + throw new RuntimeException("Incorrect view position."); + }; + } + }); + } catch (java.lang.reflect.InvocationTargetException ite) { + throw new RuntimeException("Test failed, scroll on drag doesn't work!"); + } + } + + public static void setupGUI() { + listData = new String[100]; + for (int i=0; i<100; i++) { + listData[i] = "Long Line With Item "+i; + } + mainFrame = new JFrame("Rest frame"); + mainFrame.setSize(300, 500); + mainFrame.setLayout(new BorderLayout()); + list = new JListWithScroll(listData); + list.setDragEnabled(true); + list.setAutoscrolls(true); + final DropTarget dropTarget = new DropTarget(list, DnDConstants.ACTION_MOVE, new DropTargetListener() { + @Override + public void dragEnter(DropTargetDragEvent dtde) { + dragOver(dtde); + } + + @Override + public void dragOver(DropTargetDragEvent dtde) { + dtde.acceptDrag(DnDConstants.ACTION_MOVE); + } + + @Override + public void dropActionChanged(DropTargetDragEvent dtde) { + } + + @Override + public void dragExit(DropTargetEvent dte) { + } + + @Override + public void drop(DropTargetDropEvent dtde) { + } + }, true); + scrollPane = new JScrollPane(list); + mainFrame.add(scrollPane, BorderLayout.CENTER); + mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + mainFrame.setLocation(100, 100); + mainFrame.setVisible(true); + } +} diff --git a/jdk/test/javax/swing/text/CSSBorder/6796710/bug6796710.java b/jdk/test/javax/swing/text/CSSBorder/6796710/bug6796710.java index b59ba9fd9bb..dd8508b3997 100644 --- a/jdk/test/javax/swing/text/CSSBorder/6796710/bug6796710.java +++ b/jdk/test/javax/swing/text/CSSBorder/6796710/bug6796710.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 6796710 + * @bug 6796710 7124242 * @summary Html content in JEditorPane is overlapping on swing components while resizing the application. * @library ../../../regtesthelpers * @build Util @@ -31,11 +31,10 @@ @run main bug6796710 */ -import sun.awt.SunToolkit; - -import javax.swing.*; import java.awt.*; import java.awt.image.BufferedImage; +import javax.swing.*; +import sun.awt.SunToolkit; public class bug6796710 { // The page is inlined because we want to be sure that the JEditorPane filled synchronously @@ -68,9 +67,12 @@ public class bug6796710 { robot = new Robot(); SwingUtilities.invokeAndWait(new Runnable() { + @Override public void run() { frame = new JFrame(); + frame.setUndecorated(true); + pnBottom = new JPanel(); pnBottom.add(new JLabel("Some label")); pnBottom.add(new JButton("A button")); @@ -95,9 +97,13 @@ public class bug6796710 { ((SunToolkit) SunToolkit.getDefaultToolkit()).realSync(); + // This delay should be added for MacOSX, realSync is not enough + Thread.sleep(1000); + BufferedImage bufferedImage = getPnBottomImage(); SwingUtilities.invokeAndWait(new Runnable() { + @Override public void run() { frame.setSize(400, 150); } diff --git a/jdk/test/lib/security/java.policy/Ext_AllPolicy.sh b/jdk/test/lib/security/java.policy/Ext_AllPolicy.sh index e4184062a5f..3efcce9b4e0 100644 --- a/jdk/test/lib/security/java.policy/Ext_AllPolicy.sh +++ b/jdk/test/lib/security/java.policy/Ext_AllPolicy.sh @@ -77,7 +77,7 @@ cd ${TESTCLASSES} ${TESTJAVA}${FS}bin${FS}jar -cvf Ext_AllPolicy.jar Ext_AllPolicy.class rm Ext_AllPolicy.class -${TESTJAVA}${FS}bin${FS}java \ +${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} \ -Djava.security.manager -Djava.ext.dirs="${TESTCLASSES}" Ext_AllPolicy exit $? diff --git a/jdk/test/sun/java2d/OpenGL/CustomCompositeTest.java b/jdk/test/sun/java2d/OpenGL/CustomCompositeTest.java new file mode 100644 index 00000000000..3977270d457 --- /dev/null +++ b/jdk/test/sun/java2d/OpenGL/CustomCompositeTest.java @@ -0,0 +1,266 @@ +/* + * 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. + */ + +/* + * @test + * @bug 7124347 + * @summary Verifies that rendering with XOR composite, and arbitraty + * custom composite doesn not cause internal errors. + * + * @run main/othervm -Dsun.java2d.opengl=True CustomCompositeTest + */ + +import java.awt.AWTException; +import java.awt.Color; +import java.awt.Composite; +import java.awt.CompositeContext; +import java.awt.Dimension; +import java.awt.GradientPaint; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsEnvironment; +import java.awt.ImageCapabilities; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.DataBufferInt; +import java.awt.image.Raster; +import java.awt.image.SinglePixelPackedSampleModel; +import java.awt.image.VolatileImage; +import java.awt.image.WritableRaster; +import java.util.concurrent.CountDownLatch; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; + +public class CustomCompositeTest { + + private static JFrame frame; + private static CountDownLatch paintLatch; + private static Throwable paintError; + + public static void main(String[] args) { + + paintLatch = new CountDownLatch(1); + paintError = null; + + SwingUtilities.invokeLater(new Runnable() { + public void run() { + initGUI(); + } + }); + + try { + paintLatch.await(); + } catch (InterruptedException e) { + }; + System.out.println("Paint is done!"); + if (paintError != null) { + frame.dispose(); + throw new RuntimeException("Test FAILED.", paintError); + } + + System.out.println("Phase 1: PASSED."); + + // now resise the frame in order to cause re-paint with accelerated + // source images. + paintError = null; + paintLatch = new CountDownLatch(1); + + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + Dimension size = frame.getSize(); + size.width += 50; + size.height += 50; + + frame.setSize(size); + } + }); + + try { + paintLatch.await(); + } catch (InterruptedException e) { + }; + if (paintError != null) { + frame.dispose(); + throw new RuntimeException("Resize test FAILED.", paintError); + } + frame.dispose(); + System.out.println("Phase 2: PASSED."); + + GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment(); + GraphicsConfiguration cfg = env.getDefaultScreenDevice().getDefaultConfiguration(); + // test rendering to accelerated volatile image + testVolatileImage(cfg, true); + System.out.println("Phase 3: PASSED."); + + // test rendering to unaccelerated volatile image + testVolatileImage(cfg, false); + System.out.println("Phase 4: PASSED."); + } + + private static void testVolatileImage(GraphicsConfiguration cfg, + boolean accelerated) + { + VolatileImage dst = null; + try { + dst = cfg.createCompatibleVolatileImage(640, 480, + new ImageCapabilities(accelerated)); + } catch (AWTException e) { + System.out.println("Unable to create volatile image, skip the test."); + return; + } + renderToVolatileImage(dst); + } + + private static void renderToVolatileImage(VolatileImage dst) { + Graphics2D g = dst.createGraphics(); + do { + System.out.println("Render to volatile image.."); + try { + MyComp.renderTest(g, dst.getHeight(), dst.getHeight()); + } catch (Throwable e) { + throw new RuntimeException("Test FAILED.", e); + } + } while (dst.contentsLost()); + System.out.println("Done."); + } + + private static void initGUI() { + frame = new JFrame("Silly composite"); + frame.getContentPane().add(new MyComp()); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.pack(); + frame.setVisible(true); + } + + private static class MyComp extends JComponent { + + private static BufferedImage theImage; + + public MyComp() { + } + + private static BufferedImage getTestImage() { + if (theImage == null) { + theImage = new BufferedImage(256, 256, BufferedImage.TYPE_INT_ARGB); + Graphics2D g2d = theImage.createGraphics(); + g2d.setColor(Color.red); + g2d.fillRect(0, 0, 256, 256); + + g2d.setPaint(new GradientPaint(0, 0, Color.red, 256, 256, Color.blue)); + g2d.fillRect(0, 100, 256, 256); + g2d.dispose(); + } + return theImage; + } + + public Dimension getPreferredSize() { + return new Dimension(640, 375); + } + + public void paintComponent(Graphics g) { + + + Graphics2D g2d = (Graphics2D) g; + try { + renderTest(g2d, getWidth(), getHeight()); + } catch (Throwable e) { + paintError = e; + } + if (paintLatch != null) { + paintLatch.countDown(); + } + } + + public static void renderTest(Graphics2D g2d, int w, int h) { + g2d.setColor(Color.yellow); + g2d.fillRect(0, 0, w, h); + + BufferedImage image = getTestImage(); + // draw original image + g2d.drawRenderedImage(image, null); + + // draw image with custom composite + g2d.translate(175, 25); + Composite currentComposite = g2d.getComposite(); + g2d.setComposite(new TestComposite()); + g2d.drawRenderedImage(image, null); + g2d.setComposite(currentComposite); + + // draw image with XOR + g2d.translate(175, 25); + g2d.setXORMode(Color.red); + g2d.drawRenderedImage(image, null); + + + System.out.println("Painting is done..."); + } + } + + // A silly custom Composite to demonstrate the problem - just inverts the RGB + private static class TestComposite implements Composite { + + public CompositeContext createContext(ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints) { + return new TestCompositeContext(); + } + } + + private static class TestCompositeContext implements CompositeContext { + + public void dispose() { + } + + public void compose(Raster src, Raster dstIn, WritableRaster dstOut) { + int w = src.getWidth(); + int h = src.getHeight(); + + DataBufferInt srcDB = (DataBufferInt) src.getDataBuffer(); + DataBufferInt dstOutDB = (DataBufferInt) dstOut.getDataBuffer(); + int srcRGB[] = srcDB.getBankData()[0]; + int dstOutRGB[] = dstOutDB.getBankData()[0]; + int srcOffset = srcDB.getOffset(); + int dstOutOffset = dstOutDB.getOffset(); + int srcScanStride = ((SinglePixelPackedSampleModel) src.getSampleModel()).getScanlineStride(); + int dstOutScanStride = ((SinglePixelPackedSampleModel) dstOut.getSampleModel()).getScanlineStride(); + int srcAdjust = srcScanStride - w; + int dstOutAdjust = dstOutScanStride - w; + + int si = srcOffset; + int doi = dstOutOffset; + + for (int i = 0; i < h; i++) { + for (int j = 0; j < w; j++) { + dstOutRGB[doi] = srcRGB[si] ^ 0x00ffffff; + si++; + doi++; + } + + si += srcAdjust; + doi += dstOutAdjust; + } + } + } +} diff --git a/jdk/test/sun/java2d/cmm/ColorConvertOp/InvalidRenderIntentTest.java b/jdk/test/sun/java2d/cmm/ColorConvertOp/InvalidRenderIntentTest.java new file mode 100644 index 00000000000..9140e3c4c1b --- /dev/null +++ b/jdk/test/sun/java2d/cmm/ColorConvertOp/InvalidRenderIntentTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * 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 7064516 + * @summary Test verifies that incorrect profile rendering intent + * does not cause an failure of color conversion op. + * @run main InvalidRenderIntentTest + */ + +import java.awt.color.CMMException; +import java.awt.color.ColorSpace; +import java.awt.color.ICC_ColorSpace; +import java.awt.color.ICC_Profile; +import java.awt.image.ColorConvertOp; +import java.awt.image.BufferedImage; + +import static java.awt.color.ColorSpace.CS_sRGB; +import static java.awt.image.BufferedImage.TYPE_3BYTE_BGR; + +public class InvalidRenderIntentTest { + + public static void main(String[] args) { + ICC_Profile pSRGB = ICC_Profile.getInstance(CS_sRGB); + + byte[] raw_data = pSRGB.getData(); + + setRenderingIntent(0x1000000, raw_data); + + ICC_Profile p = ICC_Profile.getInstance(raw_data); + + ICC_ColorSpace cs = new ICC_ColorSpace(p); + + // perfrom test color conversion + ColorConvertOp op = new ColorConvertOp(cs, + ColorSpace.getInstance(CS_sRGB), null); + BufferedImage src = new BufferedImage(1, 1, TYPE_3BYTE_BGR); + BufferedImage dst = new BufferedImage(1, 1, TYPE_3BYTE_BGR); + + try { + op.filter(src.getRaster(), dst.getRaster()); + } catch (CMMException e) { + throw new RuntimeException("Test failed.", e); + } + System.out.println("Test passed."); + } + + private static void setRenderingIntent(int intent, byte[] data) { + final int pos = ICC_Profile.icHdrRenderingIntent; + + data[pos + 0] = (byte) (0xff & (intent >> 24)); + data[pos + 1] = (byte) (0xff & (intent >> 16)); + data[pos + 2] = (byte) (0xff & (intent >> 8)); + data[pos + 3] = (byte) (0xff & (intent)); + } +} diff --git a/jdk/test/sun/jvmstat/monitor/MonitoredVm/MonitorVmStartTerminate.sh b/jdk/test/sun/jvmstat/monitor/MonitoredVm/MonitorVmStartTerminate.sh index c4b4756e4b3..558ac9cf109 100644 --- a/jdk/test/sun/jvmstat/monitor/MonitoredVm/MonitorVmStartTerminate.sh +++ b/jdk/test/sun/jvmstat/monitor/MonitoredVm/MonitorVmStartTerminate.sh @@ -41,4 +41,4 @@ verify_os JAVA="${TESTJAVA}/bin/java" CP=${TESTJAVA}${FS}lib${FS}tools.jar${PS}${TESTCLASSES} -${JAVA} -classpath ${CP} MonitorVmStartTerminate +${JAVA} ${TESTVMOPTS} -classpath ${CP} MonitorVmStartTerminate diff --git a/jdk/test/sun/management/jmxremote/bootstrap/CustomLauncherTest.sh b/jdk/test/sun/management/jmxremote/bootstrap/CustomLauncherTest.sh index 0cc4afade61..8622fba94a0 100644 --- a/jdk/test/sun/management/jmxremote/bootstrap/CustomLauncherTest.sh +++ b/jdk/test/sun/management/jmxremote/bootstrap/CustomLauncherTest.sh @@ -150,7 +150,7 @@ while true; do done # Start the manager - this should connect to VM -${TESTJAVA}/bin/java -classpath ${TESTCLASSES}:${TESTJAVA}/lib/tools.jar \ +${TESTJAVA}/bin/java ${TESTVMOPTS} -classpath ${TESTCLASSES}:${TESTJAVA}/lib/tools.jar \ TestManager $pid $port true if [ $? != 0 ]; then echo "Test failed" diff --git a/jdk/test/sun/management/jmxremote/bootstrap/LocalManagementTest.sh b/jdk/test/sun/management/jmxremote/bootstrap/LocalManagementTest.sh index 426e5d4ba76..7338cbe8600 100644 --- a/jdk/test/sun/management/jmxremote/bootstrap/LocalManagementTest.sh +++ b/jdk/test/sun/management/jmxremote/bootstrap/LocalManagementTest.sh @@ -43,8 +43,8 @@ doTest() rm -f ${outputfile} # Start VM with given options - echo "+ $JAVA $1 Test" - $JAVA $1 TestApplication > ${outputfile}& + echo "+ $JAVA ${TESTVMOPTS} $1 Test" + $JAVA ${TESTVMOPTS} $1 TestApplication > ${outputfile}& pid=$! # Wait for managed VM to startup @@ -64,7 +64,7 @@ doTest() done # Start the manager - this should connect to VM - sh -xc "$JAVA -classpath ${TESTCLASSES}:${TESTJAVA}/lib/tools.jar \ + sh -xc "$JAVA ${TESTVMOPTS} -classpath ${TESTCLASSES}:${TESTJAVA}/lib/tools.jar \ TestManager $pid $port" 2>&1 if [ $? != 0 ]; then failures=`expr $failures + 1`; fi } @@ -112,7 +112,7 @@ doTest " " # Test 4 - sanity check arguments to management-agent.jar echo ' ' -sh -xc "${JAVA} -javaagent:${AGENT}=com.sun.management.jmxremote.port=7775,\ +sh -xc "${JAVA} ${TESTVMOPTS} -javaagent:${AGENT}=com.sun.management.jmxremote.port=7775,\ com.sun.management.jmxremote.authenticate=false,com.sun.management.jmxremote.ssl=false \ TestApplication -exit" 2>&1 if [ $? != 0 ]; then failures=`expr $failures + 1`; fi diff --git a/jdk/test/sun/management/jmxremote/bootstrap/PasswordFilePermissionTest.sh b/jdk/test/sun/management/jmxremote/bootstrap/PasswordFilePermissionTest.sh index 700a2b188ed..dfc4a85ad5c 100644 --- a/jdk/test/sun/management/jmxremote/bootstrap/PasswordFilePermissionTest.sh +++ b/jdk/test/sun/management/jmxremote/bootstrap/PasswordFilePermissionTest.sh @@ -104,18 +104,18 @@ pp=-Dcom.sun.management.jmxremote.port=4888 go() { echo '' - sh -xc "$JAVA $1 $2 $3 $4 $5 $6 $7 $8" 2>&1 + sh -xc "$JAVA ${TESTVMOPTS} $1 $2 $3 $4 $5 $6 $7 $8" 2>&1 if [ $? != 0 ]; then failures=`expr $failures + 1`; fi } # Test 1 - password file is secure - VM should start chmod 700 ${PASSWD} -sh -xc "$JAVA $mp $pp Null" 2>&1 +sh -xc "$JAVA ${TESTVMOPTS} $mp $pp Null" 2>&1 if [ $? != 0 ]; then failures=`expr $failures + 1`; fi # Test 2 - password file is not secure - VM should fail to start chmod o+rx ${PASSWD} -sh -xc "$JAVA $mp $pp Null" 2>&1 +sh -xc "$JAVA ${TESTVMOPTS} $mp $pp Null" 2>&1 if [ $? = 0 ]; then failures=`expr $failures + 1`; fi # Reset the file permissions on the generated password file diff --git a/jdk/test/sun/management/jmxremote/bootstrap/SSLConfigFilePermissionTest.sh b/jdk/test/sun/management/jmxremote/bootstrap/SSLConfigFilePermissionTest.sh index 46927ec8335..0fa765409b6 100644 --- a/jdk/test/sun/management/jmxremote/bootstrap/SSLConfigFilePermissionTest.sh +++ b/jdk/test/sun/management/jmxremote/bootstrap/SSLConfigFilePermissionTest.sh @@ -101,18 +101,18 @@ pp=-Dcom.sun.management.jmxremote.port=4999 go() { echo '' - sh -xc "$JAVA $1 $2 $3 $4 $5 $6 $7 $8" 2>&1 + sh -xc "$JAVA ${TESTVMOPTS} $1 $2 $3 $4 $5 $6 $7 $8" 2>&1 if [ $? != 0 ]; then failures=`expr $failures + 1`; fi } # Test 1 - SSL config file is secure - VM should start chmod 700 ${SSL} -sh -xc "$JAVA $mp $pp Dummy" 2>&1 +sh -xc "$JAVA ${TESTVMOPTS} $mp $pp Dummy" 2>&1 if [ $? != 0 ]; then failures=`expr $failures + 1`; fi # Test 2 - SSL config file is not secure - VM should fail to start chmod o+rx ${SSL} -sh -xc "$JAVA $mp $pp Dummy" 2>&1 +sh -xc "$JAVA ${TESTVMOPTS} $mp $pp Dummy" 2>&1 if [ $? = 0 ]; then failures=`expr $failures + 1`; fi # Reset the file permissions on the generated SSL config file diff --git a/jdk/test/sun/management/jmxremote/startstop/JMXStartStopTest.sh b/jdk/test/sun/management/jmxremote/startstop/JMXStartStopTest.sh index f52146b3bed..6d48e17202a 100644 --- a/jdk/test/sun/management/jmxremote/startstop/JMXStartStopTest.sh +++ b/jdk/test/sun/management/jmxremote/startstop/JMXStartStopTest.sh @@ -61,7 +61,7 @@ _compile(){ } _app_start(){ - ${TESTJAVA}/bin/java -server $* -cp ${_testclasses} JMXStartStopDoSomething >> ${_logname} 2>&1 & + ${TESTJAVA}/bin/java ${TESTVMOPTS} $* -cp ${_testclasses} JMXStartStopDoSomething >> ${_logname} 2>&1 & npid=`_get_pid` if [ "${npid}" = "" ] @@ -103,7 +103,7 @@ _exit_on_jtreg(){ } _testme(){ - ${TESTJAVA}/bin/java -cp ${_testclasses} JMXStartStopTest $* + ${TESTJAVA}/bin/java ${TESTVMOPTS} -cp ${_testclasses} JMXStartStopTest $* } diff --git a/jdk/test/sun/misc/Cleaner/exitOnThrow.sh b/jdk/test/sun/misc/Cleaner/exitOnThrow.sh index f6090cd42ec..7506ce4403f 100644 --- a/jdk/test/sun/misc/Cleaner/exitOnThrow.sh +++ b/jdk/test/sun/misc/Cleaner/exitOnThrow.sh @@ -39,7 +39,7 @@ if [ -z "$TESTJAVA" ]; then TESTCLASSES=`pwd` fi -if $TESTJAVA/bin/java -cp $TESTCLASSES ExitOnThrow; then +if $TESTJAVA/bin/java ${TESTVMOPTS} -cp $TESTCLASSES ExitOnThrow; then echo Failed: VM exited normally exit 1 else diff --git a/jdk/test/sun/net/InetAddress/nameservice/dns/cname.sh b/jdk/test/sun/net/InetAddress/nameservice/dns/cname.sh index 9587d6af504..13c922aed4d 100644 --- a/jdk/test/sun/net/InetAddress/nameservice/dns/cname.sh +++ b/jdk/test/sun/net/InetAddress/nameservice/dns/cname.sh @@ -42,7 +42,7 @@ CLASSPATH=${TESTCLASSES} export CLASSPATH JAVA="${TESTJAVA}/bin/java" -sh -xc "$JAVA CanonicalName $HOST" 2>&1 +sh -xc "$JAVA ${TESTVMOPTS} CanonicalName $HOST" 2>&1 if [ $? != 0 ]; then echo "DNS not configured or host doesn't resolve to CNAME record" exit 0 @@ -52,7 +52,7 @@ failures=0 go() { echo '' - sh -xc "$JAVA $1 Lookup $2" 2>&1 + sh -xc "$JAVA ${TESTVMOPTS} $1 Lookup $2" 2>&1 if [ $? != 0 ]; then failures=`expr $failures + 1`; fi } diff --git a/jdk/test/sun/net/sdp/sanity.sh b/jdk/test/sun/net/sdp/sanity.sh index 0de27095d1c..88d80e0163e 100644 --- a/jdk/test/sun/net/sdp/sanity.sh +++ b/jdk/test/sun/net/sdp/sanity.sh @@ -57,7 +57,7 @@ CLASSPATH=${TESTCLASSES}:${TESTSRC} export CLASSPATH # Probe for IP addresses plumbed to IB interfaces -$JAVA -Djava.net.preferIPv4Stack=true ProbeIB ${IB_LINKS} > ${IB_ADDRS} +$JAVA ${TESTVMOPTS} -Djava.net.preferIPv4Stack=true ProbeIB ${IB_LINKS} > ${IB_ADDRS} # Create sdp.conf SDPCONF=sdp.conf @@ -70,4 +70,4 @@ do done # Sanity check -$JAVA -Djava.net.preferIPv4Stack=true -Dcom.sun.sdp.conf=${SDPCONF} -Dcom.sun.sdp.debug Sanity +$JAVA ${TESTVMOPTS} -Djava.net.preferIPv4Stack=true -Dcom.sun.sdp.conf=${SDPCONF} -Dcom.sun.sdp.debug Sanity diff --git a/jdk/test/sun/net/www/MarkResetTest.sh b/jdk/test/sun/net/www/MarkResetTest.sh index c3eb53a56d5..542bfe4b179 100644 --- a/jdk/test/sun/net/www/MarkResetTest.sh +++ b/jdk/test/sun/net/www/MarkResetTest.sh @@ -52,4 +52,4 @@ ${TESTJAVA}${FS}bin${FS}javac -d . ${TESTSRC}${FS}MarkResetTest.java # in this directory cp ${TESTSRC}${FS}EncDec.doc . -${TESTJAVA}${FS}bin${FS}java MarkResetTest +${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} MarkResetTest diff --git a/jdk/test/sun/net/www/MessageHeaderTest.java b/jdk/test/sun/net/www/MessageHeaderTest.java new file mode 100644 index 00000000000..aceb635cfae --- /dev/null +++ b/jdk/test/sun/net/www/MessageHeaderTest.java @@ -0,0 +1,74 @@ +/* + * 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. + */ + +/** + * @test + * @bug 8003948 + * @run main MessageHeaderTest + */ +import java.io.*; +import sun.net.www.MessageHeader; + +public class MessageHeaderTest { + public static void main (String[] args) throws Exception { + for (int i=0; i<7; i++) { + ByteArrayInputStream bis = new ByteArrayInputStream(headers[i].getBytes()); + MessageHeader h = new MessageHeader(bis); + String before = h.toString(); + before = before.substring(before.indexOf('{')); + boolean result = h.filterNTLMResponses("WWW-Authenticate"); + String after = h.toString(); + after = after.substring(after.indexOf('{')); + if (!expected[i].equals(after)) { + throw new RuntimeException(Integer.toString(i) + " expected != after"); + } + if (result != expectedResult[i]) { + throw new RuntimeException(Integer.toString(i) + " result != expectedResult"); + } + } + } + + static String expected[] = { + "{null: HTTP/1.1 200 Ok}{Foo: bar}{Bar: foo}{WWW-Authenticate: NTLM sdsds}", + "{null: HTTP/1.1 200 Ok}{Foo: bar}{Bar: foo}{WWW-Authenticate: }", + "{null: HTTP/1.1 200 Ok}{Foo: bar}{Bar: foo}{WWW-Authenticate: NTLM sdsds}", + "{null: HTTP/1.1 200 Ok}{Foo: bar}{Bar: foo}{WWW-Authenticate: NTLM sdsds}", + "{null: HTTP/1.1 200 Ok}{Foo: bar}{Bar: foo}{WWW-Authenticate: NTLM sdsds}{Bar: foo}", + "{null: HTTP/1.1 200 Ok}{WWW-Authenticate: Negotiate}{Foo: bar}{Bar: foo}{WWW-Authenticate: NTLM}{Bar: foo}{WWW-Authenticate: Kerberos}", + "{null: HTTP/1.1 200 Ok}{Foo: foo}{Bar: }{WWW-Authenticate: NTLM blob}{Bar: foo blob}" + }; + + static boolean[] expectedResult = { + false, false, true, true, true, false, false + }; + + static String[] headers = { + "HTTP/1.1 200 Ok\r\nFoo: bar\r\nBar: foo\r\nWWW-Authenticate: NTLM sdsds", + "HTTP/1.1 200 Ok\r\nFoo: bar\r\nBar: foo\r\nWWW-Authenticate:", + "HTTP/1.1 200 Ok\r\nFoo: bar\r\nBar: foo\r\nWWW-Authenticate: NTLM sdsds\r\nWWW-Authenticate: Negotiate", + "HTTP/1.1 200 Ok\r\nFoo: bar\r\nBar: foo\r\nWWW-Authenticate: NTLM sdsds\r\nWWW-Authenticate: Negotiate\r\nWWW-Authenticate: Kerberos", + "HTTP/1.1 200 Ok\r\nWWW-Authenticate: Negotiate\r\nFoo: bar\r\nBar: foo\r\nWWW-Authenticate: NTLM sdsds\r\nBar: foo\r\nWWW-Authenticate: Kerberos", + "HTTP/1.1 200 Ok\r\nWWW-Authenticate: Negotiate\r\nFoo: bar\r\nBar: foo\r\nWWW-Authenticate: NTLM\r\nBar: foo\r\nWWW-Authenticate: Kerberos", + "HTTP/1.1 200 Ok\r\nFoo: foo\r\nBar:\r\nWWW-Authenticate: NTLM blob\r\nBar: foo blob" + }; +} diff --git a/jdk/test/sun/net/www/http/HttpClient/RetryPost.sh b/jdk/test/sun/net/www/http/HttpClient/RetryPost.sh index 314a007c64f..fc563c83b16 100644 --- a/jdk/test/sun/net/www/http/HttpClient/RetryPost.sh +++ b/jdk/test/sun/net/www/http/HttpClient/RetryPost.sh @@ -50,14 +50,14 @@ esac ${TESTJAVA}${FS}bin${FS}javac -d . ${TESTSRC}${FS}RetryPost.java # run with no option specified. Should retry POST request. -${TESTJAVA}${FS}bin${FS}java RetryPost +${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} RetryPost result=$? if [ "$result" -ne "0" ]; then exit 1 fi # run with option specified. Should not retry POST request. -${TESTJAVA}${FS}bin${FS}java -Dsun.net.http.retryPost=false RetryPost noRetry +${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -Dsun.net.http.retryPost=false RetryPost noRetry result=$? if [ "$result" -ne "0" ]; then exit 1 diff --git a/jdk/test/sun/net/www/protocol/file/DirPermissionDenied.sh b/jdk/test/sun/net/www/protocol/file/DirPermissionDenied.sh index a85f4d53a99..7606b3dd9ac 100644 --- a/jdk/test/sun/net/www/protocol/file/DirPermissionDenied.sh +++ b/jdk/test/sun/net/www/protocol/file/DirPermissionDenied.sh @@ -35,7 +35,7 @@ rm -rf ${TESTDIR} mkdir -p ${TESTDIR} chmod 333 ${TESTDIR} -$TESTJAVA/bin/java -classpath $TESTCLASSES DirPermissionDenied ${TESTDIR} +$TESTJAVA/bin/java ${TESTVMOPTS} -classpath $TESTCLASSES DirPermissionDenied ${TESTDIR} result=$? # Add back read access for user, otherwise not removable on some systems diff --git a/jdk/test/sun/net/www/protocol/jar/B5105410.sh b/jdk/test/sun/net/www/protocol/jar/B5105410.sh index 3dbce7f3f77..1fdbdd58ff8 100644 --- a/jdk/test/sun/net/www/protocol/jar/B5105410.sh +++ b/jdk/test/sun/net/www/protocol/jar/B5105410.sh @@ -51,5 +51,5 @@ esac cp ${TESTSRC}${FS}foo2.jar . ${TESTJAVA}${FS}bin${FS}javac -d . ${TESTSRC}${FS}B5105410.java -${TESTJAVA}${FS}bin${FS}java B5105410 +${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} B5105410 diff --git a/jdk/test/sun/net/www/protocol/jar/getcontenttype.sh b/jdk/test/sun/net/www/protocol/jar/getcontenttype.sh index da3563db5c6..a3a1a2a1310 100644 --- a/jdk/test/sun/net/www/protocol/jar/getcontenttype.sh +++ b/jdk/test/sun/net/www/protocol/jar/getcontenttype.sh @@ -33,5 +33,5 @@ if [ x"$TESTCLASSES" = x ]; then TESTCLASSES=.; fi if [ x"$TESTSRC" = x ]; then TESTSRC=.; fi # now start the test -${TESTJAVA}/bin/java -Djava.ext.dirs=$TESTSRC -cp $TESTCLASSES GetContentType +${TESTJAVA}/bin/java ${TESTVMOPTS} -Djava.ext.dirs=$TESTSRC -cp $TESTCLASSES GetContentType diff --git a/jdk/test/sun/net/www/protocol/jar/jarbug/run.sh b/jdk/test/sun/net/www/protocol/jar/jarbug/run.sh index 31cfbe86158..72a11681d1c 100644 --- a/jdk/test/sun/net/www/protocol/jar/jarbug/run.sh +++ b/jdk/test/sun/net/www/protocol/jar/jarbug/run.sh @@ -71,7 +71,7 @@ mv jar1.jar .. # ${TESTJAVA}${FS}bin${FS}javac -d ${DEST} ${TESTSRC}${FS}src${FS}test${FS}*.java cd ${DEST} -${TESTJAVA}${FS}bin${FS}java RunAllTests +${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} RunAllTests result=$? if [ "$result" -ne "0" ]; then exit 1 diff --git a/jdk/test/sun/rmi/log/ReliableLog/LogAlignmentTest.java b/jdk/test/sun/rmi/log/ReliableLog/LogAlignmentTest.java index 04d2fd9fe03..012c0b8cab9 100644 --- a/jdk/test/sun/rmi/log/ReliableLog/LogAlignmentTest.java +++ b/jdk/test/sun/rmi/log/ReliableLog/LogAlignmentTest.java @@ -22,8 +22,10 @@ */ /* @test - @bug 4094889 - @summary rmid can have a corrupted log + * @bug 4094889 + * @summary rmid can have a corrupted log + * + * @run main LogAlignmentTest */ /* Fault: ReliableLog used RandomAccessFile.skipBytes() to seek past the end diff --git a/jdk/test/sun/rmi/log/ReliableLog/SnapshotSize.java b/jdk/test/sun/rmi/log/ReliableLog/SnapshotSize.java index f1febfc1fc2..592ef5eaba9 100644 --- a/jdk/test/sun/rmi/log/ReliableLog/SnapshotSize.java +++ b/jdk/test/sun/rmi/log/ReliableLog/SnapshotSize.java @@ -25,6 +25,8 @@ * @bug 4319866 * @summary Verify that ReliableLog.snapshotSize() returns correct snapshot * file size even if LogHandler doesn't flush. + * + * @run main SnapshotSize */ import java.io.ByteArrayOutputStream; diff --git a/jdk/test/sun/rmi/rmic/RMIGenerator/RmicDefault.java b/jdk/test/sun/rmi/rmic/RMIGenerator/RmicDefault.java index ad2484168ea..5f4587ecdfb 100644 --- a/jdk/test/sun/rmi/rmic/RMIGenerator/RmicDefault.java +++ b/jdk/test/sun/rmi/rmic/RMIGenerator/RmicDefault.java @@ -28,7 +28,6 @@ * @library ../../../../java/rmi/testlibrary * * @build StreamPipe - * @build RmicDefault * @run main RmicDefault */ diff --git a/jdk/test/sun/rmi/rmic/manifestClassPath/run.sh b/jdk/test/sun/rmi/rmic/manifestClassPath/run.sh index 4faf141ff91..f20ab75527e 100644 --- a/jdk/test/sun/rmi/rmic/manifestClassPath/run.sh +++ b/jdk/test/sun/rmi/rmic/manifestClassPath/run.sh @@ -114,26 +114,26 @@ EOF Success "$javac" -classpath "jars/A.jar" Main.java MainI.java Success "$rmic" -classpath "jars/A.jar${PS}." Main -Success "$java" -classpath "jars/A.jar${PS}." Main +Success "$java" ${TESTVMOPTS} -classpath "jars/A.jar${PS}." Main Sys rm -f Main.class MainI.class Main_Stub.class Success "$javac" -classpath "jars/sub/B.zip" Main.java MainI.java Success "$rmic" -classpath "jars/sub/B.zip${PS}." Main -Success "$java" -classpath "jars/sub/B.zip${PS}." Main +Success "$java" ${TESTVMOPTS} -classpath "jars/sub/B.zip${PS}." Main #Sys rm -f Main.class MainI.class Main_Stub.class Sys rm -f Main_Stub.class # javac -extdirs workaround #Success "$javac" -extdirs "jars" -classpath None Main.java MainI.java Success "$rmic" -extdirs "jars" -classpath . Main -Success "$java" -Djava.ext.dirs="jars" -cp . Main +Success "$java" ${TESTVMOPTS} -Djava.ext.dirs="jars" -cp . Main Sys rm -f Main_Stub.class #Success "$javac" -extdirs "jars/sub" -classpath None Main.java MainI.java Success "$rmic" -extdirs "jars/sub" -classpath . Main -Success "$java" -Djava.ext.dirs="jars/sub" -cp . Main +Success "$java" ${TESTVMOPTS} -Djava.ext.dirs="jars/sub" -cp . Main Cleanup diff --git a/jdk/test/sun/rmi/rmic/minimizeWrapperInstances/run.sh b/jdk/test/sun/rmi/rmic/minimizeWrapperInstances/run.sh index 204947dcea6..3c8e831e311 100644 --- a/jdk/test/sun/rmi/rmic/minimizeWrapperInstances/run.sh +++ b/jdk/test/sun/rmi/rmic/minimizeWrapperInstances/run.sh @@ -41,13 +41,13 @@ fi set -ex ${TESTJAVA}/bin/rmic -classpath ${TESTCLASSES:-.} -d ${TESTCLASSES:-.} PImpl -${TESTJAVA}/bin/java -classpath ${TESTCLASSES:-.} Test +${TESTJAVA}/bin/java ${TESTVMOPTS} -classpath ${TESTCLASSES:-.} Test ${TESTJAVA}/bin/rmic -classpath ${TESTCLASSES:-.} -d ${TESTCLASSES:-.} -vcompat PImpl -${TESTJAVA}/bin/java -classpath ${TESTCLASSES:-.} Test +${TESTJAVA}/bin/java ${TESTVMOPTS} -classpath ${TESTCLASSES:-.} Test ${TESTJAVA}/bin/rmic -Xnew -classpath ${TESTCLASSES:-.} -d ${TESTCLASSES:-.} PImpl -${TESTJAVA}/bin/java -classpath ${TESTCLASSES:-.} Test +${TESTJAVA}/bin/java ${TESTVMOPTS} -classpath ${TESTCLASSES:-.} Test ${TESTJAVA}/bin/rmic -Xnew -classpath ${TESTCLASSES:-.} -d ${TESTCLASSES:-.} -vcompat PImpl -${TESTJAVA}/bin/java -classpath ${TESTCLASSES:-.} Test +${TESTJAVA}/bin/java ${TESTVMOPTS} -classpath ${TESTCLASSES:-.} Test diff --git a/jdk/test/sun/rmi/rmic/newrmic/equivalence/run.sh b/jdk/test/sun/rmi/rmic/newrmic/equivalence/run.sh index 8d4f419d346..27c86041414 100644 --- a/jdk/test/sun/rmi/rmic/newrmic/equivalence/run.sh +++ b/jdk/test/sun/rmi/rmic/newrmic/equivalence/run.sh @@ -26,22 +26,24 @@ # @summary This test verifies that the new implementation of rmic # generates equivalent classes as the old implementation, for a set # of sample input classes. -# @library ../../../../../java/rmi/testlibrary -# @build TestLibrary # @author Peter Jones # -# @build AgentServerImpl -# @build AppleImpl -# @build AppleUserImpl -# @build ComputeServerImpl -# @build CountServerImpl -# @build DayTimeServerImpl -# @build G1Impl -# @build MyObjectImpl -# @build NotActivatableServerImpl -# @build OrangeEchoImpl -# @build OrangeImpl -# @build ServerImpl +# @library ../../../../../java/rmi/testlibrary +# +# @build TestLibrary +# AgentServerImpl +# AppleImpl +# AppleUserImpl +# ComputeServerImpl +# CountServerImpl +# DayTimeServerImpl +# G1Impl +# MyObjectImpl +# NotActivatableServerImpl +# OrangeEchoImpl +# OrangeImpl +# ServerImpl +# # @run shell run.sh if [ "${TESTJAVA}" = "" ] diff --git a/jdk/test/sun/rmi/rmic/oldjavacRemoved/sunToolsJavacMain.sh b/jdk/test/sun/rmi/rmic/oldjavacRemoved/sunToolsJavacMain.sh index fbb55817582..11840fa5037 100644 --- a/jdk/test/sun/rmi/rmic/oldjavacRemoved/sunToolsJavacMain.sh +++ b/jdk/test/sun/rmi/rmic/oldjavacRemoved/sunToolsJavacMain.sh @@ -37,7 +37,7 @@ fi set -x -${TESTJAVA}/bin/java -classpath ${TESTJAVA}/lib/tools.jar sun.tools.javac.Main -d ${TESTCLASSES:-.} ${TESTSRC:-.}/Foo.java +${TESTJAVA}/bin/java ${TESTVMOPTS} -classpath ${TESTJAVA}/lib/tools.jar sun.tools.javac.Main -d ${TESTCLASSES:-.} ${TESTSRC:-.}/Foo.java result=$? if [ $result -eq 0 ] diff --git a/jdk/test/sun/rmi/runtime/Log/6409194/NoConsoleOutput.java b/jdk/test/sun/rmi/runtime/Log/6409194/NoConsoleOutput.java index e5e19fe12dd..afcc13571e5 100644 --- a/jdk/test/sun/rmi/runtime/Log/6409194/NoConsoleOutput.java +++ b/jdk/test/sun/rmi/runtime/Log/6409194/NoConsoleOutput.java @@ -31,8 +31,7 @@ * @author Peter Jones * * @library ../../../../../java/rmi/testlibrary - * @build JavaVM - * @build NoConsoleOutput + * @build TestLibrary JavaVM * @run main/othervm NoConsoleOutput */ diff --git a/jdk/test/sun/rmi/runtime/Log/checkLogging/CheckLogStreams.java b/jdk/test/sun/rmi/runtime/Log/checkLogging/CheckLogStreams.java index 34cfc485d1e..1e959536c22 100644 --- a/jdk/test/sun/rmi/runtime/Log/checkLogging/CheckLogStreams.java +++ b/jdk/test/sun/rmi/runtime/Log/checkLogging/CheckLogStreams.java @@ -28,11 +28,7 @@ * @author Laird Dornin * * @library ../../../../../java/rmi/testlibrary - * @build TestLibrary - * @build TestParams - * @build TestFailedException - * @build CheckLogging - * @build CheckLogStreams + * @build TestLibrary CheckLogging * @run main/othervm -Dsun.rmi.log.useOld=true CheckLogStreams */ diff --git a/jdk/test/sun/rmi/runtime/Log/checkLogging/CheckLogging.java b/jdk/test/sun/rmi/runtime/Log/checkLogging/CheckLogging.java index 77c236d4371..347725a3d6d 100644 --- a/jdk/test/sun/rmi/runtime/Log/checkLogging/CheckLogging.java +++ b/jdk/test/sun/rmi/runtime/Log/checkLogging/CheckLogging.java @@ -29,9 +29,6 @@ * * @library ../../../../../java/rmi/testlibrary * @build TestLibrary - * @build TestParams - * @build TestFailedException - * @build CheckLogging * @run main/othervm CheckLogging */ diff --git a/jdk/test/sun/rmi/server/MarshalOutputStream/marshalForeignStub/MarshalForeignStub.java b/jdk/test/sun/rmi/server/MarshalOutputStream/marshalForeignStub/MarshalForeignStub.java index 165dfbe1cf9..bf1eb11372f 100644 --- a/jdk/test/sun/rmi/server/MarshalOutputStream/marshalForeignStub/MarshalForeignStub.java +++ b/jdk/test/sun/rmi/server/MarshalOutputStream/marshalForeignStub/MarshalForeignStub.java @@ -31,11 +31,7 @@ * @author Ann Wollrath * * @library ../../../../../java/rmi/testlibrary - * @build TestLibrary - * @build TestFailedException - * @build MarshalForeignStub - * @build Receiver - * @build MarshalForeignStub_Stub + * @build TestLibrary Receiver MarshalForeignStub_Stub * @run main/othervm/policy=security.policy MarshalForeignStub */ diff --git a/jdk/test/sun/rmi/transport/proxy/EagerHttpFallback.java b/jdk/test/sun/rmi/transport/proxy/EagerHttpFallback.java index 1f54e2cb845..3879c665d14 100644 --- a/jdk/test/sun/rmi/transport/proxy/EagerHttpFallback.java +++ b/jdk/test/sun/rmi/transport/proxy/EagerHttpFallback.java @@ -25,6 +25,7 @@ * @bug 4290727 * @summary Verify that ConnectException will trigger HTTP fallback if * sun.rmi.transport.proxy.eagerHttpFallback system property is set. + * * @library ../../../../java/rmi/testlibrary * @build TestLibrary * @run main/othervm EagerHttpFallback diff --git a/jdk/test/sun/rmi/transport/tcp/DeadCachedConnection.java b/jdk/test/sun/rmi/transport/tcp/DeadCachedConnection.java index 1372b03feab..7bcd5a71024 100644 --- a/jdk/test/sun/rmi/transport/tcp/DeadCachedConnection.java +++ b/jdk/test/sun/rmi/transport/tcp/DeadCachedConnection.java @@ -25,9 +25,7 @@ * @bug 4094891 * @summary unable to retry call if cached connection to server is used * @library ../../../../java/rmi/testlibrary - * @build DeadCachedConnection - * @build JavaVM - * @build TestLibrary + * @build TestLibrary JavaVM * @run main/othervm DeadCachedConnection */ diff --git a/jdk/test/sun/rmi/transport/tcp/blockAccept/BlockAcceptTest.java b/jdk/test/sun/rmi/transport/tcp/blockAccept/BlockAcceptTest.java index af41bf0a7af..1624f68ee8c 100644 --- a/jdk/test/sun/rmi/transport/tcp/blockAccept/BlockAcceptTest.java +++ b/jdk/test/sun/rmi/transport/tcp/blockAccept/BlockAcceptTest.java @@ -27,11 +27,8 @@ * @summary RMI blocks in HttpAwareServerSocket.accept() if you telnet to it * @author Adrian Colley * - * @library ../../../../../java/rmi/testlibrary/ - * @build TestIface - * @build TestImpl - * @build TestImpl_Stub - * @build BlockAcceptTest + * @library ../../../../../java/rmi/testlibrary + * @build TestIface TestImpl TestImpl_Stub * @run main/othervm/policy=security.policy/timeout=60 BlockAcceptTest */ diff --git a/jdk/test/sun/rmi/transport/tcp/disableMultiplexing/DisableMultiplexing.java b/jdk/test/sun/rmi/transport/tcp/disableMultiplexing/DisableMultiplexing.java index 51dbeec1060..805c798ae45 100644 --- a/jdk/test/sun/rmi/transport/tcp/disableMultiplexing/DisableMultiplexing.java +++ b/jdk/test/sun/rmi/transport/tcp/disableMultiplexing/DisableMultiplexing.java @@ -28,7 +28,6 @@ * on that port, rather than engage in the deprecated "multiplexing protocol". * @author Peter Jones * - * @build DisableMultiplexing * @build DisableMultiplexing_Stub * @run main/othervm DisableMultiplexing */ diff --git a/jdk/test/sun/security/krb5/auto/KeyPermissions.java b/jdk/test/sun/security/krb5/auto/KeyPermissions.java new file mode 100644 index 00000000000..78f0eafc6c5 --- /dev/null +++ b/jdk/test/sun/security/krb5/auto/KeyPermissions.java @@ -0,0 +1,56 @@ +/* + * 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. + */ + +/* + * @test + * @bug 8004488 + * @summary wrong permissions checked in krb5 + * @compile -XDignore.symbol.file KeyPermissions.java + * @run main/othervm KeyPermissions + */ + +import java.security.AccessControlException; +import java.security.Permission; +import javax.security.auth.PrivateCredentialPermission; +import sun.security.jgss.GSSUtil; + +public class KeyPermissions extends SecurityManager { + + @Override + public void checkPermission(Permission perm) { + if (perm instanceof PrivateCredentialPermission) { + if (!perm.getName().startsWith("javax.security.auth.kerberos.")) { + throw new AccessControlException( + "I don't like this", perm); + } + } + } + + public static void main(String[] args) throws Exception { + System.setSecurityManager(new KeyPermissions()); + new OneKDC(null).writeJAASConf(); + Context s = Context.fromJAAS("server"); + s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID); + } +} + diff --git a/jdk/test/sun/security/krb5/auto/KeyTabCompat.java b/jdk/test/sun/security/krb5/auto/KeyTabCompat.java index f6763510fd2..87a3e7e9c78 100644 --- a/jdk/test/sun/security/krb5/auto/KeyTabCompat.java +++ b/jdk/test/sun/security/krb5/auto/KeyTabCompat.java @@ -24,6 +24,7 @@ /* * @test * @bug 6894072 + * @bug 8004488 * @compile -XDignore.symbol.file KeyTabCompat.java * @run main/othervm KeyTabCompat * @summary always refresh keytab @@ -70,21 +71,8 @@ public class KeyTabCompat { s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID); s.status(); - if (s.s().getPrivateCredentials(KerberosKey.class).size() != 1) { - throw new Exception("There should be one KerberosKey"); + if (s.s().getPrivateCredentials(KerberosKey.class).size() != 0) { + throw new Exception("There should be no KerberosKey"); } - - Thread.sleep(2000); // make sure ktab timestamp is different - - kdc.addPrincipal(OneKDC.SERVER, "pass2".toCharArray()); - kdc.writeKtab(OneKDC.KTAB); - - Context.handshake(c, s); - s.status(); - - if (s.s().getPrivateCredentials(KerberosKey.class).size() != 1) { - throw new Exception("There should be only one KerberosKey"); - } - } } diff --git a/jdk/test/sun/security/krb5/runNameEquals.sh b/jdk/test/sun/security/krb5/runNameEquals.sh index 15096cc99de..1fea3620e19 100644 --- a/jdk/test/sun/security/krb5/runNameEquals.sh +++ b/jdk/test/sun/security/krb5/runNameEquals.sh @@ -81,7 +81,7 @@ EXIT_STATUS=0 if [ "${NATIVE}" = "true" ] ; then echo "Testing native provider" - ${TESTJAVA}${FILESEP}bin${FILESEP}java \ + ${TESTJAVA}${FILESEP}bin${FILESEP}java ${TESTVMOPTS} \ -classpath ${TESTCLASSES} \ -Dsun.security.jgss.native=true \ ${TEST} @@ -92,7 +92,7 @@ if [ "${NATIVE}" = "true" ] ; then fi echo "Testing java provider" -${TESTJAVA}${FILESEP}bin${FILESEP}java \ +${TESTJAVA}${FILESEP}bin${FILESEP}java ${TESTVMOPTS} \ -classpath ${TESTCLASSES} \ -Djava.security.krb5.realm=R \ -Djava.security.krb5.kdc=127.0.0.1 \ diff --git a/jdk/test/sun/security/krb5/tools/ktcheck.sh b/jdk/test/sun/security/krb5/tools/ktcheck.sh index 383de8fc4f9..b1b3743076d 100644 --- a/jdk/test/sun/security/krb5/tools/ktcheck.sh +++ b/jdk/test/sun/security/krb5/tools/ktcheck.sh @@ -58,7 +58,7 @@ ${TESTJAVA}${FS}bin${FS}javac -d . ${TESTSRC}${FS}KtabCheck.java EXTRA_OPTIONS="-Djava.security.krb5.conf=${TESTSRC}${FS}onlythree.conf" KTAB="${TESTJAVA}${FS}bin${FS}ktab -J${EXTRA_OPTIONS} -k $KEYTAB -f" -CHECK="${TESTJAVA}${FS}bin${FS}java ${EXTRA_OPTIONS} KtabCheck $KEYTAB" +CHECK="${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} ${EXTRA_OPTIONS} KtabCheck $KEYTAB" echo ${EXTRA_OPTIONS} diff --git a/jdk/test/sun/security/mscapi/AccessKeyStore.sh b/jdk/test/sun/security/mscapi/AccessKeyStore.sh index 6706aa3ff39..0998de4821f 100644 --- a/jdk/test/sun/security/mscapi/AccessKeyStore.sh +++ b/jdk/test/sun/security/mscapi/AccessKeyStore.sh @@ -42,13 +42,13 @@ case "$OS" in ${TESTJAVA}/bin/javac -d . ${TESTSRC}\\AccessKeyStore.java echo "Using access.policy..." - ${TESTJAVA}/bin/java \ + ${TESTJAVA}/bin/java ${TESTVMOPTS} \ -Djava.security.manager \ -Djava.security.policy==${TESTSRC}\\access.policy \ AccessKeyStore echo "Using noaccess.policy..." - ${TESTJAVA}/bin/java \ + ${TESTJAVA}/bin/java ${TESTVMOPTS} \ -Djava.security.manager \ -Djava.security.policy==${TESTSRC}\\noaccess.policy \ AccessKeyStore -deny diff --git a/jdk/test/sun/security/mscapi/IsSunMSCAPIAvailable.sh b/jdk/test/sun/security/mscapi/IsSunMSCAPIAvailable.sh index 197ee37b134..77e258e4cda 100644 --- a/jdk/test/sun/security/mscapi/IsSunMSCAPIAvailable.sh +++ b/jdk/test/sun/security/mscapi/IsSunMSCAPIAvailable.sh @@ -40,7 +40,7 @@ case "$OS" in # execute test program - rely on it to exit if platform unsupported ${TESTJAVA}/bin/javac -d . ${TESTSRC}\\IsSunMSCAPIAvailable.java - ${TESTJAVA}/bin/java IsSunMSCAPIAvailable + ${TESTJAVA}/bin/java ${TESTVMOPTS} IsSunMSCAPIAvailable exit ;; diff --git a/jdk/test/sun/security/mscapi/KeyStoreCompatibilityMode.sh b/jdk/test/sun/security/mscapi/KeyStoreCompatibilityMode.sh index ee0c6c3609f..b6ca1395d76 100644 --- a/jdk/test/sun/security/mscapi/KeyStoreCompatibilityMode.sh +++ b/jdk/test/sun/security/mscapi/KeyStoreCompatibilityMode.sh @@ -43,15 +43,15 @@ case "$OS" in ${TESTJAVA}/bin/javac -d . ${TESTSRC}\\KeyStoreCompatibilityMode.java # mode implicitly enabled - ${TESTJAVA}/bin/java KeyStoreCompatibilityMode + ${TESTJAVA}/bin/java ${TESTVMOPTS} KeyStoreCompatibilityMode # mode explicitly enabled - ${TESTJAVA}/bin/java \ + ${TESTJAVA}/bin/java ${TESTVMOPTS} \ -Dsun.security.mscapi.keyStoreCompatibilityMode="true" \ KeyStoreCompatibilityMode # mode explicitly disabled - ${TESTJAVA}/bin/java \ + ${TESTJAVA}/bin/java ${TESTVMOPTS} \ -Dsun.security.mscapi.keyStoreCompatibilityMode="false" \ KeyStoreCompatibilityMode -disable diff --git a/jdk/test/sun/security/mscapi/PublicKeyInterop.sh b/jdk/test/sun/security/mscapi/PublicKeyInterop.sh index 1967e63d266..abdad4c6530 100644 --- a/jdk/test/sun/security/mscapi/PublicKeyInterop.sh +++ b/jdk/test/sun/security/mscapi/PublicKeyInterop.sh @@ -62,7 +62,7 @@ case "$OS" in echo echo "Running the test..." ${TESTJAVA}/bin/javac -d . ${TESTSRC}\\PublicKeyInterop.java - ${TESTJAVA}/bin/java PublicKeyInterop + ${TESTJAVA}/bin/java ${TESTVMOPTS} PublicKeyInterop rc=$? diff --git a/jdk/test/sun/security/mscapi/RSAEncryptDecrypt.sh b/jdk/test/sun/security/mscapi/RSAEncryptDecrypt.sh index 19add0a7356..ed17bd1159e 100644 --- a/jdk/test/sun/security/mscapi/RSAEncryptDecrypt.sh +++ b/jdk/test/sun/security/mscapi/RSAEncryptDecrypt.sh @@ -70,7 +70,7 @@ case "$OS" in # unsupported ${TESTJAVA}/bin/javac -d . ${TESTSRC}\\RSAEncryptDecrypt.java - ${TESTJAVA}/bin/java RSAEncryptDecrypt + ${TESTJAVA}/bin/java ${TESTVMOPTS} RSAEncryptDecrypt exit ;; diff --git a/jdk/test/sun/security/mscapi/ShortRSAKey1024.sh b/jdk/test/sun/security/mscapi/ShortRSAKey1024.sh index 1e01377ed29..05db70e1a3e 100644 --- a/jdk/test/sun/security/mscapi/ShortRSAKey1024.sh +++ b/jdk/test/sun/security/mscapi/ShortRSAKey1024.sh @@ -89,7 +89,7 @@ case "$OS" in echo "Running the test..." ${TESTJAVA}${FS}bin${FS}javac -d . \ ${TESTSRC}${FS}ShortRSAKeyWithinTLS.java - ${TESTJAVA}${FS}bin${FS}java ShortRSAKeyWithinTLS 7106773.$BITS $BITS \ + ${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} ShortRSAKeyWithinTLS 7106773.$BITS $BITS \ TLSv1.2 TLS_DHE_RSA_WITH_AES_128_CBC_SHA rc=$? diff --git a/jdk/test/sun/security/mscapi/SignUsingNONEwithRSA.sh b/jdk/test/sun/security/mscapi/SignUsingNONEwithRSA.sh index c89a8687877..f794e298d18 100644 --- a/jdk/test/sun/security/mscapi/SignUsingNONEwithRSA.sh +++ b/jdk/test/sun/security/mscapi/SignUsingNONEwithRSA.sh @@ -61,7 +61,7 @@ case "$OS" in echo echo "Running the test..." ${TESTJAVA}/bin/javac -d . ${TESTSRC}\\SignUsingNONEwithRSA.java - ${TESTJAVA}/bin/java SignUsingNONEwithRSA + ${TESTJAVA}/bin/java ${TESTVMOPTS} SignUsingNONEwithRSA rc=$? diff --git a/jdk/test/sun/security/mscapi/SignUsingSHA2withRSA.sh b/jdk/test/sun/security/mscapi/SignUsingSHA2withRSA.sh index c939fb39e3f..2d433f108f0 100644 --- a/jdk/test/sun/security/mscapi/SignUsingSHA2withRSA.sh +++ b/jdk/test/sun/security/mscapi/SignUsingSHA2withRSA.sh @@ -61,7 +61,7 @@ case "$OS" in echo echo "Running the test..." ${TESTJAVA}/bin/javac -d . ${TESTSRC}\\SignUsingSHA2withRSA.java - ${TESTJAVA}/bin/java SignUsingSHA2withRSA + ${TESTJAVA}/bin/java ${TESTVMOPTS} SignUsingSHA2withRSA rc=$? diff --git a/jdk/test/sun/security/pkcs11/KeyStore/Basic.sh b/jdk/test/sun/security/pkcs11/KeyStore/Basic.sh index 54408bdfd99..452b6290e4a 100644 --- a/jdk/test/sun/security/pkcs11/KeyStore/Basic.sh +++ b/jdk/test/sun/security/pkcs11/KeyStore/Basic.sh @@ -171,7 +171,7 @@ fi # run test -${TESTJAVA}${FS}bin${FS}java \ +${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} \ -classpath ${TESTCLASSES}${PS}${TESTSRC}${FS}loader.jar \ -DDIR=${TESTSRC}${FS}BasicData \ -DCUSTOM_DB_DIR=${TESTCLASSES} \ diff --git a/jdk/test/sun/security/pkcs11/KeyStore/ClientAuth.sh b/jdk/test/sun/security/pkcs11/KeyStore/ClientAuth.sh index 0593ddf144c..d0996c1823a 100644 --- a/jdk/test/sun/security/pkcs11/KeyStore/ClientAuth.sh +++ b/jdk/test/sun/security/pkcs11/KeyStore/ClientAuth.sh @@ -128,7 +128,7 @@ ${TESTJAVA}${FS}bin${FS}javac \ # run test echo "Run ClientAuth ..." -${TESTJAVA}${FS}bin${FS}java \ +${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} \ -classpath ${TESTCLASSES}${PS}${TESTSRC}${FS}loader.jar \ -DDIR=${TESTSRC}${FS}ClientAuthData${FS} \ -DCUSTOM_DB_DIR=${TESTCLASSES} \ @@ -149,7 +149,7 @@ fi # run test with specified TLS protocol and cipher suite echo "Run ClientAuth TLSv1.2 TLS_DHE_RSA_WITH_AES_128_CBC_SHA" -${TESTJAVA}${FS}bin${FS}java \ +${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} \ -classpath ${TESTCLASSES}${PS}${TESTSRC}${FS}loader.jar \ -DDIR=${TESTSRC}${FS}ClientAuthData${FS} \ -DCUSTOM_DB_DIR=${TESTCLASSES} \ diff --git a/jdk/test/sun/security/pkcs11/KeyStore/SecretKeysBasic.sh b/jdk/test/sun/security/pkcs11/KeyStore/SecretKeysBasic.sh index 4041c0e093a..30334555302 100644 --- a/jdk/test/sun/security/pkcs11/KeyStore/SecretKeysBasic.sh +++ b/jdk/test/sun/security/pkcs11/KeyStore/SecretKeysBasic.sh @@ -141,7 +141,7 @@ fi # run test cd ${TESTSRC} -${TESTJAVA}${FS}bin${FS}java \ +${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} \ -DDIR=${TESTSRC}${FS}BasicData${FS} \ -classpath ${TESTCLASSES}${PS}${TESTSRC}${FS}loader.jar \ -DCUSTOM_DB_DIR=${TESTCLASSES} \ diff --git a/jdk/test/sun/security/pkcs11/KeyStore/Solaris.sh b/jdk/test/sun/security/pkcs11/KeyStore/Solaris.sh index 9da8ab9c069..5ec1ac2ec95 100644 --- a/jdk/test/sun/security/pkcs11/KeyStore/Solaris.sh +++ b/jdk/test/sun/security/pkcs11/KeyStore/Solaris.sh @@ -142,7 +142,7 @@ fi # run test cd ${TESTSRC} -${TESTJAVA}${FS}bin${FS}java \ +${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} \ -classpath ${TESTCLASSES}${PS}${TESTSRC}${FS}loader.jar \ -DDIR=${TESTSRC}${FS}BasicData${FS} \ -DCUSTOM_P11_CONFIG=${TESTSRC}${FS}BasicData${FS}p11-solaris.txt \ diff --git a/jdk/test/sun/security/pkcs11/Provider/ConfigQuotedString.sh b/jdk/test/sun/security/pkcs11/Provider/ConfigQuotedString.sh index ce5693f5968..1a749d89490 100644 --- a/jdk/test/sun/security/pkcs11/Provider/ConfigQuotedString.sh +++ b/jdk/test/sun/security/pkcs11/Provider/ConfigQuotedString.sh @@ -99,7 +99,7 @@ ${TESTJAVA}${FS}bin${FS}javac \ # run test -${TESTJAVA}${FS}bin${FS}java \ +${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} \ -classpath ${TESTCLASSES} \ -DCUSTOM_P11_CONFIG=${TESTSRC}${FS}ConfigQuotedString-nss.txt \ -Dtest.src=${TESTSRC} \ diff --git a/jdk/test/sun/security/pkcs11/Provider/Login.sh b/jdk/test/sun/security/pkcs11/Provider/Login.sh index 86d8f9e4f70..6b37ef837d2 100644 --- a/jdk/test/sun/security/pkcs11/Provider/Login.sh +++ b/jdk/test/sun/security/pkcs11/Provider/Login.sh @@ -108,7 +108,7 @@ ${TESTJAVA}${FS}bin${FS}javac \ # run test -${TESTJAVA}${FS}bin${FS}java \ +${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} \ -classpath ${TESTCLASSES} \ -DCUSTOM_DB_DIR=${TESTCLASSES} \ -DCUSTOM_P11_CONFIG=${TESTSRC}${FS}Login-nss.txt \ diff --git a/jdk/test/sun/security/pkcs11/ec/TestECDSA.java b/jdk/test/sun/security/pkcs11/ec/TestECDSA.java index a684d8aa8e1..92dac4c34b6 100644 --- a/jdk/test/sun/security/pkcs11/ec/TestECDSA.java +++ b/jdk/test/sun/security/pkcs11/ec/TestECDSA.java @@ -179,7 +179,6 @@ public class TestECDSA extends PKCS11Test { // SHA1withECDSA and NONEwithECDSA Signature s = Signature.getInstance("SHA1withECDSA", provider); s.initSign(privateKey); - s.initSign(privateKey); s.update(data); byte[] s1 = s.sign(); diff --git a/jdk/test/sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java b/jdk/test/sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java index 5ccaa0ab72a..2788f03f8ad 100644 --- a/jdk/test/sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java +++ b/jdk/test/sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -21,6 +21,11 @@ * questions. */ +// +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. +// + /* * @test * @bug 6405536 @@ -28,6 +33,7 @@ * @author Andreas Sterbenz * @library .. * @library ../../../../java/security/testlibrary + * @run main/othervm ClientJSSEServerJSSE */ import java.security.*; diff --git a/jdk/test/sun/security/provider/PolicyFile/GrantAllPermToExtWhenNoPolicy.sh b/jdk/test/sun/security/provider/PolicyFile/GrantAllPermToExtWhenNoPolicy.sh index ee4035cc6ec..b09d1564b7f 100644 --- a/jdk/test/sun/security/provider/PolicyFile/GrantAllPermToExtWhenNoPolicy.sh +++ b/jdk/test/sun/security/provider/PolicyFile/GrantAllPermToExtWhenNoPolicy.sh @@ -82,7 +82,7 @@ mv \ ${TESTJAVA}${FILESEP}jre${FILESEP}lib${FILESEP}security${FILESEP}tmp_pol # run the test program -${TESTJAVA}${FILESEP}bin${FILESEP}java -Djava.security.manager \ +${TESTJAVA}${FILESEP}bin${FILESEP}java ${TESTVMOPTS} -Djava.security.manager \ GrantAllPermToExtWhenNoPolicy # save error status diff --git a/jdk/test/sun/security/provider/PolicyFile/getinstance/getinstance.sh b/jdk/test/sun/security/provider/PolicyFile/getinstance/getinstance.sh index b52db72b326..893bbb65bc5 100644 --- a/jdk/test/sun/security/provider/PolicyFile/getinstance/getinstance.sh +++ b/jdk/test/sun/security/provider/PolicyFile/getinstance/getinstance.sh @@ -92,7 +92,7 @@ ${TESTJAVA}${FS}bin${FS}javac -d ${TESTCLASSES}${FS}boot \ ${TESTJAVA}${FS}bin${FS}javac -d ${TESTCLASSES}${FS}app \ ${TESTSRC}${FS}GetInstance.java -${TESTJAVA}${FS}bin${FS}java \ +${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} \ -Xbootclasspath/a:"${TESTCLASSES}${FS}boot" \ -classpath "${TESTCLASSES}${FS}app" -Djava.security.manager \ -Djava.security.policy=GetInstance.policy \ @@ -106,7 +106,7 @@ if [ $status1 -ne 0 ]; then echo "Failed on first test" fi -${TESTJAVA}${FS}bin${FS}java \ +${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} \ -classpath "${TESTCLASSES}${FS}boot${PS}${TESTCLASSES}${FS}app" \ -Djava.security.manager \ -Djava.security.policy=GetInstance.policy \ diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/EngineArgs/DebugReportsOneExtraByte.sh b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/EngineArgs/DebugReportsOneExtraByte.sh index c2d14c75bd3..f29f6cedd94 100644 --- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/EngineArgs/DebugReportsOneExtraByte.sh +++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/EngineArgs/DebugReportsOneExtraByte.sh @@ -59,7 +59,7 @@ echo "Examining debug output for the string:" echo "${STRING}" echo "=========" -${TESTJAVA}${FS}bin${FS}java -Djavax.net.debug=all \ +${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -Djavax.net.debug=all \ -Dtest.src=${TESTSRC} \ DebugReportsOneExtraByte 2>&1 | \ grep "${STRING}" diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/NotifyHandshakeTest.sh b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/NotifyHandshakeTest.sh index fa5a410aa64..60a38468be5 100644 --- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/NotifyHandshakeTest.sh +++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/NotifyHandshakeTest.sh @@ -82,7 +82,7 @@ rm -rf com edu # This is the only thing we really care about as far as # test status goes. # -${TESTJAVA}${FILESEP}bin${FILESEP}java \ +${TESTJAVA}${FILESEP}bin${FILESEP}java ${TESTVMOPTS} \ -Dtest.src=${TESTSRC} \ -classpath "com.jar${PATHSEP}edu.jar" \ -Djava.security.manager \ diff --git a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxy.sh b/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxy.sh index 7696cbbd6b3..85e9c22c4af 100644 --- a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxy.sh +++ b/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxy.sh @@ -52,5 +52,5 @@ esac ${TESTJAVA}${FS}bin${FS}javac -d . ${TESTSRC}${FS}OriginServer.java \ ${TESTSRC}${FS}ProxyTunnelServer.java ${TESTSRC}${FS}PostThruProxy.java -${TESTJAVA}${FS}bin${FS}java PostThruProxy ${HOSTNAME} ${TESTSRC} +${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} PostThruProxy ${HOSTNAME} ${TESTSRC} exit diff --git a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxyWithAuth.sh b/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxyWithAuth.sh index 9e2ed3c4bf0..96c0642480b 100644 --- a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxyWithAuth.sh +++ b/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxyWithAuth.sh @@ -53,5 +53,5 @@ esac ${TESTJAVA}${FS}bin${FS}javac -d . ${TESTSRC}${FS}OriginServer.java \ ${TESTSRC}${FS}ProxyTunnelServer.java \ ${TESTSRC}${FS}PostThruProxyWithAuth.java -${TESTJAVA}${FS}bin${FS}java PostThruProxyWithAuth ${HOSTNAME} ${TESTSRC} +${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} PostThruProxyWithAuth ${HOSTNAME} ${TESTSRC} exit diff --git a/jdk/test/sun/security/tools/jarsigner/emptymanifest.sh b/jdk/test/sun/security/tools/jarsigner/emptymanifest.sh index 81c0937f436..cbb72413f1a 100644 --- a/jdk/test/sun/security/tools/jarsigner/emptymanifest.sh +++ b/jdk/test/sun/security/tools/jarsigner/emptymanifest.sh @@ -65,7 +65,7 @@ class CrLf { } EOF $JAVAC CrLf.java -$JAVA CrLf > META-INF${FS}MANIFEST.MF +$JAVA ${TESTVMOPTS} CrLf > META-INF${FS}MANIFEST.MF zip $JFILE META-INF${FS}MANIFEST.MF A B $KT -alias a -dname CN=a -keyalg rsa -genkey -validity 300 diff --git a/jdk/test/sun/security/tools/jarsigner/ts.sh b/jdk/test/sun/security/tools/jarsigner/ts.sh index 3293a7dfa71..43a3651f62a 100644 --- a/jdk/test/sun/security/tools/jarsigner/ts.sh +++ b/jdk/test/sun/security/tools/jarsigner/ts.sh @@ -87,5 +87,5 @@ $KT -alias tsbad3 -certreq | \ $KT -alias tsbad3 -importcert $JAVAC -d . ${TESTSRC}/TimestampCheck.java -$JAVA TimestampCheck +$JAVA ${TESTVMOPTS} TimestampCheck diff --git a/jdk/test/sun/security/tools/keytool/console.sh b/jdk/test/sun/security/tools/keytool/console.sh index 994befcde28..ec0f05961f8 100644 --- a/jdk/test/sun/security/tools/keytool/console.sh +++ b/jdk/test/sun/security/tools/keytool/console.sh @@ -31,62 +31,101 @@ # @run shell/manual console.sh if [ "$ALT_PASS" = "" ]; then - export PASS=äöäöäöäö + PASSW=äöäöäö else - export PASS=$ALT_PASS + PASSW=$ALT_PASS +fi + +KS=/tmp/kkk.$$ + +cat <<____ + +ATTENTION +=============================================================== + +This test is about non-ASCII password input compatibility between +JDK 5.0 and later versions. Before running the test, make sure that -- + + \$J5 points to a JDK 5.0 installation + \$JM points to the current installation + +The password string used in this test is $PASSW. If you find difficulty +entering it in in your system, feel free to change it to something else +by providing \$ALT_PASS. It should be no less than 6 characters and include +some non-ASCII characters. + +For each test, type into the characters as described in the test header. + means the RETURN (or ENTER key). Please wait for a little while +after is pressed each time. + +\$J5 is now $J5 +\$JM is now $JM + +____ + + +if [ "$J5" = "" -o "$JM" = "" ]; then + echo "Define \$J5 and \$JM first" + exit 1 fi -echo "ATTENTION" -echo "===============================================================" -echo -echo "This test is about console password input compatibility between" -echo "Tiger and Mustang. Before running the test, make sure that --" -echo "\$J5 points to a JDK 5.0 installation" -echo "\$JM points to a JDK 6 installation". -echo -echo "The password string used in this test is $PASS. If you find difficulty" -echo "entering it in in your system, feel free to change it to something else" -echo "by providing \$ALT_PASS (should be not less than 6 characters)" -echo -echo "For all prompt of \"Enter keystore password\", type $PASS and press ENTER" -echo "For all prompt of \"Enter key password for (RETURN if same as keystore password)\", press ENTER" -echo "If you see both the prompts appear, say --" -echo " Enter key password for " -echo " (RETURN if same as keystore password): Enter keystore password:" -echo "only response to the last prompt by typing $PASS and press ENTER" -echo -echo "Only if all the command run correctly without showing any error " -echo "or warning, this test passes." -echo echo "Press ENTER to start the test, or Ctrl-C to stop it" -read +read x + echo -echo "Test #1: 5->6, non-prompt" -rm kkk -$J5/bin/keytool -keystore kkk -genkey -dname CN=olala -storepass $PASS -$JM/bin/keytool -keystore kkk -list -storepass $PASS -echo "Test #2: 6->5, non-prompt" -rm kkk -$JM/bin/keytool -keystore kkk -genkey -dname CN=olala -storepass $PASS -$J5/bin/keytool -keystore kkk -list -storepass $PASS -echo "Test #3: 5->6, prompt" -rm kkk -$J5/bin/keytool -keystore kkk -genkey -dname CN=olala -$JM/bin/keytool -keystore kkk -list -echo $PASS| $J5/bin/keytool -keystore kkk -list -echo $PASS| $JM/bin/keytool -keystore kkk -list -echo "Test #4: 6->5, prompt" -rm kkk -$JM/bin/keytool -keystore kkk -genkey -dname CN=olala -$J5/bin/keytool -keystore kkk -list -echo $PASS| $JM/bin/keytool -keystore kkk -list -echo $PASS| $J5/bin/keytool -keystore kkk -list -echo "Test #5: 5->6, pipe" -rm kkk -echo $PASS| $J5/bin/keytool -keystore kkk -genkey -dname CN=olala -$JM/bin/keytool -keystore kkk -list -echo $PASS| $J5/bin/keytool -keystore kkk -list -echo $PASS| $JM/bin/keytool -keystore kkk -list -rm kkk +echo "==========================================" +echo "Test #1: 5->6, non-prompt. Please type " +echo "==========================================" +echo +rm $KS 2> /dev/null +$J5/bin/keytool -keystore $KS -genkey -dname CN=olala -storepass $PASSW || exit 1 +$JM/bin/keytool -keystore $KS -list -storepass $PASSW || exit 2 + +echo "==========================================" +echo "Test #2: 6->5, non-prompt. Please type " +echo "==========================================" +echo + +rm $KS 2> /dev/null +$JM/bin/keytool -keystore $KS -genkey -dname CN=olala -storepass $PASSW || exit 3 +$J5/bin/keytool -keystore $KS -list -storepass $PASSW || exit 4 + +echo "============================================================" +echo "Test #3: 5->6, prompt. Please type $PASSW $PASSW " +echo "============================================================" +echo + +rm $KS 2> /dev/null +$J5/bin/keytool -keystore $KS -genkey -dname CN=olala || exit 5 +$JM/bin/keytool -keystore $KS -list || exit 6 +echo $PASSW| $J5/bin/keytool -keystore $KS -list || exit 7 +echo $PASSW| $JM/bin/keytool -keystore $KS -list || exit 8 + +echo "=======================================================================" +echo "Test #4: 6->5, prompt. Please type $PASSW $PASSW $PASSW " +echo "=======================================================================" +echo + +rm $KS 2> /dev/null +$JM/bin/keytool -keystore $KS -genkey -dname CN=olala || exit 9 +$J5/bin/keytool -keystore $KS -list || exit 10 +echo $PASSW| $JM/bin/keytool -keystore $KS -list || exit 11 +echo $PASSW| $J5/bin/keytool -keystore $KS -list || exit 12 + +echo "===========================================" +echo "Test #5: 5->6, pipe. Please type $PASSW " +echo "===========================================" +echo + +rm $KS 2> /dev/null +echo $PASSW| $J5/bin/keytool -keystore $KS -genkey -dname CN=olala || exit 13 +$JM/bin/keytool -keystore $KS -list || exit 14 +echo $PASSW| $J5/bin/keytool -keystore $KS -list || exit 15 +echo $PASSW| $JM/bin/keytool -keystore $KS -list || exit 16 + +rm $KS 2> /dev/null + +echo +echo "Success" exit 0 diff --git a/jdk/test/sun/security/tools/keytool/printssl.sh b/jdk/test/sun/security/tools/keytool/printssl.sh index b750ffe8d2d..46de2609b0b 100644 --- a/jdk/test/sun/security/tools/keytool/printssl.sh +++ b/jdk/test/sun/security/tools/keytool/printssl.sh @@ -53,7 +53,7 @@ case "$OS" in esac ${TESTJAVA}${FS}bin${FS}javac -d . ${TESTSRC}${FS}PrintSSL.java || exit 10 -${TESTJAVA}${FS}bin${FS}java -Dtest.src=$TESTSRC PrintSSL | ( read PORT; ${TESTJAVA}${FS}bin${FS}keytool -printcert -sslserver localhost:$PORT ) +${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -Dtest.src=$TESTSRC PrintSSL | ( read PORT; ${TESTJAVA}${FS}bin${FS}keytool -printcert -sslserver localhost:$PORT ) status=$? rm PrintSSL*.class diff --git a/jdk/test/sun/security/tools/keytool/standard.sh b/jdk/test/sun/security/tools/keytool/standard.sh index 756d2fb1f1e..c75a7a49b46 100644 --- a/jdk/test/sun/security/tools/keytool/standard.sh +++ b/jdk/test/sun/security/tools/keytool/standard.sh @@ -58,7 +58,7 @@ esac ${TESTJAVA}${FS}bin${FS}javac -d . -XDignore.symbol.file ${TESTSRC}${FS}KeyToolTest.java || exit 10 -echo | ${TESTJAVA}${FS}bin${FS}java -Dfile KeyToolTest +echo | ${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -Dfile KeyToolTest status=$? rm HumanInputStream*.class diff --git a/jdk/test/sun/security/validator/certreplace.sh b/jdk/test/sun/security/validator/certreplace.sh index 16470a3994a..b45a70edaa8 100644 --- a/jdk/test/sun/security/validator/certreplace.sh +++ b/jdk/test/sun/security/validator/certreplace.sh @@ -82,4 +82,4 @@ $KT -delete -alias user # 5. Build and run test $JAVAC -d . ${TESTSRC}${FS}CertReplace.java -$JAVA CertReplace certreplace.jks certreplace.certs +$JAVA ${TESTVMOPTS} CertReplace certreplace.jks certreplace.certs diff --git a/jdk/test/sun/security/validator/samedn.sh b/jdk/test/sun/security/validator/samedn.sh index 9d5afd40a8e..5d9b0455713 100644 --- a/jdk/test/sun/security/validator/samedn.sh +++ b/jdk/test/sun/security/validator/samedn.sh @@ -78,5 +78,5 @@ $KT -delete -alias user # Check both, one of them might be dropped out of map in old codes. $JAVAC -d . ${TESTSRC}${FS}CertReplace.java -$JAVA CertReplace samedn.jks samedn1.certs || exit 1 -$JAVA CertReplace samedn.jks samedn2.certs || exit 2 +$JAVA ${TESTVMOPTS} CertReplace samedn.jks samedn1.certs || exit 1 +$JAVA ${TESTVMOPTS} CertReplace samedn.jks samedn2.certs || exit 2 diff --git a/jdk/test/sun/text/resources/LocaleData b/jdk/test/sun/text/resources/LocaleData index 2e630767548..8a85b7c9bf5 100644 --- a/jdk/test/sun/text/resources/LocaleData +++ b/jdk/test/sun/text/resources/LocaleData @@ -7074,3 +7074,586 @@ FormatData/sl/DatePatterns/1=dd. MMMM y # bug 7189611 CurrencyNames/es_VE/VEF=Bs.F. + +# rfe 8000983 (narrow names support) +FormatData//DayNarrows/0=S +FormatData//DayNarrows/1=M +FormatData//DayNarrows/2=T +FormatData//DayNarrows/3=W +FormatData//DayNarrows/4=T +FormatData//DayNarrows/5=F +FormatData//DayNarrows/6=S +FormatData//narrow.AmPmMarkers/0=a +FormatData//narrow.AmPmMarkers/1=p +FormatData//narrow.Eras/0=B +FormatData//narrow.Eras/1=A +FormatData//buddhist.narrow.Eras/0=BC +FormatData//buddhist.narrow.Eras/1=B.E. +FormatData//japanese.narrow.Eras/0= +FormatData//japanese.narrow.Eras/1=M +FormatData//japanese.narrow.Eras/2=T +FormatData//japanese.narrow.Eras/3=S +FormatData//japanese.narrow.Eras/4=H + +FormatData/ar/DayNarrows/0=\u062d +FormatData/ar/DayNarrows/1=\u0646 +FormatData/ar/DayNarrows/2=\u062b +FormatData/ar/DayNarrows/3=\u0631 +FormatData/ar/DayNarrows/4=\u062e +FormatData/ar/DayNarrows/5=\u062c +FormatData/ar/DayNarrows/6=\u0633 + +FormatData/be/standalone.MonthNarrows/0=\u0441 +FormatData/be/standalone.MonthNarrows/1=\u043b +FormatData/be/standalone.MonthNarrows/2=\u0441 +FormatData/be/standalone.MonthNarrows/3=\u043a +FormatData/be/standalone.MonthNarrows/4=\u043c +FormatData/be/standalone.MonthNarrows/5=\u0447 +FormatData/be/standalone.MonthNarrows/6=\u043b +FormatData/be/standalone.MonthNarrows/7=\u0436 +FormatData/be/standalone.MonthNarrows/8=\u0432 +FormatData/be/standalone.MonthNarrows/9=\u043a +FormatData/be/standalone.MonthNarrows/10=\u043b +FormatData/be/standalone.MonthNarrows/11=\u0441 +FormatData/be/standalone.MonthNarrows/12= +FormatData/be/DayNarrows/0=\u043d +FormatData/be/DayNarrows/1=\u043f +FormatData/be/DayNarrows/2=\u0430 +FormatData/be/DayNarrows/3=\u0441 +FormatData/be/DayNarrows/4=\u0447 +FormatData/be/DayNarrows/5=\u043f +FormatData/be/DayNarrows/6=\u0441 + +FormatData/bg/DayNarrows/0=\u043d +FormatData/bg/DayNarrows/1=\u043f +FormatData/bg/DayNarrows/2=\u0432 +FormatData/bg/DayNarrows/3=\u0441 +FormatData/bg/DayNarrows/4=\u0447 +FormatData/bg/DayNarrows/5=\u043f +FormatData/bg/DayNarrows/6=\u0441 + +FormatData/ca/standalone.MonthNarrows/0=g +FormatData/ca/standalone.MonthNarrows/1=f +FormatData/ca/standalone.MonthNarrows/2=m +FormatData/ca/standalone.MonthNarrows/3=a +FormatData/ca/standalone.MonthNarrows/4=m +FormatData/ca/standalone.MonthNarrows/5=j +FormatData/ca/standalone.MonthNarrows/6=j +FormatData/ca/standalone.MonthNarrows/7=a +FormatData/ca/standalone.MonthNarrows/8=s +FormatData/ca/standalone.MonthNarrows/9=o +FormatData/ca/standalone.MonthNarrows/10=n +FormatData/ca/standalone.MonthNarrows/11=d +FormatData/ca/standalone.MonthNarrows/12= +FormatData/ca/DayNarrows/0=G +# Note: "L" is a contribued item in CLDR +FormatData/ca/DayNarrows/1=L +FormatData/ca/DayNarrows/2=T +FormatData/ca/DayNarrows/3=C +FormatData/ca/DayNarrows/4=J +FormatData/ca/DayNarrows/5=V +FormatData/ca/DayNarrows/6=S +FormatData/ca/standalone.DayNarrows/0=g +FormatData/ca/standalone.DayNarrows/1=l +FormatData/ca/standalone.DayNarrows/2=t +FormatData/ca/standalone.DayNarrows/3=c +FormatData/ca/standalone.DayNarrows/4=j +FormatData/ca/standalone.DayNarrows/5=v +FormatData/ca/standalone.DayNarrows/6=s + +FormatData/cs/DayNarrows/0=N +FormatData/cs/DayNarrows/1=P +FormatData/cs/DayNarrows/2=\u00da +FormatData/cs/DayNarrows/3=S +FormatData/cs/DayNarrows/4=\u010c +FormatData/cs/DayNarrows/5=P +FormatData/cs/DayNarrows/6=S + +FormatData/da/DayNarrows/0=S +FormatData/da/DayNarrows/1=M +FormatData/da/DayNarrows/2=T +FormatData/da/DayNarrows/3=O +FormatData/da/DayNarrows/4=T +FormatData/da/DayNarrows/5=F +FormatData/da/DayNarrows/6=L + +FormatData/de/DayNarrows/0=S +FormatData/de/DayNarrows/1=M +FormatData/de/DayNarrows/2=D +FormatData/de/DayNarrows/3=M +FormatData/de/DayNarrows/4=D +FormatData/de/DayNarrows/5=F +FormatData/de/DayNarrows/6=S + +FormatData/el/DayNarrows/0=\u039a +FormatData/el/DayNarrows/1=\u0394 +FormatData/el/DayNarrows/2=\u03a4 +FormatData/el/DayNarrows/3=\u03a4 +FormatData/el/DayNarrows/4=\u03a0 +FormatData/el/DayNarrows/5=\u03a0 +FormatData/el/DayNarrows/6=\u03a3 + +FormatData/es/DayNarrows/0=D +FormatData/es/DayNarrows/1=L +FormatData/es/DayNarrows/2=M +FormatData/es/DayNarrows/3=X +FormatData/es/DayNarrows/4=J +FormatData/es/DayNarrows/5=V +FormatData/es/DayNarrows/6=S + +FormatData/et/DayNarrows/0=P +FormatData/et/DayNarrows/1=E +FormatData/et/DayNarrows/2=T +FormatData/et/DayNarrows/3=K +FormatData/et/DayNarrows/4=N +FormatData/et/DayNarrows/5=R +FormatData/et/DayNarrows/6=L + +FormatData/fi/standalone.MonthNarrows/0=T +FormatData/fi/standalone.MonthNarrows/1=H +FormatData/fi/standalone.MonthNarrows/2=M +FormatData/fi/standalone.MonthNarrows/3=H +FormatData/fi/standalone.MonthNarrows/4=T +FormatData/fi/standalone.MonthNarrows/5=K +FormatData/fi/standalone.MonthNarrows/6=H +FormatData/fi/standalone.MonthNarrows/7=E +FormatData/fi/standalone.MonthNarrows/8=S +FormatData/fi/standalone.MonthNarrows/9=L +FormatData/fi/standalone.MonthNarrows/10=M +FormatData/fi/standalone.MonthNarrows/11=J +FormatData/fi/standalone.MonthNarrows/12= +FormatData/fi/DayNarrows/0=S +FormatData/fi/DayNarrows/1=M +FormatData/fi/DayNarrows/2=T +FormatData/fi/DayNarrows/3=K +FormatData/fi/DayNarrows/4=T +FormatData/fi/DayNarrows/5=P +FormatData/fi/DayNarrows/6=L +FormatData/fi/standalone.DayNarrows/0=S +FormatData/fi/standalone.DayNarrows/1=M +FormatData/fi/standalone.DayNarrows/2=T +FormatData/fi/standalone.DayNarrows/3=K +FormatData/fi/standalone.DayNarrows/4=T +FormatData/fi/standalone.DayNarrows/5=P +FormatData/fi/standalone.DayNarrows/6=L +FormatData/fi/narrow.AmPmMarkers/0=ap. +FormatData/fi/narrow.AmPmMarkers/1=ip. + +FormatData/fr/DayNarrows/0=D +FormatData/fr/DayNarrows/1=L +FormatData/fr/DayNarrows/2=M +FormatData/fr/DayNarrows/3=M +FormatData/fr/DayNarrows/4=J +FormatData/fr/DayNarrows/5=V +FormatData/fr/DayNarrows/6=S + +FormatData/hi_IN/DayNarrows/0=\u0930 +FormatData/hi_IN/DayNarrows/1=\u0938\u094b +FormatData/hi_IN/DayNarrows/2=\u092e\u0902 +FormatData/hi_IN/DayNarrows/3=\u092c\u0941 +FormatData/hi_IN/DayNarrows/4=\u0917\u0941 +FormatData/hi_IN/DayNarrows/5=\u0936\u0941 +FormatData/hi_IN/DayNarrows/6=\u0936 + +FormatData/hr/standalone.MonthNarrows/0=1. +FormatData/hr/standalone.MonthNarrows/1=2. +FormatData/hr/standalone.MonthNarrows/2=3. +FormatData/hr/standalone.MonthNarrows/3=4. +FormatData/hr/standalone.MonthNarrows/4=5. +FormatData/hr/standalone.MonthNarrows/5=6. +FormatData/hr/standalone.MonthNarrows/6=7. +FormatData/hr/standalone.MonthNarrows/7=8. +FormatData/hr/standalone.MonthNarrows/8=9. +FormatData/hr/standalone.MonthNarrows/9=10. +FormatData/hr/standalone.MonthNarrows/10=11. +FormatData/hr/standalone.MonthNarrows/11=12. +FormatData/hr/standalone.MonthNarrows/12= +FormatData/hr/DayNarrows/0=N +FormatData/hr/DayNarrows/1=P +FormatData/hr/DayNarrows/2=U +FormatData/hr/DayNarrows/3=S +FormatData/hr/DayNarrows/4=\u010c +FormatData/hr/DayNarrows/5=P +FormatData/hr/DayNarrows/6=S +FormatData/hr/standalone.DayNarrows/0=n +FormatData/hr/standalone.DayNarrows/1=p +FormatData/hr/standalone.DayNarrows/2=u +FormatData/hr/standalone.DayNarrows/3=s +FormatData/hr/standalone.DayNarrows/4=\u010d +FormatData/hr/standalone.DayNarrows/5=p +FormatData/hr/standalone.DayNarrows/6=s + +FormatData/hu/DayNarrows/0=V +FormatData/hu/DayNarrows/1=H +FormatData/hu/DayNarrows/2=K +FormatData/hu/DayNarrows/3=Sz +FormatData/hu/DayNarrows/4=Cs +FormatData/hu/DayNarrows/5=P +FormatData/hu/DayNarrows/6=Sz + +FormatData/is/standalone.MonthNarrows/0=j +FormatData/is/standalone.MonthNarrows/1=f +FormatData/is/standalone.MonthNarrows/2=m +FormatData/is/standalone.MonthNarrows/3=a +FormatData/is/standalone.MonthNarrows/4=m +FormatData/is/standalone.MonthNarrows/5=j +FormatData/is/standalone.MonthNarrows/6=j +FormatData/is/standalone.MonthNarrows/7=\u00e1 +FormatData/is/standalone.MonthNarrows/8=s +FormatData/is/standalone.MonthNarrows/9=o +FormatData/is/standalone.MonthNarrows/10=n +FormatData/is/standalone.MonthNarrows/11=d +FormatData/is/standalone.MonthNarrows/12= +FormatData/is/DayNarrows/0=S +FormatData/is/DayNarrows/1=M +FormatData/is/DayNarrows/2=\u00de +FormatData/is/DayNarrows/3=M +FormatData/is/DayNarrows/4=F +FormatData/is/DayNarrows/5=F +FormatData/is/DayNarrows/6=L +FormatData/is/standalone.DayNarrows/0=s +FormatData/is/standalone.DayNarrows/1=m +FormatData/is/standalone.DayNarrows/2=\u00fe +FormatData/is/standalone.DayNarrows/3=m +FormatData/is/standalone.DayNarrows/4=f +FormatData/is/standalone.DayNarrows/5=f +FormatData/is/standalone.DayNarrows/6=l + +FormatData/it/DayNarrows/0=D +FormatData/it/DayNarrows/1=L +FormatData/it/DayNarrows/2=M +FormatData/it/DayNarrows/3=M +FormatData/it/DayNarrows/4=G +FormatData/it/DayNarrows/5=V +FormatData/it/DayNarrows/6=S + +FormatData/iw/DayNarrows/0=\u05d0 +FormatData/iw/DayNarrows/1=\u05d1 +FormatData/iw/DayNarrows/2=\u05d2 +FormatData/iw/DayNarrows/3=\u05d3 +FormatData/iw/DayNarrows/4=\u05d4 +FormatData/iw/DayNarrows/5=\u05d5 +FormatData/iw/DayNarrows/6=\u05e9 +FormatData/iw/standalone.DayNarrows/0=\u05d0 +FormatData/iw/standalone.DayNarrows/1=\u05d1 +FormatData/iw/standalone.DayNarrows/2=\u05d2 +FormatData/iw/standalone.DayNarrows/3=\u05d3 +FormatData/iw/standalone.DayNarrows/4=\u05d4 +FormatData/iw/standalone.DayNarrows/5=\u05d5 +FormatData/iw/standalone.DayNarrows/6=\u05e9 + +FormatData/ja/DayNarrows/0=\u65e5 +FormatData/ja/DayNarrows/1=\u6708 +FormatData/ja/DayNarrows/2=\u706b +FormatData/ja/DayNarrows/3=\u6c34 +FormatData/ja/DayNarrows/4=\u6728 +FormatData/ja/DayNarrows/5=\u91d1 +FormatData/ja/DayNarrows/6=\u571f + +FormatData/ko/DayNarrows/0=\uc77c +FormatData/ko/DayNarrows/1=\uc6d4 +FormatData/ko/DayNarrows/2=\ud654 +FormatData/ko/DayNarrows/3=\uc218 +FormatData/ko/DayNarrows/4=\ubaa9 +FormatData/ko/DayNarrows/5=\uae08 +FormatData/ko/DayNarrows/6=\ud1a0 + +FormatData/lt/standalone.MonthNarrows/0=S +FormatData/lt/standalone.MonthNarrows/1=V +FormatData/lt/standalone.MonthNarrows/2=K +FormatData/lt/standalone.MonthNarrows/3=B +FormatData/lt/standalone.MonthNarrows/4=G +FormatData/lt/standalone.MonthNarrows/5=B +FormatData/lt/standalone.MonthNarrows/6=L +FormatData/lt/standalone.MonthNarrows/7=R +FormatData/lt/standalone.MonthNarrows/8=R +FormatData/lt/standalone.MonthNarrows/9=S +FormatData/lt/standalone.MonthNarrows/10=L +FormatData/lt/standalone.MonthNarrows/11=G +FormatData/lt/standalone.MonthNarrows/12= + +FormatData/lt/DayNarrows/0=S +FormatData/lt/DayNarrows/1=P +FormatData/lt/DayNarrows/2=A +FormatData/lt/DayNarrows/3=T +FormatData/lt/DayNarrows/4=K +FormatData/lt/DayNarrows/5=P +FormatData/lt/DayNarrows/6=\u0160 +FormatData/lt/standalone.DayNarrows/0=S +FormatData/lt/standalone.DayNarrows/1=P +FormatData/lt/standalone.DayNarrows/2=A +FormatData/lt/standalone.DayNarrows/3=T +FormatData/lt/standalone.DayNarrows/4=K +FormatData/lt/standalone.DayNarrows/5=P +FormatData/lt/standalone.DayNarrows/6=\u0160 + +FormatData/lv/DayNarrows/0=S +FormatData/lv/DayNarrows/1=P +FormatData/lv/DayNarrows/2=O +FormatData/lv/DayNarrows/3=T +FormatData/lv/DayNarrows/4=C +FormatData/lv/DayNarrows/5=P +FormatData/lv/DayNarrows/6=S + +FormatData/mk/DayNarrows/0=\u043d +FormatData/mk/DayNarrows/1=\u043f +FormatData/mk/DayNarrows/2=\u0432 +FormatData/mk/DayNarrows/3=\u0441 +FormatData/mk/DayNarrows/4=\u0447 +FormatData/mk/DayNarrows/5=\u043f +FormatData/mk/DayNarrows/6=\u0441 + +FormatData/ms/standalone.MonthNarrows/0=J +FormatData/ms/standalone.MonthNarrows/1=F +FormatData/ms/standalone.MonthNarrows/2=M +FormatData/ms/standalone.MonthNarrows/3=A +FormatData/ms/standalone.MonthNarrows/4=M +FormatData/ms/standalone.MonthNarrows/5=J +FormatData/ms/standalone.MonthNarrows/6=J +FormatData/ms/standalone.MonthNarrows/7=O +FormatData/ms/standalone.MonthNarrows/8=S +FormatData/ms/standalone.MonthNarrows/9=O +FormatData/ms/standalone.MonthNarrows/10=N +FormatData/ms/standalone.MonthNarrows/11=D +FormatData/ms/standalone.MonthNarrows/12= +FormatData/ms/DayNarrows/0=A +FormatData/ms/DayNarrows/1=I +FormatData/ms/DayNarrows/2=S +FormatData/ms/DayNarrows/3=R +FormatData/ms/DayNarrows/4=K +FormatData/ms/DayNarrows/5=J +FormatData/ms/DayNarrows/6=S +FormatData/ms/standalone.DayNarrows/0=A +FormatData/ms/standalone.DayNarrows/1=I +FormatData/ms/standalone.DayNarrows/2=S +FormatData/ms/standalone.DayNarrows/3=R +FormatData/ms/standalone.DayNarrows/4=K +FormatData/ms/standalone.DayNarrows/5=J +FormatData/ms/standalone.DayNarrows/6=S + +FormatData/mt/DayNarrows/0=\u0126 +FormatData/mt/DayNarrows/1=T +FormatData/mt/DayNarrows/2=T +FormatData/mt/DayNarrows/3=E +FormatData/mt/DayNarrows/4=\u0126 +FormatData/mt/DayNarrows/5=\u0120 +FormatData/mt/DayNarrows/6=S + +FormatData/nl/DayNarrows/0=Z +FormatData/nl/DayNarrows/1=M +FormatData/nl/DayNarrows/2=D +FormatData/nl/DayNarrows/3=W +FormatData/nl/DayNarrows/4=D +FormatData/nl/DayNarrows/5=V +FormatData/nl/DayNarrows/6=Z + +FormatData/pl/DayNarrows/0=N +FormatData/pl/DayNarrows/1=P +FormatData/pl/DayNarrows/2=W +FormatData/pl/DayNarrows/3=\u015a +FormatData/pl/DayNarrows/4=C +FormatData/pl/DayNarrows/5=P +FormatData/pl/DayNarrows/6=S + +FormatData/pt/DayNarrows/0=D +FormatData/pt/DayNarrows/1=S +FormatData/pt/DayNarrows/2=T +FormatData/pt/DayNarrows/3=Q +FormatData/pt/DayNarrows/4=Q +FormatData/pt/DayNarrows/5=S +FormatData/pt/DayNarrows/6=S + +FormatData/ro/standalone.MonthNarrows/0=I +FormatData/ro/standalone.MonthNarrows/1=F +FormatData/ro/standalone.MonthNarrows/2=M +FormatData/ro/standalone.MonthNarrows/3=A +FormatData/ro/standalone.MonthNarrows/4=M +FormatData/ro/standalone.MonthNarrows/5=I +FormatData/ro/standalone.MonthNarrows/6=I +FormatData/ro/standalone.MonthNarrows/7=A +FormatData/ro/standalone.MonthNarrows/8=S +FormatData/ro/standalone.MonthNarrows/9=O +FormatData/ro/standalone.MonthNarrows/10=N +FormatData/ro/standalone.MonthNarrows/11=D +FormatData/ro/standalone.MonthNarrows/12= +# commented out DayNarrows due to mostly undefined +#FormatData/ro/DayNarrows/0=D +#FormatData/ro/DayNarrows/1= +#FormatData/ro/DayNarrows/2= +#FormatData/ro/DayNarrows/3= +#FormatData/ro/DayNarrows/4= +#FormatData/ro/DayNarrows/5= +#FormatData/ro/DayNarrows/6= +FormatData/ro/standalone.DayNarrows/0=D +FormatData/ro/standalone.DayNarrows/1=L +FormatData/ro/standalone.DayNarrows/2=M +FormatData/ro/standalone.DayNarrows/3=M +FormatData/ro/standalone.DayNarrows/4=J +FormatData/ro/standalone.DayNarrows/5=V +FormatData/ro/standalone.DayNarrows/6=S + +FormatData/ru/DayNarrows/0=\u0412 +FormatData/ru/DayNarrows/1=\u041f\u043d +FormatData/ru/DayNarrows/2=\u0412\u0442 +FormatData/ru/DayNarrows/3=\u0421 +FormatData/ru/DayNarrows/4=\u0427 +FormatData/ru/DayNarrows/5=\u041f +# Note: "sat" is an contributed item in CLDR. +FormatData/ru/DayNarrows/6=\u0421 + +FormatData/ru/standalone.DayNarrows/0=\u0412 +FormatData/ru/standalone.DayNarrows/1=\u041f +FormatData/ru/standalone.DayNarrows/2=\u0412 +FormatData/ru/standalone.DayNarrows/3=\u0421 +FormatData/ru/standalone.DayNarrows/4=\u0427 +FormatData/ru/standalone.DayNarrows/5=\u041f +FormatData/ru/standalone.DayNarrows/6=\u0421 + +FormatData/sk/DayNarrows/0=N +FormatData/sk/DayNarrows/1=P +FormatData/sk/DayNarrows/2=U +FormatData/sk/DayNarrows/3=S +FormatData/sk/DayNarrows/4=\u0160 +FormatData/sk/DayNarrows/5=P +FormatData/sk/DayNarrows/6=S + +FormatData/sl/DayNarrows/0=n +FormatData/sl/DayNarrows/1=p +FormatData/sl/DayNarrows/2=t +FormatData/sl/DayNarrows/3=s +FormatData/sl/DayNarrows/4=\u010d +FormatData/sl/DayNarrows/5=p +FormatData/sl/DayNarrows/6=s + +FormatData/sq/DayNarrows/0=D +FormatData/sq/DayNarrows/1=H +FormatData/sq/DayNarrows/2=M +FormatData/sq/DayNarrows/3=M +FormatData/sq/DayNarrows/4=E +FormatData/sq/DayNarrows/5=P +FormatData/sq/DayNarrows/6=S + +FormatData/sr/DayNarrows/0=\u043d +FormatData/sr/DayNarrows/1=\u043f +FormatData/sr/DayNarrows/2=\u0443 +FormatData/sr/DayNarrows/3=\u0441 +FormatData/sr/DayNarrows/4=\u0447 +FormatData/sr/DayNarrows/5=\u043f +FormatData/sr/DayNarrows/6=\u0441 +FormatData/sr/short.Eras/0=\u043f. \u043d. \u0435. +FormatData/sr/short.Eras/1=\u043d. \u0435. +FormatData/sr/narrow.Eras/0=\u043f.\u043d.\u0435. +FormatData/sr/narrow.Eras/1=\u043d.\u0435. + +FormatData/sv/standalone.MonthNarrows/0=J +FormatData/sv/standalone.MonthNarrows/1=F +FormatData/sv/standalone.MonthNarrows/2=M +FormatData/sv/standalone.MonthNarrows/3=A +FormatData/sv/standalone.MonthNarrows/4=M +FormatData/sv/standalone.MonthNarrows/5=J +FormatData/sv/standalone.MonthNarrows/6=J +FormatData/sv/standalone.MonthNarrows/7=A +FormatData/sv/standalone.MonthNarrows/8=S +FormatData/sv/standalone.MonthNarrows/9=O +FormatData/sv/standalone.MonthNarrows/10=N +FormatData/sv/standalone.MonthNarrows/11=D +FormatData/sv/standalone.MonthNarrows/12= +FormatData/sv/DayNarrows/0=S +FormatData/sv/DayNarrows/1=M +FormatData/sv/DayNarrows/2=T +FormatData/sv/DayNarrows/3=O +FormatData/sv/DayNarrows/4=T +FormatData/sv/DayNarrows/5=F +FormatData/sv/DayNarrows/6=L +FormatData/sv/standalone.DayNarrows/0=S +FormatData/sv/standalone.DayNarrows/1=M +FormatData/sv/standalone.DayNarrows/2=T +FormatData/sv/standalone.DayNarrows/3=O +FormatData/sv/standalone.DayNarrows/4=T +FormatData/sv/standalone.DayNarrows/5=F +FormatData/sv/standalone.DayNarrows/6=L +FormatData/sv/narrow.Eras/0=f.Kr. +FormatData/sv/narrow.Eras/1=e.Kr. +FormatData/sv/narrow.AmPmMarkers/0=f +FormatData/sv/narrow.AmPmMarkers/1=e + +FormatData/th/standalone.MonthNarrows/0=\u0e21.\u0e04. +FormatData/th/standalone.MonthNarrows/1=\u0e01.\u0e1e. +FormatData/th/standalone.MonthNarrows/2=\u0e21\u0e35.\u0e04. +FormatData/th/standalone.MonthNarrows/3=\u0e40\u0e21.\u0e22. +FormatData/th/standalone.MonthNarrows/4=\u0e1e.\u0e04. +FormatData/th/standalone.MonthNarrows/5=\u0e21\u0e34.\u0e22. +FormatData/th/standalone.MonthNarrows/6=\u0e01.\u0e04. +FormatData/th/standalone.MonthNarrows/7=\u0e2a.\u0e04. +FormatData/th/standalone.MonthNarrows/8=\u0e01.\u0e22. +FormatData/th/standalone.MonthNarrows/9=\u0e15.\u0e04. +FormatData/th/standalone.MonthNarrows/10=\u0e1e.\u0e22. +FormatData/th/standalone.MonthNarrows/11=\u0e18.\u0e04. +FormatData/th/standalone.MonthNarrows/12= +FormatData/th/DayNarrows/0=\u0e2d +FormatData/th/DayNarrows/1=\u0e08 +FormatData/th/DayNarrows/2=\u0e2d +FormatData/th/DayNarrows/3=\u0e1e +FormatData/th/DayNarrows/4=\u0e1e +FormatData/th/DayNarrows/5=\u0e28 +FormatData/th/DayNarrows/6=\u0e2a +FormatData/th/narrow.Eras/0=\u0e01\u0e48\u0e2d\u0e19 \u0e04.\u0e28. +FormatData/th/narrow.Eras/1=\u0e04.\u0e28. + +FormatData/tr/standalone.MonthNarrows/0=O +FormatData/tr/standalone.MonthNarrows/1=\u015e +FormatData/tr/standalone.MonthNarrows/2=M +FormatData/tr/standalone.MonthNarrows/3=N +FormatData/tr/standalone.MonthNarrows/4=M +FormatData/tr/standalone.MonthNarrows/5=H +FormatData/tr/standalone.MonthNarrows/6=T +FormatData/tr/standalone.MonthNarrows/7=A +FormatData/tr/standalone.MonthNarrows/8=E +FormatData/tr/standalone.MonthNarrows/9=E +FormatData/tr/standalone.MonthNarrows/10=K +FormatData/tr/standalone.MonthNarrows/11=A +FormatData/tr/standalone.MonthNarrows/12= +FormatData/tr/DayNarrows/0=P +FormatData/tr/DayNarrows/1=P +FormatData/tr/DayNarrows/2=S +FormatData/tr/DayNarrows/3=\u00c7 +FormatData/tr/DayNarrows/4=P +FormatData/tr/DayNarrows/5=C +FormatData/tr/DayNarrows/6=C + +FormatData/uk/DayNarrows/0=\u041d +FormatData/uk/DayNarrows/1=\u041f +FormatData/uk/DayNarrows/2=\u0412 +FormatData/uk/DayNarrows/3=\u0421 +FormatData/uk/DayNarrows/4=\u0427 +FormatData/uk/DayNarrows/5=\u041f +FormatData/uk/DayNarrows/6=\u0421 + +FormatData/vi/DayNarrows/0=CN +FormatData/vi/DayNarrows/1=T2 +FormatData/vi/DayNarrows/2=T3 +FormatData/vi/DayNarrows/3=T4 +FormatData/vi/DayNarrows/4=T5 +FormatData/vi/DayNarrows/5=T6 +FormatData/vi/DayNarrows/6=T7 + +FormatData/zh/standalone.MonthNarrows/0=1\u6708 +FormatData/zh/standalone.MonthNarrows/1=2\u6708 +FormatData/zh/standalone.MonthNarrows/2=3\u6708 +FormatData/zh/standalone.MonthNarrows/3=4\u6708 +FormatData/zh/standalone.MonthNarrows/4=5\u6708 +FormatData/zh/standalone.MonthNarrows/5=6\u6708 +FormatData/zh/standalone.MonthNarrows/6=7\u6708 +FormatData/zh/standalone.MonthNarrows/7=8\u6708 +FormatData/zh/standalone.MonthNarrows/8=9\u6708 +FormatData/zh/standalone.MonthNarrows/9=10\u6708 +FormatData/zh/standalone.MonthNarrows/10=11\u6708 +FormatData/zh/standalone.MonthNarrows/11=12\u6708 +FormatData/zh/standalone.MonthNarrows/12= +FormatData/zh/DayNarrows/0=\u65e5 +FormatData/zh/DayNarrows/1=\u4e00 +FormatData/zh/DayNarrows/2=\u4e8c +FormatData/zh/DayNarrows/3=\u4e09 +FormatData/zh/DayNarrows/4=\u56db +FormatData/zh/DayNarrows/5=\u4e94 +FormatData/zh/DayNarrows/6=\u516d diff --git a/jdk/test/sun/text/resources/LocaleDataTest.java b/jdk/test/sun/text/resources/LocaleDataTest.java index 51bf527bce1..837a8aa411e 100644 --- a/jdk/test/sun/text/resources/LocaleDataTest.java +++ b/jdk/test/sun/text/resources/LocaleDataTest.java @@ -34,7 +34,7 @@ * 6509039 6609737 6610748 6645271 6507067 6873931 6450945 6645268 6646611 * 6645405 6650730 6910489 6573250 6870908 6585666 6716626 6914413 6916787 * 6919624 6998391 7019267 7020960 7025837 7020583 7036905 7066203 7101495 - * 7003124 7085757 7028073 7171028 7189611 + * 7003124 7085757 7028073 7171028 7189611 8000983 * @summary Verify locale data * */ diff --git a/jdk/test/tools/launcher/6842838/Test6842838.sh b/jdk/test/tools/launcher/6842838/Test6842838.sh index 6c6e9aa4ba7..b552152a9f3 100644 --- a/jdk/test/tools/launcher/6842838/Test6842838.sh +++ b/jdk/test/tools/launcher/6842838/Test6842838.sh @@ -68,8 +68,8 @@ if [ ! -x ${LIBUMEM} ]; then fi BADFILE=newbadjar.jar -${JAVA_EXE} -version -${JAVA_EXE} -cp ${TESTCLASSES} CreateBadJar ${BADFILE} "META-INF/MANIFEST.MF" +${JAVA_EXE} ${TESTVMOPTS} -version +${JAVA_EXE} ${TESTVMOPTS} -cp ${TESTCLASSES} CreateBadJar ${BADFILE} "META-INF/MANIFEST.MF" LD_PRELOAD=${LIBUMEM} ${JAVA_EXE} -jar ${BADFILE} > test.out 2>&1 grep "Invalid or corrupt jarfile" test.out diff --git a/jdk/test/tools/launcher/Arrrghs.java b/jdk/test/tools/launcher/Arrrghs.java index 364589f5ad0..9bf9f21b465 100644 --- a/jdk/test/tools/launcher/Arrrghs.java +++ b/jdk/test/tools/launcher/Arrrghs.java @@ -27,7 +27,7 @@ * 6894719 6968053 7151434 7146424 * @summary Argument parsing validation. * @compile -XDignore.symbol.file Arrrghs.java - * @run main Arrrghs + * @run main/othervm Arrrghs */ import java.io.BufferedReader; @@ -204,8 +204,7 @@ public class Arrrghs extends TestHelper { // exiting the process prematurely can terminate the stderr. scratchpad.add(javaCmd + " -version " + inArgs); File batFile = new File("atest.bat"); - java.nio.file.Files.deleteIfExists(batFile.toPath()); - createFile(batFile, scratchpad); + createAFile(batFile, scratchpad); TestResult tr = doExec(batFile.getName()); diff --git a/jdk/test/tools/launcher/MultipleJRE.sh b/jdk/test/tools/launcher/MultipleJRE.sh index 5c49d8bae7c..b1ef16f4062 100644 --- a/jdk/test/tools/launcher/MultipleJRE.sh +++ b/jdk/test/tools/launcher/MultipleJRE.sh @@ -49,8 +49,8 @@ then exit 1 fi -JAVAEXE="$TESTJAVA/bin/java" -JAVA="$TESTJAVA/bin/java -classpath $TESTCLASSES" +JAVAEXE="$TESTJAVA/bin/java ${TESTVMOPTS}" +JAVA="$TESTJAVA/bin/java ${TESTVMOPTS} -classpath $TESTCLASSES" JAR="$TESTJAVA/bin/jar" OS=`uname -s`; diff --git a/jdk/test/tools/launcher/TestHelper.java b/jdk/test/tools/launcher/TestHelper.java index e630dd5df54..0115f057142 100644 --- a/jdk/test/tools/launcher/TestHelper.java +++ b/jdk/test/tools/launcher/TestHelper.java @@ -358,6 +358,51 @@ public class TestHelper { Files.copy(src.toPath(), dst.toPath(), COPY_ATTRIBUTES, REPLACE_EXISTING); } + /** + * Attempt to create a file at the given location. If an IOException + * occurs then back off for a moment and try again. When a number of + * attempts fail, give up and throw an exception. + */ + void createAFile(File aFile, List contents) throws IOException { + IOException cause = null; + for (int attempts = 0; attempts < 10; attempts++) { + try { + Files.write(aFile.getAbsoluteFile().toPath(), contents, + Charset.defaultCharset(), CREATE, TRUNCATE_EXISTING, WRITE); + if (cause != null) { + /* + * report attempts and errors that were encountered + * for diagnostic purposes + */ + System.err.println("Created batch file " + + aFile + " in " + (attempts + 1) + + " attempts"); + System.err.println("Errors encountered: " + cause); + cause.printStackTrace(); + } + return; + } catch (IOException ioe) { + if (cause != null) { + // chain the exceptions so they all get reported for diagnostics + cause.addSuppressed(ioe); + } else { + cause = ioe; + } + } + + try { + Thread.sleep(500); + } catch (InterruptedException ie) { + if (cause != null) { + // cause should alway be non-null here + ie.addSuppressed(cause); + } + throw new RuntimeException("Interrupted while creating batch file", ie); + } + } + throw new RuntimeException("Unable to create batch file", cause); + } + static void createFile(File outFile, List content) throws IOException { Files.write(outFile.getAbsoluteFile().toPath(), content, Charset.defaultCharset(), CREATE_NEW); diff --git a/langtools/.hgtags b/langtools/.hgtags index eb96b88699e..90b0283d105 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -188,3 +188,5 @@ b47bb81ba962ef80bb6f0b863c33a0afcfb0b49e jdk8-b62 e6ee43b3e2473798b17a556e9f11eebe25ab81d4 jdk8-b64 5f2faba89cac665e365c05074064ffc934a495eb jdk8-b65 20230f8b0eef92a57043735fc2ca00fea7e510a0 jdk8-b66 +303b09787a69136cd2019f9edfed3f308572e9fc jdk8-b67 +014a6a11dfe5ddc23ec8c76bb42ac998dbf49acb jdk8-b68 diff --git a/langtools/src/share/classes/com/sun/source/tree/IntersectionTypeTree.java b/langtools/src/share/classes/com/sun/source/tree/IntersectionTypeTree.java new file mode 100644 index 00000000000..09404699dac --- /dev/null +++ b/langtools/src/share/classes/com/sun/source/tree/IntersectionTypeTree.java @@ -0,0 +1,39 @@ +/* + * 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. 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.source.tree; + +import java.util.List; + +/** + * A tree node for an intersection type in a cast expression. + * + * @author Maurizio Cimadamore + * + * @since 1.8 + */ +public interface IntersectionTypeTree extends Tree { + List getBounds(); +} diff --git a/langtools/src/share/classes/com/sun/source/tree/Tree.java b/langtools/src/share/classes/com/sun/source/tree/Tree.java index 4693b84b52b..6ede0373a79 100644 --- a/langtools/src/share/classes/com/sun/source/tree/Tree.java +++ b/langtools/src/share/classes/com/sun/source/tree/Tree.java @@ -246,6 +246,11 @@ public interface Tree { */ UNION_TYPE(UnionTypeTree.class), + /** + * Used for instances of {@link IntersectionTypeTree}. + */ + INTERSECTION_TYPE(IntersectionTypeTree.class), + /** * Used for instances of {@link TypeCastTree}. */ diff --git a/langtools/src/share/classes/com/sun/source/tree/TreeVisitor.java b/langtools/src/share/classes/com/sun/source/tree/TreeVisitor.java index dd3cfcbf699..40d311e3126 100644 --- a/langtools/src/share/classes/com/sun/source/tree/TreeVisitor.java +++ b/langtools/src/share/classes/com/sun/source/tree/TreeVisitor.java @@ -98,6 +98,7 @@ public interface TreeVisitor { R visitTry(TryTree node, P p); R visitParameterizedType(ParameterizedTypeTree node, P p); R visitUnionType(UnionTypeTree node, P p); + R visitIntersectionType(IntersectionTypeTree node, P p); R visitArrayType(ArrayTypeTree node, P p); R visitTypeCast(TypeCastTree node, P p); R visitPrimitiveType(PrimitiveTypeTree node, P p); diff --git a/langtools/src/share/classes/com/sun/source/util/SimpleTreeVisitor.java b/langtools/src/share/classes/com/sun/source/util/SimpleTreeVisitor.java index 04e69161b4e..2d9079748bc 100644 --- a/langtools/src/share/classes/com/sun/source/util/SimpleTreeVisitor.java +++ b/langtools/src/share/classes/com/sun/source/util/SimpleTreeVisitor.java @@ -240,6 +240,10 @@ public class SimpleTreeVisitor implements TreeVisitor { return defaultAction(node, p); } + public R visitIntersectionType(IntersectionTypeTree node, P p) { + return defaultAction(node, p); + } + public R visitTypeParameter(TypeParameterTree node, P p) { return defaultAction(node, p); } diff --git a/langtools/src/share/classes/com/sun/source/util/TreeScanner.java b/langtools/src/share/classes/com/sun/source/util/TreeScanner.java index 0fcdf825fd4..e3baf6b1d21 100644 --- a/langtools/src/share/classes/com/sun/source/util/TreeScanner.java +++ b/langtools/src/share/classes/com/sun/source/util/TreeScanner.java @@ -371,6 +371,10 @@ public class TreeScanner implements TreeVisitor { return scan(node.getTypeAlternatives(), p); } + public R visitIntersectionType(IntersectionTypeTree node, P p) { + return scan(node.getBounds(), p); + } + public R visitTypeParameter(TypeParameterTree node, P p) { R r = scan(node.getBounds(), p); return r; diff --git a/langtools/src/share/classes/com/sun/tools/classfile/Instruction.java b/langtools/src/share/classes/com/sun/tools/classfile/Instruction.java index aafb9861994..855cc781aa3 100644 --- a/langtools/src/share/classes/com/sun/tools/classfile/Instruction.java +++ b/langtools/src/share/classes/com/sun/tools/classfile/Instruction.java @@ -71,11 +71,16 @@ public class Instruction { SHORT(3), /** Wide opcode is not followed by any operands. */ WIDE_NO_OPERANDS(2), + /** Wide opcode is followed by a 2-byte index into the local variables array. */ + WIDE_LOCAL(4), /** Wide opcode is followed by a 2-byte index into the constant pool. */ WIDE_CPREF_W(4), /** Wide opcode is followed by a 2-byte index into the constant pool, * and a signed short value. */ WIDE_CPREF_W_SHORT(6), + /** Wide opcode is followed by a 2-byte reference to a local variable, + * and a signed short value. */ + WIDE_LOCAL_SHORT(6), /** Opcode was not recognized. */ UNKNOWN(1); @@ -101,7 +106,7 @@ public class Instruction { R visitConstantPoolRef(Instruction instr, int index, P p); /** See {@link Kind#CPREF_W_UBYTE}, {@link Kind#CPREF_W_UBYTE_ZERO}, {@link Kind#WIDE_CPREF_W_SHORT}. */ R visitConstantPoolRefAndValue(Instruction instr, int index, int value, P p); - /** See {@link Kind#LOCAL}. */ + /** See {@link Kind#LOCAL}, {@link Kind#WIDE_LOCAL}. */ R visitLocal(Instruction instr, int index, P p); /** See {@link Kind#LOCAL_BYTE}. */ R visitLocalAndValue(Instruction instr, int index, int value, P p); @@ -315,6 +320,9 @@ public class Instruction { case WIDE_NO_OPERANDS: return visitor.visitNoOperands(this, p); + case WIDE_LOCAL: + return visitor.visitLocal(this, getUnsignedShort(2), p); + case WIDE_CPREF_W: return visitor.visitConstantPoolRef(this, getUnsignedShort(2), p); @@ -322,6 +330,10 @@ public class Instruction { return visitor.visitConstantPoolRefAndValue( this, getUnsignedShort(2), getUnsignedByte(4), p); + case WIDE_LOCAL_SHORT: + return visitor.visitLocalAndValue( + this, getUnsignedShort(2), getShort(4), p); + case UNKNOWN: return visitor.visitUnknown(this, p); diff --git a/langtools/src/share/classes/com/sun/tools/classfile/Opcode.java b/langtools/src/share/classes/com/sun/tools/classfile/Opcode.java index 9f27645093e..f22bec8f003 100644 --- a/langtools/src/share/classes/com/sun/tools/classfile/Opcode.java +++ b/langtools/src/share/classes/com/sun/tools/classfile/Opcode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -246,18 +246,18 @@ public enum Opcode { // impdep 0xff: Picojava priv // wide opcodes - ILOAD_W(0xc415, WIDE_CPREF_W), - LLOAD_W(0xc416, WIDE_CPREF_W), - FLOAD_W(0xc417, WIDE_CPREF_W), - DLOAD_W(0xc418, WIDE_CPREF_W), - ALOAD_W(0xc419, WIDE_CPREF_W), - ISTORE_W(0xc436, WIDE_CPREF_W), - LSTORE_W(0xc437, WIDE_CPREF_W), - FSTORE_W(0xc438, WIDE_CPREF_W), - DSTORE_W(0xc439, WIDE_CPREF_W), - ASTORE_W(0xc43a, WIDE_CPREF_W), - IINC_W(0xc484, WIDE_CPREF_W_SHORT), - RET_W(0xc4a9, WIDE_CPREF_W), + ILOAD_W(0xc415, WIDE_LOCAL), + LLOAD_W(0xc416, WIDE_LOCAL), + FLOAD_W(0xc417, WIDE_LOCAL), + DLOAD_W(0xc418, WIDE_LOCAL), + ALOAD_W(0xc419, WIDE_LOCAL), + ISTORE_W(0xc436, WIDE_LOCAL), + LSTORE_W(0xc437, WIDE_LOCAL), + FSTORE_W(0xc438, WIDE_LOCAL), + DSTORE_W(0xc439, WIDE_LOCAL), + ASTORE_W(0xc43a, WIDE_LOCAL), + IINC_W(0xc484, WIDE_LOCAL_SHORT), + RET_W(0xc4a9, WIDE_LOCAL), // PicoJava nonpriv instructions LOAD_UBYTE(PICOJAVA, 0xfe00), @@ -448,10 +448,10 @@ public enum Opcode { } - private static Opcode[] stdOpcodes = new Opcode[256]; - private static Opcode[] wideOpcodes = new Opcode[256]; - private static Opcode[] nonPrivOpcodes = new Opcode[256]; - private static Opcode[] privOpcodes = new Opcode[256]; + private static final Opcode[] stdOpcodes = new Opcode[256]; + private static final Opcode[] wideOpcodes = new Opcode[256]; + private static final Opcode[] nonPrivOpcodes = new Opcode[256]; + private static final Opcode[] privOpcodes = new Opcode[256]; static { for (Opcode o: values()) getOpcodeBlock(o.opcode >> 8)[o.opcode & 0xff] = o; diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFileFactory.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFileFactory.java index dc5349c87bc..57db795ae16 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFileFactory.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFileFactory.java @@ -46,7 +46,7 @@ import com.sun.tools.doclets.internal.toolkit.Configuration; * @since 1.8 */ abstract class DocFileFactory { - private static Map factories = + private static final Map factories = new WeakHashMap(); /** diff --git a/langtools/src/share/classes/com/sun/tools/javac/Server.java b/langtools/src/share/classes/com/sun/tools/javac/Server.java index fcb2127138c..6fb48a9cf8e 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/Server.java +++ b/langtools/src/share/classes/com/sun/tools/javac/Server.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -49,7 +49,7 @@ class Server implements Runnable { private final OutputStream out; private final boolean isSocket; private static final JavaCompiler tool = ToolProvider.getSystemJavaCompiler(); - private static Logger logger = Logger.getLogger("com.sun.tools.javac"); + private static final Logger logger = Logger.getLogger("com.sun.tools.javac"); static class CwdFileManager extends ForwardingJavaFileManager { String cwd; CwdFileManager(JavaFileManager fileManager) { @@ -69,7 +69,7 @@ class Server implements Runnable { // } } // static CwdFileManager fm = new CwdFileManager(tool.getStandardFileManager()); - static StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null); + static final StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null); static { // Use the same file manager for all compilations. This will // cache jar files in the standard file manager. Use diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Annotations.java b/langtools/src/share/classes/com/sun/tools/javac/code/Annotations.java index 84d9108b5d3..29c88c9d90e 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Annotations.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Annotations.java @@ -74,12 +74,12 @@ public class Annotations { */ private List attributes = NOT_STARTED; /* - * The Symbol this Annotatios belong to + * The Symbol this Annotations belong to */ - private final Symbol s; + private final Symbol sym; - public Annotations(Symbol s) { - this.s = s; + public Annotations(Symbol sym) { + this.sym = sym; } public List getAttributes() { @@ -102,7 +102,7 @@ public class Annotations { } public void setAttributesWithCompletion(final Annotate.AnnotateRepeatedContext ctx) { - Assert.check(pendingCompletion() || (!isStarted() && s.kind == PCK)); + Assert.check(pendingCompletion() || (!isStarted() && sym.kind == PCK)); Map> annotated = ctx.annotated; boolean atLeastOneRepeated = false; @@ -111,7 +111,7 @@ public class Annotations { if (lb.size() == 1) { buf = buf.prepend(lb.first()); } else { // repeated - buf = buf.prepend(new Placeholder(lb.toList(), s)); + buf = buf.prepend(new Placeholder(lb.toList(), sym)); atLeastOneRepeated = true; } } @@ -141,7 +141,7 @@ public class Annotations { @Override public String toString() { - return "repeated annotation pass of: " + s + " in: " + s.owner; + return "repeated annotation pass of: " + sym + " in: " + sym.owner; } @Override @@ -253,7 +253,7 @@ public class Annotations { // Process repeated annotations Attribute.Compound validRepeated = - ctx.processRepeatedAnnotations(placeholder.getPlaceholderFor()); + ctx.processRepeatedAnnotations(placeholder.getPlaceholderFor(), sym); if (validRepeated != null) { // Check that the container isn't manually diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Flags.java b/langtools/src/share/classes/com/sun/tools/javac/code/Flags.java index 36b669b6337..bbaba526807 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Flags.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Flags.java @@ -307,7 +307,7 @@ public class Flags { } // Cache of modifier sets. - private static Map> modifierSets = + private static final Map> modifierSets = new java.util.concurrent.ConcurrentHashMap>(64); public static boolean isStatic(Symbol symbol) { @@ -356,7 +356,7 @@ public class Flags { VARARGS("varargs"), PACKAGE("package"); - String name; + private final String name; Flag(String name) { this.name = name; diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Kinds.java b/langtools/src/share/classes/com/sun/tools/javac/code/Kinds.java index 12d3703d1fd..08fbd1a57e4 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Kinds.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Kinds.java @@ -110,7 +110,7 @@ public class Kinds { INSTANCE_INIT("kindname.instance.init"), PACKAGE("kindname.package"); - private String name; + private final String name; KindName(String name) { this.name = name; diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Lint.java b/langtools/src/share/classes/com/sun/tools/javac/code/Lint.java index 88573c593ca..552b4eeb1d4 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Lint.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Lint.java @@ -28,11 +28,14 @@ package com.sun.tools.javac.code; import java.util.EnumSet; import java.util.HashMap; import java.util.Map; +import java.util.Set; +import javax.lang.model.element.Modifier; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.Options; import com.sun.tools.javac.util.Pair; + import static com.sun.tools.javac.code.Flags.*; @@ -95,7 +98,8 @@ public class Lint private final EnumSet values; private final EnumSet suppressedValues; - private static Map map = new HashMap(); + private static final Map map = + new java.util.concurrent.ConcurrentHashMap(20); protected Lint(Context context) { diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Source.java b/langtools/src/share/classes/com/sun/tools/javac/code/Source.java index afa1c437d0a..18ebdfe1124 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Source.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Source.java @@ -87,7 +87,7 @@ public enum Source { public final String name; - private static Map tab = new HashMap(); + private static final Map tab = new HashMap(); static { for (Source s : values()) { tab.put(s.name, s); @@ -215,6 +215,9 @@ public enum Source { public boolean allowRepeatedAnnotations() { return compareTo(JDK1_8) >= 0; } + public boolean allowIntersectionTypesInCast() { + return compareTo(JDK1_8) >= 0; + } public static SourceVersion toSourceVersion(Source source) { switch(source) { case JDK1_2: diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/TargetType.java b/langtools/src/share/classes/com/sun/tools/javac/code/TargetType.java index 573f6275ddd..45a90307f6e 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/TargetType.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/TargetType.java @@ -166,7 +166,7 @@ public enum TargetType { static final int MAXIMUM_TARGET_TYPE_VALUE = 0x22; private final int targetTypeValue; - private Set flags; + private final Set flags; TargetType(int targetTypeValue, TargetAttribute... attributes) { if (targetTypeValue < Byte.MIN_VALUE @@ -233,10 +233,10 @@ public enum TargetType { return this.targetTypeValue; } - private static TargetType[] targets = null; + private static final TargetType[] targets; - private static TargetType[] buildTargets() { - TargetType[] targets = new TargetType[MAXIMUM_TARGET_TYPE_VALUE + 1]; + static { + targets = new TargetType[MAXIMUM_TARGET_TYPE_VALUE + 1]; TargetType[] alltargets = values(); for (TargetType target : alltargets) { if (target.targetTypeValue >= 0) @@ -246,13 +246,9 @@ public enum TargetType { if (targets[i] == null) targets[i] = UNKNOWN; } - return targets; } public static boolean isValidTargetTypeValue(int tag) { - if (targets == null) - targets = buildTargets(); - if (((byte)tag) == ((byte)UNKNOWN.targetTypeValue)) return true; @@ -260,9 +256,6 @@ public enum TargetType { } public static TargetType fromTargetTypeValue(int tag) { - if (targets == null) - targets = buildTargets(); - if (((byte)tag) == ((byte)UNKNOWN.targetTypeValue)) return UNKNOWN; diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Type.java b/langtools/src/share/classes/com/sun/tools/javac/code/Type.java index f75bbf3e8b6..80aabeeb9ba 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Type.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Type.java @@ -839,6 +839,49 @@ public class Type implements PrimitiveType { } } + // a clone of a ClassType that knows about the bounds of an intersection type. + public static class IntersectionClassType extends ClassType implements IntersectionType { + + public boolean allInterfaces; + + public enum IntersectionKind { + EXPLICIT, + IMPLICT; + } + + public IntersectionKind intersectionKind; + + public IntersectionClassType(List bounds, ClassSymbol csym, boolean allInterfaces) { + super(Type.noType, List.nil(), csym); + this.allInterfaces = allInterfaces; + Assert.check((csym.flags() & COMPOUND) != 0); + supertype_field = bounds.head; + interfaces_field = bounds.tail; + Assert.check(supertype_field.tsym.completer != null || + !supertype_field.isInterface(), supertype_field); + } + + public java.util.List getBounds() { + return Collections.unmodifiableList(getComponents()); + } + + public List getComponents() { + return interfaces_field.prepend(supertype_field); + } + + @Override + public TypeKind getKind() { + return TypeKind.INTERSECTION; + } + + @Override + public R accept(TypeVisitor v, P p) { + return intersectionKind == IntersectionKind.EXPLICIT ? + v.visitIntersection(this, p) : + v.visitDeclared(this, p); + } + } + public static class ArrayType extends Type implements javax.lang.model.type.ArrayType { diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/TypeTag.java b/langtools/src/share/classes/com/sun/tools/javac/code/TypeTag.java index da6affeec42..d786621e918 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/TypeTag.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/TypeTag.java @@ -135,9 +135,11 @@ public enum TypeTag { /** This field will only be used for tags related with numeric types for * optimization reasons. */ - private int order = 0; + private final int order; - private TypeTag() {} + private TypeTag() { + this(0); + } private TypeTag(int order) { this.order = order; diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java index 22063dcbf16..88882955b4f 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java @@ -26,7 +26,13 @@ package com.sun.tools.javac.code; import java.lang.ref.SoftReference; -import java.util.*; +import java.util.Comparator; +import java.util.HashSet; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.WeakHashMap; import com.sun.tools.javac.code.Attribute.RetentionPolicy; import com.sun.tools.javac.code.Lint.LintCategory; @@ -382,28 +388,6 @@ public class Types { } } - /** - * Scope filter used to skip methods that should be ignored during - * function interface conversion (such as methods overridden by - * j.l.Object) - */ - class DescriptorFilter implements Filter { - - TypeSymbol origin; - - DescriptorFilter(TypeSymbol origin) { - this.origin = origin; - } - - @Override - public boolean accepts(Symbol sym) { - return sym.kind == Kinds.MTH && - (sym.flags() & (ABSTRACT | DEFAULT)) == ABSTRACT && - !overridesObjectMethod(origin, sym) && - (interfaceCandidates(origin.type, (MethodSymbol)sym).head.flags() & DEFAULT) == 0; - } - }; - /** * Compute the function descriptor associated with a given functional interface */ @@ -431,23 +415,8 @@ public class Types { throw failure("not.a.functional.intf.1", diags.fragment("no.abstracts", Kinds.kindName(origin), origin)); } else if (abstracts.size() == 1) { - if (abstracts.first().type.tag == FORALL) { - throw failure("invalid.generic.desc.in.functional.intf", - abstracts.first(), - Kinds.kindName(origin), - origin); - } else { - return new FunctionDescriptor(abstracts.first()); - } + return new FunctionDescriptor(abstracts.first()); } else { // size > 1 - for (Symbol msym : abstracts) { - if (msym.type.tag == FORALL) { - throw failure("invalid.generic.desc.in.functional.intf", - abstracts.first(), - Kinds.kindName(origin), - origin); - } - } FunctionDescriptor descRes = mergeDescriptors(origin, abstracts.toList()); if (descRes == null) { //we can get here if the functional interface is ill-formed @@ -586,6 +555,85 @@ public class Types { } // + /** + * Scope filter used to skip methods that should be ignored (such as methods + * overridden by j.l.Object) during function interface conversion/marker interface checks + */ + class DescriptorFilter implements Filter { + + TypeSymbol origin; + + DescriptorFilter(TypeSymbol origin) { + this.origin = origin; + } + + @Override + public boolean accepts(Symbol sym) { + return sym.kind == Kinds.MTH && + (sym.flags() & (ABSTRACT | DEFAULT)) == ABSTRACT && + !overridesObjectMethod(origin, sym) && + (interfaceCandidates(origin.type, (MethodSymbol)sym).head.flags() & DEFAULT) == 0; + } + }; + + // + + /** + * A cache that keeps track of marker interfaces + */ + class MarkerCache { + + private WeakHashMap _map = new WeakHashMap(); + + class Entry { + final boolean isMarkerIntf; + final int prevMark; + + public Entry(boolean isMarkerIntf, + int prevMark) { + this.isMarkerIntf = isMarkerIntf; + this.prevMark = prevMark; + } + + boolean matches(int mark) { + return this.prevMark == mark; + } + } + + boolean get(TypeSymbol origin) throws FunctionDescriptorLookupError { + Entry e = _map.get(origin); + CompoundScope members = membersClosure(origin.type, false); + if (e == null || + !e.matches(members.getMark())) { + boolean isMarkerIntf = isMarkerInterfaceInternal(origin, members); + _map.put(origin, new Entry(isMarkerIntf, members.getMark())); + return isMarkerIntf; + } + else { + return e.isMarkerIntf; + } + } + + /** + * Is given symbol a marker interface + */ + public boolean isMarkerInterfaceInternal(TypeSymbol origin, CompoundScope membersCache) throws FunctionDescriptorLookupError { + return !origin.isInterface() ? + false : + !membersCache.getElements(new DescriptorFilter(origin)).iterator().hasNext(); + } + } + + private MarkerCache markerCache = new MarkerCache(); + + /** + * Is given type a marker interface? + */ + public boolean isMarkerInterface(Type site) { + return markerCache.get(site.tsym); + } + // + // /** * Is t an unchecked subtype of s? @@ -1964,45 +2012,28 @@ public class Types { * @param supertype is objectType if all bounds are interfaces, * null otherwise. */ - public Type makeCompoundType(List bounds, - Type supertype) { + public Type makeCompoundType(List bounds) { + return makeCompoundType(bounds, bounds.head.tsym.isInterface()); + } + public Type makeCompoundType(List bounds, boolean allInterfaces) { + Assert.check(bounds.nonEmpty()); + Type firstExplicitBound = bounds.head; + if (allInterfaces) { + bounds = bounds.prepend(syms.objectType); + } ClassSymbol bc = new ClassSymbol(ABSTRACT|PUBLIC|SYNTHETIC|COMPOUND|ACYCLIC, Type.moreInfo ? names.fromString(bounds.toString()) : names.empty, + null, syms.noSymbol); - if (bounds.head.tag == TYPEVAR) - // error condition, recover - bc.erasure_field = syms.objectType; - else - bc.erasure_field = erasure(bounds.head); - bc.members_field = new Scope(bc); - ClassType bt = (ClassType)bc.type; - bt.allparams_field = List.nil(); - if (supertype != null) { - bt.supertype_field = supertype; - bt.interfaces_field = bounds; - } else { - bt.supertype_field = bounds.head; - bt.interfaces_field = bounds.tail; - } - Assert.check(bt.supertype_field.tsym.completer != null - || !bt.supertype_field.isInterface(), - bt.supertype_field); - return bt; - } - - /** - * Same as {@link #makeCompoundType(List,Type)}, except that the - * second parameter is computed directly. Note that this might - * cause a symbol completion. Hence, this version of - * makeCompoundType may not be called during a classfile read. - */ - public Type makeCompoundType(List bounds) { - Type supertype = (bounds.head.tsym.flags() & INTERFACE) != 0 ? - supertype(bounds.head) : null; - return makeCompoundType(bounds, supertype); + bc.type = new IntersectionClassType(bounds, bc, allInterfaces); + bc.erasure_field = (bounds.head.tag == TYPEVAR) ? + syms.objectType : // error condition, recover + erasure(firstExplicitBound); + bc.members_field = new Scope(bc); + return bc.type; } /** @@ -2192,12 +2223,8 @@ public class Types { * @param supertype is objectType if all bounds are interfaces, * null otherwise. */ - public void setBounds(TypeVar t, List bounds, Type supertype) { - if (bounds.tail.isEmpty()) - t.bound = bounds.head; - else - t.bound = makeCompoundType(bounds, supertype); - t.rank_field = -1; + public void setBounds(TypeVar t, List bounds) { + setBounds(t, bounds, bounds.head.tsym.isInterface()); } /** @@ -2209,10 +2236,10 @@ public class Types { * Note that this check might cause a symbol completion. Hence, this version of * setBounds may not be called during a classfile read. */ - public void setBounds(TypeVar t, List bounds) { - Type supertype = (bounds.head.tsym.flags() & INTERFACE) != 0 ? - syms.objectType : null; - setBounds(t, bounds, supertype); + public void setBounds(TypeVar t, List bounds, boolean allInterfaces) { + t.bound = bounds.tail.isEmpty() ? + bounds.head : + makeCompoundType(bounds, allInterfaces); t.rank_field = -1; } // @@ -2222,7 +2249,7 @@ public class Types { * Return list of bounds of the given type variable. */ public List getBounds(TypeVar t) { - if (t.bound.hasTag(NONE)) + if (t.bound.hasTag(NONE)) return List.nil(); else if (t.bound.isErroneous() || !t.bound.isCompound()) return List.of(t.bound); @@ -2822,7 +2849,7 @@ public class Types { } return tvars1; } - static private Mapping newInstanceFun = new Mapping("newInstanceFun") { + private static final Mapping newInstanceFun = new Mapping("newInstanceFun") { public Type apply(Type t) { return new TypeVar(t.tsym, t.getUpperBound(), t.getLowerBound()); } }; // @@ -3321,8 +3348,7 @@ public class Types { if (arraySuperType == null) { // JLS 10.8: all arrays implement Cloneable and Serializable. arraySuperType = makeCompoundType(List.of(syms.serializableType, - syms.cloneableType), - syms.objectType); + syms.cloneableType), true); } } } diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java index cc3ea1e2f96..ab5d49c3166 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java @@ -26,7 +26,6 @@ package com.sun.tools.javac.comp; import java.util.Map; - import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.code.*; @@ -171,8 +170,8 @@ public class Annotate { * @param repeatingAnnotations a List of repeating annotations * @return a new Attribute.Compound that is the container for the repeatingAnnotations */ - public Attribute.Compound processRepeatedAnnotations(List repeatingAnnotations) { - return Annotate.this.processRepeatedAnnotations(repeatingAnnotations, this); + public Attribute.Compound processRepeatedAnnotations(List repeatingAnnotations, Symbol sym) { + return Annotate.this.processRepeatedAnnotations(repeatingAnnotations, this, sym); } /** @@ -339,10 +338,11 @@ public class Annotate { * annotation are invalid. This method reports errors/warnings. */ private Attribute.Compound processRepeatedAnnotations(List annotations, - AnnotateRepeatedContext ctx) { + AnnotateRepeatedContext ctx, + Symbol on) { Attribute.Compound firstOccurrence = annotations.head; List repeated = List.nil(); - Type origAnnoType; + Type origAnnoType = null; Type arrayOfOrigAnnoType = null; Type targetContainerType = null; MethodSymbol containerValueSymbol = null; @@ -390,6 +390,13 @@ public class Annotate { new Attribute.Array(arrayOfOrigAnnoType, repeated)); annoTree = m.Annotation(new Attribute.Compound(targetContainerType, List.of(p))); + + if (!chk.annotationApplicable(annoTree, on)) + log.error(annoTree.pos(), "invalid.containedby.annotation.incompatible.target", targetContainerType, origAnnoType); + + if (!chk.validateAnnotationDeferErrors(annoTree)) + log.error(annoTree.pos(), "duplicate.annotation.invalid.repeated", origAnnoType); + Attribute.Compound c = enterAnnotation(annoTree, targetContainerType, ctx.env); @@ -410,7 +417,7 @@ public class Annotate { // annotation's declaration, or null if it has none Attribute.Compound ca = origAnnoDecl.attribute(syms.containedByType.tsym); if (ca == null) { // has no ContainedBy annotation - log.error(pos, "duplicate.annotation.missing.container", origAnnoType); + log.error(pos, "duplicate.annotation.missing.container", origAnnoType, syms.containedByType); return null; } diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java index 0d743da7be4..23fe35ec421 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java @@ -716,21 +716,8 @@ public class Attr extends JCTree.Visitor { } a.tsym.flags_field &= ~UNATTRIBUTED; } - for (JCTypeParameter tvar : typarams) + for (JCTypeParameter tvar : typarams) { chk.checkNonCyclic(tvar.pos(), (TypeVar)tvar.type); - attribStats(typarams, env); - } - - void attribBounds(List typarams) { - for (JCTypeParameter typaram : typarams) { - Type bound = typaram.type.getUpperBound(); - if (bound != null && bound.tsym instanceof ClassSymbol) { - ClassSymbol c = (ClassSymbol)bound.tsym; - if ((c.flags_field & COMPOUND) != 0) { - Assert.check((c.flags_field & UNATTRIBUTED) != 0, c); - attribClass(typaram.pos(), c); - } - } } } @@ -892,7 +879,12 @@ public class Attr extends JCTree.Visitor { deferredLintHandler.flush(tree.pos()); chk.checkDeprecatedAnnotation(tree.pos(), m); - attribBounds(tree.typarams); + // Create a new environment with local scope + // for attributing the method. + Env localEnv = memberEnter.methodEnv(tree, env); + localEnv.info.lint = lint; + + attribStats(tree.typarams, localEnv); // If we override any other methods, check that we do so properly. // JLS ??? @@ -903,12 +895,6 @@ public class Attr extends JCTree.Visitor { } chk.checkOverride(tree, m); - // Create a new environment with local scope - // for attributing the method. - Env localEnv = memberEnter.methodEnv(tree, env); - - localEnv.info.lint = lint; - if (isDefaultMethod && types.overridesObjectMethod(m.enclClass(), m)) { log.error(tree, "default.overrides.object.member", m.name, Kinds.kindName(m.location()), m.location()); } @@ -2196,7 +2182,7 @@ public class Attr extends JCTree.Visitor { Type target; Type lambdaType; if (pt() != Type.recoveryType) { - target = infer.instantiateFunctionalInterface(that, pt(), explicitParamTypes, resultInfo.checkContext); + target = infer.instantiateFunctionalInterface(that, checkIntersectionTarget(that, resultInfo), explicitParamTypes, resultInfo.checkContext); lambdaType = types.findDescriptorType(target); chk.checkFunctionalInterface(that, target); } else { @@ -2204,6 +2190,14 @@ public class Attr extends JCTree.Visitor { lambdaType = fallbackDescriptorType(that); } + if (lambdaType.hasTag(FORALL)) { + //lambda expression target desc cannot be a generic method + resultInfo.checkContext.report(that, diags.fragment("invalid.generic.lambda.target", + lambdaType, kindName(target.tsym), target.tsym)); + result = that.type = types.createErrorType(pt()); + return; + } + if (!TreeInfo.isExplicitLambda(that)) { //add param type info in the AST List actuals = lambdaType.getParameterTypes(); @@ -2244,9 +2238,13 @@ public class Attr extends JCTree.Visitor { //with the target-type, it will be recovered anyway in Attr.checkId needsRecovery = false; + FunctionalReturnContext funcContext = that.getBodyKind() == JCLambda.BodyKind.EXPRESSION ? + new ExpressionLambdaReturnContext((JCExpression)that.getBody(), resultInfo.checkContext) : + new FunctionalReturnContext(resultInfo.checkContext); + ResultInfo bodyResultInfo = lambdaType.getReturnType() == Type.recoveryType ? recoveryInfo : - new ResultInfo(VAL, lambdaType.getReturnType(), new LambdaReturnContext(resultInfo.checkContext)); + new ResultInfo(VAL, lambdaType.getReturnType(), funcContext); localEnv.info.returnResult = bodyResultInfo; if (that.getBodyKind() == JCLambda.BodyKind.EXPRESSION) { @@ -2282,6 +2280,26 @@ public class Attr extends JCTree.Visitor { } } } + + private Type checkIntersectionTarget(DiagnosticPosition pos, ResultInfo resultInfo) { + Type pt = resultInfo.pt; + if (pt != Type.recoveryType && pt.isCompound()) { + IntersectionClassType ict = (IntersectionClassType)pt; + List bounds = ict.allInterfaces ? + ict.getComponents().tail : + ict.getComponents(); + types.findDescriptorType(bounds.head); //propagate exception outwards! + for (Type bound : bounds.tail) { + if (!types.isMarkerInterface(bound)) { + resultInfo.checkContext.report(pos, diags.fragment("secondary.bound.must.be.marker.intf", bound)); + } + } + //for now (translation doesn't support intersection types) + return bounds.head; + } else { + return pt; + } + } //where private Type fallbackDescriptorType(JCExpression tree) { switch (tree.getTag()) { @@ -2327,8 +2345,9 @@ public class Attr extends JCTree.Visitor { * type according to both the inherited context and the assignment * context. */ - class LambdaReturnContext extends Check.NestedCheckContext { - public LambdaReturnContext(CheckContext enclosingContext) { + class FunctionalReturnContext extends Check.NestedCheckContext { + + FunctionalReturnContext(CheckContext enclosingContext) { super(enclosingContext); } @@ -2344,6 +2363,23 @@ public class Attr extends JCTree.Visitor { } } + class ExpressionLambdaReturnContext extends FunctionalReturnContext { + + JCExpression expr; + + ExpressionLambdaReturnContext(JCExpression expr, CheckContext enclosingContext) { + super(enclosingContext); + this.expr = expr; + } + + @Override + public boolean compatible(Type found, Type req, Warner warn) { + //a void return is compatible with an expression statement lambda + return TreeInfo.isExpressionStatement(expr) && req.hasTag(VOID) || + super.compatible(found, req, warn); + } + } + /** * Lambda compatibility. Check that given return types, thrown types, parameter types * are compatible with the expected functional interface descriptor. This means that: @@ -2428,7 +2464,7 @@ public class Attr extends JCTree.Visitor { } //attrib type-arguments - List typeargtypes = null; + List typeargtypes = List.nil(); if (that.typeargs != null) { typeargtypes = attribTypes(that.typeargs, localEnv); } @@ -2436,7 +2472,7 @@ public class Attr extends JCTree.Visitor { Type target; Type desc; if (pt() != Type.recoveryType) { - target = infer.instantiateFunctionalInterface(that, pt(), null, resultInfo.checkContext); + target = infer.instantiateFunctionalInterface(that, checkIntersectionTarget(that, resultInfo), null, resultInfo.checkContext); desc = types.findDescriptorType(target); chk.checkFunctionalInterface(that, target); } else { @@ -2498,6 +2534,26 @@ public class Attr extends JCTree.Visitor { } } + if (resultInfo.checkContext.deferredAttrContext().mode == AttrMode.CHECK) { + if (refSym.isStatic() && TreeInfo.isStaticSelector(that.expr, names) && + exprType.getTypeArguments().nonEmpty()) { + //static ref with class type-args + log.error(that.expr.pos(), "invalid.mref", Kinds.kindName(that.getMode()), + diags.fragment("static.mref.with.targs")); + result = that.type = types.createErrorType(target); + return; + } + + if (refSym.isStatic() && !TreeInfo.isStaticSelector(that.expr, names) && + !lookupHelper.referenceKind(refSym).isUnbound()) { + //no static bound mrefs + log.error(that.expr.pos(), "invalid.mref", Kinds.kindName(that.getMode()), + diags.fragment("static.bound.mref")); + result = that.type = types.createErrorType(target); + return; + } + } + if (desc.getReturnType() == Type.recoveryType) { // stop here result = that.type = target; @@ -2560,7 +2616,7 @@ public class Attr extends JCTree.Visitor { if (!returnType.hasTag(VOID) && !resType.hasTag(VOID)) { if (resType.isErroneous() || - new LambdaReturnContext(checkContext).compatible(resType, returnType, types.noWarnings)) { + new FunctionalReturnContext(checkContext).compatible(resType, returnType, types.noWarnings)) { incompatibleReturnType = null; } } @@ -3525,63 +3581,79 @@ public class Attr extends JCTree.Visitor { tree.type = result = t; } - public void visitTypeParameter(JCTypeParameter tree) { - TypeVar a = (TypeVar)tree.type; + public void visitTypeIntersection(JCTypeIntersection tree) { + attribTypes(tree.bounds, env); + tree.type = result = checkIntersection(tree, tree.bounds); + } + + public void visitTypeParameter(JCTypeParameter tree) { + TypeVar typeVar = (TypeVar)tree.type; + if (!typeVar.bound.isErroneous()) { + //fixup type-parameter bound computed in 'attribTypeVariables' + typeVar.bound = checkIntersection(tree, tree.bounds); + } + } + + Type checkIntersection(JCTree tree, List bounds) { Set boundSet = new HashSet(); - if (a.bound.isErroneous()) - return; - List bs = types.getBounds(a); - if (tree.bounds.nonEmpty()) { + if (bounds.nonEmpty()) { // accept class or interface or typevar as first bound. - Type b = checkBase(bs.head, tree.bounds.head, env, false, false, false); - boundSet.add(types.erasure(b)); - if (b.isErroneous()) { - a.bound = b; + bounds.head.type = checkBase(bounds.head.type, bounds.head, env, false, false, false); + boundSet.add(types.erasure(bounds.head.type)); + if (bounds.head.type.isErroneous()) { + return bounds.head.type; } - else if (b.hasTag(TYPEVAR)) { + else if (bounds.head.type.hasTag(TYPEVAR)) { // if first bound was a typevar, do not accept further bounds. - if (tree.bounds.tail.nonEmpty()) { - log.error(tree.bounds.tail.head.pos(), + if (bounds.tail.nonEmpty()) { + log.error(bounds.tail.head.pos(), "type.var.may.not.be.followed.by.other.bounds"); - tree.bounds = List.of(tree.bounds.head); - a.bound = bs.head; + return bounds.head.type; } } else { // if first bound was a class or interface, accept only interfaces // as further bounds. - for (JCExpression bound : tree.bounds.tail) { - bs = bs.tail; - Type i = checkBase(bs.head, bound, env, false, true, false); - if (i.isErroneous()) - a.bound = i; - else if (i.hasTag(CLASS)) - chk.checkNotRepeated(bound.pos(), types.erasure(i), boundSet); + for (JCExpression bound : bounds.tail) { + bound.type = checkBase(bound.type, bound, env, false, true, false); + if (bound.type.isErroneous()) { + bounds = List.of(bound); + } + else if (bound.type.hasTag(CLASS)) { + chk.checkNotRepeated(bound.pos(), types.erasure(bound.type), boundSet); + } } } } - bs = types.getBounds(a); - // in case of multiple bounds ... - if (bs.length() > 1) { + if (bounds.length() == 0) { + return syms.objectType; + } else if (bounds.length() == 1) { + return bounds.head.type; + } else { + Type owntype = types.makeCompoundType(TreeInfo.types(bounds)); + if (tree.hasTag(TYPEINTERSECTION)) { + ((IntersectionClassType)owntype).intersectionKind = + IntersectionClassType.IntersectionKind.EXPLICIT; + } // ... the variable's bound is a class type flagged COMPOUND // (see comment for TypeVar.bound). // In this case, generate a class tree that represents the // bound class, ... JCExpression extending; List implementing; - if ((bs.head.tsym.flags() & INTERFACE) == 0) { - extending = tree.bounds.head; - implementing = tree.bounds.tail; + if (!bounds.head.type.isInterface()) { + extending = bounds.head; + implementing = bounds.tail; } else { extending = null; - implementing = tree.bounds; + implementing = bounds; } - JCClassDecl cd = make.at(tree.pos).ClassDef( + JCClassDecl cd = make.at(tree).ClassDef( make.Modifiers(PUBLIC | ABSTRACT), - tree.name, List.nil(), + names.empty, List.nil(), extending, implementing, List.nil()); - ClassSymbol c = (ClassSymbol)a.getUpperBound().tsym; + ClassSymbol c = (ClassSymbol)owntype.tsym; Assert.check((c.flags() & COMPOUND) != 0); cd.sym = c; c.sourcefile = env.toplevel.sourcefile; @@ -3590,10 +3662,11 @@ public class Attr extends JCTree.Visitor { c.flags_field |= UNATTRIBUTED; Env cenv = enter.classEnv(cd, env); enter.typeEnvs.put(c, cenv); + attribClass(c); + return owntype; } } - public void visitWildcard(JCWildcard tree) { //- System.err.println("visitWildcard("+tree+");");//DEBUG Type type = (tree.kind.kind == BoundKind.UNBOUND) @@ -3747,7 +3820,7 @@ public class Attr extends JCTree.Visitor { chk.validateAnnotations(tree.mods.annotations, c); // Validate type parameters, supertype and interfaces. - attribBounds(tree.typarams); + attribStats(tree.typarams, env); if (!c.isAnonymous()) { //already checked if anonymous chk.validate(tree.typarams, env); diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java index 78ba105984f..7db55b62c02 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java @@ -1833,13 +1833,15 @@ public class Check { for (Scope.Entry e1 = t1.tsym.members().elems; e1 != null; e1 = e1.sibling) { Symbol s1 = e1.sym; Type st1 = null; - if (s1.kind != MTH || !s1.isInheritedIn(site.tsym, types)) continue; + if (s1.kind != MTH || !s1.isInheritedIn(site.tsym, types) || + (s1.flags() & SYNTHETIC) != 0) continue; Symbol impl = ((MethodSymbol)s1).implementation(site.tsym, types, false); if (impl != null && (impl.flags() & ABSTRACT) == 0) continue; for (Scope.Entry e2 = t2.tsym.members().lookup(s1.name); e2.scope != null; e2 = e2.next()) { Symbol s2 = e2.sym; if (s1 == s2) continue; - if (s2.kind != MTH || !s2.isInheritedIn(site.tsym, types)) continue; + if (s2.kind != MTH || !s2.isInheritedIn(site.tsym, types) || + (s2.flags() & SYNTHETIC) != 0) continue; if (st1 == null) st1 = types.memberType(t1, s1); Type st2 = types.memberType(t2, s2); if (types.overrideEquivalent(st1, st2)) { @@ -2890,39 +2892,54 @@ public class Check { } /** Check an annotation value. + * + * @param a The annotation tree to check + * @return true if this annotation tree is valid, otherwise false */ - public void validateAnnotation(JCAnnotation a) { - // collect an inventory of the members (sorted alphabetically) - Set members = new TreeSet(new Comparator() { - public int compare(Symbol t, Symbol t1) { - return t.name.compareTo(t1.name); - } - }); + public boolean validateAnnotationDeferErrors(JCAnnotation a) { + boolean res = false; + final Log.DiagnosticHandler diagHandler = new Log.DiscardDiagnosticHandler(log); + try { + res = validateAnnotation(a); + } finally { + log.popDiagnosticHandler(diagHandler); + } + return res; + } + + private boolean validateAnnotation(JCAnnotation a) { + boolean isValid = true; + // collect an inventory of the annotation elements + Set members = new LinkedHashSet(); for (Scope.Entry e = a.annotationType.type.tsym.members().elems; e != null; e = e.sibling) if (e.sym.kind == MTH) members.add((MethodSymbol) e.sym); - // count them off as they're annotated + // remove the ones that are assigned values for (JCTree arg : a.args) { if (!arg.hasTag(ASSIGN)) continue; // recovery JCAssign assign = (JCAssign) arg; Symbol m = TreeInfo.symbol(assign.lhs); if (m == null || m.type.isErroneous()) continue; - if (!members.remove(m)) + if (!members.remove(m)) { + isValid = false; log.error(assign.lhs.pos(), "duplicate.annotation.member.value", m.name, a.type); + } } // all the remaining ones better have default values - ListBuffer missingDefaults = ListBuffer.lb(); + List missingDefaults = List.nil(); for (MethodSymbol m : members) { if (m.defaultValue == null && !m.type.isErroneous()) { - missingDefaults.append(m.name); + missingDefaults = missingDefaults.append(m.name); } } + missingDefaults = missingDefaults.reverse(); if (missingDefaults.nonEmpty()) { + isValid = false; String key = (missingDefaults.size() > 1) ? "annotation.missing.default.value.1" : "annotation.missing.default.value"; @@ -2933,21 +2950,23 @@ public class Check { // repeated values in its value member if (a.annotationType.type.tsym != syms.annotationTargetType.tsym || a.args.tail == null) - return; + return isValid; - if (!a.args.head.hasTag(ASSIGN)) return; // error recovery + if (!a.args.head.hasTag(ASSIGN)) return false; // error recovery JCAssign assign = (JCAssign) a.args.head; Symbol m = TreeInfo.symbol(assign.lhs); - if (m.name != names.value) return; + if (m.name != names.value) return false; JCTree rhs = assign.rhs; - if (!rhs.hasTag(NEWARRAY)) return; + if (!rhs.hasTag(NEWARRAY)) return false; JCNewArray na = (JCNewArray) rhs; Set targets = new HashSet(); for (JCTree elem : na.elems) { if (!targets.add(TreeInfo.symbol(elem))) { + isValid = false; log.error(elem.pos(), "repeated.annotation.target"); } } + return isValid; } void checkDeprecatedAnnotation(DiagnosticPosition pos, Symbol s) { diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/ConstFold.java b/langtools/src/share/classes/com/sun/tools/javac/comp/ConstFold.java index a0f9ec1b04b..2b6003ff0c4 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/ConstFold.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/ConstFold.java @@ -62,9 +62,9 @@ strictfp class ConstFold { syms = Symtab.instance(context); } - static Integer minusOne = -1; - static Integer zero = 0; - static Integer one = 1; + static final Integer minusOne = -1; + static final Integer zero = 0; + static final Integer one = 1; /** Convert boolean to integer (true = 1, false = 0). */ diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java index d0afb484158..21863e7f075 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java @@ -246,8 +246,8 @@ public class Flow { */ SPECULATIVE_LOOP("var.might.be.assigned.in.loop", true); - String errKey; - boolean isFinal; + final String errKey; + final boolean isFinal; FlowKind(String errKey, boolean isFinal) { this.errKey = errKey; @@ -295,7 +295,7 @@ public class Flow { } }; - JCTree.Tag treeTag; + final JCTree.Tag treeTag; private JumpKind(Tag treeTag) { this.treeTag = treeTag; diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java b/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java index a4cf5cea3ff..c737c2c36c7 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java @@ -288,21 +288,20 @@ public class LambdaToMethod extends TreeTranslator { JCExpression init; switch(tree.kind) { - case IMPLICIT_INNER: /** Inner # new */ - case SUPER: /** super # instMethod */ + case IMPLICIT_INNER: /** Inner :: new */ + case SUPER: /** super :: instMethod */ init = makeThis( localContext.owner.owner.asType(), localContext.owner); break; - case BOUND: /** Expr # instMethod */ + case BOUND: /** Expr :: instMethod */ init = tree.getQualifierExpression(); break; - case STATIC_EVAL: /** Expr # staticMethod */ - case UNBOUND: /** Type # instMethod */ - case STATIC: /** Type # staticMethod */ - case TOPLEVEL: /** Top level # new */ + case UNBOUND: /** Type :: instMethod */ + case STATIC: /** Type :: staticMethod */ + case TOPLEVEL: /** Top level :: new */ init = null; break; @@ -315,14 +314,6 @@ public class LambdaToMethod extends TreeTranslator { //build a sam instance using an indy call to the meta-factory result = makeMetaFactoryIndyCall(tree, tree.targetType, localContext.referenceKind(), refSym, indy_args); - - //if we had a static reference with non-static qualifier, add a let - //expression to force the evaluation of the qualifier expr - if (tree.hasKind(ReferenceKind.STATIC_EVAL)) { - VarSymbol rec = new VarSymbol(0, names.fromString("rec$"), tree.getQualifierExpression().type, localContext.owner); - JCVariableDecl recDef = make.VarDef(rec, tree.getQualifierExpression()); - result = make.LetExpr(recDef, result).setType(tree.type); - } } /** diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java index 828e7fbbe1f..4005a25887a 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java @@ -138,6 +138,10 @@ public class Lower extends TreeTranslator { */ Map classdefs; + /** A hash table mapping local classes to a list of pruned trees. + */ + public Map> prunedTree = new WeakHashMap>(); + /** A hash table mapping virtual accessed symbols in outer subclasses * to the actually referred symbol in superclasses. */ @@ -1039,6 +1043,12 @@ public class Lower extends TreeTranslator { } } + private void addPrunedInfo(JCTree tree) { + List infoList = prunedTree.get(currentClass); + infoList = (infoList == null) ? List.of(tree) : infoList.prepend(tree); + prunedTree.put(currentClass, infoList); + } + /** Ensure that identifier is accessible, return tree accessing the identifier. * @param sym The accessed symbol. * @param tree The tree referring to the symbol. @@ -1111,7 +1121,10 @@ public class Lower extends TreeTranslator { // Constants are replaced by their constant value. if (sym.kind == VAR) { Object cv = ((VarSymbol)sym).getConstValue(); - if (cv != null) return makeLit(sym.type, cv); + if (cv != null) { + addPrunedInfo(tree); + return makeLit(sym.type, cv); + } } // Private variables and methods are replaced by calls @@ -2746,12 +2759,15 @@ public class Lower extends TreeTranslator { /** Visitor method for conditional expressions. */ + @Override public void visitConditional(JCConditional tree) { JCTree cond = tree.cond = translate(tree.cond, syms.booleanType); if (cond.type.isTrue()) { result = convert(translate(tree.truepart, tree.type), tree.type); + addPrunedInfo(cond); } else if (cond.type.isFalse()) { result = convert(translate(tree.falsepart, tree.type), tree.type); + addPrunedInfo(cond); } else { // Condition is not a compile-time constant. tree.truepart = translate(tree.truepart, tree.type); @@ -2760,14 +2776,14 @@ public class Lower extends TreeTranslator { } } //where - private JCTree convert(JCTree tree, Type pt) { - if (tree.type == pt || tree.type.hasTag(BOT)) - return tree; - JCTree result = make_at(tree.pos()).TypeCast(make.Type(pt), (JCExpression)tree); - result.type = (tree.type.constValue() != null) ? cfolder.coerce(tree.type, pt) - : pt; - return result; - } + private JCTree convert(JCTree tree, Type pt) { + if (tree.type == pt || tree.type.hasTag(BOT)) + return tree; + JCTree result = make_at(tree.pos()).TypeCast(make.Type(pt), (JCExpression)tree); + result.type = (tree.type.constValue() != null) ? cfolder.coerce(tree.type, pt) + : pt; + return result; + } /** Visitor method for if statements. */ @@ -2775,12 +2791,14 @@ public class Lower extends TreeTranslator { JCTree cond = tree.cond = translate(tree.cond, syms.booleanType); if (cond.type.isTrue()) { result = translate(tree.thenpart); + addPrunedInfo(cond); } else if (cond.type.isFalse()) { if (tree.elsepart != null) { result = translate(tree.elsepart); } else { result = make.Skip(); } + addPrunedInfo(cond); } else { // Condition is not a compile-time constant. tree.thenpart = translate(tree.thenpart); diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java index 5ca35ca7e69..5617d6ea351 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java @@ -156,7 +156,7 @@ public class Resolve { OBJECT_INIT("object-init"), INTERNAL("internal"); - String opt; + final String opt; private VerboseResolutionMode(String opt) { this.opt = opt; @@ -2617,8 +2617,7 @@ public class Resolve { @Override ReferenceKind referenceKind(Symbol sym) { if (sym.isStatic()) { - return TreeInfo.isStaticSelector(referenceTree.expr, names) ? - ReferenceKind.STATIC : ReferenceKind.STATIC_EVAL; + return ReferenceKind.STATIC; } else { Name selName = TreeInfo.name(referenceTree.getQualifierExpression()); return selName != null && selName == names._super ? @@ -3382,8 +3381,8 @@ public class Resolve { } }; - boolean isBoxingRequired; - boolean isVarargsRequired; + final boolean isBoxingRequired; + final boolean isVarargsRequired; MethodResolutionPhase(boolean isBoxingRequired, boolean isVarargsRequired) { this.isBoxingRequired = isBoxingRequired; diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java b/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java index 8b1b7f54c9a..76ca8f68ea2 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java @@ -551,6 +551,7 @@ public class TransTypes extends TreeTranslator { tree.body = translate(tree.body, null); //save non-erased target tree.targetType = tree.type; + Assert.check(!tree.targetType.isCompound(), "Intersection-type targets not supported yet!"); tree.type = erasure(tree.type); result = tree; } @@ -786,6 +787,7 @@ public class TransTypes extends TreeTranslator { tree.expr = translate(tree.expr, null); //save non-erased target tree.targetType = tree.type; + Assert.check(!tree.targetType.isCompound(), "Intersection-type targets not supported yet!"); tree.type = erasure(tree.type); result = tree; } @@ -803,6 +805,12 @@ public class TransTypes extends TreeTranslator { result = clazz; } + public void visitTypeIntersection(JCTypeIntersection tree) { + tree.bounds = translate(tree.bounds, null); + tree.type = erasure(tree.type); + result = tree; + } + /************************************************************************** * utility methods *************************************************************************/ diff --git a/langtools/src/share/classes/com/sun/tools/javac/file/ZipFileIndex.java b/langtools/src/share/classes/com/sun/tools/javac/file/ZipFileIndex.java index dbb9f68a91f..e5c66ae8c20 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/file/ZipFileIndex.java +++ b/langtools/src/share/classes/com/sun/tools/javac/file/ZipFileIndex.java @@ -83,7 +83,7 @@ public class ZipFileIndex { public final static long NOT_MODIFIED = Long.MIN_VALUE; - private static boolean NON_BATCH_MODE = System.getProperty("nonBatchMode") != null;// TODO: Use -XD compiler switch for this. + private static final boolean NON_BATCH_MODE = System.getProperty("nonBatchMode") != null;// TODO: Use -XD compiler switch for this. private Map directories = Collections.emptyMap(); diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java index 43c65db98b2..13e02848737 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java @@ -846,17 +846,17 @@ public class ClassReader implements Completer { tvar = (TypeVar)findTypeVar(name); } List bounds = List.nil(); - Type st = null; + boolean allInterfaces = false; if (signature[sigp] == ':' && signature[sigp+1] == ':') { sigp++; - st = syms.objectType; + allInterfaces = true; } while (signature[sigp] == ':') { sigp++; bounds = bounds.prepend(sigToType()); } if (!sigEnterPhase) { - types.setBounds(tvar, bounds.reverse(), st); + types.setBounds(tvar, bounds.reverse(), allInterfaces); } return tvar; } @@ -1360,6 +1360,16 @@ public class ClassReader implements Completer { void attachAnnotationDefault(final Symbol sym) { final MethodSymbol meth = (MethodSymbol)sym; // only on methods final Attribute value = readAttributeValue(); + + // The default value is set later during annotation. It might + // be the case that the Symbol sym is annotated _after_ the + // repeating instances that depend on this default value, + // because of this we set an interim value that tells us this + // element (most likely) has a default. + // + // Set interim value for now, reset just before we do this + // properly at annotate time. + meth.defaultValue = value; annotate.normal(new AnnotationDefaultCompleter(meth, value)); } @@ -1680,6 +1690,9 @@ public class ClassReader implements Completer { public void enterAnnotation() { JavaFileObject previousClassFile = currentClassFile; try { + // Reset the interim value set earlier in + // attachAnnotationDefault(). + sym.defaultValue = null; currentClassFile = classFile; sym.defaultValue = deproxy(sym.type.getReturnType(), value); } finally { diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java index 59788f2a1d5..8e33e1d92da 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java @@ -1545,10 +1545,10 @@ public class Code { public void compressCatchTable() { ListBuffer compressedCatchInfo = ListBuffer.lb(); List handlerPcs = List.nil(); - for (char[] catchEntry : catchInfo.elems) { + for (char[] catchEntry : catchInfo) { handlerPcs = handlerPcs.prepend((int)catchEntry[2]); } - for (char[] catchEntry : catchInfo.elems) { + for (char[] catchEntry : catchInfo) { int startpc = catchEntry[0]; int endpc = catchEntry[1]; if (startpc == endpc || @@ -1825,7 +1825,7 @@ public class Code { } } - static Type jsrReturnValue = new Type(INT, null); + static final Type jsrReturnValue = new Type(INT, null); /* ************************************************************************** diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java index 4bbab1eb709..d54208b5723 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java @@ -71,6 +71,7 @@ public class Gen extends JCTree.Visitor { private final Map stringBufferAppend; private Name accessDollar; private final Types types; + private final Lower lower; /** Switch: GJ mode? */ @@ -112,6 +113,7 @@ public class Gen extends JCTree.Visitor { stringBufferAppend = new HashMap(); accessDollar = names. fromString("access" + target.syntheticNameChar()); + lower = Lower.instance(context); Options options = Options.instance(context); lineDebugInfo = @@ -816,6 +818,62 @@ public class Gen extends JCTree.Visitor { } } + /** Visitor class for expressions which might be constant expressions. + * This class is a subset of TreeScanner. Intended to visit trees pruned by + * Lower as long as constant expressions looking for references to any + * ClassSymbol. Any such reference will be added to the constant pool so + * automated tools can detect class dependencies better. + */ + class ClassReferenceVisitor extends JCTree.Visitor { + + @Override + public void visitTree(JCTree tree) {} + + @Override + public void visitBinary(JCBinary tree) { + tree.lhs.accept(this); + tree.rhs.accept(this); + } + + @Override + public void visitSelect(JCFieldAccess tree) { + if (tree.selected.type.hasTag(CLASS)) { + makeRef(tree.selected.pos(), tree.selected.type); + } + } + + @Override + public void visitIdent(JCIdent tree) { + if (tree.sym.owner instanceof ClassSymbol) { + pool.put(tree.sym.owner); + } + } + + @Override + public void visitConditional(JCConditional tree) { + tree.cond.accept(this); + tree.truepart.accept(this); + tree.falsepart.accept(this); + } + + @Override + public void visitUnary(JCUnary tree) { + tree.arg.accept(this); + } + + @Override + public void visitParens(JCParens tree) { + tree.expr.accept(this); + } + + @Override + public void visitTypeCast(JCTypeCast tree) { + tree.expr.accept(this); + } + } + + private ClassReferenceVisitor classReferenceVisitor = new ClassReferenceVisitor(); + /** Visitor method: generate code for an expression, catching and reporting * any completion failures. * @param tree The expression to be visited. @@ -826,6 +884,7 @@ public class Gen extends JCTree.Visitor { try { if (tree.type.constValue() != null) { // Short circuit any expressions which are constants + tree.accept(classReferenceVisitor); checkStringConstant(tree.pos(), tree.type.constValue()); result = items.makeImmediateItem(tree.type, tree.type.constValue()); } else { @@ -2205,6 +2264,15 @@ public class Gen extends JCTree.Visitor { code.endScopes(limit); } + private void generateReferencesToPrunedTree(ClassSymbol classSymbol, Pool pool) { + List prunedInfo = lower.prunedTree.get(classSymbol); + if (prunedInfo != null) { + for (JCTree prunedTree: prunedInfo) { + prunedTree.accept(classReferenceVisitor); + } + } + } + /* ************************************************************************ * main method *************************************************************************/ @@ -2232,6 +2300,7 @@ public class Gen extends JCTree.Visitor { cdef.defs = normalizeDefs(cdef.defs, c); c.pool = pool; pool.reset(); + generateReferencesToPrunedTree(c, pool); Env localEnv = new Env(cdef, new GenContext()); localEnv.toplevel = env.toplevel; diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/Target.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/Target.java index f6432b864a0..8323a05deed 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Target.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Target.java @@ -86,17 +86,15 @@ public enum Target { return instance; } - private static Target MIN; + private static final Target MIN = values()[0]; public static Target MIN() { return MIN; } - private static Target MAX; + private static final Target MAX = values()[values().length - 1]; public static Target MAX() { return MAX; } - private static Map tab = new HashMap(); + private static final Map tab = new HashMap(); static { for (Target t : values()) { - if (MIN == null) MIN = t; - MAX = t; tab.put(t.name, t); } tab.put("5", JDK1_5); diff --git a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java index 3181727e45a..c2fb0dfb780 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java +++ b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java @@ -189,7 +189,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter { } } - private static CompilePolicy DEFAULT_COMPILE_POLICY = CompilePolicy.BY_TODO; + private static final CompilePolicy DEFAULT_COMPILE_POLICY = CompilePolicy.BY_TODO; protected static enum ImplicitSourcePolicy { /** Don't generate or process implicitly read source files. */ @@ -543,7 +543,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter { public static CompileState max(CompileState a, CompileState b) { return a.value > b.value ? a : b; } - private int value; + private final int value; }; /** Partial map to record which compiler phases have been executed * for each compilation unit. Used for ATTR and FLOW phases. diff --git a/langtools/src/share/classes/com/sun/tools/javac/main/Option.java b/langtools/src/share/classes/com/sun/tools/javac/main/Option.java index 8a44ac4345c..70e5901848a 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/main/Option.java +++ b/langtools/src/share/classes/com/sun/tools/javac/main/Option.java @@ -167,7 +167,6 @@ public enum Option { ENCODING("-encoding", "opt.arg.encoding", "opt.encoding", STANDARD, FILEMANAGER) { @Override public boolean process(OptionHelper helper, String option, String operand) { -// System.err.println("process encoding " + operand); return super.process(helper, option, operand); } @@ -246,9 +245,7 @@ public enum Option { } }, - A("-A", "opt.arg.key.equals.value", "opt.A", STANDARD, BASIC) { - { hasSuffix = true; } - + A("-A", "opt.arg.key.equals.value", "opt.A", STANDARD, BASIC, true) { @Override public boolean matches(String arg) { return arg.startsWith("-A"); @@ -293,8 +290,6 @@ public enum Option { // This option exists only for the purpose of documenting itself. // It's actually implemented by the launcher. J("-J", "opt.arg.flag", "opt.J", STANDARD, INFO) { - { hasSuffix = true; } - @Override public boolean process(OptionHelper helper, String option) { throw new AssertionError @@ -302,10 +297,6 @@ public enum Option { } }, - // stop after parsing and attributing. - // new HiddenOption("-attrparseonly"), - - // new Option("-moreinfo", "opt.moreinfo") { MOREINFO("-moreinfo", null, HIDDEN, BASIC) { @Override public boolean process(OptionHelper helper, String option) { @@ -317,23 +308,6 @@ public enum Option { // treat warnings as errors WERROR("-Werror", "opt.Werror", STANDARD, BASIC), -// // use complex inference from context in the position of a method call argument -// COMPLEXINFERENCE("-complexinference", null, HIDDEN, BASIC), - - // generare source stubs - // new HiddenOption("-stubs"), - - // relax some constraints to allow compiling from stubs - // new HiddenOption("-relax"), - - // output source after translating away inner classes - // new Option("-printflat", "opt.printflat"), - // new HiddenOption("-printflat"), - - // display scope search details - // new Option("-printsearch", "opt.printsearch"), - // new HiddenOption("-printsearch"), - // prompt after each error // new Option("-prompt", "opt.prompt"), PROMPT("-prompt", null, HIDDEN, BASIC), @@ -342,13 +316,8 @@ public enum Option { DOE("-doe", null, HIDDEN, BASIC), // output source after type erasure - // new Option("-s", "opt.s"), PRINTSOURCE("-printsource", null, HIDDEN, BASIC), - // output shrouded class files - // new Option("-scramble", "opt.scramble"), - // new Option("-scrambleall", "opt.scrambleall"), - // display warnings for generic unchecked operations WARNUNCHECKED("-warnunchecked", null, HIDDEN, BASIC) { @Override @@ -408,18 +377,16 @@ public enum Option { * -XDx sets the option x to the value x. */ XD("-XD", null, HIDDEN, BASIC) { - String s; @Override public boolean matches(String s) { - this.s = s; return s.startsWith(text); } @Override public boolean process(OptionHelper helper, String option) { - s = s.substring(text.length()); - int eq = s.indexOf('='); - String key = (eq < 0) ? s : s.substring(0, eq); - String value = (eq < 0) ? s : s.substring(eq+1); + option = option.substring(text.length()); + int eq = option.indexOf('='); + String key = (eq < 0) ? option : option.substring(0, eq); + String value = (eq < 0) ? option : option.substring(eq+1); helper.put(key, value); return false; } @@ -428,8 +395,6 @@ public enum Option { // This option exists only for the purpose of documenting itself. // It's actually implemented by the CommandLine class. AT("@", "opt.arg.file", "opt.AT", STANDARD, INFO) { - { hasSuffix = true; } - @Override public boolean process(OptionHelper helper, String option) { throw new AssertionError("the @ flag should be caught by CommandLine."); @@ -445,17 +410,15 @@ public enum Option { * name to a separate list. */ SOURCEFILE("sourcefile", null, HIDDEN, INFO) { - String s; @Override public boolean matches(String s) { - this.s = s; return s.endsWith(".java") // Java source file || SourceVersion.isName(s); // Legal type name } @Override public boolean process(OptionHelper helper, String option) { - if (s.endsWith(".java") ) { - File f = new File(s); + if (option.endsWith(".java") ) { + File f = new File(option); if (!f.exists()) { helper.error("err.file.not.found", f); return true; @@ -465,9 +428,9 @@ public enum Option { return true; } helper.addFile(f); + } else { + helper.addClassName(option); } - else - helper.addClassName(s); return false; } }; @@ -521,7 +484,7 @@ public enum Option { /** Suffix option (-foo=bar or -foo:bar) */ - boolean hasSuffix; + final boolean hasSuffix; /** The kind of choices for this option, if any. */ @@ -535,24 +498,30 @@ public enum Option { Option(String text, String descrKey, OptionKind kind, OptionGroup group) { - this(text, null, descrKey, kind, group, null, null); + this(text, null, descrKey, kind, group, null, null, false); } Option(String text, String argsNameKey, String descrKey, OptionKind kind, OptionGroup group) { - this(text, argsNameKey, descrKey, kind, group, null, null); + this(text, argsNameKey, descrKey, kind, group, null, null, false); + } + + Option(String text, String argsNameKey, String descrKey, + OptionKind kind, OptionGroup group, boolean doHasSuffix) { + this(text, argsNameKey, descrKey, kind, group, null, null, doHasSuffix); } Option(String text, String descrKey, OptionKind kind, OptionGroup group, ChoiceKind choiceKind, Map choices) { - this(text, null, descrKey, kind, group, choiceKind, choices); + this(text, null, descrKey, kind, group, choiceKind, choices, false); } Option(String text, String descrKey, OptionKind kind, OptionGroup group, ChoiceKind choiceKind, String... choices) { - this(text, null, descrKey, kind, group, choiceKind, createChoices(choices)); + this(text, null, descrKey, kind, group, choiceKind, + createChoices(choices), false); } // where private static Map createChoices(String... choices) { @@ -564,7 +533,8 @@ public enum Option { private Option(String text, String argsNameKey, String descrKey, OptionKind kind, OptionGroup group, - ChoiceKind choiceKind, Map choices) { + ChoiceKind choiceKind, Map choices, + boolean doHasSuffix) { this.text = text; this.argsNameKey = argsNameKey; this.descrKey = descrKey; @@ -573,7 +543,7 @@ public enum Option { this.choiceKind = choiceKind; this.choices = choices; char lastChar = text.charAt(text.length()-1); - hasSuffix = lastChar == ':' || lastChar == '='; + this.hasSuffix = doHasSuffix || lastChar == ':' || lastChar == '='; } public String getText() { diff --git a/langtools/src/share/classes/com/sun/tools/javac/model/JavacTypes.java b/langtools/src/share/classes/com/sun/tools/javac/model/JavacTypes.java index 88406c3fdf1..40a36019214 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/model/JavacTypes.java +++ b/langtools/src/share/classes/com/sun/tools/javac/model/JavacTypes.java @@ -74,6 +74,7 @@ public class JavacTypes implements javax.lang.model.util.Types { public Element asElement(TypeMirror t) { switch (t.getKind()) { case DECLARED: + case INTERSECTION: case ERROR: case TYPEVAR: Type type = cast(Type.class, t); diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java b/langtools/src/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java index 2048c1cd48a..2c77a712901 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java @@ -44,7 +44,7 @@ import static com.sun.tools.javac.util.LayoutCharacters.*; */ public class JavaTokenizer { - private static boolean scannerDebug = false; + private static final boolean scannerDebug = false; /** Allow hex floating-point literals. */ @@ -348,8 +348,8 @@ public class JavaTokenizer { private void scanIdent() { boolean isJavaIdentifierPart; char high; + reader.putChar(true); do { - reader.putChar(true); switch (reader.ch) { case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': @@ -366,6 +366,7 @@ public class JavaTokenizer { case '$': case '_': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': + break; case '\u0000': case '\u0001': case '\u0002': case '\u0003': case '\u0004': case '\u0005': case '\u0006': case '\u0007': case '\u0008': case '\u000E': case '\u000F': case '\u0010': @@ -373,26 +374,33 @@ public class JavaTokenizer { case '\u0015': case '\u0016': case '\u0017': case '\u0018': case '\u0019': case '\u001B': case '\u007F': - break; + reader.scanChar(); + continue; case '\u001A': // EOI is also a legal identifier part if (reader.bp >= reader.buflen) { name = reader.name(); tk = tokens.lookupKind(name); return; } - break; + reader.scanChar(); + continue; default: if (reader.ch < '\u0080') { // all ASCII range chars already handled, above isJavaIdentifierPart = false; } else { - high = reader.scanSurrogates(); - if (high != 0) { - reader.putChar(high); - isJavaIdentifierPart = Character.isJavaIdentifierPart( - Character.toCodePoint(high, reader.ch)); + if (Character.isIdentifierIgnorable(reader.ch)) { + reader.scanChar(); + continue; } else { - isJavaIdentifierPart = Character.isJavaIdentifierPart(reader.ch); + high = reader.scanSurrogates(); + if (high != 0) { + reader.putChar(high); + isJavaIdentifierPart = Character.isJavaIdentifierPart( + Character.toCodePoint(high, reader.ch)); + } else { + isJavaIdentifierPart = Character.isJavaIdentifierPart(reader.ch); + } } } if (!isJavaIdentifierPart) { @@ -401,6 +409,7 @@ public class JavaTokenizer { return; } } + reader.putChar(true); } while (true); } diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java index 35fa62915bb..28f6d8a29eb 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java @@ -124,6 +124,9 @@ public class JavacParser implements Parser { this.allowLambda = source.allowLambda(); this.allowMethodReferences = source.allowMethodReferences(); this.allowDefaultMethods = source.allowDefaultMethods(); + this.allowIntersectionTypesInCast = + source.allowIntersectionTypesInCast() && + fac.options.isSet("allowIntersectionTypes"); this.keepDocComments = keepDocComments; docComments = newDocCommentTable(keepDocComments, fac); this.keepLineMap = keepLineMap; @@ -197,6 +200,10 @@ public class JavacParser implements Parser { */ boolean allowDefaultMethods; + /** Switch: should we allow intersection types in cast? + */ + boolean allowIntersectionTypesInCast; + /** Switch: should we keep docComments? */ boolean keepDocComments; @@ -239,22 +246,38 @@ public class JavacParser implements Parser { } protected boolean peekToken(TokenKind tk) { - return S.token(1).kind == tk; + return peekToken(0, tk); + } + + protected boolean peekToken(int lookahead, TokenKind tk) { + return S.token(lookahead + 1).kind == tk; } protected boolean peekToken(TokenKind tk1, TokenKind tk2) { - return S.token(1).kind == tk1 && - S.token(2).kind == tk2; + return peekToken(0, tk1, tk2); + } + + protected boolean peekToken(int lookahead, TokenKind tk1, TokenKind tk2) { + return S.token(lookahead + 1).kind == tk1 && + S.token(lookahead + 2).kind == tk2; } protected boolean peekToken(TokenKind tk1, TokenKind tk2, TokenKind tk3) { - return S.token(1).kind == tk1 && - S.token(2).kind == tk2 && - S.token(3).kind == tk3; + return peekToken(0, tk1, tk2, tk3); + } + + protected boolean peekToken(int lookahead, TokenKind tk1, TokenKind tk2, TokenKind tk3) { + return S.token(lookahead + 1).kind == tk1 && + S.token(lookahead + 2).kind == tk2 && + S.token(lookahead + 3).kind == tk3; } protected boolean peekToken(TokenKind... kinds) { - for (int lookahead = 0 ; lookahead < kinds.length ; lookahead++) { + return peekToken(0, kinds); + } + + protected boolean peekToken(int lookahead, TokenKind... kinds) { + for (; lookahead < kinds.length ; lookahead++) { if (S.token(lookahead + 1).kind != kinds[lookahead]) { return false; } @@ -795,9 +818,7 @@ public class JavacParser implements Parser { * | "*" | "/" | "%" */ JCExpression term2Rest(JCExpression t, int minprec) { - List savedOd = odStackSupply.elems; JCExpression[] odStack = newOdStack(); - List savedOp = opStackSupply.elems; Token[] opStack = newOpStack(); // optimization, was odStack = new Tree[...]; opStack = new Tree[...]; @@ -828,8 +849,8 @@ public class JavacParser implements Parser { } } - odStackSupply.elems = savedOd; // optimization - opStackSupply.elems = savedOp; // optimization + odStackSupply.add(odStack); + opStackSupply.add(opStack); return t; } //where @@ -883,23 +904,19 @@ public class JavacParser implements Parser { /** optimization: To save allocating a new operand/operator stack * for every binary operation, we use supplys. */ - ListBuffer odStackSupply = new ListBuffer(); - ListBuffer opStackSupply = new ListBuffer(); + ArrayList odStackSupply = new ArrayList(); + ArrayList opStackSupply = new ArrayList(); private JCExpression[] newOdStack() { - if (odStackSupply.elems == odStackSupply.last) - odStackSupply.append(new JCExpression[infixPrecedenceLevels + 1]); - JCExpression[] odStack = odStackSupply.elems.head; - odStackSupply.elems = odStackSupply.elems.tail; - return odStack; + if (odStackSupply.isEmpty()) + return new JCExpression[infixPrecedenceLevels + 1]; + return odStackSupply.remove(odStackSupply.size() - 1); } private Token[] newOpStack() { - if (opStackSupply.elems == opStackSupply.last) - opStackSupply.append(new Token[infixPrecedenceLevels + 1]); - Token[] opStack = opStackSupply.elems.head; - opStackSupply.elems = opStackSupply.elems.tail; - return opStack; + if (opStackSupply.isEmpty()) + return new Token[infixPrecedenceLevels + 1]; + return opStackSupply.remove(opStackSupply.size() - 1); } /** @@ -966,102 +983,40 @@ public class JavacParser implements Parser { break; case LPAREN: if (typeArgs == null && (mode & EXPR) != 0) { - if (peekToken(MONKEYS_AT) || - peekToken(FINAL) || - peekToken(RPAREN) || - peekToken(IDENTIFIER, COMMA) || - peekToken(IDENTIFIER, RPAREN, ARROW)) { - //implicit n-ary lambda - t = lambdaExpressionOrStatement(true, peekToken(MONKEYS_AT) || peekToken(FINAL), pos); - break; - } else { - nextToken(); - mode = EXPR | TYPE | NOPARAMS; - t = term3(); - if ((mode & TYPE) != 0 && token.kind == LT) { - // Could be a cast to a parameterized type - JCTree.Tag op = JCTree.Tag.LT; - int pos1 = token.pos; - nextToken(); - mode &= (EXPR | TYPE); - mode |= TYPEARG; - JCExpression t1 = term3(); - if ((mode & TYPE) != 0 && - (token.kind == COMMA || token.kind == GT)) { - mode = TYPE; - ListBuffer args = new ListBuffer(); - args.append(t1); - while (token.kind == COMMA) { - nextToken(); - args.append(typeArgument()); - } - accept(GT); - t = toP(F.at(pos1).TypeApply(t, args.toList())); - checkGenerics(); - mode = EXPR | TYPE; //could be a lambda or a method ref or a cast to a type - t = term3Rest(t, typeArgs); - if (token.kind == IDENTIFIER || token.kind == ELLIPSIS) { - //explicit lambda (w/ generic type) - mode = EXPR; - JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER); - if (token.kind == ELLIPSIS) { - mods.flags = Flags.VARARGS; - t = to(F.at(token.pos).TypeArray(t)); - nextToken(); - } - t = lambdaExpressionOrStatement(variableDeclaratorId(mods, t), pos); - break; - } - } else if ((mode & EXPR) != 0) { - mode = EXPR; - JCExpression e = term2Rest(t1, TreeInfo.shiftPrec); - t = F.at(pos1).Binary(op, t, e); - t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec))); - } else { - accept(GT); - } - } else if ((mode & TYPE) != 0 && - (token.kind == IDENTIFIER || token.kind == ELLIPSIS)) { - //explicit lambda (w/ non-generic type) - mode = EXPR; - JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER); - if (token.kind == ELLIPSIS) { - mods.flags = Flags.VARARGS; - t = to(F.at(token.pos).TypeArray(t)); - nextToken(); - } - t = lambdaExpressionOrStatement(variableDeclaratorId(mods, t), pos); + ParensResult pres = analyzeParens(); + switch (pres) { + case CAST: + accept(LPAREN); + mode = TYPE; + int pos1 = pos; + List targets = List.of(t = term3()); + while (token.kind == AMP) { + checkIntersectionTypesInCast(); + accept(AMP); + targets = targets.prepend(term3()); + } + if (targets.length() > 1) { + t = toP(F.at(pos1).TypeIntersection(targets.reverse())); + } + accept(RPAREN); + mode = EXPR; + JCExpression t1 = term3(); + return F.at(pos).TypeCast(t, t1); + case IMPLICIT_LAMBDA: + case EXPLICIT_LAMBDA: + t = lambdaExpressionOrStatement(true, pres == ParensResult.EXPLICIT_LAMBDA, pos); + break; + default: //PARENS + accept(LPAREN); + mode = EXPR; + t = termRest(term1Rest(term2Rest(term3(), TreeInfo.orPrec))); + accept(RPAREN); + t = toP(F.at(pos).Parens(t)); break; - } else { - t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec))); - } - } - - accept(RPAREN); - lastmode = mode; - mode = EXPR; - if ((lastmode & EXPR) == 0) { - JCExpression t1 = term3(); - return F.at(pos).TypeCast(t, t1); - } else if ((lastmode & TYPE) != 0) { - switch (token.kind) { - /*case PLUSPLUS: case SUBSUB: */ - case BANG: case TILDE: - case LPAREN: case THIS: case SUPER: - case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: - case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL: - case TRUE: case FALSE: case NULL: - case NEW: case IDENTIFIER: case ASSERT: case ENUM: - case BYTE: case SHORT: case CHAR: case INT: - case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID: - JCExpression t1 = term3(); - return F.at(pos).TypeCast(t, t1); - } } } else { return illegal(); } - t = toP(F.at(pos).Parens(t)); break; case THIS: if ((mode & EXPR) != 0) { @@ -1346,6 +1301,138 @@ public class JavacParser implements Parser { } } + /** + * If we see an identifier followed by a '<' it could be an unbound + * method reference or a binary expression. To disambiguate, look for a + * matching '>' and see if the subsequent terminal is either '.' or '#'. + */ + @SuppressWarnings("fallthrough") + ParensResult analyzeParens() { + int depth = 0; + boolean type = false; + for (int lookahead = 0 ; ; lookahead++) { + TokenKind tk = S.token(lookahead).kind; + switch (tk) { + case EXTENDS: case SUPER: case COMMA: + type = true; + case QUES: case DOT: case AMP: + //skip + break; + case BYTE: case SHORT: case INT: case LONG: case FLOAT: + case DOUBLE: case BOOLEAN: case CHAR: + if (peekToken(lookahead, RPAREN)) { + //Type, ')' -> cast + return ParensResult.CAST; + } else if (peekToken(lookahead, IDENTIFIER)) { + //Type, 'Identifier -> explicit lambda + return ParensResult.EXPLICIT_LAMBDA; + } + break; + case LPAREN: + if (lookahead != 0) { + // '(' in a non-starting position -> parens + return ParensResult.PARENS; + } else if (peekToken(lookahead, RPAREN)) { + // '(', ')' -> explicit lambda + return ParensResult.EXPLICIT_LAMBDA; + } + break; + case RPAREN: + // if we have seen something that looks like a type, + // then it's a cast expression + if (type) return ParensResult.CAST; + // otherwise, disambiguate cast vs. parenthesized expression + // based on subsequent token. + switch (S.token(lookahead + 1).kind) { + /*case PLUSPLUS: case SUBSUB: */ + case BANG: case TILDE: + case LPAREN: case THIS: case SUPER: + case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: + case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL: + case TRUE: case FALSE: case NULL: + case NEW: case IDENTIFIER: case ASSERT: case ENUM: + case BYTE: case SHORT: case CHAR: case INT: + case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID: + return ParensResult.CAST; + default: + return ParensResult.PARENS; + } + case IDENTIFIER: + if (peekToken(lookahead, IDENTIFIER)) { + // Identifier, Identifier -> explicit lambda + return ParensResult.EXPLICIT_LAMBDA; + } else if (peekToken(lookahead, RPAREN, ARROW)) { + // Identifier, ')' '->' -> implicit lambda + return ParensResult.IMPLICIT_LAMBDA; + } + break; + case FINAL: + case ELLIPSIS: + case MONKEYS_AT: + //those can only appear in explicit lambdas + return ParensResult.EXPLICIT_LAMBDA; + case LBRACKET: + if (peekToken(lookahead, RBRACKET, IDENTIFIER)) { + // '[', ']', Identifier -> explicit lambda + return ParensResult.EXPLICIT_LAMBDA; + } else if (peekToken(lookahead, RBRACKET, RPAREN) || + peekToken(lookahead, RBRACKET, AMP)) { + // '[', ']', ')' -> cast + // '[', ']', '&' -> cast (intersection type) + return ParensResult.CAST; + } else if (peekToken(lookahead, RBRACKET)) { + //consume the ']' and skip + type = true; + lookahead++; + break; + } else { + return ParensResult.PARENS; + } + case LT: + depth++; break; + case GTGTGT: + depth--; + case GTGT: + depth--; + case GT: + depth--; + if (depth == 0) { + if (peekToken(lookahead, RPAREN) || + peekToken(lookahead, AMP)) { + // '>', ')' -> cast + // '>', '&' -> cast + return ParensResult.CAST; + } else if (peekToken(lookahead, IDENTIFIER, COMMA) || + peekToken(lookahead, IDENTIFIER, RPAREN, ARROW) || + peekToken(lookahead, ELLIPSIS)) { + // '>', Identifier, ',' -> explicit lambda + // '>', Identifier, ')', '->' -> explicit lambda + // '>', '...' -> explicit lambda + return ParensResult.EXPLICIT_LAMBDA; + } + //it looks a type, but could still be (i) a cast to generic type, + //(ii) an unbound method reference or (iii) an explicit lambda + type = true; + break; + } else if (depth < 0) { + //unbalanced '<', '>' - not a generic type + return ParensResult.PARENS; + } + break; + default: + //this includes EOF + return ParensResult.PARENS; + } + } + } + + enum ParensResult { + CAST, + EXPLICIT_LAMBDA, + IMPLICIT_LAMBDA, + PARENS; + } + JCExpression lambdaExpressionOrStatement(JCVariableDecl firstParam, int pos) { ListBuffer params = new ListBuffer(); params.append(firstParam); @@ -1908,7 +1995,7 @@ public class JavacParser implements Parser { ListBuffer stats = variableDeclarators(mods, t, new ListBuffer()); // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon - storeEnd(stats.elems.last(), token.endPos); + storeEnd(stats.last(), token.endPos); accept(SEMI); return stats.toList(); } @@ -1949,7 +2036,7 @@ public class JavacParser implements Parser { ListBuffer stats = variableDeclarators(mods, t, new ListBuffer()); // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon - storeEnd(stats.elems.last(), token.endPos); + storeEnd(stats.last(), token.endPos); accept(SEMI); return stats.toList(); } else { @@ -2484,7 +2571,7 @@ public class JavacParser implements Parser { vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc)); while (token.kind == COMMA) { // All but last of multiple declarators subsume a comma - storeEnd((JCTree)vdefs.elems.last(), token.endPos); + storeEnd((JCTree)vdefs.last(), token.endPos); nextToken(); vdefs.append(variableDeclarator(mods, type, reqInit, dc)); } @@ -2539,7 +2626,7 @@ public class JavacParser implements Parser { defs.append(resource()); while (token.kind == SEMI) { // All but last of multiple declarators must subsume a semicolon - storeEnd(defs.elems.last(), token.endPos); + storeEnd(defs.last(), token.endPos); int semiColonPos = token.pos; nextToken(); if (token.kind == RPAREN) { // Optional trailing semicolon @@ -2617,7 +2704,7 @@ public class JavacParser implements Parser { JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(packageAnnotations, pid, defs.toList()); if (!consumedToplevelDoc) attach(toplevel, firstToken.comment(CommentStyle.JAVADOC)); - if (defs.elems.isEmpty()) + if (defs.isEmpty()) storeEnd(toplevel, S.prevToken().endPos); if (keepDocComments) toplevel.docComments = docComments; @@ -3171,21 +3258,12 @@ public class JavacParser implements Parser { /** Check that given tree is a legal expression statement. */ protected JCExpression checkExprStat(JCExpression t) { - switch(t.getTag()) { - case PREINC: case PREDEC: - case POSTINC: case POSTDEC: - case ASSIGN: - case BITOR_ASG: case BITXOR_ASG: case BITAND_ASG: - case SL_ASG: case SR_ASG: case USR_ASG: - case PLUS_ASG: case MINUS_ASG: - case MUL_ASG: case DIV_ASG: case MOD_ASG: - case APPLY: case NEWCLASS: - case ERRONEOUS: - return t; - default: + if (!TreeInfo.isExpressionStatement(t)) { JCExpression ret = F.at(t.pos).Erroneous(List.of(t)); error(ret, "not.stmt"); return ret; + } else { + return t; } } @@ -3395,6 +3473,12 @@ public class JavacParser implements Parser { allowDefaultMethods = true; } } + void checkIntersectionTypesInCast() { + if (!allowIntersectionTypesInCast) { + log.error(token.pos, "intersection.types.in.cast.not.supported.in.source", source.name); + allowIntersectionTypesInCast = true; + } + } /* * a functional source tree and end position mappings diff --git a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java index 061d571478c..498ca34b415 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java +++ b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java @@ -1336,7 +1336,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea return nodes; } - private static TreeScanner treeCleaner = new TreeScanner() { + private static final TreeScanner treeCleaner = new TreeScanner() { public void scan(JCTree node) { super.scan(node); if (node != null) diff --git a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties index 2ac10a97658..e1de0630e94 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -187,8 +187,9 @@ compiler.misc.not.a.functional.intf.1=\ {0} # 0: symbol, 1: symbol kind, 2: symbol -compiler.misc.invalid.generic.desc.in.functional.intf=\ - invalid functional descriptor: method {0} in {1} {2} is generic +compiler.misc.invalid.generic.lambda.target=\ + invalid functional descriptor for lambda expression\n\ + method {0} in {1} {2} is generic # 0: symbol kind, 1: symbol compiler.misc.incompatible.descs.in.functional.intf=\ @@ -206,6 +207,10 @@ compiler.misc.descriptor.throws=\ compiler.misc.no.suitable.functional.intf.inst=\ cannot infer functional interface descriptor for {0} +# 0: type +compiler.misc.secondary.bound.must.be.marker.intf=\ + secondary bound {0} must be a marker interface + # 0: symbol kind, 1: message segment compiler.err.invalid.mref=\ invalid {0} reference; {1} @@ -214,6 +219,12 @@ compiler.err.invalid.mref=\ compiler.misc.invalid.mref=\ invalid {0} reference; {1} +compiler.misc.static.mref.with.targs=\ + parameterized qualifier on static method reference + +compiler.misc.static.bound.mref=\ + static bound method reference + # 0: symbol compiler.err.cant.assign.val.to.final.var=\ cannot assign a value to final variable {0} @@ -296,13 +307,17 @@ compiler.err.doesnt.exist=\ compiler.err.duplicate.annotation=\ duplicate annotation +# 0: type +compiler.err.duplicate.annotation.invalid.repeated=\ + annotation {0} cannot be repeated\nIt does not define a valid containing annotation. + # 0: name, 1: type compiler.err.duplicate.annotation.member.value=\ duplicate annotation member value {0} in {1} -# 0: type +# 0: type, 1: type compiler.err.duplicate.annotation.missing.container=\ - duplicate annotation, the declaration of {0} does not have a ContainedBy annotation + duplicate annotation, the declaration of {0} does not have a valid {1} annotation # 0: type, 1: type compiler.err.invalid.container.no.containedby=\ @@ -2196,6 +2211,11 @@ compiler.err.default.methods.not.supported.in.source=\ default methods are not supported in -source {0}\n\ (use -source 8 or higher to enable default methods) +# 0: string +compiler.err.intersection.types.in.cast.not.supported.in.source=\ + intersection types in cast are not supported in -source {0}\n\ + (use -source 8 or higher to enable default methods) + ######################################## # Diagnostics for verbose resolution # used by Resolve (debug only) diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java b/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java index 22926654a00..269890eeb2b 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java @@ -254,6 +254,10 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { */ TYPEUNION, + /** Intersection types, of type TypeIntersection + */ + TYPEINTERSECTION, + /** Formal type parameters, of type TypeParameter. */ TYPEPARAMETER, @@ -336,15 +340,17 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { */ LETEXPR; // ala scheme - private Tag noAssignTag; + private final Tag noAssignTag; - private static int numberOfOperators = MOD.ordinal() - POS.ordinal() + 1; + private static final int numberOfOperators = MOD.ordinal() - POS.ordinal() + 1; private Tag(Tag noAssignTag) { this.noAssignTag = noAssignTag; } - private Tag() { } + private Tag() { + this(null); + } public static int getNumberOfOperators() { return numberOfOperators; @@ -1829,15 +1835,13 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { STATIC(ReferenceMode.INVOKE, false), /** Expr # instMethod */ BOUND(ReferenceMode.INVOKE, false), - /** Expr # staticMethod */ - STATIC_EVAL(ReferenceMode.INVOKE, false), /** Inner # new */ IMPLICIT_INNER(ReferenceMode.NEW, false), /** Toplevel # new */ TOPLEVEL(ReferenceMode.NEW, false); - ReferenceMode mode; - boolean unbound; + final ReferenceMode mode; + final boolean unbound; private ReferenceKind(ReferenceMode mode, boolean unbound) { this.mode = mode; @@ -2063,6 +2067,34 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { } } + /** + * An intersection type, T1 & T2 & ... Tn (used in cast expressions) + */ + public static class JCTypeIntersection extends JCExpression implements IntersectionTypeTree { + + public List bounds; + + protected JCTypeIntersection(List bounds) { + this.bounds = bounds; + } + @Override + public void accept(Visitor v) { v.visitTypeIntersection(this); } + + public Kind getKind() { return Kind.INTERSECTION_TYPE; } + + public List getBounds() { + return bounds; + } + @Override + public R accept(TreeVisitor v, D d) { + return v.visitIntersectionType(this, d); + } + @Override + public Tag getTag() { + return TYPEINTERSECTION; + } + } + /** * A formal class parameter. */ @@ -2385,6 +2417,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { public void visitTypeArray(JCArrayTypeTree that) { visitTree(that); } public void visitTypeApply(JCTypeApply that) { visitTree(that); } public void visitTypeUnion(JCTypeUnion that) { visitTree(that); } + public void visitTypeIntersection(JCTypeIntersection that) { visitTree(that); } public void visitTypeParameter(JCTypeParameter that) { visitTree(that); } public void visitWildcard(JCWildcard that) { visitTree(that); } public void visitTypeBoundKind(TypeBoundKind that) { visitTree(that); } diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java b/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java index e2f7b89399b..fa021522d95 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java @@ -1249,6 +1249,14 @@ public class Pretty extends JCTree.Visitor { } } + public void visitTypeIntersection(JCTypeIntersection tree) { + try { + printExprs(tree.bounds, " & "); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + public void visitTypeParameter(JCTypeParameter tree) { try { print(tree.name); diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java index f8efaa32018..c2e2ef92290 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java @@ -358,6 +358,12 @@ public class TreeCopier

      implements TreeVisitor { return M.at(t.pos).TypeUnion(components); } + public JCTree visitIntersectionType(IntersectionTypeTree node, P p) { + JCTypeIntersection t = (JCTypeIntersection) node; + List bounds = copy(t.bounds, p); + return M.at(t.pos).TypeIntersection(bounds); + } + public JCTree visitArrayType(ArrayTypeTree node, P p) { JCArrayTypeTree t = (JCArrayTypeTree) node; JCExpression elemtype = copy(t.elemtype, p); diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java index a68c719a7dc..9b1c85227d9 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java @@ -267,6 +267,25 @@ public class TreeInfo { return lambda.params.isEmpty() || lambda.params.head.vartype != null; } + + /** Return true if the tree corresponds to an expression statement */ + public static boolean isExpressionStatement(JCExpression tree) { + switch(tree.getTag()) { + case PREINC: case PREDEC: + case POSTINC: case POSTDEC: + case ASSIGN: + case BITOR_ASG: case BITXOR_ASG: case BITAND_ASG: + case SL_ASG: case SR_ASG: case USR_ASG: + case PLUS_ASG: case MINUS_ASG: + case MUL_ASG: case DIV_ASG: case MOD_ASG: + case APPLY: case NEWCLASS: + case ERRONEOUS: + return true; + default: + return false; + } + } + /** * Return true if the AST corresponds to a static select of the kind A.B */ diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java index 3182d6ed954..ce69edbe3f2 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java @@ -456,6 +456,12 @@ public class TreeMaker implements JCTree.Factory { return tree; } + public JCTypeIntersection TypeIntersection(List components) { + JCTypeIntersection tree = new JCTypeIntersection(components); + tree.pos = pos; + return tree; + } + public JCTypeParameter TypeParameter(Name name, List bounds) { JCTypeParameter tree = new JCTypeParameter(name, bounds); tree.pos = pos; diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java index 9a7c321f368..eff0fe2c617 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java @@ -286,6 +286,10 @@ public class TreeScanner extends Visitor { scan(tree.alternatives); } + public void visitTypeIntersection(JCTypeIntersection tree) { + scan(tree.bounds); + } + public void visitTypeParameter(JCTypeParameter tree) { scan(tree.bounds); } diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java index 2bc9c7a1290..daf456fa90d 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java @@ -379,6 +379,11 @@ public class TreeTranslator extends JCTree.Visitor { result = tree; } + public void visitTypeIntersection(JCTypeIntersection tree) { + tree.bounds = translate(tree.bounds); + result = tree; + } + public void visitTypeParameter(JCTypeParameter tree) { tree.bounds = translate(tree.bounds); result = tree; diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/BaseFileManager.java b/langtools/src/share/classes/com/sun/tools/javac/util/BaseFileManager.java index db3d662ba0e..cd27b07d4a7 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/util/BaseFileManager.java +++ b/langtools/src/share/classes/com/sun/tools/javac/util/BaseFileManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -181,7 +181,7 @@ public abstract class BaseFileManager { return false; } // where - private static Set extends AbstractCollection implements java.util.List return (List)EMPTY_LIST; } - private static List EMPTY_LIST = new List(null,null) { + private static final List EMPTY_LIST = new List(null,null) { public List setTail(List tail) { throw new UnsupportedOperationException(); } @@ -391,7 +391,7 @@ public class List extends AbstractCollection implements java.util.List return (List)list; } - private static Iterator EMPTYITERATOR = new Iterator() { + private static final Iterator EMPTYITERATOR = new Iterator() { public boolean hasNext() { return false; } diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/ListBuffer.java b/langtools/src/share/classes/com/sun/tools/javac/util/ListBuffer.java index 9756b3591a5..0aa751ffe96 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/util/ListBuffer.java +++ b/langtools/src/share/classes/com/sun/tools/javac/util/ListBuffer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -52,19 +52,20 @@ public class ListBuffer extends AbstractQueue { /** The list of elements of this buffer. */ - public List elems; + private List elems; - /** A pointer pointing to the last, sentinel element of `elems'. + /** A pointer pointing to the last element of 'elems' containing data, + * or null if the list is empty. */ - public List last; + private List last; /** The number of element in this buffer. */ - public int count; + private int count; /** Has a list been created from this buffer yet? */ - public boolean shared; + private boolean shared; /** Create a new initially empty list buffer. */ @@ -73,8 +74,8 @@ public class ListBuffer extends AbstractQueue { } public final void clear() { - this.elems = new List(null,null); - this.last = this.elems; + this.elems = List.nil(); + this.last = null; count = 0; shared = false; } @@ -103,22 +104,23 @@ public class ListBuffer extends AbstractQueue { /** Copy list and sets last. */ private void copy() { - List p = elems = new List(elems.head, elems.tail); - while (true) { - List tail = p.tail; - if (tail == null) break; - tail = new List(tail.head, tail.tail); - p.setTail(tail); - p = tail; + if (elems.nonEmpty()) { + List orig = elems; + + elems = last = List.of(orig.head); + + while ((orig = orig.tail).nonEmpty()) { + last.tail = List.of(orig.head); + last = last.tail; + } } - last = p; - shared = false; } /** Prepend an element to buffer. */ public ListBuffer prepend(A x) { elems = elems.prepend(x); + if (last == null) last = elems; count++; return this; } @@ -128,9 +130,13 @@ public class ListBuffer extends AbstractQueue { public ListBuffer append(A x) { x.getClass(); // null check if (shared) copy(); - last.head = x; - last.setTail(new List(null,null)); - last = last.tail; + List newLast = List.of(x); + if (last != null) { + last.tail = newLast; + last = newLast; + } else { + elems = last = newLast; + } count++; return this; } @@ -192,8 +198,9 @@ public class ListBuffer extends AbstractQueue { */ public A next() { A x = elems.head; - if (elems != last) { + if (!elems.isEmpty()) { elems = elems.tail; + if (elems.isEmpty()) last = null; count--; } return x; @@ -205,10 +212,10 @@ public class ListBuffer extends AbstractQueue { return new Iterator() { List elems = ListBuffer.this.elems; public boolean hasNext() { - return elems != last; + return !elems.isEmpty(); } public A next() { - if (elems == last) + if (elems.isEmpty()) throw new NoSuchElementException(); A elem = elems.head; elems = elems.tail; @@ -263,4 +270,8 @@ public class ListBuffer extends AbstractQueue { public A peek() { return first(); } + + public A last() { + return last != null ? last.head : null; + } } diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/MandatoryWarningHandler.java b/langtools/src/share/classes/com/sun/tools/javac/util/MandatoryWarningHandler.java index bb2dd5654f7..1cf0e60401f 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/util/MandatoryWarningHandler.java +++ b/langtools/src/share/classes/com/sun/tools/javac/util/MandatoryWarningHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -91,7 +91,7 @@ public class MandatoryWarningHandler { DeferredDiagnosticKind(String v) { value = v; } String getKey(String prefix) { return prefix + value; } - private String value; + private final String value; } diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java b/langtools/src/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java index ae637f56c3b..46867d5fa75 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java +++ b/langtools/src/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java @@ -249,7 +249,7 @@ public class RichDiagnosticFormatter extends INTERSECTION("where.description.intersection"); /** resource key for this where clause kind */ - private String key; + private final String key; WhereClauseKind(String key) { this.key = key; diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/AnnotationTypeDocImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/AnnotationTypeDocImpl.java index 35ce0dbae60..f4bfd5e4463 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/AnnotationTypeDocImpl.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/AnnotationTypeDocImpl.java @@ -27,13 +27,13 @@ package com.sun.tools.javadoc; import com.sun.javadoc.*; +import com.sun.source.util.TreePath; import com.sun.tools.javac.code.Kinds; import com.sun.tools.javac.code.Scope; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.Names; -import com.sun.tools.javac.util.Position; /** * Represents an annotation type. @@ -51,12 +51,11 @@ public class AnnotationTypeDocImpl extends ClassDocImpl implements AnnotationTypeDoc { public AnnotationTypeDocImpl(DocEnv env, ClassSymbol sym) { - this(env, sym, null, null, null); + this(env, sym, null); } - public AnnotationTypeDocImpl(DocEnv env, ClassSymbol sym, - String doc, JCClassDecl tree, Position.LineMap lineMap) { - super(env, sym, doc, tree, lineMap); + public AnnotationTypeDocImpl(DocEnv env, ClassSymbol sym, TreePath treePath) { + super(env, sym, treePath); } /** diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/AnnotationTypeElementDocImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/AnnotationTypeElementDocImpl.java index 4c3fad63f42..ebd5f804ba5 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/AnnotationTypeElementDocImpl.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/AnnotationTypeElementDocImpl.java @@ -27,9 +27,9 @@ package com.sun.tools.javadoc; import com.sun.javadoc.*; +import com.sun.source.util.TreePath; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.tree.JCTree.*; -import com.sun.tools.javac.util.Position; /** * Represents an element of an annotation type. @@ -50,9 +50,8 @@ public class AnnotationTypeElementDocImpl super(env, sym); } - public AnnotationTypeElementDocImpl(DocEnv env, MethodSymbol sym, - String doc, JCMethodDecl tree, Position.LineMap lineMap) { - super(env, sym, doc, tree, lineMap); + public AnnotationTypeElementDocImpl(DocEnv env, MethodSymbol sym, TreePath treePath) { + super(env, sym, treePath); } /** diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java index 37b3547e590..4445244c36c 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java @@ -31,13 +31,14 @@ import java.lang.reflect.Modifier; import java.net.URI; import java.util.HashSet; import java.util.Set; + import javax.tools.FileObject; import javax.tools.JavaFileManager.Location; import javax.tools.StandardJavaFileManager; import javax.tools.StandardLocation; import com.sun.javadoc.*; - +import com.sun.source.util.TreePath; import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.code.Kinds; import com.sun.tools.javac.code.Scope; @@ -45,22 +46,17 @@ import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Type; import com.sun.tools.javac.code.Type.ClassType; - import com.sun.tools.javac.comp.AttrContext; import com.sun.tools.javac.comp.Env; - import com.sun.tools.javac.tree.JCTree; -import com.sun.tools.javac.tree.JCTree.JCClassDecl; import com.sun.tools.javac.tree.JCTree.JCFieldAccess; import com.sun.tools.javac.tree.JCTree.JCImport; import com.sun.tools.javac.tree.TreeInfo; - import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Name; import com.sun.tools.javac.util.Names; import com.sun.tools.javac.util.Position; - import static com.sun.tools.javac.code.Kinds.*; import static com.sun.tools.javac.code.TypeTag.CLASS; import static com.sun.tools.javac.tree.JCTree.Tag.*; @@ -100,15 +96,14 @@ public class ClassDocImpl extends ProgramElementDocImpl implements ClassDoc { * Constructor */ public ClassDocImpl(DocEnv env, ClassSymbol sym) { - this(env, sym, null, null, null); + this(env, sym, null); } /** * Constructor */ - public ClassDocImpl(DocEnv env, ClassSymbol sym, String documentation, - JCClassDecl tree, Position.LineMap lineMap) { - super(env, sym, documentation, tree, lineMap); + public ClassDocImpl(DocEnv env, ClassSymbol sym, TreePath treePath) { + super(env, sym, treePath); this.type = (ClassType)sym.type; this.tsym = sym; } diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/ConstructorDocImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/ConstructorDocImpl.java index e1f4678c713..1753a310933 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/ConstructorDocImpl.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/ConstructorDocImpl.java @@ -27,10 +27,9 @@ package com.sun.tools.javadoc; import com.sun.javadoc.*; +import com.sun.source.util.TreePath; import com.sun.tools.javac.code.Symbol.ClassSymbol; import com.sun.tools.javac.code.Symbol.MethodSymbol; -import com.sun.tools.javac.tree.JCTree.JCMethodDecl; -import com.sun.tools.javac.util.Position; /** * Represents a constructor of a java class. @@ -58,9 +57,8 @@ public class ConstructorDocImpl /** * constructor. */ - public ConstructorDocImpl(DocEnv env, MethodSymbol sym, - String docComment, JCMethodDecl tree, Position.LineMap lineMap) { - super(env, sym, docComment, tree, lineMap); + public ConstructorDocImpl(DocEnv env, MethodSymbol sym, TreePath treePath) { + super(env, sym, treePath); } /** diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/DocEnv.java b/langtools/src/share/classes/com/sun/tools/javadoc/DocEnv.java index 6b14caca675..ba08ae47eaa 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/DocEnv.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/DocEnv.java @@ -27,18 +27,20 @@ package com.sun.tools.javadoc; import java.lang.reflect.Modifier; import java.util.*; + import javax.tools.JavaFileManager; import com.sun.javadoc.*; - +import com.sun.source.util.TreePath; +import com.sun.tools.javac.api.JavacTrees; import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Type.ClassType; import com.sun.tools.javac.comp.Check; +import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.Names; -import com.sun.tools.javac.util.Position; /** * Holds the environment for a run of javadoc. @@ -104,6 +106,8 @@ public class DocEnv { JavaFileManager fileManager; Context context; + WeakHashMap treePaths = new WeakHashMap(); + /** Allow documenting from class files? */ boolean docClasses = false; @@ -540,13 +544,12 @@ public class DocEnv { /** * Create the PackageDoc (or a subtype) for a package symbol. */ - void makePackageDoc(PackageSymbol pack, String docComment, JCCompilationUnit tree) { + void makePackageDoc(PackageSymbol pack, TreePath treePath) { PackageDocImpl result = packageMap.get(pack); if (result != null) { - if (docComment != null) result.setRawCommentText(docComment); - if (tree != null) result.setTree(tree); + if (treePath != null) result.setTreePath(treePath); } else { - result = new PackageDocImpl(this, pack, docComment, tree); + result = new PackageDocImpl(this, pack, treePath); packageMap.put(pack, result); } } @@ -572,17 +575,16 @@ public class DocEnv { /** * Create the ClassDoc (or a subtype) for a class symbol. */ - protected void makeClassDoc(ClassSymbol clazz, String docComment, JCClassDecl tree, Position.LineMap lineMap) { + protected void makeClassDoc(ClassSymbol clazz, TreePath treePath) { ClassDocImpl result = classMap.get(clazz); if (result != null) { - if (docComment != null) result.setRawCommentText(docComment); - if (tree != null) result.setTree(tree); + if (treePath != null) result.setTreePath(treePath); return; } - if (isAnnotationType(tree)) { // flags of clazz may not yet be set - result = new AnnotationTypeDocImpl(this, clazz, docComment, tree, lineMap); + if (isAnnotationType((JCClassDecl) treePath.getLeaf())) { // flags of clazz may not yet be set + result = new AnnotationTypeDocImpl(this, clazz, treePath); } else { - result = new ClassDocImpl(this, clazz, docComment, tree, lineMap); + result = new ClassDocImpl(this, clazz, treePath); } classMap.put(clazz, result); } @@ -610,13 +612,12 @@ public class DocEnv { /** * Create a FieldDoc for a var symbol. */ - protected void makeFieldDoc(VarSymbol var, String docComment, JCVariableDecl tree, Position.LineMap lineMap) { + protected void makeFieldDoc(VarSymbol var, TreePath treePath) { FieldDocImpl result = fieldMap.get(var); if (result != null) { - if (docComment != null) result.setRawCommentText(docComment); - if (tree != null) result.setTree(tree); + if (treePath != null) result.setTreePath(treePath); } else { - result = new FieldDocImpl(this, var, docComment, tree, lineMap); + result = new FieldDocImpl(this, var, treePath); fieldMap.put(var, result); } } @@ -627,14 +628,12 @@ public class DocEnv { * Create a MethodDoc for this MethodSymbol. * Should be called only on symbols representing methods. */ - protected void makeMethodDoc(MethodSymbol meth, String docComment, - JCMethodDecl tree, Position.LineMap lineMap) { + protected void makeMethodDoc(MethodSymbol meth, TreePath treePath) { MethodDocImpl result = (MethodDocImpl)methodMap.get(meth); if (result != null) { - if (docComment != null) result.setRawCommentText(docComment); - if (tree != null) result.setTree(tree); + if (treePath != null) result.setTreePath(treePath); } else { - result = new MethodDocImpl(this, meth, docComment, tree, lineMap); + result = new MethodDocImpl(this, meth, treePath); methodMap.put(meth, result); } } @@ -656,14 +655,12 @@ public class DocEnv { * Create the ConstructorDoc for a MethodSymbol. * Should be called only on symbols representing constructors. */ - protected void makeConstructorDoc(MethodSymbol meth, String docComment, - JCMethodDecl tree, Position.LineMap lineMap) { + protected void makeConstructorDoc(MethodSymbol meth, TreePath treePath) { ConstructorDocImpl result = (ConstructorDocImpl)methodMap.get(meth); if (result != null) { - if (docComment != null) result.setRawCommentText(docComment); - if (tree != null) result.setTree(tree); + if (treePath != null) result.setTreePath(treePath); } else { - result = new ConstructorDocImpl(this, meth, docComment, tree, lineMap); + result = new ConstructorDocImpl(this, meth, treePath); methodMap.put(meth, result); } } @@ -685,16 +682,14 @@ public class DocEnv { * Create the AnnotationTypeElementDoc for a MethodSymbol. * Should be called only on symbols representing annotation type elements. */ - protected void makeAnnotationTypeElementDoc(MethodSymbol meth, - String docComment, JCMethodDecl tree, Position.LineMap lineMap) { + protected void makeAnnotationTypeElementDoc(MethodSymbol meth, TreePath treePath) { AnnotationTypeElementDocImpl result = (AnnotationTypeElementDocImpl)methodMap.get(meth); if (result != null) { - if (docComment != null) result.setRawCommentText(docComment); - if (tree != null) result.setTree(tree); + if (treePath != null) result.setTreePath(treePath); } else { result = - new AnnotationTypeElementDocImpl(this, meth, docComment, tree, lineMap); + new AnnotationTypeElementDocImpl(this, meth, treePath); methodMap.put(meth, result); } } @@ -730,6 +725,18 @@ public class DocEnv { // return result; } + TreePath getTreePath(JCCompilationUnit tree) { + TreePath p = treePaths.get(tree); + if (p == null) + treePaths.put(tree, p = new TreePath(tree)); + return p; + } + + TreePath getTreePath(JCCompilationUnit toplevel, JCTree tree) { + // don't bother to cache paths for classes and members + return new TreePath(getTreePath(toplevel), tree); + } + /** * Set the encoding. */ diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/DocImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/DocImpl.java index f263123c2a5..12451293c9a 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/DocImpl.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/DocImpl.java @@ -35,6 +35,9 @@ import java.util.regex.Pattern; import javax.tools.FileObject; import com.sun.javadoc.*; +import com.sun.source.util.TreePath; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; import com.sun.tools.javac.util.Position; /** @@ -60,6 +63,12 @@ public abstract class DocImpl implements Doc, Comparable { */ protected final DocEnv env; //### Rename this everywhere to 'docenv' ? + /** + * Back pointer to the tree node for this doc item. + * May be null if there is no associated tree. + */ + protected TreePath treePath; + /** * The complex comment object, lazily initialized. */ @@ -88,11 +97,21 @@ public abstract class DocImpl implements Doc, Comparable { /** * Constructor. */ - DocImpl(DocEnv env, String documentation) { - this.documentation = documentation; + DocImpl(DocEnv env, TreePath treePath) { + this.treePath = treePath; + this.documentation = getCommentText(treePath); this.env = env; } + private static String getCommentText(TreePath p) { + if (p == null) + return null; + + JCCompilationUnit topLevel = (JCCompilationUnit) p.getCompilationUnit(); + JCTree tree = (JCTree) p.getLeaf(); + return topLevel.docComments.getCommentText(tree); + } + /** * So subclasses have the option to do lazy initialization of * "documentation" string. @@ -213,10 +232,20 @@ public abstract class DocImpl implements Doc, Comparable { * operations like internalization. */ public void setRawCommentText(String rawDocumentation) { + treePath = null; documentation = rawDocumentation; comment = null; } + /** + * Set the full unprocessed text of the comment and tree path. + */ + void setTreePath(TreePath treePath) { + this.treePath = treePath; + documentation = getCommentText(treePath); + comment = null; + } + /** * return a key for sorting. */ diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/ExecutableMemberDocImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/ExecutableMemberDocImpl.java index 600eeb2ee13..72a666d27a7 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/ExecutableMemberDocImpl.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/ExecutableMemberDocImpl.java @@ -30,13 +30,12 @@ import java.text.CollationKey; import com.sun.javadoc.*; +import com.sun.source.util.TreePath; import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Type; -import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; -import com.sun.tools.javac.util.Position; /** * Represents a method or constructor of a java class. @@ -60,9 +59,8 @@ public abstract class ExecutableMemberDocImpl /** * Constructor. */ - public ExecutableMemberDocImpl(DocEnv env, MethodSymbol sym, - String rawDocs, JCMethodDecl tree, Position.LineMap lineMap) { - super(env, sym, rawDocs, tree, lineMap); + public ExecutableMemberDocImpl(DocEnv env, MethodSymbol sym, TreePath treePath) { + super(env, sym, treePath); this.sym = sym; } @@ -70,7 +68,7 @@ public abstract class ExecutableMemberDocImpl * Constructor. */ public ExecutableMemberDocImpl(DocEnv env, MethodSymbol sym) { - this(env, sym, null, null, null); + this(env, sym, null); } /** diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/FieldDocImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/FieldDocImpl.java index b10992a99b9..e8e8f59d55c 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/FieldDocImpl.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/FieldDocImpl.java @@ -25,6 +25,7 @@ package com.sun.tools.javadoc; +import com.sun.source.util.TreePath; import java.lang.reflect.Modifier; import com.sun.javadoc.*; @@ -61,9 +62,8 @@ public class FieldDocImpl extends MemberDocImpl implements FieldDoc { /** * Constructor. */ - public FieldDocImpl(DocEnv env, VarSymbol sym, - String rawDocs, JCVariableDecl tree, Position.LineMap lineMap) { - super(env, sym, rawDocs, tree, lineMap); + public FieldDocImpl(DocEnv env, VarSymbol sym, TreePath treePath) { + super(env, sym, treePath); this.sym = sym; } @@ -71,7 +71,7 @@ public class FieldDocImpl extends MemberDocImpl implements FieldDoc { * Constructor. */ public FieldDocImpl(DocEnv env, VarSymbol sym) { - this(env, sym, null, null, null); + this(env, sym, null); } /** diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/JavadocEnter.java b/langtools/src/share/classes/com/sun/tools/javadoc/JavadocEnter.java index d914eefc855..3a85a530310 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/JavadocEnter.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/JavadocEnter.java @@ -25,13 +25,14 @@ package com.sun.tools.javadoc; + import javax.tools.JavaFileObject; +import com.sun.source.util.TreePath; import com.sun.tools.javac.code.Kinds; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.comp.Enter; import com.sun.tools.javac.tree.JCTree.*; -import com.sun.tools.javac.tree.TreeInfo; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.util.List; @@ -85,8 +86,7 @@ public class JavadocEnter extends Enter { public void visitTopLevel(JCCompilationUnit tree) { super.visitTopLevel(tree); if (tree.sourcefile.isNameCompatible("package-info", JavaFileObject.Kind.SOURCE)) { - String comment = TreeInfo.getCommentText(env, tree); - docenv.makePackageDoc(tree.packge, comment, tree); + docenv.makePackageDoc(tree.packge, docenv.getTreePath(tree)); } } @@ -95,9 +95,8 @@ public class JavadocEnter extends Enter { super.visitClassDef(tree); if (tree.sym == null) return; if (tree.sym.kind == Kinds.TYP || tree.sym.kind == Kinds.ERR) { - String comment = TreeInfo.getCommentText(env, tree); ClassSymbol c = tree.sym; - docenv.makeClassDoc(c, comment, tree, env.toplevel.lineMap); + docenv.makeClassDoc(c, docenv.getTreePath(env.toplevel, tree)); } } diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/JavadocMemberEnter.java b/langtools/src/share/classes/com/sun/tools/javadoc/JavadocMemberEnter.java index bb4eee23cc3..76e93a34367 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/JavadocMemberEnter.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/JavadocMemberEnter.java @@ -25,14 +25,13 @@ package com.sun.tools.javadoc; +import com.sun.source.util.TreePath; import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.code.Kinds; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.comp.MemberEnter; import com.sun.tools.javac.tree.JCTree.*; -import com.sun.tools.javac.tree.TreeInfo; import com.sun.tools.javac.util.Context; -import com.sun.tools.javac.util.Position; /** * Javadoc's own memberEnter phase does a few things above and beyond that @@ -73,14 +72,13 @@ public class JavadocMemberEnter extends MemberEnter { super.visitMethodDef(tree); MethodSymbol meth = tree.sym; if (meth == null || meth.kind != Kinds.MTH) return; - String docComment = TreeInfo.getCommentText(env, tree); - Position.LineMap lineMap = env.toplevel.lineMap; + TreePath treePath = docenv.getTreePath(env.toplevel, tree); if (meth.isConstructor()) - docenv.makeConstructorDoc(meth, docComment, tree, lineMap); + docenv.makeConstructorDoc(meth, treePath); else if (isAnnotationTypeElement(meth)) - docenv.makeAnnotationTypeElementDoc(meth, docComment, tree, lineMap); + docenv.makeAnnotationTypeElementDoc(meth, treePath); else - docenv.makeMethodDoc(meth, docComment, tree, lineMap); + docenv.makeMethodDoc(meth, treePath); // release resources tree.body = null; @@ -92,9 +90,7 @@ public class JavadocMemberEnter extends MemberEnter { if (tree.sym != null && tree.sym.kind == Kinds.VAR && !isParameter(tree.sym)) { - String docComment = TreeInfo.getCommentText(env, tree); - Position.LineMap lineMap = env.toplevel.lineMap; - docenv.makeFieldDoc(tree.sym, docComment, tree, lineMap); + docenv.makeFieldDoc(tree.sym, docenv.getTreePath(env.toplevel, tree)); } } diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/MemberDocImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/MemberDocImpl.java index 88da9c0d68b..37c7c66eb46 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/MemberDocImpl.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/MemberDocImpl.java @@ -27,9 +27,8 @@ package com.sun.tools.javadoc; import com.sun.javadoc.*; +import com.sun.source.util.TreePath; import com.sun.tools.javac.code.Symbol; -import com.sun.tools.javac.tree.JCTree; -import com.sun.tools.javac.util.Position; /** * Represents a member of a java class: field, constructor, or method. @@ -57,8 +56,8 @@ public abstract class MemberDocImpl /** * constructor. */ - public MemberDocImpl(DocEnv env, Symbol sym, String doc, JCTree tree, Position.LineMap lineMap) { - super(env, sym, doc, tree, lineMap); + public MemberDocImpl(DocEnv env, Symbol sym, TreePath treePath) { + super(env, sym, treePath); } /** diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/MethodDocImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/MethodDocImpl.java index 025463cf136..7c942feb429 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/MethodDocImpl.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/MethodDocImpl.java @@ -28,12 +28,10 @@ package com.sun.tools.javadoc; import java.lang.reflect.Modifier; import com.sun.javadoc.*; +import com.sun.source.util.TreePath; import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Type; -import com.sun.tools.javac.tree.JCTree.JCMethodDecl; -import com.sun.tools.javac.util.Position; - import static com.sun.tools.javac.code.TypeTag.CLASS; /** @@ -62,9 +60,8 @@ public class MethodDocImpl /** * constructor. */ - public MethodDocImpl(DocEnv env, MethodSymbol sym, - String docComment, JCMethodDecl tree, Position.LineMap lineMap) { - super(env, sym, docComment, tree, lineMap); + public MethodDocImpl(DocEnv env, MethodSymbol sym, TreePath treePath) { + super(env, sym, treePath); } /** diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/PackageDocImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/PackageDocImpl.java index 9a072250eb2..1068f803053 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/PackageDocImpl.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/PackageDocImpl.java @@ -31,6 +31,7 @@ import java.io.InputStream; import javax.tools.FileObject; import com.sun.javadoc.*; +import com.sun.source.util.TreePath; import com.sun.tools.javac.code.Attribute; import com.sun.tools.javac.code.Scope; import com.sun.tools.javac.code.Symbol.ClassSymbol; @@ -75,17 +76,16 @@ public class PackageDocImpl extends DocImpl implements PackageDoc { * Constructor */ public PackageDocImpl(DocEnv env, PackageSymbol sym) { - this(env, sym, null, null); + this(env, sym, null); } /** * Constructor */ - public PackageDocImpl(DocEnv env, PackageSymbol sym, - String documentation, JCTree tree) { - super(env, documentation); + public PackageDocImpl(DocEnv env, PackageSymbol sym, TreePath treePath) { + super(env, treePath); this.sym = sym; - this.tree = (JCCompilationUnit) tree; + this.tree = (treePath == null) ? null : (JCCompilationUnit) treePath.getCompilationUnit(); foundDoc = (documentation != null); } @@ -93,8 +93,8 @@ public class PackageDocImpl extends DocImpl implements PackageDoc { this.tree = (JCCompilationUnit) tree; } - public void setRawCommentText(String rawDocumentation) { - super.setRawCommentText(rawDocumentation); + public void setTreePath(TreePath treePath) { + super.setTreePath(treePath); checkDoc(); } diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/ProgramElementDocImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/ProgramElementDocImpl.java index cdd4a44da15..f4f923ea9c1 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/ProgramElementDocImpl.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/ProgramElementDocImpl.java @@ -29,10 +29,12 @@ import java.lang.reflect.Modifier; import java.text.CollationKey; import com.sun.javadoc.*; +import com.sun.source.util.TreePath; import com.sun.tools.javac.code.Attribute; import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symbol.ClassSymbol; import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; import com.sun.tools.javac.util.Position; /** @@ -66,16 +68,20 @@ public abstract class ProgramElementDocImpl // Cache for getModifiers(). private int modifiers = -1; - protected ProgramElementDocImpl(DocEnv env, Symbol sym, - String doc, JCTree tree, Position.LineMap lineMap) { - super(env, doc); + protected ProgramElementDocImpl(DocEnv env, Symbol sym, TreePath treePath) { + super(env, treePath); this.sym = sym; - this.tree = tree; - this.lineMap = lineMap; + if (treePath != null) { + tree = (JCTree) treePath.getLeaf(); + lineMap = ((JCCompilationUnit) treePath.getCompilationUnit()).lineMap; + } } - void setTree(JCTree tree) { - this.tree = tree; + @Override + void setTreePath(TreePath treePath) { + super.setTreePath(treePath); + this.tree = (JCTree) treePath.getLeaf(); + this.lineMap = ((JCCompilationUnit) treePath.getCompilationUnit()).lineMap; } /** diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/RootDocImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/RootDocImpl.java index bb9364d192c..f662dd749db 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/RootDocImpl.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/RootDocImpl.java @@ -331,7 +331,6 @@ public class RootDocImpl extends DocImpl implements RootDoc { @Override protected String documentation() { if (documentation == null) { - int cnt = options.length(); JavaFileObject overviewPath = getOverviewPath(); if (overviewPath == null) { // no doc file to be had diff --git a/langtools/src/share/classes/com/sun/tools/javah/JavahTask.java b/langtools/src/share/classes/com/sun/tools/javah/JavahTask.java index 6b8abf9d6d1..f29faf05cd7 100644 --- a/langtools/src/share/classes/com/sun/tools/javah/JavahTask.java +++ b/langtools/src/share/classes/com/sun/tools/javah/JavahTask.java @@ -147,7 +147,7 @@ public class JavahTask implements NativeHeaderTool.NativeHeaderTask { } } - static Option[] recognizedOptions = { + static final Option[] recognizedOptions = { new Option(true, "-o") { void process(JavahTask task, String opt, String arg) { task.ofile = new File(arg); diff --git a/langtools/src/share/classes/com/sun/tools/javap/JavapTask.java b/langtools/src/share/classes/com/sun/tools/javap/JavapTask.java index 98966078974..7f367d18429 100644 --- a/langtools/src/share/classes/com/sun/tools/javap/JavapTask.java +++ b/langtools/src/share/classes/com/sun/tools/javap/JavapTask.java @@ -117,7 +117,7 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages { final String[] aliases; } - static Option[] recognizedOptions = { + static final Option[] recognizedOptions = { new Option(false, "-help", "--help", "-?") { void process(JavapTask task, String opt, String arg) { diff --git a/langtools/src/share/classes/javax/lang/model/element/Modifier.java b/langtools/src/share/classes/javax/lang/model/element/Modifier.java index 2b6d8ac6642..995334d8deb 100644 --- a/langtools/src/share/classes/javax/lang/model/element/Modifier.java +++ b/langtools/src/share/classes/javax/lang/model/element/Modifier.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -61,16 +61,10 @@ public enum Modifier { /** The modifier {@code native} */ NATIVE, /** The modifier {@code strictfp} */ STRICTFP; - - private String lowercase = null; // modifier name in lowercase - /** * Returns this modifier's name in lowercase. */ public String toString() { - if (lowercase == null) { - lowercase = name().toLowerCase(java.util.Locale.US); - } - return lowercase; + return name().toLowerCase(java.util.Locale.US); } } diff --git a/langtools/src/share/classes/javax/lang/model/type/IntersectionType.java b/langtools/src/share/classes/javax/lang/model/type/IntersectionType.java new file mode 100644 index 00000000000..80dca497e74 --- /dev/null +++ b/langtools/src/share/classes/javax/lang/model/type/IntersectionType.java @@ -0,0 +1,47 @@ +/* + * 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. 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 javax.lang.model.type; + +import java.util.List; + +/** + * Represents an intersection type. + * + * As of the {@link javax.lang.model.SourceVersion#RELEASE_8 + * RELEASE_8} source version, intersection types can appear as the target type + * of a cast expression. + * + * @since 1.8 + */ +public interface IntersectionType extends TypeMirror { + + /** + * Return the bounds comprising this intersection type. + * + * @return the bounds of this intersection types. + */ + List getBounds(); +} diff --git a/langtools/src/share/classes/javax/lang/model/type/TypeKind.java b/langtools/src/share/classes/javax/lang/model/type/TypeKind.java index 717737649f0..0f67a3ba7b6 100644 --- a/langtools/src/share/classes/javax/lang/model/type/TypeKind.java +++ b/langtools/src/share/classes/javax/lang/model/type/TypeKind.java @@ -144,7 +144,14 @@ public enum TypeKind { * * @since 1.7 */ - UNION; + UNION, + + /** + * An intersection type. + * + * @since 1.8 + */ + INTERSECTION; /** * Returns {@code true} if this kind corresponds to a primitive diff --git a/langtools/src/share/classes/javax/lang/model/type/TypeVisitor.java b/langtools/src/share/classes/javax/lang/model/type/TypeVisitor.java index 58f63637f64..f95af6c87d9 100644 --- a/langtools/src/share/classes/javax/lang/model/type/TypeVisitor.java +++ b/langtools/src/share/classes/javax/lang/model/type/TypeVisitor.java @@ -172,4 +172,14 @@ public interface TypeVisitor { * @since 1.7 */ R visitUnion(UnionType t, P p); + + /** + * Visits an intersection type. + * + * @param t the type to visit + * @param p a visitor-specified parameter + * @return a visitor-specified result + * @since 1.8 + */ + R visitIntersection(IntersectionType t, P p); } diff --git a/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor6.java b/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor6.java index bff7e69b2a7..c36fda3dec9 100644 --- a/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor6.java +++ b/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor6.java @@ -110,6 +110,20 @@ public abstract class AbstractTypeVisitor6 implements TypeVisitor { return visitUnknown(t, p); } + /** + * Visits an {@code IntersectionType} element by calling {@code + * visitUnknown}. + + * @param t {@inheritDoc} + * @param p {@inheritDoc} + * @return the result of {@code visitUnknown} + * + * @since 1.8 + */ + public R visitIntersection(IntersectionType t, P p) { + return visitUnknown(t, p); + } + /** * {@inheritDoc} * diff --git a/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor8.java b/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor8.java index 40a7eea6028..3f038d29e79 100644 --- a/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor8.java +++ b/langtools/src/share/classes/javax/lang/model/util/AbstractTypeVisitor8.java @@ -66,4 +66,13 @@ public abstract class AbstractTypeVisitor8 extends AbstractTypeVisitor7 CONSTRUCTOR_KIND = + private static final Set CONSTRUCTOR_KIND = Collections.unmodifiableSet(EnumSet.of(ElementKind.CONSTRUCTOR)); - private static Set FIELD_KINDS = + private static final Set FIELD_KINDS = Collections.unmodifiableSet(EnumSet.of(ElementKind.FIELD, ElementKind.ENUM_CONSTANT)); - private static Set METHOD_KIND = + private static final Set METHOD_KIND = Collections.unmodifiableSet(EnumSet.of(ElementKind.METHOD)); - private static Set PACKAGE_KIND = + private static final Set PACKAGE_KIND = Collections.unmodifiableSet(EnumSet.of(ElementKind.PACKAGE)); - private static Set TYPE_KINDS = + private static final Set TYPE_KINDS = Collections.unmodifiableSet(EnumSet.of(ElementKind.CLASS, ElementKind.ENUM, ElementKind.INTERFACE, diff --git a/langtools/src/share/classes/javax/tools/JavaCompiler.java b/langtools/src/share/classes/javax/tools/JavaCompiler.java index 36d86cfe8f3..5588c80d428 100644 --- a/langtools/src/share/classes/javax/tools/JavaCompiler.java +++ b/langtools/src/share/classes/javax/tools/JavaCompiler.java @@ -108,8 +108,8 @@ import javax.annotation.processing.Processor; * example a recommended coding pattern: * *
      - *       Files[] files1 = ... ; // input for first compilation task
      - *       Files[] files2 = ... ; // input for second compilation task
      + *       File[] files1 = ... ; // input for first compilation task
      + *       File[] files2 = ... ; // input for second compilation task
        *
        *       JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        *       StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
      @@ -165,7 +165,7 @@ import javax.annotation.processing.Processor;
        *       JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        *       StandardJavaFileManager stdFileManager = compiler.getStandardFileManager(null, null, null);
        *       JavaFileManager fileManager = new ForwardingJavaFileManager(stdFileManager) {
      - *           public void flush() {
      + *           public void flush() throws IOException {
        *               logger.entering(StandardJavaFileManager.class.getName(), "flush");
        *               super.flush();
        *               logger.exiting(StandardJavaFileManager.class.getName(), "flush");
      diff --git a/langtools/src/share/classes/javax/tools/StandardLocation.java b/langtools/src/share/classes/javax/tools/StandardLocation.java
      index ff2abf6e2c8..9c6184d60b3 100644
      --- a/langtools/src/share/classes/javax/tools/StandardLocation.java
      +++ b/langtools/src/share/classes/javax/tools/StandardLocation.java
      @@ -97,7 +97,7 @@ public enum StandardLocation implements Location {
               return locations.get(name);
           }
           //where
      -        private static ConcurrentMap locations
      +        private static final ConcurrentMap locations
                   = new ConcurrentHashMap();
       
           public String getName() { return name(); }
      diff --git a/langtools/test/tools/javac/7144981/IgnoreIgnorableCharactersInInput.java b/langtools/test/tools/javac/7144981/IgnoreIgnorableCharactersInInput.java
      new file mode 100644
      index 00000000000..95bce2a3716
      --- /dev/null
      +++ b/langtools/test/tools/javac/7144981/IgnoreIgnorableCharactersInInput.java
      @@ -0,0 +1,92 @@
      +
      +/*
      + * @test  /nodynamiccopyright/
      + * @bug 7144981
      + * @summary javac should ignore ignorable characters in input
      + * @run main IgnoreIgnorableCharactersInInput
      + */
      +
      +import com.sun.source.util.JavacTask;
      +import java.io.File;
      +import java.net.URI;
      +import java.util.Arrays;
      +import java.util.Set;
      +import java.util.TreeSet;
      +import javax.tools.JavaCompiler;
      +import javax.tools.JavaFileObject;
      +import javax.tools.SimpleJavaFileObject;
      +import javax.tools.ToolProvider;
      +
      +public class IgnoreIgnorableCharactersInInput {
      +
      +    public static void main(String... args) throws Exception {
      +        new IgnoreIgnorableCharactersInInput().run();
      +    }
      +
      +    void run() throws Exception {
      +        JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
      +        File classesDir = new File(System.getProperty("user.dir"), "classes");
      +        classesDir.mkdirs();
      +        JavaSource[] sources = new JavaSource[]{
      +            new JavaSource("TestOneIgnorableChar", "AA\\u0000BB"),
      +            new JavaSource("TestMultipleIgnorableChar", "AA\\u0000\\u0000\\u0000BB")};
      +        JavacTask ct = (JavacTask)comp.getTask(null, null, null,
      +                Arrays.asList("-d", classesDir.getPath()),
      +                null, Arrays.asList(sources));
      +        try {
      +            if (!ct.call()) {
      +                throw new AssertionError("Error thrown when compiling test cases");
      +            }
      +        } catch (Throwable ex) {
      +            throw new AssertionError("Error thrown when compiling test cases");
      +        }
      +        check(classesDir,
      +                "TestOneIgnorableChar.class",
      +                "TestOneIgnorableChar$AABB.class",
      +                "TestMultipleIgnorableChar.class",
      +                "TestMultipleIgnorableChar$AABB.class");
      +        if (errors > 0)
      +            throw new AssertionError("There are some errors in the test check the error output");
      +    }
      +
      +    /**
      +     *  Check that a directory contains the expected files.
      +     */
      +    void check(File dir, String... paths) {
      +        Set found = new TreeSet(Arrays.asList(dir.list()));
      +        Set expect = new TreeSet(Arrays.asList(paths));
      +        if (found.equals(expect))
      +            return;
      +        for (String f: found) {
      +            if (!expect.contains(f))
      +                error("Unexpected file found: " + f);
      +        }
      +        for (String e: expect) {
      +            if (!found.contains(e))
      +                error("Expected file not found: " + e);
      +        }
      +    }
      +
      +    int errors;
      +
      +    void error(String msg) {
      +        System.err.println(msg);
      +        errors++;
      +    }
      +
      +    class JavaSource extends SimpleJavaFileObject {
      +
      +        String internalSource =
      +            "public class #O {public class #I {} }";
      +        public JavaSource(String outerClassName, String innerClassName) {
      +            super(URI.create(outerClassName + ".java"), JavaFileObject.Kind.SOURCE);
      +            internalSource =
      +                    internalSource.replace("#O", outerClassName).replace("#I", innerClassName);
      +        }
      +
      +        @Override
      +        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
      +            return internalSource;
      +        }
      +    }
      +}
      diff --git a/langtools/test/tools/javac/7153958/CPoolRefClassContainingInlinedCts.java b/langtools/test/tools/javac/7153958/CPoolRefClassContainingInlinedCts.java
      new file mode 100644
      index 00000000000..e518df8d3fc
      --- /dev/null
      +++ b/langtools/test/tools/javac/7153958/CPoolRefClassContainingInlinedCts.java
      @@ -0,0 +1,134 @@
      +/*
      + * 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.  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 7153958
      + * @summary add constant pool reference to class containing inlined constants
      + * @compile pkg/ClassToBeStaticallyImported.java
      + * @run main CPoolRefClassContainingInlinedCts
      + */
      +
      +import com.sun.tools.classfile.ClassFile;
      +import com.sun.tools.classfile.ConstantPool.CONSTANT_Class_info;
      +import com.sun.tools.classfile.ConstantPool.CPInfo;
      +import com.sun.tools.classfile.ConstantPoolException;
      +import java.io.File;
      +import java.io.IOException;
      +
      +import static pkg.ClassToBeStaticallyImported.staticField;
      +
      +public class CPoolRefClassContainingInlinedCts {
      +
      +    public static void main(String args[]) throws Exception {
      +        new CPoolRefClassContainingInlinedCts().run();
      +    }
      +
      +    void run() throws Exception {
      +        checkReferences();
      +    }
      +
      +    int numberOfReferencedClassesToBeChecked = 0;
      +
      +    void checkClassName(String className) {
      +        switch (className) {
      +            case "SimpleAssignClass" : case "BinaryExpClass":
      +            case "UnaryExpClass" : case "CastClass":
      +            case "ParensClass" : case "CondClass":
      +            case "IfClass" : case "pkg/ClassToBeStaticallyImported":
      +                numberOfReferencedClassesToBeChecked++;
      +        }
      +    }
      +
      +    void checkReferences() throws IOException, ConstantPoolException {
      +        File testClasses = new File(System.getProperty("test.classes"));
      +        File file = new File(testClasses,
      +                CPoolRefClassContainingInlinedCts.class.getName() + ".class");
      +        ClassFile classFile = ClassFile.read(file);
      +        int i = 1;
      +        CPInfo cpInfo;
      +        while (i < classFile.constant_pool.size()) {
      +            cpInfo = classFile.constant_pool.get(i);
      +            if (cpInfo instanceof CONSTANT_Class_info) {
      +                checkClassName(((CONSTANT_Class_info)cpInfo).getName());
      +            }
      +            i += cpInfo.size();
      +        }
      +        if (numberOfReferencedClassesToBeChecked != 8) {
      +            throw new AssertionError("Class reference missing in the constant pool");
      +        }
      +    }
      +
      +    private int assign = SimpleAssignClass.x;
      +    private int binary = BinaryExpClass.x + 1;
      +    private int unary = -UnaryExpClass.x;
      +    private int cast = (int)CastClass.x;
      +    private int parens = (ParensClass.x);
      +    private int cond = (CondClass.x == 1) ? 1 : 2;
      +    private static int ifConstant;
      +    private static int importStatic;
      +    static {
      +        if (IfClass.x == 1) {
      +            ifConstant = 1;
      +        } else {
      +            ifConstant = 2;
      +        }
      +    }
      +    static {
      +        if (staticField == 1) {
      +            importStatic = 1;
      +        } else {
      +            importStatic = 2;
      +        }
      +    }
      +}
      +
      +class SimpleAssignClass {
      +    public static final int x = 1;
      +}
      +
      +class BinaryExpClass {
      +    public static final int x = 1;
      +}
      +
      +class UnaryExpClass {
      +    public static final int x = 1;
      +}
      +
      +class CastClass {
      +    public static final int x = 1;
      +}
      +
      +class ParensClass {
      +    public static final int x = 1;
      +}
      +
      +class CondClass {
      +    public static final int x = 1;
      +}
      +
      +class IfClass {
      +    public static final int x = 1;
      +}
      diff --git a/langtools/test/tools/javac/7153958/pkg/ClassToBeStaticallyImported.java b/langtools/test/tools/javac/7153958/pkg/ClassToBeStaticallyImported.java
      new file mode 100644
      index 00000000000..801098d0293
      --- /dev/null
      +++ b/langtools/test/tools/javac/7153958/pkg/ClassToBeStaticallyImported.java
      @@ -0,0 +1,29 @@
      +/*
      + * 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.  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 pkg;
      +
      +public class ClassToBeStaticallyImported {
      +    public static final int staticField = 1;
      +}
      diff --git a/langtools/test/tools/javac/T8003967/DetectMutableStaticFields.java b/langtools/test/tools/javac/T8003967/DetectMutableStaticFields.java
      new file mode 100644
      index 00000000000..c419cd3332e
      --- /dev/null
      +++ b/langtools/test/tools/javac/T8003967/DetectMutableStaticFields.java
      @@ -0,0 +1,242 @@
      +/*
      + * Copyright (c) 2006, 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.
      + */
      +
      +/*
      + * @test
      + * @bug 8003967
      + * @summary detect and remove all mutable implicit static enum fields in langtools
      + * @run main DetectMutableStaticFields
      + */
      +
      +import java.io.File;
      +import java.io.IOException;
      +import java.net.URI;
      +import java.net.URISyntaxException;
      +import java.util.ArrayList;
      +import java.util.Arrays;
      +import java.util.EnumSet;
      +import java.util.HashMap;
      +import java.util.List;
      +import java.util.Map;
      +import javax.tools.JavaCompiler;
      +import javax.tools.JavaFileManager;
      +import javax.tools.JavaFileObject;
      +import javax.tools.StandardJavaFileManager;
      +import javax.tools.StandardLocation;
      +import javax.tools.ToolProvider;
      +import com.sun.tools.classfile.ClassFile;
      +import com.sun.tools.classfile.ConstantPoolException;
      +import com.sun.tools.classfile.Descriptor;
      +import com.sun.tools.classfile.Descriptor.InvalidDescriptor;
      +import com.sun.tools.classfile.Field;
      +
      +import static javax.tools.JavaFileObject.Kind.CLASS;
      +import static com.sun.tools.classfile.AccessFlags.ACC_ENUM;
      +import static com.sun.tools.classfile.AccessFlags.ACC_FINAL;
      +import static com.sun.tools.classfile.AccessFlags.ACC_STATIC;
      +
      +public class DetectMutableStaticFields {
      +
      +    private static final String keyResource =
      +            "com/sun/tools/javac/tree/JCTree.class";
      +
      +    private String[] packagesToSeekFor = new String[] {
      +        "javax.tools",
      +        "javax.lang.model",
      +        "com.sun.javadoc",
      +        "com.sun.source",
      +        "com.sun.tools.classfile",
      +        "com.sun.tools.doclets",
      +        "com.sun.tools.javac",
      +        "com.sun.tools.javadoc",
      +        "com.sun.tools.javah",
      +        "com.sun.tools.javap",
      +    };
      +
      +    private static final Map> classFieldsToIgnoreMap = new HashMap<>();
      +
      +    static {
      +        classFieldsToIgnoreMap.
      +                put("javax/tools/ToolProvider",
      +                    Arrays.asList("instance"));
      +        classFieldsToIgnoreMap.
      +                put("com/sun/tools/javah/JavahTask",
      +                    Arrays.asList("versionRB"));
      +        classFieldsToIgnoreMap.
      +                put("com/sun/tools/classfile/Dependencies$DefaultFilter",
      +                    Arrays.asList("instance"));
      +        classFieldsToIgnoreMap.
      +                put("com/sun/tools/javap/JavapTask",
      +                    Arrays.asList("versionRB"));
      +        classFieldsToIgnoreMap.
      +                put("com/sun/tools/doclets/formats/html/HtmlDoclet",
      +                    Arrays.asList("docletToStart"));
      +        classFieldsToIgnoreMap.
      +                put("com/sun/tools/javac/util/JCDiagnostic",
      +                    Arrays.asList("fragmentFormatter"));
      +        classFieldsToIgnoreMap.
      +                put("com/sun/tools/javac/util/JavacMessages",
      +                    Arrays.asList("defaultBundle", "defaultMessages"));
      +        classFieldsToIgnoreMap.
      +                put("com/sun/tools/javac/file/ZipFileIndexCache",
      +                    Arrays.asList("sharedInstance"));
      +        classFieldsToIgnoreMap.
      +                put("com/sun/tools/javac/main/JavaCompiler",
      +                    Arrays.asList("versionRB"));
      +        classFieldsToIgnoreMap.
      +                put("com/sun/tools/javac/code/Type",
      +                    Arrays.asList("moreInfo"));
      +        classFieldsToIgnoreMap.
      +                put("com/sun/tools/javac/util/SharedNameTable",
      +                    Arrays.asList("freelist"));
      +        classFieldsToIgnoreMap.
      +                put("com/sun/tools/javac/util/Log",
      +                    Arrays.asList("useRawMessages"));
      +    }
      +
      +    private List errors = new ArrayList<>();
      +
      +    public static void main(String[] args) {
      +        try {
      +            new DetectMutableStaticFields().run();
      +        } catch (Exception ex) {
      +            throw new AssertionError(
      +                    "Exception during test execution with cause ",
      +                    ex.getCause());
      +        }
      +    }
      +
      +    private void run()
      +        throws
      +            IOException,
      +            ConstantPoolException,
      +            InvalidDescriptor,
      +            URISyntaxException {
      +
      +        URI resource = findResource(keyResource);
      +        if (resource == null) {
      +            throw new AssertionError("Resource " + keyResource +
      +                "not found in the class path");
      +        }
      +        analyzeResource(resource);
      +
      +        if (errors.size() > 0) {
      +            for (String error: errors) {
      +                System.err.println(error);
      +            }
      +            throw new AssertionError("There are mutable fields, "
      +                + "please check output");
      +        }
      +    }
      +
      +    URI findResource(String className) throws URISyntaxException {
      +        URI uri = getClass().getClassLoader().getResource(className).toURI();
      +        if (uri.getScheme().equals("jar")) {
      +            String ssp = uri.getRawSchemeSpecificPart();
      +            int sep = ssp.lastIndexOf("!");
      +            uri = new URI(ssp.substring(0, sep));
      +        } else if (uri.getScheme().equals("file")) {
      +            uri = new URI(uri.getPath().substring(0,
      +                    uri.getPath().length() - keyResource.length()));
      +        }
      +        return uri;
      +    }
      +
      +    boolean shouldAnalyzePackage(String packageName) {
      +        for (String aPackage: packagesToSeekFor) {
      +            if (packageName.contains(aPackage)) {
      +                return true;
      +            }
      +        }
      +        return false;
      +    }
      +
      +    void analyzeResource(URI resource)
      +        throws
      +            IOException,
      +            ConstantPoolException,
      +            InvalidDescriptor {
      +        JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
      +        StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null);
      +        JavaFileManager.Location location =
      +                StandardLocation.locationFor(resource.getPath());
      +        fm.setLocation(location, com.sun.tools.javac.util.List.of(
      +                new File(resource.getPath())));
      +
      +        for (JavaFileObject file : fm.list(location, "", EnumSet.of(CLASS), true)) {
      +            String className = fm.inferBinaryName(location, file);
      +            int index = className.lastIndexOf('.');
      +            String pckName = index == -1 ? "" : className.substring(0, index);
      +            if (shouldAnalyzePackage(pckName)) {
      +                analyzeClassFile(ClassFile.read(file.openInputStream()));
      +            }
      +        }
      +    }
      +
      +    List currentFieldsToIgnore;
      +
      +    boolean ignoreField(String field) {
      +        if (currentFieldsToIgnore != null) {
      +            for (String fieldToIgnore : currentFieldsToIgnore) {
      +                if (field.equals(fieldToIgnore)) {
      +                    return true;
      +                }
      +            }
      +        }
      +        return false;
      +    }
      +
      +    void analyzeClassFile(ClassFile classFileToCheck)
      +        throws
      +            IOException,
      +            ConstantPoolException,
      +            Descriptor.InvalidDescriptor {
      +        boolean enumClass =
      +                (classFileToCheck.access_flags.flags & ACC_ENUM) != 0;
      +        boolean nonFinalStaticEnumField;
      +        boolean nonFinalStaticField;
      +
      +        currentFieldsToIgnore =
      +                classFieldsToIgnoreMap.get(classFileToCheck.getName());
      +
      +        for (Field field : classFileToCheck.fields) {
      +            if (ignoreField(field.getName(classFileToCheck.constant_pool))) {
      +                continue;
      +            }
      +            nonFinalStaticEnumField =
      +                    (field.access_flags.flags & (ACC_ENUM | ACC_FINAL)) == 0;
      +            nonFinalStaticField =
      +                    (field.access_flags.flags & ACC_STATIC) != 0 &&
      +                    (field.access_flags.flags & ACC_FINAL) == 0;
      +            if (enumClass ? nonFinalStaticEnumField : nonFinalStaticField) {
      +                errors.add("There is a mutable field named " +
      +                        field.getName(classFileToCheck.constant_pool) +
      +                        ", at class " +
      +                        classFileToCheck.getName());
      +            }
      +        }
      +    }
      +
      +}
      diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase1.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase1.java
      index a994aa8cf77..c29d0e8afa7 100644
      --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase1.java
      +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase1.java
      @@ -20,4 +20,3 @@ import java.lang.annotation.ContainerFor;
       
       @Foo @Foo
       public class MissingDefaultCase1 {}
      -
      diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase1.out b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase1.out
      index 9724b370b4d..ae188503866 100644
      --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase1.out
      +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase1.out
      @@ -1,2 +1,3 @@
      +MissingDefaultCase1.java:21:1: compiler.err.duplicate.annotation.invalid.repeated: Foo
       MissingDefaultCase1.java:12:1: compiler.err.invalid.containedby.annotation.elem.nondefault: FooContainer, other()
      -1 error
      +2 errors
      diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase2.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase2.java
      index bd50b909cb4..b0b42b40cfc 100644
      --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase2.java
      +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase2.java
      @@ -20,4 +20,3 @@ import java.lang.annotation.ContainerFor;
       
       @Foo @Foo
       public class MissingDefaultCase2 {}
      -
      diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase2.out b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase2.out
      index 13d93f2f7c6..7e3a4229587 100644
      --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase2.out
      +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingDefaultCase2.out
      @@ -1,2 +1,3 @@
      +MissingDefaultCase2.java:21:1: compiler.err.duplicate.annotation.invalid.repeated: Foo
       MissingDefaultCase2.java:12:1: compiler.err.invalid.containedby.annotation.elem.nondefault: FooContainer, other()
      -1 error
      +2 errors
      diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/NoRepeatableAnno.out b/langtools/test/tools/javac/annotations/repeatingAnnotations/NoRepeatableAnno.out
      index df37cdd1852..42a8105b79d 100644
      --- a/langtools/test/tools/javac/annotations/repeatingAnnotations/NoRepeatableAnno.out
      +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/NoRepeatableAnno.out
      @@ -1,3 +1,3 @@
      -NoRepeatableAnno.java:11:1: compiler.err.duplicate.annotation.missing.container: Foo
      -NoRepeatableAnno.java:11:6: compiler.err.duplicate.annotation.missing.container: Foo
      +NoRepeatableAnno.java:11:1: compiler.err.duplicate.annotation.missing.container: Foo, java.lang.annotation.ContainedBy
      +NoRepeatableAnno.java:11:6: compiler.err.duplicate.annotation.missing.container: Foo, java.lang.annotation.ContainedBy
       2 errors
      diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingTargetNotAllowed.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingTargetNotAllowed.java
      new file mode 100644
      index 00000000000..7210b3f573b
      --- /dev/null
      +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingTargetNotAllowed.java
      @@ -0,0 +1,45 @@
      +/*
      + * 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.
      + */
      +
      +/**
      + * @test
      + * @summary Container annotation is not checked for semantic correctness
      + * @bug 8001114
      + *
      + * @compile/fail/ref=RepeatingTargetNotAllowed.out -XDrawDiagnostics RepeatingTargetNotAllowed.java
      + */
      +
      +import java.lang.annotation.*;
      +
      +@ContainedBy(Foos.class)
      +@interface Foo {}
      +
      +@ContainerFor(Foo.class)
      +@Target(ElementType.ANNOTATION_TYPE)
      +@interface Foos {
      +    Foo[] value();
      +}
      +
      +public class RepeatingTargetNotAllowed {
      +    @Foo @Foo int f = 0;
      +}
      diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingTargetNotAllowed.out b/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingTargetNotAllowed.out
      new file mode 100644
      index 00000000000..fd4b6acc4cc
      --- /dev/null
      +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingTargetNotAllowed.out
      @@ -0,0 +1,2 @@
      +RepeatingTargetNotAllowed.java:44:5: compiler.err.invalid.containedby.annotation.incompatible.target: Foos, Foo
      +1 error
      diff --git a/langtools/test/tools/javac/cast/intersection/IntersectionTypeCastTest.java b/langtools/test/tools/javac/cast/intersection/IntersectionTypeCastTest.java
      new file mode 100644
      index 00000000000..b82e1babf34
      --- /dev/null
      +++ b/langtools/test/tools/javac/cast/intersection/IntersectionTypeCastTest.java
      @@ -0,0 +1,330 @@
      +/*
      + * 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.
      + */
      +
      +/*
      + * @test
      + * @bug 8002099
      + * @summary Add support for intersection types in cast expression
      + */
      +
      +import com.sun.source.util.JavacTask;
      +import com.sun.tools.javac.util.List;
      +import com.sun.tools.javac.util.ListBuffer;
      +import java.net.URI;
      +import java.util.Arrays;
      +import javax.tools.Diagnostic;
      +import javax.tools.JavaCompiler;
      +import javax.tools.JavaFileObject;
      +import javax.tools.SimpleJavaFileObject;
      +import javax.tools.StandardJavaFileManager;
      +import javax.tools.ToolProvider;
      +
      +public class IntersectionTypeCastTest {
      +
      +    static int checkCount = 0;
      +
      +    interface Type {
      +        boolean subtypeOf(Type that);
      +        String asString();
      +        boolean isClass();
      +        boolean isInterface();
      +    }
      +
      +    enum InterfaceKind implements Type {
      +        A("interface A { }\n", "A", null),
      +        B("interface B { }\n", "B", null),
      +        C("interface C extends A { }\n", "C", A);
      +
      +        String declStr;
      +        String typeStr;
      +        InterfaceKind superInterface;
      +
      +        InterfaceKind(String declStr, String typeStr, InterfaceKind superInterface) {
      +            this.declStr = declStr;
      +            this.typeStr = typeStr;
      +            this.superInterface = superInterface;
      +        }
      +
      +        @Override
      +        public boolean subtypeOf(Type that) {
      +            return this == that || superInterface == that || that == ClassKind.OBJECT;
      +        }
      +
      +        @Override
      +        public String asString() {
      +            return typeStr;
      +        }
      +
      +        @Override
      +        public boolean isClass() {
      +            return false;
      +        }
      +
      +        @Override
      +        public boolean isInterface() {
      +            return true;
      +        }
      +    }
      +
      +    enum ClassKind implements Type {
      +        OBJECT(null, "Object"),
      +        CA("#M class CA implements A { }\n", "CA", InterfaceKind.A),
      +        CB("#M class CB implements B { }\n", "CB", InterfaceKind.B),
      +        CAB("#M class CAB implements A, B { }\n", "CAB", InterfaceKind.A, InterfaceKind.B),
      +        CC("#M class CC implements C { }\n", "CC", InterfaceKind.C, InterfaceKind.A),
      +        CCA("#M class CCA implements C, A { }\n", "CCA", InterfaceKind.C, InterfaceKind.A),
      +        CCB("#M class CCB implements C, B { }\n", "CCB", InterfaceKind.C, InterfaceKind.A, InterfaceKind.B),
      +        CCAB("#M class CCAB implements C, A, B { }\n", "CCAB", InterfaceKind.C, InterfaceKind.A, InterfaceKind.B);
      +
      +        String declTemplate;
      +        String typeStr;
      +        List superInterfaces;
      +
      +        ClassKind(String declTemplate, String typeStr, InterfaceKind... superInterfaces) {
      +            this.declTemplate = declTemplate;
      +            this.typeStr = typeStr;
      +            this.superInterfaces = List.from(superInterfaces);
      +        }
      +
      +        String getDecl(ModifierKind mod) {
      +            return declTemplate != null ?
      +                    declTemplate.replaceAll("#M", mod.modStr) :
      +                    "";
      +        }
      +
      +        @Override
      +        public boolean subtypeOf(Type that) {
      +            return this == that || superInterfaces.contains(that) || that == OBJECT;
      +        }
      +
      +        @Override
      +        public String asString() {
      +            return typeStr;
      +        }
      +
      +        @Override
      +        public boolean isClass() {
      +            return true;
      +        }
      +
      +        @Override
      +        public boolean isInterface() {
      +            return false;
      +        }
      +    }
      +
      +    enum ModifierKind {
      +        NONE(""),
      +        FINAL("final");
      +
      +        String modStr;
      +
      +        ModifierKind(String modStr) {
      +            this.modStr = modStr;
      +        }
      +    }
      +
      +    enum CastKind {
      +        CLASS("(#C)", 0),
      +        INTERFACE("(#I0)", 1),
      +        INTERSECTION2("(#C & #I0)", 1),
      +        INTERSECTION3("(#C & #I0 & #I1)", 2);
      +        //INTERSECTION4("(#C & #I0 & #I1 & #I2)", 3);
      +
      +        String castTemplate;
      +        int interfaceBounds;
      +
      +        CastKind(String castTemplate, int interfaceBounds) {
      +            this.castTemplate = castTemplate;
      +            this.interfaceBounds = interfaceBounds;
      +        }
      +    }
      +
      +    static class CastInfo {
      +        CastKind kind;
      +        Type[] types;
      +
      +        CastInfo(CastKind kind, Type... types) {
      +            this.kind = kind;
      +            this.types = types;
      +        }
      +
      +        String getCast() {
      +            String temp = kind.castTemplate.replaceAll("#C", types[0].asString());
      +            for (int i = 0; i < kind.interfaceBounds ; i++) {
      +                temp = temp.replace(String.format("#I%d", i), types[i + 1].asString());
      +            }
      +            return temp;
      +        }
      +
      +        boolean hasDuplicateTypes() {
      +            for (int i = 0 ; i < types.length ; i++) {
      +                for (int j = 0 ; j < types.length ; j++) {
      +                    if (i != j && types[i] == types[j]) {
      +                        return true;
      +                    }
      +                }
      +            }
      +            return false;
      +        }
      +
      +        boolean compatibleWith(ModifierKind mod, CastInfo that) {
      +            for (Type t1 : types) {
      +                for (Type t2 : that.types) {
      +                    boolean compat =
      +                            t1.subtypeOf(t2) ||
      +                            t2.subtypeOf(t1) ||
      +                            (t1.isInterface() && t2.isInterface()) || //side-cast (1)
      +                            (mod == ModifierKind.NONE && (t1.isInterface() != t2.isInterface())); //side-cast (2)
      +                    if (!compat) return false;
      +                }
      +            }
      +            return true;
      +        }
      +    }
      +
      +    public static void main(String... args) throws Exception {
      +        //create default shared JavaCompiler - reused across multiple compilations
      +        JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
      +        StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
      +
      +        for (ModifierKind mod : ModifierKind.values()) {
      +            for (CastInfo cast1 : allCastInfo()) {
      +                for (CastInfo cast2 : allCastInfo()) {
      +                    new IntersectionTypeCastTest(mod, cast1, cast2).run(comp, fm);
      +                }
      +            }
      +        }
      +        System.out.println("Total check executed: " + checkCount);
      +    }
      +
      +    static List allCastInfo() {
      +        ListBuffer buf = ListBuffer.lb();
      +        for (CastKind kind : CastKind.values()) {
      +            for (ClassKind clazz : ClassKind.values()) {
      +                if (kind == CastKind.INTERFACE && clazz != ClassKind.OBJECT) {
      +                    continue;
      +                } else if (kind.interfaceBounds == 0) {
      +                    buf.append(new CastInfo(kind, clazz));
      +                    continue;
      +                } else {
      +                    for (InterfaceKind intf1 : InterfaceKind.values()) {
      +                        if (kind.interfaceBounds == 1) {
      +                            buf.append(new CastInfo(kind, clazz, intf1));
      +                            continue;
      +                        } else {
      +                            for (InterfaceKind intf2 : InterfaceKind.values()) {
      +                                if (kind.interfaceBounds == 2) {
      +                                    buf.append(new CastInfo(kind, clazz, intf1, intf2));
      +                                    continue;
      +                                } else {
      +                                    for (InterfaceKind intf3 : InterfaceKind.values()) {
      +                                        buf.append(new CastInfo(kind, clazz, intf1, intf2, intf3));
      +                                        continue;
      +                                    }
      +                                }
      +                            }
      +                        }
      +                    }
      +                }
      +            }
      +        }
      +        return buf.toList();
      +    }
      +
      +    ModifierKind mod;
      +    CastInfo cast1, cast2;
      +    JavaSource source;
      +    DiagnosticChecker diagChecker;
      +
      +    IntersectionTypeCastTest(ModifierKind mod, CastInfo cast1, CastInfo cast2) {
      +        this.mod = mod;
      +        this.cast1 = cast1;
      +        this.cast2 = cast2;
      +        this.source = new JavaSource();
      +        this.diagChecker = new DiagnosticChecker();
      +    }
      +
      +    class JavaSource extends SimpleJavaFileObject {
      +
      +        String bodyTemplate = "class Test {\n" +
      +                              "   void test() {\n" +
      +                              "      Object o = #C1#C2null;\n" +
      +                              "   } }";
      +
      +        String source = "";
      +
      +        public JavaSource() {
      +            super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
      +            for (ClassKind ck : ClassKind.values()) {
      +                source += ck.getDecl(mod);
      +            }
      +            for (InterfaceKind ik : InterfaceKind.values()) {
      +                source += ik.declStr;
      +            }
      +            source += bodyTemplate.replaceAll("#C1", cast1.getCast()).replaceAll("#C2", cast2.getCast());
      +        }
      +
      +        @Override
      +        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
      +            return source;
      +        }
      +    }
      +
      +    void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception {
      +        JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker,
      +                Arrays.asList("-XDallowIntersectionTypes"), null, Arrays.asList(source));
      +        try {
      +            ct.analyze();
      +        } catch (Throwable ex) {
      +            throw new AssertionError("Error thrown when compiling the following code:\n" + source.getCharContent(true));
      +        }
      +        check();
      +    }
      +
      +    void check() {
      +        checkCount++;
      +
      +        boolean errorExpected = cast1.hasDuplicateTypes() || cast2.hasDuplicateTypes();
      +
      +        errorExpected |= !cast2.compatibleWith(mod, cast1);
      +
      +        if (errorExpected != diagChecker.errorFound) {
      +            throw new Error("invalid diagnostics for source:\n" +
      +                source.getCharContent(true) +
      +                "\nFound error: " + diagChecker.errorFound +
      +                "\nExpected error: " + errorExpected);
      +        }
      +    }
      +
      +    static class DiagnosticChecker implements javax.tools.DiagnosticListener {
      +
      +        boolean errorFound;
      +
      +        public void report(Diagnostic diagnostic) {
      +            if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
      +                errorFound = true;
      +            }
      +        }
      +    }
      +}
      diff --git a/langtools/test/tools/javac/cast/intersection/IntersectionTypeParserTest.java b/langtools/test/tools/javac/cast/intersection/IntersectionTypeParserTest.java
      new file mode 100644
      index 00000000000..7f113900bc6
      --- /dev/null
      +++ b/langtools/test/tools/javac/cast/intersection/IntersectionTypeParserTest.java
      @@ -0,0 +1,191 @@
      +/*
      + * 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.
      + */
      +
      +/*
      + * @test
      + * @bug 8002099
      + * @summary Add support for intersection types in cast expression
      + */
      +
      +import com.sun.source.util.JavacTask;
      +import java.net.URI;
      +import java.util.Arrays;
      +import javax.tools.Diagnostic;
      +import javax.tools.JavaCompiler;
      +import javax.tools.JavaFileObject;
      +import javax.tools.SimpleJavaFileObject;
      +import javax.tools.StandardJavaFileManager;
      +import javax.tools.ToolProvider;
      +
      +public class IntersectionTypeParserTest {
      +
      +    static int checkCount = 0;
      +
      +    enum TypeKind {
      +        SIMPLE("A"),
      +        GENERIC("A"),
      +        WILDCARD("A");
      +
      +        String typeStr;
      +
      +        TypeKind(String typeStr) {
      +            this.typeStr = typeStr;
      +        }
      +    }
      +
      +    enum ArrayKind {
      +        NONE(""),
      +        SINGLE("[]"),
      +        DOUBLE("[][]");
      +
      +        String arrStr;
      +
      +        ArrayKind(String arrStr) {
      +            this.arrStr = arrStr;
      +        }
      +    }
      +
      +    static class Type {
      +        TypeKind tk;
      +        ArrayKind ak;
      +
      +        Type(TypeKind tk, ArrayKind ak) {
      +            this.tk = tk;
      +            this.ak = ak;
      +        }
      +
      +        String asString() {
      +            return tk.typeStr + ak.arrStr;
      +        }
      +    }
      +
      +    enum CastKind {
      +        ONE("(#T0)", 1),
      +        TWO("(#T0 & T1)", 2),
      +        THREE("(#T0 & #T1 & #T2)", 3);
      +
      +        String castTemplate;
      +        int nBounds;
      +
      +        CastKind(String castTemplate, int nBounds) {
      +            this.castTemplate = castTemplate;
      +            this.nBounds = nBounds;
      +        }
      +
      +        String asString(Type... types) {
      +            String res = castTemplate;
      +            for (int i = 0; i < nBounds ; i++) {
      +                res = res.replaceAll(String.format("#T%d", i), types[i].asString());
      +            }
      +            return res;
      +        }
      +    }
      +
      +    public static void main(String... args) throws Exception {
      +        //create default shared JavaCompiler - reused across multiple compilations
      +        JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
      +        StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
      +
      +        for (CastKind ck : CastKind.values()) {
      +            for (TypeKind t1 : TypeKind.values()) {
      +                for (ArrayKind ak1 : ArrayKind.values()) {
      +                    Type typ1 = new Type(t1, ak1);
      +                    if (ck.nBounds == 1) {
      +                        new IntersectionTypeParserTest(ck, typ1).run(comp, fm);
      +                        continue;
      +                    }
      +                    for (TypeKind t2 : TypeKind.values()) {
      +                        for (ArrayKind ak2 : ArrayKind.values()) {
      +                            Type typ2 = new Type(t2, ak2);
      +                            if (ck.nBounds == 2) {
      +                                new IntersectionTypeParserTest(ck, typ1, typ2).run(comp, fm);
      +                                continue;
      +                            }
      +                            for (TypeKind t3 : TypeKind.values()) {
      +                                for (ArrayKind ak3 : ArrayKind.values()) {
      +                                    Type typ3 = new Type(t3, ak3);
      +                                    new IntersectionTypeParserTest(ck, typ1, typ2, typ3).run(comp, fm);
      +                                }
      +                            }
      +                        }
      +                    }
      +                }
      +            }
      +        }
      +        System.out.println("Total check executed: " + checkCount);
      +    }
      +
      +    CastKind ck;
      +    Type[] types;
      +    JavaSource source;
      +    DiagnosticChecker diagChecker;
      +
      +    IntersectionTypeParserTest(CastKind ck, Type... types) {
      +        this.ck = ck;
      +        this.types = types;
      +        this.source = new JavaSource();
      +        this.diagChecker = new DiagnosticChecker();
      +    }
      +
      +    class JavaSource extends SimpleJavaFileObject {
      +
      +        String bodyTemplate = "class Test {\n" +
      +                              "   void test() {\n" +
      +                              "      Object o = #Cnull;\n" +
      +                              "   } }";
      +
      +        String source = "";
      +
      +        public JavaSource() {
      +            super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
      +            source += bodyTemplate.replaceAll("#C", ck.asString(types));
      +        }
      +
      +        @Override
      +        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
      +            return source;
      +        }
      +    }
      +
      +    void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception {
      +        checkCount++;
      +        JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker,
      +                Arrays.asList("-XDallowIntersectionTypes"), null, Arrays.asList(source));
      +        ct.parse();
      +        if (diagChecker.errorFound) {
      +            throw new Error("Unexpected parser error for source:\n" +
      +                source.getCharContent(true));
      +        }
      +    }
      +
      +    static class DiagnosticChecker implements javax.tools.DiagnosticListener {
      +
      +        boolean errorFound;
      +
      +        public void report(Diagnostic diagnostic) {
      +            if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
      +                errorFound = true;
      +            }
      +        }
      +    }
      +}
      diff --git a/langtools/test/tools/javac/cast/intersection/model/Check.java b/langtools/test/tools/javac/cast/intersection/model/Check.java
      new file mode 100644
      index 00000000000..d47a6fd792f
      --- /dev/null
      +++ b/langtools/test/tools/javac/cast/intersection/model/Check.java
      @@ -0,0 +1,27 @@
      +/*
      + * 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.
      + */
      +
      +/**
      + * Annotation used by ModelChecker to mark the class whose model is to be checked
      + */
      +@interface Check {}
      diff --git a/langtools/test/tools/javac/cast/intersection/model/IntersectionTypeInfo.java b/langtools/test/tools/javac/cast/intersection/model/IntersectionTypeInfo.java
      new file mode 100644
      index 00000000000..bed6fc023a2
      --- /dev/null
      +++ b/langtools/test/tools/javac/cast/intersection/model/IntersectionTypeInfo.java
      @@ -0,0 +1,29 @@
      +/*
      + * 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.
      + */
      +
      +/**
      + * Used by ModelChecker to validate the modeling information of a union type.
      + */
      +@interface IntersectionTypeInfo {
      +    String[] value();
      +}
      diff --git a/langtools/test/tools/javac/cast/intersection/model/Member.java b/langtools/test/tools/javac/cast/intersection/model/Member.java
      new file mode 100644
      index 00000000000..ee14474e74d
      --- /dev/null
      +++ b/langtools/test/tools/javac/cast/intersection/model/Member.java
      @@ -0,0 +1,31 @@
      +/*
      + * 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.
      + */
      +
      +import javax.lang.model.element.ElementKind;
      +
      +/**
      + * Annotation used by ModelChecker to mark a member that is to be checked
      + */
      +@interface Member {
      +   ElementKind value();
      +}
      diff --git a/langtools/test/tools/javac/cast/intersection/model/Model01.java b/langtools/test/tools/javac/cast/intersection/model/Model01.java
      new file mode 100644
      index 00000000000..1809d6228d2
      --- /dev/null
      +++ b/langtools/test/tools/javac/cast/intersection/model/Model01.java
      @@ -0,0 +1,52 @@
      +/*
      + * 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.
      + */
      +
      +/*
      + * @test
      + * @bug 8002099
      + * @summary Add support for intersection types in cast expression
      + * @library ../../../lib
      + * @build JavacTestingAbstractProcessor ModelChecker
      + * @compile -XDallowIntersectionTypes -processor ModelChecker Model01.java
      + */
      +
      +import javax.lang.model.element.ElementKind;
      +
      +@Check
      +class Test {
      +
      +    interface A {
      +        @Member(ElementKind.METHOD)
      +        public void m1();
      +    }
      +
      +    interface B {
      +        @Member(ElementKind.METHOD)
      +        public void m2();
      +    }
      +
      +    void test(){
      +        @IntersectionTypeInfo({"java.lang.Object", "Test.A", "Test.B"})
      +        Object o = (A & B)null;
      +    }
      +}
      diff --git a/langtools/test/tools/javac/cast/intersection/model/ModelChecker.java b/langtools/test/tools/javac/cast/intersection/model/ModelChecker.java
      new file mode 100644
      index 00000000000..1486d21bf1b
      --- /dev/null
      +++ b/langtools/test/tools/javac/cast/intersection/model/ModelChecker.java
      @@ -0,0 +1,153 @@
      +/*
      + * 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.
      + */
      +
      +import com.sun.source.tree.ExpressionTree;
      +import com.sun.source.tree.Tree;
      +import com.sun.source.tree.TypeCastTree;
      +import com.sun.source.tree.VariableTree;
      +import com.sun.source.util.TreePathScanner;
      +import com.sun.source.util.Trees;
      +import com.sun.source.util.TreePath;
      +import com.sun.tools.javac.tree.JCTree.JCExpression;
      +
      +import java.util.Set;
      +
      +import javax.annotation.processing.RoundEnvironment;
      +import javax.annotation.processing.SupportedAnnotationTypes;
      +import javax.lang.model.element.Element;
      +import javax.lang.model.element.TypeElement;
      +import javax.lang.model.type.TypeMirror;
      +import javax.lang.model.type.TypeKind;
      +import javax.lang.model.type.IntersectionType;
      +import javax.lang.model.type.UnknownTypeException;
      +import javax.lang.model.util.SimpleTypeVisitor6;
      +import javax.lang.model.util.SimpleTypeVisitor7;
      +
      +@SupportedAnnotationTypes("Check")
      +public class ModelChecker extends JavacTestingAbstractProcessor {
      +
      +    @Override
      +    public boolean process(Set annotations, RoundEnvironment roundEnv) {
      +        if (roundEnv.processingOver())
      +            return true;
      +
      +        Trees trees = Trees.instance(processingEnv);
      +
      +        TypeElement testAnno = elements.getTypeElement("Check");
      +        for (Element elem: roundEnv.getElementsAnnotatedWith(testAnno)) {
      +            TreePath p = trees.getPath(elem);
      +            new IntersectionCastTester(trees).scan(p, null);
      +        }
      +        return true;
      +    }
      +
      +    class IntersectionCastTester extends TreePathScanner {
      +        Trees trees;
      +
      +        public IntersectionCastTester(Trees trees) {
      +            super();
      +            this.trees = trees;
      +        }
      +
      +        @Override
      +        public Void visitVariable(VariableTree node, Void p) {
      +
      +            TreePath varPath = new TreePath(getCurrentPath(), node);
      +            Element v = trees.getElement(varPath);
      +
      +            IntersectionTypeInfo it = v.getAnnotation(IntersectionTypeInfo.class);
      +            assertTrue(it != null, "IntersectionType annotation must be present");
      +
      +            ExpressionTree varInit = node.getInitializer();
      +            assertTrue(varInit != null && varInit.getKind() == Tree.Kind.TYPE_CAST,
      +                    "variable must have be initialized to an expression containing an intersection type cast");
      +
      +            TypeMirror t = ((JCExpression)((TypeCastTree)varInit).getType()).type;
      +
      +            validateIntersectionTypeInfo(t, it);
      +
      +            for (Element e2 : types.asElement(t).getEnclosedElements()) {
      +                assertTrue(false, "an intersection type has no declared members");
      +            }
      +
      +            for (Element e2 : elements.getAllMembers((TypeElement)types.asElement(t))) {
      +                Member m = e2.getAnnotation(Member.class);
      +                if (m != null) {
      +                    assertTrue(e2.getKind() == m.value(), "Expected " + m.value() + " - found " + e2.getKind());
      +                }
      +            }
      +
      +            assertTrue(assertionCount == 10, "Expected 10 assertions - found " + assertionCount);
      +            return super.visitVariable(node, p);
      +        }
      +    }
      +
      +    private void validateIntersectionTypeInfo(TypeMirror expectedIntersectionType, IntersectionTypeInfo it) {
      +
      +        assertTrue(expectedIntersectionType.getKind() == TypeKind.INTERSECTION, "INTERSECTION kind expected");
      +
      +        try {
      +            new SimpleTypeVisitor6(){}.visit(expectedIntersectionType);
      +            throw new RuntimeException("Expected UnknownTypeException not thrown.");
      +        } catch (UnknownTypeException ute) {
      +            ; // Expected
      +        }
      +
      +        try {
      +            new SimpleTypeVisitor7(){}.visit(expectedIntersectionType);
      +            throw new RuntimeException("Expected UnknownTypeException not thrown.");
      +        } catch (UnknownTypeException ute) {
      +            ; // Expected
      +        }
      +
      +        IntersectionType intersectionType = new SimpleTypeVisitor(){
      +            @Override
      +            protected IntersectionType defaultAction(TypeMirror e, Void p) {return null;}
      +
      +            @Override
      +            public IntersectionType visitIntersection(IntersectionType t, Void p) {return t;}
      +        }.visit(expectedIntersectionType);
      +        assertTrue(intersectionType != null, "Must get a non-null intersection type.");
      +
      +        assertTrue(it.value().length == intersectionType.getBounds().size(), "Cardinalities do not match");
      +
      +        String[] typeNames = it.value();
      +        for(int i = 0; i < typeNames.length; i++) {
      +            TypeMirror typeFromAnnotation = nameToType(typeNames[i]);
      +            assertTrue(types.isSameType(typeFromAnnotation, intersectionType.getBounds().get(i)),
      +                       "Types were not equal.");
      +        }
      +    }
      +
      +    private TypeMirror nameToType(String name) {
      +        return elements.getTypeElement(name).asType();
      +    }
      +
      +    private static void assertTrue(boolean cond, String msg) {
      +        assertionCount++;
      +        if (!cond)
      +            throw new AssertionError(msg);
      +    }
      +
      +    static int assertionCount = 0;
      +}
      diff --git a/langtools/test/tools/javac/defaultMethodExecution/DefaultMethodRegressionTests.java b/langtools/test/tools/javac/defaultMethods/defaultMethodExecution/DefaultMethodRegressionTests.java
      similarity index 99%
      rename from langtools/test/tools/javac/defaultMethodExecution/DefaultMethodRegressionTests.java
      rename to langtools/test/tools/javac/defaultMethods/defaultMethodExecution/DefaultMethodRegressionTests.java
      index e22f44b01d3..124e39c5d1e 100644
      --- a/langtools/test/tools/javac/defaultMethodExecution/DefaultMethodRegressionTests.java
      +++ b/langtools/test/tools/javac/defaultMethods/defaultMethodExecution/DefaultMethodRegressionTests.java
      @@ -25,6 +25,7 @@
       
       /**
        * @test
      + * @ignore 8004360
        * @bug 8003639
        * @summary convert lambda testng tests to jtreg and add them
        * @run testng DefaultMethodRegressionTests
      diff --git a/langtools/test/tools/javac/diags/examples/ContainedByNonDefault.java b/langtools/test/tools/javac/diags/examples/ContainedByNonDefault.java
      index d64b6b31d7c..d6006dedfe3 100644
      --- a/langtools/test/tools/javac/diags/examples/ContainedByNonDefault.java
      +++ b/langtools/test/tools/javac/diags/examples/ContainedByNonDefault.java
      @@ -31,6 +31,4 @@ import java.lang.annotation.*;
       @ContainerFor(Anno.class)
       @interface Annos { Anno[] value(); String foo(); }
       
      -@Anno
      -@Anno
       class ContainedByNonDefault { }
      diff --git a/langtools/test/tools/javac/diags/examples/IntersectionTypesInCastNotSupported.java b/langtools/test/tools/javac/diags/examples/IntersectionTypesInCastNotSupported.java
      new file mode 100644
      index 00000000000..8126a354249
      --- /dev/null
      +++ b/langtools/test/tools/javac/diags/examples/IntersectionTypesInCastNotSupported.java
      @@ -0,0 +1,29 @@
      +/*
      + * 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.
      + */
      +
      +// key: compiler.err.intersection.types.in.cast.not.supported.in.source
      +// options: -source 7 -Xlint:-options
      +
      +interface IntersectionTypesInCastNotSupported {
      +    Object o = (A & B)null;
      +}
      diff --git a/langtools/test/tools/javac/diags/examples/InvalidDuplicateAnnotation.java b/langtools/test/tools/javac/diags/examples/InvalidDuplicateAnnotation.java
      new file mode 100644
      index 00000000000..1dcc0997961
      --- /dev/null
      +++ b/langtools/test/tools/javac/diags/examples/InvalidDuplicateAnnotation.java
      @@ -0,0 +1,40 @@
      +/*
      + * 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.
      + */
      +
      +// key: compiler.err.duplicate.annotation.invalid.repeated
      +// key: compiler.err.invalid.containedby.annotation.elem.nondefault
      +//
      +// We need an almost valid containing annotation. The easiest way to get
      +// one close enough to valid is by forgetting a default.
      +
      +import java.lang.annotation.*;
      +
      +@ContainedBy(Annos.class)
      +@interface Anno { }
      +
      +@ContainerFor(Anno.class)
      +@interface Annos { Anno[] value(); String foo(); }
      +
      +@Anno
      +@Anno
      +class InvalidDuplicateAnnotation { }
      diff --git a/langtools/test/tools/javac/diags/examples/InvalidGenericDescInFunctionalInterface.java b/langtools/test/tools/javac/diags/examples/InvalidGenericLambdaTarget.java
      similarity index 91%
      rename from langtools/test/tools/javac/diags/examples/InvalidGenericDescInFunctionalInterface.java
      rename to langtools/test/tools/javac/diags/examples/InvalidGenericLambdaTarget.java
      index a43795ea1dc..225b5f3cde1 100644
      --- a/langtools/test/tools/javac/diags/examples/InvalidGenericDescInFunctionalInterface.java
      +++ b/langtools/test/tools/javac/diags/examples/InvalidGenericLambdaTarget.java
      @@ -22,9 +22,9 @@
        */
       
       // key: compiler.err.prob.found.req
      -// key: compiler.misc.invalid.generic.desc.in.functional.intf
      +// key: compiler.misc.invalid.generic.lambda.target
       
      -class InvalidGenericDescInFunctionalIntf {
      +class InvalidGenericLambdaTarget {
       
           interface SAM {
                void m();
      diff --git a/langtools/test/tools/javac/diags/examples/SecondaryBoundMustBeMarkerIntf.java b/langtools/test/tools/javac/diags/examples/SecondaryBoundMustBeMarkerIntf.java
      new file mode 100644
      index 00000000000..2520f8fb00c
      --- /dev/null
      +++ b/langtools/test/tools/javac/diags/examples/SecondaryBoundMustBeMarkerIntf.java
      @@ -0,0 +1,30 @@
      +/*
      + * 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.
      + */
      +
      +// key: compiler.err.prob.found.req
      +// key: compiler.misc.secondary.bound.must.be.marker.intf
      +// options: -XDallowIntersectionTypes
      +
      +class SecondaryBoundMustBeMarkerInterface {
      +    Runnable r = (Runnable & Comparable)()->{};
      +}
      diff --git a/langtools/test/tools/javac/diags/examples/StaticBoundMref.java b/langtools/test/tools/javac/diags/examples/StaticBoundMref.java
      new file mode 100644
      index 00000000000..e53ce7d6b6a
      --- /dev/null
      +++ b/langtools/test/tools/javac/diags/examples/StaticBoundMref.java
      @@ -0,0 +1,32 @@
      +/*
      + * 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.
      + */
      +
      +// key: compiler.err.invalid.mref
      +// key: compiler.misc.static.bound.mref
      +
      +class StaticBoundMref {
      +
      +    Runnable r = new StaticBoundMref()::m;
      +
      +    static void m() { }
      +}
      diff --git a/langtools/test/tools/javac/diags/examples/StaticMrefWithTargs.java b/langtools/test/tools/javac/diags/examples/StaticMrefWithTargs.java
      new file mode 100644
      index 00000000000..a033291315e
      --- /dev/null
      +++ b/langtools/test/tools/javac/diags/examples/StaticMrefWithTargs.java
      @@ -0,0 +1,32 @@
      +/*
      + * 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.
      + */
      +
      +// key: compiler.err.invalid.mref
      +// key: compiler.misc.static.mref.with.targs
      +
      +class StaticMrefWithTargs {
      +
      +    Runnable r = StaticMrefWithTargs::m;
      +
      +    static void m() { }
      +}
      diff --git a/langtools/test/tools/javac/generics/8004094/B.java b/langtools/test/tools/javac/generics/8004094/B.java
      new file mode 100644
      index 00000000000..735a7fdfa85
      --- /dev/null
      +++ b/langtools/test/tools/javac/generics/8004094/B.java
      @@ -0,0 +1,47 @@
      +/*
      + * 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.
      + */
      +abstract class A {
      +
      +    private static String s = null;
      +
      +    static void test() {
      +        new Object() {
      +            void m() {
      +                Object o = s;
      +            }
      +        };
      +    }
      +}
      +
      +public abstract class B extends A {
      +
      +    private static Integer i = null;
      +
      +    static void test() {
      +        new Object() {
      +            void m() {
      +                Object o = i;
      +            }
      +        };
      +    }
      +}
      diff --git a/langtools/test/tools/javac/generics/8004094/T8004094.java b/langtools/test/tools/javac/generics/8004094/T8004094.java
      new file mode 100644
      index 00000000000..76c54d2c9e5
      --- /dev/null
      +++ b/langtools/test/tools/javac/generics/8004094/T8004094.java
      @@ -0,0 +1,32 @@
      +/*
      + * 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.
      + */
      +
      +/*
      + * @test
      + * @bug 8004094
      + * @summary Javac compiler error - synthetic method accessor generated with duplicate name
      + *
      + * @compile B.java T8004094.java
      + */
      +
      +public class T8004094 extends B { }
      diff --git a/langtools/test/tools/javac/lambda/LambdaConversionTest.java b/langtools/test/tools/javac/lambda/FunctionalInterfaceConversionTest.java
      similarity index 68%
      rename from langtools/test/tools/javac/lambda/LambdaConversionTest.java
      rename to langtools/test/tools/javac/lambda/FunctionalInterfaceConversionTest.java
      index 0db2904e665..add4cd2def5 100644
      --- a/langtools/test/tools/javac/lambda/LambdaConversionTest.java
      +++ b/langtools/test/tools/javac/lambda/FunctionalInterfaceConversionTest.java
      @@ -1,5 +1,5 @@
       /*
      - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
      + * 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
      @@ -23,11 +23,11 @@
       
       /**
        * @test
      - * @bug 8003280
      + * @bug 8003280 8004102
        * @summary Add lambda tests
        *  perform several automated checks in lambda conversion, esp. around accessibility
        * @author  Maurizio Cimadamore
      - * @run main LambdaConversionTest
      + * @run main FunctionalInterfaceConversionTest
        */
       
       import com.sun.source.util.JavacTask;
      @@ -37,9 +37,10 @@ import javax.tools.Diagnostic;
       import javax.tools.JavaCompiler;
       import javax.tools.JavaFileObject;
       import javax.tools.SimpleJavaFileObject;
      +import javax.tools.StandardJavaFileManager;
       import javax.tools.ToolProvider;
       
      -public class LambdaConversionTest {
      +public class FunctionalInterfaceConversionTest {
       
           enum PackageKind {
               NO_PKG(""),
      @@ -108,10 +109,21 @@ public class LambdaConversionTest {
               }
           }
       
      +    enum ExprKind {
      +        LAMBDA("x -> null"),
      +        MREF("this::m");
      +
      +        String exprStr;
      +
      +        private ExprKind(String exprStr) {
      +            this.exprStr = exprStr;
      +        }
      +    }
      +
           enum MethodKind {
               NONE(""),
      -        NON_GENERIC("public #R m(#ARG s) throws #T;"),
      -        GENERIC("public  #R m(#ARG s) throws #T;");
      +        NON_GENERIC("public abstract #R m(#ARG s) throws #T;"),
      +        GENERIC("public abstract  #R m(#ARG s) throws #T;");
       
               String methodTemplate;
       
      @@ -127,15 +139,21 @@ public class LambdaConversionTest {
           }
       
           public static void main(String[] args) throws Exception {
      +        final JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
      +        StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
               for (PackageKind samPkg : PackageKind.values()) {
                   for (ModifierKind modKind : ModifierKind.values()) {
                       for (SamKind samKind : SamKind.values()) {
      -                    for (MethodKind meth : MethodKind.values()) {
      -                        for (TypeKind retType : TypeKind.values()) {
      -                            for (TypeKind argType : TypeKind.values()) {
      -                                for (TypeKind thrownType : TypeKind.values()) {
      -                                    new LambdaConversionTest(samPkg, modKind, samKind,
      -                                            meth, retType, argType, thrownType).test();
      +                    for (MethodKind samMeth : MethodKind.values()) {
      +                        for (MethodKind clientMeth : MethodKind.values()) {
      +                            for (TypeKind retType : TypeKind.values()) {
      +                                for (TypeKind argType : TypeKind.values()) {
      +                                    for (TypeKind thrownType : TypeKind.values()) {
      +                                        for (ExprKind exprKind : ExprKind.values()) {
      +                                            new FunctionalInterfaceConversionTest(samPkg, modKind, samKind,
      +                                                    samMeth, clientMeth, retType, argType, thrownType, exprKind).test(comp, fm);
      +                                        }
      +                                    }
                                       }
                                   }
                               }
      @@ -148,15 +166,18 @@ public class LambdaConversionTest {
           PackageKind samPkg;
           ModifierKind modKind;
           SamKind samKind;
      -    MethodKind meth;
      +    MethodKind samMeth;
      +    MethodKind clientMeth;
           TypeKind retType;
           TypeKind argType;
           TypeKind thrownType;
      +    ExprKind exprKind;
      +    DiagnosticChecker dc;
       
           SourceFile samSourceFile = new SourceFile("Sam.java", "#P \n #C") {
               public String toString() {
                   return template.replaceAll("#P", samPkg.getPkgDecl()).
      -                    replaceAll("#C", samKind.getSam(meth.getMethod(retType, argType, thrownType)));
      +                    replaceAll("#C", samKind.getSam(samMeth.getMethod(retType, argType, thrownType)));
               }
           };
       
      @@ -169,27 +190,33 @@ public class LambdaConversionTest {
           };
       
           SourceFile clientSourceFile = new SourceFile("Client.java",
      -                                                 "#I\n class Client { Sam s = x -> null; }") {
      +                                                 "#I\n abstract class Client { \n" +
      +                                                 "  Sam s = #E;\n" +
      +                                                 "  #M \n }") {
               public String toString() {
      -            return template.replaceAll("#I", samPkg.getImportStat());
      +            return template.replaceAll("#I", samPkg.getImportStat())
      +                    .replaceAll("#E", exprKind.exprStr)
      +                    .replaceAll("#M", clientMeth.getMethod(retType, argType, thrownType));
               }
           };
       
      -    LambdaConversionTest(PackageKind samPkg, ModifierKind modKind, SamKind samKind,
      -            MethodKind meth, TypeKind retType, TypeKind argType, TypeKind thrownType) {
      +    FunctionalInterfaceConversionTest(PackageKind samPkg, ModifierKind modKind, SamKind samKind,
      +            MethodKind samMeth, MethodKind clientMeth, TypeKind retType, TypeKind argType,
      +            TypeKind thrownType, ExprKind exprKind) {
               this.samPkg = samPkg;
               this.modKind = modKind;
               this.samKind = samKind;
      -        this.meth = meth;
      +        this.samMeth = samMeth;
      +        this.clientMeth = clientMeth;
               this.retType = retType;
               this.argType = argType;
               this.thrownType = thrownType;
      +        this.exprKind = exprKind;
      +        this.dc = new DiagnosticChecker();
           }
       
      -    void test() throws Exception {
      -        final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
      -        DiagnosticChecker dc = new DiagnosticChecker();
      -        JavacTask ct = (JavacTask)tool.getTask(null, null, dc,
      +    void test(JavaCompiler comp, StandardJavaFileManager fm) throws Exception {
      +        JavacTask ct = (JavacTask)comp.getTask(null, fm, dc,
                       null, null, Arrays.asList(samSourceFile, pkgClassSourceFile, clientSourceFile));
               ct.analyze();
               if (dc.errorFound == checkSamConversion()) {
      @@ -201,8 +228,15 @@ public class LambdaConversionTest {
               if (samKind != SamKind.INTERFACE) {
                   //sam type must be an interface
                   return false;
      -        } else if (meth != MethodKind.NON_GENERIC) {
      -            //target method must be non-generic
      +        } else if (samMeth == MethodKind.NONE) {
      +            //interface must have at least a method
      +            return false;
      +        } else if (exprKind == ExprKind.LAMBDA &&
      +                samMeth != MethodKind.NON_GENERIC) {
      +            //target method for lambda must be non-generic
      +            return false;
      +        } else if (exprKind == ExprKind.MREF &&
      +                clientMeth == MethodKind.NONE) {
                   return false;
               } else if (samPkg != PackageKind.NO_PKG &&
                       modKind != ModifierKind.PUBLIC &&
      diff --git a/langtools/test/tools/javac/lambda/Intersection01.java b/langtools/test/tools/javac/lambda/Intersection01.java
      new file mode 100644
      index 00000000000..a04950eaff5
      --- /dev/null
      +++ b/langtools/test/tools/javac/lambda/Intersection01.java
      @@ -0,0 +1,42 @@
      +/*
      + * 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.
      + */
      +
      +/*
      + * @test
      + * @bug 8002099
      + * @summary Add support for intersection types in cast expression
      + * @compile/fail/ref=Intersection01.out -XDallowIntersectionTypes -XDrawDiagnostics Intersection01.java
      + */
      +class Intersection01 {
      +
      +    interface SAM {
      +        void m();
      +    }
      +
      +    Object o1 = (java.io.Serializable & SAM)()->{};
      +    Object o2 = (SAM & java.io.Serializable)()->{};
      +    Object o3 = (java.io.Serializable & SAM)Intersection01::m;
      +    Object o4 = (SAM & java.io.Serializable)Intersection01::m;
      +
      +    static void m() { }
      +}
      diff --git a/langtools/test/tools/javac/lambda/Intersection01.out b/langtools/test/tools/javac/lambda/Intersection01.out
      new file mode 100644
      index 00000000000..122935b0913
      --- /dev/null
      +++ b/langtools/test/tools/javac/lambda/Intersection01.out
      @@ -0,0 +1,3 @@
      +Intersection01.java:36:45: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: (compiler.misc.no.abstracts: kindname.interface, java.io.Serializable))
      +Intersection01.java:38:45: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf.1: (compiler.misc.no.abstracts: kindname.interface, java.io.Serializable))
      +2 errors
      diff --git a/langtools/test/tools/javac/lambda/LambdaConv21.java b/langtools/test/tools/javac/lambda/LambdaConv21.java
      index ecc45931588..d4ac403cbbb 100644
      --- a/langtools/test/tools/javac/lambda/LambdaConv21.java
      +++ b/langtools/test/tools/javac/lambda/LambdaConv21.java
      @@ -23,7 +23,7 @@ class LambdaConv21 {
           static void testExpressionLambda() {
               SAM_void s1 = ()->m_void(); //ok
               SAM_java_lang_Void s2 = ()->m_void(); //no - incompatible target
      -        SAM_void s3 = ()->m_java_lang_Void(); //no - incompatible target
      +        SAM_void s3 = ()->m_java_lang_Void(); //ok - expression statement lambda is compatible with void
               SAM_java_lang_Void s4 = ()->m_java_lang_Void(); //ok
           }
       
      diff --git a/langtools/test/tools/javac/lambda/LambdaConv21.out b/langtools/test/tools/javac/lambda/LambdaConv21.out
      index 1ddf803701b..9976d9c7438 100644
      --- a/langtools/test/tools/javac/lambda/LambdaConv21.out
      +++ b/langtools/test/tools/javac/lambda/LambdaConv21.out
      @@ -1,6 +1,5 @@
       LambdaConv21.java:25:43: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: void, java.lang.Void))
      -LambdaConv21.java:26:43: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: java.lang.Void, void))
       LambdaConv21.java:32:33: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.missing.ret.val: java.lang.Void))
       LambdaConv21.java:33:53: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.unexpected.ret.val))
       LambdaConv21.java:36:33: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.missing.ret.val: java.lang.Void))
      -5 errors
      +4 errors
      diff --git a/langtools/test/tools/javac/lambda/LambdaParserTest.java b/langtools/test/tools/javac/lambda/LambdaParserTest.java
      index e208e792f8e..fdc56f6cb1c 100644
      --- a/langtools/test/tools/javac/lambda/LambdaParserTest.java
      +++ b/langtools/test/tools/javac/lambda/LambdaParserTest.java
      @@ -90,9 +90,14 @@ public class LambdaParserTest {
           enum LambdaParameterKind {
               IMPLICIT(""),
               EXPLIICT_SIMPLE("A"),
      +        EXPLIICT_SIMPLE_ARR1("A[]"),
      +        EXPLIICT_SIMPLE_ARR2("A[][]"),
               EXPLICIT_VARARGS("A..."),
               EXPLICIT_GENERIC1("A"),
      -        EXPLICIT_GENERIC3("A");
      +        EXPLICIT_GENERIC2("A"),
      +        EXPLICIT_GENERIC2_VARARGS("A..."),
      +        EXPLICIT_GENERIC2_ARR1("A[]"),
      +        EXPLICIT_GENERIC2_ARR2("A[][]");
       
               String parameterType;
       
      @@ -103,6 +108,11 @@ public class LambdaParserTest {
               boolean explicit() {
                   return this != IMPLICIT;
               }
      +
      +        boolean isVarargs() {
      +            return this == EXPLICIT_VARARGS ||
      +                    this == EXPLICIT_GENERIC2_VARARGS;
      +        }
           }
       
           enum ModifierKind {
      @@ -253,7 +263,7 @@ public class LambdaParserTest {
       
               if (lk.arity() == 2 &&
                       (pk1.explicit() != pk2.explicit() ||
      -                pk1 == LambdaParameterKind.EXPLICIT_VARARGS)) {
      +                pk1.isVarargs())) {
                   errorExpected = true;
               }
       
      diff --git a/langtools/test/tools/javac/lambda/MethodReference30.java b/langtools/test/tools/javac/lambda/MethodReference30.java
      index dec31d00e98..81945c6ec01 100644
      --- a/langtools/test/tools/javac/lambda/MethodReference30.java
      +++ b/langtools/test/tools/javac/lambda/MethodReference30.java
      @@ -46,7 +46,7 @@ public class MethodReference30 {
               assertTrue(true);
           }
       
      -   static void m() { }
      +   void m() { }
       
          public static void main(String[] args) {
             SAM s = new MethodReference30()::m;
      diff --git a/langtools/test/tools/javac/lambda/MethodReference55.java b/langtools/test/tools/javac/lambda/MethodReference55.java
      new file mode 100644
      index 00000000000..e21bf3e7f4a
      --- /dev/null
      +++ b/langtools/test/tools/javac/lambda/MethodReference55.java
      @@ -0,0 +1,45 @@
      +/*
      + * 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.
      + */
      +
      +/*
      + * @test
      + * @bug 8004101
      + * @summary Add checks for method reference well-formedness
      + * @compile/fail/ref=MethodReference55.out -XDrawDiagnostics MethodReference55.java
      + */
      +class MethodReference55 {
      +
      +    interface V {
      +        void m(Object o);
      +    }
      +
      +    V v = new MethodReference55()::m;
      +
      +    void test() {
      +        g(new MethodReference55()::m);
      +    }
      +
      +    void g(V v) { }
      +
      +    static void m(Object o) { };
      +}
      diff --git a/langtools/test/tools/javac/lambda/MethodReference55.out b/langtools/test/tools/javac/lambda/MethodReference55.out
      new file mode 100644
      index 00000000000..8488a28b229
      --- /dev/null
      +++ b/langtools/test/tools/javac/lambda/MethodReference55.out
      @@ -0,0 +1,3 @@
      +MethodReference55.java:36:11: compiler.err.invalid.mref: kindname.method, (compiler.misc.static.bound.mref)
      +MethodReference55.java:39:11: compiler.err.invalid.mref: kindname.method, (compiler.misc.static.bound.mref)
      +2 errors
      diff --git a/langtools/test/tools/javac/lambda/MethodReference56.java b/langtools/test/tools/javac/lambda/MethodReference56.java
      new file mode 100644
      index 00000000000..9e79fab6cc0
      --- /dev/null
      +++ b/langtools/test/tools/javac/lambda/MethodReference56.java
      @@ -0,0 +1,45 @@
      +/*
      + * 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.
      + */
      +
      +/*
      + * @test
      + * @bug 8004101
      + * @summary Add checks for method reference well-formedness
      + * @compile/fail/ref=MethodReference56.out -XDrawDiagnostics MethodReference56.java
      + */
      +class MethodReference56 {
      +
      +    interface V {
      +        void m(Object o);
      +    }
      +
      +    V v = MethodReference56::m;
      +
      +    void test() {
      +        g(MethodReference56::m);
      +    }
      +
      +    void g(V v) { }
      +
      +    static void m(Object o) { };
      +}
      diff --git a/langtools/test/tools/javac/lambda/MethodReference56.out b/langtools/test/tools/javac/lambda/MethodReference56.out
      new file mode 100644
      index 00000000000..34ccd15956d
      --- /dev/null
      +++ b/langtools/test/tools/javac/lambda/MethodReference56.out
      @@ -0,0 +1,3 @@
      +MethodReference56.java:36:28: compiler.err.invalid.mref: kindname.method, (compiler.misc.static.mref.with.targs)
      +MethodReference56.java:39:28: compiler.err.invalid.mref: kindname.method, (compiler.misc.static.mref.with.targs)
      +2 errors
      diff --git a/langtools/test/tools/javac/lambda/MethodReference57.java b/langtools/test/tools/javac/lambda/MethodReference57.java
      new file mode 100644
      index 00000000000..b24749fb2bc
      --- /dev/null
      +++ b/langtools/test/tools/javac/lambda/MethodReference57.java
      @@ -0,0 +1,41 @@
      +/*
      + * 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.
      + */
      +
      +/*
      + * @test
      + * @bug 8004102
      + * @summary Add support for generic functional descriptors
      + * @compile MethodReference57.java
      + */
      +class MethodReference57 {
      +
      +    interface F {
      +         void m();
      +    }
      +
      +    void test() {
      +        F f = this::g; //ok
      +    }
      +
      +    void g() { }
      +}
      diff --git a/langtools/test/tools/javac/lambda/MethodReference58.java b/langtools/test/tools/javac/lambda/MethodReference58.java
      new file mode 100644
      index 00000000000..02652da68f0
      --- /dev/null
      +++ b/langtools/test/tools/javac/lambda/MethodReference58.java
      @@ -0,0 +1,46 @@
      +/*
      + * 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.
      + */
      +
      +/*
      + * @test
      + * @bug 8004102
      + * @summary Add support for generic functional descriptors
      + * @compile/fail/ref=MethodReference58.out -XDrawDiagnostics MethodReference58.java
      + */
      +class MethodReference58 {
      +
      +    interface F_Object {
      +         void m(X x);
      +    }
      +
      +    interface F_Integer {
      +         void m(X x);
      +    }
      +
      +    void test() {
      +        F_Object f1 = this::g; //incompatible bounds
      +        F_Integer f2 = this::g; //ok
      +    }
      +
      +     void g(Z z) { }
      +}
      diff --git a/langtools/test/tools/javac/lambda/MethodReference58.out b/langtools/test/tools/javac/lambda/MethodReference58.out
      new file mode 100644
      index 00000000000..102facb7213
      --- /dev/null
      +++ b/langtools/test/tools/javac/lambda/MethodReference58.out
      @@ -0,0 +1,2 @@
      +MethodReference58.java:41:23: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, g, Z, X, kindname.class, MethodReference58, (compiler.misc.inferred.do.not.conform.to.upper.bounds: X, java.lang.Number)))
      +1 error
      diff --git a/langtools/test/tools/javac/lambda/VoidCompatibility.out b/langtools/test/tools/javac/lambda/VoidCompatibility.out
      index 7686554c58e..0d3a8e809b9 100644
      --- a/langtools/test/tools/javac/lambda/VoidCompatibility.out
      +++ b/langtools/test/tools/javac/lambda/VoidCompatibility.out
      @@ -1,2 +1,3 @@
      +VoidCompatibility.java:17:9: compiler.err.ref.ambiguous: schedule, kindname.method, schedule(VoidCompatibility.Runnable), VoidCompatibility, kindname.method, schedule(VoidCompatibility.Thunk), VoidCompatibility
       VoidCompatibility.java:23:9: compiler.err.ref.ambiguous: schedule, kindname.method, schedule(VoidCompatibility.Runnable), VoidCompatibility, kindname.method, schedule(VoidCompatibility.Thunk), VoidCompatibility
      -1 error
      +2 errors
      diff --git a/langtools/test/tools/javac/lambda/intersection/IntersectionTargetTypeTest.java b/langtools/test/tools/javac/lambda/intersection/IntersectionTargetTypeTest.java
      new file mode 100644
      index 00000000000..560aae32e4a
      --- /dev/null
      +++ b/langtools/test/tools/javac/lambda/intersection/IntersectionTargetTypeTest.java
      @@ -0,0 +1,294 @@
      +/*
      + * 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.
      + */
      +
      +/*
      + * @test
      + * @bug 8002099
      + * @summary Add support for intersection types in cast expression
      + */
      +
      +import com.sun.source.util.JavacTask;
      +import com.sun.tools.javac.util.List;
      +import com.sun.tools.javac.util.ListBuffer;
      +import java.net.URI;
      +import java.util.Arrays;
      +import javax.tools.Diagnostic;
      +import javax.tools.JavaCompiler;
      +import javax.tools.JavaFileObject;
      +import javax.tools.SimpleJavaFileObject;
      +import javax.tools.StandardJavaFileManager;
      +import javax.tools.ToolProvider;
      +
      +public class IntersectionTargetTypeTest {
      +
      +    static int checkCount = 0;
      +
      +    enum BoundKind {
      +        INTF,
      +        CLASS,
      +        SAM,
      +        ZAM;
      +    }
      +
      +    enum MethodKind {
      +        NONE,
      +        ABSTRACT,
      +        DEFAULT;
      +    }
      +
      +    enum TypeKind {
      +        A("interface A { }\n", "A", BoundKind.ZAM),
      +        B("interface B { default void m() { } }\n", "B", BoundKind.ZAM),
      +        C("interface C { void m(); }\n", "C", BoundKind.SAM),
      +        D("interface D extends B { }\n", "D", BoundKind.ZAM),
      +        E("interface E extends C { }\n", "E", BoundKind.SAM),
      +        F("interface F extends C { void g(); }\n", "F", BoundKind.INTF),
      +        G("interface G extends B { void g(); }\n", "G", BoundKind.SAM),
      +        H("interface H extends A { void g(); }\n", "H", BoundKind.SAM),
      +        OBJECT("", "Object", BoundKind.CLASS),
      +        STRING("", "String", BoundKind.CLASS);
      +
      +        String declStr;
      +        String typeStr;
      +        BoundKind boundKind;
      +
      +        private TypeKind(String declStr, String typeStr, BoundKind boundKind) {
      +            this.declStr = declStr;
      +            this.typeStr = typeStr;
      +            this.boundKind = boundKind;
      +        }
      +
      +        boolean compatibleSupertype(TypeKind tk) {
      +            if (tk == this) return true;
      +            switch (tk) {
      +                case B:
      +                    return this != C && this != E && this != F;
      +                case C:
      +                    return this != B && this != C && this != D && this != G;
      +                case D: return compatibleSupertype(B);
      +                case E:
      +                case F: return compatibleSupertype(C);
      +                case G: return compatibleSupertype(B);
      +                case H: return compatibleSupertype(A);
      +                default:
      +                    return true;
      +            }
      +        }
      +    }
      +
      +    enum CastKind {
      +        ONE_ARY("(#B0)", 1),
      +        TWO_ARY("(#B0 & #B1)", 2),
      +        THREE_ARY("(#B0 & #B1 & #B2)", 3);
      +
      +        String castTemplate;
      +        int nbounds;
      +
      +        CastKind(String castTemplate, int nbounds) {
      +            this.castTemplate = castTemplate;
      +            this.nbounds = nbounds;
      +        }
      +    }
      +
      +    enum ExpressionKind {
      +        LAMBDA("()->{}", true),
      +        MREF("this::m", true),
      +        //COND_LAMBDA("(true ? ()->{} : ()->{})", true), re-enable if spec allows this
      +        //COND_MREF("(true ? this::m : this::m)", true),
      +        STANDALONE("null", false);
      +
      +        String exprString;
      +        boolean isFunctional;
      +
      +        private ExpressionKind(String exprString, boolean isFunctional) {
      +            this.exprString = exprString;
      +            this.isFunctional = isFunctional;
      +        }
      +    }
      +
      +    static class CastInfo {
      +        CastKind kind;
      +        TypeKind[] types;
      +
      +        CastInfo(CastKind kind, TypeKind... types) {
      +            this.kind = kind;
      +            this.types = types;
      +        }
      +
      +        String getCast() {
      +            String temp = kind.castTemplate;
      +            for (int i = 0; i < kind.nbounds ; i++) {
      +                temp = temp.replace(String.format("#B%d", i), types[i].typeStr);
      +            }
      +            return temp;
      +        }
      +
      +        boolean wellFormed() {
      +            //check for duplicate types
      +            for (int i = 0 ; i < types.length ; i++) {
      +                for (int j = 0 ; j < types.length ; j++) {
      +                    if (i != j && types[i] == types[j]) {
      +                        return false;
      +                    }
      +                }
      +            }
      +            //check that classes only appear as first bound
      +            boolean classOk = true;
      +            for (int i = 0 ; i < types.length ; i++) {
      +                if (types[i].boundKind == BoundKind.CLASS &&
      +                        !classOk) {
      +                    return false;
      +                }
      +                classOk = false;
      +            }
      +            //check that supertypes are mutually compatible
      +            for (int i = 0 ; i < types.length ; i++) {
      +                for (int j = 0 ; j < types.length ; j++) {
      +                    if (!types[i].compatibleSupertype(types[j]) && i != j) {
      +                        return false;
      +                    }
      +                }
      +            }
      +            return true;
      +        }
      +    }
      +
      +    public static void main(String... args) throws Exception {
      +        //create default shared JavaCompiler - reused across multiple compilations
      +        JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
      +        StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
      +
      +        for (CastInfo cInfo : allCastInfo()) {
      +            for (ExpressionKind ek : ExpressionKind.values()) {
      +                new IntersectionTargetTypeTest(cInfo, ek).run(comp, fm);
      +            }
      +        }
      +        System.out.println("Total check executed: " + checkCount);
      +    }
      +
      +    static List allCastInfo() {
      +        ListBuffer buf = ListBuffer.lb();
      +        for (CastKind kind : CastKind.values()) {
      +            for (TypeKind b1 : TypeKind.values()) {
      +                if (kind.nbounds == 1) {
      +                    buf.append(new CastInfo(kind, b1));
      +                    continue;
      +                } else {
      +                    for (TypeKind b2 : TypeKind.values()) {
      +                        if (kind.nbounds == 2) {
      +                            buf.append(new CastInfo(kind, b1, b2));
      +                            continue;
      +                        } else {
      +                            for (TypeKind b3 : TypeKind.values()) {
      +                                buf.append(new CastInfo(kind, b1, b2, b3));
      +                            }
      +                        }
      +                    }
      +                }
      +            }
      +        }
      +        return buf.toList();
      +    }
      +
      +    CastInfo cInfo;
      +    ExpressionKind ek;
      +    JavaSource source;
      +    DiagnosticChecker diagChecker;
      +
      +    IntersectionTargetTypeTest(CastInfo cInfo, ExpressionKind ek) {
      +        this.cInfo = cInfo;
      +        this.ek = ek;
      +        this.source = new JavaSource();
      +        this.diagChecker = new DiagnosticChecker();
      +    }
      +
      +    class JavaSource extends SimpleJavaFileObject {
      +
      +        String bodyTemplate = "class Test {\n" +
      +                              "   void m() { }\n" +
      +                              "   void test() {\n" +
      +                              "      Object o = #C#E;\n" +
      +                              "   } }";
      +
      +        String source = "";
      +
      +        public JavaSource() {
      +            super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
      +            for (TypeKind tk : TypeKind.values()) {
      +                source += tk.declStr;
      +            }
      +            source += bodyTemplate.replaceAll("#C", cInfo.getCast()).replaceAll("#E", ek.exprString);
      +        }
      +
      +        @Override
      +        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
      +            return source;
      +        }
      +    }
      +
      +    void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception {
      +        JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker,
      +                Arrays.asList("-XDallowIntersectionTypes"), null, Arrays.asList(source));
      +        try {
      +            ct.analyze();
      +        } catch (Throwable ex) {
      +            throw new AssertionError("Error thrown when compiling the following code:\n" + source.getCharContent(true));
      +        }
      +        check();
      +    }
      +
      +    void check() {
      +        checkCount++;
      +
      +        boolean errorExpected = !cInfo.wellFormed();
      +
      +        if (ek.isFunctional) {
      +            //first bound must be a SAM
      +            errorExpected |= cInfo.types[0].boundKind != BoundKind.SAM;
      +            if (cInfo.types.length > 1) {
      +                //additional bounds must be ZAMs
      +                for (int i = 1; i < cInfo.types.length; i++) {
      +                    errorExpected |= cInfo.types[i].boundKind != BoundKind.ZAM;
      +                }
      +            }
      +        }
      +
      +        if (errorExpected != diagChecker.errorFound) {
      +            throw new Error("invalid diagnostics for source:\n" +
      +                source.getCharContent(true) +
      +                "\nFound error: " + diagChecker.errorFound +
      +                "\nExpected error: " + errorExpected);
      +        }
      +    }
      +
      +    static class DiagnosticChecker implements javax.tools.DiagnosticListener {
      +
      +        boolean errorFound;
      +
      +        public void report(Diagnostic diagnostic) {
      +            if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
      +                errorFound = true;
      +            }
      +        }
      +    }
      +}
      diff --git a/langtools/test/tools/javac/lambda/methodReference/MethodRef1.java b/langtools/test/tools/javac/lambda/methodReference/MethodRef1.java
      index 2f79439fbd2..bfccad87526 100644
      --- a/langtools/test/tools/javac/lambda/methodReference/MethodRef1.java
      +++ b/langtools/test/tools/javac/lambda/methodReference/MethodRef1.java
      @@ -70,9 +70,6 @@ public class MethodRef1 {
               b = MethodRef1::foo; //static reference to foo(int)
               b.m(1);
       
      -        b = new MethodRef1()::foo; //instance reference to static methods, supported for now
      -        b.m(1);
      -
               b = MethodRef1::bar; //static reference to bar(int)
               b.m(2);
       
      diff --git a/langtools/test/tools/javac/lambda/methodReference/SamConversion.java b/langtools/test/tools/javac/lambda/methodReference/SamConversion.java
      index fbbbb0f80bb..afe24fb7bd4 100644
      --- a/langtools/test/tools/javac/lambda/methodReference/SamConversion.java
      +++ b/langtools/test/tools/javac/lambda/methodReference/SamConversion.java
      @@ -133,15 +133,6 @@ public class SamConversion {
               } catch (Exception e) {
                   assertTrue(false);
               }
      -
      -        bar = new A()::method6;
      -        try {
      -            bar.m(1);
      -            assertTrue(false);
      -        } catch (MyException e) {
      -        } catch (Exception e) {
      -            assertTrue(false);
      -        }
           }
       
           /**
      diff --git a/langtools/test/tools/javac/lambda/methodReferenceExecution/MethodReferenceTestKinds.java b/langtools/test/tools/javac/lambda/methodReferenceExecution/MethodReferenceTestKinds.java
      index c8f1aa1a0db..5ae83fa3a5e 100644
      --- a/langtools/test/tools/javac/lambda/methodReferenceExecution/MethodReferenceTestKinds.java
      +++ b/langtools/test/tools/javac/lambda/methodReferenceExecution/MethodReferenceTestKinds.java
      @@ -119,20 +119,6 @@ public class MethodReferenceTestKinds extends MethodReferenceTestKindsSup {
               assertEquals(var.get(inst("arg")), "SM:1-MethodReferenceTestKinds(arg)");
           }
       
      -    public void testMRStaticEval() {
      -        MethodReferenceTestKinds evalCheck;
      -        S0 var = (evalCheck = inst("discard"))::staticMethod0;
      -        assertEquals(evalCheck.toString(), "MethodReferenceTestKinds(discard)");
      -        assertEquals(var.get(), "SM:0");
      -    }
      -
      -    public void testMRStaticEvalArg() {
      -        MethodReferenceTestKinds evalCheck;
      -        S1 var = (evalCheck = inst("discard"))::staticMethod1;
      -        assertEquals(evalCheck.toString(), "MethodReferenceTestKinds(discard)");
      -        assertEquals(var.get(inst("arg")), "SM:1-MethodReferenceTestKinds(arg)");
      -    }
      -
           public void testMRTopLevel() {
               SN0 var = MethodReferenceTestKindsBase::new;
               assertEquals(var.make().toString(), "MethodReferenceTestKindsBase(blank)");
      @@ -142,17 +128,7 @@ public class MethodReferenceTestKinds extends MethodReferenceTestKindsSup {
               SN1 var = MethodReferenceTestKindsBase::new;
               assertEquals(var.make("name").toString(), "MethodReferenceTestKindsBase(name)");
           }
      -/* unbound inner case not supported anymore (dropped by EG)
      -    public void testMRUnboundInner() {
      -        SXN0 var = MethodReferenceTestKinds.In::new;
      -        assertEquals(var.make(inst("out")).toString(), "In(blank)");
      -    }
       
      -   public void testMRUnboundInnerArg() {
      -        SXN1 var = MethodReferenceTestKinds.In::new;
      -        assertEquals(var.make(inst("out"), "name").toString(), "In(name)");
      -    }
      -*/
           public void testMRImplicitInner() {
               SN0 var = MethodReferenceTestKinds.In::new;
               assertEquals(var.make().toString(), "In(blank)");
      diff --git a/langtools/test/tools/javac/util/list/ListBufferTest.java b/langtools/test/tools/javac/util/list/ListBufferTest.java
      new file mode 100644
      index 00000000000..ae26c84ef06
      --- /dev/null
      +++ b/langtools/test/tools/javac/util/list/ListBufferTest.java
      @@ -0,0 +1,112 @@
      +/*
      + * 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.
      + */
      +
      +/*
      + * @test
      + * @bug 8004504
      + * @summary Ensure that ListBuffer is working properly
      + */
      +
      +import com.sun.tools.javac.util.List;
      +import com.sun.tools.javac.util.ListBuffer;
      +import java.util.Iterator;
      +import java.util.Objects;
      +
      +public class ListBufferTest {
      +    public static void main(String... args) {
      +        testRemove();
      +        testCopiedEndsWithList_nil();
      +    }
      +
      +    private static void testCopiedEndsWithList_nil() {
      +        ListBuffer lb = new ListBuffer<>();
      +
      +        lb.add("a");
      +        lb.add("b");
      +        lb.add("c");
      +
      +        List l1 = lb.toList();
      +
      +        assertListEquals(l1, "a", "b", "c");
      +        assertEndsWithNil(l1);
      +
      +        lb.add("d");
      +
      +        List l2 = lb.toList();
      +        assertListEquals(l2, "a", "b", "c", "d");
      +        assertEndsWithNil(l2);
      +        assertListEquals(l1, "a", "b", "c");
      +    }
      +
      +    private static void testRemove() {
      +        ListBuffer lb1 = new ListBuffer<>();
      +
      +        lb1.add("a");
      +        lb1.add("b");
      +        lb1.add("c");
      +
      +        assertListEquals(lb1.toList(), "a", "b", "c");
      +        assertEquals(lb1.next(), "a");
      +        assertListEquals(lb1.toList(), "b", "c");
      +        assertEquals(lb1.next(), "b");
      +        assertListEquals(lb1.toList(), "c");
      +        assertEquals(lb1.next(), "c");
      +        assertListEquals(lb1.toList());
      +        assertEquals(lb1.next(), null);
      +
      +        lb1.add("d");
      +
      +        assertEquals(lb1.next(), "d");
      +    }
      +
      +    private static void assertEndsWithNil(List list) {
      +        while (!list.isEmpty()) {
      +            list = list.tail;
      +        }
      +
      +        if (list != List.nil()) throw new IllegalStateException("Not ending with List.nil()");
      +    }
      +
      +    private static  void assertListEquals(Iterable list, T... data) {
      +        int i = 0;
      +        Iterator it = list.iterator();
      +
      +        while (it.hasNext() && i < data.length) {
      +            assertEquals(it.next(), data[i++]);
      +        }
      +
      +        if (it.hasNext()) {
      +            throw new IllegalStateException("Too many elements in the list");
      +        }
      +
      +        if (i < data.length) {
      +            throw new IllegalStateException("Too few elements in the list");
      +        }
      +    }
      +
      +    private static void assertEquals(Object expected, Object actual) {
      +        if (!Objects.equals(expected, actual)) {
      +            throw new IllegalStateException("Incorrect content. Expected: " + expected + ", actual: " + actual);
      +        }
      +    }
      +}
      diff --git a/langtools/test/tools/javap/T7190862.java b/langtools/test/tools/javap/T7190862.java
      new file mode 100644
      index 00000000000..b7b57daa2f7
      --- /dev/null
      +++ b/langtools/test/tools/javap/T7190862.java
      @@ -0,0 +1,157 @@
      +
      +/*
      + * @test /nodynamiccopyright/
      + * @bug 7190862 7109747
      + * @summary javap shows an incorrect type for operands if the 'wide' prefix is used
      + */
      +
      +import com.sun.source.util.JavacTask;
      +import com.sun.tools.javap.JavapFileManager;
      +import com.sun.tools.javap.JavapTask;
      +import java.io.PrintWriter;
      +import java.io.StringWriter;
      +import java.net.URI;
      +import java.util.Arrays;
      +import java.util.List;
      +import java.util.Locale;
      +import javax.tools.Diagnostic;
      +import javax.tools.DiagnosticCollector;
      +import javax.tools.JavaCompiler;
      +import javax.tools.JavaFileManager;
      +import javax.tools.JavaFileObject;
      +import javax.tools.SimpleJavaFileObject;
      +import javax.tools.ToolProvider;
      +
      +public class T7190862 {
      +
      +    enum TypeWideInstructionMap {
      +        INT("int", new String[]{"istore_w", "iload_w"}),
      +        LONG("long", new String[]{"lstore_w", "lload_w"}),
      +        FLOAT("float", new String[]{"fstore_w", "fload_w"}),
      +        DOUBLE("double", new String[]{"dstore_w", "dload_w"}),
      +        OBJECT("Object", new String[]{"astore_w", "aload_w"});
      +
      +        String type;
      +        String[] instructions;
      +
      +        TypeWideInstructionMap(String type, String[] instructions) {
      +            this.type = type;
      +            this.instructions = instructions;
      +        }
      +    }
      +
      +    JavaSource source;
      +
      +    public static void main(String[] args) {
      +        JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
      +        new T7190862().run(comp);
      +    }
      +
      +    private void run(JavaCompiler comp) {
      +        String code;
      +        for (TypeWideInstructionMap typeInstructionMap: TypeWideInstructionMap.values()) {
      +            if (typeInstructionMap != TypeWideInstructionMap.OBJECT) {
      +                code = createWideLocalSource(typeInstructionMap.type, 300);
      +            } else {
      +                code = createWideLocalSourceForObject(300);
      +            }
      +            source = new JavaSource(code);
      +            compile(comp);
      +            check(typeInstructionMap.instructions);
      +        }
      +
      +        //an extra test for the iinc instruction
      +        code = createIincSource();
      +        source = new JavaSource(code);
      +        compile(comp);
      +        check(new String[]{"iinc_w"});
      +    }
      +
      +    private void compile(JavaCompiler comp) {
      +        JavacTask ct = (JavacTask)comp.getTask(null, null, null, null, null, Arrays.asList(source));
      +        try {
      +            if (!ct.call()) {
      +                throw new AssertionError("Error thrown when compiling the following source:\n" + source.getCharContent(true));
      +            }
      +        } catch (Throwable ex) {
      +            throw new AssertionError("Error thrown when compiling the following source:\n" + source.getCharContent(true));
      +        }
      +    }
      +
      +    private void check(String[] instructions) {
      +        String out = javap(Arrays.asList("-c"), Arrays.asList("Test.class"));
      +        for (String line: out.split(System.getProperty("line.separator"))) {
      +            line = line.trim();
      +            for (String instruction: instructions) {
      +                if (line.contains(instruction) && line.contains("#")) {
      +                    throw new Error("incorrect type for operands for instruction " + instruction);
      +                }
      +            }
      +        }
      +    }
      +
      +    private String javap(List args, List classes) {
      +        DiagnosticCollector dc = new DiagnosticCollector();
      +        StringWriter sw = new StringWriter();
      +        PrintWriter pw = new PrintWriter(sw);
      +        JavaFileManager fm = JavapFileManager.create(dc, pw);
      +        JavapTask t = new JavapTask(pw, fm, dc, args, classes);
      +        boolean ok = t.run();
      +        if (!ok)
      +            throw new Error("javap failed unexpectedly");
      +
      +        List> diags = dc.getDiagnostics();
      +        for (Diagnostic d: diags) {
      +            if (d.getKind() == Diagnostic.Kind.ERROR)
      +                throw new Error(d.getMessage(Locale.ENGLISH));
      +        }
      +        return sw.toString();
      +
      +    }
      +
      +    private String createWideLocalSource(String type, int numberOfVars) {
      +        String result = "    " + type + " x0 = 0;\n";
      +        for (int i = 1; i < numberOfVars; i++) {
      +            result += "        " + type + " x" + i + " = x" + (i - 1) + " + 1;\n";
      +        }
      +        return result;
      +    }
      +
      +    private String createWideLocalSourceForObject(int numberOfVars) {
      +        String result = "    Object x0 = new Object();\n";
      +        for (int i = 1; i < numberOfVars; i++) {
      +            result += "        Object x" + i + " = x0;\n";
      +        }
      +        return result;
      +    }
      +
      +    private String createIincSource() {
      +        return "    int i = 0;\n"
      +                + "        i += 1;\n"
      +                + "        i += 51;\n"
      +                + "        i += 101;\n"
      +                + "        i += 151;\n";
      +    }
      +
      +    class JavaSource extends SimpleJavaFileObject {
      +
      +        String template = "class Test {\n" +
      +                          "    public static void main(String[] args)\n" +
      +                          "    {\n" +
      +                          "        #C" +
      +                          "    }\n" +
      +                          "}";
      +
      +        String source;
      +
      +        public JavaSource(String code) {
      +            super(URI.create("Test.java"), JavaFileObject.Kind.SOURCE);
      +            source = template.replaceAll("#C", code);
      +        }
      +
      +        @Override
      +        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
      +            return source;
      +        }
      +    }
      +}
      diff --git a/make/jprt.properties b/make/jprt.properties
      index 984c2b1b4e8..603ce5fda94 100644
      --- a/make/jprt.properties
      +++ b/make/jprt.properties
      @@ -88,7 +88,6 @@ jprt.make.rule.core.test.targets=                               \
           ${jprt.my.test.target.set:TESTNAME=jdk_jmx},                \
           ${jprt.my.test.target.set:TESTNAME=jdk_text},		\
           ${jprt.my.test.target.set:TESTNAME=jdk_tools},              \
      -    ${jprt.my.test.target.set:TESTNAME=jdk_jdi},                \
           ${jprt.my.test.target.set:TESTNAME=jdk_jfr},                \
           ${jprt.my.test.target.set:TESTNAME=jdk_other}
       
      @@ -105,6 +104,7 @@ jprt.make.rule.all.test.targets=    				\
           ${jprt.my.test.target.set:TESTNAME=jdk_beans1},             \
           ${jprt.my.test.target.set:TESTNAME=jdk_beans2},		\
           ${jprt.my.test.target.set:TESTNAME=jdk_beans3},		\
      +    ${jprt.my.test.target.set:TESTNAME=jdk_jdi},                \
           ${jprt.my.test.target.set:TESTNAME=jdk_sound},		\
           ${jprt.my.test.target.set:TESTNAME=jdk_swing}