diff --git a/.hgignore b/.hgignore index 49620dba792..aec0e31d131 100644 --- a/.hgignore +++ b/.hgignore @@ -4,6 +4,7 @@ nbproject/private/ ^webrev ^.hgtip ^.bridge2 +^.jib/ .DS_Store .metadata/ .recommenders/ diff --git a/.hgtags b/.hgtags index 6f4a5a24636..e8fd19f2e22 100644 --- a/.hgtags +++ b/.hgtags @@ -338,3 +338,4 @@ f242d4332f563648426a1b0fa02d8741beba19ef jdk9-b92 09206c6513b300e1ac8541f3be012e1a49312104 jdk9-b93 25a2cab05cfbe6034b71d9e72d64c65b0572ce63 jdk9-b94 5ac6287ec71aafe021cc839d8bc828108d23aaba jdk-9+95 +139f19d70350238e15e107945cea75082b6380b3 jdk-9+96 diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 4adaf3c1e14..f280e1fa3a5 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -338,3 +338,4 @@ cf1dc4c035fb84693d4ae5ad818785cb4d1465d1 jdk9-b90 331fda57dfd323c61804ba0472776790de572937 jdk9-b93 349488425abcaf3ff62f580007860b4b56875d10 jdk9-b94 12a6fb4f070f8ca8fbca219ab9abf5da8908b317 jdk-9+95 +5582a79892596169ebddb3e2c2aa44939e4e3f40 jdk-9+96 diff --git a/common/autoconf/basics.m4 b/common/autoconf/basics.m4 index 1bac9a47386..f6b11c8a3bf 100644 --- a/common/autoconf/basics.m4 +++ b/common/autoconf/basics.m4 @@ -99,7 +99,13 @@ AC_DEFUN([BASIC_FIXUP_PATH], AC_MSG_ERROR([The path of $1, which resolves as "$path", is not found.]) fi - $1="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + $1="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + $1="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi ]) @@ -237,12 +243,18 @@ AC_DEFUN([BASIC_DEPRECATED_ARG_WITH], # Register a --enable argument but mark it as deprecated # $1: The name of the with argument to deprecate, not including --enable- # $2: The name of the argument to deprecate, in shell variable style (i.e. with _ instead of -) +# $3: Messages to user. AC_DEFUN([BASIC_DEPRECATED_ARG_ENABLE], [ AC_ARG_ENABLE($1, [AS_HELP_STRING([--enable-$1], [Deprecated. Option is kept for backwards compatibility and is ignored])]) if test "x$enable_$2" != x; then AC_MSG_WARN([Option --enable-$1 is deprecated and will be ignored.]) + + if test "x$3" != x; then + AC_MSG_WARN([$3]) + fi + fi ]) @@ -1072,6 +1084,26 @@ AC_DEFUN_ONCE([BASIC_CHECK_BASH_OPTIONS], AC_SUBST(BASH_ARGS) ]) +################################################################################ +# +# Default make target +# +AC_DEFUN_ONCE([BASIC_SETUP_DEFAULT_MAKE_TARGET], +[ + AC_ARG_WITH(default-make-target, [AS_HELP_STRING([--with-default-make-target], + [set the default make target @<:@exploded-image@:>@])]) + if test "x$with_default_make_target" = "x" \ + || test "x$with_default_make_target" = "xyes"; then + DEFAULT_MAKE_TARGET="exploded-image" + elif test "x$with_default_make_target" = "xno"; then + AC_MSG_ERROR([--without-default-make-target is not a valid option]) + else + DEFAULT_MAKE_TARGET="$with_default_make_target" + fi + + AC_SUBST(DEFAULT_MAKE_TARGET) +]) + # Code to run after AC_OUTPUT AC_DEFUN_ONCE([BASIC_POST_CONFIG_OUTPUT], [ diff --git a/common/autoconf/configure b/common/autoconf/configure index 4ac6fa1730b..008fd7ff7e6 100644 --- a/common/autoconf/configure +++ b/common/autoconf/configure @@ -257,10 +257,14 @@ fi # Now transfer control to the script generated by autoconf. This is where the # main work is done. +RCDIR=`mktemp -dt jdk-build-configure.tmp.XXXXXX` || exit $? +trap "rm -rf \"$RCDIR\"" EXIT conf_logfile=./configure.log -(exec 3>&1 ; (. $conf_script_to_run "${conf_processed_arguments[@]}" 2>&1 1>&3 ) | tee -a $conf_logfile 1>&2 ; exec 3>&-) | tee -a $conf_logfile +(exec 3>&1 ; ((. $conf_script_to_run "${conf_processed_arguments[@]}" 2>&1 1>&3 ) \ + ; echo $? > "$RCDIR/rc" ) \ + | tee -a $conf_logfile 1>&2 ; exec 3>&-) | tee -a $conf_logfile -conf_result_code=$? +conf_result_code=`cat "$RCDIR/rc"` ### ### Post-processing ### diff --git a/common/autoconf/configure.ac b/common/autoconf/configure.ac index 062bac927e9..cafecd5a993 100644 --- a/common/autoconf/configure.ac +++ b/common/autoconf/configure.ac @@ -121,6 +121,9 @@ PKG_PROG_PKG_CONFIG # After basic tools have been setup, we can check build os specific details. PLATFORM_SETUP_OPENJDK_BUILD_OS_VERSION +# Misc basic settings +BASIC_SETUP_DEFAULT_MAKE_TARGET + ############################################################################### # # Determine OpenJDK variants, options and version numbers. diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index 9318de77b41..a322c533c01 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -690,6 +690,9 @@ FIXPATH GCOV_ENABLED ZIP_DEBUGINFO_FILES ENABLE_DEBUG_SYMBOLS +STRIP_POLICY +DEBUG_BINARIES +NATIVE_DEBUG_SYMBOLS CFLAGS_WARNINGS_ARE_ERRORS DISABLE_WARNING_PREFIX HOTSPOT_SET_WARNINGS_AS_ERRORS @@ -862,6 +865,7 @@ TEST_IN_BUILD BUILD_HEADLESS SUPPORT_HEADFUL SUPPORT_HEADLESS +DEFAULT_MAKE_TARGET OS_VERSION_MICRO OS_VERSION_MINOR OS_VERSION_MAJOR @@ -1067,6 +1071,7 @@ with_extra_path with_sdk_name with_conf_name with_output_sync +with_default_make_target enable_headful enable_hotspot_test_in_build with_cacerts_file @@ -1105,6 +1110,7 @@ with_toolchain_version with_build_devkit with_jtreg enable_warnings_as_errors +with_native_debug_symbols enable_debug_symbols enable_zip_debug_info enable_native_coverage @@ -1885,9 +1891,10 @@ Optional Features: --disable-warnings-as-errors do not consider native warnings to be an error [enabled] - --disable-debug-symbols disable generation of debug symbols [enabled] - --disable-zip-debug-info - disable zipping of debug-info files [enabled] + --enable-debug-symbols Deprecated. Option is kept for backwards + compatibility and is ignored + --enable-zip-debug-info Deprecated. Option is kept for backwards + compatibility and is ignored --enable-native-coverage enable native compilation with code coverage data[disabled] @@ -1933,6 +1940,8 @@ Optional Packages: from important configuration options] --with-output-sync set make output sync type if supported by make. [recurse] + --with-default-make-target + set the default make target [exploded-image] --with-cacerts-file specify alternative cacerts file --with-copyright-year Set copyright year value for build [current year] --with-milestone Deprecated. Option is kept for backwards @@ -1997,6 +2006,9 @@ Optional Packages: dependent] --with-build-devkit Devkit to use for the build platform toolchain --with-jtreg Regression Test Harness [probed] + --with-native-debug-symbols + set the native debug symbol configuration (none, + internal, external, zipped) [zipped] --with-stdc++lib=,, force linking of the C++ runtime on Linux to either static or dynamic, default is static with dynamic as @@ -3477,6 +3489,7 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Register a --enable argument but mark it as deprecated # $1: The name of the with argument to deprecate, not including --enable- # $2: The name of the argument to deprecate, in shell variable style (i.e. with _ instead of -) +# $3: Messages to user. @@ -3563,6 +3576,12 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Check for support for specific options in bash +################################################################################ +# +# Default make target +# + + # Code to run after AC_OUTPUT @@ -4052,6 +4071,15 @@ pkgadd_help() { # +################################################################################ +# +# Static build support. When enabled will generate static +# libraries instead of shared libraries for all JDK libs. +# + + + + # # Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -4091,15 +4119,6 @@ pkgadd_help() { -################################################################################ -# -# Static build support. When enabled will generate static -# libraries instead of shared libraries for all JDK libs. -# - - - - # # Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -4709,7 +4728,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=1449049746 +DATE_WHEN_GENERATED=1449850507 ############################################################################### # @@ -15326,7 +15345,13 @@ $as_echo "$as_me: The path of CURDIR, which resolves as \"$path\", is invalid." as_fn_error $? "The path of CURDIR, which resolves as \"$path\", is not found." "$LINENO" 5 fi - CURDIR="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + CURDIR="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + CURDIR="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -15452,7 +15477,13 @@ $as_echo "$as_me: The path of TOPDIR, which resolves as \"$path\", is invalid." as_fn_error $? "The path of TOPDIR, which resolves as \"$path\", is not found." "$LINENO" 5 fi - TOPDIR="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + TOPDIR="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + TOPDIR="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -16022,7 +16053,13 @@ $as_echo "$as_me: The path of with_devkit, which resolves as \"$path\", is inval as_fn_error $? "The path of with_devkit, which resolves as \"$path\", is not found." "$LINENO" 5 fi - with_devkit="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + with_devkit="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + with_devkit="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -16554,7 +16591,13 @@ $as_echo "$as_me: The path of OUTPUT_ROOT, which resolves as \"$path\", is inval as_fn_error $? "The path of OUTPUT_ROOT, which resolves as \"$path\", is not found." "$LINENO" 5 fi - OUTPUT_ROOT="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + OUTPUT_ROOT="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + OUTPUT_ROOT="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -23051,6 +23094,26 @@ fi +# Misc basic settings + + +# Check whether --with-default-make-target was given. +if test "${with_default_make_target+set}" = set; then : + withval=$with_default_make_target; +fi + + if test "x$with_default_make_target" = "x" \ + || test "x$with_default_make_target" = "xyes"; then + DEFAULT_MAKE_TARGET="exploded-image" + elif test "x$with_default_make_target" = "xno"; then + as_fn_error $? "--without-default-make-target is not a valid option" "$LINENO" 5 + else + DEFAULT_MAKE_TARGET="$with_default_make_target" + fi + + + + ############################################################################### # # Determine OpenJDK variants, options and version numbers. @@ -23792,7 +23855,13 @@ $as_echo "$as_me: The path of BOOT_JDK, which resolves as \"$path\", is invalid. as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5 fi - BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + BOOT_JDK="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -23988,7 +24057,13 @@ $as_echo "$as_me: The path of BOOT_JDK, which resolves as \"$path\", is invalid. as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5 fi - BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + BOOT_JDK="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -24172,7 +24247,13 @@ $as_echo "$as_me: The path of BOOT_JDK, which resolves as \"$path\", is invalid. as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5 fi - BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + BOOT_JDK="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -24355,7 +24436,13 @@ $as_echo "$as_me: The path of BOOT_JDK, which resolves as \"$path\", is invalid. as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5 fi - BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + BOOT_JDK="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -24538,7 +24625,13 @@ $as_echo "$as_me: The path of BOOT_JDK, which resolves as \"$path\", is invalid. as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5 fi - BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + BOOT_JDK="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -24712,7 +24805,13 @@ $as_echo "$as_me: The path of BOOT_JDK, which resolves as \"$path\", is invalid. as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5 fi - BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + BOOT_JDK="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -24861,7 +24960,13 @@ $as_echo "$as_me: The path of JAVA_HOME_PROCESSED, which resolves as \"$path\", as_fn_error $? "The path of JAVA_HOME_PROCESSED, which resolves as \"$path\", is not found." "$LINENO" 5 fi - JAVA_HOME_PROCESSED="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + JAVA_HOME_PROCESSED="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + JAVA_HOME_PROCESSED="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -25031,7 +25136,13 @@ $as_echo "$as_me: The path of BOOT_JDK, which resolves as \"$path\", is invalid. as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5 fi - BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + BOOT_JDK="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -25356,7 +25467,13 @@ $as_echo "$as_me: The path of BOOT_JDK, which resolves as \"$path\", is invalid. as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5 fi - BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + BOOT_JDK="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -25568,7 +25685,13 @@ $as_echo "$as_me: The path of BOOT_JDK, which resolves as \"$path\", is invalid. as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5 fi - BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + BOOT_JDK="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -25745,7 +25868,13 @@ $as_echo "$as_me: The path of BOOT_JDK, which resolves as \"$path\", is invalid. as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5 fi - BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + BOOT_JDK="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -25950,7 +26079,13 @@ $as_echo "$as_me: The path of BOOT_JDK, which resolves as \"$path\", is invalid. as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5 fi - BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + BOOT_JDK="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -26127,7 +26262,13 @@ $as_echo "$as_me: The path of BOOT_JDK, which resolves as \"$path\", is invalid. as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5 fi - BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + BOOT_JDK="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -26332,7 +26473,13 @@ $as_echo "$as_me: The path of BOOT_JDK, which resolves as \"$path\", is invalid. as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5 fi - BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + BOOT_JDK="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -26509,7 +26656,13 @@ $as_echo "$as_me: The path of BOOT_JDK, which resolves as \"$path\", is invalid. as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5 fi - BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + BOOT_JDK="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -26714,7 +26867,13 @@ $as_echo "$as_me: The path of BOOT_JDK, which resolves as \"$path\", is invalid. as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5 fi - BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + BOOT_JDK="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -26891,7 +27050,13 @@ $as_echo "$as_me: The path of BOOT_JDK, which resolves as \"$path\", is invalid. as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5 fi - BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + BOOT_JDK="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -27083,7 +27248,13 @@ $as_echo "$as_me: The path of BOOT_JDK, which resolves as \"$path\", is invalid. as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5 fi - BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + BOOT_JDK="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -27258,7 +27429,13 @@ $as_echo "$as_me: The path of BOOT_JDK, which resolves as \"$path\", is invalid. as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5 fi - BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + BOOT_JDK="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -27451,7 +27628,13 @@ $as_echo "$as_me: The path of BOOT_JDK, which resolves as \"$path\", is invalid. as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5 fi - BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + BOOT_JDK="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -27626,7 +27809,13 @@ $as_echo "$as_me: The path of BOOT_JDK, which resolves as \"$path\", is invalid. as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5 fi - BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + BOOT_JDK="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -27818,7 +28007,13 @@ $as_echo "$as_me: The path of BOOT_JDK, which resolves as \"$path\", is invalid. as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5 fi - BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + BOOT_JDK="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -27993,7 +28188,13 @@ $as_echo "$as_me: The path of BOOT_JDK, which resolves as \"$path\", is invalid. as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5 fi - BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + BOOT_JDK="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -28186,7 +28387,13 @@ $as_echo "$as_me: The path of BOOT_JDK, which resolves as \"$path\", is invalid. as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5 fi - BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + BOOT_JDK="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -28361,7 +28568,13 @@ $as_echo "$as_me: The path of BOOT_JDK, which resolves as \"$path\", is invalid. as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5 fi - BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + BOOT_JDK="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -28535,7 +28748,13 @@ $as_echo "$as_me: The path of BOOT_JDK, which resolves as \"$path\", is invalid. as_fn_error $? "The path of BOOT_JDK, which resolves as \"$path\", is not found." "$LINENO" 5 fi - BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + BOOT_JDK="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + BOOT_JDK="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -31014,7 +31233,13 @@ $as_echo "$as_me: The path of ipath, which resolves as \"$path\", is invalid." > as_fn_error $? "The path of ipath, which resolves as \"$path\", is not found." "$LINENO" 5 fi - ipath="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + ipath="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + ipath="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -31164,7 +31389,13 @@ $as_echo "$as_me: The path of libpath, which resolves as \"$path\", is invalid." as_fn_error $? "The path of libpath, which resolves as \"$path\", is not found." "$LINENO" 5 fi - libpath="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + libpath="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + libpath="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -42918,7 +43149,13 @@ $as_echo "$as_me: The path of with_build_devkit, which resolves as \"$path\", is as_fn_error $? "The path of with_build_devkit, which resolves as \"$path\", is not found." "$LINENO" 5 fi - with_build_devkit="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + with_build_devkit="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + with_build_devkit="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -45433,7 +45670,13 @@ $as_echo "$as_me: The path of JT_HOME, which resolves as \"$path\", is invalid." as_fn_error $? "The path of JT_HOME, which resolves as \"$path\", is not found." "$LINENO" 5 fi - JT_HOME="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + JT_HOME="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + JT_HOME="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -47405,68 +47648,113 @@ $as_echo "$supports" >&6; } # Setup debug symbols (need objcopy from the toolchain for that) # - # ENABLE_DEBUG_SYMBOLS + # NATIVE_DEBUG_SYMBOLS # This must be done after the toolchain is setup, since we're looking at objcopy. # + { $as_echo "$as_me:${as_lineno-$LINENO}: checking what type of native debug symbols to use" >&5 +$as_echo_n "checking what type of native debug symbols to use... " >&6; } + +# Check whether --with-native-debug-symbols was given. +if test "${with_native_debug_symbols+set}" = set; then : + withval=$with_native_debug_symbols; +else + with_native_debug_symbols="zipped" +fi + + NATIVE_DEBUG_SYMBOLS=$with_native_debug_symbols + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NATIVE_DEBUG_SYMBOLS" >&5 +$as_echo "$NATIVE_DEBUG_SYMBOLS" >&6; } + + if test "x$NATIVE_DEBUG_SYMBOLS" = xzipped; then + + if test "x$OPENJDK_TARGET_OS" = xsolaris || test "x$OPENJDK_TARGET_OS" = xlinux; then + if test "x$OBJCOPY" = x; then + # enabling of enable-debug-symbols and can't find objcopy + # this is an error + as_fn_error $? "Unable to find objcopy, cannot enable native debug symbols" "$LINENO" 5 + fi + fi + + ENABLE_DEBUG_SYMBOLS=true + ZIP_DEBUGINFO_FILES=true + DEBUG_BINARIES=true + STRIP_POLICY=min_strip + elif test "x$NATIVE_DEBUG_SYMBOLS" = xnone; then + ENABLE_DEBUG_SYMBOLS=false + ZIP_DEBUGINFO_FILES=false + DEBUG_BINARIES=false + STRIP_POLICY=no_strip + elif test "x$NATIVE_DEBUG_SYMBOLS" = xinternal; then + ENABLE_DEBUG_SYMBOLS=false # -g option only + ZIP_DEBUGINFO_FILES=false + DEBUG_BINARIES=true + STRIP_POLICY=no_strip + STRIP="" + elif test "x$NATIVE_DEBUG_SYMBOLS" = xexternal; then + + if test "x$OPENJDK_TARGET_OS" = xsolaris || test "x$OPENJDK_TARGET_OS" = xlinux; then + if test "x$OBJCOPY" = x; then + # enabling of enable-debug-symbols and can't find objcopy + # this is an error + as_fn_error $? "Unable to find objcopy, cannot enable native debug symbols" "$LINENO" 5 + fi + fi + + ENABLE_DEBUG_SYMBOLS=true + ZIP_DEBUGINFO_FILES=false + DEBUG_BINARIES=true + STRIP_POLICY=min_strip + else + as_fn_error $? "Allowed native debug symbols are: none, internal, external, zipped" "$LINENO" 5 + fi + + # --enable-debug-symbols is deprecated. + # Please use --with-native-debug-symbols=[internal,external,zipped] . + # Check whether --enable-debug-symbols was given. if test "${enable_debug_symbols+set}" = set; then : enableval=$enable_debug_symbols; fi + if test "x$enable_debug_symbols" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --enable-debug-symbols is deprecated and will be ignored." >&5 +$as_echo "$as_me: WARNING: Option --enable-debug-symbols is deprecated and will be ignored." >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we should generate debug symbols" >&5 -$as_echo_n "checking if we should generate debug symbols... " >&6; } - - if test "x$enable_debug_symbols" = "xyes" && test "x$OBJCOPY" = x; then - # explicit enabling of enable-debug-symbols and can't find objcopy - # this is an error - as_fn_error $? "Unable to find objcopy, cannot enable debug-symbols" "$LINENO" 5 - fi - - if test "x$enable_debug_symbols" = "xyes"; then - ENABLE_DEBUG_SYMBOLS=true - elif test "x$enable_debug_symbols" = "xno"; then - ENABLE_DEBUG_SYMBOLS=false - else - # Default is on if objcopy is found - if test "x$OBJCOPY" != x; then - ENABLE_DEBUG_SYMBOLS=true - # MacOS X and Windows don't use objcopy but default is on for those OSes - elif test "x$OPENJDK_TARGET_OS" = xmacosx || test "x$OPENJDK_TARGET_OS" = xwindows; then - ENABLE_DEBUG_SYMBOLS=true - else - ENABLE_DEBUG_SYMBOLS=false + if test "xPlease use --with-native-debug-symbols=[internal,external,zipped] ." != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Please use --with-native-debug-symbols=[internal,external,zipped] ." >&5 +$as_echo "$as_me: WARNING: Please use --with-native-debug-symbols=[internal,external,zipped] ." >&2;} fi + fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ENABLE_DEBUG_SYMBOLS" >&5 -$as_echo "$ENABLE_DEBUG_SYMBOLS" >&6; } - # - # ZIP_DEBUGINFO_FILES - # - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we should zip debug-info files" >&5 -$as_echo_n "checking if we should zip debug-info files... " >&6; } + # --enable-zip-debug-info is deprecated. + # Please use --with-native-debug-symbols=zipped . + # Check whether --enable-zip-debug-info was given. if test "${enable_zip_debug_info+set}" = set; then : - enableval=$enable_zip_debug_info; enable_zip_debug_info="${enableval}" -else - enable_zip_debug_info="yes" + enableval=$enable_zip_debug_info; fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${enable_zip_debug_info}" >&5 -$as_echo "${enable_zip_debug_info}" >&6; } + if test "x$enable_zip_debug_info" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --enable-zip-debug-info is deprecated and will be ignored." >&5 +$as_echo "$as_me: WARNING: Option --enable-zip-debug-info is deprecated and will be ignored." >&2;} + + if test "xPlease use --with-native-debug-symbols=zipped ." != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Please use --with-native-debug-symbols=zipped ." >&5 +$as_echo "$as_me: WARNING: Please use --with-native-debug-symbols=zipped ." >&2;} + fi - if test "x${enable_zip_debug_info}" = "xno"; then - ZIP_DEBUGINFO_FILES=false - else - ZIP_DEBUGINFO_FILES=true fi + + + + # Check whether --enable-native-coverage was given. if test "${enable_native_coverage+set}" = set; then : enableval=$enable_native_coverage; @@ -47947,7 +48235,13 @@ $as_echo "$as_me: The path of MSVC_DLL, which resolves as \"$path\", is invalid. as_fn_error $? "The path of MSVC_DLL, which resolves as \"$path\", is not found." "$LINENO" 5 fi - MSVC_DLL="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + MSVC_DLL="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + MSVC_DLL="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -48121,7 +48415,13 @@ $as_echo "$as_me: The path of MSVC_DLL, which resolves as \"$path\", is invalid. as_fn_error $? "The path of MSVC_DLL, which resolves as \"$path\", is not found." "$LINENO" 5 fi - MSVC_DLL="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + MSVC_DLL="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + MSVC_DLL="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -48319,7 +48619,13 @@ $as_echo "$as_me: The path of MSVC_DLL, which resolves as \"$path\", is invalid. as_fn_error $? "The path of MSVC_DLL, which resolves as \"$path\", is not found." "$LINENO" 5 fi - MSVC_DLL="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + MSVC_DLL="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + MSVC_DLL="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -48494,7 +48800,13 @@ $as_echo "$as_me: The path of MSVC_DLL, which resolves as \"$path\", is invalid. as_fn_error $? "The path of MSVC_DLL, which resolves as \"$path\", is not found." "$LINENO" 5 fi - MSVC_DLL="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + MSVC_DLL="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + MSVC_DLL="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -48679,7 +48991,13 @@ $as_echo "$as_me: The path of MSVC_DLL, which resolves as \"$path\", is invalid. as_fn_error $? "The path of MSVC_DLL, which resolves as \"$path\", is not found." "$LINENO" 5 fi - MSVC_DLL="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + MSVC_DLL="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + MSVC_DLL="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -48871,7 +49189,13 @@ $as_echo "$as_me: The path of MSVC_DLL, which resolves as \"$path\", is invalid. as_fn_error $? "The path of MSVC_DLL, which resolves as \"$path\", is not found." "$LINENO" 5 fi - MSVC_DLL="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + MSVC_DLL="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + MSVC_DLL="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -49060,7 +49384,13 @@ $as_echo "$as_me: The path of MSVC_DLL, which resolves as \"$path\", is invalid. as_fn_error $? "The path of MSVC_DLL, which resolves as \"$path\", is not found." "$LINENO" 5 fi - MSVC_DLL="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + MSVC_DLL="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + MSVC_DLL="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -49254,7 +49584,13 @@ $as_echo "$as_me: The path of MSVC_DLL, which resolves as \"$path\", is invalid. as_fn_error $? "The path of MSVC_DLL, which resolves as \"$path\", is not found." "$LINENO" 5 fi - MSVC_DLL="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + MSVC_DLL="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + MSVC_DLL="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -49428,7 +49764,13 @@ $as_echo "$as_me: The path of MSVC_DLL, which resolves as \"$path\", is invalid. as_fn_error $? "The path of MSVC_DLL, which resolves as \"$path\", is not found." "$LINENO" 5 fi - MSVC_DLL="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + MSVC_DLL="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + MSVC_DLL="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -49626,7 +49968,13 @@ $as_echo "$as_me: The path of MSVC_DLL, which resolves as \"$path\", is invalid. as_fn_error $? "The path of MSVC_DLL, which resolves as \"$path\", is not found." "$LINENO" 5 fi - MSVC_DLL="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + MSVC_DLL="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + MSVC_DLL="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -49801,7 +50149,13 @@ $as_echo "$as_me: The path of MSVC_DLL, which resolves as \"$path\", is invalid. as_fn_error $? "The path of MSVC_DLL, which resolves as \"$path\", is not found." "$LINENO" 5 fi - MSVC_DLL="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + MSVC_DLL="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + MSVC_DLL="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -49986,7 +50340,13 @@ $as_echo "$as_me: The path of MSVC_DLL, which resolves as \"$path\", is invalid. as_fn_error $? "The path of MSVC_DLL, which resolves as \"$path\", is not found." "$LINENO" 5 fi - MSVC_DLL="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + MSVC_DLL="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + MSVC_DLL="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -50178,7 +50538,13 @@ $as_echo "$as_me: The path of MSVC_DLL, which resolves as \"$path\", is invalid. as_fn_error $? "The path of MSVC_DLL, which resolves as \"$path\", is not found." "$LINENO" 5 fi - MSVC_DLL="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + MSVC_DLL="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + MSVC_DLL="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -50367,7 +50733,13 @@ $as_echo "$as_me: The path of MSVC_DLL, which resolves as \"$path\", is invalid. as_fn_error $? "The path of MSVC_DLL, which resolves as \"$path\", is not found." "$LINENO" 5 fi - MSVC_DLL="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + MSVC_DLL="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + MSVC_DLL="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -51746,7 +52118,13 @@ $as_echo "$as_me: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as as_fn_error $? "The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is not found." "$LINENO" 5 fi - POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -51872,7 +52250,13 @@ $as_echo "$as_me: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$ as_fn_error $? "The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is not found." "$LINENO" 5 fi - POTENTIAL_FREETYPE_LIB_PATH="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + POTENTIAL_FREETYPE_LIB_PATH="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + POTENTIAL_FREETYPE_LIB_PATH="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -52107,7 +52491,13 @@ $as_echo "$as_me: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as as_fn_error $? "The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is not found." "$LINENO" 5 fi - POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -52233,7 +52623,13 @@ $as_echo "$as_me: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$ as_fn_error $? "The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is not found." "$LINENO" 5 fi - POTENTIAL_FREETYPE_LIB_PATH="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + POTENTIAL_FREETYPE_LIB_PATH="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + POTENTIAL_FREETYPE_LIB_PATH="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -52567,7 +52963,13 @@ $as_echo "$as_me: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as as_fn_error $? "The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is not found." "$LINENO" 5 fi - POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -52693,7 +53095,13 @@ $as_echo "$as_me: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$ as_fn_error $? "The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is not found." "$LINENO" 5 fi - POTENTIAL_FREETYPE_LIB_PATH="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + POTENTIAL_FREETYPE_LIB_PATH="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + POTENTIAL_FREETYPE_LIB_PATH="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -52903,7 +53311,13 @@ $as_echo "$as_me: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as as_fn_error $? "The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is not found." "$LINENO" 5 fi - POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -53029,7 +53443,13 @@ $as_echo "$as_me: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$ as_fn_error $? "The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is not found." "$LINENO" 5 fi - POTENTIAL_FREETYPE_LIB_PATH="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + POTENTIAL_FREETYPE_LIB_PATH="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + POTENTIAL_FREETYPE_LIB_PATH="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -53230,7 +53650,13 @@ $as_echo "$as_me: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as as_fn_error $? "The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is not found." "$LINENO" 5 fi - POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -53356,7 +53782,13 @@ $as_echo "$as_me: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$ as_fn_error $? "The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is not found." "$LINENO" 5 fi - POTENTIAL_FREETYPE_LIB_PATH="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + POTENTIAL_FREETYPE_LIB_PATH="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + POTENTIAL_FREETYPE_LIB_PATH="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -53557,7 +53989,13 @@ $as_echo "$as_me: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as as_fn_error $? "The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is not found." "$LINENO" 5 fi - POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -53683,7 +54121,13 @@ $as_echo "$as_me: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$ as_fn_error $? "The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is not found." "$LINENO" 5 fi - POTENTIAL_FREETYPE_LIB_PATH="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + POTENTIAL_FREETYPE_LIB_PATH="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + POTENTIAL_FREETYPE_LIB_PATH="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -53885,7 +54329,13 @@ $as_echo "$as_me: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as as_fn_error $? "The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is not found." "$LINENO" 5 fi - POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -54011,7 +54461,13 @@ $as_echo "$as_me: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$ as_fn_error $? "The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is not found." "$LINENO" 5 fi - POTENTIAL_FREETYPE_LIB_PATH="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + POTENTIAL_FREETYPE_LIB_PATH="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + POTENTIAL_FREETYPE_LIB_PATH="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -54214,7 +54670,13 @@ $as_echo "$as_me: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as as_fn_error $? "The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is not found." "$LINENO" 5 fi - POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -54340,7 +54802,13 @@ $as_echo "$as_me: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$ as_fn_error $? "The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is not found." "$LINENO" 5 fi - POTENTIAL_FREETYPE_LIB_PATH="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + POTENTIAL_FREETYPE_LIB_PATH="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + POTENTIAL_FREETYPE_LIB_PATH="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -54539,7 +55007,13 @@ $as_echo "$as_me: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as as_fn_error $? "The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is not found." "$LINENO" 5 fi - POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -54665,7 +55139,13 @@ $as_echo "$as_me: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$ as_fn_error $? "The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is not found." "$LINENO" 5 fi - POTENTIAL_FREETYPE_LIB_PATH="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + POTENTIAL_FREETYPE_LIB_PATH="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + POTENTIAL_FREETYPE_LIB_PATH="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -54864,7 +55344,13 @@ $as_echo "$as_me: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as as_fn_error $? "The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is not found." "$LINENO" 5 fi - POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -54990,7 +55476,13 @@ $as_echo "$as_me: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$ as_fn_error $? "The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is not found." "$LINENO" 5 fi - POTENTIAL_FREETYPE_LIB_PATH="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + POTENTIAL_FREETYPE_LIB_PATH="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + POTENTIAL_FREETYPE_LIB_PATH="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -55172,7 +55664,13 @@ $as_echo "$as_me: The path of FREETYPE_INCLUDE_PATH, which resolves as \"$path\" as_fn_error $? "The path of FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is not found." "$LINENO" 5 fi - FREETYPE_INCLUDE_PATH="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + FREETYPE_INCLUDE_PATH="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + FREETYPE_INCLUDE_PATH="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi @@ -55306,7 +55804,13 @@ $as_echo "$as_me: The path of FREETYPE_LIB_PATH, which resolves as \"$path\", is as_fn_error $? "The path of FREETYPE_LIB_PATH, which resolves as \"$path\", is not found." "$LINENO" 5 fi - FREETYPE_LIB_PATH="`cd "$path"; $THEPWDCMD -L`" + if test -d "$path"; then + FREETYPE_LIB_PATH="`cd "$path"; $THEPWDCMD -L`" + else + dir="`$DIRNAME "$path"`" + base="`$BASENAME "$path"`" + FREETYPE_LIB_PATH="`cd "$dir"; $THEPWDCMD -L`/$base" + fi fi fi diff --git a/common/autoconf/jdk-options.m4 b/common/autoconf/jdk-options.m4 index 83877e6c60b..3f7a29e0abb 100644 --- a/common/autoconf/jdk-options.m4 +++ b/common/autoconf/jdk-options.m4 @@ -491,53 +491,74 @@ AC_DEFUN_ONCE([JDKOPT_DETECT_INTREE_EC], AC_DEFUN_ONCE([JDKOPT_SETUP_DEBUG_SYMBOLS], [ # - # ENABLE_DEBUG_SYMBOLS + # NATIVE_DEBUG_SYMBOLS # This must be done after the toolchain is setup, since we're looking at objcopy. # - AC_ARG_ENABLE([debug-symbols], - [AS_HELP_STRING([--disable-debug-symbols],[disable generation of debug symbols @<:@enabled@:>@])]) + AC_MSG_CHECKING([what type of native debug symbols to use]) + AC_ARG_WITH([native-debug-symbols], + [AS_HELP_STRING([--with-native-debug-symbols], + [set the native debug symbol configuration (none, internal, external, zipped) @<:@zipped@:>@])], + [], + [with_native_debug_symbols="zipped"]) + NATIVE_DEBUG_SYMBOLS=$with_native_debug_symbols + AC_MSG_RESULT([$NATIVE_DEBUG_SYMBOLS]) - AC_MSG_CHECKING([if we should generate debug symbols]) + if test "x$NATIVE_DEBUG_SYMBOLS" = xzipped; then - if test "x$enable_debug_symbols" = "xyes" && test "x$OBJCOPY" = x; then - # explicit enabling of enable-debug-symbols and can't find objcopy - # this is an error - AC_MSG_ERROR([Unable to find objcopy, cannot enable debug-symbols]) - fi - - if test "x$enable_debug_symbols" = "xyes"; then - ENABLE_DEBUG_SYMBOLS=true - elif test "x$enable_debug_symbols" = "xno"; then - ENABLE_DEBUG_SYMBOLS=false - else - # Default is on if objcopy is found - if test "x$OBJCOPY" != x; then - ENABLE_DEBUG_SYMBOLS=true - # MacOS X and Windows don't use objcopy but default is on for those OSes - elif test "x$OPENJDK_TARGET_OS" = xmacosx || test "x$OPENJDK_TARGET_OS" = xwindows; then - ENABLE_DEBUG_SYMBOLS=true - else - ENABLE_DEBUG_SYMBOLS=false + if test "x$OPENJDK_TARGET_OS" = xsolaris || test "x$OPENJDK_TARGET_OS" = xlinux; then + if test "x$OBJCOPY" = x; then + # enabling of enable-debug-symbols and can't find objcopy + # this is an error + AC_MSG_ERROR([Unable to find objcopy, cannot enable native debug symbols]) + fi fi - fi - AC_MSG_RESULT([$ENABLE_DEBUG_SYMBOLS]) - - # - # ZIP_DEBUGINFO_FILES - # - AC_MSG_CHECKING([if we should zip debug-info files]) - AC_ARG_ENABLE([zip-debug-info], - [AS_HELP_STRING([--disable-zip-debug-info],[disable zipping of debug-info files @<:@enabled@:>@])], - [enable_zip_debug_info="${enableval}"], [enable_zip_debug_info="yes"]) - AC_MSG_RESULT([${enable_zip_debug_info}]) - - if test "x${enable_zip_debug_info}" = "xno"; then - ZIP_DEBUGINFO_FILES=false - else + ENABLE_DEBUG_SYMBOLS=true ZIP_DEBUGINFO_FILES=true + DEBUG_BINARIES=true + STRIP_POLICY=min_strip + elif test "x$NATIVE_DEBUG_SYMBOLS" = xnone; then + ENABLE_DEBUG_SYMBOLS=false + ZIP_DEBUGINFO_FILES=false + DEBUG_BINARIES=false + STRIP_POLICY=no_strip + elif test "x$NATIVE_DEBUG_SYMBOLS" = xinternal; then + ENABLE_DEBUG_SYMBOLS=false # -g option only + ZIP_DEBUGINFO_FILES=false + DEBUG_BINARIES=true + STRIP_POLICY=no_strip + STRIP="" + elif test "x$NATIVE_DEBUG_SYMBOLS" = xexternal; then + + if test "x$OPENJDK_TARGET_OS" = xsolaris || test "x$OPENJDK_TARGET_OS" = xlinux; then + if test "x$OBJCOPY" = x; then + # enabling of enable-debug-symbols and can't find objcopy + # this is an error + AC_MSG_ERROR([Unable to find objcopy, cannot enable native debug symbols]) + fi + fi + + ENABLE_DEBUG_SYMBOLS=true + ZIP_DEBUGINFO_FILES=false + DEBUG_BINARIES=true + STRIP_POLICY=min_strip + else + AC_MSG_ERROR([Allowed native debug symbols are: none, internal, external, zipped]) fi + # --enable-debug-symbols is deprecated. + # Please use --with-native-debug-symbols=[internal,external,zipped] . + BASIC_DEPRECATED_ARG_ENABLE(debug-symbols, debug_symbols, + [Please use --with-native-debug-symbols=[[internal,external,zipped]] .]) + + # --enable-zip-debug-info is deprecated. + # Please use --with-native-debug-symbols=zipped . + BASIC_DEPRECATED_ARG_ENABLE(zip-debug-info, zip_debug_info, + [Please use --with-native-debug-symbols=zipped .]) + + AC_SUBST(NATIVE_DEBUG_SYMBOLS) + AC_SUBST(DEBUG_BINARIES) + AC_SUBST(STRIP_POLICY) AC_SUBST(ENABLE_DEBUG_SYMBOLS) AC_SUBST(ZIP_DEBUGINFO_FILES) ]) diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in index dfe57c9b30f..10b65f2592d 100644 --- a/common/autoconf/spec.gmk.in +++ b/common/autoconf/spec.gmk.in @@ -271,6 +271,9 @@ SJAVAC_SERVER_DIR=$(MAKESUPPORT_OUTPUTDIR)/javacservers # Number of parallel jobs to use for compilation JOBS?=@JOBS@ +# Default make target +DEFAULT_MAKE_TARGET:=@DEFAULT_MAKE_TARGET@ + FREETYPE_LIBS:=@FREETYPE_LIBS@ FREETYPE_CFLAGS:=@FREETYPE_CFLAGS@ FREETYPE_BUNDLE_LIB_PATH=@FREETYPE_BUNDLE_LIB_PATH@ @@ -418,6 +421,9 @@ ENABLE_DEBUG_SYMBOLS:=@ENABLE_DEBUG_SYMBOLS@ CFLAGS_DEBUG_SYMBOLS:=@CFLAGS_DEBUG_SYMBOLS@ CXXFLAGS_DEBUG_SYMBOLS:=@CXXFLAGS_DEBUG_SYMBOLS@ ZIP_DEBUGINFO_FILES:=@ZIP_DEBUGINFO_FILES@ +NATIVE_DEBUG_SYMBOLS:=@NATIVE_DEBUG_SYMBOLS@ +DEBUG_BINARIES:=@DEBUG_BINARIES@ +STRIP_POLICY:=@STRIP_POLICY@ # # Compress (or not) jars diff --git a/common/bin/jib.sh b/common/bin/jib.sh new file mode 100644 index 00000000000..0fc60e9e76f --- /dev/null +++ b/common/bin/jib.sh @@ -0,0 +1,127 @@ +#!/bin/bash +# +# 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. +# + +# This script installs the JIB tool into it's own local repository and +# puts a wrapper scripts into /.jib + +mydir="$(dirname "${BASH_SOURCE[0]}")" +myname="$(basename "${BASH_SOURCE[0]}")" + +installed_jib_script=${mydir}/../../.jib/jib +install_data=${mydir}/../../.jib/.data + +setup_url() { + if [ -f "~/.config/jib/jib.conf" ]; then + source ~/.config/jib/jib.conf + fi + + jib_repository="jdk-virtual" + jib_organization="jpg/infra/builddeps" + jib_module="jib" + jib_revision="2.0-SNAPSHOT" + jib_ext="jib.sh.gz" + + closed_script="${mydir}/../../closed/conf/jib-install.conf" + if [ -f "${closed_script}" ]; then + source "${closed_script}" + fi + + if [ -n "${JIB_SERVER}" ]; then + jib_server="${JIB_SERVER}" + fi + if [ -n "${JIB_REPOSITORY}" ]; then + jib_repository="${JIB_REPOSITORY}" + fi + if [ -n "${JIB_ORGANIZATION}" ]; then + jib_organization="${JIB_ORGANIZATION}" + fi + if [ -n "${JIB_MODULE}" ]; then + jib_module="${JIB_MODULE}" + fi + if [ -n "${JIB_REVISION}" ]; then + jib_revision="${JIB_REVISION}" + fi + if [ -n "${JIB_EXTENSION}" ]; then + jib_extension="${JIB_EXTENSION}" + fi + + if [ -n "${JIB_URL}" ]; then + jib_url="${JIB_URL}" + data_string="${jib_url}" + else + data_string="${jib_repository}/${jib_organization}/${jib_module}/${jib_revision}/${jib_module}-${jib_revision}.${jib_ext}" + jib_url="${jib_server}/${data_string}" + fi +} + +install_jib() { + if [ -z "${jib_server}" -a -z "${JIB_URL}" ]; then + echo "No jib server or URL provided, set either" + echo "JIB_SERVER=" + echo "or" + echo "JIB_URL=" + exit 1 + fi + + if command -v curl > /dev/null; then + getcmd="curl -s" + elif command -v wget > /dev/null; then + getcmd="wget --quiet -O -" + else + echo "Could not find either curl or wget" + exit 1 + fi + + if ! command -v gunzip > /dev/null; then + echo "Could not find gunzip" + exit 1 + fi + + echo "Downloading JIB bootstrap script" + mkdir -p "${installed_jib_script%/*}" + rm -f "${installed_jib_script}.gz" + ${getcmd} ${jib_url} > "${installed_jib_script}.gz" + if [ ! -s "${installed_jib_script}.gz" ]; then + echo "Failed to download ${jib_url}" + exit 1 + fi + echo "Extracting JIB bootstrap script" + rm -f "${installed_jib_script}" + gunzip "${installed_jib_script}.gz" + chmod +x "${installed_jib_script}" + echo "${data_string}" > "${install_data}" +} + +# Main body starts here + +setup_url + +if [ ! -x "${installed_jib_script}" ]; then + install_jib +elif [ ! -e "${install_data}" ] || [ "${data_string}" != "$(cat "${install_data}")" ]; then + echo "Install url changed since last time, reinstalling" + install_jib +fi + +${installed_jib_script} "$@" diff --git a/common/bin/unshuffle_list.txt b/common/bin/unshuffle_list.txt index 68acb88fde4..e50fb3fe235 100644 --- a/common/bin/unshuffle_list.txt +++ b/common/bin/unshuffle_list.txt @@ -1293,10 +1293,7 @@ jdk/src/jdk.crypto.pkcs11/windows/native/libj2pkcs11/j2secmod_md.h : jdk/src/win jdk/src/jdk.crypto.pkcs11/windows/native/libj2pkcs11/p11_md.c : jdk/src/windows/native/sun/security/pkcs11/wrapper/p11_md.c jdk/src/jdk.crypto.pkcs11/windows/native/libj2pkcs11/p11_md.h : jdk/src/windows/native/sun/security/pkcs11/wrapper/p11_md.h jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/package.html : jdk/src/macosx/classes/com/apple/concurrent/package.html -jdk/src/jdk.deploy.osx/macosx/classes/apple/applescript : jdk/src/macosx/classes/apple/applescript -jdk/src/jdk.deploy.osx/macosx/classes/apple/security : jdk/src/macosx/classes/apple/security jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent : jdk/src/macosx/classes/com/apple/concurrent -jdk/src/jdk.deploy.osx/macosx/native/libapplescriptengine : jdk/src/macosx/native/apple/applescript jdk/src/jdk.deploy.osx/macosx/native/libosx/CFileManager.m : jdk/src/macosx/native/com/apple/eio/CFileManager.m jdk/src/jdk.deploy.osx/macosx/native/libosx/Dispatch.m : jdk/src/macosx/native/com/apple/concurrent/Dispatch.m jdk/src/jdk.deploy.osx/macosx/native/libosx/JavaAppLauncher.m : jdk/src/macosx/native/apple/launcher/JavaAppLauncher.m diff --git a/common/conf/jib-profiles.js b/common/conf/jib-profiles.js new file mode 100644 index 00000000000..b9c09fcd018 --- /dev/null +++ b/common/conf/jib-profiles.js @@ -0,0 +1,555 @@ +/* + * 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. + */ + +/* + * This file defines build profiles for the JIB tool and others. + * + * A build profile defines a set of configuration options and external + * dependencies that we for some reason or other care about specifically. + * Typically, build profiles are defined for the build configurations we + * build regularly. + * + * Contract against this file from the tools that use it, is to provide + * a function on the form: + * + * getJibProfiles(input) + * + * which returns an object graph describing the profiles and their + * dependencies. The name of the function is based on the name of this + * file, minus the extension and the '-', camel cased and prefixed with + * 'get'. + * + * + * The parameter 'input' is an object that optionally contains some data. + * Optionally because a tool may read the configuration for different purposes. + * To initially get a list of available profiles, the active profile may not + * yet be known for instance. + * + * Data that may be set on the input object: + * + * input.profile = + * + * If the active profile is set, the following data from it must also + * be provided: + * + * input.profile + * input.target_os + * input.target_cpu + * input.build_os + * input.build_cpu + * input.target_platform + * input.build_platform + * // The build_osenv_* variables describe the unix layer on Windows systems, + * // i.e. Cygwin, which may also be 32 or 64 bit. + * input.build_osenv + * input.build_osenv_cpu + * input.build_osenv_platform + * + * For more complex nested attributes, there is a method "get": + * + * input.get("", "") + * + * Valid attributes are: + * install_path + * download_path + * download_dir + * + * + * The output data generated by this configuration file has the following + * format: + * + * data: { + * // Identifies the version of this format to the tool reading it + * format_version: "1.0", + * + * // Name of base outputdir. JIB assumes the actual output dir is formed + * // by adding the configuration name: / + * output_basedir: "build", + * // Configure argument to use to specify configuration name + * configuration_configure_arg: + * // Make argument to use to specify configuration name + * configuration_make_arg: + * + * profiles: { + * : { + * // Name of os the profile is built to run on + * target_os; + * // Name of cpu the profile is built to run on + * target_cpu; + * // Combination of target_os and target_cpu for convenience + * target_platform; + * // Name of os the profile is built on + * build_os; + * // Name of cpu the profile is built on + * build_cpu; + * // Combination of build_os and build_cpu for convenience + * build_platform; + * + * // List of dependencies needed to build this profile + * dependencies: + * + * // List of configure args to use for this profile + * configure_args: + * + * // List of free form labels describing aspects of this profile + * labels: + * } + * } + * + * // Dependencies use a Maven like deployment structure + * dependencies: { + * : { + * // Organization part of path defining this dependency + * organization: + * // File extension for this dependency + * ext: + * // Module part of path for defining this dependency, + * // defaults to + * module: + * // Revision part of path for defining this dependency + * revision: + * + * // List of configure args to add when using this dependency, + * // defaults to + * // "--with-=input.get(" + * + * // Name of environment variable to set when using this dependency + * // when running make + * environment_name: + * // Value of environment variable to set when using this dependency + * // when running make + * environment_value: + * + * // Value to add to the PATH variable when using this dependency, + * // applies to both make and configure + * environment_path: + * } + * + * : { + * // For certain dependencies where a legacy distribution mechanism is + * // already in place, the "javare" server layout is also supported + * // Indicate that an alternate server source and layout should be used + * server: "javare" + * + * // For "javare", a combination of module, revision, + * // build number (optional), files and checksum file is possible for + * // artifacts following the standard layout. + * module: + * revision: + * build_number: + * checksum_file: + * file: + * + * // For other files, use checksum path and path instead + * checksum_path: + * path: + * } + * } + * } + */ + +/** + * Main entry to generate the profile configuration + * + * @param input External data to use for generating the configuration + * @returns {{}} Profile configuration + */ +var getJibProfiles = function (input) { + + var data = {}; + + // Identifies the version of this format to the tool reading it + data.format_version = "1.0"; + + // Organization is used when uploading/publishing build results + data.organization = "com.oracle.jpg.jdk"; + + // The base directory for the build output. JIB will assume that the + // actual build directory will be / + data.output_basedir = "build"; + // The configure argument to use to specify the name of the configuration + data.configuration_configure_arg = "--with-conf-name="; + // The make argument to use to specify the name of the configuration + data.configuration_make_arg = "CONF_NAME="; + + // Define some common values + var common = getJibProfilesCommon(input); + // Generate the profiles part of the configuration + data.profiles = getJibProfilesProfiles(input, common); + // Generate the dependencies part of the configuration + data.dependencies = getJibProfilesDependencies(input, common); + + return data; +}; + +/** + * Generates some common values + * + * @param input External data to use for generating the configuration + * @returns Common values + */ +var getJibProfilesCommon = function (input) { + var common = { + dependencies: ["boot_jdk", "gnumake", "jtreg"], + configure_args: ["--with-default-make-target=all"], + configure_args_32bit: ["--with-target-bits=32", "--with-jvm-variants=client,server"], + configure_args_debug: ["--enable-debug"], + organization: "jpg.infra.builddeps" + }; + + return common; +}; + +/** + * Generates the profiles part of the configuration. + * + * @param input External data to use for generating the configuration + * @param common The common values + * @returns {{}} Profiles part of the configuration + */ +var getJibProfilesProfiles = function (input, common) { + var profiles = {}; + + // Main SE profiles + var mainProfiles = { + + "linux-x64": { + target_os: "linux", + target_cpu: "x64", + dependencies: concat(common.dependencies, "devkit"), + configure_args: common.configure_args, + make_args: common.make_args + }, + + "linux-x86": { + target_os: "linux", + target_cpu: "x86", + build_cpu: "x64", + dependencies: concat(common.dependencies, "devkit"), + configure_args: concat(common.configure_args, common.configure_args_32bit), + make_args: common.make_args + }, + + "macosx-x64": { + target_os: "macosx", + target_cpu: "x64", + dependencies: concat(common.dependencies, "devkit"), + configure_args: concat(common.configure_args, "--with-sdk-name=macosx10.9"), + make_args: common.make_args + }, + + "solaris-x64": { + target_os: "solaris", + target_cpu: "x64", + dependencies: concat(common.dependencies, "devkit", "cups"), + configure_args: common.configure_args, + make_args: common.make_args + }, + + "solaris-sparcv9": { + target_os: "solaris", + target_cpu: "sparcv9", + dependencies: concat(common.dependencies, "devkit", "cups"), + configure_args: common.configure_args, + make_args: common.make_args + }, + + "windows-x64": { + target_os: "windows", + target_cpu: "x64", + dependencies: concat(common.dependencies, "devkit", "freetype"), + configure_args: common.configure_args, + make_args: common.make_args + }, + + "windows-x86": { + target_os: "windows", + target_cpu: "x86", + build_cpu: "x64", + dependencies: concat(common.dependencies, "devkit", "freetype"), + configure_args: concat(common.configure_args, common.configure_args_32bit), + make_args: common.make_args + } + }; + profiles = concatObjects(profiles, mainProfiles); + // Generate debug versions of all the main profiles + profiles = concatObjects(profiles, generateDebugProfiles(common, mainProfiles)); + + // Specific open profiles needed for JPRT testing + var jprtOpenProfiles = { + + "linux-x64-open": { + target_os: mainProfiles["linux-x64"].target_os, + target_cpu: mainProfiles["linux-x64"].target_cpu, + dependencies: mainProfiles["linux-x64"].dependencies, + configure_args: concat(mainProfiles["linux-x64"].configure_args, + "--enable-openjdk-only"), + make_args: mainProfiles["linux-x64"].make_args, + labels: [ "open" ] + }, + + "solaris-x64-open": { + target_os: mainProfiles["solaris-x64"].target_os, + target_cpu: mainProfiles["solaris-x64"].target_cpu, + dependencies: mainProfiles["solaris-x64"].dependencies, + configure_args: concat(mainProfiles["solaris-x64"].configure_args, + "--enable-openjdk-only"), + make_args: mainProfiles["solaris-x64"].make_args, + labels: [ "open" ] + } + }; + profiles = concatObjects(profiles, jprtOpenProfiles); + // Generate debug profiles for the open jprt profiles + profiles = concatObjects(profiles, generateDebugProfiles(common, jprtOpenProfiles)); + + // Profiles used to run tests. Used in JPRT. + var testOnlyProfiles = { + + "run-test": { + target_os: input.build_os, + target_cpu: input.build_cpu, + dependencies: [ "jtreg", "gnumake" ], + labels: "test" + } + }; + profiles = concatObjects(profiles, testOnlyProfiles); + + // Generate the missing platform attributes + profiles = generatePlatformAttributes(profiles); + return profiles; +}; + +/** + * Generate the dependencies part of the configuration + * + * @param input External data to use for generating the configuration + * @param common The common values + * @returns {{}} Dependencies part of configuration + */ +var getJibProfilesDependencies = function (input, common) { + + var boot_jdk_platform = input.build_os + "-" + + (input.build_cpu == "x86" ? "i586" : input.build_cpu); + + var devkit_platform_revisions = { + linux_x64: "gcc4.9.2-OEL6.4+1.0", + macosx_x64: "Xcode6.3-MacOSX10.9+1.0", + solaris_x64: "SS12u3-Solaris10u10+1.0", + solaris_sparcv9: "SS12u3-Solaris10u10+1.0", + windows_x64: "VS2013SP4+1.0" + }; + + var devkit_platform = (input.target_cpu == "x86" + ? input.target_os + "_x64" + : input.target_platform); + + var dependencies = { + + boot_jdk: { + server: "javare", + module: "jdk", + revision: "8", + checksum_file: boot_jdk_platform + "/MD5_VALUES", + file: boot_jdk_platform + "/jdk-8-" + boot_jdk_platform + ".tar.gz", + configure_args: (input.build_os == "macosx" + ? "--with-boot-jdk=" + input.get("boot_jdk", "install_path") + "/jdk1.8.0.jdk/Contents/Home" + : "--with-boot-jdk=" + input.get("boot_jdk", "install_path") + "/jdk1.8.0") + }, + + devkit: { + organization: common.organization, + ext: "tar.gz", + module: "devkit-" + devkit_platform, + revision: devkit_platform_revisions[devkit_platform] + }, + + build_devkit: { + organization: common.organization, + ext: "tar.gz", + module: "devkit-" + input.build_platform, + revision: devkit_platform_revisions[input.build_platform] + }, + + cups: { + organization: common.organization, + ext: "tar.gz", + revision: "1.0118+1.0" + }, + + jtreg: { + server: "javare", + revision: "4.1", + build_number: "b12", + checksum_file: "MD5_VALUES", + file: "jtreg_bin-4.1.zip", + environment_name: "JT_HOME" + }, + + gnumake: { + organization: common.organization, + ext: "tar.gz", + revision: "4.0+1.0", + + module: (input.build_os == "windows" + ? "gnumake-" + input.build_osenv_platform + : "gnumake-" + input.build_platform), + + configure_args: (input.build_os == "windows" + ? "MAKE=" + input.get("gnumake", "install_path") + "/cygwin/bin/make" + : "MAKE=" + input.get("gnumake", "install_path") + "/bin/make"), + + environment_path: (input.build_os == "windows" + ? input.get("gnumake", "install_path") + "/cygwin/bin" + : input.get("gnumake", "install_path") + "/bin") + }, + + freetype: { + organization: common.organization, + ext: "tar.gz", + revision: "2.3.4+1.0", + module: "freetype-" + input.target_platform + } + }; + + return dependencies; +}; + +/** + * Generate the missing platform attributes for profiles + * + * @param profiles Profiles map to generate attributes on + * @returns {{}} New profiles map with platform attributes fully filled in + */ +var generatePlatformAttributes = function (profiles) { + var ret = concatObjects(profiles, {}); + for (var profile in profiles) { + if (ret[profile].build_os == null) { + ret[profile].build_os = ret[profile].target_os; + } + if (ret[profile].build_cpu == null) { + ret[profile].build_cpu = ret[profile].target_cpu; + } + ret[profile].target_platform = ret[profile].target_os + "_" + ret[profile].target_cpu; + ret[profile].build_platform = ret[profile].build_os + "_" + ret[profile].build_cpu; + } + return ret; +}; + +/** + * Generates debug versions of profiles. Clones the given profiles and adds + * debug metadata. + * + * @param common Common values + * @param profiles Profiles map to generate debug profiles for + * @returns {{}} New map of profiles containing debug profiles + */ +var generateDebugProfiles = function (common, profiles) { + var newProfiles = {}; + for (var profile in profiles) { + var debugProfile = profile + "-debug"; + newProfiles[debugProfile] = clone(profiles[profile]); + newProfiles[debugProfile].debug_level = "fastdebug"; + newProfiles[debugProfile].labels + = concat(newProfiles[debugProfile].labels || [], "debug"), + newProfiles[debugProfile].configure_args + = concat(newProfiles[debugProfile].configure_args, + common.configure_args_debug); + } + return newProfiles; +}; + +/** + * Deep clones an object tree. + * + * @param o Object to clone + * @returns {{}} Clone of o + */ +var clone = function (o) { + return JSON.parse(JSON.stringify(o)); +}; + +/** + * Concatenates all arguments into a new array + * + * @returns {Array.} New array containing all arguments + */ +var concat = function () { + return Array.prototype.concat.apply([], arguments); +}; + +/** + * Copies all elements in an array into a new array but replacing all + * occurrences of original with replacement. + * + * @param original Element to look for + * @param replacement Element to replace with + * @param a Array to copy + * @returns {Array} New array with all occurrences of original replaced + * with replacement + */ +var replace = function (original, replacement, a) { + var newA = []; + for (var i in a) { + if (original == a[i]) { + newA.push(replacement); + } else { + newA.push(a[i]); + } + } + return newA; +}; + +/** + * Deep concatenation of two objects. For each node encountered, merge + * the contents with the corresponding node in the other object tree, + * treating all strings as array elements. + * + * @param o1 Object to concatenate + * @param o2 Object to concatenate + * @returns {{}} New object tree containing the concatenation of o1 and o2 + */ +var concatObjects = function (o1, o2) { + var ret = {}; + for (var a in o1) { + if (o2[a] == null) { + ret[a] = o1[a]; + } + } + for (var a in o2) { + if (o1[a] == null) { + ret[a] = o2[a]; + } else { + if (typeof o1[a] == 'string') { + ret[a] = [o1[a]].concat(o2[a]); + } else if (Array.isArray(o1[a])) { + ret[a] = o1[a].concat(o2[a]); + } else if (typeof o1[a] == 'object') { + ret[a] = concatObjects(o1[a], o2[a]); + } + } + } + return ret; +}; diff --git a/corba/.hgtags b/corba/.hgtags index 18091f19086..68ea48b8a39 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -338,3 +338,4 @@ f7d70caad89ad0c43bb057bca0aad6f17ce05a6a jdk9-b92 27e9c8d8091e2447ea7ef3e3103e9b7dd286e03a jdk9-b93 61e9f509be0f78f0961477960f372b0533214bb8 jdk9-b94 fd038e8a16eec80d0d6b337d74a582790ed4b3ee jdk-9+95 +feb1bd85d7990dcf5584ca9e53104269c01db006 jdk-9+96 diff --git a/hotspot/.hgignore b/hotspot/.hgignore index 8bd4af0eb82..f0010a40148 100644 --- a/hotspot/.hgignore +++ b/hotspot/.hgignore @@ -11,7 +11,12 @@ ^.hgtip .DS_Store \.class$ -^\.?mx.jvmci/ +^\.mx.jvmci/env +^\.mx.jvmci/.*\.pyc +^\.mx.jvmci/eclipse-launches/.* +^\.mx.jvmci/hotspot/eclipse/.* +^\.idea/ +^workingsets.xml ^src/jdk.vm.ci/share/classes/\w[\w\.]*/.*\.xml ^src/jdk.vm.ci/share/classes/\w[\w\.]*/.*\.iml ^src/jdk.vm.ci/share/classes/\w[\w\.]*/nbproject diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 3506fe2faf7..045c4944462 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -498,3 +498,4 @@ bc48b669bc6610fac97e16593050c0f559cf6945 jdk9-b88 d8b24776484cc4dfd19f50b23eaa18a80a161371 jdk9-b93 a22b7c80529f5f05c847e932e017456e83c46233 jdk9-b94 0c79cf3cdf0904fc4a630b91b32904491e1ae430 jdk-9+95 +a94bb7203596dd632486f1e3655fa5f70541dc08 jdk-9+96 diff --git a/hotspot/.mx.jvmci/.project b/hotspot/.mx.jvmci/.project new file mode 100644 index 00000000000..5d4c97b68bc --- /dev/null +++ b/hotspot/.mx.jvmci/.project @@ -0,0 +1,18 @@ + + + mx.jvmci + + + mx + + + + org.python.pydev.PyDevBuilder + + + + + + org.python.pydev.pythonNature + + diff --git a/hotspot/.mx.jvmci/.pydevproject b/hotspot/.mx.jvmci/.pydevproject new file mode 100644 index 00000000000..93dc745f1db --- /dev/null +++ b/hotspot/.mx.jvmci/.pydevproject @@ -0,0 +1,14 @@ + + + + +Default +python 2.7 + +/mx.jvmci + + +/mx + + + diff --git a/hotspot/.mx.jvmci/eclipse-settings/org.eclipse.jdt.core.prefs b/hotspot/.mx.jvmci/eclipse-settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000000..1c652f69b64 --- /dev/null +++ b/hotspot/.mx.jvmci/eclipse-settings/org.eclipse.jdt.core.prefs @@ -0,0 +1 @@ +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=disabled diff --git a/hotspot/.mx.jvmci/hotspot/templates/eclipse/cproject b/hotspot/.mx.jvmci/hotspot/templates/eclipse/cproject new file mode 100644 index 00000000000..b156340e98b --- /dev/null +++ b/hotspot/.mx.jvmci/hotspot/templates/eclipse/cproject @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hotspot/.mx.jvmci/hotspot/templates/eclipse/settings/org.eclipse.cdt.core.prefs b/hotspot/.mx.jvmci/hotspot/templates/eclipse/settings/org.eclipse.cdt.core.prefs new file mode 100644 index 00000000000..370adf764a5 --- /dev/null +++ b/hotspot/.mx.jvmci/hotspot/templates/eclipse/settings/org.eclipse.cdt.core.prefs @@ -0,0 +1,198 @@ +eclipse.preferences.version=1 +environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.1958236162/BUILDING_FROM_IDE/delimiter=\: +environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.1958236162/BUILDING_FROM_IDE/operation=append +environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.1958236162/BUILDING_FROM_IDE/value=true +environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.1958236162/append=true +environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.1958236162/appendContributed=true +environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.2116626004.562670952/BUILDING_FROM_IDE/delimiter=\: +environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.2116626004.562670952/BUILDING_FROM_IDE/operation=append +environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.2116626004.562670952/BUILDING_FROM_IDE/value=true +environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.2116626004.562670952/append=true +environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.2116626004.562670952/appendContributed=true +environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.2116626004/BUILDING_FROM_IDE/delimiter=\: +environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.2116626004/BUILDING_FROM_IDE/operation=append +environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.2116626004/BUILDING_FROM_IDE/value=true +environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.2116626004/append=true +environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.2116626004/appendContributed=true +environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.500153051/BUILDING_FROM_IDE/delimiter=\: +environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.500153051/BUILDING_FROM_IDE/operation=append +environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.500153051/BUILDING_FROM_IDE/value=true +environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.500153051/append=true +environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.500153051/appendContributed=true +environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.915924225/BUILDING_FROM_IDE/delimiter=\: +environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.915924225/BUILDING_FROM_IDE/operation=append +environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.915924225/BUILDING_FROM_IDE/value=true +environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.915924225/append=true +environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.915924225/appendContributed=true +environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.982312162/BUILDING_FROM_IDE/delimiter=\: +environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.982312162/BUILDING_FROM_IDE/operation=append +environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.982312162/BUILDING_FROM_IDE/value=true +environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.982312162/append=true +environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881.982312162/appendContributed=true +environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881/BUILDING_FROM_IDE/delimiter=\: +environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881/BUILDING_FROM_IDE/operation=append +environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881/BUILDING_FROM_IDE/value=true +environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881/append=true +environment/project/cdt.managedbuild.toolchain.gnu.solaris.base.945602881/appendContributed=true +org.eclipse.cdt.core.formatter.alignment_for_arguments_in_method_invocation=16 +org.eclipse.cdt.core.formatter.alignment_for_assignment=16 +org.eclipse.cdt.core.formatter.alignment_for_base_clause_in_type_declaration=80 +org.eclipse.cdt.core.formatter.alignment_for_binary_expression=16 +org.eclipse.cdt.core.formatter.alignment_for_compact_if=0 +org.eclipse.cdt.core.formatter.alignment_for_conditional_expression=80 +org.eclipse.cdt.core.formatter.alignment_for_conditional_expression_chain=18 +org.eclipse.cdt.core.formatter.alignment_for_constructor_initializer_list=0 +org.eclipse.cdt.core.formatter.alignment_for_declarator_list=16 +org.eclipse.cdt.core.formatter.alignment_for_enumerator_list=48 +org.eclipse.cdt.core.formatter.alignment_for_expression_list=0 +org.eclipse.cdt.core.formatter.alignment_for_expressions_in_array_initializer=16 +org.eclipse.cdt.core.formatter.alignment_for_member_access=0 +org.eclipse.cdt.core.formatter.alignment_for_overloaded_left_shift_chain=16 +org.eclipse.cdt.core.formatter.alignment_for_parameters_in_method_declaration=16 +org.eclipse.cdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 +org.eclipse.cdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.cdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.cdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.cdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.cdt.core.formatter.brace_position_for_namespace_declaration=end_of_line +org.eclipse.cdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.cdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.cdt.core.formatter.comment.min_distance_between_code_and_line_comment=1 +org.eclipse.cdt.core.formatter.comment.never_indent_line_comments_on_first_column=true +org.eclipse.cdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false +org.eclipse.cdt.core.formatter.compact_else_if=true +org.eclipse.cdt.core.formatter.continuation_indentation=2 +org.eclipse.cdt.core.formatter.continuation_indentation_for_array_initializer=2 +org.eclipse.cdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.cdt.core.formatter.indent_access_specifier_compare_to_type_header=false +org.eclipse.cdt.core.formatter.indent_access_specifier_extra_spaces=0 +org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_access_specifier=true +org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_namespace_header=false +org.eclipse.cdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.cdt.core.formatter.indent_declaration_compare_to_template_header=false +org.eclipse.cdt.core.formatter.indent_empty_lines=false +org.eclipse.cdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.cdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_switch=true +org.eclipse.cdt.core.formatter.indentation.size=2 +org.eclipse.cdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.cdt.core.formatter.insert_new_line_after_template_declaration=do not insert +org.eclipse.cdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.cdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.cdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.cdt.core.formatter.insert_new_line_before_colon_in_constructor_initializer_list=do not insert +org.eclipse.cdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.cdt.core.formatter.insert_new_line_before_identifier_in_function_declaration=do not insert +org.eclipse.cdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.cdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.cdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.cdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_arguments=insert +org.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_parameters=insert +org.eclipse.cdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.cdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.cdt.core.formatter.insert_space_after_colon_in_base_clause=insert +org.eclipse.cdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.cdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.cdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.cdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.cdt.core.formatter.insert_space_after_comma_in_base_types=insert +org.eclipse.cdt.core.formatter.insert_space_after_comma_in_declarator_list=insert +org.eclipse.cdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.cdt.core.formatter.insert_space_after_comma_in_expression_list=insert +org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_arguments=insert +org.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_parameters=insert +org.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_arguments=do not insert +org.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_parameters=do not insert +org.eclipse.cdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.cdt.core.formatter.insert_space_after_opening_bracket=do not insert +org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_exception_specification=do not insert +org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.cdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.cdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.cdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.cdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.cdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.cdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_arguments=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_parameters=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.cdt.core.formatter.insert_space_before_closing_bracket=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_exception_specification=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_colon_in_base_clause=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.cdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_comma_in_base_types=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_comma_in_declarator_list=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_comma_in_expression_list=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_arguments=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_parameters=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_arguments=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_parameters=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_namespace_declaration=insert +org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.cdt.core.formatter.insert_space_before_opening_bracket=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_exception_specification=insert +org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.cdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.cdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.cdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.cdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.cdt.core.formatter.insert_space_between_empty_brackets=do not insert +org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_exception_specification=do not insert +org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.cdt.core.formatter.join_wrapped_lines=true +org.eclipse.cdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.cdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.cdt.core.formatter.keep_imple_if_on_one_line=true +org.eclipse.cdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.cdt.core.formatter.lineSplit=160 +org.eclipse.cdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.cdt.core.formatter.put_empty_statement_on_new_line=true +org.eclipse.cdt.core.formatter.tabulation.char=space +org.eclipse.cdt.core.formatter.tabulation.size=2 +org.eclipse.cdt.core.formatter.use_tabs_only_for_leading_indentations=false diff --git a/hotspot/.mx.jvmci/hotspot/templates/eclipse/settings/org.eclipse.cdt.ui.prefs b/hotspot/.mx.jvmci/hotspot/templates/eclipse/settings/org.eclipse.cdt.ui.prefs new file mode 100644 index 00000000000..c8d45cd349f --- /dev/null +++ b/hotspot/.mx.jvmci/hotspot/templates/eclipse/settings/org.eclipse.cdt.ui.prefs @@ -0,0 +1,5 @@ +#Wed Sep 01 16:21:02 PDT 2010 +eclipse.preferences.version=1 +formatter_profile=_hotspotStyle +formatter_settings_version=1 + diff --git a/hotspot/.mx.jvmci/hotspot/templates/eclipse/settings/org.eclipse.core.runtime.prefs b/hotspot/.mx.jvmci/hotspot/templates/eclipse/settings/org.eclipse.core.runtime.prefs new file mode 100644 index 00000000000..55f0bfe5d18 --- /dev/null +++ b/hotspot/.mx.jvmci/hotspot/templates/eclipse/settings/org.eclipse.core.runtime.prefs @@ -0,0 +1,6 @@ +#Wed Sep 01 16:13:40 PDT 2010 +content-types/enabled=true +content-types/org.eclipse.cdt.core.cxxHeader/file-extensions=hpp,incl +content-types/org.eclipse.cdt.core.cxxSource/file-extensions=cpp +eclipse.preferences.version=1 + diff --git a/hotspot/.mx.jvmci/mx_jvmci.py b/hotspot/.mx.jvmci/mx_jvmci.py new file mode 100644 index 00000000000..0e3ac639bb3 --- /dev/null +++ b/hotspot/.mx.jvmci/mx_jvmci.py @@ -0,0 +1,890 @@ +# +# ---------------------------------------------------------------------------------------------------- +# +# Copyright (c) 2007, 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. +# +# ---------------------------------------------------------------------------------------------------- + +import os, shutil, zipfile, re, time, sys, datetime, platform +from os.path import join, exists, dirname, isdir +from argparse import ArgumentParser, REMAINDER +import StringIO +import xml.dom.minidom +import subprocess + +import mx +import mx_gate +import mx_unittest + +from mx_gate import Task +from mx_unittest import unittest + +_suite = mx.suite('jvmci') + +""" +Top level directory of the JDK source workspace. +""" +_jdkSourceRoot = dirname(_suite.dir) + +_JVMCI_JDK_TAG = 'jvmci' + +_minVersion = mx.VersionSpec('1.9') + +# max version (first _unsupported_ version) +_untilVersion = None + +_jvmciModes = { + 'hosted' : ['-XX:+UnlockExperimentalVMOptions', '-XX:+EnableJVMCI'], + 'jit' : ['-XX:+UnlockExperimentalVMOptions', '-XX:+EnableJVMCI', '-XX:+UseJVMCICompiler'], + 'disabled' : [] +} + +# TODO: can optimized be built without overriding release build? +_jdkDebugLevels = ['release', 'fastdebug', 'slowdebug'] + +# TODO: add client once/if it can be built on 64-bit platforms +_jdkJvmVariants = ['server'] + +""" +Translation table from mx_jvmci:8 --vmbuild values to mx_jvmci:9 --jdk-debug-level values. +""" +_legacyVmbuilds = { + 'product' : 'release', + 'debug' : 'slowdebug' +} + +""" +Translates a mx_jvmci:8 --vmbuild value to a mx_jvmci:9 --jdk-debug-level value. +""" +def _translateLegacyDebugLevel(debugLevel): + return _legacyVmbuilds.get(debugLevel, debugLevel) + +""" +Translation table from mx_jvmci:8 --vm values to mx_jvmci:9 (--jdk-jvm-variant, --jvmci-mode) tuples. +""" +_legacyVms = { + 'jvmci' : ('server', 'jit') +} + +""" +A VM configuration composed of a JDK debug level, JVM variant and a JVMCI mode. +This is also a context manager that can be used with the 'with' statement to set/change +a VM configuration within a dynamic scope. For example: + + with ConfiguredJDK(debugLevel='fastdebug'): + dacapo(['pmd']) +""" +class VM: + def __init__(self, jvmVariant=None, debugLevel=None, jvmciMode=None): + self.update(jvmVariant, debugLevel, jvmciMode) + + def update(self, jvmVariant=None, debugLevel=None, jvmciMode=None): + if jvmVariant in _legacyVms: + # Backwards compatibility for mx_jvmci:8 API + jvmVariant, newJvmciMode = _legacyVms[jvmVariant] + if jvmciMode is not None and jvmciMode != newJvmciMode: + mx.abort('JVM variant "' + jvmVariant + '" implies JVMCI mode "' + newJvmciMode + + '" which conflicts with explicitly specified JVMCI mode of "' + jvmciMode + '"') + jvmciMode = newJvmciMode + debugLevel = _translateLegacyDebugLevel(debugLevel) + assert jvmVariant is None or jvmVariant in _jdkJvmVariants, jvmVariant + assert debugLevel is None or debugLevel in _jdkDebugLevels, debugLevel + assert jvmciMode is None or jvmciMode in _jvmciModes, jvmciMode + self.jvmVariant = jvmVariant or _vm.jvmVariant + self.debugLevel = debugLevel or _vm.debugLevel + self.jvmciMode = jvmciMode or _vm.jvmciMode + + def __enter__(self): + global _vm + self.previousVm = _vm + _vm = self + + def __exit__(self, exc_type, exc_value, traceback): + global _vm + _vm = self.previousVm + +_vm = VM(jvmVariant=_jdkJvmVariants[0], debugLevel=_jdkDebugLevels[0], jvmciMode='hosted') + +def get_vm(): + """ + Gets the configured VM. + """ + return _vm + +def relativeVmLibDirInJdk(): + mxos = mx.get_os() + if mxos == 'darwin': + return join('lib') + if mxos == 'windows' or mxos == 'cygwin': + return join('bin') + return join('lib', mx.get_arch()) + +def isJVMCIEnabled(vm): + assert vm in _jdkJvmVariants + return True + +class JvmciJDKDeployedDist(object): + def __init__(self, name, compilers=False): + self._name = name + self._compilers = compilers + + def dist(self): + return mx.distribution(self._name) + + def deploy(self, jdkDir): + mx.nyi('deploy', self) + +class ExtJDKDeployedDist(JvmciJDKDeployedDist): + def __init__(self, name): + JvmciJDKDeployedDist.__init__(self, name) + + +""" +The monolithic JVMCI distribution is deployed through use of -Xbootclasspath/p +so that it's not necessary to run JDK make after editing JVMCI sources. +The latter causes all JDK Java sources to be rebuilt since JVMCI is +(currently) in java.base. +""" +_monolithicJvmci = JvmciJDKDeployedDist('JVMCI') + +""" +List of distributions that are deployed on the boot class path. +Note: In jvmci-8, they were deployed directly into the JDK directory. +""" +jdkDeployedDists = [_monolithicJvmci] + +def _makehelp(): + return subprocess.check_output([mx.gmake_cmd(), 'help'], cwd=_jdkSourceRoot) + +def _runmake(args): + """run the JDK make process + +To build hotspot and import it into the JDK: "mx make hotspot import-hotspot" +{0}""" + + jdkBuildDir = _get_jdk_build_dir() + if not exists(jdkBuildDir): + # JDK9 must be bootstrapped with a JDK8 + compliance = mx.JavaCompliance('8') + jdk8 = mx.get_jdk(compliance.exactMatch, versionDescription=compliance.value) + cmd = ['sh', 'configure', '--with-debug-level=' + _vm.debugLevel, '--disable-debug-symbols', '--disable-precompiled-headers', + '--with-jvm-variants=' + _vm.jvmVariant, '--disable-warnings-as-errors', '--with-boot-jdk=' + jdk8.home] + mx.run(cmd, cwd=_jdkSourceRoot) + cmd = [mx.gmake_cmd(), 'CONF=' + _vm.debugLevel] + if mx.get_opts().verbose: + cmd.append('LOG=debug') + cmd.extend(args) + if mx.get_opts().use_jdk_image and 'images' not in args: + cmd.append('images') + + if not mx.get_opts().verbose: + mx.log('--------------- make execution ----------------------') + mx.log('Working directory: ' + _jdkSourceRoot) + mx.log('Command line: ' + ' '.join(cmd)) + mx.log('-----------------------------------------------------') + + mx.run(cmd, cwd=_jdkSourceRoot) + + if 'images' in cmd: + _create_jdk_bundle(jdkBuildDir) + +def _get_jdk_bundle_arches(): + """ + Gets a list of names that will be the part of a JDK bundle's file name denoting the architecture. + The first element in the list is the canonical name. Symlinks should be created for the + remaining names. + """ + cpu = mx.get_arch() + if cpu == 'amd64': + return ['x64', 'x86_64', 'amd64'] + elif cpu == 'sparcv9': + return ['sparcv9'] + mx.abort('Unsupported JDK bundle arch: ' + cpu) + +def _create_jdk_bundle(jdkBuildDir): + """ + Creates a tar.gz JDK archive, an accompanying tar.gz.sha1 file with its + SHA1 signature plus symlinks to the archive for non-canonical architecture names. + """ + jdkImageDir = join(jdkBuildDir, 'images', 'jdk') + + arches = _get_jdk_bundle_arches() + jdkTgzPath = join(_suite.get_output_root(), 'jdk-bundles', 'jdk9-{}-{}.tar.gz'.format(_get_openjdk_os(), arches[0])) + with mx.Archiver(jdkTgzPath, kind='tgz') as arc: + mx.log('Creating ' + jdkTgzPath) + for root, _, filenames in os.walk(jdkImageDir): + for name in filenames: + f = join(root, name) + arcname = 'jdk1.9.0/' + os.path.relpath(f, jdkImageDir) + arc.zf.add(name=f, arcname=arcname, recursive=False) + # The OpenJDK build creates an empty cacerts file so grab one from + # the default JDK which is assumed to be an OracleJDK + cacerts = join(mx.get_jdk(tag='default').home, 'jre', 'lib', 'security', 'cacerts') + arc.zf.add(name=cacerts, arcname='jdk1.9.0/lib/security/cacerts') + + with open(jdkTgzPath + '.sha1', 'w') as fp: + mx.log('Creating ' + jdkTgzPath + '.sha1') + fp.write(mx.sha1OfFile(jdkTgzPath)) + + def _create_link(source, link_name): + if exists(link_name): + os.remove(link_name) + mx.log('Creating ' + link_name + ' -> ' + source) + os.symlink(source, link_name) + + for arch in arches[1:]: + link_name = join(_suite.get_output_root(), 'jdk-bundles', 'jdk9-{}-{}.tar.gz'.format(_get_openjdk_os(), arch)) + jdkTgzName = os.path.basename(jdkTgzPath) + _create_link(jdkTgzName, link_name) + _create_link(jdkTgzName + '.sha1', link_name + '.sha1') + +def _runmultimake(args): + """run the JDK make process for one or more configurations""" + + jvmVariantsDefault = ','.join(_jdkJvmVariants) + debugLevelsDefault = ','.join(_jdkDebugLevels) + + parser = ArgumentParser(prog='mx multimake') + parser.add_argument('--jdk-jvm-variants', '--vms', help='a comma separated list of VMs to build (default: ' + jvmVariantsDefault + ')', metavar='', default=jvmVariantsDefault) + parser.add_argument('--jdk-debug-levels', '--builds', help='a comma separated list of JDK debug levels (default: ' + debugLevelsDefault + ')', metavar='', default=debugLevelsDefault) + parser.add_argument('-n', '--no-check', action='store_true', help='omit running "java -version" after each build') + select = parser.add_mutually_exclusive_group() + select.add_argument('-c', '--console', action='store_true', help='send build output to console instead of log files') + select.add_argument('-d', '--output-dir', help='directory for log files instead of current working directory', default=os.getcwd(), metavar='') + + args = parser.parse_args(args) + jvmVariants = args.jdk_jvm_variants.split(',') + debugLevels = [_translateLegacyDebugLevel(dl) for dl in args.jdk_debug_levels.split(',')] + + allStart = time.time() + for jvmVariant in jvmVariants: + for debugLevel in debugLevels: + if not args.console: + logFile = join(mx.ensure_dir_exists(args.output_dir), jvmVariant + '-' + debugLevel + '.log') + log = open(logFile, 'wb') + start = time.time() + mx.log('BEGIN: ' + jvmVariant + '-' + debugLevel + '\t(see: ' + logFile + ')') + verbose = ['-v'] if mx.get_opts().verbose else [] + # Run as subprocess so that output can be directed to a file + cmd = [sys.executable, '-u', mx.__file__] + verbose + ['--jdk-jvm-variant=' + jvmVariant, '--jdk-debug-level=' + debugLevel, 'make'] + mx.logv("executing command: " + str(cmd)) + subprocess.check_call(cmd, cwd=_suite.dir, stdout=log, stderr=subprocess.STDOUT) + duration = datetime.timedelta(seconds=time.time() - start) + mx.log('END: ' + jvmVariant + '-' + debugLevel + '\t[' + str(duration) + ']') + else: + with VM(jvmVariant=jvmVariant, debugLevel=debugLevel): + _runmake([]) + if not args.no_check: + with VM(jvmciMode='jit'): + run_vm(['-XX:-BootstrapJVMCI', '-version']) + allDuration = datetime.timedelta(seconds=time.time() - allStart) + mx.log('TOTAL TIME: ' + '[' + str(allDuration) + ']') + +class HotSpotProject(mx.NativeProject): + """ + Defines a NativeProject representing the HotSpot binaries built via make. + """ + def __init__(self, suite, name, deps, workingSets, **args): + assert name == 'hotspot' + mx.NativeProject.__init__(self, suite, name, "", [], deps, workingSets, None, None, join(suite.mxDir, name)) + + def eclipse_config_up_to_date(self, configZip): + # Assume that any change to this module might imply changes to the generated IDE files + if configZip.isOlderThan(__file__): + return False + for _, source in self._get_eclipse_settings_sources().iteritems(): + if configZip.isOlderThan(source): + return False + return True + + def _get_eclipse_settings_sources(self): + """ + Gets a dictionary from the name of an Eclipse settings file to + the file providing its generated content. + """ + if not hasattr(self, '_eclipse_settings'): + esdict = {} + templateSettingsDir = join(self.dir, 'templates', 'eclipse', 'settings') + if exists(templateSettingsDir): + for name in os.listdir(templateSettingsDir): + source = join(templateSettingsDir, name) + esdict[name] = source + self._eclipse_settings = esdict + return self._eclipse_settings + + def _eclipseinit(self, files=None, libFiles=None): + """ + Generates an Eclipse project for each HotSpot build configuration. + """ + + roots = [ + 'ASSEMBLY_EXCEPTION', + 'LICENSE', + 'README', + 'THIRD_PARTY_README', + 'agent', + 'make', + 'src', + 'test' + ] + + for jvmVariant in _jdkJvmVariants: + for debugLevel in _jdkDebugLevels: + name = jvmVariant + '-' + debugLevel + eclProjectDir = join(self.dir, 'eclipse', name) + mx.ensure_dir_exists(eclProjectDir) + + out = mx.XMLDoc() + out.open('projectDescription') + out.element('name', data='hotspot:' + name) + out.element('comment', data='') + out.element('projects', data='') + out.open('buildSpec') + out.open('buildCommand') + out.element('name', data='org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder') + out.element('triggers', data='full,incremental') + out.element('arguments', data='') + out.close('buildCommand') + + out.close('buildSpec') + out.open('natures') + out.element('nature', data='org.eclipse.cdt.core.cnature') + out.element('nature', data='org.eclipse.cdt.core.ccnature') + out.element('nature', data='org.eclipse.cdt.managedbuilder.core.managedBuildNature') + out.element('nature', data='org.eclipse.cdt.managedbuilder.core.ScannerConfigNature') + out.close('natures') + + if roots: + out.open('linkedResources') + for r in roots: + f = join(_suite.dir, r) + out.open('link') + out.element('name', data=r) + out.element('type', data='2' if isdir(f) else '1') + out.element('locationURI', data=mx.get_eclipse_project_rel_locationURI(f, eclProjectDir)) + out.close('link') + + out.open('link') + out.element('name', data='generated') + out.element('type', data='2') + generated = join(_get_hotspot_build_dir(jvmVariant, debugLevel), 'generated') + out.element('locationURI', data=mx.get_eclipse_project_rel_locationURI(generated, eclProjectDir)) + out.close('link') + + out.close('linkedResources') + out.close('projectDescription') + projectFile = join(eclProjectDir, '.project') + mx.update_file(projectFile, out.xml(indent='\t', newl='\n')) + if files: + files.append(projectFile) + + cprojectTemplate = join(self.dir, 'templates', 'eclipse', 'cproject') + cprojectFile = join(eclProjectDir, '.cproject') + with open(cprojectTemplate) as f: + content = f.read() + mx.update_file(cprojectFile, content) + if files: + files.append(cprojectFile) + + settingsDir = join(eclProjectDir, ".settings") + mx.ensure_dir_exists(settingsDir) + for name, source in self._get_eclipse_settings_sources().iteritems(): + out = StringIO.StringIO() + print >> out, '# GENERATED -- DO NOT EDIT' + print >> out, '# Source:', source + with open(source) as f: + print >> out, f.read() + content = out.getvalue() + mx.update_file(join(settingsDir, name), content) + if files: + files.append(join(settingsDir, name)) + + def getBuildTask(self, args): + return JDKBuildTask(self, args, _vm.debugLevel, _vm.jvmVariant) + + +class JDKBuildTask(mx.NativeBuildTask): + def __init__(self, project, args, debugLevel, jvmVariant): + mx.NativeBuildTask.__init__(self, args, project) + self.jvmVariant = jvmVariant + self.debugLevel = debugLevel + + def __str__(self): + return 'Building JDK[{}, {}]'.format(self.debugLevel, self.jvmVariant) + + def build(self): + if mx.get_opts().use_jdk_image: + _runmake(['images']) + else: + _runmake([]) + self._newestOutput = None + + def clean(self, forBuild=False): + if forBuild: # Let make handle incremental builds + return + if exists(_get_jdk_build_dir(self.debugLevel)): + _runmake(['clean']) + self._newestOutput = None + +# Backwards compatibility for mx_jvmci:8 API +def buildvms(args): + _runmultimake(args) + +def run_vm(args, vm=None, nonZeroIsFatal=True, out=None, err=None, cwd=None, timeout=None, debugLevel=None, vmbuild=None): + """run a Java program by executing the java executable in a JVMCI JDK""" + jdkTag = mx.get_jdk_option().tag + if jdkTag and jdkTag != _JVMCI_JDK_TAG: + mx.abort('The "--jdk" option must have the tag "' + _JVMCI_JDK_TAG + '" when running a command requiring a JVMCI VM') + jdk = get_jvmci_jdk(debugLevel=debugLevel or _translateLegacyDebugLevel(vmbuild)) + return jdk.run_java(args, nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, cwd=cwd, timeout=timeout) + +def _unittest_vm_launcher(vmArgs, mainClass, mainClassArgs): + run_vm(vmArgs + [mainClass] + mainClassArgs) + +mx_unittest.set_vm_launcher('JVMCI VM launcher', _unittest_vm_launcher) + +def _jvmci_gate_runner(args, tasks): + # Build release server VM now so we can run the unit tests + with Task('BuildHotSpotJVMCIHosted: release', tasks) as t: + if t: _runmultimake(['--jdk-jvm-variants', 'server', '--jdk-debug-levels', 'release']) + + # Run unit tests in hosted mode + with VM(jvmVariant='server', debugLevel='release', jvmciMode='hosted'): + with Task('JVMCI UnitTests: hosted-release', tasks) as t: + if t: unittest(['--suite', 'jvmci', '--enable-timing', '--verbose', '--fail-fast']) + + # Build the other VM flavors + with Task('BuildHotSpotJVMCIOthers: fastdebug', tasks) as t: + if t: _runmultimake(['--jdk-jvm-variants', 'server', '--jdk-debug-levels', 'fastdebug']) + + with Task('CleanAndBuildIdealGraphVisualizer', tasks, disableJacoco=True) as t: + if t and platform.processor() != 'sparc': + buildxml = mx._cygpathU2W(join(_suite.dir, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'build.xml')) + mx.run(['ant', '-f', buildxml, '-q', 'clean', 'build'], env=_igvBuildEnv()) + +mx_gate.add_gate_runner(_suite, _jvmci_gate_runner) +mx_gate.add_gate_argument('-g', '--only-build-jvmci', action='store_false', dest='buildNonJVMCI', help='only build the JVMCI VM') + +def _igvJdk(): + v8u20 = mx.VersionSpec("1.8.0_20") + v8u40 = mx.VersionSpec("1.8.0_40") + v8 = mx.VersionSpec("1.8") + def _igvJdkVersionCheck(version): + return version >= v8 and (version < v8u20 or version >= v8u40) + return mx.get_jdk(_igvJdkVersionCheck, versionDescription='>= 1.8 and < 1.8.0u20 or >= 1.8.0u40', purpose="building & running IGV").home + +def _igvBuildEnv(): + # When the http_proxy environment variable is set, convert it to the proxy settings that ant needs + env = dict(os.environ) + proxy = os.environ.get('http_proxy') + if not (proxy is None) and len(proxy) > 0: + if '://' in proxy: + # Remove the http:// prefix (or any other protocol prefix) + proxy = proxy.split('://', 1)[1] + # Separate proxy server name and port number + proxyName, proxyPort = proxy.split(':', 1) + proxyEnv = '-DproxyHost="' + proxyName + '" -DproxyPort=' + proxyPort + env['ANT_OPTS'] = proxyEnv + + env['JAVA_HOME'] = _igvJdk() + return env + +def igv(args): + """run the Ideal Graph Visualizer""" + logFile = '.ideal_graph_visualizer.log' + with open(join(_suite.dir, logFile), 'w') as fp: + mx.logv('[Ideal Graph Visualizer log is in ' + fp.name + ']') + nbplatform = join(_suite.dir, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'nbplatform') + + # Remove NetBeans platform if it is earlier than the current supported version + if exists(nbplatform): + updateTrackingFile = join(nbplatform, 'platform', 'update_tracking', 'org-netbeans-core.xml') + if not exists(updateTrackingFile): + mx.log('Could not find \'' + updateTrackingFile + '\', removing NetBeans platform') + shutil.rmtree(nbplatform) + else: + dom = xml.dom.minidom.parse(updateTrackingFile) + currentVersion = mx.VersionSpec(dom.getElementsByTagName('module_version')[0].getAttribute('specification_version')) + supportedVersion = mx.VersionSpec('3.43.1') + if currentVersion < supportedVersion: + mx.log('Replacing NetBeans platform version ' + str(currentVersion) + ' with version ' + str(supportedVersion)) + shutil.rmtree(nbplatform) + elif supportedVersion < currentVersion: + mx.log('Supported NetBeans version in igv command should be updated to ' + str(currentVersion)) + + if not exists(nbplatform): + mx.logv('[This execution may take a while as the NetBeans platform needs to be downloaded]') + + env = _igvBuildEnv() + # make the jar for Batik 1.7 available. + env['IGV_BATIK_JAR'] = mx.library('BATIK').get_path(True) + if mx.run(['ant', '-f', mx._cygpathU2W(join(_suite.dir, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'build.xml')), '-l', mx._cygpathU2W(fp.name), 'run'], env=env, nonZeroIsFatal=False): + mx.abort("IGV ant build & launch failed. Check '" + logFile + "'. You can also try to delete 'src/share/tools/IdealGraphVisualizer/nbplatform'.") + +def c1visualizer(args): + """run the Cl Compiler Visualizer""" + libpath = join(_suite.dir, 'lib') + if mx.get_os() == 'windows': + executable = join(libpath, 'c1visualizer', 'bin', 'c1visualizer.exe') + else: + executable = join(libpath, 'c1visualizer', 'bin', 'c1visualizer') + + # Check whether the current C1Visualizer installation is the up-to-date + if exists(executable) and not exists(mx.library('C1VISUALIZER_DIST').get_path(resolve=False)): + mx.log('Updating C1Visualizer') + shutil.rmtree(join(libpath, 'c1visualizer')) + + archive = mx.library('C1VISUALIZER_DIST').get_path(resolve=True) + + if not exists(executable): + zf = zipfile.ZipFile(archive, 'r') + zf.extractall(libpath) + + if not exists(executable): + mx.abort('C1Visualizer binary does not exist: ' + executable) + + if mx.get_os() != 'windows': + # Make sure that execution is allowed. The zip file does not always specfiy that correctly + os.chmod(executable, 0777) + + mx.run([executable]) + +def hsdis(args, copyToDir=None): + """download the hsdis library + + This is needed to support HotSpot's assembly dumping features. + By default it downloads the Intel syntax version, use the 'att' argument to install AT&T syntax.""" + flavor = 'intel' + if 'att' in args: + flavor = 'att' + if mx.get_arch() == "sparcv9": + flavor = "sparcv9" + lib = mx.add_lib_suffix('hsdis-' + mx.get_arch()) + path = join(_suite.dir, 'lib', lib) + + sha1s = { + 'att/hsdis-amd64.dll' : 'bcbd535a9568b5075ab41e96205e26a2bac64f72', + 'att/hsdis-amd64.so' : '58919ba085d4ef7a513f25bae75e7e54ee73c049', + 'intel/hsdis-amd64.dll' : '6a388372cdd5fe905c1a26ced614334e405d1f30', + 'intel/hsdis-amd64.so' : '844ed9ffed64fe9599638f29a8450c50140e3192', + 'intel/hsdis-amd64.dylib' : 'fdb13ef0d7d23d93dacaae9c98837bea0d4fc5a2', + 'sparcv9/hsdis-sparcv9.so': '970640a9af0bd63641f9063c11275b371a59ee60', + } + + flavoredLib = flavor + "/" + lib + if flavoredLib not in sha1s: + mx.logv("hsdis not supported on this plattform or architecture") + return + + if not exists(path): + sha1 = sha1s[flavoredLib] + sha1path = path + '.sha1' + mx.download_file_with_sha1('hsdis', path, ['https://lafo.ssw.uni-linz.ac.at/pub/hsdis/' + flavoredLib], sha1, sha1path, True, True, sources=False) + if copyToDir is not None and exists(copyToDir): + shutil.copy(path, copyToDir) + +def hcfdis(args): + """disassemble HexCodeFiles embedded in text files + + Run a tool over the input files to convert all embedded HexCodeFiles + to a disassembled format.""" + + parser = ArgumentParser(prog='mx hcfdis') + parser.add_argument('-m', '--map', help='address to symbol map applied to disassembler output') + parser.add_argument('files', nargs=REMAINDER, metavar='files...') + + args = parser.parse_args(args) + + path = mx.library('HCFDIS').get_path(resolve=True) + mx.run_java(['-cp', path, 'com.oracle.max.hcfdis.HexCodeFileDis'] + args.files) + + if args.map is not None: + addressRE = re.compile(r'0[xX]([A-Fa-f0-9]+)') + with open(args.map) as fp: + lines = fp.read().splitlines() + symbols = dict() + for l in lines: + addressAndSymbol = l.split(' ', 1) + if len(addressAndSymbol) == 2: + address, symbol = addressAndSymbol + if address.startswith('0x'): + address = long(address, 16) + symbols[address] = symbol + for f in args.files: + with open(f) as fp: + lines = fp.read().splitlines() + updated = False + for i in range(0, len(lines)): + l = lines[i] + for m in addressRE.finditer(l): + sval = m.group(0) + val = long(sval, 16) + sym = symbols.get(val) + if sym: + l = l.replace(sval, sym) + updated = True + lines[i] = l + if updated: + mx.log('updating ' + f) + with open('new_' + f, "w") as fp: + for l in lines: + print >> fp, l + +def jol(args): + """Java Object Layout""" + joljar = mx.library('JOL_INTERNALS').get_path(resolve=True) + candidates = mx.findclass(args, logToConsole=False, matcher=lambda s, classname: s == classname or classname.endswith('.' + s) or classname.endswith('$' + s)) + + if len(candidates) > 0: + candidates = mx.select_items(sorted(candidates)) + else: + # mx.findclass can be mistaken, don't give up yet + candidates = args + + run_vm(['-javaagent:' + joljar, '-cp', os.pathsep.join([mx.classpath(), joljar]), "org.openjdk.jol.MainObjectInternals"] + candidates) + +class JVMCIArchiveParticipant: + def __init__(self, dist): + self.dist = dist + + def __opened__(self, arc, srcArc, services): + self.services = services + self.arc = arc + + def __add__(self, arcname, contents): + if arcname.startswith('META-INF/jvmci.providers/'): + provider = arcname[len('META-INF/jvmci.providers/'):] + for service in contents.strip().split(os.linesep): + assert service + self.services.setdefault(service, []).append(provider) + return True + elif arcname.endswith('_OptionDescriptors.class'): + # Need to create service files for the providers of the + # jdk.vm.ci.options.Options service created by + # jdk.vm.ci.options.processor.OptionProcessor. + provider = arcname[:-len('.class'):].replace('/', '.') + self.services.setdefault('jdk.vm.ci.options.OptionDescriptors', []).append(provider) + return False + + def __addsrc__(self, arcname, contents): + return False + + def __closing__(self): + pass + +def _get_openjdk_os(): + # See: common/autoconf/platform.m4 + os = mx.get_os() + if 'darwin' in os: + os = 'macosx' + elif 'linux' in os: + os = 'linux' + elif 'solaris' in os: + os = 'solaris' + elif 'cygwin' in os or 'mingw' in os: + os = 'windows' + return os + +def _get_openjdk_cpu(): + cpu = mx.get_arch() + if cpu == 'amd64': + cpu = 'x86_64' + elif cpu == 'sparcv9': + cpu = 'sparcv9' + return cpu + +def _get_openjdk_os_cpu(): + return _get_openjdk_os() + '-' + _get_openjdk_cpu() + +def _get_jdk_build_dir(debugLevel=None): + """ + Gets the directory into which the JDK is built. This directory contains + the exploded JDK under jdk/ and the JDK image under images/jdk/. + """ + if debugLevel is None: + debugLevel = _vm.debugLevel + name = '{}-{}-{}-{}'.format(_get_openjdk_os_cpu(), 'normal', _vm.jvmVariant, debugLevel) + return join(dirname(_suite.dir), 'build', name) + +_jvmci_bootclasspath_prepends = [] + +def _get_hotspot_build_dir(jvmVariant=None, debugLevel=None): + """ + Gets the directory in which a particular HotSpot configuration is built + (e.g., /build/macosx-x86_64-normal-server-release/hotspot/bsd_amd64_compiler2) + """ + if jvmVariant is None: + jvmVariant = _vm.jvmVariant + + os = mx.get_os() + if os == 'darwin': + os = 'bsd' + arch = mx.get_arch() + buildname = {'client': 'compiler1', 'server': 'compiler2'}.get(jvmVariant, jvmVariant) + + name = '{}_{}_{}'.format(os, arch, buildname) + return join(_get_jdk_build_dir(debugLevel=debugLevel), 'hotspot', name) + +def add_bootclasspath_prepend(dep): + assert isinstance(dep, mx.ClasspathDependency) + _jvmci_bootclasspath_prepends.append(dep) + +class JVMCI9JDKConfig(mx.JDKConfig): + def __init__(self, debugLevel): + self.debugLevel = debugLevel + jdkBuildDir = _get_jdk_build_dir(debugLevel) + jdkDir = join(jdkBuildDir, 'images', 'jdk') if mx.get_opts().use_jdk_image else join(jdkBuildDir, 'jdk') + mx.JDKConfig.__init__(self, jdkDir, tag=_JVMCI_JDK_TAG) + + def parseVmArgs(self, args, addDefaultArgs=True): + args = mx.expand_project_in_args(args, insitu=False) + jacocoArgs = mx_gate.get_jacoco_agent_args() + if jacocoArgs: + args = jacocoArgs + args + + # Support for -G: options + def translateGOption(arg): + if arg.startswith('-G:+'): + if '=' in arg: + mx.abort('Mixing + and = in -G: option specification: ' + arg) + arg = '-Djvmci.option.' + arg[len('-G:+'):] + '=true' + elif arg.startswith('-G:-'): + if '=' in arg: + mx.abort('Mixing - and = in -G: option specification: ' + arg) + arg = '-Djvmci.option.' + arg[len('-G:+'):] + '=false' + elif arg.startswith('-G:'): + arg = '-Djvmci.option.' + arg[len('-G:'):] + return arg + args = map(translateGOption, args) + + args = ['-Xbootclasspath/p:' + dep.classpath_repr() for dep in _jvmci_bootclasspath_prepends] + args + + jvmciModeArgs = _jvmciModes[_vm.jvmciMode] + if jvmciModeArgs: + bcpDeps = [jdkDist.dist() for jdkDist in jdkDeployedDists] + if bcpDeps: + args = ['-Xbootclasspath/p:' + os.pathsep.join([d.classpath_repr() for d in bcpDeps])] + args + + # Set the default JVMCI compiler + for jdkDist in reversed(jdkDeployedDists): + assert isinstance(jdkDist, JvmciJDKDeployedDist), jdkDist + if jdkDist._compilers: + jvmciCompiler = jdkDist._compilers[-1] + args = ['-Djvmci.compiler=' + jvmciCompiler] + args + break + + if '-version' in args: + ignoredArgs = args[args.index('-version') + 1:] + if len(ignoredArgs) > 0: + mx.log("Warning: The following options will be ignored by the vm because they come after the '-version' argument: " + ' '.join(ignoredArgs)) + return self.processArgs(args, addDefaultArgs=addDefaultArgs) + + # Overrides JDKConfig + def run_java(self, args, vm=None, nonZeroIsFatal=True, out=None, err=None, cwd=None, timeout=None, env=None, addDefaultArgs=True): + if vm is None: + vm = 'server' + + args = self.parseVmArgs(args, addDefaultArgs=addDefaultArgs) + + jvmciModeArgs = _jvmciModes[_vm.jvmciMode] + cmd = [self.java] + ['-' + vm] + jvmciModeArgs + args + return mx.run(cmd, nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, cwd=cwd) + +""" +The dict of JVMCI JDKs indexed by debug-level names. +""" +_jvmci_jdks = {} + +def get_jvmci_jdk(debugLevel=None): + """ + Gets the JVMCI JDK corresponding to 'debugLevel'. + """ + if not debugLevel: + debugLevel = _vm.debugLevel + jdk = _jvmci_jdks.get(debugLevel) + if jdk is None: + try: + jdk = JVMCI9JDKConfig(debugLevel) + except mx.JDKConfigException as e: + jdkBuildDir = _get_jdk_build_dir(debugLevel) + msg = 'Error with the JDK built into {}:\n{}\nTry (re)building it with: mx --jdk-debug-level={} make' + if mx.get_opts().use_jdk_image: + msg += ' images' + mx.abort(msg.format(jdkBuildDir, e.message, debugLevel)) + _jvmci_jdks[debugLevel] = jdk + return jdk + +class JVMCIJDKFactory(mx.JDKFactory): + def getJDKConfig(self): + jdk = get_jvmci_jdk(_vm.debugLevel) + return jdk + + def description(self): + return "JVMCI JDK" + +mx.update_commands(_suite, { + 'make': [_runmake, '[args...]', _makehelp], + 'multimake': [_runmultimake, '[options]'], + 'c1visualizer' : [c1visualizer, ''], + 'hsdis': [hsdis, '[att]'], + 'hcfdis': [hcfdis, ''], + 'igv' : [igv, ''], + 'jol' : [jol, ''], + 'vm': [run_vm, '[-options] class [args...]'], +}) + +mx.add_argument('-M', '--jvmci-mode', action='store', choices=sorted(_jvmciModes.viewkeys()), help='the JVM variant type to build/run (default: ' + _vm.jvmciMode + ')') +mx.add_argument('--jdk-jvm-variant', '--vm', action='store', choices=_jdkJvmVariants + sorted(_legacyVms.viewkeys()), help='the JVM variant type to build/run (default: ' + _vm.jvmVariant + ')') +mx.add_argument('--jdk-debug-level', '--vmbuild', action='store', choices=_jdkDebugLevels + sorted(_legacyVmbuilds.viewkeys()), help='the JDK debug level to build/run (default: ' + _vm.debugLevel + ')') +mx.add_argument('-I', '--use-jdk-image', action='store_true', help='build/run JDK image instead of exploded JDK') + +def mx_post_parse_cmd_line(opts): + mx.addJDKFactory(_JVMCI_JDK_TAG, mx.JavaCompliance('9'), JVMCIJDKFactory()) + mx.set_java_command_default_jdk_tag(_JVMCI_JDK_TAG) + + jdkTag = mx.get_jdk_option().tag + + jvmVariant = None + debugLevel = None + jvmciMode = None + + if opts.jdk_jvm_variant is not None: + jvmVariant = opts.jdk_jvm_variant + if jdkTag and jdkTag != _JVMCI_JDK_TAG: + mx.warn('Ignoring "--jdk-jvm-variant" option as "--jdk" tag is not "' + _JVMCI_JDK_TAG + '"') + + if opts.jdk_debug_level is not None: + debugLevel = _translateLegacyDebugLevel(opts.jdk_debug_level) + if jdkTag and jdkTag != _JVMCI_JDK_TAG: + mx.warn('Ignoring "--jdk-debug-level" option as "--jdk" tag is not "' + _JVMCI_JDK_TAG + '"') + + if opts.jvmci_mode is not None: + jvmciMode = opts.jvmci_mode + if jdkTag and jdkTag != _JVMCI_JDK_TAG: + mx.warn('Ignoring "--jvmci-mode" option as "--jdk" tag is not "' + _JVMCI_JDK_TAG + '"') + + _vm.update(jvmVariant, debugLevel, jvmciMode) + + for jdkDist in jdkDeployedDists: + dist = jdkDist.dist() + if isinstance(jdkDist, JvmciJDKDeployedDist): + dist.set_archiveparticipant(JVMCIArchiveParticipant(dist)) diff --git a/hotspot/.mx.jvmci/suite.py b/hotspot/.mx.jvmci/suite.py new file mode 100644 index 00000000000..3fd3a3cddc1 --- /dev/null +++ b/hotspot/.mx.jvmci/suite.py @@ -0,0 +1,358 @@ +suite = { + "mxversion" : "5.5.12", + "name" : "jvmci", + "url" : "http://openjdk.java.net/projects/graal", + "developer" : { + "name" : "Truffle and Graal developers", + "email" : "graal-dev@openjdk.java.net", + "organization" : "Graal", + "organizationUrl" : "http://openjdk.java.net/projects/graal", + }, + "repositories" : { + "lafo-snapshots" : { + "url" : "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", + "licenses" : ["GPLv2-CPE", "UPL"] + }, + }, + + "licenses" : { + "UPL" : { + "name" : "Universal Permissive License, Version 1.0", + "url" : "http://opensource.org/licenses/UPL", + } + }, + + "defaultLicense" : "GPLv2-CPE", + + # This puts mx/ as a sibiling of the JDK build configuration directories + # (e.g., macosx-x86_64-normal-server-release). + "outputRoot" : "../build/mx/hotspot", + + # ------------- Libraries ------------- + + "libraries" : { + + # ------------- Libraries ------------- + + "HCFDIS" : { + "urls" : ["https://lafo.ssw.uni-linz.ac.at/pub/hcfdis-3.jar"], + "sha1" : "a71247c6ddb90aad4abf7c77e501acc60674ef57", + }, + + "C1VISUALIZER_DIST" : { + "urls" : ["https://java.net/downloads/c1visualizer/c1visualizer_2015-07-22.zip"], + "sha1" : "7ead6b2f7ed4643ef4d3343a5562e3d3f39564ac", + }, + + "JOL_INTERNALS" : { + "urls" : ["https://lafo.ssw.uni-linz.ac.at/pub/truffle/jol/jol-internals.jar"], + "sha1" : "508bcd26a4d7c4c44048990c6ea789a3b11a62dc", + }, + + "BATIK" : { + "sha1" : "122b87ca88e41a415cf8b523fd3d03b4325134a3", + "urls" : ["https://lafo.ssw.uni-linz.ac.at/pub/graal-external-deps/batik-all-1.7.jar"], + }, + }, + + "projects" : { + + # ------------- JVMCI:Service ------------- + + "jdk.vm.ci.service" : { + "subDir" : "src/jdk.vm.ci/share/classes", + "sourceDirs" : ["src"], + "javaCompliance" : "1.8", + "workingSets" : "API,JVMCI", + }, + + "jdk.vm.ci.service.processor" : { + "subDir" : "src/jdk.vm.ci/share/classes", + "sourceDirs" : ["src"], + "dependencies" : ["jdk.vm.ci.service"], + "checkstyle" : "jdk.vm.ci.service", + "javaCompliance" : "1.8", + "workingSets" : "JVMCI,Codegen,HotSpot", + }, + + # ------------- JVMCI:API ------------- + + "jdk.vm.ci.common" : { + "subDir" : "src/jdk.vm.ci/share/classes", + "sourceDirs" : ["src"], + "checkstyle" : "jdk.vm.ci.service", + "javaCompliance" : "1.8", + "workingSets" : "API,JVMCI", + }, + + "jdk.vm.ci.meta" : { + "subDir" : "src/jdk.vm.ci/share/classes", + "sourceDirs" : ["src"], + "checkstyle" : "jdk.vm.ci.service", + "javaCompliance" : "1.8", + "workingSets" : "API,JVMCI", + }, + + "jdk.vm.ci.code" : { + "subDir" : "src/jdk.vm.ci/share/classes", + "sourceDirs" : ["src"], + "dependencies" : ["jdk.vm.ci.meta"], + "checkstyle" : "jdk.vm.ci.service", + "javaCompliance" : "1.8", + "workingSets" : "API,JVMCI", + }, + + "jdk.vm.ci.runtime" : { + "subDir" : "src/jdk.vm.ci/share/classes", + "sourceDirs" : ["src"], + "dependencies" : [ + "jdk.vm.ci.code", + ], + "checkstyle" : "jdk.vm.ci.service", + "annotationProcessors" : ["JVMCI_OPTIONS_PROCESSOR"], + "javaCompliance" : "1.8", + "workingSets" : "API,JVMCI", + }, + + "jdk.vm.ci.runtime.test" : { + "subDir" : "test/compiler/jvmci", + "sourceDirs" : ["src"], + "dependencies" : [ + "mx:JUNIT", + "jdk.vm.ci.common", + "jdk.vm.ci.runtime", + ], + "checkstyle" : "jdk.vm.ci.service", + "javaCompliance" : "1.8", + "workingSets" : "API,JVMCI", + }, + + "jdk.vm.ci.inittimer" : { + "subDir" : "src/jdk.vm.ci/share/classes", + "sourceDirs" : ["src"], + "checkstyle" : "jdk.vm.ci.service", + "javaCompliance" : "1.8", + "workingSets" : "JVMCI", + }, + + "jdk.vm.ci.options" : { + "subDir" : "src/jdk.vm.ci/share/classes", + "sourceDirs" : ["src"], + "checkstyle" : "jdk.vm.ci.service", + "dependencies" : ["jdk.vm.ci.inittimer"], + "javaCompliance" : "1.8", + "workingSets" : "JVMCI", + }, + + "jdk.vm.ci.options.processor" : { + "subDir" : "src/jdk.vm.ci/share/classes", + "sourceDirs" : ["src"], + "dependencies" : [ + "jdk.vm.ci.options", + ], + "checkstyle" : "jdk.vm.ci.service", + "javaCompliance" : "1.8", + "workingSets" : "JVMCI,Codegen", + }, + + "jdk.vm.ci.options.test" : { + "subDir" : "test/compiler/jvmci", + "sourceDirs" : ["src"], + "dependencies" : [ + "jdk.vm.ci.options", + "mx:JUNIT", + ], + "checkstyle" : "jdk.vm.ci.service", + "javaCompliance" : "1.8", + "workingSets" : "JVMCI", + }, + + # ------------- JVMCI:HotSpot ------------- + + "jdk.vm.ci.amd64" : { + "subDir" : "src/jdk.vm.ci/share/classes", + "sourceDirs" : ["src"], + "dependencies" : ["jdk.vm.ci.code"], + "checkstyle" : "jdk.vm.ci.service", + "javaCompliance" : "1.8", + "workingSets" : "JVMCI,AMD64", + }, + + "jdk.vm.ci.sparc" : { + "subDir" : "src/jdk.vm.ci/share/classes", + "sourceDirs" : ["src"], + "dependencies" : ["jdk.vm.ci.code"], + "checkstyle" : "jdk.vm.ci.service", + "javaCompliance" : "1.8", + "workingSets" : "JVMCI,SPARC", + }, + + "jdk.vm.ci.hotspot" : { + "subDir" : "src/jdk.vm.ci/share/classes", + "sourceDirs" : ["src"], + "dependencies" : [ + "jdk.vm.ci.options", + "jdk.vm.ci.hotspotvmconfig", + "jdk.vm.ci.common", + "jdk.vm.ci.runtime", + "jdk.vm.ci.service", + ], + "annotationProcessors" : [ + "JVMCI_OPTIONS_PROCESSOR", + ], + "checkstyle" : "jdk.vm.ci.service", + "javaCompliance" : "1.8", + "workingSets" : "JVMCI", + }, + + "jdk.vm.ci.hotspotvmconfig" : { + "subDir" : "src/jdk.vm.ci/share/classes", + "sourceDirs" : ["src"], + "checkstyle" : "jdk.vm.ci.service", + "javaCompliance" : "1.8", + "workingSets" : "JVMCI,HotSpot", + }, + + "jdk.vm.ci.hotspot.amd64" : { + "subDir" : "src/jdk.vm.ci/share/classes", + "sourceDirs" : ["src"], + "dependencies" : [ + "jdk.vm.ci.amd64", + "jdk.vm.ci.hotspot", + ], + "checkstyle" : "jdk.vm.ci.service", + "annotationProcessors" : [ + "JVMCI_SERVICE_PROCESSOR", + ], + "javaCompliance" : "1.8", + "workingSets" : "JVMCI,HotSpot,AMD64", + }, + + "jdk.vm.ci.hotspot.sparc" : { + "subDir" : "src/jdk.vm.ci/share/classes", + "sourceDirs" : ["src"], + "dependencies" : [ + "jdk.vm.ci.sparc", + "jdk.vm.ci.hotspot", + ], + "checkstyle" : "jdk.vm.ci.service", + "annotationProcessors" : [ + "JVMCI_SERVICE_PROCESSOR", + ], + "javaCompliance" : "1.8", + "workingSets" : "JVMCI,HotSpot,SPARC", + }, + + "hotspot" : { + "native" : True, + "class" : "HotSpotProject", + } + }, + + "distributions" : { + + # ------------- Distributions ------------- + + "JVMCI_SERVICE" : { + "subDir" : "src/jdk.vm.ci/share/classes", + "dependencies" : ["jdk.vm.ci.service"], + }, + + "JVMCI_OPTIONS" : { + "subDir" : "src/jdk.vm.ci/share/classes", + "dependencies" : ["jdk.vm.ci.options"], + }, + + "JVMCI_API" : { + "subDir" : "src/jdk.vm.ci/share/classes", + "dependencies" : [ + "jdk.vm.ci.inittimer", + "jdk.vm.ci.runtime", + "jdk.vm.ci.common", + "jdk.vm.ci.amd64", + "jdk.vm.ci.sparc", + ], + "distDependencies" : [ + "JVMCI_OPTIONS", + "JVMCI_SERVICE", + ], + }, + + "JVMCI_HOTSPOTVMCONFIG" : { + "subDir" : "src/jdk.vm.ci/share/classes", + "dependencies" : [ + "jdk.vm.ci.hotspotvmconfig", + ], + }, + + "JVMCI_HOTSPOT" : { + "subDir" : "src/jdk.vm.ci/share/classes", + "dependencies" : [ + "jdk.vm.ci.hotspot.amd64", + "jdk.vm.ci.hotspot.sparc", + ], + "distDependencies" : [ + "JVMCI_HOTSPOTVMCONFIG", + "JVMCI_SERVICE", + "JVMCI_API", + ], + }, + + "JVMCI_TEST" : { + "subDir" : "test/compiler/jvmci", + "dependencies" : [ + "jdk.vm.ci.options.test", + "jdk.vm.ci.runtime.test", + ], + "distDependencies" : [ + "JVMCI_API", + ], + "exclude" : ["mx:JUNIT"], + }, + + "JVMCI_OPTIONS_PROCESSOR" : { + "subDir" : "src/jdk.vm.ci/share/classes", + "dependencies" : ["jdk.vm.ci.options.processor"], + "distDependencies" : [ + "JVMCI_OPTIONS", + ], + }, + + "JVMCI_SERVICE_PROCESSOR" : { + "subDir" : "src/jdk.vm.ci/share/classes", + "dependencies" : ["jdk.vm.ci.service.processor"], + "distDependencies" : [ + "JVMCI_SERVICE", + ], + }, + + # This exists to have a monolithic jvmci.jar file which simplifies + # using the -Xoverride option in JDK9. + "JVMCI" : { + "subDir" : "src/jdk.vm.ci/share/classes", + "overlaps" : [ + "JVMCI_API", + "JVMCI_OPTIONS", + "JVMCI_SERVICE", + "JVMCI_HOTSPOT", + "JVMCI_HOTSPOTVMCONFIG", + "JVMCI_SERVICE_PROCESSOR", + "JVMCI_OPTIONS_PROCESSOR" + ], + "dependencies" : [ + "jdk.vm.ci.options", + "jdk.vm.ci.service", + "jdk.vm.ci.inittimer", + "jdk.vm.ci.runtime", + "jdk.vm.ci.common", + "jdk.vm.ci.amd64", + "jdk.vm.ci.sparc", + "jdk.vm.ci.hotspotvmconfig", + "jdk.vm.ci.hotspot.amd64", + "jdk.vm.ci.hotspot.sparc", + "jdk.vm.ci.options.processor", + "jdk.vm.ci.service.processor" + ], + }, + }, +} diff --git a/hotspot/make/windows/create_obj_files.sh b/hotspot/make/windows/create_obj_files.sh index 1bdf4d8c7a0..a6481549bd6 100644 --- a/hotspot/make/windows/create_obj_files.sh +++ b/hotspot/make/windows/create_obj_files.sh @@ -129,7 +129,7 @@ esac # Special handling of arch model. case "${Platform_arch_model}" in - "x86_32") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} *x86_64*" ;; + "x86_32") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} *x86_64* ${JVMCI_SPECIFIC_FILES}" ;; "x86_64") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} *x86_32*" ;; esac diff --git a/hotspot/make/windows/makefiles/vm.make b/hotspot/make/windows/makefiles/vm.make index 0aaf2cf13ce..0e7b3c13519 100644 --- a/hotspot/make/windows/makefiles/vm.make +++ b/hotspot/make/windows/makefiles/vm.make @@ -45,10 +45,16 @@ CXX_FLAGS=$(CXX_FLAGS) /D "COMPILER1" /D INCLUDE_JVMCI=0 !if "$(Variant)" == "compiler2" CXX_FLAGS=$(CXX_FLAGS) /D "COMPILER2" +!if "$(BUILDARCH)" == "i486" +CXX_FLAGS=$(CXX_FLAGS) /D INCLUDE_JVMCI=0 +!endif !endif !if "$(Variant)" == "tiered" CXX_FLAGS=$(CXX_FLAGS) /D "COMPILER1" /D "COMPILER2" +!if "$(BUILDARCH)" == "i486" +CXX_FLAGS=$(CXX_FLAGS) /D INCLUDE_JVMCI=0 +!endif !endif !if "$(BUILDARCH)" == "i486" diff --git a/hotspot/src/cpu/aarch64/vm/aarch64.ad b/hotspot/src/cpu/aarch64/vm/aarch64.ad index 802db1b24b0..afa30b74491 100644 --- a/hotspot/src/cpu/aarch64/vm/aarch64.ad +++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad @@ -4306,7 +4306,6 @@ encode %{ int disp = $mem$$disp; if (index == -1) { __ prfm(Address(base, disp), PSTL1KEEP); - __ nop(); } else { Register index_reg = as_Register(index); if (disp == 0) { @@ -13844,6 +13843,139 @@ instruct cmpP_narrowOop_imm0_branch(cmpOp cmp, iRegN oop, immP0 zero, label labl ins_pipe(pipe_cmp_branch); %} +// Test bit and Branch + +instruct cmpL_branch_sign(cmpOp cmp, iRegL op1, immL0 op2, label labl, rFlagsReg cr) %{ + match(If cmp (CmpL op1 op2)); + predicate(n->in(1)->as_Bool()->_test._test == BoolTest::lt + || n->in(1)->as_Bool()->_test._test == BoolTest::ge); + effect(USE labl); + + ins_cost(BRANCH_COST); + format %{ "cb$cmp $op1, $labl # long" %} + ins_encode %{ + Label* L = $labl$$label; + Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode; + if (cond == Assembler::LT) + __ tbnz($op1$$Register, 63, *L); + else + __ tbz($op1$$Register, 63, *L); + %} + ins_pipe(pipe_cmp_branch); +%} + +instruct cmpI_branch_sign(cmpOp cmp, iRegIorL2I op1, immI0 op2, label labl, rFlagsReg cr) %{ + match(If cmp (CmpI op1 op2)); + predicate(n->in(1)->as_Bool()->_test._test == BoolTest::lt + || n->in(1)->as_Bool()->_test._test == BoolTest::ge); + effect(USE labl); + + ins_cost(BRANCH_COST); + format %{ "cb$cmp $op1, $labl # int" %} + ins_encode %{ + Label* L = $labl$$label; + Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode; + if (cond == Assembler::LT) + __ tbnz($op1$$Register, 31, *L); + else + __ tbz($op1$$Register, 31, *L); + %} + ins_pipe(pipe_cmp_branch); +%} + +instruct cmpL_branch_bit(cmpOp cmp, iRegL op1, immL op2, immL0 op3, label labl, rFlagsReg cr) %{ + match(If cmp (CmpL (AndL op1 op2) op3)); + predicate((n->in(1)->as_Bool()->_test._test == BoolTest::ne + || n->in(1)->as_Bool()->_test._test == BoolTest::eq) + && is_power_of_2(n->in(2)->in(1)->in(2)->get_long())); + effect(USE labl); + + ins_cost(BRANCH_COST); + format %{ "tb$cmp $op1, $op2, $labl" %} + ins_encode %{ + Label* L = $labl$$label; + Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode; + int bit = exact_log2($op2$$constant); + if (cond == Assembler::EQ) + __ tbz($op1$$Register, bit, *L); + else + __ tbnz($op1$$Register, bit, *L); + %} + ins_pipe(pipe_cmp_branch); +%} + +instruct cmpI_branch_bit(cmpOp cmp, iRegIorL2I op1, immI op2, immI0 op3, label labl, rFlagsReg cr) %{ + match(If cmp (CmpI (AndI op1 op2) op3)); + predicate((n->in(1)->as_Bool()->_test._test == BoolTest::ne + || n->in(1)->as_Bool()->_test._test == BoolTest::eq) + && is_power_of_2(n->in(2)->in(1)->in(2)->get_int())); + effect(USE labl); + + ins_cost(BRANCH_COST); + format %{ "tb$cmp $op1, $op2, $labl" %} + ins_encode %{ + Label* L = $labl$$label; + Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode; + int bit = exact_log2($op2$$constant); + if (cond == Assembler::EQ) + __ tbz($op1$$Register, bit, *L); + else + __ tbnz($op1$$Register, bit, *L); + %} + ins_pipe(pipe_cmp_branch); +%} + +// Test bits + +instruct cmpL_and(cmpOp cmp, iRegL op1, immL op2, immL0 op3, rFlagsReg cr) %{ + match(Set cr (CmpL (AndL op1 op2) op3)); + predicate(Assembler::operand_valid_for_logical_immediate + (/*is_32*/false, n->in(1)->in(2)->get_long())); + + ins_cost(INSN_COST); + format %{ "tst $op1, $op2 # long" %} + ins_encode %{ + __ tst($op1$$Register, $op2$$constant); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct cmpI_and(cmpOp cmp, iRegIorL2I op1, immI op2, immI0 op3, rFlagsReg cr) %{ + match(Set cr (CmpI (AndI op1 op2) op3)); + predicate(Assembler::operand_valid_for_logical_immediate + (/*is_32*/true, n->in(1)->in(2)->get_int())); + + ins_cost(INSN_COST); + format %{ "tst $op1, $op2 # int" %} + ins_encode %{ + __ tstw($op1$$Register, $op2$$constant); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct cmpL_and_reg(cmpOp cmp, iRegL op1, iRegL op2, immL0 op3, rFlagsReg cr) %{ + match(Set cr (CmpL (AndL op1 op2) op3)); + + ins_cost(INSN_COST); + format %{ "tst $op1, $op2 # long" %} + ins_encode %{ + __ tst($op1$$Register, $op2$$Register); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct cmpI_and_reg(cmpOp cmp, iRegIorL2I op1, iRegIorL2I op2, immI0 op3, rFlagsReg cr) %{ + match(Set cr (CmpI (AndI op1 op2) op3)); + + ins_cost(INSN_COST); + format %{ "tstw $op1, $op2 # int" %} + ins_encode %{ + __ tstw($op1$$Register, $op2$$Register); + %} + ins_pipe(ialu_reg_reg); +%} + + // Conditional Far Branch // Conditional Far Branch Unsigned // TODO: fixme @@ -14167,6 +14299,9 @@ instruct string_compare(iRegP_R1 str1, iRegI_R2 cnt1, iRegP_R3 str2, iRegI_R4 cn format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result # KILL $tmp1" %} ins_encode %{ + // Count is in 8-bit bytes; non-Compact chars are 16 bits. + __ asrw($cnt1$$Register, $cnt1$$Register, 1); + __ asrw($cnt2$$Register, $cnt2$$Register, 1); __ string_compare($str1$$Register, $str2$$Register, $cnt1$$Register, $cnt2$$Register, $result$$Register, $tmp1$$Register); @@ -14223,6 +14358,8 @@ instruct string_equals(iRegP_R1 str1, iRegP_R3 str2, iRegI_R4 cnt, format %{ "String Equals $str1,$str2,$cnt -> $result // KILL $tmp" %} ins_encode %{ + // Count is in 8-bit bytes; non-Compact chars are 16 bits. + __ asrw($cnt$$Register, $cnt$$Register, 1); __ string_equals($str1$$Register, $str2$$Register, $cnt$$Register, $result$$Register, $tmp$$Register); diff --git a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp index 563a24a1238..4c4e79b8629 100644 --- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp +++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp @@ -215,8 +215,11 @@ class MacroAssembler: public Assembler { inline void moviw(Register Rd, unsigned imm) { orrw(Rd, zr, imm); } inline void movi(Register Rd, unsigned imm) { orr(Rd, zr, imm); } - inline void tstw(Register Rd, unsigned imm) { andsw(zr, Rd, imm); } - inline void tst(Register Rd, unsigned imm) { ands(zr, Rd, imm); } + inline void tstw(Register Rd, Register Rn) { andsw(zr, Rd, Rn); } + inline void tst(Register Rd, Register Rn) { ands(zr, Rd, Rn); } + + inline void tstw(Register Rd, uint64_t imm) { andsw(zr, Rd, imm); } + inline void tst(Register Rd, uint64_t imm) { ands(zr, Rd, imm); } inline void bfiw(Register Rd, Register Rn, unsigned lsb, unsigned width) { bfmw(Rd, Rn, ((32 - lsb) & 31), (width - 1)); diff --git a/hotspot/src/cpu/aarch64/vm/templateTable_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/templateTable_aarch64.cpp index a19184e3617..1ee5823f7f6 100644 --- a/hotspot/src/cpu/aarch64/vm/templateTable_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/templateTable_aarch64.cpp @@ -386,7 +386,8 @@ void TemplateTable::ldc(bool wide) // get type __ add(r3, r1, tags_offset); - __ ldrb(r3, Address(r0, r3)); + __ lea(r3, Address(r0, r3)); + __ ldarb(r3, r3); // unresolved class - get the resolved class __ cmp(r3, JVM_CONSTANT_UnresolvedClass); @@ -3316,7 +3317,8 @@ void TemplateTable::_new() { // how Constant Pool is updated (see ConstantPool::klass_at_put) const int tags_offset = Array::base_offset_in_bytes(); __ lea(rscratch1, Address(r0, r3, Address::lsl(0))); - __ ldrb(rscratch1, Address(rscratch1, tags_offset)); + __ lea(rscratch1, Address(rscratch1, tags_offset)); + __ ldarb(rscratch1, rscratch1); __ cmp(rscratch1, JVM_CONSTANT_Class); __ br(Assembler::NE, slow_case); @@ -3460,7 +3462,8 @@ void TemplateTable::checkcast() __ get_unsigned_2_byte_index_at_bcp(r19, 1); // r19=index // See if bytecode has already been quicked __ add(rscratch1, r3, Array::base_offset_in_bytes()); - __ ldrb(r1, Address(rscratch1, r19)); + __ lea(r1, Address(rscratch1, r19)); + __ ldarb(r1, r1); __ cmp(r1, JVM_CONSTANT_Class); __ br(Assembler::EQ, quicked); @@ -3514,7 +3517,8 @@ void TemplateTable::instanceof() { __ get_unsigned_2_byte_index_at_bcp(r19, 1); // r19=index // See if bytecode has already been quicked __ add(rscratch1, r3, Array::base_offset_in_bytes()); - __ ldrb(r1, Address(rscratch1, r19)); + __ lea(r1, Address(rscratch1, r19)); + __ ldarb(r1, r1); __ cmp(r1, JVM_CONSTANT_Class); __ br(Assembler::EQ, quicked); diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CompilationResult.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CompilationResult.java index 9967d0cfdae..b8c5ff4843a 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CompilationResult.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CompilationResult.java @@ -552,6 +552,8 @@ public class CompilationResult { */ private final boolean isImmutablePIC; + private boolean closed; + private int entryBCI = -1; private final DataSection dataSection = new DataSection(); @@ -666,6 +668,7 @@ public class CompilationResult { * @param entryBCI the entryBCI to set */ public void setEntryBCI(int entryBCI) { + checkOpen(); this.entryBCI = entryBCI; } @@ -673,11 +676,14 @@ public class CompilationResult { * Sets the assumptions made during compilation. */ public void setAssumptions(Assumption[] assumptions) { + checkOpen(); this.assumptions = assumptions; } /** * Gets the assumptions made during compilation. + * + * The caller must not modify the contents of the returned array. */ public Assumption[] getAssumptions() { return assumptions; @@ -690,6 +696,7 @@ public class CompilationResult { * @param inlinedMethods the methods inlined during compilation */ public void setMethods(ResolvedJavaMethod rootMethod, Collection inlinedMethods) { + checkOpen(); assert rootMethod != null; assert inlinedMethods != null; if (inlinedMethods.contains(rootMethod)) { @@ -717,6 +724,8 @@ public class CompilationResult { /** * Gets the methods whose bytecodes were used as input to the compilation. * + * The caller must not modify the contents of the returned array. + * * @return {@code null} if the compilation did not record method dependencies otherwise the * methods whose bytecodes were used as input to the compilation with the first element * being the root method of the compilation @@ -726,6 +735,7 @@ public class CompilationResult { } public void setBytecodeSize(int bytecodeSize) { + checkOpen(); this.bytecodeSize = bytecodeSize; } @@ -755,6 +765,7 @@ public class CompilationResult { * @param size the size of the frame in bytes */ public void setTotalFrameSize(int size) { + checkOpen(); totalFrameSize = size; } @@ -765,6 +776,7 @@ public class CompilationResult { * @param size the size of the machine code */ public void setTargetCode(byte[] code, int size) { + checkOpen(); targetCode = code; targetCodeSize = size; } @@ -778,6 +790,7 @@ public class CompilationResult { * @param ref The reference that should be inserted in the code. */ public void recordDataPatch(int codePos, Reference ref) { + checkOpen(); assert codePos >= 0 && ref != null; dataPatches.add(new DataPatch(codePos, ref)); } @@ -814,6 +827,7 @@ public class CompilationResult { * @param direct specifies if this is a {@linkplain Call#direct direct} call */ public void recordCall(int codePos, int size, InvokeTarget target, DebugInfo debugInfo, boolean direct) { + checkOpen(); final Call call = new Call(target, codePos, size, direct, debugInfo); addInfopoint(call); } @@ -825,6 +839,7 @@ public class CompilationResult { * @param handlerPos the position of the handler */ public void recordExceptionHandler(int codePos, int handlerPos) { + checkOpen(); assert validateExceptionHandlerAdd(codePos, handlerPos) : String.format("Duplicate exception handler for pc 0x%x handlerPos 0x%x", codePos, handlerPos); exceptionHandlers.add(new ExceptionHandler(codePos, handlerPos)); } @@ -870,31 +885,12 @@ public class CompilationResult { * Records a custom infopoint in the code section. * * Compiler implementations can use this method to record non-standard infopoints, which are not - * handled by the dedicated methods like {@link #recordCall}. + * handled by dedicated methods like {@link #recordCall}. * * @param infopoint the infopoint to record, usually a derived class from {@link Infopoint} */ public void addInfopoint(Infopoint infopoint) { - // The infopoints list must always be sorted - if (!infopoints.isEmpty()) { - Infopoint previousInfopoint = infopoints.get(infopoints.size() - 1); - if (previousInfopoint.pcOffset > infopoint.pcOffset) { - // This re-sorting should be very rare - Collections.sort(infopoints); - previousInfopoint = infopoints.get(infopoints.size() - 1); - } - if (previousInfopoint.pcOffset == infopoint.pcOffset) { - if (infopoint.reason.canBeOmitted()) { - return; - } - if (previousInfopoint.reason.canBeOmitted()) { - Infopoint removed = infopoints.remove(infopoints.size() - 1); - assert removed == previousInfopoint; - } else { - throw new RuntimeException("Infopoints that can not be omited should have distinct PCs"); - } - } - } + checkOpen(); infopoints.add(infopoint); } @@ -905,6 +901,7 @@ public class CompilationResult { * @param markId the identifier for this mark */ public Mark recordMark(int codePos, Object markId) { + checkOpen(); Mark mark = new Mark(codePos, markId); marks.add(mark); return mark; @@ -924,6 +921,7 @@ public class CompilationResult { * @param offset */ public void setCustomStackAreaOffset(int offset) { + checkOpen(); customStackAreaOffset = offset; } @@ -952,6 +950,7 @@ public class CompilationResult { } public void addAnnotation(CodeAnnotation annotation) { + checkOpen(); assert annotation != null; if (annotations == null) { annotations = new ArrayList<>(); @@ -1034,6 +1033,7 @@ public class CompilationResult { } public void setHasUnsafeAccess(boolean hasUnsafeAccess) { + checkOpen(); this.hasUnsafeAccess = hasUnsafeAccess; } @@ -1041,8 +1041,14 @@ public class CompilationResult { return hasUnsafeAccess; } - public void reset() { - hasUnsafeAccess = false; + /** + * Clears the information in this object pertaining to generating code. That is, the + * {@linkplain #getMarks() marks}, {@linkplain #getInfopoints() infopoints}, + * {@linkplain #getExceptionHandlers() exception handlers}, {@linkplain #getDataPatches() data + * patches} and {@linkplain #getAnnotations() annotations} recorded in this object are cleared. + */ + public void resetForEmittingCode() { + checkOpen(); infopoints.clear(); dataPatches.clear(); exceptionHandlers.clear(); @@ -1052,4 +1058,21 @@ public class CompilationResult { annotations.clear(); } } + + private void checkOpen() { + if (closed) { + throw new IllegalStateException(); + } + } + + /** + * Closes this compilation result to future updates. + */ + public void close() { + if (closed) { + throw new IllegalStateException("Cannot re-close compilation result " + this); + } + dataSection.close(); + closed = true; + } } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/DataSection.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/DataSection.java index 295d4425ac1..c397cd1c0fb 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/DataSection.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/DataSection.java @@ -141,7 +141,7 @@ public final class DataSection implements Iterable { private final ArrayList dataItems = new ArrayList<>(); - private boolean finalLayout; + private boolean closed; private int sectionAlignment; private int sectionSize; @@ -163,7 +163,7 @@ public final class DataSection implements Iterable { } if (obj instanceof DataSection) { DataSection that = (DataSection) obj; - if (this.finalLayout == that.finalLayout && this.sectionAlignment == that.sectionAlignment && this.sectionSize == that.sectionSize && Objects.equals(this.dataItems, that.dataItems)) { + if (this.closed == that.closed && this.sectionAlignment == that.sectionAlignment && this.sectionSize == that.sectionSize && Objects.equals(this.dataItems, that.dataItems)) { return true; } } @@ -171,14 +171,14 @@ public final class DataSection implements Iterable { } /** - * Insert a {@link Data} item into the data section. If the item is already in the data section, - * the same {@link DataSectionReference} is returned. + * Inserts a {@link Data} item into the data section. If the item is already in the data + * section, the same {@link DataSectionReference} is returned. * * @param data the {@link Data} item to be inserted * @return a unique {@link DataSectionReference} identifying the {@link Data} item */ public DataSectionReference insertData(Data data) { - assert !finalLayout; + checkOpen(); synchronized (data) { if (data.ref == null) { data.ref = new DataSectionReference(); @@ -193,7 +193,8 @@ public final class DataSection implements Iterable { * {@link DataSection}, and empties the other section. */ public void addAll(DataSection other) { - assert !finalLayout && !other.finalLayout; + checkOpen(); + other.checkOpen(); for (Data data : other.dataItems) { assert data.ref != null; @@ -203,12 +204,20 @@ public final class DataSection implements Iterable { } /** - * Compute the layout of the data section. This can be called only once, and after it has been - * called, the data section can no longer be modified. + * Determines if this object has been {@link #close() closed}. */ - public void finalizeLayout() { - assert !finalLayout; - finalLayout = true; + public boolean closed() { + return closed; + } + + /** + * Computes the layout of the data section and closes this object to further updates. + * + * This must be called exactly once. + */ + void close() { + checkOpen(); + closed = true; // simple heuristic: put items with larger alignment requirement first dataItems.sort((a, b) -> a.alignment - b.alignment); @@ -227,37 +236,38 @@ public final class DataSection implements Iterable { sectionSize = position; } - public boolean isFinalized() { - return finalLayout; - } - /** - * Get the size of the data section. Can only be called after {@link #finalizeLayout}. + * Gets the size of the data section. + * + * This must only be called once this object has been {@linkplain #closed() closed}. */ public int getSectionSize() { - assert finalLayout; + checkClosed(); return sectionSize; } /** - * Get the minimum alignment requirement of the data section. Can only be called after - * {@link #finalizeLayout}. + * Gets the minimum alignment requirement of the data section. + * + * This must only be called once this object has been {@linkplain #closed() closed}. */ public int getSectionAlignment() { - assert finalLayout; + checkClosed(); return sectionAlignment; } /** - * Build the data section. Can only be called after {@link #finalizeLayout}. + * Builds the data section into a given buffer. * - * @param buffer The {@link ByteBuffer} where the data section should be built. The buffer must + * This must only be called once this object has been {@linkplain #closed() closed}. + * + * @param buffer the {@link ByteBuffer} where the data section should be built. The buffer must * hold at least {@link #getSectionSize()} bytes. - * @param patch A {@link Consumer} to receive {@link DataPatch data patches} for relocations in - * the data section. + * @param patch a {@link Consumer} to receive {@link DataPatch data patches} for relocations in + * the data section */ public void buildDataSection(ByteBuffer buffer, Consumer patch) { - assert finalLayout; + checkClosed(); for (Data d : dataItems) { buffer.position(d.ref.getOffset()); d.builder.emit(buffer, patch); @@ -300,8 +310,20 @@ public final class DataSection implements Iterable { return ((position + alignment - 1) / alignment) * alignment; } + private void checkClosed() { + if (!closed) { + throw new IllegalStateException(); + } + } + + private void checkOpen() { + if (closed) { + throw new IllegalStateException(); + } + } + public void clear() { - assert !finalLayout; + checkOpen(); this.dataItems.clear(); this.sectionAlignment = 0; this.sectionSize = 0; diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/InfopointReason.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/InfopointReason.java index 026bb5bd412..317ed96ce7e 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/InfopointReason.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/InfopointReason.java @@ -26,22 +26,12 @@ package jdk.vm.ci.code; * A reason for infopoint insertion. */ public enum InfopointReason { - UNKNOWN(false), - SAFEPOINT(false), - CALL(false), - IMPLICIT_EXCEPTION(false), - METHOD_START(true), - METHOD_END(true), - LINE_NUMBER(true), - METASPACE_ACCESS(true); - private InfopointReason(boolean canBeOmitted) { - this.canBeOmitted = canBeOmitted; - } - - private final boolean canBeOmitted; - - public boolean canBeOmitted() { - return canBeOmitted; - } + SAFEPOINT, + CALL, + IMPLICIT_EXCEPTION, + METASPACE_ACCESS, + METHOD_START, + METHOD_END, + BYTECODE_POSITION; } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledCode.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledCode.java index a2ec65fbafc..27236ad771d 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledCode.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledCode.java @@ -24,9 +24,12 @@ package jdk.vm.ci.hotspot; import java.nio.ByteBuffer; import java.nio.ByteOrder; +import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; +import java.util.EnumMap; import java.util.List; +import java.util.Map; import java.util.stream.Stream; import java.util.stream.Stream.Builder; @@ -41,6 +44,8 @@ import jdk.vm.ci.code.CompilationResult.JumpTable; import jdk.vm.ci.code.CompilationResult.Mark; import jdk.vm.ci.code.CompilationResult.Site; import jdk.vm.ci.code.DataSection; +import jdk.vm.ci.code.InfopointReason; +import jdk.vm.ci.common.JVMCIError; import jdk.vm.ci.meta.Assumptions.Assumption; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -118,7 +123,6 @@ public class HotSpotCompiledCode { targetCodeSize = compResult.getTargetCodeSize(); DataSection data = compResult.getDataSection(); - data.finalizeLayout(); dataSection = new byte[data.getSectionSize()]; ByteBuffer buffer = ByteBuffer.wrap(dataSection).order(ByteOrder.nativeOrder()); @@ -155,14 +159,75 @@ public class HotSpotCompiledCode { static class SiteComparator implements Comparator { + /** + * Defines an order for sorting {@link Infopoint}s based on their + * {@linkplain Infopoint#reason reasons}. This is used to choose which infopoint to preserve + * when multiple infopoints collide on the same PC offset. A negative order value implies a + * non-optional infopoint (i.e., must be preserved). Non-optional infopoints must not + * collide. + */ + static final Map HOTSPOT_INFOPOINT_SORT_ORDER = new EnumMap<>(InfopointReason.class); + static { + HOTSPOT_INFOPOINT_SORT_ORDER.put(InfopointReason.SAFEPOINT, -4); + HOTSPOT_INFOPOINT_SORT_ORDER.put(InfopointReason.CALL, -3); + HOTSPOT_INFOPOINT_SORT_ORDER.put(InfopointReason.IMPLICIT_EXCEPTION, -2); + HOTSPOT_INFOPOINT_SORT_ORDER.put(InfopointReason.METASPACE_ACCESS, 1); + HOTSPOT_INFOPOINT_SORT_ORDER.put(InfopointReason.METHOD_START, 2); + HOTSPOT_INFOPOINT_SORT_ORDER.put(InfopointReason.METHOD_END, 3); + HOTSPOT_INFOPOINT_SORT_ORDER.put(InfopointReason.BYTECODE_POSITION, 4); + } + + static int ord(Infopoint info) { + return HOTSPOT_INFOPOINT_SORT_ORDER.get(info.reason); + } + + static int checkCollision(Infopoint i1, Infopoint i2) { + int o1 = ord(i1); + int o2 = ord(i2); + if (o1 < 0 && o2 < 0) { + throw new JVMCIError("Non-optional infopoints cannot collide: %s and %s", i1, i2); + } + return o1 - o2; + } + + /** + * Records whether any two {@link Infopoint}s had the same {@link Infopoint#pcOffset}. + */ + boolean sawCollidingInfopoints; + public int compare(Site s1, Site s2) { - if (s1.pcOffset == s2.pcOffset && (s1 instanceof Mark ^ s2 instanceof Mark)) { - return s1 instanceof Mark ? -1 : 1; + if (s1.pcOffset == s2.pcOffset) { + // Marks must come first since patching a call site + // may need to know the mark denoting the call type + // (see uses of CodeInstaller::_next_call_type). + boolean s1IsMark = s1 instanceof Mark; + boolean s2IsMark = s2 instanceof Mark; + if (s1IsMark != s2IsMark) { + return s1IsMark ? -1 : 1; + } + + // Infopoints must group together so put them after + // other Site types. + boolean s1IsInfopoint = s1 instanceof Infopoint; + boolean s2IsInfopoint = s2 instanceof Infopoint; + if (s1IsInfopoint != s2IsInfopoint) { + return s1IsInfopoint ? 1 : -1; + } + + if (s1IsInfopoint) { + sawCollidingInfopoints = true; + return checkCollision((Infopoint) s1, (Infopoint) s2); + } } return s1.pcOffset - s2.pcOffset; } } + /** + * HotSpot expects sites to be presented in ascending order of PC (see + * {@code DebugInformationRecorder::add_new_pc_offset}). In addition, it expects + * {@link Infopoint} PCs to be unique. + */ private static Site[] getSortedSites(CompilationResult target) { List[] lists = new List[]{target.getInfopoints(), target.getDataPatches(), target.getMarks()}; int count = 0; @@ -176,7 +241,27 @@ public class HotSpotCompiledCode { result[pos++] = (Site) elem; } } - Arrays.sort(result, new SiteComparator()); + SiteComparator c = new SiteComparator(); + Arrays.sort(result, c); + if (c.sawCollidingInfopoints) { + Infopoint lastInfopoint = null; + List copy = new ArrayList<>(count); + for (int i = 0; i < count; i++) { + if (result[i] instanceof Infopoint) { + Infopoint info = (Infopoint) result[i]; + if (lastInfopoint == null || lastInfopoint.pcOffset != info.pcOffset) { + lastInfopoint = info; + copy.add(info); + } else { + // Omit this colliding infopoint + assert lastInfopoint.reason.compareTo(info.reason) <= 0; + } + } else { + copy.add(result[i]); + } + } + result = copy.toArray(new Site[copy.size()]); + } return result; } diff --git a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp index c3638147e13..d6b687dc01c 100644 --- a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp +++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp @@ -36,7 +36,7 @@ void LIR_Assembler::patching_epilog(PatchingStub* patch, LIR_PatchCode patch_cod // We must have enough patching space so that call can be inserted. // We cannot use fat nops here, since the concurrent code rewrite may transiently // create the illegal instruction sequence. - while ((intx) _masm->pc() - (intx) patch->pc_start() < NativeCall::instruction_size) { + while ((intx) _masm->pc() - (intx) patch->pc_start() < NativeGeneralJump::instruction_size) { _masm->nop(); } patch->install(_masm, patch_code, obj, info); diff --git a/hotspot/src/share/vm/c1/c1_Runtime1.cpp b/hotspot/src/share/vm/c1/c1_Runtime1.cpp index cf6099d0d65..faff84dcbe7 100644 --- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp +++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp @@ -1163,7 +1163,7 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* thread, Runtime1::StubID stub_i } #endif - for (int i = NativeCall::instruction_size; i < *byte_count; i++) { + for (int i = NativeGeneralJump::instruction_size; i < *byte_count; i++) { address ptr = copy_buff + i; int a_byte = (*ptr) & 0xFF; address dst = instr_pc + i; diff --git a/hotspot/src/share/vm/code/debugInfoRec.cpp b/hotspot/src/share/vm/code/debugInfoRec.cpp index e82d9801d12..36c35a92f55 100644 --- a/hotspot/src/share/vm/code/debugInfoRec.cpp +++ b/hotspot/src/share/vm/code/debugInfoRec.cpp @@ -33,7 +33,7 @@ // We keep track of these chunks in order to detect // repetition and enable sharing. class DIR_Chunk { - friend class DebugInformationRecorder; +private: int _offset; // location in the stream of this scope int _length; // number of bytes in the stream int _hash; // hash of stream bytes (for quicker reuse) @@ -41,6 +41,9 @@ class DIR_Chunk { DebugInformationRecorder* _DIR; #endif +public: + int offset() { return _offset; } + void* operator new(size_t ignore, DebugInformationRecorder* dir) throw() { assert(ignore == sizeof(DIR_Chunk), ""); if (dir->_next_chunk >= dir->_next_chunk_limit) { @@ -284,7 +287,7 @@ int DebugInformationRecorder::find_sharable_decode_offset(int stream_offset) { NOT_PRODUCT(++dir_stats.chunks_shared); assert(ns+1 == _next_chunk, ""); _next_chunk = ns; - return match->_offset; + return match->offset(); } else { // Inserted this chunk, so nothing to do return serialized_null; @@ -296,7 +299,7 @@ int DebugInformationRecorder::find_sharable_decode_offset(int stream_offset) { NOT_PRODUCT(++dir_stats.chunks_reshared); assert(ns+1 == _next_chunk, ""); _next_chunk = ns; - return ms->_offset; + return ms->offset(); } // Look in recently encountered scopes next: @@ -311,7 +314,7 @@ int DebugInformationRecorder::find_sharable_decode_offset(int stream_offset) { _shared_chunks->append(ms); assert(ns+1 == _next_chunk, ""); _next_chunk = ns; - return ms->_offset; + return ms->offset(); } // No match. Add this guy to the list, in hopes of future shares. diff --git a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp index df84301f5bf..7adb8e3fdfb 100644 --- a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp +++ b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp @@ -727,10 +727,9 @@ JVMCIEnv::CodeInstallResult CodeInstaller::initialize_buffer(CodeBuffer& buffer, if (InfopointReason::SAFEPOINT() == reason || InfopointReason::CALL() == reason || InfopointReason::IMPLICIT_EXCEPTION() == reason) { TRACE_jvmci_4("safepoint at %i", pc_offset); site_Safepoint(buffer, pc_offset, site, CHECK_OK); - } else if (InfopointReason::METHOD_START() == reason || InfopointReason::METHOD_END() == reason || InfopointReason::LINE_NUMBER() == reason) { - site_Infopoint(buffer, pc_offset, site, CHECK_OK); } else { - JVMCI_ERROR_OK("unknown infopoint reason at %i", pc_offset); + TRACE_jvmci_4("infopoint at %i", pc_offset); + site_Infopoint(buffer, pc_offset, site, CHECK_OK); } } else if (site->is_a(CompilationResult_DataPatch::klass())) { TRACE_jvmci_4("datapatch at %i", pc_offset); @@ -868,25 +867,33 @@ GrowableArray* CodeInstaller::record_virtual_objects(Handle debug_i return objects; } -void CodeInstaller::record_scope(jint pc_offset, Handle debug_info, TRAPS) { +void CodeInstaller::record_scope(jint pc_offset, Handle debug_info, ScopeMode scope_mode, TRAPS) { Handle position = DebugInfo::bytecodePosition(debug_info); if (position.is_null()) { // Stubs do not record scope info, just oop maps return; } - GrowableArray* objectMapping = record_virtual_objects(debug_info, CHECK); - record_scope(pc_offset, position, objectMapping, CHECK); + GrowableArray* objectMapping; + if (scope_mode == CodeInstaller::FullFrame) { + objectMapping = record_virtual_objects(debug_info, CHECK); + } else { + objectMapping = NULL; + } + record_scope(pc_offset, position, scope_mode, objectMapping, CHECK); } -void CodeInstaller::record_scope(jint pc_offset, Handle position, GrowableArray* objects, TRAPS) { +void CodeInstaller::record_scope(jint pc_offset, Handle position, ScopeMode scope_mode, GrowableArray* objects, TRAPS) { Handle frame; - if (position->is_a(BytecodeFrame::klass())) { + if (scope_mode == CodeInstaller::FullFrame) { + if (!position->is_a(BytecodeFrame::klass())) { + JVMCI_ERROR("Full frame expected for debug info at %i", pc_offset); + } frame = position; } Handle caller_frame = BytecodePosition::caller(position); if (caller_frame.not_null()) { - record_scope(pc_offset, caller_frame, objects, CHECK); + record_scope(pc_offset, caller_frame, scope_mode, objects, CHECK); } Handle hotspot_method = BytecodePosition::method(position); @@ -990,7 +997,7 @@ void CodeInstaller::site_Safepoint(CodeBuffer& buffer, jint pc_offset, Handle si // jint next_pc_offset = Assembler::locate_next_instruction(instruction) - _instructions->start(); OopMap *map = create_oop_map(debug_info, CHECK); _debug_recorder->add_safepoint(pc_offset, map); - record_scope(pc_offset, debug_info, CHECK); + record_scope(pc_offset, debug_info, CodeInstaller::FullFrame, CHECK); _debug_recorder->end_safepoint(pc_offset); } @@ -1000,8 +1007,12 @@ void CodeInstaller::site_Infopoint(CodeBuffer& buffer, jint pc_offset, Handle si JVMCI_ERROR("debug info expected at infopoint at %i", pc_offset); } + // We'd like to check that pc_offset is greater than the + // last pc recorded with _debug_recorder (raising an exception if not) + // but DebugInformationRecorder doesn't have sufficient public API. + _debug_recorder->add_non_safepoint(pc_offset); - record_scope(pc_offset, debug_info, CHECK); + record_scope(pc_offset, debug_info, CodeInstaller::BytecodePosition, CHECK); _debug_recorder->end_non_safepoint(pc_offset); } @@ -1028,7 +1039,7 @@ void CodeInstaller::site_Call(CodeBuffer& buffer, jint pc_offset, Handle site, T if (debug_info.not_null()) { OopMap *map = create_oop_map(debug_info, CHECK); _debug_recorder->add_safepoint(next_pc_offset, map); - record_scope(next_pc_offset, debug_info, CHECK); + record_scope(next_pc_offset, debug_info, CodeInstaller::FullFrame, CHECK); } if (foreign_call.not_null()) { diff --git a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.hpp b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.hpp index d2e40c86338..394d263f668 100644 --- a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.hpp +++ b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.hpp @@ -219,8 +219,18 @@ protected: OopMap* create_oop_map(Handle debug_info, TRAPS); - void record_scope(jint pc_offset, Handle debug_info, TRAPS); - void record_scope(jint pc_offset, Handle code_pos, GrowableArray* objects, TRAPS); + /** + * Specifies the level of detail to record for a scope. + */ + enum ScopeMode { + // Only record a method and BCI + BytecodePosition, + // Record a method, bci and JVM frame state + FullFrame + }; + + void record_scope(jint pc_offset, Handle debug_info, ScopeMode scope_mode, TRAPS); + void record_scope(jint pc_offset, Handle position, ScopeMode scope_mode, GrowableArray* objects, TRAPS); void record_object_value(ObjectValue* sv, Handle value, GrowableArray* objects, TRAPS); GrowableArray* record_virtual_objects(Handle debug_info, TRAPS); diff --git a/hotspot/src/share/vm/jvmci/jvmciJavaClasses.hpp b/hotspot/src/share/vm/jvmci/jvmciJavaClasses.hpp index cf26827be8f..a49eda73d4d 100644 --- a/hotspot/src/share/vm/jvmci/jvmciJavaClasses.hpp +++ b/hotspot/src/share/vm/jvmci/jvmciJavaClasses.hpp @@ -148,14 +148,9 @@ class JVMCIJavaClasses : AllStatic { int_field(CompilationResult_DataSectionReference, offset) \ end_class \ start_class(InfopointReason) \ - static_oop_field(InfopointReason, UNKNOWN, "Ljdk/vm/ci/code/InfopointReason;") \ static_oop_field(InfopointReason, SAFEPOINT, "Ljdk/vm/ci/code/InfopointReason;") \ static_oop_field(InfopointReason, CALL, "Ljdk/vm/ci/code/InfopointReason;") \ static_oop_field(InfopointReason, IMPLICIT_EXCEPTION, "Ljdk/vm/ci/code/InfopointReason;") \ - static_oop_field(InfopointReason, METHOD_START, "Ljdk/vm/ci/code/InfopointReason;") \ - static_oop_field(InfopointReason, METHOD_END, "Ljdk/vm/ci/code/InfopointReason;") \ - static_oop_field(InfopointReason, LINE_NUMBER, "Ljdk/vm/ci/code/InfopointReason;") \ - static_oop_field(InfopointReason, METASPACE_ACCESS, "Ljdk/vm/ci/code/InfopointReason;") \ end_class \ start_class(CompilationResult_Infopoint) \ oop_field(CompilationResult_Infopoint, debugInfo, "Ljdk/vm/ci/code/DebugInfo;") \ diff --git a/hotspot/src/share/vm/opto/c2_globals.hpp b/hotspot/src/share/vm/opto/c2_globals.hpp index ba3a535111d..0001104c001 100644 --- a/hotspot/src/share/vm/opto/c2_globals.hpp +++ b/hotspot/src/share/vm/opto/c2_globals.hpp @@ -744,7 +744,10 @@ range(0, max_intx) \ \ develop(bool, StressArrayCopyMacroNode, false, \ - "Perform ArrayCopy load/store replacement during IGVN only") + "Perform ArrayCopy load/store replacement during IGVN only") \ + \ + develop(bool, RenumberLiveNodes, true, \ + "Renumber live nodes") \ C2_FLAGS(DECLARE_DEVELOPER_FLAG, \ DECLARE_PD_DEVELOPER_FLAG, \ diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp index c96b6532a83..474aee8d8ea 100644 --- a/hotspot/src/share/vm/opto/compile.cpp +++ b/hotspot/src/share/vm/opto/compile.cpp @@ -2156,6 +2156,20 @@ void Compile::Optimize() { // so keep only the actual candidates for optimizations. cleanup_expensive_nodes(igvn); + if (!failing() && RenumberLiveNodes && live_nodes() + NodeLimitFudgeFactor < unique()) { + Compile::TracePhase tp("", &timers[_t_renumberLive]); + initial_gvn()->replace_with(&igvn); + for_igvn()->clear(); + Unique_Node_List new_worklist(C->comp_arena()); + { + ResourceMark rm; + PhaseRenumberLive prl = PhaseRenumberLive(initial_gvn(), for_igvn(), &new_worklist); + } + set_for_igvn(&new_worklist); + igvn = PhaseIterGVN(initial_gvn()); + igvn.optimize(); + } + // Perform escape analysis if (_do_escape_analysis && ConnectionGraph::has_candidates(this)) { if (has_loops()) { diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index 749c4680b23..ff068a7fd55 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -152,6 +152,8 @@ class LibraryCallKit : public GraphKit { Node* generate_limit_guard(Node* offset, Node* subseq_length, Node* array_length, RegionNode* region); + void generate_string_range_check(Node* array, Node* offset, + Node* length, bool char_count); Node* generate_current_thread(Node* &tls_output); Node* load_mirror_from_klass(Node* klass); Node* load_klass_from_mirror_common(Node* mirror, bool never_see_null, @@ -204,6 +206,8 @@ class LibraryCallKit : public GraphKit { bool inline_string_compareTo(StrIntrinsicNode::ArgEnc ae); bool inline_string_indexOf(StrIntrinsicNode::ArgEnc ae); bool inline_string_indexOfI(StrIntrinsicNode::ArgEnc ae); + Node* make_indexOf_node(Node* src_start, Node* src_count, Node* tgt_start, Node* tgt_count, + RegionNode* region, Node* phi, StrIntrinsicNode::ArgEnc ae); bool inline_string_indexOfChar(); bool inline_string_equals(StrIntrinsicNode::ArgEnc ae); bool inline_string_toBytesU(); @@ -897,6 +901,31 @@ inline Node* LibraryCallKit::generate_limit_guard(Node* offset, return is_over; } +// Emit range checks for the given String.value byte array +void LibraryCallKit::generate_string_range_check(Node* array, Node* offset, Node* count, bool char_count) { + if (stopped()) { + return; // already stopped + } + RegionNode* bailout = new RegionNode(1); + record_for_igvn(bailout); + if (char_count) { + // Convert char count to byte count + count = _gvn.transform(new LShiftINode(count, intcon(1))); + } + + // Offset and count must not be negative + generate_negative_guard(offset, bailout); + generate_negative_guard(count, bailout); + // Offset + count must not exceed length of array + generate_limit_guard(offset, count, load_array_length(array), bailout); + + if (bailout->req() > 1) { + PreserveJVMState pjvms(this); + set_control(_gvn.transform(bailout)); + uncommon_trap(Deoptimization::Reason_intrinsic, + Deoptimization::Action_maybe_recompile); + } +} //--------------------------generate_current_thread-------------------- Node* LibraryCallKit::generate_current_thread(Node* &tls_output) { @@ -1016,7 +1045,9 @@ bool LibraryCallKit::inline_array_equals(StrIntrinsicNode::ArgEnc ae) { //------------------------------inline_hasNegatives------------------------------ bool LibraryCallKit::inline_hasNegatives() { - if (too_many_traps(Deoptimization::Reason_intrinsic)) return false; + if (too_many_traps(Deoptimization::Reason_intrinsic)) { + return false; + } assert(callee()->signature()->size() == 3, "hasNegatives has 3 parameters"); // no receiver since it is static method @@ -1024,26 +1055,14 @@ bool LibraryCallKit::inline_hasNegatives() { Node* offset = argument(1); Node* len = argument(2); - RegionNode* bailout = new RegionNode(1); - record_for_igvn(bailout); - - // offset must not be negative. - generate_negative_guard(offset, bailout); - - // offset + length must not exceed length of ba. - generate_limit_guard(offset, len, load_array_length(ba), bailout); - - if (bailout->req() > 1) { - PreserveJVMState pjvms(this); - set_control(_gvn.transform(bailout)); - uncommon_trap(Deoptimization::Reason_intrinsic, - Deoptimization::Action_maybe_recompile); - } - if (!stopped()) { - Node* ba_start = array_element_address(ba, offset, T_BYTE); - Node* result = new HasNegativesNode(control(), memory(TypeAryPtr::BYTES), ba_start, len); - set_result(_gvn.transform(result)); + // Range checks + generate_string_range_check(ba, offset, len, false); + if (stopped()) { + return true; } + Node* ba_start = array_element_address(ba, offset, T_BYTE); + Node* result = new HasNegativesNode(control(), memory(TypeAryPtr::BYTES), ba_start, len); + set_result(_gvn.transform(result)); return true; } @@ -1124,30 +1143,10 @@ bool LibraryCallKit::inline_string_indexOf(StrIntrinsicNode::ArgEnc ae) { tgt_count = _gvn.transform(new RShiftINode(tgt_count, intcon(1))); } - // Check for substr count > string count - Node* cmp = _gvn.transform(new CmpINode(tgt_count, src_count)); - Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::gt)); - Node* if_gt = generate_slow_guard(bol, NULL); - if (if_gt != NULL) { - result_phi->init_req(2, intcon(-1)); - result_rgn->init_req(2, if_gt); - } - - if (!stopped()) { - // Check for substr count == 0 - cmp = _gvn.transform(new CmpINode(tgt_count, intcon(0))); - bol = _gvn.transform(new BoolNode(cmp, BoolTest::eq)); - Node* if_zero = generate_slow_guard(bol, NULL); - if (if_zero != NULL) { - result_phi->init_req(3, intcon(0)); - result_rgn->init_req(3, if_zero); - } - } - - if (!stopped()) { - Node* result = make_string_method_node(Op_StrIndexOf, src_start, src_count, tgt_start, tgt_count, ae); - result_phi->init_req(1, result); - result_rgn->init_req(1, control()); + Node* result = make_indexOf_node(src_start, src_count, tgt_start, tgt_count, result_rgn, result_phi, ae); + if (result != NULL) { + result_phi->init_req(3, result); + result_rgn->init_req(3, control()); } set_control(_gvn.transform(result_rgn)); record_for_igvn(result_rgn); @@ -1158,44 +1157,53 @@ bool LibraryCallKit::inline_string_indexOf(StrIntrinsicNode::ArgEnc ae) { //-----------------------------inline_string_indexOf----------------------- bool LibraryCallKit::inline_string_indexOfI(StrIntrinsicNode::ArgEnc ae) { + if (too_many_traps(Deoptimization::Reason_intrinsic)) { + return false; + } if (!Matcher::has_match_rule(Op_StrIndexOf) || !UseSSE42Intrinsics) { return false; } assert(callee()->signature()->size() == 5, "String.indexOf() has 5 arguments"); Node* src = argument(0); // byte[] - Node* src_count = argument(1); + Node* src_count = argument(1); // char count Node* tgt = argument(2); // byte[] - Node* tgt_count = argument(3); - Node* from_index = argument(4); - - // Java code which calls this method has range checks for from_index value. - src_count = _gvn.transform(new SubINode(src_count, from_index)); + Node* tgt_count = argument(3); // char count + Node* from_index = argument(4); // char index // Multiply byte array index by 2 if String is UTF16 encoded Node* src_offset = (ae == StrIntrinsicNode::LL) ? from_index : _gvn.transform(new LShiftINode(from_index, intcon(1))); + src_count = _gvn.transform(new SubINode(src_count, from_index)); Node* src_start = array_element_address(src, src_offset, T_BYTE); Node* tgt_start = array_element_address(tgt, intcon(0), T_BYTE); - Node* result = make_string_method_node(Op_StrIndexOf, src_start, src_count, tgt_start, tgt_count, ae); + // Range checks + generate_string_range_check(src, src_offset, src_count, ae != StrIntrinsicNode::LL); + generate_string_range_check(tgt, intcon(0), tgt_count, ae == StrIntrinsicNode::UU); + if (stopped()) { + return true; + } - // The result is index relative to from_index if substring was found, -1 otherwise. - // Generate code which will fold into cmove. - RegionNode* region = new RegionNode(3); + RegionNode* region = new RegionNode(5); Node* phi = new PhiNode(region, TypeInt::INT); - Node* cmp = _gvn.transform(new CmpINode(result, intcon(0))); - Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::lt)); + Node* result = make_indexOf_node(src_start, src_count, tgt_start, tgt_count, region, phi, ae); + if (result != NULL) { + // The result is index relative to from_index if substring was found, -1 otherwise. + // Generate code which will fold into cmove. + Node* cmp = _gvn.transform(new CmpINode(result, intcon(0))); + Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::lt)); - Node* if_lt = generate_slow_guard(bol, NULL); - if (if_lt != NULL) { - // result == -1 - phi->init_req(2, result); - region->init_req(2, if_lt); - } - if (!stopped()) { - result = _gvn.transform(new AddINode(result, from_index)); - phi->init_req(1, result); - region->init_req(1, control()); + Node* if_lt = generate_slow_guard(bol, NULL); + if (if_lt != NULL) { + // result == -1 + phi->init_req(3, result); + region->init_req(3, if_lt); + } + if (!stopped()) { + result = _gvn.transform(new AddINode(result, from_index)); + phi->init_req(4, result); + region->init_req(4, control()); + } } set_control(_gvn.transform(region)); @@ -1205,8 +1213,38 @@ bool LibraryCallKit::inline_string_indexOfI(StrIntrinsicNode::ArgEnc ae) { return true; } +// Create StrIndexOfNode with fast path checks +Node* LibraryCallKit::make_indexOf_node(Node* src_start, Node* src_count, Node* tgt_start, Node* tgt_count, + RegionNode* region, Node* phi, StrIntrinsicNode::ArgEnc ae) { + // Check for substr count > string count + Node* cmp = _gvn.transform(new CmpINode(tgt_count, src_count)); + Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::gt)); + Node* if_gt = generate_slow_guard(bol, NULL); + if (if_gt != NULL) { + phi->init_req(1, intcon(-1)); + region->init_req(1, if_gt); + } + if (!stopped()) { + // Check for substr count == 0 + cmp = _gvn.transform(new CmpINode(tgt_count, intcon(0))); + bol = _gvn.transform(new BoolNode(cmp, BoolTest::eq)); + Node* if_zero = generate_slow_guard(bol, NULL); + if (if_zero != NULL) { + phi->init_req(2, intcon(0)); + region->init_req(2, if_zero); + } + } + if (!stopped()) { + return make_string_method_node(Op_StrIndexOf, src_start, src_count, tgt_start, tgt_count, ae); + } + return NULL; +} + //-----------------------------inline_string_indexOfChar----------------------- bool LibraryCallKit::inline_string_indexOfChar() { + if (too_many_traps(Deoptimization::Reason_intrinsic)) { + return false; + } if (!Matcher::has_match_rule(Op_StrIndexOfChar) || !(UseSSE > 4)) { return false; } @@ -1218,9 +1256,14 @@ bool LibraryCallKit::inline_string_indexOfChar() { Node* src_offset = _gvn.transform(new LShiftINode(from_index, intcon(1))); Node* src_start = array_element_address(src, src_offset, T_BYTE); - Node* src_count = _gvn.transform(new SubINode(max, from_index)); + // Range checks + generate_string_range_check(src, src_offset, src_count, true); + if (stopped()) { + return true; + } + RegionNode* region = new RegionNode(3); Node* phi = new PhiNode(region, TypeInt::INT); @@ -1256,6 +1299,9 @@ bool LibraryCallKit::inline_string_indexOfChar() { // void StringLatin1.inflate(byte[] src, int srcOff, char[] dst, int dstOff, int len) // void StringLatin1.inflate(byte[] src, int srcOff, byte[] dst, int dstOff, int len) bool LibraryCallKit::inline_string_copy(bool compress) { + if (too_many_traps(Deoptimization::Reason_intrinsic)) { + return false; + } int nargs = 5; // 2 oops, 3 ints assert(callee()->signature()->size() == nargs, "string copy has 5 arguments"); @@ -1278,6 +1324,13 @@ bool LibraryCallKit::inline_string_copy(bool compress) { (!compress && src_elem == T_BYTE && (dst_elem == T_BYTE || dst_elem == T_CHAR)), "Unsupported array types for inline_string_copy"); + // Range checks + generate_string_range_check(src, src_offset, length, compress && src_elem == T_BYTE); + generate_string_range_check(dst, dst_offset, length, !compress && dst_elem == T_BYTE); + if (stopped()) { + return true; + } + // Convert char[] offsets to byte[] offsets if (compress && src_elem == T_BYTE) { src_offset = _gvn.transform(new LShiftINode(src_offset, intcon(1))); @@ -1329,6 +1382,9 @@ bool LibraryCallKit::inline_string_copy(bool compress) { //------------------------inline_string_toBytesU-------------------------- // public static byte[] StringUTF16.toBytes(char[] value, int off, int len) bool LibraryCallKit::inline_string_toBytesU() { + if (too_many_traps(Deoptimization::Reason_intrinsic)) { + return false; + } // Get the arguments. Node* value = argument(0); Node* offset = argument(1); @@ -1347,8 +1403,11 @@ bool LibraryCallKit::inline_string_toBytesU() { RegionNode* bailout = new RegionNode(1); record_for_igvn(bailout); - // Make sure that resulting byte[] length does not overflow Integer.MAX_VALUE + // Range checks + generate_negative_guard(offset, bailout); generate_negative_guard(length, bailout); + generate_limit_guard(offset, length, load_array_length(value), bailout); + // Make sure that resulting byte[] length does not overflow Integer.MAX_VALUE generate_limit_guard(length, intcon(0), intcon(max_jint/2), bailout); if (bailout->req() > 1) { @@ -1357,9 +1416,9 @@ bool LibraryCallKit::inline_string_toBytesU() { uncommon_trap(Deoptimization::Reason_intrinsic, Deoptimization::Action_maybe_recompile); } - if (stopped()) return true; - - // Range checks are done by caller. + if (stopped()) { + return true; + } Node* size = _gvn.transform(new LShiftINode(length, intcon(1))); Node* klass_node = makecon(TypeKlassPtr::make(ciTypeArrayKlass::make(T_BYTE))); @@ -1412,12 +1471,14 @@ bool LibraryCallKit::inline_string_toBytesU() { } //------------------------inline_string_getCharsU-------------------------- -// public void StringUTF16.getChars(byte[] value, int srcBegin, int srcEnd, char dst[], int dstBegin) +// public void StringUTF16.getChars(byte[] src, int srcBegin, int srcEnd, char dst[], int dstBegin) bool LibraryCallKit::inline_string_getCharsU() { - if (too_many_traps(Deoptimization::Reason_intrinsic)) return false; + if (too_many_traps(Deoptimization::Reason_intrinsic)) { + return false; + } // Get the arguments. - Node* value = argument(0); + Node* src = argument(0); Node* src_begin = argument(1); Node* src_end = argument(2); // exclusive offset (i < src_end) Node* dst = argument(3); @@ -1428,21 +1489,26 @@ bool LibraryCallKit::inline_string_getCharsU() { AllocateArrayNode* alloc = tightly_coupled_allocation(dst, NULL); // Check if a null path was taken unconditionally. - value = null_check(value); + src = null_check(src); dst = null_check(dst); if (stopped()) { return true; } - // Range checks are done by caller. - // Get length and convert char[] offset to byte[] offset Node* length = _gvn.transform(new SubINode(src_end, src_begin)); src_begin = _gvn.transform(new LShiftINode(src_begin, intcon(1))); + // Range checks + generate_string_range_check(src, src_begin, length, true); + generate_string_range_check(dst, dst_begin, length, false); + if (stopped()) { + return true; + } + if (!stopped()) { // Calculate starting addresses. - Node* src_start = array_element_address(value, src_begin, T_BYTE); + Node* src_start = array_element_address(src, src_begin, T_BYTE); Node* dst_start = array_element_address(dst, dst_begin, T_CHAR); // Check if array addresses are aligned to HeapWordSize diff --git a/hotspot/src/share/vm/opto/node.cpp b/hotspot/src/share/vm/opto/node.cpp index 9ac166bc49f..dc91ef3e471 100644 --- a/hotspot/src/share/vm/opto/node.cpp +++ b/hotspot/src/share/vm/opto/node.cpp @@ -316,6 +316,9 @@ inline int Node::Init(int req) { // Create a Node, with a given number of required edges. Node::Node(uint req) : _idx(Init(req)) +#ifdef ASSERT + , _parse_idx(_idx) +#endif { assert( req < Compile::current()->max_node_limit() - NodeLimitFudgeFactor, "Input limit exceeded" ); debug_only( verify_construction() ); @@ -335,6 +338,9 @@ Node::Node(uint req) //------------------------------Node------------------------------------------- Node::Node(Node *n0) : _idx(Init(1)) +#ifdef ASSERT + , _parse_idx(_idx) +#endif { debug_only( verify_construction() ); NOT_PRODUCT(nodes_created++); @@ -347,6 +353,9 @@ Node::Node(Node *n0) //------------------------------Node------------------------------------------- Node::Node(Node *n0, Node *n1) : _idx(Init(2)) +#ifdef ASSERT + , _parse_idx(_idx) +#endif { debug_only( verify_construction() ); NOT_PRODUCT(nodes_created++); @@ -361,6 +370,9 @@ Node::Node(Node *n0, Node *n1) //------------------------------Node------------------------------------------- Node::Node(Node *n0, Node *n1, Node *n2) : _idx(Init(3)) +#ifdef ASSERT + , _parse_idx(_idx) +#endif { debug_only( verify_construction() ); NOT_PRODUCT(nodes_created++); @@ -377,6 +389,9 @@ Node::Node(Node *n0, Node *n1, Node *n2) //------------------------------Node------------------------------------------- Node::Node(Node *n0, Node *n1, Node *n2, Node *n3) : _idx(Init(4)) +#ifdef ASSERT + , _parse_idx(_idx) +#endif { debug_only( verify_construction() ); NOT_PRODUCT(nodes_created++); @@ -395,6 +410,9 @@ Node::Node(Node *n0, Node *n1, Node *n2, Node *n3) //------------------------------Node------------------------------------------- Node::Node(Node *n0, Node *n1, Node *n2, Node *n3, Node *n4) : _idx(Init(5)) +#ifdef ASSERT + , _parse_idx(_idx) +#endif { debug_only( verify_construction() ); NOT_PRODUCT(nodes_created++); @@ -416,6 +434,9 @@ Node::Node(Node *n0, Node *n1, Node *n2, Node *n3, Node *n4) Node::Node(Node *n0, Node *n1, Node *n2, Node *n3, Node *n4, Node *n5) : _idx(Init(6)) +#ifdef ASSERT + , _parse_idx(_idx) +#endif { debug_only( verify_construction() ); NOT_PRODUCT(nodes_created++); @@ -439,6 +460,9 @@ Node::Node(Node *n0, Node *n1, Node *n2, Node *n3, Node::Node(Node *n0, Node *n1, Node *n2, Node *n3, Node *n4, Node *n5, Node *n6) : _idx(Init(7)) +#ifdef ASSERT + , _parse_idx(_idx) +#endif { debug_only( verify_construction() ); NOT_PRODUCT(nodes_created++); diff --git a/hotspot/src/share/vm/opto/node.hpp b/hotspot/src/share/vm/opto/node.hpp index 0117027d5d5..0d29b85b45a 100644 --- a/hotspot/src/share/vm/opto/node.hpp +++ b/hotspot/src/share/vm/opto/node.hpp @@ -293,10 +293,16 @@ protected: public: // Each Node is assigned a unique small/dense number. This number is used - // to index into auxiliary arrays of data and bitvectors. - // It is declared const to defend against inadvertant assignment, - // since it is used by clients as a naked field. + // to index into auxiliary arrays of data and bit vectors. + // The field _idx is declared constant to defend against inadvertent assignments, + // since it is used by clients as a naked field. However, the field's value can be + // changed using the set_idx() method. + // + // The PhaseRenumberLive phase renumbers nodes based on liveness information. + // Therefore, it updates the value of the _idx field. The parse-time _idx is + // preserved in _parse_idx. const node_idx_t _idx; + DEBUG_ONLY(const node_idx_t _parse_idx;) // Get the (read-only) number of input edges uint req() const { return _cnt; } diff --git a/hotspot/src/share/vm/opto/phase.cpp b/hotspot/src/share/vm/opto/phase.cpp index 9662bbcbbfb..397a5371313 100644 --- a/hotspot/src/share/vm/opto/phase.cpp +++ b/hotspot/src/share/vm/opto/phase.cpp @@ -77,6 +77,7 @@ void Phase::print_timers() { tty->print_cr(" Other: %7.3f s", other); } } + tty->print_cr (" Renumber Live: %7.3f s", timers[_t_renumberLive].seconds()); tty->print_cr (" IdealLoop: %7.3f s", timers[_t_idealLoop].seconds()); tty->print_cr (" IdealLoop Verify: %7.3f s", timers[_t_idealLoopVerify].seconds()); tty->print_cr (" Cond Const Prop: %7.3f s", timers[_t_ccp].seconds()); @@ -88,6 +89,7 @@ void Phase::print_timers() { (timers[_t_escapeAnalysis].seconds() + timers[_t_iterGVN].seconds() + timers[_t_incrInline].seconds() + + timers[_t_renumberLive].seconds() + timers[_t_idealLoop].seconds() + timers[_t_idealLoopVerify].seconds() + timers[_t_ccp].seconds() + diff --git a/hotspot/src/share/vm/opto/phase.hpp b/hotspot/src/share/vm/opto/phase.hpp index 4b5d53d1656..4b0c53ffc56 100644 --- a/hotspot/src/share/vm/opto/phase.hpp +++ b/hotspot/src/share/vm/opto/phase.hpp @@ -42,22 +42,23 @@ class PhaseGVN; class Phase : public StackObj { public: enum PhaseNumber { - Compiler, // Top-level compiler phase - Parser, // Parse bytecodes - Remove_Useless, // Remove useless nodes - Optimistic, // Optimistic analysis phase - GVN, // Pessimistic global value numbering phase - Ins_Select, // Instruction selection phase - CFG, // Build a CFG - BlockLayout, // Linear ordering of blocks - Register_Allocation, // Register allocation, duh - LIVE, // Dragon-book LIVE range problem - StringOpts, // StringBuilder related optimizations - Interference_Graph, // Building the IFG - Coalesce, // Coalescing copies - Ideal_Loop, // Find idealized trip-counted loops - Macro_Expand, // Expand macro nodes - Peephole, // Apply peephole optimizations + Compiler, // Top-level compiler phase + Parser, // Parse bytecodes + Remove_Useless, // Remove useless nodes + Remove_Useless_And_Renumber_Live, // First, remove useless nodes from the graph. Then, renumber live nodes. + Optimistic, // Optimistic analysis phase + GVN, // Pessimistic global value numbering phase + Ins_Select, // Instruction selection phase + CFG, // Build a CFG + BlockLayout, // Linear ordering of blocks + Register_Allocation, // Register allocation, duh + LIVE, // Dragon-book LIVE range problem + StringOpts, // StringBuilder related optimizations + Interference_Graph, // Building the IFG + Coalesce, // Coalescing copies + Ideal_Loop, // Find idealized trip-counted loops + Macro_Expand, // Expand macro nodes + Peephole, // Apply peephole optimizations last_phase }; @@ -73,6 +74,7 @@ public: _t_incrInline_igvn, _t_incrInline_pru, _t_incrInline_inline, + _t_renumberLive, _t_idealLoop, _t_idealLoopVerify, _t_ccp, diff --git a/hotspot/src/share/vm/opto/phaseX.cpp b/hotspot/src/share/vm/opto/phaseX.cpp index 9d2b11e26a7..0274f0e7c98 100644 --- a/hotspot/src/share/vm/opto/phaseX.cpp +++ b/hotspot/src/share/vm/opto/phaseX.cpp @@ -406,7 +406,7 @@ void NodeHash::operator=(const NodeHash& nh) { //============================================================================= //------------------------------PhaseRemoveUseless----------------------------- // 1) Use a breadthfirst walk to collect useful nodes reachable from root. -PhaseRemoveUseless::PhaseRemoveUseless( PhaseGVN *gvn, Unique_Node_List *worklist ) : Phase(Remove_Useless), +PhaseRemoveUseless::PhaseRemoveUseless(PhaseGVN *gvn, Unique_Node_List *worklist, PhaseNumber phase_num) : Phase(phase_num), _useful(Thread::current()->resource_area()) { // Implementation requires 'UseLoopSafepoints == true' and an edge from root @@ -443,6 +443,82 @@ PhaseRemoveUseless::PhaseRemoveUseless( PhaseGVN *gvn, Unique_Node_List *worklis } } +//============================================================================= +//------------------------------PhaseRenumberLive------------------------------ +// First, remove useless nodes (equivalent to identifying live nodes). +// Then, renumber live nodes. +// +// The set of live nodes is returned by PhaseRemoveUseless in the _useful structure. +// If the number of live nodes is 'x' (where 'x' == _useful.size()), then the +// PhaseRenumberLive updates the node ID of each node (the _idx field) with a unique +// value in the range [0, x). +// +// At the end of the PhaseRenumberLive phase, the compiler's count of unique nodes is +// updated to 'x' and the list of dead nodes is reset (as there are no dead nodes). +// +// The PhaseRenumberLive phase updates two data structures with the new node IDs. +// (1) The worklist is used by the PhaseIterGVN phase to identify nodes that must be +// processed. A new worklist (with the updated node IDs) is returned in 'new_worklist'. +// (2) Type information (the field PhaseGVN::_types) maps type information to each +// node ID. The mapping is updated to use the new node IDs as well. Updated type +// information is returned in PhaseGVN::_types. +// +// The PhaseRenumberLive phase does not preserve the order of elements in the worklist. +// +// Other data structures used by the compiler are not updated. The hash table for value +// numbering (the field PhaseGVN::_table) is not updated because computing the hash +// values is not based on node IDs. The field PhaseGVN::_nodes is not updated either +// because it is empty wherever PhaseRenumberLive is used. +PhaseRenumberLive::PhaseRenumberLive(PhaseGVN* gvn, + Unique_Node_List* worklist, Unique_Node_List* new_worklist, + PhaseNumber phase_num) : + PhaseRemoveUseless(gvn, worklist, Remove_Useless_And_Renumber_Live) { + + assert(RenumberLiveNodes, "RenumberLiveNodes must be set to true for node renumbering to take place"); + assert(C->live_nodes() == _useful.size(), "the number of live nodes must match the number of useful nodes"); + assert(gvn->nodes_size() == 0, "GVN must not contain any nodes at this point"); + + uint old_unique_count = C->unique(); + uint live_node_count = C->live_nodes(); + uint worklist_size = worklist->size(); + + // Storage for the updated type information. + Type_Array new_type_array(C->comp_arena()); + + // Iterate over the set of live nodes. + uint current_idx = 0; // The current new node ID. Incremented after every assignment. + for (uint i = 0; i < _useful.size(); i++) { + Node* n = _useful.at(i); + const Type* type = gvn->type_or_null(n); + new_type_array.map(current_idx, type); + + bool in_worklist = false; + if (worklist->member(n)) { + in_worklist = true; + } + + n->set_idx(current_idx); // Update node ID. + + if (in_worklist) { + new_worklist->push(n); + } + + current_idx++; + } + + assert(worklist_size == new_worklist->size(), "the new worklist must have the same size as the original worklist"); + assert(live_node_count == current_idx, "all live nodes must be processed"); + + // Replace the compiler's type information with the updated type information. + gvn->replace_types(new_type_array); + + // Update the unique node count of the compilation to the number of currently live nodes. + C->set_unique(live_node_count); + + // Set the dead node count to 0 and reset dead node list. + C->reset_dead_node_list(); +} + //============================================================================= //------------------------------PhaseTransform--------------------------------- diff --git a/hotspot/src/share/vm/opto/phaseX.hpp b/hotspot/src/share/vm/opto/phaseX.hpp index efd7b456853..990383e76c6 100644 --- a/hotspot/src/share/vm/opto/phaseX.hpp +++ b/hotspot/src/share/vm/opto/phaseX.hpp @@ -148,11 +148,21 @@ protected: Unique_Node_List _useful; // Nodes reachable from root // list is allocated from current resource area public: - PhaseRemoveUseless( PhaseGVN *gvn, Unique_Node_List *worklist ); + PhaseRemoveUseless(PhaseGVN *gvn, Unique_Node_List *worklist, PhaseNumber phase_num = Remove_Useless); Unique_Node_List *get_useful() { return &_useful; } }; +//------------------------------PhaseRenumber---------------------------------- +// Phase that first performs a PhaseRemoveUseless, then it renumbers compiler +// structures accordingly. +class PhaseRenumberLive : public PhaseRemoveUseless { +public: + PhaseRenumberLive(PhaseGVN* gvn, + Unique_Node_List* worklist, Unique_Node_List* new_worklist, + PhaseNumber phase_num = Remove_Useless_And_Renumber_Live); +}; + //------------------------------PhaseTransform--------------------------------- // Phases that analyze, then transform. Constructing the Phase object does any @@ -162,7 +172,7 @@ public: class PhaseTransform : public Phase { protected: Arena* _arena; - Node_Array _nodes; // Map old node indices to new nodes. + Node_List _nodes; // Map old node indices to new nodes. Type_Array _types; // Map old node indices to Types. // ConNode caches: @@ -187,7 +197,13 @@ public: Arena* arena() { return _arena; } Type_Array& types() { return _types; } + void replace_types(Type_Array new_types) { + _types = new_types; + } // _nodes is used in varying ways by subclasses, which define local accessors + uint nodes_size() { + return _nodes.size(); + } public: // Get a previously recorded type for the node n. diff --git a/hotspot/test/compiler/codegen/8144028/BitTests.java b/hotspot/test/compiler/codegen/8144028/BitTests.java new file mode 100644 index 00000000000..d00b048acbc --- /dev/null +++ b/hotspot/test/compiler/codegen/8144028/BitTests.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2015, Red Hat, Inc. All rights reserved. + * 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 8144028 + * @summary Use AArch64 bit-test instructions in C2 + * @modules java.base + * @run main/othervm -Xbatch -XX:CompileCommand=dontinline,BitTests::* -XX:-TieredCompilation BitTests + * @run main/othervm -Xbatch -XX:+TieredCompilation -XX:TieredStopAtLevel=1 BitTests + * @run main/othervm -Xbatch -XX:+TieredCompilation BitTests + * + */ + +// Try to ensure that the bit test instructions TBZ/TBNZ, TST/TSTW +// don't generate incorrect code. We can't guarantee that C2 will use +// bit test instructions for this test and it's not a bug if it +// doesn't. However, these test cases are ideal candidates for each +// of the instruction forms. +public class BitTests { + + private final XorShift r = new XorShift(); + + private final long increment(long ctr) { + return ctr + 1; + } + + private final int increment(int ctr) { + return ctr + 1; + } + + private final long testIntSignedBranch(long counter) { + if ((int)r.nextLong() < 0) { + counter = increment(counter); + } + return counter; + } + + private final long testLongSignedBranch(long counter) { + if (r.nextLong() < 0) { + counter = increment(counter); + } + return counter; + } + + private final long testIntBitBranch(long counter) { + if (((int)r.nextLong() & (1 << 27)) != 0) { + counter = increment(counter); + } + if (((int)r.nextLong() & (1 << 27)) != 0) { + counter = increment(counter); + } + return counter; + } + + private final long testLongBitBranch(long counter) { + if ((r.nextLong() & (1l << 50)) != 0) { + counter = increment(counter); + } + if ((r.nextLong() & (1l << 50)) != 0) { + counter = increment(counter); + } + return counter; + } + + private final long testLongMaskBranch(long counter) { + if (((r.nextLong() & 0x0800000000l) != 0)) { + counter++; + } + return counter; + } + + private final long testIntMaskBranch(long counter) { + if ((((int)r.nextLong() & 0x08) != 0)) { + counter++; + } + return counter; + } + + private final long testLongMaskBranch(long counter, long mask) { + if (((r.nextLong() & mask) != 0)) { + counter++; + } + return counter; + } + + private final long testIntMaskBranch(long counter, int mask) { + if ((((int)r.nextLong() & mask) != 0)) { + counter++; + } + return counter; + } + + private final long step(long counter) { + counter = testIntSignedBranch(counter); + counter = testLongSignedBranch(counter); + counter = testIntBitBranch(counter); + counter = testLongBitBranch(counter); + counter = testIntMaskBranch(counter); + counter = testLongMaskBranch(counter); + counter = testIntMaskBranch(counter, 0x8000); + counter = testLongMaskBranch(counter, 0x800000000l); + return counter; + } + + + private final long finalBits = 3; + + private long bits = 7; + + public static void main(String[] args) { + BitTests t = new BitTests(); + + long counter = 0; + for (int i = 0; i < 10000000; i++) { + counter = t.step((int) counter); + } + if (counter != 50001495) { + System.err.println("FAILED: counter = " + counter + ", should be 50001495."); + System.exit(97); + } + System.out.println("PASSED"); + } + +} + +// Marsaglia's xor-shift generator, used here because it is +// reproducible across all Java implementations. It is also very +// fast. +class XorShift { + + private long y; + + XorShift() { + y = 2463534242l; + } + + public long nextLong() { + y ^= (y << 13); + y ^= (y >>> 17); + return (y ^= (y << 5)); + + } +} diff --git a/hotspot/test/compiler/intrinsics/string/TestStringConstruction.java b/hotspot/test/compiler/intrinsics/string/TestStringConstruction.java new file mode 100644 index 00000000000..20c010dfb7a --- /dev/null +++ b/hotspot/test/compiler/intrinsics/string/TestStringConstruction.java @@ -0,0 +1,52 @@ +/* + * 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 8142303 + * @summary Tests handling of invalid array indices in C2 intrinsic if explicit range check in Java code is not inlined. + * @run main/othervm -XX:CompileCommand=inline,java.lang.String::* -XX:CompileCommand=inline,java.lang.StringUTF16::* -XX:CompileCommand=exclude,java.lang.String::checkBoundsOffCount TestStringConstruction + */ +public class TestStringConstruction { + + public static void main(String[] args) { + char[] chars = new char[42]; + for (int i = 0; i < 10_000; ++i) { + test(chars); + } + } + + private static String test(char[] chars) { + try { + // The constructor calls String::checkBoundsOffCount(-1, 42) to perform + // range checks on offset and count. If this method is not inlined, C2 + // does not know about the explicit range checks and does not cut off the + // dead code. As a result, -1 is fed as offset into the StringUTF16.compress + // intrinsic which is replaced by TOP and causes a failure in the matcher. + return new String(chars, -1 , 42); + } catch (Exception e) { + return ""; + } + } +} + diff --git a/hotspot/test/compiler/jvmci/errors/CodeInstallerTest.java b/hotspot/test/compiler/jvmci/errors/CodeInstallerTest.java index 56b32cd10c6..195b7d52cd7 100644 --- a/hotspot/test/compiler/jvmci/errors/CodeInstallerTest.java +++ b/hotspot/test/compiler/jvmci/errors/CodeInstallerTest.java @@ -68,6 +68,7 @@ public class CodeInstallerTest { } protected void installCode(CompilationResult result) { + result.close(); codeCache.addCode(dummyMethod, result, null, null); } diff --git a/hotspot/test/compiler/jvmci/errors/TestInvalidCompilationResult.java b/hotspot/test/compiler/jvmci/errors/TestInvalidCompilationResult.java index 89d6114cccd..98ad40ed2ad 100644 --- a/hotspot/test/compiler/jvmci/errors/TestInvalidCompilationResult.java +++ b/hotspot/test/compiler/jvmci/errors/TestInvalidCompilationResult.java @@ -218,13 +218,6 @@ public class TestInvalidCompilationResult extends CodeInstallerTest { installCode(result); } - @Test(expected = JVMCIError.class) - public void testUnknownInfopointReason() { - CompilationResult result = createEmptyCompilationResult(); - result.addInfopoint(new Infopoint(0, null, InfopointReason.UNKNOWN)); - installCode(result); - } - @Test(expected = JVMCIError.class) public void testInfopointMissingDebugInfo() { CompilationResult result = createEmptyCompilationResult(); diff --git a/hotspot/test/compiler/jvmci/events/JvmciNotifyInstallEventTest.java b/hotspot/test/compiler/jvmci/events/JvmciNotifyInstallEventTest.java index 89a81b19990..cea5bafbd9b 100644 --- a/hotspot/test/compiler/jvmci/events/JvmciNotifyInstallEventTest.java +++ b/hotspot/test/compiler/jvmci/events/JvmciNotifyInstallEventTest.java @@ -106,13 +106,12 @@ public class JvmciNotifyInstallEventTest implements HotSpotVMEventListener { HotSpotCompilationRequest compRequest = new HotSpotCompilationRequest(method, -1, 0L); // to pass sanity check of default -1 compResult.setTotalFrameSize(0); + compResult.close(); codeCache.installCode(compRequest, compResult, /* installedCode = */ null, /* speculationLog = */ null, /* isDefault = */ false); Asserts.assertEQ(gotInstallNotification, 1, "Got unexpected event count after 1st install attempt"); // since "empty" compilation result is ok, a second attempt should be ok - compResult = new CompilationResult(METHOD_NAME); // create another instance with fresh state - compResult.setTotalFrameSize(0); codeCache.installCode(compRequest, compResult, /* installedCode = */ null, /* speculationLog = */ null, /* isDefault = */ false); Asserts.assertEQ(gotInstallNotification, 2, diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 7caf815e7a5..d9d054fdd41 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -338,3 +338,4 @@ fcabfb3c38ac1da99394e821902537d92e45222d jdk9-b92 b9c50c63305cf1120263f6b7c6993021b53c2c40 jdk9-b93 5e75b8a9c01bca09c56dec7539e44dc82090c7c2 jdk9-b94 c8d0845877a811ab4350935892f826929359a3ff jdk-9+95 +1f3182529f2c474e5506955ccb3820cfa5822265 jdk-9+96 diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java index ea0f2e2f74b..1ea57877573 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java @@ -1394,7 +1394,12 @@ public class XMLDocumentFragmentScannerImpl fEmptyElement = true; return true; } else if (!isValidNameStartChar(c) || !sawSpace) { - reportFatalError("ElementUnterminated", new Object[]{fElementQName.rawname}); + // Second chance. Check if this character is a high + // surrogate of a valid name start character. + if (!isValidNameStartHighSurrogate(c) || !sawSpace) { + reportFatalError("ElementUnterminated", + new Object[]{fElementQName.rawname}); + } } return false; @@ -2606,40 +2611,38 @@ public class XMLDocumentFragmentScannerImpl private void startOfMarkup() throws IOException { fMarkupDepth++; final int ch = fEntityScanner.peekChar(); - - switch(ch){ - case '?' :{ - setScannerState(SCANNER_STATE_PI); - fEntityScanner.skipChar(ch); - break; - } - case '!' :{ - fEntityScanner.skipChar(ch); - if (fEntityScanner.skipChar('-')) { - if (!fEntityScanner.skipChar('-')) { - reportFatalError("InvalidCommentStart", + if (isValidNameStartChar(ch) || isValidNameStartHighSurrogate(ch)) { + setScannerState(SCANNER_STATE_START_ELEMENT_TAG); + } else { + switch(ch){ + case '?' :{ + setScannerState(SCANNER_STATE_PI); + fEntityScanner.skipChar(ch); + break; + } + case '!' :{ + fEntityScanner.skipChar(ch); + if (fEntityScanner.skipChar('-')) { + if (!fEntityScanner.skipChar('-')) { + reportFatalError("InvalidCommentStart", + null); + } + setScannerState(SCANNER_STATE_COMMENT); + } else if (fEntityScanner.skipString(cdata)) { + setScannerState(SCANNER_STATE_CDATA ); + } else if (!scanForDoctypeHook()) { + reportFatalError("MarkupNotRecognizedInContent", null); } - setScannerState(SCANNER_STATE_COMMENT); - } else if (fEntityScanner.skipString(cdata)) { - setScannerState(SCANNER_STATE_CDATA ); - } else if (!scanForDoctypeHook()) { - reportFatalError("MarkupNotRecognizedInContent", - null); + break; } - break; - } - case '/' :{ - setScannerState(SCANNER_STATE_END_ELEMENT_TAG); - fEntityScanner.skipChar(ch); - break; - } - default :{ - if (isValidNameStartChar(ch)) { - setScannerState(SCANNER_STATE_START_ELEMENT_TAG); - } else { - reportFatalError("MarkupNotRecognizedInContent", - null); + case '/' :{ + setScannerState(SCANNER_STATE_END_ELEMENT_TAG); + fEntityScanner.skipChar(ch); + break; + } + default :{ + reportFatalError("MarkupNotRecognizedInContent", null); } } } diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java index e562457f85c..3d839652705 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java @@ -847,9 +847,12 @@ public class XMLDocumentScannerImpl case SCANNER_STATE_START_OF_MARKUP: { fMarkupDepth++; - - if (fEntityScanner.skipChar('?')) { - setScannerState(SCANNER_STATE_PI); + if (isValidNameStartChar(fEntityScanner.peekChar()) || + isValidNameStartHighSurrogate(fEntityScanner.peekChar())) { + setScannerState(SCANNER_STATE_ROOT_ELEMENT); + setDriver(fContentDriver); + //from now onwards this would be handled by fContentDriver,in the same next() call + return fContentDriver.next(); } else if (fEntityScanner.skipChar('!')) { if (fEntityScanner.skipChar('-')) { if (!fEntityScanner.skipChar('-')) { @@ -872,12 +875,8 @@ public class XMLDocumentScannerImpl reportFatalError("MarkupNotRecognizedInProlog", null); } - } else if (XMLChar.isNameStart(fEntityScanner.peekChar())) { - setScannerState(SCANNER_STATE_ROOT_ELEMENT); - setDriver(fContentDriver); - //from now onwards this would be handled by fContentDriver,in the same next() call - return fContentDriver.next(); - + } else if (fEntityScanner.skipChar('?')) { + setScannerState(SCANNER_STATE_PI); } else { reportFatalError("MarkupNotRecognizedInProlog", null); @@ -1395,7 +1394,8 @@ public class XMLDocumentScannerImpl } else if (fEntityScanner.skipChar('/')) { reportFatalError("MarkupNotRecognizedInMisc", null); - } else if (XMLChar.isNameStart(fEntityScanner.peekChar())) { + } else if (isValidNameStartChar(fEntityScanner.peekChar()) || + isValidNameStartHighSurrogate(fEntityScanner.peekChar())) { reportFatalError("MarkupNotRecognizedInMisc", null); scanStartElement(); diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLScanner.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLScanner.java index 6316d4a3bfb..96864c3886d 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLScanner.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLScanner.java @@ -784,7 +784,7 @@ public abstract class XMLScanner if (XMLChar.isHighSurrogate(c)) { scanSurrogates(text); } - if (isInvalidLiteral(c)) { + else if (isInvalidLiteral(c)) { reportFatalError("InvalidCharInComment", new Object[] { Integer.toHexString(c) }); fEntityScanner.scanChar(); @@ -1385,6 +1385,14 @@ public abstract class XMLScanner return (XMLChar.isNameStart(value)); } // isValidNameStartChar(int): boolean + // returns true if the given character is + // a valid high surrogate for a nameStartChar + // with respect to the version of XML understood + // by this scanner. + protected boolean isValidNameStartHighSurrogate(int value) { + return false; + } // isValidNameStartHighSurrogate(int): boolean + protected boolean versionSupported(String version ) { return version.equals("1.0") || version.equals("1.1"); } // version Supported diff --git a/jaxp/test/javax/xml/jaxp/unittest/parsers/SupplementaryChars.java b/jaxp/test/javax/xml/jaxp/unittest/parsers/SupplementaryChars.java new file mode 100644 index 00000000000..7430e03f5c4 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/unittest/parsers/SupplementaryChars.java @@ -0,0 +1,67 @@ +package parsers; + +import java.io.ByteArrayInputStream; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import org.xml.sax.SAXParseException; +import org.xml.sax.helpers.DefaultHandler; + +/** + * @bug 8072081 + * @summary verifies that supplementary characters are supported as character + * data in xml 1.0, and also names in xml 1.1. + * + * Joe Wang (huizhe.wang@oracle.com) + */ + +public class SupplementaryChars { + + @Test(dataProvider = "supported") + public void test(String xml) throws Exception { + ByteArrayInputStream stream = new ByteArrayInputStream(xml.getBytes("UTF-8")); + getParser().parse(stream, new DefaultHandler()); + stream.close(); + } + + @Test(dataProvider = "unsupported", expectedExceptions = SAXParseException.class) + public void testInvalid(String xml) throws Exception { + ByteArrayInputStream stream = new ByteArrayInputStream(xml.getBytes("UTF-8")); + getParser().parse(stream, new DefaultHandler()); + stream.close(); + } + + @DataProvider(name = "supported") + private Object[][] supported() { + + return new Object[][] { + {"\uD840\uDC0B"}, + {""}, + {"in tag name"}, + {"in attribute name"}, + {"\uD840\uDC0B"}, + {""} + }; + } + + @DataProvider(name = "unsupported") + private Object[][] unsupported() { + return new Object[][] { + {"in tag name"}, + {"in attribute name"} + }; + } + + private SAXParser getParser() { + SAXParser parser = null; + try { + SAXParserFactory factory = SAXParserFactory.newInstance(); + parser = factory.newSAXParser(); + } catch (Exception e) { + throw new RuntimeException(e.getMessage()); + } + return parser; + } +} diff --git a/jaxws/.hgtags b/jaxws/.hgtags index 7c9c0a7e3c6..4a477ff33cb 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -341,3 +341,4 @@ fe772cbc64f4e0418c5bf694e9e7123f02e1808f jdk9-b92 5e94fbbb7032b3bba8254ddb1af8fc45a4d1448b jdk9-b93 e8d15c61400c1682a7873e053d7b39efde0b79be jdk9-b94 3e03ddaaac6585fa27e91596eb2a9a31e10bdcc9 jdk-9+95 +b55cebc47555293cf9c2aefb3bf63c56e847ab19 jdk-9+96 diff --git a/jdk/make/CompileDemos.gmk b/jdk/make/CompileDemos.gmk index 423378389cc..90796dd0f1e 100644 --- a/jdk/make/CompileDemos.gmk +++ b/jdk/make/CompileDemos.gmk @@ -459,7 +459,7 @@ ifeq ($(OPENJDK_TARGET_OS), solaris) # We can only compile native code after java has been compiled (since we # depend on generated .h files) $(SUPPORT_OUTPUTDIR)/demos/native/jni/Poller/Poller.o: \ - $(BUILD_DEMO_JAVA_Poller_COMPILE_TARGET) + $(BUILD_DEMO_JAVA_Poller) # Copy to image $(SUPPORT_OUTPUTDIR)/demos/image/jni/Poller/README.txt: \ diff --git a/jdk/make/mapfiles/libnio/mapfile-linux b/jdk/make/mapfiles/libnio/mapfile-linux index 428553e122c..b9b059a80c2 100644 --- a/jdk/make/mapfiles/libnio/mapfile-linux +++ b/jdk/make/mapfiles/libnio/mapfile-linux @@ -173,7 +173,7 @@ SUNWprivate_1.1 { Java_sun_nio_fs_UnixNativeDispatcher_futimes; Java_sun_nio_fs_UnixNativeDispatcher_open0; Java_sun_nio_fs_UnixNativeDispatcher_openat0; - Java_sun_nio_fs_UnixNativeDispatcher_close; + Java_sun_nio_fs_UnixNativeDispatcher_close0; Java_sun_nio_fs_UnixNativeDispatcher_read; Java_sun_nio_fs_UnixNativeDispatcher_write; Java_sun_nio_fs_UnixNativeDispatcher_fopen0; diff --git a/jdk/make/mapfiles/libnio/mapfile-macosx b/jdk/make/mapfiles/libnio/mapfile-macosx index 97207e2c816..6e4a7fb594c 100644 --- a/jdk/make/mapfiles/libnio/mapfile-macosx +++ b/jdk/make/mapfiles/libnio/mapfile-macosx @@ -150,7 +150,7 @@ SUNWprivate_1.1 { Java_sun_nio_fs_UnixNativeDispatcher_futimes; Java_sun_nio_fs_UnixNativeDispatcher_open0; Java_sun_nio_fs_UnixNativeDispatcher_openat0; - Java_sun_nio_fs_UnixNativeDispatcher_close; + Java_sun_nio_fs_UnixNativeDispatcher_close0; Java_sun_nio_fs_UnixNativeDispatcher_read; Java_sun_nio_fs_UnixNativeDispatcher_write; Java_sun_nio_fs_UnixNativeDispatcher_fopen0; diff --git a/jdk/make/mapfiles/libnio/mapfile-solaris b/jdk/make/mapfiles/libnio/mapfile-solaris index 12f418cad8a..6834bd221d4 100644 --- a/jdk/make/mapfiles/libnio/mapfile-solaris +++ b/jdk/make/mapfiles/libnio/mapfile-solaris @@ -150,7 +150,7 @@ SUNWprivate_1.1 { Java_sun_nio_fs_UnixNativeDispatcher_futimes; Java_sun_nio_fs_UnixNativeDispatcher_open0; Java_sun_nio_fs_UnixNativeDispatcher_openat0; - Java_sun_nio_fs_UnixNativeDispatcher_close; + Java_sun_nio_fs_UnixNativeDispatcher_close0; Java_sun_nio_fs_UnixNativeDispatcher_read; Java_sun_nio_fs_UnixNativeDispatcher_write; Java_sun_nio_fs_UnixNativeDispatcher_fopen0; diff --git a/jdk/make/mapfiles/libzip/mapfile-vers b/jdk/make/mapfiles/libzip/mapfile-vers index ceace23f26d..c1ab48c10cf 100644 --- a/jdk/make/mapfiles/libzip/mapfile-vers +++ b/jdk/make/mapfiles/libzip/mapfile-vers @@ -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 @@ -27,7 +27,6 @@ SUNWprivate_1.1 { global: - Java_java_util_jar_JarFile_getMetaInfEntryNames; Java_java_util_zip_Adler32_update; Java_java_util_zip_Adler32_updateBytes; Java_java_util_zip_Adler32_updateByteBuffer; @@ -48,25 +47,6 @@ SUNWprivate_1.1 { Java_java_util_zip_Inflater_initIDs; Java_java_util_zip_Inflater_reset; Java_java_util_zip_Inflater_setDictionary; - Java_java_util_zip_ZipFile_close; - Java_java_util_zip_ZipFile_getCommentBytes; - Java_java_util_zip_ZipFile_freeEntry; - Java_java_util_zip_ZipFile_getEntry; - Java_java_util_zip_ZipFile_getEntryBytes; - Java_java_util_zip_ZipFile_getEntryCrc; - Java_java_util_zip_ZipFile_getEntryCSize; - Java_java_util_zip_ZipFile_getEntryFlag; - Java_java_util_zip_ZipFile_getEntryMethod; - Java_java_util_zip_ZipFile_getEntrySize; - Java_java_util_zip_ZipFile_getEntryTime; - Java_java_util_zip_ZipFile_getNextEntry; - Java_java_util_zip_ZipFile_getZipMessage; - Java_java_util_zip_ZipFile_getTotal; - Java_java_util_zip_ZipFile_initIDs; - Java_java_util_zip_ZipFile_open; - Java_java_util_zip_ZipFile_read; - Java_java_util_zip_ZipFile_startsWithLOC; - ZIP_Close; ZIP_CRC32; ZIP_FindEntry; diff --git a/jdk/make/mapfiles/libzip/reorder-sparc b/jdk/make/mapfiles/libzip/reorder-sparc index 154e7998a53..63b2ad6fc28 100644 --- a/jdk/make/mapfiles/libzip/reorder-sparc +++ b/jdk/make/mapfiles/libzip/reorder-sparc @@ -16,30 +16,14 @@ text: .text%ZIP_InflateFully; text: .text%ZIP_Lock; text: .text%ZIP_Unlock; text: .text%ZIP_FreeEntry; -text: .text%Java_java_util_zip_ZipFile_initIDs; -text: .text%Java_java_util_zip_ZipFile_open; -text: .text%Java_java_util_zip_ZipFile_getTotal; -text: .text%Java_java_util_zip_ZipFile_startsWithLOC; -text: .text%Java_java_util_zip_ZipFile_getEntry; -text: .text%Java_java_util_zip_ZipFile_freeEntry; -text: .text%Java_java_util_zip_ZipFile_getEntryTime; -text: .text%Java_java_util_zip_ZipFile_getEntryCrc; -text: .text%Java_java_util_zip_ZipFile_getEntryCSize; -text: .text%Java_java_util_zip_ZipFile_getEntrySize; -text: .text%Java_java_util_zip_ZipFile_getEntryFlag; -text: .text%Java_java_util_zip_ZipFile_getEntryMethod; -text: .text%Java_java_util_zip_ZipFile_getEntryBytes; text: .text%Java_java_util_zip_Inflater_initIDs; text: .text%Java_java_util_zip_Inflater_init; text: .text%inflateInit2_; text: .text%zcalloc; text: .text%Java_java_util_zip_Inflater_inflateBytes; -text: .text%Java_java_util_zip_ZipFile_read; text: .text%ZIP_Read; text: .text%zcfree; -text: .text%Java_java_util_jar_JarFile_getMetaInfEntryNames; text: .text%Java_java_util_zip_Inflater_reset; text: .text%Java_java_util_zip_Inflater_end; text: .text%inflateEnd; -text: .text%Java_java_util_zip_ZipFile_close; text: .text%ZIP_Close; diff --git a/jdk/make/mapfiles/libzip/reorder-sparcv9 b/jdk/make/mapfiles/libzip/reorder-sparcv9 index 89690b8dabb..caca118de98 100644 --- a/jdk/make/mapfiles/libzip/reorder-sparcv9 +++ b/jdk/make/mapfiles/libzip/reorder-sparcv9 @@ -15,19 +15,6 @@ text: .text%ZIP_InflateFully; text: .text%ZIP_Lock; text: .text%ZIP_Unlock; text: .text%ZIP_FreeEntry; -text: .text%Java_java_util_zip_ZipFile_initIDs; -text: .text%Java_java_util_zip_ZipFile_open; -text: .text%Java_java_util_zip_ZipFile_getTotal; -text: .text%Java_java_util_zip_ZipFile_startsWithLOC; -text: .text%Java_java_util_zip_ZipFile_getEntry; -text: .text%Java_java_util_zip_ZipFile_freeEntry; -text: .text%Java_java_util_zip_ZipFile_getEntryTime; -text: .text%Java_java_util_zip_ZipFile_getEntryCrc; -text: .text%Java_java_util_zip_ZipFile_getEntryCSize; -text: .text%Java_java_util_zip_ZipFile_getEntrySize; -text: .text%Java_java_util_zip_ZipFile_getEntryFlag; -text: .text%Java_java_util_zip_ZipFile_getEntryMethod; -text: .text%Java_java_util_zip_ZipFile_getEntryBytes; text: .text%Java_java_util_zip_Inflater_initIDs; text: .text%Java_java_util_zip_Inflater_init; text: .text%inflateInit2_; @@ -35,7 +22,6 @@ text: .text%zcalloc; text: .text%inflateReset; text: .text%Java_java_util_zip_Inflater_inflateBytes; text: .text%inflate; -text: .text%Java_java_util_zip_ZipFile_read; text: .text%ZIP_Read; text: .text%zcfree; text: .text%Java_java_util_jar_JarFile_getMetaInfEntryNames; @@ -43,6 +29,5 @@ text: .text%ZIP_ReadEntry; text: .text%InflateFully; text: .text%inflateEnd; text: .text%Java_java_util_zip_Inflater_reset; -text: .text%Java_java_util_zip_ZipFile_close; text: .text%ZIP_Close; text: .text%Java_java_util_zip_Inflater_end; diff --git a/jdk/make/mapfiles/libzip/reorder-x86 b/jdk/make/mapfiles/libzip/reorder-x86 index 746948315eb..dfd57c7752e 100644 --- a/jdk/make/mapfiles/libzip/reorder-x86 +++ b/jdk/make/mapfiles/libzip/reorder-x86 @@ -16,34 +16,16 @@ text: .text%ZIP_InflateFully; text: .text%ZIP_Lock; text: .text%ZIP_Unlock; text: .text%ZIP_FreeEntry; -text: .text%Java_java_util_zip_ZipFile_initIDs; -text: .text%Java_java_util_zip_ZipFile_open; -text: .text%Java_java_util_zip_ZipFile_getTotal; -text: .text%Java_java_util_zip_ZipFile_startsWithLOC; -text: .text%Java_java_util_zip_ZipFile_getEntry; -text: .text%Java_java_util_zip_ZipFile_freeEntry; -text: .text%Java_java_util_zip_ZipFile_getEntryTime; -text: .text%Java_java_util_zip_ZipFile_getEntryCrc; -text: .text%Java_java_util_zip_ZipFile_getEntryCSize; -text: .text%Java_java_util_zip_ZipFile_getEntrySize; -text: .text%Java_java_util_zip_ZipFile_getEntryFlag; -text: .text%Java_java_util_zip_ZipFile_getEntryMethod; -text: .text%Java_java_util_zip_ZipFile_getEntryBytes; -text: .text%Java_java_util_zip_Inflater_initIDs; -text: .text%Java_java_util_zip_Inflater_init; text: .text%inflateInit2_; text: .text%zcalloc; text: .text%inflateReset; text: .text%Java_java_util_zip_Inflater_inflateBytes; text: .text%inflate; -text: .text%Java_java_util_zip_ZipFile_read; text: .text%ZIP_Read; text: .text%zcfree; -text: .text%Java_java_util_jar_JarFile_getMetaInfEntryNames; text: .text%ZIP_ReadEntry; text: .text%InflateFully; text: .text%inflateEnd; text: .text%Java_java_util_zip_Inflater_reset; -text: .text%Java_java_util_zip_ZipFile_close; text: .text%ZIP_Close; text: .text%Java_java_util_zip_Inflater_end; diff --git a/jdk/make/src/native/genconstants/fs/genUnixConstants.c b/jdk/make/src/native/genconstants/fs/genUnixConstants.c index c2cfc0aba39..792ecf81415 100644 --- a/jdk/make/src/native/genconstants/fs/genUnixConstants.c +++ b/jdk/make/src/native/genconstants/fs/genUnixConstants.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -104,6 +104,7 @@ int main(int argc, const char* argv[]) { // errors DEF(ENOENT); + DEF(ENXIO); DEF(EACCES); DEF(EEXIST); DEF(ENOTDIR); diff --git a/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxDosFileAttributeView.java b/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxDosFileAttributeView.java index dba638e8da9..a60f2ad45f9 100644 --- a/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxDosFileAttributeView.java +++ b/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxDosFileAttributeView.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -117,8 +117,9 @@ class LinuxDosFileAttributeView public DosFileAttributes readAttributes() throws IOException { file.checkRead(); - int fd = file.openForAttributeAccess(followLinks); + int fd = -1; try { + fd = file.openForAttributeAccess(followLinks); final UnixFileAttributes attrs = UnixFileAttributes.get(fd); final int dosAttribute = getDosAttribute(fd); @@ -253,8 +254,9 @@ class LinuxDosFileAttributeView private void updateDosAttribute(int flag, boolean enable) throws IOException { file.checkWrite(); - int fd = file.openForAttributeAccess(followLinks); + int fd = -1; try { + fd = file.openForAttributeAccess(followLinks); int oldValue = getDosAttribute(fd); int newValue = oldValue; if (enable) { diff --git a/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxFileStore.java b/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxFileStore.java index 360a8d33ba7..217a8850d65 100644 --- a/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxFileStore.java +++ b/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxFileStore.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -94,22 +94,20 @@ class LinuxFileStore // returns true if extended attributes enabled on file system where given // file resides, returns false if disabled or unable to determine. private boolean isExtendedAttributesEnabled(UnixPath path) { + int fd = -1; try { - int fd = path.openForAttributeAccess(false); - try { - // fgetxattr returns size if called with size==0 - byte[] name = Util.toBytes("user.java"); - LinuxNativeDispatcher.fgetxattr(fd, name, 0L, 0); + fd = path.openForAttributeAccess(false); + + // fgetxattr returns size if called with size==0 + byte[] name = Util.toBytes("user.java"); + LinuxNativeDispatcher.fgetxattr(fd, name, 0L, 0); + return true; + } catch (UnixException e) { + // attribute does not exist + if (e.errno() == UnixConstants.ENODATA) return true; - } catch (UnixException e) { - // attribute does not exist - if (e.errno() == UnixConstants.ENODATA) - return true; - } finally { - UnixNativeDispatcher.close(fd); - } - } catch (IOException ignore) { - // nothing we can do + } finally { + UnixNativeDispatcher.close(fd); } return false; } diff --git a/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxUserDefinedFileAttributeView.java b/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxUserDefinedFileAttributeView.java index 18b880c550f..568341be3ec 100644 --- a/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxUserDefinedFileAttributeView.java +++ b/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxUserDefinedFileAttributeView.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -97,7 +97,12 @@ class LinuxUserDefinedFileAttributeView if (System.getSecurityManager() != null) checkAccess(file.getPathForPermissionCheck(), true, false); - int fd = file.openForAttributeAccess(followLinks); + int fd = -1; + try { + fd = file.openForAttributeAccess(followLinks); + } catch (UnixException x) { + x.rethrowAsIOException(file); + } NativeBuffer buffer = null; try { int size = 1024; @@ -133,7 +138,12 @@ class LinuxUserDefinedFileAttributeView if (System.getSecurityManager() != null) checkAccess(file.getPathForPermissionCheck(), true, false); - int fd = file.openForAttributeAccess(followLinks); + int fd = -1; + try { + fd = file.openForAttributeAccess(followLinks); + } catch (UnixException x) { + x.rethrowAsIOException(file); + } try { // fgetxattr returns size if called with size==0 return fgetxattr(fd, nameAsBytes(file,name), 0L, 0); @@ -169,7 +179,12 @@ class LinuxUserDefinedFileAttributeView address = nb.address(); } - int fd = file.openForAttributeAccess(followLinks); + int fd = -1; + try { + fd = file.openForAttributeAccess(followLinks); + } catch (UnixException x) { + x.rethrowAsIOException(file); + } try { try { int n = fgetxattr(fd, nameAsBytes(file,name), address, rem); @@ -236,7 +251,12 @@ class LinuxUserDefinedFileAttributeView } } - int fd = file.openForAttributeAccess(followLinks); + int fd = -1; + try { + fd = file.openForAttributeAccess(followLinks); + } catch (UnixException x) { + x.rethrowAsIOException(file); + } try { try { fsetxattr(fd, nameAsBytes(file,name), address, rem); @@ -260,7 +280,12 @@ class LinuxUserDefinedFileAttributeView if (System.getSecurityManager() != null) checkAccess(file.getPathForPermissionCheck(), false, true); - int fd = file.openForAttributeAccess(followLinks); + int fd = -1; + try { + fd = file.openForAttributeAccess(followLinks); + } catch (UnixException x) { + x.rethrowAsIOException(file); + } try { fremovexattr(fd, nameAsBytes(file,name)); } catch (UnixException x) { 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 4471de71198..1c44659daf4 100644 --- a/jdk/src/java.base/share/classes/java/math/BigInteger.java +++ b/jdk/src/java.base/share/classes/java/math/BigInteger.java @@ -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 @@ -2409,6 +2409,53 @@ public class BigInteger extends Number implements Comparable { } } + /** + * Returns the integer square root of this BigInteger. The integer square + * root of the corresponding mathematical integer {@code n} is the largest + * mathematical integer {@code s} such that {@code s*s <= n}. It is equal + * to the value of {@code floor(sqrt(n))}, where {@code sqrt(n)} denotes the + * real square root of {@code n} treated as a real. Note that the integer + * square root will be less than the real square root if the latter is not + * representable as an integral value. + * + * @return the integer square root of {@code this} + * @throws ArithmeticException if {@code this} is negative. (The square + * root of a negative integer {@code val} is + * {@code (i * sqrt(-val))} where i is the + * imaginary unit and is equal to + * {@code sqrt(-1)}.) + * @since 1.9 + */ + public BigInteger sqrt() { + if (this.signum < 0) { + throw new ArithmeticException("Negative BigInteger"); + } + + return new MutableBigInteger(this.mag).sqrt().toBigInteger(); + } + + /** + * Returns an array of two BigIntegers containing the integer square root + * {@code s} of {@code this} and its remainder {@code this - s*s}, + * respectively. + * + * @return an array of two BigIntegers with the integer square root at + * offset 0 and the remainder at offset 1 + * @throws ArithmeticException if {@code this} is negative. (The square + * root of a negative integer {@code val} is + * {@code (i * sqrt(-val))} where i is the + * imaginary unit and is equal to + * {@code sqrt(-1)}.) + * @see #sqrt() + * @since 1.9 + */ + public BigInteger[] sqrtAndRemainder() { + BigInteger s = sqrt(); + BigInteger r = this.subtract(s.square()); + assert r.compareTo(BigInteger.ZERO) >= 0; + return new BigInteger[] {s, r}; + } + /** * Returns a BigInteger whose value is the greatest common divisor of * {@code abs(this)} and {@code abs(val)}. Returns 0 if diff --git a/jdk/src/java.base/share/classes/java/math/MutableBigInteger.java b/jdk/src/java.base/share/classes/java/math/MutableBigInteger.java index 46e79a1da60..65eca1e743d 100644 --- a/jdk/src/java.base/share/classes/java/math/MutableBigInteger.java +++ b/jdk/src/java.base/share/classes/java/math/MutableBigInteger.java @@ -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 @@ -1866,6 +1866,96 @@ class MutableBigInteger { return (r << 32) | (q & LONG_MASK); } + /** + * Calculate the integer square root {@code floor(sqrt(this))} where + * {@code sqrt(.)} denotes the mathematical square root. The contents of + * {@code this} are not changed. The value of {@code this} is assumed + * to be non-negative. + * + * @implNote The implementation is based on the material in Henry S. Warren, + * Jr., Hacker's Delight (2nd ed.) (Addison Wesley, 2013), 279-282. + * + * @throws ArithmeticException if the value returned by {@code bitLength()} + * overflows the range of {@code int}. + * @return the integer square root of {@code this} + * @since 1.9 + */ + MutableBigInteger sqrt() { + // Special cases. + if (this.isZero()) { + return new MutableBigInteger(0); + } else if (this.value.length == 1 + && (this.value[0] & LONG_MASK) < 4) { // result is unity + return ONE; + } + + if (bitLength() <= 63) { + // Initial estimate is the square root of the positive long value. + long v = new BigInteger(this.value, 1).longValueExact(); + long xk = (long)Math.floor(Math.sqrt(v)); + + // Refine the estimate. + do { + long xk1 = (xk + v/xk)/2; + + // Terminate when non-decreasing. + if (xk1 >= xk) { + return new MutableBigInteger(new int[] { + (int)(xk >>> 32), (int)(xk & LONG_MASK) + }); + } + + xk = xk1; + } while (true); + } else { + // Set up the initial estimate of the iteration. + + // Obtain the bitLength > 63. + int bitLength = (int) this.bitLength(); + if (bitLength != this.bitLength()) { + throw new ArithmeticException("bitLength() integer overflow"); + } + + // Determine an even valued right shift into positive long range. + int shift = bitLength - 63; + if (shift % 2 == 1) { + shift++; + } + + // Shift the value into positive long range. + MutableBigInteger xk = new MutableBigInteger(this); + xk.rightShift(shift); + xk.normalize(); + + // Use the square root of the shifted value as an approximation. + double d = new BigInteger(xk.value, 1).doubleValue(); + BigInteger bi = BigInteger.valueOf((long)Math.ceil(Math.sqrt(d))); + xk = new MutableBigInteger(bi.mag); + + // Shift the approximate square root back into the original range. + xk.leftShift(shift / 2); + + // Refine the estimate. + MutableBigInteger xk1 = new MutableBigInteger(); + do { + // xk1 = (xk + n/xk)/2 + this.divide(xk, xk1, false); + xk1.add(xk); + xk1.rightShift(1); + + // Terminate when non-decreasing. + if (xk1.compare(xk) >= 0) { + return xk; + } + + // xk = xk1 + xk.copyValue(xk1); + + xk1.reset(); + } while (true); + } + } + /** * Calculate GCD of this and b. This and b are changed by the computation. */ diff --git a/jdk/src/java.base/share/classes/java/security/acl/package-info.java b/jdk/src/java.base/share/classes/java/security/acl/package-info.java index f0362fdf0b6..9f2186fbb2e 100644 --- a/jdk/src/java.base/share/classes/java/security/acl/package-info.java +++ b/jdk/src/java.base/share/classes/java/security/acl/package-info.java @@ -24,12 +24,11 @@ */ /** - * The classes and interfaces in this package have been deprecated. - * The {@code java.security} package contains suitable replacements. - * See that package and, for example, {@code java.security.Permission} - * for details. + * The classes and interfaces in this package have been deprecated. New + * classes should not be added to this package. The {@code java.security} + * package contains suitable replacements. See {@link java.security.Policy} + * and related classes for details. * * @since 1.1 */ -@Deprecated package java.security.acl; diff --git a/jdk/src/java.base/share/classes/java/util/Map.java b/jdk/src/java.base/share/classes/java/util/Map.java index f958607dfc5..0967523eba3 100644 --- a/jdk/src/java.base/share/classes/java/util/Map.java +++ b/jdk/src/java.base/share/classes/java/util/Map.java @@ -1670,9 +1670,9 @@ public interface Map { */ @SafeVarargs @SuppressWarnings("varargs") - static Map ofEntries(Entry... entries) { + static Map ofEntries(Entry... entries) { Map map = new HashMap<>(entries.length * 4 / 3 + 1); // throws NPE if entries is null - for (Entry e : entries) { + for (Entry e : entries) { // next line throws NPE if e is null map.put(Objects.requireNonNull(e.getKey()), Objects.requireNonNull(e.getValue())); } diff --git a/jdk/src/java.base/share/classes/java/util/jar/JarFile.java b/jdk/src/java.base/share/classes/java/util/jar/JarFile.java index 6d16a517ac9..62734ceefbd 100644 --- a/jdk/src/java.base/share/classes/java/util/jar/JarFile.java +++ b/jdk/src/java.base/share/classes/java/util/jar/JarFile.java @@ -203,7 +203,10 @@ class JarFile extends ZipFile { return man; } - private native String[] getMetaInfEntryNames(); + private String[] getMetaInfEntryNames() { + return jdk.internal.misc.SharedSecrets.getJavaUtilZipFileAccess() + .getMetaInfEntryNames((ZipFile)this); + } /** * Returns the {@code JarEntry} for the given entry name or diff --git a/jdk/src/java.base/share/classes/java/util/regex/Pattern.java b/jdk/src/java.base/share/classes/java/util/regex/Pattern.java index e4f64db438a..3a6ac6f56a8 100644 --- a/jdk/src/java.base/share/classes/java/util/regex/Pattern.java +++ b/jdk/src/java.base/share/classes/java/util/regex/Pattern.java @@ -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 @@ -5814,7 +5814,7 @@ NEXT: while (i <= last) { */ public Stream splitAsStream(final CharSequence input) { class MatcherIterator implements Iterator { - private final Matcher matcher; + private Matcher matcher; // The start position of the next sub-sequence of input // when current == input.length there are no more elements private int current; @@ -5823,14 +5823,6 @@ NEXT: while (i <= last) { // > 0 if there are N next empty elements private int emptyElementCount; - MatcherIterator() { - this.matcher = matcher(input); - // If the input is an empty string then the result can only be a - // stream of the input. Induce that by setting the empty - // element count to 1 - this.emptyElementCount = input.length() == 0 ? 1 : 0; - } - public String next() { if (!hasNext()) throw new NoSuchElementException(); @@ -5846,6 +5838,13 @@ NEXT: while (i <= last) { } public boolean hasNext() { + if (matcher == null) { + matcher = matcher(input); + // If the input is an empty string then the result can only be a + // stream of the input. Induce that by setting the empty + // element count to 1 + emptyElementCount = input.length() == 0 ? 1 : 0; + } if (nextElement != null || emptyElementCount > 0) return true; diff --git a/jdk/src/java.base/share/classes/java/util/stream/Collectors.java b/jdk/src/java.base/share/classes/java/util/stream/Collectors.java index c3be0d97eb8..97e05c326ec 100644 --- a/jdk/src/java.base/share/classes/java/util/stream/Collectors.java +++ b/jdk/src/java.base/share/classes/java/util/stream/Collectors.java @@ -434,7 +434,7 @@ public final class Collectors { * stream returned by mapper * @return a collector which applies the mapping function to the input * elements and provides the flat mapped results to the downstream collector - * @since 1.9 + * @since 9 */ public static Collector flatMapping(Function> mapper, @@ -451,6 +451,53 @@ public final class Collectors { downstream.characteristics()); } + /** + * Adapts a {@code Collector} to one accepting elements of the same type + * {@code T} by applying the predicate to each input element and only + * accumulating if the predicate returns {@code true}. + * + * @apiNote + * The {@code filtering()} collectors are most useful when used in a + * multi-level reduction, such as downstream of a {@code groupingBy} or + * {@code partitioningBy}. For example, given a stream of + * {@code Employee}, to accumulate the employees in each department that have a + * salary above a certain threshold: + *
{@code
+     *     Map> wellPaidEmployeesByDepartment
+     *         = employees.stream().collect(groupingBy(Employee::getDepartment,
+     *                                              filtering(e -> e.getSalary() > 2000, toSet())));
+     * }
+ * A filtering collector differs from a stream's {@code filter()} operation. + * In this example, suppose there are no employees whose salary is above the + * threshold in some department. Using a filtering collector as shown above + * would result in a mapping from that department to an empty {@code Set}. + * If a stream {@code filter()} operation were done instead, there would be + * no mapping for that department at all. + * + * @param the type of the input elements + * @param intermediate accumulation type of the downstream collector + * @param result type of collector + * @param predicate a predicate to be applied to the input elements + * @param downstream a collector which will accept values that match the + * predicate + * @return a collector which applies the predicate to the input elements + * and provides matching elements to the downstream collector + * @since 9 + */ + public static + Collector filtering(Predicate predicate, + Collector downstream) { + BiConsumer downstreamAccumulator = downstream.accumulator(); + return new CollectorImpl<>(downstream.supplier(), + (r, t) -> { + if (predicate.test(t)) { + downstreamAccumulator.accept(r, t); + } + }, + downstream.combiner(), downstream.finisher(), + downstream.characteristics()); + } + /** * Adapts a {@code Collector} to perform an additional finishing * transformation. For example, one could adapt the {@link #toList()} diff --git a/jdk/src/java.base/share/classes/java/util/zip/ZipCoder.java b/jdk/src/java.base/share/classes/java/util/zip/ZipCoder.java index b920b820e03..243d6e8c065 100644 --- a/jdk/src/java.base/share/classes/java/util/zip/ZipCoder.java +++ b/jdk/src/java.base/share/classes/java/util/zip/ZipCoder.java @@ -43,7 +43,7 @@ import sun.nio.cs.ArrayEncoder; final class ZipCoder { - String toString(byte[] ba, int length) { + String toString(byte[] ba, int off, int length) { CharsetDecoder cd = decoder().reset(); int len = (int)(length * cd.maxCharsPerByte()); char[] ca = new char[len]; @@ -53,12 +53,12 @@ final class ZipCoder { // CodingErrorAction.REPLACE mode. ZipCoder uses // REPORT mode. if (isUTF8 && cd instanceof ArrayDecoder) { - int clen = ((ArrayDecoder)cd).decode(ba, 0, length, ca); + int clen = ((ArrayDecoder)cd).decode(ba, off, length, ca); if (clen == -1) // malformed throw new IllegalArgumentException("MALFORMED"); return new String(ca, 0, clen); } - ByteBuffer bb = ByteBuffer.wrap(ba, 0, length); + ByteBuffer bb = ByteBuffer.wrap(ba, off, length); CharBuffer cb = CharBuffer.wrap(ca); CoderResult cr = cd.decode(bb, cb, true); if (!cr.isUnderflow()) @@ -69,8 +69,12 @@ final class ZipCoder { return new String(ca, 0, cb.position()); } + String toString(byte[] ba, int length) { + return toString(ba, 0, length); + } + String toString(byte[] ba) { - return toString(ba, ba.length); + return toString(ba, 0, ba.length); } byte[] getBytes(String s) { @@ -111,13 +115,16 @@ final class ZipCoder { return utf8.getBytes(s); } - String toStringUTF8(byte[] ba, int len) { + return toStringUTF8(ba, 0, len); + } + + String toStringUTF8(byte[] ba, int off, int len) { if (isUTF8) - return toString(ba, len); + return toString(ba, off, len); if (utf8 == null) utf8 = new ZipCoder(StandardCharsets.UTF_8); - return utf8.toString(ba, len); + return utf8.toString(ba, off, len); } boolean isUTF8() { diff --git a/jdk/src/java.base/share/classes/java/util/zip/ZipFile.java b/jdk/src/java.base/share/classes/java/util/zip/ZipFile.java index 4e3a6d20417..1c5eb9c90b5 100644 --- a/jdk/src/java.base/share/classes/java/util/zip/ZipFile.java +++ b/jdk/src/java.base/share/classes/java/util/zip/ZipFile.java @@ -30,14 +30,22 @@ import java.io.InputStream; import java.io.IOException; import java.io.EOFException; import java.io.File; +import java.io.RandomAccessFile; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.nio.file.attribute.BasicFileAttributes; +import java.nio.file.Path; +import java.nio.file.Files; + import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Deque; import java.util.Enumeration; import java.util.HashMap; import java.util.Iterator; import java.util.Map; +import java.util.Objects; import java.util.NoSuchElementException; import java.util.Spliterator; import java.util.Spliterators; @@ -47,7 +55,9 @@ import java.util.stream.StreamSupport; import jdk.internal.misc.JavaUtilZipFileAccess; import jdk.internal.misc.SharedSecrets; +import static java.util.zip.ZipConstants.*; import static java.util.zip.ZipConstants64.*; +import static java.util.zip.ZipUtils.*; /** * This class is used to read entries from a zip file. @@ -60,11 +70,11 @@ import static java.util.zip.ZipConstants64.*; */ public class ZipFile implements ZipConstants, Closeable { - private long jzfile; // address of jzfile data + private final String name; // zip file name - private final int total; // total number of entries - private final boolean locsig; // if zip file starts with LOCSIG (usually true) private volatile boolean closeRequested = false; + private Source zsrc; + private ZipCoder zc; private static final int STORED = ZipEntry.STORED; private static final int DEFLATED = ZipEntry.DEFLATED; @@ -83,23 +93,6 @@ class ZipFile implements ZipConstants, Closeable { */ public static final int OPEN_DELETE = 0x4; - static { - /* Zip library is loaded from System.initializeSystemClass */ - initIDs(); - } - - private static native void initIDs(); - - private static final boolean usemmap; - - static { - // A system prpperty to disable mmap use to avoid vm crash when - // in-use zip file is accidently overwritten by others. - String prop = sun.misc.VM.getSavedProperty("sun.zip.disableMemoryMapping"); - usemmap = (prop == null || - !(prop.length() == 0 || prop.equalsIgnoreCase("true"))); - } - /** * Opens a zip file for reading. * @@ -165,8 +158,6 @@ class ZipFile implements ZipConstants, Closeable { this(file, OPEN_READ); } - private ZipCoder zc; - /** * Opens a new {@code ZipFile} to read from the specified * {@code File} object in the specified mode. The mode argument @@ -214,16 +205,13 @@ class ZipFile implements ZipConstants, Closeable { sm.checkDelete(name); } } - if (charset == null) - throw new NullPointerException("charset is null"); + Objects.requireNonNull(charset, "charset"); this.zc = ZipCoder.get(charset); + this.name = name; long t0 = System.nanoTime(); - jzfile = open(name, mode, file.lastModified(), usemmap); + this.zsrc = Source.get(file, (mode & OPEN_DELETE) != 0); sun.misc.PerfCounter.getZipFileOpenTime().addElapsedTimeFrom(t0); sun.misc.PerfCounter.getZipFileCount().increment(); - this.name = name; - this.total = getTotal(jzfile); - this.locsig = startsWithLOC(jzfile); } /** @@ -257,6 +245,7 @@ class ZipFile implements ZipConstants, Closeable { /** * Opens a ZIP file for reading given the specified File object. + * * @param file the ZIP file to be opened for reading * @param charset * The {@linkplain java.nio.charset.Charset charset} to be @@ -287,10 +276,10 @@ class ZipFile implements ZipConstants, Closeable { public String getComment() { synchronized (this) { ensureOpen(); - byte[] bcomm = getCommentBytes(jzfile); - if (bcomm == null) + if (zsrc.comment == null) { return null; - return zc.toString(bcomm, bcomm.length); + } + return zc.toString(zsrc.comment); } } @@ -303,38 +292,28 @@ class ZipFile implements ZipConstants, Closeable { * @throws IllegalStateException if the zip file has been closed */ public ZipEntry getEntry(String name) { - if (name == null) { - throw new NullPointerException("name"); - } - long jzentry = 0; + + Objects.requireNonNull(name, "name"); synchronized (this) { ensureOpen(); - jzentry = getEntry(jzfile, zc.getBytes(name), true); - if (jzentry != 0) { - ZipEntry ze = getZipEntry(name, jzentry); - freeEntry(jzfile, jzentry); - return ze; + int pos = zsrc.getEntryPos(zc.getBytes(name), true); + if (pos != -1) { + return getZipEntry(name, pos); } } return null; } - private static native long getEntry(long jzfile, byte[] name, - boolean addSlash); - - // freeEntry releases the C jzentry struct. - private static native void freeEntry(long jzfile, long jzentry); - - // the outstanding inputstreams that need to be closed, + // The outstanding inputstreams that need to be closed, // mapped to the inflater objects they use. private final Map streams = new WeakHashMap<>(); /** * Returns an input stream for reading the contents of the specified * zip file entry. - * - *

Closing this ZIP file will, in turn, close all input - * streams that have been returned by invocations of this method. + *

+ * Closing this ZIP file will, in turn, close all input streams that + * have been returned by invocations of this method. * * @param entry the zip file entry * @return the input stream for reading the contents of the specified @@ -344,37 +323,38 @@ class ZipFile implements ZipConstants, Closeable { * @throws IllegalStateException if the zip file has been closed */ public InputStream getInputStream(ZipEntry entry) throws IOException { - if (entry == null) { - throw new NullPointerException("entry"); - } - long jzentry = 0; + Objects.requireNonNull(entry, "entry"); + int pos = -1; ZipFileInputStream in = null; synchronized (this) { ensureOpen(); if (!zc.isUTF8() && (entry.flag & EFS) != 0) { - jzentry = getEntry(jzfile, zc.getBytesUTF8(entry.name), false); + pos = zsrc.getEntryPos(zc.getBytesUTF8(entry.name), false); } else { - jzentry = getEntry(jzfile, zc.getBytes(entry.name), false); + pos = zsrc.getEntryPos(zc.getBytes(entry.name), false); } - if (jzentry == 0) { + if (pos == -1) { return null; } - in = new ZipFileInputStream(jzentry); - - switch (getEntryMethod(jzentry)) { + in = new ZipFileInputStream(zsrc.cen, pos); + switch (CENHOW(zsrc.cen, pos)) { case STORED: synchronized (streams) { streams.put(in, null); } return in; case DEFLATED: + // Inflater likes a bit of slack // MORE: Compute good size for inflater stream: - long size = getEntrySize(jzentry) + 2; // Inflater likes a bit of slack - if (size > 65536) size = 8192; - if (size <= 0) size = 4096; + long size = CENLEN(zsrc.cen, pos) + 2; + if (size > 65536) { + size = 8192; + } + if (size <= 0) { + size = 4096; + } Inflater inf = getInflater(); - InputStream is = - new ZipFileInflaterInputStream(in, inf, (int)size); + InputStream is = new ZipFileInflaterInputStream(in, inf, (int)size); synchronized (streams) { streams.put(is, inf); } @@ -447,8 +427,8 @@ class ZipFile implements ZipConstants, Closeable { private Inflater getInflater() { Inflater inf; synchronized (inflaterCache) { - while (null != (inf = inflaterCache.poll())) { - if (false == inf.ended()) { + while ((inf = inflaterCache.poll()) != null) { + if (!inf.ended()) { return inf; } } @@ -460,7 +440,7 @@ class ZipFile implements ZipConstants, Closeable { * Releases the specified inflater to the list of available inflaters. */ private void releaseInflater(Inflater inf) { - if (false == inf.ended()) { + if (!inf.ended()) { inf.reset(); synchronized (inflaterCache) { inflaterCache.add(inf); @@ -469,7 +449,7 @@ class ZipFile implements ZipConstants, Closeable { } // List of available Inflater objects for decompression - private Deque inflaterCache = new ArrayDeque<>(); + private final Deque inflaterCache = new ArrayDeque<>(); /** * Returns the path name of the ZIP file. @@ -493,7 +473,7 @@ class ZipFile implements ZipConstants, Closeable { public boolean hasNext() { synchronized (ZipFile.this) { ensureOpen(); - return i < total; + return i < zsrc.total; } } @@ -504,28 +484,11 @@ class ZipFile implements ZipConstants, Closeable { public ZipEntry next() { synchronized (ZipFile.this) { ensureOpen(); - if (i >= total) { + if (i >= zsrc.total) { throw new NoSuchElementException(); } - long jzentry = getNextEntry(jzfile, i++); - if (jzentry == 0) { - String message; - if (closeRequested) { - message = "ZipFile concurrently closed"; - } else { - message = getZipMessage(ZipFile.this.jzfile); - } - throw new ZipError("jzentry == 0" + - ",\n jzfile = " + ZipFile.this.jzfile + - ",\n total = " + ZipFile.this.total + - ",\n name = " + ZipFile.this.name + - ",\n i = " + i + - ",\n message = " + message - ); - } - ZipEntry ze = getZipEntry(null, jzentry); - freeEntry(jzfile, jzentry); - return ze; + // each "entry" has 3 ints in table entries + return getZipEntry(null, zsrc.getEntryPos(i++ * 3)); } } @@ -559,48 +522,53 @@ class ZipFile implements ZipConstants, Closeable { Spliterator.IMMUTABLE | Spliterator.NONNULL), false); } - private ZipEntry getZipEntry(String name, long jzentry) { + /* Checks ensureOpen() before invoke this method */ + private ZipEntry getZipEntry(String name, int pos) { + byte[] cen = zsrc.cen; ZipEntry e = new ZipEntry(); - e.flag = getEntryFlag(jzentry); // get the flag first + int nlen = CENNAM(cen, pos); + int elen = CENEXT(cen, pos); + int clen = CENCOM(cen, pos); + e.flag = CENFLG(cen, pos); // get the flag first if (name != null) { e.name = name; } else { - byte[] bname = getEntryBytes(jzentry, JZENTRY_NAME); if (!zc.isUTF8() && (e.flag & EFS) != 0) { - e.name = zc.toStringUTF8(bname, bname.length); + e.name = zc.toStringUTF8(cen, pos + CENHDR, nlen); } else { - e.name = zc.toString(bname, bname.length); + e.name = zc.toString(cen, pos + CENHDR, nlen); } } - e.xdostime = getEntryTime(jzentry); - e.crc = getEntryCrc(jzentry); - e.size = getEntrySize(jzentry); - e.csize = getEntryCSize(jzentry); - e.method = getEntryMethod(jzentry); - e.setExtra0(getEntryBytes(jzentry, JZENTRY_EXTRA), false); - byte[] bcomm = getEntryBytes(jzentry, JZENTRY_COMMENT); - if (bcomm == null) { - e.comment = null; - } else { + e.xdostime = CENTIM(cen, pos); + e.crc = CENCRC(cen, pos); + e.size = CENLEN(cen, pos); + e.csize = CENSIZ(cen, pos); + e.method = CENHOW(cen, pos); + if (elen != 0) { + e.setExtra0(Arrays.copyOfRange(cen, pos + CENHDR + nlen, + pos + CENHDR + nlen + elen), true); + } + if (clen != 0) { if (!zc.isUTF8() && (e.flag & EFS) != 0) { - e.comment = zc.toStringUTF8(bcomm, bcomm.length); + e.comment = zc.toStringUTF8(cen, pos + CENHDR + nlen + elen, clen); } else { - e.comment = zc.toString(bcomm, bcomm.length); + e.comment = zc.toString(cen, pos + CENHDR + nlen + elen, clen); } } return e; } - private static native long getNextEntry(long jzfile, int i); - /** * Returns the number of entries in the ZIP file. + * * @return the number of entries in the ZIP file * @throws IllegalStateException if the zip file has been closed */ public int size() { - ensureOpen(); - return total; + synchronized (this) { + ensureOpen(); + return zsrc.total; + } } /** @@ -612,14 +580,15 @@ class ZipFile implements ZipConstants, Closeable { * @throws IOException if an I/O error has occurred */ public void close() throws IOException { - if (closeRequested) + if (closeRequested) { return; + } closeRequested = true; synchronized (this) { // Close streams, release their inflaters synchronized (streams) { - if (false == streams.isEmpty()) { + if (!streams.isEmpty()) { Map copy = new HashMap<>(streams); streams.clear(); for (Map.Entry e : copy.entrySet()) { @@ -631,21 +600,17 @@ class ZipFile implements ZipConstants, Closeable { } } } - // Release cached inflaters - Inflater inf; synchronized (inflaterCache) { - while (null != (inf = inflaterCache.poll())) { + Inflater inf; + while ((inf = inflaterCache.poll()) != null) { inf.end(); } } - - if (jzfile != 0) { - // Close the zip file - long zf = this.jzfile; - jzfile = 0; - - close(zf); + // Release zip src + if (zsrc != null) { + Source.close(zsrc); + zsrc = null; } } } @@ -668,14 +633,11 @@ class ZipFile implements ZipConstants, Closeable { close(); } - private static native void close(long jzfile); - private void ensureOpen() { if (closeRequested) { throw new IllegalStateException("zip file closed"); } - - if (jzfile == 0) { + if (zsrc == null) { throw new IllegalStateException("The object is not initialized."); } } @@ -691,40 +653,99 @@ class ZipFile implements ZipConstants, Closeable { * (possibly compressed) zip file entry. */ private class ZipFileInputStream extends InputStream { - private volatile boolean zfisCloseRequested = false; - protected long jzentry; // address of jzentry data + private volatile boolean closeRequested = false; private long pos; // current position within entry data protected long rem; // number of remaining bytes within entry protected long size; // uncompressed size of this entry - ZipFileInputStream(long jzentry) { - pos = 0; - rem = getEntryCSize(jzentry); - size = getEntrySize(jzentry); - this.jzentry = jzentry; + ZipFileInputStream(byte[] cen, int cenpos) throws IOException { + rem = CENSIZ(cen, cenpos); + size = CENLEN(cen, cenpos); + pos = CENOFF(cen, cenpos); + // zip64 + if (rem == ZIP64_MAGICVAL || size == ZIP64_MAGICVAL || + pos == ZIP64_MAGICVAL) { + checkZIP64(cen, cenpos); + } + // negative for lazy initialization, see getDataOffset(); + pos = - (pos + ZipFile.this.zsrc.locpos); + } + + private void checkZIP64(byte[] cen, int cenpos) throws IOException { + int off = cenpos + CENHDR + CENNAM(cen, cenpos); + int end = off + CENEXT(cen, cenpos); + while (off + 4 < end) { + int tag = get16(cen, off); + int sz = get16(cen, off + 2); + off += 4; + if (off + sz > end) // invalid data + break; + if (tag == EXTID_ZIP64) { + if (size == ZIP64_MAGICVAL) { + if (sz < 8 || (off + 8) > end) + break; + size = get64(cen, off); + sz -= 8; + off += 8; + } + if (rem == ZIP64_MAGICVAL) { + if (sz < 8 || (off + 8) > end) + break; + rem = get64(cen, off); + sz -= 8; + off += 8; + } + if (pos == ZIP64_MAGICVAL) { + if (sz < 8 || (off + 8) > end) + break; + pos = get64(cen, off); + sz -= 8; + off += 8; + } + break; + } + off += sz; + } + } + + /* The Zip file spec explicitly allows the LOC extra data size to + * be different from the CEN extra data size. Since we cannot trust + * the CEN extra data size, we need to read the LOC to determine + * the entry data offset. + */ + private long initDataOffset() throws IOException { + if (pos <= 0) { + byte[] loc = new byte[LOCHDR]; + pos = -pos; + int len = ZipFile.this.zsrc.readFullyAt(loc, 0, loc.length, pos); + if (len != LOCHDR) { + throw new ZipException("ZipFile error reading zip file"); + } + if (LOCSIG(loc) != LOCSIG) { + throw new ZipException("ZipFile invalid LOC header (bad signature)"); + } + pos += LOCHDR + LOCNAM(loc) + LOCEXT(loc); + } + return pos; } public int read(byte b[], int off, int len) throws IOException { synchronized (ZipFile.this) { - long rem = this.rem; - long pos = this.pos; + ensureOpenOrZipException(); + initDataOffset(); if (rem == 0) { return -1; } - if (len <= 0) { - return 0; - } if (len > rem) { len = (int) rem; } - - // Check if ZipFile open - ensureOpenOrZipException(); - len = ZipFile.read(ZipFile.this.jzfile, jzentry, pos, b, - off, len); + if (len <= 0) { + return 0; + } + len = ZipFile.this.zsrc.readAt(b, off, len, pos); if (len > 0) { - this.pos = (pos + len); - this.rem = (rem - len); + pos += len; + rem -= len; } } if (rem == 0) { @@ -742,11 +763,16 @@ class ZipFile implements ZipConstants, Closeable { } } - public long skip(long n) { - if (n > rem) - n = rem; - pos += n; - rem -= n; + public long skip(long n) throws IOException { + synchronized (ZipFile.this) { + ensureOpenOrZipException(); + initDataOffset(); + if (n > rem) { + n = rem; + } + pos += n; + rem -= n; + } if (rem == 0) { close(); } @@ -762,17 +788,11 @@ class ZipFile implements ZipConstants, Closeable { } public void close() { - if (zfisCloseRequested) + if (closeRequested) { return; - zfisCloseRequested = true; - - rem = 0; - synchronized (ZipFile.this) { - if (jzentry != 0 && ZipFile.this.jzfile != 0) { - freeEntry(ZipFile.this.jzfile, jzentry); - jzentry = 0; - } } + closeRequested = true; + rem = 0; synchronized (streams) { streams.remove(this); } @@ -787,40 +807,501 @@ class ZipFile implements ZipConstants, Closeable { SharedSecrets.setJavaUtilZipFileAccess( new JavaUtilZipFileAccess() { public boolean startsWithLocHeader(ZipFile zip) { - return zip.startsWithLocHeader(); + return zip.zsrc.startsWithLoc; } - } + public String[] getMetaInfEntryNames(ZipFile zip) { + return zip.getMetaInfEntryNames(); + } + } ); } - /** - * Returns {@code true} if, and only if, the zip file begins with {@code - * LOCSIG}. + /* + * Returns an array of strings representing the names of all entries + * that begin with "META-INF/" (case ignored). This method is used + * in JarFile, via SharedSecrets, as an optimization when looking up + * manifest and signature file entries. Returns null if no entries + * were found. */ - private boolean startsWithLocHeader() { - return locsig; + private String[] getMetaInfEntryNames() { + synchronized (this) { + ensureOpen(); + if (zsrc.metanames.size() == 0) { + return null; + } + String[] names = new String[zsrc.metanames.size()]; + byte[] cen = zsrc.cen; + for (int i = 0; i < names.length; i++) { + int pos = zsrc.metanames.get(i); + names[i] = zc.toStringUTF8(cen, pos + CENHDR, CENNAM(cen, pos)); + } + return names; + } } - private static native long open(String name, int mode, long lastModified, - boolean usemmap) throws IOException; - private static native int getTotal(long jzfile); - private static native boolean startsWithLOC(long jzfile); - private static native int read(long jzfile, long jzentry, - long pos, byte[] b, int off, int len); + private static class Source { + private final Key key; // the key in files + private int refs = 1; - // access to the native zentry object - private static native long getEntryTime(long jzentry); - private static native long getEntryCrc(long jzentry); - private static native long getEntryCSize(long jzentry); - private static native long getEntrySize(long jzentry); - private static native int getEntryMethod(long jzentry); - private static native int getEntryFlag(long jzentry); - private static native byte[] getCommentBytes(long jzfile); + private RandomAccessFile zfile; // zfile of the underlying zip file + private byte[] cen; // CEN & ENDHDR + private long locpos; // position of first LOC header (usually 0) + private byte[] comment; // zip file comment + // list of meta entries in META-INF dir + private ArrayList metanames = new ArrayList<>(); + private final boolean startsWithLoc; // true, if zip file starts with LOCSIG (usually true) - private static final int JZENTRY_NAME = 0; - private static final int JZENTRY_EXTRA = 1; - private static final int JZENTRY_COMMENT = 2; - private static native byte[] getEntryBytes(long jzentry, int type); + // A Hashmap for all entries. + // + // A cen entry of Zip/JAR file. As we have one for every entry in every active Zip/JAR, + // We might have a lot of these in a typical system. In order to save space we don't + // keep the name in memory, but merely remember a 32 bit {@code hash} value of the + // entry name and its offset {@code pos} in the central directory hdeader. + // + // private static class Entry { + // int hash; // 32 bit hashcode on name + // int next; // hash chain: index into entries + // int pos; // Offset of central directory file header + // } + // private Entry[] entries; // array of hashed cen entry + // + // To reduce the total size of entries further, we use a int[] here to store 3 "int" + // {@code hash}, {@code next and {@code "pos for each entry. The entry can then be + // referred by their index of their positions in the {@code entries}. + // + private int[] entries; // array of hashed cen entry + private int addEntry(int index, int hash, int next, int pos) { + entries[index++] = hash; + entries[index++] = next; + entries[index++] = pos; + return index; + } + private int getEntryHash(int index) { return entries[index]; } + private int getEntryNext(int index) { return entries[index + 1]; } + private int getEntryPos(int index) { return entries[index + 2]; } + private static final int ZIP_ENDCHAIN = -1; + private int total; // total number of entries + private int[] table; // Hash chain heads: indexes into entries + private int tablelen; // number of hash heads - private static native String getZipMessage(long jzfile); + private static class Key { + BasicFileAttributes attrs; + File file; + + public Key(File file, BasicFileAttributes attrs) { + this.attrs = attrs; + this.file = file; + } + + public int hashCode() { + long t = attrs.lastModifiedTime().toMillis(); + return ((int)(t ^ (t >>> 32))) + file.hashCode(); + } + + public boolean equals(Object obj) { + if (obj instanceof Key) { + Key key = (Key)obj; + if (!attrs.lastModifiedTime().equals(key.attrs.lastModifiedTime())) { + return false; + } + Object fk = attrs.fileKey(); + if (fk != null) { + return fk.equals(key.attrs.fileKey()); + } else { + return file.equals(key.file); + } + } + return false; + } + } + private static final HashMap files = new HashMap<>(); + + + public static Source get(File file, boolean toDelete) throws IOException { + Key key = new Key(file, + Files.readAttributes(file.toPath(), BasicFileAttributes.class)); + Source src = null; + synchronized (files) { + src = files.get(key); + if (src != null) { + src.refs++; + return src; + } + } + src = new Source(key, toDelete); + + synchronized (files) { + if (files.containsKey(key)) { // someone else put in first + src.close(); // close the newly created one + src = files.get(key); + src.refs++; + return src; + } + files.put(key, src); + return src; + } + } + + private static void close(Source src) throws IOException { + synchronized (files) { + if (--src.refs == 0) { + files.remove(src.key); + src.close(); + } + } + } + + private Source(Key key, boolean toDelete) throws IOException { + this.key = key; + this.zfile = new RandomAccessFile(key.file, "r"); + if (toDelete) { + key.file.delete(); + } + try { + initCEN(-1); + byte[] buf = new byte[4]; + readFullyAt(buf, 0, 4, 0); + this.startsWithLoc = (LOCSIG(buf) == LOCSIG); + } catch (IOException x) { + try { + this.zfile.close(); + } catch (IOException xx) {} + throw x; + } + } + + private void close() throws IOException { + zfile.close(); + zfile = null; + cen = null; + entries = null; + table = null; + metanames = null; + } + + private static final int BUF_SIZE = 8192; + private final int readFullyAt(byte[] buf, int off, int len, long pos) + throws IOException + { + synchronized(zfile) { + zfile.seek(pos); + int N = len; + while (N > 0) { + int n = Math.min(BUF_SIZE, N); + zfile.readFully(buf, off, n); + off += n; + N -= n; + } + return len; + } + } + + private final int readAt(byte[] buf, int off, int len, long pos) + throws IOException + { + synchronized(zfile) { + zfile.seek(pos); + return zfile.read(buf, off, len); + } + } + + private static final int hashN(byte[] a, int off, int len) { + int h = 1; + while (len-- > 0) { + h = 31 * h + a[off++]; + } + return h; + } + + private static final int hash_append(int hash, byte b) { + return hash * 31 + b; + } + + private static class End { + int centot; // 4 bytes + long cenlen; // 4 bytes + long cenoff; // 4 bytes + long endpos; // 4 bytes + } + + /* + * Searches for end of central directory (END) header. The contents of + * the END header will be read and placed in endbuf. Returns the file + * position of the END header, otherwise returns -1 if the END header + * was not found or an error occurred. + */ + private End findEND() throws IOException { + long ziplen = zfile.length(); + if (ziplen <= 0) + zerror("zip file is empty"); + End end = new End(); + byte[] buf = new byte[READBLOCKSZ]; + long minHDR = (ziplen - END_MAXLEN) > 0 ? ziplen - END_MAXLEN : 0; + long minPos = minHDR - (buf.length - ENDHDR); + for (long pos = ziplen - buf.length; pos >= minPos; pos -= (buf.length - ENDHDR)) { + int off = 0; + if (pos < 0) { + // Pretend there are some NUL bytes before start of file + off = (int)-pos; + Arrays.fill(buf, 0, off, (byte)0); + } + int len = buf.length - off; + if (readFullyAt(buf, off, len, pos + off) != len ) { + zerror("zip END header not found"); + } + // Now scan the block backwards for END header signature + for (int i = buf.length - ENDHDR; i >= 0; i--) { + if (buf[i+0] == (byte)'P' && + buf[i+1] == (byte)'K' && + buf[i+2] == (byte)'\005' && + buf[i+3] == (byte)'\006') { + // Found ENDSIG header + byte[] endbuf = Arrays.copyOfRange(buf, i, i + ENDHDR); + end.centot = ENDTOT(endbuf); + end.cenlen = ENDSIZ(endbuf); + end.cenoff = ENDOFF(endbuf); + end.endpos = pos + i; + int comlen = ENDCOM(endbuf); + if (end.endpos + ENDHDR + comlen != ziplen) { + // ENDSIG matched, however the size of file comment in it does + // not match the real size. One "common" cause for this problem + // is some "extra" bytes are padded at the end of the zipfile. + // Let's do some extra verification, we don't care about the + // performance in this situation. + byte[] sbuf = new byte[4]; + long cenpos = end.endpos - end.cenlen; + long locpos = cenpos - end.cenoff; + if (cenpos < 0 || + locpos < 0 || + readFullyAt(sbuf, 0, sbuf.length, cenpos) != 4 || + GETSIG(sbuf) != CENSIG || + readFullyAt(sbuf, 0, sbuf.length, locpos) != 4 || + GETSIG(sbuf) != LOCSIG) { + continue; + } + } + if (comlen > 0) { // this zip file has comlen + comment = new byte[comlen]; + if (readFullyAt(comment, 0, comlen, end.endpos + ENDHDR) != comlen) { + zerror("zip comment read failed"); + } + } + if (end.cenlen == ZIP64_MAGICVAL || + end.cenoff == ZIP64_MAGICVAL || + end.centot == ZIP64_MAGICCOUNT) + { + // need to find the zip64 end; + try { + byte[] loc64 = new byte[ZIP64_LOCHDR]; + if (readFullyAt(loc64, 0, loc64.length, end.endpos - ZIP64_LOCHDR) + != loc64.length || GETSIG(loc64) != ZIP64_LOCSIG) { + return end; + } + long end64pos = ZIP64_LOCOFF(loc64); + byte[] end64buf = new byte[ZIP64_ENDHDR]; + if (readFullyAt(end64buf, 0, end64buf.length, end64pos) + != end64buf.length || GETSIG(end64buf) != ZIP64_ENDSIG) { + return end; + } + // end64 found, re-calcualte everything. + end.cenlen = ZIP64_ENDSIZ(end64buf); + end.cenoff = ZIP64_ENDOFF(end64buf); + end.centot = (int)ZIP64_ENDTOT(end64buf); // assume total < 2g + end.endpos = end64pos; + } catch (IOException x) {} // no zip64 loc/end + } + return end; + } + } + } + zerror("zip END header not found"); + return null; //make compiler happy + } + + // Reads zip file central directory. + private void initCEN(int knownTotal) throws IOException { + if (knownTotal == -1) { + End end = findEND(); + if (end.endpos == 0) { + locpos = 0; + total = 0; + entries = new int[0]; + cen = null; + return; // only END header present + } + if (end.cenlen > end.endpos) + zerror("invalid END header (bad central directory size)"); + long cenpos = end.endpos - end.cenlen; // position of CEN table + // Get position of first local file (LOC) header, taking into + // account that there may be a stub prefixed to the zip file. + locpos = cenpos - end.cenoff; + if (locpos < 0) { + zerror("invalid END header (bad central directory offset)"); + } + // read in the CEN and END + cen = new byte[(int)(end.cenlen + ENDHDR)]; + if (readFullyAt(cen, 0, cen.length, cenpos) != end.cenlen + ENDHDR) { + zerror("read CEN tables failed"); + } + total = end.centot; + } else { + total = knownTotal; + } + // hash table for entries + entries = new int[total * 3]; + tablelen = ((total/2) | 1); // Odd -> fewer collisions + table = new int[tablelen]; + Arrays.fill(table, ZIP_ENDCHAIN); + int idx = 0; + int hash = 0; + int next = -1; + + // list for all meta entries + metanames = new ArrayList<>(); + + // Iterate through the entries in the central directory + int i = 0; + int hsh = 0; + int pos = 0; + int limit = cen.length - ENDHDR; + while (pos + CENHDR <= limit) { + if (i >= total) { + // This will only happen if the zip file has an incorrect + // ENDTOT field, which usually means it contains more than + // 65535 entries. + initCEN(countCENHeaders(cen, limit)); + return; + } + if (CENSIG(cen, pos) != CENSIG) + zerror("invalid CEN header (bad signature)"); + int method = CENHOW(cen, pos); + int nlen = CENNAM(cen, pos); + int elen = CENEXT(cen, pos); + int clen = CENCOM(cen, pos); + if ((CENFLG(cen, pos) & 1) != 0) + zerror("invalid CEN header (encrypted entry)"); + if (method != STORED && method != DEFLATED) + zerror("invalid CEN header (bad compression method: " + method + ")"); + if (pos + CENHDR + nlen > limit) + zerror("invalid CEN header (bad header size)"); + // Record the CEN offset and the name hash in our hash cell. + hash = hashN(cen, pos + CENHDR, nlen); + hsh = (hash & 0x7fffffff) % tablelen; + next = table[hsh]; + table[hsh] = idx; + idx = addEntry(idx, hash, next, pos); + // Adds name to metanames. + if (isMetaName(cen, pos + CENHDR, nlen)) { + metanames.add(pos); + } + // skip ext and comment + pos += (CENHDR + nlen + elen + clen); + i++; + } + total = i; + if (pos + ENDHDR != cen.length) { + zerror("invalid CEN header (bad header size)"); + } + } + + private static void zerror(String msg) throws ZipException { + throw new ZipException(msg); + } + + /* + * Returns the {@code pos} of the zip cen entry corresponding to the + * specified entry name, or -1 if not found. + */ + private int getEntryPos(byte[] name, boolean addSlash) { + if (total == 0) { + return -1; + } + int hsh = hashN(name, 0, name.length); + int idx = table[(hsh & 0x7fffffff) % tablelen]; + /* + * This while loop is an optimization where a double lookup + * for name and name+/ is being performed. The name char + * array has enough room at the end to try again with a + * slash appended if the first table lookup does not succeed. + */ + while(true) { + /* + * Search down the target hash chain for a entry whose + * 32 bit hash matches the hashed name. + */ + while (idx != ZIP_ENDCHAIN) { + if (getEntryHash(idx) == hsh) { + // The CEN name must match the specfied one + int pos = getEntryPos(idx); + if (name.length == CENNAM(cen, pos)) { + boolean matched = true; + int nameoff = pos + CENHDR; + for (int i = 0; i < name.length; i++) { + if (name[i] != cen[nameoff++]) { + matched = false; + break; + } + } + if (matched) { + return pos; + } + } + } + idx = getEntryNext(idx); + } + /* If not addSlash, or slash is already there, we are done */ + if (!addSlash || name[name.length - 1] == '/') { + return -1; + } + /* Add slash and try once more */ + name = Arrays.copyOf(name, name.length + 1); + name[name.length - 1] = '/'; + hsh = hash_append(hsh, (byte)'/'); + //idx = table[hsh % tablelen]; + idx = table[(hsh & 0x7fffffff) % tablelen]; + addSlash = false; + } + } + + private static byte[] metainf = new byte[] { + 'M', 'E', 'T', 'A', '-', 'I' , 'N', 'F', '/', + }; + + /* + * Returns true if the specified entry's name begins with the string + * "META-INF/" irrespective of case. + */ + private static boolean isMetaName(byte[] name, int off, int len) { + if (len < 9 || (name[off] != 'M' && name[off] != 'm')) { // sizeof("META-INF/") - 1 + return false; + } + off++; + for (int i = 1; i < metainf.length; i++) { + byte c = name[off++]; + // Avoid toupper; it's locale-dependent + if (c >= 'a' && c <= 'z') { + c += 'A' - 'a'; + } + if (metainf[i] != c) { + return false; + } + } + return true; + } + + /* + * Counts the number of CEN headers in a central directory extending + * from BEG to END. Might return a bogus answer if the zip file is + * corrupt, but will not crash. + */ + static int countCENHeaders(byte[] cen, int end) { + int count = 0; + int pos = 0; + while (pos + CENHDR <= end) { + count++; + pos += (CENHDR + CENNAM(cen, pos) + CENEXT(cen, pos) + CENCOM(cen, pos)); + } + return count; + } + } } diff --git a/jdk/src/java.base/share/classes/java/util/zip/ZipUtils.java b/jdk/src/java.base/share/classes/java/util/zip/ZipUtils.java index 81882fdcec6..a6632f0fa83 100644 --- a/jdk/src/java.base/share/classes/java/util/zip/ZipUtils.java +++ b/jdk/src/java.base/share/classes/java/util/zip/ZipUtils.java @@ -31,6 +31,8 @@ import java.time.LocalDateTime; import java.time.ZoneId; import java.util.concurrent.TimeUnit; +import static java.util.zip.ZipConstants.ENDHDR; + class ZipUtils { // used to adjust values between Windows and java epoch @@ -133,7 +135,7 @@ class ZipUtils { * The bytes are assumed to be in Intel (little-endian) byte order. */ public static final int get16(byte b[], int off) { - return Byte.toUnsignedInt(b[off]) | (Byte.toUnsignedInt(b[off+1]) << 8); + return (b[off] & 0xff) | ((b[off + 1] & 0xff) << 8); } /** @@ -160,4 +162,79 @@ class ZipUtils { public static final int get32S(byte b[], int off) { return (get16(b, off) | (get16(b, off+2) << 16)); } + + // fields access methods + static final int CH(byte[] b, int n) { + return b[n] & 0xff ; + } + + static final int SH(byte[] b, int n) { + return (b[n] & 0xff) | ((b[n + 1] & 0xff) << 8); + } + + static final long LG(byte[] b, int n) { + return ((SH(b, n)) | (SH(b, n + 2) << 16)) & 0xffffffffL; + } + + static final long LL(byte[] b, int n) { + return (LG(b, n)) | (LG(b, n + 4) << 32); + } + + static final long GETSIG(byte[] b) { + return LG(b, 0); + } + + // local file (LOC) header fields + static final long LOCSIG(byte[] b) { return LG(b, 0); } // signature + static final int LOCVER(byte[] b) { return SH(b, 4); } // version needed to extract + static final int LOCFLG(byte[] b) { return SH(b, 6); } // general purpose bit flags + static final int LOCHOW(byte[] b) { return SH(b, 8); } // compression method + static final long LOCTIM(byte[] b) { return LG(b, 10);} // modification time + static final long LOCCRC(byte[] b) { return LG(b, 14);} // crc of uncompressed data + static final long LOCSIZ(byte[] b) { return LG(b, 18);} // compressed data size + static final long LOCLEN(byte[] b) { return LG(b, 22);} // uncompressed data size + static final int LOCNAM(byte[] b) { return SH(b, 26);} // filename length + static final int LOCEXT(byte[] b) { return SH(b, 28);} // extra field length + + // extra local (EXT) header fields + static final long EXTCRC(byte[] b) { return LG(b, 4);} // crc of uncompressed data + static final long EXTSIZ(byte[] b) { return LG(b, 8);} // compressed size + static final long EXTLEN(byte[] b) { return LG(b, 12);} // uncompressed size + + // end of central directory header (END) fields + static final int ENDSUB(byte[] b) { return SH(b, 8); } // number of entries on this disk + static final int ENDTOT(byte[] b) { return SH(b, 10);} // total number of entries + static final long ENDSIZ(byte[] b) { return LG(b, 12);} // central directory size + static final long ENDOFF(byte[] b) { return LG(b, 16);} // central directory offset + static final int ENDCOM(byte[] b) { return SH(b, 20);} // size of zip file comment + static final int ENDCOM(byte[] b, int off) { return SH(b, off + 20);} + + // zip64 end of central directory recoder fields + static final long ZIP64_ENDTOD(byte[] b) { return LL(b, 24);} // total number of entries on disk + static final long ZIP64_ENDTOT(byte[] b) { return LL(b, 32);} // total number of entries + static final long ZIP64_ENDSIZ(byte[] b) { return LL(b, 40);} // central directory size + static final long ZIP64_ENDOFF(byte[] b) { return LL(b, 48);} // central directory offset + static final long ZIP64_LOCOFF(byte[] b) { return LL(b, 8);} // zip64 end offset + + // central directory header (CEN) fields + static final long CENSIG(byte[] b, int pos) { return LG(b, pos + 0); } + static final int CENVEM(byte[] b, int pos) { return SH(b, pos + 4); } + static final int CENVER(byte[] b, int pos) { return SH(b, pos + 6); } + static final int CENFLG(byte[] b, int pos) { return SH(b, pos + 8); } + static final int CENHOW(byte[] b, int pos) { return SH(b, pos + 10);} + static final long CENTIM(byte[] b, int pos) { return LG(b, pos + 12);} + static final long CENCRC(byte[] b, int pos) { return LG(b, pos + 16);} + static final long CENSIZ(byte[] b, int pos) { return LG(b, pos + 20);} + static final long CENLEN(byte[] b, int pos) { return LG(b, pos + 24);} + static final int CENNAM(byte[] b, int pos) { return SH(b, pos + 28);} + static final int CENEXT(byte[] b, int pos) { return SH(b, pos + 30);} + static final int CENCOM(byte[] b, int pos) { return SH(b, pos + 32);} + static final int CENDSK(byte[] b, int pos) { return SH(b, pos + 34);} + static final int CENATT(byte[] b, int pos) { return SH(b, pos + 36);} + static final long CENATX(byte[] b, int pos) { return LG(b, pos + 38);} + static final long CENOFF(byte[] b, int pos) { return LG(b, pos + 42);} + + // The END header is followed by a variable length comment of size < 64k. + static final long END_MAXLEN = 0xFFFF + ENDHDR; + static final int READBLOCKSZ = 128; } diff --git a/jdk/src/java.base/share/classes/javax/security/cert/package-info.java b/jdk/src/java.base/share/classes/javax/security/cert/package-info.java index a1d7a34fae1..753598ef534 100644 --- a/jdk/src/java.base/share/classes/javax/security/cert/package-info.java +++ b/jdk/src/java.base/share/classes/javax/security/cert/package-info.java @@ -26,16 +26,16 @@ /** * Provides classes for public key certificates. * - * This package has been deprecated. These classes include a simplified - * version of the {@code java.security.cert} package. These classes were - * developed as part of the Java Secure Socket - * Extension (JSSE). When JSSE was added to the J2SE version 1.4, this - * package was added for backward-compatibility reasons only. + * The classes in this package have been deprecated. New classes should not + * be added to this package. These classes include a simplified version of + * the {@code java.security.cert} package. These classes were developed as + * part of the Java Secure Socket Extension (JSSE). When JSSE was added to + * the J2SE version 1.4, this package was added for backward-compatibility + * reasons only. * * New applications should not use this package, but rather * {@code java.security.cert}. * * @since 1.4 */ -@Deprecated package javax.security.cert; diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaUtilZipFileAccess.java b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaUtilZipFileAccess.java index df10fda22ca..9b9b1e85788 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaUtilZipFileAccess.java +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaUtilZipFileAccess.java @@ -29,5 +29,6 @@ import java.util.zip.ZipFile; public interface JavaUtilZipFileAccess { public boolean startsWithLocHeader(ZipFile zip); + public String[] getMetaInfEntryNames(ZipFile zip); } diff --git a/jdk/src/java.base/share/classes/sun/misc/VM.java b/jdk/src/java.base/share/classes/sun/misc/VM.java index 0c75f10c657..37dc3b38fa1 100644 --- a/jdk/src/java.base/share/classes/sun/misc/VM.java +++ b/jdk/src/java.base/share/classes/sun/misc/VM.java @@ -274,9 +274,6 @@ public class VM { // used by java.lang.Integer.IntegerCache props.remove("java.lang.Integer.IntegerCache.high"); - // used by java.util.zip.ZipFile - props.remove("sun.zip.disableMemoryMapping"); - // used by sun.launcher.LauncherHelper props.remove("sun.java.launcher.diag"); } diff --git a/jdk/src/java.base/share/native/libzip/ZipFile.c b/jdk/src/java.base/share/native/libzip/ZipFile.c deleted file mode 100644 index d7a21a6cf88..00000000000 --- a/jdk/src/java.base/share/native/libzip/ZipFile.c +++ /dev/null @@ -1,406 +0,0 @@ -/* - * 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 - * 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. - */ - -/* - * Native method support for java.util.zip.ZipFile - */ - -#include -#include -#include -#include -#include -#include -#include "jlong.h" -#include "jvm.h" -#include "jni.h" -#include "jni_util.h" -#include "zip_util.h" -#ifdef WIN32 -#include "io_util_md.h" -#else -#include "io_util.h" -#endif - -#include "java_util_zip_ZipFile.h" -#include "java_util_jar_JarFile.h" - -#define DEFLATED 8 -#define STORED 0 - -static jfieldID jzfileID; - -static int OPEN_READ = java_util_zip_ZipFile_OPEN_READ; -static int OPEN_DELETE = java_util_zip_ZipFile_OPEN_DELETE; - - -/* - * Declare library specific JNI_Onload entry if static build - */ -DEF_STATIC_JNI_OnLoad - -JNIEXPORT void JNICALL -Java_java_util_zip_ZipFile_initIDs(JNIEnv *env, jclass cls) -{ - jzfileID = (*env)->GetFieldID(env, cls, "jzfile", "J"); - assert(jzfileID != 0); -} - -static void -ThrowZipException(JNIEnv *env, const char *msg) -{ - jstring s = NULL; - jobject x; - - if (msg != NULL) { - s = JNU_NewStringPlatform(env, msg); - } - if (s != NULL) { - x = JNU_NewObjectByName(env, - "java/util/zip/ZipException", - "(Ljava/lang/String;)V", s); - if (x != NULL) { - (*env)->Throw(env, x); - } - } -} - -JNIEXPORT jlong JNICALL -Java_java_util_zip_ZipFile_open(JNIEnv *env, jclass cls, jstring name, - jint mode, jlong lastModified, - jboolean usemmap) -{ - const char *path = JNU_GetStringPlatformChars(env, name, 0); - char *msg = 0; - jlong result = 0; - int flag = 0; - jzfile *zip = 0; - - if (mode & OPEN_READ) flag |= O_RDONLY; - - if (path != 0) { - zip = ZIP_Get_From_Cache(path, &msg, lastModified); - if (zip == 0 && msg == 0) { - ZFILE zfd = 0; -#ifdef WIN32 - if (mode & OPEN_DELETE) flag |= O_TEMPORARY; - zfd = winFileHandleOpen(env, name, flag); - if (zfd == -1) { - /* Exception already pending. */ - goto finally; - } -#else - zfd = open(path, flag, 0); - if (zfd < 0) { - throwFileNotFoundException(env, name); - goto finally; - } - if (mode & OPEN_DELETE) { - unlink(path); - } -#endif - zip = ZIP_Put_In_Cache0(path, zfd, &msg, lastModified, usemmap); - } - - if (zip != 0) { - result = ptr_to_jlong(zip); - } else if (msg != 0) { - ThrowZipException(env, msg); - free(msg); - } else if (errno == ENOMEM) { - JNU_ThrowOutOfMemoryError(env, 0); - } else { - ThrowZipException(env, "error in opening zip file"); - } -finally: - JNU_ReleaseStringPlatformChars(env, name, path); - } - return result; -} - -JNIEXPORT jint JNICALL -Java_java_util_zip_ZipFile_getTotal(JNIEnv *env, jclass cls, jlong zfile) -{ - jzfile *zip = jlong_to_ptr(zfile); - - return zip->total; -} - -JNIEXPORT jboolean JNICALL -Java_java_util_zip_ZipFile_startsWithLOC(JNIEnv *env, jclass cls, jlong zfile) -{ - jzfile *zip = jlong_to_ptr(zfile); - - return zip->locsig; -} - -JNIEXPORT void JNICALL -Java_java_util_zip_ZipFile_close(JNIEnv *env, jclass cls, jlong zfile) -{ - ZIP_Close(jlong_to_ptr(zfile)); -} - -JNIEXPORT jlong JNICALL -Java_java_util_zip_ZipFile_getEntry(JNIEnv *env, jclass cls, jlong zfile, - jbyteArray name, jboolean addSlash) -{ -#define MAXNAME 1024 - jzfile *zip = jlong_to_ptr(zfile); - jsize ulen = (*env)->GetArrayLength(env, name); - char buf[MAXNAME+2], *path; - jzentry *ze; - - if (ulen > MAXNAME) { - path = malloc(ulen + 2); - if (path == 0) { - JNU_ThrowOutOfMemoryError(env, 0); - return 0; - } - } else { - path = buf; - } - (*env)->GetByteArrayRegion(env, name, 0, ulen, (jbyte *)path); - path[ulen] = '\0'; - ze = ZIP_GetEntry2(zip, path, (jint)ulen, addSlash); - if (path != buf) { - free(path); - } - return ptr_to_jlong(ze); -} - -JNIEXPORT void JNICALL -Java_java_util_zip_ZipFile_freeEntry(JNIEnv *env, jclass cls, jlong zfile, - jlong zentry) -{ - jzfile *zip = jlong_to_ptr(zfile); - jzentry *ze = jlong_to_ptr(zentry); - ZIP_FreeEntry(zip, ze); -} - -JNIEXPORT jlong JNICALL -Java_java_util_zip_ZipFile_getNextEntry(JNIEnv *env, jclass cls, jlong zfile, - jint n) -{ - jzentry *ze = ZIP_GetNextEntry(jlong_to_ptr(zfile), n); - return ptr_to_jlong(ze); -} - -JNIEXPORT jint JNICALL -Java_java_util_zip_ZipFile_getEntryMethod(JNIEnv *env, jclass cls, jlong zentry) -{ - jzentry *ze = jlong_to_ptr(zentry); - return ze->csize != 0 ? DEFLATED : STORED; -} - -JNIEXPORT jint JNICALL -Java_java_util_zip_ZipFile_getEntryFlag(JNIEnv *env, jclass cls, jlong zentry) -{ - jzentry *ze = jlong_to_ptr(zentry); - return ze->flag; -} - -JNIEXPORT jlong JNICALL -Java_java_util_zip_ZipFile_getEntryCSize(JNIEnv *env, jclass cls, jlong zentry) -{ - jzentry *ze = jlong_to_ptr(zentry); - return ze->csize != 0 ? ze->csize : ze->size; -} - -JNIEXPORT jlong JNICALL -Java_java_util_zip_ZipFile_getEntrySize(JNIEnv *env, jclass cls, jlong zentry) -{ - jzentry *ze = jlong_to_ptr(zentry); - return ze->size; -} - -JNIEXPORT jlong JNICALL -Java_java_util_zip_ZipFile_getEntryTime(JNIEnv *env, jclass cls, jlong zentry) -{ - jzentry *ze = jlong_to_ptr(zentry); - return (jlong)ze->time & 0xffffffffUL; -} - -JNIEXPORT jlong JNICALL -Java_java_util_zip_ZipFile_getEntryCrc(JNIEnv *env, jclass cls, jlong zentry) -{ - jzentry *ze = jlong_to_ptr(zentry); - return (jlong)ze->crc & 0xffffffffUL; -} - -JNIEXPORT jbyteArray JNICALL -Java_java_util_zip_ZipFile_getCommentBytes(JNIEnv *env, - jclass cls, - jlong zfile) -{ - jzfile *zip = jlong_to_ptr(zfile); - jbyteArray jba = NULL; - - if (zip->comment != NULL) { - if ((jba = (*env)->NewByteArray(env, zip->clen)) == NULL) - return NULL; - (*env)->SetByteArrayRegion(env, jba, 0, zip->clen, (jbyte*)zip->comment); - } - return jba; -} - -JNIEXPORT jbyteArray JNICALL -Java_java_util_zip_ZipFile_getEntryBytes(JNIEnv *env, - jclass cls, - jlong zentry, jint type) -{ - jzentry *ze = jlong_to_ptr(zentry); - int len = 0; - jbyteArray jba = NULL; - switch (type) { - case java_util_zip_ZipFile_JZENTRY_NAME: - if (ze->name != 0) { - len = (int)ze->nlen; - // Unlike for extra and comment, we never return null for - // an (extremely rarely seen) empty name - if ((jba = (*env)->NewByteArray(env, len)) == NULL) - break; - (*env)->SetByteArrayRegion(env, jba, 0, len, (jbyte *)ze->name); - } - break; - case java_util_zip_ZipFile_JZENTRY_EXTRA: - if (ze->extra != 0) { - unsigned char *bp = (unsigned char *)&ze->extra[0]; - len = (bp[0] | (bp[1] << 8)); - if (len <= 0 || (jba = (*env)->NewByteArray(env, len)) == NULL) - break; - (*env)->SetByteArrayRegion(env, jba, 0, len, &ze->extra[2]); - } - break; - case java_util_zip_ZipFile_JZENTRY_COMMENT: - if (ze->comment != 0) { - len = (int)strlen(ze->comment); - if (len == 0 || (jba = (*env)->NewByteArray(env, len)) == NULL) - break; - (*env)->SetByteArrayRegion(env, jba, 0, len, (jbyte*)ze->comment); - } - break; - } - return jba; -} - -JNIEXPORT jint JNICALL -Java_java_util_zip_ZipFile_read(JNIEnv *env, jclass cls, jlong zfile, - jlong zentry, jlong pos, jbyteArray bytes, - jint off, jint len) -{ - jzfile *zip = jlong_to_ptr(zfile); - char *msg; - -#define BUFSIZE 8192 - /* copy via tmp stack buffer: */ - jbyte buf[BUFSIZE]; - - if (len > BUFSIZE) { - len = BUFSIZE; - } - - ZIP_Lock(zip); - len = ZIP_Read(zip, jlong_to_ptr(zentry), pos, buf, len); - msg = zip->msg; - ZIP_Unlock(zip); - if (len != -1) { - (*env)->SetByteArrayRegion(env, bytes, off, len, buf); - } - - if (len == -1) { - if (msg != 0) { - ThrowZipException(env, msg); - } else { - char errmsg[128]; - sprintf(errmsg, "errno: %d, error: %s\n", - errno, "Error reading ZIP file"); - JNU_ThrowIOExceptionWithLastError(env, errmsg); - } - } - - return len; -} - -/* - * Returns an array of strings representing the names of all entries - * that begin with "META-INF/" (case ignored). This native method is - * used in JarFile as an optimization when looking up manifest and - * signature file entries. Returns null if no entries were found. - */ -JNIEXPORT jobjectArray JNICALL -Java_java_util_jar_JarFile_getMetaInfEntryNames(JNIEnv *env, jobject obj) -{ - jlong zfile = (*env)->GetLongField(env, obj, jzfileID); - jzfile *zip; - int i, count; - jobjectArray result = 0; - - if (zfile == 0) { - JNU_ThrowByName(env, - "java/lang/IllegalStateException", "zip file closed"); - return NULL; - } - zip = jlong_to_ptr(zfile); - - /* count the number of valid ZIP metanames */ - count = 0; - if (zip->metanames != 0) { - for (i = 0; i < zip->metacount; i++) { - if (zip->metanames[i] != 0) { - count++; - } - } - } - - /* If some names were found then build array of java strings */ - if (count > 0) { - jclass cls = JNU_ClassString(env); - CHECK_NULL_RETURN(cls, NULL); - result = (*env)->NewObjectArray(env, count, cls, 0); - CHECK_NULL_RETURN(result, NULL); - if (result != 0) { - for (i = 0; i < count; i++) { - jstring str = (*env)->NewStringUTF(env, zip->metanames[i]); - if (str == 0) { - break; - } - (*env)->SetObjectArrayElement(env, result, i, str); - (*env)->DeleteLocalRef(env, str); - } - } - } - return result; -} - -JNIEXPORT jstring JNICALL -Java_java_util_zip_ZipFile_getZipMessage(JNIEnv *env, jclass cls, jlong zfile) -{ - jzfile *zip = jlong_to_ptr(zfile); - char *msg = zip->msg; - if (msg == NULL) { - return NULL; - } - return JNU_NewStringPlatform(env, msg); -} diff --git a/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java b/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java index 7027bd96c2a..004cb4e3bef 100644 --- a/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java +++ b/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -309,7 +309,12 @@ class SolarisAclFileAttributeView checkAccess(file, true, false); // open file (will fail if file is a link and not following links) - int fd = file.openForAttributeAccess(followLinks); + int fd = -1; + try { + fd = file.openForAttributeAccess(followLinks); + } catch (UnixException x) { + x.rethrowAsIOException(file); + } try { long address = unsafe.allocateMemory(SIZEOF_ACE_T * MAX_ACL_ENTRIES); try { @@ -338,7 +343,12 @@ class SolarisAclFileAttributeView checkAccess(file, false, true); // open file (will fail if file is a link and not following links) - int fd = file.openForAttributeAccess(followLinks); + int fd = -1; + try { + fd = file.openForAttributeAccess(followLinks); + } catch (UnixException x) { + x.rethrowAsIOException(file); + } try { // SECURITY: need to copy list as can change during processing acl = new ArrayList(acl); diff --git a/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisUserDefinedFileAttributeView.java b/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisUserDefinedFileAttributeView.java index d5edf3f3962..baa92cddb96 100644 --- a/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisUserDefinedFileAttributeView.java +++ b/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisUserDefinedFileAttributeView.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -71,9 +71,11 @@ class SolarisUserDefinedFileAttributeView if (System.getSecurityManager() != null) checkAccess(file.getPathForPermissionCheck(), true, false); - int fd = file.openForAttributeAccess(followLinks); + int fd = -1; try { try { + fd = file.openForAttributeAccess(followLinks); + // open extended attribute directory int dfd = openat(fd, HERE, (O_RDONLY|O_XATTR), 0); long dp; @@ -112,9 +114,11 @@ class SolarisUserDefinedFileAttributeView if (System.getSecurityManager() != null) checkAccess(file.getPathForPermissionCheck(), true, false); - int fd = file.openForAttributeAccess(followLinks); + int fd = -1; try { try { + fd = file.openForAttributeAccess(followLinks); + // open attribute file int afd = openat(fd, nameAsBytes(file,name), (O_RDONLY|O_XATTR), 0); try { @@ -142,9 +146,11 @@ class SolarisUserDefinedFileAttributeView if (System.getSecurityManager() != null) checkAccess(file.getPathForPermissionCheck(), true, false); - int fd = file.openForAttributeAccess(followLinks); + int fd = -1; try { try { + fd = file.openForAttributeAccess(followLinks); + // open attribute file int afd = openat(fd, nameAsBytes(file,name), (O_RDONLY|O_XATTR), 0); @@ -181,9 +187,11 @@ class SolarisUserDefinedFileAttributeView if (System.getSecurityManager() != null) checkAccess(file.getPathForPermissionCheck(), false, true); - int fd = file.openForAttributeAccess(followLinks); + int fd = -1; try { try { + fd = file.openForAttributeAccess(followLinks); + // open/create attribute file int afd = openat(fd, nameAsBytes(file,name), (O_CREAT|O_WRONLY|O_TRUNC|O_XATTR), @@ -217,8 +225,10 @@ class SolarisUserDefinedFileAttributeView if (System.getSecurityManager() != null) checkAccess(file.getPathForPermissionCheck(), false, true); - int fd = file.openForAttributeAccess(followLinks); + int fd = -1; try { + fd = file.openForAttributeAccess(followLinks); + int dfd = openat(fd, HERE, (O_RDONLY|O_XATTR), 0); try { unlinkat(dfd, nameAsBytes(file,name), 0); diff --git a/jdk/src/java.base/unix/classes/sun/nio/fs/UnixException.java b/jdk/src/java.base/unix/classes/sun/nio/fs/UnixException.java index 9481a75d891..22a41ebccc4 100644 --- a/jdk/src/java.base/unix/classes/sun/nio/fs/UnixException.java +++ b/jdk/src/java.base/unix/classes/sun/nio/fs/UnixException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -86,6 +86,9 @@ class UnixException extends Exception { return new NoSuchFileException(file, other, null); if (errno() == UnixConstants.EEXIST) return new FileAlreadyExistsException(file, other, null); + if (errno() == UnixConstants.ELOOP) + return new FileSystemException(file, other, errorString() + + " or unable to access attributes of symbolic link"); // fallback to the more general exception return new FileSystemException(file, other, errorString()); diff --git a/jdk/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java b/jdk/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java index 89d94aa02a8..6d43c0f4e95 100644 --- a/jdk/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java +++ b/jdk/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -71,14 +71,30 @@ class UnixFileAttributeViews { // permission check file.checkWrite(); - int fd = file.openForAttributeAccess(followLinks); + boolean haveFd = false; + boolean useFutimes = false; + int fd = -1; + try { + fd = file.openForAttributeAccess(followLinks); + if (fd != -1) { + haveFd = true; + useFutimes = futimesSupported(); + } + } catch (UnixException x) { + if (x.errno() != UnixConstants.ENXIO) { + x.rethrowAsIOException(file); + } + } + try { // assert followLinks || !UnixFileAttributes.get(fd).isSymbolicLink(); // if not changing both attributes then need existing attributes if (lastModifiedTime == null || lastAccessTime == null) { try { - UnixFileAttributes attrs = UnixFileAttributes.get(fd); + UnixFileAttributes attrs = haveFd ? + UnixFileAttributes.get(fd) : + UnixFileAttributes.get(file, followLinks); if (lastModifiedTime == null) lastModifiedTime = attrs.lastModifiedTime(); if (lastAccessTime == null) @@ -94,7 +110,7 @@ class UnixFileAttributeViews { boolean retry = false; try { - if (futimesSupported()) { + if (useFutimes) { futimes(fd, accessValue, modValue); } else { utimes(file, accessValue, modValue); @@ -113,7 +129,7 @@ class UnixFileAttributeViews { if (modValue < 0L) modValue = 0L; if (accessValue < 0L) accessValue= 0L; try { - if (futimesSupported()) { + if (useFutimes) { futimes(fd, accessValue, modValue); } else { utimes(file, accessValue, modValue); diff --git a/jdk/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java b/jdk/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java index b84fa5c3861..c64374125cb 100644 --- a/jdk/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java +++ b/jdk/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -91,9 +91,14 @@ class UnixNativeDispatcher { throws UnixException; /** - * close(int filedes) + * close(int filedes). If fd is -1 this is a no-op. */ - static native void close(int fd); + static void close(int fd) { + if (fd != -1) { + close0(fd); + } + } + private static native void close0(int fd); /** * FILE* fopen(const char *filename, const char* mode); diff --git a/jdk/src/java.base/unix/classes/sun/nio/fs/UnixPath.java b/jdk/src/java.base/unix/classes/sun/nio/fs/UnixPath.java index b219764d3e7..8382c8cdfe8 100644 --- a/jdk/src/java.base/unix/classes/sun/nio/fs/UnixPath.java +++ b/jdk/src/java.base/unix/classes/sun/nio/fs/UnixPath.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -764,11 +764,12 @@ class UnixPath implements Path { // -- file operations -- // package-private - int openForAttributeAccess(boolean followLinks) throws IOException { + int openForAttributeAccess(boolean followLinks) throws UnixException { int flags = O_RDONLY; if (!followLinks) { if (O_NOFOLLOW == 0) - throw new IOException("NOFOLLOW_LINKS is not supported on this platform"); + throw new UnixException + ("NOFOLLOW_LINKS is not supported on this platform"); flags |= O_NOFOLLOW; } try { @@ -778,12 +779,7 @@ class UnixPath implements Path { if (getFileSystem().isSolaris() && x.errno() == EINVAL) x.setError(ELOOP); - if (x.errno() == ELOOP) - throw new FileSystemException(getPathForExceptionMessage(), null, - x.getMessage() + " or unable to access attributes of symbolic link"); - - x.rethrowAsIOException(this); - return -1; // keep compile happy + throw x; } } 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 262986f9c05..7e6e5286473 100644 --- a/jdk/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c +++ b/jdk/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -408,7 +408,7 @@ Java_sun_nio_fs_UnixNativeDispatcher_openat0(JNIEnv* env, jclass this, jint dfd, } JNIEXPORT void JNICALL -Java_sun_nio_fs_UnixNativeDispatcher_close(JNIEnv* env, jclass this, jint fd) { +Java_sun_nio_fs_UnixNativeDispatcher_close0(JNIEnv* env, jclass this, jint fd) { int err; /* TDB - need to decide if EIO and other errors should cause exception */ RESTARTABLE(close((int)fd), err); diff --git a/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-atomic-private.hh b/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-atomic-private.hh index 778e30bc2e8..fc6bbf0d40b 100644 --- a/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-atomic-private.hh +++ b/jdk/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-atomic-private.hh @@ -119,6 +119,31 @@ typedef unsigned int hb_atomic_int_impl_t; #define hb_atomic_ptr_impl_cmpexch(P,O,N) ( ({__machine_rw_barrier ();}), atomic_cas_ptr ((void **) (P), (void *) (O), (void *) (N)) == (void *) (O) ? true : false) +#elif !defined(HB_NO_MT) && defined(_AIX) && defined(__IBMCPP__) + +#include + + +static inline int hb_fetch_and_add(volatile int* AI, unsigned int V) { + __lwsync(); + int result = __fetch_and_add(AI, V); + __isync(); + return result; +} +static inline int hb_compare_and_swaplp(volatile long* P, long O, long N) { + __sync(); + int result = __compare_and_swaplp (P, &O, N); + __sync(); + return result; +} + +typedef int hb_atomic_int_impl_t; +#define HB_ATOMIC_INT_IMPL_INIT(V) (V) +#define hb_atomic_int_impl_add(AI, V) hb_fetch_and_add (&(AI), (V)) + +#define hb_atomic_ptr_impl_get(P) (__sync(), (void *) *(P)) +#define hb_atomic_ptr_impl_cmpexch(P,O,N) hb_compare_and_swaplp ((long*)(P), (long)(O), (long)(N)) + #elif !defined(HB_NO_MT) #define HB_ATOMIC_INT_NIL 1 /* Warn that fallback implementation is in use. */ diff --git a/jdk/src/java.management/share/classes/sun/management/Agent.java b/jdk/src/java.management/share/classes/sun/management/Agent.java index 6a236fd8f3a..5582b428f87 100644 --- a/jdk/src/java.management/share/classes/sun/management/Agent.java +++ b/jdk/src/java.management/share/classes/sun/management/Agent.java @@ -37,9 +37,13 @@ import java.net.InetAddress; import java.net.MalformedURLException; import java.net.UnknownHostException; import java.text.MessageFormat; +import java.util.HashMap; +import java.util.Map; import java.util.MissingResourceException; import java.util.Properties; import java.util.ResourceBundle; +import java.util.function.Function; +import java.util.function.Predicate; import javax.management.remote.JMXConnectorServer; import javax.management.remote.JMXServiceURL; @@ -60,6 +64,30 @@ public class Agent { * Agent status collector strategy class */ private static abstract class StatusCollector { + protected static final Map DEFAULT_PROPS = new HashMap<>(); + + static { + DEFAULT_PROPS.put(ConnectorBootstrap.PropertyNames.PORT, + ConnectorBootstrap.DefaultValues.PORT); + DEFAULT_PROPS.put(ConnectorBootstrap.PropertyNames.USE_LOCAL_ONLY, + ConnectorBootstrap.DefaultValues.USE_LOCAL_ONLY); + DEFAULT_PROPS.put(ConnectorBootstrap.PropertyNames.USE_AUTHENTICATION, + ConnectorBootstrap.DefaultValues.USE_AUTHENTICATION); + DEFAULT_PROPS.put(ConnectorBootstrap.PropertyNames.USE_SSL, + ConnectorBootstrap.DefaultValues.USE_SSL); + DEFAULT_PROPS.put(ConnectorBootstrap.PropertyNames.USE_REGISTRY_SSL, + ConnectorBootstrap.DefaultValues.USE_REGISTRY_SSL); + DEFAULT_PROPS.put(ConnectorBootstrap.PropertyNames.SSL_NEED_CLIENT_AUTH, + ConnectorBootstrap.DefaultValues.SSL_NEED_CLIENT_AUTH); + DEFAULT_PROPS.put(ConnectorBootstrap.PropertyNames.CONFIG_FILE_NAME, + ConnectorBootstrap.DefaultValues.CONFIG_FILE_NAME); + DEFAULT_PROPS.put(ConnectorBootstrap.PropertyNames.PASSWORD_FILE_NAME, + ConnectorBootstrap.DefaultValues.PASSWORD_FILE_NAME); + DEFAULT_PROPS.put(ConnectorBootstrap.PropertyNames.ACCESS_FILE_NAME, + ConnectorBootstrap.DefaultValues.ACCESS_FILE_NAME); + + } + final protected StringBuilder sb = new StringBuilder(); final public String collect() { Properties agentProps = VMSupport.getAgentProperties(); @@ -93,28 +121,49 @@ public class Agent { private void addConnection(boolean remote, JMXServiceURL u) { appendConnectionHeader(remote); addConnectionDetails(u); - if (remote) { - addConfigProperties(); - } + addConfigProperties(); appendConnectionFooter(remote); } private void addConfigProperties() { appendConfigPropsHeader(); - boolean[] first = new boolean[] {true}; - Properties props = configProps != null ? - configProps : getManagementProperties(); - props.entrySet().stream().forEach((e) -> { - String key = (String)e.getKey(); - if (key.startsWith("com.sun.management.")) { - addConfigProp(key, e.getValue(), first[0]); - first[0] = false; + Properties remoteProps = configProps != null ? + configProps : getManagementProperties(); + Map props = new HashMap<>(DEFAULT_PROPS); + + if (remoteProps == null) { + // local connector only + String loc_only = System.getProperty( + ConnectorBootstrap.PropertyNames.USE_LOCAL_ONLY + ); + + if (loc_only != null && + !ConnectorBootstrap.DefaultValues.USE_LOCAL_ONLY.equals(loc_only)) { + props.put( + ConnectorBootstrap.PropertyNames.USE_LOCAL_ONLY, + loc_only + ); } - }); + } else { + props.putAll(remoteProps); + } + + props.entrySet().stream() + .filter(preprocess(Map.Entry::getKey, StatusCollector::isManagementProp)) + .forEach(this::addConfigProp); + appendConfigPropsFooter(); } + private static boolean isManagementProp(Object pName) { + return pName != null && pName.toString().startsWith("com.sun.management."); + } + + private static Predicate preprocess(Function f, Predicate p) { + return (T t) -> p.test(f.apply(t)); + } + abstract protected void addAgentStatus(boolean enabled); abstract protected void appendConnectionsHeader(); abstract protected void appendConnectionsFooter(); @@ -123,7 +172,7 @@ public class Agent { abstract protected void appendConnectionFooter(boolean remote); abstract protected void appendConfigPropsHeader(); abstract protected void appendConfigPropsFooter(); - abstract protected void addConfigProp(String key, Object value, boolean first); + abstract protected void addConfigProp(Map.Entry prop); } /** @@ -159,11 +208,14 @@ public class Agent { } @Override - protected void addConfigProp(String key, Object value, boolean first) { - if (!first) { - sb.append('\n'); + protected void addConfigProp(Map.Entry prop) { + sb.append(" ").append(prop.getKey()).append(" = ") + .append(prop.getValue()); + Object defVal = DEFAULT_PROPS.get(prop.getKey()); + if (defVal != null && defVal.equals(prop.getValue())) { + sb.append(" [default]"); } - sb.append(" ").append(key).append(" = ").append(value); + sb.append("\n"); } @Override diff --git a/jdk/src/jdk.jartool/share/classes/com/sun/jarsigner/ContentSigner.java b/jdk/src/jdk.jartool/share/classes/com/sun/jarsigner/ContentSigner.java index 2911f0bb452..4de54e95083 100644 --- a/jdk/src/jdk.jartool/share/classes/com/sun/jarsigner/ContentSigner.java +++ b/jdk/src/jdk.jartool/share/classes/com/sun/jarsigner/ContentSigner.java @@ -35,7 +35,7 @@ import java.security.cert.CertificateException; * * @since 1.5 * @author Vincent Ryan - * @deprecated This package has been deprecated. + * @deprecated This class has been deprecated. */ @jdk.Exported diff --git a/jdk/src/jdk.jartool/share/classes/com/sun/jarsigner/ContentSignerParameters.java b/jdk/src/jdk.jartool/share/classes/com/sun/jarsigner/ContentSignerParameters.java index 2caef7eda74..3a45318b316 100644 --- a/jdk/src/jdk.jartool/share/classes/com/sun/jarsigner/ContentSignerParameters.java +++ b/jdk/src/jdk.jartool/share/classes/com/sun/jarsigner/ContentSignerParameters.java @@ -34,7 +34,7 @@ import java.util.zip.ZipFile; * * @since 1.5 * @author Vincent Ryan - * @deprecated This package has been deprecated. + * @deprecated This class has been deprecated. */ @jdk.Exported @Deprecated diff --git a/jdk/src/jdk.jartool/share/classes/com/sun/jarsigner/package-info.java b/jdk/src/jdk.jartool/share/classes/com/sun/jarsigner/package-info.java index 278bb57312a..cfed536a9eb 100644 --- a/jdk/src/jdk.jartool/share/classes/com/sun/jarsigner/package-info.java +++ b/jdk/src/jdk.jartool/share/classes/com/sun/jarsigner/package-info.java @@ -30,9 +30,10 @@ * tool by supplying an alternative implementation of * {@link com.sun.jarsigner.ContentSigner}. * - * This package has been deprecated. + * The classes in this package have been deprecated. New classes should not be + * added to this package. Use the {@link jdk.security.jarsigner.JarSigner} API + * to sign JAR files. */ @jdk.Exported -@Deprecated package com.sun.jarsigner; diff --git a/jdk/test/java/math/BigInteger/BigIntegerTest.java b/jdk/test/java/math/BigInteger/BigIntegerTest.java index 1c589fb201b..f8632809fb0 100644 --- a/jdk/test/java/math/BigInteger/BigIntegerTest.java +++ b/jdk/test/java/math/BigInteger/BigIntegerTest.java @@ -26,7 +26,7 @@ * @library /lib/testlibrary/ * @build jdk.testlibrary.* * @run main BigIntegerTest - * @bug 4181191 4161971 4227146 4194389 4823171 4624738 4812225 4837946 4026465 8074460 8078672 + * @bug 4181191 4161971 4227146 4194389 4823171 4624738 4812225 4837946 4026465 8074460 8078672 8032027 * @summary tests methods in BigInteger (use -Dseed=X to set PRNG seed) * @run main/timeout=400 BigIntegerTest * @author madbot @@ -38,8 +38,15 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; +import java.math.BigDecimal; import java.math.BigInteger; import java.util.Random; +import java.util.function.ToIntFunction; +import java.util.stream.Collectors; +import java.util.stream.DoubleStream; +import java.util.stream.IntStream; +import java.util.stream.LongStream; +import java.util.stream.Stream; import jdk.testlibrary.RandomFactory; /** @@ -243,6 +250,146 @@ public class BigIntegerTest { report("square for " + order + " bits", failCount1); } + private static void printErr(String msg) { + System.err.println(msg); + } + + private static int checkResult(BigInteger expected, BigInteger actual, + String failureMessage) { + if (expected.compareTo(actual) != 0) { + printErr(failureMessage + " - expected: " + expected + + ", actual: " + actual); + return 1; + } + return 0; + } + + private static void squareRootSmall() { + int failCount = 0; + + // A negative value should cause an exception. + BigInteger n = BigInteger.ONE.negate(); + BigInteger s; + try { + s = n.sqrt(); + // If sqrt() does not throw an exception that is a failure. + failCount++; + printErr("sqrt() of negative number did not throw an exception"); + } catch (ArithmeticException expected) { + // A negative value should cause an exception and is not a failure. + } + + // A zero value should return BigInteger.ZERO. + failCount += checkResult(BigInteger.ZERO, BigInteger.ZERO.sqrt(), + "sqrt(0) != BigInteger.ZERO"); + + // 1 <= value < 4 should return BigInteger.ONE. + long[] smalls = new long[] {1, 2, 3}; + for (long small : smalls) { + failCount += checkResult(BigInteger.ONE, + BigInteger.valueOf(small).sqrt(), "sqrt("+small+") != 1"); + } + + report("squareRootSmall", failCount); + } + + public static void squareRoot() { + squareRootSmall(); + + ToIntFunction f = (n) -> { + int failCount = 0; + + // square root of n^2 -> n + BigInteger n2 = n.pow(2); + failCount += checkResult(n, n2.sqrt(), "sqrt() n^2 -> n"); + + // square root of n^2 + 1 -> n + BigInteger n2up = n2.add(BigInteger.ONE); + failCount += checkResult(n, n2up.sqrt(), "sqrt() n^2 + 1 -> n"); + + // square root of (n + 1)^2 - 1 -> n + BigInteger up = + n.add(BigInteger.ONE).pow(2).subtract(BigInteger.ONE); + failCount += checkResult(n, up.sqrt(), "sqrt() (n + 1)^2 - 1 -> n"); + + // sqrt(n)^2 <= n + BigInteger s = n.sqrt(); + if (s.multiply(s).compareTo(n) > 0) { + failCount++; + printErr("sqrt(n)^2 > n for n = " + n); + } + + // (sqrt(n) + 1)^2 > n + if (s.add(BigInteger.ONE).pow(2).compareTo(n) <= 0) { + failCount++; + printErr("(sqrt(n) + 1)^2 <= n for n = " + n); + } + + return failCount; + }; + + Stream.Builder sb = Stream.builder(); + int maxExponent = Double.MAX_EXPONENT + 1; + for (int i = 1; i <= maxExponent; i++) { + BigInteger p2 = BigInteger.ONE.shiftLeft(i); + sb.add(p2.subtract(BigInteger.ONE)); + sb.add(p2); + sb.add(p2.add(BigInteger.ONE)); + } + sb.add((new BigDecimal(Double.MAX_VALUE)).toBigInteger()); + sb.add((new BigDecimal(Double.MAX_VALUE)).toBigInteger().add(BigInteger.ONE)); + report("squareRoot for 2^N and 2^N - 1, 1 <= N <= Double.MAX_EXPONENT", + sb.build().collect(Collectors.summingInt(f))); + + IntStream ints = random.ints(SIZE, 4, Integer.MAX_VALUE); + report("squareRoot for int", ints.mapToObj(x -> + BigInteger.valueOf(x)).collect(Collectors.summingInt(f))); + + LongStream longs = random.longs(SIZE, (long)Integer.MAX_VALUE + 1L, + Long.MAX_VALUE); + report("squareRoot for long", longs.mapToObj(x -> + BigInteger.valueOf(x)).collect(Collectors.summingInt(f))); + + DoubleStream doubles = random.doubles(SIZE, + (double) Long.MAX_VALUE + 1.0, Math.sqrt(Double.MAX_VALUE)); + report("squareRoot for double", doubles.mapToObj(x -> + BigDecimal.valueOf(x).toBigInteger()).collect(Collectors.summingInt(f))); + } + + public static void squareRootAndRemainder() { + ToIntFunction g = (n) -> { + int failCount = 0; + BigInteger n2 = n.pow(2); + + // square root of n^2 -> n + BigInteger[] actual = n2.sqrtAndRemainder(); + failCount += checkResult(n, actual[0], "sqrtAndRemainder()[0]"); + failCount += checkResult(BigInteger.ZERO, actual[1], + "sqrtAndRemainder()[1]"); + + // square root of n^2 + 1 -> n + BigInteger n2up = n2.add(BigInteger.ONE); + actual = n2up.sqrtAndRemainder(); + failCount += checkResult(n, actual[0], "sqrtAndRemainder()[0]"); + failCount += checkResult(BigInteger.ONE, actual[1], + "sqrtAndRemainder()[1]"); + + // square root of (n + 1)^2 - 1 -> n + BigInteger up = + n.add(BigInteger.ONE).pow(2).subtract(BigInteger.ONE); + actual = up.sqrtAndRemainder(); + failCount += checkResult(n, actual[0], "sqrtAndRemainder()[0]"); + BigInteger r = up.subtract(n2); + failCount += checkResult(r, actual[1], "sqrtAndRemainder()[1]"); + + return failCount; + }; + + IntStream bits = random.ints(SIZE, 3, Short.MAX_VALUE); + report("sqrtAndRemainder", bits.mapToObj(x -> + BigInteger.valueOf(x)).collect(Collectors.summingInt(g))); + } + public static void arithmetic(int order) { int failCount = 0; @@ -1101,6 +1248,9 @@ public class BigIntegerTest { square(ORDER_KARATSUBA_SQUARE); square(ORDER_TOOM_COOK_SQUARE); + squareRoot(); + squareRootAndRemainder(); + bitCount(); bitLength(); bitOps(order1); diff --git a/jdk/test/java/nio/file/FileSystem/Basic.java b/jdk/test/java/nio/file/FileSystem/Basic.java index 481392929ce..4b02ff498e7 100644 --- a/jdk/test/java/nio/file/FileSystem/Basic.java +++ b/jdk/test/java/nio/file/FileSystem/Basic.java @@ -67,8 +67,6 @@ public class Basic { } catch (ProviderNotFoundException pnfe) { System.out.println("Expected ProviderNotFoundException caught: " + "\"" + pnfe.getMessage() + "\""); - } finally { - FileUtils.deleteFileWithRetry(path); } } diff --git a/jdk/test/java/nio/file/attribute/BasicFileAttributeView/UnixSocketFile.java b/jdk/test/java/nio/file/attribute/BasicFileAttributeView/UnixSocketFile.java new file mode 100644 index 00000000000..caa712ebb2a --- /dev/null +++ b/jdk/test/java/nio/file/attribute/BasicFileAttributeView/UnixSocketFile.java @@ -0,0 +1,133 @@ +/* + * 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 8139133 + * @summary Verify ability to set time attributes of socket files with no device + * @requires os.family == "linux" + */ + +import java.io.File; +import java.io.IOException; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardWatchEventKinds; +import java.nio.file.WatchKey; +import java.nio.file.WatchService; +import java.nio.file.attribute.BasicFileAttributeView; +import java.nio.file.attribute.BasicFileAttributes; +import java.nio.file.attribute.FileTime; + +public class UnixSocketFile { + private static final String TEST_SUB_DIR = "UnixSocketFile"; + private static final String SOCKET_FILE_NAME = "mysocket"; + private static final String CMD_BASE = "nc -lU"; + + public static void main(String[] args) + throws InterruptedException, IOException { + + // Create a new sub-directory of the nominal test directory in which + // 'nc' will create the socket file. + String testSubDir = System.getProperty("test.dir", ".") + + File.separator + TEST_SUB_DIR; + Path socketTestDir = Paths.get(testSubDir); + Files.createDirectory(socketTestDir); + + // Set the path of the socket file. + String socketFilePath = testSubDir + File.separator + + SOCKET_FILE_NAME; + + // Create a process which executes the nc (netcat) utility to create + // a socket file at the indicated location. + Process proc; + FileSystem fs = FileSystems.getDefault(); + try (WatchService ws = fs.newWatchService()) { + // Watch the test sub-directory to receive notification when an + // entry, i.e., the socket file, is added to the sub-directory. + WatchKey wk = socketTestDir.register(ws, + StandardWatchEventKinds.ENTRY_CREATE); + + // Execute the 'nc' command. + proc = Runtime.getRuntime().exec(CMD_BASE + " " + socketFilePath); + + // Wait until the socket file is created. + WatchKey key = ws.take(); + if (key != wk) { + throw new RuntimeException("Unknown entry created - expected: " + + wk.watchable() + ", actual: " + key.watchable()); + } + wk.cancel(); + } + + // Verify that the socket file in fact exists. + Path socketPath = fs.getPath(socketFilePath); + if (!Files.exists(socketPath)) { + throw new RuntimeException("Socket file " + socketFilePath + + " was not created by \"nc\" command."); + } + + // Retrieve the most recent access and modification times of the + // socket file; print the values. + BasicFileAttributeView attributeView = Files.getFileAttributeView( + socketPath, BasicFileAttributeView.class); + BasicFileAttributes oldAttributes = attributeView.readAttributes(); + FileTime oldAccessTime = oldAttributes.lastAccessTime(); + FileTime oldModifiedTime = oldAttributes.lastModifiedTime(); + System.out.println("Old times: " + oldAccessTime + + " " + oldModifiedTime); + + // Calculate the time to which the access and modification times of the + // socket file will be changed. + FileTime newFileTime = + FileTime.fromMillis(oldAccessTime.toMillis() + 1066); + + try { + // Set the access and modification times of the socket file. + attributeView.setTimes(newFileTime, newFileTime, null); + + // Retrieve the updated access and modification times of the + // socket file; print the values. + FileTime newAccessTime = null; + FileTime newModifiedTime = null; + BasicFileAttributes newAttributes = attributeView.readAttributes(); + newAccessTime = newAttributes.lastAccessTime(); + newModifiedTime = newAttributes.lastModifiedTime(); + System.out.println("New times: " + newAccessTime + " " + + newModifiedTime); + + // Verify that the updated times have the expected values. + if ((newAccessTime != null && !newAccessTime.equals(newFileTime)) + || (newModifiedTime != null + && !newModifiedTime.equals(newFileTime))) { + throw new RuntimeException("Failed to set correct times."); + } + } finally { + // Destry the process running netcat and delete the socket file. + proc.destroy(); + Files.delete(socketPath); + } + } +} diff --git a/jdk/test/java/util/Map/MapFactories.java b/jdk/test/java/util/Map/MapFactories.java index 1bdb020680d..b8ff0c9f3f2 100644 --- a/jdk/test/java/util/Map/MapFactories.java +++ b/jdk/test/java/util/Map/MapFactories.java @@ -377,4 +377,13 @@ public class MapFactories { assertEquals(sie.toString(), kvh1.toString()); } + // compile-time test of wildcards + @Test + public void entryWildcardTests() { + Map.Entry e1 = Map.entry(1, 2.0); + Map.Entry e2 = Map.entry(3.0f, 4L); + Map map = Map.ofEntries(e1, e2); + assertEquals(map.size(), 2); + } + } diff --git a/jdk/test/java/util/regex/PatternStreamTest.java b/jdk/test/java/util/regex/PatternStreamTest.java index 349faad034a..1ac3bfd23e8 100644 --- a/jdk/test/java/util/regex/PatternStreamTest.java +++ b/jdk/test/java/util/regex/PatternStreamTest.java @@ -23,7 +23,7 @@ /** * @test - * @bug 8016846 8024341 8071479 + * @bug 8016846 8024341 8071479 8145006 * @summary Unit tests stream and lambda-based methods on Pattern and Matcher * @library ../stream/bootlib/java.base * @build java.util.stream.OpTestCase @@ -42,6 +42,7 @@ import java.util.function.Supplier; import java.util.regex.MatchResult; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; import java.util.stream.LambdaTestHelpers; import java.util.stream.OpTestCase; import java.util.stream.Stream; @@ -185,6 +186,20 @@ public class PatternStreamTest extends OpTestCase { .exercise(); } + @Test + public void testLateBinding() { + Pattern pattern = Pattern.compile(","); + + StringBuilder sb = new StringBuilder("a,b,c,d,e"); + Stream stream = pattern.splitAsStream(sb); + sb.setLength(3); + assertEquals(Arrays.asList("a", "b"), stream.collect(Collectors.toList())); + + stream = pattern.splitAsStream(sb); + sb.append(",f,g"); + assertEquals(Arrays.asList("a", "b", "f", "g"), stream.collect(Collectors.toList())); + } + public void testFailfastMatchResults() { Pattern p = Pattern.compile("X"); Matcher m = p.matcher("XX"); diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CollectorsTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CollectorsTest.java index 07fa5bcb5cf..d07b6eba4a7 100644 --- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CollectorsTest.java +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CollectorsTest.java @@ -56,6 +56,7 @@ import org.testng.annotations.Test; import static java.util.stream.Collectors.collectingAndThen; import static java.util.stream.Collectors.flatMapping; +import static java.util.stream.Collectors.filtering; import static java.util.stream.Collectors.groupingBy; import static java.util.stream.Collectors.groupingByConcurrent; import static java.util.stream.Collectors.mapping; @@ -72,7 +73,7 @@ import static java.util.stream.LambdaTestHelpers.mDoubler; /* * @test - * @bug 8071600 + * @bug 8071600 8144675 * @summary Test for collectors. */ public class CollectorsTest extends OpTestCase { @@ -118,6 +119,23 @@ public class CollectorsTest extends OpTestCase { } } + static class FilteringAssertion extends CollectorAssertion { + private final Predicate filter; + private final CollectorAssertion downstream; + + public FilteringAssertion(Predicate filter, CollectorAssertion downstream) { + this.filter = filter; + this.downstream = downstream; + } + + @Override + void assertValue(R value, Supplier> source, boolean ordered) throws ReflectiveOperationException { + downstream.assertValue(value, + () -> source.get().filter(filter), + ordered); + } + } + static class GroupingByAssertion> extends CollectorAssertion { private final Class clazz; private final Function classifier; @@ -550,6 +568,36 @@ public class CollectorsTest extends OpTestCase { new ToListAssertion<>()))); } + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testGroupingByWithFiltering(String name, TestData.OfRef data) throws ReflectiveOperationException { + Function classifier = i -> i % 3; + Predicate filteringByMod2 = i -> i % 2 == 0; + Predicate filteringByUnder100 = i -> i % 2 < 100; + Predicate filteringByTrue = i -> true; + Predicate filteringByFalse = i -> false; + + exerciseMapCollection(data, + groupingBy(classifier, filtering(filteringByMod2, toList())), + new GroupingByAssertion<>(classifier, HashMap.class, + new FilteringAssertion<>(filteringByMod2, + new ToListAssertion<>()))); + exerciseMapCollection(data, + groupingBy(classifier, filtering(filteringByUnder100, toList())), + new GroupingByAssertion<>(classifier, HashMap.class, + new FilteringAssertion<>(filteringByUnder100, + new ToListAssertion<>()))); + exerciseMapCollection(data, + groupingBy(classifier, filtering(filteringByTrue, toList())), + new GroupingByAssertion<>(classifier, HashMap.class, + new FilteringAssertion<>(filteringByTrue, + new ToListAssertion<>()))); + exerciseMapCollection(data, + groupingBy(classifier, filtering(filteringByFalse, toList())), + new GroupingByAssertion<>(classifier, HashMap.class, + new FilteringAssertion<>(filteringByFalse, + new ToListAssertion<>()))); + } + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) public void testTwoLevelGroupingBy(String name, TestData.OfRef data) throws ReflectiveOperationException { Function classifier = i -> i % 6; diff --git a/jdk/test/java/util/zip/TestZipError.java b/jdk/test/java/util/zip/TestZipError.java index 90d05c03ba3..5448add92da 100644 --- a/jdk/test/java/util/zip/TestZipError.java +++ b/jdk/test/java/util/zip/TestZipError.java @@ -84,9 +84,10 @@ public class TestZipError { try { while (entries.hasMoreElements()) { ze = entries.nextElement(); + zf.getInputStream(ze).readAllBytes(); } fail("Did not get expected exception"); - } catch (ZipError e) { + } catch (ZipException e) { pass(); } catch (InternalError e) { fail("Caught InternalError instead of expected ZipError"); diff --git a/jdk/test/java/util/zip/ZipFile/ReadZip.java b/jdk/test/java/util/zip/ZipFile/ReadZip.java index 1052642eda7..fe923e81eee 100644 --- a/jdk/test/java/util/zip/ZipFile/ReadZip.java +++ b/jdk/test/java/util/zip/ZipFile/ReadZip.java @@ -30,6 +30,7 @@ import java.io.*; import java.nio.file.Files; import java.nio.file.Paths; +import java.nio.file.NoSuchFileException; import java.nio.file.StandardCopyOption; import java.nio.file.StandardOpenOption; import java.util.zip.*; @@ -110,6 +111,6 @@ public class ReadZip { "input" + String.valueOf(new java.util.Random().nextInt()) + ".zip"))); - } catch (FileNotFoundException fnfe) {} + } catch (NoSuchFileException nsfe) {} } } diff --git a/jdk/test/java/util/zip/ZipFile/TestZipFile.java b/jdk/test/java/util/zip/ZipFile/TestZipFile.java new file mode 100644 index 00000000000..986877731db --- /dev/null +++ b/jdk/test/java/util/zip/ZipFile/TestZipFile.java @@ -0,0 +1,361 @@ +/* + * 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 8142508 + * @summary Tests various ZipFile apis + * @run main/manual TestZipFile + */ + +import java.io.*; +import java.lang.reflect.Method; +import java.nio.*; +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.util.*; +import java.util.concurrent.*; +import java.util.zip.*; + +public class TestZipFile { + + private static Random r = new Random(); + private static int N = 50; + private static int NN = 10; + private static int ENUM = 10000; + private static int ESZ = 10000; + private static ExecutorService executor = Executors.newFixedThreadPool(20); + private static Set paths = new HashSet<>(); + + static void realMain (String[] args) throws Throwable { + + try { + for (int i = 0; i < N; i++) { + test(r.nextInt(ENUM), r.nextInt(ESZ), false, true); + test(r.nextInt(ENUM), r.nextInt(ESZ), true, true); + } + + for (int i = 0; i < NN; i++) { + test(r.nextInt(ENUM), 100000 + r.nextInt(ESZ), false, true); + test(r.nextInt(ENUM), 100000 + r.nextInt(ESZ), true, true); + testCachedDelete(); + testCachedOverwrite(); + //test(r.nextInt(ENUM), r.nextInt(ESZ), false, true); + } + + test(70000, 1000, false, true); // > 65536 entry number; + testDelete(); // OPEN_DELETE + + executor.shutdown(); + executor.awaitTermination(10, TimeUnit.MINUTES); + } finally { + for (Path path : paths) { + Files.deleteIfExists(path); + } + } + } + + static void test(int numEntry, int szMax, boolean addPrefix, boolean cleanOld) { + String name = "zftest" + r.nextInt() + ".zip"; + Zip zip = new Zip(name, numEntry, szMax, addPrefix, cleanOld); + for (int i = 0; i < NN; i++) { + executor.submit(() -> doTest(zip)); + } + } + + // test scenario: + // (1) open the ZipFile(zip) with OPEN_READ | OPEN_DELETE + // (2) test the ZipFile works correctly + // (3) check the zip is deleted after ZipFile gets closed + static void testDelete() throws Throwable { + String name = "zftest" + r.nextInt() + ".zip"; + Zip zip = new Zip(name, r.nextInt(ENUM), r.nextInt(ESZ), false, true); + try (ZipFile zf = new ZipFile(new File(zip.name), + ZipFile.OPEN_READ | ZipFile.OPEN_DELETE )) + { + doTest0(zip, zf); + } + Path p = Paths.get(name); + if (Files.exists(p)) { + fail("Failed to delete " + name + " with OPEN_DELETE"); + } + } + + // test scenario: + // (1) keep a ZipFile(zip1) alive (in ZipFile's cache), dont close it + // (2) delete zip1 and create zip2 with the same name the zip1 with zip2 + // (3) zip1 tests should fail, but no crash + // (4) zip2 tasks should all get zip2, then pass normal testing. + static void testCachedDelete() throws Throwable { + String name = "zftest" + r.nextInt() + ".zip"; + Zip zip1 = new Zip(name, r.nextInt(ENUM), r.nextInt(ESZ), false, true); + + try (ZipFile zf = new ZipFile(zip1.name)) { + for (int i = 0; i < NN; i++) { + executor.submit(() -> verifyNoCrash(zip1)); + } + // delete the "zip1" and create a new one to test + Zip zip2 = new Zip(name, r.nextInt(ENUM), r.nextInt(ESZ), false, true); + /* + System.out.println("========================================"); + System.out.printf(" zip1=%s, mt=%d, enum=%d%n ->attrs=[key=%s, sz=%d, mt=%d]%n", + zip1.name, zip1.lastModified, zip1.entries.size(), + zip1.attrs.fileKey(), zip1.attrs.size(), zip1.attrs.lastModifiedTime().toMillis()); + System.out.printf(" zip2=%s, mt=%d, enum=%d%n ->attrs=[key=%s, sz=%d, mt=%d]%n", + zip2.name, zip2.lastModified, zip2.entries.size(), + zip2.attrs.fileKey(), zip2.attrs.size(), zip2.attrs.lastModifiedTime().toMillis()); + */ + for (int i = 0; i < NN; i++) { + executor.submit(() -> doTest(zip2)); + } + } + } + + // overwrite the "zip1" and create a new one to test. So the two zip files + // have the same fileKey, but probably different lastModified() + static void testCachedOverwrite() throws Throwable { + String name = "zftest" + r.nextInt() + ".zip"; + Zip zip1 = new Zip(name, r.nextInt(ENUM), r.nextInt(ESZ), false, true); + try (ZipFile zf = new ZipFile(zip1.name)) { + for (int i = 0; i < NN; i++) { + executor.submit(() -> verifyNoCrash(zip1)); + } + // overwrite the "zip1" with new contents + Zip zip2 = new Zip(name, r.nextInt(ENUM), r.nextInt(ESZ), false, false); + for (int i = 0; i < NN; i++) { + executor.submit(() -> doTest(zip2)); + } + } + } + + // just check the entries and contents. since the file has been either overwritten + // or deleted/rewritten, we only care if it crahes or not. + static void verifyNoCrash(Zip zip) throws RuntimeException { + try (ZipFile zf = new ZipFile(zip.name)) { + List zlist = new ArrayList(zip.entries.keySet()); + String[] elist = zf.stream().map( e -> e.getName()).toArray(String[]::new); + if (!Arrays.equals(elist, + zlist.stream().map( e -> e.getName()).toArray(String[]::new))) + { + //System.out.printf("++++++ LIST NG [%s] entries.len=%d, expected=%d+++++++%n", + // zf.getName(), elist.length, zlist.size()); + return; + } + for (ZipEntry ze : zlist) { + byte[] zdata = zip.entries.get(ze); + ZipEntry e = zf.getEntry(ze.getName()); + if (e != null) { + checkEqual(e, ze); + if (!e.isDirectory()) { + // check with readAllBytes + try (InputStream is = zf.getInputStream(e)) { + if (!Arrays.equals(zdata, is.readAllBytes())) { + //System.out.printf("++++++ BYTES NG [%s]/[%s] ++++++++%n", + // zf.getName(), ze.getName()); + } + } + } + } + } + } catch (Throwable t) { + // t.printStackTrace(); + // fail(t.toString()); + } + } + + static void checkEqual(ZipEntry x, ZipEntry y) { + if (x.getName().equals(y.getName()) && + x.isDirectory() == y.isDirectory() && + x.getMethod() == y.getMethod() && + (x.getTime() / 2000) == y.getTime() / 2000 && + x.getSize() == y.getSize() && + x.getCompressedSize() == y.getCompressedSize() && + x.getCrc() == y.getCrc() && + x.getComment().equals(y.getComment()) + ) { + pass(); + } else { + fail(x + " not equal to " + y); + System.out.printf(" %s %s%n", x.getName(), y.getName()); + System.out.printf(" %d %d%n", x.getMethod(), y.getMethod()); + System.out.printf(" %d %d%n", x.getTime(), y.getTime()); + System.out.printf(" %d %d%n", x.getSize(), y.getSize()); + System.out.printf(" %d %d%n", x.getCompressedSize(), y.getCompressedSize()); + System.out.printf(" %d %d%n", x.getCrc(), y.getCrc()); + System.out.println("-----------------"); + } + } + + static void doTest(Zip zip) throws RuntimeException { + //Thread me = Thread.currentThread(); + try (ZipFile zf = new ZipFile(zip.name)) { + doTest0(zip, zf); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + + static void doTest0(Zip zip, ZipFile zf) throws Throwable { + List list = new ArrayList(zip.entries.keySet()); + // (1) check entry list, in expected order + if (!check(Arrays.equals( + list.stream().map( e -> e.getName()).toArray(String[]::new), + zf.stream().map( e -> e.getName()).toArray(String[]::new)))) { + return; + } + // (2) shuffle, and check each entry and its bytes + Collections.shuffle(list); + for (ZipEntry ze : list) { + byte[] data = zip.entries.get(ze); + ZipEntry e = zf.getEntry(ze.getName()); + checkEqual(e, ze); + if (!e.isDirectory()) { + // check with readAllBytes + try (InputStream is = zf.getInputStream(e)) { + check(Arrays.equals(data, is.readAllBytes())); + } + // check with smaller sized buf + try (InputStream is = zf.getInputStream(e)) { + byte[] buf = new byte[(int)e.getSize()]; + int sz = r.nextInt((int)e.getSize()/4 + 1) + 1; + int off = 0; + int n; + while ((n = is.read(buf, off, buf.length - off)) > 0) { + off += n; + } + check(is.read() == -1); + check(Arrays.equals(data, buf)); + } + } + } + // (3) check getMetaInfEntryNames + String[] metas = list.stream() + .map( e -> e.getName()) + .filter( s -> s.startsWith("META-INF/")) + .sorted() + .toArray(String[]::new); + if (metas.length > 0) { + // meta-inf entries + Method getMetas = ZipFile.class.getDeclaredMethod("getMetaInfEntryNames"); + getMetas.setAccessible(true); + String[] names = (String[])getMetas.invoke(zf); + if (names == null) { + fail("Failed to get metanames from " + zf); + } else { + Arrays.sort(names); + check(Arrays.equals(names, metas)); + } + } + } + + private static class Zip { + String name; + Map entries; + BasicFileAttributes attrs; + long lastModified; + + Zip(String name, int num, int szMax, boolean prefix, boolean clean) { + this.name = name; + entries = new LinkedHashMap<>(num); + try { + Path p = Paths.get(name); + if (clean) { + Files.deleteIfExists(p); + } + paths.add(p); + } catch (Exception x) { + throw (RuntimeException)x; + } + + try (FileOutputStream fos = new FileOutputStream(name); + BufferedOutputStream bos = new BufferedOutputStream(fos); + ZipOutputStream zos = new ZipOutputStream(bos)) + { + if (prefix) { + byte[] bytes = new byte[r.nextInt(1000)]; + r.nextBytes(bytes); + bos.write(bytes); + } + CRC32 crc = new CRC32(); + for (int i = 0; i < num; i++) { + String ename = "entry-" + i + "-name-" + r.nextLong(); + ZipEntry ze = new ZipEntry(ename); + int method = r.nextBoolean() ? ZipEntry.STORED : ZipEntry.DEFLATED; + writeEntry(zos, crc, ze, ZipEntry.STORED, szMax); + } + // add some manifest entries + for (int i = 0; i < r.nextInt(20); i++) { + String meta = "META-INF/" + "entry-" + i + "-metainf-" + r.nextLong(); + ZipEntry ze = new ZipEntry(meta); + writeEntry(zos, crc, ze, ZipEntry.STORED, szMax); + } + } catch (Exception x) { + throw (RuntimeException)x; + } + try { + this.attrs = Files.readAttributes(Paths.get(name), BasicFileAttributes.class); + this.lastModified = new File(name).lastModified(); + } catch (Exception x) { + throw (RuntimeException)x; + } + } + + private void writeEntry(ZipOutputStream zos, CRC32 crc, + ZipEntry ze, int method, int szMax) + throws IOException + { + ze.setMethod(method); + byte[] data = new byte[r.nextInt(szMax + 1)]; + r.nextBytes(data); + if (method == ZipEntry.STORED) { // must set size/csize/crc + ze.setSize(data.length); + ze.setCompressedSize(data.length); + crc.reset(); + crc.update(data); + ze.setCrc(crc.getValue()); + } + ze.setTime(System.currentTimeMillis()); + ze.setComment(ze.getName()); + zos.putNextEntry(ze); + zos.write(data); + zos.closeEntry(); + entries.put(ze, data); + } + } + + //--------------------- Infrastructure --------------------------- + static volatile int passed = 0, failed = 0; + static void pass() {passed++;} + static void pass(String msg) {System.out.println(msg); passed++;} + static void fail() {failed++; Thread.dumpStack();} + static void fail(String msg) {System.out.println(msg); fail();} + static void unexpected(Throwable t) {failed++; t.printStackTrace();} + static void unexpected(Throwable t, String msg) { + System.out.println(msg); failed++; t.printStackTrace();} + static boolean check(boolean cond) {if (cond) pass(); else fail(); return cond;} + + public static void main(String[] args) throws Throwable { + try {realMain(args);} catch (Throwable t) {unexpected(t);} + System.out.println("\nPassed = " + passed + " failed = " + failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +} diff --git a/jdk/test/javax/xml/crypto/dsig/SecurityManager/XMLDSigWithSecMgr.java b/jdk/test/javax/xml/crypto/dsig/SecurityManager/XMLDSigWithSecMgr.java index 014a7a6ab38..ca3be869c4d 100644 --- a/jdk/test/javax/xml/crypto/dsig/SecurityManager/XMLDSigWithSecMgr.java +++ b/jdk/test/javax/xml/crypto/dsig/SecurityManager/XMLDSigWithSecMgr.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -33,8 +33,6 @@ import java.io.*; import java.net.*; import java.security.KeyPair; import java.security.KeyPairGenerator; -import java.security.Policy; -import java.security.URIParameter; import java.util.ArrayList; import java.util.Collections; import javax.xml.crypto.dsig.*; @@ -115,10 +113,8 @@ public class XMLDSigWithSecMgr implements Runnable { // the policy only grants this test SocketPermission to accept, resolve // and connect to localhost so that it can dereference 2nd reference - URI policyURI = - new File(System.getProperty("test.src", "."), "policy").toURI(); - Policy.setPolicy - (Policy.getInstance("JavaPolicy", new URIParameter(policyURI))); + System.setProperty("java.security.policy", + System.getProperty("test.src", ".") + File.separator + "policy"); System.setSecurityManager(new SecurityManager()); try { diff --git a/jdk/test/sun/management/jmxremote/startstop/JMXStatusTest.java b/jdk/test/sun/management/jmxremote/startstop/JMXStatusTest.java index 84943bd69d9..5de4986742b 100644 --- a/jdk/test/sun/management/jmxremote/startstop/JMXStatusTest.java +++ b/jdk/test/sun/management/jmxremote/startstop/JMXStatusTest.java @@ -33,7 +33,7 @@ import jdk.testlibrary.ProcessTools; /** * @test - * @bug 8023093 8138748 + * @bug 8023093 8138748 8142398 * @summary Performs a sanity test for the ManagementAgent.status diagnostic command. * Management agent may be disabled, started (only local connections) and started. * The test asserts that the expected text is being printed. @@ -56,7 +56,8 @@ abstract public class JMXStatusTest { "Connection Type\\s*\\:\\s*local\\n+" + "Protocol\\s*\\:\\s*[a-z]+\\n+" + "Host\\s*\\:\\s*.+\\n+" + - "URL\\s*\\:\\s*service\\:jmx\\:.+", + "URL\\s*\\:\\s*service\\:jmx\\:.+\\n+" + + "Properties\\s*\\:\\n+(\\s*\\S+\\s*=\\s*\\S+(\\s+\\[default\\])?\\n*)+", Pattern.MULTILINE ); @@ -67,7 +68,7 @@ abstract public class JMXStatusTest { "Protocol\\s*\\: [a-z]+\\n+" + "Host\\s*\\: .+\\n+" + "URL\\s*\\: service\\:jmx\\:.+\\n+" + - "Properties\\s*\\:\\n+(\\s*\\S+\\s*=\\s*\\S+\\n*)+", + "Properties\\s*\\:\\n+(\\s*\\S+\\s*=\\s*\\S+(\\s+\\[default\\])?\\n*)+", Pattern.MULTILINE | Pattern.DOTALL ); diff --git a/langtools/.hgtags b/langtools/.hgtags index dc7d051fa56..ff46d011cf0 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -338,3 +338,4 @@ a3415b57507c928af8f2ad1c771eebafcd00c6c7 jdk9-b92 7f880f98506c9046f8fb69597a41762ea1b7d042 jdk9-b93 8356d7a909a29f321e3eaf9d3c2bbc71648529e2 jdk9-b94 c35ddcde581676275cfeff33e1a2b90b902593d9 jdk-9+95 +d2a44416cba39957ea231eedc2fb8aad7be1b30c jdk-9+96 diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/source/doctree/DocTree.java b/langtools/src/jdk.compiler/share/classes/com/sun/source/doctree/DocTree.java index 5d728ee1aab..0b54ca8334a 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/source/doctree/DocTree.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/doctree/DocTree.java @@ -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 @@ -109,6 +109,12 @@ public interface DocTree { */ IDENTIFIER, + /** + * Used for instances of {@index term optional-descr} + * representing a search term. + */ + INDEX("index"), + /** * Used for instances of {@link InheritDocTree} * representing an @inheritDoc tag. diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/source/doctree/DocTreeVisitor.java b/langtools/src/jdk.compiler/share/classes/com/sun/source/doctree/DocTreeVisitor.java index fdfa116fc63..1512cf08f2f 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/source/doctree/DocTreeVisitor.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/doctree/DocTreeVisitor.java @@ -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 @@ -137,6 +137,14 @@ public interface DocTreeVisitor { */ R visitIdentifier(IdentifierTree node, P p); + /** + * Visits an IndexTree node. + * @param node the node being visited + * @param p a parameter value + * @return a result value + */ + R visitIndex(IndexTree node, P p); + /** * Visits an InheritDocTree node. * @param node the node being visited diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/source/doctree/IndexTree.java b/langtools/src/jdk.compiler/share/classes/com/sun/source/doctree/IndexTree.java new file mode 100644 index 00000000000..bfceffa2b81 --- /dev/null +++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/doctree/IndexTree.java @@ -0,0 +1,51 @@ +/* + * 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 com.sun.source.doctree; + +import java.util.List; + +/** + * A tree node for an @index or @index inline tag. + * + *

+ * {@index keyword optional description}
+ * + * @since 1.9 + */ +@jdk.Exported +public interface IndexTree extends InlineTagTree { + /** + * Returns the specified search term. + * @return the search term + */ + DocTree getSearchTerm(); + + /** + * Returns the description, if any. + * @return the description + */ + List getDescription(); +} diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/source/util/DocTreeScanner.java b/langtools/src/jdk.compiler/share/classes/com/sun/source/util/DocTreeScanner.java index 55fe6e14541..4866ab6b0c8 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/source/util/DocTreeScanner.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/util/DocTreeScanner.java @@ -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 @@ -26,6 +26,7 @@ package com.sun.source.util; import com.sun.source.doctree.*; +import com.sun.tools.javac.tree.DCTree.DCIndex; /** @@ -247,6 +248,20 @@ public class DocTreeScanner implements DocTreeVisitor { return null; } + /** + * {@inheritDoc} This implementation returns {@code null}. + * + * @param node {@inheritDoc} + * @param p {@inheritDoc} + * @return the result of scanning + */ + @Override + public R visitIndex(IndexTree node, P p) { + R r = scan(node.getSearchTerm(), p); + r = scanAndReduce(node.getDescription(), p, r); + return r; + } + /** * {@inheritDoc} This implementation returns {@code null}. * diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/source/util/SimpleDocTreeVisitor.java b/langtools/src/jdk.compiler/share/classes/com/sun/source/util/SimpleDocTreeVisitor.java index 13bce1293df..28a946a8f83 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/source/util/SimpleDocTreeVisitor.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/util/SimpleDocTreeVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -216,6 +216,18 @@ public class SimpleDocTreeVisitor implements DocTreeVisitor { return defaultAction(node, p); } + /** + * {@inheritDoc} This implementation calls {@code defaultAction}. + * + * @param node {@inheritDoc} + * @param p {@inheritDoc} + * @return the result of {@code defaultAction} + */ + @Override + public R visitIndex(IndexTree node, P p) { + return defaultAction(node, p); + } + /** * {@inheritDoc} This implementation calls {@code defaultAction}. * diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java index dae62265599..0c602c4c16a 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java @@ -343,7 +343,7 @@ public class ClassFinder { } currentClassFile = classfile; if (verbose) { - log.printVerbose("loading", currentClassFile.toString()); + log.printVerbose("loading", currentClassFile.getName()); } if (classfile.getKind() == JavaFileObject.Kind.CLASS || classfile.getKind() == JavaFileObject.Kind.OTHER) { diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java index 0fbe7da988a..428a30abb83 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java @@ -424,6 +424,9 @@ public abstract class Symbol extends AnnoConstruct implements Element { } /** The closest enclosing class of this symbol's declaration. + * Warning: this (misnamed) method returns the receiver itself + * when the receiver is a class (as opposed to its enclosing + * class as one may be misled to believe.) */ public ClassSymbol enclClass() { Symbol c = this; diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java index 97b56f1070d..26fec55e56c 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java @@ -1056,7 +1056,7 @@ public class Types { } /** - * A polymorphic signature method (JLS SE 7, 8.4.1) is a method that + * A polymorphic signature method (JLS 15.12.3) is a method that * (i) is declared in the java.lang.invoke.MethodHandle class, (ii) takes * a single variable arity parameter (iii) whose declared type is Object[], * (iv) has a return type of Object and (v) is native. diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java index e776e6c5e08..3f53f74d04f 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java @@ -2037,7 +2037,7 @@ public class LambdaToMethod extends TreeTranslator { }; break; case CAPTURED_OUTER_THIS: - Name name = names.fromString(new String(sym.flatName().toString() + names.dollarThis)); + Name name = names.fromString(new String(sym.flatName().toString().replace('.', '$') + names.dollarThis)); ret = new VarSymbol(SYNTHETIC | FINAL | PARAMETER, name, types.erasure(sym.type), translatedSym) { @Override public Symbol baseSymbol() { diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java index 7aef1258415..a92276ec604 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java @@ -2784,8 +2784,6 @@ public class Resolve { .map(c -> StaticKind.from(c.sym)) .reduce(StaticKind::reduce) .orElse(StaticKind.UNDEFINED); - case HIDDEN: - return StaticKind.from(((AccessError)sym).sym); default: return StaticKind.UNDEFINED; } @@ -3365,7 +3363,7 @@ public class Resolve { if (env1 != null) { while (env1 != null && env1.outer != null) { if (isStatic(env1)) staticOnly = true; - if (env1.enclClass.sym.isSubClass(member.owner, types)) { + if (env1.enclClass.sym.isSubClass(member.owner.enclClass(), types)) { Symbol sym = env1.info.scope.findFirst(name); if (sym != null) { if (staticOnly) sym = new StaticError(sym); diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileObject.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileObject.java deleted file mode 100644 index 71c869fc1a3..00000000000 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileObject.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.tools.javac.file; - -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.Reader; -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.charset.CharsetDecoder; -import java.nio.file.Path; - -import javax.lang.model.element.Modifier; -import javax.lang.model.element.NestingKind; -import javax.tools.FileObject; -import javax.tools.JavaFileObject; - -import com.sun.tools.javac.util.DefinedBy; -import com.sun.tools.javac.util.DefinedBy.Api; - -/** - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. -*/ -public abstract class BaseFileObject implements JavaFileObject { - protected BaseFileObject(JavacFileManager fileManager) { - this.fileManager = fileManager; - } - - /** Return a short name for the object, such as for use in raw diagnostics - */ - public abstract String getShortName(); - - @Override - public String toString() { - return getClass().getSimpleName() + "[" + getName() + "]"; - } - - @DefinedBy(Api.COMPILER) - public NestingKind getNestingKind() { return null; } - - @DefinedBy(Api.COMPILER) - public Modifier getAccessLevel() { return null; } - - @DefinedBy(Api.COMPILER) - public Reader openReader(boolean ignoreEncodingErrors) throws IOException { - return new InputStreamReader(openInputStream(), getDecoder(ignoreEncodingErrors)); - } - - protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) { - throw new UnsupportedOperationException(); - } - - protected abstract String inferBinaryName(Iterable path); - - protected static JavaFileObject.Kind getKind(String filename) { - return BaseFileManager.getKind(filename); - } - - protected static String removeExtension(String fileName) { - int lastDot = fileName.lastIndexOf("."); - return (lastDot == -1 ? fileName : fileName.substring(0, lastDot)); - } - - protected static URI createJarUri(Path jarFile, String entryName) { - URI jarURI = jarFile.toUri().normalize(); - String separator = entryName.startsWith("/") ? "!" : "!/"; - try { - // The jar URI convention appears to be not to re-encode the jarURI - return new URI("jar:" + jarURI + separator + entryName); - } catch (URISyntaxException e) { - throw new CannotCreateUriError(jarURI + separator + entryName, e); - } - } - - /** Used when URLSyntaxException is thrown unexpectedly during - * implementations of (Base)FileObject.toURI(). */ - protected static class CannotCreateUriError extends Error { - private static final long serialVersionUID = 9101708840997613546L; - public CannotCreateUriError(String value, Throwable cause) { - super(value, cause); - } - } - - /** Return the last component of a presumed hierarchical URI. - * From the scheme specific part of the URI, it returns the substring - * after the last "/" if any, or everything if no "/" is found. - */ - public static String getSimpleName(FileObject fo) { - URI uri = fo.toUri(); - String s = uri.getSchemeSpecificPart(); - return s.substring(s.lastIndexOf("/") + 1); // safe when / not found - - } - - // force subtypes to define equals - @Override - public abstract boolean equals(Object other); - - // force subtypes to define hashCode - @Override - public abstract int hashCode(); - - /** The file manager that created this JavaFileObject. */ - protected final JavacFileManager fileManager; -} diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/FSInfo.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/FSInfo.java index 5d5530122de..974f28fe5ce 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/FSInfo.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/FSInfo.java @@ -48,7 +48,7 @@ public class FSInfo { try { return file.toRealPath(); } catch (IOException e) { - return file.toAbsolutePath(); + return file.toAbsolutePath().normalize(); } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JRTIndex.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JRTIndex.java index 331db0fa1ef..f2cf19cea61 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JRTIndex.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JRTIndex.java @@ -200,7 +200,7 @@ public class JRTIndex { if (Files.exists(dir)) { try (DirectoryStream modules = Files.newDirectoryStream(dir)) { for (Path module: modules) { - Path p = rd.getFile(module); + Path p = rd.resolveAgainst(module); if (!Files.exists(p)) continue; try (DirectoryStream stream = Files.newDirectoryStream(p)) { diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java index 048c4b547df..2e684dffff6 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java @@ -26,7 +26,6 @@ package com.sun.tools.javac.file; import java.io.File; -import java.io.FileNotFoundException; import java.io.IOException; import java.net.MalformedURLException; import java.net.URI; @@ -34,16 +33,20 @@ import java.net.URISyntaxException; import java.net.URL; import java.nio.CharBuffer; import java.nio.charset.Charset; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.FileVisitOption; +import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.InvalidPathException; import java.nio.file.LinkOption; -import java.nio.file.NoSuchFileException; import java.nio.file.Path; import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.Collections; import java.util.Comparator; import java.util.EnumSet; import java.util.HashMap; @@ -53,7 +56,6 @@ import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; -import java.util.zip.ZipFile; import javax.lang.model.SourceVersion; import javax.tools.FileObject; @@ -69,6 +71,8 @@ import com.sun.tools.javac.util.DefinedBy.Api; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; +import static java.nio.file.FileVisitOption.FOLLOW_LINKS; + import static javax.tools.StandardLocation.*; /** @@ -92,9 +96,6 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil private FSInfo fsInfo; - private boolean contextUseOptimizedZip; - private ZipFileIndexCache zipFileIndexCache; - private final Set sourceOrClass = EnumSet.of(JavaFileObject.Kind.SOURCE, JavaFileObject.Kind.CLASS); @@ -149,10 +150,6 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil fsInfo = FSInfo.instance(context); - contextUseOptimizedZip = options.getBoolean("useOptimizedZip", true); - if (contextUseOptimizedZip) - zipFileIndexCache = ZipFileIndexCache.getSharedInstance(); - symbolFileEnabled = !options.isSet("ignore.symbol.file"); String sf = options.get("sortFiles"); @@ -173,13 +170,13 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil } // used by tests - public JavaFileObject getFileForInput(String name) { - return getRegularFile(Paths.get(name)); + public JavaFileObject getJavaFileObject(String name) { + return getJavaFileObjects(name).iterator().next(); } // used by tests - public JavaFileObject getRegularFile(Path file) { - return new RegularFileObject(this, file); + public JavaFileObject getJavaFileObject(Path file) { + return getJavaFileObjects(file).iterator().next(); } public JavaFileObject getFileForOutput(String classname, @@ -277,7 +274,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil for (Path file: e.files.values()) { if (fileKinds.contains(getKind(file))) { JavaFileObject fe - = PathFileObject.createJRTPathFileObject(JavacFileManager.this, file); + = PathFileObject.forJRTPath(JavacFileManager.this, file); resultList.append(fe); } } @@ -302,14 +299,14 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil * Insert all files in subdirectory subdirectory of directory directory * which match fileKinds into resultList */ - private void listDirectory(Path directory, + private void listDirectory(Path directory, Path realDirectory, RelativeDirectory subdirectory, Set fileKinds, boolean recurse, ListBuffer resultList) { Path d; try { - d = subdirectory.getFile(directory); + d = subdirectory.resolveAgainst(directory); } catch (InvalidPathException ignore) { return; } @@ -329,13 +326,16 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil return; } + if (realDirectory == null) + realDirectory = fsInfo.getCanonicalFile(directory); + for (Path f: files) { String fname = f.getFileName().toString(); if (fname.endsWith("/")) fname = fname.substring(0, fname.length() - 1); if (Files.isDirectory(f)) { if (recurse && SourceVersion.isIdentifier(fname)) { - listDirectory(directory, + listDirectory(directory, realDirectory, new RelativeDirectory(subdirectory, fname), fileKinds, recurse, @@ -343,8 +343,9 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil } } else { if (isValidFile(fname, fileKinds)) { - JavaFileObject fe = - new RegularFileObject(this, fname, d.resolve(fname)); + RelativeFile file = new RelativeFile(subdirectory, fname); + JavaFileObject fe = PathFileObject.forDirectoryPath(this, + file.resolveAgainst(realDirectory), directory, file); resultList.append(fe); } } @@ -352,34 +353,61 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil } /** - * Insert all files in subdirectory subdirectory of archive archive + * Insert all files in subdirectory subdirectory of archive archivePath * which match fileKinds into resultList */ - private void listArchive(Archive archive, - RelativeDirectory subdirectory, - Set fileKinds, - boolean recurse, - ListBuffer resultList) { - // Get the files directly in the subdir - List files = archive.getFiles(subdirectory); - if (files != null) { - for (; !files.isEmpty(); files = files.tail) { - String file = files.head; - if (isValidFile(file, fileKinds)) { - resultList.append(archive.getFileObject(subdirectory, file)); - } - } + private void listArchive(Path archivePath, + RelativeDirectory subdirectory, + Set fileKinds, + boolean recurse, + ListBuffer resultList) + throws IOException { + FileSystem fs = getFileSystem(archivePath); + if (fs == null) { + return; } - if (recurse) { - for (RelativeDirectory s: archive.getSubdirectories()) { - if (subdirectory.contains(s)) { - // Because the archive map is a flat list of directories, - // the enclosing loop will pick up all child subdirectories. - // Therefore, there is no need to recurse deeper. - listArchive(archive, s, fileKinds, false, resultList); - } - } + + Path containerSubdir = subdirectory.resolveAgainst(fs); + if (!Files.exists(containerSubdir)) { + return; } + + int maxDepth = (recurse ? Integer.MAX_VALUE : 1); + Set opts = EnumSet.of(FOLLOW_LINKS); + Files.walkFileTree(containerSubdir, opts, maxDepth, + new SimpleFileVisitor() { + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { + if (isValid(dir.getFileName())) { + return FileVisitResult.CONTINUE; + } else { + return FileVisitResult.SKIP_SUBTREE; + } + } + + boolean isValid(Path fileName) { + if (fileName == null) { + return true; + } else { + String name = fileName.toString(); + if (name.endsWith("/")) { + name = name.substring(0, name.length() - 1); + } + return SourceVersion.isIdentifier(name); + } + } + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { + if (attrs.isRegularFile() && fileKinds.contains(getKind(file.getFileName().toString()))) { + JavaFileObject fe = PathFileObject.forJarPath( + JavacFileManager.this, file, archivePath); + resultList.append(fe); + } + return FileVisitResult.CONTINUE; + } + }); + } /** @@ -391,54 +419,46 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil RelativeDirectory subdirectory, Set fileKinds, boolean recurse, - ListBuffer resultList) { - Archive archive = archives.get(container); - if (archive == null) { - // Very temporary and obnoxious interim hack - if (container.endsWith("bootmodules.jimage")) { - System.err.println("Warning: reference to bootmodules.jimage replaced by jrt:"); - container = Locations.JRT_MARKER_FILE; - } else if (container.getFileName().toString().endsWith(".jimage")) { - System.err.println("Warning: reference to " + container + " ignored"); - return; - } - - // archives are not created for directories or jrt: images - if (container == Locations.JRT_MARKER_FILE) { - try { - listJRTImage(subdirectory, - fileKinds, - recurse, - resultList); - } catch (IOException ex) { - ex.printStackTrace(System.err); - log.error("error.reading.file", container, getMessage(ex)); - } - return; - } - - if (fsInfo.isDirectory(container)) { - listDirectory(container, - subdirectory, - fileKinds, - recurse, - resultList); - return; - } - - // Not a directory; either a file or non-existant, create the archive - try { - archive = openArchive(container); - } catch (IOException ex) { - log.error("error.reading.file", container, getMessage(ex)); - return; - } + ListBuffer resultList) + throws IOException { + // Very temporary and obnoxious interim hack + if (container.endsWith("bootmodules.jimage")) { + System.err.println("Warning: reference to bootmodules.jimage replaced by jrt:"); + container = Locations.JRT_MARKER_FILE; + } else if (container.getFileName().toString().endsWith(".jimage")) { + System.err.println("Warning: reference to " + container + " ignored"); + return; } - listArchive(archive, + + if (container == Locations.JRT_MARKER_FILE) { + try { + listJRTImage(subdirectory, + fileKinds, + recurse, + resultList); + } catch (IOException ex) { + ex.printStackTrace(System.err); + log.error("error.reading.file", container, getMessage(ex)); + } + return; + } + + if (fsInfo.isDirectory(container)) { + listDirectory(container, null, + subdirectory, + fileKinds, + recurse, + resultList); + return; + } + + if (Files.exists(container)) { + listArchive(container, subdirectory, fileKinds, recurse, resultList); + } } private boolean isValidFile(String s, Set fileKinds) { @@ -481,141 +501,17 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil return j < 0; } - /** - * An archive provides a flat directory structure of a ZipFile by - * mapping directory names to lists of files (basenames). - */ - public interface Archive { - void close() throws IOException; - - boolean contains(RelativePath name); - - JavaFileObject getFileObject(RelativeDirectory subdirectory, String file); - - List getFiles(RelativeDirectory subdirectory); - - Set getSubdirectories(); + private FileSystem getFileSystem(Path path) throws IOException { + Path realPath = fsInfo.getCanonicalFile(path); + FileSystem fs = fileSystems.get(realPath); + if (fs == null) { + fileSystems.put(realPath, fs = FileSystems.newFileSystem(realPath, null)); + } + return fs; } - public class MissingArchive implements Archive { - final Path zipFileName; - public MissingArchive(Path name) { - zipFileName = name; - } - @Override - public boolean contains(RelativePath name) { - return false; - } + private final Map fileSystems = new HashMap<>(); - @Override - public void close() { - } - - @Override - public JavaFileObject getFileObject(RelativeDirectory subdirectory, String file) { - return null; - } - - @Override - public List getFiles(RelativeDirectory subdirectory) { - return List.nil(); - } - - @Override - public Set getSubdirectories() { - return Collections.emptySet(); - } - - @Override - public String toString() { - return "MissingArchive[" + zipFileName + "]"; - } - } - - /** A directory of zip files already opened. - */ - Map archives = new HashMap<>(); - - /* - * This method looks for a ZipFormatException and takes appropriate - * evasive action. If there is a failure in the fast mode then we - * fail over to the platform zip, and allow it to deal with a potentially - * non compliant zip file. - */ - protected Archive openArchive(Path zipFilename) throws IOException { - try { - return openArchive(zipFilename, contextUseOptimizedZip); - } catch (IOException ioe) { - if (ioe instanceof ZipFileIndex.ZipFormatException) { - return openArchive(zipFilename, false); - } else { - throw ioe; - } - } - } - - /** Open a new zip file directory, and cache it. - */ - private Archive openArchive(Path zipFileName, boolean useOptimizedZip) throws IOException { - Archive archive; - try { - - ZipFile zdir = null; - - boolean usePreindexedCache = false; - String preindexCacheLocation = null; - - if (!useOptimizedZip) { - zdir = new ZipFile(zipFileName.toFile()); - } else { - usePreindexedCache = options.isSet("usezipindex"); - preindexCacheLocation = options.get("java.io.tmpdir"); - String optCacheLoc = options.get("cachezipindexdir"); - - if (optCacheLoc != null && optCacheLoc.length() != 0) { - if (optCacheLoc.startsWith("\"")) { - if (optCacheLoc.endsWith("\"")) { - optCacheLoc = optCacheLoc.substring(1, optCacheLoc.length() - 1); - } - else { - optCacheLoc = optCacheLoc.substring(1); - } - } - - File cacheDir = new File(optCacheLoc); - if (cacheDir.exists() && cacheDir.canWrite()) { - preindexCacheLocation = optCacheLoc; - if (!preindexCacheLocation.endsWith("/") && - !preindexCacheLocation.endsWith(File.separator)) { - preindexCacheLocation += File.separator; - } - } - } - } - - if (!useOptimizedZip) { - archive = new ZipArchive(this, zdir); - } else { - archive = new ZipFileIndexArchive(this, - zipFileIndexCache.getZipFileIndex(zipFileName, - null, - usePreindexedCache, - preindexCacheLocation, - options.isSet("writezipindexfiles"))); - } - } catch (FileNotFoundException | NoSuchFileException ex) { - archive = new MissingArchive(zipFileName); - } catch (ZipFileIndex.ZipFormatException zfe) { - throw zfe; - } catch (IOException ex) { - if (Files.exists(zipFileName)) - log.error("error.reading.file", zipFileName, getMessage(ex)); - archive = new MissingArchive(zipFileName); - } - - archives.put(zipFileName, archive); - return archive; - } /** Flush any output resources. */ @@ -628,15 +524,9 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil * Close the JavaFileManager, releasing resources. */ @Override @DefinedBy(Api.COMPILER) - public void close() { - for (Iterator i = archives.values().iterator(); i.hasNext(); ) { - Archive a = i.next(); - i.remove(); - try { - a.close(); - } catch (IOException ignore) { - } - } + public void close() throws IOException { + for (FileSystem fs: fileSystems.values()) + fs.close(); } @Override @DefinedBy(Api.COMPILER) @@ -689,10 +579,8 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil return null; } - if (file instanceof BaseFileObject) { - return ((BaseFileObject) file).inferBinaryName(path); - } else if (file instanceof PathFileObject) { - return ((PathFileObject) file).inferBinaryName(null); + if (file instanceof PathFileObject) { + return ((PathFileObject) file).inferBinaryName(path); } else throw new IllegalArgumentException(file.getClass().getName()); } @@ -703,11 +591,6 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil nullCheck(b); if (a instanceof PathFileObject && b instanceof PathFileObject) return ((PathFileObject) a).isSameFile((PathFileObject) b); - // In time, we should phase out BaseFileObject in favor of PathFileObject - if (!(a instanceof BaseFileObject || a instanceof PathFileObject)) - throw new IllegalArgumentException("Not supported: " + a); - if (!(b instanceof BaseFileObject || b instanceof PathFileObject)) - throw new IllegalArgumentException("Not supported: " + b); return a.equals(b); } @@ -754,32 +637,29 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil return null; for (Path file: path) { - Archive a = archives.get(file); - if (a == null) { - // archives are not created for directories or jrt: images - if (file == Locations.JRT_MARKER_FILE) { - JRTIndex.Entry e = getJRTIndex().getEntry(name.dirname()); - if (symbolFileEnabled && e.ctSym.hidden) - continue; - Path p = e.files.get(name.basename()); - if (p != null) - return PathFileObject.createJRTPathFileObject(this, p); - continue; - } else if (fsInfo.isDirectory(file)) { - try { - Path f = name.getFile(file); - if (Files.exists(f)) - return new RegularFileObject(this, f); - } catch (InvalidPathException ignore) { - } + if (file == Locations.JRT_MARKER_FILE) { + JRTIndex.Entry e = getJRTIndex().getEntry(name.dirname()); + if (symbolFileEnabled && e.ctSym.hidden) continue; + Path p = e.files.get(name.basename()); + if (p != null) + return PathFileObject.forJRTPath(this, p); + } else if (fsInfo.isDirectory(file)) { + try { + Path f = name.resolveAgainst(file); + if (Files.exists(f)) + return PathFileObject.forSimplePath(this, + fsInfo.getCanonicalFile(f), f); + } catch (InvalidPathException ignore) { + } + } else if (Files.exists(file)) { + FileSystem fs = getFileSystem(file); + if (fs != null) { + Path fsRoot = fs.getRootDirectories().iterator().next(); + Path f = name.resolveAgainst(fsRoot); + if (Files.exists(f)) + return PathFileObject.forJarPath(this, f, file); } - // Not a directory, create the archive - a = openArchive(file); - } - // Process the archive - if (a.contains(name)) { - return a.getFileObject(name.dirname(), name.basename()); } } return null; @@ -829,14 +709,14 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil if (getClassOutDir() != null) { dir = getClassOutDir(); } else { - Path siblingDir = null; - if (sibling != null && sibling instanceof RegularFileObject) { - siblingDir = ((RegularFileObject)sibling).file.getParent(); + String baseName = fileName.basename(); + if (sibling != null && sibling instanceof PathFileObject) { + return ((PathFileObject) sibling).getSibling(baseName); + } else { + Path p = Paths.get(baseName); + Path real = fsInfo.getCanonicalFile(p); + return PathFileObject.forSimplePath(this, real, p); } - if (siblingDir == null) - return new RegularFileObject(this, Paths.get(fileName.basename())); - else - return new RegularFileObject(this, siblingDir.resolve(fileName.basename())); } } else if (location == SOURCE_OUTPUT) { dir = (getSourceOutDir() != null ? getSourceOutDir() : getClassOutDir()); @@ -850,8 +730,11 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil } try { - Path file = fileName.getFile(dir); // null-safe - return new RegularFileObject(this, file); + if (dir == null) { + dir = Paths.get(System.getProperty("user.dir")); + } + Path path = fileName.resolveAgainst(fsInfo.getCanonicalFile(dir)); + return PathFileObject.forDirectoryPath(this, path, dir, fileName); } catch (InvalidPathException e) { throw new IOException("bad filename " + fileName, e); } @@ -861,13 +744,17 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil public Iterable getJavaFileObjectsFromFiles( Iterable files) { - ArrayList result; + ArrayList result; if (files instanceof Collection) result = new ArrayList<>(((Collection)files).size()); else result = new ArrayList<>(); - for (File f: files) - result.add(new RegularFileObject(this, nullCheck(f).toPath())); + for (File f: files) { + Objects.requireNonNull(f); + Path p = f.toPath(); + result.add(PathFileObject.forSimplePath(this, + fsInfo.getCanonicalFile(p), p)); + } return result; } @@ -875,13 +762,14 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil public Iterable getJavaFileObjectsFromPaths( Iterable paths) { - ArrayList result; + ArrayList result; if (paths instanceof Collection) result = new ArrayList<>(((Collection)paths).size()); else result = new ArrayList<>(); for (Path p: paths) - result.add(new RegularFileObject(this, nullCheck(p))); + result.add(PathFileObject.forSimplePath(this, + fsInfo.getCanonicalFile(p), p)); return result; } @@ -935,8 +823,8 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil @Override @DefinedBy(Api.COMPILER) public Path asPath(FileObject file) { - if (file instanceof RegularFileObject) { - return ((RegularFileObject) file).file; + if (file instanceof PathFileObject) { + return ((PathFileObject) file).path; } else throw new IllegalArgumentException(file.getName()); } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/PathFileObject.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/PathFileObject.java index 1d0dce79322..5dddaa40166 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/PathFileObject.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/PathFileObject.java @@ -33,18 +33,24 @@ import java.io.OutputStreamWriter; import java.io.Reader; import java.io.Writer; import java.net.URI; +import java.net.URISyntaxException; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.CharsetDecoder; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.Path; +import java.text.Normalizer; import java.util.Objects; import javax.lang.model.element.Modifier; import javax.lang.model.element.NestingKind; +import javax.tools.FileObject; import javax.tools.JavaFileObject; +import com.sun.tools.javac.file.RelativePath.RelativeFile; import com.sun.tools.javac.util.DefinedBy; import com.sun.tools.javac.util.DefinedBy.Api; @@ -53,10 +59,16 @@ import com.sun.tools.javac.util.DefinedBy.Api; * Implementation of JavaFileObject using java.nio.file API. * *

PathFileObjects are, for the most part, straightforward wrappers around - * Path objects. The primary complexity is the support for "inferBinaryName". - * This is left as an abstract method, implemented by each of a number of - * different factory methods, which compute the binary name based on - * information available at the time the file object is created. + * immutable absolute Path objects. Different subtypes are used to provide + * specialized implementations of "inferBinaryName" and "getName" that capture + * additional information available at the time the object is created. + * + *

In general, {@link JavaFileManager#isSameFile} should be used to + * determine whether two file objects refer to the same file on disk. + * PathFileObject also supports the standard {@code equals} and {@code hashCode} + * methods, primarily for convenience when working with collections. + * All of these operations delegate to the equivalent operations on the + * underlying Path object. * *

This is NOT part of any supported API. * If you write code that depends on this, you do so at your own risk. @@ -64,108 +76,297 @@ import com.sun.tools.javac.util.DefinedBy.Api; * deletion without notice. */ public abstract class PathFileObject implements JavaFileObject { - private final BaseFileManager fileManager; - private final Path path; + private static final FileSystem defaultFileSystem = FileSystems.getDefault(); + private static final boolean isMacOS = System.getProperty("os.name", "").contains("OS X"); + + protected final BaseFileManager fileManager; + protected final Path path; + private boolean hasParents; /** - * Create a PathFileObject within a directory, such that the binary name - * can be inferred from the relationship to the parent directory. + * Create a PathFileObject for a file within a directory, such that the + * binary name can be inferred from the relationship to an enclosing directory. + * + * The binary name is derived from {@code relativePath}. + * The name is derived from the composition of {@code userPackageRootDir} + * and {@code relativePath}. + * + * @param fileManager the file manager creating this file object + * @param path the absolute path referred to by this file object + * @param userPackageRootDir the path of the directory containing the + * root of the package hierarchy + * @param relativePath the path of this file relative to {@code userPackageRootDir} */ - static PathFileObject createDirectoryPathFileObject(BaseFileManager fileManager, - final Path path, final Path dir) { - return new PathFileObject(fileManager, path) { - @Override - public String inferBinaryName(Iterable paths) { - return toBinaryName(dir.relativize(path)); - } - }; + static PathFileObject forDirectoryPath(BaseFileManager fileManager, Path path, + Path userPackageRootDir, RelativePath relativePath) { + return new DirectoryFileObject(fileManager, path, userPackageRootDir, relativePath); + } + + private static class DirectoryFileObject extends PathFileObject { + private final Path userPackageRootDir; + private final RelativePath relativePath; + + private DirectoryFileObject(BaseFileManager fileManager, Path path, + Path userPackageRootDir, RelativePath relativePath) { + super(fileManager, path); + this.userPackageRootDir = userPackageRootDir; + this.relativePath = relativePath; + } + + @Override @DefinedBy(Api.COMPILER) + public String getName() { + return relativePath.resolveAgainst(userPackageRootDir).toString(); + } + + @Override + public String inferBinaryName(Iterable paths) { + return toBinaryName(relativePath); + } + + @Override + public String toString() { + return "DirectoryFileObject[" + userPackageRootDir + ":" + relativePath.path + "]"; + } + + @Override + PathFileObject getSibling(String baseName) { + return new DirectoryFileObject(fileManager, + path.resolveSibling(baseName), + userPackageRootDir, + new RelativeFile(relativePath.dirname(), baseName) + ); + } } /** - * Create a PathFileObject in a file system such as a jar file, such that - * the binary name can be inferred from its position within the filesystem. + * Create a PathFileObject for a file in a file system such as a jar file, + * such that the binary name can be inferred from its position within the + * file system. + * + * The binary name is derived from {@code path}. + * The name is derived from the composition of {@code userJarPath} + * and {@code path}. + * + * @param fileManager the file manager creating this file object + * @param path the path referred to by this file object + * @param userJarPath the path of the jar file containing the file system. */ - public static PathFileObject createJarPathFileObject(BaseFileManager fileManager, + public static PathFileObject forJarPath(BaseFileManager fileManager, + Path path, Path userJarPath) { + return new JarFileObject(fileManager, path, userJarPath); + } + + private static class JarFileObject extends PathFileObject { + private final Path userJarPath; + + private JarFileObject(BaseFileManager fileManager, Path path, Path userJarPath) { + super(fileManager, path); + this.userJarPath = userJarPath; + } + + @Override @DefinedBy(Api.COMPILER) + public String getName() { + // The use of ( ) to delimit the entry name is not ideal + // but it does match earlier behavior + return userJarPath + "(" + path + ")"; + } + + @Override + public String inferBinaryName(Iterable paths) { + Path root = path.getFileSystem().getRootDirectories().iterator().next(); + return toBinaryName(root.relativize(path)); + } + + @Override @DefinedBy(Api.COMPILER) + public URI toUri() { + // Work around bug JDK-8134451: + // path.toUri() returns double-encoded URIs, that cannot be opened by URLConnection + return createJarUri(userJarPath, path.toString()); + } + + @Override + public String toString() { + return "JarFileObject[" + userJarPath + ":" + path + "]"; + } + + @Override + PathFileObject getSibling(String baseName) { + return new JarFileObject(fileManager, + path.resolveSibling(baseName), + userJarPath + ); + } + + private static URI createJarUri(Path jarFile, String entryName) { + URI jarURI = jarFile.toUri().normalize(); + String separator = entryName.startsWith("/") ? "!" : "!/"; + try { + // The jar URI convention appears to be not to re-encode the jarURI + return new URI("jar:" + jarURI + separator + entryName); + } catch (URISyntaxException e) { + throw new CannotCreateUriError(jarURI + separator + entryName, e); + } + } + } + + /** + * Create a PathFileObject for a file in a modular file system, such as jrt:, + * such that the binary name can be inferred from its position within the + * filesystem. + * + * The binary name is derived from {@code path}, ignoring the first two + * elements of the name (which are "modules" and a module name). + * The name is derived from {@code path}. + * + * @param fileManager the file manager creating this file object + * @param path the path referred to by this file object + */ + public static PathFileObject forJRTPath(BaseFileManager fileManager, final Path path) { - return new PathFileObject(fileManager, path) { - @Override - public String inferBinaryName(Iterable paths) { - return toBinaryName(path); - } - }; + return new JRTFileObject(fileManager, path); + } + + private static class JRTFileObject extends PathFileObject { + // private final Path javaHome; + private JRTFileObject(BaseFileManager fileManager, Path path) { + super(fileManager, path); + } + + @Override @DefinedBy(Api.COMPILER) + public String getName() { + return path.toString(); + } + + @Override + public String inferBinaryName(Iterable paths) { + // use subpath to ignore the leading /modules/MODULE-NAME + return toBinaryName(path.subpath(2, path.getNameCount())); + } + + @Override + public String toString() { + return "JRTFileObject[" + path + "]"; + } + + @Override + PathFileObject getSibling(String baseName) { + return new JRTFileObject(fileManager, + path.resolveSibling(baseName) + ); + } } /** - * Create a PathFileObject in a modular file system, such as jrt:, such that - * the binary name can be inferred from its position within the filesystem. + * Create a PathFileObject for a file whose binary name must be inferred + * from its position on a search path. + * + * The binary name is inferred by finding an enclosing directory in + * the sequence of paths associated with the location given to + * {@link JavaFileManager#inferBinaryName). + * The name is derived from {@code userPath}. + * + * @param fileManager the file manager creating this file object + * @param path the path referred to by this file object + * @param userPath the "user-friendly" name for this path. */ - public static PathFileObject createJRTPathFileObject(BaseFileManager fileManager, - final Path path) { - return new PathFileObject(fileManager, path) { - @Override - public String inferBinaryName(Iterable paths) { - // use subpath to ignore the leading /modules/MODULE-NAME - return toBinaryName(path.subpath(2, path.getNameCount())); - } - }; + static PathFileObject forSimplePath(BaseFileManager fileManager, + Path path, Path userPath) { + return new SimpleFileObject(fileManager, path, userPath); } - /** - * Create a PathFileObject whose binary name can be inferred from the - * relative path to a sibling. - */ - static PathFileObject createSiblingPathFileObject(BaseFileManager fileManager, - final Path path, final String relativePath) { - return new PathFileObject(fileManager, path) { - @Override - public String inferBinaryName(Iterable paths) { - return toBinaryName(relativePath, "/"); - } - }; - } + private static class SimpleFileObject extends PathFileObject { + private final Path userPath; + private SimpleFileObject(BaseFileManager fileManager, Path path, Path userPath) { + super(fileManager, path); + this.userPath = userPath; + } - /** - * Create a PathFileObject whose binary name might be inferred from its - * position on a search path. - */ - static PathFileObject createSimplePathFileObject(BaseFileManager fileManager, - final Path path) { - return new PathFileObject(fileManager, path) { - @Override - public String inferBinaryName(Iterable paths) { - Path absPath = path.toAbsolutePath(); - for (Path p: paths) { - Path ap = p.toAbsolutePath(); - if (absPath.startsWith(ap)) { - try { - Path rp = ap.relativize(absPath); - if (rp != null) // maybe null if absPath same as ap - return toBinaryName(rp); - } catch (IllegalArgumentException e) { - // ignore this p if cannot relativize path to p - } + @Override @DefinedBy(Api.COMPILER) + public String getName() { + return userPath.toString(); + } + + @Override + public String inferBinaryName(Iterable paths) { + Path absPath = path.toAbsolutePath(); + for (Path p: paths) { + Path ap = p.toAbsolutePath(); + if (absPath.startsWith(ap)) { + try { + Path rp = ap.relativize(absPath); + if (rp != null) // maybe null if absPath same as ap + return toBinaryName(rp); + } catch (IllegalArgumentException e) { + // ignore this p if cannot relativize path to p } } - return null; } - }; + return null; + } + + @Override + PathFileObject getSibling(String baseName) { + return new SimpleFileObject(fileManager, + path.resolveSibling(baseName), + userPath.resolveSibling(baseName) + ); + } } + /** + * Create a PathFileObject, for a specified path, in the context of + * a given file manager. + * + * In general, this path should be an + * {@link Path#toAbsolutePath absolute path}, if not a + * {@link Path#toRealPath} real path. + * It will be used as the basis of {@code equals}, {@code hashCode} + * and {@code isSameFile} methods on this file object. + * + * A PathFileObject should also have a "friendly name" per the + * specification for {@link FileObject#getName}. The friendly name + * is provided by the various subtypes of {@code PathFileObject}. + * + * @param fileManager the file manager creating this file object + * @param path the path contained in this file object. + */ protected PathFileObject(BaseFileManager fileManager, Path path) { this.fileManager = Objects.requireNonNull(fileManager); - this.path = Objects.requireNonNull(path); + if (Files.isDirectory(path)) { + throw new IllegalArgumentException("directories not supported"); + } + this.path = path; } - public abstract String inferBinaryName(Iterable paths); + /** + * See {@link JavacFileManager#inferBinaryName}. + */ + abstract String inferBinaryName(Iterable paths); + + /** + * Return the file object for a sibling file with a given file name. + * See {@link JavacFileManager#getFileForOutput} and + * {@link JavacFileManager#getJavaFileForOutput}. + */ + abstract PathFileObject getSibling(String basename); /** * Return the Path for this object. * @return the Path for this object. + * @see StandardJavaFileManager#asPath */ public Path getPath() { return path; } + /** + * The short name is used when generating raw diagnostics. + * @return the last component of the path + */ + public String getShortName() { + return path.getFileName().toString(); + } + @Override @DefinedBy(Api.COMPILER) public Kind getKind() { return BaseFileManager.getKind(path.getFileName().toString()); @@ -174,22 +375,43 @@ public abstract class PathFileObject implements JavaFileObject { @Override @DefinedBy(Api.COMPILER) public boolean isNameCompatible(String simpleName, Kind kind) { Objects.requireNonNull(simpleName); - // null check + Objects.requireNonNull(kind); + if (kind == Kind.OTHER && getKind() != kind) { return false; } + String sn = simpleName + kind.extension; String pn = path.getFileName().toString(); if (pn.equals(sn)) { return true; } - if (pn.equalsIgnoreCase(sn)) { - try { - // allow for Windows - return path.toRealPath(LinkOption.NOFOLLOW_LINKS).getFileName().toString().equals(sn); - } catch (IOException e) { + + if (path.getFileSystem() == defaultFileSystem) { + if (isMacOS) { + String name = path.getFileName().toString(); + if (Normalizer.isNormalized(name, Normalizer.Form.NFD) + && Normalizer.isNormalized(sn, Normalizer.Form.NFC)) { + // On Mac OS X it is quite possible to have the file name and the + // given simple name normalized in different ways. + // In that case we have to normalize file name to the + // Normal Form Composed (NFC). + String normName = Normalizer.normalize(name, Normalizer.Form.NFC); + if (normName.equals(sn)) { + return true; + } + } + } + + if (pn.equalsIgnoreCase(sn)) { + try { + // allow for Windows + return path.toRealPath(LinkOption.NOFOLLOW_LINKS).getFileName().toString().equals(sn); + } catch (IOException e) { + } } } + return false; } @@ -208,11 +430,6 @@ public abstract class PathFileObject implements JavaFileObject { return path.toUri(); } - @Override @DefinedBy(Api.COMPILER) - public String getName() { - return path.toString(); - } - @Override @DefinedBy(Api.COMPILER) public InputStream openInputStream() throws IOException { return Files.newInputStream(path); @@ -264,7 +481,7 @@ public abstract class PathFileObject implements JavaFileObject { try { return Files.getLastModifiedTime(path).toMillis(); } catch (IOException e) { - return -1; + return 0; } } @@ -278,7 +495,7 @@ public abstract class PathFileObject implements JavaFileObject { } } - public boolean isSameFile(PathFileObject other) { + boolean isSameFile(PathFileObject other) { try { return Files.isSameFile(path, other.path); } catch (IOException e) { @@ -302,17 +519,21 @@ public abstract class PathFileObject implements JavaFileObject { } private void ensureParentDirectoriesExist() throws IOException { - Path parent = path.getParent(); - if (parent != null) - Files.createDirectories(parent); + if (!hasParents) { + Path parent = path.getParent(); + if (parent != null && !Files.isDirectory(parent)) { + try { + Files.createDirectories(parent); + } catch (IOException e) { + throw new IOException("could not create parent directories", e); + } + } + hasParents = true; + } } - private long size() { - try { - return Files.size(path); - } catch (IOException e) { - return -1; - } + protected static String toBinaryName(RelativePath relativePath) { + return toBinaryName(relativePath.path, "/"); } protected static String toBinaryName(Path relativePath) { @@ -320,12 +541,32 @@ public abstract class PathFileObject implements JavaFileObject { relativePath.getFileSystem().getSeparator()); } - protected static String toBinaryName(String relativePath, String sep) { + private static String toBinaryName(String relativePath, String sep) { return removeExtension(relativePath).replace(sep, "."); } - protected static String removeExtension(String fileName) { + private static String removeExtension(String fileName) { int lastDot = fileName.lastIndexOf("."); return (lastDot == -1 ? fileName : fileName.substring(0, lastDot)); } + + /** Return the last component of a presumed hierarchical URI. + * From the scheme specific part of the URI, it returns the substring + * after the last "/" if any, or everything if no "/" is found. + */ + public static String getSimpleName(FileObject fo) { + URI uri = fo.toUri(); + String s = uri.getSchemeSpecificPart(); + return s.substring(s.lastIndexOf("/") + 1); // safe when / not found + + } + + /** Used when URLSyntaxException is thrown unexpectedly during + * implementations of FileObject.toURI(). */ + public static class CannotCreateUriError extends Error { + private static final long serialVersionUID = 9101708840997613546L; + public CannotCreateUriError(String value, Throwable cause) { + super(value, cause); + } + } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/RegularFileObject.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/RegularFileObject.java deleted file mode 100644 index 6a605073c29..00000000000 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/RegularFileObject.java +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.tools.javac.file; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.Writer; -import java.lang.ref.Reference; -import java.lang.ref.SoftReference; -import java.net.URI; -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.charset.CharsetDecoder; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.text.Normalizer; -import java.util.Objects; - -import javax.tools.JavaFileObject; - -import com.sun.tools.javac.util.DefinedBy; -import com.sun.tools.javac.util.DefinedBy.Api; - -/** - * A subclass of JavaFileObject representing regular files. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -class RegularFileObject extends BaseFileObject { - - /** Have the parent directories been created? - */ - private boolean hasParents = false; - private String name; - final Path file; - private Reference absFileRef; - final static boolean isMacOS = System.getProperty("os.name", "").contains("OS X"); - - public RegularFileObject(JavacFileManager fileManager, Path f) { - this(fileManager, f.getFileName().toString(), f); - } - - public RegularFileObject(JavacFileManager fileManager, String name, Path f) { - super(fileManager); - if (Files.isDirectory(f)) { - throw new IllegalArgumentException("directories not supported"); - } - this.name = name; - this.file = f; - if (getLastModified() > System.currentTimeMillis()) - fileManager.log.warning("file.from.future", f); - } - - @Override @DefinedBy(Api.COMPILER) - public URI toUri() { - return file.toUri().normalize(); - } - - @Override @DefinedBy(Api.COMPILER) - public String getName() { - return file.toString(); - } - - @Override - public String getShortName() { - return name; - } - - @Override @DefinedBy(Api.COMPILER) - public JavaFileObject.Kind getKind() { - return getKind(name); - } - - @Override @DefinedBy(Api.COMPILER) - public InputStream openInputStream() throws IOException { - return Files.newInputStream(file); - } - - @Override @DefinedBy(Api.COMPILER) - public OutputStream openOutputStream() throws IOException { - fileManager.flushCache(this); - ensureParentDirectoriesExist(); - return Files.newOutputStream(file); - } - - @Override @DefinedBy(Api.COMPILER) - public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException { - CharBuffer cb = fileManager.getCachedContent(this); - if (cb == null) { - try (InputStream in = Files.newInputStream(file)) { - ByteBuffer bb = fileManager.makeByteBuffer(in); - JavaFileObject prev = fileManager.log.useSource(this); - try { - cb = fileManager.decode(bb, ignoreEncodingErrors); - } finally { - fileManager.log.useSource(prev); - } - fileManager.recycleByteBuffer(bb); - if (!ignoreEncodingErrors) { - fileManager.cache(this, cb); - } - } - } - return cb; - } - - @Override @DefinedBy(Api.COMPILER) - public Writer openWriter() throws IOException { - fileManager.flushCache(this); - ensureParentDirectoriesExist(); - return new OutputStreamWriter(Files.newOutputStream(file), fileManager.getEncodingName()); - } - - @Override @DefinedBy(Api.COMPILER) - public long getLastModified() { - try { - return Files.getLastModifiedTime(file).toMillis(); - } catch (IOException e) { - return 0; - } - } - - @Override @DefinedBy(Api.COMPILER) - public boolean delete() { - try { - Files.delete(file); - return true; - } catch (IOException e) { - return false; - } - } - - @Override - protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) { - return fileManager.getDecoder(fileManager.getEncodingName(), ignoreEncodingErrors); - } - - @Override - protected String inferBinaryName(Iterable path) { - String fPath = file.toString(); - //System.err.println("RegularFileObject " + file + " " +r.getPath()); - for (Path dir: path) { - //System.err.println("dir: " + dir); - String sep = dir.getFileSystem().getSeparator(); - String dPath = dir.toString(); - if (dPath.length() == 0) - dPath = System.getProperty("user.dir"); - if (!dPath.endsWith(sep)) - dPath += sep; - if (fPath.regionMatches(true, 0, dPath, 0, dPath.length()) - && Paths.get(fPath.substring(0, dPath.length())).equals(Paths.get(dPath))) { - String relativeName = fPath.substring(dPath.length()); - return removeExtension(relativeName).replace(sep, "."); - } - } - return null; - } - - @Override @DefinedBy(Api.COMPILER) - public boolean isNameCompatible(String cn, JavaFileObject.Kind kind) { - Objects.requireNonNull(cn); - // null check - if (kind == Kind.OTHER && getKind() != kind) { - return false; - } - String n = cn + kind.extension; - if (name.equals(n)) { - return true; - } - if (isMacOS && Normalizer.isNormalized(name, Normalizer.Form.NFD) - && Normalizer.isNormalized(n, Normalizer.Form.NFC)) { - // On Mac OS X it is quite possible to file name and class - // name normalized in a different way - in that case we have to normalize file name - // to the Normal Form Compised (NFC) - String normName = Normalizer.normalize(name, Normalizer.Form.NFC); - if (normName.equals(n)) { - this.name = normName; - return true; - } - } - - if (name.equalsIgnoreCase(n)) { - try { - // allow for Windows - return file.toRealPath().getFileName().toString().equals(n); - } catch (IOException e) { - } - } - return false; - } - - private void ensureParentDirectoriesExist() throws IOException { - if (!hasParents) { - Path parent = file.getParent(); - if (parent != null && !Files.isDirectory(parent)) { - try { - Files.createDirectories(parent); - } catch (IOException e) { - throw new IOException("could not create parent directories", e); - } - } - hasParents = true; - } - } - - /** - * Check if two file objects are equal. - * Two RegularFileObjects are equal if the absolute paths of the underlying - * files are equal. - */ - @Override - public boolean equals(Object other) { - if (this == other) - return true; - - if (!(other instanceof RegularFileObject)) - return false; - - RegularFileObject o = (RegularFileObject) other; - return getAbsoluteFile().equals(o.getAbsoluteFile()); - } - - @Override - public int hashCode() { - return getAbsoluteFile().hashCode(); - } - - private Path getAbsoluteFile() { - Path absFile = (absFileRef == null ? null : absFileRef.get()); - if (absFile == null) { - absFile = file.toAbsolutePath(); - absFileRef = new SoftReference<>(absFile); - } - return absFile; - } -} diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/RelativePath.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/RelativePath.java index cae98cd3064..59d79df9ac1 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/RelativePath.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/RelativePath.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -26,6 +26,7 @@ package com.sun.tools.javac.file; import java.io.File; +import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.InvalidPathException; import java.nio.file.Path; @@ -57,7 +58,7 @@ public abstract class RelativePath implements Comparable { public abstract String basename(); - public Path getFile(Path directory) throws /*unchecked*/ InvalidPathException { + public Path resolveAgainst(Path directory) throws /*unchecked*/ InvalidPathException { if (directory == null) { String sep = FileSystems.getDefault().getSeparator(); return Paths.get(path.replace("/", sep)); @@ -67,6 +68,12 @@ public abstract class RelativePath implements Comparable { } } + public Path resolveAgainst(FileSystem fs) throws /*unchecked*/ InvalidPathException { + String sep = fs.getSeparator(); + Path root = fs.getRootDirectories().iterator().next(); + return root.resolve(path.replace("/", sep)); + } + @Override public int compareTo(RelativePath other) { return path.compareTo(other.path); diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/ZipArchive.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/ZipArchive.java deleted file mode 100644 index 05c291eb421..00000000000 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/ZipArchive.java +++ /dev/null @@ -1,290 +0,0 @@ -/* - * Copyright (c) 2005, 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 com.sun.tools.javac.file; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.Writer; -import java.lang.ref.Reference; -import java.lang.ref.SoftReference; -import java.net.URI; -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.charset.CharsetDecoder; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; - -import javax.tools.JavaFileObject; - -import com.sun.tools.javac.file.JavacFileManager.Archive; -import com.sun.tools.javac.file.RelativePath.RelativeDirectory; -import com.sun.tools.javac.file.RelativePath.RelativeFile; -import com.sun.tools.javac.util.DefinedBy; -import com.sun.tools.javac.util.DefinedBy.Api; -import com.sun.tools.javac.util.List; - -/** - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class ZipArchive implements Archive { - - public ZipArchive(JavacFileManager fm, ZipFile zfile) throws IOException { - this(fm, zfile, true); - } - - protected ZipArchive(JavacFileManager fm, ZipFile zfile, boolean initMap) throws IOException { - this.fileManager = fm; - this.zfile = zfile; - this.map = new HashMap<>(); - if (initMap) - initMap(); - } - - protected void initMap() throws IOException { - for (Enumeration e = zfile.entries(); e.hasMoreElements(); ) { - ZipEntry entry; - try { - entry = e.nextElement(); - } catch (InternalError ex) { - IOException io = new IOException(); - io.initCause(ex); // convenience constructors added in Mustang :-( - throw io; - } - addZipEntry(entry); - } - } - - void addZipEntry(ZipEntry entry) { - String name = entry.getName(); - int i = name.lastIndexOf('/'); - RelativeDirectory dirname = new RelativeDirectory(name.substring(0, i+1)); - String basename = name.substring(i+1); - if (basename.length() == 0) - return; - List list = map.get(dirname); - if (list == null) - list = List.nil(); - list = list.prepend(basename); - map.put(dirname, list); - } - - public boolean contains(RelativePath name) { - RelativeDirectory dirname = name.dirname(); - String basename = name.basename(); - if (basename.length() == 0) - return false; - List list = map.get(dirname); - return (list != null && list.contains(basename)); - } - - public List getFiles(RelativeDirectory subdirectory) { - return map.get(subdirectory); - } - - public JavaFileObject getFileObject(RelativeDirectory subdirectory, String file) { - ZipEntry ze = new RelativeFile(subdirectory, file).getZipEntry(zfile); - return new ZipFileObject(this, file, ze); - } - - public Set getSubdirectories() { - return map.keySet(); - } - - public void close() throws IOException { - zfile.close(); - } - - @Override - public String toString() { - return "ZipArchive[" + zfile.getName() + "]"; - } - - private Path getAbsoluteFile() { - Path absFile = (absFileRef == null ? null : absFileRef.get()); - if (absFile == null) { - absFile = Paths.get(zfile.getName()).toAbsolutePath(); - absFileRef = new SoftReference<>(absFile); - } - return absFile; - } - - /** - * The file manager that created this archive. - */ - protected JavacFileManager fileManager; - /** - * The index for the contents of this archive. - */ - protected final Map> map; - /** - * The zip file for the archive. - */ - protected final ZipFile zfile; - /** - * A reference to the absolute filename for the zip file for the archive. - */ - protected Reference absFileRef; - - /** - * A subclass of JavaFileObject representing zip entries. - */ - public static class ZipFileObject extends BaseFileObject { - - private String name; - ZipArchive zarch; - ZipEntry entry; - - protected ZipFileObject(ZipArchive zarch, String name, ZipEntry entry) { - super(zarch.fileManager); - this.zarch = zarch; - this.name = name; - this.entry = entry; - } - - @DefinedBy(Api.COMPILER) - public URI toUri() { - Path zipFile = Paths.get(zarch.zfile.getName()); - return createJarUri(zipFile, entry.getName()); - } - - @Override @DefinedBy(Api.COMPILER) - public String getName() { - return zarch.zfile.getName() + "(" + entry.getName() + ")"; - } - - @Override - public String getShortName() { - return Paths.get(zarch.zfile.getName()).getFileName() + "(" + entry + ")"; - } - - @Override @DefinedBy(Api.COMPILER) - public JavaFileObject.Kind getKind() { - return getKind(entry.getName()); - } - - @Override @DefinedBy(Api.COMPILER) - public InputStream openInputStream() throws IOException { - return zarch.zfile.getInputStream(entry); - } - - @Override @DefinedBy(Api.COMPILER) - public OutputStream openOutputStream() throws IOException { - throw new UnsupportedOperationException(); - } - - @Override @DefinedBy(Api.COMPILER) - public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException { - CharBuffer cb = fileManager.getCachedContent(this); - if (cb == null) { - try (InputStream in = zarch.zfile.getInputStream(entry)) { - ByteBuffer bb = fileManager.makeByteBuffer(in); - JavaFileObject prev = fileManager.log.useSource(this); - try { - cb = fileManager.decode(bb, ignoreEncodingErrors); - } finally { - fileManager.log.useSource(prev); - } - fileManager.recycleByteBuffer(bb); - if (!ignoreEncodingErrors) { - fileManager.cache(this, cb); - } - } - } - return cb; - } - - @Override @DefinedBy(Api.COMPILER) - public Writer openWriter() throws IOException { - throw new UnsupportedOperationException(); - } - - @Override @DefinedBy(Api.COMPILER) - public long getLastModified() { - return entry.getTime(); - } - - @Override @DefinedBy(Api.COMPILER) - public boolean delete() { - throw new UnsupportedOperationException(); - } - - @Override - protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) { - return fileManager.getDecoder(fileManager.getEncodingName(), ignoreEncodingErrors); - } - - @Override - protected String inferBinaryName(Iterable path) { - String entryName = entry.getName(); - return removeExtension(entryName).replace('/', '.'); - } - - @Override @DefinedBy(Api.COMPILER) - public boolean isNameCompatible(String cn, JavaFileObject.Kind k) { - Objects.requireNonNull(cn); - // null check - if (k == Kind.OTHER && getKind() != k) { - return false; - } - return name.equals(cn + k.extension); - } - - /** - * Check if two file objects are equal. - * Two ZipFileObjects are equal if the absolute paths of the underlying - * zip files are equal and if the paths within those zip files are equal. - */ - @Override - public boolean equals(Object other) { - if (this == other) - return true; - - if (!(other instanceof ZipFileObject)) - return false; - - ZipFileObject o = (ZipFileObject) other; - return zarch.getAbsoluteFile().equals(o.zarch.getAbsoluteFile()) - && entry.getName().equals(o.entry.getName()); - } - - @Override - public int hashCode() { - return zarch.getAbsoluteFile().hashCode() + entry.getName().hashCode(); - } - } - -} diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/ZipFileIndex.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/ZipFileIndex.java deleted file mode 100644 index 9002498a732..00000000000 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/ZipFileIndex.java +++ /dev/null @@ -1,1171 +0,0 @@ -/* - * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.tools.javac.file; - - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.lang.ref.Reference; -import java.lang.ref.SoftReference; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.zip.DataFormatException; -import java.util.zip.Inflater; -import java.util.zip.ZipException; - -import com.sun.tools.javac.file.RelativePath.RelativeDirectory; -import com.sun.tools.javac.file.RelativePath.RelativeFile; - -/** - * This class implements the building of index of a zip archive and access to - * its context. It also uses a prebuilt index if available. - * It supports invocations where it will serialize an optimized zip index file - * to disk. - * - * In order to use a secondary index file, set "usezipindex" in the Options - * object when JavacFileManager is invoked. (You can pass "-XDusezipindex" on - * the command line.) - * - * Location where to look for/generate optimized zip index files can be - * provided using "{@code -XDcachezipindexdir=}". If this flag is not - * provided, the default location is the value of the "java.io.tmpdir" system - * property. - * - * If "-XDwritezipindexfiles" is specified, there will be new optimized index - * file created for each archive, used by the compiler for compilation, at the - * location specified by the "cachezipindexdir" option. - * - * If system property nonBatchMode option is specified the compiler will use - * timestamp checking to reindex the zip files if it is needed. In batch mode - * the timestamps are not checked and the compiler uses the cached indexes. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class ZipFileIndex { - private static final String MIN_CHAR = String.valueOf(Character.MIN_VALUE); - private static final String MAX_CHAR = String.valueOf(Character.MAX_VALUE); - - public final static long NOT_MODIFIED = Long.MIN_VALUE; - - - private static final boolean NON_BATCH_MODE = System.getProperty("nonBatchMode") != null;// TODO: Use -XD compiler switch for this. - - private Map directories = - Collections.emptyMap(); - private Set allDirs = - Collections.emptySet(); - - // ZipFileIndex data entries - final Path zipFile; - private Reference absFileRef; - long zipFileLastModified = NOT_MODIFIED; - private RandomAccessFile zipRandomFile; - private Entry[] entries; - - private boolean readFromIndex = false; - private Path zipIndexFile = null; - private boolean triedToReadIndex = false; - final RelativeDirectory symbolFilePrefix; - private final int symbolFilePrefixLength; - private boolean hasPopulatedData = false; - long lastReferenceTimeStamp = NOT_MODIFIED; - - private final boolean usePreindexedCache; - private final String preindexedCacheLocation; - - private boolean writeIndex = false; - - private Map> relativeDirectoryCache = new HashMap<>(); - - - public synchronized boolean isOpen() { - return (zipRandomFile != null); - } - - ZipFileIndex(Path zipFile, RelativeDirectory symbolFilePrefix, boolean writeIndex, - boolean useCache, String cacheLocation) throws IOException { - this.zipFile = zipFile; - this.symbolFilePrefix = symbolFilePrefix; - this.symbolFilePrefixLength = (symbolFilePrefix == null ? 0 : - symbolFilePrefix.getPath().getBytes("UTF-8").length); - this.writeIndex = writeIndex; - this.usePreindexedCache = useCache; - this.preindexedCacheLocation = cacheLocation; - - if (zipFile != null) { - this.zipFileLastModified = Files.getLastModifiedTime(zipFile).toMillis(); - } - - // Validate integrity of the zip file - checkIndex(); - } - - @Override - public String toString() { - return "ZipFileIndex[" + zipFile + "]"; - } - - // Just in case... - @Override - protected void finalize() throws Throwable { - closeFile(); - super.finalize(); - } - - private boolean isUpToDate() { - try { - return (zipFile != null - && ((!NON_BATCH_MODE) || zipFileLastModified == Files.getLastModifiedTime(zipFile).toMillis()) - && hasPopulatedData); - } catch (IOException ignore) { - } - - return false; - } - - /** - * Here we need to make sure that the ZipFileIndex is valid. Check the timestamp of the file and - * if its the same as the one at the time the index was build we don't need to reopen anything. - */ - private void checkIndex() throws IOException { - boolean isUpToDate = true; - if (!isUpToDate()) { - closeFile(); - isUpToDate = false; - } - - if (zipRandomFile != null || isUpToDate) { - lastReferenceTimeStamp = System.currentTimeMillis(); - return; - } - - hasPopulatedData = true; - - if (readIndex()) { - lastReferenceTimeStamp = System.currentTimeMillis(); - return; - } - - directories = Collections.emptyMap(); - allDirs = Collections.emptySet(); - - try { - openFile(); - long totalLength = zipRandomFile.length(); - ZipDirectory directory = new ZipDirectory(zipRandomFile, 0L, totalLength, this); - directory.buildIndex(); - } finally { - if (zipRandomFile != null) { - closeFile(); - } - } - - lastReferenceTimeStamp = System.currentTimeMillis(); - } - - private void openFile() throws FileNotFoundException { - if (zipRandomFile == null && zipFile != null) { - zipRandomFile = new RandomAccessFile(zipFile.toFile(), "r"); - } - } - - private void cleanupState() { - // Make sure there is a valid but empty index if the file doesn't exist - entries = Entry.EMPTY_ARRAY; - directories = Collections.emptyMap(); - zipFileLastModified = NOT_MODIFIED; - allDirs = Collections.emptySet(); - } - - public synchronized void close() { - writeIndex(); - closeFile(); - } - - private void closeFile() { - if (zipRandomFile != null) { - try { - zipRandomFile.close(); - } catch (IOException ex) { - } - zipRandomFile = null; - } - } - - /** - * Returns the ZipFileIndexEntry for a path, if there is one. - */ - synchronized Entry getZipIndexEntry(RelativePath path) { - try { - checkIndex(); - DirectoryEntry de = directories.get(path.dirname()); - String lookFor = path.basename(); - return (de == null) ? null : de.getEntry(lookFor); - } - catch (IOException e) { - return null; - } - } - - /** - * Returns a javac List of filenames within a directory in the ZipFileIndex. - */ - public synchronized com.sun.tools.javac.util.List getFiles(RelativeDirectory path) { - try { - checkIndex(); - - DirectoryEntry de = directories.get(path); - com.sun.tools.javac.util.List ret = de == null ? null : de.getFiles(); - - if (ret == null) { - return com.sun.tools.javac.util.List.nil(); - } - return ret; - } - catch (IOException e) { - return com.sun.tools.javac.util.List.nil(); - } - } - - public synchronized List getDirectories(RelativeDirectory path) { - try { - checkIndex(); - - DirectoryEntry de = directories.get(path); - com.sun.tools.javac.util.List ret = de == null ? null : de.getDirectories(); - - if (ret == null) { - return com.sun.tools.javac.util.List.nil(); - } - - return ret; - } - catch (IOException e) { - return com.sun.tools.javac.util.List.nil(); - } - } - - public synchronized Set getAllDirectories() { - try { - checkIndex(); - if (allDirs == Collections.EMPTY_SET) { - allDirs = new java.util.LinkedHashSet<>(directories.keySet()); - } - - return allDirs; - } - catch (IOException e) { - return Collections.emptySet(); - } - } - - /** - * Tests if a specific path exists in the zip. This method will return true - * for file entries and directories. - * - * @param path A path within the zip. - * @return True if the path is a file or dir, false otherwise. - */ - public synchronized boolean contains(RelativePath path) { - try { - checkIndex(); - return getZipIndexEntry(path) != null; - } - catch (IOException e) { - return false; - } - } - - public synchronized boolean isDirectory(RelativePath path) throws IOException { - // The top level in a zip file is always a directory. - if (path.getPath().length() == 0) { - lastReferenceTimeStamp = System.currentTimeMillis(); - return true; - } - - checkIndex(); - return directories.get(path) != null; - } - - public synchronized long getLastModified(RelativeFile path) throws IOException { - Entry entry = getZipIndexEntry(path); - if (entry == null) - throw new FileNotFoundException(); - return entry.getLastModified(); - } - - public synchronized int length(RelativeFile path) throws IOException { - Entry entry = getZipIndexEntry(path); - if (entry == null) - throw new FileNotFoundException(); - - if (entry.isDir) { - return 0; - } - - byte[] header = getHeader(entry); - // entry is not compressed? - if (get2ByteLittleEndian(header, 8) == 0) { - return entry.compressedSize; - } else { - return entry.size; - } - } - - public synchronized byte[] read(RelativeFile path) throws IOException { - Entry entry = getZipIndexEntry(path); - if (entry == null) - throw new FileNotFoundException("Path not found in ZIP: " + path.path); - return read(entry); - } - - synchronized byte[] read(Entry entry) throws IOException { - openFile(); - byte[] result = readBytes(entry); - closeFile(); - return result; - } - - public synchronized int read(RelativeFile path, byte[] buffer) throws IOException { - Entry entry = getZipIndexEntry(path); - if (entry == null) - throw new FileNotFoundException(); - return read(entry, buffer); - } - - synchronized int read(Entry entry, byte[] buffer) - throws IOException { - int result = readBytes(entry, buffer); - return result; - } - - private byte[] readBytes(Entry entry) throws IOException { - byte[] header = getHeader(entry); - int csize = entry.compressedSize; - byte[] cbuf = new byte[csize]; - zipRandomFile.skipBytes(get2ByteLittleEndian(header, 26) + get2ByteLittleEndian(header, 28)); - zipRandomFile.readFully(cbuf, 0, csize); - - // is this compressed - offset 8 in the ZipEntry header - if (get2ByteLittleEndian(header, 8) == 0) - return cbuf; - - int size = entry.size; - byte[] buf = new byte[size]; - if (inflate(cbuf, buf) != size) - throw new ZipException("corrupted zip file"); - - return buf; - } - - /** - * - */ - private int readBytes(Entry entry, byte[] buffer) throws IOException { - byte[] header = getHeader(entry); - - // entry is not compressed? - if (get2ByteLittleEndian(header, 8) == 0) { - zipRandomFile.skipBytes(get2ByteLittleEndian(header, 26) + get2ByteLittleEndian(header, 28)); - int offset = 0; - int size = buffer.length; - while (offset < size) { - int count = zipRandomFile.read(buffer, offset, size - offset); - if (count == -1) - break; - offset += count; - } - return entry.size; - } - - int csize = entry.compressedSize; - byte[] cbuf = new byte[csize]; - zipRandomFile.skipBytes(get2ByteLittleEndian(header, 26) + get2ByteLittleEndian(header, 28)); - zipRandomFile.readFully(cbuf, 0, csize); - - int count = inflate(cbuf, buffer); - if (count == -1) - throw new ZipException("corrupted zip file"); - - return entry.size; - } - - //---------------------------------------------------------------------------- - // Zip utilities - //---------------------------------------------------------------------------- - - private byte[] getHeader(Entry entry) throws IOException { - zipRandomFile.seek(entry.offset); - byte[] header = new byte[30]; - zipRandomFile.readFully(header); - if (get4ByteLittleEndian(header, 0) != 0x04034b50) - throw new ZipException("corrupted zip file"); - if ((get2ByteLittleEndian(header, 6) & 1) != 0) - throw new ZipException("encrypted zip file"); // offset 6 in the header of the ZipFileEntry - return header; - } - - /* - * Inflate using the java.util.zip.Inflater class - */ - private SoftReference inflaterRef; - private int inflate(byte[] src, byte[] dest) { - Inflater inflater = (inflaterRef == null ? null : inflaterRef.get()); - - // construct the inflater object or reuse an existing one - if (inflater == null) - inflaterRef = new SoftReference<>(inflater = new Inflater(true)); - - inflater.reset(); - inflater.setInput(src); - try { - return inflater.inflate(dest); - } catch (DataFormatException ex) { - return -1; - } - } - - /** - * return the two bytes buf[pos], buf[pos+1] as an unsigned integer in little - * endian format. - */ - private static int get2ByteLittleEndian(byte[] buf, int pos) { - return (buf[pos] & 0xFF) + ((buf[pos+1] & 0xFF) << 8); - } - - /** - * return the 4 bytes buf[i..i+3] as an integer in little endian format. - */ - private static int get4ByteLittleEndian(byte[] buf, int pos) { - return (buf[pos] & 0xFF) + ((buf[pos + 1] & 0xFF) << 8) + - ((buf[pos + 2] & 0xFF) << 16) + ((buf[pos + 3] & 0xFF) << 24); - } - - /* ---------------------------------------------------------------------------- - * ZipDirectory - * ----------------------------------------------------------------------------*/ - - private class ZipDirectory { - private RelativeDirectory lastDir; - private int lastStart; - private int lastLen; - - byte[] zipDir; - RandomAccessFile zipRandomFile = null; - ZipFileIndex zipFileIndex = null; - - public ZipDirectory(RandomAccessFile zipRandomFile, long start, long end, ZipFileIndex index) throws IOException { - this.zipRandomFile = zipRandomFile; - this.zipFileIndex = index; - hasValidHeader(); - findCENRecord(start, end); - } - - /* - * the zip entry signature should be at offset 0, otherwise allow the - * calling logic to take evasive action by throwing ZipFormatException. - */ - private boolean hasValidHeader() throws IOException { - final long pos = zipRandomFile.getFilePointer(); - try { - if (zipRandomFile.read() == 'P') { - if (zipRandomFile.read() == 'K') { - if (zipRandomFile.read() == 0x03) { - if (zipRandomFile.read() == 0x04) { - return true; - } - } - } - } - } finally { - zipRandomFile.seek(pos); - } - throw new ZipFormatException("invalid zip magic"); - } - - /* - * Reads zip file central directory. - * For more details see readCEN in zip_util.c from the JDK sources. - * This is a Java port of that function. - */ - private void findCENRecord(long start, long end) throws IOException { - long totalLength = end - start; - int endbuflen = 1024; - byte[] endbuf = new byte[endbuflen]; - long endbufend = end - start; - - // There is a variable-length field after the dir offset record. We need to do consequential search. - while (endbufend >= 22) { - if (endbufend < endbuflen) - endbuflen = (int)endbufend; - long endbufpos = endbufend - endbuflen; - zipRandomFile.seek(start + endbufpos); - zipRandomFile.readFully(endbuf, 0, endbuflen); - int i = endbuflen - 22; - while (i >= 0 && - !(endbuf[i] == 0x50 && - endbuf[i + 1] == 0x4b && - endbuf[i + 2] == 0x05 && - endbuf[i + 3] == 0x06 && - endbufpos + i + 22 + - get2ByteLittleEndian(endbuf, i + 20) == totalLength)) { - i--; - } - - if (i >= 0) { - zipDir = new byte[get4ByteLittleEndian(endbuf, i + 12)]; - int sz = get4ByteLittleEndian(endbuf, i + 16); - // a negative offset or the entries field indicates a - // potential zip64 archive - if (sz < 0 || get2ByteLittleEndian(endbuf, i + 10) == 0xffff) { - throw new ZipFormatException("detected a zip64 archive"); - } - zipRandomFile.seek(start + sz); - zipRandomFile.readFully(zipDir, 0, zipDir.length); - return; - } else { - endbufend = endbufpos + 21; - } - } - throw new ZipException("cannot read zip file"); - } - - private void buildIndex() throws IOException { - int len = zipDir.length; - - // Add each of the files - if (len > 0) { - directories = new LinkedHashMap<>(); - ArrayList entryList = new ArrayList<>(); - for (int pos = 0; pos < len; ) { - pos = readEntry(pos, entryList, directories); - } - - // Add the accumulated dirs into the same list - for (RelativeDirectory d: directories.keySet()) { - // use shared RelativeDirectory objects for parent dirs - RelativeDirectory parent = getRelativeDirectory(d.dirname().getPath()); - String file = d.basename(); - Entry zipFileIndexEntry = new Entry(parent, file); - zipFileIndexEntry.isDir = true; - entryList.add(zipFileIndexEntry); - } - - entries = entryList.toArray(new Entry[entryList.size()]); - Arrays.sort(entries); - } else { - cleanupState(); - } - } - - private int readEntry(int pos, List entryList, - Map directories) throws IOException { - if (get4ByteLittleEndian(zipDir, pos) != 0x02014b50) { - throw new ZipException("cannot read zip file entry"); - } - - int dirStart = pos + 46; - int fileStart = dirStart; - int fileEnd = fileStart + get2ByteLittleEndian(zipDir, pos + 28); - - if (zipFileIndex.symbolFilePrefixLength != 0 && - ((fileEnd - fileStart) >= symbolFilePrefixLength)) { - dirStart += zipFileIndex.symbolFilePrefixLength; - fileStart += zipFileIndex.symbolFilePrefixLength; - } - // Force any '\' to '/'. Keep the position of the last separator. - for (int index = fileStart; index < fileEnd; index++) { - byte nextByte = zipDir[index]; - if (nextByte == (byte)'\\') { - zipDir[index] = (byte)'/'; - fileStart = index + 1; - } else if (nextByte == (byte)'/') { - fileStart = index + 1; - } - } - - RelativeDirectory directory = null; - if (fileStart == dirStart) - directory = getRelativeDirectory(""); - else if (lastDir != null && lastLen == fileStart - dirStart - 1) { - int index = lastLen - 1; - while (zipDir[lastStart + index] == zipDir[dirStart + index]) { - if (index == 0) { - directory = lastDir; - break; - } - index--; - } - } - - // Sub directories - if (directory == null) { - lastStart = dirStart; - lastLen = fileStart - dirStart - 1; - - directory = getRelativeDirectory(new String(zipDir, dirStart, lastLen, "UTF-8")); - lastDir = directory; - - // Enter also all the parent directories - RelativeDirectory tempDirectory = directory; - - while (directories.get(tempDirectory) == null) { - directories.put(tempDirectory, new DirectoryEntry(tempDirectory, zipFileIndex)); - if (tempDirectory.path.indexOf("/") == tempDirectory.path.length() - 1) - break; - else { - // use shared RelativeDirectory objects for parent dirs - tempDirectory = getRelativeDirectory(tempDirectory.dirname().getPath()); - } - } - } - else { - if (directories.get(directory) == null) { - directories.put(directory, new DirectoryEntry(directory, zipFileIndex)); - } - } - - // For each dir create also a file - if (fileStart != fileEnd) { - Entry entry = new Entry(directory, - new String(zipDir, fileStart, fileEnd - fileStart, "UTF-8")); - - entry.setNativeTime(get4ByteLittleEndian(zipDir, pos + 12)); - entry.compressedSize = get4ByteLittleEndian(zipDir, pos + 20); - entry.size = get4ByteLittleEndian(zipDir, pos + 24); - entry.offset = get4ByteLittleEndian(zipDir, pos + 42); - entryList.add(entry); - } - - return pos + 46 + - get2ByteLittleEndian(zipDir, pos + 28) + - get2ByteLittleEndian(zipDir, pos + 30) + - get2ByteLittleEndian(zipDir, pos + 32); - } - } - - /** - * Returns the last modified timestamp of a zip file. - * @return long - */ - public long getZipFileLastModified() throws IOException { - synchronized (this) { - checkIndex(); - return zipFileLastModified; - } - } - - /** ------------------------------------------------------------------------ - * DirectoryEntry class - * -------------------------------------------------------------------------*/ - - static class DirectoryEntry { - private boolean filesInited; - private boolean directoriesInited; - private boolean zipFileEntriesInited; - private boolean entriesInited; - - private long writtenOffsetOffset = 0; - - private RelativeDirectory dirName; - - private com.sun.tools.javac.util.List zipFileEntriesFiles = com.sun.tools.javac.util.List.nil(); - private com.sun.tools.javac.util.List zipFileEntriesDirectories = com.sun.tools.javac.util.List.nil(); - private com.sun.tools.javac.util.List zipFileEntries = com.sun.tools.javac.util.List.nil(); - - private List entries = new ArrayList<>(); - - private ZipFileIndex zipFileIndex; - - private int numEntries; - - DirectoryEntry(RelativeDirectory dirName, ZipFileIndex index) { - filesInited = false; - directoriesInited = false; - entriesInited = false; - - this.dirName = dirName; - this.zipFileIndex = index; - } - - private com.sun.tools.javac.util.List getFiles() { - if (!filesInited) { - initEntries(); - for (Entry e : entries) { - if (!e.isDir) { - zipFileEntriesFiles = zipFileEntriesFiles.append(e.name); - } - } - filesInited = true; - } - return zipFileEntriesFiles; - } - - private com.sun.tools.javac.util.List getDirectories() { - if (!directoriesInited) { - initEntries(); - for (Entry e : entries) { - if (e.isDir) { - zipFileEntriesDirectories = zipFileEntriesDirectories.append(e.name); - } - } - directoriesInited = true; - } - return zipFileEntriesDirectories; - } - - private com.sun.tools.javac.util.List getEntries() { - if (!zipFileEntriesInited) { - initEntries(); - zipFileEntries = com.sun.tools.javac.util.List.nil(); - for (Entry zfie : entries) { - zipFileEntries = zipFileEntries.append(zfie); - } - zipFileEntriesInited = true; - } - return zipFileEntries; - } - - private Entry getEntry(String rootName) { - initEntries(); - int index = Collections.binarySearch(entries, new Entry(dirName, rootName)); - if (index < 0) { - return null; - } - - return entries.get(index); - } - - private void initEntries() { - if (entriesInited) { - return; - } - - if (!zipFileIndex.readFromIndex) { - int from = -Arrays.binarySearch(zipFileIndex.entries, - new Entry(dirName, ZipFileIndex.MIN_CHAR)) - 1; - int to = -Arrays.binarySearch(zipFileIndex.entries, - new Entry(dirName, MAX_CHAR)) - 1; - - for (int i = from; i < to; i++) { - entries.add(zipFileIndex.entries[i]); - } - } else { - Path indexFile = zipFileIndex.getIndexFile(); - if (indexFile != null) { - RandomAccessFile raf = null; - try { - raf = new RandomAccessFile(indexFile.toFile(), "r"); - raf.seek(writtenOffsetOffset); - - for (int nFiles = 0; nFiles < numEntries; nFiles++) { - // Read the name bytes - int zfieNameBytesLen = raf.readInt(); - byte [] zfieNameBytes = new byte[zfieNameBytesLen]; - raf.read(zfieNameBytes); - String eName = new String(zfieNameBytes, "UTF-8"); - - // Read isDir - boolean eIsDir = raf.readByte() == (byte)0 ? false : true; - - // Read offset of bytes in the real Jar/Zip file - int eOffset = raf.readInt(); - - // Read size of the file in the real Jar/Zip file - int eSize = raf.readInt(); - - // Read compressed size of the file in the real Jar/Zip file - int eCsize = raf.readInt(); - - // Read java time stamp of the file in the real Jar/Zip file - long eJavaTimestamp = raf.readLong(); - - Entry rfie = new Entry(dirName, eName); - rfie.isDir = eIsDir; - rfie.offset = eOffset; - rfie.size = eSize; - rfie.compressedSize = eCsize; - rfie.javatime = eJavaTimestamp; - entries.add(rfie); - } - } catch (Throwable t) { - // Do nothing - } finally { - try { - if (raf != null) { - raf.close(); - } - } catch (Throwable t) { - // Do nothing - } - } - } - } - - entriesInited = true; - } - - List getEntriesAsCollection() { - initEntries(); - - return entries; - } - } - - private boolean readIndex() { - if (triedToReadIndex || !usePreindexedCache) { - return false; - } - - boolean ret = false; - synchronized (this) { - triedToReadIndex = true; - RandomAccessFile raf = null; - try { - Path indexFileName = getIndexFile(); - raf = new RandomAccessFile(indexFileName.toFile(), "r"); - - long fileStamp = raf.readLong(); - if (Files.getLastModifiedTime(zipFile).toMillis() != fileStamp) { - ret = false; - } else { - directories = new LinkedHashMap<>(); - int numDirs = raf.readInt(); - for (int nDirs = 0; nDirs < numDirs; nDirs++) { - int dirNameBytesLen = raf.readInt(); - byte [] dirNameBytes = new byte[dirNameBytesLen]; - raf.read(dirNameBytes); - - RelativeDirectory dirNameStr = getRelativeDirectory(new String(dirNameBytes, "UTF-8")); - DirectoryEntry de = new DirectoryEntry(dirNameStr, this); - de.numEntries = raf.readInt(); - de.writtenOffsetOffset = raf.readLong(); - directories.put(dirNameStr, de); - } - ret = true; - zipFileLastModified = fileStamp; - } - } catch (Throwable t) { - // Do nothing - } finally { - if (raf != null) { - try { - raf.close(); - } catch (Throwable tt) { - // Do nothing - } - } - } - if (ret == true) { - readFromIndex = true; - } - } - - return ret; - } - - private boolean writeIndex() { - boolean ret = false; - if (readFromIndex || !usePreindexedCache) { - return true; - } - - if (!writeIndex) { - return true; - } - - Path indexFile = getIndexFile(); - if (indexFile == null) { - return false; - } - - RandomAccessFile raf = null; - long writtenSoFar = 0; - try { - raf = new RandomAccessFile(indexFile.toFile(), "rw"); - - raf.writeLong(zipFileLastModified); - writtenSoFar += 8; - - List directoriesToWrite = new ArrayList<>(); - Map offsets = new HashMap<>(); - raf.writeInt(directories.keySet().size()); - writtenSoFar += 4; - - for (RelativeDirectory dirName: directories.keySet()) { - DirectoryEntry dirEntry = directories.get(dirName); - - directoriesToWrite.add(dirEntry); - - // Write the dir name bytes - byte [] dirNameBytes = dirName.getPath().getBytes("UTF-8"); - int dirNameBytesLen = dirNameBytes.length; - raf.writeInt(dirNameBytesLen); - writtenSoFar += 4; - - raf.write(dirNameBytes); - writtenSoFar += dirNameBytesLen; - - // Write the number of files in the dir - List dirEntries = dirEntry.getEntriesAsCollection(); - raf.writeInt(dirEntries.size()); - writtenSoFar += 4; - - offsets.put(dirName, new Long(writtenSoFar)); - - // Write the offset of the file's data in the dir - dirEntry.writtenOffsetOffset = 0L; - raf.writeLong(0L); - writtenSoFar += 8; - } - - for (DirectoryEntry de : directoriesToWrite) { - // Fix up the offset in the directory table - long currFP = raf.getFilePointer(); - - long offsetOffset = offsets.get(de.dirName).longValue(); - raf.seek(offsetOffset); - raf.writeLong(writtenSoFar); - - raf.seek(currFP); - - // Now write each of the files in the DirectoryEntry - List list = de.getEntriesAsCollection(); - for (Entry zfie : list) { - // Write the name bytes - byte [] zfieNameBytes = zfie.name.getBytes("UTF-8"); - int zfieNameBytesLen = zfieNameBytes.length; - raf.writeInt(zfieNameBytesLen); - writtenSoFar += 4; - raf.write(zfieNameBytes); - writtenSoFar += zfieNameBytesLen; - - // Write isDir - raf.writeByte(zfie.isDir ? (byte)1 : (byte)0); - writtenSoFar += 1; - - // Write offset of bytes in the real Jar/Zip file - raf.writeInt(zfie.offset); - writtenSoFar += 4; - - // Write size of the file in the real Jar/Zip file - raf.writeInt(zfie.size); - writtenSoFar += 4; - - // Write compressed size of the file in the real Jar/Zip file - raf.writeInt(zfie.compressedSize); - writtenSoFar += 4; - - // Write java time stamp of the file in the real Jar/Zip file - raf.writeLong(zfie.getLastModified()); - writtenSoFar += 8; - } - } - } catch (Throwable t) { - // Do nothing - } finally { - try { - if (raf != null) { - raf.close(); - } - } catch(IOException ioe) { - // Do nothing - } - } - - return ret; - } - - public boolean writeZipIndex() { - synchronized (this) { - return writeIndex(); - } - } - - private Path getIndexFile() { - if (zipIndexFile == null) { - if (zipFile == null) { - return null; - } - - zipIndexFile = Paths.get((preindexedCacheLocation == null ? "" : preindexedCacheLocation) + - zipFile.getFileName() + ".index"); - } - - return zipIndexFile; - } - - public Path getZipFile() { - return zipFile; - } - - Path getAbsoluteFile() { - Path absFile = (absFileRef == null ? null : absFileRef.get()); - if (absFile == null) { - absFile = zipFile.toAbsolutePath(); - absFileRef = new SoftReference<>(absFile); - } - return absFile; - } - - private RelativeDirectory getRelativeDirectory(String path) { - RelativeDirectory rd; - SoftReference ref = relativeDirectoryCache.get(path); - if (ref != null) { - rd = ref.get(); - if (rd != null) - return rd; - } - rd = new RelativeDirectory(path); - relativeDirectoryCache.put(path, new SoftReference<>(rd)); - return rd; - } - - static class Entry implements Comparable { - public static final Entry[] EMPTY_ARRAY = {}; - - // Directory related - RelativeDirectory dir; - boolean isDir; - - // File related - String name; - - int offset; - int size; - int compressedSize; - long javatime; - - private int nativetime; - - public Entry(RelativePath path) { - this(path.dirname(), path.basename()); - } - - public Entry(RelativeDirectory directory, String name) { - this.dir = directory; - this.name = name; - } - - public String getName() { - return new RelativeFile(dir, name).getPath(); - } - - public String getFileName() { - return name; - } - - public long getLastModified() { - if (javatime == 0) { - javatime = dosToJavaTime(nativetime); - } - return javatime; - } - - // based on dosToJavaTime in java.util.Zip, but avoiding the - // use of deprecated Date constructor - private static long dosToJavaTime(int dtime) { - Calendar c = Calendar.getInstance(); - c.set(Calendar.YEAR, ((dtime >> 25) & 0x7f) + 1980); - c.set(Calendar.MONTH, ((dtime >> 21) & 0x0f) - 1); - c.set(Calendar.DATE, ((dtime >> 16) & 0x1f)); - c.set(Calendar.HOUR_OF_DAY, ((dtime >> 11) & 0x1f)); - c.set(Calendar.MINUTE, ((dtime >> 5) & 0x3f)); - c.set(Calendar.SECOND, ((dtime << 1) & 0x3e)); - c.set(Calendar.MILLISECOND, 0); - return c.getTimeInMillis(); - } - - void setNativeTime(int natTime) { - nativetime = natTime; - } - - public boolean isDirectory() { - return isDir; - } - - public int compareTo(Entry other) { - RelativeDirectory otherD = other.dir; - if (dir != otherD) { - int c = dir.compareTo(otherD); - if (c != 0) - return c; - } - return name.compareTo(other.name); - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof Entry)) - return false; - Entry other = (Entry) o; - return dir.equals(other.dir) && name.equals(other.name); - } - - @Override - public int hashCode() { - int hash = 7; - hash = 97 * hash + (this.dir != null ? this.dir.hashCode() : 0); - hash = 97 * hash + (this.name != null ? this.name.hashCode() : 0); - return hash; - } - - @Override - public String toString() { - return isDir ? ("Dir:" + dir + " : " + name) : - (dir + ":" + name); - } - } - - /* - * Exception primarily used to implement a failover, used exclusively here. - */ - - static final class ZipFormatException extends IOException { - private static final long serialVersionUID = 8000196834066748623L; - protected ZipFormatException(String message) { - super(message); - } - - protected ZipFormatException(String message, Throwable cause) { - super(message, cause); - } - } -} diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/ZipFileIndexArchive.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/ZipFileIndexArchive.java deleted file mode 100644 index 39764d4224b..00000000000 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/ZipFileIndexArchive.java +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright (c) 2005, 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 com.sun.tools.javac.file; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.Writer; -import java.net.URI; -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.charset.CharsetDecoder; -import java.nio.file.Path; -import java.util.Objects; -import java.util.Set; - -import javax.tools.JavaFileObject; - -import com.sun.tools.javac.file.JavacFileManager.Archive; -import com.sun.tools.javac.file.RelativePath.RelativeDirectory; -import com.sun.tools.javac.file.RelativePath.RelativeFile; -import com.sun.tools.javac.util.Assert; -import com.sun.tools.javac.util.DefinedBy; -import com.sun.tools.javac.util.DefinedBy.Api; -import com.sun.tools.javac.util.List; - -/** - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class ZipFileIndexArchive implements Archive { - - private final ZipFileIndex zfIndex; - private final JavacFileManager fileManager; - - public ZipFileIndexArchive(JavacFileManager fileManager, ZipFileIndex zdir) throws IOException { - super(); - this.fileManager = fileManager; - this.zfIndex = zdir; - } - - public boolean contains(RelativePath name) { - return zfIndex.contains(name); - } - - public List getFiles(RelativeDirectory subdirectory) { - return zfIndex.getFiles(subdirectory); - } - - public JavaFileObject getFileObject(RelativeDirectory subdirectory, String file) { - RelativeFile fullZipFileName = new RelativeFile(subdirectory, file); - ZipFileIndex.Entry entry = zfIndex.getZipIndexEntry(fullZipFileName); - JavaFileObject ret = new ZipFileIndexFileObject(fileManager, zfIndex, entry, zfIndex.getZipFile()); - return ret; - } - - public Set getSubdirectories() { - return zfIndex.getAllDirectories(); - } - - public void close() throws IOException { - zfIndex.close(); - } - - @Override - public String toString() { - return "ZipFileIndexArchive[" + zfIndex + "]"; - } - - /** - * A subclass of JavaFileObject representing zip entries using the com.sun.tools.javac.file.ZipFileIndex implementation. - */ - public static class ZipFileIndexFileObject extends BaseFileObject { - - /** The entry's name. - */ - private String name; - - /** The zipfile containing the entry. - */ - ZipFileIndex zfIndex; - - /** The underlying zip entry object. - */ - ZipFileIndex.Entry entry; - - /** The name of the zip file where this entry resides. - */ - Path zipName; - - - ZipFileIndexFileObject(JavacFileManager fileManager, ZipFileIndex zfIndex, ZipFileIndex.Entry entry, Path zipFileName) { - super(fileManager); - this.name = entry.getFileName(); - this.zfIndex = zfIndex; - this.entry = entry; - this.zipName = zipFileName; - } - - @Override @DefinedBy(Api.COMPILER) - public URI toUri() { - return createJarUri(zipName, getPrefixedEntryName()); - } - - @Override @DefinedBy(Api.COMPILER) - public String getName() { - return zipName + "(" + getPrefixedEntryName() + ")"; - } - - @Override - public String getShortName() { - return zipName.getFileName() + "(" + entry.getName() + ")"; - } - - @Override @DefinedBy(Api.COMPILER) - public JavaFileObject.Kind getKind() { - return getKind(entry.getName()); - } - - @Override @DefinedBy(Api.COMPILER) - public InputStream openInputStream() throws IOException { - Assert.checkNonNull(entry); // see constructor - return new ByteArrayInputStream(zfIndex.read(entry)); - } - - @Override @DefinedBy(Api.COMPILER) - public OutputStream openOutputStream() throws IOException { - throw new UnsupportedOperationException(); - } - - @Override @DefinedBy(Api.COMPILER) - public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException { - CharBuffer cb = fileManager.getCachedContent(this); - if (cb == null) { - try (InputStream in = new ByteArrayInputStream(zfIndex.read(entry))) { - ByteBuffer bb = fileManager.makeByteBuffer(in); - JavaFileObject prev = fileManager.log.useSource(this); - try { - cb = fileManager.decode(bb, ignoreEncodingErrors); - } finally { - fileManager.log.useSource(prev); - } - fileManager.recycleByteBuffer(bb); // save for next time - if (!ignoreEncodingErrors) - fileManager.cache(this, cb); - } - } - return cb; - } - - @Override @DefinedBy(Api.COMPILER) - public Writer openWriter() throws IOException { - throw new UnsupportedOperationException(); - } - - @Override @DefinedBy(Api.COMPILER) - public long getLastModified() { - return entry.getLastModified(); - } - - @Override @DefinedBy(Api.COMPILER) - public boolean delete() { - throw new UnsupportedOperationException(); - } - - @Override - protected CharsetDecoder getDecoder(boolean ignoreEncodingErrors) { - return fileManager.getDecoder(fileManager.getEncodingName(), ignoreEncodingErrors); - } - - @Override - protected String inferBinaryName(Iterable path) { - String entryName = entry.getName(); - if (zfIndex.symbolFilePrefix != null) { - String prefix = zfIndex.symbolFilePrefix.path; - if (entryName.startsWith(prefix)) - entryName = entryName.substring(prefix.length()); - } - return removeExtension(entryName).replace('/', '.'); - } - - @Override @DefinedBy(Api.COMPILER) - public boolean isNameCompatible(String cn, JavaFileObject.Kind k) { - Objects.requireNonNull(cn); - if (k == Kind.OTHER && getKind() != k) - return false; - return name.equals(cn + k.extension); - } - - /** - * Check if two file objects are equal. - * Two ZipFileIndexFileObjects are equal if the absolute paths of the underlying - * zip files are equal and if the paths within those zip files are equal. - */ - @Override - public boolean equals(Object other) { - if (this == other) - return true; - - if (!(other instanceof ZipFileIndexFileObject)) - return false; - - ZipFileIndexFileObject o = (ZipFileIndexFileObject) other; - return zfIndex.getAbsoluteFile().equals(o.zfIndex.getAbsoluteFile()) - && entry.equals(o.entry); - } - - @Override - public int hashCode() { - return zfIndex.getAbsoluteFile().hashCode() + entry.hashCode(); - } - - private String getPrefixedEntryName() { - if (zfIndex.symbolFilePrefix != null) - return zfIndex.symbolFilePrefix.path + entry.getName(); - else - return entry.getName(); - } - } - -} diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/ZipFileIndexCache.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/ZipFileIndexCache.java deleted file mode 100644 index f16fa411eb2..00000000000 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/ZipFileIndexCache.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.tools.javac.file; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import com.sun.tools.javac.file.RelativePath.RelativeDirectory; -import com.sun.tools.javac.util.Context; - - -/** A cache for ZipFileIndex objects. */ -public class ZipFileIndexCache { - - private final Map map = new HashMap<>(); - - /** Get a shared instance of the cache. */ - private static ZipFileIndexCache sharedInstance; - public synchronized static ZipFileIndexCache getSharedInstance() { - if (sharedInstance == null) - sharedInstance = new ZipFileIndexCache(); - return sharedInstance; - } - - /** Get a context-specific instance of a cache. */ - public static ZipFileIndexCache instance(Context context) { - ZipFileIndexCache instance = context.get(ZipFileIndexCache.class); - if (instance == null) - context.put(ZipFileIndexCache.class, instance = new ZipFileIndexCache()); - return instance; - } - - /** - * Returns a list of all ZipFileIndex entries - * - * @return A list of ZipFileIndex entries, or an empty list - */ - public List getZipFileIndexes() { - return getZipFileIndexes(false); - } - - /** - * Returns a list of all ZipFileIndex entries - * - * @param openedOnly If true it returns a list of only opened ZipFileIndex entries, otherwise - * all ZipFileEntry(s) are included into the list. - * @return A list of ZipFileIndex entries, or an empty list - */ - public synchronized List getZipFileIndexes(boolean openedOnly) { - List zipFileIndexes = new ArrayList<>(); - - zipFileIndexes.addAll(map.values()); - - if (openedOnly) { - for(ZipFileIndex elem : zipFileIndexes) { - if (!elem.isOpen()) { - zipFileIndexes.remove(elem); - } - } - } - - return zipFileIndexes; - } - - public synchronized ZipFileIndex getZipFileIndex(Path zipFile, - RelativeDirectory symbolFilePrefix, - boolean useCache, String cacheLocation, - boolean writeIndex) throws IOException { - ZipFileIndex zi = getExistingZipIndex(zipFile); - - if (zi == null || (zi != null && Files.getLastModifiedTime(zipFile).toMillis() != zi.zipFileLastModified)) { - zi = new ZipFileIndex(zipFile, symbolFilePrefix, writeIndex, - useCache, cacheLocation); - map.put(zipFile, zi); - } - return zi; - } - - public synchronized ZipFileIndex getExistingZipIndex(Path zipFile) { - return map.get(zipFile); - } - - public synchronized void clearCache() { - map.clear(); - } - - public synchronized void clearCache(long timeNotUsed) { - for (Path cachedFile : map.keySet()) { - ZipFileIndex cachedZipIndex = map.get(cachedFile); - if (cachedZipIndex != null) { - long timeToTest = cachedZipIndex.lastReferenceTimeStamp + timeNotUsed; - if (timeToTest < cachedZipIndex.lastReferenceTimeStamp || // Overflow... - System.currentTimeMillis() > timeToTest) { - map.remove(cachedFile); - } - } - } - } - - public synchronized void removeFromCache(Path file) { - map.remove(file); - } - - /** Sets already opened list of ZipFileIndexes from an outside client - * of the compiler. This functionality should be used in a non-batch clients of the compiler. - */ - public synchronized void setOpenedIndexes(Listindexes) throws IllegalStateException { - if (map.isEmpty()) { - String msg = - "Setting opened indexes should be called only when the ZipFileCache is empty. " - + "Call JavacFileManager.flush() before calling this method."; - throw new IllegalStateException(msg); - } - - for (ZipFileIndex zfi : indexes) { - map.put(zfi.zipFile, zfi); - } - } -} diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java index acfa02dd8bc..d0d1d899d39 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java @@ -29,15 +29,18 @@ import java.io.*; import java.net.URI; import java.net.URISyntaxException; import java.nio.CharBuffer; -import java.nio.file.Path; import java.util.Arrays; import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; + +import javax.lang.model.element.Modifier; +import javax.lang.model.element.NestingKind; import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; + import com.sun.tools.javac.comp.Annotate; import com.sun.tools.javac.comp.Annotate.AnnotationTypeCompleter; import com.sun.tools.javac.code.*; @@ -47,7 +50,8 @@ import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Symtab; import com.sun.tools.javac.code.Type.*; import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata; -import com.sun.tools.javac.file.BaseFileObject; +import com.sun.tools.javac.file.BaseFileManager; +import com.sun.tools.javac.file.PathFileObject; import com.sun.tools.javac.jvm.ClassFile.NameAndType; import com.sun.tools.javac.jvm.ClassFile.Version; import com.sun.tools.javac.util.*; @@ -2465,15 +2469,14 @@ public class ClassReader { * to be valid as is, so operations other than those to access the name throw * UnsupportedOperationException */ - private static class SourceFileObject extends BaseFileObject { + private static class SourceFileObject implements JavaFileObject { /** The file's name. */ - private Name name; - private Name flatname; + private final Name name; + private final Name flatname; public SourceFileObject(Name name, Name flatname) { - super(null); // no file manager; never referenced for this file object this.name = name; this.flatname = flatname; } @@ -2483,7 +2486,7 @@ public class ClassReader { try { return new URI(null, name.toString(), null); } catch (URISyntaxException e) { - throw new CannotCreateUriError(name.toString(), e); + throw new PathFileObject.CannotCreateUriError(name.toString(), e); } } @@ -2492,14 +2495,9 @@ public class ClassReader { return name.toString(); } - @Override - public String getShortName() { - return getName(); - } - @Override @DefinedBy(Api.COMPILER) public JavaFileObject.Kind getKind() { - return getKind(getName()); + return BaseFileManager.getKind(getName()); } @Override @DefinedBy(Api.COMPILER) @@ -2537,16 +2535,21 @@ public class ClassReader { throw new UnsupportedOperationException(); } - @Override - protected String inferBinaryName(Iterable path) { - return flatname.toString(); - } - @Override @DefinedBy(Api.COMPILER) public boolean isNameCompatible(String simpleName, JavaFileObject.Kind kind) { return true; // fail-safe mode } + @Override @DefinedBy(Api.COMPILER) + public NestingKind getNestingKind() { + return null; + } + + @Override @DefinedBy(Api.COMPILER) + public Modifier getAccessLevel() { + return null; + } + /** * Check if two file objects are equal. * SourceFileObjects are just placeholder objects for the value of a diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java index 81dd6225b07..1b1f8a15457 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java @@ -40,7 +40,7 @@ import com.sun.tools.javac.code.Attribute.RetentionPolicy; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Type.*; import com.sun.tools.javac.code.Types.UniqueType; -import com.sun.tools.javac.file.BaseFileObject; +import com.sun.tools.javac.file.PathFileObject; import com.sun.tools.javac.jvm.Pool.DynamicMethod; import com.sun.tools.javac.jvm.Pool.Method; import com.sun.tools.javac.jvm.Pool.MethodHandle; @@ -52,6 +52,7 @@ import static com.sun.tools.javac.code.Kinds.Kind.*; import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE; import static com.sun.tools.javac.code.TypeTag.*; import static com.sun.tools.javac.main.Option.*; + import static javax.tools.StandardLocation.CLASS_OUTPUT; /** This class provides operations to map an internal symbol table graph @@ -1699,7 +1700,7 @@ public class ClassWriter extends ClassFile { // the last possible moment because the sourcefile may be used // elsewhere in error diagnostics. Fixes 4241573. //databuf.appendChar(c.pool.put(c.sourcefile)); - String simpleName = BaseFileObject.getSimpleName(c.sourcefile); + String simpleName = PathFileObject.getSimpleName(c.sourcefile); databuf.appendChar(c.pool.put(names.fromString(simpleName))); endAttr(alenIdx); acount++; diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Main.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Main.java index 718bbe71736..4d42113eb29 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Main.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Main.java @@ -141,8 +141,11 @@ public class Main { JavacFileManager.preRegister(context); // can't create it until Log has been set up Result result = compile(args, context); if (fileManager instanceof JavacFileManager) { - // A fresh context was created above, so jfm must be a JavacFileManager - ((JavacFileManager)fileManager).close(); + try { + // A fresh context was created above, so jfm must be a JavacFileManager + ((JavacFileManager)fileManager).close(); + } catch (IOException ignore) { + } } return result; } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/DocCommentParser.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/DocCommentParser.java index af1e623528c..0a9794219ff 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/DocCommentParser.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/DocCommentParser.java @@ -577,13 +577,50 @@ public class DocCommentParser { return null; } + /** + * Read a term ie. one word. + * It is an error if the beginning of the next tag is detected. + */ + @SuppressWarnings("fallthrough") + protected DCText inlineWord() { + int pos = bp; + int depth = 0; + loop: + while (bp < buflen) { + switch (ch) { + case '\n': + newline = true; + // fallthrough + + case '\r': case '\f': case ' ': case '\t': + return m.at(pos).Text(newString(pos, bp)); + + case '@': + if (newline) + break loop; + + case '{': + depth++; + break; + + case '}': + if (depth == 0 || --depth == 0) + return m.at(pos).Text(newString(pos, bp)); + break; + } + newline = false; + nextChar(); + } + return null; + } + /** * Read general text content of an inline tag, including HTML entities and elements. * Matching pairs of { } are skipped; the text is terminated by the first * unmatched }. It is an error if the beginning of the next tag is detected. */ @SuppressWarnings("fallthrough") - protected List inlineContent() { + private List inlineContent() { ListBuffer trees = new ListBuffer<>(); skipWhitespace(); @@ -614,6 +651,8 @@ public class DocCommentParser { break; case '{': + if (textStart == -1) + textStart = bp; newline = false; depth++; nextChar(); @@ -1022,6 +1061,28 @@ public class DocCommentParser { } }, + // @index search-term options-description + new TagParser(Kind.INLINE, DCTree.Kind.INDEX) { + public DCTree parse(int pos) throws ParseException { + skipWhitespace(); + if (ch == '}') { + throw new ParseException("dc.no.content"); + } + DCTree term = ch == '"' ? quotedString() : inlineWord(); + if (term == null) { + throw new ParseException("dc.no.content"); + } + skipWhitespace(); + List description = List.nil(); + if (ch != '}') { + description = inlineContent(); + } else { + nextChar(); + } + return m.at(pos).Index(term, description); + } + }, + // {@inheritDoc} new TagParser(Kind.INLINE, DCTree.Kind.INHERIT_DOC) { public DCTree parse(int pos) throws ParseException { diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/ct.properties b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/ct.properties index e177ba1da1f..135646a3fdb 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/ct.properties +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/ct.properties @@ -1,4 +1,3 @@ -apple.applescript.*: hidden apple.laf.*: hidden apple.security.*: hidden com.apple.concurrent.*: hidden diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DCTree.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DCTree.java index 3a820c6d934..691d4429c08 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DCTree.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DCTree.java @@ -408,6 +408,36 @@ public abstract class DCTree implements DocTree { } } + public static class DCIndex extends DCInlineTag implements IndexTree { + public final DCTree term; + public final List description; + + DCIndex(DCTree term, List description) { + this.term = term; + this.description = description; + } + + @Override @DefinedBy(Api.COMPILER_TREE) + public Kind getKind() { + return Kind.INDEX; + } + + @Override @DefinedBy(Api.COMPILER_TREE) + public R accept(DocTreeVisitor v, D d) { + return v.visitIndex(this, d); + } + + @Override @DefinedBy(Api.COMPILER_TREE) + public DocTree getSearchTerm() { + return term; + } + + @Override @DefinedBy(Api.COMPILER_TREE) + public java.util.List getDescription() { + return description; + } + } + public static class DCInheritDoc extends DCInlineTag implements InheritDocTree { @Override @DefinedBy(Api.COMPILER_TREE) public Kind getKind() { diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocPretty.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocPretty.java index 4af8a81e1f5..21018d821ed 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocPretty.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocPretty.java @@ -269,6 +269,24 @@ public class DocPretty implements DocTreeVisitor { return null; } + @DefinedBy(Api.COMPILER_TREE) + public Void visitIndex(IndexTree node, Void p) { + try { + print("{"); + printTagName(node); + print(" "); + print(node.getSearchTerm()); + if (!node.getDescription().isEmpty()) { + print(" "); + print(node.getDescription()); + } + print("}"); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + return null; + } + @DefinedBy(Api.COMPILER_TREE) public Void visitInheritDoc(InheritDocTree node, Void p) { try { diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocTreeMaker.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocTreeMaker.java index 6f5478dc3a0..4cd121ca0f8 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocTreeMaker.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocTreeMaker.java @@ -50,6 +50,7 @@ import com.sun.tools.javac.tree.DCTree.DCEndElement; import com.sun.tools.javac.tree.DCTree.DCEntity; import com.sun.tools.javac.tree.DCTree.DCErroneous; import com.sun.tools.javac.tree.DCTree.DCIdentifier; +import com.sun.tools.javac.tree.DCTree.DCIndex; import com.sun.tools.javac.tree.DCTree.DCInheritDoc; import com.sun.tools.javac.tree.DCTree.DCLink; import com.sun.tools.javac.tree.DCTree.DCLiteral; @@ -224,6 +225,12 @@ public class DocTreeMaker { return tree; } + public DCIndex Index(DCTree term, List description) { + DCIndex tree = new DCIndex(term, description); + tree.pos = pos; + return tree; + } + public DCInheritDoc InheritDoc() { DCInheritDoc tree = new DCInheritDoc(); tree.pos = pos; diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java index a2d4a66ff41..2204c10b09b 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -45,7 +45,7 @@ import com.sun.tools.javac.code.Printer; import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Type; import com.sun.tools.javac.code.Type.CapturedType; -import com.sun.tools.javac.file.BaseFileObject; +import com.sun.tools.javac.file.PathFileObject; import com.sun.tools.javac.jvm.Profile; import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.javac.tree.Pretty; @@ -144,10 +144,10 @@ public abstract class AbstractDiagnosticFormatter implements DiagnosticFormatter throw new IllegalArgumentException(); // d should have source set if (fullname) return fo.getName(); - else if (fo instanceof BaseFileObject) - return ((BaseFileObject) fo).getShortName(); + else if (fo instanceof PathFileObject) + return ((PathFileObject) fo).getShortName(); else - return BaseFileObject.getSimpleName(fo); + return PathFileObject.getSimpleName(fo); } /** diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/RawDiagnosticFormatter.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/RawDiagnosticFormatter.java index 00e0b1f4210..13c0a6339c1 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/RawDiagnosticFormatter.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/RawDiagnosticFormatter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ import javax.tools.JavaFileObject; import com.sun.tools.javac.api.DiagnosticFormatter.Configuration.*; import com.sun.tools.javac.api.Formattable; -import com.sun.tools.javac.file.BaseFileObject; +import com.sun.tools.javac.file.PathFileObject; import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.javac.util.AbstractDiagnosticFormatter.SimpleConfiguration; @@ -123,8 +123,8 @@ public final class RawDiagnosticFormatter extends AbstractDiagnosticFormatter { } else if (arg instanceof JCExpression) { JCExpression tree = (JCExpression)arg; s = "@" + tree.getStartPosition(); - } else if (arg instanceof BaseFileObject) { - s = ((BaseFileObject) arg).getShortName(); + } else if (arg instanceof PathFileObject) { + s = ((PathFileObject) arg).getShortName(); } else { s = super.formatArgument(diag, arg, null); } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java index 79a7ae143af..246bcde264f 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java @@ -115,7 +115,11 @@ public class SjavacImpl implements Sjavac { // Clean up JavaFileManager fileManager = context.get(JavaFileManager.class); if (fileManager instanceof JavacFileManager) { - ((JavacFileManager) fileManager).close(); + try { + ((JavacFileManager) fileManager).close(); + } catch (IOException e) { + return RC_FATAL; + } } return result.exitCode; diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/SourcePositionImpl.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/SourcePositionImpl.java index 89106de0163..b508b615ea6 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/SourcePositionImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/SourcePositionImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -103,10 +103,14 @@ public class SourcePositionImpl implements SourcePosition { String fn = filename.getName(); if (fn.endsWith(")")) { int paren = fn.lastIndexOf("("); - if (paren != -1) + if (paren != -1) { + int i = paren+1; + if (fn.charAt(i) == '/') + i++; fn = fn.substring(0, paren) + File.separatorChar - + fn.substring(paren + 1, fn.length() - 1); + + fn.substring(i, fn.length() - 1); + } } if (position == Position.NOPOS) diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java index 698dbb17214..a66d9cbc1aa 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java @@ -86,10 +86,11 @@ import jdk.jshell.JShell.Subscription; import static java.nio.file.StandardOpenOption.CREATE; import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING; import static java.nio.file.StandardOpenOption.WRITE; -import java.util.Locale; import java.util.MissingResourceException; import java.util.Optional; import java.util.ResourceBundle; +import java.util.Spliterators; +import java.util.function.Supplier; import static java.util.stream.Collectors.toList; /** @@ -600,6 +601,7 @@ public class JShellTool { } private static final CompletionProvider EMPTY_COMPLETION_PROVIDER = new FixedCompletionProvider(); + private static final CompletionProvider KEYWORD_COMPLETION_PROVIDER = new FixedCompletionProvider("all ", "start ", "history "); private static final CompletionProvider FILE_COMPLETION_PROVIDER = fileCompletions(p -> true); private final Map commands = new LinkedHashMap<>(); private void registerCommand(Command cmd) { @@ -650,13 +652,21 @@ public class JShellTool { }; } + private CompletionProvider editKeywordCompletion() { + return (code, cursor, anchor) -> { + List result = new ArrayList<>(); + result.addAll(KEYWORD_COMPLETION_PROVIDER.completionSuggestions(code, cursor, anchor)); + result.addAll(editCompletion().completionSuggestions(code, cursor, anchor)); + return result; + }; + } + private static CompletionProvider saveCompletion() { - CompletionProvider keyCompletion = new FixedCompletionProvider("all ", "history ", "start "); return (code, cursor, anchor) -> { List result = new ArrayList<>(); int space = code.indexOf(' '); if (space == (-1)) { - result.addAll(keyCompletion.completionSuggestions(code, cursor, anchor)); + result.addAll(KEYWORD_COMPLETION_PROVIDER.completionSuggestions(code, cursor, anchor)); } result.addAll(FILE_COMPLETION_PROVIDER.completionSuggestions(code.substring(space + 1), cursor - space - 1, anchor)); anchor[0] += space + 1; @@ -667,9 +677,9 @@ public class JShellTool { // Table of commands -- with command forms, argument kinds, help message, implementation, ... { - registerCommand(new Command("/list", "[all]", "list the source you have typed", + registerCommand(new Command("/list", "[all|start|history|]", "list the source you have typed", arg -> cmdList(arg), - new FixedCompletionProvider("all"))); + editKeywordCompletion())); registerCommand(new Command("/seteditor", "", "set the external editor command to use", arg -> cmdSetEditor(arg), EMPTY_COMPLETION_PROVIDER)); @@ -937,49 +947,67 @@ public class JShellTool { } /** - * Convert a user argument to a list of snippets referenced by that - * argument (or lack of argument). - * @param arg The user's argument to the command - * @return a list of referenced snippets + * Avoid parameterized varargs possible heap pollution warning. */ - private List argToSnippets(String arg) { - List snippets = new ArrayList<>(); - if (arg.isEmpty()) { - // Default is all user snippets - for (Snippet sn : state.snippets()) { - if (notInStartUp(sn)) { - snippets.add(sn); - } - } - } else { - // Look for all declarations with matching names - for (Snippet key : state.snippets()) { - switch (key.kind()) { - case METHOD: - case VAR: - case TYPE_DECL: - if (((DeclarationSnippet) key).name().equals(arg)) { - snippets.add(key); - } - break; - } - } - // If no declarations found, look for an id of this name - if (snippets.isEmpty()) { - for (Snippet sn : state.snippets()) { - if (sn.id().equals(arg)) { - snippets.add(sn); - break; - } - } - } - // If still no matches found, give an error - if (snippets.isEmpty()) { - hard("No definition or id named %s found. See /classes /methods /vars or /list", arg); - return null; + private interface SnippetPredicate extends Predicate { } + + /** + * Apply filters to a stream until one that is non-empty is found. + * Adapted from Stuart Marks + * + * @param supplier Supply the Snippet stream to filter + * @param filters Filters to attempt + * @return The non-empty filtered Stream, or null + */ + private static Stream nonEmptyStream(Supplier> supplier, + SnippetPredicate... filters) { + for (SnippetPredicate filt : filters) { + Iterator iterator = supplier.get().filter(filt).iterator(); + if (iterator.hasNext()) { + return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false); } } - return snippets; + return null; + } + + private boolean mainActive(Snippet sn) { + return notInStartUp(sn) && state.status(sn).isActive; + } + + private boolean matchingDeclaration(Snippet sn, String name) { + return sn instanceof DeclarationSnippet + && ((DeclarationSnippet) sn).name().equals(name); + } + + /** + * Convert a user argument to a Stream of snippets referenced by that argument + * (or lack of argument). + * + * @param arg The user's argument to the command, maybe be the empty string + * @return a Stream of referenced snippets or null if no matches to specific arg + */ + private Stream argToSnippets(String arg, boolean allowAll) { + List snippets = state.snippets(); + if (allowAll && arg.equals("all")) { + // all snippets including start-up, failed, and overwritten + return snippets.stream(); + } else if (arg.isEmpty()) { + // Default is all active user snippets + return snippets.stream() + .filter(this::mainActive); + } else { + Stream result = + nonEmptyStream( + () -> snippets.stream(), + // look for active user declarations matching the name + sn -> mainActive(sn) && matchingDeclaration(sn, arg), + // else, look for any declarations matching the name + sn -> matchingDeclaration(sn, arg), + // else, look for an id of this name + sn -> sn.id().equals(arg) + ); + return result; + } } private void cmdDrop(String arg) { @@ -988,39 +1016,40 @@ public class JShellTool { hard("Specify by id or name. Use /list to see ids. Use /reset to reset all state."); return; } - List snippetSet = argToSnippets(arg); - if (snippetSet == null) { + Stream stream = argToSnippets(arg, false); + if (stream == null) { + hard("No definition or id named %s found. See /classes, /methods, /vars, or /list", arg); return; } - snippetSet = snippetSet.stream() - .filter(sn -> state.status(sn).isActive) + List snippets = stream + .filter(sn -> state.status(sn).isActive && sn instanceof PersistentSnippet) .collect(toList()); - snippetSet.removeIf(sn -> !(sn instanceof PersistentSnippet)); - if (snippetSet.isEmpty()) { - hard("The argument did not specify an import, variable, method, or class to drop."); + if (snippets.isEmpty()) { + hard("The argument did not specify an active import, variable, method, or class to drop."); return; } - if (snippetSet.size() > 1) { + if (snippets.size() > 1) { hard("The argument references more than one import, variable, method, or class."); hard("Try again with one of the ids below:"); - for (Snippet sn : snippetSet) { + for (Snippet sn : snippets) { cmdout.printf("%4s : %s\n", sn.id(), sn.source().replace("\n", "\n ")); } return; } - PersistentSnippet psn = (PersistentSnippet) snippetSet.iterator().next(); + PersistentSnippet psn = (PersistentSnippet) snippets.get(0); state.drop(psn).forEach(this::handleEvent); } private void cmdEdit(String arg) { - List snippetSet = argToSnippets(arg); - if (snippetSet == null) { + Stream stream = argToSnippets(arg, true); + if (stream == null) { + hard("No definition or id named %s found. See /classes, /methods, /vars, or /list", arg); return; } Set srcSet = new LinkedHashSet<>(); - for (Snippet key : snippetSet) { - String src = key.source(); - switch (key.subKind()) { + stream.forEachOrdered(sn -> { + String src = sn.source(); + switch (sn.subKind()) { case VAR_VALUE_SUBKIND: break; case ASSIGNMENT_SUBKIND: @@ -1035,7 +1064,7 @@ public class JShellTool { srcSet.add(src); break; } - } + }); StringBuilder sb = new StringBuilder(); for (String s : srcSet) { sb.append(s); @@ -1107,31 +1136,30 @@ public class JShellTool { } private void cmdList(String arg) { - boolean all = false; - switch (arg) { - case "all": - all = true; - break; - case "history": - cmdHistory(); - return; - case "": - break; - default: - hard("Invalid /list argument: %s", arg); - return; + if (arg.equals("history")) { + cmdHistory(); + return; } - boolean hasOutput = false; - for (Snippet sn : state.snippets()) { - if (all || (notInStartUp(sn) && state.status(sn).isActive)) { - if (!hasOutput) { - cmdout.println(); - hasOutput = true; - } - cmdout.printf("%4s : %s\n", sn.id(), sn.source().replace("\n", "\n ")); - + Stream stream = argToSnippets(arg, true); + if (stream == null) { + // Check if there are any definitions at all + if (argToSnippets("", false).iterator().hasNext()) { + hard("No definition or id named %s found. Try /list without arguments.", arg); + } else { + hard("No definition or id named %s found. There are no active definitions.", arg); } + return; } + + // prevent double newline on empty list + boolean[] hasOutput = new boolean[1]; + stream.forEachOrdered(sn -> { + if (!hasOutput[0]) { + cmdout.println(); + hasOutput[0] = true; + } + cmdout.printf("%4s : %s\n", sn.id(), sn.source().replace("\n", "\n ")); + }); } private void cmdOpen(String filename) { @@ -1166,12 +1194,12 @@ public class JShellTool { return; } boolean useHistory = false; - boolean saveAll = false; + String saveAll = ""; boolean saveStart = false; String cmd = mat.group("cmd"); if (cmd != null) switch (cmd) { case "all": - saveAll = true; + saveAll = "all"; break; case "history": useHistory = true; @@ -1196,8 +1224,9 @@ public class JShellTool { } else if (saveStart) { writer.append(DEFAULT_STARTUP); } else { - for (Snippet sn : state.snippets()) { - if (saveAll || notInStartUp(sn)) { + Stream stream = argToSnippets(saveAll, true); + if (stream != null) { + for (Snippet sn : stream.collect(toList())) { writer.write(sn.source()); writer.write("\n"); } diff --git a/langtools/test/com/sun/javadoc/testSearch/TestSearch.java b/langtools/test/com/sun/javadoc/testSearch/TestSearch.java index 197b5e3fa0f..b6ebc8ba744 100644 --- a/langtools/test/com/sun/javadoc/testSearch/TestSearch.java +++ b/langtools/test/com/sun/javadoc/testSearch/TestSearch.java @@ -71,7 +71,8 @@ public class TestSearch extends JavadocTester { @Test void test3() { - javadoc("-d", "out-3", "-noindex", "-sourcepath", testSrc, + javadoc("-d", "out-3", "-noindex", "-Xdoclint:none", + "-sourcepath", testSrc, "-use", "pkg", "pkg1", "pkg2", "pkg3"); checkExit(Exit.OK); checkSearchOutput(false); @@ -86,7 +87,8 @@ public class TestSearch extends JavadocTester { @Test void test4() { - javadoc("-d", "out-4", "-html5", "-sourcepath", testSrc, + javadoc("-d", "out-4", "-html5", "-Xdoclint:none", + "-sourcepath", testSrc, "-use", "pkg", "pkg1", "pkg2", "pkg3"); checkExit(Exit.OK); checkSearchOutput(true); @@ -101,7 +103,8 @@ public class TestSearch extends JavadocTester { @Test void test5() { - javadoc("-d", "out-5", "-noindex", "-html5", "-sourcepath", testSrc, + javadoc("-d", "out-5", "-noindex", "-html5", "-Xdoclint:none", + "-sourcepath", testSrc, "-use", "pkg", "pkg1", "pkg2", "pkg3"); checkExit(Exit.OK); checkSearchOutput(false); @@ -116,7 +119,8 @@ public class TestSearch extends JavadocTester { @Test void test6() { - javadoc("-d", "out-6", "-nocomment", "-sourcepath", testSrc, + javadoc("-d", "out-6", "-nocomment", "-Xdoclint:none", + "-sourcepath", testSrc, "-use", "pkg", "pkg1", "pkg2", "pkg3"); checkExit(Exit.OK); checkSearchOutput(true); @@ -131,7 +135,8 @@ public class TestSearch extends JavadocTester { @Test void test7() { - javadoc("-d", "out-7", "-nodeprecated", "-sourcepath", testSrc, + javadoc("-d", "out-7", "-nodeprecated", "-Xdoclint:none", + "-sourcepath", testSrc, "-use", "pkg", "pkg1", "pkg2", "pkg3"); checkExit(Exit.OK); checkSearchOutput(true); diff --git a/langtools/test/jdk/jshell/CommandCompletionTest.java b/langtools/test/jdk/jshell/CommandCompletionTest.java index 505799fea58..549f09fd532 100644 --- a/langtools/test/jdk/jshell/CommandCompletionTest.java +++ b/langtools/test/jdk/jshell/CommandCompletionTest.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8144095 * @summary Test Command Completion * @library /tools/lib * @build ReplToolTesting TestingInputStream Compiler ToolBox @@ -56,15 +57,20 @@ public class CommandCompletionTest extends ReplToolTesting { } public void testList() { - assertCompletion("/l|", false, "/list "); - assertCompletion("/list |", false, "all"); - assertCompletion("/list q|", false); + test(false, new String[] {"-nostartup"}, + a -> assertCompletion(a, "/l|", false, "/list "), + a -> assertCompletion(a, "/list |", false, "all ", "history ", "start "), + a -> assertCompletion(a, "/list h|", false, "history "), + a -> assertCompletion(a, "/list q|", false), + a -> assertVariable(a, "int", "xray"), + a -> assertCompletion(a, "/list |", false, "1", "all ", "history ", "start ", "xray"), + a -> assertCompletion(a, "/list x|", false, "xray") + ); } public void testDrop() { - assertCompletion("/d|", false, "/drop "); - test(false, new String[] {"-nostartup"}, + a -> assertCompletion(a, "/d|", false, "/drop "), a -> assertClass(a, "class cTest {}", "class", "cTest"), a -> assertMethod(a, "int mTest() { return 0; }", "()I", "mTest"), a -> assertVariable(a, "int", "fTest"), @@ -74,10 +80,9 @@ public class CommandCompletionTest extends ReplToolTesting { } public void testEdit() { - assertCompletion("/e|", false, "/edit ", "/exit "); - assertCompletion("/ed|", false, "/edit "); - test(false, new String[]{"-nostartup"}, + a -> assertCompletion(a, "/e|", false, "/edit ", "/exit "), + a -> assertCompletion(a, "/ed|", false, "/edit "), a -> assertClass(a, "class cTest {}", "class", "cTest"), a -> assertMethod(a, "int mTest() { return 0; }", "()I", "mTest"), a -> assertVariable(a, "int", "fTest"), diff --git a/langtools/test/jdk/jshell/EditorTestBase.java b/langtools/test/jdk/jshell/EditorTestBase.java index 182d2655a85..f6f7bef8a8e 100644 --- a/langtools/test/jdk/jshell/EditorTestBase.java +++ b/langtools/test/jdk/jshell/EditorTestBase.java @@ -73,11 +73,11 @@ public abstract class EditorTestBase extends ReplToolTesting { for (String edit : new String[] {"/e", "/edit"}) { test(new String[]{"-nostartup"}, a -> assertCommand(a, edit + " 1", - "| No definition or id named 1 found. See /classes /methods /vars or /list\n"), + "| No definition or id named 1 found. See /classes, /methods, /vars, or /list\n"), a -> assertCommand(a, edit + " -1", - "| No definition or id named -1 found. See /classes /methods /vars or /list\n"), + "| No definition or id named -1 found. See /classes, /methods, /vars, or /list\n"), a -> assertCommand(a, edit + " unknown", - "| No definition or id named unknown found. See /classes /methods /vars or /list\n") + "| No definition or id named unknown found. See /classes, /methods, /vars, or /list\n") ); } } diff --git a/langtools/test/jdk/jshell/ReplToolTesting.java b/langtools/test/jdk/jshell/ReplToolTesting.java index 88bac9102d9..a4d1fab3f21 100644 --- a/langtools/test/jdk/jshell/ReplToolTesting.java +++ b/langtools/test/jdk/jshell/ReplToolTesting.java @@ -26,6 +26,7 @@ import java.io.OutputStream; import java.io.PrintStream; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -40,6 +41,7 @@ import java.util.stream.Stream; import jdk.internal.jshell.tool.JShellTool; import jdk.jshell.SourceCodeAnalysis.Suggestion; +import static java.util.stream.Collectors.toList; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; @@ -48,6 +50,24 @@ import static org.testng.Assert.fail; public class ReplToolTesting { private final static String DEFAULT_STARTUP_MESSAGE = "| Welcome to"; + final static List START_UP_IMPORTS = Stream.of( + "java.util.*", + "java.io.*", + "java.math.*", + "java.net.*", + "java.util.concurrent.*", + "java.util.prefs.*", + "java.util.regex.*") + .map(s -> new ImportInfo("import " + s + ";", "", s)) + .collect(toList()); + final static List START_UP_METHODS = Stream.of( + new MethodInfo("void printf(String format, Object... args) { System.out.printf(format, args); }", + "(String,Object...)void", "printf")) + .collect(toList()); + final static List START_UP = Collections.unmodifiableList( + Stream.concat(START_UP_IMPORTS.stream(), START_UP_METHODS.stream()) + .map(s -> s.getSource()) + .collect(toList())); private WaitingTestingInputStream cmdin = null; private ByteArrayOutputStream cmdout = null; @@ -190,18 +210,11 @@ public class ReplToolTesting { classes = new HashMap<>(); imports = new HashMap<>(); if (isDefaultStartUp) { - methods.put("printf (String,Object...)void", - new MethodInfo("", "(String,Object...)void", "printf")); + methods.putAll( + START_UP_METHODS.stream() + .collect(Collectors.toMap(Object::toString, Function.identity()))); imports.putAll( - Stream.of( - "java.util.*", - "java.io.*", - "java.math.*", - "java.net.*", - "java.util.concurrent.*", - "java.util.prefs.*", - "java.util.regex.*") - .map(s -> new ImportInfo("", "", s)) + START_UP_IMPORTS.stream() .collect(Collectors.toMap(Object::toString, Function.identity()))); } } diff --git a/langtools/test/jdk/jshell/ToolBasicTest.java b/langtools/test/jdk/jshell/ToolBasicTest.java index b16eef0e6b5..03c0e29d9af 100644 --- a/langtools/test/jdk/jshell/ToolBasicTest.java +++ b/langtools/test/jdk/jshell/ToolBasicTest.java @@ -23,10 +23,10 @@ /* * @test - * @bug 8143037 8142447 + * @bug 8143037 8142447 8144095 8140265 * @summary Tests for Basic tests for REPL tool - * @ignore 8139873 * @library /tools/lib + * @ignore 8139873 * @build KullaTesting TestingInputStream ToolBox Compiler * @run testng ToolBasicTest */ @@ -529,6 +529,7 @@ public class ToolBasicTest extends ReplToolTesting { ); test( (a) -> assertVariable(a, "int", "a"), + (a) -> assertCommand(a, "()", null, null, null, "", ""), (a) -> assertClass(a, "class A { public String toString() { return \"A\"; } }", "class", "A"), (a) -> assertCommand(a, "/save " + path.toString(), "") ); @@ -537,6 +538,7 @@ public class ToolBasicTest extends ReplToolTesting { List output = new ArrayList<>(); test( (a) -> assertCommand(a, "int a;", null), + (a) -> assertCommand(a, "()", null, null, null, "", ""), (a) -> assertClass(a, "class A { public String toString() { return \"A\"; } }", "class", "A"), (a) -> assertCommandCheckOutput(a, "/list all", (out) -> output.addAll(Stream.of(out.split("\n")) @@ -551,6 +553,7 @@ public class ToolBasicTest extends ReplToolTesting { List output = new ArrayList<>(); test( (a) -> assertVariable(a, "int", "a"), + (a) -> assertCommand(a, "()", null, null, null, "", ""), (a) -> assertClass(a, "class A { public String toString() { return \"A\"; } }", "class", "A"), (a) -> assertCommandCheckOutput(a, "/history", (out) -> output.addAll(Stream.of(out.split("\n")) @@ -632,15 +635,7 @@ public class ToolBasicTest extends ReplToolTesting { List lines = Files.lines(startSave) .filter(s -> !s.isEmpty()) .collect(Collectors.toList()); - assertEquals(lines, Arrays.asList( - "import java.util.*;", - "import java.io.*;", - "import java.math.*;", - "import java.net.*;", - "import java.util.concurrent.*;", - "import java.util.prefs.*;", - "import java.util.regex.*;", - "void printf(String format, Object... args) { System.out.printf(format, args); }")); + assertEquals(lines, START_UP); } public void testConstrainedUpdates() { @@ -665,15 +660,35 @@ public class ToolBasicTest extends ReplToolTesting { ); } + // Check that each line of output contains the corresponding string from the list + private void checkLineToList(String in, List match) { + String[] res = in.trim().split("\n"); + assertEquals(res.length, match.size(), "Got: " + Arrays.asList(res)); + for (int i = 0; i < match.size(); ++i) { + assertTrue(res[i].contains(match.get(i))); + } + } + public void testListArgs() { - Consumer assertList = s -> assertTrue(s.split("\n").length >= 4, s); String arg = "qqqq"; - Consumer assertError = s -> assertEquals(s, "| Invalid /list argument: " + arg + "\n"); + List startVarList = new ArrayList<>(START_UP); + startVarList.add("int aardvark"); test( - a -> assertCommandCheckOutput(a, "/list all", assertList), - a -> assertCommandCheckOutput(a, "/list " + arg, assertError), - a -> assertVariable(a, "int", "a"), - a -> assertCommandCheckOutput(a, "/list history", assertList) + a -> assertCommandCheckOutput(a, "/list all", + s -> checkLineToList(s, START_UP)), + a -> assertCommandCheckOutput(a, "/list " + arg, + s -> assertEquals(s, "| No definition or id named " + arg + + " found. There are no active definitions.\n")), + a -> assertVariable(a, "int", "aardvark"), + a -> assertCommandCheckOutput(a, "/list aardvark", + s -> assertTrue(s.contains("aardvark"))), + a -> assertCommandCheckOutput(a, "/list all", + s -> checkLineToList(s, startVarList)), + a -> assertCommandCheckOutput(a, "/list history", + s -> assertTrue(s.split("\n").length >= 4, s)), + a -> assertCommandCheckOutput(a, "/list " + arg, + s -> assertEquals(s, "| No definition or id named " + arg + + " found. Try /list without arguments.\n")) ); } @@ -806,13 +821,13 @@ public class ToolBasicTest extends ReplToolTesting { public void testDropNegative() { test(false, new String[]{"-nostartup"}, - a -> assertCommand(a, "/drop 0", "| No definition or id named 0 found. See /classes /methods /vars or /list\n"), - a -> assertCommand(a, "/drop a", "| No definition or id named a found. See /classes /methods /vars or /list\n"), + a -> assertCommand(a, "/drop 0", "| No definition or id named 0 found. See /classes, /methods, /vars, or /list\n"), + a -> assertCommand(a, "/drop a", "| No definition or id named a found. See /classes, /methods, /vars, or /list\n"), a -> assertCommandCheckOutput(a, "/drop", assertStartsWith("| In the /drop argument, please specify an import, variable, method, or class to drop.")), a -> assertVariable(a, "int", "a"), a -> assertCommand(a, "a", "| Variable a of type int has value 0\n"), - a -> assertCommand(a, "/drop 2", "| The argument did not specify an import, variable, method, or class to drop.\n") + a -> assertCommand(a, "/drop 2", "| The argument did not specify an active import, variable, method, or class to drop.\n") ); } diff --git a/langtools/test/tools/javac/6508981/TestInferBinaryName.java b/langtools/test/tools/javac/6508981/TestInferBinaryName.java index e04bf6b56bf..a573cf1d639 100644 --- a/langtools/test/tools/javac/6508981/TestInferBinaryName.java +++ b/langtools/test/tools/javac/6508981/TestInferBinaryName.java @@ -53,9 +53,6 @@ import static javax.tools.StandardLocation.*; * the impl of inferBinaryName for that file object. */ public class TestInferBinaryName { - static final boolean DONT_USE_ZIP_FILE_INDEX = false; - static final boolean USE_ZIP_FILE_INDEX = true; - public static void main(String... args) throws Exception { new TestInferBinaryName().run(); } @@ -64,10 +61,7 @@ public class TestInferBinaryName { testDirectory(); File testJar = createJar(); - testZipArchive(testJar); - testZipFileIndexArchive(testJar); - testZipFileIndexArchive2(testJar); if (errors > 0) throw new Exception(errors + " error found"); @@ -87,40 +81,18 @@ public class TestInferBinaryName { void testDirectory() throws IOException { String testClassName = "p.A"; List testClasses = Arrays.asList(new File(System.getProperty("test.classes"))); - try (JavaFileManager fm = - getFileManager(testClasses, USE_ZIP_FILE_INDEX)) { + try (JavaFileManager fm = getFileManager(testClasses)) { test("testDirectory", - fm, testClassName, "com.sun.tools.javac.file.RegularFileObject"); + fm, testClassName, "SimpleFileObject"); } } void testZipArchive(File testJar) throws IOException { String testClassName = "java.lang.String"; List path = Arrays.asList(testJar); - try (JavaFileManager fm = - getFileManager(path, DONT_USE_ZIP_FILE_INDEX)) { + try (JavaFileManager fm = getFileManager(path)) { test("testZipArchive", - fm, testClassName, "com.sun.tools.javac.file.ZipArchive$ZipFileObject"); - } - } - - void testZipFileIndexArchive(File testJar) throws IOException { - String testClassName = "java.lang.String"; - List path = Arrays.asList(testJar); - try (JavaFileManager fm = - getFileManager(path, USE_ZIP_FILE_INDEX)) { - test("testZipFileIndexArchive", - fm, testClassName, "com.sun.tools.javac.file.ZipFileIndexArchive$ZipFileIndexFileObject"); - } - } - - void testZipFileIndexArchive2(File testJar) throws IOException { - String testClassName = "java.lang.String"; - List path = Arrays.asList(testJar); - try (JavaFileManager fm = - getFileManager(path, USE_ZIP_FILE_INDEX)) { - test("testZipFileIndexArchive2", - fm, testClassName, "com.sun.tools.javac.file.ZipFileIndexArchive$ZipFileIndexFileObject"); + fm, testClassName, "JarFileObject"); } } @@ -141,21 +113,17 @@ public class TestInferBinaryName { return; } - String cn = fo.getClass().getName(); + String cn = fo.getClass().getSimpleName(); String bn = fm.inferBinaryName(CLASS_PATH, fo); System.err.println(testName + " " + cn + " " + bn); - check(cn, implClassName); - check(bn, testClassName); + checkEqual(cn, implClassName); + checkEqual(bn, testClassName); System.err.println("OK"); } - JavaFileManager getFileManager(List path, - boolean zipFileIndexKind) + JavaFileManager getFileManager(List path) throws IOException { Context ctx = new Context(); - Options options = Options.instance(ctx); - options.put("useOptimizedZip", - Boolean.toString(zipFileIndexKind == USE_ZIP_FILE_INDEX)); JavacFileManager fm = new JavacFileManager(ctx, false, null); fm.setLocation(CLASS_PATH, path); @@ -163,7 +131,7 @@ public class TestInferBinaryName { } List getPath(String s) { - List path = new ArrayList(); + List path = new ArrayList<>(); for (String f: s.split(File.pathSeparator)) { if (f.length() > 0) path.add(new File(f)); @@ -172,7 +140,7 @@ public class TestInferBinaryName { return path; } - void check(String found, String expect) { + void checkEqual(String found, String expect) { if (!found.equals(expect)) { System.err.println("Expected: " + expect); System.err.println(" Found: " + found); diff --git a/langtools/test/tools/javac/T6358024.java b/langtools/test/tools/javac/T6358024.java index fd27069ffd9..51ffef94a6b 100644 --- a/langtools/test/tools/javac/T6358024.java +++ b/langtools/test/tools/javac/T6358024.java @@ -53,7 +53,7 @@ public class T6358024 extends AbstractProcessor { String testSrc = System.getProperty("test.src"); fm = new JavacFileManager(new Context(), false, null); - JavaFileObject f = fm.getFileForInput(testSrc + File.separatorChar + self + ".java"); + JavaFileObject f = fm.getJavaFileObject(testSrc + File.separatorChar + self + ".java"); test(fm, f, new Option[] { new Option("-d", ".")}, diff --git a/langtools/test/tools/javac/T6358166.java b/langtools/test/tools/javac/T6358166.java index 3bacd7bfa6e..e6a73d63bf7 100644 --- a/langtools/test/tools/javac/T6358166.java +++ b/langtools/test/tools/javac/T6358166.java @@ -54,7 +54,7 @@ public class T6358166 extends AbstractProcessor { String testSrc = System.getProperty("test.src"); JavacFileManager fm = new JavacFileManager(new Context(), false, null); - JavaFileObject f = fm.getFileForInput(testSrc + File.separatorChar + self + ".java"); + JavaFileObject f = fm.getJavaFileObject(testSrc + File.separatorChar + self + ".java"); test(fm, f, "-verbose", "-d", "."); diff --git a/langtools/test/tools/javac/T6705935.java b/langtools/test/tools/javac/T6705935.java deleted file mode 100644 index bd325f1a88e..00000000000 --- a/langtools/test/tools/javac/T6705935.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2008, 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 6705935 - * @summary javac reports path name of entry in ZipFileIndex incorectly - * @modules jdk.compiler/com.sun.tools.javac.file - */ - -import java.io.*; -import java.util.*; -import javax.tools.*; -import com.sun.tools.javac.file.*; -import com.sun.tools.javac.file.ZipArchive.ZipFileObject; -import com.sun.tools.javac.file.ZipFileIndexArchive.ZipFileIndexFileObject; - -public class T6705935 { - public static void main(String... args) throws Exception { - new T6705935().run(); - } - - public void run() throws Exception { - File java_home = new File(System.getProperty("java.home")); - - JavaCompiler c = ToolProvider.getSystemJavaCompiler(); - try (StandardJavaFileManager fm = c.getStandardFileManager(null, null, null)) { - //System.err.println("platform class path: " + asList(fm.getLocation(StandardLocation.PLATFORM_CLASS_PATH))); - - for (JavaFileObject fo: fm.list(StandardLocation.PLATFORM_CLASS_PATH, - "java.lang", - Collections.singleton(JavaFileObject.Kind.CLASS), - false)) { - test++; - - if (!(fo instanceof ZipFileObject || fo instanceof ZipFileIndexFileObject)) { - System.out.println("Skip " + fo.getClass().getSimpleName() + " " + fo.getName()); - skip++; - continue; - } - - //System.err.println(fo.getName()); - String p = fo.getName(); - int bra = p.indexOf("("); - int ket = p.indexOf(")"); - //System.err.println(bra + "," + ket + "," + p.length()); - if (bra == -1 || ket != p.length() -1) - throw new Exception("unexpected path: " + p + "[" + bra + "," + ket + "," + p.length()); - String part1 = p.substring(0, bra); - String part2 = p.substring(bra + 1, ket); - //System.err.println("[" + part1 + "|" + part2 + "]" + " " + java_home); - if (part1.equals(part2) || !part1.startsWith(java_home.getPath())) - throw new Exception("bad path: " + p); - - } - - if (test == 0) - throw new Exception("no files found"); - - if (skip == 0) - System.out.println(test + " files found"); - else - System.out.println(test + " files found, " + skip + " files skipped"); - - if (test == skip) - System.out.println("Warning: all files skipped; no platform classes found in zip files."); - } - } - - private List asList(Iterable items) { - List list = new ArrayList(); - for (T item: items) - list.add(item); - return list; - } - - private int skip; - private int test; -} diff --git a/langtools/test/tools/javac/T6725036.java b/langtools/test/tools/javac/T6725036.java index 2dabb428cab..8eb72a88e9f 100644 --- a/langtools/test/tools/javac/T6725036.java +++ b/langtools/test/tools/javac/T6725036.java @@ -37,16 +37,15 @@ import java.io.File; import java.io.IOException; +import java.util.Collections; import java.util.Date; import java.util.jar.JarEntry; import java.util.jar.JarFile; + import javax.tools.*; import com.sun.tools.javac.file.JavacFileManager; import com.sun.tools.javac.file.RelativePath.RelativeFile; -import com.sun.tools.javac.file.ZipFileIndex; -import com.sun.tools.javac.file.ZipFileIndexArchive; -import com.sun.tools.javac.file.ZipFileIndexCache; import com.sun.tools.javac.util.Context; public class T6725036 { @@ -63,21 +62,14 @@ public class T6725036 { JarEntry je = j.getJarEntry(TEST_ENTRY_NAME.getPath()); long jarEntryTime = je.getTime(); - ZipFileIndexCache zfic = ZipFileIndexCache.getSharedInstance(); - ZipFileIndex zfi = zfic.getZipFileIndex(testJar.toPath(), null, false, null, false); - long zfiTime = zfi.getLastModified(TEST_ENTRY_NAME); - - check(je, jarEntryTime, zfi + ":" + TEST_ENTRY_NAME.getPath(), zfiTime); - Context context = new Context(); JavacFileManager fm = new JavacFileManager(context, false, null); - ZipFileIndexArchive zfia = new ZipFileIndexArchive(fm, zfi); - JavaFileObject jfo = - zfia.getFileObject(TEST_ENTRY_NAME.dirname(), - TEST_ENTRY_NAME.basename()); - long jfoTime = jfo.getLastModified(); + fm.setLocation(StandardLocation.CLASS_PATH, Collections.singletonList(testJar)); + FileObject fo = + fm.getFileForInput(StandardLocation.CLASS_PATH, "", TEST_ENTRY_NAME.getPath()); + long jfoTime = fo.getLastModified(); - check(je, jarEntryTime, jfo, jfoTime); + check(je, jarEntryTime, fo, jfoTime); if (errors > 0) throw new Exception(errors + " occurred"); diff --git a/langtools/test/tools/javac/TryWithResources/T7022711.java b/langtools/test/tools/javac/TryWithResources/T7022711.java index 03346cb02fe..0994630e6a1 100644 --- a/langtools/test/tools/javac/TryWithResources/T7022711.java +++ b/langtools/test/tools/javac/TryWithResources/T7022711.java @@ -9,12 +9,22 @@ import java.io.*; class T7022711 { public static void main (String args[]) throws Exception { + // declared resource try (DataInputStream is = new DataInputStream(new FileInputStream("x"))) { while (true) { is.getChar(); // method not found } } catch (EOFException e) { } + + // resource as variable + DataInputStream is = new DataInputStream(new FileInputStream("x")); + try (is) { + while (true) { + is.getChar(); // method not found + } + } catch (EOFException e) { + } } } diff --git a/langtools/test/tools/javac/TryWithResources/T7022711.out b/langtools/test/tools/javac/TryWithResources/T7022711.out index 1157efff4c2..930620a37f1 100644 --- a/langtools/test/tools/javac/TryWithResources/T7022711.out +++ b/langtools/test/tools/javac/TryWithResources/T7022711.out @@ -1,2 +1,3 @@ -T7022711.java:14:19: compiler.err.cant.resolve.location.args: kindname.method, getChar, , , (compiler.misc.location.1: kindname.variable, is, java.io.DataInputStream) -1 error +T7022711.java:15:19: compiler.err.cant.resolve.location.args: kindname.method, getChar, , , (compiler.misc.location.1: kindname.variable, is, java.io.DataInputStream) +T7022711.java:24:19: compiler.err.cant.resolve.location.args: kindname.method, getChar, , , (compiler.misc.location.1: kindname.variable, is, java.io.DataInputStream) +2 errors diff --git a/langtools/test/tools/javac/TryWithResources/T7032633.java b/langtools/test/tools/javac/TryWithResources/T7032633.java index 81164c89df7..d6dd2ce619c 100644 --- a/langtools/test/tools/javac/TryWithResources/T7032633.java +++ b/langtools/test/tools/javac/TryWithResources/T7032633.java @@ -33,8 +33,15 @@ import java.io.OutputStream; public class T7032633 { void test() throws IOException { + // declared resource try (OutputStream out = System.out) { out.flush(); } + + // resource as variable + OutputStream out = System.out; + try (out) { + out.flush(); + } } } diff --git a/langtools/test/tools/javac/TryWithResources/TwrAndLambda.java b/langtools/test/tools/javac/TryWithResources/TwrAndLambda.java new file mode 100644 index 00000000000..da693b3686b --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/TwrAndLambda.java @@ -0,0 +1,55 @@ +/* + * @test /nodynamiccopyright/ + * @bug 7196163 + * @summary Twr with resource variables as lambda expressions and method references + * @compile/fail/ref=TwrAndLambda.out -XDrawDiagnostics TwrAndLambda.java + */ + +public class TwrAndLambda { + + public static void main(String... args) { + + // Lambda expression + AutoCloseable v1 = () -> {}; + // Static method reference + AutoCloseable v2 = TwrAndLambda::close1; + // Instance method reference + AutoCloseable v3 = new TwrAndLambda()::close2; + // Lambda expression which is not AutoCloseable + Runnable r1 = () -> {}; + // Static method reference which is not AutoCloseable + Runnable r2 = TwrAndLambda::close1; + // Instance method reference which is not AutoCloseable + Runnable r3 = new TwrAndLambda()::close2; + + try (v1) { + } catch(Exception e) {} + try (v2) { + } catch(Exception e) {} + try (v3) { + } catch(Exception e) {} + try (r1) { + } catch(Exception e) {} + try (r2) { + } catch(Exception e) {} + try (r3) { + } catch(Exception e) {} + + // lambda invocation + I i = (x) -> { try(x) { } catch (Exception e) { } }; + i.m(v1); + i.m(v2); + i.m(v3); + i.m(r1); + i.m(r2); + i.m(r3); + } + + static interface I { + public void m(AutoCloseable r); + } + + public static void close1() { } + + public void close2() { } +} diff --git a/langtools/test/tools/javac/TryWithResources/TwrAndLambda.out b/langtools/test/tools/javac/TryWithResources/TwrAndLambda.out new file mode 100644 index 00000000000..33fea3b8149 --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/TwrAndLambda.out @@ -0,0 +1,7 @@ +TwrAndLambda.java:31:14: compiler.err.prob.found.req: (compiler.misc.try.not.applicable.to.type: (compiler.misc.inconvertible.types: java.lang.Runnable, java.lang.AutoCloseable)) +TwrAndLambda.java:33:14: compiler.err.prob.found.req: (compiler.misc.try.not.applicable.to.type: (compiler.misc.inconvertible.types: java.lang.Runnable, java.lang.AutoCloseable)) +TwrAndLambda.java:35:14: compiler.err.prob.found.req: (compiler.misc.try.not.applicable.to.type: (compiler.misc.inconvertible.types: java.lang.Runnable, java.lang.AutoCloseable)) +TwrAndLambda.java:43:10: compiler.err.cant.apply.symbol: kindname.method, m, java.lang.AutoCloseable, java.lang.Runnable, kindname.interface, TwrAndLambda.I, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.Runnable, java.lang.AutoCloseable)) +TwrAndLambda.java:44:10: compiler.err.cant.apply.symbol: kindname.method, m, java.lang.AutoCloseable, java.lang.Runnable, kindname.interface, TwrAndLambda.I, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.Runnable, java.lang.AutoCloseable)) +TwrAndLambda.java:45:10: compiler.err.cant.apply.symbol: kindname.method, m, java.lang.AutoCloseable, java.lang.Runnable, kindname.interface, TwrAndLambda.I, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.Runnable, java.lang.AutoCloseable)) +6 errors diff --git a/langtools/test/tools/javac/TryWithResources/TwrAndTypeVariables.java b/langtools/test/tools/javac/TryWithResources/TwrAndTypeVariables.java new file mode 100644 index 00000000000..43462a4de02 --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/TwrAndTypeVariables.java @@ -0,0 +1,23 @@ +/* + * @test /nodynamiccopyright/ + * @bug 7196163 + * @summary Twr with resource variables of parametrized types + * @compile/fail/ref=TwrAndTypeVariables.out -XDrawDiagnostics TwrAndTypeVariables.java + */ + +public class TwrAndTypeVariables { + + // positive + public static + void copy(S s, T t) throws Exception { + try (s; t;) { + } + } + + // negative + public static void copy(S s) throws Exception { + try (s) { + } + } +} diff --git a/langtools/test/tools/javac/TryWithResources/TwrAndTypeVariables.out b/langtools/test/tools/javac/TryWithResources/TwrAndTypeVariables.out new file mode 100644 index 00000000000..8bcac84825e --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/TwrAndTypeVariables.out @@ -0,0 +1,2 @@ +TwrAndTypeVariables.java:20:14: compiler.err.prob.found.req: (compiler.misc.try.not.applicable.to.type: (compiler.misc.inconvertible.types: S, java.lang.AutoCloseable)) +1 error diff --git a/langtools/test/tools/javac/TryWithResources/TwrForVariable1.java b/langtools/test/tools/javac/TryWithResources/TwrForVariable1.java index 6e5d3fec4ba..dca1ada3e39 100644 --- a/langtools/test/tools/javac/TryWithResources/TwrForVariable1.java +++ b/langtools/test/tools/javac/TryWithResources/TwrForVariable1.java @@ -37,6 +37,49 @@ public class TwrForVariable1 implements AutoCloseable { } assertCloseCount(6); + + // null test cases + TwrForVariable1 n = null; + + try (n) { + } + try (n) { + throw new Exception(); + } catch (Exception e) { + } + + assertCloseCount(6); + + // initialization exception + TwrForVariable1 i1 = new TwrForVariable1(); + try (i1; TwrForVariable1 i2 = new TwrForVariable1(true)) { + } catch (Exception e) { + } + + assertCloseCount(7); + + // multiple closures + TwrForVariable1 m1 = new TwrForVariable1(); + try (m1; TwrForVariable1 m2 = m1; TwrForVariable1 m3 = m2;) { + } + + assertCloseCount(10); + + // aliasing of variables keeps equality (bugs 6911256 6964740) + TwrForVariable1 a1 = new TwrForVariable1(); + try (a1; TwrForVariable1 a2 = a1;) { + if (a2 != a2) + throw new RuntimeException("Unexpected inequality."); + } + + assertCloseCount(12); + + // anonymous class implementing AutoCloseable as variable in twr + AutoCloseable a = new AutoCloseable() { + public void close() { }; + }; + try (a) { + } catch (Exception e) {} } static void assertCloseCount(int expectedCloseCount) { @@ -66,4 +109,13 @@ public class TwrForVariable1 implements AutoCloseable { closeCount++; } } + + public TwrForVariable1(boolean throwException) { + if (throwException) + throw new RuntimeException("Initialization exception"); + } + + public TwrForVariable1() { + this(false); + } } diff --git a/langtools/test/tools/javac/TryWithResources/TwrForVariable2.java b/langtools/test/tools/javac/TryWithResources/TwrForVariable2.java index 70ca96b9193..73dd3fa2571 100644 --- a/langtools/test/tools/javac/TryWithResources/TwrForVariable2.java +++ b/langtools/test/tools/javac/TryWithResources/TwrForVariable2.java @@ -8,6 +8,7 @@ public class TwrForVariable2 implements AutoCloseable { public static void main(String... args) { TwrForVariable2 v = new TwrForVariable2(); TwrForVariable3[] v2 = new TwrForVariable3[1]; + TwrForVariable3[][] v3 = new TwrForVariable3[1][1]; try (final v) { fail("no modifiers before variables"); @@ -24,9 +25,15 @@ public class TwrForVariable2 implements AutoCloseable { try (v2[0]) { fail("array access not allowed"); } + try (v3[0][0]) { + fail("array access not allowed"); + } try (args.length == 0 ? v : v) { fail("general expressions not allowed"); } + try ((TwrForVariable2)null) { + fail("null as variable is not allowed"); + } } static void fail(String reason) { diff --git a/langtools/test/tools/javac/TryWithResources/TwrForVariable2.out b/langtools/test/tools/javac/TryWithResources/TwrForVariable2.out index 491cb5e3cbb..77a5ad2d55d 100644 --- a/langtools/test/tools/javac/TryWithResources/TwrForVariable2.out +++ b/langtools/test/tools/javac/TryWithResources/TwrForVariable2.out @@ -1,7 +1,9 @@ -TwrForVariable2.java:12:21: compiler.err.expected: token.identifier -TwrForVariable2.java:15:27: compiler.err.expected: token.identifier -TwrForVariable2.java:18:16: compiler.err.illegal.start.of.expr -TwrForVariable2.java:21:14: compiler.err.try.with.resources.expr.needs.var -TwrForVariable2.java:24:16: compiler.err.try.with.resources.expr.needs.var -TwrForVariable2.java:27:31: compiler.err.try.with.resources.expr.needs.var -6 errors +TwrForVariable2.java:13:21: compiler.err.expected: token.identifier +TwrForVariable2.java:16:27: compiler.err.expected: token.identifier +TwrForVariable2.java:19:16: compiler.err.illegal.start.of.expr +TwrForVariable2.java:22:14: compiler.err.try.with.resources.expr.needs.var +TwrForVariable2.java:25:16: compiler.err.try.with.resources.expr.needs.var +TwrForVariable2.java:28:19: compiler.err.try.with.resources.expr.needs.var +TwrForVariable2.java:31:31: compiler.err.try.with.resources.expr.needs.var +TwrForVariable2.java:34:14: compiler.err.try.with.resources.expr.needs.var +8 errors diff --git a/langtools/test/tools/javac/TryWithResources/TwrForVariable3.java b/langtools/test/tools/javac/TryWithResources/TwrForVariable3.java index 5f57bb370e8..c947fc8f0a4 100644 --- a/langtools/test/tools/javac/TryWithResources/TwrForVariable3.java +++ b/langtools/test/tools/javac/TryWithResources/TwrForVariable3.java @@ -7,9 +7,16 @@ public class TwrForVariable3 implements AutoCloseable { public static void main(String... args) { TwrForVariable3 v1 = new TwrForVariable3(); Object v2 = new Object(); + Object v3 = new Object() { + public void close() { + } + }; try (v2) { - fail("no an AutoCloseable"); + fail("not an AutoCloseable"); + } + try (v3) { + fail("not an AutoCloseable although has close() method"); } try (java.lang.Object) { fail("not a variable access"); diff --git a/langtools/test/tools/javac/TryWithResources/TwrForVariable3.out b/langtools/test/tools/javac/TryWithResources/TwrForVariable3.out index 248aac132ed..26e539910c2 100644 --- a/langtools/test/tools/javac/TryWithResources/TwrForVariable3.out +++ b/langtools/test/tools/javac/TryWithResources/TwrForVariable3.out @@ -1,4 +1,5 @@ -TwrForVariable3.java:11:14: compiler.err.prob.found.req: (compiler.misc.try.not.applicable.to.type: (compiler.misc.inconvertible.types: java.lang.Object, java.lang.AutoCloseable)) -TwrForVariable3.java:14:18: compiler.err.cant.resolve.location: kindname.class, lang, , , (compiler.misc.location: kindname.package, java, null) -TwrForVariable3.java:17:14: compiler.err.cant.resolve.location: kindname.variable, java, , , (compiler.misc.location: kindname.class, TwrForVariable3, null) -3 errors +TwrForVariable3.java:15:14: compiler.err.prob.found.req: (compiler.misc.try.not.applicable.to.type: (compiler.misc.inconvertible.types: java.lang.Object, java.lang.AutoCloseable)) +TwrForVariable3.java:18:14: compiler.err.prob.found.req: (compiler.misc.try.not.applicable.to.type: (compiler.misc.inconvertible.types: java.lang.Object, java.lang.AutoCloseable)) +TwrForVariable3.java:21:18: compiler.err.cant.resolve.location: kindname.class, lang, , , (compiler.misc.location: kindname.package, java, null) +TwrForVariable3.java:24:14: compiler.err.cant.resolve.location: kindname.variable, java, , , (compiler.misc.location: kindname.class, TwrForVariable3, null) +4 errors diff --git a/langtools/test/tools/javac/TryWithResources/TwrVarKinds.java b/langtools/test/tools/javac/TryWithResources/TwrVarKinds.java new file mode 100644 index 00000000000..5d9c3c5aff4 --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/TwrVarKinds.java @@ -0,0 +1,81 @@ +/* + * @test /nodynamiccopyright/ + * @bug 7196163 + * @summary Twr with different kinds of variables: local, instance, class, array component, parameter + * @compile/fail/ref=TwrVarKinds.out -XDrawDiagnostics TwrVarKinds.java + */ + +public class TwrVarKinds implements AutoCloseable { + + final static TwrVarKinds r1 = new TwrVarKinds(); + final TwrVarKinds r2 = new TwrVarKinds(); + static TwrVarKinds r3 = new TwrVarKinds(); + TwrVarKinds r4 = new TwrVarKinds(); + + public static void main(String... args) { + + TwrVarKinds r5 = new TwrVarKinds(); + + /* static final field - ok */ + try (r1) { + } + + /* non-static final field - ok */ + try (r1.r2) { + } + + /* static non-final field - wrong */ + try (r3) { + fail("Static non-final field is not allowed"); + } + + /* non-static non-final field - wrong */ + try (r1.r4) { + fail("Non-static non-final field is not allowed"); + } + + /* local variable - covered by TwrForVariable1 test */ + + /* array components - covered by TwrForVariable2 test */ + + /* method parameter - ok */ + method(r5); + + /* constructor parameter - ok */ + TwrVarKinds r6 = new TwrVarKinds(r5); + + /* lambda parameter - covered by TwrAndLambda */ + + /* exception parameter - ok */ + try { + throw new ResourceException(); + } catch (ResourceException e) { + try (e) { + } + } + } + + public TwrVarKinds() { + } + + public TwrVarKinds(TwrVarKinds r) { + try (r) { + } + } + + static void method(TwrVarKinds r) { + /* parameter */ + try (r) { + } + } + + static void fail(String reason) { + throw new RuntimeException(reason); + } + + public void close() {} + + static class ResourceException extends Exception implements AutoCloseable { + public void close() {} + } +} diff --git a/langtools/test/tools/javac/TryWithResources/TwrVarKinds.out b/langtools/test/tools/javac/TryWithResources/TwrVarKinds.out new file mode 100644 index 00000000000..1eaab01f963 --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/TwrVarKinds.out @@ -0,0 +1,3 @@ +TwrVarKinds.java:28:14: compiler.err.try.with.resources.expr.effectively.final.var: r3 +TwrVarKinds.java:33:16: compiler.err.try.with.resources.expr.effectively.final.var: r4 +2 errors diff --git a/langtools/test/tools/javac/TryWithResources/TwrVarRedeclaration.java b/langtools/test/tools/javac/TryWithResources/TwrVarRedeclaration.java new file mode 100644 index 00000000000..3bc4b83082e --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/TwrVarRedeclaration.java @@ -0,0 +1,28 @@ +/* + * @test /nodynamiccopyright/ + * @bug 7196163 + * @summary Variable redeclaration inside twr block + * @compile/fail/ref=TwrVarRedeclaration.out -XDrawDiagnostics TwrVarRedeclaration.java + */ + +public class TwrVarRedeclaration implements AutoCloseable { + + public static void main(String... args) { + TwrVarRedeclaration r = new TwrVarRedeclaration(); + + try (r) { + TwrVarRedeclaration r = new TwrVarRedeclaration(); + } + + try (r) { + Object r = new Object(); + } + + try (r) { + } catch (Exception e) { + Exception r = new Exception(); + } + } + + public void close() {} +} diff --git a/langtools/test/tools/javac/TryWithResources/TwrVarRedeclaration.out b/langtools/test/tools/javac/TryWithResources/TwrVarRedeclaration.out new file mode 100644 index 00000000000..d2e219cf783 --- /dev/null +++ b/langtools/test/tools/javac/TryWithResources/TwrVarRedeclaration.out @@ -0,0 +1,4 @@ +TwrVarRedeclaration.java:14:33: compiler.err.already.defined: kindname.variable, r, kindname.method, main(java.lang.String...) +TwrVarRedeclaration.java:18:20: compiler.err.already.defined: kindname.variable, r, kindname.method, main(java.lang.String...) +TwrVarRedeclaration.java:23:23: compiler.err.already.defined: kindname.variable, r, kindname.method, main(java.lang.String...) +3 errors diff --git a/langtools/test/tools/javac/api/6440528/T6440528.java b/langtools/test/tools/javac/api/6440528/T6440528.java index febcf2d2f27..c67dd292381 100644 --- a/langtools/test/tools/javac/api/6440528/T6440528.java +++ b/langtools/test/tools/javac/api/6440528/T6440528.java @@ -55,19 +55,13 @@ public class T6440528 extends ToolTester { "package-info.class", src); File expect = new File(test_src, "package-info.class"); - File got = getUnderlyingFile(cls); + File got = fm.asPath(cls).toFile(); if (!got.equals(expect)) throw new AssertionError(String.format("Expected: %s; got: %s", expect, got)); System.err.println("Expected: " + expect); System.err.println("Got: " + got); } - private File getUnderlyingFile(FileObject o) throws Exception { - Field file = o.getClass().getDeclaredField("file"); // assumes RegularFileObject - file.setAccessible(true); - return ((Path)file.get(o)).toFile(); - } - public static void main(String... args) throws Exception { try (T6440528 t = new T6440528()) { t.test(args); diff --git a/langtools/test/tools/javac/api/T6358955.java b/langtools/test/tools/javac/api/T6358955.java index 88d023053f9..ef08fb1231c 100644 --- a/langtools/test/tools/javac/api/T6358955.java +++ b/langtools/test/tools/javac/api/T6358955.java @@ -24,7 +24,7 @@ /* * @test * @bug 6358955 - * @summary JavacFileManager.getFileForInput(dir) shuld throw IAE + * @summary JavacFileManager.getFileForInput(dir) should throw IAE * @modules java.compiler * jdk.compiler */ diff --git a/langtools/test/tools/javac/api/T6838467.java b/langtools/test/tools/javac/api/T6838467.java index ef68ca7e83b..e328aa2f700 100644 --- a/langtools/test/tools/javac/api/T6838467.java +++ b/langtools/test/tools/javac/api/T6838467.java @@ -32,18 +32,18 @@ import java.io.*; import java.util.*; import java.util.zip.*; + import javax.tools.*; +import javax.tools.JavaFileManager.Location; + import com.sun.tools.javac.file.JavacFileManager; import com.sun.tools.javac.util.Context; -import com.sun.tools.javac.util.Options; public class T6838467 { - boolean fileSystemIsCaseSignificant = !new File("a").equals(new File("A")); enum FileKind { DIR("dir"), - ZIP("zip"), - ZIPFILEINDEX("zip"); + ZIP("zip"); FileKind(String path) { file = new File(path); } @@ -52,15 +52,19 @@ public class T6838467 { enum CompareKind { SAME { + @Override File other(File f) { return f; } }, ABSOLUTE { + @Override File other(File f) { return f.getAbsoluteFile(); } }, DIFFERENT { + @Override File other(File f) { return new File("not_" + f.getPath()); } }, CASEEQUIV { + @Override File other(File f) { return new File(f.getPath().toUpperCase()); } }; abstract File other(File f); @@ -73,10 +77,17 @@ public class T6838467 { } void run() throws Exception { + boolean fileNameIsCaseSignificant = isFileNameCaseSignificant(); + boolean fileLookupIsCaseSignificant = isFileLookupCaseSignificant(); + + String osName = System.getProperty("os.name"); + System.err.println("OS: " + osName); + System.err.println("fileNameIsCaseSignificant:" + fileNameIsCaseSignificant); + System.err.println("fileLookupIsCaseSignificant:" + fileLookupIsCaseSignificant); + // on Windows, verify file system is not case significant - if (System.getProperty("os.name").toLowerCase().startsWith("windows") - && fileSystemIsCaseSignificant) { - error("fileSystemIsCaseSignificant is set on Windows."); + if ((osName.startsWith("windows")) && fileNameIsCaseSignificant) { + error("fileNameIsCaseSignificant is set on " + osName + "."); } // create a set of directories and zip files to compare @@ -84,7 +95,7 @@ public class T6838467 { createTestDir(new File("not_dir"), paths); createTestZip(new File("zip"), paths); createTestZip(new File("not_zip"), paths); - if (fileSystemIsCaseSignificant) { + if (fileNameIsCaseSignificant || fileLookupIsCaseSignificant) { createTestDir(new File("DIR"), paths); createTestZip(new File("ZIP"), paths); } @@ -99,8 +110,9 @@ public class T6838467 { // verify that the various different types of file object were all // tested - Set expectClasses = new HashSet(Arrays.asList( - "RegularFileObject", "ZipFileObject", "ZipFileIndexFileObject" )); + Set expectClasses = new HashSet<>(Arrays.asList( + "DirectoryFileObject", + "JarFileObject" )); if (!foundClasses.equals(expectClasses)) { error("expected fileobject classes not found\n" + "expected: " + expectClasses + "\n" @@ -112,26 +124,22 @@ public class T6838467 { } void test(FileKind fk, CompareKind ck) throws IOException { - File f1 = fk.file; - JavaFileManager fm1 = createFileManager(fk, f1); + try (StandardJavaFileManager fm = createFileManager()) { + File f1 = fk.file; + Location l1 = createLocation(fm, "l1", f1); - File f2 = ck.other(fk.file); - JavaFileManager fm2 = createFileManager(fk, f2); + File f2 = ck.other(fk.file); + Location l2 = createLocation(fm, "l2", f2); - try { // If the directories or zip files match, we expect "n" matches in // the "n-squared" comparisons to come, where "n" is the number of // entries in the the directories or zip files. // If the directories or zip files don't themselves match, // we obviously don't expect any of their contents to match either. - int expect = (f1.getAbsoluteFile().equals(f2.getAbsoluteFile()) ? paths.length : 0); + int expectEqualCount = (f1.getCanonicalFile().equals(f2.getCanonicalFile()) ? paths.length : 0); System.err.println("test " + (++count) + " " + fk + " " + ck + " " + f1 + " " + f2); - test(fm1, fm2, expect); - - } finally { - fm1.close(); - fm2.close(); + test(fm, l1, l2, expectEqualCount); } } @@ -140,17 +148,17 @@ public class T6838467 { // returned from the other. For each pair of files, verify that if they // are equal, the hashcode is equal as well, and finally verify that the // expected number of matches was found. - void test(JavaFileManager fm1, JavaFileManager fm2, int expectEqualCount) throws IOException { + void test(JavaFileManager fm, Location l1, Location l2, int expectEqualCount) throws IOException { boolean foundFiles1 = false; boolean foundFiles2 = false; int foundEqualCount = 0; Set kinds = EnumSet.allOf(JavaFileObject.Kind.class); - for (FileObject fo1: fm1.list(StandardLocation.CLASS_PATH, "p", kinds, false)) { + for (FileObject fo1: fm.list(l1, "p", kinds, false)) { foundFiles1 = true; foundClasses.add(fo1.getClass().getSimpleName()); - for (FileObject fo2: fm2.list(StandardLocation.CLASS_PATH, "p", kinds, false)) { + for (FileObject fo2: fm.list(l2, "p", kinds, false)) { foundFiles2 = true; - foundClasses.add(fo1.getClass().getSimpleName()); + foundClasses.add(fo2.getClass().getSimpleName()); System.err.println("compare " + fo1 + " " + fo2); if (fo1.equals(fo2)) { foundEqualCount++; @@ -163,26 +171,35 @@ public class T6838467 { } } if (!foundFiles1) - error("no files found for file manager 1"); + error("no files found for location " + l1); if (!foundFiles2) - error("no files found for file manager 2"); + error("no files found for location " + l2); // verify the expected number of matches were found if (foundEqualCount != expectEqualCount) error("expected matches not found: expected " + expectEqualCount + ", found " + foundEqualCount); } - // create a file manager to test a FileKind, with a given directory - // or zip file placed on the classpath - JavaFileManager createFileManager(FileKind fk, File classpath) throws IOException { - StandardJavaFileManager fm = createFileManager(fk == FileKind.ZIP); - fm.setLocation(StandardLocation.CLASS_PATH, Arrays.asList(classpath)); - return fm; + // create and initialize a location to test a FileKind, with a given directory + // or zip file placed on the path + Location createLocation(StandardJavaFileManager fm, String name, File classpath) throws IOException { + Location l = new Location() { + @Override + public String getName() { + return name; + } + + @Override + public boolean isOutputLocation() { + return false; + } + + }; + fm.setLocation(l, Arrays.asList(classpath)); + return l; } - JavacFileManager createFileManager(boolean useOptimizedZip) { + JavacFileManager createFileManager() { Context ctx = new Context(); - Options options = Options.instance(ctx); - options.put("useOptimizedZip", Boolean.toString(useOptimizedZip)); return new JavacFileManager(ctx, false, null); } @@ -191,21 +208,17 @@ public class T6838467 { for (String p: paths) { File file = new File(dir, p); file.getParentFile().mkdirs(); - FileWriter out = new FileWriter(file); - try { + try (FileWriter out = new FileWriter(file)) { out.write(p); - } finally { - out.close(); } } } - // create a sip file containing a given set of entries + // create a zip file containing a given set of entries void createTestZip(File zip, String[] paths) throws IOException { if (zip.getParentFile() != null) zip.getParentFile().mkdirs(); - ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zip)); - try { + try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zip))) { for (String p: paths) { ZipEntry ze = new ZipEntry(p); zos.putNextEntry(ze); @@ -213,8 +226,6 @@ public class T6838467 { zos.write(bytes, 0, bytes.length); zos.closeEntry(); } - } finally { - zos.close(); } } @@ -223,8 +234,24 @@ public class T6838467 { errors++; } + boolean isFileNameCaseSignificant() { + File lower = new File("test.txt"); + File upper = new File(lower.getPath().toUpperCase()); + return !lower.equals(upper); + } + + boolean isFileLookupCaseSignificant() throws IOException { + File lower = new File("test.txt"); + File upper = new File(lower.getPath().toUpperCase()); + if (upper.exists()) { + upper.delete(); + } + try (FileWriter out = new FileWriter(lower)) { } + return !upper.exists(); + } + int count; int errors; - Set foundClasses = new HashSet(); + Set foundClasses = new HashSet<>(); } diff --git a/langtools/test/tools/javac/api/T6877206.java b/langtools/test/tools/javac/api/T6877206.java index 56127c2db0c..77fd394b8a6 100644 --- a/langtools/test/tools/javac/api/T6877206.java +++ b/langtools/test/tools/javac/api/T6877206.java @@ -62,15 +62,12 @@ public class T6877206 { test(createFileManager(), createDir("dir", entries), "p", entries.length); test(createFileManager(), createDir("a b/dir", entries), "p", entries.length); - - for (boolean useOptimizedZip: new boolean[] { false, true }) { - test(createFileManager(useOptimizedZip), createJar("jar", entries), "p", entries.length); - test(createFileManager(useOptimizedZip), createJar("jar jar", entries), "p", entries.length); - } + test(createFileManager(), createJar("jar", entries), "p", entries.length); + test(createFileManager(), createJar("jar jar", entries), "p", entries.length); // Verify that we hit the files we intended checkCoverage("classes", foundClasses, - "RegularFileObject", "ZipFileIndexFileObject", "ZipFileObject"); + "DirectoryFileObject", "JarFileObject"); // Verify that we hit the jar files we intended checkCoverage("jar files", foundJars, "jar", "jar jar"); @@ -153,17 +150,12 @@ public class T6877206 { } JavacFileManager createFileManager() { - return createFileManager(false, false); + return createFileManager(false); } - JavacFileManager createFileManager(boolean useOptimizedZip) { - return createFileManager(useOptimizedZip, false); - } - - JavacFileManager createFileManager(boolean useOptimizedZip, boolean useSymbolFile) { + JavacFileManager createFileManager(boolean useSymbolFile) { Context ctx = new Context(); Options options = Options.instance(ctx); - options.put("useOptimizedZip", Boolean.toString(useOptimizedZip)); if (!useSymbolFile) { options.put("ignore.symbol.file", "true"); } diff --git a/langtools/test/tools/javac/defaultMethods/private/PrivateGenerics.java b/langtools/test/tools/javac/defaultMethods/private/PrivateGenerics.java new file mode 100644 index 00000000000..5b8a7bd2dfa --- /dev/null +++ b/langtools/test/tools/javac/defaultMethods/private/PrivateGenerics.java @@ -0,0 +1,57 @@ +/* + * 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 8071453 + * @summary Verify that generics work with private method in interface + */ + +public class PrivateGenerics { + + interface I { + private T foo() { return null; }; + default void m(T t) { + T t1 = t; + T t2 = foo(); + } + } + + interface J { + private M foo() { return null; } + default void m(N n) { + N n1 = n; + N n2 = foo(); + } + } + + public static void main(String[] args) { + I i = new I<>() {}; + i.m("string"); + String s = i.foo(); + + J j = new J() {}; + j.m("string"); + s = j.foo(); + } +} diff --git a/langtools/test/tools/javac/doctree/DocCommentTester.java b/langtools/test/tools/javac/doctree/DocCommentTester.java index 3d3fd0e1072..344943a30c1 100644 --- a/langtools/test/tools/javac/doctree/DocCommentTester.java +++ b/langtools/test/tools/javac/doctree/DocCommentTester.java @@ -444,6 +444,18 @@ public class DocCommentTester { return null; } + @Override + public Void visitIndex(IndexTree node, Void p) { + header(node); + indent(+1); + print("term", node.getSearchTerm()); + print("description", node.getDescription()); + indent(-1); + indent(); + out.println("]"); + return null; + } + public Void visitInheritDoc(InheritDocTree node, Void p) { header(node, ""); return null; @@ -619,11 +631,19 @@ public class DocCommentTester { throw new UnsupportedOperationException("Not supported yet."); } + /* + * Use this method to start printing a multi-line representation of a + * DocTree node. The representation should be termintated by calling + * out.println("]"). + */ void header(DocTree node) { indent(); out.println(simpleClassName(node) + "[" + node.getKind() + ", pos:" + ((DCTree) node).pos); } + /* + * Use this method to print a single-line representation of a DocTree node. + */ void header(DocTree node, String rest) { indent(); out.println(simpleClassName(node) + "[" + node.getKind() + ", pos:" + ((DCTree) node).pos diff --git a/langtools/test/tools/javac/doctree/IndexTest.java b/langtools/test/tools/javac/doctree/IndexTest.java new file mode 100644 index 00000000000..3dcb83859fd --- /dev/null +++ b/langtools/test/tools/javac/doctree/IndexTest.java @@ -0,0 +1,289 @@ +/* + * 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 8144287 + * @summary extend com.sun.source API to support parsing javadoc comments + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.file + * jdk.compiler/com.sun.tools.javac.tree + * jdk.compiler/com.sun.tools.javac.util + * @build DocCommentTester + * @run main DocCommentTester IndexTest.java + */ + +class IndexTest { + /** + * abc {@index xyz} def + */ + void simple_term() {} +/* +DocComment[DOC_COMMENT, pos:1 + firstSentence: 3 + Text[TEXT, pos:1, abc_] + Index[INDEX, pos:5 + term: + Text[TEXT, pos:13, xyz] + description: empty + ] + Text[TEXT, pos:17, _def] + body: empty + block tags: empty +] +*/ + + /** + * abc {@index lmn pqr stu} def + */ + void simple_term_with_description() { } +/* +DocComment[DOC_COMMENT, pos:1 + firstSentence: 3 + Text[TEXT, pos:1, abc_] + Index[INDEX, pos:5 + term: + Text[TEXT, pos:13, lmn] + description: 1 + Text[TEXT, pos:17, pqr_stu] + ] + Text[TEXT, pos:25, _def] + body: empty + block tags: empty +] +*/ + + /** + * abc {@index ijk {lmn opq} } def + */ + void phrase_with_curly_description() { } +/* +DocComment[DOC_COMMENT, pos:1 + firstSentence: 3 + Text[TEXT, pos:1, abc_] + Index[INDEX, pos:5 + term: + Text[TEXT, pos:13, ijk] + description: 1 + Text[TEXT, pos:17, {lmn_opq}_] + ] + Text[TEXT, pos:28, _def] + body: empty + block tags: empty +] +*/ + /** + * abc {@index ijk lmn + * opq + * rst + * } def + */ + void phrase_with_nl_description() { } +/* +DocComment[DOC_COMMENT, pos:1 + firstSentence: 3 + Text[TEXT, pos:1, abc_] + Index[INDEX, pos:5 + term: + Text[TEXT, pos:13, ijk] + description: 1 + Text[TEXT, pos:17, lmn|_opq|_rst|_] + ] + Text[TEXT, pos:33, _def] + body: empty + block tags: empty +] +*/ + + /** + * abc {@index "lmn pqr"} def + */ + void phrase_no_description() { } +/* +DocComment[DOC_COMMENT, pos:1 + firstSentence: 3 + Text[TEXT, pos:1, abc_] + Index[INDEX, pos:5 + term: + Text[TEXT, pos:13, "lmn_pqr"] + description: empty + ] + Text[TEXT, pos:23, _def] + body: empty + block tags: empty +] +*/ + + /** + * abc {@index "ijk lmn" pqr xyz} def + */ + void phrase_with_description() { } +/* +DocComment[DOC_COMMENT, pos:1 + firstSentence: 3 + Text[TEXT, pos:1, abc_] + Index[INDEX, pos:5 + term: + Text[TEXT, pos:13, "ijk_lmn"] + description: 1 + Text[TEXT, pos:23, pqr_xyz] + ] + Text[TEXT, pos:31, _def] + body: empty + block tags: empty +] +*/ + + /** + * abc {@index {@xyz} "{@see xyz}" def} + */ + void term_and_description_with_nested_tag() {} +/* +DocComment[DOC_COMMENT, pos:1 + firstSentence: 2 + Text[TEXT, pos:1, abc_] + Index[INDEX, pos:5 + term: + Text[TEXT, pos:13, {@xyz}] + description: 1 + Text[TEXT, pos:20, "{@see_xyz}"_def] + ] + body: empty + block tags: empty +] +*/ + /** + * abc {@index @def lmn } xyz + */ + void term_with_at() { } +/* +DocComment[DOC_COMMENT, pos:1 + firstSentence: 3 + Text[TEXT, pos:1, abc_] + Index[INDEX, pos:5 + term: + Text[TEXT, pos:13, @def] + description: 1 + Text[TEXT, pos:18, lmn_] + ] + Text[TEXT, pos:23, _xyz] + body: empty + block tags: empty +] +*/ + + /** + * abc {@index ijk@lmn pqr } xyz + */ + void term_with_text_at() { } +/* +DocComment[DOC_COMMENT, pos:1 + firstSentence: 3 + Text[TEXT, pos:1, abc_] + Index[INDEX, pos:5 + term: + Text[TEXT, pos:13, ijk@lmn] + description: 1 + Text[TEXT, pos:21, pqr_] + ] + Text[TEXT, pos:26, _xyz] + body: empty + block tags: empty +] +*/ + + /** + * abc {@index ""} def + */ + void empty_index_in_quotes() {} +/* +DocComment[DOC_COMMENT, pos:1 + firstSentence: 3 + Text[TEXT, pos:1, abc_] + Index[INDEX, pos:5 + term: + Text[TEXT, pos:13, ""] + description: empty + ] + Text[TEXT, pos:16, _def] + body: empty + block tags: empty +] +*/ + + /** + * abc {@index + * @return def} xyz + */ + void bad_nl_at_in_term() {} +/* +DocComment[DOC_COMMENT, pos:1 + firstSentence: 2 + Text[TEXT, pos:1, abc_] + Erroneous[ERRONEOUS, pos:5 + code: compiler.err.dc.no.content + body: {@index + ] + body: empty + block tags: 1 + Return[RETURN, pos:14 + description: 1 + Text[TEXT, pos:22, def}_xyz] + ] +] +*/ + /** + * abc {@index "xyz } def + */ + void bad_unbalanced_quote() {} +/* +DocComment[DOC_COMMENT, pos:1 + firstSentence: 2 + Text[TEXT, pos:1, abc_] + Erroneous[ERRONEOUS, pos:5 + code: compiler.err.dc.no.content + body: {@index_"xyz_}_def + ] + body: empty + block tags: empty +] +*/ + /** + * abc {@index} def + */ + void bad_no_index() {} +/* +DocComment[DOC_COMMENT, pos:1 + firstSentence: 3 + Text[TEXT, pos:1, abc_] + Erroneous[ERRONEOUS, pos:5 + code: compiler.err.dc.no.content + body: {@index + ] + Text[TEXT, pos:12, }_def] + body: empty + block tags: empty +] +*/ + +} diff --git a/langtools/test/tools/javac/file/zip/T8076104.java b/langtools/test/tools/javac/file/zip/T8076104.java index d30ee53ca0a..b076fa52ac4 100644 --- a/langtools/test/tools/javac/file/zip/T8076104.java +++ b/langtools/test/tools/javac/file/zip/T8076104.java @@ -60,7 +60,6 @@ public class T8076104 extends AbstractProcessor { void run() throws Exception { File testJar = createJar(); doTest(testJar); - doTest(testJar, "-XDuseOptimizedZip=false"); } File createJar() throws Exception { diff --git a/langtools/test/tools/javac/lambda/MethodReferenceStaticNotAccessibleTest.java b/langtools/test/tools/javac/lambda/MethodReferenceStaticNotAccessibleTest.java new file mode 100644 index 00000000000..b0f078bde2f --- /dev/null +++ b/langtools/test/tools/javac/lambda/MethodReferenceStaticNotAccessibleTest.java @@ -0,0 +1,44 @@ +/* + * 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 8136809 + * @summary Javac fails compiling Collectors.reducing with method reference combiner + * @compile MethodReferenceStaticNotAccessibleTest.java + */ + +import java.util.function.BinaryOperator; + +class MethodReferenceStaticNotAccessibleTest_Foo { + MethodReferenceStaticNotAccessibleTest_Foo m(MethodReferenceStaticNotAccessibleTest_Foo foo) { return null; } + private static void m(MethodReferenceStaticNotAccessibleTest_Foo foo1, MethodReferenceStaticNotAccessibleTest_Foo foo2) {} +} + +public class MethodReferenceStaticNotAccessibleTest { + void m(T t, BinaryOperator binop) {} + + void test(MethodReferenceStaticNotAccessibleTest_Foo foo) { + m(foo, MethodReferenceStaticNotAccessibleTest_Foo::m); + } +} diff --git a/langtools/test/tools/javac/lambda/T8145051.java b/langtools/test/tools/javac/lambda/T8145051.java new file mode 100644 index 00000000000..9368a2a8aa8 --- /dev/null +++ b/langtools/test/tools/javac/lambda/T8145051.java @@ -0,0 +1,43 @@ +/* + * 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 8145051 + * @summary Wrong parameter name in synthetic lambda method leads to verifier error + * @compile pkg/T8145051.java + * @run main/othervm -Xverify:all T8145051 + */ + +public class T8145051 { + + public static void main(String [] args) { + pkg.T8145051 t8145051 = new pkg.T8145051(); + t8145051.new Sub(); + if (!t8145051.s.equals("Executed lambda")) + throw new AssertionError("Unexpected data"); + else + System.out.println("OK"); + } + +} diff --git a/langtools/test/tools/javac/lambda/methodReference/MethodRefToLocalClassMethodTest.java b/langtools/test/tools/javac/lambda/methodReference/MethodRefToLocalClassMethodTest.java new file mode 100644 index 00000000000..97eb7f0dabb --- /dev/null +++ b/langtools/test/tools/javac/lambda/methodReference/MethodRefToLocalClassMethodTest.java @@ -0,0 +1,52 @@ +/* + * 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 8144673 + * @summary Suspect message regarding suitable enclosing instance not being in scope + * @run main MethodRefToLocalClassMethodTest + */ + + +import java.util.ArrayList; +import java.util.List; + +public class MethodRefToLocalClassMethodTest { + + public static void main(String[] args) { + new MethodRefToLocalClassMethodTest().foo(); + } + + public void foo() { + class LocalFoo { + LocalFoo(String in) { + if (!in.equals("Hello")) + throw new AssertionError("Unexpected data: " + in); + } + } + List ls = new ArrayList<>(); + ls.add("Hello"); + ls.stream().map(LocalFoo::new).forEach(x->{}); + } +} diff --git a/langtools/test/tools/javac/lambda/pkg/T8145051.java b/langtools/test/tools/javac/lambda/pkg/T8145051.java new file mode 100644 index 00000000000..ca0b7265ed7 --- /dev/null +++ b/langtools/test/tools/javac/lambda/pkg/T8145051.java @@ -0,0 +1,43 @@ +/* + * 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 pkg; + +public class T8145051 { + + public String s; + + public static class Sup { + Sup(Runnable r) { + r.run(); + } + } + + public class Sub extends Sup { + public Sub() { + super(() -> { + s = "Executed lambda"; + }); + } + } +} diff --git a/langtools/test/tools/javac/lib/DPrinter.java b/langtools/test/tools/javac/lib/DPrinter.java index b447dfb83e6..c4304e41264 100644 --- a/langtools/test/tools/javac/lib/DPrinter.java +++ b/langtools/test/tools/javac/lib/DPrinter.java @@ -1049,6 +1049,13 @@ public class DPrinter { return visitTree(node, null); } + public Void visitIndex(IndexTree node, Void p) { + printString("kind", node.getKind().name()); + printDocTree("term", node.getSearchTerm()); + printList("desc", node.getDescription()); + return visitInlineTag(node, p); + } + public Void visitInheritDoc(InheritDocTree node, Void p) { return visitInlineTag(node, null); } diff --git a/langtools/test/tools/javac/options/modes/Tester.java b/langtools/test/tools/javac/options/modes/Tester.java index bcabc52d81d..3e0a8313e85 100644 --- a/langtools/test/tools/javac/options/modes/Tester.java +++ b/langtools/test/tools/javac/options/modes/Tester.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 @@ -136,8 +136,11 @@ public class Tester { } catch (IllegalArgumentException | IllegalStateException | IOException e) { tr.setThrown(e); } finally { - ((JavacFileManager) context.get(JavaFileManager.class)).close(); - tr.setLogs(sw.toString(), sysOut.close(), sysErr.close()); + try { + ((JavacFileManager) context.get(JavaFileManager.class)).close(); + tr.setLogs(sw.toString(), sysOut.close(), sysErr.close()); + } catch (IOException e) { + } } tr.setContext(context); tr.show(); @@ -149,6 +152,7 @@ public class Tester { class TestResult { final List args; Throwable thrown; + List suppressed = new ArrayList<>(); Object rc; // Number or Boolean Map logs; Context context; @@ -172,6 +176,10 @@ public class Tester { this.rc = ok ? 0 : 1; } + void setSuppressed(Throwable thrown) { + this.suppressed.add(thrown); + } + void setThrown(Throwable thrown) { this.thrown = thrown; } @@ -199,6 +207,11 @@ public class Tester { out.print("thrown:" + thrown); needSep = true; } + if (!suppressed.isEmpty()) { + if (needSep) out.print("; "); + out.print("suppressed:" + suppressed); + needSep = true; + } if (needSep) out.println(); logs.forEach((k, v) -> { diff --git a/langtools/test/tools/javac/parser/T4910483.java b/langtools/test/tools/javac/parser/T4910483.java index 7aa1c5120fb..544b1ec0366 100644 --- a/langtools/test/tools/javac/parser/T4910483.java +++ b/langtools/test/tools/javac/parser/T4910483.java @@ -49,7 +49,7 @@ public class T4910483 { String testSrc = System.getProperty("test.src"); JavacFileManager fm = new JavacFileManager(new Context(), false, null); - JavaFileObject f = fm.getFileForInput(testSrc + File.separatorChar + "T4910483.java"); + JavaFileObject f = fm.getJavaFileObject(testSrc + File.separatorChar + "T4910483.java"); JCTree.JCCompilationUnit cu = compiler.parse(f); JCTree classDef = cu.getTypeDecls().head; diff --git a/langtools/test/tools/javac/processing/TestMultipleErrors.java b/langtools/test/tools/javac/processing/TestMultipleErrors.java index be03f5da81f..d5b297bb553 100644 --- a/langtools/test/tools/javac/processing/TestMultipleErrors.java +++ b/langtools/test/tools/javac/processing/TestMultipleErrors.java @@ -1,29 +1,5 @@ /* - * 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -/* - * @test + * @test /nodynamiccopyright * @bug 8066843 * @summary Annotation processors should be able to print multiple errors at the same location. * @library /tools/javac/lib diff --git a/langtools/test/tools/javac/processing/TestMultipleErrors.out b/langtools/test/tools/javac/processing/TestMultipleErrors.out index a0d908894a6..9a5882e2b40 100644 --- a/langtools/test/tools/javac/processing/TestMultipleErrors.out +++ b/langtools/test/tools/javac/processing/TestMultipleErrors.out @@ -1,5 +1,5 @@ -TestMultipleErrors.java:42:8: compiler.err.proc.messager: error1 -TestMultipleErrors.java:42:8: compiler.err.proc.messager: error2 -TestMultipleErrors.java:42:8: compiler.err.proc.messager: error3 -TestMultipleErrors.java:42:8: compiler.err.proc.messager: error4 +TestMultipleErrors.java:18:8: compiler.err.proc.messager: error1 +TestMultipleErrors.java:18:8: compiler.err.proc.messager: error2 +TestMultipleErrors.java:18:8: compiler.err.proc.messager: error3 +TestMultipleErrors.java:18:8: compiler.err.proc.messager: error4 4 errors diff --git a/langtools/test/tools/javac/processing/errors/CrashOnNonExistingAnnotation/Processor.java b/langtools/test/tools/javac/processing/errors/CrashOnNonExistingAnnotation/Processor.java index 1e0ce80c9d8..7c246127f8c 100644 --- a/langtools/test/tools/javac/processing/errors/CrashOnNonExistingAnnotation/Processor.java +++ b/langtools/test/tools/javac/processing/errors/CrashOnNonExistingAnnotation/Processor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, 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 @@ -88,7 +88,7 @@ public class Processor extends AbstractProcessor { if (!testFile.canRead()) throw new IllegalStateException("Cannot read the test source"); JavacTool compiler = JavacTool.create(); JavacFileManager fm = compiler.getStandardFileManager(null, null, null); - testContent = fm.getRegularFile(testFile.toPath()).getCharContent(true).toString(); + testContent = fm.getJavaFileObject(testFile.toPath()).getCharContent(true).toString(); JavaFileObject testFileObject = new TestFO(new URI("mem://" + args[0]), testContent); TestFM testFileManager = new TestFM(fm); JavacTask task = compiler.getTask(null, diff --git a/langtools/test/tools/javac/processing/errors/StopOnInapplicableAnnotations/Processor.java b/langtools/test/tools/javac/processing/errors/StopOnInapplicableAnnotations/Processor.java index 6e85a83e967..0a3b525510c 100644 --- a/langtools/test/tools/javac/processing/errors/StopOnInapplicableAnnotations/Processor.java +++ b/langtools/test/tools/javac/processing/errors/StopOnInapplicableAnnotations/Processor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, 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 @@ -71,7 +71,7 @@ public class Processor extends AbstractProcessor { File inp = new File(sp, args[0]); if (inp.canRead()) { - testContent = fm.getRegularFile(inp.toPath()).getCharContent(true).toString(); + testContent = fm.getJavaFileObject(inp.toPath()).getCharContent(true).toString(); } } if (testContent == null) throw new IllegalStateException(); diff --git a/langtools/test/tools/javac/warnings/suppress/VerifySuppressWarnings.java b/langtools/test/tools/javac/warnings/suppress/VerifySuppressWarnings.java index e5e3f6d8b54..9d198b746cc 100644 --- a/langtools/test/tools/javac/warnings/suppress/VerifySuppressWarnings.java +++ b/langtools/test/tools/javac/warnings/suppress/VerifySuppressWarnings.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, 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 @@ -74,7 +74,7 @@ public class VerifySuppressWarnings { File inp = new File(sp, args[0]); if (inp.canRead()) { - testContent = fm.getRegularFile(inp.toPath()).getCharContent(true).toString(); + testContent = fm.getJavaFileObject(inp.toPath()).getCharContent(true).toString(); } } if (testContent == null) throw new IllegalStateException(); diff --git a/make/CompileJavaModules.gmk b/make/CompileJavaModules.gmk index 8d11590ccfa..83eb00338a9 100644 --- a/make/CompileJavaModules.gmk +++ b/make/CompileJavaModules.gmk @@ -556,7 +556,7 @@ CLASSPATH := $(foreach d, $(DEPS), $(if $($d_BIN), $($d_BIN), \ ifneq ($(BUILD_CRYPTO), true) CLASSPATH += $(JDK_OUTPUTDIR)/modules/$(MODULE) endif -JAVAC_FLAGS := -bootclasspath $(EMPTY_DIR) -extdirs $(EMPTY_DIR) \ +JAVAC_FLAGS_BOOTCLASSPATH := -bootclasspath $(EMPTY_DIR) -extdirs $(EMPTY_DIR) \ -endorseddirs $(EMPTY_DIR) $($(MODULE)_ADD_JAVAC_FLAGS) $(eval $(call SetupJavaCompilation, $(MODULE), \ @@ -566,7 +566,7 @@ $(eval $(call SetupJavaCompilation, $(MODULE), \ BIN := $(if $($(MODULE)_BIN), $($(MODULE)_BIN), $(JDK_OUTPUTDIR)/modules/$(MODULE)), \ HEADERS := $(SUPPORT_OUTPUTDIR)/headers/$(MODULE), \ CLASSPATH := $(CLASSPATH), \ - ADD_JAVAC_FLAGS := $($(MODULE)_ADD_JAVAC_FLAGS) $(JAVAC_FLAGS) \ + ADD_JAVAC_FLAGS := $($(MODULE)_ADD_JAVAC_FLAGS) $(JAVAC_FLAGS_BOOTCLASSPATH) \ )) TARGETS += $($(MODULE)) $($(MODULE)_COPY_EXTRA) diff --git a/make/Help.gmk b/make/Help.gmk index 739a85e2ee7..e48ec4cc48c 100644 --- a/make/Help.gmk +++ b/make/Help.gmk @@ -75,6 +75,7 @@ help: $(info $(_) CONF= # Build all configurations (note, assignment is empty)) $(info $(_) CONF= # Build the configuration(s) with a name matching) $(info $(_) # ) + $(info $(_) CONF_NAME= # Build the configuration with exactly the ) $(info $(_) SPEC= # Build the configuration given by the spec file) $(info $(_) LOG= # Change the log level from warn to ) $(info $(_) # Available log levels are:) diff --git a/make/InitSupport.gmk b/make/InitSupport.gmk index 6584d006f4d..eaec6b26950 100644 --- a/make/InitSupport.gmk +++ b/make/InitSupport.gmk @@ -40,7 +40,7 @@ ifeq ($(HAS_SPEC),) ############################################################################## # Make control variables, handled by Init.gmk - INIT_CONTROL_VARIABLES := LOG CONF SPEC JOBS CONF_CHECK COMPARE_BUILD + INIT_CONTROL_VARIABLES := LOG CONF CONF_NAME SPEC JOBS CONF_CHECK COMPARE_BUILD # All known make control variables MAKE_CONTROL_VARIABLES := $(INIT_CONTROL_VARIABLES) TEST JDK_FILTER @@ -169,6 +169,11 @@ ifeq ($(HAS_SPEC),) $$(info Error: Cannot use CONF=$$(CONF) and SPEC=$$(SPEC) at the same time. Choose one.) $$(error Cannot continue) endif + ifneq ($$(origin CONF_NAME), undefined) + # We also have a CONF_NAME argument. We can't have both. + $$(info Error: Cannot use CONF_NAME=$$(CONF_NAME) and SPEC=$$(SPEC) at the same time. Choose one.) + $$(error Cannot continue) + endif ifeq ($$(wildcard $$(SPEC)),) $$(info Error: Cannot locate spec.gmk, given by SPEC=$$(SPEC).) $$(error Cannot continue) @@ -191,7 +196,29 @@ ifeq ($(HAS_SPEC),) $$(error Cannot continue) endif - ifneq ($$(origin CONF), undefined) + ifneq ($$(origin CONF_NAME), undefined) + ifneq ($$(origin CONF), undefined) + # We also have a CONF argument. We can't have both. + $$(info Error: Cannot use CONF=$$(CONF) and CONF_NAME=$$(CONF_NAME) at the same time. Choose one.) + $$(error Cannot continue) + endif + matching_conf := $$(strip $$(filter $$(CONF_NAME), $$(all_confs))) + ifeq ($$(matching_conf),) + $$(info Error: No configurations found matching CONF_NAME=$$(CONF_NAME).) + $$(info Available configurations in $$(build_dir):) + $$(foreach var, $$(all_confs), $$(info * $$(var))) + $$(error Cannot continue) + else ifneq ($$(words $$(matching_conf)), 1) + $$(info Error: Matching more than one configuration CONF_NAME=$$(CONF_NAME).) + $$(info Available configurations in $$(build_dir):) + $$(foreach var, $$(all_confs), $$(info * $$(var))) + $$(error Cannot continue) + else + $$(info Building configuration '$$(matching_conf)' (matching CONF_NAME=$$(CONF_NAME))) + endif + # Create a SPEC definition. This will contain the path to exactly one spec file. + SPECS := $$(build_dir)/$$(matching_conf)/spec.gmk + else ifneq ($$(origin CONF), undefined) # User have given a CONF= argument. ifeq ($$(CONF),) # If given CONF=, match all configurations diff --git a/make/Main.gmk b/make/Main.gmk index 422a396b4f4..3b60038e42d 100644 --- a/make/Main.gmk +++ b/make/Main.gmk @@ -554,7 +554,7 @@ ALL_TARGETS += buildtools gensrc gendata copy java rmic libs launchers \ # Traditional targets typically run by users. # These can be considered aliases for the targets now named by a more # "modern" naming scheme. -default: exploded-image +default: $(DEFAULT_MAKE_TARGET) jdk: exploded-image images: product-images docs: docs-image diff --git a/make/common/NativeCompilation.gmk b/make/common/NativeCompilation.gmk index 3f0116339ee..87d851692ae 100644 --- a/make/common/NativeCompilation.gmk +++ b/make/common/NativeCompilation.gmk @@ -513,6 +513,10 @@ define SetupNativeCompilationBody $1_EXTRA_CXXFLAGS:=$$($1_EXTRA_CFLAGS) endif + ifeq ($(DEBUG_BINARIES), true) + $1_EXTRA_CFLAGS+=$(CFLAGS_DEBUG_SYMBOLS) + $1_EXTRA_CXXFLAGS+=$(CXXFLAGS_DEBUG_SYMBOLS) + endif ifeq ($$($1_DEBUG_SYMBOLS), true) ifeq ($(ENABLE_DEBUG_SYMBOLS), true) ifdef OPENJDK diff --git a/modules.xml b/modules.xml index d5736bda0b4..e2eaa754a07 100644 --- a/modules.xml +++ b/modules.xml @@ -1655,7 +1655,6 @@ jdk.deploy.osx java.base java.desktop - java.scripting jdk.dev diff --git a/nashorn/.hgtags b/nashorn/.hgtags index 1972d6e82b2..408589a3ebd 100644 --- a/nashorn/.hgtags +++ b/nashorn/.hgtags @@ -329,3 +329,4 @@ fee4d2015e24ced4f28f4dcf93076a4fbd03844d jdk9-b91 e13533f7bb78da49bbd909fdf22e13e0e2538146 jdk9-b93 328932975c749ba7ae40cd5b63e3a7983b564936 jdk9-b94 9d52f9bb589c4caa3617fe1cf11c72512ab8e973 jdk-9+95 +d52c09d5d98a81ee6102a25f662ec4b9ae614163 jdk-9+96 diff --git a/nashorn/samples/dynalink/ArrayStreamLinkerExporter.java b/nashorn/samples/dynalink/ArrayStreamLinkerExporter.java new file mode 100644 index 00000000000..5fbfabdeb7e --- /dev/null +++ b/nashorn/samples/dynalink/ArrayStreamLinkerExporter.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.DoubleStream; +import java.util.stream.IntStream; +import java.util.stream.LongStream; +import java.util.stream.Stream; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.CompositeOperation; +import jdk.dynalink.NamedOperation; +import jdk.dynalink.Operation; +import jdk.dynalink.StandardOperation; +import jdk.dynalink.linker.GuardingDynamicLinker; +import jdk.dynalink.linker.GuardingDynamicLinkerExporter; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.TypeBasedGuardingDynamicLinker; +import jdk.dynalink.linker.LinkRequest; +import jdk.dynalink.linker.LinkerServices; +import jdk.dynalink.linker.support.Guards; +import jdk.dynalink.linker.support.Lookup; + +/** + * This is a dynalink pluggable linker (see http://openjdk.java.net/jeps/276). + * This linker adds "stream" property to Java arrays. The appropriate Stream + * type object is returned for "stream" property on Java arrays. Note that + * the dynalink beans linker just adds "length" property and Java array objects + * don't have any other property. "stream" property does not conflict with anything + * else! + */ +public final class ArrayStreamLinkerExporter extends GuardingDynamicLinkerExporter { + static { + System.out.println("pluggable dynalink array stream linker loaded"); + } + + public static Object arrayToStream(Object array) { + if (array instanceof int[]) { + return IntStream.of((int[])array); + } else if (array instanceof long[]) { + return LongStream.of((long[])array); + } else if (array instanceof double[]) { + return DoubleStream.of((double[])array); + } else if (array instanceof Object[]) { + return Stream.of((Object[])array); + } else { + throw new IllegalArgumentException(); + } + } + + private static final MethodType GUARD_TYPE = MethodType.methodType(Boolean.TYPE, Object.class); + private static final MethodHandle ARRAY_TO_STREAM = Lookup.PUBLIC.findStatic( + ArrayStreamLinkerExporter.class, "arrayToStream", + MethodType.methodType(Object.class, Object.class)); + + @Override + public List get() { + final ArrayList linkers = new ArrayList<>(); + linkers.add(new TypeBasedGuardingDynamicLinker() { + @Override + public boolean canLinkType(final Class type) { + return type == Object[].class || type == int[].class || + type == long[].class || type == double[].class; + } + + @Override + public GuardedInvocation getGuardedInvocation(LinkRequest request, + LinkerServices linkerServices) throws Exception { + final Object self = request.getReceiver(); + if (self == null || !canLinkType(self.getClass())) { + return null; + } + + CallSiteDescriptor desc = request.getCallSiteDescriptor(); + Operation op = desc.getOperation(); + Object name = NamedOperation.getName(op); + boolean getProp = CompositeOperation.contains( + NamedOperation.getBaseOperation(op), + StandardOperation.GET_PROPERTY); + if (getProp && "stream".equals(name)) { + return new GuardedInvocation(ARRAY_TO_STREAM, + Guards.isOfClass(self.getClass(), GUARD_TYPE)); + } + + return null; + } + }); + return linkers; + } +} diff --git a/nashorn/samples/dynalink/BufferIndexingLinkerExporter.java b/nashorn/samples/dynalink/BufferIndexingLinkerExporter.java new file mode 100644 index 00000000000..64ca714f8c8 --- /dev/null +++ b/nashorn/samples/dynalink/BufferIndexingLinkerExporter.java @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.ArrayList; +import java.util.List; +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.DoubleBuffer; +import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import java.nio.LongBuffer; +import java.nio.ShortBuffer; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.CompositeOperation; +import jdk.dynalink.NamedOperation; +import jdk.dynalink.Operation; +import jdk.dynalink.StandardOperation; +import jdk.dynalink.linker.GuardingDynamicLinker; +import jdk.dynalink.linker.GuardingDynamicLinkerExporter; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.TypeBasedGuardingDynamicLinker; +import jdk.dynalink.linker.LinkRequest; +import jdk.dynalink.linker.LinkerServices; +import jdk.dynalink.linker.support.Guards; +import jdk.dynalink.linker.support.Lookup; + +/** + * This is a dynalink pluggable linker (see http://openjdk.java.net/jeps/276). + * This linker adds array-like indexing and "length" property to nio Buffer objects. + */ +public final class BufferIndexingLinkerExporter extends GuardingDynamicLinkerExporter { + static { + System.out.println("pluggable dynalink buffer indexing linker loaded"); + } + + private static final MethodHandle BUFFER_LIMIT; + private static final MethodHandle BYTEBUFFER_GET; + private static final MethodHandle BYTEBUFFER_PUT; + private static final MethodHandle CHARBUFFER_GET; + private static final MethodHandle CHARBUFFER_PUT; + private static final MethodHandle SHORTBUFFER_GET; + private static final MethodHandle SHORTBUFFER_PUT; + private static final MethodHandle INTBUFFER_GET; + private static final MethodHandle INTBUFFER_PUT; + private static final MethodHandle LONGBUFFER_GET; + private static final MethodHandle LONGBUFFER_PUT; + private static final MethodHandle FLOATBUFFER_GET; + private static final MethodHandle FLOATBUFFER_PUT; + private static final MethodHandle DOUBLEBUFFER_GET; + private static final MethodHandle DOUBLEBUFFER_PUT; + + // guards + private static final MethodHandle IS_BUFFER; + private static final MethodHandle IS_BYTEBUFFER; + private static final MethodHandle IS_CHARBUFFER; + private static final MethodHandle IS_SHORTBUFFER; + private static final MethodHandle IS_INTBUFFER; + private static final MethodHandle IS_LONGBUFFER; + private static final MethodHandle IS_FLOATBUFFER; + private static final MethodHandle IS_DOUBLEBUFFER; + + private static final MethodType GUARD_TYPE; + + static { + Lookup look = Lookup.PUBLIC; + BUFFER_LIMIT = look.findVirtual(Buffer.class, "limit", MethodType.methodType(int.class)); + BYTEBUFFER_GET = look.findVirtual(ByteBuffer.class, "get", + MethodType.methodType(byte.class, int.class)); + BYTEBUFFER_PUT = look.findVirtual(ByteBuffer.class, "put", + MethodType.methodType(ByteBuffer.class, int.class, byte.class)); + CHARBUFFER_GET = look.findVirtual(CharBuffer.class, "get", + MethodType.methodType(char.class, int.class)); + CHARBUFFER_PUT = look.findVirtual(CharBuffer.class, "put", + MethodType.methodType(CharBuffer.class, int.class, char.class)); + SHORTBUFFER_GET = look.findVirtual(ShortBuffer.class, "get", + MethodType.methodType(short.class, int.class)); + SHORTBUFFER_PUT = look.findVirtual(ShortBuffer.class, "put", + MethodType.methodType(ShortBuffer.class, int.class, short.class)); + INTBUFFER_GET = look.findVirtual(IntBuffer.class, "get", + MethodType.methodType(int.class, int.class)); + INTBUFFER_PUT = look.findVirtual(IntBuffer.class, "put", + MethodType.methodType(IntBuffer.class, int.class, int.class)); + LONGBUFFER_GET = look.findVirtual(LongBuffer.class, "get", + MethodType.methodType(long.class, int.class)); + LONGBUFFER_PUT = look.findVirtual(LongBuffer.class, "put", + MethodType.methodType(LongBuffer.class, int.class, long.class)); + FLOATBUFFER_GET = look.findVirtual(FloatBuffer.class, "get", + MethodType.methodType(float.class, int.class)); + FLOATBUFFER_PUT = look.findVirtual(FloatBuffer.class, "put", + MethodType.methodType(FloatBuffer.class, int.class, float.class)); + DOUBLEBUFFER_GET = look.findVirtual(DoubleBuffer.class, "get", + MethodType.methodType(double.class, int.class)); + DOUBLEBUFFER_PUT = look.findVirtual(DoubleBuffer.class, "put", + MethodType.methodType(DoubleBuffer.class, int.class, double.class)); + + GUARD_TYPE = MethodType.methodType(boolean.class, Object.class); + IS_BUFFER = Guards.isInstance(Buffer.class, GUARD_TYPE); + IS_BYTEBUFFER = Guards.isInstance(ByteBuffer.class, GUARD_TYPE); + IS_CHARBUFFER = Guards.isInstance(CharBuffer.class, GUARD_TYPE); + IS_SHORTBUFFER = Guards.isInstance(ShortBuffer.class, GUARD_TYPE); + IS_INTBUFFER = Guards.isInstance(IntBuffer.class, GUARD_TYPE); + IS_LONGBUFFER = Guards.isInstance(LongBuffer.class, GUARD_TYPE); + IS_FLOATBUFFER = Guards.isInstance(FloatBuffer.class, GUARD_TYPE); + IS_DOUBLEBUFFER = Guards.isInstance(DoubleBuffer.class, GUARD_TYPE); + } + + // locate the first standard operation from the call descriptor + private static StandardOperation getFirstStandardOperation(final CallSiteDescriptor desc) { + final Operation base = NamedOperation.getBaseOperation(desc.getOperation()); + if (base instanceof StandardOperation) { + return (StandardOperation)base; + } else if (base instanceof CompositeOperation) { + final CompositeOperation cop = (CompositeOperation)base; + for(int i = 0; i < cop.getOperationCount(); ++i) { + final Operation op = cop.getOperation(i); + if (op instanceof StandardOperation) { + return (StandardOperation)op; + } + } + } + return null; + } + + @Override + public List get() { + final ArrayList linkers = new ArrayList<>(); + linkers.add(new TypeBasedGuardingDynamicLinker() { + @Override + public boolean canLinkType(final Class type) { + return Buffer.class.isAssignableFrom(type); + } + + @Override + public GuardedInvocation getGuardedInvocation(LinkRequest request, + LinkerServices linkerServices) throws Exception { + final Object self = request.getReceiver(); + if (self == null || !canLinkType(self.getClass())) { + return null; + } + + CallSiteDescriptor desc = request.getCallSiteDescriptor(); + StandardOperation op = getFirstStandardOperation(desc); + if (op == null) { + return null; + } + + switch (op) { + case GET_ELEMENT: + return linkGetElement(self); + case SET_ELEMENT: + return linkSetElement(self); + case GET_PROPERTY: { + Object name = NamedOperation.getName(desc.getOperation()); + if ("length".equals(name)) { + return linkLength(); + } + } + } + + return null; + } + }); + return linkers; + } + + private static GuardedInvocation linkGetElement(Object self) { + MethodHandle method = null; + MethodHandle guard = null; + if (self instanceof ByteBuffer) { + method = BYTEBUFFER_GET; + guard = IS_BYTEBUFFER; + } else if (self instanceof CharBuffer) { + method = CHARBUFFER_GET; + guard = IS_CHARBUFFER; + } else if (self instanceof ShortBuffer) { + method = SHORTBUFFER_GET; + guard = IS_SHORTBUFFER; + } else if (self instanceof IntBuffer) { + method = INTBUFFER_GET; + guard = IS_INTBUFFER; + } else if (self instanceof LongBuffer) { + method = LONGBUFFER_GET; + guard = IS_LONGBUFFER; + } else if (self instanceof FloatBuffer) { + method = FLOATBUFFER_GET; + guard = IS_FLOATBUFFER; + } else if (self instanceof DoubleBuffer) { + method = DOUBLEBUFFER_GET; + guard = IS_DOUBLEBUFFER; + } + + return method != null? new GuardedInvocation(method, guard) : null; + } + + private static GuardedInvocation linkSetElement(Object self) { + MethodHandle method = null; + MethodHandle guard = null; + if (self instanceof ByteBuffer) { + method = BYTEBUFFER_PUT; + guard = IS_BYTEBUFFER; + } else if (self instanceof CharBuffer) { + method = CHARBUFFER_PUT; + guard = IS_CHARBUFFER; + } else if (self instanceof ShortBuffer) { + method = SHORTBUFFER_PUT; + guard = IS_SHORTBUFFER; + } else if (self instanceof IntBuffer) { + method = INTBUFFER_PUT; + guard = IS_INTBUFFER; + } else if (self instanceof LongBuffer) { + method = LONGBUFFER_PUT; + guard = IS_LONGBUFFER; + } else if (self instanceof FloatBuffer) { + method = FLOATBUFFER_PUT; + guard = IS_FLOATBUFFER; + } else if (self instanceof DoubleBuffer) { + method = DOUBLEBUFFER_PUT; + guard = IS_DOUBLEBUFFER; + } + + return method != null? new GuardedInvocation(method, guard) : null; + } + + private static GuardedInvocation linkLength() { + return new GuardedInvocation(BUFFER_LIMIT, IS_BUFFER); + } +} diff --git a/nashorn/samples/DOMLinkerExporter.java b/nashorn/samples/dynalink/DOMLinkerExporter.java similarity index 100% rename from nashorn/samples/DOMLinkerExporter.java rename to nashorn/samples/dynalink/DOMLinkerExporter.java diff --git a/nashorn/samples/META-INF/services/jdk.dynalink.linker.GuardingDynamicLinkerExporter b/nashorn/samples/dynalink/META-INF/services/jdk.dynalink.linker.GuardingDynamicLinkerExporter similarity index 57% rename from nashorn/samples/META-INF/services/jdk.dynalink.linker.GuardingDynamicLinkerExporter rename to nashorn/samples/dynalink/META-INF/services/jdk.dynalink.linker.GuardingDynamicLinkerExporter index 6e63266aeeb..745f0615bd7 100644 --- a/nashorn/samples/META-INF/services/jdk.dynalink.linker.GuardingDynamicLinkerExporter +++ b/nashorn/samples/dynalink/META-INF/services/jdk.dynalink.linker.GuardingDynamicLinkerExporter @@ -1,3 +1,5 @@ DOMLinkerExporter UnderscoreNameLinkerExporter MissingMethodLinkerExporter +ArrayStreamLinkerExporter +BufferIndexingLinkerExporter diff --git a/nashorn/samples/MissingMethodExample.java b/nashorn/samples/dynalink/MissingMethodExample.java similarity index 96% rename from nashorn/samples/MissingMethodExample.java rename to nashorn/samples/dynalink/MissingMethodExample.java index 4354a67615d..49175d62119 100644 --- a/nashorn/samples/MissingMethodExample.java +++ b/nashorn/samples/dynalink/MissingMethodExample.java @@ -38,7 +38,7 @@ public class MissingMethodExample extends ArrayList @Override public Object doesNotUnderstand(String name, Object... args) { - // This dummy doesNotUnderstand just prints method name and args. + // This simple doesNotUnderstand just prints method name and args. // You can put useful method routing logic here. System.out.println("you called " + name); if (args.length != 0) { diff --git a/nashorn/samples/MissingMethodHandler.java b/nashorn/samples/dynalink/MissingMethodHandler.java similarity index 100% rename from nashorn/samples/MissingMethodHandler.java rename to nashorn/samples/dynalink/MissingMethodHandler.java diff --git a/nashorn/samples/MissingMethodLinkerExporter.java b/nashorn/samples/dynalink/MissingMethodLinkerExporter.java similarity index 100% rename from nashorn/samples/MissingMethodLinkerExporter.java rename to nashorn/samples/dynalink/MissingMethodLinkerExporter.java diff --git a/nashorn/samples/dynalink/README b/nashorn/samples/dynalink/README new file mode 100644 index 00000000000..6b53698846b --- /dev/null +++ b/nashorn/samples/dynalink/README @@ -0,0 +1,51 @@ +This directory contains samples for Dynalink API (http://openjdk.java.net/jeps/276). +These samples require a jar file to be built and such jars be placed in the +classpath of the jjs tool. Linker samples are named with the naming pattern +"xyz_linker.js". These scripts build dynalink linker jar from java code and exec +another jjs process with appropriate classpath set. + +Note: you need to build jdk9 forest and put "images/jdk/bin" in your PATH to use +these scripts. This is because these scripts use javac to build dynalink jar and +exec another jjs with classpath set! Alternatively, you can also manually build +dynalink linker jars and invoke sample scripts by putting linker jar in jjs tool's +classpath as well. + +Dynalink samples: + +* array_stream_linker.js + +This sample builds ArrayStreamLinkerExporter.java and uses it in a sample script +called "array_stream.js". This linker adds "stream" property to Java array +objects. The "stream" property returns appropriate Stream type for the given +Java array (IntStream, DoubleStream ...). + +* buffer_indexing_linker.js + +This sample builds BufferIndexingLinkerExporter.java and uses it in a sample script +called "buffer_index.js". This linker adds array-like indexed access, indexed assignment +and "length" property to Java NIO Buffer objects. Script can treat NIO Buffer objects +as if those are just array objects. + +* dom_linker.js + +This sample builds DOMLinkerExporter.java and uses it in a sample script +called "dom_linker_gutenberg.js". This linker handles DOM Element objects to add +properties to access child elements of a given element by child element tag name. +This simplifies script access of parsed XML DOM Documents. + +* missing_method_linker.js + +This sample builds MissingMethodLinkerExporter.java and uses it in a sample script +called "missing_method.js". This linker supports Smalltalk-style "doesNotUnderstand" +calls on Java objects. i.e., A Java class can implement MissingMethodHandler interface +with one method named "doesNotUnderstand". When script accesses a method on such +object and if that method does not exist in the Java class (or any of it's supertypes), +then "doesNotUnderstand" method is invoked. + +* underscore_linker.js + +This sample builds UnderscoreNameLinkerExporter.java and uses it in a sample script +called "underscore.js". This linker converts underscore separated names to Camel Case +names (as used in Java APIs). You can call Java APIs using Ruby-like naming convention +and this linker converts method names to CamelCase! + diff --git a/nashorn/samples/UnderscoreNameLinkerExporter.java b/nashorn/samples/dynalink/UnderscoreNameLinkerExporter.java similarity index 100% rename from nashorn/samples/UnderscoreNameLinkerExporter.java rename to nashorn/samples/dynalink/UnderscoreNameLinkerExporter.java diff --git a/nashorn/samples/dynalink/array_stream.js b/nashorn/samples/dynalink/array_stream.js new file mode 100644 index 00000000000..e024d0ace02 --- /dev/null +++ b/nashorn/samples/dynalink/array_stream.js @@ -0,0 +1,54 @@ +# Usage: jjs -cp array_stream_linker.jar array_stream.js + +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// This script depends on array stream dynalink linker +// to work as expected. Without that linker in jjs classpath, +// this script will fail to run. + +// Object[] and then Stream +var s = Java.to(["hello", "world"]).stream +s.map(function(s) s.toUpperCase()).forEach(print) + +// IntStream +var is = Java.to([3, 56, 4, 23], "int[]").stream +print(is.map(function(x) x*x).sum()) + +// DoubleStream +var DoubleArray = Java.type("double[]") +var arr = new DoubleArray(100) +for (var i = 0; i < arr.length; i++) + arr[i] = Math.random() + +print(arr.stream.summaryStatistics()) + + diff --git a/nashorn/samples/dynalink/array_stream_linker.js b/nashorn/samples/dynalink/array_stream_linker.js new file mode 100644 index 00000000000..91a5d6620ff --- /dev/null +++ b/nashorn/samples/dynalink/array_stream_linker.js @@ -0,0 +1,49 @@ +#! array stream linker example + +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// This script assumes you've built jdk9 or using latest +// jdk9 image and put the 'bin' directory in the PATH + +$EXEC.throwOnError=true + +// compile ArrayStreamLinkerExporter +`javac -cp ../../dist/nashorn.jar ArrayStreamLinkerExporter.java` + +// make a jar file out of pluggable linker +`jar cvf array_stream_linker.jar ArrayStreamLinkerExporter*.class META-INF/` + +// run a sample script that uses pluggable linker +// but make sure classpath points to the pluggable linker jar! + +`jjs -cp array_stream_linker.jar array_stream.js` +print($OUT) diff --git a/nashorn/samples/dynalink/buffer_index.js b/nashorn/samples/dynalink/buffer_index.js new file mode 100644 index 00000000000..4f3559afa4b --- /dev/null +++ b/nashorn/samples/dynalink/buffer_index.js @@ -0,0 +1,65 @@ +# Usage: jjs -cp buffer_indexing_linker.jar buffer_index.js + +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// This script depends on buffer indexing dynalink linker. Without that +// linker in classpath, this script will fail to run properly. + +function str(buf) { + var s = '' + for (var i = 0; i < buf.length; i++) + s += buf[i] + "," + return s +} + +var ByteBuffer = Java.type("java.nio.ByteBuffer") +var bb = ByteBuffer.allocate(10) +for (var i = 0; i < bb.length; i++) + bb[i] = i*i +print(str(bb)) + +var CharBuffer = Java.type("java.nio.CharBuffer") +var cb = CharBuffer.wrap("hello world") +print(str(cb)) + +var RandomAccessFile = Java.type("java.io.RandomAccessFile") +var raf = new RandomAccessFile("buffer_index.js", "r") +var chan = raf.getChannel() +var fileSize = chan.size() +var buf = ByteBuffer.allocate(fileSize) +chan.read(buf) +chan.close() + +var str = '' +for (var i = 0; i < buf.length; i++) + str += String.fromCharCode(buf[i]) +print(str) diff --git a/nashorn/samples/dynalink/buffer_indexing_linker.js b/nashorn/samples/dynalink/buffer_indexing_linker.js new file mode 100644 index 00000000000..669cf9bf871 --- /dev/null +++ b/nashorn/samples/dynalink/buffer_indexing_linker.js @@ -0,0 +1,49 @@ +# buffer indexing linker example + +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// This script assumes you've built jdk9 or using latest +// jdk9 image and put the 'bin' directory in the PATH + +$EXEC.throwOnError=true + +// compile BufferIndexingLinkerExporter +`javac -cp ../../dist/nashorn.jar BufferIndexingLinkerExporter.java` + +// make a jar file out of pluggable linker +`jar cvf buffer_indexing_linker.jar BufferIndexingLinkerExporter*.class META-INF/` + +// run a sample script that uses pluggable linker +// but make sure classpath points to the pluggable linker jar! + +`jjs -cp buffer_indexing_linker.jar buffer_index.js` +print($OUT) diff --git a/nashorn/samples/dom_linker.js b/nashorn/samples/dynalink/dom_linker.js similarity index 97% rename from nashorn/samples/dom_linker.js rename to nashorn/samples/dynalink/dom_linker.js index 70f5745621a..6bc0318982e 100644 --- a/nashorn/samples/dom_linker.js +++ b/nashorn/samples/dynalink/dom_linker.js @@ -37,7 +37,7 @@ $EXEC.throwOnError=true // compile DOMLinkerExporter -`javac -cp ../dist/nashorn.jar DOMLinkerExporter.java` +`javac -cp ../../dist/nashorn.jar DOMLinkerExporter.java` // make a jar file out of pluggable linker `jar cvf dom_linker.jar DOMLinkerExporter*.class META-INF/` diff --git a/nashorn/samples/dom_linker_gutenberg.js b/nashorn/samples/dynalink/dom_linker_gutenberg.js similarity index 100% rename from nashorn/samples/dom_linker_gutenberg.js rename to nashorn/samples/dynalink/dom_linker_gutenberg.js diff --git a/nashorn/samples/missing_method.js b/nashorn/samples/dynalink/missing_method.js similarity index 100% rename from nashorn/samples/missing_method.js rename to nashorn/samples/dynalink/missing_method.js diff --git a/nashorn/samples/missing_method_linker.js b/nashorn/samples/dynalink/missing_method_linker.js similarity index 94% rename from nashorn/samples/missing_method_linker.js rename to nashorn/samples/dynalink/missing_method_linker.js index 2a22fa4d7d9..81f6124d0f3 100644 --- a/nashorn/samples/missing_method_linker.js +++ b/nashorn/samples/dynalink/missing_method_linker.js @@ -37,7 +37,7 @@ $EXEC.throwOnError=true // compile MissingMethodLinkerExporter -`javac -cp ../dist/nashorn.jar MissingMethodLinkerExporter.java MissingMethodHandler.java MissingMethodExample.java` +`javac -cp ../../dist/nashorn.jar MissingMethodLinkerExporter.java MissingMethodHandler.java MissingMethodExample.java` // make a jar file out of pluggable linker `jar cvf missing_method_linker.jar MissingMethod*.class META-INF/` diff --git a/nashorn/samples/underscore.js b/nashorn/samples/dynalink/underscore.js similarity index 100% rename from nashorn/samples/underscore.js rename to nashorn/samples/dynalink/underscore.js diff --git a/nashorn/samples/underscore_linker.js b/nashorn/samples/dynalink/underscore_linker.js similarity index 96% rename from nashorn/samples/underscore_linker.js rename to nashorn/samples/dynalink/underscore_linker.js index 0204a391346..98acd9e3fdb 100644 --- a/nashorn/samples/underscore_linker.js +++ b/nashorn/samples/dynalink/underscore_linker.js @@ -37,7 +37,7 @@ $EXEC.throwOnError=true // compile UnderscoreNameLinkerExporter -`javac -cp ../dist/nashorn.jar UnderscoreNameLinkerExporter.java` +`javac -cp ../../dist/nashorn.jar UnderscoreNameLinkerExporter.java` // make a jar file out of pluggable linker `jar cvf underscore_linker.jar UnderscoreNameLinkerExporter*.class META-INF/` diff --git a/nashorn/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/PackagesHelper.java b/nashorn/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/PackagesHelper.java index a726edc7063..8ab02b03929 100644 --- a/nashorn/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/PackagesHelper.java +++ b/nashorn/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/PackagesHelper.java @@ -27,6 +27,12 @@ package jdk.nashorn.tools.jjs; import java.io.IOException; import java.io.File; +import java.net.URI; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; import java.util.EnumSet; @@ -58,16 +64,17 @@ final class PackagesHelper { } /** - * Is Java package properties helper available? + * Is javac available? * - * @return true if package properties support is available + * @return true if javac is available */ - static boolean isAvailable() { + private static boolean isJavacAvailable() { return compiler != null; } private final StandardJavaFileManager fm; private final Set fileKinds; + private final FileSystem jrtfs; /** * Construct a new PackagesHelper. @@ -75,16 +82,23 @@ final class PackagesHelper { * @param classPath Class path to compute properties of java package objects */ PackagesHelper(final String classPath) throws IOException { - assert isAvailable() : "no java compiler found!"; + if (isJavacAvailable()) { + fm = compiler.getStandardFileManager(null, null, null); + fileKinds = EnumSet.of(JavaFileObject.Kind.CLASS); - fm = compiler.getStandardFileManager(null, null, null); - fileKinds = EnumSet.of(JavaFileObject.Kind.CLASS); - - if (classPath != null && !classPath.isEmpty()) { - fm.setLocation(StandardLocation.CLASS_PATH, getFiles(classPath)); + if (classPath != null && !classPath.isEmpty()) { + fm.setLocation(StandardLocation.CLASS_PATH, getFiles(classPath)); + } else { + // no classpath set. Make sure that it is empty and not any default like "." + fm.setLocation(StandardLocation.CLASS_PATH, Collections.emptyList()); + } + jrtfs = null; } else { - // no classpath set. Make sure that it is empty and not any default like "." - fm.setLocation(StandardLocation.CLASS_PATH, Collections.emptyList()); + // javac is not available - directly use jrt fs + // to support at least platform classes. + fm = null; + fileKinds = null; + jrtfs = FileSystems.getFileSystem(URI.create("jrt:/")); } } @@ -127,13 +141,41 @@ final class PackagesHelper { } public void close() throws IOException { - fm.close(); + if (fm != null) { + fm.close(); + } } private Set listPackage(final String pkg) throws IOException { final Set props = new HashSet<>(); - listPackage(StandardLocation.PLATFORM_CLASS_PATH, pkg, props); - listPackage(StandardLocation.CLASS_PATH, pkg, props); + if (fm != null) { + listPackage(StandardLocation.PLATFORM_CLASS_PATH, pkg, props); + listPackage(StandardLocation.CLASS_PATH, pkg, props); + } else if (jrtfs != null) { + // look for the /packages/ directory + Path pkgDir = jrtfs.getPath("/packages/" + pkg); + if (Files.exists(pkgDir)) { + String pkgSlashName = pkg.replace('.', '/'); + try (DirectoryStream ds = Files.newDirectoryStream(pkgDir)) { + // it has module links under which this package occurs + for (Path mod : ds) { + // get the package directory under /modules + Path pkgUnderMod = jrtfs.getPath(mod.toString() + "/" + pkgSlashName); + try (DirectoryStream ds2 = Files.newDirectoryStream(pkgUnderMod)) { + for (Path p : ds2) { + String str = p.getFileName().toString(); + // get rid of ".class", if any + if (str.endsWith(".class")) { + props.add(str.substring(0, str.length() - ".class".length())); + } else { + props.add(str); + } + } + } + } + } + } + } return props; } diff --git a/nashorn/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/PropertiesHelper.java b/nashorn/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/PropertiesHelper.java index c37e1f46fc1..16283a27d64 100644 --- a/nashorn/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/PropertiesHelper.java +++ b/nashorn/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/PropertiesHelper.java @@ -54,15 +54,13 @@ final class PropertiesHelper { * @param classPath Class path to compute properties of java package objects */ PropertiesHelper(final String classPath) { - if (PackagesHelper.isAvailable()) { - try { - this.pkgsHelper = new PackagesHelper(classPath); - } catch (final IOException exp) { - if (Main.DEBUG) { - exp.printStackTrace(); - } - this.pkgsHelper = null; + try { + this.pkgsHelper = new PackagesHelper(classPath); + } catch (final IOException exp) { + if (Main.DEBUG) { + exp.printStackTrace(); } + this.pkgsHelper = null; } } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java index e70d830756b..cbc4d2eae7f 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java @@ -1300,7 +1300,16 @@ public final class Context { * @return context */ static Context fromClass(final Class clazz) { - final ClassLoader loader = clazz.getClassLoader(); + ClassLoader loader = null; + try { + loader = clazz.getClassLoader(); + } catch (SecurityException ignored) { + // This could fail because of anonymous classes being used. + // Accessing loader of anonymous class fails (for extension + // loader class too?). In any case, for us fetching Context + // from class loader is just an optimization. We can always + // get Context from thread local storage (below). + } if (loader instanceof ScriptLoader) { return ((ScriptLoader)loader).getContext(); diff --git a/test/lib/sun/hotspot/WhiteBox.java b/test/lib/sun/hotspot/WhiteBox.java index 93c24705b7e..02a4c562993 100644 --- a/test/lib/sun/hotspot/WhiteBox.java +++ b/test/lib/sun/hotspot/WhiteBox.java @@ -32,6 +32,7 @@ import java.util.function.BiFunction; import java.util.function.Function; import java.security.BasicPermission; import java.util.Objects; +import jdk.internal.HotSpotIntrinsicCandidate; import sun.hotspot.parser.DiagnosticCommand; @@ -170,6 +171,9 @@ public class WhiteBox { public native boolean shouldPrintAssembly(Executable method); public native int deoptimizeFrames(boolean makeNotEntrant); public native void deoptimizeAll(); + + @HotSpotIntrinsicCandidate + public void deoptimize() {} public boolean isMethodCompiled(Executable method) { return isMethodCompiled(method, false /*not osr*/); } @@ -304,6 +308,8 @@ public class WhiteBox { } public native Object[] getCodeBlob(long addr); + public native void clearInlineCaches(); + // Intered strings public native boolean isInStringTable(String str);