diff --git a/.hgtags b/.hgtags index 0e1e6146c83..25861ade374 100644 --- a/.hgtags +++ b/.hgtags @@ -310,3 +310,5 @@ e7dbbef69d12b6a74dfad331b7188e7f893e8d29 jdk9-b62 4915246064b2f89d5f00c96e758686b7fdad36a6 jdk9-b65 ff3fc75f3214ad7e03595be1b0d0f38d887b6f0e jdk9-b66 56166ce66037952fa21e9f680b31bf8eb47312c0 jdk9-b67 +5b500c93ce4822d47061cd518ff3f72d9d8cb5b5 jdk9-b68 +d69c968463f0ae5d0b45de3fc14fe65171b23948 jdk9-b69 diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 3b7f5316ae8..85bad55aac1 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -310,3 +310,5 @@ ea38728b4f4bdd8fd0d7a89b18069f521cf05013 jdk9-b61 7c31f9d7b932f7924f1258d52885b1c7c3e078c2 jdk9-b65 dc6e8336f51bb6b67b7245766179eab5ca7720b4 jdk9-b66 f546760134eb861fcfecd4ce611b0040b0d25a6a jdk9-b67 +70e4272790b6199e9ca89df2758ff9cb58ec4125 jdk9-b68 +1bcfd6b8726582cff5a42dbfc75903e36f9dd4fe jdk9-b69 diff --git a/common/autoconf/basics.m4 b/common/autoconf/basics.m4 index a9d1034eae0..858ed2e9ea7 100644 --- a/common/autoconf/basics.m4 +++ b/common/autoconf/basics.m4 @@ -436,7 +436,6 @@ AC_DEFUN_ONCE([BASIC_SETUP_FUNDAMENTAL_TOOLS], BASIC_PATH_PROGS(CYGPATH, cygpath) BASIC_PATH_PROGS(READLINK, [greadlink readlink]) BASIC_PATH_PROGS(DF, df) - BASIC_PATH_PROGS(SETFILE, SetFile) BASIC_PATH_PROGS(CPIO, [cpio bsdcpio]) ]) @@ -574,10 +573,11 @@ AC_DEFUN_ONCE([BASIC_SETUP_DEVKIT], ) if test "x$OPENJDK_BUILD_OS" = "xmacosx"; then - # detect if Xcode is installed by running xcodebuild -version + # If a devkit has been supplied, find xcodebuild in the toolchain_path. + # If not, detect if Xcode is installed by running xcodebuild -version # if no Xcode installed, xcodebuild exits with 1 # if Xcode is installed, even if xcode-select is misconfigured, then it exits with 0 - if /usr/bin/xcodebuild -version >/dev/null 2>&1; then + if test "x$DEVKIT_ROOT" != x || /usr/bin/xcodebuild -version >/dev/null 2>&1; then # We need to use xcodebuild in the toolchain dir provided by the user, this will # fall back on the stub binary in /usr/bin/xcodebuild AC_PATH_PROG([XCODEBUILD], [xcodebuild], [/usr/bin/xcodebuild], [$TOOLCHAIN_PATH]) @@ -961,6 +961,7 @@ AC_DEFUN_ONCE([BASIC_SETUP_COMPLEX_TOOLS], AC_MSG_RESULT([yes]) fi fi + BASIC_REQUIRE_PROGS(SETFILE, SetFile) fi ]) diff --git a/common/autoconf/build-aux/config.guess b/common/autoconf/build-aux/config.guess index a450a2760f6..148a61a8ab8 100644 --- a/common/autoconf/build-aux/config.guess +++ b/common/autoconf/build-aux/config.guess @@ -86,4 +86,11 @@ if [ "x$OUT" = x ]; then fi fi +# Test and fix cpu on Macosx when C preprocessor is not on the path +echo $OUT | grep i386-apple-darwin > /dev/null 2> /dev/null +if test $? = 0; then + REAL_CPU=`uname -m` + OUT=$REAL_CPU`echo $OUT | sed -e 's/[^-]*//'` +fi + echo $OUT diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index f262cf48b17..446fadaba6a 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -855,6 +855,7 @@ OS_VERSION_MINOR OS_VERSION_MAJOR PKG_CONFIG BASH_ARGS +SETFILE CODESIGN XATTR DSYMUTIL @@ -946,7 +947,6 @@ build_vendor build_cpu build CPIO -SETFILE DF READLINK CYGPATH @@ -1167,7 +1167,6 @@ SED CYGPATH READLINK DF -SETFILE CPIO UNZIP ZIP @@ -1180,6 +1179,7 @@ TIME DSYMUTIL XATTR CODESIGN +SETFILE PKG_CONFIG JAVA JAVAC @@ -2049,7 +2049,6 @@ Some influential environment variables: CYGPATH Override default value for CYGPATH READLINK Override default value for READLINK DF Override default value for DF - SETFILE Override default value for SETFILE CPIO Override default value for CPIO UNZIP Override default value for UNZIP ZIP Override default value for ZIP @@ -2062,6 +2061,7 @@ Some influential environment variables: DSYMUTIL Override default value for DSYMUTIL XATTR Override default value for XATTR CODESIGN Override default value for CODESIGN + SETFILE Override default value for SETFILE PKG_CONFIG path to pkg-config utility JAVA Override default value for JAVA JAVAC Override default value for JAVAC @@ -4364,7 +4364,7 @@ VS_SDK_PLATFORM_NAME_2013= #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1433337614 +DATE_WHEN_GENERATED=1434614912 ############################################################################### # @@ -13055,192 +13055,6 @@ $as_echo "$tool_specified" >&6; } - # Publish this variable in the help. - - - if test "x$SETFILE" = x; then - # The variable is not set by user, try to locate tool using the code snippet - for ac_prog in SetFile -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_SETFILE+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $SETFILE in - [\\/]* | ?:[\\/]*) - ac_cv_path_SETFILE="$SETFILE" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_SETFILE="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -SETFILE=$ac_cv_path_SETFILE -if test -n "$SETFILE"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SETFILE" >&5 -$as_echo "$SETFILE" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$SETFILE" && break -done - - else - # The variable is set, but is it from the command line or the environment? - - # Try to remove the string !SETFILE! from our list. - try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!SETFILE!/} - if test "x$try_remove_var" = "x$CONFIGURE_OVERRIDDEN_VARIABLES"; then - # If it failed, the variable was not from the command line. Ignore it, - # but warn the user (except for BASH, which is always set by the calling BASH). - if test "xSETFILE" != xBASH; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of SETFILE from the environment. Use command line variables instead." >&5 -$as_echo "$as_me: WARNING: Ignoring value of SETFILE from the environment. Use command line variables instead." >&2;} - fi - # Try to locate tool using the code snippet - for ac_prog in SetFile -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_SETFILE+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $SETFILE in - [\\/]* | ?:[\\/]*) - ac_cv_path_SETFILE="$SETFILE" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_SETFILE="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -SETFILE=$ac_cv_path_SETFILE -if test -n "$SETFILE"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SETFILE" >&5 -$as_echo "$SETFILE" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$SETFILE" && break -done - - else - # If it succeeded, then it was overridden by the user. We will use it - # for the tool. - - # First remove it from the list of overridden variables, so we can test - # for unknown variables in the end. - CONFIGURE_OVERRIDDEN_VARIABLES="$try_remove_var" - - # Check if the provided tool contains a complete path. - tool_specified="$SETFILE" - tool_basename="${tool_specified##*/}" - if test "x$tool_basename" = "x$tool_specified"; then - # A command without a complete path is provided, search $PATH. - { $as_echo "$as_me:${as_lineno-$LINENO}: Will search for user supplied tool SETFILE=$tool_basename" >&5 -$as_echo "$as_me: Will search for user supplied tool SETFILE=$tool_basename" >&6;} - # Extract the first word of "$tool_basename", so it can be a program name with args. -set dummy $tool_basename; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_SETFILE+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $SETFILE in - [\\/]* | ?:[\\/]*) - ac_cv_path_SETFILE="$SETFILE" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_SETFILE="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -SETFILE=$ac_cv_path_SETFILE -if test -n "$SETFILE"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SETFILE" >&5 -$as_echo "$SETFILE" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - if test "x$SETFILE" = x; then - as_fn_error $? "User supplied tool $tool_basename could not be found" "$LINENO" 5 - fi - else - # Otherwise we believe it is a complete path. Use it as it is. - { $as_echo "$as_me:${as_lineno-$LINENO}: Will use user supplied tool SETFILE=$tool_specified" >&5 -$as_echo "$as_me: Will use user supplied tool SETFILE=$tool_specified" >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SETFILE" >&5 -$as_echo_n "checking for SETFILE... " >&6; } - if test ! -x "$tool_specified"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 -$as_echo "not found" >&6; } - as_fn_error $? "User supplied tool SETFILE=$tool_specified does not exist or is not executable" "$LINENO" 5 - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tool_specified" >&5 -$as_echo "$tool_specified" >&6; } - fi - fi - fi - - - - # Publish this variable in the help. @@ -15140,10 +14954,11 @@ fi if test "x$OPENJDK_BUILD_OS" = "xmacosx"; then - # detect if Xcode is installed by running xcodebuild -version + # If a devkit has been supplied, find xcodebuild in the toolchain_path. + # If not, detect if Xcode is installed by running xcodebuild -version # if no Xcode installed, xcodebuild exits with 1 # if Xcode is installed, even if xcode-select is misconfigured, then it exits with 0 - if /usr/bin/xcodebuild -version >/dev/null 2>&1; then + if test "x$DEVKIT_ROOT" != x || /usr/bin/xcodebuild -version >/dev/null 2>&1; then # We need to use xcodebuild in the toolchain dir provided by the user, this will # fall back on the stub binary in /usr/bin/xcodebuild # Extract the first word of "xcodebuild", so it can be a program name with args. @@ -19653,6 +19468,199 @@ $as_echo "no" >&6; } $as_echo "yes" >&6; } fi fi + + + + # Publish this variable in the help. + + + if test "x$SETFILE" = x; then + # The variable is not set by user, try to locate tool using the code snippet + for ac_prog in SetFile +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_SETFILE+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $SETFILE in + [\\/]* | ?:[\\/]*) + ac_cv_path_SETFILE="$SETFILE" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_SETFILE="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +SETFILE=$ac_cv_path_SETFILE +if test -n "$SETFILE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SETFILE" >&5 +$as_echo "$SETFILE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$SETFILE" && break +done + + else + # The variable is set, but is it from the command line or the environment? + + # Try to remove the string !SETFILE! from our list. + try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!SETFILE!/} + if test "x$try_remove_var" = "x$CONFIGURE_OVERRIDDEN_VARIABLES"; then + # If it failed, the variable was not from the command line. Ignore it, + # but warn the user (except for BASH, which is always set by the calling BASH). + if test "xSETFILE" != xBASH; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of SETFILE from the environment. Use command line variables instead." >&5 +$as_echo "$as_me: WARNING: Ignoring value of SETFILE from the environment. Use command line variables instead." >&2;} + fi + # Try to locate tool using the code snippet + for ac_prog in SetFile +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_SETFILE+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $SETFILE in + [\\/]* | ?:[\\/]*) + ac_cv_path_SETFILE="$SETFILE" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_SETFILE="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +SETFILE=$ac_cv_path_SETFILE +if test -n "$SETFILE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SETFILE" >&5 +$as_echo "$SETFILE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$SETFILE" && break +done + + else + # If it succeeded, then it was overridden by the user. We will use it + # for the tool. + + # First remove it from the list of overridden variables, so we can test + # for unknown variables in the end. + CONFIGURE_OVERRIDDEN_VARIABLES="$try_remove_var" + + # Check if the provided tool contains a complete path. + tool_specified="$SETFILE" + tool_basename="${tool_specified##*/}" + if test "x$tool_basename" = "x$tool_specified"; then + # A command without a complete path is provided, search $PATH. + { $as_echo "$as_me:${as_lineno-$LINENO}: Will search for user supplied tool SETFILE=$tool_basename" >&5 +$as_echo "$as_me: Will search for user supplied tool SETFILE=$tool_basename" >&6;} + # Extract the first word of "$tool_basename", so it can be a program name with args. +set dummy $tool_basename; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_SETFILE+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $SETFILE in + [\\/]* | ?:[\\/]*) + ac_cv_path_SETFILE="$SETFILE" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_SETFILE="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +SETFILE=$ac_cv_path_SETFILE +if test -n "$SETFILE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SETFILE" >&5 +$as_echo "$SETFILE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "x$SETFILE" = x; then + as_fn_error $? "User supplied tool $tool_basename could not be found" "$LINENO" 5 + fi + else + # Otherwise we believe it is a complete path. Use it as it is. + { $as_echo "$as_me:${as_lineno-$LINENO}: Will use user supplied tool SETFILE=$tool_specified" >&5 +$as_echo "$as_me: Will use user supplied tool SETFILE=$tool_specified" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SETFILE" >&5 +$as_echo_n "checking for SETFILE... " >&6; } + if test ! -x "$tool_specified"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 +$as_echo "not found" >&6; } + as_fn_error $? "User supplied tool SETFILE=$tool_specified does not exist or is not executable" "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tool_specified" >&5 +$as_echo "$tool_specified" >&6; } + fi + fi + fi + + + + if test "x$SETFILE" = x; then + as_fn_error $? "Could not find required tool for SETFILE" "$LINENO" 5 + fi + + fi diff --git a/corba/.hgtags b/corba/.hgtags index 4c9c74c6bdb..009eac142d9 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -310,3 +310,5 @@ d27f7e0a7aca129969de23e9934408a31b4abf4c jdk9-b62 afc1e295c4bf83f9a5dd539c29914edd4a754a3f jdk9-b65 44ee68f7dbacab24a45115fd6a8ccdc7eb6e8f0b jdk9-b66 4418697e56f1f43597f55c7cb6573549c6117868 jdk9-b67 +8efad64f40eb8cd4df376c0a5275892eeb396bbd jdk9-b68 +de8acedcb5b5870f1dc54cba575aaa5d33897ea2 jdk9-b69 diff --git a/corba/src/java.corba/share/classes/org/omg/CORBA/BoundsHelper.java b/corba/src/java.corba/share/classes/org/omg/CORBA/BoundsHelper.java new file mode 100644 index 00000000000..54aae7c1df0 --- /dev/null +++ b/corba/src/java.corba/share/classes/org/omg/CORBA/BoundsHelper.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.omg.CORBA; + + +/** + * This Helper class is used to facilitate the marshalling of Bounds. + * For more information on Helper files, see + * + * "Generated Files: Helper Files".

+ */ + +abstract public class BoundsHelper +{ + private static String _id = "IDL:omg.org/CORBA/Bounds:1.0"; + + public static void insert (org.omg.CORBA.Any a, org.omg.CORBA.Bounds that) + { + org.omg.CORBA.portable.OutputStream out = a.create_output_stream (); + a.type (type ()); + write (out, that); + a.read_value (out.create_input_stream (), type ()); + } + + public static org.omg.CORBA.Bounds extract (org.omg.CORBA.Any a) + { + return read (a.create_input_stream ()); + } + + private static org.omg.CORBA.TypeCode __typeCode = null; + private static boolean __active = false; + synchronized public static org.omg.CORBA.TypeCode type () + { + if (__typeCode == null) + { + synchronized (org.omg.CORBA.TypeCode.class) + { + if (__typeCode == null) + { + if (__active) + { + return org.omg.CORBA.ORB.init().create_recursive_tc ( _id ); + } + __active = true; + org.omg.CORBA.StructMember[] _members0 = new org.omg.CORBA.StructMember [0]; + org.omg.CORBA.TypeCode _tcOf_members0 = null; + __typeCode = org.omg.CORBA.ORB.init ().create_exception_tc (org.omg.CORBA.BoundsHelper.id (), "Bounds", _members0); + __active = false; + } + } + } + return __typeCode; + } + + public static String id () + { + return _id; + } + + public static org.omg.CORBA.Bounds read (org.omg.CORBA.portable.InputStream istream) + { + org.omg.CORBA.Bounds value = new org.omg.CORBA.Bounds (); + // read and discard the repository ID + istream.read_string (); + return value; + } + + public static void write (org.omg.CORBA.portable.OutputStream ostream, org.omg.CORBA.Bounds value) + { + // write the repository ID + ostream.write_string (id ()); + } + +} diff --git a/corba/src/java.corba/share/classes/org/omg/CORBA/DynAny.java b/corba/src/java.corba/share/classes/org/omg/CORBA/DynAny.java index 8024a6d8ea6..5d0af777e54 100644 --- a/corba/src/java.corba/share/classes/org/omg/CORBA/DynAny.java +++ b/corba/src/java.corba/share/classes/org/omg/CORBA/DynAny.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,8 +52,8 @@ public interface DynAny extends org.omg.CORBA.Object * * @param dyn_any the DynAny object whose contents * are assigned to this DynAny. - * @throws Invalid if the source DynAny is - * invalid + * @throws org.omg.CORBA.DynAnyPackage.Invalid if the source + * DynAny is invalid */ public void assign(org.omg.CORBA.DynAny dyn_any) throws org.omg.CORBA.DynAnyPackage.Invalid; @@ -63,8 +63,8 @@ public interface DynAny extends org.omg.CORBA.Object * object. * * @param value the Any object. - * @throws Invalid if the source Any object is - * empty or bad + * @throws org.omg.CORBA.DynAnyPackage.Invalid if the source + * Any object is empty or bad */ public void from_any(org.omg.CORBA.Any value) throws org.omg.CORBA.DynAnyPackage.Invalid; @@ -74,8 +74,8 @@ public interface DynAny extends org.omg.CORBA.Object * object. * * @return the Any object. - * @throws Invalid if this DynAny is empty or - * bad. + * @throws org.omg.CORBA.DynAnyPackage.Invalid if this + * DynAny is empty or bad. * created or does not contain a meaningful value */ public org.omg.CORBA.Any to_any() diff --git a/corba/src/java.corba/share/classes/org/omg/CORBA/DynArray.java b/corba/src/java.corba/share/classes/org/omg/CORBA/DynArray.java index 7018090693b..14559e4a681 100644 --- a/corba/src/java.corba/share/classes/org/omg/CORBA/DynArray.java +++ b/corba/src/java.corba/share/classes/org/omg/CORBA/DynArray.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,7 +48,8 @@ public interface DynArray extends org.omg.CORBA.Object, org.omg.CORBA.DynAny * DynArray object to the given array. * * @param value the array of Any objects - * @exception InvalidSeq if the sequence is bad + * @exception org.omg.CORBA.DynAnyPackage.InvalidSeq if the + * sequence is bad * @see #get_elements */ public void set_elements(org.omg.CORBA.Any[] value) diff --git a/corba/src/java.corba/share/classes/org/omg/CORBA/DynSequence.java b/corba/src/java.corba/share/classes/org/omg/CORBA/DynSequence.java index 3bbcc0555c9..c5361834c75 100644 --- a/corba/src/java.corba/share/classes/org/omg/CORBA/DynSequence.java +++ b/corba/src/java.corba/share/classes/org/omg/CORBA/DynSequence.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,7 +65,8 @@ public interface DynSequence extends org.omg.CORBA.Object, org.omg.CORBA.DynAny * array. * * @param value the array of Any objects to be set - * @exception InvalidSeq if the array of values is bad + * @exception org.omg.CORBA.DynAnyPackage.InvalidSeq if the array + * of values is bad * @see #get_elements */ public void set_elements(org.omg.CORBA.Any[] value) diff --git a/corba/src/java.corba/share/classes/org/omg/CORBA/ORBPackage/InvalidNameHelper.java b/corba/src/java.corba/share/classes/org/omg/CORBA/ORBPackage/InvalidNameHelper.java new file mode 100644 index 00000000000..044e2b17eb4 --- /dev/null +++ b/corba/src/java.corba/share/classes/org/omg/CORBA/ORBPackage/InvalidNameHelper.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.omg.CORBA.ORBPackage; + + +/** + * This Helper class is used to facilitate the marshalling of + * ORBPackage/InvalidName. + * For more information on Helper files, see + * + * "Generated Files: Helper Files".

+ */ + +abstract public class InvalidNameHelper +{ + private static String _id = "IDL:omg.org.CORBA/ORB/InvalidName:1.0"; + + public static void insert (org.omg.CORBA.Any a, org.omg.CORBA.ORBPackage.InvalidName that) + { + org.omg.CORBA.portable.OutputStream out = a.create_output_stream (); + a.type (type ()); + write (out, that); + a.read_value (out.create_input_stream (), type ()); + } + + public static org.omg.CORBA.ORBPackage.InvalidName extract (org.omg.CORBA.Any a) + { + return read (a.create_input_stream ()); + } + + private static org.omg.CORBA.TypeCode __typeCode = null; + private static boolean __active = false; + synchronized public static org.omg.CORBA.TypeCode type () + { + if (__typeCode == null) + { + synchronized (org.omg.CORBA.TypeCode.class) + { + if (__typeCode == null) + { + if (__active) + { + return org.omg.CORBA.ORB.init().create_recursive_tc ( _id ); + } + __active = true; + org.omg.CORBA.StructMember[] _members0 = new org.omg.CORBA.StructMember [0]; + org.omg.CORBA.TypeCode _tcOf_members0 = null; + __typeCode = org.omg.CORBA.ORB.init ().create_exception_tc (org.omg.CORBA.ORBPackage.InvalidNameHelper.id (), "InvalidName", _members0); + __active = false; + } + } + } + return __typeCode; + } + + public static String id () + { + return _id; + } + + public static org.omg.CORBA.ORBPackage.InvalidName read (org.omg.CORBA.portable.InputStream istream) + { + org.omg.CORBA.ORBPackage.InvalidName value = new org.omg.CORBA.ORBPackage.InvalidName (); + // read and discard the repository ID + istream.read_string (); + return value; + } + + public static void write (org.omg.CORBA.portable.OutputStream ostream, org.omg.CORBA.ORBPackage.InvalidName value) + { + // write the repository ID + ostream.write_string (id ()); + } + +} diff --git a/corba/src/java.corba/share/classes/org/omg/CORBA/ServerRequest.java b/corba/src/java.corba/share/classes/org/omg/CORBA/ServerRequest.java index f4f5ed264ae..04cdeb6ffde 100644 --- a/corba/src/java.corba/share/classes/org/omg/CORBA/ServerRequest.java +++ b/corba/src/java.corba/share/classes/org/omg/CORBA/ServerRequest.java @@ -248,7 +248,7 @@ public abstract class ServerRequest { * contain an exception will result in a BAD_PARAM system exception. Passing * in an unlisted user exception will result in either the DIR receiving a * BAD_PARAM system exception or in the client receiving an - * UNKNOWN_EXCEPTION system exception. + * UNKNOWN system exception. * * @param any the Any object containing the exception * @deprecated use set_exception() @@ -272,13 +272,13 @@ public abstract class ServerRequest { * will cause a BAD_PARAM system exception to be thrown. Passing * in an unlisted user exception will result in either the DIR receiving a * BAD_PARAM system exception or in the client receiving an - * UNKNOWN_EXCEPTION system exception. + * UNKNOWN system exception. * * @param any the Any object containing the exception * @exception BAD_PARAM if the given Any object does not * contain an exception or the exception is an * unlisted user exception - * @exception UNKNOWN_EXCEPTION if the given exception is an unlisted + * @exception UNKNOWN if the given exception is an unlisted * user exception and the DIR did not * receive a BAD_PARAM exception * @see CORBA diff --git a/corba/src/java.corba/share/classes/org/omg/CORBA/TypeCodePackage/BadKindHelper.java b/corba/src/java.corba/share/classes/org/omg/CORBA/TypeCodePackage/BadKindHelper.java new file mode 100644 index 00000000000..755935698dd --- /dev/null +++ b/corba/src/java.corba/share/classes/org/omg/CORBA/TypeCodePackage/BadKindHelper.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.omg.CORBA.TypeCodePackage; + + +/** + * This Helper class is used to facilitate the marshalling of + * TypeCodePackage/BadKind. + * For more information on Helper files, see + * + * "Generated Files: Helper Files".

+ */ + +abstract public class BadKindHelper +{ + private static String _id = "IDL:omg.org.CORBA/TypeCode/BadKind:1.0"; + + public static void insert (org.omg.CORBA.Any a, org.omg.CORBA.TypeCodePackage.BadKind that) + { + org.omg.CORBA.portable.OutputStream out = a.create_output_stream (); + a.type (type ()); + write (out, that); + a.read_value (out.create_input_stream (), type ()); + } + + public static org.omg.CORBA.TypeCodePackage.BadKind extract (org.omg.CORBA.Any a) + { + return read (a.create_input_stream ()); + } + + private static org.omg.CORBA.TypeCode __typeCode = null; + private static boolean __active = false; + synchronized public static org.omg.CORBA.TypeCode type () + { + if (__typeCode == null) + { + synchronized (org.omg.CORBA.TypeCode.class) + { + if (__typeCode == null) + { + if (__active) + { + return org.omg.CORBA.ORB.init().create_recursive_tc ( _id ); + } + __active = true; + org.omg.CORBA.StructMember[] _members0 = new org.omg.CORBA.StructMember [0]; + org.omg.CORBA.TypeCode _tcOf_members0 = null; + __typeCode = org.omg.CORBA.ORB.init ().create_exception_tc (org.omg.CORBA.TypeCodePackage.BadKindHelper.id (), "BadKind", _members0); + __active = false; + } + } + } + return __typeCode; + } + + public static String id () + { + return _id; + } + + public static org.omg.CORBA.TypeCodePackage.BadKind read (org.omg.CORBA.portable.InputStream istream) + { + org.omg.CORBA.TypeCodePackage.BadKind value = new org.omg.CORBA.TypeCodePackage.BadKind (); + // read and discard the repository ID + istream.read_string (); + return value; + } + + public static void write (org.omg.CORBA.portable.OutputStream ostream, org.omg.CORBA.TypeCodePackage.BadKind value) + { + // write the repository ID + ostream.write_string (id ()); + } + +} diff --git a/corba/src/java.corba/share/classes/org/omg/CORBA/TypeCodePackage/BoundsHelper.java b/corba/src/java.corba/share/classes/org/omg/CORBA/TypeCodePackage/BoundsHelper.java new file mode 100644 index 00000000000..c234c595b17 --- /dev/null +++ b/corba/src/java.corba/share/classes/org/omg/CORBA/TypeCodePackage/BoundsHelper.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.omg.CORBA.TypeCodePackage; + + +/** + * This Helper class is used to facilitate the marshalling of + * TypeCodePackage/Bounds. + * For more information on Helper files, see + * + * "Generated Files: Helper Files".

+ */ + +abstract public class BoundsHelper +{ + private static String _id = "IDL:omg.org.CORBA/TypeCode/Bounds:1.0"; + + public static void insert (org.omg.CORBA.Any a, org.omg.CORBA.TypeCodePackage.Bounds that) + { + org.omg.CORBA.portable.OutputStream out = a.create_output_stream (); + a.type (type ()); + write (out, that); + a.read_value (out.create_input_stream (), type ()); + } + + public static org.omg.CORBA.TypeCodePackage.Bounds extract (org.omg.CORBA.Any a) + { + return read (a.create_input_stream ()); + } + + private static org.omg.CORBA.TypeCode __typeCode = null; + private static boolean __active = false; + synchronized public static org.omg.CORBA.TypeCode type () + { + if (__typeCode == null) + { + synchronized (org.omg.CORBA.TypeCode.class) + { + if (__typeCode == null) + { + if (__active) + { + return org.omg.CORBA.ORB.init().create_recursive_tc ( _id ); + } + __active = true; + org.omg.CORBA.StructMember[] _members0 = new org.omg.CORBA.StructMember [0]; + org.omg.CORBA.TypeCode _tcOf_members0 = null; + __typeCode = org.omg.CORBA.ORB.init ().create_exception_tc (org.omg.CORBA.TypeCodePackage.BoundsHelper.id (), "Bounds", _members0); + __active = false; + } + } + } + return __typeCode; + } + + public static String id () + { + return _id; + } + + public static org.omg.CORBA.TypeCodePackage.Bounds read (org.omg.CORBA.portable.InputStream istream) + { + org.omg.CORBA.TypeCodePackage.Bounds value = new org.omg.CORBA.TypeCodePackage.Bounds (); + // read and discard the repository ID + istream.read_string (); + return value; + } + + public static void write (org.omg.CORBA.portable.OutputStream ostream, org.omg.CORBA.TypeCodePackage.Bounds value) + { + // write the repository ID + ostream.write_string (id ()); + } + +} diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 57051d33f64..c13907dcf7d 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -470,3 +470,5 @@ bf92b8db249cdfa5651ef954b6c0743a7e0ea4cd jdk9-b64 e7ae94c4f35e940ea423fc1dd260435df34a77c0 jdk9-b65 197e94e0dacddd16816f101d24fc0442ab518326 jdk9-b66 d47dfabd16d48eb96a451edd1b61194a39ee0eb5 jdk9-b67 +11af3990d56c97b40318bc1f20608e86f051a3f7 jdk9-b68 +ff0929a59ced0e144201aa05819ae2e47d6f2c61 jdk9-b69 diff --git a/hotspot/make/linux/makefiles/dtrace.make b/hotspot/make/linux/makefiles/dtrace.make index 4dbe4cbf21d..2c898d0e778 100644 --- a/hotspot/make/linux/makefiles/dtrace.make +++ b/hotspot/make/linux/makefiles/dtrace.make @@ -31,8 +31,8 @@ ifndef OPENJDK REASON = "This JDK does not support SDT probes" else -# We need a recent GCC for the default -ifeq "$(shell expr \( $(CC_VER_MAJOR) \>= 4 \) \& \( $(CC_VER_MINOR) \>= 4 \) )" "0" +# We need a recent GCC for the default (4.4 or later) +ifeq "$(shell expr \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 4 \) \) \| \( $(CC_VER_MAJOR) \>= 5 \) )" "0" REASON = "gcc version is too old" else diff --git a/hotspot/make/test/JtregNative.gmk b/hotspot/make/test/JtregNative.gmk index e62bc94abe2..e447560be56 100644 --- a/hotspot/make/test/JtregNative.gmk +++ b/hotspot/make/test/JtregNative.gmk @@ -44,6 +44,7 @@ BUILD_HOTSPOT_JTREG_NATIVE_SRC := \ $(HOTSPOT_TOPDIR)/test/native_sanity \ $(HOTSPOT_TOPDIR)/test/runtime/jni/8025979 \ $(HOTSPOT_TOPDIR)/test/runtime/jni/8033445 \ + $(HOTSPOT_TOPDIR)/test/runtime/jni/ToStringInInterfaceTest \ # BUILD_HOTSPOT_JTREG_OUTPUT_DIR := $(BUILD_OUTPUT)/support/test/hotspot/jtreg/native diff --git a/hotspot/src/cpu/sparc/vm/sparc.ad b/hotspot/src/cpu/sparc/vm/sparc.ad index 01e0c805b5f..4a742755f29 100644 --- a/hotspot/src/cpu/sparc/vm/sparc.ad +++ b/hotspot/src/cpu/sparc/vm/sparc.ad @@ -3372,6 +3372,25 @@ operand immI() %{ interface(CONST_INTER); %} +// Integer Immediate: 0-bit +operand immI0() %{ + predicate(n->get_int() == 0); + match(ConI); + op_cost(0); + + format %{ %} + interface(CONST_INTER); +%} + +// Integer Immediate: 5-bit +operand immI5() %{ + predicate(Assembler::is_simm5(n->get_int())); + match(ConI); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + // Integer Immediate: 8-bit operand immI8() %{ predicate(Assembler::is_simm8(n->get_int())); @@ -3381,6 +3400,25 @@ operand immI8() %{ interface(CONST_INTER); %} +// Integer Immediate: the value 10 +operand immI10() %{ + predicate(n->get_int() == 10); + match(ConI); + op_cost(0); + + format %{ %} + interface(CONST_INTER); +%} + +// Integer Immediate: 11-bit +operand immI11() %{ + predicate(Assembler::is_simm11(n->get_int())); + match(ConI); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + // Integer Immediate: 13-bit operand immI13() %{ predicate(Assembler::is_simm13(n->get_int())); @@ -3410,84 +3448,6 @@ operand immI16() %{ interface(CONST_INTER); %} -// Unsigned Integer Immediate: 12-bit (non-negative that fits in simm13) -operand immU12() %{ - predicate((0 <= n->get_int()) && Assembler::is_simm13(n->get_int())); - match(ConI); - op_cost(0); - - format %{ %} - interface(CONST_INTER); -%} - -// Integer Immediate: 6-bit -operand immU6() %{ - predicate(n->get_int() >= 0 && n->get_int() <= 63); - match(ConI); - op_cost(0); - format %{ %} - interface(CONST_INTER); -%} - -// Integer Immediate: 11-bit -operand immI11() %{ - predicate(Assembler::is_simm11(n->get_int())); - match(ConI); - op_cost(0); - format %{ %} - interface(CONST_INTER); -%} - -// Integer Immediate: 5-bit -operand immI5() %{ - predicate(Assembler::is_simm5(n->get_int())); - match(ConI); - op_cost(0); - format %{ %} - interface(CONST_INTER); -%} - -// Int Immediate non-negative -operand immU31() -%{ - predicate(n->get_int() >= 0); - match(ConI); - - op_cost(0); - format %{ %} - interface(CONST_INTER); -%} - -// Integer Immediate: 0-bit -operand immI0() %{ - predicate(n->get_int() == 0); - match(ConI); - op_cost(0); - - format %{ %} - interface(CONST_INTER); -%} - -// Integer Immediate: the value 10 -operand immI10() %{ - predicate(n->get_int() == 10); - match(ConI); - op_cost(0); - - format %{ %} - interface(CONST_INTER); -%} - -// Integer Immediate: the values 0-31 -operand immU5() %{ - predicate(n->get_int() >= 0 && n->get_int() <= 31); - match(ConI); - op_cost(0); - - format %{ %} - interface(CONST_INTER); -%} - // Integer Immediate: the values 1-31 operand immI_1_31() %{ predicate(n->get_int() >= 1 && n->get_int() <= 31); @@ -3529,7 +3489,6 @@ operand immI_24() %{ format %{ %} interface(CONST_INTER); %} - // Integer Immediate: the value 255 operand immI_255() %{ predicate( n->get_int() == 255 ); @@ -3550,6 +3509,46 @@ operand immI_65535() %{ interface(CONST_INTER); %} +// Integer Immediate: the values 0-31 +operand immU5() %{ + predicate(n->get_int() >= 0 && n->get_int() <= 31); + match(ConI); + op_cost(0); + + format %{ %} + interface(CONST_INTER); +%} + +// Integer Immediate: 6-bit +operand immU6() %{ + predicate(n->get_int() >= 0 && n->get_int() <= 63); + match(ConI); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + +// Unsigned Integer Immediate: 12-bit (non-negative that fits in simm13) +operand immU12() %{ + predicate((0 <= n->get_int()) && Assembler::is_simm13(n->get_int())); + match(ConI); + op_cost(0); + + format %{ %} + interface(CONST_INTER); +%} + +// Integer Immediate non-negative +operand immU31() +%{ + predicate(n->get_int() >= 0); + match(ConI); + + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + // Long Immediate: the value FF operand immL_FF() %{ predicate( n->get_long() == 0xFFL ); @@ -5653,17 +5652,17 @@ instruct loadUB2L(iRegL dst, memory mem) %{ ins_pipe(iload_mem); %} -// Load Unsigned Byte (8 bit UNsigned) with 8-bit mask into Long Register -instruct loadUB2L_immI8(iRegL dst, memory mem, immI8 mask) %{ +// Load Unsigned Byte (8 bit UNsigned) with 32-bit mask into Long Register +instruct loadUB2L_immI(iRegL dst, memory mem, immI mask) %{ match(Set dst (ConvI2L (AndI (LoadUB mem) mask))); ins_cost(MEMORY_REF_COST + DEFAULT_COST); size(2*4); - format %{ "LDUB $mem,$dst\t# ubyte & 8-bit mask -> long\n\t" - "AND $dst,$mask,$dst" %} + format %{ "LDUB $mem,$dst\t# ubyte & 32-bit mask -> long\n\t" + "AND $dst,right_n_bits($mask, 8),$dst" %} ins_encode %{ __ ldub($mem$$Address, $dst$$Register); - __ and3($dst$$Register, $mask$$constant, $dst$$Register); + __ and3($dst$$Register, $mask$$constant & right_n_bits(8), $dst$$Register); %} ins_pipe(iload_mem); %} @@ -5776,20 +5775,20 @@ instruct loadUS2L_immI13(iRegL dst, memory mem, immI13 mask) %{ ins_pipe(iload_mem); %} -// Load Unsigned Short/Char (16bit UNsigned) with a 16-bit mask into a Long Register -instruct loadUS2L_immI16(iRegL dst, memory mem, immI16 mask, iRegL tmp) %{ +// Load Unsigned Short/Char (16bit UNsigned) with a 32-bit mask into a Long Register +instruct loadUS2L_immI(iRegL dst, memory mem, immI mask, iRegL tmp) %{ match(Set dst (ConvI2L (AndI (LoadUS mem) mask))); effect(TEMP dst, TEMP tmp); ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST); - format %{ "LDUH $mem,$dst\t! ushort/char & 16-bit mask -> long\n\t" - "SET $mask,$tmp\n\t" + format %{ "LDUH $mem,$dst\t! ushort/char & 32-bit mask -> long\n\t" + "SET right_n_bits($mask, 16),$tmp\n\t" "AND $dst,$tmp,$dst" %} ins_encode %{ Register Rdst = $dst$$Register; Register Rtmp = $tmp$$Register; __ lduh($mem$$Address, Rdst); - __ set($mask$$constant, Rtmp); + __ set($mask$$constant & right_n_bits(16), Rtmp); __ and3(Rdst, Rtmp, Rdst); %} ins_pipe(iload_mem); diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.cpp b/hotspot/src/cpu/x86/vm/assembler_x86.cpp index b6f92e8730e..7844b15a778 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp @@ -2813,6 +2813,13 @@ void Assembler::orl(Register dst, Register src) { emit_arith(0x0B, 0xC0, dst, src); } +void Assembler::orl(Address dst, Register src) { + InstructionMark im(this); + prefix(dst, src); + emit_int8(0x09); + emit_operand(src, dst); +} + void Assembler::packuswb(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes"); @@ -6907,6 +6914,19 @@ void Assembler::rclq(Register dst, int imm8) { } } +void Assembler::rcrq(Register dst, int imm8) { + assert(isShiftCount(imm8 >> 1), "illegal shift count"); + int encode = prefixq_and_encode(dst->encoding()); + if (imm8 == 1) { + emit_int8((unsigned char)0xD1); + emit_int8((unsigned char)(0xD8 | encode)); + } else { + emit_int8((unsigned char)0xC1); + emit_int8((unsigned char)(0xD8 | encode)); + emit_int8(imm8); + } +} + void Assembler::rorq(Register dst, int imm8) { assert(isShiftCount(imm8 >> 1), "illegal shift count"); int encode = prefixq_and_encode(dst->encoding()); diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.hpp b/hotspot/src/cpu/x86/vm/assembler_x86.hpp index 32619735400..f3d8410c200 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp @@ -1594,6 +1594,7 @@ private: void orl(Register dst, int32_t imm32); void orl(Register dst, Address src); void orl(Register dst, Register src); + void orl(Address dst, Register src); void orq(Address dst, int32_t imm32); void orq(Register dst, int32_t imm32); @@ -1694,6 +1695,8 @@ private: void rclq(Register dst, int imm8); + void rcrq(Register dst, int imm8); + void rdtsc(); void ret(int imm16); diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp index d172a467f3c..599d905648f 100644 --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp @@ -7750,6 +7750,503 @@ void MacroAssembler::multiply_to_len(Register x, Register xlen, Register y, Regi pop(tmp2); pop(tmp1); } + +//Helper functions for square_to_len() + +/** + * Store the squares of x[], right shifted one bit (divided by 2) into z[] + * Preserves x and z and modifies rest of the registers. + */ + +void MacroAssembler::square_rshift(Register x, Register xlen, Register z, Register tmp1, Register tmp3, Register tmp4, Register tmp5, Register rdxReg, Register raxReg) { + // Perform square and right shift by 1 + // Handle odd xlen case first, then for even xlen do the following + // jlong carry = 0; + // for (int j=0, i=0; j < xlen; j+=2, i+=4) { + // huge_128 product = x[j:j+1] * x[j:j+1]; + // z[i:i+1] = (carry << 63) | (jlong)(product >>> 65); + // z[i+2:i+3] = (jlong)(product >>> 1); + // carry = (jlong)product; + // } + + xorq(tmp5, tmp5); // carry + xorq(rdxReg, rdxReg); + xorl(tmp1, tmp1); // index for x + xorl(tmp4, tmp4); // index for z + + Label L_first_loop, L_first_loop_exit; + + testl(xlen, 1); + jccb(Assembler::zero, L_first_loop); //jump if xlen is even + + // Square and right shift by 1 the odd element using 32 bit multiply + movl(raxReg, Address(x, tmp1, Address::times_4, 0)); + imulq(raxReg, raxReg); + shrq(raxReg, 1); + adcq(tmp5, 0); + movq(Address(z, tmp4, Address::times_4, 0), raxReg); + incrementl(tmp1); + addl(tmp4, 2); + + // Square and right shift by 1 the rest using 64 bit multiply + bind(L_first_loop); + cmpptr(tmp1, xlen); + jccb(Assembler::equal, L_first_loop_exit); + + // Square + movq(raxReg, Address(x, tmp1, Address::times_4, 0)); + rorq(raxReg, 32); // convert big-endian to little-endian + mulq(raxReg); // 64-bit multiply rax * rax -> rdx:rax + + // Right shift by 1 and save carry + shrq(tmp5, 1); // rdx:rax:tmp5 = (tmp5:rdx:rax) >>> 1 + rcrq(rdxReg, 1); + rcrq(raxReg, 1); + adcq(tmp5, 0); + + // Store result in z + movq(Address(z, tmp4, Address::times_4, 0), rdxReg); + movq(Address(z, tmp4, Address::times_4, 8), raxReg); + + // Update indices for x and z + addl(tmp1, 2); + addl(tmp4, 4); + jmp(L_first_loop); + + bind(L_first_loop_exit); +} + + +/** + * Perform the following multiply add operation using BMI2 instructions + * carry:sum = sum + op1*op2 + carry + * op2 should be in rdx + * op2 is preserved, all other registers are modified + */ +void MacroAssembler::multiply_add_64_bmi2(Register sum, Register op1, Register op2, Register carry, Register tmp2) { + // assert op2 is rdx + mulxq(tmp2, op1, op1); // op1 * op2 -> tmp2:op1 + addq(sum, carry); + adcq(tmp2, 0); + addq(sum, op1); + adcq(tmp2, 0); + movq(carry, tmp2); +} + +/** + * Perform the following multiply add operation: + * carry:sum = sum + op1*op2 + carry + * Preserves op1, op2 and modifies rest of registers + */ +void MacroAssembler::multiply_add_64(Register sum, Register op1, Register op2, Register carry, Register rdxReg, Register raxReg) { + // rdx:rax = op1 * op2 + movq(raxReg, op2); + mulq(op1); + + // rdx:rax = sum + carry + rdx:rax + addq(sum, carry); + adcq(rdxReg, 0); + addq(sum, raxReg); + adcq(rdxReg, 0); + + // carry:sum = rdx:sum + movq(carry, rdxReg); +} + +/** + * Add 64 bit long carry into z[] with carry propogation. + * Preserves z and carry register values and modifies rest of registers. + * + */ +void MacroAssembler::add_one_64(Register z, Register zlen, Register carry, Register tmp1) { + Label L_fourth_loop, L_fourth_loop_exit; + + movl(tmp1, 1); + subl(zlen, 2); + addq(Address(z, zlen, Address::times_4, 0), carry); + + bind(L_fourth_loop); + jccb(Assembler::carryClear, L_fourth_loop_exit); + subl(zlen, 2); + jccb(Assembler::negative, L_fourth_loop_exit); + addq(Address(z, zlen, Address::times_4, 0), tmp1); + jmp(L_fourth_loop); + bind(L_fourth_loop_exit); +} + +/** + * Shift z[] left by 1 bit. + * Preserves x, len, z and zlen registers and modifies rest of the registers. + * + */ +void MacroAssembler::lshift_by_1(Register x, Register len, Register z, Register zlen, Register tmp1, Register tmp2, Register tmp3, Register tmp4) { + + Label L_fifth_loop, L_fifth_loop_exit; + + // Fifth loop + // Perform primitiveLeftShift(z, zlen, 1) + + const Register prev_carry = tmp1; + const Register new_carry = tmp4; + const Register value = tmp2; + const Register zidx = tmp3; + + // int zidx, carry; + // long value; + // carry = 0; + // for (zidx = zlen-2; zidx >=0; zidx -= 2) { + // (carry:value) = (z[i] << 1) | carry ; + // z[i] = value; + // } + + movl(zidx, zlen); + xorl(prev_carry, prev_carry); // clear carry flag and prev_carry register + + bind(L_fifth_loop); + decl(zidx); // Use decl to preserve carry flag + decl(zidx); + jccb(Assembler::negative, L_fifth_loop_exit); + + if (UseBMI2Instructions) { + movq(value, Address(z, zidx, Address::times_4, 0)); + rclq(value, 1); + rorxq(value, value, 32); + movq(Address(z, zidx, Address::times_4, 0), value); // Store back in big endian form + } + else { + // clear new_carry + xorl(new_carry, new_carry); + + // Shift z[i] by 1, or in previous carry and save new carry + movq(value, Address(z, zidx, Address::times_4, 0)); + shlq(value, 1); + adcl(new_carry, 0); + + orq(value, prev_carry); + rorq(value, 0x20); + movq(Address(z, zidx, Address::times_4, 0), value); // Store back in big endian form + + // Set previous carry = new carry + movl(prev_carry, new_carry); + } + jmp(L_fifth_loop); + + bind(L_fifth_loop_exit); +} + + +/** + * Code for BigInteger::squareToLen() intrinsic + * + * rdi: x + * rsi: len + * r8: z + * rcx: zlen + * r12: tmp1 + * r13: tmp2 + * r14: tmp3 + * r15: tmp4 + * rbx: tmp5 + * + */ +void MacroAssembler::square_to_len(Register x, Register len, Register z, Register zlen, Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5, Register rdxReg, Register raxReg) { + + Label L_second_loop, L_second_loop_exit, L_third_loop, L_third_loop_exit, fifth_loop, fifth_loop_exit, L_last_x, L_multiply; + push(tmp1); + push(tmp2); + push(tmp3); + push(tmp4); + push(tmp5); + + // First loop + // Store the squares, right shifted one bit (i.e., divided by 2). + square_rshift(x, len, z, tmp1, tmp3, tmp4, tmp5, rdxReg, raxReg); + + // Add in off-diagonal sums. + // + // Second, third (nested) and fourth loops. + // zlen +=2; + // for (int xidx=len-2,zidx=zlen-4; xidx > 0; xidx-=2,zidx-=4) { + // carry = 0; + // long op2 = x[xidx:xidx+1]; + // for (int j=xidx-2,k=zidx; j >= 0; j-=2) { + // k -= 2; + // long op1 = x[j:j+1]; + // long sum = z[k:k+1]; + // carry:sum = multiply_add_64(sum, op1, op2, carry, tmp_regs); + // z[k:k+1] = sum; + // } + // add_one_64(z, k, carry, tmp_regs); + // } + + const Register carry = tmp5; + const Register sum = tmp3; + const Register op1 = tmp4; + Register op2 = tmp2; + + push(zlen); + push(len); + addl(zlen,2); + bind(L_second_loop); + xorq(carry, carry); + subl(zlen, 4); + subl(len, 2); + push(zlen); + push(len); + cmpl(len, 0); + jccb(Assembler::lessEqual, L_second_loop_exit); + + // Multiply an array by one 64 bit long. + if (UseBMI2Instructions) { + op2 = rdxReg; + movq(op2, Address(x, len, Address::times_4, 0)); + rorxq(op2, op2, 32); + } + else { + movq(op2, Address(x, len, Address::times_4, 0)); + rorq(op2, 32); + } + + bind(L_third_loop); + decrementl(len); + jccb(Assembler::negative, L_third_loop_exit); + decrementl(len); + jccb(Assembler::negative, L_last_x); + + movq(op1, Address(x, len, Address::times_4, 0)); + rorq(op1, 32); + + bind(L_multiply); + subl(zlen, 2); + movq(sum, Address(z, zlen, Address::times_4, 0)); + + // Multiply 64 bit by 64 bit and add 64 bits lower half and upper 64 bits as carry. + if (UseBMI2Instructions) { + multiply_add_64_bmi2(sum, op1, op2, carry, tmp2); + } + else { + multiply_add_64(sum, op1, op2, carry, rdxReg, raxReg); + } + + movq(Address(z, zlen, Address::times_4, 0), sum); + + jmp(L_third_loop); + bind(L_third_loop_exit); + + // Fourth loop + // Add 64 bit long carry into z with carry propogation. + // Uses offsetted zlen. + add_one_64(z, zlen, carry, tmp1); + + pop(len); + pop(zlen); + jmp(L_second_loop); + + // Next infrequent code is moved outside loops. + bind(L_last_x); + movl(op1, Address(x, 0)); + jmp(L_multiply); + + bind(L_second_loop_exit); + pop(len); + pop(zlen); + pop(len); + pop(zlen); + + // Fifth loop + // Shift z left 1 bit. + lshift_by_1(x, len, z, zlen, tmp1, tmp2, tmp3, tmp4); + + // z[zlen-1] |= x[len-1] & 1; + movl(tmp3, Address(x, len, Address::times_4, -4)); + andl(tmp3, 1); + orl(Address(z, zlen, Address::times_4, -4), tmp3); + + pop(tmp5); + pop(tmp4); + pop(tmp3); + pop(tmp2); + pop(tmp1); +} + +/** + * Helper function for mul_add() + * Multiply the in[] by int k and add to out[] starting at offset offs using + * 128 bit by 32 bit multiply and return the carry in tmp5. + * Only quad int aligned length of in[] is operated on in this function. + * k is in rdxReg for BMI2Instructions, for others it is in tmp2. + * This function preserves out, in and k registers. + * len and offset point to the appropriate index in "in" & "out" correspondingly + * tmp5 has the carry. + * other registers are temporary and are modified. + * + */ +void MacroAssembler::mul_add_128_x_32_loop(Register out, Register in, + Register offset, Register len, Register tmp1, Register tmp2, Register tmp3, + Register tmp4, Register tmp5, Register rdxReg, Register raxReg) { + + Label L_first_loop, L_first_loop_exit; + + movl(tmp1, len); + shrl(tmp1, 2); + + bind(L_first_loop); + subl(tmp1, 1); + jccb(Assembler::negative, L_first_loop_exit); + + subl(len, 4); + subl(offset, 4); + + Register op2 = tmp2; + const Register sum = tmp3; + const Register op1 = tmp4; + const Register carry = tmp5; + + if (UseBMI2Instructions) { + op2 = rdxReg; + } + + movq(op1, Address(in, len, Address::times_4, 8)); + rorq(op1, 32); + movq(sum, Address(out, offset, Address::times_4, 8)); + rorq(sum, 32); + if (UseBMI2Instructions) { + multiply_add_64_bmi2(sum, op1, op2, carry, raxReg); + } + else { + multiply_add_64(sum, op1, op2, carry, rdxReg, raxReg); + } + // Store back in big endian from little endian + rorq(sum, 0x20); + movq(Address(out, offset, Address::times_4, 8), sum); + + movq(op1, Address(in, len, Address::times_4, 0)); + rorq(op1, 32); + movq(sum, Address(out, offset, Address::times_4, 0)); + rorq(sum, 32); + if (UseBMI2Instructions) { + multiply_add_64_bmi2(sum, op1, op2, carry, raxReg); + } + else { + multiply_add_64(sum, op1, op2, carry, rdxReg, raxReg); + } + // Store back in big endian from little endian + rorq(sum, 0x20); + movq(Address(out, offset, Address::times_4, 0), sum); + + jmp(L_first_loop); + bind(L_first_loop_exit); +} + +/** + * Code for BigInteger::mulAdd() intrinsic + * + * rdi: out + * rsi: in + * r11: offs (out.length - offset) + * rcx: len + * r8: k + * r12: tmp1 + * r13: tmp2 + * r14: tmp3 + * r15: tmp4 + * rbx: tmp5 + * Multiply the in[] by word k and add to out[], return the carry in rax + */ +void MacroAssembler::mul_add(Register out, Register in, Register offs, + Register len, Register k, Register tmp1, Register tmp2, Register tmp3, + Register tmp4, Register tmp5, Register rdxReg, Register raxReg) { + + Label L_carry, L_last_in, L_done; + +// carry = 0; +// for (int j=len-1; j >= 0; j--) { +// long product = (in[j] & LONG_MASK) * kLong + +// (out[offs] & LONG_MASK) + carry; +// out[offs--] = (int)product; +// carry = product >>> 32; +// } +// + push(tmp1); + push(tmp2); + push(tmp3); + push(tmp4); + push(tmp5); + + Register op2 = tmp2; + const Register sum = tmp3; + const Register op1 = tmp4; + const Register carry = tmp5; + + if (UseBMI2Instructions) { + op2 = rdxReg; + movl(op2, k); + } + else { + movl(op2, k); + } + + xorq(carry, carry); + + //First loop + + //Multiply in[] by k in a 4 way unrolled loop using 128 bit by 32 bit multiply + //The carry is in tmp5 + mul_add_128_x_32_loop(out, in, offs, len, tmp1, tmp2, tmp3, tmp4, tmp5, rdxReg, raxReg); + + //Multiply the trailing in[] entry using 64 bit by 32 bit, if any + decrementl(len); + jccb(Assembler::negative, L_carry); + decrementl(len); + jccb(Assembler::negative, L_last_in); + + movq(op1, Address(in, len, Address::times_4, 0)); + rorq(op1, 32); + + subl(offs, 2); + movq(sum, Address(out, offs, Address::times_4, 0)); + rorq(sum, 32); + + if (UseBMI2Instructions) { + multiply_add_64_bmi2(sum, op1, op2, carry, raxReg); + } + else { + multiply_add_64(sum, op1, op2, carry, rdxReg, raxReg); + } + + // Store back in big endian from little endian + rorq(sum, 0x20); + movq(Address(out, offs, Address::times_4, 0), sum); + + testl(len, len); + jccb(Assembler::zero, L_carry); + + //Multiply the last in[] entry, if any + bind(L_last_in); + movl(op1, Address(in, 0)); + movl(sum, Address(out, offs, Address::times_4, -4)); + + movl(raxReg, k); + mull(op1); //tmp4 * eax -> edx:eax + addl(sum, carry); + adcl(rdxReg, 0); + addl(sum, raxReg); + adcl(rdxReg, 0); + movl(carry, rdxReg); + + movl(Address(out, offs, Address::times_4, -4), sum); + + bind(L_carry); + //return tmp5/carry as carry in rax + movl(rax, carry); + + bind(L_done); + pop(tmp5); + pop(tmp4); + pop(tmp3); + pop(tmp2); + pop(tmp1); +} #endif /** diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp index ad75e27ddd9..025456eeaf5 100644 --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp @@ -1241,6 +1241,25 @@ public: Register carry2); void multiply_to_len(Register x, Register xlen, Register y, Register ylen, Register z, Register zlen, Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5); + + void square_rshift(Register x, Register len, Register z, Register tmp1, Register tmp3, + Register tmp4, Register tmp5, Register rdxReg, Register raxReg); + void multiply_add_64_bmi2(Register sum, Register op1, Register op2, Register carry, + Register tmp2); + void multiply_add_64(Register sum, Register op1, Register op2, Register carry, + Register rdxReg, Register raxReg); + void add_one_64(Register z, Register zlen, Register carry, Register tmp1); + void lshift_by_1(Register x, Register len, Register z, Register zlen, Register tmp1, Register tmp2, + Register tmp3, Register tmp4); + void square_to_len(Register x, Register len, Register z, Register zlen, Register tmp1, Register tmp2, + Register tmp3, Register tmp4, Register tmp5, Register rdxReg, Register raxReg); + + void mul_add_128_x_32_loop(Register out, Register in, Register offset, Register len, Register tmp1, + Register tmp2, Register tmp3, Register tmp4, Register tmp5, Register rdxReg, + Register raxReg); + void mul_add(Register out, Register in, Register offset, Register len, Register k, Register tmp1, + Register tmp2, Register tmp3, Register tmp4, Register tmp5, Register rdxReg, + Register raxReg); #endif // CRC32 code for java.util.zip.CRC32::updateBytes() instrinsic. diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp index e52da3ec6b6..ffcb7696114 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp @@ -3785,6 +3785,107 @@ class StubGenerator: public StubCodeGenerator { return start; } +/** + * Arguments: + * + // Input: + // c_rarg0 - x address + // c_rarg1 - x length + // c_rarg2 - z address + // c_rarg3 - z lenth + * + */ + address generate_squareToLen() { + + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", "squareToLen"); + + address start = __ pc(); + // Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...) + // Unix: rdi, rsi, rdx, rcx (c_rarg0, c_rarg1, ...) + const Register x = rdi; + const Register len = rsi; + const Register z = r8; + const Register zlen = rcx; + + const Register tmp1 = r12; + const Register tmp2 = r13; + const Register tmp3 = r14; + const Register tmp4 = r15; + const Register tmp5 = rbx; + + BLOCK_COMMENT("Entry:"); + __ enter(); // required for proper stackwalking of RuntimeStub frame + + setup_arg_regs(4); // x => rdi, len => rsi, z => rdx + // zlen => rcx + // r9 and r10 may be used to save non-volatile registers + __ movptr(r8, rdx); + __ square_to_len(x, len, z, zlen, tmp1, tmp2, tmp3, tmp4, tmp5, rdx, rax); + + restore_arg_regs(); + + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ ret(0); + + return start; + } + + /** + * Arguments: + * + * Input: + * c_rarg0 - out address + * c_rarg1 - in address + * c_rarg2 - offset + * c_rarg3 - len + * not Win64 + * c_rarg4 - k + * Win64 + * rsp+40 - k + */ + address generate_mulAdd() { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", "mulAdd"); + + address start = __ pc(); + // Win64: rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...) + // Unix: rdi, rsi, rdx, rcx, r8, r9 (c_rarg0, c_rarg1, ...) + const Register out = rdi; + const Register in = rsi; + const Register offset = r11; + const Register len = rcx; + const Register k = r8; + + // Next registers will be saved on stack in mul_add(). + const Register tmp1 = r12; + const Register tmp2 = r13; + const Register tmp3 = r14; + const Register tmp4 = r15; + const Register tmp5 = rbx; + + BLOCK_COMMENT("Entry:"); + __ enter(); // required for proper stackwalking of RuntimeStub frame + + setup_arg_regs(4); // out => rdi, in => rsi, offset => rdx + // len => rcx, k => r8 + // r9 and r10 may be used to save non-volatile registers +#ifdef _WIN64 + // last argument is on stack on Win64 + __ movl(k, Address(rsp, 6 * wordSize)); +#endif + __ movptr(r11, rdx); // move offset in rdx to offset(r11) + __ mul_add(out, in, offset, len, k, tmp1, tmp2, tmp3, tmp4, tmp5, rdx, rax); + + restore_arg_regs(); + + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ ret(0); + + return start; + } + + #undef __ #define __ masm-> @@ -4030,6 +4131,12 @@ class StubGenerator: public StubCodeGenerator { if (UseMultiplyToLenIntrinsic) { StubRoutines::_multiplyToLen = generate_multiplyToLen(); } + if (UseSquareToLenIntrinsic) { + StubRoutines::_squareToLen = generate_squareToLen(); + } + if (UseMulAddIntrinsic) { + StubRoutines::_mulAdd = generate_mulAdd(); + } #endif } diff --git a/hotspot/src/cpu/x86/vm/stubRoutines_x86_64.hpp b/hotspot/src/cpu/x86/vm/stubRoutines_x86_64.hpp index 205bce4eb76..15922b8aedc 100644 --- a/hotspot/src/cpu/x86/vm/stubRoutines_x86_64.hpp +++ b/hotspot/src/cpu/x86/vm/stubRoutines_x86_64.hpp @@ -33,7 +33,7 @@ static bool returns_to_call_stub(address return_pc) { return return_pc == _ enum platform_dependent_constants { code_size1 = 19000, // simply increase if too small (assembler will crash if too small) - code_size2 = 22000 // simply increase if too small (assembler will crash if too small) + code_size2 = 23000 // simply increase if too small (assembler will crash if too small) }; class x86 { diff --git a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp index e09a13af3b7..7a8f6c11969 100644 --- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp +++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp @@ -790,6 +790,12 @@ void VM_Version::get_processor_features() { if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) { UseMultiplyToLenIntrinsic = true; } + if (FLAG_IS_DEFAULT(UseSquareToLenIntrinsic)) { + UseSquareToLenIntrinsic = true; + } + if (FLAG_IS_DEFAULT(UseMulAddIntrinsic)) { + UseMulAddIntrinsic = true; + } #else if (UseMultiplyToLenIntrinsic) { if (!FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) { @@ -797,6 +803,18 @@ void VM_Version::get_processor_features() { } FLAG_SET_DEFAULT(UseMultiplyToLenIntrinsic, false); } + if (UseSquareToLenIntrinsic) { + if (!FLAG_IS_DEFAULT(UseSquareToLenIntrinsic)) { + warning("squareToLen intrinsic is not available in 32-bit VM"); + } + FLAG_SET_DEFAULT(UseSquareToLenIntrinsic, false); + } + if (UseMulAddIntrinsic) { + if (!FLAG_IS_DEFAULT(UseMulAddIntrinsic)) { + warning("mulAdd intrinsic is not available in 32-bit VM"); + } + FLAG_SET_DEFAULT(UseMulAddIntrinsic, false); + } #endif #endif // COMPILER2 diff --git a/hotspot/src/cpu/x86/vm/x86_32.ad b/hotspot/src/cpu/x86/vm/x86_32.ad index 23731beea1a..be2f7e65b36 100644 --- a/hotspot/src/cpu/x86/vm/x86_32.ad +++ b/hotspot/src/cpu/x86/vm/x86_32.ad @@ -5431,18 +5431,18 @@ instruct loadUB2L(eRegL dst, memory mem, eFlagsReg cr) %{ %} // Load Unsigned Byte (8 bit UNsigned) with mask into Long Register -instruct loadUB2L_immI8(eRegL dst, memory mem, immI8 mask, eFlagsReg cr) %{ +instruct loadUB2L_immI(eRegL dst, memory mem, immI mask, eFlagsReg cr) %{ match(Set dst (ConvI2L (AndI (LoadUB mem) mask))); effect(KILL cr); - format %{ "MOVZX8 $dst.lo,$mem\t# ubyte & 8-bit mask -> long\n\t" + format %{ "MOVZX8 $dst.lo,$mem\t# ubyte & 32-bit mask -> long\n\t" "XOR $dst.hi,$dst.hi\n\t" - "AND $dst.lo,$mask" %} + "AND $dst.lo,right_n_bits($mask, 8)" %} ins_encode %{ Register Rdst = $dst$$Register; __ movzbl(Rdst, $mem$$Address); __ xorl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rdst)); - __ andl(Rdst, $mask$$constant); + __ andl(Rdst, $mask$$constant & right_n_bits(8)); %} ins_pipe(ialu_reg_mem); %} @@ -5550,19 +5550,19 @@ instruct loadUS2L_immI_255(eRegL dst, memory mem, immI_255 mask, eFlagsReg cr) % ins_pipe(ialu_reg_mem); %} -// Load Unsigned Short/Char (16 bit UNsigned) with a 16-bit mask into Long Register -instruct loadUS2L_immI16(eRegL dst, memory mem, immI16 mask, eFlagsReg cr) %{ +// Load Unsigned Short/Char (16 bit UNsigned) with a 32-bit mask into Long Register +instruct loadUS2L_immI(eRegL dst, memory mem, immI mask, eFlagsReg cr) %{ match(Set dst (ConvI2L (AndI (LoadUS mem) mask))); effect(KILL cr); - format %{ "MOVZX $dst.lo, $mem\t# ushort/char & 16-bit mask -> long\n\t" + format %{ "MOVZX $dst.lo, $mem\t# ushort/char & 32-bit mask -> long\n\t" "XOR $dst.hi,$dst.hi\n\t" - "AND $dst.lo,$mask" %} + "AND $dst.lo,right_n_bits($mask, 16)" %} ins_encode %{ Register Rdst = $dst$$Register; __ movzwl(Rdst, $mem$$Address); __ xorl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rdst)); - __ andl(Rdst, $mask$$constant); + __ andl(Rdst, $mask$$constant & right_n_bits(16)); %} ins_pipe(ialu_reg_mem); %} diff --git a/hotspot/src/cpu/x86/vm/x86_64.ad b/hotspot/src/cpu/x86/vm/x86_64.ad index 538ec3a360d..ea8b1c81276 100644 --- a/hotspot/src/cpu/x86/vm/x86_64.ad +++ b/hotspot/src/cpu/x86/vm/x86_64.ad @@ -4753,17 +4753,17 @@ instruct loadUB2L(rRegL dst, memory mem) ins_pipe(ialu_reg_mem); %} -// Load Unsigned Byte (8 bit UNsigned) with a 8-bit mask into Long Register -instruct loadUB2L_immI8(rRegL dst, memory mem, immI8 mask, rFlagsReg cr) %{ +// Load Unsigned Byte (8 bit UNsigned) with 32-bit mask into Long Register +instruct loadUB2L_immI(rRegL dst, memory mem, immI mask, rFlagsReg cr) %{ match(Set dst (ConvI2L (AndI (LoadUB mem) mask))); effect(KILL cr); - format %{ "movzbq $dst, $mem\t# ubyte & 8-bit mask -> long\n\t" - "andl $dst, $mask" %} + format %{ "movzbq $dst, $mem\t# ubyte & 32-bit mask -> long\n\t" + "andl $dst, right_n_bits($mask, 8)" %} ins_encode %{ Register Rdst = $dst$$Register; __ movzbq(Rdst, $mem$$Address); - __ andl(Rdst, $mask$$constant); + __ andl(Rdst, $mask$$constant & right_n_bits(8)); %} ins_pipe(ialu_reg_mem); %} @@ -4863,17 +4863,17 @@ instruct loadUS2L_immI_255(rRegL dst, memory mem, immI_255 mask) %{ ins_pipe(ialu_reg_mem); %} -// Load Unsigned Short/Char (16 bit UNsigned) with mask into Long Register -instruct loadUS2L_immI16(rRegL dst, memory mem, immI16 mask, rFlagsReg cr) %{ +// Load Unsigned Short/Char (16 bit UNsigned) with 32-bit mask into Long Register +instruct loadUS2L_immI(rRegL dst, memory mem, immI mask, rFlagsReg cr) %{ match(Set dst (ConvI2L (AndI (LoadUS mem) mask))); effect(KILL cr); - format %{ "movzwq $dst, $mem\t# ushort/char & 16-bit mask -> long\n\t" - "andl $dst, $mask" %} + format %{ "movzwq $dst, $mem\t# ushort/char & 32-bit mask -> long\n\t" + "andl $dst, right_n_bits($mask, 16)" %} ins_encode %{ Register Rdst = $dst$$Register; __ movzwq(Rdst, $mem$$Address); - __ andl(Rdst, $mask$$constant); + __ andl(Rdst, $mask$$constant & right_n_bits(16)); %} ins_pipe(ialu_reg_mem); %} diff --git a/hotspot/src/os/aix/vm/os_aix.cpp b/hotspot/src/os/aix/vm/os_aix.cpp index eee444ea1fb..49b5c63d7f1 100644 --- a/hotspot/src/os/aix/vm/os_aix.cpp +++ b/hotspot/src/os/aix/vm/os_aix.cpp @@ -1267,10 +1267,6 @@ void os::shutdown() { // Note: os::abort() might be called very early during initialization, or // called from signal handler. Before adding something to os::abort(), make // sure it is async-safe and can handle partially initialized VM. -void os::abort(bool dump_core) { - abort(dump_core, NULL, NULL); -} - void os::abort(bool dump_core, void* siginfo, void* context) { os::shutdown(); if (dump_core) { diff --git a/hotspot/src/os/bsd/vm/os_bsd.cpp b/hotspot/src/os/bsd/vm/os_bsd.cpp index d725b35350b..84bc8a9cff8 100644 --- a/hotspot/src/os/bsd/vm/os_bsd.cpp +++ b/hotspot/src/os/bsd/vm/os_bsd.cpp @@ -1131,10 +1131,6 @@ void os::shutdown() { // Note: os::abort() might be called very early during initialization, or // called from signal handler. Before adding something to os::abort(), make // sure it is async-safe and can handle partially initialized VM. -void os::abort(bool dump_core) { - abort(dump_core, NULL, NULL); -} - void os::abort(bool dump_core, void* siginfo, void* context) { os::shutdown(); if (dump_core) { diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index 3ae38ebed3c..f893061e288 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -1478,10 +1478,6 @@ void os::shutdown() { // Note: os::abort() might be called very early during initialization, or // called from signal handler. Before adding something to os::abort(), make // sure it is async-safe and can handle partially initialized VM. -void os::abort(bool dump_core) { - abort(dump_core, NULL, NULL); -} - void os::abort(bool dump_core, void* siginfo, void* context) { os::shutdown(); if (dump_core) { diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index befdb29b5cc..7ece72dd792 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -1520,10 +1520,6 @@ void os::shutdown() { // Note: os::abort() might be called very early during initialization, or // called from signal handler. Before adding something to os::abort(), make // sure it is async-safe and can handle partially initialized VM. -void os::abort(bool dump_core) { - abort(dump_core, NULL, NULL); -} - void os::abort(bool dump_core, void* siginfo, void* context) { os::shutdown(); if (dump_core) { diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index 2bae2d0e992..faf658a71ca 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -997,7 +997,16 @@ void os::check_dump_limit(char* buffer, size_t buffsz) { if (!FLAG_IS_DEFAULT(CreateCoredumpOnCrash) && !CreateCoredumpOnCrash) { jio_snprintf(buffer, buffsz, "CreateCoredumpOnCrash is disabled from command line"); status = false; - } else { + } + +#ifndef ASSERT + if (!os::win32::is_windows_server() && FLAG_IS_DEFAULT(CreateCoredumpOnCrash)) { + jio_snprintf(buffer, buffsz, "Minidumps are not enabled by default on client versions of Windows"); + status = false; + } +#endif + + if (status) { const char* cwd = get_current_directory(NULL, 0); int pid = current_process_id(); if (cwd != NULL) { @@ -1086,10 +1095,6 @@ void os::abort(bool dump_core, void* siginfo, void* context) { win32::exit_process_or_thread(win32::EPT_PROCESS, 1); } -void os::abort(bool dump_core) { - abort(dump_core, NULL, NULL); -} - // Die immediately, no exit hook, no abort hook, no cleanup. void os::die() { win32::exit_process_or_thread(win32::EPT_PROCESS_DIE, -1); diff --git a/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp b/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp index 3e388568342..08c46153e5f 100644 --- a/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp +++ b/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp @@ -59,8 +59,8 @@ extern sigjmp_buf* get_jmp_buf_for_continuation(); address os::current_stack_pointer() { - address dummy = (address) &dummy; - return dummy; + // return the address of the current function + return (address)__builtin_frame_address(0); } frame os::get_sender_for_C_frame(frame* fr) { diff --git a/hotspot/src/share/vm/ci/ciCallSite.cpp b/hotspot/src/share/vm/ci/ciCallSite.cpp index 028a4ed724f..fb222fe3f5a 100644 --- a/hotspot/src/share/vm/ci/ciCallSite.cpp +++ b/hotspot/src/share/vm/ci/ciCallSite.cpp @@ -49,25 +49,6 @@ ciMethodHandle* ciCallSite::get_target() const { return CURRENT_ENV->get_object(method_handle_oop)->as_method_handle(); } -// ------------------------------------------------------------------ -// ciCallSite::get_context -// -// Return the target MethodHandle of this CallSite. -ciKlass* ciCallSite::get_context() { - assert(!is_constant_call_site(), ""); - - VM_ENTRY_MARK; - oop call_site_oop = get_oop(); - InstanceKlass* ctxk = MethodHandles::get_call_site_context(call_site_oop); - if (ctxk == NULL) { - // The call site doesn't have a context associated. Set it to the default context. - oop def_context_oop = java_lang_invoke_CallSite::default_context(); - java_lang_invoke_CallSite::set_context_cas(call_site_oop, def_context_oop, /*expected=*/NULL); - ctxk = MethodHandles::get_call_site_context(call_site_oop); - } - return (CURRENT_ENV->get_metadata(ctxk))->as_klass(); -} - // ------------------------------------------------------------------ // ciCallSite::print // diff --git a/hotspot/src/share/vm/ci/ciCallSite.hpp b/hotspot/src/share/vm/ci/ciCallSite.hpp index 040e894d0df..063f1e3a5fe 100644 --- a/hotspot/src/share/vm/ci/ciCallSite.hpp +++ b/hotspot/src/share/vm/ci/ciCallSite.hpp @@ -43,7 +43,6 @@ public: // Return the target MethodHandle of this CallSite. ciMethodHandle* get_target() const; - ciKlass* get_context(); void print(); }; diff --git a/hotspot/src/share/vm/ci/ciEnv.cpp b/hotspot/src/share/vm/ci/ciEnv.cpp index b95ca80d6dc..6473606d499 100644 --- a/hotspot/src/share/vm/ci/ciEnv.cpp +++ b/hotspot/src/share/vm/ci/ciEnv.cpp @@ -709,24 +709,23 @@ Method* ciEnv::lookup_method(InstanceKlass* accessor, KlassHandle h_holder(THREAD, holder); LinkResolver::check_klass_accessability(h_accessor, h_holder, KILL_COMPILE_ON_FATAL_(NULL)); methodHandle dest_method; + LinkInfo link_info(h_holder, name, sig, h_accessor, /*check_access*/true); switch (bc) { case Bytecodes::_invokestatic: dest_method = - LinkResolver::resolve_static_call_or_null(h_holder, name, sig, h_accessor); + LinkResolver::resolve_static_call_or_null(link_info); break; case Bytecodes::_invokespecial: dest_method = - LinkResolver::resolve_special_call_or_null(h_holder, name, sig, h_accessor); + LinkResolver::resolve_special_call_or_null(link_info); break; case Bytecodes::_invokeinterface: dest_method = - LinkResolver::linktime_resolve_interface_method_or_null(h_holder, name, sig, - h_accessor, true); + LinkResolver::linktime_resolve_interface_method_or_null(link_info); break; case Bytecodes::_invokevirtual: dest_method = - LinkResolver::linktime_resolve_virtual_method_or_null(h_holder, name, sig, - h_accessor, true); + LinkResolver::linktime_resolve_virtual_method_or_null(link_info); break; default: ShouldNotReachHere(); } diff --git a/hotspot/src/share/vm/ci/ciField.cpp b/hotspot/src/share/vm/ci/ciField.cpp index ba3d07157aa..9fe63de27bf 100644 --- a/hotspot/src/share/vm/ci/ciField.cpp +++ b/hotspot/src/share/vm/ci/ciField.cpp @@ -352,11 +352,11 @@ bool ciField::will_link(ciInstanceKlass* accessing_klass, } } + LinkInfo link_info(_holder->get_instanceKlass(), + _name->get_symbol(), _signature->get_symbol(), + accessing_klass->get_Klass()); fieldDescriptor result; - LinkResolver::resolve_field(result, _holder->get_instanceKlass(), - _name->get_symbol(), _signature->get_symbol(), - accessing_klass->get_Klass(), bc, true, false, - KILL_COMPILE_ON_FATAL_(false)); + LinkResolver::resolve_field(result, link_info, bc, false, KILL_COMPILE_ON_FATAL_(false)); // update the hit-cache, unless there is a problem with memory scoping: if (accessing_klass->is_shared() || !is_shared()) { diff --git a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp index b81206a1616..ec97e100d48 100644 --- a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp +++ b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp @@ -453,8 +453,12 @@ int ciInstanceKlass::compute_nonstatic_fields() { if (fields == NULL) { // This can happen if this class (java.lang.Class) has invisible fields. - _nonstatic_fields = super_fields; - return super_fields->length(); + if (super_fields != NULL) { + _nonstatic_fields = super_fields; + return super_fields->length(); + } else { + return 0; + } } int flen = fields->length(); diff --git a/hotspot/src/share/vm/ci/ciMethod.cpp b/hotspot/src/share/vm/ci/ciMethod.cpp index 859bd3eef4c..81ef4bf37df 100644 --- a/hotspot/src/share/vm/ci/ciMethod.cpp +++ b/hotspot/src/share/vm/ci/ciMethod.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -786,6 +786,7 @@ ciMethod* ciMethod::resolve_invoke(ciKlass* caller, ciKlass* exact_receiver, boo Symbol* h_name = name()->get_symbol(); Symbol* h_signature = signature()->get_symbol(); + LinkInfo link_info(h_resolved, h_name, h_signature, caller_klass, check_access); methodHandle m; // Only do exact lookup if receiver klass has been linked. Otherwise, // the vtable has not been setup, and the LinkResolver will fail. @@ -793,9 +794,9 @@ ciMethod* ciMethod::resolve_invoke(ciKlass* caller, ciKlass* exact_receiver, boo || InstanceKlass::cast(h_recv())->is_linked() && !exact_receiver->is_interface()) { if (holder()->is_interface()) { - m = LinkResolver::resolve_interface_call_or_null(h_recv, h_resolved, h_name, h_signature, caller_klass, check_access); + m = LinkResolver::resolve_interface_call_or_null(h_recv, link_info); } else { - m = LinkResolver::resolve_virtual_call_or_null(h_recv, h_resolved, h_name, h_signature, caller_klass, check_access); + m = LinkResolver::resolve_virtual_call_or_null(h_recv, link_info); } } @@ -839,7 +840,8 @@ int ciMethod::resolve_vtable_index(ciKlass* caller, ciKlass* receiver) { Symbol* h_name = name()->get_symbol(); Symbol* h_signature = signature()->get_symbol(); - vtable_index = LinkResolver::resolve_virtual_vtable_index(h_recv, h_recv, h_name, h_signature, caller_klass); + LinkInfo link_info(h_recv, h_name, h_signature, caller_klass); + vtable_index = LinkResolver::resolve_virtual_vtable_index(h_recv, link_info); if (vtable_index == Method::nonvirtual_vtable_index) { // A statically bound method. Return "no such index". vtable_index = Method::invalid_vtable_index; @@ -1285,10 +1287,8 @@ bool ciMethod::check_call(int refinfo_index, bool is_static) const { EXCEPTION_MARK; HandleMark hm(THREAD); constantPoolHandle pool (THREAD, get_Method()->constants()); - methodHandle spec_method; - KlassHandle spec_klass; Bytecodes::Code code = (is_static ? Bytecodes::_invokestatic : Bytecodes::_invokevirtual); - LinkResolver::resolve_method_statically(spec_method, spec_klass, code, pool, refinfo_index, THREAD); + methodHandle spec_method = LinkResolver::resolve_method_statically(code, pool, refinfo_index, THREAD); if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; return false; diff --git a/hotspot/src/share/vm/classfile/javaClasses.cpp b/hotspot/src/share/vm/classfile/javaClasses.cpp index 9ac84cc631f..a50e6762164 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.cpp +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp @@ -2967,47 +2967,42 @@ int java_lang_invoke_MethodType::rtype_slot_count(oop mt) { int java_lang_invoke_CallSite::_target_offset; int java_lang_invoke_CallSite::_context_offset; -int java_lang_invoke_CallSite::_default_context_offset; void java_lang_invoke_CallSite::compute_offsets() { Klass* k = SystemDictionary::CallSite_klass(); if (k != NULL) { compute_offset(_target_offset, k, vmSymbols::target_name(), vmSymbols::java_lang_invoke_MethodHandle_signature()); - compute_offset(_context_offset, k, vmSymbols::context_name(), vmSymbols::sun_misc_Cleaner_signature()); - compute_offset(_default_context_offset, k, - vmSymbols::DEFAULT_CONTEXT_name(), vmSymbols::sun_misc_Cleaner_signature(), - /*is_static=*/true, /*allow_super=*/false); + compute_offset(_context_offset, k, vmSymbols::context_name(), + vmSymbols::java_lang_invoke_MethodHandleNatives_CallSiteContext_signature()); } } -oop java_lang_invoke_CallSite::context_volatile(oop call_site) { +oop java_lang_invoke_CallSite::context(oop call_site) { assert(java_lang_invoke_CallSite::is_instance(call_site), ""); - oop dep_oop = call_site->obj_field_volatile(_context_offset); + oop dep_oop = call_site->obj_field(_context_offset); return dep_oop; } -void java_lang_invoke_CallSite::set_context_volatile(oop call_site, oop context) { - assert(java_lang_invoke_CallSite::is_instance(call_site), ""); - call_site->obj_field_put_volatile(_context_offset, context); -} +// Support for java_lang_invoke_MethodHandleNatives_CallSiteContext -bool java_lang_invoke_CallSite::set_context_cas(oop call_site, oop context, oop expected) { - assert(java_lang_invoke_CallSite::is_instance(call_site), ""); - HeapWord* context_addr = call_site->obj_field_addr(_context_offset); - oop res = oopDesc::atomic_compare_exchange_oop(context, context_addr, expected, true); - bool success = (res == expected); - if (success) { - update_barrier_set((void*)context_addr, context); +int java_lang_invoke_MethodHandleNatives_CallSiteContext::_vmdependencies_offset; + +void java_lang_invoke_MethodHandleNatives_CallSiteContext::compute_offsets() { + Klass* k = SystemDictionary::Context_klass(); + if (k != NULL) { + CALLSITECONTEXT_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET); } - return success; } -oop java_lang_invoke_CallSite::default_context() { - InstanceKlass* ik = InstanceKlass::cast(SystemDictionary::CallSite_klass()); - oop def_context_oop = ik->java_mirror()->obj_field(_default_context_offset); - assert(!oopDesc::is_null(def_context_oop), ""); - return def_context_oop; +nmethodBucket* java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(oop call_site) { + assert(java_lang_invoke_MethodHandleNatives_CallSiteContext::is_instance(call_site), ""); + return (nmethodBucket*) (address) call_site->long_field(_vmdependencies_offset); +} + +void java_lang_invoke_MethodHandleNatives_CallSiteContext::set_vmdependencies(oop call_site, nmethodBucket* context) { + assert(java_lang_invoke_MethodHandleNatives_CallSiteContext::is_instance(call_site), ""); + call_site->long_field_put(_vmdependencies_offset, (jlong) (address) context); } // Support for java_security_AccessControlContext @@ -3403,6 +3398,7 @@ void JavaClasses::compute_offsets() { java_lang_invoke_LambdaForm::compute_offsets(); java_lang_invoke_MethodType::compute_offsets(); java_lang_invoke_CallSite::compute_offsets(); + java_lang_invoke_MethodHandleNatives_CallSiteContext::compute_offsets(); java_security_AccessControlContext::compute_offsets(); // Initialize reflection classes. The layouts of these classes // changed with the new reflection implementation in JDK 1.4, and diff --git a/hotspot/src/share/vm/classfile/javaClasses.hpp b/hotspot/src/share/vm/classfile/javaClasses.hpp index 700cf4afab5..8410c8c2a2d 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.hpp +++ b/hotspot/src/share/vm/classfile/javaClasses.hpp @@ -1170,8 +1170,6 @@ class java_lang_invoke_CallSite: AllStatic { private: static int _target_offset; static int _context_offset; - static int _default_context_offset; - static void compute_offsets(); @@ -1181,11 +1179,7 @@ public: static void set_target( oop site, oop target); static void set_target_volatile( oop site, oop target); - static oop context_volatile(oop site); - static void set_context_volatile(oop site, oop context); - static bool set_context_cas (oop site, oop context, oop expected); - - static oop default_context(); + static oop context(oop site); // Testers static bool is_subclass(Klass* klass) { @@ -1197,6 +1191,31 @@ public: static int target_offset_in_bytes() { return _target_offset; } }; +// Interface to java.lang.invoke.MethodHandleNatives$CallSiteContext objects + +#define CALLSITECONTEXT_INJECTED_FIELDS(macro) \ + macro(java_lang_invoke_MethodHandleNatives_CallSiteContext, vmdependencies, intptr_signature, false) + +class java_lang_invoke_MethodHandleNatives_CallSiteContext : AllStatic { + friend class JavaClasses; + +private: + static int _vmdependencies_offset; + + static void compute_offsets(); + +public: + // Accessors + static nmethodBucket* vmdependencies(oop context); + static void set_vmdependencies(oop context, nmethodBucket* bucket); + + // Testers + static bool is_subclass(Klass* klass) { + return klass->is_subclass_of(SystemDictionary::Context_klass()); + } + static bool is_instance(oop obj); +}; + // Interface to java.security.AccessControlContext objects class java_security_AccessControlContext: AllStatic { @@ -1406,7 +1425,8 @@ class InjectedField { #define ALL_INJECTED_FIELDS(macro) \ CLASS_INJECTED_FIELDS(macro) \ CLASSLOADER_INJECTED_FIELDS(macro) \ - MEMBERNAME_INJECTED_FIELDS(macro) + MEMBERNAME_INJECTED_FIELDS(macro) \ + CALLSITECONTEXT_INJECTED_FIELDS(macro) // Interface to hard-coded offset checking diff --git a/hotspot/src/share/vm/classfile/javaClasses.inline.hpp b/hotspot/src/share/vm/classfile/javaClasses.inline.hpp index c5b2f32066d..723c2e86757 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.inline.hpp +++ b/hotspot/src/share/vm/classfile/javaClasses.inline.hpp @@ -49,6 +49,10 @@ inline bool java_lang_invoke_CallSite::is_instance(oop obj) { return obj != NULL && is_subclass(obj->klass()); } +inline bool java_lang_invoke_MethodHandleNatives_CallSiteContext::is_instance(oop obj) { + return obj != NULL && is_subclass(obj->klass()); +} + inline bool java_lang_invoke_MemberName::is_instance(oop obj) { return obj != NULL && is_subclass(obj->klass()); } diff --git a/hotspot/src/share/vm/classfile/systemDictionary.hpp b/hotspot/src/share/vm/classfile/systemDictionary.hpp index 126fc31d872..1f5644c236d 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.hpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp @@ -159,6 +159,7 @@ class Ticks; do_klass(MethodType_klass, java_lang_invoke_MethodType, Pre ) \ do_klass(BootstrapMethodError_klass, java_lang_BootstrapMethodError, Pre ) \ do_klass(CallSite_klass, java_lang_invoke_CallSite, Pre ) \ + do_klass(Context_klass, java_lang_invoke_MethodHandleNatives_CallSiteContext, Pre ) \ do_klass(ConstantCallSite_klass, java_lang_invoke_ConstantCallSite, Pre ) \ do_klass(MutableCallSite_klass, java_lang_invoke_MutableCallSite, Pre ) \ do_klass(VolatileCallSite_klass, java_lang_invoke_VolatileCallSite, Pre ) \ diff --git a/hotspot/src/share/vm/classfile/verifier.cpp b/hotspot/src/share/vm/classfile/verifier.cpp index f922aa3e96d..cdfe83edd9b 100644 --- a/hotspot/src/share/vm/classfile/verifier.cpp +++ b/hotspot/src/share/vm/classfile/verifier.cpp @@ -45,6 +45,8 @@ #include "runtime/javaCalls.hpp" #include "runtime/orderAccess.inline.hpp" #include "runtime/os.hpp" +#include "runtime/thread.hpp" +#include "services/threadService.hpp" #include "utilities/bytes.hpp" #define NOFAILOVER_MAJOR_VERSION 51 @@ -130,6 +132,16 @@ bool Verifier::verify(instanceKlassHandle klass, Verifier::Mode mode, bool shoul return true; } + // Timer includes any side effects of class verification (resolution, + // etc), but not recursive calls to Verifier::verify(). + JavaThread* jt = (JavaThread*)THREAD; + PerfClassTraceTime timer(ClassLoader::perf_class_verify_time(), + ClassLoader::perf_class_verify_selftime(), + ClassLoader::perf_classes_verified(), + jt->get_thread_stat()->perf_recursion_counts_addr(), + jt->get_thread_stat()->perf_timers_addr(), + PerfClassTraceTime::CLASS_VERIFY); + // If the class should be verified, first see if we can use the split // verifier. If not, or if verification fails and FailOverToOldVerifier // is set, then call the inference verifier. diff --git a/hotspot/src/share/vm/classfile/vmSymbols.hpp b/hotspot/src/share/vm/classfile/vmSymbols.hpp index 8d9f53e359d..d2a85e84492 100644 --- a/hotspot/src/share/vm/classfile/vmSymbols.hpp +++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp @@ -274,12 +274,14 @@ /* internal classes known only to the JVM: */ \ template(java_lang_invoke_MemberName, "java/lang/invoke/MemberName") \ template(java_lang_invoke_MethodHandleNatives, "java/lang/invoke/MethodHandleNatives") \ + template(java_lang_invoke_MethodHandleNatives_CallSiteContext, "java/lang/invoke/MethodHandleNatives$CallSiteContext") \ template(java_lang_invoke_LambdaForm, "java/lang/invoke/LambdaForm") \ template(java_lang_invoke_ForceInline_signature, "Ljava/lang/invoke/ForceInline;") \ template(java_lang_invoke_DontInline_signature, "Ljava/lang/invoke/DontInline;") \ template(java_lang_invoke_Stable_signature, "Ljava/lang/invoke/Stable;") \ template(java_lang_invoke_LambdaForm_Compiled_signature, "Ljava/lang/invoke/LambdaForm$Compiled;") \ template(java_lang_invoke_LambdaForm_Hidden_signature, "Ljava/lang/invoke/LambdaForm$Hidden;") \ + template(java_lang_invoke_MethodHandleNatives_CallSiteContext_signature, "Ljava/lang/invoke/MethodHandleNatives$CallSiteContext;") \ /* internal up-calls made only by the JVM, via class sun.invoke.MethodHandleNatives: */ \ template(findMethodHandleType_name, "findMethodHandleType") \ template(findMethodHandleType_signature, "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/invoke/MethodType;") \ @@ -401,7 +403,7 @@ template(protection_domain_name, "protection_domain") \ template(signers_name, "signers_name") \ template(loader_data_name, "loader_data") \ - template(dependencies_name, "dependencies") \ + template(vmdependencies_name, "vmdependencies") \ template(input_stream_void_signature, "(Ljava/io/InputStream;)V") \ template(getFileURL_name, "getFileURL") \ template(getFileURL_signature, "(Ljava/io/File;)Ljava/net/URL;") \ @@ -797,6 +799,14 @@ do_name( multiplyToLen_name, "multiplyToLen") \ do_signature(multiplyToLen_signature, "([II[II[I)[I") \ \ + do_intrinsic(_squareToLen, java_math_BigInteger, squareToLen_name, squareToLen_signature, F_S) \ + do_name( squareToLen_name, "implSquareToLen") \ + do_signature(squareToLen_signature, "([II[II)[I") \ + \ + do_intrinsic(_mulAdd, java_math_BigInteger, mulAdd_name, mulAdd_signature, F_S) \ + do_name( mulAdd_name, "implMulAdd") \ + do_signature(mulAdd_signature, "([I[IIII)I") \ + \ /* java/lang/ref/Reference */ \ do_intrinsic(_Reference_get, java_lang_ref_Reference, get_name, void_object_signature, F_R) \ \ diff --git a/hotspot/src/share/vm/code/codeCache.cpp b/hotspot/src/share/vm/code/codeCache.cpp index 8d801094d0f..16ee831ddb1 100644 --- a/hotspot/src/share/vm/code/codeCache.cpp +++ b/hotspot/src/share/vm/code/codeCache.cpp @@ -1047,40 +1047,6 @@ void CodeCache::flush_dependents_on(instanceKlassHandle dependee) { } } -// Flushes compiled methods dependent on a particular CallSite -// instance when its target is different than the given MethodHandle. -void CodeCache::flush_dependents_on(Handle call_site, Handle method_handle) { - assert_lock_strong(Compile_lock); - - if (number_of_nmethods_with_dependencies() == 0) return; - - // CodeCache can only be updated by a thread_in_VM and they will all be - // stopped during the safepoint so CodeCache will be safe to update without - // holding the CodeCache_lock. - - CallSiteDepChange changes(call_site(), method_handle()); - - // Compute the dependent nmethods that have a reference to a - // CallSite object. We use InstanceKlass::mark_dependent_nmethod - // directly instead of CodeCache::mark_for_deoptimization because we - // want dependents on the call site class only not all classes in - // the ContextStream. - int marked = 0; - { - MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); - InstanceKlass* ctxk = MethodHandles::get_call_site_context(call_site()); - if (ctxk == NULL) { - return; // No dependencies to invalidate yet. - } - marked = ctxk->mark_dependent_nmethods(changes); - } - if (marked > 0) { - // At least one nmethod has been marked for deoptimization - VM_Deoptimize op; - VMThread::execute(&op); - } -} - #ifdef HOTSWAP // Flushes compiled methods dependent on dependee in the evolutionary sense void CodeCache::flush_evol_dependents_on(instanceKlassHandle ev_k_h) { diff --git a/hotspot/src/share/vm/code/codeCache.hpp b/hotspot/src/share/vm/code/codeCache.hpp index 09879b125da..7030df6fc84 100644 --- a/hotspot/src/share/vm/code/codeCache.hpp +++ b/hotspot/src/share/vm/code/codeCache.hpp @@ -224,7 +224,6 @@ class CodeCache : AllStatic { // Flushing and deoptimization static void flush_dependents_on(instanceKlassHandle dependee); - static void flush_dependents_on(Handle call_site, Handle method_handle); #ifdef HOTSWAP // Flushing and deoptimization in case of evolution static void flush_evol_dependents_on(instanceKlassHandle dependee); diff --git a/hotspot/src/share/vm/code/dependencies.cpp b/hotspot/src/share/vm/code/dependencies.cpp index 1f56103be5b..132bc162d42 100644 --- a/hotspot/src/share/vm/code/dependencies.cpp +++ b/hotspot/src/share/vm/code/dependencies.cpp @@ -117,9 +117,7 @@ void Dependencies::assert_has_no_finalizable_subclasses(ciKlass* ctxk) { } void Dependencies::assert_call_site_target_value(ciCallSite* call_site, ciMethodHandle* method_handle) { - ciKlass* ctxk = call_site->get_context(); - check_ctxk(ctxk); - assert_common_3(call_site_target_value, ctxk, call_site, method_handle); + assert_common_2(call_site_target_value, call_site, method_handle); } // Helper function. If we are adding a new dep. under ctxk2, @@ -175,7 +173,6 @@ void Dependencies::assert_common_2(DepType dept, } } } else { - assert(dep_implicit_context_arg(dept) == 0, "sanity"); if (note_dep_seen(dept, x0) && note_dep_seen(dept, x1)) { // look in this bucket for redundant assertions const int stride = 2; @@ -389,7 +386,7 @@ int Dependencies::_dep_args[TYPE_LIMIT] = { 3, // unique_concrete_subtypes_2 ctxk, k1, k2 3, // unique_concrete_methods_2 ctxk, m1, m2 1, // no_finalizable_subclasses ctxk - 3 // call_site_target_value ctxk, call_site, method_handle + 2 // call_site_target_value call_site, method_handle }; const char* Dependencies::dep_name(Dependencies::DepType dept) { @@ -1515,16 +1512,11 @@ Klass* Dependencies::check_has_no_finalizable_subclasses(Klass* ctxk, KlassDepCh return find_finalizable_subclass(search_at); } -Klass* Dependencies::check_call_site_target_value(Klass* recorded_ctxk, oop call_site, oop method_handle, CallSiteDepChange* changes) { - assert(call_site->is_a(SystemDictionary::CallSite_klass()), "sanity"); +Klass* Dependencies::check_call_site_target_value(oop call_site, oop method_handle, CallSiteDepChange* changes) { + assert(!oopDesc::is_null(call_site), "sanity"); assert(!oopDesc::is_null(method_handle), "sanity"); + assert(call_site->is_a(SystemDictionary::CallSite_klass()), "sanity"); - Klass* call_site_ctxk = MethodHandles::get_call_site_context(call_site); - assert(!Klass::is_null(call_site_ctxk), "call site context should be initialized already"); - if (recorded_ctxk != call_site_ctxk) { - // Stale context - return recorded_ctxk; - } if (changes == NULL) { // Validate all CallSites if (java_lang_invoke_CallSite::target(call_site) != method_handle) @@ -1599,7 +1591,7 @@ Klass* Dependencies::DepStream::check_call_site_dependency(CallSiteDepChange* ch Klass* witness = NULL; switch (type()) { case call_site_target_value: - witness = check_call_site_target_value(context_type(), argument_oop(1), argument_oop(2), changes); + witness = check_call_site_target_value(argument_oop(0), argument_oop(1), changes); break; default: witness = NULL; diff --git a/hotspot/src/share/vm/code/dependencies.hpp b/hotspot/src/share/vm/code/dependencies.hpp index cacc5cac095..3129a2cb5de 100644 --- a/hotspot/src/share/vm/code/dependencies.hpp +++ b/hotspot/src/share/vm/code/dependencies.hpp @@ -173,7 +173,7 @@ class Dependencies: public ResourceObj { non_klass_types = (1 << call_site_target_value), klass_types = all_types & ~non_klass_types, - non_ctxk_types = (1 << evol_method), + non_ctxk_types = (1 << evol_method) | (1 << call_site_target_value), implicit_ctxk_types = 0, explicit_ctxk_types = all_types & ~(non_ctxk_types | implicit_ctxk_types), @@ -330,7 +330,7 @@ class Dependencies: public ResourceObj { static Klass* check_exclusive_concrete_methods(Klass* ctxk, Method* m1, Method* m2, KlassDepChange* changes = NULL); static Klass* check_has_no_finalizable_subclasses(Klass* ctxk, KlassDepChange* changes = NULL); - static Klass* check_call_site_target_value(Klass* recorded_ctxk, oop call_site, oop method_handle, CallSiteDepChange* changes = NULL); + static Klass* check_call_site_target_value(oop call_site, oop method_handle, CallSiteDepChange* changes = NULL); // A returned Klass* is NULL if the dependency assertion is still // valid. A non-NULL Klass* is a 'witness' to the assertion // failure, a point in the class hierarchy where the assertion has @@ -496,7 +496,7 @@ class Dependencies: public ResourceObj { bool next(); DepType type() { return _type; } - bool is_oop_argument(int i) { return type() == call_site_target_value && i > 0; } + bool is_oop_argument(int i) { return type() == call_site_target_value; } uintptr_t get_identifier(int i); int argument_count() { return dep_args(type()); } diff --git a/hotspot/src/share/vm/code/nmethod.cpp b/hotspot/src/share/vm/code/nmethod.cpp index 5063674ea29..c3d1c076b8a 100644 --- a/hotspot/src/share/vm/code/nmethod.cpp +++ b/hotspot/src/share/vm/code/nmethod.cpp @@ -565,13 +565,18 @@ nmethod* nmethod::new_nmethod(methodHandle method, // the number of methods compiled. For applications with a lot // classes the slow way is too slow. for (Dependencies::DepStream deps(nm); deps.next(); ) { - Klass* klass = deps.context_type(); - if (klass == NULL) { - continue; // ignore things like evol_method + if (deps.type() == Dependencies::call_site_target_value) { + // CallSite dependencies are managed on per-CallSite instance basis. + oop call_site = deps.argument_oop(0); + MethodHandles::add_dependent_nmethod(call_site, nm); + } else { + Klass* klass = deps.context_type(); + if (klass == NULL) { + continue; // ignore things like evol_method + } + // record this nmethod as dependent on this klass + InstanceKlass::cast(klass)->add_dependent_nmethod(nm); } - - // record this nmethod as dependent on this klass - InstanceKlass::cast(klass)->add_dependent_nmethod(nm); } NOT_PRODUCT(nmethod_stats.note_nmethod(nm)); if (PrintAssembly || CompilerOracle::has_option_string(method, "PrintAssembly")) { @@ -1464,13 +1469,20 @@ void nmethod::flush_dependencies(BoolObjectClosure* is_alive) { if (!has_flushed_dependencies()) { set_has_flushed_dependencies(); for (Dependencies::DepStream deps(this); deps.next(); ) { - Klass* klass = deps.context_type(); - if (klass == NULL) continue; // ignore things like evol_method - - // During GC the is_alive closure is non-NULL, and is used to - // determine liveness of dependees that need to be updated. - if (is_alive == NULL || klass->is_loader_alive(is_alive)) { - InstanceKlass::cast(klass)->remove_dependent_nmethod(this); + if (deps.type() == Dependencies::call_site_target_value) { + // CallSite dependencies are managed on per-CallSite instance basis. + oop call_site = deps.argument_oop(0); + MethodHandles::remove_dependent_nmethod(call_site, this); + } else { + Klass* klass = deps.context_type(); + if (klass == NULL) { + continue; // ignore things like evol_method + } + // During GC the is_alive closure is non-NULL, and is used to + // determine liveness of dependees that need to be updated. + if (is_alive == NULL || klass->is_loader_alive(is_alive)) { + InstanceKlass::cast(klass)->remove_dependent_nmethod(this); + } } } } diff --git a/hotspot/src/share/vm/gc/cms/vmCMSOperations.cpp b/hotspot/src/share/vm/gc/cms/vmCMSOperations.cpp index 539aef1f569..54970b010a3 100644 --- a/hotspot/src/share/vm/gc/cms/vmCMSOperations.cpp +++ b/hotspot/src/share/vm/gc/cms/vmCMSOperations.cpp @@ -254,9 +254,9 @@ void VM_GenCollectFullConcurrent::doit_epilogue() { if (_gc_cause != GCCause::_gc_locker && gch->total_full_collections_completed() <= _full_gc_count_before) { // maybe we should change the condition to test _gc_cause == - // GCCause::_java_lang_system_gc, instead of - // _gc_cause != GCCause::_gc_locker - assert(_gc_cause == GCCause::_java_lang_system_gc, + // GCCause::_java_lang_system_gc or GCCause::_dcmd_gc_run, + // instead of _gc_cause != GCCause::_gc_locker + assert(GCCause::is_user_requested_gc(_gc_cause), "the only way to get here if this was a System.gc()-induced GC"); assert(ExplicitGCInvokesConcurrent, "Error"); // Now, wait for witnessing concurrent gc cycle to complete, diff --git a/hotspot/src/share/vm/gc/cms/yieldingWorkgroup.cpp b/hotspot/src/share/vm/gc/cms/yieldingWorkgroup.cpp index 29eb4dbf9c1..7bbe26ce0dc 100644 --- a/hotspot/src/share/vm/gc/cms/yieldingWorkgroup.cpp +++ b/hotspot/src/share/vm/gc/cms/yieldingWorkgroup.cpp @@ -43,7 +43,7 @@ GangWorker* YieldingFlexibleWorkGang::allocate_worker(uint which) { } // Run a task; returns when the task is done, or the workers yield, -// or the task is aborted, or the work gang is terminated via stop(). +// or the task is aborted. // A task that has been yielded can be continued via this interface // by using the same task repeatedly as the argument to the call. // It is expected that the YieldingFlexibleGangTask carries the appropriate @@ -297,16 +297,9 @@ void YieldingFlexibleGangWorker::loop() { WorkData data; int id; while (true) { - // Check if there is work to do or if we have been asked - // to terminate + // Check if there is work to do. gang()->internal_worker_poll(&data); - if (data.terminate()) { - // We have been asked to terminate. - assert(gang()->task() == NULL, "No task binding"); - // set_status(TERMINATED); - return; - } else if (data.task() != NULL && - data.sequence_number() != previous_sequence_number) { + if (data.task() != NULL && data.sequence_number() != previous_sequence_number) { // There is work to be done. // First check if we need to become active or if there // are already the requisite number of workers diff --git a/hotspot/src/share/vm/gc/cms/yieldingWorkgroup.hpp b/hotspot/src/share/vm/gc/cms/yieldingWorkgroup.hpp index 3400f0fcfaf..23ddb321ffd 100644 --- a/hotspot/src/share/vm/gc/cms/yieldingWorkgroup.hpp +++ b/hotspot/src/share/vm/gc/cms/yieldingWorkgroup.hpp @@ -176,7 +176,7 @@ public: GangWorker* allocate_worker(uint which); // Run a task; returns when the task is done, or the workers yield, - // or the task is aborted, or the work gang is terminated via stop(). + // or the task is aborted. // A task that has been yielded can be continued via this same interface // by using the same task repeatedly as the argument to the call. // It is expected that the YieldingFlexibleGangTask carries the appropriate diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index 2ce9501550b..f17c1ea024c 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -1183,7 +1183,7 @@ bool G1CollectedHeap::do_collection(bool explicit_gc, IsGCActiveMark x; // Timing - assert(gc_cause() != GCCause::_java_lang_system_gc || explicit_gc, "invariant"); + assert(!GCCause::is_user_requested_gc(gc_cause()) || explicit_gc, "invariant"); TraceCPUTime tcpu(G1Log::finer(), true, gclog_or_tty); { @@ -2199,6 +2199,7 @@ bool G1CollectedHeap::should_do_concurrent_full_gc(GCCause::Cause cause) { switch (cause) { case GCCause::_gc_locker: return GCLockerInvokesConcurrent; case GCCause::_java_lang_system_gc: return ExplicitGCInvokesConcurrent; + case GCCause::_dcmd_gc_run: return ExplicitGCInvokesConcurrent; case GCCause::_g1_humongous_allocation: return true; case GCCause::_update_allocation_context_stats_inc: return true; case GCCause::_wb_conc_mark: return true; diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp index 48e8b2a5080..821d9f8716d 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp @@ -324,7 +324,8 @@ private: // explicitly started if: // (a) cause == _gc_locker and +GCLockerInvokesConcurrent, or // (b) cause == _java_lang_system_gc and +ExplicitGCInvokesConcurrent. - // (c) cause == _g1_humongous_allocation + // (c) cause == _dcmd_gc_run and +ExplicitGCInvokesConcurrent. + // (d) cause == _g1_humongous_allocation bool should_do_concurrent_full_gc(GCCause::Cause cause); // Keeps track of how many "old marking cycles" (i.e., Full GCs or diff --git a/hotspot/src/share/vm/gc/g1/vm_operations_g1.cpp b/hotspot/src/share/vm/gc/g1/vm_operations_g1.cpp index 676d0751da5..90a74d367d5 100644 --- a/hotspot/src/share/vm/gc/g1/vm_operations_g1.cpp +++ b/hotspot/src/share/vm/gc/g1/vm_operations_g1.cpp @@ -168,7 +168,7 @@ void VM_G1IncCollectionPause::doit_epilogue() { // +ExplicitGCInvokesConcurrent, we have to wait here for the cycle // that just started (or maybe one that was already in progress) to // finish. - if (_gc_cause == GCCause::_java_lang_system_gc && + if (GCCause::is_user_requested_gc(_gc_cause) && _should_initiate_conc_mark) { assert(ExplicitGCInvokesConcurrent, "the only way to be here is if ExplicitGCInvokesConcurrent is set"); diff --git a/hotspot/src/share/vm/gc/parallel/psAdaptiveSizePolicy.cpp b/hotspot/src/share/vm/gc/parallel/psAdaptiveSizePolicy.cpp index 2992f8d22dc..51359c64d9c 100644 --- a/hotspot/src/share/vm/gc/parallel/psAdaptiveSizePolicy.cpp +++ b/hotspot/src/share/vm/gc/parallel/psAdaptiveSizePolicy.cpp @@ -130,7 +130,7 @@ void PSAdaptiveSizePolicy::major_collection_end(size_t amount_live, // Update the pause time. _major_timer.stop(); - if (gc_cause != GCCause::_java_lang_system_gc || + if (!GCCause::is_user_requested_gc(gc_cause) || UseAdaptiveSizePolicyWithSystemGC) { double major_pause_in_seconds = _major_timer.seconds(); double major_pause_in_ms = major_pause_in_seconds * MILLIUNITS; diff --git a/hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp b/hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp index cc8b33e064d..540ae77b9fd 100644 --- a/hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp +++ b/hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp @@ -272,7 +272,7 @@ bool PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) { // Don't check if the size_policy is ready here. Let // the size_policy check that internally. if (UseAdaptiveGenerationSizePolicyAtMajorCollection && - ((gc_cause != GCCause::_java_lang_system_gc) || + (!GCCause::is_user_requested_gc(gc_cause) || UseAdaptiveSizePolicyWithSystemGC)) { // Swap the survivor spaces if from_space is empty. The // resize_young_gen() called below is normally used after diff --git a/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp b/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp index 6b2553fb408..98c1b26bae0 100644 --- a/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp +++ b/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp @@ -2053,7 +2053,7 @@ bool PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) { marking_phase(vmthread_cm, maximum_heap_compaction, &_gc_tracer); bool max_on_system_gc = UseMaximumCompactionOnSystemGC - && gc_cause == GCCause::_java_lang_system_gc; + && GCCause::is_user_requested_gc(gc_cause); summary_phase(vmthread_cm, maximum_heap_compaction || max_on_system_gc); COMPILER2_PRESENT(assert(DerivedPointerTable::is_active(), "Sanity")); @@ -2089,7 +2089,7 @@ bool PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) { // Don't check if the size_policy is ready here. Let // the size_policy check that internally. if (UseAdaptiveGenerationSizePolicyAtMajorCollection && - ((gc_cause != GCCause::_java_lang_system_gc) || + (!GCCause::is_user_requested_gc(gc_cause) || UseAdaptiveSizePolicyWithSystemGC)) { // Swap the survivor spaces if from_space is empty. The // resize_young_gen() called below is normally used after diff --git a/hotspot/src/share/vm/gc/parallel/psScavenge.cpp b/hotspot/src/share/vm/gc/parallel/psScavenge.cpp index 8f7b693b252..9023bd8997f 100644 --- a/hotspot/src/share/vm/gc/parallel/psScavenge.cpp +++ b/hotspot/src/share/vm/gc/parallel/psScavenge.cpp @@ -290,7 +290,7 @@ bool PSScavenge::invoke_no_policy() { AdaptiveSizePolicyOutput(size_policy, heap->total_collections()); - if ((gc_cause != GCCause::_java_lang_system_gc) || + if (!GCCause::is_user_requested_gc(gc_cause) || UseAdaptiveSizePolicyWithSystemGC) { // Gather the feedback data for eden occupancy. young_gen->eden_space()->accumulate_statistics(); diff --git a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp index 33a40c3744d..4374359b664 100644 --- a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp +++ b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp @@ -960,7 +960,7 @@ void DefNewGeneration::gc_epilogue(bool full) { GCCause::to_string(gch->gc_cause())); } assert(gch->gc_cause() == GCCause::_scavenge_alot || - (gch->gc_cause() == GCCause::_java_lang_system_gc && UseConcMarkSweepGC && ExplicitGCInvokesConcurrent) || + (GCCause::is_user_requested_gc(gch->gc_cause()) && UseConcMarkSweepGC && ExplicitGCInvokesConcurrent) || !gch->incremental_collection_failed(), "Twice in a row"); seen_incremental_collection_failed = false; diff --git a/hotspot/src/share/vm/gc/shared/adaptiveSizePolicy.cpp b/hotspot/src/share/vm/gc/shared/adaptiveSizePolicy.cpp index eba54f95aff..d2d90956073 100644 --- a/hotspot/src/share/vm/gc/shared/adaptiveSizePolicy.cpp +++ b/hotspot/src/share/vm/gc/shared/adaptiveSizePolicy.cpp @@ -244,7 +244,7 @@ void AdaptiveSizePolicy::minor_collection_end(GCCause::Cause gc_cause) { // Update the pause time. _minor_timer.stop(); - if (gc_cause != GCCause::_java_lang_system_gc || + if (!GCCause::is_user_requested_gc(gc_cause) || UseAdaptiveSizePolicyWithSystemGC) { double minor_pause_in_seconds = _minor_timer.seconds(); double minor_pause_in_ms = minor_pause_in_seconds * MILLIUNITS; diff --git a/hotspot/src/share/vm/gc/shared/gcCause.cpp b/hotspot/src/share/vm/gc/shared/gcCause.cpp index e7fd667dc0c..526e4fc90cb 100644 --- a/hotspot/src/share/vm/gc/shared/gcCause.cpp +++ b/hotspot/src/share/vm/gc/shared/gcCause.cpp @@ -103,6 +103,9 @@ const char* GCCause::to_string(GCCause::Cause cause) { case _last_ditch_collection: return "Last ditch collection"; + case _dcmd_gc_run: + return "Diagnostic Command"; + case _last_gc_cause: return "ILLEGAL VALUE - last gc cause - ILLEGAL VALUE"; diff --git a/hotspot/src/share/vm/gc/shared/gcCause.hpp b/hotspot/src/share/vm/gc/shared/gcCause.hpp index 88dc37fe2a2..0d711d8c24a 100644 --- a/hotspot/src/share/vm/gc/shared/gcCause.hpp +++ b/hotspot/src/share/vm/gc/shared/gcCause.hpp @@ -74,12 +74,15 @@ class GCCause : public AllStatic { _g1_humongous_allocation, _last_ditch_collection, + + _dcmd_gc_run, + _last_gc_cause }; inline static bool is_user_requested_gc(GCCause::Cause cause) { return (cause == GCCause::_java_lang_system_gc || - cause == GCCause::_jvmti_force_gc); + cause == GCCause::_dcmd_gc_run); } inline static bool is_serviceability_requested_gc(GCCause::Cause diff --git a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp index 5f490f61a7a..821df40b821 100644 --- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp @@ -304,9 +304,16 @@ bool GenCollectedHeap::must_clear_all_soft_refs() { } bool GenCollectedHeap::should_do_concurrent_full_gc(GCCause::Cause cause) { - return UseConcMarkSweepGC && - ((cause == GCCause::_gc_locker && GCLockerInvokesConcurrent) || - (cause == GCCause::_java_lang_system_gc && ExplicitGCInvokesConcurrent)); + if (!UseConcMarkSweepGC) { + return false; + } + + switch (cause) { + case GCCause::_gc_locker: return GCLockerInvokesConcurrent; + case GCCause::_java_lang_system_gc: + case GCCause::_dcmd_gc_run: return ExplicitGCInvokesConcurrent; + default: return false; + } } void GenCollectedHeap::collect_generation(Generation* gen, bool full, size_t size, diff --git a/hotspot/src/share/vm/gc/shared/workgroup.cpp b/hotspot/src/share/vm/gc/shared/workgroup.cpp index 6d615dd7bcb..e2aaa9ae440 100644 --- a/hotspot/src/share/vm/gc/shared/workgroup.cpp +++ b/hotspot/src/share/vm/gc/shared/workgroup.cpp @@ -47,7 +47,6 @@ AbstractWorkGang::AbstractWorkGang(const char* name, /* allow_vm_block */ are_GC_task_threads, Monitor::_safepoint_check_sometimes); assert(monitor() != NULL, "Failed to allocate monitor"); - _terminate = false; _task = NULL; _sequence_number = 0; _started_workers = 0; @@ -106,18 +105,6 @@ bool WorkGang::initialize_workers() { return true; } -AbstractWorkGang::~AbstractWorkGang() { - if (TraceWorkGang) { - tty->print_cr("Destructing work gang %s", name()); - } - stop(); // stop all the workers - for (uint worker = 0; worker < total_workers(); worker += 1) { - delete gang_worker(worker); - } - delete gang_workers(); - delete monitor(); -} - GangWorker* AbstractWorkGang::gang_worker(uint i) const { // Array index bounds checking. GangWorker* result = NULL; @@ -175,28 +162,9 @@ void FlexibleWorkGang::run_task(AbstractGangTask* task) { WorkGang::run_task(task, (uint) active_workers()); } -void AbstractWorkGang::stop() { - // Tell all workers to terminate, then wait for them to become inactive. - MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag); - if (TraceWorkGang) { - tty->print_cr("Stopping work gang %s task %s", name(), task()->name()); - } - _task = NULL; - _terminate = true; - monitor()->notify_all(); - while (finished_workers() < active_workers()) { - if (TraceWorkGang) { - tty->print_cr("Waiting in work gang %s: %u/%u finished", - name(), finished_workers(), active_workers()); - } - monitor()->wait(/* no_safepoint_check */ true); - } -} - void AbstractWorkGang::internal_worker_poll(WorkData* data) const { assert(monitor()->owned_by_self(), "worker_poll is an internal method"); assert(data != NULL, "worker data is null"); - data->set_terminate(terminate()); data->set_task(task()); data->set_sequence_number(sequence_number()); } @@ -259,7 +227,7 @@ void GangWorker::initialize() { void GangWorker::loop() { int previous_sequence_number = 0; Monitor* gang_monitor = gang()->monitor(); - for ( ; /* !terminate() */; ) { + for ( ; ; ) { WorkData data; int part; // Initialized below. { @@ -272,8 +240,6 @@ void GangWorker::loop() { if (TraceWorkGang) { tty->print("Polled outside for work in gang %s worker %u", gang()->name(), id()); - tty->print(" terminate: %s", - data.terminate() ? "true" : "false"); tty->print(" sequence: %d (prev: %d)", data.sequence_number(), previous_sequence_number); if (data.task() != NULL) { @@ -283,13 +249,7 @@ void GangWorker::loop() { } tty->cr(); } - for ( ; /* break or return */; ) { - // Terminate if requested. - if (data.terminate()) { - gang()->internal_note_finish(); - gang_monitor->notify_all(); - return; - } + for ( ; /* break */; ) { // Check for new work. if ((data.task() != NULL) && (data.sequence_number() != previous_sequence_number)) { @@ -306,8 +266,6 @@ void GangWorker::loop() { if (TraceWorkGang) { tty->print("Polled inside for work in gang %s worker %u", gang()->name(), id()); - tty->print(" terminate: %s", - data.terminate() ? "true" : "false"); tty->print(" sequence: %d (prev: %d)", data.sequence_number(), previous_sequence_number); if (data.task() != NULL) { diff --git a/hotspot/src/share/vm/gc/shared/workgroup.hpp b/hotspot/src/share/vm/gc/shared/workgroup.hpp index 1c0aad8cf0e..44464023a05 100644 --- a/hotspot/src/share/vm/gc/shared/workgroup.hpp +++ b/hotspot/src/share/vm/gc/shared/workgroup.hpp @@ -103,16 +103,15 @@ class AbstractGangTaskWOopQueues : public AbstractGangTask { // An abstract class representing a gang of workers. // You subclass this to supply an implementation of run_task(). class AbstractWorkGang: public CHeapObj { - // Here's the public interface to this class. +protected: + // Work gangs are never deleted, so no need to cleanup. + ~AbstractWorkGang() { ShouldNotReachHere(); } public: - // Constructor and destructor. + // Constructor. AbstractWorkGang(const char* name, bool are_GC_task_threads, bool are_ConcurrentGC_threads); - ~AbstractWorkGang(); // Run a task, returns when the task is done (or terminated). virtual void run_task(AbstractGangTask* task) = 0; - // Stop and terminate all workers. - virtual void stop(); // Return true if more workers should be applied to the task. virtual bool needs_more_workers() const { return true; } public: @@ -129,8 +128,6 @@ protected: Monitor* _monitor; // The count of the number of workers in the gang. uint _total_workers; - // Whether the workers should terminate. - bool _terminate; // The array of worker threads for this gang. // This is only needed for cleaning up. GangWorker** _gang_workers; @@ -153,9 +150,6 @@ public: virtual uint active_workers() const { return _total_workers; } - bool terminate() const { - return _terminate; - } GangWorker** gang_workers() const { return _gang_workers; } @@ -205,21 +199,16 @@ protected: class WorkData: public StackObj { // This would be a struct, but I want accessor methods. private: - bool _terminate; AbstractGangTask* _task; int _sequence_number; public: // Constructor and destructor WorkData() { - _terminate = false; _task = NULL; _sequence_number = 0; } ~WorkData() { } - // Accessors and modifiers - bool terminate() const { return _terminate; } - void set_terminate(bool value) { _terminate = value; } AbstractGangTask* task() const { return _task; } void set_task(AbstractGangTask* value) { _task = value; } int sequence_number() const { return _sequence_number; } diff --git a/hotspot/src/share/vm/interpreter/bytecode.cpp b/hotspot/src/share/vm/interpreter/bytecode.cpp index 70c3584e55c..80b95d627b5 100644 --- a/hotspot/src/share/vm/interpreter/bytecode.cpp +++ b/hotspot/src/share/vm/interpreter/bytecode.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -147,13 +147,10 @@ BasicType Bytecode_member_ref::result_type() const { methodHandle Bytecode_invoke::static_target(TRAPS) { - methodHandle m; - KlassHandle resolved_klass; constantPoolHandle constants(THREAD, this->constants()); Bytecodes::Code bc = invoke_code(); - LinkResolver::resolve_method_statically(m, resolved_klass, bc, constants, index(), CHECK_(methodHandle())); - return m; + return LinkResolver::resolve_method_statically(bc, constants, index(), THREAD); } Handle Bytecode_invoke::appendix(TRAPS) { diff --git a/hotspot/src/share/vm/interpreter/linkResolver.cpp b/hotspot/src/share/vm/interpreter/linkResolver.cpp index 5141f19dbc2..d3a97225c20 100644 --- a/hotspot/src/share/vm/interpreter/linkResolver.cpp +++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp @@ -52,13 +52,17 @@ // Implementation of CallInfo -void CallInfo::set_static(KlassHandle resolved_klass, methodHandle resolved_method, TRAPS) { +void CallInfo::set_static(KlassHandle resolved_klass, const methodHandle& resolved_method, TRAPS) { int vtable_index = Method::nonvirtual_vtable_index; set_common(resolved_klass, resolved_klass, resolved_method, resolved_method, CallInfo::direct_call, vtable_index, CHECK); } -void CallInfo::set_interface(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int itable_index, TRAPS) { +void CallInfo::set_interface(KlassHandle resolved_klass, + KlassHandle selected_klass, + const methodHandle& resolved_method, + const methodHandle& selected_method, + int itable_index, TRAPS) { // This is only called for interface methods. If the resolved_method // comes from java/lang/Object, it can be the subject of a virtual call, so // we should pick the vtable index from the resolved method. @@ -68,7 +72,11 @@ void CallInfo::set_interface(KlassHandle resolved_klass, KlassHandle selected_kl set_common(resolved_klass, selected_klass, resolved_method, selected_method, CallInfo::itable_call, itable_index, CHECK); } -void CallInfo::set_virtual(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index, TRAPS) { +void CallInfo::set_virtual(KlassHandle resolved_klass, + KlassHandle selected_klass, + const methodHandle& resolved_method, + const methodHandle& selected_method, + int vtable_index, TRAPS) { assert(vtable_index >= 0 || vtable_index == Method::nonvirtual_vtable_index, "valid index"); assert(vtable_index < 0 || !resolved_method->has_vtable_index() || vtable_index == resolved_method->vtable_index(), ""); CallKind kind = (vtable_index >= 0 && !resolved_method->can_be_statically_bound() ? CallInfo::vtable_call : CallInfo::direct_call); @@ -76,7 +84,9 @@ void CallInfo::set_virtual(KlassHandle resolved_klass, KlassHandle selected_klas assert(!resolved_method->is_compiled_lambda_form(), "these must be handled via an invokehandle call"); } -void CallInfo::set_handle(methodHandle resolved_method, Handle resolved_appendix, Handle resolved_method_type, TRAPS) { +void CallInfo::set_handle(const methodHandle& resolved_method, + Handle resolved_appendix, + Handle resolved_method_type, TRAPS) { if (resolved_method.is_null()) { THROW_MSG(vmSymbols::java_lang_InternalError(), "resolved method is null"); } @@ -93,8 +103,8 @@ void CallInfo::set_handle(methodHandle resolved_method, Handle resolved_appendix void CallInfo::set_common(KlassHandle resolved_klass, KlassHandle selected_klass, - methodHandle resolved_method, - methodHandle selected_method, + const methodHandle& resolved_method, + const methodHandle& selected_method, CallKind kind, int index, TRAPS) { @@ -210,8 +220,52 @@ void CallInfo::verify() { } #endif //ASSERT +#ifndef PRODUCT +void CallInfo::print() { + ResourceMark rm; + const char* kindstr = "unknown"; + switch (_call_kind) { + case direct_call: kindstr = "direct"; break; + case vtable_call: kindstr = "vtable"; break; + case itable_call: kindstr = "itable"; break; + } + tty->print_cr("Call %s@%d %s", kindstr, _call_index, + _resolved_method.is_null() ? "(none)" : _resolved_method->name_and_sig_as_C_string()); +} +#endif +//------------------------------------------------------------------------------------------------------------------------ +// Implementation of LinkInfo +LinkInfo::LinkInfo(constantPoolHandle pool, int index, TRAPS) { + // resolve klass + Klass* result = pool->klass_ref_at(index, CHECK); + _resolved_klass = KlassHandle(THREAD, result); + + // Get name, signature, and static klass + _name = pool->name_ref_at(index); + _signature = pool->signature_ref_at(index); + _current_klass = KlassHandle(THREAD, pool->pool_holder()); + + // Coming from the constant pool always checks access + _check_access = true; +} + +char* LinkInfo::method_string() const { + return Method::name_and_sig_as_C_string(_resolved_klass(), _name, _signature); +} + +#ifndef PRODUCT +void LinkInfo::print() { + ResourceMark rm; + tty->print_cr("Link resolved_klass=%s name=%s signature=%s current_klass=%s check_access=%s", + _resolved_klass->name()->as_C_string(), + _name->as_C_string(), + _signature->as_C_string(), + _current_klass.is_null() ? "(none)" : _current_klass->name()->as_C_string(), + _check_access ? "true" : "false"); +} +#endif // PRODUCT //------------------------------------------------------------------------------------------------------------------------ // Klass resolution @@ -231,11 +285,6 @@ void LinkResolver::check_klass_accessability(KlassHandle ref_klass, KlassHandle } } -void LinkResolver::resolve_klass(KlassHandle& result, constantPoolHandle pool, int index, TRAPS) { - Klass* result_oop = pool->klass_ref_at(index, CHECK); - result = KlassHandle(THREAD, result_oop); -} - //------------------------------------------------------------------------------------------------------------------------ // Method resolution // @@ -243,76 +292,84 @@ void LinkResolver::resolve_klass(KlassHandle& result, constantPoolHandle pool, i // Look up method in klasses, including static methods // Then look up local default methods -void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, bool checkpolymorphism, bool in_imethod_resolve, TRAPS) { +methodHandle LinkResolver::lookup_method_in_klasses(const LinkInfo& link_info, + bool checkpolymorphism, + bool in_imethod_resolve, TRAPS) { + KlassHandle klass = link_info.resolved_klass(); + Symbol* name = link_info.name(); + Symbol* signature = link_info.signature(); + // Ignore overpasses so statics can be found during resolution - Method* result_oop = klass->uncached_lookup_method(name, signature, Klass::skip_overpass); + Method* result = klass->uncached_lookup_method(name, signature, Klass::skip_overpass); if (klass->oop_is_array()) { // Only consider klass and super klass for arrays - result = methodHandle(THREAD, result_oop); - return; + return methodHandle(THREAD, result); } // JDK 8, JVMS 5.4.3.4: Interface method resolution should // ignore static and non-public methods of java.lang.Object, // like clone, finalize, registerNatives. if (in_imethod_resolve && - result_oop != NULL && + result != NULL && klass->is_interface() && - (result_oop->is_static() || !result_oop->is_public()) && - result_oop->method_holder() == SystemDictionary::Object_klass()) { - result_oop = NULL; + (result->is_static() || !result->is_public()) && + result->method_holder() == SystemDictionary::Object_klass()) { + result = NULL; } // Before considering default methods, check for an overpass in the // current class if a method has not been found. - if (result_oop == NULL) { - result_oop = InstanceKlass::cast(klass())->find_method(name, signature); + if (result == NULL) { + result = InstanceKlass::cast(klass())->find_method(name, signature); } - if (result_oop == NULL) { + if (result == NULL) { Array* default_methods = InstanceKlass::cast(klass())->default_methods(); if (default_methods != NULL) { - result_oop = InstanceKlass::find_method(default_methods, name, signature); + result = InstanceKlass::find_method(default_methods, name, signature); } } - if (checkpolymorphism && result_oop != NULL) { - vmIntrinsics::ID iid = result_oop->intrinsic_id(); + if (checkpolymorphism && result != NULL) { + vmIntrinsics::ID iid = result->intrinsic_id(); if (MethodHandles::is_signature_polymorphic(iid)) { // Do not link directly to these. The VM must produce a synthetic one using lookup_polymorphic_method. - return; + return NULL; } } - result = methodHandle(THREAD, result_oop); + return methodHandle(THREAD, result); } // returns first instance method // Looks up method in classes, then looks up local default methods -void LinkResolver::lookup_instance_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) { - Method* result_oop = klass->uncached_lookup_method(name, signature, Klass::find_overpass); - result = methodHandle(THREAD, result_oop); - while (!result.is_null() && result->is_static() && result->method_holder()->super() != NULL) { - KlassHandle super_klass = KlassHandle(THREAD, result->method_holder()->super()); - result = methodHandle(THREAD, super_klass->uncached_lookup_method(name, signature, Klass::find_overpass)); +methodHandle LinkResolver::lookup_instance_method_in_klasses(KlassHandle klass, + Symbol* name, + Symbol* signature, TRAPS) { + Method* result = klass->uncached_lookup_method(name, signature, Klass::find_overpass); + + while (result != NULL && result->is_static() && result->method_holder()->super() != NULL) { + Klass* super_klass = result->method_holder()->super(); + result = super_klass->uncached_lookup_method(name, signature, Klass::find_overpass); } if (klass->oop_is_array()) { // Only consider klass and super klass for arrays - return; + return methodHandle(THREAD, result); } - if (result.is_null()) { + if (result == NULL) { Array* default_methods = InstanceKlass::cast(klass())->default_methods(); if (default_methods != NULL) { - result = methodHandle(InstanceKlass::find_method(default_methods, name, signature)); - assert(result.is_null() || !result->is_static(), "static defaults not allowed"); + result = InstanceKlass::find_method(default_methods, name, signature); + assert(result == NULL || !result->is_static(), "static defaults not allowed"); } } + return methodHandle(THREAD, result); } int LinkResolver::vtable_index_of_interface_method(KlassHandle klass, - methodHandle resolved_method) { + const methodHandle& resolved_method) { int vtable_index = Method::invalid_vtable_index; Symbol* name = resolved_method->name(); @@ -336,21 +393,26 @@ int LinkResolver::vtable_index_of_interface_method(KlassHandle klass, return vtable_index; } -void LinkResolver::lookup_method_in_interfaces(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) { - InstanceKlass *ik = InstanceKlass::cast(klass()); +methodHandle LinkResolver::lookup_method_in_interfaces(const LinkInfo& cp_info, TRAPS) { + InstanceKlass *ik = InstanceKlass::cast(cp_info.resolved_klass()()); // Specify 'true' in order to skip default methods when searching the // interfaces. Function lookup_method_in_klasses() already looked for // the method in the default methods table. - result = methodHandle(THREAD, ik->lookup_method_in_all_interfaces(name, signature, Klass::skip_defaults)); + return methodHandle(THREAD, + ik->lookup_method_in_all_interfaces(cp_info.name(), cp_info.signature(), + Klass::skip_defaults)); } -void LinkResolver::lookup_polymorphic_method(methodHandle& result, - KlassHandle klass, Symbol* name, Symbol* full_signature, - KlassHandle current_klass, +methodHandle LinkResolver::lookup_polymorphic_method( + const LinkInfo& link_info, Handle *appendix_result_or_null, Handle *method_type_result, TRAPS) { + KlassHandle klass = link_info.resolved_klass(); + Symbol* name = link_info.name(); + Symbol* full_signature = link_info.signature(); + vmIntrinsics::ID iid = MethodHandles::signature_polymorphic_name_id(name); if (TraceMethodHandles) { ResourceMark rm(THREAD); @@ -365,7 +427,7 @@ void LinkResolver::lookup_polymorphic_method(methodHandle& result, // Do not erase last argument type (MemberName) if it is a static linkTo method. bool keep_last_arg = MethodHandles::is_signature_polymorphic_static(iid); TempNewSymbol basic_signature = - MethodHandles::lookup_basic_type_signature(full_signature, keep_last_arg, CHECK); + MethodHandles::lookup_basic_type_signature(full_signature, keep_last_arg, CHECK_NULL); if (TraceMethodHandles) { ResourceMark rm(THREAD); tty->print_cr("lookup_polymorphic_method %s %s => basic %s", @@ -373,9 +435,9 @@ void LinkResolver::lookup_polymorphic_method(methodHandle& result, full_signature->as_C_string(), basic_signature->as_C_string()); } - result = SystemDictionary::find_method_handle_intrinsic(iid, + methodHandle result = SystemDictionary::find_method_handle_intrinsic(iid, basic_signature, - CHECK); + CHECK_NULL); if (result.not_null()) { assert(result->is_method_handle_intrinsic(), "MH.invokeBasic or MH.linkTo* intrinsic"); assert(result->intrinsic_id() != vmIntrinsics::_invokeGeneric, "wrong place to find this"); @@ -384,8 +446,8 @@ void LinkResolver::lookup_polymorphic_method(methodHandle& result, tty->print("lookup_polymorphic_method => intrinsic "); result->print_on(tty); } - return; } + return result; } else if (iid == vmIntrinsics::_invokeGeneric && !THREAD->is_Compiler_thread() && appendix_result_or_null != NULL) { @@ -399,18 +461,19 @@ void LinkResolver::lookup_polymorphic_method(methodHandle& result, Handle(), Handle(), true, - CHECK); + CHECK_NULL); } } Handle appendix; Handle method_type; - result = SystemDictionary::find_method_handle_invoker(name, + methodHandle result = SystemDictionary::find_method_handle_invoker( + name, full_signature, - current_klass, + link_info.current_klass(), &appendix, &method_type, - CHECK); + CHECK_NULL); if (TraceMethodHandles) { tty->print("lookup_polymorphic_method => (via Java) "); result->print_on(tty); @@ -423,7 +486,7 @@ void LinkResolver::lookup_polymorphic_method(methodHandle& result, ResourceMark rm(THREAD); TempNewSymbol basic_signature = - MethodHandles::lookup_basic_type_signature(full_signature, CHECK); + MethodHandles::lookup_basic_type_signature(full_signature, CHECK_NULL); int actual_size_of_params = result->size_of_parameters(); int expected_size_of_params = ArgumentSizeComputer(basic_signature).size(); // +1 for MethodHandle.this, +1 for trailing MethodType @@ -441,16 +504,17 @@ void LinkResolver::lookup_polymorphic_method(methodHandle& result, assert(appendix_result_or_null != NULL, ""); (*appendix_result_or_null) = appendix; (*method_type_result) = method_type; - return; } + return result; } } + return NULL; } void LinkResolver::check_method_accessability(KlassHandle ref_klass, KlassHandle resolved_klass, KlassHandle sel_klass, - methodHandle sel_method, + const methodHandle& sel_method, TRAPS) { AccessFlags flags = sel_method->access_flags(); @@ -493,8 +557,8 @@ void LinkResolver::check_method_accessability(KlassHandle ref_klass, } } -void LinkResolver::resolve_method_statically(methodHandle& resolved_method, KlassHandle& resolved_klass, - Bytecodes::Code code, constantPoolHandle pool, int index, TRAPS) { +methodHandle LinkResolver::resolve_method_statically(Bytecodes::Code code, + constantPoolHandle pool, int index, TRAPS) { // This method is used only // (1) in C2 from InlineTree::ok_to_inline (via ciMethod::check_call), // and @@ -502,49 +566,108 @@ void LinkResolver::resolve_method_statically(methodHandle& resolved_method, Klas // It appears to fail when applied to an invokeinterface call site. // FIXME: Remove this method and ciMethod::check_call; refactor to use the other LinkResolver entry points. // resolve klass + KlassHandle resolved_klass; if (code == Bytecodes::_invokedynamic) { resolved_klass = SystemDictionary::MethodHandle_klass(); Symbol* method_name = vmSymbols::invoke_name(); Symbol* method_signature = pool->signature_ref_at(index); KlassHandle current_klass(THREAD, pool->pool_holder()); - resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, false, CHECK); - return; + LinkInfo link_info(resolved_klass, method_name, method_signature, current_klass); + return resolve_method(link_info, /*require_methodref*/false, THREAD); } - resolve_klass(resolved_klass, pool, index, CHECK); - - Symbol* method_name = pool->name_ref_at(index); - Symbol* method_signature = pool->signature_ref_at(index); - KlassHandle current_klass(THREAD, pool->pool_holder()); + LinkInfo link_info(pool, index, CHECK_NULL); + resolved_klass = link_info.resolved_klass(); if (pool->has_preresolution() || (resolved_klass() == SystemDictionary::MethodHandle_klass() && - MethodHandles::is_signature_polymorphic_name(resolved_klass(), method_name))) { - Method* result_oop = ConstantPool::method_at_if_loaded(pool, index); - if (result_oop != NULL) { - resolved_method = methodHandle(THREAD, result_oop); - return; + MethodHandles::is_signature_polymorphic_name(resolved_klass(), link_info.name()))) { + Method* result = ConstantPool::method_at_if_loaded(pool, index); + if (result != NULL) { + return methodHandle(THREAD, result); } } if (code == Bytecodes::_invokeinterface) { - resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, true, CHECK); + return resolve_interface_method(link_info, true, THREAD); } else if (code == Bytecodes::_invokevirtual) { - resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, true, CHECK); + return resolve_method(link_info, /*require_methodref*/true, THREAD); } else if (!resolved_klass->is_interface()) { - resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, false, CHECK); + return resolve_method(link_info, /*require_methodref*/false, THREAD); } else { bool nostatics = (code == Bytecodes::_invokestatic) ? false : true; - resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, nostatics, CHECK); + return resolve_interface_method(link_info, nostatics, THREAD); } } -void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle resolved_klass, - Symbol* method_name, Symbol* method_signature, - KlassHandle current_klass, bool check_access, - bool require_methodref, TRAPS) { +// Check and print a loader constraint violation message for method or interface method +void LinkResolver::check_method_loader_constraints(const LinkInfo& link_info, + const methodHandle& resolved_method, + const char* method_type, TRAPS) { + Handle current_loader(THREAD, link_info.current_klass()->class_loader()); + Handle resolved_loader(THREAD, resolved_method->method_holder()->class_loader()); + + ResourceMark rm(THREAD); + Symbol* failed_type_symbol = + SystemDictionary::check_signature_loaders(link_info.signature(), current_loader, + resolved_loader, true, CHECK); + if (failed_type_symbol != NULL) { + const char* msg = "loader constraint violation: when resolving %s" + " \"%s\" the class loader (instance of %s) of the current class, %s," + " and the class loader (instance of %s) for the method's defining class, %s, have" + " different Class objects for the type %s used in the signature"; + char* sig = link_info.method_string(); + const char* loader1_name = SystemDictionary::loader_name(current_loader()); + char* current = link_info.current_klass()->name()->as_C_string(); + const char* loader2_name = SystemDictionary::loader_name(resolved_loader()); + char* target = resolved_method->method_holder()->name()->as_C_string(); + char* failed_type_name = failed_type_symbol->as_C_string(); + size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1_name) + + strlen(current) + strlen(loader2_name) + strlen(target) + + strlen(failed_type_name) + strlen(method_type) + 1; + char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen); + jio_snprintf(buf, buflen, msg, method_type, sig, loader1_name, current, loader2_name, + target, failed_type_name); + THROW_MSG(vmSymbols::java_lang_LinkageError(), buf); + } +} + +void LinkResolver::check_field_loader_constraints(Symbol* field, Symbol* sig, + KlassHandle current_klass, + KlassHandle sel_klass, TRAPS) { + Handle ref_loader(THREAD, current_klass->class_loader()); + Handle sel_loader(THREAD, sel_klass->class_loader()); + + ResourceMark rm(THREAD); // needed for check_signature_loaders + Symbol* failed_type_symbol = + SystemDictionary::check_signature_loaders(sig, + ref_loader, sel_loader, + false, + CHECK); + if (failed_type_symbol != NULL) { + const char* msg = "loader constraint violation: when resolving field" + " \"%s\" the class loader (instance of %s) of the referring class, " + "%s, and the class loader (instance of %s) for the field's resolved " + "type, %s, have different Class objects for that type"; + char* field_name = field->as_C_string(); + const char* loader1_name = SystemDictionary::loader_name(ref_loader()); + char* sel = sel_klass->name()->as_C_string(); + const char* loader2_name = SystemDictionary::loader_name(sel_loader()); + char* failed_type_name = failed_type_symbol->as_C_string(); + size_t buflen = strlen(msg) + strlen(field_name) + strlen(loader1_name) + + strlen(sel) + strlen(loader2_name) + strlen(failed_type_name) + 1; + char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen); + jio_snprintf(buf, buflen, msg, field_name, loader1_name, sel, loader2_name, + failed_type_name); + THROW_MSG(vmSymbols::java_lang_LinkageError(), buf); + } +} + +methodHandle LinkResolver::resolve_method(const LinkInfo& link_info, + bool require_methodref, TRAPS) { Handle nested_exception; + KlassHandle resolved_klass = link_info.resolved_klass(); // 1. check if methodref required, that resolved_klass is not interfacemethodref if (require_methodref && resolved_klass->is_interface()) { @@ -552,20 +675,19 @@ void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle res char buf[200]; jio_snprintf(buf, sizeof(buf), "Found interface %s, but class was expected", resolved_klass()->external_name()); - THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); + THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); } // 2. lookup method in resolved klass and its super klasses - lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, true, false, CHECK); + methodHandle resolved_method = lookup_method_in_klasses(link_info, true, false, CHECK_NULL); if (resolved_method.is_null() && !resolved_klass->oop_is_array()) { // not found in the class hierarchy // 3. lookup method in all the interfaces implemented by the resolved klass - lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK); + resolved_method = lookup_method_in_interfaces(link_info, CHECK_NULL); if (resolved_method.is_null()) { // JSR 292: see if this is an implicitly generated method MethodHandle.linkToVirtual(*...), etc - lookup_polymorphic_method(resolved_method, resolved_klass, method_name, method_signature, - current_klass, (Handle*)NULL, (Handle*)NULL, THREAD); + resolved_method = lookup_polymorphic_method(link_info, (Handle*)NULL, (Handle*)NULL, THREAD); if (HAS_PENDING_EXCEPTION) { nested_exception = Handle(THREAD, PENDING_EXCEPTION); CLEAR_PENDING_EXCEPTION; @@ -576,15 +698,16 @@ void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle res if (resolved_method.is_null()) { // 4. method lookup failed ResourceMark rm(THREAD); - THROW_MSG_CAUSE(vmSymbols::java_lang_NoSuchMethodError(), + THROW_MSG_CAUSE_(vmSymbols::java_lang_NoSuchMethodError(), Method::name_and_sig_as_C_string(resolved_klass(), - method_name, - method_signature), - nested_exception); + link_info.name(), + link_info.signature()), + nested_exception, NULL); } // 5. access checks, access checking may be turned off when calling from within the VM. - if (check_access) { + KlassHandle current_klass = link_info.current_klass(); + if (link_info.check_access()) { assert(current_klass.not_null() , "current_klass should not be null"); // check if method can be accessed by the referring class @@ -592,76 +715,50 @@ void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle res resolved_klass, KlassHandle(THREAD, resolved_method->method_holder()), resolved_method, - CHECK); + CHECK_NULL); // check loader constraints - Handle loader (THREAD, InstanceKlass::cast(current_klass())->class_loader()); - Handle class_loader (THREAD, resolved_method->method_holder()->class_loader()); - { - ResourceMark rm(THREAD); - Symbol* failed_type_symbol = - SystemDictionary::check_signature_loaders(method_signature, loader, - class_loader, true, CHECK); - if (failed_type_symbol != NULL) { - const char* msg = "loader constraint violation: when resolving method" - " \"%s\" the class loader (instance of %s) of the current class, %s," - " and the class loader (instance of %s) for the method's defining class, %s, have" - " different Class objects for the type %s used in the signature"; - char* sig = Method::name_and_sig_as_C_string(resolved_klass(),method_name,method_signature); - const char* loader1 = SystemDictionary::loader_name(loader()); - char* current = InstanceKlass::cast(current_klass())->name()->as_C_string(); - const char* loader2 = SystemDictionary::loader_name(class_loader()); - char* target = InstanceKlass::cast(resolved_method->method_holder()) - ->name()->as_C_string(); - char* failed_type_name = failed_type_symbol->as_C_string(); - size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) + - strlen(current) + strlen(loader2) + strlen(target) + - strlen(failed_type_name) + 1; - char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen); - jio_snprintf(buf, buflen, msg, sig, loader1, current, loader2, - target, failed_type_name); - THROW_MSG(vmSymbols::java_lang_LinkageError(), buf); - } - } + check_method_loader_constraints(link_info, resolved_method, "method", CHECK_NULL); } + + return resolved_method; } -void LinkResolver::resolve_interface_method(methodHandle& resolved_method, - KlassHandle resolved_klass, - Symbol* method_name, - Symbol* method_signature, - KlassHandle current_klass, - bool check_access, - bool nostatics, TRAPS) { +methodHandle LinkResolver::resolve_interface_method(const LinkInfo& link_info, + bool nostatics, TRAPS) { + + KlassHandle resolved_klass = link_info.resolved_klass(); // check if klass is interface if (!resolved_klass->is_interface()) { ResourceMark rm(THREAD); char buf[200]; jio_snprintf(buf, sizeof(buf), "Found class %s, but interface was expected", resolved_klass()->external_name()); - THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); + THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); } // lookup method in this interface or its super, java.lang.Object // JDK8: also look for static methods - lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, false, true, CHECK); + methodHandle resolved_method = lookup_method_in_klasses(link_info, false, true, CHECK_NULL); if (resolved_method.is_null() && !resolved_klass->oop_is_array()) { // lookup method in all the super-interfaces - lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK); + resolved_method = lookup_method_in_interfaces(link_info, CHECK_NULL); } if (resolved_method.is_null()) { // no method found ResourceMark rm(THREAD); - THROW_MSG(vmSymbols::java_lang_NoSuchMethodError(), - Method::name_and_sig_as_C_string(resolved_klass(), - method_name, - method_signature)); + THROW_MSG_NULL(vmSymbols::java_lang_NoSuchMethodError(), + Method::name_and_sig_as_C_string(resolved_klass(), + link_info.name(), + link_info.signature())); } - if (check_access) { + if (link_info.check_access()) { // JDK8 adds non-public interface methods, and accessability check requirement + KlassHandle current_klass = link_info.current_klass(); + assert(current_klass.not_null() , "current_klass should not be null"); // check if method can be accessed by the referring class @@ -669,38 +766,9 @@ void LinkResolver::resolve_interface_method(methodHandle& resolved_method, resolved_klass, KlassHandle(THREAD, resolved_method->method_holder()), resolved_method, - CHECK); + CHECK_NULL); - HandleMark hm(THREAD); - Handle loader (THREAD, InstanceKlass::cast(current_klass())->class_loader()); - Handle class_loader (THREAD, resolved_method->method_holder()->class_loader()); - { - ResourceMark rm(THREAD); - Symbol* failed_type_symbol = - SystemDictionary::check_signature_loaders(method_signature, loader, - class_loader, true, CHECK); - if (failed_type_symbol != NULL) { - const char* msg = "loader constraint violation: when resolving " - "interface method \"%s\" the class loader (instance of %s) of the " - "current class, %s, and the class loader (instance of %s) for " - "the method's defining class, %s, have different Class objects for the type %s " - "used in the signature"; - char* sig = Method::name_and_sig_as_C_string(resolved_klass(),method_name,method_signature); - const char* loader1 = SystemDictionary::loader_name(loader()); - char* current = InstanceKlass::cast(current_klass())->name()->as_C_string(); - const char* loader2 = SystemDictionary::loader_name(class_loader()); - char* target = InstanceKlass::cast(resolved_method->method_holder()) - ->name()->as_C_string(); - char* failed_type_name = failed_type_symbol->as_C_string(); - size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) + - strlen(current) + strlen(loader2) + strlen(target) + - strlen(failed_type_name) + 1; - char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen); - jio_snprintf(buf, buflen, msg, sig, loader1, current, loader2, - target, failed_type_name); - THROW_MSG(vmSymbols::java_lang_LinkageError(), buf); - } - } + check_method_loader_constraints(link_info, resolved_method, "interface method", CHECK_NULL); } if (nostatics && resolved_method->is_static()) { @@ -709,28 +777,16 @@ void LinkResolver::resolve_interface_method(methodHandle& resolved_method, jio_snprintf(buf, sizeof(buf), "Expected instance not static method %s", Method::name_and_sig_as_C_string(resolved_klass(), resolved_method->name(), resolved_method->signature())); - THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); + THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); } if (TraceItables && Verbose) { - ResourceMark rm(THREAD); - tty->print("invokeinterface resolved method: caller-class:%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: ", - (current_klass.is_null() ? "" : current_klass->internal_name()), - (resolved_klass.is_null() ? "" : resolved_klass->internal_name()), - Method::name_and_sig_as_C_string(resolved_klass(), - resolved_method->name(), - resolved_method->signature()), - resolved_method->method_holder()->internal_name() - ); - resolved_method->access_flags().print_on(tty); - if (resolved_method->is_default_method()) { - tty->print("default "); - } - if (resolved_method->is_overpass()) { - tty->print("overpass"); - } + trace_method_resolution("invokeinterface resolved method: caller-class", + link_info.current_klass(), resolved_klass, resolved_method); tty->cr(); } + + return resolved_method; } //------------------------------------------------------------------------------------------------------------------------ @@ -739,7 +795,7 @@ void LinkResolver::resolve_interface_method(methodHandle& resolved_method, void LinkResolver::check_field_accessability(KlassHandle ref_klass, KlassHandle resolved_klass, KlassHandle sel_klass, - fieldDescriptor& fd, + const fieldDescriptor& fd, TRAPS) { if (!Reflection::verify_field_access(ref_klass(), resolved_klass(), @@ -759,30 +815,27 @@ void LinkResolver::check_field_accessability(KlassHandle ref_klass, } } -void LinkResolver::resolve_field_access(fieldDescriptor& result, constantPoolHandle pool, int index, Bytecodes::Code byte, TRAPS) { - // Load these early in case the resolve of the containing klass fails - Symbol* field = pool->name_ref_at(index); - Symbol* sig = pool->signature_ref_at(index); - - // resolve specified klass - KlassHandle resolved_klass; - resolve_klass(resolved_klass, pool, index, CHECK); - - KlassHandle current_klass(THREAD, pool->pool_holder()); - resolve_field(result, resolved_klass, field, sig, current_klass, byte, true, true, CHECK); +void LinkResolver::resolve_field_access(fieldDescriptor& fd, constantPoolHandle pool, int index, Bytecodes::Code byte, TRAPS) { + LinkInfo link_info(pool, index, CHECK); + resolve_field(fd, link_info, byte, true, CHECK); } -void LinkResolver::resolve_field(fieldDescriptor& fd, KlassHandle resolved_klass, Symbol* field, Symbol* sig, - KlassHandle current_klass, Bytecodes::Code byte, bool check_access, bool initialize_class, +void LinkResolver::resolve_field(fieldDescriptor& fd, + const LinkInfo& link_info, + Bytecodes::Code byte, bool initialize_class, TRAPS) { assert(byte == Bytecodes::_getstatic || byte == Bytecodes::_putstatic || byte == Bytecodes::_getfield || byte == Bytecodes::_putfield || byte == Bytecodes::_nofast_getfield || byte == Bytecodes::_nofast_putfield || - (byte == Bytecodes::_nop && !check_access), "bad field access bytecode"); + (byte == Bytecodes::_nop && !link_info.check_access()), "bad field access bytecode"); bool is_static = (byte == Bytecodes::_getstatic || byte == Bytecodes::_putstatic); bool is_put = (byte == Bytecodes::_putfield || byte == Bytecodes::_putstatic || byte == Bytecodes::_nofast_putfield); // Check if there's a resolved klass containing the field + KlassHandle resolved_klass = link_info.resolved_klass(); + Symbol* field = link_info.name(); + Symbol* sig = link_info.signature(); + if (resolved_klass.is_null()) { ResourceMark rm(THREAD); THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), field->as_C_string()); @@ -796,11 +849,12 @@ void LinkResolver::resolve_field(fieldDescriptor& fd, KlassHandle resolved_klass THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), field->as_C_string()); } - if (!check_access) + if (!link_info.check_access()) // Access checking may be turned off when calling from within the VM. return; // check access + KlassHandle current_klass = link_info.current_klass(); check_field_accessability(current_klass, resolved_klass, sel_klass, fd, CHECK); // check for errors @@ -827,34 +881,7 @@ void LinkResolver::resolve_field(fieldDescriptor& fd, KlassHandle resolved_klass } if (sel_klass() != current_klass()) { - HandleMark hm(THREAD); - Handle ref_loader (THREAD, InstanceKlass::cast(current_klass())->class_loader()); - Handle sel_loader (THREAD, InstanceKlass::cast(sel_klass())->class_loader()); - { - ResourceMark rm(THREAD); - Symbol* failed_type_symbol = - SystemDictionary::check_signature_loaders(sig, - ref_loader, sel_loader, - false, - CHECK); - if (failed_type_symbol != NULL) { - const char* msg = "loader constraint violation: when resolving field" - " \"%s\" the class loader (instance of %s) of the referring class, " - "%s, and the class loader (instance of %s) for the field's resolved " - "type, %s, have different Class objects for that type"; - char* field_name = field->as_C_string(); - const char* loader1 = SystemDictionary::loader_name(ref_loader()); - char* sel = InstanceKlass::cast(sel_klass())->name()->as_C_string(); - const char* loader2 = SystemDictionary::loader_name(sel_loader()); - char* failed_type_name = failed_type_symbol->as_C_string(); - size_t buflen = strlen(msg) + strlen(field_name) + strlen(loader1) + - strlen(sel) + strlen(loader2) + strlen(failed_type_name) + 1; - char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen); - jio_snprintf(buf, buflen, msg, field_name, loader1, sel, loader2, - failed_type_name); - THROW_MSG(vmSymbols::java_lang_LinkageError(), buf); - } - } + check_field_loader_constraints(field, sig, current_klass, sel_klass, CHECK); } // return information. note that the klass is set to the actual klass containing the @@ -873,32 +900,38 @@ void LinkResolver::resolve_field(fieldDescriptor& fd, KlassHandle resolved_klass // recv_klass the receiver klass -void LinkResolver::resolve_static_call(CallInfo& result, KlassHandle& resolved_klass, Symbol* method_name, - Symbol* method_signature, KlassHandle current_klass, - bool check_access, bool initialize_class, TRAPS) { - methodHandle resolved_method; - linktime_resolve_static_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK); - resolved_klass = KlassHandle(THREAD, resolved_method->method_holder()); +void LinkResolver::resolve_static_call(CallInfo& result, + const LinkInfo& link_info, + bool initialize_class, TRAPS) { + methodHandle resolved_method = linktime_resolve_static_method(link_info, CHECK); + // The resolved class can change as a result of this resolution. + KlassHandle resolved_klass = KlassHandle(THREAD, resolved_method->method_holder()); + + Method* save_resolved_method = resolved_method(); // Initialize klass (this should only happen if everything is ok) if (initialize_class && resolved_klass->should_be_initialized()) { resolved_klass->initialize(CHECK); - linktime_resolve_static_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK); + // Use updated LinkInfo (to reresolve with resolved_klass as method_holder?) + LinkInfo new_info(resolved_klass, link_info.name(), link_info.signature(), + link_info.current_klass(), link_info.check_access()); + resolved_method = linktime_resolve_static_method(new_info, CHECK); } + assert(save_resolved_method == resolved_method(), "does this change?"); // setup result result.set_static(resolved_klass, resolved_method, CHECK); } // throws linktime exceptions -void LinkResolver::linktime_resolve_static_method(methodHandle& resolved_method, KlassHandle resolved_klass, - Symbol* method_name, Symbol* method_signature, - KlassHandle current_klass, bool check_access, TRAPS) { +methodHandle LinkResolver::linktime_resolve_static_method(const LinkInfo& link_info, TRAPS) { + KlassHandle resolved_klass = link_info.resolved_klass(); + methodHandle resolved_method; if (!resolved_klass->is_interface()) { - resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, false, CHECK); + resolved_method = resolve_method(link_info, /*require_methodref*/false, CHECK_NULL); } else { - resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, false, CHECK); + resolved_method = resolve_interface_method(link_info, /*nostatics*/false, CHECK_NULL); } assert(resolved_method->name() != vmSymbols::class_initializer_name(), "should have been checked in verifier"); @@ -909,22 +942,25 @@ void LinkResolver::linktime_resolve_static_method(methodHandle& resolved_method, jio_snprintf(buf, sizeof(buf), "Expected static method %s", Method::name_and_sig_as_C_string(resolved_klass(), resolved_method->name(), resolved_method->signature())); - THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); + THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); } + return resolved_method; } -void LinkResolver::resolve_special_call(CallInfo& result, KlassHandle resolved_klass, Symbol* method_name, - Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS) { - methodHandle resolved_method; - linktime_resolve_special_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK); - runtime_resolve_special_method(result, resolved_method, resolved_klass, current_klass, check_access, CHECK); +void LinkResolver::resolve_special_call(CallInfo& result, + const LinkInfo& link_info, + TRAPS) { + methodHandle resolved_method = linktime_resolve_special_method(link_info, CHECK); + runtime_resolve_special_method(result, resolved_method, + link_info.resolved_klass(), + link_info.current_klass(), + link_info.check_access(), CHECK); } // throws linktime exceptions -void LinkResolver::linktime_resolve_special_method(methodHandle& resolved_method, KlassHandle resolved_klass, - Symbol* method_name, Symbol* method_signature, - KlassHandle current_klass, bool check_access, TRAPS) { +methodHandle LinkResolver::linktime_resolve_special_method(const LinkInfo& link_info, + TRAPS) { // Invokespecial is called for multiple special reasons: // @@ -932,11 +968,13 @@ void LinkResolver::linktime_resolve_special_method(methodHandle& resolved_method // superclass.method, which can also resolve to a default method // and the selected method is recalculated relative to the direct superclass // superinterface.method, which explicitly does not check shadowing + KlassHandle resolved_klass = link_info.resolved_klass(); + methodHandle resolved_method; if (!resolved_klass->is_interface()) { - resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, false, CHECK); + resolved_method = resolve_method(link_info, /*require_methodref*/false, CHECK_NULL); } else { - resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, true, CHECK); + resolved_method = resolve_interface_method(link_info, /*nostatics*/true, CHECK_NULL); } // check if method name is , that it is found in same klass as static type @@ -951,10 +989,11 @@ void LinkResolver::linktime_resolve_special_method(methodHandle& resolved_method resolved_method->name()->as_C_string(), resolved_method->signature()->as_C_string() ); - return; + return NULL; } // check if invokespecial's interface method reference is in an indirect superinterface + KlassHandle current_klass = link_info.current_klass(); if (!current_klass.is_null() && resolved_klass->is_interface()) { Klass *klass_to_check = !InstanceKlass::cast(current_klass())->is_anonymous() ? current_klass() : @@ -973,7 +1012,7 @@ void LinkResolver::linktime_resolve_special_method(methodHandle& resolved_method resolved_method->name(), resolved_method->signature()), current_klass->external_name()); - THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); + THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); } } @@ -984,35 +1023,26 @@ void LinkResolver::linktime_resolve_special_method(methodHandle& resolved_method jio_snprintf(buf, sizeof(buf), "Expecting non-static method %s", Method::name_and_sig_as_C_string(resolved_klass(), - resolved_method->name(), - resolved_method->signature())); - THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); + resolved_method->name(), + resolved_method->signature())); + THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); } if (TraceItables && Verbose) { - ResourceMark rm(THREAD); - tty->print("invokespecial resolved method: caller-class:%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: ", - (current_klass.is_null() ? "" : current_klass->internal_name()), - (resolved_klass.is_null() ? "" : resolved_klass->internal_name()), - Method::name_and_sig_as_C_string(resolved_klass(), - resolved_method->name(), - resolved_method->signature()), - resolved_method->method_holder()->internal_name() - ); - resolved_method->access_flags().print_on(tty); - if (resolved_method->is_default_method()) { - tty->print("default "); - } - if (resolved_method->is_overpass()) { - tty->print("overpass"); - } + trace_method_resolution("invokespecial resolved method: caller-class:", + current_klass, resolved_klass, resolved_method); tty->cr(); } + + return resolved_method; } // throws runtime exceptions -void LinkResolver::runtime_resolve_special_method(CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass, - KlassHandle current_klass, bool check_access, TRAPS) { +void LinkResolver::runtime_resolve_special_method(CallInfo& result, + const methodHandle& resolved_method, + KlassHandle resolved_klass, + KlassHandle current_klass, + bool check_access, TRAPS) { // resolved method is selected method unless we have an old-style lookup // for a superclass method @@ -1037,7 +1067,7 @@ void LinkResolver::runtime_resolve_special_method(CallInfo& result, methodHandle resolved_method->name() != vmSymbols::object_initializer_name()) { // Lookup super method KlassHandle super_klass(THREAD, current_klass->super()); - lookup_instance_method_in_klasses(sel_method, super_klass, + sel_method = lookup_instance_method_in_klasses(super_klass, resolved_method->name(), resolved_method->signature(), CHECK); // check if found @@ -1066,26 +1096,13 @@ void LinkResolver::runtime_resolve_special_method(CallInfo& result, methodHandle ResourceMark rm(THREAD); THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), Method::name_and_sig_as_C_string(resolved_klass(), - sel_method->name(), - sel_method->signature())); + sel_method->name(), + sel_method->signature())); } if (TraceItables && Verbose) { - ResourceMark rm(THREAD); - tty->print("invokespecial selected method: resolved-class:%s, method:%s, method_holder:%s, access_flags: ", - (resolved_klass.is_null() ? "" : resolved_klass->internal_name()), - Method::name_and_sig_as_C_string(resolved_klass(), - sel_method->name(), - sel_method->signature()), - sel_method->method_holder()->internal_name() - ); - sel_method->access_flags().print_on(tty); - if (sel_method->is_default_method()) { - tty->print("default "); - } - if (sel_method->is_overpass()) { - tty->print("overpass"); - } + trace_method_resolution("invokespecial selected method: resolved-class:", + resolved_klass, resolved_klass, sel_method); tty->cr(); } @@ -1093,25 +1110,29 @@ void LinkResolver::runtime_resolve_special_method(CallInfo& result, methodHandle result.set_static(resolved_klass, sel_method, CHECK); } -void LinkResolver::resolve_virtual_call(CallInfo& result, Handle recv, KlassHandle receiver_klass, KlassHandle resolved_klass, - Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, - bool check_access, bool check_null_and_abstract, TRAPS) { - methodHandle resolved_method; - linktime_resolve_virtual_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK); - runtime_resolve_virtual_method(result, resolved_method, resolved_klass, recv, receiver_klass, check_null_and_abstract, CHECK); +void LinkResolver::resolve_virtual_call(CallInfo& result, Handle recv, KlassHandle receiver_klass, + const LinkInfo& link_info, + bool check_null_and_abstract, TRAPS) { + methodHandle resolved_method = linktime_resolve_virtual_method(link_info, CHECK); + runtime_resolve_virtual_method(result, resolved_method, + link_info.resolved_klass(), + recv, receiver_klass, + check_null_and_abstract, CHECK); } // throws linktime exceptions -void LinkResolver::linktime_resolve_virtual_method(methodHandle &resolved_method, KlassHandle resolved_klass, - Symbol* method_name, Symbol* method_signature, - KlassHandle current_klass, bool check_access, TRAPS) { +methodHandle LinkResolver::linktime_resolve_virtual_method(const LinkInfo& link_info, + TRAPS) { // normal method resolution - resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, true, CHECK); + methodHandle resolved_method = resolve_method(link_info, /*require_methodref*/true, CHECK_NULL); assert(resolved_method->name() != vmSymbols::object_initializer_name(), "should have been checked in verifier"); assert(resolved_method->name() != vmSymbols::class_initializer_name (), "should have been checked in verifier"); // check if private interface method + KlassHandle resolved_klass = link_info.resolved_klass(); + KlassHandle current_klass = link_info.current_klass(); + if (resolved_klass->is_interface() && resolved_method->is_private()) { ResourceMark rm(THREAD); char buf[200]; @@ -1120,7 +1141,7 @@ void LinkResolver::linktime_resolve_virtual_method(methodHandle &resolved_method resolved_method->name(), resolved_method->signature()), (current_klass.is_null() ? "" : current_klass->internal_name())); - THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); + THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); } // check if not static @@ -1130,33 +1151,21 @@ void LinkResolver::linktime_resolve_virtual_method(methodHandle &resolved_method jio_snprintf(buf, sizeof(buf), "Expecting non-static method %s", Method::name_and_sig_as_C_string(resolved_klass(), resolved_method->name(), resolved_method->signature())); - THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); + THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); } if (PrintVtables && Verbose) { - ResourceMark rm(THREAD); - tty->print("invokevirtual resolved method: caller-class:%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: ", - (current_klass.is_null() ? "" : current_klass->internal_name()), - (resolved_klass.is_null() ? "" : resolved_klass->internal_name()), - Method::name_and_sig_as_C_string(resolved_klass(), - resolved_method->name(), - resolved_method->signature()), - resolved_method->method_holder()->internal_name() - ); - resolved_method->access_flags().print_on(tty); - if (resolved_method->is_default_method()) { - tty->print("default "); - } - if (resolved_method->is_overpass()) { - tty->print("overpass"); - } + trace_method_resolution("invokevirtual resolved method: caller-class:", + current_klass, resolved_klass, resolved_method); tty->cr(); } + + return resolved_method; } // throws runtime exceptions void LinkResolver::runtime_resolve_virtual_method(CallInfo& result, - methodHandle resolved_method, + const methodHandle& resolved_method, KlassHandle resolved_klass, Handle recv, KlassHandle recv_klass, @@ -1227,50 +1236,40 @@ void LinkResolver::runtime_resolve_virtual_method(CallInfo& result, } if (PrintVtables && Verbose) { - ResourceMark rm(THREAD); - tty->print("invokevirtual selected method: receiver-class:%s, resolved-class:%s, method:%s, method_holder:%s, vtable_index:%d, access_flags: ", - (recv_klass.is_null() ? "" : recv_klass->internal_name()), - (resolved_klass.is_null() ? "" : resolved_klass->internal_name()), - Method::name_and_sig_as_C_string(resolved_klass(), - resolved_method->name(), - resolved_method->signature()), - selected_method->method_holder()->internal_name(), - vtable_index - ); - selected_method->access_flags().print_on(tty); - if (selected_method->is_default_method()) { - tty->print("default "); - } - if (selected_method->is_overpass()) { - tty->print("overpass"); - } - tty->cr(); + trace_method_resolution("invokevirtual selected method: receiver-class:", + recv_klass, resolved_klass, selected_method); + tty->print_cr("vtable_index:%d", vtable_index); } // setup result result.set_virtual(resolved_klass, recv_klass, resolved_method, selected_method, vtable_index, CHECK); } -void LinkResolver::resolve_interface_call(CallInfo& result, Handle recv, KlassHandle recv_klass, KlassHandle resolved_klass, - Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, - bool check_access, bool check_null_and_abstract, TRAPS) { - methodHandle resolved_method; - linktime_resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK); - runtime_resolve_interface_method(result, resolved_method, resolved_klass, recv, recv_klass, check_null_and_abstract, CHECK); +void LinkResolver::resolve_interface_call(CallInfo& result, Handle recv, KlassHandle recv_klass, + const LinkInfo& link_info, + bool check_null_and_abstract, TRAPS) { + // throws linktime exceptions + methodHandle resolved_method = linktime_resolve_interface_method(link_info, CHECK); + runtime_resolve_interface_method(result, resolved_method,link_info.resolved_klass(), + recv, recv_klass, check_null_and_abstract, CHECK); } -// throws linktime exceptions -void LinkResolver::linktime_resolve_interface_method(methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, - Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS) { +methodHandle LinkResolver::linktime_resolve_interface_method(const LinkInfo& link_info, + TRAPS) { // normal interface method resolution - resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, true, CHECK); - + methodHandle resolved_method = resolve_interface_method(link_info, true, CHECK_NULL); assert(resolved_method->name() != vmSymbols::object_initializer_name(), "should have been checked in verifier"); assert(resolved_method->name() != vmSymbols::class_initializer_name (), "should have been checked in verifier"); + + return resolved_method; } // throws runtime exceptions -void LinkResolver::runtime_resolve_interface_method(CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass, - Handle recv, KlassHandle recv_klass, bool check_null_and_abstract, TRAPS) { +void LinkResolver::runtime_resolve_interface_method(CallInfo& result, + const methodHandle& resolved_method, + KlassHandle resolved_klass, + Handle recv, + KlassHandle recv_klass, + bool check_null_and_abstract, TRAPS) { // check if receiver exists if (check_null_and_abstract && recv.is_null()) { THROW(vmSymbols::java_lang_NullPointerException()); @@ -1298,12 +1297,11 @@ void LinkResolver::runtime_resolve_interface_method(CallInfo& result, methodHand } // do lookup based on receiver klass - methodHandle sel_method; // This search must match the linktime preparation search for itable initialization // to correctly enforce loader constraints for interface method inheritance - lookup_instance_method_in_klasses(sel_method, recv_klass, - resolved_method->name(), - resolved_method->signature(), CHECK); + methodHandle sel_method = lookup_instance_method_in_klasses(recv_klass, + resolved_method->name(), + resolved_method->signature(), CHECK); if (sel_method.is_null() && !check_null_and_abstract) { // In theory this is a harmless placeholder value, but // in practice leaving in null affects the nsk default method tests. @@ -1314,9 +1312,9 @@ void LinkResolver::runtime_resolve_interface_method(CallInfo& result, methodHand if (sel_method.is_null()) { ResourceMark rm(THREAD); THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), - Method::name_and_sig_as_C_string(recv_klass(), - resolved_method->name(), - resolved_method->signature())); + Method::name_and_sig_as_C_string(recv_klass(), + resolved_method->name(), + resolved_method->signature())); } // check access // Throw Illegal Access Error if sel_method is not public. @@ -1337,22 +1335,8 @@ void LinkResolver::runtime_resolve_interface_method(CallInfo& result, methodHand } if (TraceItables && Verbose) { - ResourceMark rm(THREAD); - tty->print("invokeinterface selected method: receiver-class:%s, resolved-class:%s, method:%s, method_holder:%s, access_flags: ", - (recv_klass.is_null() ? "" : recv_klass->internal_name()), - (resolved_klass.is_null() ? "" : resolved_klass->internal_name()), - Method::name_and_sig_as_C_string(resolved_klass(), - resolved_method->name(), - resolved_method->signature()), - sel_method->method_holder()->internal_name() - ); - sel_method->access_flags().print_on(tty); - if (sel_method->is_default_method()) { - tty->print("default "); - } - if (sel_method->is_overpass()) { - tty->print("overpass"); - } + trace_method_resolution("invokeinterface selected method: receiver-class", + recv_klass, resolved_klass, sel_method); tty->cr(); } // setup result @@ -1368,14 +1352,9 @@ void LinkResolver::runtime_resolve_interface_method(CallInfo& result, methodHand methodHandle LinkResolver::linktime_resolve_interface_method_or_null( - KlassHandle resolved_klass, - Symbol* method_name, - Symbol* method_signature, - KlassHandle current_klass, - bool check_access) { + const LinkInfo& link_info) { EXCEPTION_MARK; - methodHandle method_result; - linktime_resolve_interface_method(method_result, resolved_klass, method_name, method_signature, current_klass, check_access, THREAD); + methodHandle method_result = linktime_resolve_interface_method(link_info, THREAD); if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; return methodHandle(); @@ -1385,14 +1364,9 @@ methodHandle LinkResolver::linktime_resolve_interface_method_or_null( } methodHandle LinkResolver::linktime_resolve_virtual_method_or_null( - KlassHandle resolved_klass, - Symbol* method_name, - Symbol* method_signature, - KlassHandle current_klass, - bool check_access) { + const LinkInfo& link_info) { EXCEPTION_MARK; - methodHandle method_result; - linktime_resolve_virtual_method(method_result, resolved_klass, method_name, method_signature, current_klass, check_access, THREAD); + methodHandle method_result = linktime_resolve_virtual_method(link_info, THREAD); if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; return methodHandle(); @@ -1403,14 +1377,10 @@ methodHandle LinkResolver::linktime_resolve_virtual_method_or_null( methodHandle LinkResolver::resolve_virtual_call_or_null( KlassHandle receiver_klass, - KlassHandle resolved_klass, - Symbol* name, - Symbol* signature, - KlassHandle current_klass, - bool check_access) { + const LinkInfo& link_info) { EXCEPTION_MARK; CallInfo info; - resolve_virtual_call(info, Handle(), receiver_klass, resolved_klass, name, signature, current_klass, check_access, false, THREAD); + resolve_virtual_call(info, Handle(), receiver_klass, link_info, false, THREAD); if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; return methodHandle(); @@ -1420,14 +1390,10 @@ methodHandle LinkResolver::resolve_virtual_call_or_null( methodHandle LinkResolver::resolve_interface_call_or_null( KlassHandle receiver_klass, - KlassHandle resolved_klass, - Symbol* name, - Symbol* signature, - KlassHandle current_klass, - bool check_access) { + const LinkInfo& link_info) { EXCEPTION_MARK; CallInfo info; - resolve_interface_call(info, Handle(), receiver_klass, resolved_klass, name, signature, current_klass, check_access, false, THREAD); + resolve_interface_call(info, Handle(), receiver_klass, link_info, false, THREAD); if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; return methodHandle(); @@ -1435,15 +1401,12 @@ methodHandle LinkResolver::resolve_interface_call_or_null( return info.selected_method(); } -int LinkResolver::resolve_virtual_vtable_index( - KlassHandle receiver_klass, - KlassHandle resolved_klass, - Symbol* name, - Symbol* signature, - KlassHandle current_klass) { +int LinkResolver::resolve_virtual_vtable_index(KlassHandle receiver_klass, + const LinkInfo& link_info) { EXCEPTION_MARK; CallInfo info; - resolve_virtual_call(info, Handle(), receiver_klass, resolved_klass, name, signature, current_klass, true, false, THREAD); + resolve_virtual_call(info, Handle(), receiver_klass, link_info, + /*check_null_or_abstract*/false, THREAD); if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; return Method::invalid_vtable_index; @@ -1451,15 +1414,10 @@ int LinkResolver::resolve_virtual_vtable_index( return info.vtable_index(); } -methodHandle LinkResolver::resolve_static_call_or_null( - KlassHandle resolved_klass, - Symbol* name, - Symbol* signature, - KlassHandle current_klass, - bool check_access) { +methodHandle LinkResolver::resolve_static_call_or_null(const LinkInfo& link_info) { EXCEPTION_MARK; CallInfo info; - resolve_static_call(info, resolved_klass, name, signature, current_klass, check_access, false, THREAD); + resolve_static_call(info, link_info, /*initialize_class*/false, THREAD); if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; return methodHandle(); @@ -1467,15 +1425,10 @@ methodHandle LinkResolver::resolve_static_call_or_null( return info.selected_method(); } -methodHandle LinkResolver::resolve_special_call_or_null( - KlassHandle resolved_klass, - Symbol* name, - Symbol* signature, - KlassHandle current_klass, - bool check_access) { +methodHandle LinkResolver::resolve_special_call_or_null(const LinkInfo& link_info) { EXCEPTION_MARK; CallInfo info; - resolve_special_call(info, resolved_klass, name, signature, current_klass, check_access, THREAD); + resolve_special_call(info, link_info, THREAD); if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; return methodHandle(); @@ -1500,35 +1453,15 @@ void LinkResolver::resolve_invoke(CallInfo& result, Handle recv, constantPoolHan return; } -void LinkResolver::resolve_pool(KlassHandle& resolved_klass, Symbol*& method_name, Symbol*& method_signature, - KlassHandle& current_klass, constantPoolHandle pool, int index, TRAPS) { - // resolve klass - resolve_klass(resolved_klass, pool, index, CHECK); - - // Get name, signature, and static klass - method_name = pool->name_ref_at(index); - method_signature = pool->signature_ref_at(index); - current_klass = KlassHandle(THREAD, pool->pool_holder()); -} - - void LinkResolver::resolve_invokestatic(CallInfo& result, constantPoolHandle pool, int index, TRAPS) { - KlassHandle resolved_klass; - Symbol* method_name = NULL; - Symbol* method_signature = NULL; - KlassHandle current_klass; - resolve_pool(resolved_klass, method_name, method_signature, current_klass, pool, index, CHECK); - resolve_static_call(result, resolved_klass, method_name, method_signature, current_klass, true, true, CHECK); + LinkInfo link_info(pool, index, CHECK); + resolve_static_call(result, link_info, /*initialize_class*/true, CHECK); } void LinkResolver::resolve_invokespecial(CallInfo& result, constantPoolHandle pool, int index, TRAPS) { - KlassHandle resolved_klass; - Symbol* method_name = NULL; - Symbol* method_signature = NULL; - KlassHandle current_klass; - resolve_pool(resolved_klass, method_name, method_signature, current_klass, pool, index, CHECK); - resolve_special_call(result, resolved_klass, method_name, method_signature, current_klass, true, CHECK); + LinkInfo link_info(pool, index, CHECK); + resolve_special_call(result, link_info, CHECK); } @@ -1536,54 +1469,40 @@ void LinkResolver::resolve_invokevirtual(CallInfo& result, Handle recv, constantPoolHandle pool, int index, TRAPS) { - KlassHandle resolved_klass; - Symbol* method_name = NULL; - Symbol* method_signature = NULL; - KlassHandle current_klass; - resolve_pool(resolved_klass, method_name, method_signature, current_klass, pool, index, CHECK); + LinkInfo link_info(pool, index, CHECK); KlassHandle recvrKlass (THREAD, recv.is_null() ? (Klass*)NULL : recv->klass()); - resolve_virtual_call(result, recv, recvrKlass, resolved_klass, method_name, method_signature, current_klass, true, true, CHECK); + resolve_virtual_call(result, recv, recvrKlass, link_info, /*check_null_or_abstract*/true, CHECK); } void LinkResolver::resolve_invokeinterface(CallInfo& result, Handle recv, constantPoolHandle pool, int index, TRAPS) { - KlassHandle resolved_klass; - Symbol* method_name = NULL; - Symbol* method_signature = NULL; - KlassHandle current_klass; - resolve_pool(resolved_klass, method_name, method_signature, current_klass, pool, index, CHECK); + LinkInfo link_info(pool, index, CHECK); KlassHandle recvrKlass (THREAD, recv.is_null() ? (Klass*)NULL : recv->klass()); - resolve_interface_call(result, recv, recvrKlass, resolved_klass, method_name, method_signature, current_klass, true, true, CHECK); + resolve_interface_call(result, recv, recvrKlass, link_info, true, CHECK); } void LinkResolver::resolve_invokehandle(CallInfo& result, constantPoolHandle pool, int index, TRAPS) { // This guy is reached from InterpreterRuntime::resolve_invokehandle. - KlassHandle resolved_klass; - Symbol* method_name = NULL; - Symbol* method_signature = NULL; - KlassHandle current_klass; - resolve_pool(resolved_klass, method_name, method_signature, current_klass, pool, index, CHECK); + LinkInfo link_info(pool, index, CHECK); if (TraceMethodHandles) { ResourceMark rm(THREAD); - tty->print_cr("resolve_invokehandle %s %s", method_name->as_C_string(), method_signature->as_C_string()); + tty->print_cr("resolve_invokehandle %s %s", link_info.name()->as_C_string(), + link_info.signature()->as_C_string()); } - resolve_handle_call(result, resolved_klass, method_name, method_signature, current_klass, CHECK); + resolve_handle_call(result, link_info, CHECK); } -void LinkResolver::resolve_handle_call(CallInfo& result, KlassHandle resolved_klass, - Symbol* method_name, Symbol* method_signature, - KlassHandle current_klass, +void LinkResolver::resolve_handle_call(CallInfo& result, + const LinkInfo& link_info, TRAPS) { // JSR 292: this must be an implicitly generated method MethodHandle.invokeExact(*...) or similar - assert(resolved_klass() == SystemDictionary::MethodHandle_klass(), ""); - assert(MethodHandles::is_signature_polymorphic_name(method_name), ""); - methodHandle resolved_method; + assert(link_info.resolved_klass()() == SystemDictionary::MethodHandle_klass(), ""); + assert(MethodHandles::is_signature_polymorphic_name(link_info.name()), ""); Handle resolved_appendix; Handle resolved_method_type; - lookup_polymorphic_method(resolved_method, resolved_klass, - method_name, method_signature, - current_klass, &resolved_appendix, &resolved_method_type, CHECK); + methodHandle resolved_method = lookup_polymorphic_method(link_info, + &resolved_appendix, &resolved_method_type, CHECK); result.set_handle(resolved_method, resolved_appendix, resolved_method_type, CHECK); } @@ -1609,7 +1528,6 @@ static void wrap_invokedynamic_exception(TRAPS) { } void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle pool, int index, TRAPS) { - //resolve_pool(, method_name, method_signature, current_klass, pool, index, CHECK); Symbol* method_name = pool->name_ref_at(index); Symbol* method_signature = pool->signature_ref_at(index); KlassHandle current_klass = KlassHandle(THREAD, pool->pool_holder()); @@ -1667,19 +1585,27 @@ void LinkResolver::resolve_dynamic_call(CallInfo& result, wrap_invokedynamic_exception(CHECK); } -//------------------------------------------------------------------------------------------------------------------------ #ifndef PRODUCT - -void CallInfo::print() { +void LinkResolver::trace_method_resolution(const char* prefix, + KlassHandle klass, + KlassHandle resolved_klass, + const methodHandle& method) { ResourceMark rm; - const char* kindstr = "unknown"; - switch (_call_kind) { - case direct_call: kindstr = "direct"; break; - case vtable_call: kindstr = "vtable"; break; - case itable_call: kindstr = "itable"; break; + tty->print("%s%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: ", + prefix, + (klass.is_null() ? "" : klass->internal_name()), + (resolved_klass.is_null() ? "" : resolved_klass->internal_name()), + Method::name_and_sig_as_C_string(resolved_klass(), + method->name(), + method->signature()), + method->method_holder()->internal_name() + ); + method->access_flags().print_on(tty); + if (method->is_default_method()) { + tty->print("default "); + } + if (method->is_overpass()) { + tty->print("overpass "); } - tty->print_cr("Call %s@%d %s", kindstr, _call_index, - _resolved_method.is_null() ? "(none)" : _resolved_method->name_and_sig_as_C_string()); } - -#endif +#endif // PRODUCT diff --git a/hotspot/src/share/vm/interpreter/linkResolver.hpp b/hotspot/src/share/vm/interpreter/linkResolver.hpp index 5fa536491c9..d3fda4368ef 100644 --- a/hotspot/src/share/vm/interpreter/linkResolver.hpp +++ b/hotspot/src/share/vm/interpreter/linkResolver.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,7 @@ // that method. If the info is invalid, the link has not been resolved // successfully. -class CallInfo VALUE_OBJ_CLASS_SPEC { +class CallInfo : public StackObj { public: // Ways that a method call might be selected (or not) based on receiver type. // Note that an invokevirtual instruction might be linked with no_dispatch, @@ -58,11 +58,22 @@ class CallInfo VALUE_OBJ_CLASS_SPEC { Handle _resolved_appendix; // extra argument in constant pool (if CPCE::has_appendix) Handle _resolved_method_type; // MethodType (for invokedynamic and invokehandle call sites) - void set_static( KlassHandle resolved_klass, methodHandle resolved_method , TRAPS); - void set_interface(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int itable_index , TRAPS); - void set_virtual( KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index , TRAPS); - void set_handle( methodHandle resolved_method, Handle resolved_appendix, Handle resolved_method_type, TRAPS); - void set_common( KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, CallKind kind, int index, TRAPS); + void set_static(KlassHandle resolved_klass, const methodHandle& resolved_method, TRAPS); + void set_interface(KlassHandle resolved_klass, KlassHandle selected_klass, + const methodHandle& resolved_method, + const methodHandle& selected_method, + int itable_index, TRAPS); + void set_virtual(KlassHandle resolved_klass, KlassHandle selected_klass, + const methodHandle& resolved_method, + const methodHandle& selected_method, + int vtable_index, TRAPS); + void set_handle(const methodHandle& resolved_method, + Handle resolved_appendix, Handle resolved_method_type, TRAPS); + void set_common(KlassHandle resolved_klass, KlassHandle selected_klass, + const methodHandle& resolved_method, + const methodHandle& selected_method, + CallKind kind, + int index, TRAPS); friend class LinkResolver; @@ -113,6 +124,37 @@ class CallInfo VALUE_OBJ_CLASS_SPEC { void print() PRODUCT_RETURN; }; + +// Condensed information from constant pool to use to resolve the method or field. +// resolved_klass = specified class (i.e., static receiver class) +// current_klass = sending method holder (i.e., class containing the method +// containing the call being resolved) +class LinkInfo : public StackObj { + Symbol* _name; // extracted from JVM_CONSTANT_NameAndType + Symbol* _signature; + KlassHandle _resolved_klass; // class that the constant pool entry points to + KlassHandle _current_klass; // class that owns the constant pool + bool _check_access; + public: + LinkInfo(constantPoolHandle pool, int index, TRAPS); + // Condensed information from other call sites within the vm. + LinkInfo(KlassHandle resolved_klass, Symbol* name, Symbol* signature, + KlassHandle current_klass, bool check_access = true) : + _resolved_klass(resolved_klass), + _name(name), _signature(signature), _current_klass(current_klass), + _check_access(check_access) {} + + // accessors + Symbol* name() const { return _name; } + Symbol* signature() const { return _signature; } + KlassHandle resolved_klass() const { return _resolved_klass; } + KlassHandle current_klass() const { return _current_klass; } + bool check_access() const { return _check_access; } + char* method_string() const; + + void print() PRODUCT_RETURN; +}; + // Link information for getfield/putfield & getstatic/putstatic bytecodes // is represented using a fieldDescriptor. @@ -124,85 +166,136 @@ class LinkResolver: AllStatic { friend class klassItable; private: - static void lookup_method_in_klasses (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, bool checkpolymorphism, bool in_imethod_resolve, TRAPS); - static void lookup_instance_method_in_klasses (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS); - static void lookup_method_in_interfaces (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS); - static void lookup_polymorphic_method (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, - KlassHandle current_klass, Handle *appendix_result_or_null, Handle *method_type_result, TRAPS); - static void resolve_klass (KlassHandle& result, constantPoolHandle pool, int index, TRAPS); + static methodHandle lookup_method_in_klasses(const LinkInfo& link_info, + bool checkpolymorphism, + bool in_imethod_resolve, TRAPS); + static methodHandle lookup_method_in_interfaces(const LinkInfo& link_info, TRAPS); + static methodHandle lookup_polymorphic_method(const LinkInfo& link_info, + Handle *appendix_result_or_null, + Handle *method_type_result, TRAPS); + // Not Linktime so doesn't take LinkInfo + static methodHandle lookup_instance_method_in_klasses ( + KlassHandle klass, Symbol* name, Symbol* signature, TRAPS); - static void resolve_pool (KlassHandle& resolved_klass, Symbol*& method_name, Symbol*& method_signature, KlassHandle& current_klass, constantPoolHandle pool, int index, TRAPS); + // Similar loader constraint checking functions that throw + // LinkageError with descriptive message. + static void check_method_loader_constraints(const LinkInfo& link_info, + const methodHandle& resolved_method, + const char* method_type, TRAPS); + static void check_field_loader_constraints(Symbol* field, Symbol* sig, + KlassHandle current_klass, + KlassHandle sel_klass, TRAPS); - static void resolve_interface_method(methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool nostatics, TRAPS); - static void resolve_method (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool require_methodref, TRAPS); + static methodHandle resolve_interface_method(const LinkInfo& link_info, bool nostatics, TRAPS); + static methodHandle resolve_method (const LinkInfo& link_info, bool require_methodref, TRAPS); - static void linktime_resolve_static_method (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS); - static void linktime_resolve_special_method (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS); - static void linktime_resolve_virtual_method (methodHandle &resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature,KlassHandle current_klass, bool check_access, TRAPS); - static void linktime_resolve_interface_method (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS); + static methodHandle linktime_resolve_static_method (const LinkInfo& link_info, TRAPS); + static methodHandle linktime_resolve_special_method (const LinkInfo& link_info, TRAPS); + static methodHandle linktime_resolve_virtual_method (const LinkInfo& link_info, TRAPS); + static methodHandle linktime_resolve_interface_method (const LinkInfo& link_info, TRAPS); - static void runtime_resolve_special_method (CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass, KlassHandle current_klass, bool check_access, TRAPS); - static void runtime_resolve_virtual_method (CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass, Handle recv, KlassHandle recv_klass, bool check_null_and_abstract, TRAPS); - static void runtime_resolve_interface_method (CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass, Handle recv, KlassHandle recv_klass, bool check_null_and_abstract, TRAPS); + static void runtime_resolve_special_method (CallInfo& result, + const methodHandle& resolved_method, + KlassHandle resolved_klass, + KlassHandle current_klass, + bool check_access, TRAPS); + static void runtime_resolve_virtual_method (CallInfo& result, + const methodHandle& resolved_method, + KlassHandle resolved_klass, + Handle recv, + KlassHandle recv_klass, + bool check_null_and_abstract, TRAPS); + static void runtime_resolve_interface_method (CallInfo& result, + const methodHandle& resolved_method, + KlassHandle resolved_klass, + Handle recv, + KlassHandle recv_klass, + bool check_null_and_abstract, TRAPS); - static void check_field_accessability (KlassHandle ref_klass, KlassHandle resolved_klass, KlassHandle sel_klass, fieldDescriptor& fd, TRAPS); - static void check_method_accessability (KlassHandle ref_klass, KlassHandle resolved_klass, KlassHandle sel_klass, methodHandle sel_method, TRAPS); + static void check_field_accessability(KlassHandle ref_klass, + KlassHandle resolved_klass, + KlassHandle sel_klass, + const fieldDescriptor& fd, TRAPS); + static void check_method_accessability(KlassHandle ref_klass, + KlassHandle resolved_klass, + KlassHandle sel_klass, + const methodHandle& sel_method, TRAPS); + // runtime resolving from constant pool + static void resolve_invokestatic (CallInfo& result, + constantPoolHandle pool, int index, TRAPS); + static void resolve_invokespecial (CallInfo& result, + constantPoolHandle pool, int index, TRAPS); + static void resolve_invokevirtual (CallInfo& result, Handle recv, + constantPoolHandle pool, int index, TRAPS); + static void resolve_invokeinterface(CallInfo& result, Handle recv, + constantPoolHandle pool, int index, TRAPS); + static void resolve_invokedynamic (CallInfo& result, + constantPoolHandle pool, int index, TRAPS); + static void resolve_invokehandle (CallInfo& result, + constantPoolHandle pool, int index, TRAPS); public: // constant pool resolving static void check_klass_accessability(KlassHandle ref_klass, KlassHandle sel_klass, TRAPS); - // static resolving calls (will not run any Java code); used only from Bytecode_invoke::static_target - static void resolve_method_statically(methodHandle& method_result, KlassHandle& klass_result, - Bytecodes::Code code, constantPoolHandle pool, int index, TRAPS); + // static resolving calls (will not run any Java code); + // used only from Bytecode_invoke::static_target + static methodHandle resolve_method_statically(Bytecodes::Code code, + constantPoolHandle pool, + int index, TRAPS); - // runtime/static resolving for fields - static void resolve_field_access(fieldDescriptor& result, constantPoolHandle pool, int index, Bytecodes::Code byte, TRAPS); - static void resolve_field(fieldDescriptor& result, KlassHandle resolved_klass, Symbol* field_name, Symbol* field_signature, - KlassHandle current_klass, Bytecodes::Code access_kind, bool check_access, bool initialize_class, TRAPS); + static void resolve_field_access(fieldDescriptor& result, + constantPoolHandle pool, + int index, Bytecodes::Code byte, TRAPS); + static void resolve_field(fieldDescriptor& result, const LinkInfo& link_info, + Bytecodes::Code access_kind, + bool initialize_class, TRAPS); - // source of access_kind codes: - static Bytecodes::Code field_access_kind(bool is_static, bool is_put) { - return (is_static - ? (is_put ? Bytecodes::_putstatic : Bytecodes::_getstatic) - : (is_put ? Bytecodes::_putfield : Bytecodes::_getfield )); - } + static void resolve_static_call (CallInfo& result, + const LinkInfo& link_info, + bool initialize_klass, TRAPS); + static void resolve_special_call (CallInfo& result, + const LinkInfo& link_info, + TRAPS); + static void resolve_virtual_call (CallInfo& result, Handle recv, KlassHandle recv_klass, + const LinkInfo& link_info, + bool check_null_and_abstract, TRAPS); + static void resolve_interface_call(CallInfo& result, Handle recv, KlassHandle recv_klass, + const LinkInfo& link_info, + bool check_null_and_abstract, TRAPS); + static void resolve_handle_call (CallInfo& result, + const LinkInfo& link_info, TRAPS); + static void resolve_dynamic_call (CallInfo& result, Handle bootstrap_specifier, + Symbol* method_name, Symbol* method_signature, + KlassHandle current_klass, TRAPS); - // runtime resolving: - // resolved_klass = specified class (i.e., static receiver class) - // current_klass = sending method holder (i.e., class containing the method containing the call being resolved) - static void resolve_static_call (CallInfo& result, KlassHandle& resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool initialize_klass, TRAPS); - static void resolve_special_call (CallInfo& result, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS); - static void resolve_virtual_call (CallInfo& result, Handle recv, KlassHandle recv_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool check_null_and_abstract, TRAPS); - static void resolve_interface_call(CallInfo& result, Handle recv, KlassHandle recv_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool check_null_and_abstract, TRAPS); - static void resolve_handle_call (CallInfo& result, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, TRAPS); - static void resolve_dynamic_call (CallInfo& result, Handle bootstrap_specifier, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, TRAPS); + // same as above for compile-time resolution; but returns null handle instead of throwing + // an exception on error also, does not initialize klass (i.e., no side effects) + static methodHandle resolve_virtual_call_or_null (KlassHandle receiver_klass, + const LinkInfo& link_info); + static methodHandle resolve_interface_call_or_null(KlassHandle receiver_klass, + const LinkInfo& link_info); + static methodHandle resolve_static_call_or_null (const LinkInfo& link_info); + static methodHandle resolve_special_call_or_null (const LinkInfo& link_info); - // same as above for compile-time resolution; but returns null handle instead of throwing an exception on error - // also, does not initialize klass (i.e., no side effects) - static methodHandle resolve_virtual_call_or_null (KlassHandle receiver_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access = true); - static methodHandle resolve_interface_call_or_null(KlassHandle receiver_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access = true); - static methodHandle resolve_static_call_or_null (KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access = true); - static methodHandle resolve_special_call_or_null (KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access = true); - static int vtable_index_of_interface_method(KlassHandle klass, methodHandle resolved_method); + static int vtable_index_of_interface_method(KlassHandle klass, const methodHandle& resolved_method); // same as above for compile-time resolution; returns vtable_index if current_klass if linked - static int resolve_virtual_vtable_index (KlassHandle receiver_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass); + static int resolve_virtual_vtable_index (KlassHandle receiver_klass, + const LinkInfo& link_info); // static resolving for compiler (does not throw exceptions, returns null handle if unsuccessful) - static methodHandle linktime_resolve_virtual_method_or_null (KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access); - static methodHandle linktime_resolve_interface_method_or_null(KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access); + static methodHandle linktime_resolve_virtual_method_or_null (const LinkInfo& link_info); + static methodHandle linktime_resolve_interface_method_or_null(const LinkInfo& link_info); // runtime resolving from constant pool - static void resolve_invokestatic (CallInfo& result, constantPoolHandle pool, int index, TRAPS); - static void resolve_invokespecial (CallInfo& result, constantPoolHandle pool, int index, TRAPS); - static void resolve_invokevirtual (CallInfo& result, Handle recv, constantPoolHandle pool, int index, TRAPS); - static void resolve_invokeinterface(CallInfo& result, Handle recv, constantPoolHandle pool, int index, TRAPS); - static void resolve_invokedynamic (CallInfo& result, constantPoolHandle pool, int index, TRAPS); - static void resolve_invokehandle (CallInfo& result, constantPoolHandle pool, int index, TRAPS); - - static void resolve_invoke (CallInfo& result, Handle recv, constantPoolHandle pool, int index, Bytecodes::Code byte, TRAPS); + static void resolve_invoke(CallInfo& result, Handle recv, + constantPoolHandle pool, int index, + Bytecodes::Code byte, TRAPS); + private: + static void trace_method_resolution(const char* prefix, KlassHandle klass, + KlassHandle resolved_klass, + const methodHandle& method) PRODUCT_RETURN; }; - #endif // SHARE_VM_INTERPRETER_LINKRESOLVER_HPP diff --git a/hotspot/src/share/vm/memory/metaspace.cpp b/hotspot/src/share/vm/memory/metaspace.cpp index fd48fe11021..187be2ca38f 100644 --- a/hotspot/src/share/vm/memory/metaspace.cpp +++ b/hotspot/src/share/vm/memory/metaspace.cpp @@ -614,8 +614,7 @@ class SpaceManager : public CHeapObj { Metachunk* _chunks_in_use[NumberOfInUseLists]; Metachunk* _current_chunk; - // Number of small chunks to allocate to a manager - // If class space manager, small chunks are unlimited + // Maximum number of small chunks to allocate to a SpaceManager static uint const _small_chunk_limit; // Sum of all space in allocated chunks @@ -730,6 +729,8 @@ class SpaceManager : public CHeapObj { // Block allocation and deallocation. // Allocates a block from the current chunk MetaWord* allocate(size_t word_size); + // Allocates a block from a small chunk + MetaWord* get_small_chunk_and_allocate(size_t word_size); // Helper for allocations MetaWord* allocate_work(size_t word_size); @@ -2011,9 +2012,8 @@ void SpaceManager::locked_print_chunks_in_use_on(outputStream* st) const { size_t SpaceManager::calc_chunk_size(size_t word_size) { // Decide between a small chunk and a medium chunk. Up to - // _small_chunk_limit small chunks can be allocated but - // once a medium chunk has been allocated, no more small - // chunks will be allocated. + // _small_chunk_limit small chunks can be allocated. + // After that a medium chunk is preferred. size_t chunk_word_size; if (chunks_in_use(MediumIndex) == NULL && sum_count_in_chunks_in_use(SmallIndex) < _small_chunk_limit) { @@ -2081,7 +2081,7 @@ MetaWord* SpaceManager::grow_and_allocate(size_t word_size) { word_size, words_used, words_left); } - // Get another chunk out of the virtual space + // Get another chunk size_t grow_chunks_by_words = calc_chunk_size(word_size); Metachunk* next = get_new_chunk(word_size, grow_chunks_by_words); @@ -2412,6 +2412,43 @@ Metachunk* SpaceManager::get_new_chunk(size_t word_size, return next; } +/* + * The policy is to allocate up to _small_chunk_limit small chunks + * after which only medium chunks are allocated. This is done to + * reduce fragmentation. In some cases, this can result in a lot + * of small chunks being allocated to the point where it's not + * possible to expand. If this happens, there may be no medium chunks + * available and OOME would be thrown. Instead of doing that, + * if the allocation request size fits in a small chunk, an attempt + * will be made to allocate a small chunk. + */ +MetaWord* SpaceManager::get_small_chunk_and_allocate(size_t word_size) { + if (word_size + Metachunk::overhead() > small_chunk_size()) { + return NULL; + } + + MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag); + MutexLockerEx cl1(expand_lock(), Mutex::_no_safepoint_check_flag); + + Metachunk* chunk = chunk_manager()->chunk_freelist_allocate(small_chunk_size()); + + MetaWord* mem = NULL; + + if (chunk != NULL) { + // Add chunk to the in-use chunk list and do an allocation from it. + // Add to this manager's list of chunks in use. + add_chunk(chunk, false); + mem = chunk->allocate(word_size); + + inc_used_metrics(word_size); + + // Track metaspace memory usage statistic. + track_metaspace_memory_usage(); + } + + return mem; +} + MetaWord* SpaceManager::allocate(size_t word_size) { MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag); @@ -3560,7 +3597,18 @@ MetaWord* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size, } if (result == NULL) { - report_metadata_oome(loader_data, word_size, type, mdtype, CHECK_NULL); + SpaceManager* sm; + if (is_class_space_allocation(mdtype)) { + sm = loader_data->metaspace_non_null()->class_vsm(); + } else { + sm = loader_data->metaspace_non_null()->vsm(); + } + + result = sm->get_small_chunk_and_allocate(word_size); + + if (result == NULL) { + report_metadata_oome(loader_data, word_size, type, mdtype, CHECK_NULL); + } } // Zero initialize. diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index a3d6408bb15..f3eafba456c 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -622,14 +622,6 @@ bool InstanceKlass::link_class_impl( if (!this_k->is_linked()) { if (!this_k->is_rewritten()) { { - // Timer includes any side effects of class verification (resolution, - // etc), but not recursive entry into verify_code(). - PerfClassTraceTime timer(ClassLoader::perf_class_verify_time(), - ClassLoader::perf_class_verify_selftime(), - ClassLoader::perf_classes_verified(), - jt->get_thread_stat()->perf_recursion_counts_addr(), - jt->get_thread_stat()->perf_timers_addr(), - PerfClassTraceTime::CLASS_VERIFY); bool verify_ok = verify_code(this_k, throw_verifyerror, THREAD); if (!verify_ok) { return false; @@ -1830,11 +1822,10 @@ int nmethodBucket::decrement() { // are dependent on the changes that were passed in and mark them for // deoptimization. Returns the number of nmethods found. // -int InstanceKlass::mark_dependent_nmethods(DepChange& changes) { +int nmethodBucket::mark_dependent_nmethods(nmethodBucket* deps, DepChange& changes) { assert_locked_or_safepoint(CodeCache_lock); int found = 0; - nmethodBucket* b = _dependencies; - while (b != NULL) { + for (nmethodBucket* b = deps; b != NULL; b = b->next()) { nmethod* nm = b->get_nmethod(); // since dependencies aren't removed until an nmethod becomes a zombie, // the dependency list may contain nmethods which aren't alive. @@ -1842,7 +1833,6 @@ int InstanceKlass::mark_dependent_nmethods(DepChange& changes) { if (TraceDependencies) { ResourceMark rm; tty->print_cr("Marked for deoptimization"); - tty->print_cr(" context = %s", this->external_name()); changes.print(); nm->print(); nm->print_dependencies(); @@ -1850,36 +1840,119 @@ int InstanceKlass::mark_dependent_nmethods(DepChange& changes) { nm->mark_for_deoptimization(); found++; } - b = b->next(); } return found; } +// +// Add an nmethodBucket to the list of dependencies for this nmethod. +// It's possible that an nmethod has multiple dependencies on this klass +// so a count is kept for each bucket to guarantee that creation and +// deletion of dependencies is consistent. Returns new head of the list. +// +nmethodBucket* nmethodBucket::add_dependent_nmethod(nmethodBucket* deps, nmethod* nm) { + assert_locked_or_safepoint(CodeCache_lock); + for (nmethodBucket* b = deps; b != NULL; b = b->next()) { + if (nm == b->get_nmethod()) { + b->increment(); + return deps; + } + } + return new nmethodBucket(nm, deps); +} + +// +// Decrement count of the nmethod in the dependency list and remove +// the bucket completely when the count goes to 0. This method must +// find a corresponding bucket otherwise there's a bug in the +// recording of dependencies. Returns true if the bucket is ready for reclamation. +// +bool nmethodBucket::remove_dependent_nmethod(nmethodBucket* deps, nmethod* nm) { + assert_locked_or_safepoint(CodeCache_lock); + + for (nmethodBucket* b = deps; b != NULL; b = b->next()) { + if (nm == b->get_nmethod()) { + int val = b->decrement(); + guarantee(val >= 0, err_msg("Underflow: %d", val)); + return (val == 0); + } + } +#ifdef ASSERT + tty->print_raw_cr("### can't find dependent nmethod"); + nm->print(); +#endif // ASSERT + ShouldNotReachHere(); + return false; +} + +// +// Reclaim all unused buckets. Returns new head of the list. +// +nmethodBucket* nmethodBucket::clean_dependent_nmethods(nmethodBucket* deps) { + nmethodBucket* first = deps; + nmethodBucket* last = NULL; + nmethodBucket* b = first; + + while (b != NULL) { + assert(b->count() >= 0, err_msg("bucket count: %d", b->count())); + nmethodBucket* next = b->next(); + if (b->count() == 0) { + if (last == NULL) { + first = next; + } else { + last->set_next(next); + } + delete b; + // last stays the same. + } else { + last = b; + } + b = next; + } + return first; +} + +#ifndef PRODUCT +void nmethodBucket::print_dependent_nmethods(nmethodBucket* deps, bool verbose) { + int idx = 0; + for (nmethodBucket* b = deps; b != NULL; b = b->next()) { + nmethod* nm = b->get_nmethod(); + tty->print("[%d] count=%d { ", idx++, b->count()); + if (!verbose) { + nm->print_on(tty, "nmethod"); + tty->print_cr(" } "); + } else { + nm->print(); + nm->print_dependencies(); + tty->print_cr("--- } "); + } + } +} + +bool nmethodBucket::is_dependent_nmethod(nmethodBucket* deps, nmethod* nm) { + for (nmethodBucket* b = deps; b != NULL; b = b->next()) { + if (nm == b->get_nmethod()) { +#ifdef ASSERT + int count = b->count(); + assert(count >= 0, err_msg("count shouldn't be negative: %d", count)); +#endif + return true; + } + } + return false; +} +#endif //PRODUCT + +int InstanceKlass::mark_dependent_nmethods(DepChange& changes) { + assert_locked_or_safepoint(CodeCache_lock); + return nmethodBucket::mark_dependent_nmethods(_dependencies, changes); +} + void InstanceKlass::clean_dependent_nmethods() { assert_locked_or_safepoint(CodeCache_lock); if (has_unloaded_dependent()) { - nmethodBucket* b = _dependencies; - nmethodBucket* last = NULL; - while (b != NULL) { - assert(b->count() >= 0, err_msg("bucket count: %d", b->count())); - - nmethodBucket* next = b->next(); - - if (b->count() == 0) { - if (last == NULL) { - _dependencies = next; - } else { - last->set_next(next); - } - delete b; - // last stays the same. - } else { - last = b; - } - - b = next; - } + _dependencies = nmethodBucket::clean_dependent_nmethods(_dependencies); set_has_unloaded_dependent(false); } #ifdef ASSERT @@ -1893,90 +1966,26 @@ void InstanceKlass::clean_dependent_nmethods() { #endif } -// -// Add an nmethodBucket to the list of dependencies for this nmethod. -// It's possible that an nmethod has multiple dependencies on this klass -// so a count is kept for each bucket to guarantee that creation and -// deletion of dependencies is consistent. -// void InstanceKlass::add_dependent_nmethod(nmethod* nm) { assert_locked_or_safepoint(CodeCache_lock); - nmethodBucket* b = _dependencies; - nmethodBucket* last = NULL; - while (b != NULL) { - if (nm == b->get_nmethod()) { - b->increment(); - return; - } - b = b->next(); - } - _dependencies = new nmethodBucket(nm, _dependencies); + _dependencies = nmethodBucket::add_dependent_nmethod(_dependencies, nm); } - -// -// Decrement count of the nmethod in the dependency list and remove -// the bucket competely when the count goes to 0. This method must -// find a corresponding bucket otherwise there's a bug in the -// recording of dependecies. -// void InstanceKlass::remove_dependent_nmethod(nmethod* nm) { assert_locked_or_safepoint(CodeCache_lock); - nmethodBucket* b = _dependencies; - nmethodBucket* last = NULL; - while (b != NULL) { - if (nm == b->get_nmethod()) { - int val = b->decrement(); - guarantee(val >= 0, err_msg("Underflow: %d", val)); - if (val == 0) { - set_has_unloaded_dependent(true); - } - return; - } - last = b; - b = b->next(); - } -#ifdef ASSERT - tty->print_cr("### %s can't find dependent nmethod:", this->external_name()); - nm->print(); -#endif // ASSERT - ShouldNotReachHere(); -} + if (nmethodBucket::remove_dependent_nmethod(_dependencies, nm)) { + set_has_unloaded_dependent(true); + } +} #ifndef PRODUCT void InstanceKlass::print_dependent_nmethods(bool verbose) { - nmethodBucket* b = _dependencies; - int idx = 0; - while (b != NULL) { - nmethod* nm = b->get_nmethod(); - tty->print("[%d] count=%d { ", idx++, b->count()); - if (!verbose) { - nm->print_on(tty, "nmethod"); - tty->print_cr(" } "); - } else { - nm->print(); - nm->print_dependencies(); - tty->print_cr("--- } "); - } - b = b->next(); - } + nmethodBucket::print_dependent_nmethods(_dependencies, verbose); } - bool InstanceKlass::is_dependent_nmethod(nmethod* nm) { - nmethodBucket* b = _dependencies; - while (b != NULL) { - if (nm == b->get_nmethod()) { -#ifdef ASSERT - int count = b->count(); - assert(count >= 0, err_msg("count shouldn't be negative: %d", count)); -#endif - return true; - } - b = b->next(); - } - return false; + return nmethodBucket::is_dependent_nmethod(_dependencies, nm); } #endif //PRODUCT diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index b9aaa75480e..141ec1139e6 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -1290,6 +1290,15 @@ class nmethodBucket: public CHeapObj { nmethodBucket* next() { return _next; } void set_next(nmethodBucket* b) { _next = b; } nmethod* get_nmethod() { return _nmethod; } + + static int mark_dependent_nmethods(nmethodBucket* deps, DepChange& changes); + static nmethodBucket* add_dependent_nmethod(nmethodBucket* deps, nmethod* nm); + static bool remove_dependent_nmethod(nmethodBucket* deps, nmethod* nm); + static nmethodBucket* clean_dependent_nmethods(nmethodBucket* deps); +#ifndef PRODUCT + static void print_dependent_nmethods(nmethodBucket* deps, bool verbose); + static bool is_dependent_nmethod(nmethodBucket* deps, nmethod* nm); +#endif //PRODUCT }; // An iterator that's used to access the inner classes indices in the diff --git a/hotspot/src/share/vm/oops/klassVtable.cpp b/hotspot/src/share/vm/oops/klassVtable.cpp index aa16cb6dc21..54df450637b 100644 --- a/hotspot/src/share/vm/oops/klassVtable.cpp +++ b/hotspot/src/share/vm/oops/klassVtable.cpp @@ -1136,7 +1136,7 @@ void klassItable::initialize_itable_for_interface(int method_table_offset, Klass if (m->has_itable_index()) { // This search must match the runtime resolution, i.e. selection search for invokeinterface // to correctly enforce loader constraints for interface method inheritance - LinkResolver::lookup_instance_method_in_klasses(target, _klass, m->name(), m->signature(), CHECK); + target = LinkResolver::lookup_instance_method_in_klasses(_klass, m->name(), m->signature(), CHECK); } if (target == NULL || !target->is_public() || target->is_abstract()) { // Entry does not resolve. Leave it empty for AbstractMethodError. diff --git a/hotspot/src/share/vm/opto/arraycopynode.cpp b/hotspot/src/share/vm/opto/arraycopynode.cpp index a9e673cff58..64233d49722 100644 --- a/hotspot/src/share/vm/opto/arraycopynode.cpp +++ b/hotspot/src/share/vm/opto/arraycopynode.cpp @@ -599,10 +599,14 @@ Node *ArrayCopyNode::Ideal(PhaseGVN *phase, bool can_reshape) { } bool ArrayCopyNode::may_modify(const TypeOopPtr *t_oop, PhaseTransform *phase) { - const TypeOopPtr* dest_t = phase->type(in(ArrayCopyNode::Dest))->is_oopptr(); + Node* dest = in(ArrayCopyNode::Dest); + if (dest->is_top()) { + return false; + } + const TypeOopPtr* dest_t = phase->type(dest)->is_oopptr(); assert(!dest_t->is_known_instance() || _dest_type->is_known_instance(), "result of EA not recorded"); - const TypeOopPtr* src_t = phase->type(in(ArrayCopyNode::Src))->is_oopptr(); - assert(!src_t->is_known_instance() || _src_type->is_known_instance(), "result of EA not recorded"); + assert(in(ArrayCopyNode::Src)->is_top() || !phase->type(in(ArrayCopyNode::Src))->is_oopptr()->is_known_instance() || + _src_type->is_known_instance(), "result of EA not recorded"); if (_dest_type != TypeOopPtr::BOTTOM || t_oop->is_known_instance()) { assert(_dest_type == TypeOopPtr::BOTTOM || _dest_type->is_known_instance(), "result of EA is known instance"); diff --git a/hotspot/src/share/vm/opto/c2_globals.hpp b/hotspot/src/share/vm/opto/c2_globals.hpp index 2acc7911ca4..bee4830f9b3 100644 --- a/hotspot/src/share/vm/opto/c2_globals.hpp +++ b/hotspot/src/share/vm/opto/c2_globals.hpp @@ -665,6 +665,12 @@ product(bool, UseMultiplyToLenIntrinsic, false, \ "Enables intrinsification of BigInteger.multiplyToLen()") \ \ + product(bool, UseSquareToLenIntrinsic, false, \ + "Enables intrinsification of BigInteger.squareToLen()") \ + \ + product(bool, UseMulAddIntrinsic, false, \ + "Enables intrinsification of BigInteger.mulAdd()") \ + \ product(bool, UseTypeSpeculation, true, \ "Speculatively propagate types from profiles") \ \ diff --git a/hotspot/src/share/vm/opto/callnode.cpp b/hotspot/src/share/vm/opto/callnode.cpp index 36927498fff..7a4eeb0939a 100644 --- a/hotspot/src/share/vm/opto/callnode.cpp +++ b/hotspot/src/share/vm/opto/callnode.cpp @@ -1946,7 +1946,7 @@ bool CallLeafNode::may_modify(const TypeOopPtr *t_oop, PhaseTransform *phase) { } } } - if (may_modify_arraycopy_helper(phase->type(dest)->is_oopptr(), t_oop, phase)) { + if (!dest->is_top() && may_modify_arraycopy_helper(phase->type(dest)->is_oopptr(), t_oop, phase)) { return true; } return false; diff --git a/hotspot/src/share/vm/opto/escape.cpp b/hotspot/src/share/vm/opto/escape.cpp index 67b49117aaf..9496776a5c6 100644 --- a/hotspot/src/share/vm/opto/escape.cpp +++ b/hotspot/src/share/vm/opto/escape.cpp @@ -972,7 +972,9 @@ void ConnectionGraph::process_call_arguments(CallNode *call) { strcmp(call->as_CallLeaf()->_name, "sha256_implCompressMB") == 0 || strcmp(call->as_CallLeaf()->_name, "sha512_implCompress") == 0 || strcmp(call->as_CallLeaf()->_name, "sha512_implCompressMB") == 0 || - strcmp(call->as_CallLeaf()->_name, "multiplyToLen") == 0) + strcmp(call->as_CallLeaf()->_name, "multiplyToLen") == 0 || + strcmp(call->as_CallLeaf()->_name, "squareToLen") == 0 || + strcmp(call->as_CallLeaf()->_name, "mulAdd") == 0) ))) { call->dump(); fatal(err_msg_res("EA unexpected CallLeaf %s", call->as_CallLeaf()->_name)); diff --git a/hotspot/src/share/vm/opto/graphKit.cpp b/hotspot/src/share/vm/opto/graphKit.cpp index b52f90c4d34..e8ff735a150 100644 --- a/hotspot/src/share/vm/opto/graphKit.cpp +++ b/hotspot/src/share/vm/opto/graphKit.cpp @@ -1457,18 +1457,18 @@ void GraphKit::set_all_memory_call(Node* call, bool separate_io_proj) { // factory methods in "int adr_idx" Node* GraphKit::make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, int adr_idx, - MemNode::MemOrd mo, bool require_atomic_access) { + MemNode::MemOrd mo, LoadNode::ControlDependency control_dependency, bool require_atomic_access) { assert(adr_idx != Compile::AliasIdxTop, "use other make_load factory" ); const TypePtr* adr_type = NULL; // debug-mode-only argument debug_only(adr_type = C->get_adr_type(adr_idx)); Node* mem = memory(adr_idx); Node* ld; if (require_atomic_access && bt == T_LONG) { - ld = LoadLNode::make_atomic(ctl, mem, adr, adr_type, t, mo); + ld = LoadLNode::make_atomic(ctl, mem, adr, adr_type, t, mo, control_dependency); } else if (require_atomic_access && bt == T_DOUBLE) { - ld = LoadDNode::make_atomic(ctl, mem, adr, adr_type, t, mo); + ld = LoadDNode::make_atomic(ctl, mem, adr, adr_type, t, mo, control_dependency); } else { - ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt, mo); + ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt, mo, control_dependency); } ld = _gvn.transform(ld); if ((bt == T_OBJECT) && C->do_escape_analysis() || C->eliminate_boxing()) { diff --git a/hotspot/src/share/vm/opto/graphKit.hpp b/hotspot/src/share/vm/opto/graphKit.hpp index ce0178d6a5a..fbc34e1093e 100644 --- a/hotspot/src/share/vm/opto/graphKit.hpp +++ b/hotspot/src/share/vm/opto/graphKit.hpp @@ -512,21 +512,24 @@ class GraphKit : public Phase { // adapted the `do_put_xxx' and `do_get_xxx' procedures for the case // of volatile fields. Node* make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, - MemNode::MemOrd mo, bool require_atomic_access = false) { + MemNode::MemOrd mo, LoadNode::ControlDependency control_dependency = LoadNode::DependsOnlyOnTest, + bool require_atomic_access = false) { // This version computes alias_index from bottom_type return make_load(ctl, adr, t, bt, adr->bottom_type()->is_ptr(), - mo, require_atomic_access); + mo, control_dependency, require_atomic_access); } Node* make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, const TypePtr* adr_type, - MemNode::MemOrd mo, bool require_atomic_access = false) { + MemNode::MemOrd mo, LoadNode::ControlDependency control_dependency = LoadNode::DependsOnlyOnTest, + bool require_atomic_access = false) { // This version computes alias_index from an address type assert(adr_type != NULL, "use other make_load factory"); return make_load(ctl, adr, t, bt, C->get_alias_index(adr_type), - mo, require_atomic_access); + mo, control_dependency, require_atomic_access); } // This is the base version which is given an alias index. Node* make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, int adr_idx, - MemNode::MemOrd mo, bool require_atomic_access = false); + MemNode::MemOrd mo, LoadNode::ControlDependency control_dependency = LoadNode::DependsOnlyOnTest, + bool require_atomic_access = false); // Create & transform a StoreNode and store the effect into the // parser's memory state. diff --git a/hotspot/src/share/vm/opto/ifnode.cpp b/hotspot/src/share/vm/opto/ifnode.cpp index aad3039d0ef..bc107f4b7d5 100644 --- a/hotspot/src/share/vm/opto/ifnode.cpp +++ b/hotspot/src/share/vm/opto/ifnode.cpp @@ -817,19 +817,78 @@ bool IfNode::fold_compares_helper(ProjNode* proj, ProjNode* success, ProjNode* f BoolTest::mask hi_test = this_bool->_test._test; BoolTest::mask cond = hi_test; + // convert: + // + // dom_bool = x {<,<=,>,>=} a + // / \ + // proj = {True,False} / \ otherproj = {False,True} + // / + // this_bool = x {<,<=} b + // / \ + // fail = {True,False} / \ success = {False,True} + // / + // + // (Second test guaranteed canonicalized, first one may not have + // been canonicalized yet) + // + // into: + // + // cond = (x - lo) {u,>=u} adjusted_lim + // / \ + // fail / \ success + // / + // + // Figure out which of the two tests sets the upper bound and which // sets the lower bound if any. + Node* adjusted_lim = NULL; if (hi_type->_lo > lo_type->_hi && hi_type->_hi == max_jint && lo_type->_lo == min_jint) { - assert((dom_bool->_test.is_less() && !proj->_con) || (dom_bool->_test.is_greater() && proj->_con), "incorrect test"); // this test was canonicalized assert(this_bool->_test.is_less() && fail->_con, "incorrect test"); + // this_bool = < + // dom_bool = >= (proj = True) or dom_bool = < (proj = False) + // x in [a, b[ on the fail (= True) projection, b > a-1 (because of hi_type->_lo > lo_type->_hi test above): + // lo = a, hi = b, adjusted_lim = b-a, cond = (proj = True) or dom_bool = <= (proj = False) + // x in ]a, b[ on the fail (= True) projection, b > a: + // lo = a+1, hi = b, adjusted_lim = b-a-1, cond = = (proj = True) or dom_bool = < (proj = False) + // x in [a, b] on the fail (= True) projection, b+1 > a-1: + // lo = a, hi = b, adjusted_lim = b-a, cond = <=u + // dom_bool = > (proj = True) or dom_bool = <= (proj = False) + // x in ]a, b] on the fail (= True) projection b+1 > a: + // lo = a+1, hi = b, adjusted_lim = b-a, cond = transform(new SubINode(hi, lo)); + cond = BoolTest::lt; + } lo = igvn->transform(new AddINode(lo, igvn->intcon(1))); } } else if (lo_type->_lo > hi_type->_hi && lo_type->_hi == max_jint && hi_type->_lo == min_jint) { + + // this_bool = < + // dom_bool = < (proj = True) or dom_bool = >= (proj = False) + // x in [b, a[ on the fail (= False) projection, a > b-1 (because of lo_type->_lo > hi_type->_hi above): + // lo = b, hi = a, adjusted_lim = a-b, cond = >=u + // dom_bool = <= (proj = True) or dom_bool = > (proj = False) + // x in [b, a] on the fail (= False) projection, a+1 > b-1: + // lo = b, hi = a, adjusted_lim = a-b, cond = >u + // this_bool = <= + // dom_bool = < (proj = True) or dom_bool = >= (proj = False) + // x in ]b, a[ on the fail (= False) projection, a > b: + // lo = b+1, hi = a, adjusted_lim = a-b-1, cond = >=u + // dom_bool = <= (proj = True) or dom_bool = > (proj = False) + // x in ]b, a] on the fail (= False) projection, a+1 > b: + // lo = b+1, hi = a, adjusted_lim = a-b, cond = >=u + // lo = b+1, hi = a, adjusted_lim = a-b-1, cond = >u doesn't work because a = b is possible, then hi-lo = -1 + swap(lo, hi); swap(lo_type, hi_type); swap(lo_test, hi_test); @@ -842,6 +901,10 @@ bool IfNode::fold_compares_helper(ProjNode* proj, ProjNode* success, ProjNode* f cond = (hi_test == BoolTest::le || hi_test == BoolTest::gt) ? BoolTest::gt : BoolTest::ge; if (lo_test == BoolTest::le) { + if (cond == BoolTest::gt) { + adjusted_lim = igvn->transform(new SubINode(hi, lo)); + cond = BoolTest::ge; + } lo = igvn->transform(new AddINode(lo, igvn->intcon(1))); } @@ -860,7 +923,6 @@ bool IfNode::fold_compares_helper(ProjNode* proj, ProjNode* success, ProjNode* f } } } - lo = NULL; hi = NULL; } @@ -868,12 +930,13 @@ bool IfNode::fold_compares_helper(ProjNode* proj, ProjNode* success, ProjNode* f if (lo && hi) { // Merge the two compares into a single unsigned compare by building (CmpU (n - lo) (hi - lo)) Node* adjusted_val = igvn->transform(new SubINode(n, lo)); - Node* adjusted_lim = igvn->transform(new SubINode(hi, lo)); + if (adjusted_lim == NULL) { + adjusted_lim = igvn->transform(new SubINode(hi, lo)); + } Node* newcmp = igvn->transform(new CmpUNode(adjusted_val, adjusted_lim)); Node* newbool = igvn->transform(new BoolNode(newcmp, cond)); - igvn->is_IterGVN()->replace_input_of(dom_iff, 1, igvn->intcon(proj->_con)); - igvn->hash_delete(this); + igvn->replace_input_of(dom_iff, 1, igvn->intcon(proj->_con)); set_req(1, newbool); return true; diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index 62ae310cc52..83a1673aa74 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -291,6 +291,8 @@ class LibraryCallKit : public GraphKit { bool inline_updateBytesCRC32(); bool inline_updateByteBufferCRC32(); bool inline_multiplyToLen(); + bool inline_squareToLen(); + bool inline_mulAdd(); bool inline_profileBoolean(); bool inline_isCompileConstant(); @@ -494,6 +496,14 @@ CallGenerator* Compile::make_vm_intrinsic(ciMethod* m, bool is_virtual) { if (!UseMultiplyToLenIntrinsic) return NULL; break; + case vmIntrinsics::_squareToLen: + if (!UseSquareToLenIntrinsic) return NULL; + break; + + case vmIntrinsics::_mulAdd: + if (!UseMulAddIntrinsic) return NULL; + break; + case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt: case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt: if (!UseAESIntrinsics) return NULL; @@ -913,6 +923,12 @@ bool LibraryCallKit::try_to_inline(int predicate) { case vmIntrinsics::_multiplyToLen: return inline_multiplyToLen(); + case vmIntrinsics::_squareToLen: + return inline_squareToLen(); + + case vmIntrinsics::_mulAdd: + return inline_mulAdd(); + case vmIntrinsics::_encodeISOArray: return inline_encodeISOArray(); @@ -2631,7 +2647,9 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas if (!is_store) { MemNode::MemOrd mo = is_volatile ? MemNode::acquire : MemNode::unordered; - Node* p = make_load(control(), adr, value_type, type, adr_type, mo, is_volatile); + // To be valid, unsafe loads may depend on other conditions than + // the one that guards them: pin the Load node + Node* p = make_load(control(), adr, value_type, type, adr_type, mo, LoadNode::Pinned, is_volatile); // load value switch (type) { case T_BOOLEAN: @@ -5304,6 +5322,100 @@ bool LibraryCallKit::inline_multiplyToLen() { return true; } +//-------------inline_squareToLen------------------------------------ +bool LibraryCallKit::inline_squareToLen() { + assert(UseSquareToLenIntrinsic, "not implementated on this platform"); + + address stubAddr = StubRoutines::squareToLen(); + if (stubAddr == NULL) { + return false; // Intrinsic's stub is not implemented on this platform + } + const char* stubName = "squareToLen"; + + assert(callee()->signature()->size() == 4, "implSquareToLen has 4 parameters"); + + Node* x = argument(0); + Node* len = argument(1); + Node* z = argument(2); + Node* zlen = argument(3); + + const Type* x_type = x->Value(&_gvn); + const Type* z_type = z->Value(&_gvn); + const TypeAryPtr* top_x = x_type->isa_aryptr(); + const TypeAryPtr* top_z = z_type->isa_aryptr(); + if (top_x == NULL || top_x->klass() == NULL || + top_z == NULL || top_z->klass() == NULL) { + // failed array check + return false; + } + + BasicType x_elem = x_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type(); + BasicType z_elem = z_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type(); + if (x_elem != T_INT || z_elem != T_INT) { + return false; + } + + + Node* x_start = array_element_address(x, intcon(0), x_elem); + Node* z_start = array_element_address(z, intcon(0), z_elem); + + Node* call = make_runtime_call(RC_LEAF|RC_NO_FP, + OptoRuntime::squareToLen_Type(), + stubAddr, stubName, TypePtr::BOTTOM, + x_start, len, z_start, zlen); + + set_result(z); + return true; +} + +//-------------inline_mulAdd------------------------------------------ +bool LibraryCallKit::inline_mulAdd() { + assert(UseMulAddIntrinsic, "not implementated on this platform"); + + address stubAddr = StubRoutines::mulAdd(); + if (stubAddr == NULL) { + return false; // Intrinsic's stub is not implemented on this platform + } + const char* stubName = "mulAdd"; + + assert(callee()->signature()->size() == 5, "mulAdd has 5 parameters"); + + Node* out = argument(0); + Node* in = argument(1); + Node* offset = argument(2); + Node* len = argument(3); + Node* k = argument(4); + + const Type* out_type = out->Value(&_gvn); + const Type* in_type = in->Value(&_gvn); + const TypeAryPtr* top_out = out_type->isa_aryptr(); + const TypeAryPtr* top_in = in_type->isa_aryptr(); + if (top_out == NULL || top_out->klass() == NULL || + top_in == NULL || top_in->klass() == NULL) { + // failed array check + return false; + } + + BasicType out_elem = out_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type(); + BasicType in_elem = in_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type(); + if (out_elem != T_INT || in_elem != T_INT) { + return false; + } + + Node* outlen = load_array_length(out); + Node* new_offset = _gvn.transform(new SubINode(outlen, offset)); + Node* out_start = array_element_address(out, intcon(0), out_elem); + Node* in_start = array_element_address(in, intcon(0), in_elem); + + Node* call = make_runtime_call(RC_LEAF|RC_NO_FP, + OptoRuntime::mulAdd_Type(), + stubAddr, stubName, TypePtr::BOTTOM, + out_start,in_start, new_offset, len, k); + Node* result = _gvn.transform(new ProjNode(call, TypeFunc::Parms)); + set_result(result); + return true; +} + /** * Calculate CRC32 for byte. @@ -5488,7 +5600,7 @@ Node * LibraryCallKit::load_field_from_object(Node * fromObj, const char * field } // Build the load. MemNode::MemOrd mo = is_vol ? MemNode::acquire : MemNode::unordered; - Node* loadedField = make_load(NULL, adr, type, bt, adr_type, mo, is_vol); + Node* loadedField = make_load(NULL, adr, type, bt, adr_type, mo, LoadNode::DependsOnlyOnTest, is_vol); // If reference is volatile, prevent following memory ops from // floating up past the volatile read. Also prevents commoning // another volatile read. diff --git a/hotspot/src/share/vm/opto/loopPredicate.cpp b/hotspot/src/share/vm/opto/loopPredicate.cpp index d5157b79afb..7d25d965d91 100644 --- a/hotspot/src/share/vm/opto/loopPredicate.cpp +++ b/hotspot/src/share/vm/opto/loopPredicate.cpp @@ -437,7 +437,13 @@ class Invariance : public StackObj { } } if (all_inputs_invariant) { - _invariant.set(n->_idx); // I am a invariant too + // If n's control is a predicate that was moved out of the + // loop, it was marked invariant but n is only invariant if + // it depends only on that test. Otherwise, unless that test + // is out of the loop, it's not invariant. + if (n->is_CFG() || n->depends_only_on_test() || n->in(0) == NULL || !_phase->is_member(_lpt, n->in(0))) { + _invariant.set(n->_idx); // I am a invariant too + } } } else { // process next input _stack.set_index(idx + 1); diff --git a/hotspot/src/share/vm/opto/loopTransform.cpp b/hotspot/src/share/vm/opto/loopTransform.cpp index a73391a38a8..a0b48ea9aea 100644 --- a/hotspot/src/share/vm/opto/loopTransform.cpp +++ b/hotspot/src/share/vm/opto/loopTransform.cpp @@ -475,7 +475,7 @@ void PhaseIdealLoop::do_peeling( IdealLoopTree *loop, Node_List &old_new ) { C->set_major_progress(); // Peeling a 'main' loop in a pre/main/post situation obfuscates the - // 'pre' loop from the main and the 'pre' can no longer have it's + // 'pre' loop from the main and the 'pre' can no longer have its // iterations adjusted. Therefore, we need to declare this loop as // no longer a 'main' loop; it will need new pre and post loops before // we can do further RCE. @@ -1582,13 +1582,36 @@ void PhaseIdealLoop::mark_reductions(IdealLoopTree *loop) { if (opc != ReductionNode::opcode(opc, def_node->bottom_type()->basic_type())) { if (!def_node->is_reduction()) { // Not marked yet // To be a reduction, the arithmetic node must have the phi as input and provide a def to it + bool ok = false; for (unsigned j = 1; j < def_node->req(); j++) { Node* in = def_node->in(j); if (in == phi) { - def_node->add_flag(Node::Flag_is_reduction); + ok = true; break; } } + + // do nothing if we did not match the initial criteria + if (ok == false) { + continue; + } + + // The result of the reduction must not be used in the loop + for (DUIterator_Fast imax, i = def_node->fast_outs(imax); i < imax && ok; i++) { + Node* u = def_node->fast_out(i); + if (has_ctrl(u) && !loop->is_member(get_loop(get_ctrl(u)))) { + continue; + } + if (u == phi) { + continue; + } + ok = false; + } + + // iff the uses conform + if (ok) { + def_node->add_flag(Node::Flag_is_reduction); + } } } } @@ -1888,10 +1911,13 @@ void PhaseIdealLoop::do_range_check( IdealLoopTree *loop, Node_List &old_new ) { return; assert(opqzm->in(1) == main_limit, "do not understand situation"); - // Find the pre-loop limit; we will expand it's iterations to + // Find the pre-loop limit; we will expand its iterations to // not ever trip low tests. Node *p_f = iffm->in(0); - assert(p_f->Opcode() == Op_IfFalse, ""); + // pre loop may have been optimized out + if (p_f->Opcode() != Op_IfFalse) { + return; + } CountedLoopEndNode *pre_end = p_f->in(0)->as_CountedLoopEnd(); assert(pre_end->loopnode()->is_pre_loop(), ""); Node *pre_opaq1 = pre_end->limit(); @@ -2192,6 +2218,56 @@ void IdealLoopTree::adjust_loop_exit_prob( PhaseIdealLoop *phase ) { } } +#ifdef ASSERT +static CountedLoopNode* locate_pre_from_main(CountedLoopNode *cl) { + Node *ctrl = cl->in(LoopNode::EntryControl); + assert(ctrl->Opcode() == Op_IfTrue || ctrl->Opcode() == Op_IfFalse, ""); + Node *iffm = ctrl->in(0); + assert(iffm->Opcode() == Op_If, ""); + Node *p_f = iffm->in(0); + assert(p_f->Opcode() == Op_IfFalse, ""); + CountedLoopEndNode *pre_end = p_f->in(0)->as_CountedLoopEnd(); + assert(pre_end->loopnode()->is_pre_loop(), ""); + return pre_end->loopnode(); +} +#endif + +// Remove the main and post loops and make the pre loop execute all +// iterations. Useful when the pre loop is found empty. +void IdealLoopTree::remove_main_post_loops(CountedLoopNode *cl, PhaseIdealLoop *phase) { + CountedLoopEndNode* pre_end = cl->loopexit(); + Node* pre_cmp = pre_end->cmp_node(); + if (pre_cmp->in(2)->Opcode() != Op_Opaque1) { + // Only safe to remove the main loop if the compiler optimized it + // out based on an unknown number of iterations + return; + } + + // Can we find the main loop? + if (_next == NULL) { + return; + } + + Node* next_head = _next->_head; + if (!next_head->is_CountedLoop()) { + return; + } + + CountedLoopNode* main_head = next_head->as_CountedLoop(); + if (!main_head->is_main_loop()) { + return; + } + + assert(locate_pre_from_main(main_head) == cl, "bad main loop"); + Node* main_iff = main_head->in(LoopNode::EntryControl)->in(0); + + // Remove the Opaque1Node of the pre loop and make it execute all iterations + phase->_igvn.replace_input_of(pre_cmp, 2, pre_cmp->in(2)->in(2)); + // Remove the Opaque1Node of the main loop so it can be optimized out + Node* main_cmp = main_iff->in(1)->in(1); + assert(main_cmp->in(2)->Opcode() == Op_Opaque1, "main loop has no opaque node?"); + phase->_igvn.replace_input_of(main_cmp, 2, main_cmp->in(2)->in(1)); +} //------------------------------policy_do_remove_empty_loop-------------------- // Micro-benchmark spamming. Policy is to always remove empty loops. @@ -2210,6 +2286,12 @@ bool IdealLoopTree::policy_do_remove_empty_loop( PhaseIdealLoop *phase ) { if (!phase->is_member(this, phase->get_ctrl(cl->loopexit()->in(CountedLoopEndNode::TestValue)))) return false; // Infinite loop + if (cl->is_pre_loop()) { + // If the loop we are removing is a pre-loop then the main and + // post loop can be removed as well + remove_main_post_loops(cl, phase); + } + #ifdef ASSERT // Ensure only one phi which is the iv. Node* iv = NULL; diff --git a/hotspot/src/share/vm/opto/loopnode.hpp b/hotspot/src/share/vm/opto/loopnode.hpp index a2063232763..3f0cb512a08 100644 --- a/hotspot/src/share/vm/opto/loopnode.hpp +++ b/hotspot/src/share/vm/opto/loopnode.hpp @@ -485,6 +485,8 @@ public: bool is_inner() { return is_loop() && _child == NULL; } bool is_counted() { return is_loop() && _head != NULL && _head->is_CountedLoop(); } + void remove_main_post_loops(CountedLoopNode *cl, PhaseIdealLoop *phase); + #ifndef PRODUCT void dump_head( ) const; // Dump loop head only void dump() const; // Dump this loop recursively diff --git a/hotspot/src/share/vm/opto/loopopts.cpp b/hotspot/src/share/vm/opto/loopopts.cpp index ae221593d88..cee45df287e 100644 --- a/hotspot/src/share/vm/opto/loopopts.cpp +++ b/hotspot/src/share/vm/opto/loopopts.cpp @@ -718,7 +718,7 @@ Node *PhaseIdealLoop::split_if_with_blocks_pre( Node *n ) { } // Use same limit as split_if_with_blocks_post - if( C->unique() > 35000 ) return n; // Method too big + if( C->live_nodes() > 35000 ) return n; // Method too big // Split 'n' through the merge point if it is profitable Node *phi = split_thru_phi( n, n_blk, policy ); @@ -802,7 +802,7 @@ void PhaseIdealLoop::split_if_with_blocks_post( Node *n ) { // Cloning Cmp through Phi's involves the split-if transform. // FastLock is not used by an If if( n->is_Cmp() && !n->is_FastLock() ) { - if( C->unique() > 35000 ) return; // Method too big + if( C->live_nodes() > 35000 ) return; // Method too big // Do not do 'split-if' if irreducible loops are present. if( _has_irreducible_loops ) diff --git a/hotspot/src/share/vm/opto/matcher.cpp b/hotspot/src/share/vm/opto/matcher.cpp index d3dbc51c620..ee66e1aac4b 100644 --- a/hotspot/src/share/vm/opto/matcher.cpp +++ b/hotspot/src/share/vm/opto/matcher.cpp @@ -844,7 +844,7 @@ void Matcher::init_spill_mask( Node *ret ) { MachNode *spillCP = match_tree(new LoadNNode(NULL,mem,fp,atp,TypeInstPtr::BOTTOM,MemNode::unordered)); #endif MachNode *spillI = match_tree(new LoadINode(NULL,mem,fp,atp,TypeInt::INT,MemNode::unordered)); - MachNode *spillL = match_tree(new LoadLNode(NULL,mem,fp,atp,TypeLong::LONG,MemNode::unordered,false)); + MachNode *spillL = match_tree(new LoadLNode(NULL,mem,fp,atp,TypeLong::LONG,MemNode::unordered, LoadNode::DependsOnlyOnTest, false)); MachNode *spillF = match_tree(new LoadFNode(NULL,mem,fp,atp,Type::FLOAT,MemNode::unordered)); MachNode *spillD = match_tree(new LoadDNode(NULL,mem,fp,atp,Type::DOUBLE,MemNode::unordered)); MachNode *spillP = match_tree(new LoadPNode(NULL,mem,fp,atp,TypeInstPtr::BOTTOM,MemNode::unordered)); diff --git a/hotspot/src/share/vm/opto/memnode.cpp b/hotspot/src/share/vm/opto/memnode.cpp index c2a03c96b31..09438ea03f8 100644 --- a/hotspot/src/share/vm/opto/memnode.cpp +++ b/hotspot/src/share/vm/opto/memnode.cpp @@ -784,6 +784,9 @@ void LoadNode::dump_spec(outputStream *st) const { // standard dump does this in Verbose and WizardMode st->print(" #"); _type->dump_on(st); } + if (!_depends_only_on_test) { + st->print(" (does not depend only on test)"); + } } #endif @@ -800,7 +803,7 @@ bool LoadNode::is_immutable_value(Node* adr) { //----------------------------LoadNode::make----------------------------------- // Polymorphic factory method: -Node *LoadNode::make(PhaseGVN& gvn, Node *ctl, Node *mem, Node *adr, const TypePtr* adr_type, const Type *rt, BasicType bt, MemOrd mo) { +Node *LoadNode::make(PhaseGVN& gvn, Node *ctl, Node *mem, Node *adr, const TypePtr* adr_type, const Type *rt, BasicType bt, MemOrd mo, ControlDependency control_dependency) { Compile* C = gvn.C; // sanity check the alias category against the created node type @@ -816,39 +819,39 @@ Node *LoadNode::make(PhaseGVN& gvn, Node *ctl, Node *mem, Node *adr, const TypeP rt->isa_oopptr() || is_immutable_value(adr), "raw memory operations should have control edge"); switch (bt) { - case T_BOOLEAN: return new LoadUBNode(ctl, mem, adr, adr_type, rt->is_int(), mo); - case T_BYTE: return new LoadBNode (ctl, mem, adr, adr_type, rt->is_int(), mo); - case T_INT: return new LoadINode (ctl, mem, adr, adr_type, rt->is_int(), mo); - case T_CHAR: return new LoadUSNode(ctl, mem, adr, adr_type, rt->is_int(), mo); - case T_SHORT: return new LoadSNode (ctl, mem, adr, adr_type, rt->is_int(), mo); - case T_LONG: return new LoadLNode (ctl, mem, adr, adr_type, rt->is_long(), mo); - case T_FLOAT: return new LoadFNode (ctl, mem, adr, adr_type, rt, mo); - case T_DOUBLE: return new LoadDNode (ctl, mem, adr, adr_type, rt, mo); - case T_ADDRESS: return new LoadPNode (ctl, mem, adr, adr_type, rt->is_ptr(), mo); + case T_BOOLEAN: return new LoadUBNode(ctl, mem, adr, adr_type, rt->is_int(), mo, control_dependency); + case T_BYTE: return new LoadBNode (ctl, mem, adr, adr_type, rt->is_int(), mo, control_dependency); + case T_INT: return new LoadINode (ctl, mem, adr, adr_type, rt->is_int(), mo, control_dependency); + case T_CHAR: return new LoadUSNode(ctl, mem, adr, adr_type, rt->is_int(), mo, control_dependency); + case T_SHORT: return new LoadSNode (ctl, mem, adr, adr_type, rt->is_int(), mo, control_dependency); + case T_LONG: return new LoadLNode (ctl, mem, adr, adr_type, rt->is_long(), mo, control_dependency); + case T_FLOAT: return new LoadFNode (ctl, mem, adr, adr_type, rt, mo, control_dependency); + case T_DOUBLE: return new LoadDNode (ctl, mem, adr, adr_type, rt, mo, control_dependency); + case T_ADDRESS: return new LoadPNode (ctl, mem, adr, adr_type, rt->is_ptr(), mo, control_dependency); case T_OBJECT: #ifdef _LP64 if (adr->bottom_type()->is_ptr_to_narrowoop()) { - Node* load = gvn.transform(new LoadNNode(ctl, mem, adr, adr_type, rt->make_narrowoop(), mo)); + Node* load = gvn.transform(new LoadNNode(ctl, mem, adr, adr_type, rt->make_narrowoop(), mo, control_dependency)); return new DecodeNNode(load, load->bottom_type()->make_ptr()); } else #endif { assert(!adr->bottom_type()->is_ptr_to_narrowoop() && !adr->bottom_type()->is_ptr_to_narrowklass(), "should have got back a narrow oop"); - return new LoadPNode(ctl, mem, adr, adr_type, rt->is_oopptr(), mo); + return new LoadPNode(ctl, mem, adr, adr_type, rt->is_oopptr(), mo, control_dependency); } } ShouldNotReachHere(); return (LoadNode*)NULL; } -LoadLNode* LoadLNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo) { +LoadLNode* LoadLNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo, ControlDependency control_dependency) { bool require_atomic = true; - return new LoadLNode(ctl, mem, adr, adr_type, rt->is_long(), mo, require_atomic); + return new LoadLNode(ctl, mem, adr, adr_type, rt->is_long(), mo, control_dependency, require_atomic); } -LoadDNode* LoadDNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo) { +LoadDNode* LoadDNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo, ControlDependency control_dependency) { bool require_atomic = true; - return new LoadDNode(ctl, mem, adr, adr_type, rt, mo, require_atomic); + return new LoadDNode(ctl, mem, adr, adr_type, rt, mo, control_dependency, require_atomic); } diff --git a/hotspot/src/share/vm/opto/memnode.hpp b/hotspot/src/share/vm/opto/memnode.hpp index 814d6d410a6..8c389e16409 100644 --- a/hotspot/src/share/vm/opto/memnode.hpp +++ b/hotspot/src/share/vm/opto/memnode.hpp @@ -137,7 +137,33 @@ public: //------------------------------LoadNode--------------------------------------- // Load value; requires Memory and Address class LoadNode : public MemNode { +public: + // Some loads (from unsafe) should be pinned: they don't depend only + // on the dominating test. The boolean field _depends_only_on_test + // below records whether that node depends only on the dominating + // test. + // Methods used to build LoadNodes pass an argument of type enum + // ControlDependency instead of a boolean because those methods + // typically have multiple boolean parameters with default values: + // passing the wrong boolean to one of these parameters by mistake + // goes easily unnoticed. Using an enum, the compiler can check that + // the type of a value and the type of the parameter match. + enum ControlDependency { + Pinned, + DependsOnlyOnTest + }; private: + // LoadNode::hash() doesn't take the _depends_only_on_test field + // into account: If the graph already has a non-pinned LoadNode and + // we add a pinned LoadNode with the same inputs, it's safe for GVN + // to replace the pinned LoadNode with the non-pinned LoadNode, + // otherwise it wouldn't be safe to have a non pinned LoadNode with + // those inputs in the first place. If the graph already has a + // pinned LoadNode and we add a non pinned LoadNode with the same + // inputs, it's safe (but suboptimal) for GVN to replace the + // non-pinned LoadNode by the pinned LoadNode. + bool _depends_only_on_test; + // On platforms with weak memory ordering (e.g., PPC, Ia64) we distinguish // loads that can be reordered, and such requiring acquire semantics to // adhere to the Java specification. The required behaviour is stored in @@ -154,8 +180,8 @@ protected: virtual Node* find_previous_arraycopy(PhaseTransform* phase, Node* ld_alloc, Node*& mem, bool can_see_stored_value) const; public: - LoadNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *rt, MemOrd mo) - : MemNode(c,mem,adr,at), _type(rt), _mo(mo) { + LoadNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *rt, MemOrd mo, ControlDependency control_dependency) + : MemNode(c,mem,adr,at), _type(rt), _mo(mo), _depends_only_on_test(control_dependency == DependsOnlyOnTest) { init_class_id(Class_Load); } inline bool is_unordered() const { return !is_acquire(); } @@ -166,7 +192,8 @@ public: // Polymorphic factory method: static Node* make(PhaseGVN& gvn, Node *c, Node *mem, Node *adr, - const TypePtr* at, const Type *rt, BasicType bt, MemOrd mo); + const TypePtr* at, const Type *rt, BasicType bt, + MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest); virtual uint hash() const; // Check the type @@ -234,16 +261,15 @@ protected: // which produce results (new raw memory state) inside of loops preventing all // manner of other optimizations). Basically, it's ugly but so is the alternative. // See comment in macro.cpp, around line 125 expand_allocate_common(). - virtual bool depends_only_on_test() const { return adr_type() != TypeRawPtr::BOTTOM; } - + virtual bool depends_only_on_test() const { return adr_type() != TypeRawPtr::BOTTOM && _depends_only_on_test; } }; //------------------------------LoadBNode-------------------------------------- // Load a byte (8bits signed) from memory class LoadBNode : public LoadNode { public: - LoadBNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo) - : LoadNode(c, mem, adr, at, ti, mo) {} + LoadBNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest) + : LoadNode(c, mem, adr, at, ti, mo, control_dependency) {} virtual int Opcode() const; virtual uint ideal_reg() const { return Op_RegI; } virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); @@ -256,8 +282,8 @@ public: // Load a unsigned byte (8bits unsigned) from memory class LoadUBNode : public LoadNode { public: - LoadUBNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeInt* ti, MemOrd mo) - : LoadNode(c, mem, adr, at, ti, mo) {} + LoadUBNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeInt* ti, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest) + : LoadNode(c, mem, adr, at, ti, mo, control_dependency) {} virtual int Opcode() const; virtual uint ideal_reg() const { return Op_RegI; } virtual Node* Ideal(PhaseGVN *phase, bool can_reshape); @@ -270,8 +296,8 @@ public: // Load an unsigned short/char (16bits unsigned) from memory class LoadUSNode : public LoadNode { public: - LoadUSNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo) - : LoadNode(c, mem, adr, at, ti, mo) {} + LoadUSNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest) + : LoadNode(c, mem, adr, at, ti, mo, control_dependency) {} virtual int Opcode() const; virtual uint ideal_reg() const { return Op_RegI; } virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); @@ -284,8 +310,8 @@ public: // Load a short (16bits signed) from memory class LoadSNode : public LoadNode { public: - LoadSNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo) - : LoadNode(c, mem, adr, at, ti, mo) {} + LoadSNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest) + : LoadNode(c, mem, adr, at, ti, mo, control_dependency) {} virtual int Opcode() const; virtual uint ideal_reg() const { return Op_RegI; } virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); @@ -298,8 +324,8 @@ public: // Load an integer from memory class LoadINode : public LoadNode { public: - LoadINode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo) - : LoadNode(c, mem, adr, at, ti, mo) {} + LoadINode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest) + : LoadNode(c, mem, adr, at, ti, mo, control_dependency) {} virtual int Opcode() const; virtual uint ideal_reg() const { return Op_RegI; } virtual int store_Opcode() const { return Op_StoreI; } @@ -331,15 +357,15 @@ class LoadLNode : public LoadNode { public: LoadLNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeLong *tl, - MemOrd mo, bool require_atomic_access = false) - : LoadNode(c, mem, adr, at, tl, mo), _require_atomic_access(require_atomic_access) {} + MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest, bool require_atomic_access = false) + : LoadNode(c, mem, adr, at, tl, mo, control_dependency), _require_atomic_access(require_atomic_access) {} virtual int Opcode() const; virtual uint ideal_reg() const { return Op_RegL; } virtual int store_Opcode() const { return Op_StoreL; } virtual BasicType memory_type() const { return T_LONG; } bool require_atomic_access() const { return _require_atomic_access; } static LoadLNode* make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, - const Type* rt, MemOrd mo); + const Type* rt, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest); #ifndef PRODUCT virtual void dump_spec(outputStream *st) const { LoadNode::dump_spec(st); @@ -352,8 +378,8 @@ public: // Load a long from unaligned memory class LoadL_unalignedNode : public LoadLNode { public: - LoadL_unalignedNode(Node *c, Node *mem, Node *adr, const TypePtr* at, MemOrd mo) - : LoadLNode(c, mem, adr, at, TypeLong::LONG, mo) {} + LoadL_unalignedNode(Node *c, Node *mem, Node *adr, const TypePtr* at, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest) + : LoadLNode(c, mem, adr, at, TypeLong::LONG, mo, control_dependency) {} virtual int Opcode() const; }; @@ -361,8 +387,8 @@ public: // Load a float (64 bits) from memory class LoadFNode : public LoadNode { public: - LoadFNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *t, MemOrd mo) - : LoadNode(c, mem, adr, at, t, mo) {} + LoadFNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *t, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest) + : LoadNode(c, mem, adr, at, t, mo, control_dependency) {} virtual int Opcode() const; virtual uint ideal_reg() const { return Op_RegF; } virtual int store_Opcode() const { return Op_StoreF; } @@ -382,15 +408,15 @@ class LoadDNode : public LoadNode { public: LoadDNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *t, - MemOrd mo, bool require_atomic_access = false) - : LoadNode(c, mem, adr, at, t, mo), _require_atomic_access(require_atomic_access) {} + MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest, bool require_atomic_access = false) + : LoadNode(c, mem, adr, at, t, mo, control_dependency), _require_atomic_access(require_atomic_access) {} virtual int Opcode() const; virtual uint ideal_reg() const { return Op_RegD; } virtual int store_Opcode() const { return Op_StoreD; } virtual BasicType memory_type() const { return T_DOUBLE; } bool require_atomic_access() const { return _require_atomic_access; } static LoadDNode* make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, - const Type* rt, MemOrd mo); + const Type* rt, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest); #ifndef PRODUCT virtual void dump_spec(outputStream *st) const { LoadNode::dump_spec(st); @@ -403,8 +429,8 @@ public: // Load a double from unaligned memory class LoadD_unalignedNode : public LoadDNode { public: - LoadD_unalignedNode(Node *c, Node *mem, Node *adr, const TypePtr* at, MemOrd mo) - : LoadDNode(c, mem, adr, at, Type::DOUBLE, mo) {} + LoadD_unalignedNode(Node *c, Node *mem, Node *adr, const TypePtr* at, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest) + : LoadDNode(c, mem, adr, at, Type::DOUBLE, mo, control_dependency) {} virtual int Opcode() const; }; @@ -412,8 +438,8 @@ public: // Load a pointer from memory (either object or array) class LoadPNode : public LoadNode { public: - LoadPNode(Node *c, Node *mem, Node *adr, const TypePtr *at, const TypePtr* t, MemOrd mo) - : LoadNode(c, mem, adr, at, t, mo) {} + LoadPNode(Node *c, Node *mem, Node *adr, const TypePtr *at, const TypePtr* t, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest) + : LoadNode(c, mem, adr, at, t, mo, control_dependency) {} virtual int Opcode() const; virtual uint ideal_reg() const { return Op_RegP; } virtual int store_Opcode() const { return Op_StoreP; } @@ -425,8 +451,8 @@ public: // Load a narrow oop from memory (either object or array) class LoadNNode : public LoadNode { public: - LoadNNode(Node *c, Node *mem, Node *adr, const TypePtr *at, const Type* t, MemOrd mo) - : LoadNode(c, mem, adr, at, t, mo) {} + LoadNNode(Node *c, Node *mem, Node *adr, const TypePtr *at, const Type* t, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest) + : LoadNode(c, mem, adr, at, t, mo, control_dependency) {} virtual int Opcode() const; virtual uint ideal_reg() const { return Op_RegN; } virtual int store_Opcode() const { return Op_StoreN; } diff --git a/hotspot/src/share/vm/opto/parse3.cpp b/hotspot/src/share/vm/opto/parse3.cpp index 0f07506774e..f1cc539dc72 100644 --- a/hotspot/src/share/vm/opto/parse3.cpp +++ b/hotspot/src/share/vm/opto/parse3.cpp @@ -235,7 +235,7 @@ void Parse::do_get_xxx(Node* obj, ciField* field, bool is_field) { // MemNode::MemOrd mo = is_vol ? MemNode::acquire : MemNode::unordered; bool needs_atomic_access = is_vol || AlwaysAtomicAccesses; - Node* ld = make_load(NULL, adr, type, bt, adr_type, mo, needs_atomic_access); + Node* ld = make_load(NULL, adr, type, bt, adr_type, mo, LoadNode::DependsOnlyOnTest, needs_atomic_access); // Adjust Java stack if (type2size[bt] == 1) diff --git a/hotspot/src/share/vm/opto/phaseX.cpp b/hotspot/src/share/vm/opto/phaseX.cpp index 861a84f4d20..1426a31c9c5 100644 --- a/hotspot/src/share/vm/opto/phaseX.cpp +++ b/hotspot/src/share/vm/opto/phaseX.cpp @@ -1573,11 +1573,12 @@ void PhaseCCP::analyze() { set_type(n, t); for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { Node* m = n->fast_out(i); // Get user - if( m->is_Region() ) { // New path to Region? Must recheck Phis too + if (m->is_Region()) { // New path to Region? Must recheck Phis too for (DUIterator_Fast i2max, i2 = m->fast_outs(i2max); i2 < i2max; i2++) { Node* p = m->fast_out(i2); // Propagate changes to uses - if( p->bottom_type() != type(p) ) // If not already bottomed out + if (p->bottom_type() != type(p)) { // If not already bottomed out worklist.push(p); // Propagate change to user + } } } // If we changed the receiver type to a call, we need to revisit @@ -1587,12 +1588,31 @@ void PhaseCCP::analyze() { if (m->is_Call()) { for (DUIterator_Fast i2max, i2 = m->fast_outs(i2max); i2 < i2max; i2++) { Node* p = m->fast_out(i2); // Propagate changes to uses - if (p->is_Proj() && p->as_Proj()->_con == TypeFunc::Control && p->outcnt() == 1) + if (p->is_Proj() && p->as_Proj()->_con == TypeFunc::Control && p->outcnt() == 1) { worklist.push(p->unique_out()); + } } } - if( m->bottom_type() != type(m) ) // If not already bottomed out + if (m->bottom_type() != type(m)) { // If not already bottomed out worklist.push(m); // Propagate change to user + } + + // CmpU nodes can get their type information from two nodes up in the + // graph (instead of from the nodes immediately above). Make sure they + // are added to the worklist if nodes they depend on are updated, since + // they could be missed and get wrong types otherwise. + uint m_op = m->Opcode(); + if (m_op == Op_AddI || m_op == Op_SubI) { + for (DUIterator_Fast i2max, i2 = m->fast_outs(i2max); i2 < i2max; i2++) { + Node* p = m->fast_out(i2); // Propagate changes to uses + if (p->Opcode() == Op_CmpU) { + // Got a CmpU which might need the new type information from node n. + if(p->bottom_type() != type(p)) { // If not already bottomed out + worklist.push(p); // Propagate change to user + } + } + } + } } } } diff --git a/hotspot/src/share/vm/opto/runtime.cpp b/hotspot/src/share/vm/opto/runtime.cpp index ca5e5af7833..9806ad62483 100644 --- a/hotspot/src/share/vm/opto/runtime.cpp +++ b/hotspot/src/share/vm/opto/runtime.cpp @@ -945,6 +945,48 @@ const TypeFunc* OptoRuntime::multiplyToLen_Type() { return TypeFunc::make(domain, range); } +const TypeFunc* OptoRuntime::squareToLen_Type() { + // create input type (domain) + int num_args = 4; + int argcnt = num_args; + const Type** fields = TypeTuple::fields(argcnt); + int argp = TypeFunc::Parms; + fields[argp++] = TypePtr::NOTNULL; // x + fields[argp++] = TypeInt::INT; // len + fields[argp++] = TypePtr::NOTNULL; // z + fields[argp++] = TypeInt::INT; // zlen + assert(argp == TypeFunc::Parms+argcnt, "correct decoding"); + const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields); + + // no result type needed + fields = TypeTuple::fields(1); + fields[TypeFunc::Parms+0] = NULL; + const TypeTuple* range = TypeTuple::make(TypeFunc::Parms, fields); + return TypeFunc::make(domain, range); +} + +// for mulAdd calls, 2 pointers and 3 ints, returning int +const TypeFunc* OptoRuntime::mulAdd_Type() { + // create input type (domain) + int num_args = 5; + int argcnt = num_args; + const Type** fields = TypeTuple::fields(argcnt); + int argp = TypeFunc::Parms; + fields[argp++] = TypePtr::NOTNULL; // out + fields[argp++] = TypePtr::NOTNULL; // in + fields[argp++] = TypeInt::INT; // offset + fields[argp++] = TypeInt::INT; // len + fields[argp++] = TypeInt::INT; // k + assert(argp == TypeFunc::Parms+argcnt, "correct decoding"); + const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields); + + // returning carry (int) + fields = TypeTuple::fields(1); + fields[TypeFunc::Parms+0] = TypeInt::INT; + const TypeTuple* range = TypeTuple::make(TypeFunc::Parms+1, fields); + return TypeFunc::make(domain, range); +} + //------------- Interpreter state access for on stack replacement diff --git a/hotspot/src/share/vm/opto/runtime.hpp b/hotspot/src/share/vm/opto/runtime.hpp index aa08b657e05..3f2a73039c8 100644 --- a/hotspot/src/share/vm/opto/runtime.hpp +++ b/hotspot/src/share/vm/opto/runtime.hpp @@ -312,6 +312,10 @@ private: static const TypeFunc* multiplyToLen_Type(); + static const TypeFunc* squareToLen_Type(); + + static const TypeFunc* mulAdd_Type(); + static const TypeFunc* updateBytesCRC32_Type(); // leaf on stack replacement interpreter accessor types diff --git a/hotspot/src/share/vm/opto/superword.cpp b/hotspot/src/share/vm/opto/superword.cpp index be63462c088..8dba68b8af2 100644 --- a/hotspot/src/share/vm/opto/superword.cpp +++ b/hotspot/src/share/vm/opto/superword.cpp @@ -1631,7 +1631,7 @@ void SuperWord::output() { } Node* adr = low_adr->in(MemNode::Address); const TypePtr* atyp = n->adr_type(); - vn = LoadVectorNode::make(opc, ctl, mem, adr, atyp, vlen, velt_basic_type(n)); + vn = LoadVectorNode::make(opc, ctl, mem, adr, atyp, vlen, velt_basic_type(n), control_dependency(p)); vlen_in_bytes = vn->as_LoadVector()->memory_size(); } else if (n->is_Store()) { // Promote value to be stored to vector @@ -2280,6 +2280,19 @@ Node* SuperWord::executed_last(Node_List* p) { return n; } +LoadNode::ControlDependency SuperWord::control_dependency(Node_List* p) { + LoadNode::ControlDependency dep = LoadNode::DependsOnlyOnTest; + for (uint i = 0; i < p->size(); i++) { + Node* n = p->at(i); + assert(n->is_Load(), "only meaningful for loads"); + if (!n->depends_only_on_test()) { + dep = LoadNode::Pinned; + } + } + return dep; +} + + //----------------------------align_initial_loop_index--------------------------- // Adjust pre-loop limit so that in main loop, a load/store reference // to align_to_ref will be a position zero in the vector. diff --git a/hotspot/src/share/vm/opto/superword.hpp b/hotspot/src/share/vm/opto/superword.hpp index c56931a76fc..5ea8979c06b 100644 --- a/hotspot/src/share/vm/opto/superword.hpp +++ b/hotspot/src/share/vm/opto/superword.hpp @@ -428,6 +428,7 @@ class SuperWord : public ResourceObj { Node* executed_first(Node_List* p); // Return the node executed last in pack p. Node* executed_last(Node_List* p); + static LoadNode::ControlDependency control_dependency(Node_List* p); // Alignment within a vector memory reference int memory_alignment(MemNode* s, int iv_adjust); // (Start, end] half-open range defining which operands are vector diff --git a/hotspot/src/share/vm/opto/vectornode.cpp b/hotspot/src/share/vm/opto/vectornode.cpp index f1dae4cdc8a..8f88329bd05 100644 --- a/hotspot/src/share/vm/opto/vectornode.cpp +++ b/hotspot/src/share/vm/opto/vectornode.cpp @@ -406,9 +406,11 @@ PackNode* PackNode::binary_tree_pack(int lo, int hi) { // Return the vector version of a scalar load node. LoadVectorNode* LoadVectorNode::make(int opc, Node* ctl, Node* mem, - Node* adr, const TypePtr* atyp, uint vlen, BasicType bt) { + Node* adr, const TypePtr* atyp, + uint vlen, BasicType bt, + ControlDependency control_dependency) { const TypeVect* vt = TypeVect::make(bt, vlen); - return new LoadVectorNode(ctl, mem, adr, atyp, vt); + return new LoadVectorNode(ctl, mem, adr, atyp, vt, control_dependency); } // Return the vector version of a scalar store node. diff --git a/hotspot/src/share/vm/opto/vectornode.hpp b/hotspot/src/share/vm/opto/vectornode.hpp index e848dc2ee91..572c44c8648 100644 --- a/hotspot/src/share/vm/opto/vectornode.hpp +++ b/hotspot/src/share/vm/opto/vectornode.hpp @@ -454,8 +454,8 @@ class XorVNode : public VectorNode { // Load Vector from memory class LoadVectorNode : public LoadNode { public: - LoadVectorNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeVect* vt) - : LoadNode(c, mem, adr, at, vt, MemNode::unordered) { + LoadVectorNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeVect* vt, ControlDependency control_dependency = LoadNode::DependsOnlyOnTest) + : LoadNode(c, mem, adr, at, vt, MemNode::unordered, control_dependency) { init_class_id(Class_LoadVector); } @@ -471,7 +471,9 @@ class LoadVectorNode : public LoadNode { virtual int store_Opcode() const { return Op_StoreVector; } static LoadVectorNode* make(int opc, Node* ctl, Node* mem, - Node* adr, const TypePtr* atyp, uint vlen, BasicType bt); + Node* adr, const TypePtr* atyp, + uint vlen, BasicType bt, + ControlDependency control_dependency = LoadNode::DependsOnlyOnTest); }; //------------------------------StoreVectorNode-------------------------------- diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp index a8b6ec79134..2061f6330e2 100644 --- a/hotspot/src/share/vm/prims/jni.cpp +++ b/hotspot/src/share/vm/prims/jni.cpp @@ -1126,39 +1126,32 @@ static void jni_invoke_nonstatic(JNIEnv *env, JavaValue* result, jobject receive Method* m = Method::resolve_jmethod_id(method_id); number_of_parameters = m->size_of_parameters(); Klass* holder = m->method_holder(); - if (!(holder)->is_interface()) { + if (call_type != JNI_VIRTUAL) { + selected_method = m; + } else if (!m->has_itable_index()) { // non-interface call -- for that little speed boost, don't handlize debug_only(No_Safepoint_Verifier nosafepoint;) - if (call_type == JNI_VIRTUAL) { - // jni_GetMethodID makes sure class is linked and initialized - // so m should have a valid vtable index. - assert(!m->has_itable_index(), ""); - int vtbl_index = m->vtable_index(); - if (vtbl_index != Method::nonvirtual_vtable_index) { - Klass* k = h_recv->klass(); - // k might be an arrayKlassOop but all vtables start at - // the same place. The cast is to avoid virtual call and assertion. - InstanceKlass *ik = (InstanceKlass*)k; - selected_method = ik->method_at_vtable(vtbl_index); - } else { - // final method - selected_method = m; - } + // jni_GetMethodID makes sure class is linked and initialized + // so m should have a valid vtable index. + assert(m->valid_vtable_index(), "no valid vtable index"); + int vtbl_index = m->vtable_index(); + if (vtbl_index != Method::nonvirtual_vtable_index) { + Klass* k = h_recv->klass(); + // k might be an arrayKlassOop but all vtables start at + // the same place. The cast is to avoid virtual call and assertion. + InstanceKlass *ik = (InstanceKlass*)k; + selected_method = ik->method_at_vtable(vtbl_index); } else { - // JNI_NONVIRTUAL call + // final method selected_method = m; } } else { // interface call KlassHandle h_holder(THREAD, holder); - if (call_type == JNI_VIRTUAL) { - int itbl_index = m->itable_index(); - Klass* k = h_recv->klass(); - selected_method = InstanceKlass::cast(k)->method_at_itable(h_holder(), itbl_index, CHECK); - } else { - selected_method = m; - } + int itbl_index = m->itable_index(); + Klass* k = h_recv->klass(); + selected_method = InstanceKlass::cast(k)->method_at_itable(h_holder(), itbl_index, CHECK); } } diff --git a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp index 2d3d200f207..db0437ab119 100644 --- a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp +++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp @@ -842,7 +842,7 @@ JvmtiEnvBase::get_stack_trace(JavaThread *java_thread, // optimize to limit the number of times that java_sender() is called javaVFrame *jvf_cursor = jvf; javaVFrame *jvf_prev = NULL; - javaVFrame *jvf_prev_prev; + javaVFrame *jvf_prev_prev = NULL; int j = 0; while (jvf_cursor != NULL) { jvf_prev_prev = jvf_prev; diff --git a/hotspot/src/share/vm/prims/methodHandles.cpp b/hotspot/src/share/vm/prims/methodHandles.cpp index b9cf17732a4..0856cffa236 100644 --- a/hotspot/src/share/vm/prims/methodHandles.cpp +++ b/hotspot/src/share/vm/prims/methodHandles.cpp @@ -677,24 +677,24 @@ Handle MethodHandles::resolve_MemberName(Handle mname, KlassHandle caller, TRAPS case IS_METHOD: { CallInfo result; + LinkInfo link_info(defc, name, type, caller, caller.not_null()); { assert(!HAS_PENDING_EXCEPTION, ""); if (ref_kind == JVM_REF_invokeStatic) { LinkResolver::resolve_static_call(result, - defc, name, type, caller, caller.not_null(), false, THREAD); + link_info, false, THREAD); } else if (ref_kind == JVM_REF_invokeInterface) { LinkResolver::resolve_interface_call(result, Handle(), defc, - defc, name, type, caller, caller.not_null(), false, THREAD); + link_info, false, THREAD); } else if (mh_invoke_id != vmIntrinsics::_none) { assert(!is_signature_polymorphic_static(mh_invoke_id), ""); - LinkResolver::resolve_handle_call(result, - defc, name, type, caller, THREAD); + LinkResolver::resolve_handle_call(result, link_info, THREAD); } else if (ref_kind == JVM_REF_invokeSpecial) { LinkResolver::resolve_special_call(result, - defc, name, type, caller, caller.not_null(), THREAD); + link_info, THREAD); } else if (ref_kind == JVM_REF_invokeVirtual) { LinkResolver::resolve_virtual_call(result, Handle(), defc, - defc, name, type, caller, caller.not_null(), false, THREAD); + link_info, false, THREAD); } else { assert(false, err_msg("ref_kind=%d", ref_kind)); } @@ -714,11 +714,11 @@ Handle MethodHandles::resolve_MemberName(Handle mname, KlassHandle caller, TRAPS case IS_CONSTRUCTOR: { CallInfo result; + LinkInfo link_info(defc, name, type, caller, caller.not_null()); { assert(!HAS_PENDING_EXCEPTION, ""); if (name == vmSymbols::object_initializer_name()) { - LinkResolver::resolve_special_call(result, - defc, name, type, caller, caller.not_null(), THREAD); + LinkResolver::resolve_special_call(result, link_info, THREAD); } else { break; // will throw after end of switch } @@ -735,7 +735,8 @@ Handle MethodHandles::resolve_MemberName(Handle mname, KlassHandle caller, TRAPS fieldDescriptor result; // find_field initializes fd if found { assert(!HAS_PENDING_EXCEPTION, ""); - LinkResolver::resolve_field(result, defc, name, type, caller, Bytecodes::_nop, false, false, THREAD); + LinkInfo link_info(defc, name, type, caller, /*check_access*/false); + LinkResolver::resolve_field(result, link_info, Bytecodes::_nop, false, THREAD); if (HAS_PENDING_EXCEPTION) { return empty; } @@ -942,22 +943,56 @@ int MethodHandles::find_MemberNames(KlassHandle k, return rfill + overflow; } -// Get context class for a CallSite instance: either extract existing context or use default one. -InstanceKlass* MethodHandles::get_call_site_context(oop call_site) { - // In order to extract a context the following traversal is performed: - // CallSite.context => Cleaner.referent => Class._klass => Klass - assert(java_lang_invoke_CallSite::is_instance(call_site), ""); - oop context_oop = java_lang_invoke_CallSite::context_volatile(call_site); - if (oopDesc::is_null(context_oop)) { - return NULL; // The context hasn't been initialized yet. +void MethodHandles::add_dependent_nmethod(oop call_site, nmethod* nm) { + assert_locked_or_safepoint(CodeCache_lock); + + oop context = java_lang_invoke_CallSite::context(call_site); + nmethodBucket* deps = java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(context); + + nmethodBucket* new_deps = nmethodBucket::add_dependent_nmethod(deps, nm); + if (deps != new_deps) { + java_lang_invoke_MethodHandleNatives_CallSiteContext::set_vmdependencies(context, new_deps); } - oop context_class_oop = java_lang_ref_Reference::referent(context_oop); - if (oopDesc::is_null(context_class_oop)) { - // The context reference was cleared by GC, so current dependency context - // isn't usable anymore. Context should be fetched from CallSite again. - return NULL; +} + +void MethodHandles::remove_dependent_nmethod(oop call_site, nmethod* nm) { + assert_locked_or_safepoint(CodeCache_lock); + + oop context = java_lang_invoke_CallSite::context(call_site); + nmethodBucket* deps = java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(context); + + if (nmethodBucket::remove_dependent_nmethod(deps, nm)) { + nmethodBucket* new_deps = nmethodBucket::clean_dependent_nmethods(deps); + if (deps != new_deps) { + java_lang_invoke_MethodHandleNatives_CallSiteContext::set_vmdependencies(context, new_deps); + } + } +} + +void MethodHandles::flush_dependent_nmethods(Handle call_site, Handle target) { + assert_lock_strong(Compile_lock); + + int marked = 0; + CallSiteDepChange changes(call_site(), target()); + { + MutexLockerEx mu2(CodeCache_lock, Mutex::_no_safepoint_check_flag); + + oop context = java_lang_invoke_CallSite::context(call_site()); + nmethodBucket* deps = java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(context); + + marked = nmethodBucket::mark_dependent_nmethods(deps, changes); + if (marked > 0) { + nmethodBucket* new_deps = nmethodBucket::clean_dependent_nmethods(deps); + if (deps != new_deps) { + java_lang_invoke_MethodHandleNatives_CallSiteContext::set_vmdependencies(context, new_deps); + } + } + } + if (marked > 0) { + // At least one nmethod has been marked for deoptimization + VM_Deoptimize op; + VMThread::execute(&op); } - return InstanceKlass::cast(java_lang_Class::as_Klass(context_class_oop)); } //------------------------------------------------------------------------------ @@ -1276,7 +1311,7 @@ JVM_ENTRY(void, MHN_setCallSiteTargetNormal(JNIEnv* env, jobject igcls, jobject { // Walk all nmethods depending on this call site. MutexLocker mu(Compile_lock, thread); - CodeCache::flush_dependents_on(call_site, target); + MethodHandles::flush_dependent_nmethods(call_site, target); java_lang_invoke_CallSite::set_target(call_site(), target()); } } @@ -1288,30 +1323,34 @@ JVM_ENTRY(void, MHN_setCallSiteTargetVolatile(JNIEnv* env, jobject igcls, jobjec { // Walk all nmethods depending on this call site. MutexLocker mu(Compile_lock, thread); - CodeCache::flush_dependents_on(call_site, target); + MethodHandles::flush_dependent_nmethods(call_site, target); java_lang_invoke_CallSite::set_target_volatile(call_site(), target()); } } JVM_END -JVM_ENTRY(void, MHN_invalidateDependentNMethods(JNIEnv* env, jobject igcls, jobject call_site_jh)) { - Handle call_site(THREAD, JNIHandles::resolve_non_null(call_site_jh)); +JVM_ENTRY(void, MHN_clearCallSiteContext(JNIEnv* env, jobject igcls, jobject context_jh)) { + Handle context(THREAD, JNIHandles::resolve_non_null(context_jh)); { // Walk all nmethods depending on this call site. MutexLocker mu1(Compile_lock, thread); - CallSiteDepChange changes(call_site(), Handle()); - - InstanceKlass* ctxk = MethodHandles::get_call_site_context(call_site()); - if (ctxk == NULL) { - return; // No dependencies to invalidate yet. - } int marked = 0; { MutexLockerEx mu2(CodeCache_lock, Mutex::_no_safepoint_check_flag); - marked = ctxk->mark_dependent_nmethods(changes); + nmethodBucket* b = java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(context()); + while(b != NULL) { + nmethod* nm = b->get_nmethod(); + if (b->count() > 0 && nm->is_alive() && !nm->is_marked_for_deoptimization()) { + nm->mark_for_deoptimization(); + marked++; + } + nmethodBucket* next = b->next(); + delete b; + b = next; + } + java_lang_invoke_MethodHandleNatives_CallSiteContext::set_vmdependencies(context(), NULL); // reset context } - java_lang_invoke_CallSite::set_context_volatile(call_site(), NULL); // Reset call site to initial state if (marked > 0) { // At least one nmethod has been marked for deoptimization VM_Deoptimize op; @@ -1357,6 +1396,7 @@ JVM_END #define MT JLINV"MethodType;" #define MH JLINV"MethodHandle;" #define MEM JLINV"MemberName;" +#define CTX JLINV"MethodHandleNatives$CallSiteContext;" #define CC (char*) /*cast a literal from (const char*)*/ #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f) @@ -1374,7 +1414,7 @@ static JNINativeMethod MHN_methods[] = { {CC"objectFieldOffset", CC"("MEM")J", FN_PTR(MHN_objectFieldOffset)}, {CC"setCallSiteTargetNormal", CC"("CS""MH")V", FN_PTR(MHN_setCallSiteTargetNormal)}, {CC"setCallSiteTargetVolatile", CC"("CS""MH")V", FN_PTR(MHN_setCallSiteTargetVolatile)}, - {CC"invalidateDependentNMethods", CC"("CS")V", FN_PTR(MHN_invalidateDependentNMethods)}, + {CC"clearCallSiteContext", CC"("CTX")V", FN_PTR(MHN_clearCallSiteContext)}, {CC"staticFieldOffset", CC"("MEM")J", FN_PTR(MHN_staticFieldOffset)}, {CC"staticFieldBase", CC"("MEM")"OBJ, FN_PTR(MHN_staticFieldBase)}, {CC"getMemberVMInfo", CC"("MEM")"OBJ, FN_PTR(MHN_getMemberVMInfo)} diff --git a/hotspot/src/share/vm/prims/methodHandles.hpp b/hotspot/src/share/vm/prims/methodHandles.hpp index 5dd69bd42ff..ab41c31b4a3 100644 --- a/hotspot/src/share/vm/prims/methodHandles.hpp +++ b/hotspot/src/share/vm/prims/methodHandles.hpp @@ -69,7 +69,10 @@ class MethodHandles: AllStatic { enum { _suppress_defc = 1, _suppress_name = 2, _suppress_type = 4 }; // CallSite support - static InstanceKlass* get_call_site_context(oop call_site); + static void add_dependent_nmethod(oop call_site, nmethod* nm); + static void remove_dependent_nmethod(oop call_site, nmethod* nm); + + static void flush_dependent_nmethods(Handle call_site, Handle target); // Generate MethodHandles adapters. static bool generate_adapters(); diff --git a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp index 5ac9413e8d0..76c2aaa9f22 100644 --- a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp +++ b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp @@ -64,7 +64,7 @@ void AdvancedThresholdPolicy::initialize() { } #endif -#ifdef SPARC +#if defined SPARC || defined AARCH64 if (FLAG_IS_DEFAULT(InlineSmallCode)) { FLAG_SET_DEFAULT(InlineSmallCode, 2500); } diff --git a/hotspot/src/share/vm/runtime/javaCalls.cpp b/hotspot/src/share/vm/runtime/javaCalls.cpp index a7bdc680e93..9d4eccd8d69 100644 --- a/hotspot/src/share/vm/runtime/javaCalls.cpp +++ b/hotspot/src/share/vm/runtime/javaCalls.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -179,9 +179,9 @@ void JavaCalls::call_virtual(JavaValue* result, KlassHandle spec_klass, Symbol* CallInfo callinfo; Handle receiver = args->receiver(); KlassHandle recvrKlass(THREAD, receiver.is_null() ? (Klass*)NULL : receiver->klass()); + LinkInfo link_info(spec_klass, name, signature, KlassHandle(), /*check_access*/false); LinkResolver::resolve_virtual_call( - callinfo, receiver, recvrKlass, spec_klass, name, signature, - KlassHandle(), false, true, CHECK); + callinfo, receiver, recvrKlass, link_info, true, CHECK); methodHandle method = callinfo.selected_method(); assert(method.not_null(), "should have thrown exception"); @@ -216,7 +216,8 @@ void JavaCalls::call_virtual(JavaValue* result, Handle receiver, KlassHandle spe void JavaCalls::call_special(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) { CallInfo callinfo; - LinkResolver::resolve_special_call(callinfo, klass, name, signature, KlassHandle(), false, CHECK); + LinkInfo link_info(klass, name, signature, KlassHandle(), /*check_access*/false); + LinkResolver::resolve_special_call(callinfo, link_info, CHECK); methodHandle method = callinfo.selected_method(); assert(method.not_null(), "should have thrown exception"); @@ -250,7 +251,8 @@ void JavaCalls::call_special(JavaValue* result, Handle receiver, KlassHandle kla void JavaCalls::call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) { CallInfo callinfo; - LinkResolver::resolve_static_call(callinfo, klass, name, signature, KlassHandle(), false, true, CHECK); + LinkInfo link_info(klass, name, signature, KlassHandle(), /*check_access*/false); + LinkResolver::resolve_static_call(callinfo, link_info, true, CHECK); methodHandle method = callinfo.selected_method(); assert(method.not_null(), "should have thrown exception"); diff --git a/hotspot/src/share/vm/runtime/os.cpp b/hotspot/src/share/vm/runtime/os.cpp index 525c1a929c8..9cc4ea92dd1 100644 --- a/hotspot/src/share/vm/runtime/os.cpp +++ b/hotspot/src/share/vm/runtime/os.cpp @@ -775,6 +775,10 @@ void os::start_thread(Thread* thread) { pd_start_thread(thread); } +void os::abort(bool dump_core) { + abort(dump_core && CreateCoredumpOnCrash, NULL, NULL); +} + //--------------------------------------------------------------------------- // Helper functions for fatal error handler diff --git a/hotspot/src/share/vm/runtime/reflection.cpp b/hotspot/src/share/vm/runtime/reflection.cpp index 85a2b0aade3..0e439e87137 100644 --- a/hotspot/src/share/vm/runtime/reflection.cpp +++ b/hotspot/src/share/vm/runtime/reflection.cpp @@ -831,9 +831,9 @@ methodHandle Reflection::resolve_interface_call(instanceKlassHandle klass, metho CallInfo info; Symbol* signature = method->signature(); Symbol* name = method->name(); - LinkResolver::resolve_interface_call(info, receiver, recv_klass, klass, - name, signature, - KlassHandle(), false, true, + LinkResolver::resolve_interface_call(info, receiver, recv_klass, + LinkInfo(klass, name, signature, KlassHandle(), false), + true, CHECK_(methodHandle())); return info.selected_method(); } diff --git a/hotspot/src/share/vm/runtime/stubRoutines.cpp b/hotspot/src/share/vm/runtime/stubRoutines.cpp index aac4353837d..66ec5e99566 100644 --- a/hotspot/src/share/vm/runtime/stubRoutines.cpp +++ b/hotspot/src/share/vm/runtime/stubRoutines.cpp @@ -137,6 +137,8 @@ address StubRoutines::_updateBytesCRC32 = NULL; address StubRoutines::_crc_table_adr = NULL; address StubRoutines::_multiplyToLen = NULL; +address StubRoutines::_squareToLen = NULL; +address StubRoutines::_mulAdd = NULL; double (* StubRoutines::_intrinsic_log )(double) = NULL; double (* StubRoutines::_intrinsic_log10 )(double) = NULL; diff --git a/hotspot/src/share/vm/runtime/stubRoutines.hpp b/hotspot/src/share/vm/runtime/stubRoutines.hpp index 619b3b45b42..56376b6cedd 100644 --- a/hotspot/src/share/vm/runtime/stubRoutines.hpp +++ b/hotspot/src/share/vm/runtime/stubRoutines.hpp @@ -197,6 +197,8 @@ class StubRoutines: AllStatic { static address _crc_table_adr; static address _multiplyToLen; + static address _squareToLen; + static address _mulAdd; // These are versions of the java.lang.Math methods which perform // the same operations as the intrinsic version. They are used for @@ -356,6 +358,8 @@ class StubRoutines: AllStatic { static address crc_table_addr() { return _crc_table_adr; } static address multiplyToLen() {return _multiplyToLen; } + static address squareToLen() {return _squareToLen; } + static address mulAdd() {return _mulAdd; } static address select_fill_function(BasicType t, bool aligned, const char* &name); diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index bd7ad14dab9..3f8c7ea8f7b 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -831,6 +831,8 @@ typedef CompactHashtable SymbolCompactHashTable; static_field(StubRoutines, _updateBytesCRC32, address) \ static_field(StubRoutines, _crc_table_adr, address) \ static_field(StubRoutines, _multiplyToLen, address) \ + static_field(StubRoutines, _squareToLen, address) \ + static_field(StubRoutines, _mulAdd, address) \ \ /*****************/ \ /* SharedRuntime */ \ diff --git a/hotspot/src/share/vm/services/diagnosticCommand.cpp b/hotspot/src/share/vm/services/diagnosticCommand.cpp index 491f3568d47..6f50c76e16e 100644 --- a/hotspot/src/share/vm/services/diagnosticCommand.cpp +++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp @@ -315,7 +315,7 @@ int VMUptimeDCmd::num_arguments() { void SystemGCDCmd::execute(DCmdSource source, TRAPS) { if (!DisableExplicitGC) { - Universe::heap()->collect(GCCause::_java_lang_system_gc); + Universe::heap()->collect(GCCause::_dcmd_gc_run); } else { output()->print_cr("Explicit GC is disabled, no GC has been performed."); } diff --git a/hotspot/src/share/vm/utilities/fakeRttiSupport.hpp b/hotspot/src/share/vm/utilities/fakeRttiSupport.hpp index 8c564004a91..e6a155aced4 100644 --- a/hotspot/src/share/vm/utilities/fakeRttiSupport.hpp +++ b/hotspot/src/share/vm/utilities/fakeRttiSupport.hpp @@ -89,11 +89,11 @@ private: return ((uintx)1) << validate_tag(tag); } - static TagType validate_tag(uintx tag) { - // Type of tag is not TagType to dodge useless MacOSX compiler warning. - assert(tag < (sizeof(uintx) * BitsPerByte), - err_msg("Tag " UINTX_FORMAT " is too large", tag)); - return static_cast(tag); + static TagType validate_tag(TagType tag) { + assert(0 <= tag, err_msg("Tag " INTX_FORMAT " is negative", (intx)tag)); + assert(tag < BitsPerWord, + err_msg("Tag " UINTX_FORMAT " is too large", (uintx)tag)); + return tag; } }; diff --git a/hotspot/test/compiler/arraycopy/TestDeadArrayCopyOnMemChain.java b/hotspot/test/compiler/arraycopy/TestDeadArrayCopyOnMemChain.java new file mode 100644 index 00000000000..1492254a054 --- /dev/null +++ b/hotspot/test/compiler/arraycopy/TestDeadArrayCopyOnMemChain.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8080699 + * @summary eliminated arraycopy node still reachable through exception edges + * @run main/othervm -XX:-UseOnStackReplacement -XX:-BackgroundCompilation TestDeadArrayCopyOnMemChain + * + */ + +public class TestDeadArrayCopyOnMemChain { + static class A { + int f; + } + + static void test_helper(Object o) { + } + + static void test(int src_off, boolean flag) { + // dst is eliminated first. Eliminating dst causes src to be + // eliminated. When working on the safepoint at the uncommon + // trap in the exception handler, the eliminated ArrayCopyNode + // is reached through the exception edges. + Object[] dst = new Object[10]; + Object[] src = new Object[10]; + + // src_off causes the exception handler to be run sometimes + try { + System.arraycopy(src, src_off, dst, 0, 10); + } catch (IndexOutOfBoundsException ioobe) { + // flag always false so test becomes uncommon trap. Make + // sure src is live at the unc. + if (flag) { + test_helper(src); + } + } + } + + static public void main(String[] args) { + for (int i = 0; i < 20000; i++) { + test((i%2) == 0 ? 0 : -1, false); + } + } +} diff --git a/hotspot/test/compiler/intrinsics/muladd/TestMulAdd.java b/hotspot/test/compiler/intrinsics/muladd/TestMulAdd.java new file mode 100644 index 00000000000..4d7b274c284 --- /dev/null +++ b/hotspot/test/compiler/intrinsics/muladd/TestMulAdd.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8081778 + * @summary Add C2 x86 intrinsic for BigInteger::mulAdd() method + * + * @run main/othervm/timeout=600 -XX:-TieredCompilation -Xbatch + * -XX:+IgnoreUnrecognizedVMOptions -XX:-UseSquareToLenIntrinsic -XX:-UseMultiplyToLenIntrinsic + * -XX:CompileCommand=dontinline,TestMulAdd::main + * -XX:CompileCommand=option,TestMulAdd::base_multiply,ccstr,DisableIntrinsic,_mulAdd + * -XX:CompileCommand=option,java.math.BigInteger::multiply,ccstr,DisableIntrinsic,_mulAdd + * -XX:CompileCommand=option,java.math.BigInteger::square,ccstr,DisableIntrinsic,_mulAdd + * -XX:CompileCommand=option,java.math.BigInteger::squareToLen,ccstr,DisableIntrinsic,_mulAdd + * -XX:CompileCommand=option,java.math.BigInteger::mulAdd,ccstr,DisableIntrinsic,_mulAdd + * -XX:CompileCommand=inline,java.math.BigInteger::multiply + * -XX:CompileCommand=inline,java.math.BigInteger::square + * -XX:CompileCommand=inline,java.math.BigInteger::squareToLen + * -XX:CompileCommand=inline,java.math.BigInteger::mulAdd TestMulAdd + */ + +import java.util.Random; +import java.math.*; + +public class TestMulAdd { + + // Avoid intrinsic by preventing inlining multiply() and mulAdd(). + public static BigInteger base_multiply(BigInteger op1) { + return op1.multiply(op1); + } + + // Generate mulAdd() intrinsic by inlining multiply(). + public static BigInteger new_multiply(BigInteger op1) { + return op1.multiply(op1); + } + + public static boolean bytecompare(BigInteger b1, BigInteger b2) { + byte[] data1 = b1.toByteArray(); + byte[] data2 = b2.toByteArray(); + if (data1.length != data2.length) + return false; + for (int i = 0; i < data1.length; i++) { + if (data1[i] != data2[i]) + return false; + } + return true; + } + + public static String stringify(BigInteger b) { + String strout= ""; + byte [] data = b.toByteArray(); + for (int i = 0; i < data.length; i++) { + strout += (String.format("%02x",data[i]) + " "); + } + return strout; + } + + public static void main(String args[]) throws Exception { + + BigInteger oldsum = new BigInteger("0"); + BigInteger newsum = new BigInteger("0"); + + BigInteger b1, b2, oldres, newres; + + Random rand = new Random(); + long seed = System.nanoTime(); + Random rand1 = new Random(); + long seed1 = System.nanoTime(); + rand.setSeed(seed); + rand1.setSeed(seed1); + + for (int j = 0; j < 100000; j++) { + int rand_int = rand1.nextInt(3136)+32; + b1 = new BigInteger(rand_int, rand); + + oldres = base_multiply(b1); + newres = new_multiply(b1); + + oldsum = oldsum.add(oldres); + newsum = newsum.add(newres); + + if (!bytecompare(oldres,newres)) { + System.out.print("mismatch for:b1:" + stringify(b1) + " :oldres:" + stringify(oldres) + " :newres:" + stringify(newres)); + System.out.println(b1); + throw new Exception("Failed"); + } + } + if (!bytecompare(oldsum,newsum)) { + System.out.println("Failure: oldsum:" + stringify(oldsum) + " newsum:" + stringify(newsum)); + throw new Exception("Failed"); + } else { + System.out.println("Success"); + } + } +} diff --git a/hotspot/test/compiler/intrinsics/squaretolen/TestSquareToLen.java b/hotspot/test/compiler/intrinsics/squaretolen/TestSquareToLen.java new file mode 100644 index 00000000000..79ebbe3af2a --- /dev/null +++ b/hotspot/test/compiler/intrinsics/squaretolen/TestSquareToLen.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8081778 + * @summary Add C2 x86 intrinsic for BigInteger::squareToLen() method + * + * @run main/othervm/timeout=600 -XX:-TieredCompilation -Xbatch + * -XX:CompileCommand=exclude,TestSquareToLen::main + * -XX:CompileCommand=option,TestSquareToLen::base_multiply,ccstr,DisableIntrinsic,_squareToLen + * -XX:CompileCommand=option,java.math.BigInteger::multiply,ccstr,DisableIntrinsic,_squareToLen + * -XX:CompileCommand=option,java.math.BigInteger::square,ccstr,DisableIntrinsic,_squareToLen + * -XX:CompileCommand=option,java.math.BigInteger::squareToLen,ccstr,DisableIntrinsic,_squareToLen + * -XX:CompileCommand=inline,java.math.BigInteger::multiply + * -XX:CompileCommand=inline,java.math.BigInteger::square + * -XX:CompileCommand=inline,java.math.BigInteger::squareToLen TestSquareToLen + */ + +import java.util.Random; +import java.math.*; + +public class TestSquareToLen { + + // Avoid intrinsic by preventing inlining multiply() and squareToLen(). + public static BigInteger base_multiply(BigInteger op1) { + return op1.multiply(op1); + } + + // Generate squareToLen() intrinsic by inlining multiply(). + public static BigInteger new_multiply(BigInteger op1) { + return op1.multiply(op1); + } + + public static boolean bytecompare(BigInteger b1, BigInteger b2) { + byte[] data1 = b1.toByteArray(); + byte[] data2 = b2.toByteArray(); + if (data1.length != data2.length) + return false; + for (int i = 0; i < data1.length; i++) { + if (data1[i] != data2[i]) + return false; + } + return true; + } + + public static String stringify(BigInteger b) { + String strout= ""; + byte [] data = b.toByteArray(); + for (int i = 0; i < data.length; i++) { + strout += (String.format("%02x",data[i]) + " "); + } + return strout; + } + + public static void main(String args[]) throws Exception { + + BigInteger oldsum = new BigInteger("0"); + BigInteger newsum = new BigInteger("0"); + + BigInteger b1, b2, oldres, newres; + + Random rand = new Random(); + long seed = System.nanoTime(); + Random rand1 = new Random(); + long seed1 = System.nanoTime(); + rand.setSeed(seed); + rand1.setSeed(seed1); + + for (int j = 0; j < 100000; j++) { + int rand_int = rand1.nextInt(3136)+32; + b1 = new BigInteger(rand_int, rand); + + oldres = base_multiply(b1); + newres = new_multiply(b1); + + oldsum = oldsum.add(oldres); + newsum = newsum.add(newres); + + if (!bytecompare(oldres,newres)) { + System.out.print("mismatch for:b1:" + stringify(b1) + " :oldres:" + stringify(oldres) + " :newres:" + stringify(newres)); + System.out.println(b1); + throw new Exception("Failed"); + } + } + if (!bytecompare(oldsum,newsum)) { + System.out.println("Failure: oldsum:" + stringify(oldsum) + " newsum:" + stringify(newsum)); + throw new Exception("Failed"); + } else { + System.out.println("Success"); + } + } +} diff --git a/hotspot/test/compiler/jsr292/CallSiteDepContextTest.java b/hotspot/test/compiler/jsr292/CallSiteDepContextTest.java index 8005a990d83..d65bf424228 100644 --- a/hotspot/test/compiler/jsr292/CallSiteDepContextTest.java +++ b/hotspot/test/compiler/jsr292/CallSiteDepContextTest.java @@ -24,12 +24,15 @@ /** * @test * @bug 8057967 - * @ignore 8079205 - * @run main/bootclasspath -Xbatch java.lang.invoke.CallSiteDepContextTest + * @run main/bootclasspath -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:+TraceClassUnloading + * -XX:+PrintCompilation -XX:+TraceDependencies -XX:+TraceReferenceGC + * -verbose:gc java.lang.invoke.CallSiteDepContextTest */ package java.lang.invoke; import java.lang.ref.*; +import java.lang.reflect.Field; + import jdk.internal.org.objectweb.asm.*; import sun.misc.Unsafe; @@ -96,6 +99,13 @@ public class CallSiteDepContextTest { } } + public static void testHiddenDepField() throws Exception { + try { + Field f = MethodHandleNatives.CallSiteContext.class.getDeclaredField("vmdependencies"); + throw new AssertionError("Context.dependencies field should be hidden"); + } catch(NoSuchFieldException e) { /* expected */ } + } + public static void testSharedCallSite() throws Throwable { Class cls1 = UNSAFE.defineAnonymousClass(Object.class, getClassFile("CS_1"), null); Class cls2 = UNSAFE.defineAnonymousClass(Object.class, getClassFile("CS_2"), null); @@ -132,12 +142,14 @@ public class CallSiteDepContextTest { static ReferenceQueue rq = new ReferenceQueue(); static PhantomReference ref; - public static void testGC() throws Throwable { + public static void testGC(boolean clear, boolean precompile) throws Throwable { + String id = "_" + clear + "_" + precompile; + mcs = new MutableCallSite(LOOKUP.findStatic(T.class, "f1", TYPE)); Class[] cls = new Class[] { - UNSAFE.defineAnonymousClass(Object.class, getClassFile("GC_1"), null), - UNSAFE.defineAnonymousClass(Object.class, getClassFile("GC_2"), null), + UNSAFE.defineAnonymousClass(Object.class, getClassFile("GC_1" + id), null), + UNSAFE.defineAnonymousClass(Object.class, getClassFile("GC_2" + id), null), }; MethodHandle[] mhs = new MethodHandle[] { @@ -151,30 +163,38 @@ public class CallSiteDepContextTest { execute(1, mhs); ref = new PhantomReference<>(cls[0], rq); - cls[0] = UNSAFE.defineAnonymousClass(Object.class, getClassFile("GC_3"), null); + cls[0] = UNSAFE.defineAnonymousClass(Object.class, getClassFile("GC_3" + id), null); mhs[0] = LOOKUP.findStatic(cls[0], METHOD_NAME, TYPE); do { System.gc(); try { - Reference ref1 = rq.remove(1000); + Reference ref1 = rq.remove(100); if (ref1 == ref) { - ref1.clear(); - System.gc(); // Ensure that the stale context is cleared break; } } catch(InterruptedException e) { /* ignore */ } } while (true); - execute(1, mhs); + if (clear) { + ref.clear(); + System.gc(); // Ensure that the stale context is unloaded + } + if (precompile) { + execute(1, mhs); + } mcs.setTarget(LOOKUP.findStatic(T.class, "f2", TYPE)); execute(2, mhs); } public static void main(String[] args) throws Throwable { + testHiddenDepField(); testSharedCallSite(); testNonBoundCallSite(); - testGC(); + testGC(false, false); + testGC(false, true); + testGC( true, false); + testGC( true, true); System.out.println("TEST PASSED"); } } diff --git a/hotspot/test/compiler/loopopts/superword/TestReductionWithLoopVariantUse.java b/hotspot/test/compiler/loopopts/superword/TestReductionWithLoopVariantUse.java new file mode 100644 index 00000000000..b8e1d72806c --- /dev/null +++ b/hotspot/test/compiler/loopopts/superword/TestReductionWithLoopVariantUse.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8080976 + * @summary Loop variant use in reduction should prevent vectorization + * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestReductionWithLoopVariantUse + * + */ + +public class TestReductionWithLoopVariantUse { + static int m(int[] array) { + int c = 0; + for (int i = 0; i < 256; i++) { + c += array[i]; + array[i] = c; + } + return c; + } + + static public void main(String[] args) { + int[] array = new int[256]; + int[] array2 = new int[256]; + for (int j = 0; j < 256; j++) { + array2[j] = j; + } + for (int i = 0; i < 20000; i++) { + System.arraycopy(array2, 0, array, 0, 256); + int res = m(array); + boolean success = true; + int c = 0; + for (int j = 0; j < 256; j++) { + c += array2[j]; + if (array[j] != c) { + System.out.println("Failed for " + j + " : " + array[j] + " != " + c); + success = false; + } + } + if (c != res) { + System.out.println("Failed for sum: " + c + " != " + res); + } + if (!success) { + throw new RuntimeException("Test failed"); + } + } + } +} diff --git a/hotspot/test/compiler/rangechecks/TestBadFoldCompare.java b/hotspot/test/compiler/rangechecks/TestBadFoldCompare.java new file mode 100644 index 00000000000..328807a6560 --- /dev/null +++ b/hotspot/test/compiler/rangechecks/TestBadFoldCompare.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8085832 + * @summary x <= 0 || x > 0 wrongly folded as (x-1) >u -1 + * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestBadFoldCompare + */ + +public class TestBadFoldCompare { + + static boolean test1_taken; + + static void helper1(int i, int a, int b, boolean flag) { + if (flag) { + if (i <= a || i > b) { + test1_taken = true; + } + } + } + + static void test1(int i, boolean flag) { + helper1(i, 0, 0, flag); + } + + static boolean test2_taken; + + static void helper2(int i, int a, int b, boolean flag) { + if (flag) { + if (i > b || i <= a) { + test2_taken = true; + } + } + } + + static void test2(int i, boolean flag) { + helper2(i, 0, 0, flag); + } + + static public void main(String[] args) { + boolean success = true; + + for (int i = 0; i < 20000; i++) { + helper1(5, 0, 10, (i%2)==0); + helper1(-1, 0, 10, (i%2)==0); + helper1(15, 0, 10, (i%2)==0); + test1(0, false); + } + test1_taken = false; + test1(0, true); + if (!test1_taken) { + System.out.println("Test1 failed"); + success = false; + } + + for (int i = 0; i < 20000; i++) { + helper2(5, 0, 10, (i%2)==0); + helper2(-1, 0, 10, (i%2)==0); + helper2(15, 0, 10, (i%2)==0); + test2(0, false); + } + test2_taken = false; + test2(0, true); + + if (!test2_taken) { + System.out.println("Test2 failed"); + success = false; + } + if (!success) { + throw new RuntimeException("Some tests failed"); + } + } +} diff --git a/hotspot/test/compiler/types/TestTypePropagationToCmpU.java b/hotspot/test/compiler/types/TestTypePropagationToCmpU.java new file mode 100644 index 00000000000..9e08a8b4cf0 --- /dev/null +++ b/hotspot/test/compiler/types/TestTypePropagationToCmpU.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8080156 8060036 + * @summary Test correctness of type propagation to CmpUNodes. + * @run main TestTypePropagationToCmpU + */ +public class TestTypePropagationToCmpU { + public static void main(String[] args) { + try { + // Trigger compilation + for (int i = 0; i < 100_000; ++i) { + test(); + } + } catch (NullPointerException e) { + // Test should never throw a NullPointerException + throw new RuntimeException("Test failed"); + } + } + + static int global = 42; + + public static void test() { + int a = Integer.MIN_VALUE; + int b = global; + char[] buf = { 0 }; + for (int i = 0; i <= b; ++i) { + a = i - b; + } + // C2 adds a range check and an uncommon trap here to ensure that the array index + // is in bounds. If type information is not propagated correctly to the corresponding + // CmpUNode, this trap may be always taken. Because C2 also removes the unnecessary + // allocation of 'buf', a NullPointerException is thrown in this case. + char c = buf[(a * 11) / 2 - a]; // a is 0 here if global >= 0 + buf[0] = 0; + } +} diff --git a/hotspot/test/compiler/unsafe/TestUnsafeLoadControl.java b/hotspot/test/compiler/unsafe/TestUnsafeLoadControl.java new file mode 100644 index 00000000000..edd55975378 --- /dev/null +++ b/hotspot/test/compiler/unsafe/TestUnsafeLoadControl.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8077504 + * @summary Unsafe load can loose control dependency and cause crash + * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestUnsafeLoadControl + * + */ + +import java.lang.reflect.Field; +import sun.misc.Unsafe; + +public class TestUnsafeLoadControl { + + private static final Unsafe UNSAFE; + + static { + try { + Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe"); + unsafeField.setAccessible(true); + UNSAFE = (Unsafe) unsafeField.get(null); + } catch(Exception e) { + throw new RuntimeException(e); + } + } + + static int val; + static void test1(int[] a, boolean[] flags, boolean flag, long j) { + for (int i = 0; i < 10; i++) { + if (flags[i]) { + if (flag) { + long address = (j << 2) + UNSAFE.ARRAY_INT_BASE_OFFSET; + int v = UNSAFE.getInt(a, address); + val = v; + } + } + } + } + + static int test2(int[] a, boolean[] flags, boolean flag, long j) { + int sum = 0; + for (int i = 0; i < 10; i++) { + if (flags[i]) { + if (flag) { + long address = (j << 2) + UNSAFE.ARRAY_INT_BASE_OFFSET; + int v = UNSAFE.getInt(a, address); + if (v == 0) { + sum++; + } + } + } + } + return sum; + } + + static public void main(String[] args) { + boolean[] flags = new boolean[10]; + for (int i = 0; i < flags.length; i++) { + flags[i] = true; + } + int[] array = new int[10]; + for (int i = 0; i < 20000; i++) { + test1(array, flags, true, 0); + } + for (int i = 0; i < flags.length; i++) { + flags[i] = false; + } + test1(array, flags, true, Long.MAX_VALUE/4); + + for (int i = 0; i < flags.length; i++) { + flags[i] = true; + } + for (int i = 0; i < 20000; i++) { + test2(array, flags, true, 0); + } + for (int i = 0; i < flags.length; i++) { + flags[i] = false; + } + test2(array, flags, true, Long.MAX_VALUE/4); + } +} diff --git a/hotspot/test/gc/TestSmallHeap.java b/hotspot/test/gc/TestSmallHeap.java index b78d558cb51..23c1b00a9c3 100644 --- a/hotspot/test/gc/TestSmallHeap.java +++ b/hotspot/test/gc/TestSmallHeap.java @@ -27,6 +27,7 @@ * @requires vm.gc=="null" * @requires (vm.opt.AggressiveOpts=="null") | (vm.opt.AggressiveOpts=="false") * @requires vm.compMode != "Xcomp" + * @requires vm.opt.UseCompressedOops != false * @summary Verify that starting the VM with a small heap works * @library /testlibrary /../../test/lib * @modules java.management/sun.management diff --git a/hotspot/test/runtime/jni/ToStringInInterfaceTest/ImplementationOfWithToString.java b/hotspot/test/runtime/jni/ToStringInInterfaceTest/ImplementationOfWithToString.java new file mode 100644 index 00000000000..e82d2bdfc98 --- /dev/null +++ b/hotspot/test/runtime/jni/ToStringInInterfaceTest/ImplementationOfWithToString.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * Implementation of InterfaceWithToString. + */ +public class ImplementationOfWithToString implements InterfaceWithToString { + + /** + * @see InterfaceWithToString#someMethod() + * {@inheritDoc} + */ + @Override + public void someMethod() { + // May do something here. + } + + /** + * @see java.lang.Object#toString() + * {@inheritDoc} + */ + @Override + public String toString() { + return "toString() from " + getClass().getName(); + } +} diff --git a/langtools/test/tools/javac/generics/typevars/6182630/T6182630c.java b/hotspot/test/runtime/jni/ToStringInInterfaceTest/InterfaceWithToString.java similarity index 77% rename from langtools/test/tools/javac/generics/typevars/6182630/T6182630c.java rename to hotspot/test/runtime/jni/ToStringInInterfaceTest/InterfaceWithToString.java index 00eabe482bb..dbf06a15cc0 100644 --- a/langtools/test/tools/javac/generics/typevars/6182630/T6182630c.java +++ b/hotspot/test/runtime/jni/ToStringInInterfaceTest/InterfaceWithToString.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,13 +21,17 @@ * questions. */ -public class T6182630c { - static class Foo { - public X x; - public void m(X x) { } - } - interface Bar {} - void test1(T t, S s) { - t.m(t.x); - } +/** + * Interface with toString declared. + */ +public interface InterfaceWithToString { + + void someMethod(); + + /** + * Same as Object.toString(). + * + * @return some custom string. + */ + String toString(); } diff --git a/hotspot/test/runtime/jni/ToStringInInterfaceTest/ToStringTest.java b/hotspot/test/runtime/jni/ToStringInInterfaceTest/ToStringTest.java new file mode 100644 index 00000000000..02d4d55365e --- /dev/null +++ b/hotspot/test/runtime/jni/ToStringInInterfaceTest/ToStringTest.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 8072588 + * @build InterfaceWithToString + * @build ImplementationOfWithToString + * @run main/native ToStringTest + */ +public final class ToStringTest { + + static { + System.loadLibrary("ToStringTest"); + } + + native static void nTest(); + + public static void main(String[] args) throws Exception { + nTest(); + } +} diff --git a/hotspot/test/runtime/jni/ToStringInInterfaceTest/libToStringTest.c b/hotspot/test/runtime/jni/ToStringInInterfaceTest/libToStringTest.c new file mode 100644 index 00000000000..2c4750fac07 --- /dev/null +++ b/hotspot/test/runtime/jni/ToStringInInterfaceTest/libToStringTest.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * Native test for ToStringInInterfaceTest. + */ + +#include "jni.h" + +#define checkException(env) if ((*env)->ExceptionCheck(env)) { return; } + +jstring callStringMethod(JNIEnv* env, jobject jobj, jmethodID id, ...) +{ + jstring value; + + va_list ap; + va_start(ap, id); + value = (jstring)(*env)->CallObjectMethodV(env, jobj, id, ap); + va_end(ap); + return value; +} + +JNIEXPORT void JNICALL Java_ToStringTest_nTest(JNIEnv* env, jclass jclazz) +{ + jclass classOfInterfaceWithToString; + jclass classOfImplementationOfWithToString; + jmethodID constructorOfImplementationOfWithToString; + jobject instanceOfImplementationOfWithToString; + jmethodID toStringOfInterfaceWithToString; + jmethodID toStringOfImplementationOfWithToString; + jstring jstr; + const char *chars; + + classOfInterfaceWithToString = (*env)->FindClass(env, "InterfaceWithToString"); + checkException(env); + classOfImplementationOfWithToString = (*env)->FindClass(env, "ImplementationOfWithToString"); + checkException(env); + + constructorOfImplementationOfWithToString = (*env)->GetMethodID(env, classOfImplementationOfWithToString, "", "()V"); + checkException(env); + + instanceOfImplementationOfWithToString = (*env)->NewObject(env, classOfImplementationOfWithToString, constructorOfImplementationOfWithToString); + checkException(env); + + toStringOfInterfaceWithToString = (*env)->GetMethodID(env, classOfInterfaceWithToString, "toString", "()Ljava/lang/String;"); + checkException(env); + + toStringOfImplementationOfWithToString = (*env)->GetMethodID(env, classOfImplementationOfWithToString, "toString", "()Ljava/lang/String;"); + checkException(env); + + jstr = callStringMethod(env, instanceOfImplementationOfWithToString, toStringOfImplementationOfWithToString); + checkException(env); + + chars = (*env)->GetStringUTFChars(env, jstr, NULL); + (*env)->ReleaseStringUTFChars(env, jstr, chars); + + jstr = callStringMethod(env, instanceOfImplementationOfWithToString, toStringOfInterfaceWithToString); + checkException(env); + + chars = (*env)->GetStringUTFChars(env, jstr, NULL); + (*env)->ReleaseStringUTFChars(env, jstr, chars); +} diff --git a/hotspot/test/serviceability/dcmd/gc/RunGCTest.java b/hotspot/test/serviceability/dcmd/gc/RunGCTest.java index d34ca012bea..8746f7f26d6 100644 --- a/hotspot/test/serviceability/dcmd/gc/RunGCTest.java +++ b/hotspot/test/serviceability/dcmd/gc/RunGCTest.java @@ -59,7 +59,7 @@ public class RunGCTest { } OutputAnalyzer output = new OutputAnalyzer(gcLog, ""); - output.shouldMatch(".*\\[Full GC \\(System(\\.gc\\(\\))?.*"); + output.shouldContain("[Full GC (Diagnostic Command)"); } @Test diff --git a/hotspot/test/serviceability/sa/TestClassLoaderStats.java b/hotspot/test/serviceability/sa/TestClassLoaderStats.java index 2f35d6a4edd..92bd3152752 100644 --- a/hotspot/test/serviceability/sa/TestClassLoaderStats.java +++ b/hotspot/test/serviceability/sa/TestClassLoaderStats.java @@ -24,11 +24,14 @@ import jdk.test.lib.Platform; import jdk.test.lib.ProcessTools; import jdk.test.lib.OutputAnalyzer; +import jdk.test.lib.apps.LingeredApp; /* * @test + * @library /../../test/lib/share/classes * @library /testlibrary * @build jdk.test.lib.* + * @build jdk.test.lib.apps.* * @run main TestClassLoaderStats */ public class TestClassLoaderStats { @@ -39,19 +42,27 @@ public class TestClassLoaderStats { return; } - ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder( - "-XX:+UsePerfData", - "sun.jvm.hotspot.tools.ClassLoaderStats", - Integer.toString(ProcessTools.getProcessId())); - OutputAnalyzer output = ProcessTools.executeProcess(processBuilder); - System.out.println(output.getOutput()); + LingeredApp app = null; + try { + app = LingeredApp.startApp(); - output.shouldHaveExitValue(0); - output.shouldContain("Debugger attached successfully."); - // The class loader stats header needs to be presented in the output: - output.shouldMatch("class_loader\\W+classes\\W+bytes\\W+parent_loader\\W+alive?\\W+type"); - output.stderrShouldNotMatch("[E|e]xception"); - output.stderrShouldNotMatch("[E|e]rror"); + System.out.println("Attaching sun.jvm.hotspot.tools.ClassLoaderStats to " + app.getPid()); + ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder( + "-XX:+UsePerfData", + "sun.jvm.hotspot.tools.ClassLoaderStats", + Long.toString(app.getPid())); + OutputAnalyzer output = ProcessTools.executeProcess(processBuilder); + System.out.println(output.getOutput()); + + output.shouldHaveExitValue(0); + output.shouldContain("Debugger attached successfully."); + // The class loader stats header needs to be presented in the output: + output.shouldMatch("class_loader\\W+classes\\W+bytes\\W+parent_loader\\W+alive?\\W+type"); + output.stderrShouldNotMatch("[E|e]xception"); + output.stderrShouldNotMatch("[E|e]rror"); + } finally { + app.stopApp(); + } } } diff --git a/hotspot/test/serviceability/sa/TestStackTrace.java b/hotspot/test/serviceability/sa/TestStackTrace.java index ba5a56a031d..6d5eb7b4d21 100644 --- a/hotspot/test/serviceability/sa/TestStackTrace.java +++ b/hotspot/test/serviceability/sa/TestStackTrace.java @@ -24,11 +24,14 @@ import jdk.test.lib.OutputAnalyzer; import jdk.test.lib.Platform; import jdk.test.lib.ProcessTools; +import jdk.test.lib.apps.LingeredApp; /* * @test + * @library /../../test/lib/share/classes * @library /testlibrary * @build jdk.test.lib.* + * @build jdk.test.lib.apps.* * @run main TestStackTrace */ public class TestStackTrace { @@ -39,17 +42,25 @@ public class TestStackTrace { return; } - ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder( - "-XX:+UsePerfData", - "sun.jvm.hotspot.tools.StackTrace", - Integer.toString(ProcessTools.getProcessId())); - OutputAnalyzer output = ProcessTools.executeProcess(processBuilder); - System.out.println(output.getOutput()); + LingeredApp app = null; + try { + app = LingeredApp.startApp(); - output.shouldHaveExitValue(0); - output.shouldContain("Debugger attached successfully."); - output.stderrShouldNotMatch("[E|e]xception"); - output.stderrShouldNotMatch("[E|e]rror"); + System.out.println("Attaching sun.jvm.hotspot.tools.StackTrace to " + app.getPid()); + ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder( + "-XX:+UsePerfData", + "sun.jvm.hotspot.tools.StackTrace", + Long.toString(app.getPid())); + OutputAnalyzer output = ProcessTools.executeProcess(processBuilder); + System.out.println(output.getOutput()); + + output.shouldHaveExitValue(0); + output.shouldContain("Debugger attached successfully."); + output.stderrShouldNotMatch("[E|e]xception"); + output.stderrShouldNotMatch("[E|e]rror"); + } finally { + app.stopApp(); + } } } diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 3ed239facb6..fa176f60ff2 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -310,3 +310,5 @@ f4a4a54620370f077c2e830a5561c8cfa811712b jdk9-b61 ae7406e82828fe1c245ac7507a9da5fd5b1c9529 jdk9-b65 d5963ccce28d7a3e96ee3e2dc8a8676e61699b70 jdk9-b66 78c2685daabafae827c686ca2d1bb2e451faed2b jdk9-b67 +82aae947938ec9b0119fdd78a616d0b7263072ee jdk9-b68 +f844a908d3308f47d73cf64e87c98d37d5d76ce8 jdk9-b69 diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/compiler/FunctionTable.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/compiler/FunctionTable.java index 2b653aca47e..6d5b7ff3394 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/compiler/FunctionTable.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/compiler/FunctionTable.java @@ -1,21 +1,23 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. */ -/* - * Copyright 1999-2005 The Apache Software Foundation. +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ /* * $Id: FunctionTable.java,v 1.3 2005/09/28 13:49:34 pvedula Exp $ @@ -135,6 +137,9 @@ public class FunctionTable /** The 'unparsed-entity-uri()' id (XSLT). */ public static final int FUNC_UNPARSED_ENTITY_URI = 36; + /** The 'here()' id (XML Signature). */ + public static final int FUNC_HERE = 37; + // Proprietary /** The 'document-location()' id (Proprietary). */ @@ -162,7 +167,7 @@ public class FunctionTable * Number of built in functions. Be sure to update this as * built-in functions are added. */ - private static final int NUM_BUILT_IN_FUNCS = 37; + private static final int NUM_BUILT_IN_FUNCS = 38; /** * Number of built-in functions that may be added. @@ -229,6 +234,8 @@ public class FunctionTable com.sun.org.apache.xpath.internal.functions.FuncDoclocation.class; m_functions[FUNC_UNPARSED_ENTITY_URI] = com.sun.org.apache.xpath.internal.functions.FuncUnparsedEntityURI.class; + m_functions[FUNC_HERE] = + com.sun.org.apache.xpath.internal.functions.FuncHere.class; } static{ @@ -302,6 +309,8 @@ public class FunctionTable new Integer(FunctionTable.FUNC_UNPARSED_ENTITY_URI)); m_functionID.put(Keywords.FUNC_DOCLOCATION_STRING, new Integer(FunctionTable.FUNC_DOCLOCATION)); + m_functionID.put(Keywords.FUNC_HERE_STRING, + new Integer(FunctionTable.FUNC_HERE)); } public FunctionTable(){ diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/compiler/Keywords.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/compiler/Keywords.java index 4c422c9175c..e0e47d988c5 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/compiler/Keywords.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/compiler/Keywords.java @@ -1,21 +1,23 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. */ -/* - * Copyright 1999-2005 The Apache Software Foundation. +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ /* * $Id: Keywords.java,v 1.2.4.1 2005/09/14 19:46:01 jeffsuttor Exp $ @@ -210,6 +212,9 @@ public class Keywords public static final String FUNC_UNPARSED_ENTITY_URI_STRING = "unparsed-entity-uri"; + /** here function string (XML Signature). */ + public static final String FUNC_HERE_STRING = "here"; + // Proprietary, built in functions /** current function string (Proprietary). */ diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/functions/FuncHere.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/functions/FuncHere.java new file mode 100644 index 00000000000..e52c08d5435 --- /dev/null +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/functions/FuncHere.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + */ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package com.sun.org.apache.xpath.internal.functions; + +import javax.xml.transform.TransformerException; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import com.sun.org.apache.xml.internal.dtm.DTM; +import com.sun.org.apache.xpath.internal.NodeSetDTM; +import com.sun.org.apache.xpath.internal.XPathContext; +import com.sun.org.apache.xpath.internal.objects.XNodeSet; +import com.sun.org.apache.xpath.internal.objects.XObject; +import com.sun.org.apache.xpath.internal.res.XPATHErrorResources; + +/** + * Execute the XML Signature here() function. + */ +public final class FuncHere extends Function { + + private static final long serialVersionUID = 4328660760070034592L; + + @Override + public XObject execute(XPathContext xctxt) throws TransformerException { + Node xpathOwnerNode = (Node)xctxt.getOwnerObject(); + if (xpathOwnerNode == null) { + return null; + } + + int xpathOwnerNodeDTM = xctxt.getDTMHandleFromNode(xpathOwnerNode); + int currentNode = xctxt.getCurrentNode(); + DTM dtm = xctxt.getDTM(currentNode); + int docContext = dtm.getDocument(); + + if (docContext == DTM.NULL) { + error(xctxt, XPATHErrorResources.ER_CONTEXT_HAS_NO_OWNERDOC, null); + } + + // check whether currentNode and the node containing the XPath + // expression are in the same document + Document currentDoc = getOwnerDocument(dtm.getNode(currentNode)); + Document xpathOwnerDoc = getOwnerDocument(xpathOwnerNode); + + if (currentDoc != xpathOwnerDoc) { + throw new TransformerException("Owner documents differ"); + } + + XNodeSet nodes = new XNodeSet(xctxt.getDTMManager()); + NodeSetDTM nodeSet = nodes.mutableNodeset(); + + int hereNode = DTM.NULL; + + switch (dtm.getNodeType(xpathOwnerNodeDTM)) { + + case Node.ATTRIBUTE_NODE: + case Node.PROCESSING_INSTRUCTION_NODE: { + // returns a node-set containing the attribute / processing + // instruction node + hereNode = xpathOwnerNodeDTM; + nodeSet.addNode(hereNode); + break; + } + case Node.TEXT_NODE : { + // returns a node-set containing the parent element of the + // text node that directly bears the XPath expression + hereNode = dtm.getParent(xpathOwnerNodeDTM); + nodeSet.addNode(hereNode); + break; + } + default : + break; + } + + /** $todo$ Do I have to do this detach() call? */ + nodeSet.detach(); + + return nodes; + } + + private static Document getOwnerDocument(Node node) { + if (node.getNodeType() == Node.DOCUMENT_NODE) { + return (Document)node; + } + return node.getOwnerDocument(); + } + + @Override + public void fixupVariables(java.util.Vector vars, int globalsSize) { } +} diff --git a/jaxp/test/javax/xml/jaxp/functional/TEST.properties b/jaxp/test/javax/xml/jaxp/functional/TEST.properties index a8ef42cafa3..f94f3b92152 100644 --- a/jaxp/test/javax/xml/jaxp/functional/TEST.properties +++ b/jaxp/test/javax/xml/jaxp/functional/TEST.properties @@ -7,3 +7,6 @@ lib.dirs = /javax/xml/jaxp/libs # Tests that must run in othervm mode othervm.dirs= /javax/xml/jaxp/functional +# Declare module dependency +modules=java.xml + diff --git a/jaxp/test/javax/xml/jaxp/functional/javax/xml/parsers/ptests/DocumentBuilderFactoryTest.java b/jaxp/test/javax/xml/jaxp/functional/javax/xml/parsers/ptests/DocumentBuilderFactoryTest.java index f2ab3f565f8..77196ee720d 100644 --- a/jaxp/test/javax/xml/jaxp/functional/javax/xml/parsers/ptests/DocumentBuilderFactoryTest.java +++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/parsers/ptests/DocumentBuilderFactoryTest.java @@ -23,28 +23,32 @@ package javax.xml.parsers.ptests; +import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI; +import static javax.xml.parsers.ptests.ParserTestConst.GOLDEN_DIR; +import static javax.xml.parsers.ptests.ParserTestConst.XML_DIR; +import static jaxp.library.JAXPTestUtilities.USER_DIR; +import static jaxp.library.JAXPTestUtilities.compareWithGold; +import static jaxp.library.JAXPTestUtilities.filenameToURL; import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertTrue; import java.io.BufferedReader; +import java.io.Closeable; import java.io.File; import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.FilePermission; import java.io.FileReader; -import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI; - import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.FactoryConfigurationError; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; - -import static javax.xml.parsers.ptests.ParserTestConst.GOLDEN_DIR; -import static javax.xml.parsers.ptests.ParserTestConst.XML_DIR; - import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; @@ -52,10 +56,6 @@ import javax.xml.transform.sax.SAXResult; import jaxp.library.JAXPDataProvider; import jaxp.library.JAXPFileBaseTest; -import static jaxp.library.JAXPTestUtilities.USER_DIR; -import static jaxp.library.JAXPTestUtilities.compareWithGold; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertTrue; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -67,6 +67,7 @@ import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; /** + * @bug 8080907 * This checks the methods of DocumentBuilderFactoryImpl. */ public class DocumentBuilderFactoryTest extends JAXPFileBaseTest { @@ -134,28 +135,11 @@ public class DocumentBuilderFactoryTest extends JAXPFileBaseTest { assertFalse(eh.isErrorOccured()); } - /** - * Test the default functionality of schema support method. In - * this case the schema source property is set. - * @throws Exception If any errors occur. - */ - @Test - public void testCheckSchemaSupport2() throws Exception { - try (FileInputStream fis = new FileInputStream(new File( - XML_DIR, "test.xsd"))) { - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - dbf.setValidating(true); - dbf.setNamespaceAware(true); - dbf.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaLanguage", - W3C_XML_SCHEMA_NS_URI); - dbf.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaSource", - new InputSource(fis)); - MyErrorHandler eh = MyErrorHandler.newInstance(); - DocumentBuilder db = dbf.newDocumentBuilder(); - db.setErrorHandler(eh); - db.parse(new File(XML_DIR, "test1.xml")); - assertFalse(eh.isErrorOccured()); - } + @DataProvider(name = "schema-source") + public Object[][] getSchemaSource() throws FileNotFoundException { + return new Object[][] { + { new FileInputStream(new File(XML_DIR, "test.xsd")) }, + { new InputSource(filenameToURL(XML_DIR + "test.xsd")) } }; } /** @@ -163,22 +147,50 @@ public class DocumentBuilderFactoryTest extends JAXPFileBaseTest { * this case the schema source property is set. * @throws Exception If any errors occur. */ - @Test - public void testCheckSchemaSupport3() throws Exception { - try (FileInputStream fis = new FileInputStream(new File( - XML_DIR, "test.xsd"))) { + @Test(dataProvider = "schema-source") + public void testCheckSchemaSupport2(Object schemaSource) throws Exception { + try { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + dbf.setValidating(true); + dbf.setNamespaceAware(true); + dbf.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaLanguage", + W3C_XML_SCHEMA_NS_URI); + dbf.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaSource", schemaSource); + MyErrorHandler eh = MyErrorHandler.newInstance(); + DocumentBuilder db = dbf.newDocumentBuilder(); + db.setErrorHandler(eh); + db.parse(new File(XML_DIR, "test1.xml")); + assertFalse(eh.isErrorOccured()); + } finally { + if (schemaSource instanceof Closeable) { + ((Closeable) schemaSource).close(); + } + } + + } + + /** + * Test the default functionality of schema support method. In + * this case the schema source property is set. + * @throws Exception If any errors occur. + */ + @Test(dataProvider = "schema-source") + public void testCheckSchemaSupport3(Object schemaSource) throws Exception { + try { SAXParserFactory spf = SAXParserFactory.newInstance(); - spf.setNamespaceAware(true); spf.setValidating(true); spf.setNamespaceAware(true); SAXParser sp = spf.newSAXParser(); sp.setProperty("http://java.sun.com/xml/jaxp/properties/schemaLanguage", W3C_XML_SCHEMA_NS_URI); - sp.setProperty("http://java.sun.com/xml/jaxp/properties/schemaSource", - new InputSource(fis)); + sp.setProperty("http://java.sun.com/xml/jaxp/properties/schemaSource", schemaSource); DefaultHandler dh = new DefaultHandler(); // Not expect any unrecoverable error here. sp.parse(new File(XML_DIR, "test1.xml"), dh); + } finally { + if (schemaSource instanceof Closeable) { + ((Closeable) schemaSource).close(); + } } } diff --git a/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/ptests/SchemaFactoryTest.java b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/ptests/SchemaFactoryTest.java index f2665263556..1cdcbf7e073 100644 --- a/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/ptests/SchemaFactoryTest.java +++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/ptests/SchemaFactoryTest.java @@ -27,6 +27,7 @@ import static javax.xml.validation.ptests.ValidationTestConst.XML_DIR; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertSame; +import static org.testng.Assert.assertTrue; import java.io.ByteArrayInputStream; import java.io.File; @@ -39,9 +40,12 @@ import java.nio.file.Paths; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; import javax.xml.transform.Source; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.sax.SAXSource; +import javax.xml.transform.stax.StAXSource; import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; @@ -60,6 +64,7 @@ import org.xml.sax.SAXNotSupportedException; import org.xml.sax.SAXParseException; /* + * @bug 8080907 * @summary Class containing the test cases for SchemaFactory */ @Test(singleThreaded = true) @@ -68,9 +73,10 @@ public class SchemaFactoryTest { @BeforeClass public void setup() throws SAXException, IOException, ParserConfigurationException { sf = newSchemaFactory(); - assertNotNull(sf); + ifac = XMLInputFactory.newInstance(); + xsd1 = Files.readAllBytes(Paths.get(XML_DIR + "test.xsd")); xsd2 = Files.readAllBytes(Paths.get(XML_DIR + "test1.xsd")); @@ -152,11 +158,13 @@ public class SchemaFactoryTest { } @DataProvider(name = "valid-source") - public Object[][] getValidSource() { + public Object[][] getValidSource() throws XMLStreamException { return new Object[][] { { streamSource(xsd1) }, { saxSource(xsd1) }, - { domSource(xsdDoc1) } }; + { domSource(xsdDoc1) }, + { staxStreamSource(xsd1) }, + { staxEventSource(xsd1) } }; } @@ -299,6 +307,34 @@ public class SchemaFactoryTest { sf.setFeature(null, true); } + @DataProvider(name = "source-feature") + public Object[][] getSourceFeature() { + return new Object[][] { + { StreamSource.FEATURE }, + { SAXSource.FEATURE }, + { DOMSource.FEATURE }, + { DOMSource.FEATURE } }; + + } + + /* + * Return true for each of the JAXP Source features to indicate that this + * SchemaFactory supports all of the built-in JAXP Source types. + */ + @Test(dataProvider = "source-feature") + public void testSourceFeatureGet(String sourceFeature) throws Exception { + assertTrue(newSchemaFactory().getFeature(sourceFeature)); + } + + /* + * JAXP Source features are read-only because this SchemaFactory always + * supports all JAXP Source types. + */ + @Test(dataProvider = "source-feature", expectedExceptions = SAXNotSupportedException.class) + public void testSourceFeatureSet(String sourceFeature) throws Exception { + newSchemaFactory().setFeature(sourceFeature, false); + } + @Test(expectedExceptions = IllegalArgumentException.class) public void testInvalidSchemaLanguage() { final String INVALID_SCHEMA_LANGUAGE = "http://relaxng.org/ns/structure/1.0"; @@ -337,6 +373,15 @@ public class SchemaFactoryTest { return new DOMSource(xsdDoc); } + private Source staxStreamSource(byte[] xsd) throws XMLStreamException { + return new StAXSource(ifac.createXMLStreamReader(newInputStream(xsd))); + } + + private Source staxEventSource(byte[] xsd) throws XMLStreamException { + return new StAXSource(ifac.createXMLEventReader(newInputStream(xsd))); + } + + private SchemaFactory newSchemaFactory() { return SchemaFactory.newInstance(W3C_XML_SCHEMA_NS_URI); } @@ -346,6 +391,7 @@ public class SchemaFactoryTest { private static final String SCHEMA_FACTORY_CLASSNAME = "com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory"; private SchemaFactory sf; + private XMLInputFactory ifac; private byte[] xsd1; private byte[] xsd2; private Document xsdDoc1; diff --git a/jaxp/test/javax/xml/jaxp/unittest/TEST.properties b/jaxp/test/javax/xml/jaxp/unittest/TEST.properties index e8445deaa68..23136c131a5 100644 --- a/jaxp/test/javax/xml/jaxp/unittest/TEST.properties +++ b/jaxp/test/javax/xml/jaxp/unittest/TEST.properties @@ -1,3 +1,6 @@ # jaxp test uses TestNG TestNG.dirs = . +# Declare module dependency +modules=java.xml + diff --git a/jaxp/test/javax/xml/jaxp/unittest/javax/xml/parsers/xinclude/Bug6794483Test.java b/jaxp/test/javax/xml/jaxp/unittest/javax/xml/parsers/xinclude/Bug6794483Test.java index 735efe8932b..ee5e2587d6c 100644 --- a/jaxp/test/javax/xml/jaxp/unittest/javax/xml/parsers/xinclude/Bug6794483Test.java +++ b/jaxp/test/javax/xml/jaxp/unittest/javax/xml/parsers/xinclude/Bug6794483Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,37 +23,47 @@ package javax.xml.parsers.xinclude; +import static java.lang.System.lineSeparator; +import static org.testng.Assert.assertEquals; + import java.io.File; -import java.io.IOException; import java.io.StringWriter; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerConfigurationException; -import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; -import org.testng.Assert; import org.testng.annotations.Test; import org.w3c.dom.Document; -import org.xml.sax.SAXException; +import org.w3c.dom.NodeList; /* - * @bug 6794483 - * @summary Test JAXP parser can parse xml file using to include another xml, which has an empty element. + * @bug 6794483 8080908 + * @summary Test JAXP parser can resolve the included content properly if the + * included xml contains an empty tag that ends with "/>", refer to XERCESJ-1134. */ public class Bug6794483Test { @Test - public final void test() { - String xml = getClass().getResource("test1.xml").getPath(); - Document doc = parseXmlFile(xml); + public final void test() throws Exception { + Document doc = parseXmlFile(getClass().getResource("test1.xml").getPath()); + // check node4 + NodeList nodeList = doc.getElementsByTagName("node4"); + assertEquals(nodeList.getLength(), 1); + assertEquals(nodeList.item(0).getTextContent(), "Node4 Value", "The data of node4 is missed in parsing: " + lineSeparator() + printXmlDoc(doc)); + + // check node6 + nodeList = doc.getElementsByTagName("node6"); + assertEquals(nodeList.getLength(), 1); + assertEquals(nodeList.item(0).getTextContent(), "Node6 Value", "The data of node6 is missed in parsing: " + lineSeparator() + printXmlDoc(doc)); + } + + public String printXmlDoc(Document doc) throws Exception { StringWriter sw = new StringWriter(); StreamResult result = new StreamResult(sw); @@ -61,27 +71,16 @@ public class Bug6794483Test { transformerFact.setAttribute("indent-number", new Integer(4)); Transformer transformer; - try { - transformer = transformerFact.newTransformer(); - transformer.setOutputProperty(OutputKeys.INDENT, "yes"); - transformer.setOutputProperty(OutputKeys.METHOD, "xml"); - transformer.setOutputProperty(OutputKeys.MEDIA_TYPE, "text/xml"); - - // "true" indicate Append content If file exist in system - transformer.transform(new DOMSource(doc), result); - System.out.println("test" + sw); - - } catch (TransformerConfigurationException ex) { - ex.printStackTrace(); - Assert.fail("unexpected TransformerConfigurationException"); - } catch (TransformerException ex) { - ex.printStackTrace(); - Assert.fail("unexpected TransformerException"); - } + transformer = transformerFact.newTransformer(); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.setOutputProperty(OutputKeys.METHOD, "xml"); + transformer.setOutputProperty(OutputKeys.MEDIA_TYPE, "text/xml"); + transformer.transform(new DOMSource(doc), result); + return sw.toString(); } - public Document parseXmlFile(String fileName) { + public Document parseXmlFile(String fileName) throws Exception { System.out.println("Parsing XML file... " + fileName); DocumentBuilder docBuilder = null; Document doc = null; @@ -92,20 +91,10 @@ public class Bug6794483Test { docBuilderFactory.setNamespaceAware(true); docBuilderFactory.setExpandEntityReferences(true); - try { - docBuilder = docBuilderFactory.newDocumentBuilder(); - } catch (ParserConfigurationException e) { - e.printStackTrace(); - } + docBuilder = docBuilderFactory.newDocumentBuilder(); File sourceFile = new File(fileName); - try { - doc = docBuilder.parse(sourceFile); - } catch (SAXException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } + doc = docBuilder.parse(sourceFile); System.out.println("XML file parsed"); return doc; diff --git a/jaxp/test/javax/xml/jaxp/unittest/javax/xml/validation/AnyElementTest.java b/jaxp/test/javax/xml/jaxp/unittest/javax/xml/validation/AnyElementTest.java new file mode 100644 index 00000000000..f37f0bfab28 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/unittest/javax/xml/validation/AnyElementTest.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package javax.xml.validation; + +/* + * @bug 8080907 + * @summary Test processContents attribute of any element + */ +import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI; + +import java.net.URISyntaxException; + +import javax.xml.transform.stream.StreamSource; + +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; + +public class AnyElementTest { + @BeforeClass + public void setup() throws URISyntaxException, SAXException { + validator = SchemaFactory.newInstance(W3C_XML_SCHEMA_NS_URI).newSchema(new StreamSource(getUri("ProcessContents.xsd"))).newValidator(); + } + + /* + * processContents attribute - Specifies how the XML processor should handle + * validation against the elements specified by this any element. Can be set + * to one of the following: + * strict - the XML processor must obtain the schema for the required + * namespaces and validate the elements (this is default) + * lax - same as strict, but if the schema cannot be obtained, no errors + * will occur + * skip - The XML processor does not attempt to validate any elements from + * the specified namespaces + */ + @Test + public void testProcessContents() throws Exception { + validator.validate(new StreamSource(getUri("ProcessContents-ok.xml"))); + } + + /* + * When processContents="lax", validation will be performed when the element + * is declared in the schema. + */ + @Test(expectedExceptions = SAXParseException.class) + public void testProcessContentsLax() throws Exception { + validator.validate(new StreamSource(getUri("ProcessContents-lax-error.xml"))); + } + + /* + * Get the URI of the file, which is in the same path as this class + */ + private String getUri(String fileName) throws URISyntaxException { + return this.getClass().getResource(fileName).toURI().toASCIIString(); + } + + private Validator validator; +} diff --git a/jaxp/test/javax/xml/jaxp/unittest/javax/xml/validation/ProcessContents-lax-error.xml b/jaxp/test/javax/xml/jaxp/unittest/javax/xml/validation/ProcessContents-lax-error.xml new file mode 100644 index 00000000000..b75125f5338 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/unittest/javax/xml/validation/ProcessContents-lax-error.xml @@ -0,0 +1,4 @@ + + + 25.5 + \ No newline at end of file diff --git a/jaxp/test/javax/xml/jaxp/unittest/javax/xml/validation/ProcessContents-ok.xml b/jaxp/test/javax/xml/jaxp/unittest/javax/xml/validation/ProcessContents-ok.xml new file mode 100644 index 00000000000..8c2675ca9a5 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/unittest/javax/xml/validation/ProcessContents-ok.xml @@ -0,0 +1,21 @@ + + + 255 + + 2.55 + + + 25.5 + + + TTT + + + + 2555 + TTT + + 20 + + + diff --git a/jaxp/test/javax/xml/jaxp/unittest/javax/xml/validation/ProcessContents.xsd b/jaxp/test/javax/xml/jaxp/unittest/javax/xml/validation/ProcessContents.xsd new file mode 100644 index 00000000000..74229b824ff --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/unittest/javax/xml/validation/ProcessContents.xsd @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/jaxp/test/javax/xml/jaxp/unittest/org/w3c/dom/ls/LSSerializerTest.java b/jaxp/test/javax/xml/jaxp/unittest/org/w3c/dom/ls/LSSerializerTest.java index 56aafde0bb5..0213f82a0d6 100644 --- a/jaxp/test/javax/xml/jaxp/unittest/org/w3c/dom/ls/LSSerializerTest.java +++ b/jaxp/test/javax/xml/jaxp/unittest/org/w3c/dom/ls/LSSerializerTest.java @@ -44,6 +44,7 @@ import org.xml.sax.SAXException; /* + * @bug 6439439 8080906 * @summary Test LSSerializer. */ public class LSSerializerTest { @@ -98,6 +99,17 @@ public class LSSerializerTest { } } + /* + * @bug 8080906 + * It will fail in a Jigsaw build until JDK-8080266 is fixed. + */ + @Test + public void testDefaultLSSerializer() throws Exception { + DOMImplementationLS domImpl = (DOMImplementationLS) DocumentBuilderFactory.newInstance().newDocumentBuilder().getDOMImplementation(); + LSSerializer lsSerializer = domImpl.createLSSerializer(); + Assert.assertTrue(lsSerializer.getClass().getName().endsWith("dom3.LSSerializerImpl")); + } + @Test public void testDOMErrorHandler() { diff --git a/jaxws/.hgtags b/jaxws/.hgtags index 8dda55983d4..9be6ec92c3e 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -313,3 +313,5 @@ df100399ed27d0eaa57c137ca99819a0fee66178 jdk9-b64 45ef73bb85c12ec1b291835c1d40e342a454e3f0 jdk9-b65 1232f4013417e4a9cd291096798d10f2e601d69d jdk9-b66 c9785bc8ade98a16a050d7520b70c68363857e00 jdk9-b67 +b5878b03d1b2e105917d959fbfa3c57c22495803 jdk9-b68 +f5911c6155c29ac24b6f9068273207e5ebd3a3df jdk9-b69 diff --git a/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/ContextFinder.java b/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/ContextFinder.java index 18ff8196bc7..a0329cf7744 100644 --- a/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/ContextFinder.java +++ b/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/ContextFinder.java @@ -68,6 +68,9 @@ class ContextFinder { */ private static final String PLATFORM_DEFAULT_FACTORY_CLASS = "com.sun.xml.internal.bind.v2.ContextFactory"; + // previous value of JAXBContext.JAXB_CONTEXT_FACTORY, using also this to ensure backwards compatibility + private static final String JAXB_CONTEXT_FACTORY_DEPRECATED = "javax.xml.bind.context.factory"; + private static final Logger logger; static { @@ -92,6 +95,14 @@ class ContextFinder { } } + private static ServiceLoaderUtil.ExceptionHandler EXCEPTION_HANDLER = + new ServiceLoaderUtil.ExceptionHandler() { + @Override + public JAXBException createException(Throwable throwable, String message) { + return new JAXBException(message, throwable); + } + }; + /** * If the {@link InvocationTargetException} wraps an exception that shouldn't be wrapped, * throw the wrapped exception. @@ -159,7 +170,10 @@ class ContextFinder { } } - static JAXBContext newInstance(String contextPath, Class spFactory, ClassLoader classLoader, Map properties) throws JAXBException { + static JAXBContext newInstance(String contextPath, + Class spFactory, + ClassLoader classLoader, + Map properties) throws JAXBException { try { /* @@ -239,6 +253,7 @@ class ContextFinder { Map properties, Class spFactory) throws JAXBException { try { + Method m = spFactory.getMethod("createContext", Class[].class, Map.class); Object context = m.invoke(null, classes, properties); if (!(context instanceof JAXBContext)) { @@ -246,10 +261,10 @@ class ContextFinder { throw handleClassCastException(context.getClass(), JAXBContext.class); } return (JAXBContext) context; - } catch (NoSuchMethodException e) { - throw new JAXBException(e); - } catch (IllegalAccessException e) { + + } catch (NoSuchMethodException | IllegalAccessException e) { throw new JAXBException(e); + } catch (InvocationTargetException e) { handleInvocationTargetException(e); @@ -261,9 +276,10 @@ class ContextFinder { } } - static JAXBContext find(String factoryId, String contextPath, ClassLoader classLoader, Map properties) throws JAXBException { - - // TODO: do we want/need another layer of searching in $java.home/lib/jaxb.properties like JAXP? + static JAXBContext find(String factoryId, + String contextPath, + ClassLoader classLoader, + Map properties) throws JAXBException { StringTokenizer packages = new StringTokenizer(contextPath, ":"); if (!packages.hasMoreTokens()) { @@ -275,63 +291,85 @@ class ContextFinder { logger.fine("Searching jaxb.properties"); while (packages.hasMoreTokens()) { // com.acme.foo - > com/acme/foo/jaxb.properties - String className = classNameFromPackageProperties(factoryId, classLoader, packages.nextToken(":").replace('.', '/')); - if (className != null) return newInstance(contextPath, className, classLoader, properties); + String factoryClassName = + classNameFromPackageProperties( + classLoader, + packages.nextToken(":").replace('.', '/'), + factoryId, + JAXB_CONTEXT_FACTORY_DEPRECATED); + + if (factoryClassName != null) { + return newInstance(contextPath, factoryClassName, classLoader, properties); + } } String factoryName = classNameFromSystemProperties(); if (factoryName != null) return newInstance(contextPath, factoryName, classLoader, properties); - Class ctxFactory = (Class) ServiceLoaderUtil.lookupUsingOSGiServiceLoader("javax.xml.bind.JAXBContext", logger); + JAXBContextFactory obj = ServiceLoaderUtil.firstByServiceLoader( + JAXBContextFactory.class, logger, EXCEPTION_HANDLER); + + if (obj != null) return obj.createContext(contextPath, classLoader, properties); + + // to ensure backwards compatibility + factoryName = firstByServiceLoaderDeprecated(JAXBContext.class, classLoader); + if (factoryName != null) return newInstance(contextPath, factoryName, classLoader, properties); + + Class ctxFactory = (Class) ServiceLoaderUtil.lookupUsingOSGiServiceLoader( + "javax.xml.bind.JAXBContext", logger); + if (ctxFactory != null) { return newInstance(contextPath, ctxFactory, classLoader, properties); } - // TODO: SPEC change required! This is supposed to be! - // JAXBContext obj = firstByServiceLoader(JAXBContext.class, EXCEPTION_HANDLER); - // if (obj != null) return obj; - - // TODO: Deprecated - SPEC change required! - factoryName = firstByServiceLoaderDeprecated(JAXBContext.class, classLoader); - if (factoryName != null) return newInstance(contextPath, factoryName, classLoader, properties); - // else no provider found logger.fine("Trying to create the platform default provider"); return newInstance(contextPath, PLATFORM_DEFAULT_FACTORY_CLASS, classLoader, properties); } - static JAXBContext find(Class[] classes, Map properties) throws JAXBException { + static JAXBContext find(Class[] classes, Map properties) throws JAXBException { // search for jaxb.properties in the class loader of each class first logger.fine("Searching jaxb.properties"); for (final Class c : classes) { // this classloader is used only to load jaxb.properties, so doing this should be safe. - if (c.getPackage() == null) continue; // this is possible for primitives, arrays, and classes that are loaded by poorly implemented ClassLoaders + // this is possible for primitives, arrays, and classes that are + // loaded by poorly implemented ClassLoaders + if (c.getPackage() == null) continue; // TODO: do we want to optimize away searching the same package? org.Foo, org.Bar, com.Baz // classes from the same package might come from different class loades, so it might be a bad idea // TODO: it's easier to look things up from the class // c.getResourceAsStream("jaxb.properties"); - String className = classNameFromPackageProperties(JAXBContext.JAXB_CONTEXT_FACTORY, getClassClassLoader(c), c.getPackage().getName().replace('.', '/')); - if (className != null) return newInstance(classes, properties, className); + String factoryClassName = + classNameFromPackageProperties( + getClassClassLoader(c), + c.getPackage().getName().replace('.', '/'), + JAXBContext.JAXB_CONTEXT_FACTORY, JAXB_CONTEXT_FACTORY_DEPRECATED); + + if (factoryClassName != null) return newInstance(classes, properties, factoryClassName); } - String factoryName = classNameFromSystemProperties(); - if (factoryName != null) return newInstance(classes, properties, factoryName); + String factoryClassName = classNameFromSystemProperties(); + if (factoryClassName != null) return newInstance(classes, properties, factoryClassName); - Class ctxFactoryClass = (Class) ServiceLoaderUtil.lookupUsingOSGiServiceLoader("javax.xml.bind.JAXBContext", logger); - if (ctxFactoryClass != null) { - return newInstance(classes, properties, ctxFactoryClass); - } + JAXBContextFactory factory = + ServiceLoaderUtil.firstByServiceLoader(JAXBContextFactory.class, logger, EXCEPTION_HANDLER); - // TODO: to be removed - deprecated!!! Requires SPEC change!!! + if (factory != null) return factory.createContext(classes, properties); + + // to ensure backwards compatibility String className = firstByServiceLoaderDeprecated(JAXBContext.class, getContextClassLoader()); if (className != null) return newInstance(classes, properties, className); - // // TODO: supposed to be: - // obj = firstByServiceLoader(JAXBContext.class, EXCEPTION_HANDLER); - // if (obj != null) return obj; + logger.fine("Trying to create the platform default provider"); + Class ctxFactoryClass = + (Class) ServiceLoaderUtil.lookupUsingOSGiServiceLoader("javax.xml.bind.JAXBContext", logger); + + if (ctxFactoryClass != null) { + return newInstance(classes, properties, ctxFactoryClass); + } // else no provider found logger.fine("Trying to create the platform default provider"); @@ -339,42 +377,69 @@ class ContextFinder { } - private static String classNameFromPackageProperties(String factoryId, ClassLoader classLoader, String packageName) throws JAXBException { + /** + * first factoryId should be the preffered one, + * more of those can be provided to support backwards compatibility + */ + private static String classNameFromPackageProperties(ClassLoader classLoader, + String packageName, + String ... factoryIds) throws JAXBException { + String resourceName = packageName + "/jaxb.properties"; logger.log(Level.FINE, "Trying to locate {0}", resourceName); Properties props = loadJAXBProperties(classLoader, resourceName); if (props != null) { - if (props.containsKey(factoryId)) { - return props.getProperty(factoryId); - } else { - throw new JAXBException(Messages.format(Messages.MISSING_PROPERTY, packageName, factoryId)); + for(String factoryId : factoryIds) { + if (props.containsKey(factoryId)) { + return props.getProperty(factoryId); + } } + throw new JAXBException(Messages.format(Messages.MISSING_PROPERTY, packageName, factoryIds[0])); } return null; } private static String classNameFromSystemProperties() throws JAXBException { - logger.log(Level.FINE, "Checking system property {0}", JAXBContext.JAXB_CONTEXT_FACTORY); - // search for a system property second (javax.xml.bind.JAXBContext) - String factoryClassName = AccessController.doPrivileged(new GetPropertyAction(JAXBContext.JAXB_CONTEXT_FACTORY)); + + String factoryClassName = getSystemProperty(JAXBContext.JAXB_CONTEXT_FACTORY); + if (factoryClassName != null) { + return factoryClassName; + } + // leave this here to assure compatibility + factoryClassName = getDeprecatedSystemProperty(JAXB_CONTEXT_FACTORY_DEPRECATED); + if (factoryClassName != null) { + return factoryClassName; + } + // leave this here to assure compatibility + factoryClassName = getDeprecatedSystemProperty(JAXBContext.class.getName()); if (factoryClassName != null) { - logger.log(Level.FINE, " found {0}", factoryClassName); return factoryClassName; - } else { // leave this here to assure compatibility - logger.fine(" not found"); - logger.log(Level.FINE, "Checking system property {0}", JAXBContext.class.getName()); - factoryClassName = AccessController.doPrivileged(new GetPropertyAction(JAXBContext.class.getName())); - if (factoryClassName != null) { - logger.log(Level.FINE, " found {0}", factoryClassName); - return factoryClassName; - } else { - logger.fine(" not found"); - } } return null; } - private static Properties loadJAXBProperties(ClassLoader classLoader, String propFileName) throws JAXBException { + private static String getDeprecatedSystemProperty(String property) { + String value = getSystemProperty(property); + if (value != null) { + logger.log(Level.WARNING, "Using non-standard property: {0}. Property {1} should be used instead.", + new Object[] {property, JAXBContext.JAXB_CONTEXT_FACTORY}); + } + return value; + } + + private static String getSystemProperty(String property) { + logger.log(Level.FINE, "Checking system property {0}", property); + String value = AccessController.doPrivileged(new GetPropertyAction(property)); + if (value != null) { + logger.log(Level.FINE, " found {0}", value); + } else { + logger.log(Level.FINE, " not found"); + } + return value; + } + + private static Properties loadJAXBProperties(ClassLoader classLoader, + String propFileName) throws JAXBException { Properties props = null; try { @@ -480,17 +545,18 @@ class ContextFinder { } } - // TODO: to be removed - SPEC change required - // ServiceLoaderUtil.firstByServiceLoaderDeprecated should be used instead. + // ServiceLoaderUtil.firstByServiceLoaderDeprecated should be used instead. @Deprecated - static String firstByServiceLoaderDeprecated(Class spiClass, ClassLoader classLoader) throws JAXBException { + static String firstByServiceLoaderDeprecated(Class spiClass, + ClassLoader classLoader) throws JAXBException { + final String jaxbContextFQCN = spiClass.getName(); logger.fine("Searching META-INF/services"); // search META-INF services next BufferedReader r = null; - final String resource = new StringBuilder().append("META-INF/services/").append(jaxbContextFQCN).toString(); + final String resource = "META-INF/services/" + jaxbContextFQCN; try { final InputStream resourceStream = (classLoader == null) ? @@ -510,9 +576,6 @@ class ContextFinder { logger.log(Level.FINE, "Unable to load:{0}", resource); return null; } - } catch (UnsupportedEncodingException e) { - // should never happen - throw new JAXBException(e); } catch (IOException e) { throw new JAXBException(e); } finally { diff --git a/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/JAXBContext.java b/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/JAXBContext.java index d5dc7bc4a5e..376b6738cb5 100644 --- a/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/JAXBContext.java +++ b/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/JAXBContext.java @@ -45,29 +45,20 @@ import java.io.InputStream; * specialized forms of the method available: * *

* - *

- * SPEC REQUIREMENT: the provider must supply an implementation - * class containing the following method signatures: - * - *

{@code
- * public static JAXBContext createContext( String contextPath, ClassLoader classLoader, Map properties ) throws JAXBException
- * public static JAXBContext createContext( Class[] classes, Map properties ) throws JAXBException
- * }
- * *

* The following JAXB 1.0 requirement is only required for schema to * java interface/implementation binding. It does not apply to JAXB annotated @@ -109,11 +100,11 @@ import java.io.InputStream; * any of the schemas listed in the contextPath. For example: * *

- *        JAXBContext jc = JAXBContext.newInstance( "com.acme.foo:com.acme.bar" );
- *        Unmarshaller u = jc.createUnmarshaller();
- *        FooObject fooObj = (FooObject)u.unmarshal( new File( "foo.xml" ) ); // ok
- *        BarObject barObj = (BarObject)u.unmarshal( new File( "bar.xml" ) ); // ok
- *        BazObject bazObj = (BazObject)u.unmarshal( new File( "baz.xml" ) ); // error, "com.acme.baz" not in contextPath
+ *      JAXBContext jc = JAXBContext.newInstance( "com.acme.foo:com.acme.bar" );
+ *      Unmarshaller u = jc.createUnmarshaller();
+ *      FooObject fooObj = (FooObject)u.unmarshal( new File( "foo.xml" ) ); // ok
+ *      BarObject barObj = (BarObject)u.unmarshal( new File( "bar.xml" ) ); // ok
+ *      BazObject bazObj = (BazObject)u.unmarshal( new File( "baz.xml" ) ); // error, "com.acme.baz" not in contextPath
  * 
* *

@@ -146,7 +137,7 @@ import java.io.InputStream; * Section 4.2 Java Package of the specification. * *

- * SPEC REQUIREMENT: the provider must generate a class in each + * The provider must generate a class in each * package that contains all of the necessary object factory methods for that * package named ObjectFactory as well as the static * newInstance( javaContentInterface ) method @@ -214,6 +205,7 @@ import java.io.InputStream; * by the following steps. * *

    + * *
  1. * For each package/class explicitly passed in to the {@link #newInstance} method, in the order they are specified, * jaxb.properties file is looked up in its package, by using the associated classloader — @@ -223,7 +215,7 @@ import java.io.InputStream; *

    * If such a file is discovered, it is {@link Properties#load(InputStream) loaded} as a property file, and * the value of the {@link #JAXB_CONTEXT_FACTORY} key will be assumed to be the provider factory class. - * This class is then loaded by the associated classloader discussed above. + * This class is then loaded by the associated class loader discussed above. * *

    * This phase of the look up allows some packages to force the use of a certain JAXB implementation. @@ -234,10 +226,36 @@ import java.io.InputStream; * factory class. This phase of the look up enables per-JVM override of the JAXB implementation. * *

  2. - * Look for /META-INF/services/javax.xml.bind.JAXBContext file in the associated classloader. - * This file follows the standard service descriptor convention, and if such a file exists, its content - * is assumed to be the provider factory class. This phase of the look up is for automatic discovery. - * It allows users to just put a JAXB implementation in a classpath and use it without any furhter configuration. + * Provider of {@link javax.xml.bind.JAXBContextFactory} is loaded using the service-provider loading + * facilities, defined by the {@link java.util.ServiceLoader} class, to attempt + * to locate and load an implementation of the service using the {@linkplain + * java.util.ServiceLoader#load(java.lang.Class) default loading mechanism}: the service-provider loading facility + * will use the {@linkplain java.lang.Thread#getContextClassLoader() current thread's context class loader} + * to attempt to load the context factory. If the context class loader is null, the + * {@linkplain ClassLoader#getSystemClassLoader() system class loader} will be used. + *
    + * In case of {@link java.util.ServiceConfigurationError service + * configuration error} a {@link javax.xml.bind.JAXBException} will be thrown. + *
  3. + * + *
  4. + * Look for resource {@code /META-INF/services/javax.xml.bind.JAXBContext} using provided class loader. + * Methods without class loader parameter use {@code Thread.currentThread().getContextClassLoader()}. + * If such a resource exists, its content is assumed to be the provider factory class and must supply + * an implementation class containing the following method signatures: + * + *
    + *
    + * public static JAXBContext createContext(
    + *                                      String contextPath,
    + *                                      ClassLoader classLoader,
    + *                                      Map<String,Object> properties throws JAXBException
    + *
    + * public static JAXBContext createContext(
    + *                                      Class[] classes,
    + *                                      Map<String,Object> properties ) throws JAXBException
    + * 
    + * This configuration method is deprecated. * *
  5. * Finally, if all the steps above fail, then the rest of the look up is unspecified. That said, @@ -246,17 +264,30 @@ import java.io.InputStream; *
* *

- * Once the provider factory class is discovered, its - * public static JAXBContext createContext(String,ClassLoader,Map) method - * (see {@link #newInstance(String, ClassLoader, Map)} for the parameter semantics.) - * or public static JAXBContext createContet(Class[],Map) method - * (see {@link #newInstance(Class[], Map)} for the parameter semantics) are invoked + * Once the provider factory class {@link javax.xml.bind.JAXBContextFactory} is discovered, one of its methods + * {@link javax.xml.bind.JAXBContextFactory#createContext(String, ClassLoader, java.util.Map)} or + * {@link javax.xml.bind.JAXBContextFactory#createContext(Class[], java.util.Map)} is invoked * to create a {@link JAXBContext}. * - * @author

  • Ryan Shoemaker, Sun Microsystems, Inc.
  • Kohsuke Kawaguchi, Sun Microsystems, Inc.
  • Joe Fialli, Sun Microsystems, Inc.
+ *

+ * + * @apiNote + *

Service discovery method using file /META-INF/services/javax.xml.bind.JAXBContext (described in step 4) + * and leveraging provider's static methods is supported only to allow backwards compatibility, but it is strongly + * recommended to migrate to standard ServiceLoader mechanism (described in step 3). + * + * @implNote + * Within the last step, if Glassfish AS environment detected, its specific service loader is used to find factory class. + * + * @author

  • Ryan Shoemaker, Sun Microsystems, Inc.
  • + *
  • Kohsuke Kawaguchi, Sun Microsystems, Inc.
  • + *
  • Joe Fialli, Sun Microsystems, Inc.
+ * * @see Marshaller * @see Unmarshaller - * @see S 7.4.1 "Named Packages" in Java Language Specification + * @see S 7.4.1 "Named Packages" + * in Java Language Specification + * * @since 1.6, JAXB 1.0 */ public abstract class JAXBContext { @@ -265,9 +296,7 @@ public abstract class JAXBContext { * The name of the property that contains the name of the class capable * of creating new JAXBContext objects. */ - public static final String JAXB_CONTEXT_FACTORY = - "javax.xml.bind.context.factory"; - + public static final String JAXB_CONTEXT_FACTORY = "javax.xml.bind.JAXBContextFactory"; protected JAXBContext() { } @@ -275,7 +304,7 @@ public abstract class JAXBContext { /** *

- * Obtain a new instance of a JAXBContext class. + * Create a new instance of a JAXBContext class. * *

* This is a convenience method to invoke the @@ -300,7 +329,7 @@ public abstract class JAXBContext { /** *

- * Obtain a new instance of a JAXBContext class. + * Create a new instance of a JAXBContext class. * *

* The client application must supply a context path which is a list of @@ -396,7 +425,7 @@ public abstract class JAXBContext { /** *

- * Obtain a new instance of a JAXBContext class. + * Create a new instance of a JAXBContext class. * *

* This is mostly the same as {@link JAXBContext#newInstance(String, ClassLoader)}, @@ -425,8 +454,9 @@ public abstract class JAXBContext { * * @since 1.6, JAXB 2.0 */ - public static JAXBContext newInstance( String contextPath, ClassLoader classLoader, Map properties ) - throws JAXBException { + public static JAXBContext newInstance( String contextPath, + ClassLoader classLoader, + Map properties ) throws JAXBException { return ContextFinder.find( /* The default property name according to the JAXB spec */ @@ -443,7 +473,7 @@ public abstract class JAXBContext { // TODO: resurrect this once we introduce external annotations // /** // *

-// * Obtain a new instance of a JAXBContext class. +// * Create a new instance of a JAXBContext class. // * // *

// * The client application must supply a list of classes that the new @@ -479,7 +509,7 @@ public abstract class JAXBContext { // * spec-defined classes will be returned. // * // * @return -// * A new instance of a JAXBContext. Always non-null valid object. +// * A new instance of a JAXBContext. // * // * @throws JAXBException // * if an error was encountered while creating the @@ -517,7 +547,7 @@ public abstract class JAXBContext { /** *

- * Obtain a new instance of a JAXBContext class. + * Create a new instance of a JAXBContext class. * *

* The client application must supply a list of classes that the new @@ -559,7 +589,7 @@ public abstract class JAXBContext { * spec-defined classes will be returned. * * @return - * A new instance of a JAXBContext. Always non-null valid object. + * A new instance of a JAXBContext. * * @throws JAXBException * if an error was encountered while creating the @@ -578,7 +608,7 @@ public abstract class JAXBContext { * * @since 1.6, JAXB 2.0 */ - public static JAXBContext newInstance( Class... classesToBeBound ) + public static JAXBContext newInstance( Class ... classesToBeBound ) throws JAXBException { return newInstance(classesToBeBound,Collections.emptyMap()); @@ -586,7 +616,7 @@ public abstract class JAXBContext { /** *

- * Obtain a new instance of a JAXBContext class. + * Create a new instance of a JAXBContext class. * *

* An overloading of {@link JAXBContext#newInstance(Class...)} @@ -605,7 +635,7 @@ public abstract class JAXBContext { * in an empty map. * * @return - * A new instance of a JAXBContext. Always non-null valid object. + * A new instance of a JAXBContext. * * @throws JAXBException * if an error was encountered while creating the @@ -624,7 +654,7 @@ public abstract class JAXBContext { * * @since 1.6, JAXB 2.0 */ - public static JAXBContext newInstance( Class[] classesToBeBound, Map properties ) + public static JAXBContext newInstance( Class[] classesToBeBound, Map properties ) throws JAXBException { if (classesToBeBound == null) { @@ -756,9 +786,9 @@ public abstract class JAXBContext { if (System.getSecurityManager() == null) { return Thread.currentThread().getContextClassLoader(); } else { - return (ClassLoader) java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public java.lang.Object run() { + return java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public ClassLoader run() { return Thread.currentThread().getContextClassLoader(); } }); diff --git a/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/JAXBContextFactory.java b/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/JAXBContextFactory.java new file mode 100644 index 00000000000..9353f37ad3c --- /dev/null +++ b/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/JAXBContextFactory.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package javax.xml.bind; + +import java.util.Map; + +/** + *

Factory that creates new JAXBContext instances. + * + * JAXBContextFactory can be located using {@link java.util.ServiceLoader#load(Class)} + * + * @since 1.9, JAXB 2.3 + */ +public interface JAXBContextFactory { + + /** + *

+ * Create a new instance of a JAXBContext class. + * + *

+ * For semantics see {@link javax.xml.bind.JAXBContext#newInstance(Class[], java.util.Map)} + * + * @param classesToBeBound + * list of java classes to be recognized by the new {@link JAXBContext}. + * Can be empty, in which case a {@link JAXBContext} that only knows about + * spec-defined classes will be returned. + * @param properties + * provider-specific properties. Can be null, which means the same thing as passing + * in an empty map. + * + * @return + * A new instance of a JAXBContext. + * + * @throws JAXBException + * if an error was encountered while creating the + * JAXBContext, such as (but not limited to): + *

    + *
  1. Classes use JAXB annotations incorrectly + *
  2. Classes have colliding annotations (i.e., two classes with the same type name) + *
  3. The JAXB implementation was unable to locate + * provider-specific out-of-band information (such as additional + * files generated at the development time.) + *
+ * + * @throws IllegalArgumentException + * if the parameter contains {@code null} (i.e., {@code newInstance(null,someMap);}) + * + * @since 1.9, JAXB 2.3 + */ + JAXBContext createContext(Class[] classesToBeBound, + Map properties ) throws JAXBException; + + /** + *

+ * Create a new instance of a JAXBContext class. + * + *

+ * For semantics see {@link javax.xml.bind.JAXBContext#newInstance(String, ClassLoader, java.util.Map)} + * + *

+ * The interpretation of properties is up to implementations. Implementations should + * throw JAXBException if it finds properties that it doesn't understand. + * + * @param contextPath list of java package names that contain schema derived classes + * @param classLoader + * This class loader will be used to locate the implementation classes. + * @param properties + * provider-specific properties. Can be null, which means the same thing as passing + * in an empty map. + * + * @return a new instance of a JAXBContext + * @throws JAXBException if an error was encountered while creating the + * JAXBContext such as + *

    + *
  1. failure to locate either ObjectFactory.class or jaxb.index in the packages
  2. + *
  3. an ambiguity among global elements contained in the contextPath
  4. + *
  5. failure to locate a value for the context factory provider property
  6. + *
  7. mixing schema derived packages from different providers on the same contextPath
  8. + *
+ * @since 1.9, JAXB 2.3 + */ + JAXBContext createContext(String contextPath, + ClassLoader classLoader, + Map properties ) throws JAXBException; + +} diff --git a/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/ServiceLoaderUtil.java b/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/ServiceLoaderUtil.java index 159a7c13ca5..0efc25f2061 100644 --- a/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/ServiceLoaderUtil.java +++ b/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/ServiceLoaderUtil.java @@ -25,14 +25,9 @@ package javax.xml.bind; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Iterator; -import java.util.Properties; import java.util.ServiceLoader; import java.util.logging.Level; import java.util.logging.Logger; @@ -49,27 +44,27 @@ class ServiceLoaderUtil { private static final String OSGI_SERVICE_LOADER_CLASS_NAME = "com.sun.org.glassfish.hk2.osgiresourcelocator.ServiceLoader"; private static final String OSGI_SERVICE_LOADER_METHOD_NAME = "lookupProviderClasses"; - static

P firstByServiceLoader(Class

spiClass, Logger logger) { + static P firstByServiceLoader(Class

spiClass, + Logger logger, + ExceptionHandler handler) throws T { // service discovery - ServiceLoader

serviceLoader = ServiceLoader.load(spiClass); - for (P impl : serviceLoader) { - logger.fine("ServiceProvider loading Facility used; returning object [" + impl.getClass().getName() + "]"); - return impl; + try { + ServiceLoader

serviceLoader = ServiceLoader.load(spiClass); + + for (P impl : serviceLoader) { + logger.fine("ServiceProvider loading Facility used; returning object [" + + impl.getClass().getName() + "]"); + + return impl; + } + } catch (Throwable t) { + throw handler.createException(t, "Error while searching for service [" + spiClass.getName() + "]"); } return null; } - static boolean isOsgi(Logger logger) { - try { - Class.forName(OSGI_SERVICE_LOADER_CLASS_NAME); - return true; - } catch (ClassNotFoundException ignored) { - logger.log(Level.FINE, "OSGi classes not found, OSGi not available.", ignored); - } - return false; - } - static Object lookupUsingOSGiServiceLoader(String factoryId, Logger logger) { + try { // Use reflection to avoid having any dependendcy on ServiceLoader class Class serviceClass = Class.forName(factoryId); @@ -78,39 +73,22 @@ class ServiceLoaderUtil { Iterator iter = ((Iterable) m.invoke(null, serviceClass)).iterator(); if (iter.hasNext()) { Object next = iter.next(); - logger.fine("Found implementation using OSGi facility; returning object [" + next.getClass().getName() + "]."); + logger.fine("Found implementation using OSGi facility; returning object [" + + next.getClass().getName() + "]."); return next; } else { return null; } - } catch (Exception ignored) { + } catch (IllegalAccessException | + InvocationTargetException | + ClassNotFoundException | + NoSuchMethodException ignored) { + logger.log(Level.FINE, "Unable to find from OSGi: [" + factoryId + "]", ignored); return null; } } - static String propertyFileLookup(final String configFullPath, final String factoryId) throws IOException { - File f = new File(configFullPath); - String factoryClassName = null; - if (f.exists()) { - Properties props = new Properties(); - FileInputStream stream = null; - try { - stream = new FileInputStream(f); - props.load(stream); - factoryClassName = props.getProperty(factoryId); - } finally { - if (stream != null) { - try { - stream.close(); - } catch (IOException ignored) { - } - } - } - } - return factoryClassName; - } - static void checkPackageAccess(String className) { // make sure that the current thread has an access to the package of the given name. SecurityManager s = System.getSecurityManager(); @@ -130,18 +108,12 @@ class ServiceLoaderUtil { } } - /** - * Returns instance of required class. It checks package access (security) unless it is defaultClassname. It means if you - * are trying to instantiate default implementation (fallback), pass the class name to both first and second parameter. - * - * @param className class to be instantiated - * @param isDefaultClassname says whether default implementation class - * @param handler exception handler - necessary for wrapping exceptions and logging - * @param Type of exception being thrown (necessary to distinguish between Runtime and checked exceptions) - * @return instantiated object or throws Runtime/checked exception, depending on ExceptionHandler's type - * @throws T - */ - static Object newInstance(String className, String defaultImplClassName, final ExceptionHandler handler) throws T { + // Returns instance of required class. It checks package access (security) + // unless it is defaultClassname. It means if you are trying to instantiate + // default implementation (fallback), pass the class name to both first and second parameter. + static Object newInstance(String className, + String defaultImplClassName, + final ExceptionHandler handler) throws T { try { return safeLoadClass(className, defaultImplClassName, contextClassLoader(handler)).newInstance(); } catch (ClassNotFoundException x) { @@ -151,7 +123,10 @@ class ServiceLoaderUtil { } } - static Class safeLoadClass(String className, String defaultImplClassName, ClassLoader classLoader) throws ClassNotFoundException { + static Class safeLoadClass(String className, + String defaultImplClassName, + ClassLoader classLoader) throws ClassNotFoundException { + try { checkPackageAccess(className); } catch (SecurityException se) { @@ -165,16 +140,6 @@ class ServiceLoaderUtil { return nullSafeLoadClass(className, classLoader); } - static String getJavaHomeLibConfigPath(String filename) { - String javah = AccessController.doPrivileged(new PrivilegedAction() { - @Override - public String run() { - return System.getProperty("java.home"); - } - }); - return javah + File.separator + "lib" + File.separator + filename; - } - static ClassLoader contextClassLoader(ExceptionHandler exceptionHandler) throws Exception { try { return Thread.currentThread().getContextClassLoader(); diff --git a/jdk/.hgtags b/jdk/.hgtags index 768fb1cb36b..dff033ae106 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -310,3 +310,5 @@ fd3281c400347088b36aeb16273aa679d53a81a4 jdk9-b63 ed94f3e7ba6bbfec0772de6d24e39543e13f6d88 jdk9-b65 4fbcca8ab812198c7fb747ea7b213b6e404f36e9 jdk9-b66 1abd45df5480a04bff98fba1851d66a5230e67d4 jdk9-b67 +046fd17bb9a0cdf6681124866df9626d17b0516a jdk9-b68 +551323004d0ce2f1d4b0e99552f7e0cdcebc6fca jdk9-b69 diff --git a/jdk/make/lib/Awt2dLibraries.gmk b/jdk/make/lib/Awt2dLibraries.gmk index 177fe2ad594..211620ec3a6 100644 --- a/jdk/make/lib/Awt2dLibraries.gmk +++ b/jdk/make/lib/Awt2dLibraries.gmk @@ -54,7 +54,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBMLIB_IMAGE, \ OPTIMIZATION := HIGHEST, \ CFLAGS := $(CFLAGS_JDKLIB) \ $(BUILD_LIBMLIB_CFLAGS), \ - DISABLED_WARNINGS_gcc := parentheses, \ + DISABLED_WARNINGS_gcc := parentheses array-bounds, \ DISABLED_WARNINGS_clang := parentheses, \ DISABLED_WARNINGS_solstudio := E_STATEMENT_NOT_REACHED, \ MAPFILE := $(BUILD_LIBMLIB_IMAGE_MAPFILE), \ @@ -491,10 +491,10 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJAVAJPEG, \ SRC := $(LIBJAVAJPEG_SRC), \ INCLUDE_FILES := $(BUILD_LIBJAVAJPEG_INCLUDE_FILES), \ OPTIMIZATION := HIGHEST, \ - CFLAGS := $(CFLAGS_JDKLIB) $(addprefix -I, $(LIBJAVAJPEG_SRC)) \ + CFLAGS := $(CFLAGS_JDKLIB) $(BUILD_LIBJAVAJPEG_HEADERS) \ $(LIBJAVA_HEADER_FLAGS) \ -I$(SUPPORT_OUTPUTDIR)/headers/java.desktop, \ - DISABLED_WARNINGS_gcc := clobbered parentheses, \ + DISABLED_WARNINGS_gcc := clobbered parentheses array-bounds, \ DISABLED_WARNINGS_clang := logical-op-parentheses, \ DISABLED_WARNINGS_microsoft := 4267, \ MAPFILE := $(BUILD_LIBJAVAJPEG_MAPFILE), \ diff --git a/jdk/make/lib/Lib-java.instrument.gmk b/jdk/make/lib/Lib-java.instrument.gmk index b0eb7e858db..ed40a831896 100644 --- a/jdk/make/lib/Lib-java.instrument.gmk +++ b/jdk/make/lib/Lib-java.instrument.gmk @@ -61,7 +61,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBINSTRUMENT, \ OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \ SRC := $(LIBINSTRUMENT_SRC), \ OPTIMIZATION := LOW, \ - CFLAGS := $(LIBINSTRUMENT_CFLAGS) $(CFLAGS_WARNINGS_ARE_ERRORS), \ + CFLAGS := $(LIBINSTRUMENT_CFLAGS), \ CFLAGS_debug := -DJPLIS_LOGGING, \ CFLAGS_release := -DNO_JPLIS_LOGGING, \ MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libinstrument/mapfile-vers, \ diff --git a/jdk/make/lib/Lib-java.management.gmk b/jdk/make/lib/Lib-java.management.gmk index b0062445341..9f5aaaed3a9 100644 --- a/jdk/make/lib/Lib-java.management.gmk +++ b/jdk/make/lib/Lib-java.management.gmk @@ -50,7 +50,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBMANAGEMENT, \ OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \ SRC := $(LIBMANAGEMENT_SRC), \ OPTIMIZATION := $(LIBMANAGEMENT_OPTIMIZATION), \ - CFLAGS := $(CFLAGS_JDKLIB) $(CFLAGS_WARNINGS_ARE_ERRORS) $(LIBMANAGEMENT_CFLAGS), \ + CFLAGS := $(CFLAGS_JDKLIB) $(LIBMANAGEMENT_CFLAGS), \ MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libmanagement/mapfile-vers, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ diff --git a/jdk/make/lib/Lib-jdk.attach.gmk b/jdk/make/lib/Lib-jdk.attach.gmk index dbabea5b733..d1bdd5e1bc0 100644 --- a/jdk/make/lib/Lib-jdk.attach.gmk +++ b/jdk/make/lib/Lib-jdk.attach.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -39,7 +39,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBATTACH, \ OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \ SRC := $(call FindSrcDirsForLib, jdk.attach, attach), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) $(CFLAGS_WARNINGS_ARE_ERRORS) \ + CFLAGS := $(CFLAGS_JDKLIB) \ -I$(SUPPORT_OUTPUTDIR)/headers/jdk.attach \ $(LIBJAVA_HEADER_FLAGS) $(LIBATTACH_CFLAGS), \ CFLAGS_windows := /Gy, \ diff --git a/jdk/make/lib/Lib-jdk.hprof.agent.gmk b/jdk/make/lib/Lib-jdk.hprof.agent.gmk index 7c43331b33c..c6d1bbd1d04 100644 --- a/jdk/make/lib/Lib-jdk.hprof.agent.gmk +++ b/jdk/make/lib/Lib-jdk.hprof.agent.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,7 @@ BUILD_LIBHPROF_SRC := $(call FindSrcDirsForLib, jdk.hprof.agent, hprof) BUILD_LIBHPROF_CFLAGS := $(addprefix -I, $(BUILD_LIBHPROF_SRC)) \ -I$(JDK_TOPDIR)/src/demo/share/jvmti/java_crw_demo - + BUILD_LIBHPROF_LDFLAGS := LIBHPROF_OPTIMIZATION := HIGHEST @@ -46,7 +46,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBHPROF, \ OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \ SRC := $(BUILD_LIBHPROF_SRC), \ OPTIMIZATION := $(LIBHPROF_OPTIMIZATION), \ - CFLAGS := $(CFLAGS_JDKLIB) $(CFLAGS_WARNINGS_ARE_ERRORS) \ + CFLAGS := $(CFLAGS_JDKLIB) \ $(BUILD_LIBHPROF_CFLAGS), \ CFLAGS_debug := -DHPROF_LOGGING, \ MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libhprof/mapfile-vers, \ @@ -75,7 +75,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJAVA_CRW_DEMO, \ OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \ SRC := $(LIBJAVA_CRW_DEMO_SRC), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) $(CFLAGS_WARNINGS_ARE_ERRORS) \ + CFLAGS := $(CFLAGS_JDKLIB) \ $(addprefix -I, $(LIBJAVA_CRW_DEMO_SRC)), \ MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libjava_crw_demo/mapfile-vers, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ diff --git a/jdk/make/lib/Lib-jdk.jdi.gmk b/jdk/make/lib/Lib-jdk.jdi.gmk index eb1de3b43c1..74d246f50d4 100644 --- a/jdk/make/lib/Lib-jdk.jdi.gmk +++ b/jdk/make/lib/Lib-jdk.jdi.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -44,7 +44,7 @@ ifeq ($(OPENJDK_TARGET_OS), windows) OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \ SRC := $(LIBDT_SHMEM_SRC), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) $(CFLAGS_WARNINGS_ARE_ERRORS) -DUSE_MMAP \ + CFLAGS := $(CFLAGS_JDKLIB) -DUSE_MMAP \ $(LIBDT_SHMEM_CPPFLAGS), \ LDFLAGS := $(LDFLAGS_JDKLIB), \ LDFLAGS_windows := -export:jdwpTransport_OnLoad, \ diff --git a/jdk/make/lib/Lib-jdk.jdwp.agent.gmk b/jdk/make/lib/Lib-jdk.jdwp.agent.gmk index 0743ac85a97..03a1d3e3965 100644 --- a/jdk/make/lib/Lib-jdk.jdwp.agent.gmk +++ b/jdk/make/lib/Lib-jdk.jdwp.agent.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -41,7 +41,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBDT_SOCKET, \ OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \ SRC := $(LIBDT_SOCKET_SRC), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) $(CFLAGS_CFLAGS_WARNINGS_ARE_ERRORS) -DUSE_MMAP \ + CFLAGS := $(CFLAGS_JDKLIB) -DUSE_MMAP \ $(LIBDT_SOCKET_CPPFLAGS), \ MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libdt_socket/mapfile-vers, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ @@ -77,7 +77,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJDWP, \ OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \ SRC := $(LIBJDWP_SRC), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) $(CFLAGS_WARNINGS_ARE_ERRORS) -DJDWP_LOGGING \ + CFLAGS := $(CFLAGS_JDKLIB) -DJDWP_LOGGING \ $(LIBJDWP_CPPFLAGS) \ -I$(SUPPORT_OUTPUTDIR)/headers/jdk.jdwp.agent, \ MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libjdwp/mapfile-vers, \ diff --git a/jdk/make/lib/Lib-jdk.management.gmk b/jdk/make/lib/Lib-jdk.management.gmk index 84e71f7060c..8950738b453 100644 --- a/jdk/make/lib/Lib-jdk.management.gmk +++ b/jdk/make/lib/Lib-jdk.management.gmk @@ -59,7 +59,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBMANAGEMENT_EXT, \ SRC := $(LIBMANAGEMENT_EXT_SRC), \ LANG := C, \ OPTIMIZATION := $(LIBMANAGEMENT_EXT_OPTIMIZATION), \ - CFLAGS := $(CFLAGS_JDKLIB) $(CFLAGS_WARNINGS_ARE_ERRORS) $(LIBMANAGEMENT_EXT_CFLAGS), \ + CFLAGS := $(CFLAGS_JDKLIB) $(LIBMANAGEMENT_EXT_CFLAGS), \ MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libmanagement_ext/mapfile-vers, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ diff --git a/jdk/make/lib/Lib-jdk.sctp.gmk b/jdk/make/lib/Lib-jdk.sctp.gmk index 15db8b3b380..dff84900595 100644 --- a/jdk/make/lib/Lib-jdk.sctp.gmk +++ b/jdk/make/lib/Lib-jdk.sctp.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -30,12 +30,8 @@ include LibCommon.gmk ifeq ($(OPENJDK_TARGET_OS_TYPE), unix) ifeq (, $(filter $(OPENJDK_TARGET_OS), macosx aix)) - - # Suppress unused parameters required by exported JNI functions. - SCTP_WERROR := -Werror -Wno-error=unused-parameter - ifeq ($(OPENJDK_TARGET_CPU_ARCH), ppc) - SCTP_WERROR := - endif + # DISABLED_WARNINGS_gcc := unused-parameter needed to + # suppress unused parameters required by exported JNI functions. $(eval $(call SetupNativeCompilation,BUILD_LIBSCTP, \ LIBRARY := sctp, \ @@ -49,7 +45,7 @@ ifeq ($(OPENJDK_TARGET_OS_TYPE), unix) $(LIBJAVA_HEADER_FLAGS) \ -I$(SUPPORT_OUTPUTDIR)/headers/jdk.sctp \ -I$(SUPPORT_OUTPUTDIR)/headers/java.base, \ - CFLAGS_linux := $(SCTP_WERROR), \ + DISABLED_WARNINGS_gcc := unused-parameter, \ MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libsctp/mapfile-vers, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ diff --git a/jdk/make/mapfiles/libjava/mapfile-vers b/jdk/make/mapfiles/libjava/mapfile-vers index cc406fa6e7a..855ac081431 100644 --- a/jdk/make/mapfiles/libjava/mapfile-vers +++ b/jdk/make/mapfiles/libjava/mapfile-vers @@ -129,11 +129,11 @@ SUNWprivate_1.1 { Java_java_lang_ClassLoader_defineClass0; Java_java_lang_ClassLoader_defineClass1; Java_java_lang_ClassLoader_defineClass2; + Java_java_lang_ClassLoader_findBuiltinLib; Java_java_lang_ClassLoader_findLoadedClass0; Java_java_lang_ClassLoader_00024NativeLibrary_find; Java_java_lang_ClassLoader_00024NativeLibrary_load; Java_java_lang_ClassLoader_00024NativeLibrary_unload; - Java_java_lang_ClassLoader_00024NativeLibrary_findBuiltinLib; Java_java_lang_ClassLoader_registerNatives; Java_java_lang_Double_longBitsToDouble; Java_java_lang_Double_doubleToRawLongBits; diff --git a/jdk/src/java.base/share/classes/com/sun/net/ssl/SSLContext.java b/jdk/src/java.base/share/classes/com/sun/net/ssl/SSLContext.java index f2533dd7f0c..d917c056f98 100644 --- a/jdk/src/java.base/share/classes/com/sun/net/ssl/SSLContext.java +++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/SSLContext.java @@ -58,7 +58,7 @@ public class SSLContext { * * @param contextSpi the delegate * @param provider the provider - * @param algorithm the algorithm + * @param protocol the protocol */ protected SSLContext(SSLContextSpi contextSpi, Provider provider, String protocol) { diff --git a/jdk/src/java.base/share/classes/com/sun/net/ssl/SSLContextSpi.java b/jdk/src/java.base/share/classes/com/sun/net/ssl/SSLContextSpi.java index cbb002675f9..3f2e74e8236 100644 --- a/jdk/src/java.base/share/classes/com/sun/net/ssl/SSLContextSpi.java +++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/SSLContextSpi.java @@ -49,9 +49,9 @@ public abstract class SSLContextSpi { /** * Initializes this context. * - * @param km the sources of authentication keys - * @param tm the sources of peer authentication trust decisions - * @param random the source of randomness for this generator + * @param ah the sources of authentication keys + * @param th the sources of peer authentication trust decisions + * @param sr the source of randomness for this generator */ protected abstract void engineInit(KeyManager[] ah, TrustManager[] th, SecureRandom sr) throws KeyManagementException; diff --git a/jdk/src/java.base/share/classes/com/sun/net/ssl/SSLPermission.java b/jdk/src/java.base/share/classes/com/sun/net/ssl/SSLPermission.java index 2bf9233051b..8f8c249d007 100644 --- a/jdk/src/java.base/share/classes/com/sun/net/ssl/SSLPermission.java +++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/SSLPermission.java @@ -52,7 +52,6 @@ import java.lang.SecurityManager; * The following table lists all the possible SSLPermission target names, * and for each provides a description of what the permission allows * and a discussion of the risks of granting code the permission. - *

* * * diff --git a/jdk/src/java.base/share/classes/java/io/File.java b/jdk/src/java.base/share/classes/java/io/File.java index 5aa6b200163..c2ae4400c77 100644 --- a/jdk/src/java.base/share/classes/java/io/File.java +++ b/jdk/src/java.base/share/classes/java/io/File.java @@ -2148,7 +2148,7 @@ public class File * WriteObject is called to save this filename. * The separator character is saved also so it can be replaced * in case the path is reconstituted on a different host type. - *

+ * * @serialData Default fields followed by separator character. */ private synchronized void writeObject(java.io.ObjectOutputStream s) diff --git a/jdk/src/java.base/share/classes/java/io/FilePermission.java b/jdk/src/java.base/share/classes/java/io/FilePermission.java index 0c5bcf35178..e3dc11f4eb5 100644 --- a/jdk/src/java.base/share/classes/java/io/FilePermission.java +++ b/jdk/src/java.base/share/classes/java/io/FilePermission.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,11 +27,9 @@ package java.io; import java.security.*; import java.util.Enumeration; -import java.util.List; -import java.util.ArrayList; -import java.util.Vector; -import java.util.Collections; import java.util.StringJoiner; +import java.util.Vector; +import java.util.concurrent.ConcurrentHashMap; import sun.security.util.SecurityConstants; /** @@ -288,7 +286,6 @@ public final class FilePermission extends Permission implements Serializable { * @param path the pathname of the file/directory. * @param mask the action mask to use. */ - // package private for use by the FilePermissionCollection add method FilePermission(String path, int mask) { super(path); @@ -315,6 +312,7 @@ public final class FilePermission extends Permission implements Serializable { * null and is implied by this object, * false otherwise. */ + @Override public boolean implies(Permission p) { if (!(p instanceof FilePermission)) return false; @@ -387,6 +385,7 @@ public final class FilePermission extends Permission implements Serializable { * pathname and actions as this FilePermission object, * false otherwise. */ + @Override public boolean equals(Object obj) { if (obj == this) return true; @@ -407,6 +406,7 @@ public final class FilePermission extends Permission implements Serializable { * * @return a hash code value for this object. */ + @Override public int hashCode() { return 0; } @@ -587,6 +587,7 @@ public final class FilePermission extends Permission implements Serializable { * * @return the canonical string representation of the actions. */ + @Override public String getActions() { if (actions == null) actions = getActions(this.mask); @@ -625,6 +626,7 @@ public final class FilePermission extends Permission implements Serializable { * @return a new PermissionCollection object suitable for storing * FilePermissions. */ + @Override public PermissionCollection newPermissionCollection() { return new FilePermissionCollection(); } @@ -689,13 +691,13 @@ final class FilePermissionCollection extends PermissionCollection implements Serializable { // Not serialized; see serialization section at end of class - private transient List perms; + private transient ConcurrentHashMap perms; /** * Create an empty FilePermissionCollection object. */ public FilePermissionCollection() { - perms = new ArrayList<>(); + perms = new ConcurrentHashMap<>(); } /** @@ -710,6 +712,7 @@ final class FilePermissionCollection extends PermissionCollection * @exception SecurityException - if this FilePermissionCollection object * has been marked readonly */ + @Override public void add(Permission permission) { if (! (permission instanceof FilePermission)) throw new IllegalArgumentException("invalid permission: "+ @@ -718,9 +721,31 @@ final class FilePermissionCollection extends PermissionCollection throw new SecurityException( "attempt to add a Permission to a readonly PermissionCollection"); - synchronized (this) { - perms.add(permission); - } + FilePermission fp = (FilePermission)permission; + + // Add permission to map if it is absent, or replace with new + // permission if applicable. NOTE: cannot use lambda for + // remappingFunction parameter until JDK-8076596 is fixed. + perms.merge(fp.getName(), fp, + new java.util.function.BiFunction<>() { + @Override + public Permission apply(Permission existingVal, + Permission newVal) { + int oldMask = ((FilePermission)existingVal).getMask(); + int newMask = ((FilePermission)newVal).getMask(); + if (oldMask != newMask) { + int effective = oldMask | newMask; + if (effective == newMask) { + return newVal; + } + if (effective != oldMask) { + return new FilePermission(fp.getName(), effective); + } + } + return existingVal; + } + } + ); } /** @@ -732,26 +757,25 @@ final class FilePermissionCollection extends PermissionCollection * @return true if "permission" is a proper subset of a permission in * the set, false if not. */ + @Override public boolean implies(Permission permission) { if (! (permission instanceof FilePermission)) return false; - FilePermission fp = (FilePermission) permission; + FilePermission fperm = (FilePermission) permission; - int desired = fp.getMask(); + int desired = fperm.getMask(); int effective = 0; int needed = desired; - synchronized (this) { - int len = perms.size(); - for (int i = 0; i < len; i++) { - FilePermission x = (FilePermission) perms.get(i); - if (((needed & x.getMask()) != 0) && x.impliesIgnoreMask(fp)) { - effective |= x.getMask(); - if ((effective & desired) == desired) - return true; - needed = (desired ^ effective); + for (Permission perm : perms.values()) { + FilePermission fp = (FilePermission)perm; + if (((needed & fp.getMask()) != 0) && fp.impliesIgnoreMask(fperm)) { + effective |= fp.getMask(); + if ((effective & desired) == desired) { + return true; } + needed = (desired ^ effective); } } return false; @@ -763,11 +787,9 @@ final class FilePermissionCollection extends PermissionCollection * * @return an enumeration of all the FilePermission objects. */ + @Override public Enumeration elements() { - // Convert Iterator into Enumeration - synchronized (this) { - return Collections.enumeration(perms); - } + return perms.elements(); } private static final long serialVersionUID = 2202956749081564585L; @@ -795,10 +817,7 @@ final class FilePermissionCollection extends PermissionCollection // Don't call out.defaultWriteObject() // Write out Vector - Vector permissions = new Vector<>(perms.size()); - synchronized (this) { - permissions.addAll(perms); - } + Vector permissions = new Vector<>(perms.values()); ObjectOutputStream.PutField pfields = out.putFields(); pfields.put("permissions", permissions); @@ -819,7 +838,9 @@ final class FilePermissionCollection extends PermissionCollection // Get the one we want @SuppressWarnings("unchecked") Vector permissions = (Vector)gfields.get("permissions", null); - perms = new ArrayList<>(permissions.size()); - perms.addAll(permissions); + perms = new ConcurrentHashMap<>(permissions.size()); + for (Permission perm : permissions) { + perms.put(perm.getName(), perm); + } } } diff --git a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java index 295955847ca..2ba6f5d4f0d 100644 --- a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java +++ b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java @@ -1702,7 +1702,6 @@ public abstract class ClassLoader { native long find(String name); native void unload(String name, boolean isBuiltin); - static native String findBuiltinLib(String name); public NativeLibrary(Class fromClass, String name, boolean isBuiltin) { this.name = name; @@ -1861,9 +1860,11 @@ public abstract class ClassLoader { throw new UnsatisfiedLinkError("no " + name + " in java.library.path"); } + static native String findBuiltinLib(String name); + private static boolean loadLibrary0(Class fromClass, final File file) { // Check to see if we're attempting to access a static library - String name = NativeLibrary.findBuiltinLib(file.getName()); + String name = findBuiltinLib(file.getName()); boolean isBuiltin = (name != null); if (!isBuiltin) { name = AccessController.doPrivileged( diff --git a/jdk/src/java.base/share/classes/java/lang/Process.java b/jdk/src/java.base/share/classes/java/lang/Process.java index 7eca3fd4699..88ee5f0f53f 100644 --- a/jdk/src/java.base/share/classes/java/lang/Process.java +++ b/jdk/src/java.base/share/classes/java/lang/Process.java @@ -368,7 +368,7 @@ public abstract class Process { * Processes returned from {@link ProcessBuilder#start} override the * default implementation to provide an efficient mechanism to wait * for process exit. - *

+ * * @apiNote * Using {@link #onExit() onExit} is an alternative to * {@link #waitFor() waitFor} that enables both additional concurrency diff --git a/jdk/src/java.base/share/classes/java/lang/ProcessHandle.java b/jdk/src/java.base/share/classes/java/lang/ProcessHandle.java index f16fbee20b9..1894525c6a2 100644 --- a/jdk/src/java.base/share/classes/java/lang/ProcessHandle.java +++ b/jdk/src/java.base/share/classes/java/lang/ProcessHandle.java @@ -71,7 +71,7 @@ import java.util.stream.Stream; * The ability to control processes is also restricted by the native system, * ProcessHandle provides no more access to, or control over, the native process * than would be allowed by a native application. - *

+ * * @implSpec * In the case where ProcessHandles cannot be supported then the factory * methods must consistently throw {@link java.lang.UnsupportedOperationException}. diff --git a/jdk/src/java.base/share/classes/java/lang/SecurityManager.java b/jdk/src/java.base/share/classes/java/lang/SecurityManager.java index 7f1e90d6c04..4560219fe8e 100644 --- a/jdk/src/java.base/share/classes/java/lang/SecurityManager.java +++ b/jdk/src/java.base/share/classes/java/lang/SecurityManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1447,7 +1447,7 @@ class SecurityManager { throw new NullPointerException("package name can't be null"); } - String[] pkgs; + String[] restrictedPkgs; synchronized (packageAccessLock) { /* * Do we need to update our property array? @@ -1457,8 +1457,7 @@ class SecurityManager { AccessController.doPrivileged( new PrivilegedAction<>() { public String run() { - return java.security.Security.getProperty( - "package.access"); + return Security.getProperty("package.access"); } } ); @@ -1468,14 +1467,33 @@ class SecurityManager { // Using a snapshot of packageAccess -- don't care if static field // changes afterwards; array contents won't change. - pkgs = packageAccess; + restrictedPkgs = packageAccess; } /* * Traverse the list of packages, check for any matches. */ - for (String restrictedPkg : pkgs) { - if (pkg.startsWith(restrictedPkg) || restrictedPkg.equals(pkg + ".")) { + final int plen = pkg.length(); + for (String restrictedPkg : restrictedPkgs) { + final int rlast = restrictedPkg.length() - 1; + + // Optimizations: + // + // If rlast >= plen then restrictedPkg is longer than pkg by at + // least one char. This means pkg cannot start with restrictedPkg, + // since restrictedPkg will be longer than pkg. + // + // Similarly if rlast != plen, then pkg + "." cannot be the same + // as restrictedPkg, since pkg + "." will have a different length + // than restrictedPkg. + // + if (rlast < plen && pkg.startsWith(restrictedPkg) || + // The following test is equivalent to + // restrictedPkg.equals(pkg + ".") but is noticeably more + // efficient: + rlast == plen && restrictedPkg.startsWith(pkg) && + restrictedPkg.charAt(rlast) == '.') + { checkPermission( new RuntimePermission("accessClassInPackage." + pkg)); break; // No need to continue; only need to check this once diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/CallSite.java b/jdk/src/java.base/share/classes/java/lang/invoke/CallSite.java index 11e452b96c9..13cf24ca0f2 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/CallSite.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/CallSite.java @@ -27,8 +27,6 @@ package java.lang.invoke; import static java.lang.invoke.MethodHandleStatics.*; import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; -import java.lang.reflect.Field; -import sun.misc.Cleaner; /** * A {@code CallSite} is a holder for a variable {@link MethodHandle}, @@ -138,47 +136,9 @@ public class CallSite { /** * {@code CallSite} dependency context. - * VM uses context class to store nmethod dependencies on the call site target. - * Can be in 2 states: (a) null; or (b) {@code Cleaner} instance pointing to some Class instance. - * Lazily initialized when CallSite instance is linked to some indy call site or VM needs - * it to store dependencies. As a corollary, "null" context means there are no dependencies - * registered yet. {@code Cleaner} is used in 2 roles: - * (a) context class access for VM; - * (b) stale context class cleanup. - * {@code Cleaner} holds the context class until cleanup action is finished (see {@code PhantomReference}). - * Though it's impossible to get the context class using {@code Reference.get()}, VM extracts it directly - * from {@code Reference.referent} field. + * JVM uses CallSite.context to store nmethod dependencies on the call site target. */ - private volatile Cleaner context = null; - - /** - * Default context. - * VM uses it to initialize non-linked CallSite context. - */ - private static class DefaultContext {} - private static final Cleaner DEFAULT_CONTEXT = makeContext(DefaultContext.class, null); - - private static Cleaner makeContext(Class referent, final CallSite holder) { - return Cleaner.create(referent, - new Runnable() { - @Override public void run() { - MethodHandleNatives.invalidateDependentNMethods(holder); - } - }); - } - - /** Initialize context class used for nmethod dependency tracking */ - /*package-private*/ - void initContext(Class newContext) { - // If there are concurrent actions, exactly one succeeds. - if (context == null) { - UNSAFE.compareAndSwapObject(this, CONTEXT_OFFSET, /*expected=*/null, makeContext(newContext, this)); - // No need to care about failed CAS attempt. - // Since initContext is called from indy call site linkage in newContext class, there's no risk - // that the context class becomes dead while corresponding context cleaner is alive (causing cleanup - // action in the wrong context). - } - } + private final MethodHandleNatives.CallSiteContext context = MethodHandleNatives.CallSiteContext.make(this); /** * Returns the type of this call site's target. diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java index 3d3c47f689c..b53b44b99b1 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java @@ -30,6 +30,7 @@ import java.lang.reflect.Field; import static java.lang.invoke.MethodHandleNatives.Constants.*; import static java.lang.invoke.MethodHandleStatics.*; import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; +import sun.misc.Cleaner; /** * The JVM interface for the method handles package is all here. @@ -61,8 +62,27 @@ class MethodHandleNatives { static native void setCallSiteTargetNormal(CallSite site, MethodHandle target); static native void setCallSiteTargetVolatile(CallSite site, MethodHandle target); - /** Invalidate CallSite context: clean up dependent nmethods and reset call site context to initial state (null). */ - static native void invalidateDependentNMethods(CallSite site); + /** Represents a context to track nmethod dependencies on CallSite instance target. */ + static class CallSiteContext implements Runnable { + //@Injected JVM_nmethodBucket* vmdependencies; + + static CallSiteContext make(CallSite cs) { + final CallSiteContext newContext = new CallSiteContext(); + // Cleaner is attached to CallSite instance and it clears native structures allocated for CallSite context. + // Though the CallSite can become unreachable, its Context is retained by the Cleaner instance (which is + // referenced from Cleaner class) until cleanup is performed. + Cleaner.create(cs, newContext); + return newContext; + } + + @Override + public void run() { + MethodHandleNatives.clearCallSiteContext(this); + } + } + + /** Invalidate all recorded nmethods. */ + private static native void clearCallSiteContext(CallSiteContext context); private static native void registerNatives(); static { @@ -235,7 +255,6 @@ class MethodHandleNatives { return Invokers.linkToTargetMethod(type); } else { appendixResult[0] = callSite; - callSite.initContext(caller); return Invokers.linkToCallSiteMethod(type); } } diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedArrayType.java b/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedArrayType.java index f92b51d6ff6..3a10a9a63bc 100644 --- a/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedArrayType.java +++ b/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedArrayType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,7 @@ public interface AnnotatedArrayType extends AnnotatedType { * Returns the potentially annotated generic component type of this array type. * * @return the potentially annotated generic component type of this array type + * @see GenericArrayType#getGenericComponentType() */ AnnotatedType getAnnotatedGenericComponentType(); } diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedParameterizedType.java b/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedParameterizedType.java index f1d43c9528e..b0ca3faa314 100644 --- a/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedParameterizedType.java +++ b/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedParameterizedType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,6 +38,7 @@ public interface AnnotatedParameterizedType extends AnnotatedType { * Returns the potentially annotated actual type arguments of this parameterized type. * * @return the potentially annotated actual type arguments of this parameterized type + * @see ParameterizedType#getActualTypeArguments() */ AnnotatedType[] getAnnotatedActualTypeArguments(); } diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedTypeVariable.java b/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedTypeVariable.java index 7a39bae492d..9b62bf46dc5 100644 --- a/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedTypeVariable.java +++ b/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedTypeVariable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,8 +36,11 @@ public interface AnnotatedTypeVariable extends AnnotatedType { /** * Returns the potentially annotated bounds of this type variable. + * If no bound is explicitly declared, the bound is unannotated + * {@code Object}. * * @return the potentially annotated bounds of this type variable + * @see TypeVariable#getBounds() */ AnnotatedType[] getAnnotatedBounds(); } diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedWildcardType.java b/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedWildcardType.java index 2d15f6c9770..a620516096e 100644 --- a/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedWildcardType.java +++ b/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedWildcardType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,15 +36,22 @@ public interface AnnotatedWildcardType extends AnnotatedType { /** * Returns the potentially annotated lower bounds of this wildcard type. + * If no lower bound is explicitly declared, the lower bound is the + * type of null. In this case, a zero length array is returned. * - * @return the potentially annotated lower bounds of this wildcard type + * @return the potentially annotated lower bounds of this wildcard type or + * an empty array if no lower bound is explicitly declared. + * @see WildcardType#getLowerBounds() */ AnnotatedType[] getAnnotatedLowerBounds(); /** * Returns the potentially annotated upper bounds of this wildcard type. + * If no upper bound is explicitly declared, the upper bound is + * unannotated {@code Object} * * @return the potentially annotated upper bounds of this wildcard type + * @see WildcardType#getUpperBounds() */ AnnotatedType[] getAnnotatedUpperBounds(); } diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/TypeVariable.java b/jdk/src/java.base/share/classes/java/lang/reflect/TypeVariable.java index 39ffe4bf3c0..e2e98ee02a2 100644 --- a/jdk/src/java.base/share/classes/java/lang/reflect/TypeVariable.java +++ b/jdk/src/java.base/share/classes/java/lang/reflect/TypeVariable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,7 +51,7 @@ package java.lang.reflect; public interface TypeVariable extends Type, AnnotatedElement { /** * Returns an array of {@code Type} objects representing the - * upper bound(s) of this type variable. Note that if no upper bound is + * upper bound(s) of this type variable. If no upper bound is * explicitly declared, the upper bound is {@code Object}. * *

For each upper bound B:

  • if B is a parameterized @@ -67,7 +67,7 @@ public interface TypeVariable extends Type, Annota * for any reason * @return an array of {@code Type}s representing the upper * bound(s) of this type variable - */ + */ Type[] getBounds(); /** @@ -91,11 +91,11 @@ public interface TypeVariable extends Type, Annota * Returns an array of AnnotatedType objects that represent the use of * types to denote the upper bounds of the type parameter represented by * this TypeVariable. The order of the objects in the array corresponds to - * the order of the bounds in the declaration of the type parameter. + * the order of the bounds in the declaration of the type parameter. Note that + * if no upper bound is explicitly declared, the upper bound is unannotated + * {@code Object}. * - * Returns an array of length 0 if the type parameter declares no bounds. - * - * @return an array of objects representing the upper bounds of the type variable + * @return an array of objects representing the upper bound(s) of the type variable * @since 1.8 */ AnnotatedType[] getAnnotatedBounds(); diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/WildcardType.java b/jdk/src/java.base/share/classes/java/lang/reflect/WildcardType.java index aa8e824d88a..7b8f3962514 100644 --- a/jdk/src/java.base/share/classes/java/lang/reflect/WildcardType.java +++ b/jdk/src/java.base/share/classes/java/lang/reflect/WildcardType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,7 +34,7 @@ package java.lang.reflect; public interface WildcardType extends Type { /** * Returns an array of {@code Type} objects representing the upper - * bound(s) of this type variable. Note that if no upper bound is + * bound(s) of this type variable. If no upper bound is * explicitly declared, the upper bound is {@code Object}. * *

    For each upper bound B : @@ -57,7 +57,7 @@ public interface WildcardType extends Type { /** * Returns an array of {@code Type} objects representing the - * lower bound(s) of this type variable. Note that if no lower bound is + * lower bound(s) of this type variable. If no lower bound is * explicitly declared, the lower bound is the type of {@code null}. * In this case, a zero length array is returned. * diff --git a/jdk/src/java.base/share/classes/java/math/BigInteger.java b/jdk/src/java.base/share/classes/java/math/BigInteger.java index 3690bea06b4..3b3cbf50739 100644 --- a/jdk/src/java.base/share/classes/java/math/BigInteger.java +++ b/jdk/src/java.base/share/classes/java/math/BigInteger.java @@ -1963,6 +1963,43 @@ public class BigInteger extends Number implements Comparable { * int array z. The contents of x are not changed. */ private static final int[] squareToLen(int[] x, int len, int[] z) { + int zlen = len << 1; + if (z == null || z.length < zlen) + z = new int[zlen]; + + // Execute checks before calling intrinsified method. + implSquareToLenChecks(x, len, z, zlen); + return implSquareToLen(x, len, z, zlen); + } + + /** + * Parameters validation. + */ + private static void implSquareToLenChecks(int[] x, int len, int[] z, int zlen) throws RuntimeException { + if (len < 1) { + throw new IllegalArgumentException("invalid input length: " + len); + } + if (len > x.length) { + throw new IllegalArgumentException("input length out of bound: " + + len + " > " + x.length); + } + if (len * 2 > z.length) { + throw new IllegalArgumentException("input length out of bound: " + + (len * 2) + " > " + z.length); + } + if (zlen < 1) { + throw new IllegalArgumentException("invalid input length: " + zlen); + } + if (zlen > z.length) { + throw new IllegalArgumentException("input length out of bound: " + + len + " > " + z.length); + } + } + + /** + * Java Runtime may use intrinsic for this method. + */ + private static final int[] implSquareToLen(int[] x, int len, int[] z, int zlen) { /* * The algorithm used here is adapted from Colin Plumb's C library. * Technique: Consider the partial products in the multiplication @@ -1997,9 +2034,6 @@ public class BigInteger extends Number implements Comparable { * again. The low bit is simply a copy of the low bit of the * input, so it doesn't need special care. */ - int zlen = len << 1; - if (z == null || z.length < zlen) - z = new int[zlen]; // Store the squares, right shifted one bit (i.e., divided by 2) int lastProductLowWord = 0; @@ -2857,6 +2891,32 @@ public class BigInteger extends Number implements Comparable { * Multiply an array by one word k and add to result, return the carry */ static int mulAdd(int[] out, int[] in, int offset, int len, int k) { + implMulAddCheck(out, in, offset, len, k); + return implMulAdd(out, in, offset, len, k); + } + + /** + * Parameters validation. + */ + private static void implMulAddCheck(int[] out, int[] in, int offset, int len, int k) { + if (len > in.length) { + throw new IllegalArgumentException("input length is out of bound: " + len + " > " + in.length); + } + if (offset < 0) { + throw new IllegalArgumentException("input offset is invalid: " + offset); + } + if (offset > (out.length - 1)) { + throw new IllegalArgumentException("input offset is out of bound: " + offset + " > " + (out.length - 1)); + } + if (len > (out.length - offset)) { + throw new IllegalArgumentException("input len is out of bound: " + len + " > " + (out.length - offset)); + } + } + + /** + * Java Runtime may use intrinsic for this method. + */ + private static int implMulAdd(int[] out, int[] in, int offset, int len, int k) { long kLong = k & LONG_MASK; long carry = 0; diff --git a/jdk/src/java.base/share/classes/java/net/SocketPermission.java b/jdk/src/java.base/share/classes/java/net/SocketPermission.java index 52c71b0f7a3..eb046b7122a 100644 --- a/jdk/src/java.base/share/classes/java/net/SocketPermission.java +++ b/jdk/src/java.base/share/classes/java/net/SocketPermission.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,24 +25,24 @@ package java.net; -import java.util.Enumeration; -import java.util.Vector; -import java.util.List; -import java.util.ArrayList; -import java.util.Collections; -import java.util.StringJoiner; -import java.util.StringTokenizer; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.ObjectStreamField; +import java.io.Serializable; import java.net.InetAddress; +import java.security.AccessController; import java.security.Permission; import java.security.PermissionCollection; import java.security.PrivilegedAction; -import java.security.AccessController; import java.security.Security; -import java.io.Serializable; -import java.io.ObjectStreamField; -import java.io.ObjectOutputStream; -import java.io.ObjectInputStream; -import java.io.IOException; +import java.util.Collections; +import java.util.Comparator; +import java.util.Enumeration; +import java.util.Vector; +import java.util.StringJoiner; +import java.util.StringTokenizer; +import java.util.concurrent.ConcurrentSkipListMap; import sun.net.util.IPAddressUtil; import sun.net.RegisteredDomain; import sun.net.PortConfig; @@ -832,6 +832,7 @@ public final class SocketPermission extends Permission * @return true if the specified permission is implied by this object, * false if not. */ + @Override public boolean implies(Permission p) { int i,j; @@ -1010,6 +1011,7 @@ public final class SocketPermission extends Permission * SocketPermission object. However, port range will be ignored * in the comparison if obj only contains the action, 'resolve'. */ + @Override public boolean equals(Object obj) { if (obj == this) return true; @@ -1069,7 +1071,7 @@ public final class SocketPermission extends Permission * * @return a hash code value for this object. */ - + @Override public int hashCode() { /* * If this SocketPermission was initialized with an IP address @@ -1137,6 +1139,7 @@ public final class SocketPermission extends Permission * * @return the canonical string representation of the actions. */ + @Override public String getActions() { if (actions == null) @@ -1156,7 +1159,7 @@ public final class SocketPermission extends Permission * * @return a new PermissionCollection object suitable for storing SocketPermissions. */ - + @Override public PermissionCollection newPermissionCollection() { return new SocketPermissionCollection(); } @@ -1320,15 +1323,16 @@ final class SocketPermissionCollection extends PermissionCollection implements Serializable { // Not serialized; see serialization section at end of class - private transient List perms; + // A ConcurrentSkipListMap is used to preserve order, so that most + // recently added permissions are checked first (see JDK-4301064). + private transient ConcurrentSkipListMap perms; /** * Create an empty SocketPermissions object. * */ - public SocketPermissionCollection() { - perms = new ArrayList<>(); + perms = new ConcurrentSkipListMap<>(new SPCComparator()); } /** @@ -1343,6 +1347,7 @@ final class SocketPermissionCollection extends PermissionCollection * @exception SecurityException - if this SocketPermissionCollection object * has been marked readonly */ + @Override public void add(Permission permission) { if (! (permission instanceof SocketPermission)) throw new IllegalArgumentException("invalid permission: "+ @@ -1351,11 +1356,32 @@ final class SocketPermissionCollection extends PermissionCollection throw new SecurityException( "attempt to add a Permission to a readonly PermissionCollection"); - // optimization to ensure perms most likely to be tested - // show up early (4301064) - synchronized (this) { - perms.add(0, (SocketPermission)permission); - } + SocketPermission sp = (SocketPermission)permission; + + // Add permission to map if it is absent, or replace with new + // permission if applicable. NOTE: cannot use lambda for + // remappingFunction parameter until JDK-8076596 is fixed. + perms.merge(sp.getName(), sp, + new java.util.function.BiFunction<>() { + @Override + public SocketPermission apply(SocketPermission existingVal, + SocketPermission newVal) { + int oldMask = existingVal.getMask(); + int newMask = newVal.getMask(); + if (oldMask != newMask) { + int effective = oldMask | newMask; + if (effective == newMask) { + return newVal; + } + if (effective != oldMask) { + return new SocketPermission(sp.getName(), + effective); + } + } + return existingVal; + } + } + ); } /** @@ -1367,7 +1393,7 @@ final class SocketPermissionCollection extends PermissionCollection * @return true if "permission" is a proper subset of a permission in * the collection, false if not. */ - + @Override public boolean implies(Permission permission) { if (! (permission instanceof SocketPermission)) @@ -1379,18 +1405,15 @@ final class SocketPermissionCollection extends PermissionCollection int effective = 0; int needed = desired; - synchronized (this) { - int len = perms.size(); - //System.out.println("implies "+np); - for (int i = 0; i < len; i++) { - SocketPermission x = perms.get(i); - //System.out.println(" trying "+x); - if (((needed & x.getMask()) != 0) && x.impliesIgnoreMask(np)) { - effective |= x.getMask(); - if ((effective & desired) == desired) - return true; - needed = (desired ^ effective); + //System.out.println("implies "+np); + for (SocketPermission x : perms.values()) { + //System.out.println(" trying "+x); + if (((needed & x.getMask()) != 0) && x.impliesIgnoreMask(np)) { + effective |= x.getMask(); + if ((effective & desired) == desired) { + return true; } + needed = (desired ^ effective); } } return false; @@ -1402,13 +1425,10 @@ final class SocketPermissionCollection extends PermissionCollection * * @return an enumeration of all the SocketPermission objects. */ - + @Override @SuppressWarnings("unchecked") public Enumeration elements() { - // Convert Iterator into Enumeration - synchronized (this) { - return Collections.enumeration((List)(List)perms); - } + return (Enumeration)Collections.enumeration(perms.values()); } private static final long serialVersionUID = 2787186408602843674L; @@ -1441,11 +1461,7 @@ final class SocketPermissionCollection extends PermissionCollection // Don't call out.defaultWriteObject() // Write out Vector - Vector permissions = new Vector<>(perms.size()); - - synchronized (this) { - permissions.addAll(perms); - } + Vector permissions = new Vector<>(perms.values()); ObjectOutputStream.PutField pfields = out.putFields(); pfields.put("permissions", permissions); @@ -1466,7 +1482,22 @@ final class SocketPermissionCollection extends PermissionCollection // Get the one we want @SuppressWarnings("unchecked") Vector permissions = (Vector)gfields.get("permissions", null); - perms = new ArrayList<>(permissions.size()); - perms.addAll(permissions); + perms = new ConcurrentSkipListMap<>(new SPCComparator()); + for (SocketPermission sp : permissions) { + perms.put(sp.getName(), sp); + } + } + + /** + * A simple comparator that orders new non-equal entries at the beginning. + */ + private static class SPCComparator implements Comparator { + @Override + public int compare(String s1, String s2) { + if (s1.equals(s2)) { + return 0; + } + return -1; + } } } diff --git a/jdk/src/java.base/share/classes/java/security/BasicPermission.java b/jdk/src/java.base/share/classes/java/security/BasicPermission.java index 92dbe345b26..fb5f2a260a3 100644 --- a/jdk/src/java.base/share/classes/java/security/BasicPermission.java +++ b/jdk/src/java.base/share/classes/java/security/BasicPermission.java @@ -25,15 +25,13 @@ package java.security; -import java.util.Enumeration; -import java.util.Map; -import java.util.HashMap; -import java.util.Hashtable; -import java.util.Collections; -import java.io.ObjectStreamField; -import java.io.ObjectOutputStream; -import java.io.ObjectInputStream; import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.ObjectStreamField; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.concurrent.ConcurrentHashMap; /** * The BasicPermission class extends the Permission class, and @@ -165,6 +163,7 @@ public abstract class BasicPermission extends Permission * @return true if the passed permission is equal to or * implied by this permission, false otherwise. */ + @Override public boolean implies(Permission p) { if ((p == null) || (p.getClass() != getClass())) return false; @@ -200,6 +199,7 @@ public abstract class BasicPermission extends Permission * @return true if {@code obj}'s class is the same as this object's class * and has the same name as this BasicPermission object, false otherwise. */ + @Override public boolean equals(Object obj) { if (obj == this) return true; @@ -221,6 +221,7 @@ public abstract class BasicPermission extends Permission * * @return a hash code value for this object. */ + @Override public int hashCode() { return this.getName().hashCode(); } @@ -232,6 +233,7 @@ public abstract class BasicPermission extends Permission * * @return the empty string "". */ + @Override public String getActions() { return ""; } @@ -248,6 +250,7 @@ public abstract class BasicPermission extends Permission * @return a new PermissionCollection object suitable for * storing BasicPermissions. */ + @Override public PermissionCollection newPermissionCollection() { return new BasicPermissionCollection(this.getClass()); } @@ -308,7 +311,7 @@ final class BasicPermissionCollection * collection must be of the same type. * Not serialized; see serialization section at end of class. */ - private transient Map perms; + private transient ConcurrentHashMap perms; /** * This is set to {@code true} if this BasicPermissionCollection @@ -320,7 +323,7 @@ final class BasicPermissionCollection /** * The class to which all BasicPermissions in this - * BasicPermissionCollection belongs. + * BasicPermissionCollection belong. * * @see #serialPersistentFields */ @@ -330,9 +333,8 @@ final class BasicPermissionCollection * Create an empty BasicPermissionCollection object. * */ - public BasicPermissionCollection(Class clazz) { - perms = new HashMap<>(11); + perms = new ConcurrentHashMap<>(11); all_allowed = false; permClass = clazz; } @@ -352,6 +354,7 @@ final class BasicPermissionCollection * @exception SecurityException - if this BasicPermissionCollection object * has been marked readonly */ + @Override public void add(Permission permission) { if (! (permission instanceof BasicPermission)) throw new IllegalArgumentException("invalid permission: "+ @@ -373,13 +376,12 @@ final class BasicPermissionCollection permission); } - synchronized (this) { - perms.put(bp.getCanonicalName(), permission); - } + String canonName = bp.getCanonicalName(); + perms.put(canonName, permission); // No sync on all_allowed; staleness OK if (!all_allowed) { - if (bp.getCanonicalName().equals("*")) + if (canonName.equals("*")) all_allowed = true; } } @@ -393,6 +395,7 @@ final class BasicPermissionCollection * @return true if "permission" is a proper subset of a permission in * the set, false if not. */ + @Override public boolean implies(Permission permission) { if (! (permission instanceof BasicPermission)) return false; @@ -414,11 +417,7 @@ final class BasicPermissionCollection String path = bp.getCanonicalName(); //System.out.println("check "+path); - Permission x; - - synchronized (this) { - x = perms.get(path); - } + Permission x = perms.get(path); if (x != null) { // we have a direct hit! @@ -435,9 +434,7 @@ final class BasicPermissionCollection path = path.substring(0, last+1) + "*"; //System.out.println("check "+path); - synchronized (this) { - x = perms.get(path); - } + x = perms.get(path); if (x != null) { return x.implies(permission); @@ -456,11 +453,9 @@ final class BasicPermissionCollection * * @return an enumeration of all the BasicPermission objects. */ + @Override public Enumeration elements() { - // Convert Iterator of Map values into an Enumeration - synchronized (this) { - return Collections.enumeration(perms.values()); - } + return perms.elements(); } // Need to maintain serialization interoperability with earlier releases, @@ -503,9 +498,7 @@ final class BasicPermissionCollection Hashtable permissions = new Hashtable<>(perms.size()*2); - synchronized (this) { - permissions.putAll(perms); - } + permissions.putAll(perms); // Write out serializable fields ObjectOutputStream.PutField pfields = out.putFields(); @@ -533,7 +526,7 @@ final class BasicPermissionCollection @SuppressWarnings("unchecked") Hashtable permissions = (Hashtable)gfields.get("permissions", null); - perms = new HashMap<>(permissions.size()*2); + perms = new ConcurrentHashMap<>(permissions.size()*2); perms.putAll(permissions); // Get all_allowed diff --git a/jdk/src/java.base/share/classes/java/security/CodeSource.java b/jdk/src/java.base/share/classes/java/security/CodeSource.java index e05c68f9e49..afd3fffd05f 100644 --- a/jdk/src/java.base/share/classes/java/security/CodeSource.java +++ b/jdk/src/java.base/share/classes/java/security/CodeSource.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,7 @@ import java.util.Hashtable; import java.io.ByteArrayInputStream; import java.io.IOException; import java.security.cert.*; +import sun.net.util.URLUtil; /** * @@ -72,6 +73,15 @@ public class CodeSource implements java.io.Serializable { // for generating cert paths private transient CertificateFactory factory = null; + /** + * A String form of the URL for use as a key in HashMaps/Sets. The String + * form should be behave in the same manner as the URL when compared for + * equality in a HashMap/Set, except that no nameservice lookup is done + * on the hostname (only string comparison), and the fragment is not + * considered. + */ + private transient String locationNoFragString; + /** * Constructs a CodeSource and associates it with the specified * location and set of certificates. @@ -83,6 +93,9 @@ public class CodeSource implements java.io.Serializable { */ public CodeSource(URL url, java.security.cert.Certificate certs[]) { this.location = url; + if (url != null) { + this.locationNoFragString = URLUtil.urlNoFragString(url); + } // Copy the supplied certs if (certs != null) { @@ -102,6 +115,9 @@ public class CodeSource implements java.io.Serializable { */ public CodeSource(URL url, CodeSigner[] signers) { this.location = url; + if (url != null) { + this.locationNoFragString = URLUtil.urlNoFragString(url); + } // Copy the supplied signers if (signers != null) { @@ -168,6 +184,13 @@ public class CodeSource implements java.io.Serializable { return this.location; } + /** + * Returns a String form of the URL for use as a key in HashMaps/Sets. + */ + String getLocationNoFragString() { + return locationNoFragString; + } + /** * Returns the certificates associated with this CodeSource. *

    @@ -588,6 +611,10 @@ public class CodeSource implements java.io.Serializable { } catch (IOException ioe) { // no signers present } + + if (location != null) { + locationNoFragString = URLUtil.urlNoFragString(location); + } } /* diff --git a/jdk/src/java.base/share/classes/java/security/Permissions.java b/jdk/src/java.base/share/classes/java/security/Permissions.java index 56a5059351b..b9a834a40da 100644 --- a/jdk/src/java.base/share/classes/java/security/Permissions.java +++ b/jdk/src/java.base/share/classes/java/security/Permissions.java @@ -33,6 +33,7 @@ import java.util.HashMap; import java.util.List; import java.util.Iterator; import java.util.Collections; +import java.util.concurrent.ConcurrentHashMap; import java.io.Serializable; import java.io.ObjectStreamField; import java.io.ObjectOutputStream; @@ -85,7 +86,7 @@ implements Serializable * Key is permissions Class, value is PermissionCollection for that class. * Not serialized; see serialization section at end of class. */ - private transient Map, PermissionCollection> permsMap; + private transient ConcurrentHashMap, PermissionCollection> permsMap; // optimization. keep track of whether unresolved permissions need to be // checked @@ -99,7 +100,7 @@ implements Serializable * Creates a new Permissions object containing no PermissionCollections. */ public Permissions() { - permsMap = new HashMap<>(11); + permsMap = new ConcurrentHashMap<>(11); allPermission = null; } @@ -120,18 +121,14 @@ implements Serializable * * @see PermissionCollection#isReadOnly() */ - + @Override public void add(Permission permission) { if (isReadOnly()) throw new SecurityException( "attempt to add a Permission to a readonly Permissions object"); - PermissionCollection pc; - - synchronized (this) { - pc = getPermissionCollection(permission, true); - pc.add(permission); - } + PermissionCollection pc = getPermissionCollection(permission, true); + pc.add(permission); // No sync; staleness -> optimizations delayed, which is OK if (permission instanceof AllPermission) { @@ -169,21 +166,19 @@ implements Serializable * PermissionCollection it * belongs to, false if not. */ - + @Override public boolean implies(Permission permission) { // No sync; staleness -> skip optimization, which is OK if (allPermission != null) { return true; // AllPermission has already been added } else { - synchronized (this) { - PermissionCollection pc = getPermissionCollection(permission, - false); - if (pc != null) { - return pc.implies(permission); - } else { - // none found - return false; - } + PermissionCollection pc = getPermissionCollection(permission, + false); + if (pc != null) { + return pc.implies(permission); + } else { + // none found + return false; } } } @@ -194,14 +189,12 @@ implements Serializable * * @return an enumeration of all the Permissions. */ - + @Override public Enumeration elements() { // go through each Permissions in the hash table // and call their elements() function. - synchronized (this) { - return new PermissionsEnumerator(permsMap.values().iterator()); - } + return new PermissionsEnumerator(permsMap.values().iterator()); } /** @@ -236,34 +229,39 @@ implements Serializable * It should be set to true when invoked from add(). */ private PermissionCollection getPermissionCollection(Permission p, - boolean createEmpty) { + boolean createEmpty) { Class c = p.getClass(); - PermissionCollection pc = permsMap.get(c); - if (!hasUnresolved && !createEmpty) { - return pc; - } else if (pc == null) { - - // Check for unresolved permissions - pc = (hasUnresolved ? getUnresolvedPermissions(p) : null); - - // if still null, create a new collection - if (pc == null && createEmpty) { - - pc = p.newPermissionCollection(); - - // still no PermissionCollection? - // We'll give them a PermissionsHash. - if (pc == null) - pc = new PermissionsHash(); - } - - if (pc != null) { - permsMap.put(c, pc); - } + return permsMap.get(c); } - return pc; + + // Create and add permission collection to map if it is absent. + // NOTE: cannot use lambda for mappingFunction parameter until + // JDK-8076596 is fixed. + return permsMap.computeIfAbsent(c, + new java.util.function.Function<>() { + @Override + public PermissionCollection apply(Class k) { + // Check for unresolved permissions + PermissionCollection pc = + (hasUnresolved ? getUnresolvedPermissions(p) : null); + + // if still null, create a new collection + if (pc == null && createEmpty) { + + pc = p.newPermissionCollection(); + + // still no PermissionCollection? + // We'll give them a PermissionsHash. + if (pc == null) { + pc = new PermissionsHash(); + } + } + return pc; + } + } + ); } /** @@ -277,8 +275,6 @@ implements Serializable */ private PermissionCollection getUnresolvedPermissions(Permission p) { - // Called from within synchronized method so permsMap doesn't need lock - UnresolvedPermissionCollection uc = (UnresolvedPermissionCollection) permsMap.get(UnresolvedPermission.class); @@ -362,9 +358,7 @@ implements Serializable // Copy perms into a Hashtable Hashtable, PermissionCollection> perms = new Hashtable<>(permsMap.size()*2); // no sync; estimate - synchronized (this) { - perms.putAll(permsMap); - } + perms.putAll(permsMap); // Write out serializable fields ObjectOutputStream.PutField pfields = out.putFields(); @@ -394,7 +388,7 @@ implements Serializable @SuppressWarnings("unchecked") Hashtable, PermissionCollection> perms = (Hashtable, PermissionCollection>)gfields.get("perms", null); - permsMap = new HashMap<>(perms.size()*2); + permsMap = new ConcurrentHashMap<>(perms.size()*2); permsMap.putAll(perms); // Set hasUnresolved @@ -481,14 +475,13 @@ implements Serializable * Key and value are (same) permissions objects. * Not serialized; see serialization section at end of class. */ - private transient Map permsMap; + private transient ConcurrentHashMap permsMap; /** * Create an empty PermissionsHash object. */ - PermissionsHash() { - permsMap = new HashMap<>(11); + permsMap = new ConcurrentHashMap<>(11); } /** @@ -496,11 +489,9 @@ implements Serializable * * @param permission the Permission object to add. */ - + @Override public void add(Permission permission) { - synchronized (this) { - permsMap.put(permission, permission); - } + permsMap.put(permission, permission); } /** @@ -512,23 +503,21 @@ implements Serializable * @return true if "permission" is a proper subset of a permission in * the set, false if not. */ - + @Override public boolean implies(Permission permission) { // attempt a fast lookup and implies. If that fails // then enumerate through all the permissions. - synchronized (this) { - Permission p = permsMap.get(permission); + Permission p = permsMap.get(permission); - // If permission is found, then p.equals(permission) - if (p == null) { - for (Permission p_ : permsMap.values()) { - if (p_.implies(permission)) - return true; - } - return false; - } else { - return true; + // If permission is found, then p.equals(permission) + if (p == null) { + for (Permission p_ : permsMap.values()) { + if (p_.implies(permission)) + return true; } + return false; + } else { + return true; } } @@ -537,12 +526,9 @@ implements Serializable * * @return an enumeration of all the Permissions. */ - + @Override public Enumeration elements() { - // Convert Iterator of Map values into an Enumeration - synchronized (this) { - return Collections.enumeration(permsMap.values()); - } + return permsMap.elements(); } private static final long serialVersionUID = -8491988220802933440L; @@ -570,9 +556,7 @@ implements Serializable // Copy perms into a Hashtable Hashtable perms = new Hashtable<>(permsMap.size()*2); - synchronized (this) { - perms.putAll(permsMap); - } + perms.putAll(permsMap); // Write out serializable fields ObjectOutputStream.PutField pfields = out.putFields(); @@ -597,7 +581,7 @@ implements Serializable @SuppressWarnings("unchecked") Hashtable perms = (Hashtable)gfields.get("perms", null); - permsMap = new HashMap<>(perms.size()*2); + permsMap = new ConcurrentHashMap<>(perms.size()*2); permsMap.putAll(perms); } } diff --git a/jdk/src/java.base/share/classes/java/security/SecureClassLoader.java b/jdk/src/java.base/share/classes/java/security/SecureClassLoader.java index 41b84dbe683..56d98363dd9 100644 --- a/jdk/src/java.base/share/classes/java/security/SecureClassLoader.java +++ b/jdk/src/java.base/share/classes/java/security/SecureClassLoader.java @@ -25,9 +25,11 @@ package java.security; -import java.util.HashMap; +import java.util.Map; import java.util.ArrayList; import java.net.URL; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; import sun.security.util.Debug; @@ -47,10 +49,17 @@ public class SecureClassLoader extends ClassLoader { */ private final boolean initialized; - // HashMap that maps CodeSource to ProtectionDomain - // @GuardedBy("pdcache") - private final HashMap pdcache = - new HashMap<>(11); + /* + * Map that maps the CodeSource URL (as a String) to ProtectionDomain. + * We use a String instead of a CodeSource/URL as the key to avoid + * potential expensive name service lookups. This does mean that URLs that + * are equivalent after nameservice lookup will be placed in separate + * ProtectionDomains; however during policy enforcement these URLs will be + * canonicalized and resolved resulting in a consistent set of granted + * permissions. + */ + private final Map pdcache + = new ConcurrentHashMap<>(11); private static final Debug debug = Debug.getInstance("scl"); @@ -196,23 +205,32 @@ public class SecureClassLoader extends ClassLoader { * Returned cached ProtectionDomain for the specified CodeSource. */ private ProtectionDomain getProtectionDomain(CodeSource cs) { - if (cs == null) + if (cs == null) { return null; + } - ProtectionDomain pd = null; - synchronized (pdcache) { - pd = pdcache.get(cs); - if (pd == null) { - PermissionCollection perms = getPermissions(cs); - pd = new ProtectionDomain(cs, perms, this, null); - pdcache.put(cs, pd); + // Use a String form of the URL as the key. It should behave in the + // same manner as the URL when compared for equality except that no + // nameservice lookup is done on the hostname (String comparison + // only), and the fragment is not considered. + String key = cs.getLocationNoFragString(); + if (key == null) { + key = ""; + } + return pdcache.computeIfAbsent(key, new Function<>() { + @Override + public ProtectionDomain apply(String key /* not used */) { + PermissionCollection perms + = SecureClassLoader.this.getPermissions(cs); + ProtectionDomain pd = new ProtectionDomain( + cs, perms, SecureClassLoader.this, null); if (debug != null) { - debug.println(" getPermissions "+ pd); + debug.println(" getPermissions " + pd); debug.println(""); } + return pd; } - } - return pd; + }); } /* diff --git a/jdk/src/java.base/share/classes/java/security/UnresolvedPermissionCollection.java b/jdk/src/java.base/share/classes/java/security/UnresolvedPermissionCollection.java index 87ab32d54f9..5fdc3cbc8e0 100644 --- a/jdk/src/java.base/share/classes/java/security/UnresolvedPermissionCollection.java +++ b/jdk/src/java.base/share/classes/java/security/UnresolvedPermissionCollection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,11 +25,13 @@ package java.security; -import java.util.*; -import java.io.ObjectStreamField; -import java.io.ObjectOutputStream; -import java.io.ObjectInputStream; import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.ObjectStreamField; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; /** * A UnresolvedPermissionCollection stores a collection @@ -54,14 +56,14 @@ implements java.io.Serializable * of the same type. * Not serialized; see serialization section at end of class. */ - private transient Map> perms; + private transient ConcurrentHashMap> perms; /** * Create an empty UnresolvedPermissionCollection object. * */ public UnresolvedPermissionCollection() { - perms = new HashMap<>(11); + perms = new ConcurrentHashMap<>(11); } /** @@ -70,25 +72,32 @@ implements java.io.Serializable * * @param permission the Permission object to add. */ - - public void add(Permission permission) - { + @Override + public void add(Permission permission) { if (! (permission instanceof UnresolvedPermission)) throw new IllegalArgumentException("invalid permission: "+ permission); UnresolvedPermission up = (UnresolvedPermission) permission; - List v; - synchronized (this) { - v = perms.get(up.getName()); - if (v == null) { - v = new ArrayList<>(); - perms.put(up.getName(), v); + // Add permission to map. NOTE: cannot use lambda for + // remappingFunction parameter until JDK-8076596 is fixed. + perms.compute(up.getName(), + new java.util.function.BiFunction<>() { + @Override + public List apply(String key, + List oldValue) { + if (oldValue == null) { + List v = + new CopyOnWriteArrayList<>(); + v.add(up); + return v; + } else { + oldValue.add(up); + return oldValue; + } + } } - } - synchronized (v) { - v.add(up); - } + ); } /** @@ -96,17 +105,15 @@ implements java.io.Serializable * and return the List containing them. */ List getUnresolvedPermissions(Permission p) { - synchronized (this) { - return perms.get(p.getClass().getName()); - } + return perms.get(p.getClass().getName()); } /** * always returns false for unresolved permissions * */ - public boolean implies(Permission permission) - { + @Override + public boolean implies(Permission permission) { return false; } @@ -116,18 +123,14 @@ implements java.io.Serializable * * @return an enumeration of all the UnresolvedPermission objects. */ - + @Override public Enumeration elements() { List results = new ArrayList<>(); // where results are stored // Get iterator of Map values (which are lists of permissions) - synchronized (this) { - for (List l : perms.values()) { - synchronized (l) { - results.addAll(l); - } - } + for (List l : perms.values()) { + results.addAll(l); } return Collections.enumeration(results); @@ -164,19 +167,14 @@ implements java.io.Serializable new Hashtable<>(perms.size()*2); // Convert each entry (List) into a Vector - synchronized (this) { - Set>> set = perms.entrySet(); - for (Map.Entry> e : set) { - // Convert list into Vector - List list = e.getValue(); - Vector vec = new Vector<>(list.size()); - synchronized (list) { - vec.addAll(list); - } + Set>> set = perms.entrySet(); + for (Map.Entry> e : set) { + // Convert list into Vector + List list = e.getValue(); + Vector vec = new Vector<>(list); - // Add to Hashtable being serialized - permissions.put(e.getKey(), vec); - } + // Add to Hashtable being serialized + permissions.put(e.getKey(), vec); } // Write out serializable fields @@ -203,15 +201,14 @@ implements java.io.Serializable Hashtable> permissions = (Hashtable>) gfields.get("permissions", null); - perms = new HashMap<>(permissions.size()*2); + perms = new ConcurrentHashMap<>(permissions.size()*2); // Convert each entry (Vector) into a List Set>> set = permissions.entrySet(); for (Map.Entry> e : set) { // Convert Vector into ArrayList Vector vec = e.getValue(); - List list = new ArrayList<>(vec.size()); - list.addAll(vec); + List list = new CopyOnWriteArrayList<>(vec); // Add to Hashtable being serialized perms.put(e.getKey(), list); diff --git a/jdk/src/java.base/share/classes/java/text/SimpleDateFormat.java b/jdk/src/java.base/share/classes/java/text/SimpleDateFormat.java index f76b4028041..84c472f0709 100644 --- a/jdk/src/java.base/share/classes/java/text/SimpleDateFormat.java +++ b/jdk/src/java.base/share/classes/java/text/SimpleDateFormat.java @@ -2374,7 +2374,7 @@ public class SimpleDateFormat extends DateFormat { /** * After reading an object from the input stream, the format * pattern in the object is verified. - *

    + * * @exception InvalidObjectException if the pattern is invalid */ private void readObject(ObjectInputStream stream) diff --git a/jdk/src/java.base/share/classes/java/util/DualPivotQuicksort.java b/jdk/src/java.base/share/classes/java/util/DualPivotQuicksort.java index 4682ddee5d8..fbc0359ed37 100644 --- a/jdk/src/java.base/share/classes/java/util/DualPivotQuicksort.java +++ b/jdk/src/java.base/share/classes/java/util/DualPivotQuicksort.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,11 +60,6 @@ final class DualPivotQuicksort { */ private static final int MAX_RUN_COUNT = 67; - /** - * The maximum length of run in merge sort. - */ - private static final int MAX_RUN_LENGTH = 33; - /** * If the length of an array to be sorted is less than this * constant, Quicksort is used in preference to merge sort. @@ -121,20 +116,24 @@ final class DualPivotQuicksort { // Check if the array is nearly sorted for (int k = left; k < right; run[count] = k) { + // Equal items in the beginning of the sequence + while (k < right && a[k] == a[k + 1]) + k++; + if (k == right) break; // Sequence finishes with equal items if (a[k] < a[k + 1]) { // ascending while (++k <= right && a[k - 1] <= a[k]); } else if (a[k] > a[k + 1]) { // descending while (++k <= right && a[k - 1] >= a[k]); + // Transform into an ascending sequence for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) { int t = a[lo]; a[lo] = a[hi]; a[hi] = t; } - } else { // equal - for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k]; ) { - if (--m == 0) { - sort(a, left, right, true); - return; - } - } + } + + // Merge a transformed descending sequence followed by an + // ascending sequence + if (run[count] > left && a[run[count]] >= a[run[count] - 1]) { + count--; } /* @@ -151,7 +150,7 @@ final class DualPivotQuicksort { // Implementation note: variable "right" is increased by 1. if (run[count] == right++) { // The last run contains one element run[++count] = right; - } else if (count == 1) { // The array is already sorted + } else if (count <= 1) { // The array is already sorted return; } @@ -569,20 +568,24 @@ final class DualPivotQuicksort { // Check if the array is nearly sorted for (int k = left; k < right; run[count] = k) { + // Equal items in the beginning of the sequence + while (k < right && a[k] == a[k + 1]) + k++; + if (k == right) break; // Sequence finishes with equal items if (a[k] < a[k + 1]) { // ascending while (++k <= right && a[k - 1] <= a[k]); } else if (a[k] > a[k + 1]) { // descending while (++k <= right && a[k - 1] >= a[k]); + // Transform into an ascending sequence for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) { long t = a[lo]; a[lo] = a[hi]; a[hi] = t; } - } else { // equal - for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k]; ) { - if (--m == 0) { - sort(a, left, right, true); - return; - } - } + } + + // Merge a transformed descending sequence followed by an + // ascending sequence + if (run[count] > left && a[run[count]] >= a[run[count] - 1]) { + count--; } /* @@ -599,7 +602,7 @@ final class DualPivotQuicksort { // Implementation note: variable "right" is increased by 1. if (run[count] == right++) { // The last run contains one element run[++count] = right; - } else if (count == 1) { // The array is already sorted + } else if (count <= 1) { // The array is already sorted return; } @@ -1053,20 +1056,24 @@ final class DualPivotQuicksort { // Check if the array is nearly sorted for (int k = left; k < right; run[count] = k) { + // Equal items in the beginning of the sequence + while (k < right && a[k] == a[k + 1]) + k++; + if (k == right) break; // Sequence finishes with equal items if (a[k] < a[k + 1]) { // ascending while (++k <= right && a[k - 1] <= a[k]); } else if (a[k] > a[k + 1]) { // descending while (++k <= right && a[k - 1] >= a[k]); + // Transform into an ascending sequence for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) { short t = a[lo]; a[lo] = a[hi]; a[hi] = t; } - } else { // equal - for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k]; ) { - if (--m == 0) { - sort(a, left, right, true); - return; - } - } + } + + // Merge a transformed descending sequence followed by an + // ascending sequence + if (run[count] > left && a[run[count]] >= a[run[count] - 1]) { + count--; } /* @@ -1083,7 +1090,7 @@ final class DualPivotQuicksort { // Implementation note: variable "right" is increased by 1. if (run[count] == right++) { // The last run contains one element run[++count] = right; - } else if (count == 1) { // The array is already sorted + } else if (count <= 1) { // The array is already sorted return; } @@ -1537,20 +1544,24 @@ final class DualPivotQuicksort { // Check if the array is nearly sorted for (int k = left; k < right; run[count] = k) { + // Equal items in the beginning of the sequence + while (k < right && a[k] == a[k + 1]) + k++; + if (k == right) break; // Sequence finishes with equal items if (a[k] < a[k + 1]) { // ascending while (++k <= right && a[k - 1] <= a[k]); } else if (a[k] > a[k + 1]) { // descending while (++k <= right && a[k - 1] >= a[k]); + // Transform into an ascending sequence for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) { char t = a[lo]; a[lo] = a[hi]; a[hi] = t; } - } else { // equal - for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k]; ) { - if (--m == 0) { - sort(a, left, right, true); - return; - } - } + } + + // Merge a transformed descending sequence followed by an + // ascending sequence + if (run[count] > left && a[run[count]] >= a[run[count] - 1]) { + count--; } /* @@ -1567,7 +1578,7 @@ final class DualPivotQuicksort { // Implementation note: variable "right" is increased by 1. if (run[count] == right++) { // The last run contains one element run[++count] = right; - } else if (count == 1) { // The array is already sorted + } else if (count <= 1) { // The array is already sorted return; } @@ -2117,20 +2128,24 @@ final class DualPivotQuicksort { // Check if the array is nearly sorted for (int k = left; k < right; run[count] = k) { + // Equal items in the beginning of the sequence + while (k < right && a[k] == a[k + 1]) + k++; + if (k == right) break; // Sequence finishes with equal items if (a[k] < a[k + 1]) { // ascending while (++k <= right && a[k - 1] <= a[k]); } else if (a[k] > a[k + 1]) { // descending while (++k <= right && a[k - 1] >= a[k]); + // Transform into an ascending sequence for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) { float t = a[lo]; a[lo] = a[hi]; a[hi] = t; } - } else { // equal - for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k]; ) { - if (--m == 0) { - sort(a, left, right, true); - return; - } - } + } + + // Merge a transformed descending sequence followed by an + // ascending sequence + if (run[count] > left && a[run[count]] >= a[run[count] - 1]) { + count--; } /* @@ -2147,7 +2162,7 @@ final class DualPivotQuicksort { // Implementation note: variable "right" is increased by 1. if (run[count] == right++) { // The last run contains one element run[++count] = right; - } else if (count == 1) { // The array is already sorted + } else if (count <= 1) { // The array is already sorted return; } @@ -2656,20 +2671,24 @@ final class DualPivotQuicksort { // Check if the array is nearly sorted for (int k = left; k < right; run[count] = k) { + // Equal items in the beginning of the sequence + while (k < right && a[k] == a[k + 1]) + k++; + if (k == right) break; // Sequence finishes with equal items if (a[k] < a[k + 1]) { // ascending while (++k <= right && a[k - 1] <= a[k]); } else if (a[k] > a[k + 1]) { // descending while (++k <= right && a[k - 1] >= a[k]); + // Transform into an ascending sequence for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) { double t = a[lo]; a[lo] = a[hi]; a[hi] = t; } - } else { // equal - for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k]; ) { - if (--m == 0) { - sort(a, left, right, true); - return; - } - } + } + + // Merge a transformed descending sequence followed by an + // ascending sequence + if (run[count] > left && a[run[count]] >= a[run[count] - 1]) { + count--; } /* @@ -2686,7 +2705,7 @@ final class DualPivotQuicksort { // Implementation note: variable "right" is increased by 1. if (run[count] == right++) { // The last run contains one element run[++count] = right; - } else if (count == 1) { // The array is already sorted + } else if (count <= 1) { // The array is already sorted return; } diff --git a/jdk/src/java.base/share/classes/java/util/PropertyPermission.java b/jdk/src/java.base/share/classes/java/util/PropertyPermission.java index 7e818a90b64..329e0f94232 100644 --- a/jdk/src/java.base/share/classes/java/util/PropertyPermission.java +++ b/jdk/src/java.base/share/classes/java/util/PropertyPermission.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,18 +25,15 @@ package java.util; -import java.io.Serializable; import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.ObjectStreamField; +import java.io.Serializable; import java.security.*; -import java.util.Map; -import java.util.HashMap; import java.util.Enumeration; import java.util.Hashtable; -import java.util.Collections; -import java.io.ObjectStreamField; -import java.io.ObjectOutputStream; -import java.io.ObjectInputStream; -import java.io.IOException; +import java.util.concurrent.ConcurrentHashMap; import sun.security.util.SecurityConstants; /** @@ -161,6 +158,16 @@ public final class PropertyPermission extends BasicPermission { init(getMask(actions)); } + /** + * Creates a PropertyPermission object with the specified name and + * a pre-calculated mask. Avoids the overhead of re-computing the mask. + * Called by PropertyPermissionCollection. + */ + PropertyPermission(String name, int mask) { + super(name, getActions(mask)); + this.mask = mask; + } + /** * Checks if this PropertyPermission object "implies" the specified * permission. @@ -178,6 +185,7 @@ public final class PropertyPermission extends BasicPermission { * @return true if the specified permission is implied by this object, * false if not. */ + @Override public boolean implies(Permission p) { if (!(p instanceof PropertyPermission)) return false; @@ -198,6 +206,7 @@ public final class PropertyPermission extends BasicPermission { * @return true if obj is a PropertyPermission, and has the same name and * actions as this PropertyPermission object. */ + @Override public boolean equals(Object obj) { if (obj == this) return true; @@ -219,6 +228,7 @@ public final class PropertyPermission extends BasicPermission { * * @return a hash code value for this object. */ + @Override public int hashCode() { return this.getName().hashCode(); } @@ -345,6 +355,7 @@ public final class PropertyPermission extends BasicPermission { * * @return the canonical string representation of the actions. */ + @Override public String getActions() { if (actions == null) actions = getActions(this.mask); @@ -369,6 +380,7 @@ public final class PropertyPermission extends BasicPermission { * @return a new PermissionCollection object suitable for storing * PropertyPermissions. */ + @Override public PermissionCollection newPermissionCollection() { return new PropertyPermissionCollection(); } @@ -425,7 +437,7 @@ final class PropertyPermissionCollection extends PermissionCollection * Key is property name; value is PropertyPermission. * Not serialized; see serialization section at end of class. */ - private transient Map perms; + private transient ConcurrentHashMap perms; /** * Boolean saying if "*" is in the collection. @@ -439,7 +451,7 @@ final class PropertyPermissionCollection extends PermissionCollection * Create an empty PropertyPermissionCollection object. */ public PropertyPermissionCollection() { - perms = new HashMap<>(32); // Capacity for default policy + perms = new ConcurrentHashMap<>(32); // Capacity for default policy all_allowed = false; } @@ -455,6 +467,7 @@ final class PropertyPermissionCollection extends PermissionCollection * @exception SecurityException - if this PropertyPermissionCollection * object has been marked readonly */ + @Override public void add(Permission permission) { if (! (permission instanceof PropertyPermission)) throw new IllegalArgumentException("invalid permission: "+ @@ -466,21 +479,30 @@ final class PropertyPermissionCollection extends PermissionCollection PropertyPermission pp = (PropertyPermission) permission; String propName = pp.getName(); - synchronized (this) { - PropertyPermission existing = perms.get(propName); + // Add permission to map if it is absent, or replace with new + // permission if applicable. NOTE: cannot use lambda for + // remappingFunction parameter until JDK-8076596 is fixed. + perms.merge(propName, pp, + new java.util.function.BiFunction<>() { + @Override + public PropertyPermission apply(PropertyPermission existingVal, + PropertyPermission newVal) { - if (existing != null) { - int oldMask = existing.getMask(); - int newMask = pp.getMask(); - if (oldMask != newMask) { - int effective = oldMask | newMask; - String actions = PropertyPermission.getActions(effective); - perms.put(propName, new PropertyPermission(propName, actions)); + int oldMask = existingVal.getMask(); + int newMask = newVal.getMask(); + if (oldMask != newMask) { + int effective = oldMask | newMask; + if (effective == newMask) { + return newVal; + } + if (effective != oldMask) { + return new PropertyPermission(propName, effective); + } + } + return existingVal; } - } else { - perms.put(propName, pp); } - } + ); if (!all_allowed) { if (propName.equals("*")) @@ -497,9 +519,10 @@ final class PropertyPermissionCollection extends PermissionCollection * @return true if "permission" is a proper subset of a permission in * the set, false if not. */ + @Override public boolean implies(Permission permission) { if (! (permission instanceof PropertyPermission)) - return false; + return false; PropertyPermission pp = (PropertyPermission) permission; PropertyPermission x; @@ -509,9 +532,7 @@ final class PropertyPermissionCollection extends PermissionCollection // short circuit if the "*" Permission was added if (all_allowed) { - synchronized (this) { - x = perms.get("*"); - } + x = perms.get("*"); if (x != null) { effective |= x.getMask(); if ((effective & desired) == desired) @@ -526,9 +547,7 @@ final class PropertyPermissionCollection extends PermissionCollection String name = pp.getName(); //System.out.println("check "+name); - synchronized (this) { - x = perms.get(name); - } + x = perms.get(name); if (x != null) { // we have a direct hit! @@ -546,9 +565,7 @@ final class PropertyPermissionCollection extends PermissionCollection name = name.substring(0, last+1) + "*"; //System.out.println("check "+name); - synchronized (this) { - x = perms.get(name); - } + x = perms.get(name); if (x != null) { effective |= x.getMask(); @@ -569,16 +586,14 @@ final class PropertyPermissionCollection extends PermissionCollection * * @return an enumeration of all the PropertyPermission objects. */ + @Override @SuppressWarnings("unchecked") public Enumeration elements() { - // Convert Iterator of Map values into an Enumeration - synchronized (this) { - /** - * Casting to rawtype since Enumeration - * cannot be directly cast to Enumeration - */ - return (Enumeration)Collections.enumeration(perms.values()); - } + /** + * Casting to rawtype since Enumeration + * cannot be directly cast to Enumeration + */ + return (Enumeration)perms.elements(); } private static final long serialVersionUID = 7015263904581634791L; @@ -616,9 +631,7 @@ final class PropertyPermissionCollection extends PermissionCollection // Copy perms into a Hashtable Hashtable permissions = new Hashtable<>(perms.size()*2); - synchronized (this) { - permissions.putAll(perms); - } + permissions.putAll(perms); // Write out serializable fields ObjectOutputStream.PutField pfields = out.putFields(); @@ -646,7 +659,7 @@ final class PropertyPermissionCollection extends PermissionCollection @SuppressWarnings("unchecked") Hashtable permissions = (Hashtable)gfields.get("permissions", null); - perms = new HashMap<>(permissions.size()*2); + perms = new ConcurrentHashMap<>(permissions.size()*2); perms.putAll(permissions); } } diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java b/jdk/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java index 5ebd04923d4..b59042653e7 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java @@ -780,7 +780,9 @@ public class LinkedTransferQueue extends AbstractQueue } /** - * Version of firstOfMode used by Spliterator + * Version of firstOfMode used by Spliterator. Callers must + * recheck if the returned node's item field is null or + * self-linked before using. */ final Node firstDataNode() { for (Node p = head; p != null;) { @@ -953,11 +955,12 @@ public class LinkedTransferQueue extends AbstractQueue Object[] a = new Object[n]; int i = 0; do { - if ((a[i] = p.item) != null) + Object e = p.item; + if (e != p && (a[i] = e) != null) ++i; if (p == (p = p.next)) p = q.firstDataNode(); - } while (p != null && i < n); + } while (p != null && i < n && p.isData); if ((current = p) == null) exhausted = true; if (i > 0) { @@ -980,11 +983,11 @@ public class LinkedTransferQueue extends AbstractQueue exhausted = true; do { Object e = p.item; + if (e != null && e != p) + action.accept((E)e); if (p == (p = p.next)) p = q.firstDataNode(); - if (e != null) - action.accept((E)e); - } while (p != null); + } while (p != null && p.isData); } } @@ -997,10 +1000,11 @@ public class LinkedTransferQueue extends AbstractQueue ((p = current) != null || (p = q.firstDataNode()) != null)) { Object e; do { - e = p.item; + if ((e = p.item) == p) + e = null; if (p == (p = p.next)) p = q.firstDataNode(); - } while (e == null && p != null); + } while (e == null && p != null && p.isData); if ((current = p) == null) exhausted = true; if (e != null) { diff --git a/jdk/src/java.base/share/classes/javax/security/auth/Subject.java b/jdk/src/java.base/share/classes/javax/security/auth/Subject.java index e570eb6686f..96c6eeaf30e 100644 --- a/jdk/src/java.base/share/classes/javax/security/auth/Subject.java +++ b/jdk/src/java.base/share/classes/javax/security/auth/Subject.java @@ -1401,8 +1401,6 @@ public final class Subject implements java.io.Serializable { /** * Writes this object out to a stream (i.e., serializes it). * - *

    - * * @serialData If this is a private credential set, * a security check is performed to ensure that * the caller has permission to access each credential diff --git a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceClassVisitor.java b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceClassVisitor.java index e927bff9ea5..97163ce47f1 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceClassVisitor.java +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/util/TraceClassVisitor.java @@ -74,36 +74,34 @@ import jdk.internal.org.objectweb.asm.TypePath; * visitor chain to trace the class that is visited at a given point in this * chain. This may be useful for debugging purposes. *

    - * The trace printed when visiting the Hello class is the following: - *

    + * The trace printed when visiting the {@code Hello} class is the following: *

    * - *
    + * 
    {@code
      * // class version 49.0 (49) // access flags 0x21 public class Hello {
      *
      * // compiled from: Hello.java
      *
    - * // access flags 0x1 public <init> ()V ALOAD 0 INVOKESPECIAL
    - * java/lang/Object <init> ()V RETURN MAXSTACK = 1 MAXLOCALS = 1
    + * // access flags 0x1 public  ()V ALOAD 0 INVOKESPECIAL
    + * java/lang/Object  ()V RETURN MAXSTACK = 1 MAXLOCALS = 1
      *
      * // access flags 0x9 public static main ([Ljava/lang/String;)V GETSTATIC
    - * java/lang/System out Ljava/io/PrintStream; LDC "hello"
    + * java/lang/System out Ljava/io/PrintStream; LDC "hello"
      * INVOKEVIRTUAL java/io/PrintStream println (Ljava/lang/String;)V RETURN
      * MAXSTACK = 2 MAXLOCALS = 1 }
    - * 
    + * }
    * - *
    where Hello is defined by: - *

    + * where {@code Hello} is defined by: *

    * - *
    + * 
    {@code
      * public class Hello {
      *
      *     public static void main(String[] args) {
    - *         System.out.println("hello");
    + *         System.out.println("hello");
      *     }
      * }
    - * 
    + * }
    * *
    * @@ -137,7 +135,7 @@ public final class TraceClassVisitor extends ClassVisitor { * * @param cv * the {@link ClassVisitor} to which this visitor delegates - * calls. May be null. + * calls. May be {@code null}. * @param pw * the print writer to be used to print the class. */ @@ -150,7 +148,7 @@ public final class TraceClassVisitor extends ClassVisitor { * * @param cv * the {@link ClassVisitor} to which this visitor delegates - * calls. May be null. + * calls. May be {@code null}. * @param p * the object that actually converts visit events into text. * @param pw diff --git a/jdk/src/java.base/share/classes/sun/invoke/util/BytecodeName.java b/jdk/src/java.base/share/classes/sun/invoke/util/BytecodeName.java index 9b8fa35cb70..fa34d2bbb6f 100644 --- a/jdk/src/java.base/share/classes/sun/invoke/util/BytecodeName.java +++ b/jdk/src/java.base/share/classes/sun/invoke/util/BytecodeName.java @@ -464,7 +464,7 @@ public class BytecodeName { * Report whether a character is safe in a bytecode name. * This is true of any unicode character except the following * dangerous characters: {@code ".;:$[]<>/"}. - * @param s the proposed character + * @param c the proposed character * @return true if the character is safe to use in classfiles */ public static boolean isSafeBytecodeChar(char c) { diff --git a/jdk/src/java.base/share/classes/sun/misc/ExtensionDependency.java b/jdk/src/java.base/share/classes/sun/misc/ExtensionDependency.java deleted file mode 100644 index 97c9480efd8..00000000000 --- a/jdk/src/java.base/share/classes/sun/misc/ExtensionDependency.java +++ /dev/null @@ -1,554 +0,0 @@ -/* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. 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.misc; - -import java.io.File; -import java.io.FilenameFilter; -import java.io.IOException; -import java.io.FileNotFoundException; -import java.util.StringTokenizer; -import java.util.Vector; -import java.util.Enumeration; -import java.util.jar.JarFile; -import java.util.jar.Manifest; -import java.util.jar.Attributes; -import java.util.jar.Attributes.Name; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.security.PrivilegedExceptionAction; -import java.security.PrivilegedActionException; -import java.net.URL; -import java.net.MalformedURLException; -import sun.net.www.ParseUtil; - -/** - * This class checks dependent extensions a particular jar file may have - * declared through its manifest attributes. - *

    - * Jar file declared dependent extensions through the extension-list - * attribute. The extension-list contains a list of keys used to - * fetch the other attributes describing the required extension. - * If key is the extension key declared in the extension-list - * attribute, the following describing attribute can be found in - * the manifest: - *

      - *
    • key-Extension-Name: (Specification package name)
    • - *
    • key-Specification-Version: (Specification-Version)
    • - *
    • key-Implementation-Version: (Implementation-Version)
    • - *
    • key-Implementation-Vendor-Id: (Imlementation-Vendor-Id)
    • - *
    • key-Implementation-Version: (Implementation version)
    • - *
    • key-Implementation-URL: (URL to download the requested extension)
    • - *
    - *

    - * This class also maintain versioning consistency of installed - * extensions dependencies declared in jar file manifest. - * - * @deprecated this class will be removed in a future release. - * @author Jerome Dochez - */ -@Deprecated -public class ExtensionDependency { - - /* Callbak interfaces to delegate installation of missing extensions */ - private static Vector providers; - - /** - * Register an ExtensionInstallationProvider. The provider is responsible - * for handling the installation (upgrade) of any missing extensions. - * - * @param eip ExtensionInstallationProvider implementation - */ - public synchronized static void addExtensionInstallationProvider - (ExtensionInstallationProvider eip) - { - if (providers == null) { - providers = new Vector<>(); - } - providers.add(eip); - } - - /** - * Unregister a previously installed installation provider - */ - public synchronized static void removeExtensionInstallationProvider - (ExtensionInstallationProvider eip) - { - providers.remove(eip); - } - - /** - * Checks the dependencies of the jar file on installed extension. - * - * @param jar containing the attributes declaring the dependencies - */ - public static boolean checkExtensionsDependencies(JarFile jar) - { - if (providers == null) { - // no need to bother, nobody is registered to install missing - // extensions - return true; - } - - try { - ExtensionDependency extDep = new ExtensionDependency(); - return extDep.checkExtensions(jar); - } catch (ExtensionInstallationException e) { - debug(e.getMessage()); - } - return false; - } - - /* - * Check for all declared required extensions in the jar file - * manifest. - */ - protected boolean checkExtensions(JarFile jar) - throws ExtensionInstallationException - { - Manifest man; - try { - man = jar.getManifest(); - } catch (IOException e) { - return false; - } - - if (man == null) { - // The applet does not define a manifest file, so - // we just assume all dependencies are satisfied. - return true; - } - - boolean result = true; - Attributes attr = man.getMainAttributes(); - if (attr != null) { - // Let's get the list of declared dependencies - String value = attr.getValue(Name.EXTENSION_LIST); - if (value != null) { - StringTokenizer st = new StringTokenizer(value); - // Iterate over all declared dependencies - while (st.hasMoreTokens()) { - String extensionName = st.nextToken(); - debug("The file " + jar.getName() + - " appears to depend on " + extensionName); - // Sanity Check - String extName = extensionName + "-" + - Name.EXTENSION_NAME.toString(); - if (attr.getValue(extName) == null) { - debug("The jar file " + jar.getName() + - " appers to depend on " - + extensionName + " but does not define the " + - extName + " attribute in its manifest "); - - } else { - if (!checkExtension(extensionName, attr)) { - debug("Failed installing " + extensionName); - result = false; - } - } - } - } else { - debug("No dependencies for " + jar.getName()); - } - } - return result; - } - - - /* - * Check that a particular dependency on an extension is satisfied. - * - * @param extensionName is the key used for the attributes in the manifest - * @param attr is the attributes of the manifest file - * - * @return true if the dependency is satisfied by the installed extensions - */ - protected synchronized boolean checkExtension(final String extensionName, - final Attributes attr) - throws ExtensionInstallationException - { - debug("Checking extension " + extensionName); - if (checkExtensionAgainstInstalled(extensionName, attr)) - return true; - - debug("Extension not currently installed "); - ExtensionInfo reqInfo = new ExtensionInfo(extensionName, attr); - return installExtension(reqInfo, null); - } - - /* - * Check if a particular extension is part of the currently installed - * extensions. - * - * @param extensionName is the key for the attributes in the manifest - * @param attr is the attributes of the manifest - * - * @return true if the requested extension is already installed - */ - boolean checkExtensionAgainstInstalled(String extensionName, - Attributes attr) - throws ExtensionInstallationException - { - File fExtension = checkExtensionExists(extensionName); - - if (fExtension != null) { - // Extension already installed, just check against this one - try { - if (checkExtensionAgainst(extensionName, attr, fExtension)) - return true; - } catch (FileNotFoundException e) { - debugException(e); - } catch (IOException e) { - debugException(e); - } - return false; - - } else { - // Not sure if extension is already installed, so check all the - // installed extension jar files to see if we get a match - - File[] installedExts; - - try { - // Get the list of installed extension jar files so we can - // compare the installed versus the requested extension - installedExts = getInstalledExtensions(); - } catch(IOException e) { - debugException(e); - return false; - } - - for (int i=0;i() { - public Manifest run() - throws IOException, FileNotFoundException { - if (!file.exists()) - throw new FileNotFoundException(file.getName()); - JarFile jarFile = new JarFile(file); - return jarFile.getManifest(); - } - }); - } catch(PrivilegedActionException e) { - if (e.getException() instanceof FileNotFoundException) - throw (FileNotFoundException) e.getException(); - throw (IOException) e.getException(); - } - - // Construct the extension information object - ExtensionInfo reqInfo = new ExtensionInfo(extensionName, attr); - debug("Requested Extension : " + reqInfo); - - int isCompatible = ExtensionInfo.INCOMPATIBLE; - ExtensionInfo instInfo = null; - - if (man != null) { - Attributes instAttr = man.getMainAttributes(); - if (instAttr != null) { - instInfo = new ExtensionInfo(null, instAttr); - debug("Extension Installed " + instInfo); - isCompatible = instInfo.isCompatibleWith(reqInfo); - switch(isCompatible) { - case ExtensionInfo.COMPATIBLE: - debug("Extensions are compatible"); - return true; - - case ExtensionInfo.INCOMPATIBLE: - debug("Extensions are incompatible"); - return false; - - default: - // everything else - debug("Extensions require an upgrade or vendor switch"); - return installExtension(reqInfo, instInfo); - - } - } - } - return false; - } - - /* - * An required extension is missing, if an ExtensionInstallationProvider is - * registered, delegate the installation of that particular extension to it. - * - * @param reqInfo Missing extension information - * @param instInfo Older installed version information - * - * @return true if the installation is successful - */ - protected boolean installExtension(ExtensionInfo reqInfo, - ExtensionInfo instInfo) - throws ExtensionInstallationException - { - Vector currentProviders; - synchronized(providers) { - @SuppressWarnings("unchecked") - Vector tmp = - (Vector) providers.clone(); - currentProviders = tmp; - } - for (Enumeration e = currentProviders.elements(); - e.hasMoreElements();) { - ExtensionInstallationProvider eip = e.nextElement(); - - if (eip!=null) { - // delegate the installation to the provider - if (eip.installExtension(reqInfo, instInfo)) { - debug(reqInfo.name + " installation successful"); - Launcher.ExtClassLoader cl = (Launcher.ExtClassLoader) - Launcher.getLauncher().getClassLoader().getParent(); - addNewExtensionsToClassLoader(cl); - return true; - } - } - } - // We have tried all of our providers, noone could install this - // extension, we just return failure at this point - debug(reqInfo.name + " installation failed"); - return false; - } - - /** - * Checks if the extension, that is specified in the extension-list in - * the applet jar manifest, is already installed (i.e. exists in the - * extension directory). - * - * @param extensionName extension name in the extension-list - * - * @return the extension if it exists in the extension directory - */ - private File checkExtensionExists(String extensionName) { - // Function added to fix bug 4504166 - final String extName = extensionName; - final String[] fileExt = {".jar", ".zip"}; - - return AccessController.doPrivileged( - new PrivilegedAction() { - public File run() { - try { - File fExtension; - File[] dirs = getExtDirs(); - - // Search the extension directories for the extension that is specified - // in the attribute extension-list in the applet jar manifest - for (int i=0;i urls = new Vector(); - for (int i = 0; i < dirs.length; i++) { - String[] files = dirs[i].list(new JarFilter()); - if (files != null) { - debug("getExtFiles files.length " + files.length); - for (int j = 0; j < files.length; j++) { - File f = new File(dirs[i], files[j]); - urls.add(f); - debug("getExtFiles f["+j+"] "+ f); - } - } - } - File[] ua = new File[urls.size()]; - urls.copyInto(ua); - debug("getExtFiles ua.length " + ua.length); - return ua; - } - - /* - * @return the list of installed extensions jar files - */ - private File[] getInstalledExtensions() throws IOException { - return AccessController.doPrivileged( - new PrivilegedAction() { - public File[] run() { - try { - return getExtFiles(getExtDirs()); - } catch(IOException e) { - debug("Cannot get list of installed extensions"); - debugException(e); - return new File[0]; - } - } - }); - } - - /* - * Add the newly installed jar file to the extension class loader. - * - * @param cl the current installed extension class loader - * - * @return true if successful - */ - private Boolean addNewExtensionsToClassLoader(Launcher.ExtClassLoader cl) { - try { - File[] installedExts = getInstalledExtensions(); - for (int i=0;i() { - public URL run() { - try { - return ParseUtil.fileToEncodedURL(instFile); - } catch (MalformedURLException e) { - debugException(e); - return null; - } - } - }); - if (instURL != null) { - URL[] urls = cl.getURLs(); - boolean found=false; - for (int j = 0; j{@code - * < 0 if source < version - * > 0 if source > version - * = 0 if source = version} - */ - private int compareExtensionVersion(String source, String target) - throws NumberFormatException - { - source = source.toLowerCase(); - target = target.toLowerCase(); - - return strictCompareExtensionVersion(source, target); - } - - - /* - * helper method to compare two versions. - * version are in the x.y.z.t pattern. - * - * @param source version to compare to - * @param target version used to compare against - * @return

    {@code
    -     *   < 0 if source < version
    -     *   > 0 if source > version
    -     *   = 0 if source = version}
    - */ - private int strictCompareExtensionVersion(String source, String target) - throws NumberFormatException - { - if (source.equals(target)) - return 0; - - StringTokenizer stk = new StringTokenizer(source, ".,"); - StringTokenizer ttk = new StringTokenizer(target, ".,"); - - // Compare number - int n = 0, m = 0, result = 0; - - // Convert token into meaning number for comparision - if (stk.hasMoreTokens()) - n = convertToken(stk.nextToken().toString()); - - // Convert token into meaning number for comparision - if (ttk.hasMoreTokens()) - m = convertToken(ttk.nextToken().toString()); - - if (n > m) - return 1; - else if (m > n) - return -1; - else - { - // Look for index of "." in the string - int sIdx = source.indexOf('.'); - int tIdx = target.indexOf('.'); - - if (sIdx == -1) - sIdx = source.length() - 1; - - if (tIdx == -1) - tIdx = target.length() - 1; - - return strictCompareExtensionVersion(source.substring(sIdx + 1), - target.substring(tIdx + 1)); - } - } - - private int convertToken(String token) - { - if (token == null || token.equals("")) - return 0; - - int charValue = 0; - int charVersion = 0; - int patchVersion = 0; - int strLength = token.length(); - int endIndex = strLength; - char lastChar; - - Object[] args = {name}; - MessageFormat mf = new MessageFormat(rb.getString("optpkg.versionerror")); - String versionError = mf.format(args); - - // Look for "-" for pre-release - int prIndex = token.indexOf('-'); - - // Look for "_" for patch release - int patchIndex = token.indexOf('_'); - - if (prIndex == -1 && patchIndex == -1) - { - // This is a FCS release - try { - return Integer.parseInt(token) * 100; - } catch (NumberFormatException e) { - System.out.println(versionError); - return 0; - } - } - else if (patchIndex != -1) - { - // This is a patch (update) release - int prversion; - try { - // Obtain the version - prversion = Integer.parseInt(token.substring(0, patchIndex)); - - // Check to see if the patch version is in the n.n.n_nnl format (special release) - lastChar = token.charAt(strLength-1); - if (Character.isLetter(lastChar)) { - // letters a-z have values from 10-35 - charValue = Character.getNumericValue(lastChar); - endIndex = strLength-1; - - // Obtain the patch version id - patchVersion = Integer.parseInt(token.substring(patchIndex+1, endIndex)); - - if (charValue >= Character.getNumericValue('a') && charValue <= Character.getNumericValue('z')) { - // This is a special release - charVersion = (patchVersion * 100) + charValue; - } else { - // character is not a a-z letter, ignore - charVersion = 0; - System.out.println(versionError); - } - } else { - // This is a regular update release. Obtain the patch version id - patchVersion = Integer.parseInt(token.substring(patchIndex+1, endIndex)); - } - } catch (NumberFormatException e) { - System.out.println(versionError); - return 0; - } - return prversion * 100 + (patchVersion + charVersion); - } - else - { - //This is a milestone release, either a early access, alpha, beta, or RC - - // Obtain the version - int mrversion; - try { - mrversion = Integer.parseInt(token.substring(0, prIndex)); - } catch (NumberFormatException e) { - System.out.println(versionError); - return 0; - } - - // Obtain the patch version string, including the milestone + version - String prString = token.substring(prIndex + 1); - - // Milestone version - String msVersion = ""; - int delta = 0; - - if (prString.indexOf("ea") != -1) - { - msVersion = prString.substring(2); - delta = 50; - } - else if (prString.indexOf("alpha") != -1) - { - msVersion = prString.substring(5); - delta = 40; - } - else if (prString.indexOf("beta") != -1) - { - msVersion = prString.substring(4); - delta = 30; - } - else if (prString.indexOf("rc") != -1) - { - msVersion = prString.substring(2); - delta = 20; - } - - if (msVersion == null || msVersion.equals("")) - { - // No version after the milestone, assume 0 - return mrversion * 100 - delta ; - } - else - { - // Convert the milestone version - try { - return mrversion * 100 - delta + Integer.parseInt(msVersion); - } catch (NumberFormatException e) { - System.out.println(versionError); - return 0; - } - } - } - } -} diff --git a/jdk/src/java.base/share/classes/sun/misc/ExtensionInstallationProvider.java b/jdk/src/java.base/share/classes/sun/misc/ExtensionInstallationProvider.java deleted file mode 100644 index 438e396b2c2..00000000000 --- a/jdk/src/java.base/share/classes/sun/misc/ExtensionInstallationProvider.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved. - * 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.misc; - -/** - * This interface defines the contract a extension installation capable - * provided to the extension installation dependency mechanism to - * install new extensions on the user's disk - * - * @deprecated this class will be removed in a future release. - * @author Jerome Dochez - */ -@Deprecated -public interface ExtensionInstallationProvider { - - /* - *

    - * Request the installation of an extension in the extension directory - *

    - * - * @param requestExtInfo information on the extension that need to be - * installed - * @param installedExtInfo information on the current compatible installed - * extension. Can be null if no current installation has been found. - * @return true if the installation is successful, false if the - * installation could not be attempted. - * @exception ExtensionInstallationException if an installation was - * attempted but did not succeed. - */ - boolean installExtension(ExtensionInfo requestExtInfo, - ExtensionInfo installedExtInfo) - throws ExtensionInstallationException; -} diff --git a/jdk/src/java.base/share/classes/sun/net/TelnetInputStream.java b/jdk/src/java.base/share/classes/sun/net/TelnetInputStream.java index 3b27edcb3e4..4f4d84e24f6 100644 --- a/jdk/src/java.base/share/classes/sun/net/TelnetInputStream.java +++ b/jdk/src/java.base/share/classes/sun/net/TelnetInputStream.java @@ -31,7 +31,7 @@ import java.io.*; * This class provides input and output streams for telnet clients. * This class overrides read to do CRLF processing as specified in * RFC 854. The class assumes it is running on a system where lines - * are terminated with a single newline character. + * are terminated with a single newline {@literal } character. * * This is the relevant section of RFC 824 regarding CRLF processing: * diff --git a/jdk/src/java.base/share/classes/sun/net/TelnetOutputStream.java b/jdk/src/java.base/share/classes/sun/net/TelnetOutputStream.java index 74f6c9ca973..9a399ed40d0 100644 --- a/jdk/src/java.base/share/classes/sun/net/TelnetOutputStream.java +++ b/jdk/src/java.base/share/classes/sun/net/TelnetOutputStream.java @@ -31,7 +31,7 @@ import java.io.*; * This class provides input and output streams for telnet clients. * This class overrides write to do CRLF processing as specified in * RFC 854. The class assumes it is running on a system where lines - * are terminated with a single newline character. + * are terminated with a single newline {@literal } character. * * This is the relevant section of RFC 824 regarding CRLF processing: * diff --git a/jdk/src/java.base/share/classes/sun/net/URLCanonicalizer.java b/jdk/src/java.base/share/classes/sun/net/URLCanonicalizer.java index dfa84bbd776..1a53f4d6173 100644 --- a/jdk/src/java.base/share/classes/sun/net/URLCanonicalizer.java +++ b/jdk/src/java.base/share/classes/sun/net/URLCanonicalizer.java @@ -28,10 +28,12 @@ package sun.net; /** * Helper class to map URL "abbreviations" to real URLs. * The default implementation supports the following mappings: + *
    {@code
      *   ftp.mumble.bar/... => ftp://ftp.mumble.bar/...
      *   gopher.mumble.bar/... => gopher://gopher.mumble.bar/...
      *   other.name.dom/... => http://other.name.dom/...
      *   /foo/... => file:/foo/...
    + * }
    * * Full URLs (those including a protocol name) are passed through unchanged. * diff --git a/jdk/src/java.base/share/classes/sun/net/ftp/impl/FtpClient.java b/jdk/src/java.base/share/classes/sun/net/ftp/impl/FtpClient.java index 47aabf5cbf2..f21217c58c5 100644 --- a/jdk/src/java.base/share/classes/sun/net/ftp/impl/FtpClient.java +++ b/jdk/src/java.base/share/classes/sun/net/ftp/impl/FtpClient.java @@ -1211,7 +1211,7 @@ public class FtpClient extends sun.net.ftp.FtpClient { * The OutputStream is not closed by this method at the end * of the transfer. * - * @param name a String containing the name of the file to + * @param name a {@code String} containing the name of the file to * retreive from the server. * @param local the OutputStream the file should be written to. * @throws IOException if the transfer fails. diff --git a/jdk/src/java.base/share/classes/sun/net/www/MessageHeader.java b/jdk/src/java.base/share/classes/sun/net/www/MessageHeader.java index c4ab99ac34c..ab192795332 100644 --- a/jdk/src/java.base/share/classes/sun/net/www/MessageHeader.java +++ b/jdk/src/java.base/share/classes/sun/net/www/MessageHeader.java @@ -411,7 +411,7 @@ class MessageHeader { } /** Convert a message-id string to canonical form (strips off - leading and trailing <>s) */ + leading and trailing {@literal <>s}) */ public static String canonicalID(String id) { if (id == null) return ""; diff --git a/jdk/src/java.base/share/classes/sun/net/www/http/HttpClient.java b/jdk/src/java.base/share/classes/sun/net/www/http/HttpClient.java index 0d7f09c6132..ddf8eddff01 100644 --- a/jdk/src/java.base/share/classes/sun/net/www/http/HttpClient.java +++ b/jdk/src/java.base/share/classes/sun/net/www/http/HttpClient.java @@ -625,7 +625,7 @@ public class HttpClient extends NetworkClient { } /** Parse the first line of the HTTP request. It usually looks - something like: "HTTP/1.0 comment\r\n". */ + something like: {@literal "HTTP/1.0 comment\r\n"}. */ public boolean parseHTTP(MessageHeader responses, ProgressSource pi, HttpURLConnection httpuc) throws IOException { diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java index d787ab3df1a..4f8fde23876 100644 --- a/jdk/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java @@ -68,13 +68,14 @@ import sun.security.action.GetPropertyAction; *
  • Disconnect
  • *
* You should not have to use it directly in most cases because all will be handled - * in a abstract layer. Here is an example of how to use the class : - *

- * URL url = new URL("ftp://ftp.sun.com/pub/test.txt");

- * UrlConnection con = url.openConnection();

- * InputStream is = con.getInputStream();

- * ...

- * is.close(); + * in a abstract layer. Here is an example of how to use the class: + *

{@code
+ * URL url = new URL("ftp://ftp.sun.com/pub/test.txt");
+ * UrlConnection con = url.openConnection();
+ * InputStream is = con.getInputStream();
+ * ...
+ * is.close();
+ * }
* * @see sun.net.ftp.FtpClient */ @@ -158,7 +159,7 @@ public class FtpURLConnection extends URLConnection { /** * Creates an FtpURLConnection from a URL. * - * @param url The URL to retrieve or store. + * @param url The {@code URL} to retrieve or store. */ public FtpURLConnection(URL url) { this(url, null); @@ -382,7 +383,7 @@ public class FtpURLConnection extends URLConnection { * Get the InputStream to retreive the remote file. It will issue the * "get" (or "dir") command to the ftp server. * - * @return the InputStream to the connection. + * @return the {@code InputStream} to the connection. * * @throws IOException if already opened for output * @throws FtpProtocolException if errors occur during the transfert. @@ -495,7 +496,7 @@ public class FtpURLConnection extends URLConnection { * Get the OutputStream to store the remote file. It will issue the * "put" command to the ftp server. * - * @return the OutputStream to the connection. + * @return the {@code OutputStream} to the connection. * * @throws IOException if already opened for input or the URL * points to a directory @@ -548,9 +549,9 @@ public class FtpURLConnection extends URLConnection { } /** - * Gets the Permission associated with the host & port. + * Gets the {@code Permission} associated with the host and port. * - * @return The Permission object. + * @return The {@code Permission} object. */ @Override public Permission getPermission() { @@ -568,7 +569,7 @@ public class FtpURLConnection extends URLConnection { * exists, overwrite its value with the new value. * * @param key the keyword by which the request is known - * (e.g., "accept"). + * (e.g., "{@code accept}"). * @param value the value associated with it. * @throws IllegalStateException if already connected * @see #getRequestProperty(java.lang.String) diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpAuthenticator.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpAuthenticator.java index 29902025865..4befe58b5b9 100644 --- a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpAuthenticator.java +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpAuthenticator.java @@ -59,6 +59,7 @@ public interface HttpAuthenticator { * supplied or could be found. *

* Example: + *

{@code
      * --> GET http://www.authorization-required.com/ HTTP/1.0
      * <-- HTTP/1.0 403 Unauthorized
      * <-- WWW-Authenticate: Basic realm="WallyWorld"
@@ -67,8 +68,9 @@ public interface HttpAuthenticator {
      *   return "QWadhgWERghghWERfdfQ=="
      * --> GET http://www.authorization-required.com/ HTTP/1.0
      * --> Authorization: Basic QWadhgWERghghWERfdfQ==
-     * <-- HTTP/1.0 200 OK
+     * <-- HTTP/1.0 200 OK}
      *  YAY!!!
+     * 
*/ public String authString (URL u, String scheme, String realm); diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java index b9d594b0316..84decd8fcff 100644 --- a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java @@ -1954,7 +1954,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection { /** * Set the tunneling status. * - * @param the state + * @param tunnelState the state */ public void setTunnelState(TunnelState tunnelState) { this.tunnelState = tunnelState; diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/jar/JarURLConnection.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/jar/JarURLConnection.java index 509b7122128..daa56325e2f 100644 --- a/jdk/src/java.base/share/classes/sun/net/www/protocol/jar/JarURLConnection.java +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/jar/JarURLConnection.java @@ -338,7 +338,7 @@ public class JarURLConnection extends java.net.JarURLConnection { * Sets the value of the ifModifiedSince field of * this URLConnection to the specified value. * - * @param value the new value. + * @param ifmodifiedsince the new value. * @see java.net.URLConnection#ifModifiedSince */ public void setIfModifiedSince(long ifmodifiedsince) { diff --git a/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java b/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java index ae32624c071..aa1538fae79 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java +++ b/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -277,8 +277,14 @@ public final class AnnotatedTypeFactory { @Override public AnnotatedType[] getAnnotatedUpperBounds() { - if (!hasUpperBounds()) - return new AnnotatedType[0]; + if (!hasUpperBounds()) { + return new AnnotatedType[] { buildAnnotatedType(Object.class, + LocationInfo.BASE_LOCATION, + new TypeAnnotation[0], + new TypeAnnotation[0], + null) + }; + } return getAnnotatedBounds(getWildcardType().getUpperBounds()); } diff --git a/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotationParser.java b/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotationParser.java index 32eb02f72eb..02a5a3f480b 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotationParser.java +++ b/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotationParser.java @@ -295,7 +295,7 @@ public class AnnotationParser { /** * Returns an annotation of the given type backed by the given - * member -> value map. + * member {@literal ->} value map. */ public static Annotation annotationForMap(final Class type, final Map memberValues) diff --git a/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotationType.java b/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotationType.java index 7bef3e6541e..b8967c14626 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotationType.java +++ b/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotationType.java @@ -73,8 +73,8 @@ public class AnnotationType { /** * Returns an AnnotationType instance for the specified annotation type. * - * @throw IllegalArgumentException if the specified class object for - * does not represent a valid annotation type + * @throws IllegalArgumentException if the specified class object + * does not represent a valid annotation type */ public static AnnotationType getInstance( Class annotationClass) @@ -183,7 +183,7 @@ public class AnnotationType { /** * Returns member types for this annotation type - * (member name -> type mapping). + * (member name {@literal ->} type mapping). */ public Map> memberTypes() { return memberTypes; @@ -191,7 +191,7 @@ public class AnnotationType { /** * Returns members of this annotation type - * (member name -> associated Method object mapping). + * (member name {@literal ->} associated Method object mapping). */ public Map members() { return members; @@ -199,7 +199,7 @@ public class AnnotationType { /** * Returns the default values for this annotation type - * (Member name -> default value mapping). + * (Member name {@literal ->} default value mapping). */ public Map memberDefaults() { return memberDefaults; diff --git a/jdk/src/java.base/share/classes/sun/reflect/annotation/TypeAnnotationParser.java b/jdk/src/java.base/share/classes/sun/reflect/annotation/TypeAnnotationParser.java index 8eab556fdee..e495026d420 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/annotation/TypeAnnotationParser.java +++ b/jdk/src/java.base/share/classes/sun/reflect/annotation/TypeAnnotationParser.java @@ -199,7 +199,7 @@ public final class TypeAnnotationParser { * Regular Annotations on TypeVariables are stored in the type * annotation byte[] in the class file. * - * @param genericsDecl the declaration declaring the type variable + * @param genericDecl the declaration declaring the type variable * @param typeVarIndex the 0-based index of this type variable in the declaration */ public static Annotation[] parseTypeVariableAnnotations(D genericDecl, diff --git a/jdk/src/java.base/share/classes/sun/reflect/generics/reflectiveObjects/ParameterizedTypeImpl.java b/jdk/src/java.base/share/classes/sun/reflect/generics/reflectiveObjects/ParameterizedTypeImpl.java index 1addbcc9c17..aca919f46ed 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/generics/reflectiveObjects/ParameterizedTypeImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/generics/reflectiveObjects/ParameterizedTypeImpl.java @@ -73,17 +73,17 @@ public class ParameterizedTypeImpl implements ParameterizedType { *

This method throws a MalformedParameterizedTypeException * under the following circumstances: * If the number of actual type arguments (i.e., the size of the - * array typeArgs) does not correspond to the number of + * array {@code typeArgs}) does not correspond to the number of * formal type arguments. * If any of the actual type arguments is not an instance of the * bounds on the corresponding formal. * @param rawType the Class representing the generic type declaration being * instantiated - * @param actualTypeArguments - a (possibly empty) array of types + * @param actualTypeArguments a (possibly empty) array of types * representing the actual type arguments to the parameterized type - * @param ownerType - the enclosing type, if known. - * @return An instance of ParameterizedType - * @throws MalformedParameterizedTypeException - if the instantiation + * @param ownerType the enclosing type, if known. + * @return An instance of {@code ParameterizedType} + * @throws MalformedParameterizedTypeException if the instantiation * is invalid */ public static ParameterizedTypeImpl make(Class rawType, @@ -95,18 +95,18 @@ public class ParameterizedTypeImpl implements ParameterizedType { /** - * Returns an array of Type objects representing the actual type + * Returns an array of {@code Type} objects representing the actual type * arguments to this type. * *

Note that in some cases, the returned array be empty. This can occur * if this type represents a non-parameterized type nested within * a parameterized type. * - * @return an array of Type objects representing the actual type + * @return an array of {@code Type} objects representing the actual type * arguments to this type - * @throws TypeNotPresentException if any of the + * @throws TypeNotPresentException if any of the * actual type arguments refers to a non-existent type declaration - * @throws MalformedParameterizedTypeException if any of the + * @throws MalformedParameterizedTypeException if any of the * actual type parameters refer to a parameterized type that cannot * be instantiated for any reason * @since 1.5 @@ -116,10 +116,10 @@ public class ParameterizedTypeImpl implements ParameterizedType { } /** - * Returns the Type object representing the class or interface + * Returns the {@code Type} object representing the class or interface * that declared this type. * - * @return the Type object representing the class or interface + * @return the {@code Type} object representing the class or interface * that declared this type */ public Class getRawType() { @@ -128,18 +128,18 @@ public class ParameterizedTypeImpl implements ParameterizedType { /** - * Returns a Type object representing the type that this type - * is a member of. For example, if this type is O.I, - * return a representation of O. + * Returns a {@code Type} object representing the type that this type + * is a member of. For example, if this type is {@code O.I}, + * return a representation of {@code O}. * - *

If this type is a top-level type, null is returned. + *

If this type is a top-level type, {@code null} is returned. * - * @return a Type object representing the type that + * @return a {@code Type} object representing the type that * this type is a member of. If this type is a top-level type, - * null is returned - * @throws TypeNotPresentException if the owner type + * {@code null} is returned + * @throws TypeNotPresentException if the owner type * refers to a non-existent type declaration - * @throws MalformedParameterizedTypeException if the owner type + * @throws MalformedParameterizedTypeException if the owner type * refers to a parameterized type that cannot be instantiated * for any reason * diff --git a/jdk/src/java.base/share/classes/sun/reflect/generics/scope/ConstructorScope.java b/jdk/src/java.base/share/classes/sun/reflect/generics/scope/ConstructorScope.java index 43acdb6fe06..6cf6dfb83b6 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/generics/scope/ConstructorScope.java +++ b/jdk/src/java.base/share/classes/sun/reflect/generics/scope/ConstructorScope.java @@ -56,9 +56,9 @@ public class ConstructorScope extends AbstractScope> { } /** - * Factory method. Takes a Constructor object and creates a + * Factory method. Takes a {@code Constructor} object and creates a * scope for it. - * @param m - A Constructor whose scope we want to obtain + * @param c - A Constructor whose scope we want to obtain * @return The type-variable scope for the constructor m */ public static ConstructorScope make(Constructor c) { diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java b/jdk/src/java.base/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java index 9640ffb8589..453f6752ed0 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java @@ -28,6 +28,7 @@ package sun.security.ssl; import java.security.AlgorithmConstraints; import java.security.CryptoPrimitive; import java.security.PrivateKey; +import java.security.Security; import java.util.Set; import java.util.HashSet; @@ -415,10 +416,12 @@ final class SignatureAndHashAlgorithm { "SHA1withRSA", --p); supports(HashAlgorithm.SHA1, SignatureAlgorithm.ECDSA, "SHA1withECDSA", --p); + if (Security.getProvider("SunMSCAPI") == null) { supports(HashAlgorithm.SHA224, SignatureAlgorithm.RSA, "SHA224withRSA", --p); supports(HashAlgorithm.SHA224, SignatureAlgorithm.ECDSA, "SHA224withECDSA", --p); + } supports(HashAlgorithm.SHA256, SignatureAlgorithm.RSA, "SHA256withRSA", --p); supports(HashAlgorithm.SHA256, SignatureAlgorithm.ECDSA, diff --git a/jdk/src/java.base/share/classes/sun/text/resources/en/FormatData_en_SG.java b/jdk/src/java.base/share/classes/sun/text/resources/en/FormatData_en_SG.java index c46c7652eca..396202060ce 100644 --- a/jdk/src/java.base/share/classes/sun/text/resources/en/FormatData_en_SG.java +++ b/jdk/src/java.base/share/classes/sun/text/resources/en/FormatData_en_SG.java @@ -88,6 +88,14 @@ public class FormatData_en_SG extends ParallelListResourceBundle { "NaN", } }, + { "DatePatterns", + new String[] { + "EEEE, d MMMM, yyyy", // full date pattern + "d MMMM, yyyy", // long date pattern + "d MMM, yyyy", // medium date pattern + "d/M/yy", // short date pattern + } + }, }; } } diff --git a/jdk/src/java.base/share/classes/sun/util/PreHashedMap.java b/jdk/src/java.base/share/classes/sun/util/PreHashedMap.java index 9c83984e099..1bb05705c04 100644 --- a/jdk/src/java.base/share/classes/sun/util/PreHashedMap.java +++ b/jdk/src/java.base/share/classes/sun/util/PreHashedMap.java @@ -121,8 +121,7 @@ public abstract class PreHashedMap *

This method must construct the map's hash chains and store them into * the appropriate elements of the given hash-table row array. * - * @param rows - * The row array to be initialized + * @param ht The row array to be initialized */ protected abstract void init(Object[] ht); diff --git a/jdk/src/java.base/share/classes/sun/util/calendar/BaseCalendar.java b/jdk/src/java.base/share/classes/sun/util/calendar/BaseCalendar.java index a7e763a0d7c..3c07431274c 100644 --- a/jdk/src/java.base/share/classes/sun/util/calendar/BaseCalendar.java +++ b/jdk/src/java.base/share/classes/sun/util/calendar/BaseCalendar.java @@ -28,7 +28,7 @@ package sun.util.calendar; import java.util.TimeZone; /** - * The BaseCalendar provides basic calendar calculation + * The {@code BaseCalendar} provides basic calendar calculation * functions to support the Julian, Gregorian, and Gregorian-based * calendar systems. * @@ -290,11 +290,11 @@ public abstract class BaseCalendar extends AbstractCalendar { /** * Returns 366 if the specified date is in a leap year, or 365 * otherwise This method does not perform the normalization with - * the specified CalendarDate. The - * CalendarDate must be normalized to get a correct + * the specified {@code CalendarDate}. The + * {@code CalendarDate} must be normalized to get a correct * value. * - * @param a CalendarDate + * @param date a {@code CalendarDate} * @return a year length in days * @throws ClassCastException if the specified date is not a * {@link BaseCalendar.Date} @@ -412,7 +412,7 @@ public abstract class BaseCalendar extends AbstractCalendar { /** * Calculates calendar fields and store them in the specified - * CalendarDate. + * {@code CalendarDate}. */ // should be 'protected' public void getCalendarDateFromFixedDate(CalendarDate date, diff --git a/jdk/src/java.base/share/classes/sun/util/calendar/CalendarUtils.java b/jdk/src/java.base/share/classes/sun/util/calendar/CalendarUtils.java index 92cc9b9b9e8..917dbbe657f 100644 --- a/jdk/src/java.base/share/classes/sun/util/calendar/CalendarUtils.java +++ b/jdk/src/java.base/share/classes/sun/util/calendar/CalendarUtils.java @@ -94,7 +94,7 @@ public class CalendarUtils { * 0 and -1%4 is -1. * * @param n the numerator - * @param d a divisor which must be > 0 + * @param d a divisor which must be {@literal > 0} * @param r an array of at least one element in which the value * mod(n, d) is returned. * @return the floor of the quotient. @@ -117,7 +117,7 @@ public class CalendarUtils { * 0 and -1%4 is -1. * * @param n the numerator - * @param d a divisor which must be > 0 + * @param d a divisor which must be {@literal > 0} * @param r an array of at least one element in which the value * mod(n, d) is returned. * @return the floor of the quotient. diff --git a/jdk/src/java.base/share/classes/sun/util/calendar/ZoneInfo.java b/jdk/src/java.base/share/classes/sun/util/calendar/ZoneInfo.java index cb9b74a3c18..c65f942556b 100644 --- a/jdk/src/java.base/share/classes/sun/util/calendar/ZoneInfo.java +++ b/jdk/src/java.base/share/classes/sun/util/calendar/ZoneInfo.java @@ -364,7 +364,7 @@ public class ZoneInfo extends TimeZone { * 0 for January. * @param day The day-in-month of the given date. * @param dayOfWeek The day-of-week of the given date. - * @param millis The milliseconds in day in standard local time. + * @param milliseconds The milliseconds in day in standard local time. * @return The milliseconds to add to UTC to get local time. */ public int getOffset(int era, int year, int month, int day, diff --git a/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleNameProviderImpl.java b/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleNameProviderImpl.java index fefd69d9c9c..9bb46d4e19e 100644 --- a/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleNameProviderImpl.java +++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleNameProviderImpl.java @@ -72,7 +72,7 @@ public class LocaleNameProviderImpl extends LocaleNameProvider implements Availa * If the name returned cannot be localized according to locale, * (say, the provider does not have a Japanese name for Croatian), * this method returns null. - * @param languageCode the ISO 639 language code string in the form of two + * @param lang the ISO 639 language code string in the form of two * lower-case letters between 'a' (U+0061) and 'z' (U+007A) * @param locale the desired locale * @return the name of the given language code for the specified locale, or null if it's not @@ -129,7 +129,7 @@ public class LocaleNameProviderImpl extends LocaleNameProvider implements Availa * If the name returned cannot be localized according to locale, * (say, the provider does not have a Japanese name for Croatia), * this method returns null. - * @param countryCode the ISO 3166 country code string in the form of two + * @param ctry the ISO 3166 country code string in the form of two * upper-case letters between 'A' (U+0041) and 'Z' (U+005A) * @param locale the desired locale * @return the name of the given country code for the specified locale, or null if it's not @@ -152,7 +152,7 @@ public class LocaleNameProviderImpl extends LocaleNameProvider implements Availa * is appropriate for display to the user. * If the name returned cannot be localized according to locale, * this method returns null. - * @param variant the variant string + * @param vrnt the variant string * @param locale the desired locale * @return the name of the given variant string for the specified locale, or null if it's not * available. diff --git a/jdk/src/java.base/share/classes/sun/util/locale/provider/TimeZoneNameProviderImpl.java b/jdk/src/java.base/share/classes/sun/util/locale/provider/TimeZoneNameProviderImpl.java index cf609658e01..49833933462 100644 --- a/jdk/src/java.base/share/classes/sun/util/locale/provider/TimeZoneNameProviderImpl.java +++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/TimeZoneNameProviderImpl.java @@ -79,7 +79,7 @@ public class TimeZoneNameProviderImpl extends TimeZoneNameProvider { * appropriate for daylight saving time even if the specified time zone * has not observed daylight saving time in the past. * - * @param ID a time zone ID string + * @param id a time zone ID string * @param daylight if true, return the daylight saving name. * @param style either {@link java.util.TimeZone#LONG TimeZone.LONG} or * {@link java.util.TimeZone#SHORT TimeZone.SHORT} diff --git a/jdk/src/java.base/share/classes/sun/util/logging/PlatformLogger.java b/jdk/src/java.base/share/classes/sun/util/logging/PlatformLogger.java index b81269d3fa8..a55f1425830 100644 --- a/jdk/src/java.base/share/classes/sun/util/logging/PlatformLogger.java +++ b/jdk/src/java.base/share/classes/sun/util/logging/PlatformLogger.java @@ -74,10 +74,10 @@ import sun.misc.SharedSecrets; * java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter * * Limitation: - * /conf/logging.properties is the system-wide logging + * {@code /conf/logging.properties} is the system-wide logging * configuration defined in the specification and read in the * default case to configure any java.util.logging.Logger instances. - * Platform loggers will not detect if /conf/logging.properties + * Platform loggers will not detect if {@code /conf/logging.properties} * is modified. In other words, unless the java.util.logging API * is used at runtime or the logging system properties is set, * the platform loggers will use the default setting described above. diff --git a/jdk/src/java.base/share/classes/sun/util/resources/TimeZoneNamesBundle.java b/jdk/src/java.base/share/classes/sun/util/resources/TimeZoneNamesBundle.java index 3385887596e..2706efafe40 100644 --- a/jdk/src/java.base/share/classes/sun/util/resources/TimeZoneNamesBundle.java +++ b/jdk/src/java.base/share/classes/sun/util/resources/TimeZoneNamesBundle.java @@ -55,7 +55,7 @@ import java.util.Set; * array for the enumeration returned by getKeys. *

  • Inserts the time zone ID (the key of the bundle entries) into * the string arrays returned by handleGetObject. - *
      + *
    * All TimeZoneNames resource bundles must extend this * class and implement the getContents method. */ diff --git a/jdk/src/java.base/share/native/libjava/ClassLoader.c b/jdk/src/java.base/share/native/libjava/ClassLoader.c index ae69096bd50..5a8d86156b9 100644 --- a/jdk/src/java.base/share/native/libjava/ClassLoader.c +++ b/jdk/src/java.base/share/native/libjava/ClassLoader.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -479,12 +479,12 @@ Java_java_lang_ClassLoader_00024NativeLibrary_find return res; } /* - * Class: java_lang_ClassLoader_NativeLibrary + * Class: java_lang_ClassLoader * Method: findBuiltinLib * Signature: (Ljava/lang/String;)Ljava/lang/String; */ JNIEXPORT jstring JNICALL -Java_java_lang_ClassLoader_00024NativeLibrary_findBuiltinLib +Java_java_lang_ClassLoader_findBuiltinLib (JNIEnv *env, jclass cls, jstring name) { const char *cname; @@ -500,8 +500,6 @@ Java_java_lang_ClassLoader_00024NativeLibrary_findBuiltinLib JNU_ThrowInternalError(env, "NULL filename for native library"); return NULL; } - // Can't call initIDs because it will recurse into NativeLibrary via - // FindClass to check context so set prochandle here as well. procHandle = getProcessHandle(); cname = JNU_GetStringPlatformChars(env, name, 0); if (cname == NULL) { diff --git a/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java b/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java index 625a0bed15a..c2c85a69f04 100644 --- a/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java +++ b/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java @@ -542,7 +542,22 @@ final class ProcessImpl extends Process { @Override public CompletableFuture onExit() { return ProcessHandleImpl.completion(pid, false) - .handleAsync((exitStatus, unusedThrowable) -> this); + .handleAsync((exitStatus, unusedThrowable) -> { + boolean interrupted = false; + while (true) { + // Ensure that the concurrent task setting the exit status has completed + try { + waitFor(); + break; + } catch (InterruptedException ie) { + interrupted = true; + } + } + if (interrupted) { + Thread.currentThread().interrupt(); + } + return this; + }); } @Override diff --git a/jdk/src/java.base/unix/classes/sun/misc/FileURLMapper.java b/jdk/src/java.base/unix/classes/sun/misc/FileURLMapper.java index 990704e14e3..eb359368ad5 100644 --- a/jdk/src/java.base/unix/classes/sun/misc/FileURLMapper.java +++ b/jdk/src/java.base/unix/classes/sun/misc/FileURLMapper.java @@ -50,7 +50,7 @@ public class FileURLMapper { } /** - * @returns the platform specific path corresponding to the URL + * @return the platform specific path corresponding to the URL * so long as the URL does not contain a hostname in the authority field. */ diff --git a/jdk/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java b/jdk/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java index 0c4523c19f1..398dda86f57 100644 --- a/jdk/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java +++ b/jdk/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java @@ -113,7 +113,8 @@ public class NTLMAuthentication extends AuthenticationInfo { Client client; /** * Create a NTLMAuthentication: - * Username may be specified as domainusername in the application Authenticator. + * Username may be specified as {@literal domainusername} + * in the application Authenticator. * If this notation is not used, then the domain will be taken * from a system property: "http.auth.ntlm.domain". */ diff --git a/jdk/src/java.base/unix/native/libjava/UnixFileSystem_md.c b/jdk/src/java.base/unix/native/libjava/UnixFileSystem_md.c index 487e8a2bac3..cd166933363 100644 --- a/jdk/src/java.base/unix/native/libjava/UnixFileSystem_md.c +++ b/jdk/src/java.base/unix/native/libjava/UnixFileSystem_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,12 @@ #include #include #include +#ifdef MACOSX +#include +#include +#else #include +#endif #include #include #include @@ -46,8 +51,10 @@ #define dirent64 dirent #define readdir64_r readdir_r #define stat64 stat +#ifndef MACOSX #define statvfs64 statvfs #endif +#endif /* -- Field IDs -- */ @@ -432,8 +439,32 @@ Java_java_io_UnixFileSystem_getSpace(JNIEnv *env, jobject this, jlong rv = 0L; WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) { +#ifdef MACOSX + struct statfs fsstat; +#else struct statvfs64 fsstat; +#endif memset(&fsstat, 0, sizeof(fsstat)); +#ifdef MACOSX + if (statfs(path, &fsstat) == 0) { + switch(t) { + case java_io_FileSystem_SPACE_TOTAL: + rv = jlong_mul(long_to_jlong(fsstat.f_bsize), + long_to_jlong(fsstat.f_blocks)); + break; + case java_io_FileSystem_SPACE_FREE: + rv = jlong_mul(long_to_jlong(fsstat.f_bsize), + long_to_jlong(fsstat.f_bfree)); + break; + case java_io_FileSystem_SPACE_USABLE: + rv = jlong_mul(long_to_jlong(fsstat.f_bsize), + long_to_jlong(fsstat.f_bavail)); + break; + default: + assert(0); + } + } +#else if (statvfs64(path, &fsstat) == 0) { switch(t) { case java_io_FileSystem_SPACE_TOTAL: @@ -452,6 +483,7 @@ Java_java_io_UnixFileSystem_getSpace(JNIEnv *env, jobject this, assert(0); } } +#endif } END_PLATFORM_STRING(env, path); return rv; } diff --git a/jdk/src/java.base/unix/native/libnet/Inet4AddressImpl.c b/jdk/src/java.base/unix/native/libnet/Inet4AddressImpl.c index e07b2f578f4..68e89c3579a 100644 --- a/jdk/src/java.base/unix/native/libnet/Inet4AddressImpl.c +++ b/jdk/src/java.base/unix/native/libnet/Inet4AddressImpl.c @@ -121,7 +121,7 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, jobjectArray ret = 0; int retLen = 0; - int error=0; + int getaddrinfo_error=0; struct addrinfo hints, *res, *resNew = NULL; initInetAddressIDs(env); @@ -149,22 +149,24 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, return NULL; } + + getaddrinfo_error = getaddrinfo(hostname, NULL, &hints, &res); + #ifdef MACOSX - /* If we're looking up the local machine, bypass DNS lookups and get - * address from getifaddrs. - */ - ret = lookupIfLocalhost(env, hostname, JNI_FALSE); - if (ret != NULL || (*env)->ExceptionCheck(env)) { - JNU_ReleaseStringPlatformChars(env, host, hostname); - return ret; + if (getaddrinfo_error) { + // If getaddrinfo fails try getifaddrs. + ret = lookupIfLocalhost(env, hostname, JNI_FALSE); + if (ret != NULL || (*env)->ExceptionCheck(env)) { + JNU_ReleaseStringPlatformChars(env, host, hostname); + return ret; + } } #endif - error = getaddrinfo(hostname, NULL, &hints, &res); - - if (error) { + if (getaddrinfo_error) { /* report error */ - NET_ThrowUnknownHostExceptionWithGaiError(env, hostname, error); + NET_ThrowUnknownHostExceptionWithGaiError( + env, hostname, getaddrinfo_error); JNU_ReleaseStringPlatformChars(env, host, hostname); return NULL; } else { diff --git a/jdk/src/java.base/unix/native/libnet/Inet6AddressImpl.c b/jdk/src/java.base/unix/native/libnet/Inet6AddressImpl.c index 7e348b6b79c..84e7ca4edf2 100644 --- a/jdk/src/java.base/unix/native/libnet/Inet6AddressImpl.c +++ b/jdk/src/java.base/unix/native/libnet/Inet6AddressImpl.c @@ -254,7 +254,7 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, jobjectArray ret = 0; int retLen = 0; - int error=0; + int getaddrinfo_error=0; #ifdef AF_INET6 struct addrinfo hints, *res, *resNew = NULL; #endif /* AF_INET6 */ @@ -269,19 +269,6 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE); CHECK_NULL_RETURN(hostname, NULL); -#ifdef MACOSX - /* - * If we're looking up the local machine, attempt to get the address - * from getifaddrs. This ensures we get an IPv6 address for the local - * machine. - */ - ret = lookupIfLocalhost(env, hostname, JNI_TRUE); - if (ret != NULL || (*env)->ExceptionCheck(env)) { - JNU_ReleaseStringPlatformChars(env, host, hostname); - return ret; - } -#endif - #ifdef AF_INET6 /* Try once, with our static buffer. */ memset(&hints, 0, sizeof(hints)); @@ -301,11 +288,27 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, } #endif - error = getaddrinfo(hostname, NULL, &hints, &res); + getaddrinfo_error = getaddrinfo(hostname, NULL, &hints, &res); - if (error) { +#ifdef MACOSX + if (getaddrinfo_error) { + /* + * If getaddrinfo fails looking up the local machine, attempt to get the + * address from getifaddrs. This ensures we get an IPv6 address for the + * local machine. + */ + ret = lookupIfLocalhost(env, hostname, JNI_TRUE); + if (ret != NULL || (*env)->ExceptionCheck(env)) { + JNU_ReleaseStringPlatformChars(env, host, hostname); + return ret; + } + } +#endif + + if (getaddrinfo_error) { /* report error */ - NET_ThrowUnknownHostExceptionWithGaiError(env, hostname, error); + NET_ThrowUnknownHostExceptionWithGaiError( + env, hostname, getaddrinfo_error); JNU_ReleaseStringPlatformChars(env, host, hostname); return NULL; } else { diff --git a/jdk/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c b/jdk/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c index e8a1623a87d..2808cc189f8 100644 --- a/jdk/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c +++ b/jdk/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c @@ -35,7 +35,12 @@ #include #include #include +#ifdef MACOSX +#include +#include +#else #include +#endif #include #ifdef __solaris__ @@ -50,7 +55,9 @@ #include #define stat64 stat +#ifndef MACOSX #define statvfs64 statvfs +#endif #define open64 open #define fstat64 fstat @@ -901,11 +908,18 @@ Java_sun_nio_fs_UnixNativeDispatcher_statvfs0(JNIEnv* env, jclass this, jlong pathAddress, jobject attrs) { int err; +#ifdef MACOSX + struct statfs buf; +#else struct statvfs64 buf; +#endif const char* path = (const char*)jlong_to_ptr(pathAddress); - +#ifdef MACOSX + RESTARTABLE(statfs(path, &buf), err); +#else RESTARTABLE(statvfs64(path, &buf), err); +#endif if (err == -1) { throwUnixException(env, errno); } else { @@ -921,7 +935,11 @@ Java_sun_nio_fs_UnixNativeDispatcher_statvfs0(JNIEnv* env, jclass this, buf.f_bavail = 0; } #endif +#ifdef MACOSX + (*env)->SetLongField(env, attrs, attrs_f_frsize, long_to_jlong(buf.f_bsize)); +#else (*env)->SetLongField(env, attrs, attrs_f_frsize, long_to_jlong(buf.f_frsize)); +#endif (*env)->SetLongField(env, attrs, attrs_f_blocks, long_to_jlong(buf.f_blocks)); (*env)->SetLongField(env, attrs, attrs_f_bfree, long_to_jlong(buf.f_bfree)); (*env)->SetLongField(env, attrs, attrs_f_bavail, long_to_jlong(buf.f_bavail)); diff --git a/jdk/src/java.base/windows/classes/sun/misc/FileURLMapper.java b/jdk/src/java.base/windows/classes/sun/misc/FileURLMapper.java index 9eb0cc6a611..edadd9d3730 100644 --- a/jdk/src/java.base/windows/classes/sun/misc/FileURLMapper.java +++ b/jdk/src/java.base/windows/classes/sun/misc/FileURLMapper.java @@ -46,7 +46,7 @@ public class FileURLMapper { } /** - * @returns the platform specific path corresponding to the URL, and in particular + * @return the platform specific path corresponding to the URL, and in particular * returns a UNC when the authority contains a hostname */ diff --git a/jdk/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java b/jdk/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java index 6d6340a5d22..0e17de44b4c 100644 --- a/jdk/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java +++ b/jdk/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java @@ -83,7 +83,8 @@ public class NTLMAuthentication extends AuthenticationInfo { /** * Create a NTLMAuthentication: - * Username may be specified as domainusername in the application Authenticator. + * Username may be specified as {@literal domainusername} + * in the application Authenticator. * If this notation is not used, then the domain will be taken * from a system property: "http.auth.ntlm.domain". */ diff --git a/jdk/src/java.datatransfer/share/classes/sun/datatransfer/DataFlavorUtil.java b/jdk/src/java.datatransfer/share/classes/sun/datatransfer/DataFlavorUtil.java index d7f9c2763cc..4fe07da9e44 100644 --- a/jdk/src/java.datatransfer/share/classes/sun/datatransfer/DataFlavorUtil.java +++ b/jdk/src/java.datatransfer/share/classes/sun/datatransfer/DataFlavorUtil.java @@ -55,7 +55,7 @@ import java.util.function.Supplier; /** * Utility class with different datatransfer helper functions * - * @see 1.9 + * @since 1.9 */ public class DataFlavorUtil { diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/eio/FileManager.java b/jdk/src/java.desktop/macosx/classes/com/apple/eio/FileManager.java index 84ffa184207..e098654a03d 100644 --- a/jdk/src/java.desktop/macosx/classes/com/apple/eio/FileManager.java +++ b/jdk/src/java.desktop/macosx/classes/com/apple/eio/FileManager.java @@ -97,7 +97,8 @@ public class FileManager { /** - * Converts an OSType (e.g. "macs" from ) into an int. + * Converts an OSType (e.g. "macs" + * from {@literal }) into an int. * * @param type the 4 character type to convert. * @return an int representing the 4 character value @@ -355,7 +356,7 @@ public class FileManager { /** * Moves the specified file to the Trash * - * @param file + * @param file the file * @return returns true if the NSFileManager successfully moved the file to the Trash. * @throws FileNotFoundException * diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java index f89d27a2543..0765fae5156 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java @@ -985,11 +985,13 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo } private void checkZoom() { - int state = peer.getState(); - if (state != Frame.MAXIMIZED_BOTH && isMaximized()) { - deliverZoom(true); - } else if (state == Frame.MAXIMIZED_BOTH && !isMaximized()) { - deliverZoom(false); + if (peer != null) { + int state = peer.getState(); + if (state != Frame.MAXIMIZED_BOTH && isMaximized()) { + deliverZoom(true); + } else if (state == Frame.MAXIMIZED_BOTH && !isMaximized()) { + deliverZoom(false); + } } } diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java index e2dcd71733b..0188339093e 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java @@ -370,8 +370,7 @@ public final class LWCToolkit extends LWToolkit { protected void initializeDesktopProperties() { super.initializeDesktopProperties(); Map fontHints = new HashMap<>(); - fontHints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - fontHints.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + fontHints.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB); desktopProperties.put(SunToolkit.DESKTOPFONTHINTS, fontHints); desktopProperties.put("awt.mouse.numButtons", BUTTONS); diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CFRetainedResource.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CFRetainedResource.m index 463c6bcc498..1371189b83f 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CFRetainedResource.m +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CFRetainedResource.m @@ -23,6 +23,7 @@ * questions. */ +#import #import #import "sun_lwawt_macosx_CFRetainedResource.h" @@ -37,7 +38,10 @@ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CFRetainedResource_nativeCFRelease (JNIEnv *env, jclass clazz, jlong ptr, jboolean releaseOnAppKitThread) { if (releaseOnAppKitThread) { - [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){ + // Releasing resources on the main AppKit message loop only + // Releasing resources on the nested loops may cause dangling + // pointers after the nested loop is exited + [NSApp postRunnableEvent:^(){ CFRelease(jlong_to_ptr(ptr)); }]; } else { diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m index 930c70e0963..07cd78b38c3 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m @@ -516,8 +516,10 @@ JNF_COCOA_ENTER(env); beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.010]]; if (processEvents) { //We do not spin a runloop here as date is nil, so does not matter which mode to use + // Processing all events excluding NSApplicationDefined which need to be processed + // on the main loop only (those events are intended for disposing resources) NSEvent *event; - if ((event = [NSApp nextEventMatchingMask:NSAnyEventMask + if ((event = [NSApp nextEventMatchingMask:(NSAnyEventMask & ~NSApplicationDefined) untilDate:nil inMode:NSDefaultRunLoopMode dequeue:YES]) != nil) { diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m index 2a4a2806c78..e55a267d5fe 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m @@ -311,21 +311,26 @@ JNF_COCOA_ENTER(env); jlong *glyphInfos = (*env)->GetPrimitiveArrayCritical(env, glyphInfoLongArray, NULL); - if (glyphInfos != NULL) { - jint *rawGlyphCodes = + + jint *rawGlyphCodes = (*env)->GetPrimitiveArrayCritical(env, glyphCodes, NULL); - - if (rawGlyphCodes != NULL) { + @try { + if (rawGlyphCodes != NULL && glyphInfos != NULL) { CGGlyphImages_GetGlyphImagePtrs(glyphInfos, awtStrike, - rawGlyphCodes, len); - - (*env)->ReleasePrimitiveArrayCritical(env, glyphCodes, - rawGlyphCodes, JNI_ABORT); + rawGlyphCodes, len); + } + } + @finally { + if (rawGlyphCodes != NULL) { + (*env)->ReleasePrimitiveArrayCritical(env, glyphCodes, + rawGlyphCodes, JNI_ABORT); + } + if (glyphInfos != NULL) { + // Do not use JNI_COMMIT, as that will not free the buffer copy + // when +ProtectJavaHeap is on. + (*env)->ReleasePrimitiveArrayCritical(env, glyphInfoLongArray, + glyphInfos, 0); } - // Do not use JNI_COMMIT, as that will not free the buffer copy - // when +ProtectJavaHeap is on. - (*env)->ReleasePrimitiveArrayCritical(env, glyphInfoLongArray, - glyphInfos, 0); } JNF_COCOA_EXIT(env); diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.m index 1901c1fc5cb..994bda41982 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.m +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.m @@ -195,19 +195,41 @@ DUMP_GLYPHINFO(const GlyphInfo *info) #pragma mark --- Font Rendering Mode Descriptors --- +static Int32 reverseGamma = 0; + +static UInt8 reverseGammaLut[256] = { 0 }; + +static inline UInt8* getReverseGammaLut() { + if (reverseGamma == 0) { + // initialize gamma lut + double gamma; + int i; + const char* pGammaEnv = getenv("J2D_LCD_REVERSE_GAMMA"); + if (pGammaEnv != NULL) { + reverseGamma = atol(pGammaEnv); + } + + if (reverseGamma < 100 || reverseGamma > 250) { + reverseGamma = 180; + } + + gamma = 100.0 / reverseGamma; + for (i = 0; i < 256; i++) { + double x = ((double)i) / 255.0; + reverseGammaLut[i] = (UInt8)(255 * pow(x, gamma)); + } + } + return reverseGammaLut; +} static inline void CGGI_CopyARGBPixelToRGBPixel(const UInt32 p, UInt8 *dst) { -#if __LITTLE_ENDIAN__ - *(dst + 2) = 0xFF - (p >> 24 & 0xFF); - *(dst + 1) = 0xFF - (p >> 16 & 0xFF); - *(dst) = 0xFF - (p >> 8 & 0xFF); -#else - *(dst) = 0xFF - (p >> 16 & 0xFF); - *(dst + 1) = 0xFF - (p >> 8 & 0xFF); - *(dst + 2) = 0xFF - (p & 0xFF); -#endif + UInt8* lut = getReverseGammaLut(); + + *(dst + 0) = lut[0xFF - (p >> 16 & 0xFF)]; // red + *(dst + 1) = lut[0xFF - (p >> 8 & 0xFF)]; // green + *(dst + 2) = lut[0xFF - (p & 0xFF)]; // blue } static void @@ -222,17 +244,14 @@ CGGI_CopyImageFromCanvasToRGBInfo(CGGI_GlyphCanvas *canvas, GlyphInfo *info) size_t height = info->height; size_t y; + + // fill empty glyph image with black-on-white glyph for (y = 0; y < height; y++) { size_t destRow = y * destRowWidth * 3; size_t srcRow = y * srcRowWidth; size_t x; for (x = 0; x < destRowWidth; x++) { - // size_t x3 = x * 3; - // UInt32 p = src[srcRow + x]; - // dest[destRow + x3] = 0xFF - (p >> 16 & 0xFF); - // dest[destRow + x3 + 1] = 0xFF - (p >> 8 & 0xFF); - // dest[destRow + x3 + 2] = 0xFF - (p & 0xFF); CGGI_CopyARGBPixelToRGBPixel(src[srcRow + x], dest + destRow + x * 3); } @@ -260,13 +279,9 @@ CGGI_CopyImageFromCanvasToRGBInfo(CGGI_GlyphCanvas *canvas, GlyphInfo *info) //} static inline UInt8 -CGGI_ConvertPixelToGreyBit(UInt32 p) +CGGI_ConvertBWPixelToByteGray(UInt32 p) { -#ifdef __LITTLE_ENDIAN__ - return 0xFF - ((p >> 24 & 0xFF) + (p >> 16 & 0xFF) + (p >> 8 & 0xFF)) / 3; -#else - return 0xFF - ((p >> 16 & 0xFF) + (p >> 8 & 0xFF) + (p & 0xFF)) / 3; -#endif + return 0xFF - (((p >> 24 & 0xFF) + (p >> 16 & 0xFF) + (p >> 8 & 0xFF)) / 3); } static void @@ -281,14 +296,15 @@ CGGI_CopyImageFromCanvasToAlphaInfo(CGGI_GlyphCanvas *canvas, GlyphInfo *info) size_t height = info->height; size_t y; + + // fill empty glyph image with black-on-white glyph for (y = 0; y < height; y++) { size_t destRow = y * destRowWidth; size_t srcRow = y * srcRowWidth; - size_t x; for (x = 0; x < destRowWidth; x++) { UInt32 p = src[srcRow + x]; - dest[destRow + x] = CGGI_ConvertPixelToGreyBit(p); + dest[destRow + x] = CGGI_ConvertBWPixelToByteGray(p); } } } @@ -316,13 +332,11 @@ CGGI_GetRenderingMode(const AWTStrike *strike) { CGGI_RenderingMode mode; mode.cgFontMode = strike->fStyle; + NSException *e = nil; switch (strike->fAAStyle) { - case sun_awt_SunHints_INTVAL_TEXT_ANTIALIAS_DEFAULT: case sun_awt_SunHints_INTVAL_TEXT_ANTIALIAS_OFF: case sun_awt_SunHints_INTVAL_TEXT_ANTIALIAS_ON: - case sun_awt_SunHints_INTVAL_TEXT_ANTIALIAS_GASP: - default: mode.glyphDescriptor = &grey; break; case sun_awt_SunHints_INTVAL_TEXT_ANTIALIAS_LCD_HRGB: @@ -331,6 +345,17 @@ CGGI_GetRenderingMode(const AWTStrike *strike) case sun_awt_SunHints_INTVAL_TEXT_ANTIALIAS_LCD_VBGR: mode.glyphDescriptor = &rgb; break; + case sun_awt_SunHints_INTVAL_TEXT_ANTIALIAS_GASP: + case sun_awt_SunHints_INTVAL_TEXT_ANTIALIAS_DEFAULT: + default: + /* we expect that text antialiasing hint has been already + * evaluated. Report an error if we get 'unevaluated' hint here. + */ + e = [NSException + exceptionWithName:@"IllegalArgumentException" + reason:@"Invalid hint value" + userInfo:nil]; + @throw e; } return mode; @@ -345,7 +370,8 @@ CGGI_GetRenderingMode(const AWTStrike *strike) */ static inline void CGGI_InitCanvas(CGGI_GlyphCanvas *canvas, - const vImagePixelCount width, const vImagePixelCount height) + const vImagePixelCount width, const vImagePixelCount height, + const CGGI_RenderingMode* mode) { // our canvas is *always* 4-byte ARGB size_t bytesPerRow = width * sizeof(UInt32); @@ -356,19 +382,26 @@ CGGI_InitCanvas(CGGI_GlyphCanvas *canvas, canvas->image->height = height; canvas->image->rowBytes = bytesPerRow; - canvas->image->data = (void *)calloc(byteCount, sizeof(UInt32)); + canvas->image->data = (void *)calloc(byteCount, sizeof(UInt8)); if (canvas->image->data == NULL) { [[NSException exceptionWithName:NSMallocException reason:@"Failed to allocate memory for the buffer which backs the CGContext for glyph strikes." userInfo:nil] raise]; } - CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); + uint32_t bmpInfo = kCGImageAlphaPremultipliedFirst; + if (mode->glyphDescriptor == &rgb) { + bmpInfo |= kCGBitmapByteOrder32Host; + } + + CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB); canvas->context = CGBitmapContextCreate(canvas->image->data, width, height, 8, bytesPerRow, colorSpace, - kCGImageAlphaPremultipliedFirst); + bmpInfo); + // set foreground color CGContextSetRGBFillColor(canvas->context, 0.0f, 0.0f, 0.0f, 1.0f); + CGContextSetFontSize(canvas->context, 1); CGContextSaveGState(canvas->context); @@ -404,7 +437,9 @@ CGGI_FreeCanvas(CGGI_GlyphCanvas *canvas) * Quick and easy inline to check if this canvas is big enough. */ static inline void -CGGI_SizeCanvas(CGGI_GlyphCanvas *canvas, const vImagePixelCount width, const vImagePixelCount height, const JRSFontRenderingStyle style) +CGGI_SizeCanvas(CGGI_GlyphCanvas *canvas, const vImagePixelCount width, + const vImagePixelCount height, + const CGGI_RenderingMode* mode) { if (canvas->image != NULL && width < canvas->image->width && @@ -418,8 +453,9 @@ CGGI_SizeCanvas(CGGI_GlyphCanvas *canvas, const vImagePixelCount width, const vI CGGI_FreeCanvas(canvas); CGGI_InitCanvas(canvas, width * CGGI_GLYPH_CANVAS_SLACK, - height * CGGI_GLYPH_CANVAS_SLACK); - JRSFontSetRenderingStyleOnContext(canvas->context, style); + height * CGGI_GLYPH_CANVAS_SLACK, + mode); + JRSFontSetRenderingStyleOnContext(canvas->context, mode->cgFontMode); } /* @@ -443,6 +479,7 @@ CGGI_ClearCanvas(CGGI_GlyphCanvas *canvas, GlyphInfo *info) Pixel_8888 opaqueWhite = { 0xFF, 0xFF, 0xFF, 0xFF }; #endif + // clear canvas background and set foreground color vImageBufferFill_ARGB8888(&canvasRectToClear, opaqueWhite, kvImageNoFlags); } @@ -577,7 +614,7 @@ CGGI_CreateImageForUnicode GlyphInfo *info = CGGI_CreateNewGlyphInfoFrom(advance, bbox, strike, mode); // fix the context size, just in case the substituted character is unexpectedly large - CGGI_SizeCanvas(canvas, info->width, info->height, mode->cgFontMode); + CGGI_SizeCanvas(canvas, info->width, info->height, mode); // align the transform for the real CoreText strike CGContextSetTextMatrix(canvas->context, strike->fAltTx); @@ -653,8 +690,11 @@ CGGI_FillImagesForGlyphsWithSizedCanvas(CGGI_GlyphCanvas *canvas, #endif } -static NSString *threadLocalCanvasKey = - @"Java CoreGraphics Text Renderer Cached Canvas"; +static NSString *threadLocalAACanvasKey = + @"Java CoreGraphics Text Renderer Cached Canvas for AA"; + +static NSString *threadLocalLCDCanvasKey = + @"Java CoreGraphics Text Renderer Cached Canvas for LCD"; /* * This is the maximum length and height times the above slack squared @@ -678,25 +718,28 @@ CGGI_FillImagesForGlyphs(jlong *glyphInfos, const AWTStrike *strike, CGGI_GLYPH_CANVAS_MAX*CGGI_GLYPH_CANVAS_MAX*CGGI_GLYPH_CANVAS_SLACK*CGGI_GLYPH_CANVAS_SLACK) { CGGI_GlyphCanvas *tmpCanvas = [[CGGI_GlyphCanvas alloc] init]; - CGGI_InitCanvas(tmpCanvas, maxWidth, maxHeight); + CGGI_InitCanvas(tmpCanvas, maxWidth, maxHeight, mode); CGGI_FillImagesForGlyphsWithSizedCanvas(tmpCanvas, strike, - mode, glyphInfos, uniChars, - glyphs, len); + mode, glyphInfos, uniChars, + glyphs, len); CGGI_FreeCanvas(tmpCanvas); [tmpCanvas release]; return; } - NSMutableDictionary *threadDict = [[NSThread currentThread] threadDictionary]; - CGGI_GlyphCanvas *canvas = [threadDict objectForKey:threadLocalCanvasKey]; + + NSString* theKey = (mode->glyphDescriptor == &rgb) ? + threadLocalLCDCanvasKey : threadLocalAACanvasKey; + + CGGI_GlyphCanvas *canvas = [threadDict objectForKey:theKey]; if (canvas == nil) { canvas = [[CGGI_GlyphCanvas alloc] init]; - [threadDict setObject:canvas forKey:threadLocalCanvasKey]; + [threadDict setObject:canvas forKey:theKey]; } - CGGI_SizeCanvas(canvas, maxWidth, maxHeight, mode->cgFontMode); + CGGI_SizeCanvas(canvas, maxWidth, maxHeight, mode); CGGI_FillImagesForGlyphsWithSizedCanvas(canvas, strike, mode, glyphInfos, uniChars, glyphs, len); } diff --git a/jdk/src/java.desktop/macosx/native/libosxapp/NSApplicationAWT.h b/jdk/src/java.desktop/macosx/native/libosxapp/NSApplicationAWT.h index 92692950608..99c7d63175a 100644 --- a/jdk/src/java.desktop/macosx/native/libosxapp/NSApplicationAWT.h +++ b/jdk/src/java.desktop/macosx/native/libosxapp/NSApplicationAWT.h @@ -37,6 +37,7 @@ - (void) registerWithProcessManager; - (void) setDockIconWithEnv:(JNIEnv *)env; - (void) postDummyEvent; +- (void) postRunnableEvent:(void (^)())block; - (void) waitForDummyEvent; + (void) runAWTLoopWithApp:(NSApplication*)app; diff --git a/jdk/src/java.desktop/macosx/native/libosxapp/NSApplicationAWT.m b/jdk/src/java.desktop/macosx/native/libosxapp/NSApplicationAWT.m index 3e11e1dda7e..fdaa1c3a8cb 100644 --- a/jdk/src/java.desktop/macosx/native/libosxapp/NSApplicationAWT.m +++ b/jdk/src/java.desktop/macosx/native/libosxapp/NSApplicationAWT.m @@ -337,9 +337,13 @@ AWT_ASSERT_APPKIT_THREAD; - (void)sendEvent:(NSEvent *)event { - if ([event type] == NSApplicationDefined && TS_EQUAL([event timestamp], dummyEventTimestamp)) { + if ([event type] == NSApplicationDefined && TS_EQUAL([event timestamp], dummyEventTimestamp) && [event subtype] == 0) { [seenDummyEventLock lockWhenCondition:NO]; [seenDummyEventLock unlockWithCondition:YES]; + } else if ([event type] == NSApplicationDefined && [event subtype] == 777) { + void (^block)() = (void (^)()) [event data1]; + block(); + [block release]; } else if ([event type] == NSKeyUp && ([event modifierFlags] & NSCommandKeyMask)) { // Cocoa won't send us key up event when releasing a key while Cmd is down, // so we have to do it ourselves. @@ -349,6 +353,33 @@ AWT_ASSERT_APPKIT_THREAD; } } +/* + * Posts the block to the AppKit event queue which will be executed + * on the main AppKit loop. + * While running nested loops this event will be ignored. + */ +- (void)postRunnableEvent:(void (^)())block +{ + void (^copy)() = [block copy]; + NSInteger encode = (NSInteger) copy; + [copy retain]; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSEvent* event = [NSEvent otherEventWithType: NSApplicationDefined + location: NSMakePoint(0,0) + modifierFlags: 0 + timestamp: 0 + windowNumber: 0 + context: nil + subtype: 777 + data1: encode + data2: 0]; + + [NSApp postEvent: event atStart: NO]; + [pool drain]; +} + + + - (void)postDummyEvent { seenDummyEventLock = [[NSConditionLock alloc] initWithCondition:NO]; dummyEventTimestamp = [NSProcessInfo processInfo].systemUptime; diff --git a/jdk/src/java.desktop/share/classes/com/sun/beans/introspect/PropertyInfo.java b/jdk/src/java.desktop/share/classes/com/sun/beans/introspect/PropertyInfo.java index ed5843ed40d..44d6a1f7919 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/beans/introspect/PropertyInfo.java +++ b/jdk/src/java.desktop/share/classes/com/sun/beans/introspect/PropertyInfo.java @@ -125,38 +125,36 @@ public final class PropertyInfo { put(Name.visualUpdate, annotation.visualUpdate()); put(Name.description, annotation.description()); String[] values = annotation.enumerationValues(); - if (0 < values.length) { - try { - Object[] array = new Object[3 * values.length]; - int index = 0; - for (String value : values) { - Class type = info.method.getDeclaringClass(); - String name = value; - int pos = value.lastIndexOf('.'); - if (pos > 0) { - name = value.substring(0, pos); - if (name.indexOf('.') < 0) { - String pkg = type.getName(); - name = pkg.substring(0, 1 + Math.max( - pkg.lastIndexOf('.'), - pkg.lastIndexOf('$'))) + name; - } - type = findClass(name); - name = value.substring(pos + 1); - } - Field field = type.getField(name); - if (Modifier.isStatic(field.getModifiers()) && info.type.isAssignableFrom(field.getType())) { - array[index++] = name; - array[index++] = field.get(null); - array[index++] = value; + try { + Object[] array = new Object[3 * values.length]; + int index = 0; + for (String value : values) { + Class type = info.method.getDeclaringClass(); + String name = value; + int pos = value.lastIndexOf('.'); + if (pos > 0) { + name = value.substring(0, pos); + if (name.indexOf('.') < 0) { + String pkg = type.getName(); + name = pkg.substring(0, 1 + Math.max( + pkg.lastIndexOf('.'), + pkg.lastIndexOf('$'))) + name; } + type = findClass(name); + name = value.substring(pos + 1); } - if (index == array.length) { - put(Name.enumerationValues, array); + Field field = type.getField(name); + if (Modifier.isStatic(field.getModifiers()) && info.type.isAssignableFrom(field.getType())) { + array[index++] = name; + array[index++] = field.get(null); + array[index++] = value; } - } catch (Exception ignored) { - ignored.printStackTrace(); } + if (index == array.length) { + put(Name.enumerationValues, array); + } + } catch (Exception ignored) { + ignored.printStackTrace(); } } } diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifBorders.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifBorders.java index 7a1b637850b..950f7d18b24 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifBorders.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifBorders.java @@ -41,7 +41,7 @@ import java.awt.Point; import java.awt.Rectangle; /** - * Factory object that can vend Icons appropriate for the basic L & F. + * Factory object that can vend Icons appropriate for the basic {@literal L & F}. *

    * Warning: * Serialized objects of this class will not be compatible with diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifButtonListener.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifButtonListener.java index 0e0f5d5ac9b..a1a74f1230f 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifButtonListener.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifButtonListener.java @@ -34,7 +34,6 @@ import javax.swing.event.*; /** * Button Listener - *

    * * @author Rich Schiavi */ diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifCheckBoxMenuItemUI.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifCheckBoxMenuItemUI.java index fea72f0fee3..7aa206b1fc5 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifCheckBoxMenuItemUI.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifCheckBoxMenuItemUI.java @@ -37,7 +37,6 @@ import java.awt.event.*; /** * MotifCheckboxMenuItem implementation - *

    * * @author Georges Saab * @author Rich Schiavi diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifComboBoxUI.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifComboBoxUI.java index fd8f885fb74..7e5c4701e11 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifComboBoxUI.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifComboBoxUI.java @@ -35,7 +35,8 @@ import java.beans.*; /** * ComboBox motif look and feel - *

    * Warning: + *

    + * Warning: * Serialized objects of this class will not be compatible with * future Swing releases. The current serialization support is appropriate * for short term storage or RMI between applications running the same @@ -261,9 +262,9 @@ public class MotifComboBoxUI extends BasicComboBoxUI implements Serializable { } /** - * This inner class is marked "public" due to a compiler bug. - * This class should be treated as a "protected" inner class. - * Instantiate it only within subclasses of . + * This inner class is marked "public" due to a compiler bug. + * This class should be treated as a "protected" inner class. + * Instantiate it only within subclasses of {@code }. */ public class ComboBoxLayoutManager extends BasicComboBoxUI.ComboBoxLayoutManager { public ComboBoxLayoutManager() { @@ -344,7 +345,7 @@ public class MotifComboBoxUI extends BasicComboBoxUI implements Serializable { } /** - * This class should be made "protected" in future releases. + * This class should be made "protected" in future releases. */ private class MotifPropertyChangeListener extends BasicComboBoxUI.PropertyChangeHandler { diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifInternalFrameUI.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifInternalFrameUI.java index bcd1cacfde9..8d9e5122ef6 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifInternalFrameUI.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifInternalFrameUI.java @@ -38,7 +38,7 @@ import javax.swing.plaf.*; /** - * A Motif L&F implementation of InternalFrame. + * A Motif {@literal L&F} implementation of InternalFrame. *

    * Warning: * Serialized objects of this class will not be compatible with diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifLabelUI.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifLabelUI.java index 22b224e13a7..1da0036e3fa 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifLabelUI.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifLabelUI.java @@ -32,7 +32,7 @@ import javax.swing.plaf.basic.BasicLabelUI; import javax.swing.plaf.ComponentUI; /** - * A Motif L&F implementation of LabelUI. + * A Motif {@literal L&F} implementation of LabelUI. * This merely sets up new default values in MotifLookAndFeel. *

    * Warning: diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifMenuBarUI.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifMenuBarUI.java index a2256895364..cdc05400fe2 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifMenuBarUI.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifMenuBarUI.java @@ -45,7 +45,7 @@ import javax.swing.plaf.basic.BasicMenuBarUI; import javax.swing.plaf.basic.*; /** - * A Windows L&F implementation of MenuBarUI. This implementation + * A Windows {@literal L&F} implementation of MenuBarUI. This implementation * is a "combined" view/controller. *

    * Warning: diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifMenuItemUI.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifMenuItemUI.java index c11ad6c4e05..52116aaf588 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifMenuItemUI.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifMenuItemUI.java @@ -37,7 +37,6 @@ import javax.swing.plaf.basic.BasicMenuItemUI; /** * MotifMenuItem implementation - *

    * * @author Rich Schiavi * @author Georges Saab diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifMenuUI.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifMenuUI.java index fd32fd0db48..c69e9df7c65 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifMenuUI.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifMenuUI.java @@ -36,8 +36,7 @@ import javax.swing.plaf.basic.*; import javax.swing.plaf.basic.BasicMenuUI; /** - * A Motif L&F implementation of MenuUI. - *

    + * A Motif {@literal L&F} implementation of MenuUI. * * @author Georges Saab * @author Rich Schiavi diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifPopupMenuSeparatorUI.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifPopupMenuSeparatorUI.java index bd3aa15d6cb..164b3227034 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifPopupMenuSeparatorUI.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifPopupMenuSeparatorUI.java @@ -34,8 +34,8 @@ import java.awt.Rectangle; import javax.swing.plaf.*; /** - * A Motif L&F implementation of PopupMenuSeparatorUI. This implementation - * is a "combined" view/controller. + * A Motif {@literal L&F} implementation of PopupMenuSeparatorUI. + * This implementation is a "combined" view/controller. * * @author Jeff Shapiro */ diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifPopupMenuUI.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifPopupMenuUI.java index f34c45e6d80..402bcc528b1 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifPopupMenuUI.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifPopupMenuUI.java @@ -47,7 +47,7 @@ import javax.swing.plaf.basic.BasicPopupMenuUI; /** - * A Motif L&F implementation of PopupMenuUI. + * A Motif {@literal L&F} implementation of PopupMenuUI. *

    * Warning: * Serialized objects of this class will not be compatible with diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifScrollPaneUI.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifScrollPaneUI.java index 52bc7385518..8cb5028c476 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifScrollPaneUI.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifScrollPaneUI.java @@ -34,7 +34,7 @@ import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; /** - * A CDE/Motif L&F implementation of ScrollPaneUI. + * A CDE/Motif {@code L&F} implementation of ScrollPaneUI. *

    * Warning: * Serialized objects of this class will not be compatible with diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifSeparatorUI.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifSeparatorUI.java index db6033fd4a9..bc457b01b13 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifSeparatorUI.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifSeparatorUI.java @@ -35,8 +35,8 @@ import javax.swing.plaf.*; import javax.swing.plaf.basic.BasicSeparatorUI; /** - * A Motif L&F implementation of SeparatorUI. This implementation - * is a "combined" view/controller. + * A Motif {@literal L&F} implementation of SeparatorUI. + * This implementation is a "combined" view/controller. *

    * Warning: * Serialized objects of this class will not be compatible with diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifTabbedPaneUI.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifTabbedPaneUI.java index ce2408ff623..e7bae098a55 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifTabbedPaneUI.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifTabbedPaneUI.java @@ -34,7 +34,7 @@ import javax.swing.plaf.basic.BasicTabbedPaneUI; import java.io.Serializable; /** - * A Motif L&F implementation of TabbedPaneUI. + * A Motif {@literal L&F} implementation of TabbedPaneUI. *

    * Warning: * Serialized objects of this class will not be compatible with diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/DesktopProperty.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/DesktopProperty.java index f4058eeeb8b..ab6aa617222 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/DesktopProperty.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/DesktopProperty.java @@ -199,7 +199,7 @@ public class DesktopProperty implements UIDefaults.ActiveValue { /** * Requests that all components in the GUI hierarchy be updated - * to reflect dynamic changes in this look&feel. This update occurs + * to reflect dynamic changes in this {@literal look&feel}. This update occurs * by uninstalling and re-installing the UI objects. Requests are * batched and collapsed into a single update pass because often * many desktop properties will change at once. diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsBorders.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsBorders.java index ca840ca0c42..1e10ccce1bf 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsBorders.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsBorders.java @@ -39,7 +39,7 @@ import static com.sun.java.swing.plaf.windows.TMSchema.*; import static com.sun.java.swing.plaf.windows.XPStyle.Skin; /** - * Factory object that can vend Borders appropriate for the Windows 95 L & F. + * Factory object that can vend Borders appropriate for the Windows 95 {@literal L & F}. * @author Rich Schiavi */ @@ -142,7 +142,7 @@ public class WindowsBorders { /** * A border for the ToolBar. If the ToolBar is floatable then the handle grip is drawn - *

    + * * @since 1.4 */ @SuppressWarnings("serial") // Superclass is not serializable across versions diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java index ab1a1bce0b6..99966cb210e 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java @@ -76,7 +76,7 @@ public class WindowsCheckBoxMenuItemUI extends BasicCheckBoxMenuItemUI { } /** * Method which renders the text of the current menu item. - *

    + * * @param g Graphics context * @param menuItem Current menu item to render * @param textRect Bounding rectangle to render the text. diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java index 8e2e1489580..ca9121c225d 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java @@ -48,7 +48,7 @@ import sun.swing.*; import javax.accessibility.*; /** - * Windows L&F implementation of a FileChooser. + * Windows {@literal L&F} implementation of a FileChooser. * * @author Jeff Dinkins */ diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsGraphicsUtils.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsGraphicsUtils.java index 8e168066d11..4bc8f0b612e 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsGraphicsUtils.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsGraphicsUtils.java @@ -47,7 +47,7 @@ public class WindowsGraphicsUtils { * Renders a text String in Windows without the mnemonic. * This is here because the WindowsUI hierarchy doesn't match the Component hierarchy. All * the overriden paintText methods of the ButtonUI delegates will call this static method. - *

    + * * @param g Graphics context * @param b Current button to render * @param textRect Bounding rectangle to render the text. diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsIconFactory.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsIconFactory.java index 55c79c43906..4faeba214aa 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsIconFactory.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsIconFactory.java @@ -38,7 +38,7 @@ import static com.sun.java.swing.plaf.windows.XPStyle.Skin; import sun.swing.MenuItemCheckIconFactory; /** - * Factory object that can vend Icons appropriate for the Windows L & F. + * Factory object that can vend Icons appropriate for the Windows {@literal L & F}. *

    * Warning: * Serialized objects of this class will not be compatible with diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsInternalFrameTitlePane.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsInternalFrameTitlePane.java index f86f5964693..83717d6bf93 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsInternalFrameTitlePane.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsInternalFrameTitlePane.java @@ -503,7 +503,7 @@ public class WindowsInternalFrameTitlePane extends BasicInternalFrameTitlePane { private Icon[] icons; /** - * @params objects an array of Icon or UIDefaults.LazyValue + * @param objects an array of Icon or UIDefaults.LazyValue *

    * The constructor is public so it can be called by UIDefaults.ProxyLazyValue. */ diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java index dddbeeb5074..578615829ec 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java @@ -70,7 +70,7 @@ public class WindowsMenuItemUI extends BasicMenuItemUI { /** * Method which renders the text of the current menu item. - *

    + * * @param g Graphics context * @param menuItem Current menu item to render * @param textRect Bounding rectangle to render the text. diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java index a2e7795cfe3..803952b8011 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java @@ -199,7 +199,7 @@ public class WindowsMenuUI extends BasicMenuUI { /** * Method which renders the text of the current menu item. - *

    + * * @param g Graphics context * @param menuItem Current menu item to render * @param textRect Bounding rectangle to render the text. diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsPopupMenuSeparatorUI.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsPopupMenuSeparatorUI.java index f040812a26d..ed31f00a89b 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsPopupMenuSeparatorUI.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsPopupMenuSeparatorUI.java @@ -36,7 +36,7 @@ import com.sun.java.swing.plaf.windows.TMSchema.State; import com.sun.java.swing.plaf.windows.XPStyle.Skin; /** - * Windows L&F implementation of PopupMenuSeparatorUI. + * Windows {@literal L&F} implementation of PopupMenuSeparatorUI. * * @author Leif Samuelsson * @author Igor Kushnirskiy diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java index c43876f38b4..cce34eb9a65 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java @@ -76,7 +76,7 @@ public class WindowsRadioButtonMenuItemUI extends BasicRadioButtonMenuItemUI { /** * Method which renders the text of the current menu item. - *

    + * * @param g Graphics context * @param menuItem Current menu item to render * @param textRect Bounding rectangle to render the text. diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsSeparatorUI.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsSeparatorUI.java index 1f0ece18046..65526a40c1b 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsSeparatorUI.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsSeparatorUI.java @@ -29,7 +29,5 @@ import javax.swing.plaf.basic.*; /** * Windows Separator. - *

    - * */ public class WindowsSeparatorUI extends BasicSeparatorUI { } diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsToolBarSeparatorUI.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsToolBarSeparatorUI.java index 997fc905403..ffd6daa3ad8 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsToolBarSeparatorUI.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsToolBarSeparatorUI.java @@ -37,7 +37,6 @@ import static com.sun.java.swing.plaf.windows.XPStyle.Skin; /** * Draws Windows toolbar separators. - *

    * * @author Mark Davidson */ diff --git a/jdk/src/java.desktop/share/classes/java/awt/ScrollPane.java b/jdk/src/java.desktop/share/classes/java/awt/ScrollPane.java index 3d5a8b9cd1e..65eaed68924 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/ScrollPane.java +++ b/jdk/src/java.desktop/share/classes/java/awt/ScrollPane.java @@ -499,9 +499,8 @@ public class ScrollPane extends Container implements Accessible { Point p = getScrollPosition(); Dimension cs = calculateChildSize(); Dimension vs = getViewportSize(); - Insets i = getInsets(); - c.reshape(i.left - p.x, i.top - p.y, cs.width, cs.height); + c.reshape(- p.x, - p.y, cs.width, cs.height); ScrollPanePeer peer = (ScrollPanePeer)this.peer; if (peer != null) { peer.childResized(cs.width, cs.height); diff --git a/jdk/src/java.desktop/share/classes/java/beans/BeanDescriptor.java b/jdk/src/java.desktop/share/classes/java/beans/BeanDescriptor.java index 276c027c226..e0428abb3b9 100644 --- a/jdk/src/java.desktop/share/classes/java/beans/BeanDescriptor.java +++ b/jdk/src/java.desktop/share/classes/java/beans/BeanDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -81,10 +81,7 @@ public class BeanDescriptor extends FeatureDescriptor { SwingContainer container = beanClass.getAnnotation(SwingContainer.class); if (container != null) { setValue("isContainer", container.value()); - String delegate = container.delegate(); - if (!delegate.isEmpty()) { - setValue("containerDelegate", delegate); - } + setValue("containerDelegate", container.delegate()); } } diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/MultipleDocumentHandling.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/MultipleDocumentHandling.java index c7f5f5e7664..f3e02845159 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/MultipleDocumentHandling.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/MultipleDocumentHandling.java @@ -70,8 +70,8 @@ import javax.print.attribute.PrintJobAttribute; * The standard MultipleDocumentHandling values are: *