diff --git a/.hgtags-top-repo b/.hgtags-top-repo index e13ddc6f1e06809433814f975aeb59b4f78ea93c..06edc4a1f530a63a0b8fcaa8571f81f4c472a702 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -357,3 +357,4 @@ f900d5afd9c83a0df8f36161c27c5e4c86a66f4c jdk-9+111 03543a758cd5890f2266e4b9678378a925dde22a jdk-9+112 55b6d550828d1223b364e6ead4a56e56411c56df jdk-9+113 1d992540870ff33fe6cc550443388588df9b9e4f jdk-9+114 +09617ce980b99d49abfd54dacfed353c47e2a115 jdk-9+115 diff --git a/common/autoconf/basics.m4 b/common/autoconf/basics.m4 index 753d170beb273a2d5bbb318dba524c1f5c846251..f295a46d3c413e992e35b6378e18ec2b9326dc7b 100644 --- a/common/autoconf/basics.m4 +++ b/common/autoconf/basics.m4 @@ -749,8 +749,8 @@ AC_DEFUN_ONCE([BASIC_SETUP_DEVKIT], BASIC_PREPEND_TO_PATH([PATH],$EXTRA_PATH) if test "x$OPENJDK_BUILD_OS" = "xsolaris"; then - # Add extra search paths on solaris for utilities like ar and as etc... - PATH="$PATH:/usr/ccs/bin:/usr/sfw/bin:/opt/csw/bin" + # Add extra search paths on solaris for utilities like ar, as, dtrace etc... + PATH="$PATH:/usr/ccs/bin:/usr/sfw/bin:/opt/csw/bin:/usr/sbin" fi AC_MSG_CHECKING([for sysroot]) @@ -777,7 +777,7 @@ AC_DEFUN_ONCE([BASIC_SETUP_OUTPUT_DIR], # Create a default ./build/target-variant-debuglevel output root. if test "x${CONF_NAME}" = x; then AC_MSG_RESULT([in default location]) - CONF_NAME="${OPENJDK_TARGET_OS}-${OPENJDK_TARGET_CPU}-${JDK_VARIANT}-${ANDED_JVM_VARIANTS}-${DEBUG_LEVEL}" + CONF_NAME="${OPENJDK_TARGET_OS}-${OPENJDK_TARGET_CPU}-${JDK_VARIANT}-${JVM_VARIANTS_WITH_AND}-${DEBUG_LEVEL}" else AC_MSG_RESULT([in build directory with custom name]) fi @@ -1037,6 +1037,7 @@ AC_DEFUN_ONCE([BASIC_SETUP_COMPLEX_TOOLS], BASIC_PATH_PROGS(HG, hg) BASIC_PATH_PROGS(STAT, stat) BASIC_PATH_PROGS(TIME, time) + BASIC_PATH_PROGS(DTRACE, dtrace) BASIC_PATH_PROGS(PATCH, [gpatch patch]) # Check if it's GNU time IS_GNU_TIME=`$TIME --version 2>&1 | $GREP 'GNU time'` diff --git a/common/autoconf/build-performance.m4 b/common/autoconf/build-performance.m4 index 06348d0da0045be6511ab648acaaee6e9c154f49..04944aec383ec870f6b027ef0f11a3e870add33d 100644 --- a/common/autoconf/build-performance.m4 +++ b/common/autoconf/build-performance.m4 @@ -364,6 +364,9 @@ AC_DEFUN_ONCE([BPERF_SETUP_PRECOMPILED_HEADERS], elif test "x$ICECC" != "x"; then AC_MSG_RESULT([no, does not work effectively with icecc]) USE_PRECOMPILED_HEADER=0 + elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then + AC_MSG_RESULT([no, does not work with Solaris Studio]) + USE_PRECOMPILED_HEADER=0 else AC_MSG_RESULT([yes]) fi diff --git a/common/autoconf/buildjdk-spec.gmk.in b/common/autoconf/buildjdk-spec.gmk.in index f92602edc346fd23e39df98335a2b070439a6b62..89167a388fb3063fce1ae965791fcfceef1e5eed 100644 --- a/common/autoconf/buildjdk-spec.gmk.in +++ b/common/autoconf/buildjdk-spec.gmk.in @@ -57,6 +57,12 @@ OPENJDK_TARGET_CPU_BITS := @OPENJDK_BUILD_CPU_BITS@ OPENJDK_TARGET_CPU_ENDIAN := @OPENJDK_BUILD_CPU_ENDIAN@ OPENJDK_TARGET_CPU_LEGACY := @OPENJDK_BUILD_CPU_LEGACY@ +HOTSPOT_TARGET_OS := @HOTSPOT_BUILD_OS@ +HOTSPOT_TARGET_OS_TYPE := @HOTSPOT_BUILD_OS_TYPE@ +HOTSPOT_TARGET_CPU := @HOTSPOT_BUILD_CPU@ +HOTSPOT_TARGET_CPU_ARCH := @HOTSPOT_BUILD_CPU_ARCH@ +HOTSPOT_TARGET_CPU_DEFINE := @HOTSPOT_BUILD_CPU_DEFINE@ + CFLAGS_JDKLIB := @OPENJDK_BUILD_CFLAGS_JDKLIB@ CXXFLAGS_JDKLIB := @OPENJDK_BUILD_CXXFLAGS_JDKLIB@ LDFLAGS_JDKLIB := @OPENJDK_BUILD_LDFLAGS_JDKLIB@ @@ -65,6 +71,11 @@ CXXFLAGS_JDKEXE := @OPENJDK_BUILD_CXXFLAGS_JDKEXE@ LDFLAGS_JDKEXE := @OPENJDK_BUILD_LDFLAGS_JDKEXE@ OPENJDK_TARGET_CPU_JLI_CFLAGS := @OPENJDK_BUILD_CPU_JLI_CFLAGS@ +JVM_CFLAGS := @OPENJDK_BUILD_JVM_CFLAGS@ +JVM_LDFLAGS := @OPENJDK_BUILD_JVM_LDFLAGS@ +JVM_ASFLAGS := @OPENJDK_BUILD_JVM_ASFLAGS@ +JVM_LIBS := @OPENJDK_BUILD_JVM_LIBS@ + # The compiler for the build platform is likely not warning compatible with the official # compiler. WARNINGS_AS_ERRORS := false diff --git a/common/autoconf/compare.sh.in b/common/autoconf/compare.sh.in index 67a69ff73bda32b0619e226ebdc7351436a21e4d..a6cc8d65abcb15c7ae43a3895e703bae7a3d8ecf 100644 --- a/common/autoconf/compare.sh.in +++ b/common/autoconf/compare.sh.in @@ -31,7 +31,7 @@ export LEGACY_BUILD_DIR=@OPENJDK_TARGET_OS@-@OPENJDK_TARGET_CPU_LEGACY@ -export OPENJDK_TARGET_OS="@OPENJDK_TARGET_OS@" +sexport OPENJDK_TARGET_OS="@OPENJDK_TARGET_OS@" export OPENJDK_TARGET_CPU="@OPENJDK_TARGET_CPU@" export OPENJDK_TARGET_CPU_LIBDIR="@OPENJDK_TARGET_CPU_LIBDIR@" export DEBUG_LEVEL="@DEBUG_LEVEL@" diff --git a/common/autoconf/configure b/common/autoconf/configure index 6815da9a3b1fdddd563b46f36715a82ef9c4b419..547cb33fbc850bfb968d6a66ea32f61f3c5dd5ad 100644 --- a/common/autoconf/configure +++ b/common/autoconf/configure @@ -283,7 +283,7 @@ Additional (non-autoconf) OpenJDK Options: EOT - # Print additional help, e.g. a list of toolchains. + # Print additional help, e.g. a list of toolchains and JVM features. # This must be done by the autoconf script. ( CONFIGURE_PRINT_ADDITIONAL_HELP=true . $conf_script_to_run PRINTF=printf ) diff --git a/common/autoconf/configure.ac b/common/autoconf/configure.ac index 1f0c414e1029cb30e9d6a019acb5226424344543..291851f8d1087f646582af099cbde4e7e33be5bc 100644 --- a/common/autoconf/configure.ac +++ b/common/autoconf/configure.ac @@ -95,10 +95,8 @@ JDKOPT_SETUP_OPEN_OR_CUSTOM # These are needed to be able to create a configuration name (and thus the output directory) JDKOPT_SETUP_JDK_VARIANT -HOTSPOT_SETUP_JVM_INTERPRETER -HOTSPOT_SETUP_JVM_VARIANTS JDKOPT_SETUP_DEBUG_LEVEL -HOTSPOT_SETUP_DEBUG_LEVEL +HOTSPOT_SETUP_JVM_VARIANTS # With basic setup done, call the custom early hook. CUSTOM_EARLY_HOOK @@ -135,7 +133,6 @@ BASIC_SETUP_DEFAULT_MAKE_TARGET # We need build & target for this. JDKOPT_SETUP_JDK_OPTIONS JDKOPT_SETUP_JLINK_OPTIONS -HOTSPOT_SETUP_HOTSPOT_OPTIONS JDKVER_SETUP_JDK_VERSION_NUMBERS ############################################################################### @@ -207,6 +204,10 @@ FLAGS_SETUP_COMPILER_FLAGS_MISC JDKOPT_SETUP_DEBUG_SYMBOLS JDKOPT_SETUP_CODE_COVERAGE +# Need toolchain to setup dtrace +HOTSPOT_SETUP_DTRACE +HOTSPOT_SETUP_JVM_FEATURES + ############################################################################### # # Check dependencies for external and internal libraries. @@ -225,7 +226,7 @@ LIB_SETUP_LIBRARIES # ############################################################################### -HOTSPOT_SETUP_BUILD_TWEAKS +HOTSPOT_SETUP_LEGACY_BUILD JDKOPT_DETECT_INTREE_EC JDKOPT_ENABLE_DISABLE_FAILURE_HANDLER @@ -268,6 +269,9 @@ BASIC_TEST_USABILITY_ISSUES # At the end, call the custom hook. (Dummy macro if no custom sources available) CUSTOM_LATE_HOOK +# This needs to be done after CUSTOM_LATE_HOOK since we can setup custom features. +HOTSPOT_VALIDATE_JVM_FEATURES + # We're messing a bit with internal autoconf variables to put the config.status # in the output directory instead of the current directory. CONFIG_STATUS="$CONFIGURESUPPORT_OUTPUTDIR/config.status" diff --git a/common/autoconf/flags.m4 b/common/autoconf/flags.m4 index b738ef49e22032076fc5f71de0c3368b7e1eb152..7789f01450e607ebe1ee4b178342b4033b1ef3db 100644 --- a/common/autoconf/flags.m4 +++ b/common/autoconf/flags.m4 @@ -61,6 +61,10 @@ AC_DEFUN_ONCE([FLAGS_SETUP_USER_SUPPLIED_FLAGS], AC_SUBST(LEGACY_EXTRA_CXXFLAGS) AC_SUBST(LEGACY_EXTRA_LDFLAGS) + AC_SUBST(EXTRA_CFLAGS) + AC_SUBST(EXTRA_CXXFLAGS) + AC_SUBST(EXTRA_LDFLAGS) + # The global CFLAGS and LDLAGS variables are used by configure tests and # should include the extra parameters CFLAGS="$EXTRA_CFLAGS" @@ -211,8 +215,10 @@ AC_DEFUN_ONCE([FLAGS_SETUP_INIT_FLAGS], # On Windows, we need to set RC flags. if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then RC_FLAGS="-nologo -l0x409" + JVM_RCFLAGS="-nologo" if test "x$DEBUG_LEVEL" = xrelease; then RC_FLAGS="$RC_FLAGS -DNDEBUG" + JVM_RCFLAGS="$JVM_RCFLAGS -DNDEBUG" fi # The version variables used to create RC_FLAGS may be overridden @@ -228,8 +234,19 @@ AC_DEFUN_ONCE([FLAGS_SETUP_INIT_FLAGS], -D\"JDK_COPYRIGHT=Copyright \xA9 $COPYRIGHT_YEAR\" \ -D\"JDK_NAME=\$(PRODUCT_NAME) \$(JDK_RC_PLATFORM_NAME) \$(VERSION_MAJOR)\" \ -D\"JDK_FVER=\$(subst .,\$(COMMA),\$(VERSION_NUMBER_FOUR_POSITIONS))\"" + + JVM_RCFLAGS="$JVM_RCFLAGS \ + -D\"HS_BUILD_ID=\$(VERSION_STRING)\" \ + -D\"HS_COMPANY=\$(COMPANY_NAME)\" \ + -D\"JDK_DOTVER=\$(VERSION_NUMBER_FOUR_POSITIONS)\" \ + -D\"HS_COPYRIGHT=Copyright $COPYRIGHT_YEAR\" \ + -D\"HS_NAME=\$(PRODUCT_NAME) \$(VERSION_SHORT)\" \ + -D\"JDK_VER=\$(subst .,\$(COMMA),\$(VERSION_NUMBER_FOUR_POSITIONS))\" \ + -D\"HS_FNAME=jvm.dll\" \ + -D\"HS_INTERNAL_NAME=jvm\"" fi AC_SUBST(RC_FLAGS) + AC_SUBST(JVM_RCFLAGS) if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then # silence copyright notice and other headers. @@ -237,7 +254,7 @@ AC_DEFUN_ONCE([FLAGS_SETUP_INIT_FLAGS], fi ]) -AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_LIBS], +AC_DEFUN([FLAGS_SETUP_COMPILER_FLAGS_FOR_LIBS], [ ############################################################################### # @@ -255,6 +272,7 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_LIBS], SHARED_LIBRARY_FLAGS ='-undefined dynamic_lookup' else SHARED_LIBRARY_FLAGS="-dynamiclib -compatibility_version 1.0.0 -current_version 1.0.0 $PICFLAG" + JVM_CFLAGS="$JVM_CFLAGS $PICFLAG" fi SET_EXECUTABLE_ORIGIN='-Wl,-rpath,@loader_path/.' SET_SHARED_LIBRARY_ORIGIN="$SET_EXECUTABLE_ORIGIN" @@ -280,6 +298,10 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_LIBS], SET_SHARED_LIBRARY_ORIGIN="$SET_EXECUTABLE_ORIGIN" SET_SHARED_LIBRARY_NAME='-Wl,-install_name,@rpath/[$]1' SET_SHARED_LIBRARY_MAPFILE='-Wl,-exported_symbols_list,[$]1' + + if test "x$STATIC_BUILD" = xfalse; then + JVM_CFLAGS="$JVM_CFLAGS -fPIC" + fi else # Default works for linux, might work on other platforms as well. PICFLAG='-fPIC' @@ -339,11 +361,6 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_LIBS], AC_SUBST(SET_SHARED_LIBRARY_MAPFILE) AC_SUBST(SHARED_LIBRARY_FLAGS) - if test "x$OPENJDK_TARGET_OS" = xsolaris; then - CFLAGS_JDK="${CFLAGS_JDK} -D__solaris__" - CXXFLAGS_JDK="${CXXFLAGS_JDK} -D__solaris__" - CFLAGS_JDKLIB_EXTRA='-xstrconst' - fi # The (cross) compiler is now configured, we can now test capabilities # of the target platform. ]) @@ -434,6 +451,22 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_OPTIMIZATION], AC_SUBST(CFLAGS_DEBUG_SYMBOLS) AC_SUBST(CXXFLAGS_DEBUG_SYMBOLS) + # Debug symbols for JVM_CFLAGS + if test "x$TOOLCHAIN_TYPE" = xsolstudio; then + JVM_CFLAGS_SYMBOLS="$JVM_CFLAGS_SYMBOLS -xs" + if test "x$DEBUG_LEVEL" = xslowdebug; then + JVM_CFLAGS_SYMBOLS="$JVM_CFLAGS_SYMBOLS -g" + else + # -g0 does not disable inlining, which -g does. + JVM_CFLAGS_SYMBOLS="$JVM_CFLAGS_SYMBOLS -g0" + fi + elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + JVM_CFLAGS_SYMBOLS="$JVM_CFLAGS_SYMBOLS -Z7 -d2Zi+" + else + JVM_CFLAGS_SYMBOLS="$JVM_CFLAGS_SYMBOLS -g" + fi + AC_SUBST(JVM_CFLAGS_SYMBOLS) + # bounds, memory and behavior checking options if test "x$TOOLCHAIN_TYPE" = xgcc; then case $DEBUG_LEVEL in @@ -444,7 +477,7 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_OPTIMIZATION], # no adjustment ;; slowdebug ) - # FIXME: By adding this to C(XX)FLAGS_DEBUG_OPTIONS it + # FIXME: By adding this to C(XX)FLAGS_DEBUG_OPTIONS/JVM_CFLAGS_SYMBOLS it # get's added conditionally on whether we produce debug symbols or not. # This is most likely not really correct. @@ -455,40 +488,59 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_OPTIMIZATION], CFLAGS_DEBUG_OPTIONS="$STACK_PROTECTOR_CFLAG --param ssp-buffer-size=1" CXXFLAGS_DEBUG_OPTIONS="$STACK_PROTECTOR_CFLAG --param ssp-buffer-size=1" + if test "x$STACK_PROTECTOR_CFLAG" != x; then + JVM_CFLAGS_SYMBOLS="$JVM_CFLAGS_SYMBOLS $STACK_PROTECTOR_CFLAG --param ssp-buffer-size=1" + fi ;; esac fi + if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + if test "x$DEBUG_LEVEL" != xrelease; then + if test "x$OPENJDK_TARGET_CPU" = xx86_64; then + JVM_CFLAGS="$JVM_CFLAGS -homeparams" + fi + fi + fi + # Optimization levels if test "x$TOOLCHAIN_TYPE" = xsolstudio; then CC_HIGHEST="$CC_HIGHEST -fns -fsimple -fsingle -xbuiltin=%all -xdepend -xrestrict -xlibmil" if test "x$OPENJDK_TARGET_CPU_ARCH" = "xx86"; then # FIXME: seems we always set -xregs=no%frameptr; put it elsewhere more global? + C_O_FLAG_HIGHEST_JVM="-xO4" C_O_FLAG_HIGHEST="-xO4 -Wu,-O4~yz $CC_HIGHEST -xalias_level=basic -xregs=no%frameptr" C_O_FLAG_HI="-xO4 -Wu,-O4~yz -xregs=no%frameptr" C_O_FLAG_NORM="-xO2 -Wu,-O2~yz -xregs=no%frameptr" C_O_FLAG_DEBUG="-xregs=no%frameptr" + C_O_FLAG_DEBUG_JVM="" C_O_FLAG_NONE="-xregs=no%frameptr" + CXX_O_FLAG_HIGHEST_JVM="-xO4" CXX_O_FLAG_HIGHEST="-xO4 -Qoption ube -O4~yz $CC_HIGHEST -xregs=no%frameptr" CXX_O_FLAG_HI="-xO4 -Qoption ube -O4~yz -xregs=no%frameptr" CXX_O_FLAG_NORM="-xO2 -Qoption ube -O2~yz -xregs=no%frameptr" CXX_O_FLAG_DEBUG="-xregs=no%frameptr" + CXX_O_FLAG_DEBUG_JVM="" CXX_O_FLAG_NONE="-xregs=no%frameptr" if test "x$OPENJDK_TARGET_CPU_BITS" = "x32"; then C_O_FLAG_HIGHEST="$C_O_FLAG_HIGHEST -xchip=pentium" CXX_O_FLAG_HIGHEST="$CXX_O_FLAG_HIGHEST -xchip=pentium" fi elif test "x$OPENJDK_TARGET_CPU_ARCH" = "xsparc"; then + C_O_FLAG_HIGHEST_JVM="-xO4" C_O_FLAG_HIGHEST="-xO4 -Wc,-Qrm-s -Wc,-Qiselect-T0 $CC_HIGHEST -xalias_level=basic -xprefetch=auto,explicit -xchip=ultra" C_O_FLAG_HI="-xO4 -Wc,-Qrm-s -Wc,-Qiselect-T0" C_O_FLAG_NORM="-xO2 -Wc,-Qrm-s -Wc,-Qiselect-T0" C_O_FLAG_DEBUG="" + C_O_FLAG_DEBUG_JVM="" C_O_FLAG_NONE="" + CXX_O_FLAG_HIGHEST_JVM="-xO4" CXX_O_FLAG_HIGHEST="-xO4 -Qoption cg -Qrm-s -Qoption cg -Qiselect-T0 $CC_HIGHEST -xprefetch=auto,explicit -xchip=ultra" CXX_O_FLAG_HI="-xO4 -Qoption cg -Qrm-s -Qoption cg -Qiselect-T0" CXX_O_FLAG_NORM="-xO2 -Qoption cg -Qrm-s -Qoption cg -Qiselect-T0" CXX_O_FLAG_DEBUG="" + CXX_O_FLAG_DEBUG_JVM="" CXX_O_FLAG_NONE="" fi else @@ -498,48 +550,75 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_OPTIMIZATION], if test "x$OPENJDK_TARGET_OS" = xmacosx; then # On MacOSX we optimize for size, something # we should do for all platforms? + C_O_FLAG_HIGHEST_JVM="-Os" C_O_FLAG_HIGHEST="-Os" C_O_FLAG_HI="-Os" C_O_FLAG_NORM="-Os" + C_O_FLAG_SIZE="-Os" else + C_O_FLAG_HIGHEST_JVM="-O3" C_O_FLAG_HIGHEST="-O3" C_O_FLAG_HI="-O3" C_O_FLAG_NORM="-O2" + C_O_FLAG_SIZE="-Os" fi C_O_FLAG_DEBUG="-O0" + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + C_O_FLAG_DEBUG_JVM="" + elif test "x$OPENJDK_TARGET_OS" = xlinux; then + C_O_FLAG_DEBUG_JVM="-O0" + fi C_O_FLAG_NONE="-O0" elif test "x$TOOLCHAIN_TYPE" = xclang; then if test "x$OPENJDK_TARGET_OS" = xmacosx; then # On MacOSX we optimize for size, something # we should do for all platforms? + C_O_FLAG_HIGHEST_JVM="-Os" C_O_FLAG_HIGHEST="-Os" C_O_FLAG_HI="-Os" C_O_FLAG_NORM="-Os" + C_O_FLAG_SIZE="-Os" else + C_O_FLAG_HIGHEST_JVM="-O3" C_O_FLAG_HIGHEST="-O3" C_O_FLAG_HI="-O3" C_O_FLAG_NORM="-O2" + C_O_FLAG_SIZE="-Os" fi C_O_FLAG_DEBUG="-O0" + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + C_O_FLAG_DEBUG_JVM="" + elif test "x$OPENJDK_TARGET_OS" = xlinux; then + C_O_FLAG_DEBUG_JVM="-O0" + fi C_O_FLAG_NONE="-O0" elif test "x$TOOLCHAIN_TYPE" = xxlc; then + C_O_FLAG_HIGHEST_JVM="-O3" C_O_FLAG_HIGHEST="-O3" C_O_FLAG_HI="-O3 -qstrict" C_O_FLAG_NORM="-O2" C_O_FLAG_DEBUG="-qnoopt" + # FIXME: Value below not verified. + C_O_FLAG_DEBUG_JVM="" C_O_FLAG_NONE="-qnoopt" elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + C_O_FLAG_HIGHEST_JVM="-O2 -Oy-" C_O_FLAG_HIGHEST="-O2" C_O_FLAG_HI="-O1" C_O_FLAG_NORM="-O1" C_O_FLAG_DEBUG="-Od" + C_O_FLAG_DEBUG_JVM="" C_O_FLAG_NONE="-Od" + C_O_FLAG_SIZE="-Os" fi + CXX_O_FLAG_HIGHEST_JVM="$C_O_FLAG_HIGHEST_JVM" CXX_O_FLAG_HIGHEST="$C_O_FLAG_HIGHEST" CXX_O_FLAG_HI="$C_O_FLAG_HI" CXX_O_FLAG_NORM="$C_O_FLAG_NORM" CXX_O_FLAG_DEBUG="$C_O_FLAG_DEBUG" + CXX_O_FLAG_DEBUG_JVM="$C_O_FLAG_DEBUG_JVM" CXX_O_FLAG_NONE="$C_O_FLAG_NONE" + CXX_O_FLAG_SIZE="$C_O_FLAG_SIZE" fi # Adjust optimization flags according to debug level. @@ -554,51 +633,105 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_OPTIMIZATION], ;; slowdebug ) # Disable optimization + C_O_FLAG_HIGHEST_JVM="$C_O_FLAG_DEBUG_JVM" C_O_FLAG_HIGHEST="$C_O_FLAG_DEBUG" C_O_FLAG_HI="$C_O_FLAG_DEBUG" C_O_FLAG_NORM="$C_O_FLAG_DEBUG" + C_O_FLAG_SIZE="$C_O_FLAG_DEBUG" + CXX_O_FLAG_HIGHEST_JVM="$CXX_O_FLAG_DEBUG_JVM" CXX_O_FLAG_HIGHEST="$CXX_O_FLAG_DEBUG" CXX_O_FLAG_HI="$CXX_O_FLAG_DEBUG" CXX_O_FLAG_NORM="$CXX_O_FLAG_DEBUG" + CXX_O_FLAG_SIZE="$CXX_O_FLAG_DEBUG" ;; esac + AC_SUBST(C_O_FLAG_HIGHEST_JVM) AC_SUBST(C_O_FLAG_HIGHEST) AC_SUBST(C_O_FLAG_HI) AC_SUBST(C_O_FLAG_NORM) AC_SUBST(C_O_FLAG_DEBUG) AC_SUBST(C_O_FLAG_NONE) + AC_SUBST(C_O_FLAG_SIZE) + AC_SUBST(CXX_O_FLAG_HIGHEST_JVM) AC_SUBST(CXX_O_FLAG_HIGHEST) AC_SUBST(CXX_O_FLAG_HI) AC_SUBST(CXX_O_FLAG_NORM) AC_SUBST(CXX_O_FLAG_DEBUG) AC_SUBST(CXX_O_FLAG_NONE) + AC_SUBST(CXX_O_FLAG_SIZE) ]) -AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK], + +AC_DEFUN([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK], +[ + + FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK_HELPER([TARGET]) + FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK_HELPER([BUILD], [OPENJDK_BUILD_]) + + # Tests are only ever compiled for TARGET + # Flags for compiling test libraries + CFLAGS_TESTLIB="$COMMON_CCXXFLAGS_JDK $CFLAGS_JDK $PICFLAG $CFLAGS_JDKLIB_EXTRA" + CXXFLAGS_TESTLIB="$COMMON_CCXXFLAGS_JDK $CXXFLAGS_JDK $PICFLAG $CXXFLAGS_JDKLIB_EXTRA" + + # Flags for compiling test executables + CFLAGS_TESTEXE="$COMMON_CCXXFLAGS_JDK $CFLAGS_JDK" + CXXFLAGS_TESTEXE="$COMMON_CCXXFLAGS_JDK $CXXFLAGS_JDK" + + AC_SUBST(CFLAGS_TESTLIB) + AC_SUBST(CFLAGS_TESTEXE) + AC_SUBST(CXXFLAGS_TESTLIB) + AC_SUBST(CXXFLAGS_TESTEXE) + + LDFLAGS_TESTLIB="$LDFLAGS_JDKLIB" + LDFLAGS_TESTEXE="$LDFLAGS_JDKEXE" + + AC_SUBST(LDFLAGS_TESTLIB) + AC_SUBST(LDFLAGS_TESTEXE) + +]) + +################################################################################ +# $1 - Either BUILD or TARGET to pick the correct OS/CPU variables to check +# conditionals against. +# $2 - Optional prefix for each variable defined. +AC_DEFUN([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK_HELPER], [ # Special extras... if test "x$TOOLCHAIN_TYPE" = xsolstudio; then - if test "x$OPENJDK_TARGET_CPU_ARCH" = "xsparc"; then - CFLAGS_JDKLIB_EXTRA="${CFLAGS_JDKLIB_EXTRA} -xregs=no%appl" - CXXFLAGS_JDKLIB_EXTRA="${CXXFLAGS_JDKLIB_EXTRA} -xregs=no%appl" + if test "x$OPENJDK_$1_CPU_ARCH" = "xsparc"; then + $2CFLAGS_JDKLIB_EXTRA="${$2CFLAGS_JDKLIB_EXTRA} -xregs=no%appl" + $2CXXFLAGS_JDKLIB_EXTRA="${$2CXXFLAGS_JDKLIB_EXTRA} -xregs=no%appl" fi - CFLAGS_JDKLIB_EXTRA="${CFLAGS_JDKLIB_EXTRA} -errtags=yes -errfmt" - CXXFLAGS_JDKLIB_EXTRA="${CXXFLAGS_JDKLIB_EXTRA} -errtags=yes -errfmt" + $2CFLAGS_JDKLIB_EXTRA="${$2CFLAGS_JDKLIB_EXTRA} -errtags=yes -errfmt" + $2CXXFLAGS_JDKLIB_EXTRA="${$2CXXFLAGS_JDKLIB_EXTRA} -errtags=yes -errfmt" elif test "x$TOOLCHAIN_TYPE" = xxlc; then + $2CFLAGS_JDK="${$2CFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" + $2CXXFLAGS_JDK="${$2CXXFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" + elif test "x$TOOLCHAIN_TYPE" = xgcc; then + $2CXXSTD_CXXFLAG="-std=gnu++98" + FLAGS_CXX_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [[$]$2CXXSTD_CXXFLAG -Werror], + IF_FALSE: [$2CXXSTD_CXXFLAG=""]) + $2CXXFLAGS_JDK="${$2CXXFLAGS_JDK} ${$2CXXSTD_CXXFLAG}" + AC_SUBST([$2CXXSTD_CXXFLAG]) + fi + if test "x$OPENJDK_TARGET_OS" = xsolaris; then + $2CFLAGS_JDK="${$2CFLAGS_JDK} -D__solaris__" + $2CXXFLAGS_JDK="${$2CXXFLAGS_JDK} -D__solaris__" + $2CFLAGS_JDKLIB_EXTRA='-xstrconst' CFLAGS_JDK="${CFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" CXXFLAGS_JDK="${CXXFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" - elif test "x$TOOLCHAIN_TYPE" = xgcc; then - CXXSTD_CXXFLAG="-std=gnu++98" - FLAGS_CXX_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [$CXXSTD_CXXFLAG -Werror], - IF_FALSE: [CXXSTD_CXXFLAG=""]) - CXXFLAGS_JDK="${CXXFLAGS_JDK} ${CXXSTD_CXXFLAG}" - AC_SUBST([CXXSTD_CXXFLAG]) fi - CFLAGS_JDK="${CFLAGS_JDK} $EXTRA_CFLAGS" - CXXFLAGS_JDK="${CXXFLAGS_JDK} $EXTRA_CXXFLAGS" - LDFLAGS_JDK="${LDFLAGS_JDK} $EXTRA_LDFLAGS" + if test "x$OPENJDK_TARGET_OS" = xsolaris; then + $2CFLAGS_JDK="${$2CFLAGS_JDK} -D__solaris__" + $2CXXFLAGS_JDK="${$2CXXFLAGS_JDK} -D__solaris__" + $2CFLAGS_JDKLIB_EXTRA='-xstrconst' + fi + + $2CFLAGS_JDK="${$2CFLAGS_JDK} ${$2EXTRA_CFLAGS}" + $2CXXFLAGS_JDK="${$2CXXFLAGS_JDK} ${$2EXTRA_CXXFLAGS}" + $2LDFLAGS_JDK="${$2LDFLAGS_JDK} ${$2EXTRA_LDFLAGS}" ############################################################################### # @@ -607,79 +740,94 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK], # # Setup compiler/platform specific flags into - # CFLAGS_JDK - C Compiler flags - # CXXFLAGS_JDK - C++ Compiler flags - # COMMON_CCXXFLAGS_JDK - common to C and C++ + # $2CFLAGS_JDK - C Compiler flags + # $2CXXFLAGS_JDK - C++ Compiler flags + # $2COMMON_CCXXFLAGS_JDK - common to C and C++ if test "x$TOOLCHAIN_TYPE" = xgcc; then - if test "x$OPENJDK_TARGET_CPU" = xx86; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -D_GNU_SOURCE" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -D_REENTRANT" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -fcheck-new" + if test "x$OPENJDK_$1_CPU" = xx86; then # Force compatibility with i586 on 32 bit intel platforms. - COMMON_CCXXFLAGS="${COMMON_CCXXFLAGS} -march=i586" + $2COMMON_CCXXFLAGS="${$2COMMON_CCXXFLAGS} -march=i586" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -march=i586" fi - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS $COMMON_CCXXFLAGS_JDK -Wall -Wextra -Wno-unused -Wno-unused-parameter -Wformat=2 \ + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS [$]$2COMMON_CCXXFLAGS_JDK -Wall -Wextra -Wno-unused -Wno-unused-parameter -Wformat=2 \ -pipe -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE" - case $OPENJDK_TARGET_CPU_ARCH in + case $OPENJDK_$1_CPU_ARCH in arm ) # on arm we don't prevent gcc to omit frame pointer but do prevent strict aliasing - CFLAGS_JDK="${CFLAGS_JDK} -fno-strict-aliasing" + $2CFLAGS_JDK="${$2CFLAGS_JDK} -fno-strict-aliasing" ;; ppc ) # on ppc we don't prevent gcc to omit frame pointer but do prevent strict aliasing - CFLAGS_JDK="${CFLAGS_JDK} -fno-strict-aliasing" + $2CFLAGS_JDK="${$2CFLAGS_JDK} -fno-strict-aliasing" ;; * ) - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -fno-omit-frame-pointer" - CFLAGS_JDK="${CFLAGS_JDK} -fno-strict-aliasing" + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -fno-omit-frame-pointer" + $2CFLAGS_JDK="${$2CFLAGS_JDK} -fno-strict-aliasing" ;; esac TOOLCHAIN_CHECK_COMPILER_VERSION(VERSION: 6, IF_AT_LEAST: FLAGS_SETUP_GCC6_COMPILER_FLAGS) elif test "x$TOOLCHAIN_TYPE" = xclang; then - if test "x$OPENJDK_TARGET_OS" = xlinux; then - if test "x$OPENJDK_TARGET_CPU" = xx86; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -D_GNU_SOURCE" + + # Restrict the debug information created by Clang to avoid + # too big object files and speed the build up a little bit + # (see http://llvm.org/bugs/show_bug.cgi?id=7554) + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -flimit-debug-info" + if test "x$OPENJDK_$1_OS" = xlinux; then + if test "x$OPENJDK_$1_CPU" = xx86; then # Force compatibility with i586 on 32 bit intel platforms. - COMMON_CCXXFLAGS="${COMMON_CCXXFLAGS} -march=i586" + $2COMMON_CCXXFLAGS="${$2COMMON_CCXXFLAGS} -march=i586" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -march=i586" fi - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS $COMMON_CCXXFLAGS_JDK -Wall -Wextra -Wno-unused -Wno-unused-parameter -Wformat=2 \ + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -Wno-sometimes-uninitialized" + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS [$]$2COMMON_CCXXFLAGS_JDK -Wall -Wextra -Wno-unused -Wno-unused-parameter -Wformat=2 \ -pipe -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE" - case $OPENJDK_TARGET_CPU_ARCH in + case $OPENJDK_$1_CPU_ARCH in ppc ) # on ppc we don't prevent gcc to omit frame pointer but do prevent strict aliasing - CFLAGS_JDK="${CFLAGS_JDK} -fno-strict-aliasing" + $2CFLAGS_JDK="${$2CFLAGS_JDK} -fno-strict-aliasing" ;; * ) - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -fno-omit-frame-pointer" - CFLAGS_JDK="${CFLAGS_JDK} -fno-strict-aliasing" + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -fno-omit-frame-pointer" + $2CFLAGS_JDK="${$2CFLAGS_JDK} -fno-strict-aliasing" ;; esac fi elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS $COMMON_CCXXFLAGS_JDK -DTRACING -DMACRO_MEMSYS_OPS -DBREAKPTS" - if test "x$OPENJDK_TARGET_CPU_ARCH" = xx86; then - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -DcpuIntel -Di586 -D$OPENJDK_TARGET_CPU_LEGACY_LIB" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -DSPARC_WORKS" + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS [$]$2COMMON_CCXXFLAGS_JDK -DTRACING -DMACRO_MEMSYS_OPS -DBREAKPTS" + if test "x$OPENJDK_$1_CPU_ARCH" = xx86; then + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -DcpuIntel -Di586 -D$OPENJDK_$1_CPU_LEGACY_LIB" fi - CFLAGS_JDK="$CFLAGS_JDK -xc99=%none -xCC -errshort=tags -Xa -v -mt -W0,-noglobal" - CXXFLAGS_JDK="$CXXFLAGS_JDK -errtags=yes +w -mt -features=no%except -DCC_NOEX -norunpath -xnolib" + $2CFLAGS_JDK="[$]$2CFLAGS_JDK -xc99=%none -xCC -errshort=tags -Xa -v -mt -W0,-noglobal" + $2CXXFLAGS_JDK="[$]$2CXXFLAGS_JDK -errtags=yes +w -mt -features=no%except -DCC_NOEX -norunpath -xnolib" elif test "x$TOOLCHAIN_TYPE" = xxlc; then - CFLAGS_JDK="$CFLAGS_JDK -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC" - CXXFLAGS_JDK="$CXXFLAGS_JDK -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -D_REENTRANT -D__STDC_FORMAT_MACROS" + $2CFLAGS_JDK="[$]$2CFLAGS_JDK -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC" + $2CXXFLAGS_JDK="[$]$2CXXFLAGS_JDK -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC" elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS $COMMON_CCXXFLAGS_JDK \ + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS [$]$2COMMON_CCXXFLAGS_JDK \ -MD -Zc:wchar_t- -W3 -wd4800 \ -DWIN32_LEAN_AND_MEAN \ -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE \ -D_WINSOCK_DEPRECATED_NO_WARNINGS \ -DWIN32 -DIAL" - if test "x$OPENJDK_TARGET_CPU" = xx86_64; then - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D_AMD64_ -Damd64" + if test "x$OPENJDK_$1_CPU" = xx86_64; then + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -D_AMD64_ -Damd64" else - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D_X86_ -Dx86" + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -D_X86_ -Dx86" fi # If building with Visual Studio 2010, we can still use _STATIC_CPPLIB to # avoid bundling msvcpNNN.dll. Doesn't work with newer versions of visual # studio. if test "x$TOOLCHAIN_VERSION" = "x2010"; then STATIC_CPPLIB_FLAGS="-D_STATIC_CPPLIB -D_DISABLE_DEPRECATE_STATIC_CPPLIB" - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK $STATIC_CPPLIB_FLAGS" + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK $STATIC_CPPLIB_FLAGS" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS $STATIC_CPPLIB_FLAGS" fi fi @@ -688,8 +836,8 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK], # Adjust flags according to debug level. case $DEBUG_LEVEL in fastdebug | slowdebug ) - CFLAGS_JDK="$CFLAGS_JDK $CFLAGS_DEBUG_SYMBOLS $CFLAGS_DEBUG_OPTIONS" - CXXFLAGS_JDK="$CXXFLAGS_JDK $CXXFLAGS_DEBUG_SYMBOLS $CXXFLAGS_DEBUG_OPTIONS" + $2CFLAGS_JDK="[$]$2CFLAGS_JDK $CFLAGS_DEBUG_SYMBOLS $CFLAGS_DEBUG_OPTIONS" + $2CXXFLAGS_JDK="[$]$2CXXFLAGS_JDK $CXXFLAGS_DEBUG_SYMBOLS $CXXFLAGS_DEBUG_OPTIONS" JAVAC_FLAGS="$JAVAC_FLAGS -g" ;; release ) @@ -703,58 +851,142 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK], # -D is universally accepted. # Setup endianness - if test "x$OPENJDK_TARGET_CPU_ENDIAN" = xlittle; then + if test "x$OPENJDK_$1_CPU_ENDIAN" = xlittle; then # The macro _LITTLE_ENDIAN needs to be defined the same to avoid the # Sun C compiler warning message: warning: macro redefined: _LITTLE_ENDIAN # (The Solaris X86 system defines this in file /usr/include/sys/isa_defs.h). # Note: -Dmacro is the same as #define macro 1 # -Dmacro= is the same as #define macro - if test "x$OPENJDK_TARGET_OS" = xsolaris; then - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D_LITTLE_ENDIAN=" + if test "x$OPENJDK_$1_OS" = xsolaris; then + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -D_LITTLE_ENDIAN=" else - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D_LITTLE_ENDIAN" + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -D_LITTLE_ENDIAN" fi else # Same goes for _BIG_ENDIAN. Do we really need to set *ENDIAN on Solaris if they # are defined in the system? - if test "x$OPENJDK_TARGET_OS" = xsolaris; then - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D_BIG_ENDIAN=" + if test "x$OPENJDK_$1_OS" = xsolaris; then + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -D_BIG_ENDIAN=" else - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D_BIG_ENDIAN" + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -D_BIG_ENDIAN" fi fi # Setup target OS define. Use OS target name but in upper case. - OPENJDK_TARGET_OS_UPPERCASE=`$ECHO $OPENJDK_TARGET_OS | $TR 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D$OPENJDK_TARGET_OS_UPPERCASE" + OPENJDK_$1_OS_UPPERCASE=`$ECHO $OPENJDK_$1_OS | $TR 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -D$OPENJDK_$1_OS_UPPERCASE" # Setup target CPU - OPENJDK_TARGET_CCXXFLAGS_JDK="$OPENJDK_TARGET_CCXXFLAGS_JDK \ - $ADD_LP64 \ - -DARCH='\"$OPENJDK_TARGET_CPU_LEGACY\"' -D$OPENJDK_TARGET_CPU_LEGACY" - OPENJDK_BUILD_CCXXFLAGS_JDK="$OPENJDK_BUILD_CCXXFLAGS_JDK \ - $OPENJDK_BUILD_ADD_LP64 \ - -DARCH='\"$OPENJDK_BUILD_CPU_LEGACY\"' -D$OPENJDK_BUILD_CPU_LEGACY" + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK \ + $OPENJDK_$1_ADD_LP64 \ + -DARCH='\"$OPENJDK_$1_CPU_LEGACY\"' -D$OPENJDK_$1_CPU_LEGACY" # Setup debug/release defines if test "x$DEBUG_LEVEL" = xrelease; then - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -DNDEBUG" - if test "x$OPENJDK_TARGET_OS" = xsolaris; then - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -DTRIMMED" + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -DNDEBUG" + if test "x$OPENJDK_$1_OS" = xsolaris; then + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -DTRIMMED" fi else - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -DDEBUG" + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -DDEBUG" fi # Set some additional per-OS defines. - if test "x$OPENJDK_TARGET_OS" = xmacosx; then - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D_ALLBSD_SOURCE -D_DARWIN_UNLIMITED_SELECT" - elif test "x$OPENJDK_TARGET_OS" = xbsd; then - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D_ALLBSD_SOURCE" + if test "x$OPENJDK_$1_OS" = xlinux; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -DLINUX" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -pipe -fPIC -fno-rtti -fno-exceptions \ + -fvisibility=hidden -fno-strict-aliasing -fno-omit-frame-pointer" + elif test "x$OPENJDK_$1_OS" = xsolaris; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -DSOLARIS" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -template=no%extdef -features=no%split_init \ + -D_Crun_inline_placement -library=%none -KPIC -mt -xwe -features=no%except" + elif test "x$OPENJDK_$1_OS" = xmacosx; then + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -D_ALLBSD_SOURCE -D_DARWIN_UNLIMITED_SELECT" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -D_ALLBSD_SOURCE" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -D_DARWIN_C_SOURCE -D_XOPEN_SOURCE" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -fno-rtti -fno-exceptions -fvisibility=hidden \ + -mno-omit-leaf-frame-pointer -mstack-alignment=16 -pipe -fno-strict-aliasing \ + -DMAC_OS_X_VERSION_MAX_ALLOWED=1070 -mmacosx-version-min=10.7.0 \ + -fno-omit-frame-pointer" + elif test "x$OPENJDK_$1_OS" = xaix; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -DAIX" + # We may need '-qminimaltoc' or '-qpic=large -bbigtoc' if the TOC overflows. + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -qtune=balanced -qhot=level=1 -qinline \ + -qinlglue -qalias=noansi -qstrict -qtls=default -qlanglvl=c99vla \ + -qlanglvl=noredefmac -qnortti -qnoeh -qignerrno" + elif test "x$OPENJDK_$1_OS" = xbsd; then + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -D_ALLBSD_SOURCE" + elif test "x$OPENJDK_$1_OS" = xwindows; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -D_WINDOWS -DWIN32 -D_JNI_IMPLEMENTATION_" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -nologo -W3 -MD -MP" + fi + + # Set some additional per-CPU defines. + if test "x$OPENJDK_$1_OS-$OPENJDK_$1_CPU" = xwindows-x86; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -arch:IA32" + elif test "x$OPENJDK_$1_CPU" = xsparcv9; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -xarch=sparc" + elif test "x$OPENJDK_$1_CPU" = xppc64; then + if test "x$OPENJDK_$1_OS" = xlinux; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -minsert-sched-nops=regroup_exact -mno-multiple -mno-string" + # fixes `relocation truncated to fit' error for gcc 4.1. + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -mminimal-toc" + # Use ppc64 instructions, but schedule for power5 + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -mcpu=powerpc64 -mtune=power5" + elif test "x$OPENJDK_$1_OS" = xaix; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -qarch=ppc64" + fi + elif test "x$OPENJDK_$1_CPU" = xppc64le; then + if test "x$OPENJDK_$1_OS" = xlinux; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -minsert-sched-nops=regroup_exact -mno-multiple -mno-string" + # Little endian machine uses ELFv2 ABI. + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -DABI_ELFv2" + # Use Power8, this is the first CPU to support PPC64 LE with ELFv2 ABI. + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -mcpu=power7 -mtune=power8" + fi + fi + + if test "x$OPENJDK_$1_CPU_ENDIAN" = xlittle; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -DVM_LITTLE_ENDIAN" + fi + + if test "x$OPENJDK_$1_CPU_BITS" = x64; then + if test "x$OPENJDK_$1_OS" != xsolaris && test "x$OPENJDK_$1_OS" != xaix; then + # Solaris does not have _LP64=1 in the old build. + # xlc on AIX defines _LP64=1 by default and issues a warning if we redefine it. + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -D_LP64=1" + fi + fi + + # Set $2JVM_CFLAGS warning handling + if test "x$OPENJDK_$1_OS" = xlinux; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -Wpointer-arith -Wsign-compare -Wunused-function \ + -Wunused-value -Woverloaded-virtual" + + if test "x$TOOLCHAIN_TYPE" = xgcc; then + TOOLCHAIN_CHECK_COMPILER_VERSION(VERSION: [4.8], + IF_AT_LEAST: [ + # These flags either do not work or give spurious warnings prior to gcc 4.8. + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -Wno-format-zero-length -Wtype-limits -Wuninitialized" + ] + ) + fi + if ! HOTSPOT_CHECK_JVM_VARIANT(zero) && ! HOTSPOT_CHECK_JVM_VARIANT(zeroshark); then + # Non-zero builds have stricter warnings + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -Wreturn-type -Wundef -Wformat=2" + else + if test "x$TOOLCHAIN_TYPE" = xclang; then + # Some versions of llvm do not like -Wundef + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -Wno-undef" + fi + fi + elif test "x$OPENJDK_$1_OS" = xmacosx; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -Wno-deprecated -Wpointer-arith \ + -Wsign-compare -Wundef -Wunused-function -Wformat=2" fi # Additional macosx handling - if test "x$OPENJDK_TARGET_OS" = xmacosx; then + if test "x$OPENJDK_$1_OS" = xmacosx; then # Setting these parameters makes it an error to link to macosx APIs that are # newer than the given OS version and makes the linked binaries compatible # even if built on a newer version of the OS. @@ -765,108 +997,112 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK], # The macro takes the version with no dots, ex: 1070 # Let the flags variables get resolved in make for easier override on make # command line. - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -DMAC_OS_X_VERSION_MAX_ALLOWED=\$(subst .,,\$(MACOSX_VERSION_MIN)) -mmacosx-version-min=\$(MACOSX_VERSION_MIN)" - LDFLAGS_JDK="$LDFLAGS_JDK -mmacosx-version-min=\$(MACOSX_VERSION_MIN)" + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -DMAC_OS_X_VERSION_MAX_ALLOWED=\$(subst .,,\$(MACOSX_VERSION_MIN)) -mmacosx-version-min=\$(MACOSX_VERSION_MIN)" + $2LDFLAGS_JDK="[$]$2LDFLAGS_JDK -mmacosx-version-min=\$(MACOSX_VERSION_MIN)" fi # Setup some hard coded includes - COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK \ + $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK \ -I${JDK_TOPDIR}/src/java.base/share/native/include \ - -I${JDK_TOPDIR}/src/java.base/$OPENJDK_TARGET_OS/native/include \ - -I${JDK_TOPDIR}/src/java.base/$OPENJDK_TARGET_OS_TYPE/native/include \ + -I${JDK_TOPDIR}/src/java.base/$OPENJDK_$1_OS/native/include \ + -I${JDK_TOPDIR}/src/java.base/$OPENJDK_$1_OS_TYPE/native/include \ -I${JDK_TOPDIR}/src/java.base/share/native/libjava \ - -I${JDK_TOPDIR}/src/java.base/$OPENJDK_TARGET_OS_TYPE/native/libjava" + -I${JDK_TOPDIR}/src/java.base/$OPENJDK_$1_OS_TYPE/native/libjava" # The shared libraries are compiled using the picflag. - CFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \ - $CFLAGS_JDK $EXTRA_CFLAGS_JDK $PICFLAG $CFLAGS_JDKLIB_EXTRA" - CXXFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \ - $CXXFLAGS_JDK $EXTRA_CXXFLAGS_JDK $PICFLAG $CXXFLAGS_JDKLIB_EXTRA" + $2CFLAGS_JDKLIB="[$]$2COMMON_CCXXFLAGS_JDK \ + [$]$2CFLAGS_JDK [$]$2EXTRA_CFLAGS_JDK $PICFLAG [$]$2CFLAGS_JDKLIB_EXTRA" + $2CXXFLAGS_JDKLIB="[$]$2COMMON_CCXXFLAGS_JDK \ + [$]$2CXXFLAGS_JDK [$]$2EXTRA_CXXFLAGS_JDK $PICFLAG [$]$2CXXFLAGS_JDKLIB_EXTRA" # Executable flags - CFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \ - $CFLAGS_JDK $EXTRA_CFLAGS_JDK" - CXXFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \ - $CXXFLAGS_JDK $EXTRA_CXXFLAGS_JDK" - - # The corresponding flags for building for the build platform. This is still an - # approximation, we only need something that runs on this machine when cross - # compiling the product. - OPENJDK_BUILD_CFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CCXXFLAGS_JDK \ - $PICFLAG $CFLAGS_JDKLIB_EXTRA" - OPENJDK_BUILD_CXXFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CCXXFLAGS_JDK \ - $PICFLAG $CXXFLAGS_JDKLIB_EXTRA" - OPENJDK_BUILD_CFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CCXXFLAGS_JDK" - OPENJDK_BUILD_CXXFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CCXXFLAGS_JDK" - - AC_SUBST(CFLAGS_JDKLIB) - AC_SUBST(CFLAGS_JDKEXE) - AC_SUBST(CXXFLAGS_JDKLIB) - AC_SUBST(CXXFLAGS_JDKEXE) - AC_SUBST(OPENJDK_BUILD_CFLAGS_JDKLIB) - AC_SUBST(OPENJDK_BUILD_CFLAGS_JDKEXE) - AC_SUBST(OPENJDK_BUILD_CXXFLAGS_JDKLIB) - AC_SUBST(OPENJDK_BUILD_CXXFLAGS_JDKEXE) + $2CFLAGS_JDKEXE="[$]$2COMMON_CCXXFLAGS_JDK [$]$2CFLAGS_JDK [$]$2EXTRA_CFLAGS_JDK" + $2CXXFLAGS_JDKEXE="[$]$2COMMON_CCXXFLAGS_JDK [$]$2CXXFLAGS_JDK [$]$2EXTRA_CXXFLAGS_JDK" - # Flags for compiling test libraries - CFLAGS_TESTLIB="$COMMON_CCXXFLAGS_JDK $CFLAGS_JDK $PICFLAG $CFLAGS_JDKLIB_EXTRA" - CXXFLAGS_TESTLIB="$COMMON_CCXXFLAGS_JDK $CXXFLAGS_JDK $PICFLAG $CXXFLAGS_JDKLIB_EXTRA" - - # Flags for compiling test executables - CFLAGS_TESTEXE="$COMMON_CCXXFLAGS_JDK $CFLAGS_JDK" - CXXFLAGS_TESTEXE="$COMMON_CCXXFLAGS_JDK $CXXFLAGS_JDK" - - AC_SUBST(CFLAGS_TESTLIB) - AC_SUBST(CFLAGS_TESTEXE) - AC_SUBST(CXXFLAGS_TESTLIB) - AC_SUBST(CXXFLAGS_TESTEXE) + AC_SUBST($2CFLAGS_JDKLIB) + AC_SUBST($2CFLAGS_JDKEXE) + AC_SUBST($2CXXFLAGS_JDKLIB) + AC_SUBST($2CXXFLAGS_JDKEXE) # Setup LDFLAGS et al. # if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then LDFLAGS_MICROSOFT="-nologo -opt:ref" - LDFLAGS_JDK="$LDFLAGS_JDK $LDFLAGS_MICROSOFT -incremental:no" - if test "x$OPENJDK_TARGET_CPU_BITS" = "x32"; then + $2LDFLAGS_JDK="[$]$2LDFLAGS_JDK $LDFLAGS_MICROSOFT -incremental:no" + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS $LDFLAGS_MICROSOFT -opt:icf,8 -subsystem:windows -base:0x8000000" + if test "x$OPENJDK_$1_CPU_BITS" = "x32"; then LDFLAGS_SAFESH="-safeseh" - LDFLAGS_JDK="$LDFLAGS_JDK $LDFLAGS_SAFESH" + $2LDFLAGS_JDK="[$]$2LDFLAGS_JDK $LDFLAGS_SAFESH" + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS $LDFLAGS_SAFESH" + # NOTE: Old build added -machine. Probably not needed. + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS -machine:I386" + else + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS -machine:AMD64" + fi + elif test "x$TOOLCHAIN_TYPE" = xclang; then + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS -mno-omit-leaf-frame-pointer -mstack-alignment=16 -stdlib=libstdc++ -fPIC" + if test "x$OPENJDK_$1_OS" = xmacosx; then + # FIXME: We should really generalize SET_SHARED_LIBRARY_ORIGIN instead. + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS -Wl,-rpath,@loader_path/. -Wl,-rpath,@loader_path/.." fi elif test "x$TOOLCHAIN_TYPE" = xgcc; then # If this is a --hash-style=gnu system, use --hash-style=both, why? # We have previously set HAS_GNU_HASH if this is the case if test -n "$HAS_GNU_HASH"; then - LDFLAGS_HASH_STYLE="-Wl,--hash-style=both" - LDFLAGS_JDK="${LDFLAGS_JDK} $LDFLAGS_HASH_STYLE" + $2LDFLAGS_HASH_STYLE="-Wl,--hash-style=both" + $2LDFLAGS_JDK="${$2LDFLAGS_JDK} [$]$2LDFLAGS_HASH_STYLE" + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS [$]$2LDFLAGS_HASH_STYLE" fi - if test "x$OPENJDK_TARGET_OS" = xlinux; then + if test "x$OPENJDK_$1_OS" = xmacosx; then + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS -Wl,-rpath,@loader_path/. -Wl,-rpath,@loader_path/.." + fi + if test "x$OPENJDK_$1_OS" = xlinux; then # And since we now know that the linker is gnu, then add -z defs, to forbid # undefined symbols in object files. LDFLAGS_NO_UNDEF_SYM="-Wl,-z,defs" - LDFLAGS_JDK="${LDFLAGS_JDK} $LDFLAGS_NO_UNDEF_SYM" + $2LDFLAGS_JDK="${$2LDFLAGS_JDK} $LDFLAGS_NO_UNDEF_SYM" + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS $LDFLAGS_NO_UNDEF_SYM" + LDFLAGS_NO_EXEC_STACK="-Wl,-z,noexecstack" + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS $LDFLAGS_NO_EXEC_STACK" + if test "x$OPENJDK_$1_CPU" = xx86; then + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS -march=i586" + fi case $DEBUG_LEVEL in release ) # tell linker to optimize libraries. # Should this be supplied to the OSS linker as well? LDFLAGS_DEBUGLEVEL_release="-Wl,-O1" - LDFLAGS_JDK="${LDFLAGS_JDK} $LDFLAGS_DEBUGLEVEL_release" + $2LDFLAGS_JDK="${$2LDFLAGS_JDK} $LDFLAGS_DEBUGLEVEL_release" + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS $LDFLAGS_DEBUGLEVEL_release" + if test "x$HAS_LINKER_RELRO" = "xtrue"; then + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS $LINKER_RELRO_FLAG" + fi ;; slowdebug ) + # Hotspot always let the linker optimize + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS -Wl,-O1" if test "x$HAS_LINKER_NOW" = "xtrue"; then # do relocations at load - LDFLAGS_JDK="$LDFLAGS_JDK $LINKER_NOW_FLAG" - LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK $LINKER_NOW_FLAG" + $2LDFLAGS_JDK="[$]$2LDFLAGS_JDK $LINKER_NOW_FLAG" + $2LDFLAGS_CXX_JDK="[$]$2LDFLAGS_CXX_JDK $LINKER_NOW_FLAG" + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS $LINKER_NOW_FLAG" fi if test "x$HAS_LINKER_RELRO" = "xtrue"; then # mark relocations read only - LDFLAGS_JDK="$LDFLAGS_JDK $LINKER_RELRO_FLAG" - LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK $LINKER_RELRO_FLAG" + $2LDFLAGS_JDK="[$]$2LDFLAGS_JDK $LINKER_RELRO_FLAG" + $2LDFLAGS_CXX_JDK="[$]$2LDFLAGS_CXX_JDK $LINKER_RELRO_FLAG" + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS $LINKER_RELRO_FLAG" fi ;; fastdebug ) + # Hotspot always let the linker optimize + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS -Wl,-O1" if test "x$HAS_LINKER_RELRO" = "xtrue"; then # mark relocations read only - LDFLAGS_JDK="$LDFLAGS_JDK $LINKER_RELRO_FLAG" - LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK $LINKER_RELRO_FLAG" + $2LDFLAGS_JDK="[$]$2LDFLAGS_JDK $LINKER_RELRO_FLAG" + $2LDFLAGS_CXX_JDK="[$]$2LDFLAGS_CXX_JDK $LINKER_RELRO_FLAG" + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS $LINKER_RELRO_FLAG" fi ;; * ) @@ -876,85 +1112,122 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK], fi elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then LDFLAGS_SOLSTUDIO="-Wl,-z,defs" - LDFLAGS_JDK="$LDFLAGS_JDK $LDFLAGS_SOLSTUDIO -xildoff -ztext" + $2LDFLAGS_JDK="[$]$2LDFLAGS_JDK $LDFLAGS_SOLSTUDIO -xildoff -ztext" LDFLAGS_CXX_SOLSTUDIO="-norunpath" - LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK $LDFLAGS_CXX_SOLSTUDIO -xnolib" + $2LDFLAGS_CXX_JDK="[$]$2LDFLAGS_CXX_JDK $LDFLAGS_CXX_SOLSTUDIO -xnolib" + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS $LDFLAGS_SOLSTUDIO -library=%none -mt $LDFLAGS_CXX_SOLSTUDIO -z noversion" + if test "x$OPENJDK_$1_CPU_ARCH" = "xsparc"; then + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS -xarch=sparc" + fi elif test "x$TOOLCHAIN_TYPE" = xxlc; then LDFLAGS_XLC="-b64 -brtl -bnolibpath -bexpall -bernotok" - LDFLAGS_JDK="${LDFLAGS_JDK} $LDFLAGS_XLC" + $2LDFLAGS_JDK="${$2LDFLAGS_JDK} $LDFLAGS_XLC" + $2JVM_LDFLAGS="[$]$2JVM_LDFLAGS $LDFLAGS_XLC" fi # Customize LDFLAGS for executables - LDFLAGS_JDKEXE="${LDFLAGS_JDK}" + $2LDFLAGS_JDKEXE="${$2LDFLAGS_JDK}" if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then - if test "x$OPENJDK_TARGET_CPU_BITS" = "x64"; then + if test "x$OPENJDK_$1_CPU_BITS" = "x64"; then LDFLAGS_STACK_SIZE=1048576 else LDFLAGS_STACK_SIZE=327680 fi - LDFLAGS_JDKEXE="${LDFLAGS_JDKEXE} /STACK:$LDFLAGS_STACK_SIZE" - elif test "x$OPENJDK_TARGET_OS" = xlinux; then - LDFLAGS_JDKEXE="$LDFLAGS_JDKEXE -Wl,--allow-shlib-undefined" + $2LDFLAGS_JDKEXE="${$2LDFLAGS_JDKEXE} /STACK:$LDFLAGS_STACK_SIZE" + elif test "x$OPENJDK_$1_OS" = xlinux; then + $2LDFLAGS_JDKEXE="[$]$2LDFLAGS_JDKEXE -Wl,--allow-shlib-undefined" fi - OPENJDK_BUILD_LDFLAGS_JDKEXE="${LDFLAGS_JDKEXE}" - LDFLAGS_JDKEXE="${LDFLAGS_JDKEXE} ${EXTRA_LDFLAGS_JDK}" + $2LDFLAGS_JDKEXE="${$2LDFLAGS_JDKEXE} ${$2EXTRA_LDFLAGS_JDK}" # Customize LDFLAGS for libs - LDFLAGS_JDKLIB="${LDFLAGS_JDK}" + $2LDFLAGS_JDKLIB="${$2LDFLAGS_JDK}" - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} ${SHARED_LIBRARY_FLAGS}" + $2LDFLAGS_JDKLIB="${$2LDFLAGS_JDKLIB} ${SHARED_LIBRARY_FLAGS}" if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} \ + $2LDFLAGS_JDKLIB="${$2LDFLAGS_JDKLIB} \ -libpath:${OUTPUT_ROOT}/support/modules_libs/java.base" - JDKLIB_LIBS="" + $2JDKLIB_LIBS="" else - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} \ - -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)" + $2LDFLAGS_JDKLIB="${$2LDFLAGS_JDKLIB} \ + -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_$1_CPU_LIBDIR)" + if test "x$1" = "xTARGET"; then # On some platforms (mac) the linker warns about non existing -L dirs. # Add server first if available. Linking aginst client does not always produce the same results. - # Only add client dir if client is being built. Add minimal (note not minimal1) if only building minimal1. + # Only add client/minimal dir if client/minimal is being built. # Default to server for other variants. - if test "x$JVM_VARIANT_SERVER" = xtrue; then - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/server" - elif test "x$JVM_VARIANT_CLIENT" = xtrue; then - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/client" - elif test "x$JVM_VARIANT_MINIMAL1" = xtrue; then - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/minimal" + if HOTSPOT_CHECK_JVM_VARIANT(server); then + $2LDFLAGS_JDKLIB="${$2LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_$1_CPU_LIBDIR)/server" + elif HOTSPOT_CHECK_JVM_VARIANT(client); then + $2LDFLAGS_JDKLIB="${$2LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_$1_CPU_LIBDIR)/client" + elif HOTSPOT_CHECK_JVM_VARIANT(minimal); then + $2LDFLAGS_JDKLIB="${$2LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_$1_CPU_LIBDIR)/minimal" else - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/server" + $2LDFLAGS_JDKLIB="${$2LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_$1_CPU_LIBDIR)/server" + fi + elif test "x$1" = "xBUILD"; then + # When building a buildjdk, it's always only the server variant + $2LDFLAGS_JDKLIB="${$2LDFLAGS_JDKLIB} \ + -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_$1_CPU_LIBDIR)/server" fi - JDKLIB_LIBS="-ljava -ljvm" + $2JDKLIB_LIBS="-ljava -ljvm" if test "x$TOOLCHAIN_TYPE" = xsolstudio; then - JDKLIB_LIBS="$JDKLIB_LIBS -lc" + $2JDKLIB_LIBS="[$]$2JDKLIB_LIBS -lc" fi - # When building a buildjdk, it's always only the server variant - OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} \ - -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/server" fi - OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} ${LDFLAGS_JDKLIB}" - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} ${EXTRA_LDFLAGS_JDK}" + # Set $2JVM_LIBS (per os) + if test "x$OPENJDK_$1_OS" = xlinux; then + $2JVM_LIBS="[$]$2JVM_LIBS -lm -ldl -lpthread" + elif test "x$OPENJDK_$1_OS" = xsolaris; then + # FIXME: This hard-coded path is not really proper. + if test "x$OPENJDK_$1_CPU" = xx86_64; then + $2SOLARIS_LIBM_LIBS="/usr/lib/amd64/libm.so.1" + elif test "x$OPENJDK_$1_CPU" = xsparcv9; then + $2SOLARIS_LIBM_LIBS="/usr/lib/sparcv9/libm.so.1" + fi + $2JVM_LIBS="[$]$2JVM_LIBS -lsocket -lsched -ldl $SOLARIS_LIBM_LIBS -lCrun \ + -lthread -ldoor -lc -ldemangle -lnsl -lkstat -lrt" + elif test "x$OPENJDK_$1_OS" = xmacosx; then + $2JVM_LIBS="[$]$2JVM_LIBS -lm" + elif test "x$OPENJDK_$1_OS" = xaix; then + $2JVM_LIBS="[$]$2JVM_LIBS -Wl,-lC_r -lm -ldl -lpthread" + elif test "x$OPENJDK_$1_OS" = xbsd; then + $2JVM_LIBS="[$]$2JVM_LIBS -lm" + elif test "x$OPENJDK_$1_OS" = xwindows; then + $2JVM_LIBS="[$]$2JVM_LIBS kernel32.lib user32.lib gdi32.lib winspool.lib \ + comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib \ + wsock32.lib winmm.lib version.lib psapi.lib" + fi - AC_SUBST(LDFLAGS_JDKLIB) - AC_SUBST(LDFLAGS_JDKEXE) - AC_SUBST(OPENJDK_BUILD_LDFLAGS_JDKLIB) - AC_SUBST(OPENJDK_BUILD_LDFLAGS_JDKEXE) - AC_SUBST(JDKLIB_LIBS) - AC_SUBST(JDKEXE_LIBS) - AC_SUBST(LDFLAGS_CXX_JDK) - AC_SUBST(LDFLAGS_HASH_STYLE) + # Set $2JVM_ASFLAGS + if test "x$OPENJDK_$1_OS" = xlinux; then + if test "x$OPENJDK_$1_CPU" = xx86; then + $2JVM_ASFLAGS="[$]$2JVM_ASFLAGS -march=i586" + fi + elif test "x$OPENJDK_$1_OS" = xmacosx; then + $2JVM_ASFLAGS="[$]$2JVM_ASFLAGS -x assembler-with-cpp -mno-omit-leaf-frame-pointer -mstack-alignment=16" + fi - LDFLAGS_TESTLIB="$LDFLAGS_JDKLIB" - LDFLAGS_TESTEXE="$LDFLAGS_JDKEXE" + $2LDFLAGS_JDKLIB="${$2LDFLAGS_JDKLIB} ${$2EXTRA_LDFLAGS_JDK}" + + AC_SUBST($2LDFLAGS_JDKLIB) + AC_SUBST($2LDFLAGS_JDKEXE) + AC_SUBST($2JDKLIB_LIBS) + AC_SUBST($2JDKEXE_LIBS) + AC_SUBST($2LDFLAGS_CXX_JDK) + AC_SUBST($2LDFLAGS_HASH_STYLE) + + AC_SUBST($2JVM_CFLAGS) + AC_SUBST($2JVM_LDFLAGS) + AC_SUBST($2JVM_ASFLAGS) + AC_SUBST($2JVM_LIBS) - AC_SUBST(LDFLAGS_TESTLIB) - AC_SUBST(LDFLAGS_TESTEXE) ]) # FLAGS_C_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [ARGUMENT], IF_TRUE: [RUN-IF-TRUE], diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index d6b14430edc99336753adb4850ee3c1d08b9bdcc..9563705cdcb2e3de27203e0ce5687315b9b58105 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -652,7 +652,21 @@ MEMORY_SIZE NUM_CORES BUILD_FAILURE_HANDLER ENABLE_INTREE_EC +JVM_VARIANT_CORE +JVM_VARIANT_ZEROSHARK +JVM_VARIANT_ZERO +JVM_VARIANT_HOTSPOT +JVM_VARIANT_MINIMAL1 +JVM_VARIANT_CLIENT +JVM_VARIANT_SERVER +JVM_VARIANTS_COMMA +TEST_IN_BUILD HOTSPOT_MAKE_ARGS +MACOSX_UNIVERSAL +DEBUG_CLASSFILES +FASTDEBUG +VARIANT +USE_NEW_HOTSPOT_BUILD LIBZIP_CAN_USE_MMAP LIBDL LIBM @@ -688,6 +702,15 @@ LIBCXX STATIC_CXX_SETTING FIXPATH_DETACH_FLAG FIXPATH +VALID_JVM_FEATURES +JVM_FEATURES_custom +JVM_FEATURES_zeroshark +JVM_FEATURES_zero +JVM_FEATURES_minimal +JVM_FEATURES_core +JVM_FEATURES_client +JVM_FEATURES_server +INCLUDE_DTRACE GCOV_ENABLED STRIP_POLICY DEBUG_BINARIES @@ -703,22 +726,35 @@ COMPILER_SUPPORTS_TARGET_BITS_FLAG ZERO_ARCHFLAG LDFLAGS_TESTEXE LDFLAGS_TESTLIB -LDFLAGS_HASH_STYLE -LDFLAGS_CXX_JDK -JDKEXE_LIBS -JDKLIB_LIBS -OPENJDK_BUILD_LDFLAGS_JDKEXE -OPENJDK_BUILD_LDFLAGS_JDKLIB -LDFLAGS_JDKEXE -LDFLAGS_JDKLIB CXXFLAGS_TESTEXE CXXFLAGS_TESTLIB CFLAGS_TESTEXE CFLAGS_TESTLIB +OPENJDK_BUILD_JVM_LIBS +OPENJDK_BUILD_JVM_ASFLAGS +OPENJDK_BUILD_JVM_LDFLAGS +OPENJDK_BUILD_JVM_CFLAGS +OPENJDK_BUILD_LDFLAGS_HASH_STYLE +OPENJDK_BUILD_LDFLAGS_CXX_JDK +OPENJDK_BUILD_JDKEXE_LIBS +OPENJDK_BUILD_JDKLIB_LIBS +OPENJDK_BUILD_LDFLAGS_JDKEXE +OPENJDK_BUILD_LDFLAGS_JDKLIB OPENJDK_BUILD_CXXFLAGS_JDKEXE OPENJDK_BUILD_CXXFLAGS_JDKLIB OPENJDK_BUILD_CFLAGS_JDKEXE OPENJDK_BUILD_CFLAGS_JDKLIB +OPENJDK_BUILD_CXXSTD_CXXFLAG +JVM_LIBS +JVM_ASFLAGS +JVM_LDFLAGS +JVM_CFLAGS +LDFLAGS_HASH_STYLE +LDFLAGS_CXX_JDK +JDKEXE_LIBS +JDKLIB_LIBS +LDFLAGS_JDKEXE +LDFLAGS_JDKLIB CXXFLAGS_JDKEXE CXXFLAGS_JDKLIB CFLAGS_JDKEXE @@ -727,16 +763,21 @@ MACOSX_VERSION_MIN NO_LIFETIME_DSE_CFLAG NO_NULL_POINTER_CHECK_CFLAG CXXSTD_CXXFLAG +CXX_O_FLAG_SIZE CXX_O_FLAG_NONE CXX_O_FLAG_DEBUG CXX_O_FLAG_NORM CXX_O_FLAG_HI CXX_O_FLAG_HIGHEST +CXX_O_FLAG_HIGHEST_JVM +C_O_FLAG_SIZE C_O_FLAG_NONE C_O_FLAG_DEBUG C_O_FLAG_NORM C_O_FLAG_HI C_O_FLAG_HIGHEST +C_O_FLAG_HIGHEST_JVM +JVM_CFLAGS_SYMBOLS CXXFLAGS_DEBUG_SYMBOLS CFLAGS_DEBUG_SYMBOLS CXX_FLAG_DEPS @@ -748,6 +789,7 @@ SET_SHARED_LIBRARY_ORIGIN SET_EXECUTABLE_ORIGIN CXX_FLAG_REORDER C_FLAG_REORDER +JVM_RCFLAGS RC_FLAGS AR_OUT_OPTION LD_OUT_OPTION @@ -760,6 +802,7 @@ COMPILER_COMMAND_FILE_FLAG COMPILER_TARGET_BITS_FLAG JT_HOME JTREGEXE +HOTSPOT_TOOLCHAIN_TYPE USING_BROKEN_SUSE_LD PACKAGE_PATH USE_CLANG @@ -822,6 +865,9 @@ VS_PATH CYGWIN_LINK SYSROOT_LDFLAGS SYSROOT_CFLAGS +EXTRA_LDFLAGS +EXTRA_CXXFLAGS +EXTRA_CFLAGS LEGACY_EXTRA_LDFLAGS LEGACY_EXTRA_CXXFLAGS LEGACY_EXTRA_CFLAGS @@ -878,12 +924,12 @@ VERSION_MINOR VERSION_MAJOR MACOSX_BUNDLE_ID_BASE MACOSX_BUNDLE_NAME_BASE +HOTSPOT_VM_DISTRO COMPANY_NAME JDK_RC_PLATFORM_NAME PRODUCT_SUFFIX PRODUCT_NAME LAUNCHER_NAME -TEST_IN_BUILD JLINK_KEEP_PACKAGED_MODULES COPYRIGHT_YEAR COMPRESS_JARS @@ -905,6 +951,7 @@ XATTR DSYMUTIL IS_GNU_TIME PATCH +DTRACE TIME STAT HG @@ -928,20 +975,10 @@ CONF_NAME SPEC SDKROOT XCODEBUILD -BUILD_VARIANT_RELEASE -DEBUG_CLASSFILES -FASTDEBUG -VARIANT -DEBUG_LEVEL -MACOSX_UNIVERSAL -JVM_VARIANT_CORE -JVM_VARIANT_ZEROSHARK -JVM_VARIANT_ZERO -JVM_VARIANT_MINIMAL1 -JVM_VARIANT_CLIENT -JVM_VARIANT_SERVER +VALID_JVM_VARIANTS JVM_VARIANTS -JVM_INTERPRETER +DEBUG_LEVEL +HOTSPOT_DEBUG_LEVEL JDK_VARIANT SET_OPENJDK USERNAME @@ -950,16 +987,29 @@ ORIGINAL_TOPDIR TOPDIR PATH_SEP ZERO_ARCHDEF +HOTSPOT_BUILD_CPU_DEFINE +HOTSPOT_BUILD_CPU_ARCH +HOTSPOT_BUILD_CPU +HOTSPOT_BUILD_OS_TYPE +HOTSPOT_BUILD_OS +OPENJDK_BUILD_OS_EXPORT_DIR +OPENJDK_BUILD_CPU_JLI_CFLAGS +OPENJDK_BUILD_CPU_OSARCH +OPENJDK_BUILD_CPU_ISADIR +OPENJDK_BUILD_CPU_LIBDIR +OPENJDK_BUILD_CPU_LEGACY_LIB +OPENJDK_BUILD_CPU_LEGACY +HOTSPOT_TARGET_CPU_DEFINE +HOTSPOT_TARGET_CPU_ARCH +HOTSPOT_TARGET_CPU +HOTSPOT_TARGET_OS_TYPE +HOTSPOT_TARGET_OS DEFINE_CROSS_COMPILE_ARCH LP64 OPENJDK_TARGET_OS_EXPORT_DIR -OPENJDK_BUILD_CPU_JLI_CFLAGS OPENJDK_TARGET_CPU_JLI_CFLAGS OPENJDK_TARGET_CPU_OSARCH OPENJDK_TARGET_CPU_ISADIR -OPENJDK_BUILD_CPU_LIBDIR -OPENJDK_BUILD_CPU_LEGACY_LIB -OPENJDK_BUILD_CPU_LEGACY OPENJDK_TARGET_CPU_LIBDIR OPENJDK_TARGET_CPU_LEGACY_LIB OPENJDK_TARGET_CPU_LEGACY @@ -1089,10 +1139,9 @@ with_target_bits enable_openjdk_only with_custom_make_dir with_jdk_variant -with_jvm_interpreter -with_jvm_variants enable_debug with_debug_level +with_jvm_variants with_devkit with_sys_root with_sysroot @@ -1108,7 +1157,6 @@ with_cacerts_file enable_unlimited_crypto with_copyright_year enable_keep_packaged_modules -enable_hotspot_test_in_build with_milestone with_update_version with_user_release_suffix @@ -1148,6 +1196,9 @@ with_native_debug_symbols enable_debug_symbols enable_zip_debug_info enable_native_coverage +enable_dtrace +with_jvm_features +with_jvm_interpreter with_stdc__lib with_msvcr_dll with_msvcp_dll @@ -1174,6 +1225,8 @@ with_dxsdk with_dxsdk_lib with_dxsdk_include enable_jtreg_failure_handler +enable_new_hotspot_build +enable_hotspot_test_in_build with_num_cores with_memory_size with_jobs @@ -1246,6 +1299,7 @@ READELF HG STAT TIME +DTRACE PATCH DSYMUTIL XATTR @@ -1925,8 +1979,6 @@ Optional Features: Enable unlimited crypto policy [disabled] --disable-keep-packaged-modules Do not keep packaged modules in jdk image [enable] - --enable-hotspot-test-in-build - run the Queens test after Hotspot build [disabled] --enable-static-build enable static library build [disabled] --disable-warnings-as-errors do not consider native warnings to be an error @@ -1938,10 +1990,18 @@ Optional Features: --enable-native-coverage enable native compilation with code coverage data[disabled] + --enable-dtrace[=yes/no/auto] + enable dtrace. Default is auto, where dtrace is + enabled if all dependencies are present. --disable-freetype-bundling disable bundling of the freetype library with the build result [enabled on Windows or when using --with-freetype, disabled otherwise] + --disable-new-hotspot-build + disable the new hotspot build system (use the old) + [enabled] + --enable-hotspot-test-in-build + run the Queens test after Hotspot build [disabled] --enable-jtreg-failure-handler forces build of the jtreg failure handler to be enabled, missing dependencies become fatal errors. @@ -1967,11 +2027,11 @@ Optional Packages: --with-custom-make-dir Deprecated. Option is kept for backwards compatibility and is ignored --with-jdk-variant JDK variant to build (normal) [normal] - --with-jvm-interpreter JVM interpreter to build (template, cpp) [template] - --with-jvm-variants JVM variants (separated by commas) to build (server, - client, minimal1, zero, zeroshark, core) [server] --with-debug-level set the debug level (release, fastdebug, slowdebug, optimized) [release] + --with-jvm-variants JVM variants (separated by commas) to build + (server,client,minimal,core,zero,zeroshark,custom) + [server] --with-devkit use this devkit for compilers, tools and resources --with-sys-root alias for --with-sysroot for backwards compatability --with-sysroot use this directory as sysroot @@ -2058,6 +2118,10 @@ Optional Packages: --with-native-debug-symbols set the native debug symbol configuration (none, internal, external, zipped) [varying] + --with-jvm-features additional JVM features to enable (separated by + comma), use '--help' to show possible values [none] + --with-jvm-interpreter Deprecated. Option is kept for backwards + compatibility and is ignored --with-stdc++lib=,, force linking of the C++ runtime on Linux to either static or dynamic, default is static with dynamic as @@ -2178,6 +2242,7 @@ Some influential environment variables: HG Override default value for HG STAT Override default value for STAT TIME Override default value for TIME + DTRACE Override default value for DTRACE PATCH Override default value for PATCH DSYMUTIL Override default value for DSYMUTIL XATTR Override default value for XATTR @@ -3977,6 +4042,13 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + +################################################################################ +# $1 - Either BUILD or TARGET to pick the correct OS/CPU variables to check +# conditionals against. +# $2 - Optional prefix for each variable defined. + + # FLAGS_C_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [ARGUMENT], IF_TRUE: [RUN-IF-TRUE], # IF_FALSE: [RUN-IF-FALSE]) # ------------------------------------------------------------ @@ -4101,6 +4173,8 @@ apt_help() { PKGHANDLER_COMMAND="sudo apt-get install libX11-dev libxext-dev libxrender-dev libxtst-dev libxt-dev" ;; ccache) PKGHANDLER_COMMAND="sudo apt-get install ccache" ;; + dtrace) + PKGHANDLER_COMMAND="sudo apt-get install systemtap-sdt-dev" ;; esac } @@ -4170,37 +4244,66 @@ pkgadd_help() { # questions. # +# All valid JVM features, regardless of platform +VALID_JVM_FEATURES="compiler1 compiler2 zero shark minimal dtrace jvmti jvmci \ + fprof vm-structs jni-check services management all-gcs nmt cds static-build" + +# All valid JVM variants +VALID_JVM_VARIANTS="server client minimal core zero zeroshark custom" + ############################################################################### -# Check which interpreter of the JVM we want to build. -# Currently we have: -# template: Template interpreter (the default) -# cpp : C++ interpreter +# Check if the specified JVM variant should be built. To be used in shell if +# constructs, like this: +# if HOTSPOT_CHECK_JVM_VARIANT(server); then +# +# Only valid to use after HOTSPOT_SETUP_JVM_VARIANTS has setup variants. + +# Definition kept in one line to allow inlining in if statements. +# Additional [] needed to keep m4 from mangling shell constructs. ############################################################################### -# Check which variants of the JVM that we want to build. -# Currently we have: -# server: normal interpreter and a C2 or tiered C1/C2 compiler -# client: normal interpreter and C1 (no C2 compiler) (only 32-bit platforms) -# minimal1: reduced form of client with optional VM services and features stripped out -# zero: no machine code interpreter, no compiler -# zeroshark: zero interpreter and shark/llvm compiler backend -# core: interpreter only, no compiler (only works on some platforms) +# Check if the specified JVM features are explicitly enabled. To be used in +# shell if constructs, like this: +# if HOTSPOT_CHECK_JVM_FEATURE(jvmti); then +# +# Only valid to use after HOTSPOT_SETUP_JVM_FEATURES has setup features. +# Definition kept in one line to allow inlining in if statements. +# Additional [] needed to keep m4 from mangling shell constructs. ############################################################################### -# Setup legacy vars/targets and new vars to deal with different debug levels. +# Check which variants of the JVM that we want to build. Available variants are: +# server: normal interpreter, and a tiered C1/C2 compiler +# client: normal interpreter, and C1 (no C2 compiler) +# minimal: reduced form of client with optional features stripped out +# core: normal interpreter only, no compiler +# zero: C++ based interpreter only, no compiler +# zeroshark: C++ based interpreter, and a llvm-based compiler +# custom: baseline JVM with no default features # -# release: no debug information, all optimizations, no asserts. -# optimized: no debug information, all optimizations, no asserts, HotSpot target is 'optimized'. -# fastdebug: debug information (-g), all optimizations, all asserts -# slowdebug: debug information (-g), no optimizations, all asserts + + +############################################################################### +# Check if dtrace should be enabled and has all prerequisites present. # +############################################################################### +# Set up all JVM features for each JVM variant. +# + + +############################################################################### +# Validate JVM features once all setup is complete, including custom setup. +# +############################################################################### +# Support for old hotspot build. Remove once new hotspot build has proven +# to work satisfactory. +# # @@ -4542,194 +4645,197 @@ pkgadd_help() { ################################################################################ -# -# 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 -# 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. -# - -################################################################################ -# Setup the standard C/C++ runtime libraries. -# -# Most importantly, determine if stdc++ should be linked statically or -# dynamically. -################################################################################ - - -# -# 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 -# 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. -# - -################################################################################ -# Setup X11 Windows system -################################################################################ - - - -################################################################################ -# Determine which libraries are needed for this configuration -################################################################################ - - -################################################################################ -# Parse library options, and setup needed libraries -################################################################################ - - -################################################################################ -# Setup llvm (Low-Level VM) -################################################################################ - - -################################################################################ -# Setup various libraries, typically small system libraries -################################################################################ - - -# -# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -# Support macro for PLATFORM_EXTRACT_TARGET_AND_BUILD. -# Converts autoconf style CPU name to OpenJDK style, into -# VAR_CPU, VAR_CPU_ARCH, VAR_CPU_BITS and VAR_CPU_ENDIAN. - - -# Support macro for PLATFORM_EXTRACT_TARGET_AND_BUILD. -# Converts autoconf style OS name to OpenJDK style, into -# VAR_OS, VAR_OS_TYPE and VAR_OS_ENV. - - -# Expects $host_os $host_cpu $build_os and $build_cpu -# and $with_target_bits to have been setup! -# -# Translate the standard triplet(quadruplet) definition -# of the target/build system into OPENJDK_TARGET_OS, OPENJDK_TARGET_CPU, -# OPENJDK_BUILD_OS, etc. - - -# Check if a reduced build (32-bit on 64-bit platforms) is requested, and modify behaviour -# accordingly. Must be done after setting up build and target system, but before -# doing anything else with these values. - - -# Setup the legacy variables, for controlling the old makefiles. -# - - - - -#%%% Build and target systems %%% - - - - -# Support macro for PLATFORM_SETUP_OPENJDK_TARGET_BITS. -# Add -mX to various FLAGS variables. - - - - - - -# -# 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 -# 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. -# - - - - - - - -################################################################################ -# Define a mechanism for importing extra prebuilt modules -# - - - +# +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. +# 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. +# + +################################################################################ +# Setup the standard C/C++ runtime libraries. +# +# Most importantly, determine if stdc++ should be linked statically or +# dynamically. +################################################################################ + + +# +# 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 +# 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. +# + +################################################################################ +# Setup X11 Windows system +################################################################################ + + + +################################################################################ +# Determine which libraries are needed for this configuration +################################################################################ + + +################################################################################ +# Parse library options, and setup needed libraries +################################################################################ + + +################################################################################ +# Setup llvm (Low-Level VM) +################################################################################ + + +################################################################################ +# Setup various libraries, typically small system libraries +################################################################################ + + +# +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. +# 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. +# + +# Support macro for PLATFORM_EXTRACT_TARGET_AND_BUILD. +# Converts autoconf style CPU name to OpenJDK style, into +# VAR_CPU, VAR_CPU_ARCH, VAR_CPU_BITS and VAR_CPU_ENDIAN. + + +# Support macro for PLATFORM_EXTRACT_TARGET_AND_BUILD. +# Converts autoconf style OS name to OpenJDK style, into +# VAR_OS, VAR_OS_TYPE and VAR_OS_ENV. + + +# Expects $host_os $host_cpu $build_os and $build_cpu +# and $with_target_bits to have been setup! +# +# Translate the standard triplet(quadruplet) definition +# of the target/build system into OPENJDK_TARGET_OS, OPENJDK_TARGET_CPU, +# OPENJDK_BUILD_OS, etc. + + +# Check if a reduced build (32-bit on 64-bit platforms) is requested, and modify behaviour +# accordingly. Must be done after setting up build and target system, but before +# doing anything else with these values. + + +# Setup the legacy variables, for controlling the old makefiles. +# + + +# $1 - Either TARGET or BUILD to setup the variables for. + + + + +#%%% Build and target systems %%% + + + + +# Support macro for PLATFORM_SETUP_OPENJDK_TARGET_BITS. +# Add -mX to various FLAGS variables. + + + + + + +# +# 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 +# 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. +# + + + + + + + +################################################################################ +# Define a mechanism for importing extra prebuilt modules +# + + + # # Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -4989,6 +5095,13 @@ DATE_WHEN_GENERATED=1460963400 TOOLCHAIN_DESCRIPTION=${!toolchain_var_name} $PRINTF " %-10s %s\n" $toolchain "$TOOLCHAIN_DESCRIPTION" done + $PRINTF "\n" + + # Print available jvm features + $PRINTF "The following JVM features are available as arguments to --with-jvm-features.\n" + $PRINTF "Which are valid to use depends on the target platform.\n " + $PRINTF "%s " $VALID_JVM_FEATURES + $PRINTF "\n" # And now exit directly exit 0 @@ -15229,6 +15342,7 @@ $as_echo "$COMPILE_TYPE" >&6; } + # Also store the legacy naming of the cpu. # Ie i586 and amd64 instead of x86 and x86_64 OPENJDK_TARGET_CPU_LEGACY="$OPENJDK_TARGET_CPU" @@ -15259,7 +15373,132 @@ $as_echo "$COMPILE_TYPE" >&6; } fi - # Now do the same for OPENJDK_BUILD_CPU... + # OPENJDK_TARGET_CPU_ISADIR is normally empty. On 64-bit Solaris systems, it is set to + # /amd64 or /sparcv9. This string is appended to some library paths, like this: + # /usr/lib${OPENJDK_TARGET_CPU_ISADIR}/libexample.so + OPENJDK_TARGET_CPU_ISADIR="" + if test "x$OPENJDK_TARGET_OS" = xsolaris; then + if test "x$OPENJDK_TARGET_CPU" = xx86_64; then + OPENJDK_TARGET_CPU_ISADIR="/amd64" + elif test "x$OPENJDK_TARGET_CPU" = xsparcv9; then + OPENJDK_TARGET_CPU_ISADIR="/sparcv9" + fi + fi + + + # Setup OPENJDK_TARGET_CPU_OSARCH, which is used to set the os.arch Java system property + OPENJDK_TARGET_CPU_OSARCH="$OPENJDK_TARGET_CPU" + if test "x$OPENJDK_TARGET_OS" = xlinux && test "x$OPENJDK_TARGET_CPU" = xx86; then + # On linux only, we replace x86 with i386. + OPENJDK_TARGET_CPU_OSARCH="i386" + elif test "x$OPENJDK_TARGET_OS" != xmacosx && test "x$OPENJDK_TARGET_CPU" = xx86_64; then + # On all platforms except macosx, we replace x86_64 with amd64. + OPENJDK_TARGET_CPU_OSARCH="amd64" + fi + + + OPENJDK_TARGET_CPU_JLI="$OPENJDK_TARGET_CPU" + if test "x$OPENJDK_TARGET_CPU" = xx86; then + OPENJDK_TARGET_CPU_JLI="i386" + elif test "x$OPENJDK_TARGET_OS" != xmacosx && test "x$OPENJDK_TARGET_CPU" = xx86_64; then + # On all platforms except macosx, we replace x86_64 with amd64. + OPENJDK_TARGET_CPU_JLI="amd64" + fi + # Now setup the -D flags for building libjli. + OPENJDK_TARGET_CPU_JLI_CFLAGS="-DLIBARCHNAME='\"$OPENJDK_TARGET_CPU_JLI\"'" + if test "x$OPENJDK_TARGET_OS" = xsolaris; then + if test "x$OPENJDK_TARGET_CPU_ARCH" = xsparc; then + OPENJDK_TARGET_CPU_JLI_CFLAGS="$OPENJDK_TARGET_CPU_JLI_CFLAGS -DLIBARCH32NAME='\"sparc\"' -DLIBARCH64NAME='\"sparcv9\"'" + elif test "x$OPENJDK_TARGET_CPU_ARCH" = xx86; then + OPENJDK_TARGET_CPU_JLI_CFLAGS="$OPENJDK_TARGET_CPU_JLI_CFLAGS -DLIBARCH32NAME='\"i386\"' -DLIBARCH64NAME='\"amd64\"'" + fi + fi + + + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + OPENJDK_TARGET_OS_EXPORT_DIR=macosx + else + OPENJDK_TARGET_OS_EXPORT_DIR=${OPENJDK_TARGET_OS_TYPE} + fi + + + if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then + A_LP64="LP64:=" + # -D_LP64=1 is only set on linux and mac. Setting on windows causes diff in + # unpack200.exe + if test "x$OPENJDK_TARGET_OS" = xlinux || test "x$OPENJDK_TARGET_OS" = xmacosx; then + OPENJDK_TARGET_ADD_LP64="-D_LP64=1" + fi + fi + LP64=$A_LP64 + + + if test "x$COMPILE_TYPE" = "xcross"; then + # FIXME: ... or should this include reduced builds..? + DEFINE_CROSS_COMPILE_ARCH="CROSS_COMPILE_ARCH:=$OPENJDK_TARGET_CPU_LEGACY" + else + DEFINE_CROSS_COMPILE_ARCH="" + fi + + + # Convert openjdk platform names to hotspot names + + HOTSPOT_TARGET_OS=${OPENJDK_TARGET_OS} + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + HOTSPOT_TARGET_OS=bsd + fi + + + HOTSPOT_TARGET_OS_TYPE=${OPENJDK_TARGET_OS_TYPE} + if test "x$OPENJDK_TARGET_OS_TYPE" = xunix; then + HOTSPOT_TARGET_OS_TYPE=posix + fi + + + HOTSPOT_TARGET_CPU=${OPENJDK_TARGET_CPU} + if test "x$OPENJDK_TARGET_CPU" = xx86; then + HOTSPOT_TARGET_CPU=x86_32 + elif test "x$OPENJDK_TARGET_CPU" = xsparcv9; then + HOTSPOT_TARGET_CPU=sparc + elif test "x$OPENJDK_TARGET_CPU" = xppc64; then + HOTSPOT_TARGET_CPU=ppc_64 + elif test "x$OPENJDK_TARGET_CPU" = xppc64le; then + HOTSPOT_TARGET_CPU=ppc_64 + fi + + + # This is identical with OPENJDK_*, but define anyway for consistency. + HOTSPOT_TARGET_CPU_ARCH=${OPENJDK_TARGET_CPU_ARCH} + + + # Setup HOTSPOT_TARGET_CPU_DEFINE + if test "x$OPENJDK_TARGET_CPU" = xx86; then + HOTSPOT_TARGET_CPU_DEFINE=IA32 + elif test "x$OPENJDK_TARGET_CPU" = xx86_64; then + HOTSPOT_TARGET_CPU_DEFINE=AMD64 + elif test "x$OPENJDK_TARGET_CPU" = xsparcv9; then + HOTSPOT_TARGET_CPU_DEFINE=SPARC + elif test "x$OPENJDK_TARGET_CPU" = xaarch64; then + HOTSPOT_TARGET_CPU_DEFINE=AARCH64 + elif test "x$OPENJDK_TARGET_CPU" = xppc64; then + HOTSPOT_TARGET_CPU_DEFINE=PPC64 + elif test "x$OPENJDK_TARGET_CPU" = xppc64le; then + HOTSPOT_TARGET_CPU_DEFINE=PPC64 + + # The cpu defines below are for zero, we don't support them directly. + elif test "x$OPENJDK_TARGET_CPU" = xsparc; then + HOTSPOT_TARGET_CPU_DEFINE=SPARC + elif test "x$OPENJDK_TARGET_CPU" = xppc; then + HOTSPOT_TARGET_CPU_DEFINE=PPC32 + elif test "x$OPENJDK_TARGET_CPU" = xs390; then + HOTSPOT_TARGET_CPU_DEFINE=S390 + elif test "x$OPENJDK_TARGET_CPU" = ss390x; then + HOTSPOT_TARGET_CPU_DEFINE=S390 + fi + + + + # Also store the legacy naming of the cpu. # Ie i586 and amd64 instead of x86 and x86_64 OPENJDK_BUILD_CPU_LEGACY="$OPENJDK_BUILD_CPU" @@ -15290,45 +15529,27 @@ $as_echo "$COMPILE_TYPE" >&6; } fi - # OPENJDK_TARGET_CPU_ISADIR is normally empty. On 64-bit Solaris systems, it is set to + # OPENJDK_BUILD_CPU_ISADIR is normally empty. On 64-bit Solaris systems, it is set to # /amd64 or /sparcv9. This string is appended to some library paths, like this: - # /usr/lib${OPENJDK_TARGET_CPU_ISADIR}/libexample.so - OPENJDK_TARGET_CPU_ISADIR="" - if test "x$OPENJDK_TARGET_OS" = xsolaris; then - if test "x$OPENJDK_TARGET_CPU" = xx86_64; then - OPENJDK_TARGET_CPU_ISADIR="/amd64" - elif test "x$OPENJDK_TARGET_CPU" = xsparcv9; then - OPENJDK_TARGET_CPU_ISADIR="/sparcv9" + # /usr/lib${OPENJDK_BUILD_CPU_ISADIR}/libexample.so + OPENJDK_BUILD_CPU_ISADIR="" + if test "x$OPENJDK_BUILD_OS" = xsolaris; then + if test "x$OPENJDK_BUILD_CPU" = xx86_64; then + OPENJDK_BUILD_CPU_ISADIR="/amd64" + elif test "x$OPENJDK_BUILD_CPU" = xsparcv9; then + OPENJDK_BUILD_CPU_ISADIR="/sparcv9" fi fi - # Setup OPENJDK_TARGET_CPU_OSARCH, which is used to set the os.arch Java system property - OPENJDK_TARGET_CPU_OSARCH="$OPENJDK_TARGET_CPU" - if test "x$OPENJDK_TARGET_OS" = xlinux && test "x$OPENJDK_TARGET_CPU" = xx86; then + # Setup OPENJDK_BUILD_CPU_OSARCH, which is used to set the os.arch Java system property + OPENJDK_BUILD_CPU_OSARCH="$OPENJDK_BUILD_CPU" + if test "x$OPENJDK_BUILD_OS" = xlinux && test "x$OPENJDK_BUILD_CPU" = xx86; then # On linux only, we replace x86 with i386. - OPENJDK_TARGET_CPU_OSARCH="i386" - elif test "x$OPENJDK_TARGET_OS" != xmacosx && test "x$OPENJDK_TARGET_CPU" = xx86_64; then - # On all platforms except macosx, we replace x86_64 with amd64. - OPENJDK_TARGET_CPU_OSARCH="amd64" - fi - - - OPENJDK_TARGET_CPU_JLI="$OPENJDK_TARGET_CPU" - if test "x$OPENJDK_TARGET_CPU" = xx86; then - OPENJDK_TARGET_CPU_JLI="i386" - elif test "x$OPENJDK_TARGET_OS" != xmacosx && test "x$OPENJDK_TARGET_CPU" = xx86_64; then + OPENJDK_BUILD_CPU_OSARCH="i386" + elif test "x$OPENJDK_BUILD_OS" != xmacosx && test "x$OPENJDK_BUILD_CPU" = xx86_64; then # On all platforms except macosx, we replace x86_64 with amd64. - OPENJDK_TARGET_CPU_JLI="amd64" - fi - # Now setup the -D flags for building libjli. - OPENJDK_TARGET_CPU_JLI_CFLAGS="-DLIBARCHNAME='\"$OPENJDK_TARGET_CPU_JLI\"'" - if test "x$OPENJDK_TARGET_OS" = xsolaris; then - if test "x$OPENJDK_TARGET_CPU_ARCH" = xsparc; then - OPENJDK_TARGET_CPU_JLI_CFLAGS="$OPENJDK_TARGET_CPU_JLI_CFLAGS -DLIBARCH32NAME='\"sparc\"' -DLIBARCH64NAME='\"sparcv9\"'" - elif test "x$OPENJDK_TARGET_CPU_ARCH" = xx86; then - OPENJDK_TARGET_CPU_JLI_CFLAGS="$OPENJDK_TARGET_CPU_JLI_CFLAGS -DLIBARCH32NAME='\"i386\"' -DLIBARCH64NAME='\"amd64\"'" - fi + OPENJDK_BUILD_CPU_OSARCH="amd64" fi @@ -15350,47 +15571,94 @@ $as_echo "$COMPILE_TYPE" >&6; } fi - if test "x$OPENJDK_TARGET_OS" = xmacosx; then - OPENJDK_TARGET_OS_EXPORT_DIR=macosx + if test "x$OPENJDK_BUILD_OS" = xmacosx; then + OPENJDK_BUILD_OS_EXPORT_DIR=macosx else - OPENJDK_TARGET_OS_EXPORT_DIR=${OPENJDK_TARGET_OS_TYPE} + OPENJDK_BUILD_OS_EXPORT_DIR=${OPENJDK_BUILD_OS_TYPE} fi - if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then + if test "x$OPENJDK_BUILD_CPU_BITS" = x64; then A_LP64="LP64:=" # -D_LP64=1 is only set on linux and mac. Setting on windows causes diff in # unpack200.exe - if test "x$OPENJDK_TARGET_OS" = xlinux || test "x$OPENJDK_TARGET_OS" = xmacosx; then - ADD_LP64="-D_LP64=1" - fi - fi - LP64=$A_LP64 - - if test "x$OPENJDK_BUILD_CPU_BITS" = x64; then if test "x$OPENJDK_BUILD_OS" = xlinux || test "x$OPENJDK_BUILD_OS" = xmacosx; then OPENJDK_BUILD_ADD_LP64="-D_LP64=1" fi fi + LP64=$A_LP64 + if test "x$COMPILE_TYPE" = "xcross"; then # FIXME: ... or should this include reduced builds..? - DEFINE_CROSS_COMPILE_ARCH="CROSS_COMPILE_ARCH:=$OPENJDK_TARGET_CPU_LEGACY" + DEFINE_CROSS_COMPILE_ARCH="CROSS_COMPILE_ARCH:=$OPENJDK_BUILD_CPU_LEGACY" else DEFINE_CROSS_COMPILE_ARCH="" fi - # ZERO_ARCHDEF is used to enable architecture-specific code - case "${OPENJDK_TARGET_CPU}" in - ppc) ZERO_ARCHDEF=PPC32 ;; - ppc64) ZERO_ARCHDEF=PPC64 ;; - s390*) ZERO_ARCHDEF=S390 ;; - sparc*) ZERO_ARCHDEF=SPARC ;; - x86_64*) ZERO_ARCHDEF=AMD64 ;; - x86) ZERO_ARCHDEF=IA32 ;; - *) ZERO_ARCHDEF=$(echo "${OPENJDK_TARGET_CPU_LEGACY_LIB}" | tr a-z A-Z) - esac + # Convert openjdk platform names to hotspot names + + HOTSPOT_BUILD_OS=${OPENJDK_BUILD_OS} + if test "x$OPENJDK_BUILD_OS" = xmacosx; then + HOTSPOT_BUILD_OS=bsd + fi + + + HOTSPOT_BUILD_OS_TYPE=${OPENJDK_BUILD_OS_TYPE} + if test "x$OPENJDK_BUILD_OS_TYPE" = xunix; then + HOTSPOT_BUILD_OS_TYPE=posix + fi + + + HOTSPOT_BUILD_CPU=${OPENJDK_BUILD_CPU} + if test "x$OPENJDK_BUILD_CPU" = xx86; then + HOTSPOT_BUILD_CPU=x86_32 + elif test "x$OPENJDK_BUILD_CPU" = xsparcv9; then + HOTSPOT_BUILD_CPU=sparc + elif test "x$OPENJDK_BUILD_CPU" = xppc64; then + HOTSPOT_BUILD_CPU=ppc_64 + elif test "x$OPENJDK_BUILD_CPU" = xppc64le; then + HOTSPOT_BUILD_CPU=ppc_64 + fi + + + # This is identical with OPENJDK_*, but define anyway for consistency. + HOTSPOT_BUILD_CPU_ARCH=${OPENJDK_BUILD_CPU_ARCH} + + + # Setup HOTSPOT_BUILD_CPU_DEFINE + if test "x$OPENJDK_BUILD_CPU" = xx86; then + HOTSPOT_BUILD_CPU_DEFINE=IA32 + elif test "x$OPENJDK_BUILD_CPU" = xx86_64; then + HOTSPOT_BUILD_CPU_DEFINE=AMD64 + elif test "x$OPENJDK_BUILD_CPU" = xsparcv9; then + HOTSPOT_BUILD_CPU_DEFINE=SPARC + elif test "x$OPENJDK_BUILD_CPU" = xaarch64; then + HOTSPOT_BUILD_CPU_DEFINE=AARCH64 + elif test "x$OPENJDK_BUILD_CPU" = xppc64; then + HOTSPOT_BUILD_CPU_DEFINE=PPC64 + elif test "x$OPENJDK_BUILD_CPU" = xppc64le; then + HOTSPOT_BUILD_CPU_DEFINE=PPC64 + + # The cpu defines below are for zero, we don't support them directly. + elif test "x$OPENJDK_BUILD_CPU" = xsparc; then + HOTSPOT_BUILD_CPU_DEFINE=SPARC + elif test "x$OPENJDK_BUILD_CPU" = xppc; then + HOTSPOT_BUILD_CPU_DEFINE=PPC32 + elif test "x$OPENJDK_BUILD_CPU" = xs390; then + HOTSPOT_BUILD_CPU_DEFINE=S390 + elif test "x$OPENJDK_BUILD_CPU" = ss390x; then + HOTSPOT_BUILD_CPU_DEFINE=S390 + fi + + + + + # ZERO_ARCHDEF is used to enable architecture-specific code. + # This is used in legacy hotspot build. + ZERO_ARCHDEF="$HOTSPOT_TARGET_CPU_DEFINE" + @@ -15929,98 +16197,6 @@ fi $as_echo "$JDK_VARIANT" >&6; } - -# Check whether --with-jvm-interpreter was given. -if test "${with_jvm_interpreter+set}" = set; then : - withval=$with_jvm_interpreter; -fi - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking which interpreter of the JVM to build" >&5 -$as_echo_n "checking which interpreter of the JVM to build... " >&6; } - if test "x$with_jvm_interpreter" = x; then - JVM_INTERPRETER="template" - else - JVM_INTERPRETER="$with_jvm_interpreter" - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JVM_INTERPRETER" >&5 -$as_echo "$JVM_INTERPRETER" >&6; } - - if test "x$JVM_INTERPRETER" != xtemplate && test "x$JVM_INTERPRETER" != xcpp; then - as_fn_error $? "The available JVM interpreters are: template, cpp" "$LINENO" 5 - fi - - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variants of the JVM to build" >&5 -$as_echo_n "checking which variants of the JVM to build... " >&6; } - -# Check whether --with-jvm-variants was given. -if test "${with_jvm_variants+set}" = set; then : - withval=$with_jvm_variants; -fi - - - if test "x$with_jvm_variants" = x; then - with_jvm_variants="server" - fi - - JVM_VARIANTS=",$with_jvm_variants," - TEST_VARIANTS=`$ECHO "$JVM_VARIANTS" | $SED -e 's/server,//' -e 's/client,//' -e 's/minimal1,//' -e 's/zero,//' -e 's/zeroshark,//' -e 's/core,//'` - - if test "x$TEST_VARIANTS" != "x,"; then - as_fn_error $? "The available JVM variants are: server, client, minimal1, zero, zeroshark, core" "$LINENO" 5 - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_jvm_variants" >&5 -$as_echo "$with_jvm_variants" >&6; } - - JVM_VARIANT_SERVER=`$ECHO "$JVM_VARIANTS" | $SED -e '/,server,/!s/.*/false/g' -e '/,server,/s/.*/true/g'` - JVM_VARIANT_CLIENT=`$ECHO "$JVM_VARIANTS" | $SED -e '/,client,/!s/.*/false/g' -e '/,client,/s/.*/true/g'` - JVM_VARIANT_MINIMAL1=`$ECHO "$JVM_VARIANTS" | $SED -e '/,minimal1,/!s/.*/false/g' -e '/,minimal1,/s/.*/true/g'` - JVM_VARIANT_ZERO=`$ECHO "$JVM_VARIANTS" | $SED -e '/,zero,/!s/.*/false/g' -e '/,zero,/s/.*/true/g'` - JVM_VARIANT_ZEROSHARK=`$ECHO "$JVM_VARIANTS" | $SED -e '/,zeroshark,/!s/.*/false/g' -e '/,zeroshark,/s/.*/true/g'` - JVM_VARIANT_CORE=`$ECHO "$JVM_VARIANTS" | $SED -e '/,core,/!s/.*/false/g' -e '/,core,/s/.*/true/g'` - - if test "x$JVM_VARIANT_CLIENT" = xtrue; then - if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then - as_fn_error $? "You cannot build a client JVM for a 64-bit machine." "$LINENO" 5 - fi - fi - if test "x$JVM_VARIANT_MINIMAL1" = xtrue; then - if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then - as_fn_error $? "You cannot build a minimal JVM for a 64-bit machine." "$LINENO" 5 - fi - fi - - # Replace the commas with AND for use in the build directory name. - ANDED_JVM_VARIANTS=`$ECHO "$JVM_VARIANTS" | $SED -e 's/^,//' -e 's/,$//' -e 's/,/AND/g'` - COUNT_VARIANTS=`$ECHO "$JVM_VARIANTS" | $SED -e 's/server,/1/' -e 's/client,/1/' -e 's/minimal1,/1/' -e 's/zero,/1/' -e 's/zeroshark,/1/' -e 's/core,/1/'` - if test "x$COUNT_VARIANTS" != "x,1"; then - BUILDING_MULTIPLE_JVM_VARIANTS=yes - else - BUILDING_MULTIPLE_JVM_VARIANTS=no - fi - - if test "x$JVM_VARIANT_ZERO" = xtrue && test "x$BUILDING_MULTIPLE_JVM_VARIANTS" = xyes; then - as_fn_error $? "You cannot build multiple variants with zero." "$LINENO" 5 - fi - - - - - - - - - - if test "x$OPENJDK_TARGET_OS" = "xmacosx"; then - MACOSX_UNIVERSAL="true" - fi - - - - DEBUG_LEVEL="release" { $as_echo "$as_me:${as_lineno-$LINENO}: checking which debug level to use" >&5 $as_echo_n "checking which debug level to use... " >&6; } @@ -16056,105 +16232,88 @@ $as_echo "$DEBUG_LEVEL" >&6; } as_fn_error $? "Allowed debug levels are: release, fastdebug, slowdebug and optimized" "$LINENO" 5 fi + # Translate DEBUG_LEVEL to debug level used by Hotspot + HOTSPOT_DEBUG_LEVEL="$DEBUG_LEVEL" + if test "x$DEBUG_LEVEL" = xrelease; then + HOTSPOT_DEBUG_LEVEL="product" + elif test "x$DEBUG_LEVEL" = xslowdebug; then + HOTSPOT_DEBUG_LEVEL="debug" + fi - case $DEBUG_LEVEL in - release ) - VARIANT="OPT" - FASTDEBUG="false" - DEBUG_CLASSFILES="false" - BUILD_VARIANT_RELEASE="" - HOTSPOT_DEBUG_LEVEL="product" - HOTSPOT_EXPORT="product" - ;; - fastdebug ) - VARIANT="DBG" - FASTDEBUG="true" - DEBUG_CLASSFILES="true" - BUILD_VARIANT_RELEASE="-fastdebug" - HOTSPOT_DEBUG_LEVEL="fastdebug" - HOTSPOT_EXPORT="fastdebug" - ;; - slowdebug ) - VARIANT="DBG" - FASTDEBUG="false" - DEBUG_CLASSFILES="true" - BUILD_VARIANT_RELEASE="-debug" - HOTSPOT_DEBUG_LEVEL="debug" - HOTSPOT_EXPORT="debug" - ;; - optimized ) - VARIANT="OPT" - FASTDEBUG="false" - DEBUG_CLASSFILES="false" - BUILD_VARIANT_RELEASE="-optimized" - HOTSPOT_DEBUG_LEVEL="optimized" - HOTSPOT_EXPORT="optimized" - ;; - esac - - # The debug level 'optimized' is a little special because it is currently only - # applicable to the HotSpot build where it means to build a completely - # optimized version of the VM without any debugging code (like for the - # 'release' debug level which is called 'product' in the HotSpot build) but - # with the exception that it can contain additional code which is otherwise - # protected by '#ifndef PRODUCT' macros. These 'optimized' builds are used to - # test new and/or experimental features which are not intended for customer - # shipment. Because these new features need to be tested and benchmarked in - # real world scenarios, we want to build the containing JDK at the 'release' - # debug level. if test "x$DEBUG_LEVEL" = xoptimized; then + # The debug level 'optimized' is a little special because it is currently only + # applicable to the HotSpot build where it means to build a completely + # optimized version of the VM without any debugging code (like for the + # 'release' debug level which is called 'product' in the HotSpot build) but + # with the exception that it can contain additional code which is otherwise + # protected by '#ifndef PRODUCT' macros. These 'optimized' builds are used to + # test new and/or experimental features which are not intended for customer + # shipment. Because these new features need to be tested and benchmarked in + # real world scenarios, we want to build the containing JDK at the 'release' + # debug level. DEBUG_LEVEL="release" fi - ##### - # Generate the legacy makefile targets for hotspot. - # The hotspot api for selecting the build artifacts, really, needs to be improved. - # JDK-7195896 will fix this on the hotspot side by using the JVM_VARIANT_* variables to - # determine what needs to be built. All we will need to set here is all_product, all_fastdebug etc - # But until then ... - HOTSPOT_TARGET="" - if test "x$JVM_VARIANT_SERVER" = xtrue; then - HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL} " - fi - if test "x$JVM_VARIANT_CLIENT" = xtrue; then - HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}1 " - fi - if test "x$JVM_VARIANT_MINIMAL1" = xtrue; then - HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}minimal1 " - fi - if test "x$JVM_VARIANT_ZERO" = xtrue; then - HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}zero " - fi - if test "x$JVM_VARIANT_ZEROSHARK" = xtrue; then - HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}shark " - fi +# Check whether --with-jvm-variants was given. +if test "${with_jvm_variants+set}" = set; then : + withval=$with_jvm_variants; +fi - if test "x$JVM_VARIANT_CORE" = xtrue; then - HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}core " - fi - HOTSPOT_TARGET="$HOTSPOT_TARGET docs export_$HOTSPOT_EXPORT" + if test "x$with_jvm_variants" = x; then + with_jvm_variants="server" + fi + JVM_VARIANTS_OPT="$with_jvm_variants" - # On Macosx universal binaries are produced, but they only contain - # 64 bit intel. This invalidates control of which jvms are built - # from configure, but only server is valid anyway. Fix this - # when hotspot makefiles are rewritten. - if test "x$MACOSX_UNIVERSAL" = xtrue; then - HOTSPOT_TARGET=universal_${HOTSPOT_EXPORT} + # Has the user listed more than one variant? + # Additional [] needed to keep m4 from mangling shell constructs. + if [[ "$JVM_VARIANTS_OPT" =~ "," ]] ; then + BUILDING_MULTIPLE_JVM_VARIANTS=true + else + BUILDING_MULTIPLE_JVM_VARIANTS=false fi + # Replace the commas with AND for use in the build directory name. + JVM_VARIANTS_WITH_AND=`$ECHO "$JVM_VARIANTS_OPT" | $SED -e 's/,/AND/g'` - ##### + { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variants of the JVM to build" >&5 +$as_echo_n "checking which variants of the JVM to build... " >&6; } + # JVM_VARIANTS is a space-separated list. + # Also use minimal, not minimal1 (which is kept for backwards compatibility). + JVM_VARIANTS=`$ECHO $JVM_VARIANTS_OPT | $SED -e 's/,/ /g' -e 's/minimal1/minimal/'` + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JVM_VARIANTS" >&5 +$as_echo "$JVM_VARIANTS" >&6; } + # Check that the selected variants are valid + # grep filter function inspired by a comment to http://stackoverflow.com/a/1617326 + INVALID_VARIANTS=`$GREP -Fvx "${VALID_JVM_VARIANTS// /$'\n'}" <<< "${JVM_VARIANTS// /$'\n'}"` + if test "x$INVALID_VARIANTS" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Unknown variant(s) specified: $INVALID_VARIANTS" >&5 +$as_echo "$as_me: Unknown variant(s) specified: $INVALID_VARIANTS" >&6;} + as_fn_error $? "The available JVM variants are: $VALID_JVM_VARIANTS" "$LINENO" 5 + fi + + # All "special" variants share the same output directory ("server") + VALID_MULTIPLE_JVM_VARIANTS="server client minimal" + INVALID_MULTIPLE_VARIANTS=`$GREP -Fvx "${VALID_MULTIPLE_JVM_VARIANTS// /$'\n'}" <<< "${JVM_VARIANTS// /$'\n'}"` + if test "x$INVALID_MULTIPLE_VARIANTS" != x && test "x$BUILDING_MULTIPLE_JVM_VARIANTS" = xtrue; then + as_fn_error $? "You cannot build multiple variants with anything else than $VALID_MULTIPLE_JVM_VARIANTS." "$LINENO" 5 + fi + if [[ " $JVM_VARIANTS " =~ " zero " ]] || [[ " $JVM_VARIANTS " =~ " zeroshark " ]] ; then + # zero behaves as a platform and rewrites these values. This is really weird. :( + # We are guaranteed that we do not build any other variants when building zero. + HOTSPOT_TARGET_CPU=zero + HOTSPOT_TARGET_CPU_ARCH=zero + fi # With basic setup done, call the custom early hook. @@ -16603,8 +16762,8 @@ $as_echo "$as_me: WARNING: Both SYSROOT and --with-sdk-name are set, only SYSROO if test "x$OPENJDK_BUILD_OS" = "xsolaris"; then - # Add extra search paths on solaris for utilities like ar and as etc... - PATH="$PATH:/usr/ccs/bin:/usr/sfw/bin:/opt/csw/bin" + # Add extra search paths on solaris for utilities like ar, as, dtrace etc... + PATH="$PATH:/usr/ccs/bin:/usr/sfw/bin:/opt/csw/bin:/usr/sbin" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 @@ -16643,7 +16802,7 @@ $as_echo_n "checking where to store configuration... " >&6; } if test "x${CONF_NAME}" = x; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: in default location" >&5 $as_echo "in default location" >&6; } - CONF_NAME="${OPENJDK_TARGET_OS}-${OPENJDK_TARGET_CPU}-${JDK_VARIANT}-${ANDED_JVM_VARIANTS}-${DEBUG_LEVEL}" + CONF_NAME="${OPENJDK_TARGET_OS}-${OPENJDK_TARGET_CPU}-${JDK_VARIANT}-${JVM_VARIANTS_WITH_AND}-${DEBUG_LEVEL}" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: in build directory with custom name" >&5 $as_echo "in build directory with custom name" >&6; } @@ -22143,20 +22302,20 @@ $as_echo "$tool_specified" >&6; } # Publish this variable in the help. - if [ -z "${PATCH+x}" ]; then + if [ -z "${DTRACE+x}" ]; then # The variable is not set by user, try to locate tool using the code snippet - for ac_prog in gpatch patch + for ac_prog in dtrace do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_PATCH+:} false; then : +if ${ac_cv_path_DTRACE+:} false; then : $as_echo_n "(cached) " >&6 else - case $PATCH in + case $DTRACE in [\\/]* | ?:[\\/]*) - ac_cv_path_PATCH="$PATCH" # Let the user override the test with a path. + ac_cv_path_DTRACE="$DTRACE" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR @@ -22166,7 +22325,7 @@ do test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_PATCH="$as_dir/$ac_word$ac_exec_ext" + ac_cv_path_DTRACE="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -22177,44 +22336,44 @@ IFS=$as_save_IFS ;; esac fi -PATCH=$ac_cv_path_PATCH -if test -n "$PATCH"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PATCH" >&5 -$as_echo "$PATCH" >&6; } +DTRACE=$ac_cv_path_DTRACE +if test -n "$DTRACE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DTRACE" >&5 +$as_echo "$DTRACE" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi - test -n "$PATCH" && break + test -n "$DTRACE" && break done else # The variable is set, but is it from the command line or the environment? - # Try to remove the string !PATCH! from our list. - try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!PATCH!/} + # Try to remove the string !DTRACE! from our list. + try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!DTRACE!/} if test "x$try_remove_var" = "x$CONFIGURE_OVERRIDDEN_VARIABLES"; then # If it failed, the variable was not from the command line. Ignore it, # but warn the user (except for BASH, which is always set by the calling BASH). - if test "xPATCH" != xBASH; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of PATCH from the environment. Use command line variables instead." >&5 -$as_echo "$as_me: WARNING: Ignoring value of PATCH from the environment. Use command line variables instead." >&2;} + if test "xDTRACE" != xBASH; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of DTRACE from the environment. Use command line variables instead." >&5 +$as_echo "$as_me: WARNING: Ignoring value of DTRACE from the environment. Use command line variables instead." >&2;} fi # Try to locate tool using the code snippet - for ac_prog in gpatch patch + for ac_prog in dtrace do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_PATCH+:} false; then : +if ${ac_cv_path_DTRACE+:} false; then : $as_echo_n "(cached) " >&6 else - case $PATCH in + case $DTRACE in [\\/]* | ?:[\\/]*) - ac_cv_path_PATCH="$PATCH" # Let the user override the test with a path. + ac_cv_path_DTRACE="$DTRACE" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR @@ -22224,7 +22383,7 @@ do test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_PATCH="$as_dir/$ac_word$ac_exec_ext" + ac_cv_path_DTRACE="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -22235,17 +22394,17 @@ IFS=$as_save_IFS ;; esac fi -PATCH=$ac_cv_path_PATCH -if test -n "$PATCH"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PATCH" >&5 -$as_echo "$PATCH" >&6; } +DTRACE=$ac_cv_path_DTRACE +if test -n "$DTRACE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DTRACE" >&5 +$as_echo "$DTRACE" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi - test -n "$PATCH" && break + test -n "$DTRACE" && break done else @@ -22257,21 +22416,218 @@ done CONFIGURE_OVERRIDDEN_VARIABLES="$try_remove_var" # Check if we try to supply an empty value - if test "x$PATCH" = x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Setting user supplied tool PATCH= (no value)" >&5 -$as_echo "$as_me: Setting user supplied tool PATCH= (no value)" >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PATCH" >&5 -$as_echo_n "checking for PATCH... " >&6; } + if test "x$DTRACE" = x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Setting user supplied tool DTRACE= (no value)" >&5 +$as_echo "$as_me: Setting user supplied tool DTRACE= (no value)" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for DTRACE" >&5 +$as_echo_n "checking for DTRACE... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5 $as_echo "disabled" >&6; } else # Check if the provided tool contains a complete path. - tool_specified="$PATCH" + tool_specified="$DTRACE" tool_basename="${tool_specified##*/}" if test "x$tool_basename" = "x$tool_specified"; then # A command without a complete path is provided, search $PATH. - { $as_echo "$as_me:${as_lineno-$LINENO}: Will search for user supplied tool PATCH=$tool_basename" >&5 -$as_echo "$as_me: Will search for user supplied tool PATCH=$tool_basename" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: Will search for user supplied tool DTRACE=$tool_basename" >&5 +$as_echo "$as_me: Will search for user supplied tool DTRACE=$tool_basename" >&6;} + # Extract the first word of "$tool_basename", so it can be a program name with args. +set dummy $tool_basename; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_DTRACE+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $DTRACE in + [\\/]* | ?:[\\/]*) + ac_cv_path_DTRACE="$DTRACE" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_DTRACE="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +DTRACE=$ac_cv_path_DTRACE +if test -n "$DTRACE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DTRACE" >&5 +$as_echo "$DTRACE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "x$DTRACE" = x; then + as_fn_error $? "User supplied tool $tool_basename could not be found" "$LINENO" 5 + fi + else + # Otherwise we believe it is a complete path. Use it as it is. + { $as_echo "$as_me:${as_lineno-$LINENO}: Will use user supplied tool DTRACE=$tool_specified" >&5 +$as_echo "$as_me: Will use user supplied tool DTRACE=$tool_specified" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for DTRACE" >&5 +$as_echo_n "checking for DTRACE... " >&6; } + if test ! -x "$tool_specified"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 +$as_echo "not found" >&6; } + as_fn_error $? "User supplied tool DTRACE=$tool_specified does not exist or is not executable" "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tool_specified" >&5 +$as_echo "$tool_specified" >&6; } + fi + fi + fi + + fi + + + + + # Publish this variable in the help. + + + if [ -z "${PATCH+x}" ]; then + # The variable is not set by user, try to locate tool using the code snippet + for ac_prog in gpatch patch +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PATCH+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PATCH in + [\\/]* | ?:[\\/]*) + ac_cv_path_PATCH="$PATCH" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PATCH="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PATCH=$ac_cv_path_PATCH +if test -n "$PATCH"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PATCH" >&5 +$as_echo "$PATCH" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$PATCH" && break +done + + else + # The variable is set, but is it from the command line or the environment? + + # Try to remove the string !PATCH! from our list. + try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!PATCH!/} + if test "x$try_remove_var" = "x$CONFIGURE_OVERRIDDEN_VARIABLES"; then + # If it failed, the variable was not from the command line. Ignore it, + # but warn the user (except for BASH, which is always set by the calling BASH). + if test "xPATCH" != xBASH; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of PATCH from the environment. Use command line variables instead." >&5 +$as_echo "$as_me: WARNING: Ignoring value of PATCH from the environment. Use command line variables instead." >&2;} + fi + # Try to locate tool using the code snippet + for ac_prog in gpatch patch +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PATCH+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PATCH in + [\\/]* | ?:[\\/]*) + ac_cv_path_PATCH="$PATCH" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PATCH="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PATCH=$ac_cv_path_PATCH +if test -n "$PATCH"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PATCH" >&5 +$as_echo "$PATCH" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$PATCH" && break +done + + else + # If it succeeded, then it was overridden by the user. We will use it + # for the tool. + + # First remove it from the list of overridden variables, so we can test + # for unknown variables in the end. + CONFIGURE_OVERRIDDEN_VARIABLES="$try_remove_var" + + # Check if we try to supply an empty value + if test "x$PATCH" = x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Setting user supplied tool PATCH= (no value)" >&5 +$as_echo "$as_me: Setting user supplied tool PATCH= (no value)" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PATCH" >&5 +$as_echo_n "checking for PATCH... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5 +$as_echo "disabled" >&6; } + else + # Check if the provided tool contains a complete path. + tool_specified="$PATCH" + tool_basename="${tool_specified##*/}" + if test "x$tool_basename" = "x$tool_specified"; then + # A command without a complete path is provided, search $PATH. + { $as_echo "$as_me:${as_lineno-$LINENO}: Will search for user supplied tool PATCH=$tool_basename" >&5 +$as_echo "$as_me: Will search for user supplied tool PATCH=$tool_basename" >&6;} # Extract the first word of "$tool_basename", so it can be a program name with args. set dummy $tool_basename; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 @@ -23422,10 +23778,7 @@ fi # Should we build the serviceability agent (SA)? INCLUDE_SA=true - if test "x$JVM_VARIANT_ZERO" = xtrue ; then - INCLUDE_SA=false - fi - if test "x$JVM_VARIANT_ZEROSHARK" = xtrue ; then + if [[ " $JVM_VARIANTS " =~ " zero " ]] || [[ " $JVM_VARIANTS " =~ " zeroshark " ]] ; then INCLUDE_SA=false fi if test "x$OPENJDK_TARGET_OS" = xaix ; then @@ -23487,22 +23840,6 @@ $as_echo "yes (default)" >&6; } - # Control wether Hotspot runs Queens test after build. - # Check whether --enable-hotspot-test-in-build was given. -if test "${enable_hotspot_test_in_build+set}" = set; then : - enableval=$enable_hotspot_test_in_build; -else - enable_hotspot_test_in_build=no -fi - - if test "x$enable_hotspot_test_in_build" = "xyes"; then - TEST_IN_BUILD=true - else - TEST_IN_BUILD=false - fi - - - # Warn user that old version arguments are deprecated. @@ -23553,6 +23890,7 @@ fi + # Override version from arguments # If --with-version-string is set, process it first. It is possible to @@ -30625,6 +30963,10 @@ fi + + + + # The global CFLAGS and LDLAGS variables are used by configure tests and # should include the extra parameters CFLAGS="$EXTRA_CFLAGS" @@ -46752,6 +47094,17 @@ $as_echo "yes" >&6; } fi + # Setup hotspot lecagy names for toolchains + HOTSPOT_TOOLCHAIN_TYPE=$TOOLCHAIN_TYPE + if test "x$TOOLCHAIN_TYPE" = xclang; then + HOTSPOT_TOOLCHAIN_TYPE=gcc + elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then + HOTSPOT_TOOLCHAIN_TYPE=sparcWorks + elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + HOTSPOT_TOOLCHAIN_TYPE=visCPP + fi + + # Setup the JTReg Regression Test Harness. @@ -47231,8 +47584,10 @@ $as_echo "no" >&6; } # On Windows, we need to set RC flags. if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then RC_FLAGS="-nologo -l0x409" + JVM_RCFLAGS="-nologo" if test "x$DEBUG_LEVEL" = xrelease; then RC_FLAGS="$RC_FLAGS -DNDEBUG" + JVM_RCFLAGS="$JVM_RCFLAGS -DNDEBUG" fi # The version variables used to create RC_FLAGS may be overridden @@ -47248,9 +47603,20 @@ $as_echo "no" >&6; } -D\"JDK_COPYRIGHT=Copyright \xA9 $COPYRIGHT_YEAR\" \ -D\"JDK_NAME=\$(PRODUCT_NAME) \$(JDK_RC_PLATFORM_NAME) \$(VERSION_MAJOR)\" \ -D\"JDK_FVER=\$(subst .,\$(COMMA),\$(VERSION_NUMBER_FOUR_POSITIONS))\"" + + JVM_RCFLAGS="$JVM_RCFLAGS \ + -D\"HS_BUILD_ID=\$(VERSION_STRING)\" \ + -D\"HS_COMPANY=\$(COMPANY_NAME)\" \ + -D\"JDK_DOTVER=\$(VERSION_NUMBER_FOUR_POSITIONS)\" \ + -D\"HS_COPYRIGHT=Copyright $COPYRIGHT_YEAR\" \ + -D\"HS_NAME=\$(PRODUCT_NAME) \$(VERSION_SHORT)\" \ + -D\"JDK_VER=\$(subst .,\$(COMMA),\$(VERSION_NUMBER_FOUR_POSITIONS))\" \ + -D\"HS_FNAME=jvm.dll\" \ + -D\"HS_INTERNAL_NAME=jvm\"" fi + if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then # silence copyright notice and other headers. COMMON_CCXXFLAGS="$COMMON_CCXXFLAGS -nologo" @@ -47416,6 +47782,10 @@ done CXXFLAGS_JDK="${CXXFLAGS_JDK}${ADDED_CXXFLAGS}" LDFLAGS_JDK="${LDFLAGS_JDK}${ADDED_LDFLAGS}" + JVM_CFLAGS="$JVM_CFLAGS $ADDED_CFLAGS" + JVM_LDFLAGS="$JVM_LDFLAGS $ADDED_LDFLAGS" + JVM_ASFLAGS="$JVM_ASFLAGS $ADDED_CFLAGS" + elif test "x$COMPILE_TYPE" = xreduced; then if test "x$OPENJDK_TARGET_OS_TYPE" = xunix; then # Specify -m if running reduced on unix platforms @@ -47436,8 +47806,17 @@ done CXXFLAGS_JDK="${CXXFLAGS_JDK}${ADDED_CXXFLAGS}" LDFLAGS_JDK="${LDFLAGS_JDK}${ADDED_LDFLAGS}" + JVM_CFLAGS="$JVM_CFLAGS $ADDED_CFLAGS" + JVM_LDFLAGS="$JVM_LDFLAGS $ADDED_LDFLAGS" + JVM_ASFLAGS="$JVM_ASFLAGS $ADDED_CFLAGS" + fi fi + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + JVM_CFLAGS="$JVM_CFLAGS ${COMPILER_TARGET_BITS_FLAG}${OPENJDK_TARGET_CPU_BITS}" + JVM_LDFLAGS="$JVM_LDFLAGS ${COMPILER_TARGET_BITS_FLAG}${OPENJDK_TARGET_CPU_BITS}" + JVM_ASFLAGS="$JVM_ASFLAGS ${COMPILER_TARGET_BITS_FLAG}${OPENJDK_TARGET_CPU_BITS}" + fi # Make compilation sanity check for ac_header in stdio.h @@ -47562,6 +47941,10 @@ $as_echo "$as_me: Retrying with platforms compiler target bits flag to ${COMPILE CXXFLAGS_JDK="${CXXFLAGS_JDK}${ADDED_CXXFLAGS}" LDFLAGS_JDK="${LDFLAGS_JDK}${ADDED_LDFLAGS}" + JVM_CFLAGS="$JVM_CFLAGS $ADDED_CFLAGS" + JVM_LDFLAGS="$JVM_LDFLAGS $ADDED_LDFLAGS" + JVM_ASFLAGS="$JVM_ASFLAGS $ADDED_CFLAGS" + # We have to unset 'ac_cv_sizeof_int_p' first, otherwise AC_CHECK_SIZEOF will use the previously cached value! unset ac_cv_sizeof_int_p @@ -47908,6 +48291,7 @@ $as_echo "$ac_cv_c_bigendian" >&6; } SHARED_LIBRARY_FLAGS ='-undefined dynamic_lookup' else SHARED_LIBRARY_FLAGS="-dynamiclib -compatibility_version 1.0.0 -current_version 1.0.0 $PICFLAG" + JVM_CFLAGS="$JVM_CFLAGS $PICFLAG" fi SET_EXECUTABLE_ORIGIN='-Wl,-rpath,@loader_path/.' SET_SHARED_LIBRARY_ORIGIN="$SET_EXECUTABLE_ORIGIN" @@ -47933,6 +48317,10 @@ $as_echo "$ac_cv_c_bigendian" >&6; } SET_SHARED_LIBRARY_ORIGIN="$SET_EXECUTABLE_ORIGIN" SET_SHARED_LIBRARY_NAME='-Wl,-install_name,@rpath/$1' SET_SHARED_LIBRARY_MAPFILE='-Wl,-exported_symbols_list,$1' + + if test "x$STATIC_BUILD" = xfalse; then + JVM_CFLAGS="$JVM_CFLAGS -fPIC" + fi else # Default works for linux, might work on other platforms as well. PICFLAG='-fPIC' @@ -47992,11 +48380,6 @@ $as_echo "$ac_cv_c_bigendian" >&6; } - if test "x$OPENJDK_TARGET_OS" = xsolaris; then - CFLAGS_JDK="${CFLAGS_JDK} -D__solaris__" - CXXFLAGS_JDK="${CXXFLAGS_JDK} -D__solaris__" - CFLAGS_JDKLIB_EXTRA='-xstrconst' - fi # The (cross) compiler is now configured, we can now test capabilities # of the target platform. @@ -48054,6 +48437,22 @@ $as_echo "$ac_cv_c_bigendian" >&6; } + # Debug symbols for JVM_CFLAGS + if test "x$TOOLCHAIN_TYPE" = xsolstudio; then + JVM_CFLAGS_SYMBOLS="$JVM_CFLAGS_SYMBOLS -xs" + if test "x$DEBUG_LEVEL" = xslowdebug; then + JVM_CFLAGS_SYMBOLS="$JVM_CFLAGS_SYMBOLS -g" + else + # -g0 does not disable inlining, which -g does. + JVM_CFLAGS_SYMBOLS="$JVM_CFLAGS_SYMBOLS -g0" + fi + elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + JVM_CFLAGS_SYMBOLS="$JVM_CFLAGS_SYMBOLS -Z7 -d2Zi+" + else + JVM_CFLAGS_SYMBOLS="$JVM_CFLAGS_SYMBOLS -g" + fi + + # bounds, memory and behavior checking options if test "x$TOOLCHAIN_TYPE" = xgcc; then case $DEBUG_LEVEL in @@ -48064,7 +48463,7 @@ $as_echo "$ac_cv_c_bigendian" >&6; } # no adjustment ;; slowdebug ) - # FIXME: By adding this to C(XX)FLAGS_DEBUG_OPTIONS it + # FIXME: By adding this to C(XX)FLAGS_DEBUG_OPTIONS/JVM_CFLAGS_SYMBOLS it # get's added conditionally on whether we produce debug symbols or not. # This is most likely not really correct. @@ -48339,40 +48738,59 @@ $as_echo "$supports" >&6; } CFLAGS_DEBUG_OPTIONS="$STACK_PROTECTOR_CFLAG --param ssp-buffer-size=1" CXXFLAGS_DEBUG_OPTIONS="$STACK_PROTECTOR_CFLAG --param ssp-buffer-size=1" + if test "x$STACK_PROTECTOR_CFLAG" != x; then + JVM_CFLAGS_SYMBOLS="$JVM_CFLAGS_SYMBOLS $STACK_PROTECTOR_CFLAG --param ssp-buffer-size=1" + fi ;; esac fi + if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + if test "x$DEBUG_LEVEL" != xrelease; then + if test "x$OPENJDK_TARGET_CPU" = xx86_64; then + JVM_CFLAGS="$JVM_CFLAGS -homeparams" + fi + fi + fi + # Optimization levels if test "x$TOOLCHAIN_TYPE" = xsolstudio; then CC_HIGHEST="$CC_HIGHEST -fns -fsimple -fsingle -xbuiltin=%all -xdepend -xrestrict -xlibmil" if test "x$OPENJDK_TARGET_CPU_ARCH" = "xx86"; then # FIXME: seems we always set -xregs=no%frameptr; put it elsewhere more global? + C_O_FLAG_HIGHEST_JVM="-xO4" C_O_FLAG_HIGHEST="-xO4 -Wu,-O4~yz $CC_HIGHEST -xalias_level=basic -xregs=no%frameptr" C_O_FLAG_HI="-xO4 -Wu,-O4~yz -xregs=no%frameptr" C_O_FLAG_NORM="-xO2 -Wu,-O2~yz -xregs=no%frameptr" C_O_FLAG_DEBUG="-xregs=no%frameptr" + C_O_FLAG_DEBUG_JVM="" C_O_FLAG_NONE="-xregs=no%frameptr" + CXX_O_FLAG_HIGHEST_JVM="-xO4" CXX_O_FLAG_HIGHEST="-xO4 -Qoption ube -O4~yz $CC_HIGHEST -xregs=no%frameptr" CXX_O_FLAG_HI="-xO4 -Qoption ube -O4~yz -xregs=no%frameptr" CXX_O_FLAG_NORM="-xO2 -Qoption ube -O2~yz -xregs=no%frameptr" CXX_O_FLAG_DEBUG="-xregs=no%frameptr" + CXX_O_FLAG_DEBUG_JVM="" CXX_O_FLAG_NONE="-xregs=no%frameptr" if test "x$OPENJDK_TARGET_CPU_BITS" = "x32"; then C_O_FLAG_HIGHEST="$C_O_FLAG_HIGHEST -xchip=pentium" CXX_O_FLAG_HIGHEST="$CXX_O_FLAG_HIGHEST -xchip=pentium" fi elif test "x$OPENJDK_TARGET_CPU_ARCH" = "xsparc"; then + C_O_FLAG_HIGHEST_JVM="-xO4" C_O_FLAG_HIGHEST="-xO4 -Wc,-Qrm-s -Wc,-Qiselect-T0 $CC_HIGHEST -xalias_level=basic -xprefetch=auto,explicit -xchip=ultra" C_O_FLAG_HI="-xO4 -Wc,-Qrm-s -Wc,-Qiselect-T0" C_O_FLAG_NORM="-xO2 -Wc,-Qrm-s -Wc,-Qiselect-T0" C_O_FLAG_DEBUG="" + C_O_FLAG_DEBUG_JVM="" C_O_FLAG_NONE="" + CXX_O_FLAG_HIGHEST_JVM="-xO4" CXX_O_FLAG_HIGHEST="-xO4 -Qoption cg -Qrm-s -Qoption cg -Qiselect-T0 $CC_HIGHEST -xprefetch=auto,explicit -xchip=ultra" CXX_O_FLAG_HI="-xO4 -Qoption cg -Qrm-s -Qoption cg -Qiselect-T0" CXX_O_FLAG_NORM="-xO2 -Qoption cg -Qrm-s -Qoption cg -Qiselect-T0" CXX_O_FLAG_DEBUG="" + CXX_O_FLAG_DEBUG_JVM="" CXX_O_FLAG_NONE="" fi else @@ -48382,48 +48800,75 @@ $as_echo "$supports" >&6; } if test "x$OPENJDK_TARGET_OS" = xmacosx; then # On MacOSX we optimize for size, something # we should do for all platforms? + C_O_FLAG_HIGHEST_JVM="-Os" C_O_FLAG_HIGHEST="-Os" C_O_FLAG_HI="-Os" C_O_FLAG_NORM="-Os" + C_O_FLAG_SIZE="-Os" else + C_O_FLAG_HIGHEST_JVM="-O3" C_O_FLAG_HIGHEST="-O3" C_O_FLAG_HI="-O3" C_O_FLAG_NORM="-O2" + C_O_FLAG_SIZE="-Os" fi C_O_FLAG_DEBUG="-O0" + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + C_O_FLAG_DEBUG_JVM="" + elif test "x$OPENJDK_TARGET_OS" = xlinux; then + C_O_FLAG_DEBUG_JVM="-O0" + fi C_O_FLAG_NONE="-O0" elif test "x$TOOLCHAIN_TYPE" = xclang; then if test "x$OPENJDK_TARGET_OS" = xmacosx; then # On MacOSX we optimize for size, something # we should do for all platforms? + C_O_FLAG_HIGHEST_JVM="-Os" C_O_FLAG_HIGHEST="-Os" C_O_FLAG_HI="-Os" C_O_FLAG_NORM="-Os" + C_O_FLAG_SIZE="-Os" else + C_O_FLAG_HIGHEST_JVM="-O3" C_O_FLAG_HIGHEST="-O3" C_O_FLAG_HI="-O3" C_O_FLAG_NORM="-O2" + C_O_FLAG_SIZE="-Os" fi C_O_FLAG_DEBUG="-O0" + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + C_O_FLAG_DEBUG_JVM="" + elif test "x$OPENJDK_TARGET_OS" = xlinux; then + C_O_FLAG_DEBUG_JVM="-O0" + fi C_O_FLAG_NONE="-O0" elif test "x$TOOLCHAIN_TYPE" = xxlc; then + C_O_FLAG_HIGHEST_JVM="-O3" C_O_FLAG_HIGHEST="-O3" C_O_FLAG_HI="-O3 -qstrict" C_O_FLAG_NORM="-O2" C_O_FLAG_DEBUG="-qnoopt" + # FIXME: Value below not verified. + C_O_FLAG_DEBUG_JVM="" C_O_FLAG_NONE="-qnoopt" elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + C_O_FLAG_HIGHEST_JVM="-O2 -Oy-" C_O_FLAG_HIGHEST="-O2" C_O_FLAG_HI="-O1" C_O_FLAG_NORM="-O1" C_O_FLAG_DEBUG="-Od" + C_O_FLAG_DEBUG_JVM="" C_O_FLAG_NONE="-Od" + C_O_FLAG_SIZE="-Os" fi + CXX_O_FLAG_HIGHEST_JVM="$C_O_FLAG_HIGHEST_JVM" CXX_O_FLAG_HIGHEST="$C_O_FLAG_HIGHEST" CXX_O_FLAG_HI="$C_O_FLAG_HI" CXX_O_FLAG_NORM="$C_O_FLAG_NORM" CXX_O_FLAG_DEBUG="$C_O_FLAG_DEBUG" + CXX_O_FLAG_DEBUG_JVM="$C_O_FLAG_DEBUG_JVM" CXX_O_FLAG_NONE="$C_O_FLAG_NONE" + CXX_O_FLAG_SIZE="$C_O_FLAG_SIZE" fi # Adjust optimization flags according to debug level. @@ -48438,12 +48883,16 @@ $as_echo "$supports" >&6; } ;; slowdebug ) # Disable optimization + C_O_FLAG_HIGHEST_JVM="$C_O_FLAG_DEBUG_JVM" C_O_FLAG_HIGHEST="$C_O_FLAG_DEBUG" C_O_FLAG_HI="$C_O_FLAG_DEBUG" C_O_FLAG_NORM="$C_O_FLAG_DEBUG" + C_O_FLAG_SIZE="$C_O_FLAG_DEBUG" + CXX_O_FLAG_HIGHEST_JVM="$CXX_O_FLAG_DEBUG_JVM" CXX_O_FLAG_HIGHEST="$CXX_O_FLAG_DEBUG" CXX_O_FLAG_HI="$CXX_O_FLAG_DEBUG" CXX_O_FLAG_NORM="$CXX_O_FLAG_DEBUG" + CXX_O_FLAG_SIZE="$CXX_O_FLAG_DEBUG" ;; esac @@ -48459,6 +48908,12 @@ $as_echo "$supports" >&6; } + + + + + + # Special extras... if test "x$TOOLCHAIN_TYPE" = xsolstudio; then if test "x$OPENJDK_TARGET_CPU_ARCH" = "xsparc"; then @@ -48570,10 +49025,23 @@ $as_echo "$supports" >&6; } CXXFLAGS_JDK="${CXXFLAGS_JDK} ${CXXSTD_CXXFLAG}" fi + if test "x$OPENJDK_TARGET_OS" = xsolaris; then + CFLAGS_JDK="${CFLAGS_JDK} -D__solaris__" + CXXFLAGS_JDK="${CXXFLAGS_JDK} -D__solaris__" + CFLAGS_JDKLIB_EXTRA='-xstrconst' + CFLAGS_JDK="${CFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" + CXXFLAGS_JDK="${CXXFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" + fi + + if test "x$OPENJDK_TARGET_OS" = xsolaris; then + CFLAGS_JDK="${CFLAGS_JDK} -D__solaris__" + CXXFLAGS_JDK="${CXXFLAGS_JDK} -D__solaris__" + CFLAGS_JDKLIB_EXTRA='-xstrconst' + fi - CFLAGS_JDK="${CFLAGS_JDK} $EXTRA_CFLAGS" - CXXFLAGS_JDK="${CXXFLAGS_JDK} $EXTRA_CXXFLAGS" - LDFLAGS_JDK="${LDFLAGS_JDK} $EXTRA_LDFLAGS" + CFLAGS_JDK="${CFLAGS_JDK} ${EXTRA_CFLAGS}" + CXXFLAGS_JDK="${CXXFLAGS_JDK} ${EXTRA_CXXFLAGS}" + LDFLAGS_JDK="${LDFLAGS_JDK} ${EXTRA_LDFLAGS}" ############################################################################### # @@ -48586,9 +49054,13 @@ $as_echo "$supports" >&6; } # CXXFLAGS_JDK - C++ Compiler flags # COMMON_CCXXFLAGS_JDK - common to C and C++ if test "x$TOOLCHAIN_TYPE" = xgcc; then + JVM_CFLAGS="$JVM_CFLAGS -D_GNU_SOURCE" + JVM_CFLAGS="$JVM_CFLAGS -D_REENTRANT" + JVM_CFLAGS="$JVM_CFLAGS -fcheck-new" if test "x$OPENJDK_TARGET_CPU" = xx86; then # Force compatibility with i586 on 32 bit intel platforms. COMMON_CCXXFLAGS="${COMMON_CCXXFLAGS} -march=i586" + JVM_CFLAGS="$JVM_CFLAGS -march=i586" fi COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS $COMMON_CCXXFLAGS_JDK -Wall -Wextra -Wno-unused -Wno-unused-parameter -Wformat=2 \ -pipe -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE" @@ -49225,11 +49697,19 @@ $as_echo "$supports" >&6; } elif test "x$TOOLCHAIN_TYPE" = xclang; then + JVM_CFLAGS="$JVM_CFLAGS -D_GNU_SOURCE" + + # Restrict the debug information created by Clang to avoid + # too big object files and speed the build up a little bit + # (see http://llvm.org/bugs/show_bug.cgi?id=7554) + JVM_CFLAGS="$JVM_CFLAGS -flimit-debug-info" if test "x$OPENJDK_TARGET_OS" = xlinux; then if test "x$OPENJDK_TARGET_CPU" = xx86; then # Force compatibility with i586 on 32 bit intel platforms. COMMON_CCXXFLAGS="${COMMON_CCXXFLAGS} -march=i586" + JVM_CFLAGS="$JVM_CFLAGS -march=i586" fi + JVM_CFLAGS="$JVM_CFLAGS -Wno-sometimes-uninitialized" COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS $COMMON_CCXXFLAGS_JDK -Wall -Wextra -Wno-unused -Wno-unused-parameter -Wformat=2 \ -pipe -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE" case $OPENJDK_TARGET_CPU_ARCH in @@ -49244,6 +49724,7 @@ $as_echo "$supports" >&6; } esac fi elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then + JVM_CFLAGS="$JVM_CFLAGS -DSPARC_WORKS" COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS $COMMON_CCXXFLAGS_JDK -DTRACING -DMACRO_MEMSYS_OPS -DBREAKPTS" if test "x$OPENJDK_TARGET_CPU_ARCH" = xx86; then COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -DcpuIntel -Di586 -D$OPENJDK_TARGET_CPU_LEGACY_LIB" @@ -49252,6 +49733,7 @@ $as_echo "$supports" >&6; } CFLAGS_JDK="$CFLAGS_JDK -xc99=%none -xCC -errshort=tags -Xa -v -mt -W0,-noglobal" CXXFLAGS_JDK="$CXXFLAGS_JDK -errtags=yes +w -mt -features=no%except -DCC_NOEX -norunpath -xnolib" elif test "x$TOOLCHAIN_TYPE" = xxlc; then + JVM_CFLAGS="$JVM_CFLAGS -D_REENTRANT -D__STDC_FORMAT_MACROS" CFLAGS_JDK="$CFLAGS_JDK -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC" CXXFLAGS_JDK="$CXXFLAGS_JDK -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC" elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then @@ -49272,6 +49754,7 @@ $as_echo "$supports" >&6; } if test "x$TOOLCHAIN_VERSION" = "x2010"; then STATIC_CPPLIB_FLAGS="-D_STATIC_CPPLIB -D_DISABLE_DEPRECATE_STATIC_CPPLIB" COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK $STATIC_CPPLIB_FLAGS" + JVM_CFLAGS="$JVM_CFLAGS $STATIC_CPPLIB_FLAGS" fi fi @@ -49321,12 +49804,9 @@ $as_echo "$supports" >&6; } COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D$OPENJDK_TARGET_OS_UPPERCASE" # Setup target CPU - OPENJDK_TARGET_CCXXFLAGS_JDK="$OPENJDK_TARGET_CCXXFLAGS_JDK \ - $ADD_LP64 \ + COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK \ + $OPENJDK_TARGET_ADD_LP64 \ -DARCH='\"$OPENJDK_TARGET_CPU_LEGACY\"' -D$OPENJDK_TARGET_CPU_LEGACY" - OPENJDK_BUILD_CCXXFLAGS_JDK="$OPENJDK_BUILD_CCXXFLAGS_JDK \ - $OPENJDK_BUILD_ADD_LP64 \ - -DARCH='\"$OPENJDK_BUILD_CPU_LEGACY\"' -D$OPENJDK_BUILD_CPU_LEGACY" # Setup debug/release defines if test "x$DEBUG_LEVEL" = xrelease; then @@ -49339,10 +49819,172 @@ $as_echo "$supports" >&6; } fi # Set some additional per-OS defines. - if test "x$OPENJDK_TARGET_OS" = xmacosx; then + if test "x$OPENJDK_TARGET_OS" = xlinux; then + JVM_CFLAGS="$JVM_CFLAGS -DLINUX" + JVM_CFLAGS="$JVM_CFLAGS -pipe -fPIC -fno-rtti -fno-exceptions \ + -fvisibility=hidden -fno-strict-aliasing -fno-omit-frame-pointer" + elif test "x$OPENJDK_TARGET_OS" = xsolaris; then + JVM_CFLAGS="$JVM_CFLAGS -DSOLARIS" + JVM_CFLAGS="$JVM_CFLAGS -template=no%extdef -features=no%split_init \ + -D_Crun_inline_placement -library=%none -KPIC -mt -xwe -features=no%except" + elif test "x$OPENJDK_TARGET_OS" = xmacosx; then COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D_ALLBSD_SOURCE -D_DARWIN_UNLIMITED_SELECT" + JVM_CFLAGS="$JVM_CFLAGS -D_ALLBSD_SOURCE" + JVM_CFLAGS="$JVM_CFLAGS -D_DARWIN_C_SOURCE -D_XOPEN_SOURCE" + JVM_CFLAGS="$JVM_CFLAGS -fno-rtti -fno-exceptions -fvisibility=hidden \ + -mno-omit-leaf-frame-pointer -mstack-alignment=16 -pipe -fno-strict-aliasing \ + -DMAC_OS_X_VERSION_MAX_ALLOWED=1070 -mmacosx-version-min=10.7.0 \ + -fno-omit-frame-pointer" + elif test "x$OPENJDK_TARGET_OS" = xaix; then + JVM_CFLAGS="$JVM_CFLAGS -DAIX" + # We may need '-qminimaltoc' or '-qpic=large -bbigtoc' if the TOC overflows. + JVM_CFLAGS="$JVM_CFLAGS -qtune=balanced -qhot=level=1 -qinline \ + -qinlglue -qalias=noansi -qstrict -qtls=default -qlanglvl=c99vla \ + -qlanglvl=noredefmac -qnortti -qnoeh -qignerrno" elif test "x$OPENJDK_TARGET_OS" = xbsd; then COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D_ALLBSD_SOURCE" + elif test "x$OPENJDK_TARGET_OS" = xwindows; then + JVM_CFLAGS="$JVM_CFLAGS -D_WINDOWS -DWIN32 -D_JNI_IMPLEMENTATION_" + JVM_CFLAGS="$JVM_CFLAGS -nologo -W3 -MD -MP" + fi + + # Set some additional per-CPU defines. + if test "x$OPENJDK_TARGET_OS-$OPENJDK_TARGET_CPU" = xwindows-x86; then + JVM_CFLAGS="$JVM_CFLAGS -arch:IA32" + elif test "x$OPENJDK_TARGET_CPU" = xsparcv9; then + JVM_CFLAGS="$JVM_CFLAGS -xarch=sparc" + elif test "x$OPENJDK_TARGET_CPU" = xppc64; then + if test "x$OPENJDK_TARGET_OS" = xlinux; then + JVM_CFLAGS="$JVM_CFLAGS -minsert-sched-nops=regroup_exact -mno-multiple -mno-string" + # fixes `relocation truncated to fit' error for gcc 4.1. + JVM_CFLAGS="$JVM_CFLAGS -mminimal-toc" + # Use ppc64 instructions, but schedule for power5 + JVM_CFLAGS="$JVM_CFLAGS -mcpu=powerpc64 -mtune=power5" + elif test "x$OPENJDK_TARGET_OS" = xaix; then + JVM_CFLAGS="$JVM_CFLAGS -qarch=ppc64" + fi + elif test "x$OPENJDK_TARGET_CPU" = xppc64le; then + if test "x$OPENJDK_TARGET_OS" = xlinux; then + JVM_CFLAGS="$JVM_CFLAGS -minsert-sched-nops=regroup_exact -mno-multiple -mno-string" + # Little endian machine uses ELFv2 ABI. + JVM_CFLAGS="$JVM_CFLAGS -DABI_ELFv2" + # Use Power8, this is the first CPU to support PPC64 LE with ELFv2 ABI. + JVM_CFLAGS="$JVM_CFLAGS -mcpu=power7 -mtune=power8" + fi + fi + + if test "x$OPENJDK_TARGET_CPU_ENDIAN" = xlittle; then + JVM_CFLAGS="$JVM_CFLAGS -DVM_LITTLE_ENDIAN" + fi + + if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then + if test "x$OPENJDK_TARGET_OS" != xsolaris && test "x$OPENJDK_TARGET_OS" != xaix; then + # Solaris does not have _LP64=1 in the old build. + # xlc on AIX defines _LP64=1 by default and issues a warning if we redefine it. + JVM_CFLAGS="$JVM_CFLAGS -D_LP64=1" + fi + fi + + # Set JVM_CFLAGS warning handling + if test "x$OPENJDK_TARGET_OS" = xlinux; then + JVM_CFLAGS="$JVM_CFLAGS -Wpointer-arith -Wsign-compare -Wunused-function \ + -Wunused-value -Woverloaded-virtual" + + if test "x$TOOLCHAIN_TYPE" = xgcc; then + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # Execute function body + + # Need to assign to a variable since m4 is blocked from modifying parts in []. + REFERENCE_VERSION=4.8 + + if [[ "$REFERENCE_VERSION" =~ (.*\.){3} ]] ; then + as_fn_error $? "Internal error: Cannot compare to 4.8, only three parts (X.Y.Z) is supported" "$LINENO" 5 + fi + + if [[ "$REFERENCE_VERSION" =~ [0-9]{6} ]] ; then + as_fn_error $? "Internal error: Cannot compare to 4.8, only parts < 99999 is supported" "$LINENO" 5 + fi + + # Version comparison method inspired by http://stackoverflow.com/a/24067243 + COMPARABLE_REFERENCE_VERSION=`$AWK -F. '{ printf("%05d%05d%05d\n", $1, $2, $3) }' <<< "$REFERENCE_VERSION"` + + if test $COMPARABLE_ACTUAL_VERSION -ge $COMPARABLE_REFERENCE_VERSION ; then + : + + # These flags either do not work or give spurious warnings prior to gcc 4.8. + JVM_CFLAGS="$JVM_CFLAGS -Wno-format-zero-length -Wtype-limits -Wuninitialized" + + + else + : + + fi + + + + + + + + + + + + + fi + if ! [[ " $JVM_VARIANTS " =~ " zero " ]] && ! [[ " $JVM_VARIANTS " =~ " zeroshark " ]] ; then + # Non-zero builds have stricter warnings + JVM_CFLAGS="$JVM_CFLAGS -Wreturn-type -Wundef -Wformat=2" + else + if test "x$TOOLCHAIN_TYPE" = xclang; then + # Some versions of llvm do not like -Wundef + JVM_CFLAGS="$JVM_CFLAGS -Wno-undef" + fi + fi + elif test "x$OPENJDK_TARGET_OS" = xmacosx; then + JVM_CFLAGS="$JVM_CFLAGS -Wno-deprecated -Wpointer-arith \ + -Wsign-compare -Wundef -Wunused-function -Wformat=2" fi # Additional macosx handling @@ -49370,43 +50012,14 @@ $as_echo "$supports" >&6; } -I${JDK_TOPDIR}/src/java.base/$OPENJDK_TARGET_OS_TYPE/native/libjava" # The shared libraries are compiled using the picflag. - CFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \ + CFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK \ $CFLAGS_JDK $EXTRA_CFLAGS_JDK $PICFLAG $CFLAGS_JDKLIB_EXTRA" - CXXFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \ + CXXFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK \ $CXXFLAGS_JDK $EXTRA_CXXFLAGS_JDK $PICFLAG $CXXFLAGS_JDKLIB_EXTRA" # Executable flags - CFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \ - $CFLAGS_JDK $EXTRA_CFLAGS_JDK" - CXXFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \ - $CXXFLAGS_JDK $EXTRA_CXXFLAGS_JDK" - - # The corresponding flags for building for the build platform. This is still an - # approximation, we only need something that runs on this machine when cross - # compiling the product. - OPENJDK_BUILD_CFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CCXXFLAGS_JDK \ - $PICFLAG $CFLAGS_JDKLIB_EXTRA" - OPENJDK_BUILD_CXXFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CCXXFLAGS_JDK \ - $PICFLAG $CXXFLAGS_JDKLIB_EXTRA" - OPENJDK_BUILD_CFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CCXXFLAGS_JDK" - OPENJDK_BUILD_CXXFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CCXXFLAGS_JDK" - - - - - - - - - - - # Flags for compiling test libraries - CFLAGS_TESTLIB="$COMMON_CCXXFLAGS_JDK $CFLAGS_JDK $PICFLAG $CFLAGS_JDKLIB_EXTRA" - CXXFLAGS_TESTLIB="$COMMON_CCXXFLAGS_JDK $CXXFLAGS_JDK $PICFLAG $CXXFLAGS_JDKLIB_EXTRA" - - # Flags for compiling test executables - CFLAGS_TESTEXE="$COMMON_CCXXFLAGS_JDK $CFLAGS_JDK" - CXXFLAGS_TESTEXE="$COMMON_CCXXFLAGS_JDK $CXXFLAGS_JDK" + CFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $CFLAGS_JDK $EXTRA_CFLAGS_JDK" + CXXFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $CXXFLAGS_JDK $EXTRA_CXXFLAGS_JDK" @@ -49419,9 +50032,21 @@ $as_echo "$supports" >&6; } if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then LDFLAGS_MICROSOFT="-nologo -opt:ref" LDFLAGS_JDK="$LDFLAGS_JDK $LDFLAGS_MICROSOFT -incremental:no" + JVM_LDFLAGS="$JVM_LDFLAGS $LDFLAGS_MICROSOFT -opt:icf,8 -subsystem:windows -base:0x8000000" if test "x$OPENJDK_TARGET_CPU_BITS" = "x32"; then LDFLAGS_SAFESH="-safeseh" LDFLAGS_JDK="$LDFLAGS_JDK $LDFLAGS_SAFESH" + JVM_LDFLAGS="$JVM_LDFLAGS $LDFLAGS_SAFESH" + # NOTE: Old build added -machine. Probably not needed. + JVM_LDFLAGS="$JVM_LDFLAGS -machine:I386" + else + JVM_LDFLAGS="$JVM_LDFLAGS -machine:AMD64" + fi + elif test "x$TOOLCHAIN_TYPE" = xclang; then + JVM_LDFLAGS="$JVM_LDFLAGS -mno-omit-leaf-frame-pointer -mstack-alignment=16 -stdlib=libstdc++ -fPIC" + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + # FIXME: We should really generalize SET_SHARED_LIBRARY_ORIGIN instead. + JVM_LDFLAGS="$JVM_LDFLAGS -Wl,-rpath,@loader_path/. -Wl,-rpath,@loader_path/.." fi elif test "x$TOOLCHAIN_TYPE" = xgcc; then # If this is a --hash-style=gnu system, use --hash-style=both, why? @@ -49429,36 +50054,57 @@ $as_echo "$supports" >&6; } if test -n "$HAS_GNU_HASH"; then LDFLAGS_HASH_STYLE="-Wl,--hash-style=both" LDFLAGS_JDK="${LDFLAGS_JDK} $LDFLAGS_HASH_STYLE" + JVM_LDFLAGS="$JVM_LDFLAGS $LDFLAGS_HASH_STYLE" + fi + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + JVM_LDFLAGS="$JVM_LDFLAGS -Wl,-rpath,@loader_path/. -Wl,-rpath,@loader_path/.." fi if test "x$OPENJDK_TARGET_OS" = xlinux; then # And since we now know that the linker is gnu, then add -z defs, to forbid # undefined symbols in object files. LDFLAGS_NO_UNDEF_SYM="-Wl,-z,defs" LDFLAGS_JDK="${LDFLAGS_JDK} $LDFLAGS_NO_UNDEF_SYM" + JVM_LDFLAGS="$JVM_LDFLAGS $LDFLAGS_NO_UNDEF_SYM" + LDFLAGS_NO_EXEC_STACK="-Wl,-z,noexecstack" + JVM_LDFLAGS="$JVM_LDFLAGS $LDFLAGS_NO_EXEC_STACK" + if test "x$OPENJDK_TARGET_CPU" = xx86; then + JVM_LDFLAGS="$JVM_LDFLAGS -march=i586" + fi case $DEBUG_LEVEL in release ) # tell linker to optimize libraries. # Should this be supplied to the OSS linker as well? LDFLAGS_DEBUGLEVEL_release="-Wl,-O1" LDFLAGS_JDK="${LDFLAGS_JDK} $LDFLAGS_DEBUGLEVEL_release" + JVM_LDFLAGS="$JVM_LDFLAGS $LDFLAGS_DEBUGLEVEL_release" + if test "x$HAS_LINKER_RELRO" = "xtrue"; then + JVM_LDFLAGS="$JVM_LDFLAGS $LINKER_RELRO_FLAG" + fi ;; slowdebug ) + # Hotspot always let the linker optimize + JVM_LDFLAGS="$JVM_LDFLAGS -Wl,-O1" if test "x$HAS_LINKER_NOW" = "xtrue"; then # do relocations at load LDFLAGS_JDK="$LDFLAGS_JDK $LINKER_NOW_FLAG" LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK $LINKER_NOW_FLAG" + JVM_LDFLAGS="$JVM_LDFLAGS $LINKER_NOW_FLAG" fi if test "x$HAS_LINKER_RELRO" = "xtrue"; then # mark relocations read only LDFLAGS_JDK="$LDFLAGS_JDK $LINKER_RELRO_FLAG" LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK $LINKER_RELRO_FLAG" + JVM_LDFLAGS="$JVM_LDFLAGS $LINKER_RELRO_FLAG" fi ;; fastdebug ) + # Hotspot always let the linker optimize + JVM_LDFLAGS="$JVM_LDFLAGS -Wl,-O1" if test "x$HAS_LINKER_RELRO" = "xtrue"; then # mark relocations read only LDFLAGS_JDK="$LDFLAGS_JDK $LINKER_RELRO_FLAG" LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK $LINKER_RELRO_FLAG" + JVM_LDFLAGS="$JVM_LDFLAGS $LINKER_RELRO_FLAG" fi ;; * ) @@ -49471,9 +50117,14 @@ $as_echo "$supports" >&6; } LDFLAGS_JDK="$LDFLAGS_JDK $LDFLAGS_SOLSTUDIO -xildoff -ztext" LDFLAGS_CXX_SOLSTUDIO="-norunpath" LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK $LDFLAGS_CXX_SOLSTUDIO -xnolib" + JVM_LDFLAGS="$JVM_LDFLAGS $LDFLAGS_SOLSTUDIO -library=%none -mt $LDFLAGS_CXX_SOLSTUDIO -z noversion" + if test "x$OPENJDK_TARGET_CPU_ARCH" = "xsparc"; then + JVM_LDFLAGS="$JVM_LDFLAGS -xarch=sparc" + fi elif test "x$TOOLCHAIN_TYPE" = xxlc; then LDFLAGS_XLC="-b64 -brtl -bnolibpath -bexpall -bernotok" LDFLAGS_JDK="${LDFLAGS_JDK} $LDFLAGS_XLC" + JVM_LDFLAGS="$JVM_LDFLAGS $LDFLAGS_XLC" fi # Customize LDFLAGS for executables @@ -49491,7 +50142,6 @@ $as_echo "$supports" >&6; } LDFLAGS_JDKEXE="$LDFLAGS_JDKEXE -Wl,--allow-shlib-undefined" fi - OPENJDK_BUILD_LDFLAGS_JDKEXE="${LDFLAGS_JDKEXE}" LDFLAGS_JDKEXE="${LDFLAGS_JDKEXE} ${EXTRA_LDFLAGS_JDK}" # Customize LDFLAGS for libs @@ -49506,18 +50156,24 @@ $as_echo "$supports" >&6; } LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} \ -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)" + if test "xTARGET" = "xTARGET"; then # On some platforms (mac) the linker warns about non existing -L dirs. # Add server first if available. Linking aginst client does not always produce the same results. - # Only add client dir if client is being built. Add minimal (note not minimal1) if only building minimal1. + # Only add client/minimal dir if client/minimal is being built. # Default to server for other variants. - if test "x$JVM_VARIANT_SERVER" = xtrue; then - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/server" - elif test "x$JVM_VARIANT_CLIENT" = xtrue; then - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/client" - elif test "x$JVM_VARIANT_MINIMAL1" = xtrue; then - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/minimal" + if [[ " $JVM_VARIANTS " =~ " server " ]] ; then + LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/server" + elif [[ " $JVM_VARIANTS " =~ " client " ]] ; then + LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/client" + elif [[ " $JVM_VARIANTS " =~ " minimal " ]] ; then + LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/minimal" else - LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/server" + LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/server" + fi + elif test "xTARGET" = "xBUILD"; then + # When building a buildjdk, it's always only the server variant + LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} \ + -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/server" fi JDKLIB_LIBS="-ljava -ljvm" @@ -49525,12 +50181,41 @@ $as_echo "$supports" >&6; } JDKLIB_LIBS="$JDKLIB_LIBS -lc" fi - # When building a buildjdk, it's always only the server variant - OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} \ - -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/server" fi - OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} ${LDFLAGS_JDKLIB}" + # Set JVM_LIBS (per os) + if test "x$OPENJDK_TARGET_OS" = xlinux; then + JVM_LIBS="$JVM_LIBS -lm -ldl -lpthread" + elif test "x$OPENJDK_TARGET_OS" = xsolaris; then + # FIXME: This hard-coded path is not really proper. + if test "x$OPENJDK_TARGET_CPU" = xx86_64; then + SOLARIS_LIBM_LIBS="/usr/lib/amd64/libm.so.1" + elif test "x$OPENJDK_TARGET_CPU" = xsparcv9; then + SOLARIS_LIBM_LIBS="/usr/lib/sparcv9/libm.so.1" + fi + JVM_LIBS="$JVM_LIBS -lsocket -lsched -ldl $SOLARIS_LIBM_LIBS -lCrun \ + -lthread -ldoor -lc -ldemangle -lnsl -lkstat -lrt" + elif test "x$OPENJDK_TARGET_OS" = xmacosx; then + JVM_LIBS="$JVM_LIBS -lm" + elif test "x$OPENJDK_TARGET_OS" = xaix; then + JVM_LIBS="$JVM_LIBS -Wl,-lC_r -lm -ldl -lpthread" + elif test "x$OPENJDK_TARGET_OS" = xbsd; then + JVM_LIBS="$JVM_LIBS -lm" + elif test "x$OPENJDK_TARGET_OS" = xwindows; then + JVM_LIBS="$JVM_LIBS kernel32.lib user32.lib gdi32.lib winspool.lib \ + comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib \ + wsock32.lib winmm.lib version.lib psapi.lib" + fi + + # Set JVM_ASFLAGS + if test "x$OPENJDK_TARGET_OS" = xlinux; then + if test "x$OPENJDK_TARGET_CPU" = xx86; then + JVM_ASFLAGS="$JVM_ASFLAGS -march=i586" + fi + elif test "x$OPENJDK_TARGET_OS" = xmacosx; then + JVM_ASFLAGS="$JVM_ASFLAGS -x assembler-with-cpp -mno-omit-leaf-frame-pointer -mstack-alignment=16" + fi + LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} ${EXTRA_LDFLAGS_JDK}" @@ -49542,6 +50227,802 @@ $as_echo "$supports" >&6; } + + + + + + # Special extras... + if test "x$TOOLCHAIN_TYPE" = xsolstudio; then + if test "x$OPENJDK_BUILD_CPU_ARCH" = "xsparc"; then + OPENJDK_BUILD_CFLAGS_JDKLIB_EXTRA="${OPENJDK_BUILD_CFLAGS_JDKLIB_EXTRA} -xregs=no%appl" + OPENJDK_BUILD_CXXFLAGS_JDKLIB_EXTRA="${OPENJDK_BUILD_CXXFLAGS_JDKLIB_EXTRA} -xregs=no%appl" + fi + OPENJDK_BUILD_CFLAGS_JDKLIB_EXTRA="${OPENJDK_BUILD_CFLAGS_JDKLIB_EXTRA} -errtags=yes -errfmt" + OPENJDK_BUILD_CXXFLAGS_JDKLIB_EXTRA="${OPENJDK_BUILD_CXXFLAGS_JDKLIB_EXTRA} -errtags=yes -errfmt" + elif test "x$TOOLCHAIN_TYPE" = xxlc; then + OPENJDK_BUILD_CFLAGS_JDK="${OPENJDK_BUILD_CFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" + OPENJDK_BUILD_CXXFLAGS_JDK="${OPENJDK_BUILD_CXXFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" + elif test "x$TOOLCHAIN_TYPE" = xgcc; then + OPENJDK_BUILD_CXXSTD_CXXFLAG="-std=gnu++98" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # Execute function body + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the C++ compiler supports \"$OPENJDK_BUILD_CXXSTD_CXXFLAG -Werror\"" >&5 +$as_echo_n "checking if the C++ compiler supports \"$OPENJDK_BUILD_CXXSTD_CXXFLAG -Werror\"... " >&6; } + supports=yes + + saved_cxxflags="$CXXFLAGS" + CXXFLAGS="$CXXFLAG $OPENJDK_BUILD_CXXSTD_CXXFLAG -Werror" + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int i; +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +else + supports=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + CXXFLAGS="$saved_cxxflags" + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $supports" >&5 +$as_echo "$supports" >&6; } + if test "x$supports" = "xyes" ; then + : + + else + : + OPENJDK_BUILD_CXXSTD_CXXFLAG="" + fi + + + + + + + + + + + + + OPENJDK_BUILD_CXXFLAGS_JDK="${OPENJDK_BUILD_CXXFLAGS_JDK} ${OPENJDK_BUILD_CXXSTD_CXXFLAG}" + + fi + if test "x$OPENJDK_TARGET_OS" = xsolaris; then + OPENJDK_BUILD_CFLAGS_JDK="${OPENJDK_BUILD_CFLAGS_JDK} -D__solaris__" + OPENJDK_BUILD_CXXFLAGS_JDK="${OPENJDK_BUILD_CXXFLAGS_JDK} -D__solaris__" + OPENJDK_BUILD_CFLAGS_JDKLIB_EXTRA='-xstrconst' + CFLAGS_JDK="${CFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" + CXXFLAGS_JDK="${CXXFLAGS_JDK} -qchars=signed -qfullpath -qsaveopt" + fi + + if test "x$OPENJDK_TARGET_OS" = xsolaris; then + OPENJDK_BUILD_CFLAGS_JDK="${OPENJDK_BUILD_CFLAGS_JDK} -D__solaris__" + OPENJDK_BUILD_CXXFLAGS_JDK="${OPENJDK_BUILD_CXXFLAGS_JDK} -D__solaris__" + OPENJDK_BUILD_CFLAGS_JDKLIB_EXTRA='-xstrconst' + fi + + OPENJDK_BUILD_CFLAGS_JDK="${OPENJDK_BUILD_CFLAGS_JDK} ${OPENJDK_BUILD_EXTRA_CFLAGS}" + OPENJDK_BUILD_CXXFLAGS_JDK="${OPENJDK_BUILD_CXXFLAGS_JDK} ${OPENJDK_BUILD_EXTRA_CXXFLAGS}" + OPENJDK_BUILD_LDFLAGS_JDK="${OPENJDK_BUILD_LDFLAGS_JDK} ${OPENJDK_BUILD_EXTRA_LDFLAGS}" + + ############################################################################### + # + # Now setup the CFLAGS and LDFLAGS for the JDK build. + # Later we will also have CFLAGS and LDFLAGS for the hotspot subrepo build. + # + + # Setup compiler/platform specific flags into + # OPENJDK_BUILD_CFLAGS_JDK - C Compiler flags + # OPENJDK_BUILD_CXXFLAGS_JDK - C++ Compiler flags + # OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK - common to C and C++ + if test "x$TOOLCHAIN_TYPE" = xgcc; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -D_GNU_SOURCE" + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -D_REENTRANT" + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -fcheck-new" + if test "x$OPENJDK_BUILD_CPU" = xx86; then + # Force compatibility with i586 on 32 bit intel platforms. + OPENJDK_BUILD_COMMON_CCXXFLAGS="${OPENJDK_BUILD_COMMON_CCXXFLAGS} -march=i586" + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -march=i586" + fi + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS $OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -Wall -Wextra -Wno-unused -Wno-unused-parameter -Wformat=2 \ + -pipe -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE" + case $OPENJDK_BUILD_CPU_ARCH in + arm ) + # on arm we don't prevent gcc to omit frame pointer but do prevent strict aliasing + OPENJDK_BUILD_CFLAGS_JDK="${OPENJDK_BUILD_CFLAGS_JDK} -fno-strict-aliasing" + ;; + ppc ) + # on ppc we don't prevent gcc to omit frame pointer but do prevent strict aliasing + OPENJDK_BUILD_CFLAGS_JDK="${OPENJDK_BUILD_CFLAGS_JDK} -fno-strict-aliasing" + ;; + * ) + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -fno-omit-frame-pointer" + OPENJDK_BUILD_CFLAGS_JDK="${OPENJDK_BUILD_CFLAGS_JDK} -fno-strict-aliasing" + ;; + esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # Execute function body + + # Need to assign to a variable since m4 is blocked from modifying parts in []. + REFERENCE_VERSION=6 + + if [[ "$REFERENCE_VERSION" =~ (.*\.){3} ]] ; then + as_fn_error $? "Internal error: Cannot compare to 6, only three parts (X.Y.Z) is supported" "$LINENO" 5 + fi + + if [[ "$REFERENCE_VERSION" =~ [0-9]{6} ]] ; then + as_fn_error $? "Internal error: Cannot compare to 6, only parts < 99999 is supported" "$LINENO" 5 + fi + + # Version comparison method inspired by http://stackoverflow.com/a/24067243 + COMPARABLE_REFERENCE_VERSION=`$AWK -F. '{ printf("%05d%05d%05d\n", $1, $2, $3) }' <<< "$REFERENCE_VERSION"` + + if test $COMPARABLE_ACTUAL_VERSION -ge $COMPARABLE_REFERENCE_VERSION ; then + : + + else + : + + fi + + + + + + + + + + + + + elif test "x$TOOLCHAIN_TYPE" = xclang; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -D_GNU_SOURCE" + + # Restrict the debug information created by Clang to avoid + # too big object files and speed the build up a little bit + # (see http://llvm.org/bugs/show_bug.cgi?id=7554) + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -flimit-debug-info" + if test "x$OPENJDK_BUILD_OS" = xlinux; then + if test "x$OPENJDK_BUILD_CPU" = xx86; then + # Force compatibility with i586 on 32 bit intel platforms. + OPENJDK_BUILD_COMMON_CCXXFLAGS="${OPENJDK_BUILD_COMMON_CCXXFLAGS} -march=i586" + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -march=i586" + fi + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -Wno-sometimes-uninitialized" + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS $OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -Wall -Wextra -Wno-unused -Wno-unused-parameter -Wformat=2 \ + -pipe -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE" + case $OPENJDK_BUILD_CPU_ARCH in + ppc ) + # on ppc we don't prevent gcc to omit frame pointer but do prevent strict aliasing + OPENJDK_BUILD_CFLAGS_JDK="${OPENJDK_BUILD_CFLAGS_JDK} -fno-strict-aliasing" + ;; + * ) + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -fno-omit-frame-pointer" + OPENJDK_BUILD_CFLAGS_JDK="${OPENJDK_BUILD_CFLAGS_JDK} -fno-strict-aliasing" + ;; + esac + fi + elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -DSPARC_WORKS" + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS $OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -DTRACING -DMACRO_MEMSYS_OPS -DBREAKPTS" + if test "x$OPENJDK_BUILD_CPU_ARCH" = xx86; then + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -DcpuIntel -Di586 -D$OPENJDK_BUILD_CPU_LEGACY_LIB" + fi + + OPENJDK_BUILD_CFLAGS_JDK="$OPENJDK_BUILD_CFLAGS_JDK -xc99=%none -xCC -errshort=tags -Xa -v -mt -W0,-noglobal" + OPENJDK_BUILD_CXXFLAGS_JDK="$OPENJDK_BUILD_CXXFLAGS_JDK -errtags=yes +w -mt -features=no%except -DCC_NOEX -norunpath -xnolib" + elif test "x$TOOLCHAIN_TYPE" = xxlc; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -D_REENTRANT -D__STDC_FORMAT_MACROS" + OPENJDK_BUILD_CFLAGS_JDK="$OPENJDK_BUILD_CFLAGS_JDK -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC" + OPENJDK_BUILD_CXXFLAGS_JDK="$OPENJDK_BUILD_CXXFLAGS_JDK -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC" + elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS $OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK \ + -MD -Zc:wchar_t- -W3 -wd4800 \ + -DWIN32_LEAN_AND_MEAN \ + -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE \ + -D_WINSOCK_DEPRECATED_NO_WARNINGS \ + -DWIN32 -DIAL" + if test "x$OPENJDK_BUILD_CPU" = xx86_64; then + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -D_AMD64_ -Damd64" + else + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -D_X86_ -Dx86" + fi + # If building with Visual Studio 2010, we can still use _STATIC_CPPLIB to + # avoid bundling msvcpNNN.dll. Doesn't work with newer versions of visual + # studio. + if test "x$TOOLCHAIN_VERSION" = "x2010"; then + STATIC_CPPLIB_FLAGS="-D_STATIC_CPPLIB -D_DISABLE_DEPRECATE_STATIC_CPPLIB" + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK $STATIC_CPPLIB_FLAGS" + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS $STATIC_CPPLIB_FLAGS" + fi + fi + + ############################################################################### + + # Adjust flags according to debug level. + case $DEBUG_LEVEL in + fastdebug | slowdebug ) + OPENJDK_BUILD_CFLAGS_JDK="$OPENJDK_BUILD_CFLAGS_JDK $CFLAGS_DEBUG_SYMBOLS $CFLAGS_DEBUG_OPTIONS" + OPENJDK_BUILD_CXXFLAGS_JDK="$OPENJDK_BUILD_CXXFLAGS_JDK $CXXFLAGS_DEBUG_SYMBOLS $CXXFLAGS_DEBUG_OPTIONS" + JAVAC_FLAGS="$JAVAC_FLAGS -g" + ;; + release ) + ;; + * ) + as_fn_error $? "Unrecognized \$DEBUG_LEVEL: $DEBUG_LEVEL" "$LINENO" 5 + ;; + esac + + # Set some common defines. These works for all compilers, but assume + # -D is universally accepted. + + # Setup endianness + if test "x$OPENJDK_BUILD_CPU_ENDIAN" = xlittle; then + # The macro _LITTLE_ENDIAN needs to be defined the same to avoid the + # Sun C compiler warning message: warning: macro redefined: _LITTLE_ENDIAN + # (The Solaris X86 system defines this in file /usr/include/sys/isa_defs.h). + # Note: -Dmacro is the same as #define macro 1 + # -Dmacro= is the same as #define macro + if test "x$OPENJDK_BUILD_OS" = xsolaris; then + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -D_LITTLE_ENDIAN=" + else + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -D_LITTLE_ENDIAN" + fi + else + # Same goes for _BIG_ENDIAN. Do we really need to set *ENDIAN on Solaris if they + # are defined in the system? + if test "x$OPENJDK_BUILD_OS" = xsolaris; then + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -D_BIG_ENDIAN=" + else + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -D_BIG_ENDIAN" + fi + fi + + # Setup target OS define. Use OS target name but in upper case. + OPENJDK_BUILD_OS_UPPERCASE=`$ECHO $OPENJDK_BUILD_OS | $TR 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -D$OPENJDK_BUILD_OS_UPPERCASE" + + # Setup target CPU + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK \ + $OPENJDK_BUILD_ADD_LP64 \ + -DARCH='\"$OPENJDK_BUILD_CPU_LEGACY\"' -D$OPENJDK_BUILD_CPU_LEGACY" + + # Setup debug/release defines + if test "x$DEBUG_LEVEL" = xrelease; then + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -DNDEBUG" + if test "x$OPENJDK_BUILD_OS" = xsolaris; then + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -DTRIMMED" + fi + else + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -DDEBUG" + fi + + # Set some additional per-OS defines. + if test "x$OPENJDK_BUILD_OS" = xlinux; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -DLINUX" + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -pipe -fPIC -fno-rtti -fno-exceptions \ + -fvisibility=hidden -fno-strict-aliasing -fno-omit-frame-pointer" + elif test "x$OPENJDK_BUILD_OS" = xsolaris; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -DSOLARIS" + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -template=no%extdef -features=no%split_init \ + -D_Crun_inline_placement -library=%none -KPIC -mt -xwe -features=no%except" + elif test "x$OPENJDK_BUILD_OS" = xmacosx; then + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -D_ALLBSD_SOURCE -D_DARWIN_UNLIMITED_SELECT" + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -D_ALLBSD_SOURCE" + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -D_DARWIN_C_SOURCE -D_XOPEN_SOURCE" + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -fno-rtti -fno-exceptions -fvisibility=hidden \ + -mno-omit-leaf-frame-pointer -mstack-alignment=16 -pipe -fno-strict-aliasing \ + -DMAC_OS_X_VERSION_MAX_ALLOWED=1070 -mmacosx-version-min=10.7.0 \ + -fno-omit-frame-pointer" + elif test "x$OPENJDK_BUILD_OS" = xaix; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -DAIX" + # We may need '-qminimaltoc' or '-qpic=large -bbigtoc' if the TOC overflows. + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -qtune=balanced -qhot=level=1 -qinline \ + -qinlglue -qalias=noansi -qstrict -qtls=default -qlanglvl=c99vla \ + -qlanglvl=noredefmac -qnortti -qnoeh -qignerrno" + elif test "x$OPENJDK_BUILD_OS" = xbsd; then + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -D_ALLBSD_SOURCE" + elif test "x$OPENJDK_BUILD_OS" = xwindows; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -D_WINDOWS -DWIN32 -D_JNI_IMPLEMENTATION_" + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -nologo -W3 -MD -MP" + fi + + # Set some additional per-CPU defines. + if test "x$OPENJDK_BUILD_OS-$OPENJDK_BUILD_CPU" = xwindows-x86; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -arch:IA32" + elif test "x$OPENJDK_BUILD_CPU" = xsparcv9; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -xarch=sparc" + elif test "x$OPENJDK_BUILD_CPU" = xppc64; then + if test "x$OPENJDK_BUILD_OS" = xlinux; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -minsert-sched-nops=regroup_exact -mno-multiple -mno-string" + # fixes `relocation truncated to fit' error for gcc 4.1. + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -mminimal-toc" + # Use ppc64 instructions, but schedule for power5 + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -mcpu=powerpc64 -mtune=power5" + elif test "x$OPENJDK_BUILD_OS" = xaix; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -qarch=ppc64" + fi + elif test "x$OPENJDK_BUILD_CPU" = xppc64le; then + if test "x$OPENJDK_BUILD_OS" = xlinux; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -minsert-sched-nops=regroup_exact -mno-multiple -mno-string" + # Little endian machine uses ELFv2 ABI. + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -DABI_ELFv2" + # Use Power8, this is the first CPU to support PPC64 LE with ELFv2 ABI. + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -mcpu=power7 -mtune=power8" + fi + fi + + if test "x$OPENJDK_BUILD_CPU_ENDIAN" = xlittle; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -DVM_LITTLE_ENDIAN" + fi + + if test "x$OPENJDK_BUILD_CPU_BITS" = x64; then + if test "x$OPENJDK_BUILD_OS" != xsolaris && test "x$OPENJDK_BUILD_OS" != xaix; then + # Solaris does not have _LP64=1 in the old build. + # xlc on AIX defines _LP64=1 by default and issues a warning if we redefine it. + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -D_LP64=1" + fi + fi + + # Set OPENJDK_BUILD_JVM_CFLAGS warning handling + if test "x$OPENJDK_BUILD_OS" = xlinux; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -Wpointer-arith -Wsign-compare -Wunused-function \ + -Wunused-value -Woverloaded-virtual" + + if test "x$TOOLCHAIN_TYPE" = xgcc; then + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # Execute function body + + # Need to assign to a variable since m4 is blocked from modifying parts in []. + REFERENCE_VERSION=4.8 + + if [[ "$REFERENCE_VERSION" =~ (.*\.){3} ]] ; then + as_fn_error $? "Internal error: Cannot compare to 4.8, only three parts (X.Y.Z) is supported" "$LINENO" 5 + fi + + if [[ "$REFERENCE_VERSION" =~ [0-9]{6} ]] ; then + as_fn_error $? "Internal error: Cannot compare to 4.8, only parts < 99999 is supported" "$LINENO" 5 + fi + + # Version comparison method inspired by http://stackoverflow.com/a/24067243 + COMPARABLE_REFERENCE_VERSION=`$AWK -F. '{ printf("%05d%05d%05d\n", $1, $2, $3) }' <<< "$REFERENCE_VERSION"` + + if test $COMPARABLE_ACTUAL_VERSION -ge $COMPARABLE_REFERENCE_VERSION ; then + : + + # These flags either do not work or give spurious warnings prior to gcc 4.8. + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -Wno-format-zero-length -Wtype-limits -Wuninitialized" + + + else + : + + fi + + + + + + + + + + + + + fi + if ! [[ " $JVM_VARIANTS " =~ " zero " ]] && ! [[ " $JVM_VARIANTS " =~ " zeroshark " ]] ; then + # Non-zero builds have stricter warnings + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -Wreturn-type -Wundef -Wformat=2" + else + if test "x$TOOLCHAIN_TYPE" = xclang; then + # Some versions of llvm do not like -Wundef + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -Wno-undef" + fi + fi + elif test "x$OPENJDK_BUILD_OS" = xmacosx; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -Wno-deprecated -Wpointer-arith \ + -Wsign-compare -Wundef -Wunused-function -Wformat=2" + fi + + # Additional macosx handling + if test "x$OPENJDK_BUILD_OS" = xmacosx; then + # Setting these parameters makes it an error to link to macosx APIs that are + # newer than the given OS version and makes the linked binaries compatible + # even if built on a newer version of the OS. + # The expected format is X.Y.Z + MACOSX_VERSION_MIN=10.7.0 + + + # The macro takes the version with no dots, ex: 1070 + # Let the flags variables get resolved in make for easier override on make + # command line. + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -DMAC_OS_X_VERSION_MAX_ALLOWED=\$(subst .,,\$(MACOSX_VERSION_MIN)) -mmacosx-version-min=\$(MACOSX_VERSION_MIN)" + OPENJDK_BUILD_LDFLAGS_JDK="$OPENJDK_BUILD_LDFLAGS_JDK -mmacosx-version-min=\$(MACOSX_VERSION_MIN)" + fi + + # Setup some hard coded includes + OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK \ + -I${JDK_TOPDIR}/src/java.base/share/native/include \ + -I${JDK_TOPDIR}/src/java.base/$OPENJDK_BUILD_OS/native/include \ + -I${JDK_TOPDIR}/src/java.base/$OPENJDK_BUILD_OS_TYPE/native/include \ + -I${JDK_TOPDIR}/src/java.base/share/native/libjava \ + -I${JDK_TOPDIR}/src/java.base/$OPENJDK_BUILD_OS_TYPE/native/libjava" + + # The shared libraries are compiled using the picflag. + OPENJDK_BUILD_CFLAGS_JDKLIB="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK \ + $OPENJDK_BUILD_CFLAGS_JDK $OPENJDK_BUILD_EXTRA_CFLAGS_JDK $PICFLAG $OPENJDK_BUILD_CFLAGS_JDKLIB_EXTRA" + OPENJDK_BUILD_CXXFLAGS_JDKLIB="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK \ + $OPENJDK_BUILD_CXXFLAGS_JDK $OPENJDK_BUILD_EXTRA_CXXFLAGS_JDK $PICFLAG $OPENJDK_BUILD_CXXFLAGS_JDKLIB_EXTRA" + + # Executable flags + OPENJDK_BUILD_CFLAGS_JDKEXE="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CFLAGS_JDK $OPENJDK_BUILD_EXTRA_CFLAGS_JDK" + OPENJDK_BUILD_CXXFLAGS_JDKEXE="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CXXFLAGS_JDK $OPENJDK_BUILD_EXTRA_CXXFLAGS_JDK" + + + + + + + # Setup LDFLAGS et al. + # + + if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + LDFLAGS_MICROSOFT="-nologo -opt:ref" + OPENJDK_BUILD_LDFLAGS_JDK="$OPENJDK_BUILD_LDFLAGS_JDK $LDFLAGS_MICROSOFT -incremental:no" + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $LDFLAGS_MICROSOFT -opt:icf,8 -subsystem:windows -base:0x8000000" + if test "x$OPENJDK_BUILD_CPU_BITS" = "x32"; then + LDFLAGS_SAFESH="-safeseh" + OPENJDK_BUILD_LDFLAGS_JDK="$OPENJDK_BUILD_LDFLAGS_JDK $LDFLAGS_SAFESH" + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $LDFLAGS_SAFESH" + # NOTE: Old build added -machine. Probably not needed. + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS -machine:I386" + else + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS -machine:AMD64" + fi + elif test "x$TOOLCHAIN_TYPE" = xclang; then + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS -mno-omit-leaf-frame-pointer -mstack-alignment=16 -stdlib=libstdc++ -fPIC" + if test "x$OPENJDK_BUILD_OS" = xmacosx; then + # FIXME: We should really generalize SET_SHARED_LIBRARY_ORIGIN instead. + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS -Wl,-rpath,@loader_path/. -Wl,-rpath,@loader_path/.." + fi + elif test "x$TOOLCHAIN_TYPE" = xgcc; then + # If this is a --hash-style=gnu system, use --hash-style=both, why? + # We have previously set HAS_GNU_HASH if this is the case + if test -n "$HAS_GNU_HASH"; then + OPENJDK_BUILD_LDFLAGS_HASH_STYLE="-Wl,--hash-style=both" + OPENJDK_BUILD_LDFLAGS_JDK="${OPENJDK_BUILD_LDFLAGS_JDK} $OPENJDK_BUILD_LDFLAGS_HASH_STYLE" + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $OPENJDK_BUILD_LDFLAGS_HASH_STYLE" + fi + if test "x$OPENJDK_BUILD_OS" = xmacosx; then + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS -Wl,-rpath,@loader_path/. -Wl,-rpath,@loader_path/.." + fi + if test "x$OPENJDK_BUILD_OS" = xlinux; then + # And since we now know that the linker is gnu, then add -z defs, to forbid + # undefined symbols in object files. + LDFLAGS_NO_UNDEF_SYM="-Wl,-z,defs" + OPENJDK_BUILD_LDFLAGS_JDK="${OPENJDK_BUILD_LDFLAGS_JDK} $LDFLAGS_NO_UNDEF_SYM" + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $LDFLAGS_NO_UNDEF_SYM" + LDFLAGS_NO_EXEC_STACK="-Wl,-z,noexecstack" + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $LDFLAGS_NO_EXEC_STACK" + if test "x$OPENJDK_BUILD_CPU" = xx86; then + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS -march=i586" + fi + case $DEBUG_LEVEL in + release ) + # tell linker to optimize libraries. + # Should this be supplied to the OSS linker as well? + LDFLAGS_DEBUGLEVEL_release="-Wl,-O1" + OPENJDK_BUILD_LDFLAGS_JDK="${OPENJDK_BUILD_LDFLAGS_JDK} $LDFLAGS_DEBUGLEVEL_release" + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $LDFLAGS_DEBUGLEVEL_release" + if test "x$HAS_LINKER_RELRO" = "xtrue"; then + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $LINKER_RELRO_FLAG" + fi + ;; + slowdebug ) + # Hotspot always let the linker optimize + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS -Wl,-O1" + if test "x$HAS_LINKER_NOW" = "xtrue"; then + # do relocations at load + OPENJDK_BUILD_LDFLAGS_JDK="$OPENJDK_BUILD_LDFLAGS_JDK $LINKER_NOW_FLAG" + OPENJDK_BUILD_LDFLAGS_CXX_JDK="$OPENJDK_BUILD_LDFLAGS_CXX_JDK $LINKER_NOW_FLAG" + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $LINKER_NOW_FLAG" + fi + if test "x$HAS_LINKER_RELRO" = "xtrue"; then + # mark relocations read only + OPENJDK_BUILD_LDFLAGS_JDK="$OPENJDK_BUILD_LDFLAGS_JDK $LINKER_RELRO_FLAG" + OPENJDK_BUILD_LDFLAGS_CXX_JDK="$OPENJDK_BUILD_LDFLAGS_CXX_JDK $LINKER_RELRO_FLAG" + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $LINKER_RELRO_FLAG" + fi + ;; + fastdebug ) + # Hotspot always let the linker optimize + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS -Wl,-O1" + if test "x$HAS_LINKER_RELRO" = "xtrue"; then + # mark relocations read only + OPENJDK_BUILD_LDFLAGS_JDK="$OPENJDK_BUILD_LDFLAGS_JDK $LINKER_RELRO_FLAG" + OPENJDK_BUILD_LDFLAGS_CXX_JDK="$OPENJDK_BUILD_LDFLAGS_CXX_JDK $LINKER_RELRO_FLAG" + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $LINKER_RELRO_FLAG" + fi + ;; + * ) + as_fn_error $? "Unrecognized \$DEBUG_LEVEL: $DEBUG_LEVEL" "$LINENO" 5 + ;; + esac + fi + elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then + LDFLAGS_SOLSTUDIO="-Wl,-z,defs" + OPENJDK_BUILD_LDFLAGS_JDK="$OPENJDK_BUILD_LDFLAGS_JDK $LDFLAGS_SOLSTUDIO -xildoff -ztext" + LDFLAGS_CXX_SOLSTUDIO="-norunpath" + OPENJDK_BUILD_LDFLAGS_CXX_JDK="$OPENJDK_BUILD_LDFLAGS_CXX_JDK $LDFLAGS_CXX_SOLSTUDIO -xnolib" + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $LDFLAGS_SOLSTUDIO -library=%none -mt $LDFLAGS_CXX_SOLSTUDIO -z noversion" + if test "x$OPENJDK_BUILD_CPU_ARCH" = "xsparc"; then + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS -xarch=sparc" + fi + elif test "x$TOOLCHAIN_TYPE" = xxlc; then + LDFLAGS_XLC="-b64 -brtl -bnolibpath -bexpall -bernotok" + OPENJDK_BUILD_LDFLAGS_JDK="${OPENJDK_BUILD_LDFLAGS_JDK} $LDFLAGS_XLC" + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $LDFLAGS_XLC" + fi + + # Customize LDFLAGS for executables + + OPENJDK_BUILD_LDFLAGS_JDKEXE="${OPENJDK_BUILD_LDFLAGS_JDK}" + + if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + if test "x$OPENJDK_BUILD_CPU_BITS" = "x64"; then + LDFLAGS_STACK_SIZE=1048576 + else + LDFLAGS_STACK_SIZE=327680 + fi + OPENJDK_BUILD_LDFLAGS_JDKEXE="${OPENJDK_BUILD_LDFLAGS_JDKEXE} /STACK:$LDFLAGS_STACK_SIZE" + elif test "x$OPENJDK_BUILD_OS" = xlinux; then + OPENJDK_BUILD_LDFLAGS_JDKEXE="$OPENJDK_BUILD_LDFLAGS_JDKEXE -Wl,--allow-shlib-undefined" + fi + + OPENJDK_BUILD_LDFLAGS_JDKEXE="${OPENJDK_BUILD_LDFLAGS_JDKEXE} ${OPENJDK_BUILD_EXTRA_LDFLAGS_JDK}" + + # Customize LDFLAGS for libs + OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDK}" + + OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} ${SHARED_LIBRARY_FLAGS}" + if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} \ + -libpath:${OUTPUT_ROOT}/support/modules_libs/java.base" + OPENJDK_BUILD_JDKLIB_LIBS="" + else + OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} \ + -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_BUILD_CPU_LIBDIR)" + + if test "xBUILD" = "xTARGET"; then + # On some platforms (mac) the linker warns about non existing -L dirs. + # Add server first if available. Linking aginst client does not always produce the same results. + # Only add client/minimal dir if client/minimal is being built. + # Default to server for other variants. + if [[ " $JVM_VARIANTS " =~ " server " ]] ; then + OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_BUILD_CPU_LIBDIR)/server" + elif [[ " $JVM_VARIANTS " =~ " client " ]] ; then + OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_BUILD_CPU_LIBDIR)/client" + elif [[ " $JVM_VARIANTS " =~ " minimal " ]] ; then + OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_BUILD_CPU_LIBDIR)/minimal" + else + OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_BUILD_CPU_LIBDIR)/server" + fi + elif test "xBUILD" = "xBUILD"; then + # When building a buildjdk, it's always only the server variant + OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} \ + -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_BUILD_CPU_LIBDIR)/server" + fi + + OPENJDK_BUILD_JDKLIB_LIBS="-ljava -ljvm" + if test "x$TOOLCHAIN_TYPE" = xsolstudio; then + OPENJDK_BUILD_JDKLIB_LIBS="$OPENJDK_BUILD_JDKLIB_LIBS -lc" + fi + + fi + + # Set OPENJDK_BUILD_JVM_LIBS (per os) + if test "x$OPENJDK_BUILD_OS" = xlinux; then + OPENJDK_BUILD_JVM_LIBS="$OPENJDK_BUILD_JVM_LIBS -lm -ldl -lpthread" + elif test "x$OPENJDK_BUILD_OS" = xsolaris; then + # FIXME: This hard-coded path is not really proper. + if test "x$OPENJDK_BUILD_CPU" = xx86_64; then + OPENJDK_BUILD_SOLARIS_LIBM_LIBS="/usr/lib/amd64/libm.so.1" + elif test "x$OPENJDK_BUILD_CPU" = xsparcv9; then + OPENJDK_BUILD_SOLARIS_LIBM_LIBS="/usr/lib/sparcv9/libm.so.1" + fi + OPENJDK_BUILD_JVM_LIBS="$OPENJDK_BUILD_JVM_LIBS -lsocket -lsched -ldl $SOLARIS_LIBM_LIBS -lCrun \ + -lthread -ldoor -lc -ldemangle -lnsl -lkstat -lrt" + elif test "x$OPENJDK_BUILD_OS" = xmacosx; then + OPENJDK_BUILD_JVM_LIBS="$OPENJDK_BUILD_JVM_LIBS -lm" + elif test "x$OPENJDK_BUILD_OS" = xaix; then + OPENJDK_BUILD_JVM_LIBS="$OPENJDK_BUILD_JVM_LIBS -Wl,-lC_r -lm -ldl -lpthread" + elif test "x$OPENJDK_BUILD_OS" = xbsd; then + OPENJDK_BUILD_JVM_LIBS="$OPENJDK_BUILD_JVM_LIBS -lm" + elif test "x$OPENJDK_BUILD_OS" = xwindows; then + OPENJDK_BUILD_JVM_LIBS="$OPENJDK_BUILD_JVM_LIBS kernel32.lib user32.lib gdi32.lib winspool.lib \ + comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib \ + wsock32.lib winmm.lib version.lib psapi.lib" + fi + + # Set OPENJDK_BUILD_JVM_ASFLAGS + if test "x$OPENJDK_BUILD_OS" = xlinux; then + if test "x$OPENJDK_BUILD_CPU" = xx86; then + OPENJDK_BUILD_JVM_ASFLAGS="$OPENJDK_BUILD_JVM_ASFLAGS -march=i586" + fi + elif test "x$OPENJDK_BUILD_OS" = xmacosx; then + OPENJDK_BUILD_JVM_ASFLAGS="$OPENJDK_BUILD_JVM_ASFLAGS -x assembler-with-cpp -mno-omit-leaf-frame-pointer -mstack-alignment=16" + fi + + OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} ${OPENJDK_BUILD_EXTRA_LDFLAGS_JDK}" + + + + + + + + + + + + + + + + # Tests are only ever compiled for TARGET + # Flags for compiling test libraries + CFLAGS_TESTLIB="$COMMON_CCXXFLAGS_JDK $CFLAGS_JDK $PICFLAG $CFLAGS_JDKLIB_EXTRA" + CXXFLAGS_TESTLIB="$COMMON_CCXXFLAGS_JDK $CXXFLAGS_JDK $PICFLAG $CXXFLAGS_JDKLIB_EXTRA" + + # Flags for compiling test executables + CFLAGS_TESTEXE="$COMMON_CCXXFLAGS_JDK $CFLAGS_JDK" + CXXFLAGS_TESTEXE="$COMMON_CCXXFLAGS_JDK $CXXFLAGS_JDK" + + + + + + LDFLAGS_TESTLIB="$LDFLAGS_JDKLIB" LDFLAGS_TESTEXE="$LDFLAGS_JDKEXE" @@ -49549,6 +51030,7 @@ $as_echo "$supports" >&6; } + # Some Zero and Shark settings. # ZERO_ARCHFLAG tells the compiler which mode to build for case "${OPENJDK_TARGET_CPU}" in @@ -50897,6 +52379,222 @@ $as_echo "no" >&6; } +# Need toolchain to setup dtrace + + # Test for dtrace dependencies + # Check whether --enable-dtrace was given. +if test "${enable_dtrace+set}" = set; then : + enableval=$enable_dtrace; +fi + + + DTRACE_DEP_MISSING=false + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dtrace tool" >&5 +$as_echo_n "checking for dtrace tool... " >&6; } + if test "x$DTRACE" != "x" && test -x "$DTRACE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DTRACE" >&5 +$as_echo "$DTRACE" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found, cannot build dtrace" >&5 +$as_echo "not found, cannot build dtrace" >&6; } + DTRACE_DEP_MISSING=true + fi + + for ac_header in sys/sdt.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "sys/sdt.h" "ac_cv_header_sys_sdt_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_sdt_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_SDT_H 1 +_ACEOF + DTRACE_HEADERS_OK=yes +else + DTRACE_HEADERS_OK=no +fi + +done + + if test "x$DTRACE_HEADERS_OK" != "xyes"; then + DTRACE_DEP_MISSING=true + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if dtrace should be built" >&5 +$as_echo_n "checking if dtrace should be built... " >&6; } + if test "x$enable_dtrace" = "xyes"; then + if test "x$DTRACE_DEP_MISSING" = "xtrue"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, missing dependencies" >&5 +$as_echo "no, missing dependencies" >&6; } + + # Print a helpful message on how to acquire the necessary build dependency. + # dtrace is the help tag: freetype, cups, alsa etc + MISSING_DEPENDENCY=dtrace + + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + cygwin_help $MISSING_DEPENDENCY + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + msys_help $MISSING_DEPENDENCY + else + PKGHANDLER_COMMAND= + + case $PKGHANDLER in + apt-get) + apt_help $MISSING_DEPENDENCY ;; + yum) + yum_help $MISSING_DEPENDENCY ;; + port) + port_help $MISSING_DEPENDENCY ;; + pkgutil) + pkgutil_help $MISSING_DEPENDENCY ;; + pkgadd) + pkgadd_help $MISSING_DEPENDENCY ;; + esac + + if test "x$PKGHANDLER_COMMAND" != x; then + HELP_MSG="You might be able to fix this by running '$PKGHANDLER_COMMAND'." + fi + fi + + as_fn_error $? "Cannot enable dtrace with missing dependencies. See above. $HELP_MSG" "$LINENO" 5 + else + INCLUDE_DTRACE=true + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, forced" >&5 +$as_echo "yes, forced" >&6; } + fi + elif test "x$enable_dtrace" = "xno"; then + INCLUDE_DTRACE=false + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, forced" >&5 +$as_echo "no, forced" >&6; } + elif test "x$enable_dtrace" = "xauto" || test "x$enable_dtrace" = "x"; then + if test "x$OPENJDK_TARGET_OS" = "xlinux" && test "x$OPENJDK" != "xtrue"; then + INCLUDE_DTRACE=false + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, non-open linux build" >&5 +$as_echo "no, non-open linux build" >&6; } + elif test "x$DTRACE_DEP_MISSING" = "xtrue"; then + INCLUDE_DTRACE=false + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, missing dependencies" >&5 +$as_echo "no, missing dependencies" >&6; } + else + INCLUDE_DTRACE=true + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, dependencies present" >&5 +$as_echo "yes, dependencies present" >&6; } + fi + else + as_fn_error $? "Invalid value for --enable-dtrace: $enable_dtrace" "$LINENO" 5 + fi + + + + # The user can in some cases supply additional jvm features. For the custom + # variant, this defines the entire variant. + +# Check whether --with-jvm-features was given. +if test "${with_jvm_features+set}" = set; then : + withval=$with_jvm_features; +fi + + if test "x$with_jvm_features" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking additional JVM features" >&5 +$as_echo_n "checking additional JVM features... " >&6; } + JVM_FEATURES=`$ECHO $with_jvm_features | $SED -e 's/,/ /g'` + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JVM_FEATURES" >&5 +$as_echo "$JVM_FEATURES" >&6; } + fi + + # Verify that dependencies are met for explicitly set features. + if [[ " $JVM_FEATURES " =~ " jvmti " ]] && ! [[ " $JVM_FEATURES " =~ " services " ]] ; then + as_fn_error $? "Specified JVM feature 'jvmti' requires feature 'services'" "$LINENO" 5 + fi + + if [[ " $JVM_FEATURES " =~ " management " ]] && ! [[ " $JVM_FEATURES " =~ " nmt " ]] ; then + as_fn_error $? "Specified JVM feature 'management' requires feature 'nmt'" "$LINENO" 5 + fi + + if [[ " $JVM_FEATURES " =~ " jvmci " ]] && ! [[ " $JVM_FEATURES " =~ " compiler2 " ]] ; then + as_fn_error $? "Specified JVM feature 'jvmci' requires feature 'compiler2'" "$LINENO" 5 + fi + + if [[ " $JVM_FEATURES " =~ " compiler2 " ]] && ! [[ " $JVM_FEATURES " =~ " all-gcs " ]] ; then + as_fn_error $? "Specified JVM feature 'compiler2' requires feature 'all-gcs'" "$LINENO" 5 + fi + + if [[ " $JVM_FEATURES " =~ " vm-structs " ]] && ! [[ " $JVM_FEATURES " =~ " all-gcs " ]] ; then + as_fn_error $? "Specified JVM feature 'vm-structs' requires feature 'all-gcs'" "$LINENO" 5 + fi + + # Turn on additional features based on other parts of configure + if test "x$INCLUDE_DTRACE" = "xtrue"; then + JVM_FEATURES="$JVM_FEATURES dtrace" + else + if [[ " $JVM_FEATURES " =~ " dtrace " ]] ; then + as_fn_error $? "To enable dtrace, you must use --enable-dtrace" "$LINENO" 5 + fi + fi + + if test "x$STATIC_BUILD" = "xtrue"; then + JVM_FEATURES="$JVM_FEATURES static-build" + else + if [[ " $JVM_FEATURES " =~ " static-build " ]] ; then + as_fn_error $? "To enable static-build, you must use --enable-static-build" "$LINENO" 5 + fi + fi + + if ! [[ " $JVM_VARIANTS " =~ " zero " ]] && ! [[ " $JVM_VARIANTS " =~ " zeroshark " ]] ; then + if [[ " $JVM_FEATURES " =~ " zero " ]] ; then + as_fn_error $? "To enable zero/zeroshark, you must use --with-jvm-variants=zero/zeroshark" "$LINENO" 5 + fi + fi + + if ! [[ " $JVM_VARIANTS " =~ " zeroshark " ]] ; then + if [[ " $JVM_FEATURES " =~ " shark " ]] ; then + as_fn_error $? "To enable shark, you must use --with-jvm-variants=zeroshark" "$LINENO" 5 + fi + fi + + # Only enable jvmci on x86_64, sparcv9 and aarch64, and only on server. + if test "x$OPENJDK_TARGET_CPU" = "xx86_64" || \ + test "x$OPENJDK_TARGET_CPU" = "xsparcv9" || \ + test "x$OPENJDK_TARGET_CPU" = "xaarch64" ; then + JVM_FEATURES_jvmci="jvmci" + else + JVM_FEATURES_jvmci="" + fi + + # All variants but minimal (and custom) get these features + NON_MINIMAL_FEATURES="$NON_MINIMAL_FEATURES jvmti fprof vm-structs jni-check services management all-gcs nmt cds" + + # Enable features depending on variant. + JVM_FEATURES_server="compiler1 compiler2 $NON_MINIMAL_FEATURES $JVM_FEATURES $JVM_FEATURES_jvmci" + JVM_FEATURES_client="compiler1 $NON_MINIMAL_FEATURES $JVM_FEATURES" + JVM_FEATURES_core="$NON_MINIMAL_FEATURES $JVM_FEATURES" + JVM_FEATURES_minimal="compiler1 minimal $JVM_FEATURES" + JVM_FEATURES_zero="zero $NON_MINIMAL_FEATURES $JVM_FEATURES" + JVM_FEATURES_zeroshark="zero shark $NON_MINIMAL_FEATURES $JVM_FEATURES" + JVM_FEATURES_custom="$JVM_FEATURES" + + + + + + + + + + # Used for verification of Makefiles by check-jvm-feature + + + # We don't support --with-jvm-interpreter anymore, use zero instead. + + +# Check whether --with-jvm-interpreter was given. +if test "${with_jvm_interpreter+set}" = set; then : + withval=$with_jvm_interpreter; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --with-jvm-interpreter is deprecated and will be ignored." >&5 +$as_echo "$as_me: WARNING: Option --with-jvm-interpreter is deprecated and will be ignored." >&2;} +fi + + + + ############################################################################### # # Check dependencies for external and internal libraries. @@ -51023,7 +52721,7 @@ $as_echo "yes" >&6; } fi # Check if ffi is needed - if test "x$JVM_VARIANT_ZERO" = xtrue || test "x$JVM_VARIANT_ZEROSHARK" = xtrue; then + if [[ " $JVM_VARIANTS " =~ " zero " ]] || [[ " $JVM_VARIANTS " =~ " zeroshark " ]] ; then NEEDS_LIB_FFI=true else NEEDS_LIB_FFI=false @@ -51146,14 +52844,26 @@ $as_echo "$has_static_libstdcxx" >&6; } # If dynamic wasn't requested, go with static unless it isn't available. { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libstdc++" >&5 $as_echo_n "checking how to link with libstdc++... " >&6; } - if test "x$with_stdc__lib" = xdynamic || test "x$has_static_libstdcxx" = xno || test "x$JVM_VARIANT_ZEROSHARK" = xtrue; then + if test "x$with_stdc__lib" = xdynamic || test "x$has_static_libstdcxx" = xno || [[ " $JVM_VARIANTS " =~ " zeroshark " ]] ; then LIBCXX="$LIBCXX -lstdc++" + # To help comparisons with old build, put stdc++ first in JVM_LIBS + JVM_LIBS="-lstdc++ $JVM_LIBS" + # Ideally, we should test stdc++ for the BUILD toolchain separately. For now + # just use the same setting as for the TARGET toolchain. + OPENJDK_BUILD_JVM_LIBS="-lstdc++ $OPENJDK_BUILD_JVM_LIBS" LDCXX="$CXX" STATIC_CXX_SETTING="STATIC_CXX=false" { $as_echo "$as_me:${as_lineno-$LINENO}: result: dynamic" >&5 $as_echo "dynamic" >&6; } else LIBCXX="$LIBCXX $STATIC_STDCXX_FLAGS" + JVM_LDFLAGS="$JVM_LDFLAGS -static-libgcc" + # To help comparisons with old build, put stdc++ first in JVM_LIBS + JVM_LIBS="-Wl,-Bstatic -lstdc++ -Wl,-Bdynamic $JVM_LIBS" + # Ideally, we should test stdc++ for the BUILD toolchain separately. For now + # just use the same setting as for the TARGET toolchain. + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS -static-libgcc" + OPENJDK_BUILD_JVM_LIBS="-Wl,-Bstatic -lstdc++ -Wl,-Bdynamic $OPENJDK_BUILD_JVM_LIBS" LDCXX="$CC" STATIC_CXX_SETTING="STATIC_CXX=true" { $as_echo "$as_me:${as_lineno-$LINENO}: result: static" >&5 @@ -61305,7 +63015,7 @@ $as_echo "$LIBFFI_WORKS" >&6; } - if test "x$JVM_VARIANT_ZEROSHARK" = xtrue; then + if [[ " $JVM_VARIANTS " =~ " zeroshark " ]] ; then # Extract the first word of "llvm-config", so it can be a program name with args. set dummy llvm-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 @@ -62031,9 +63741,143 @@ fi ############################################################################### + # Check whether --enable-new-hotspot-build was given. +if test "${enable_new_hotspot_build+set}" = set; then : + enableval=$enable_new_hotspot_build; +fi + + + if test "x$enable_new_hotspot_build" = "x" || test "x$enable_new_hotspot_build" = "xyes"; then + USE_NEW_HOTSPOT_BUILD=true + else + USE_NEW_HOTSPOT_BUILD=false + fi + + + case $HOTSPOT_DEBUG_LEVEL in + product ) + VARIANT="OPT" + FASTDEBUG="false" + DEBUG_CLASSFILES="false" + ;; + fastdebug ) + VARIANT="DBG" + FASTDEBUG="true" + DEBUG_CLASSFILES="true" + ;; + debug ) + VARIANT="DBG" + FASTDEBUG="false" + DEBUG_CLASSFILES="true" + ;; + optimized ) + VARIANT="OPT" + FASTDEBUG="false" + DEBUG_CLASSFILES="false" + ;; + esac + + + + + if test "x$OPENJDK_TARGET_OS" = "xmacosx"; then + MACOSX_UNIVERSAL="true" + fi + + + + # Make sure JVM_VARIANTS_COMMA use minimal1 for backwards compatibility + JVM_VARIANTS_COMMA=`$ECHO ,$JVM_VARIANTS_OPT, | $SED -e 's/,minimal,/,minimal1,/'` + + JVM_VARIANT_SERVER=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,server,/!s/.*/false/g' -e '/,server,/s/.*/true/g'` + JVM_VARIANT_CLIENT=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,client,/!s/.*/false/g' -e '/,client,/s/.*/true/g'` + JVM_VARIANT_MINIMAL1=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,minimal1\?,/!s/.*/false/g' -e '/,minimal1\?,/s/.*/true/g'` + JVM_VARIANT_CORE=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,core,/!s/.*/false/g' -e '/,core,/s/.*/true/g'` + JVM_VARIANT_ZERO=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,zero,/!s/.*/false/g' -e '/,zero,/s/.*/true/g'` + JVM_VARIANT_ZEROSHARK=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,zeroshark,/!s/.*/false/g' -e '/,zeroshark,/s/.*/true/g'` + JVM_VARIANT_CUSTOM=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,custom,/!s/.*/false/g' -e '/,custom,/s/.*/true/g'` + + ##### + # Generate the legacy makefile targets for hotspot. + HOTSPOT_TARGET="" + + if test "x$JVM_VARIANT_SERVER" = xtrue; then + HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL} " + fi + + if test "x$JVM_VARIANT_CLIENT" = xtrue; then + HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}1 " + fi + + if test "x$JVM_VARIANT_MINIMAL1" = xtrue; then + HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}minimal1 " + fi + + if test "x$JVM_VARIANT_ZERO" = xtrue; then + HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}zero " + fi + + if test "x$JVM_VARIANT_ZEROSHARK" = xtrue; then + HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}shark " + fi + + if test "x$JVM_VARIANT_CORE" = xtrue; then + HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}core " + fi + + HOTSPOT_TARGET="$HOTSPOT_TARGET docs export_$HOTSPOT_DEBUG_LEVEL" + + # On Macosx universal binaries are produced, but they only contain + # 64 bit intel. This invalidates control of which jvms are built + # from configure, but only server is valid anyway. Fix this + # when hotspot makefiles are rewritten. + if test "x$MACOSX_UNIVERSAL" = xtrue; then + HOTSPOT_TARGET=universal_${HOTSPOT_DEBUG_LEVEL} + fi + HOTSPOT_MAKE_ARGS="$HOTSPOT_TARGET" + # Control wether Hotspot runs Queens test after build. + # Check whether --enable-hotspot-test-in-build was given. +if test "${enable_hotspot_test_in_build+set}" = set; then : + enableval=$enable_hotspot_test_in_build; +else + enable_hotspot_test_in_build=no +fi + + if test "x$enable_hotspot_test_in_build" = "xyes"; then + TEST_IN_BUILD=true + else + TEST_IN_BUILD=false + fi + + + if test "x$USE_NEW_HOTSPOT_BUILD" = xfalse; then + if test "x$JVM_VARIANT_CLIENT" = xtrue; then + if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then + as_fn_error $? "You cannot build a client JVM for a 64-bit machine." "$LINENO" 5 + fi + fi + if test "x$JVM_VARIANT_MINIMAL1" = xtrue; then + if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then + as_fn_error $? "You cannot build a minimal JVM for a 64-bit machine." "$LINENO" 5 + fi + fi + if test "x$JVM_VARIANT_CUSTOM" = xtrue; then + as_fn_error $? "You cannot build a custom JVM using the old hotspot build system." "$LINENO" 5 + fi + fi + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if elliptic curve crypto implementation is present" >&5 $as_echo_n "checking if elliptic curve crypto implementation is present... " >&6; } @@ -63322,6 +65166,10 @@ $as_echo "no, forced" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, does not work effectively with icecc" >&5 $as_echo "no, does not work effectively with icecc" >&6; } USE_PRECOMPILED_HEADER=0 + elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, does not work with Solaris Studio" >&5 +$as_echo "no, does not work with Solaris Studio" >&6; } + USE_PRECOMPILED_HEADER=0 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } @@ -63742,6 +65590,32 @@ $as_echo "$OUTPUT_DIR_IS_LOCAL" >&6; } # At the end, call the custom hook. (Dummy macro if no custom sources available) +# This needs to be done after CUSTOM_LATE_HOOK since we can setup custom features. + + # Keep feature lists sorted and free of duplicates + JVM_FEATURES_server="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_server | $SORT -u))" + JVM_FEATURES_client="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_client | $SORT -u))" + JVM_FEATURES_core="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_core | $SORT -u))" + JVM_FEATURES_minimal="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_minimal | $SORT -u))" + JVM_FEATURES_zero="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_zero | $SORT -u))" + JVM_FEATURES_zeroshark="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_zeroshark | $SORT -u))" + JVM_FEATURES_custom="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_custom | $SORT -u))" + + # Validate features + for variant in $JVM_VARIANTS; do + { $as_echo "$as_me:${as_lineno-$LINENO}: checking JVM features for JVM variant '$variant'" >&5 +$as_echo_n "checking JVM features for JVM variant '$variant'... " >&6; } + features_var_name=JVM_FEATURES_$variant + JVM_FEATURES_TO_TEST=${!features_var_name} + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JVM_FEATURES_TO_TEST" >&5 +$as_echo "$JVM_FEATURES_TO_TEST" >&6; } + INVALID_FEATURES=`$GREP -Fvx "${VALID_JVM_FEATURES// /$'\n'}" <<< "${JVM_FEATURES_TO_TEST// /$'\n'}"` + if test "x$INVALID_FEATURES" != x; then + as_fn_error $? "Invalid JVM feature(s): $INVALID_FEATURES" "$LINENO" 5 + fi + done + + # We're messing a bit with internal autoconf variables to put the config.status # in the output directory instead of the current directory. CONFIG_STATUS="$CONFIGURESUPPORT_OUTPUTDIR/config.status" @@ -64965,7 +66839,7 @@ fi printf "* Debug level: $DEBUG_LEVEL\n" printf "* HS debug level: $HOTSPOT_DEBUG_LEVEL\n" printf "* JDK variant: $JDK_VARIANT\n" - printf "* JVM variants: $with_jvm_variants\n" + printf "* JVM variants: $JVM_VARIANTS\n" printf "* OpenJDK target: OS: $OPENJDK_TARGET_OS, CPU architecture: $OPENJDK_TARGET_CPU_ARCH, address length: $OPENJDK_TARGET_CPU_BITS\n" printf "* Version string: $VERSION_STRING ($VERSION_SHORT)\n" @@ -64991,7 +66865,7 @@ fi fi printf "\n" - if test "x$BUILDING_MULTIPLE_JVM_VARIANTS" = "xyes"; then + if test "x$BUILDING_MULTIPLE_JVM_VARIANTS" = "xtrue"; then printf "NOTE: You have requested to build more than one version of the JVM, which\n" printf "will result in longer build times.\n" printf "\n" diff --git a/common/autoconf/help.m4 b/common/autoconf/help.m4 index d0892c56256aff8e089a936c0c0cccc0a8d9265b..e7ccdca3cf357eacd2b44fd7c78187eb5046f64a 100644 --- a/common/autoconf/help.m4 +++ b/common/autoconf/help.m4 @@ -119,6 +119,8 @@ apt_help() { PKGHANDLER_COMMAND="sudo apt-get install libX11-dev libxext-dev libxrender-dev libxtst-dev libxt-dev" ;; ccache) PKGHANDLER_COMMAND="sudo apt-get install ccache" ;; + dtrace) + PKGHANDLER_COMMAND="sudo apt-get install systemtap-sdt-dev" ;; esac } @@ -170,6 +172,13 @@ AC_DEFUN_ONCE([HELP_PRINT_ADDITIONAL_HELP_AND_EXIT], TOOLCHAIN_DESCRIPTION=${!toolchain_var_name} $PRINTF " %-10s %s\n" $toolchain "$TOOLCHAIN_DESCRIPTION" done + $PRINTF "\n" + + # Print available jvm features + $PRINTF "The following JVM features are available as arguments to --with-jvm-features.\n" + $PRINTF "Which are valid to use depends on the target platform.\n " + $PRINTF "%s " $VALID_JVM_FEATURES + $PRINTF "\n" # And now exit directly exit 0 @@ -206,7 +215,7 @@ AC_DEFUN_ONCE([HELP_PRINT_SUMMARY_AND_WARNINGS], printf "* Debug level: $DEBUG_LEVEL\n" printf "* HS debug level: $HOTSPOT_DEBUG_LEVEL\n" printf "* JDK variant: $JDK_VARIANT\n" - printf "* JVM variants: $with_jvm_variants\n" + printf "* JVM variants: $JVM_VARIANTS\n" printf "* OpenJDK target: OS: $OPENJDK_TARGET_OS, CPU architecture: $OPENJDK_TARGET_CPU_ARCH, address length: $OPENJDK_TARGET_CPU_BITS\n" printf "* Version string: $VERSION_STRING ($VERSION_SHORT)\n" @@ -232,7 +241,7 @@ AC_DEFUN_ONCE([HELP_PRINT_SUMMARY_AND_WARNINGS], fi printf "\n" - if test "x$BUILDING_MULTIPLE_JVM_VARIANTS" = "xyes"; then + if test "x$BUILDING_MULTIPLE_JVM_VARIANTS" = "xtrue"; then printf "NOTE: You have requested to build more than one version of the JVM, which\n" printf "will result in longer build times.\n" printf "\n" diff --git a/common/autoconf/hotspot-spec.gmk.in b/common/autoconf/hotspot-spec.gmk.in index 54b6ca2f9ed2a9f90d9016d60037422ebc4d94e6..50d790876a6c3a51044aa494e498778bf1146aee 100644 --- a/common/autoconf/hotspot-spec.gmk.in +++ b/common/autoconf/hotspot-spec.gmk.in @@ -38,6 +38,16 @@ include $(BASE_SPEC) # Legacy defines controlled by the SUPPORT_HEADLESS and SUPPORT_HEADFUL options. @BUILD_HEADLESS@ +JVM_VARIANTS:=@JVM_VARIANTS_COMMA@ + +JVM_VARIANT_SERVER:=@JVM_VARIANT_SERVER@ +JVM_VARIANT_CLIENT:=@JVM_VARIANT_CLIENT@ +JVM_VARIANT_MINIMAL1:=@JVM_VARIANT_MINIMAL1@ +JVM_VARIANT_CORE:=@JVM_VARIANT_CORE@ +JVM_VARIANT_ZERO:=@JVM_VARIANT_ZERO@ +JVM_VARIANT_ZEROSHARK:=@JVM_VARIANT_ZEROSHARK@ +JVM_VARIANT_CUSTOM:=@JVM_VARIANT_HOTSPOT@ + # Legacy setting: OPT or DBG VARIANT:=@VARIANT@ # Legacy setting: true or false @@ -92,8 +102,7 @@ LLVM_LDFLAGS=@LLVM_LDFLAGS@ ALT_OUTPUTDIR=$(HOTSPOT_OUTPUTDIR) ALT_EXPORT_PATH=$(HOTSPOT_DIST) -JVM_INTERPRETER:=@JVM_INTERPRETER@ -ifeq ($(JVM_INTERPRETER), cpp) +ifeq ($(HOTSPOT_TARGET_CPU), zero) CC_INTERP=true endif diff --git a/common/autoconf/hotspot.m4 b/common/autoconf/hotspot.m4 index fe3eec0ecdee3b0837ab8223a0a23943593e2b30..4fffa86983d7a3ea3983d33771186675bf574115 100644 --- a/common/autoconf/hotspot.m4 +++ b/common/autoconf/hotspot.m4 @@ -23,170 +23,344 @@ # questions. # +# All valid JVM features, regardless of platform +VALID_JVM_FEATURES="compiler1 compiler2 zero shark minimal dtrace jvmti jvmci \ + fprof vm-structs jni-check services management all-gcs nmt cds static-build" + +# All valid JVM variants +VALID_JVM_VARIANTS="server client minimal core zero zeroshark custom" + ############################################################################### -# Check which interpreter of the JVM we want to build. -# Currently we have: -# template: Template interpreter (the default) -# cpp : C++ interpreter -AC_DEFUN_ONCE([HOTSPOT_SETUP_JVM_INTERPRETER], -[ - AC_ARG_WITH([jvm-interpreter], [AS_HELP_STRING([--with-jvm-interpreter], - [JVM interpreter to build (template, cpp) @<:@template@:>@])]) +# Check if the specified JVM variant should be built. To be used in shell if +# constructs, like this: +# if HOTSPOT_CHECK_JVM_VARIANT(server); then +# +# Only valid to use after HOTSPOT_SETUP_JVM_VARIANTS has setup variants. - AC_MSG_CHECKING([which interpreter of the JVM to build]) - if test "x$with_jvm_interpreter" = x; then - JVM_INTERPRETER="template" - else - JVM_INTERPRETER="$with_jvm_interpreter" - fi - AC_MSG_RESULT([$JVM_INTERPRETER]) +# Definition kept in one line to allow inlining in if statements. +# Additional [] needed to keep m4 from mangling shell constructs. +AC_DEFUN([HOTSPOT_CHECK_JVM_VARIANT], +[ [ [[ " $JVM_VARIANTS " =~ " $1 " ]] ] ]) - if test "x$JVM_INTERPRETER" != xtemplate && test "x$JVM_INTERPRETER" != xcpp; then - AC_MSG_ERROR([The available JVM interpreters are: template, cpp]) - fi +############################################################################### +# Check if the specified JVM features are explicitly enabled. To be used in +# shell if constructs, like this: +# if HOTSPOT_CHECK_JVM_FEATURE(jvmti); then +# +# Only valid to use after HOTSPOT_SETUP_JVM_FEATURES has setup features. - AC_SUBST(JVM_INTERPRETER) -]) +# Definition kept in one line to allow inlining in if statements. +# Additional [] needed to keep m4 from mangling shell constructs. +AC_DEFUN([HOTSPOT_CHECK_JVM_FEATURE], +[ [ [[ " $JVM_FEATURES " =~ " $1 " ]] ] ]) ############################################################################### -# Check which variants of the JVM that we want to build. -# Currently we have: -# server: normal interpreter and a C2 or tiered C1/C2 compiler -# client: normal interpreter and C1 (no C2 compiler) (only 32-bit platforms) -# minimal1: reduced form of client with optional VM services and features stripped out -# zero: no machine code interpreter, no compiler -# zeroshark: zero interpreter and shark/llvm compiler backend -# core: interpreter only, no compiler (only works on some platforms) +# Check which variants of the JVM that we want to build. Available variants are: +# server: normal interpreter, and a tiered C1/C2 compiler +# client: normal interpreter, and C1 (no C2 compiler) +# minimal: reduced form of client with optional features stripped out +# core: normal interpreter only, no compiler +# zero: C++ based interpreter only, no compiler +# zeroshark: C++ based interpreter, and a llvm-based compiler +# custom: baseline JVM with no default features +# AC_DEFUN_ONCE([HOTSPOT_SETUP_JVM_VARIANTS], [ - AC_MSG_CHECKING([which variants of the JVM to build]) AC_ARG_WITH([jvm-variants], [AS_HELP_STRING([--with-jvm-variants], - [JVM variants (separated by commas) to build (server, client, minimal1, zero, zeroshark, core) @<:@server@:>@])]) + [JVM variants (separated by commas) to build (server,client,minimal,core,zero,zeroshark,custom) @<:@server@:>@])]) if test "x$with_jvm_variants" = x; then with_jvm_variants="server" fi + JVM_VARIANTS_OPT="$with_jvm_variants" + + # Has the user listed more than one variant? + # Additional [] needed to keep m4 from mangling shell constructs. + if [ [[ "$JVM_VARIANTS_OPT" =~ "," ]] ]; then + BUILDING_MULTIPLE_JVM_VARIANTS=true + else + BUILDING_MULTIPLE_JVM_VARIANTS=false + fi + # Replace the commas with AND for use in the build directory name. + JVM_VARIANTS_WITH_AND=`$ECHO "$JVM_VARIANTS_OPT" | $SED -e 's/,/AND/g'` + + AC_MSG_CHECKING([which variants of the JVM to build]) + # JVM_VARIANTS is a space-separated list. + # Also use minimal, not minimal1 (which is kept for backwards compatibility). + JVM_VARIANTS=`$ECHO $JVM_VARIANTS_OPT | $SED -e 's/,/ /g' -e 's/minimal1/minimal/'` + AC_MSG_RESULT([$JVM_VARIANTS]) + + # Check that the selected variants are valid - JVM_VARIANTS=",$with_jvm_variants," - TEST_VARIANTS=`$ECHO "$JVM_VARIANTS" | $SED -e 's/server,//' -e 's/client,//' -e 's/minimal1,//' -e 's/zero,//' -e 's/zeroshark,//' -e 's/core,//'` + # grep filter function inspired by a comment to http://stackoverflow.com/a/1617326 + INVALID_VARIANTS=`$GREP -Fvx "${VALID_JVM_VARIANTS// /$'\n'}" <<< "${JVM_VARIANTS// /$'\n'}"` + if test "x$INVALID_VARIANTS" != x; then + AC_MSG_NOTICE([Unknown variant(s) specified: $INVALID_VARIANTS]) + AC_MSG_ERROR([The available JVM variants are: $VALID_JVM_VARIANTS]) + fi - if test "x$TEST_VARIANTS" != "x,"; then - AC_MSG_ERROR([The available JVM variants are: server, client, minimal1, zero, zeroshark, core]) + # All "special" variants share the same output directory ("server") + VALID_MULTIPLE_JVM_VARIANTS="server client minimal" + INVALID_MULTIPLE_VARIANTS=`$GREP -Fvx "${VALID_MULTIPLE_JVM_VARIANTS// /$'\n'}" <<< "${JVM_VARIANTS// /$'\n'}"` + if test "x$INVALID_MULTIPLE_VARIANTS" != x && test "x$BUILDING_MULTIPLE_JVM_VARIANTS" = xtrue; then + AC_MSG_ERROR([You cannot build multiple variants with anything else than $VALID_MULTIPLE_JVM_VARIANTS.]) fi - AC_MSG_RESULT([$with_jvm_variants]) - JVM_VARIANT_SERVER=`$ECHO "$JVM_VARIANTS" | $SED -e '/,server,/!s/.*/false/g' -e '/,server,/s/.*/true/g'` - JVM_VARIANT_CLIENT=`$ECHO "$JVM_VARIANTS" | $SED -e '/,client,/!s/.*/false/g' -e '/,client,/s/.*/true/g'` - JVM_VARIANT_MINIMAL1=`$ECHO "$JVM_VARIANTS" | $SED -e '/,minimal1,/!s/.*/false/g' -e '/,minimal1,/s/.*/true/g'` - JVM_VARIANT_ZERO=`$ECHO "$JVM_VARIANTS" | $SED -e '/,zero,/!s/.*/false/g' -e '/,zero,/s/.*/true/g'` - JVM_VARIANT_ZEROSHARK=`$ECHO "$JVM_VARIANTS" | $SED -e '/,zeroshark,/!s/.*/false/g' -e '/,zeroshark,/s/.*/true/g'` - JVM_VARIANT_CORE=`$ECHO "$JVM_VARIANTS" | $SED -e '/,core,/!s/.*/false/g' -e '/,core,/s/.*/true/g'` + AC_SUBST(JVM_VARIANTS) + AC_SUBST(VALID_JVM_VARIANTS) - if test "x$JVM_VARIANT_CLIENT" = xtrue; then - if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then - AC_MSG_ERROR([You cannot build a client JVM for a 64-bit machine.]) + if HOTSPOT_CHECK_JVM_VARIANT(zero) || HOTSPOT_CHECK_JVM_VARIANT(zeroshark); then + # zero behaves as a platform and rewrites these values. This is really weird. :( + # We are guaranteed that we do not build any other variants when building zero. + HOTSPOT_TARGET_CPU=zero + HOTSPOT_TARGET_CPU_ARCH=zero + fi +]) + +############################################################################### +# Check if dtrace should be enabled and has all prerequisites present. +# +AC_DEFUN_ONCE([HOTSPOT_SETUP_DTRACE], +[ + # Test for dtrace dependencies + AC_ARG_ENABLE([dtrace], [AS_HELP_STRING([--enable-dtrace@<:@=yes/no/auto@:>@], + [enable dtrace. Default is auto, where dtrace is enabled if all dependencies + are present.])]) + + DTRACE_DEP_MISSING=false + + AC_MSG_CHECKING([for dtrace tool]) + if test "x$DTRACE" != "x" && test -x "$DTRACE"; then + AC_MSG_RESULT([$DTRACE]) + else + AC_MSG_RESULT([not found, cannot build dtrace]) + DTRACE_DEP_MISSING=true + fi + + AC_CHECK_HEADERS([sys/sdt.h], [DTRACE_HEADERS_OK=yes],[DTRACE_HEADERS_OK=no]) + if test "x$DTRACE_HEADERS_OK" != "xyes"; then + DTRACE_DEP_MISSING=true + fi + + AC_MSG_CHECKING([if dtrace should be built]) + if test "x$enable_dtrace" = "xyes"; then + if test "x$DTRACE_DEP_MISSING" = "xtrue"; then + AC_MSG_RESULT([no, missing dependencies]) + HELP_MSG_MISSING_DEPENDENCY([dtrace]) + AC_MSG_ERROR([Cannot enable dtrace with missing dependencies. See above. $HELP_MSG]) + else + INCLUDE_DTRACE=true + AC_MSG_RESULT([yes, forced]) + fi + elif test "x$enable_dtrace" = "xno"; then + INCLUDE_DTRACE=false + AC_MSG_RESULT([no, forced]) + elif test "x$enable_dtrace" = "xauto" || test "x$enable_dtrace" = "x"; then + if test "x$OPENJDK_TARGET_OS" = "xlinux" && test "x$OPENJDK" != "xtrue"; then + INCLUDE_DTRACE=false + AC_MSG_RESULT([no, non-open linux build]) + elif test "x$DTRACE_DEP_MISSING" = "xtrue"; then + INCLUDE_DTRACE=false + AC_MSG_RESULT([no, missing dependencies]) + else + INCLUDE_DTRACE=true + AC_MSG_RESULT([yes, dependencies present]) fi + else + AC_MSG_ERROR([Invalid value for --enable-dtrace: $enable_dtrace]) fi - if test "x$JVM_VARIANT_MINIMAL1" = xtrue; then - if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then - AC_MSG_ERROR([You cannot build a minimal JVM for a 64-bit machine.]) + AC_SUBST(INCLUDE_DTRACE) +]) + +############################################################################### +# Set up all JVM features for each JVM variant. +# +AC_DEFUN_ONCE([HOTSPOT_SETUP_JVM_FEATURES], +[ + # The user can in some cases supply additional jvm features. For the custom + # variant, this defines the entire variant. + AC_ARG_WITH([jvm-features], [AS_HELP_STRING([--with-jvm-features], + [additional JVM features to enable (separated by comma), use '--help' to show possible values @<:@none@:>@])]) + if test "x$with_jvm_features" != x; then + AC_MSG_CHECKING([additional JVM features]) + JVM_FEATURES=`$ECHO $with_jvm_features | $SED -e 's/,/ /g'` + AC_MSG_RESULT([$JVM_FEATURES]) + fi + + # Verify that dependencies are met for explicitly set features. + if HOTSPOT_CHECK_JVM_FEATURE(jvmti) && ! HOTSPOT_CHECK_JVM_FEATURE(services); then + AC_MSG_ERROR([Specified JVM feature 'jvmti' requires feature 'services']) + fi + + if HOTSPOT_CHECK_JVM_FEATURE(management) && ! HOTSPOT_CHECK_JVM_FEATURE(nmt); then + AC_MSG_ERROR([Specified JVM feature 'management' requires feature 'nmt']) + fi + + if HOTSPOT_CHECK_JVM_FEATURE(jvmci) && ! HOTSPOT_CHECK_JVM_FEATURE(compiler2); then + AC_MSG_ERROR([Specified JVM feature 'jvmci' requires feature 'compiler2']) + fi + + if HOTSPOT_CHECK_JVM_FEATURE(compiler2) && ! HOTSPOT_CHECK_JVM_FEATURE(all-gcs); then + AC_MSG_ERROR([Specified JVM feature 'compiler2' requires feature 'all-gcs']) + fi + + if HOTSPOT_CHECK_JVM_FEATURE(vm-structs) && ! HOTSPOT_CHECK_JVM_FEATURE(all-gcs); then + AC_MSG_ERROR([Specified JVM feature 'vm-structs' requires feature 'all-gcs']) + fi + + # Turn on additional features based on other parts of configure + if test "x$INCLUDE_DTRACE" = "xtrue"; then + JVM_FEATURES="$JVM_FEATURES dtrace" + else + if HOTSPOT_CHECK_JVM_FEATURE(dtrace); then + AC_MSG_ERROR([To enable dtrace, you must use --enable-dtrace]) fi fi - # Replace the commas with AND for use in the build directory name. - ANDED_JVM_VARIANTS=`$ECHO "$JVM_VARIANTS" | $SED -e 's/^,//' -e 's/,$//' -e 's/,/AND/g'` - COUNT_VARIANTS=`$ECHO "$JVM_VARIANTS" | $SED -e 's/server,/1/' -e 's/client,/1/' -e 's/minimal1,/1/' -e 's/zero,/1/' -e 's/zeroshark,/1/' -e 's/core,/1/'` - if test "x$COUNT_VARIANTS" != "x,1"; then - BUILDING_MULTIPLE_JVM_VARIANTS=yes + if test "x$STATIC_BUILD" = "xtrue"; then + JVM_FEATURES="$JVM_FEATURES static-build" else - BUILDING_MULTIPLE_JVM_VARIANTS=no + if HOTSPOT_CHECK_JVM_FEATURE(static-build); then + AC_MSG_ERROR([To enable static-build, you must use --enable-static-build]) + fi fi - if test "x$JVM_VARIANT_ZERO" = xtrue && test "x$BUILDING_MULTIPLE_JVM_VARIANTS" = xyes; then - AC_MSG_ERROR([You cannot build multiple variants with zero.]) + if ! HOTSPOT_CHECK_JVM_VARIANT(zero) && ! HOTSPOT_CHECK_JVM_VARIANT(zeroshark); then + if HOTSPOT_CHECK_JVM_FEATURE(zero); then + AC_MSG_ERROR([To enable zero/zeroshark, you must use --with-jvm-variants=zero/zeroshark]) + fi fi - AC_SUBST(JVM_VARIANTS) - AC_SUBST(JVM_VARIANT_SERVER) - AC_SUBST(JVM_VARIANT_CLIENT) - AC_SUBST(JVM_VARIANT_MINIMAL1) - AC_SUBST(JVM_VARIANT_ZERO) - AC_SUBST(JVM_VARIANT_ZEROSHARK) - AC_SUBST(JVM_VARIANT_CORE) + if ! HOTSPOT_CHECK_JVM_VARIANT(zeroshark); then + if HOTSPOT_CHECK_JVM_FEATURE(shark); then + AC_MSG_ERROR([To enable shark, you must use --with-jvm-variants=zeroshark]) + fi + fi - if test "x$OPENJDK_TARGET_OS" = "xmacosx"; then - MACOSX_UNIVERSAL="true" + # Only enable jvmci on x86_64, sparcv9 and aarch64, and only on server. + if test "x$OPENJDK_TARGET_CPU" = "xx86_64" || \ + test "x$OPENJDK_TARGET_CPU" = "xsparcv9" || \ + test "x$OPENJDK_TARGET_CPU" = "xaarch64" ; then + JVM_FEATURES_jvmci="jvmci" + else + JVM_FEATURES_jvmci="" fi - AC_SUBST(MACOSX_UNIVERSAL) -]) + # All variants but minimal (and custom) get these features + NON_MINIMAL_FEATURES="$NON_MINIMAL_FEATURES jvmti fprof vm-structs jni-check services management all-gcs nmt cds" + + # Enable features depending on variant. + JVM_FEATURES_server="compiler1 compiler2 $NON_MINIMAL_FEATURES $JVM_FEATURES $JVM_FEATURES_jvmci" + JVM_FEATURES_client="compiler1 $NON_MINIMAL_FEATURES $JVM_FEATURES" + JVM_FEATURES_core="$NON_MINIMAL_FEATURES $JVM_FEATURES" + JVM_FEATURES_minimal="compiler1 minimal $JVM_FEATURES" + JVM_FEATURES_zero="zero $NON_MINIMAL_FEATURES $JVM_FEATURES" + JVM_FEATURES_zeroshark="zero shark $NON_MINIMAL_FEATURES $JVM_FEATURES" + JVM_FEATURES_custom="$JVM_FEATURES" + AC_SUBST(JVM_FEATURES_server) + AC_SUBST(JVM_FEATURES_client) + AC_SUBST(JVM_FEATURES_core) + AC_SUBST(JVM_FEATURES_minimal) + AC_SUBST(JVM_FEATURES_zero) + AC_SUBST(JVM_FEATURES_zeroshark) + AC_SUBST(JVM_FEATURES_custom) + + # Used for verification of Makefiles by check-jvm-feature + AC_SUBST(VALID_JVM_FEATURES) + + # We don't support --with-jvm-interpreter anymore, use zero instead. + BASIC_DEPRECATED_ARG_WITH(jvm-interpreter) +]) ############################################################################### -# Setup legacy vars/targets and new vars to deal with different debug levels. +# Validate JVM features once all setup is complete, including custom setup. # -# release: no debug information, all optimizations, no asserts. -# optimized: no debug information, all optimizations, no asserts, HotSpot target is 'optimized'. -# fastdebug: debug information (-g), all optimizations, all asserts -# slowdebug: debug information (-g), no optimizations, all asserts +AC_DEFUN_ONCE([HOTSPOT_VALIDATE_JVM_FEATURES], +[ + # Keep feature lists sorted and free of duplicates + JVM_FEATURES_server="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_server | $SORT -u))" + JVM_FEATURES_client="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_client | $SORT -u))" + JVM_FEATURES_core="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_core | $SORT -u))" + JVM_FEATURES_minimal="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_minimal | $SORT -u))" + JVM_FEATURES_zero="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_zero | $SORT -u))" + JVM_FEATURES_zeroshark="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_zeroshark | $SORT -u))" + JVM_FEATURES_custom="$($ECHO $($PRINTF '%s\n' $JVM_FEATURES_custom | $SORT -u))" + + # Validate features + for variant in $JVM_VARIANTS; do + AC_MSG_CHECKING([JVM features for JVM variant '$variant']) + features_var_name=JVM_FEATURES_$variant + JVM_FEATURES_TO_TEST=${!features_var_name} + AC_MSG_RESULT([$JVM_FEATURES_TO_TEST]) + INVALID_FEATURES=`$GREP -Fvx "${VALID_JVM_FEATURES// /$'\n'}" <<< "${JVM_FEATURES_TO_TEST// /$'\n'}"` + if test "x$INVALID_FEATURES" != x; then + AC_MSG_ERROR([Invalid JVM feature(s): $INVALID_FEATURES]) + fi + done +]) + +############################################################################### +# Support for old hotspot build. Remove once new hotspot build has proven +# to work satisfactory. # -AC_DEFUN_ONCE([HOTSPOT_SETUP_DEBUG_LEVEL], +AC_DEFUN_ONCE([HOTSPOT_SETUP_LEGACY_BUILD], [ - case $DEBUG_LEVEL in - release ) + AC_ARG_ENABLE(new-hotspot-build, [AS_HELP_STRING([--disable-new-hotspot-build], + [disable the new hotspot build system (use the old) @<:@enabled@:>@])]) + + if test "x$enable_new_hotspot_build" = "x" || test "x$enable_new_hotspot_build" = "xyes"; then + USE_NEW_HOTSPOT_BUILD=true + else + USE_NEW_HOTSPOT_BUILD=false + fi + AC_SUBST(USE_NEW_HOTSPOT_BUILD) + + case $HOTSPOT_DEBUG_LEVEL in + product ) VARIANT="OPT" FASTDEBUG="false" DEBUG_CLASSFILES="false" - BUILD_VARIANT_RELEASE="" - HOTSPOT_DEBUG_LEVEL="product" - HOTSPOT_EXPORT="product" ;; fastdebug ) VARIANT="DBG" FASTDEBUG="true" DEBUG_CLASSFILES="true" - BUILD_VARIANT_RELEASE="-fastdebug" - HOTSPOT_DEBUG_LEVEL="fastdebug" - HOTSPOT_EXPORT="fastdebug" ;; - slowdebug ) + debug ) VARIANT="DBG" FASTDEBUG="false" DEBUG_CLASSFILES="true" - BUILD_VARIANT_RELEASE="-debug" - HOTSPOT_DEBUG_LEVEL="debug" - HOTSPOT_EXPORT="debug" ;; optimized ) VARIANT="OPT" FASTDEBUG="false" DEBUG_CLASSFILES="false" - BUILD_VARIANT_RELEASE="-optimized" - HOTSPOT_DEBUG_LEVEL="optimized" - HOTSPOT_EXPORT="optimized" ;; esac + AC_SUBST(VARIANT) + AC_SUBST(FASTDEBUG) + AC_SUBST(DEBUG_CLASSFILES) - # The debug level 'optimized' is a little special because it is currently only - # applicable to the HotSpot build where it means to build a completely - # optimized version of the VM without any debugging code (like for the - # 'release' debug level which is called 'product' in the HotSpot build) but - # with the exception that it can contain additional code which is otherwise - # protected by '#ifndef PRODUCT' macros. These 'optimized' builds are used to - # test new and/or experimental features which are not intended for customer - # shipment. Because these new features need to be tested and benchmarked in - # real world scenarios, we want to build the containing JDK at the 'release' - # debug level. - if test "x$DEBUG_LEVEL" = xoptimized; then - DEBUG_LEVEL="release" + if test "x$OPENJDK_TARGET_OS" = "xmacosx"; then + MACOSX_UNIVERSAL="true" fi + AC_SUBST(MACOSX_UNIVERSAL) + + # Make sure JVM_VARIANTS_COMMA use minimal1 for backwards compatibility + JVM_VARIANTS_COMMA=`$ECHO ,$JVM_VARIANTS_OPT, | $SED -e 's/,minimal,/,minimal1,/'` + + JVM_VARIANT_SERVER=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,server,/!s/.*/false/g' -e '/,server,/s/.*/true/g'` + JVM_VARIANT_CLIENT=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,client,/!s/.*/false/g' -e '/,client,/s/.*/true/g'` + JVM_VARIANT_MINIMAL1=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,minimal1\?,/!s/.*/false/g' -e '/,minimal1\?,/s/.*/true/g'` + JVM_VARIANT_CORE=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,core,/!s/.*/false/g' -e '/,core,/s/.*/true/g'` + JVM_VARIANT_ZERO=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,zero,/!s/.*/false/g' -e '/,zero,/s/.*/true/g'` + JVM_VARIANT_ZEROSHARK=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,zeroshark,/!s/.*/false/g' -e '/,zeroshark,/s/.*/true/g'` + JVM_VARIANT_CUSTOM=`$ECHO "$JVM_VARIANTS_COMMA" | $SED -e '/,custom,/!s/.*/false/g' -e '/,custom,/s/.*/true/g'` + ##### # Generate the legacy makefile targets for hotspot. - # The hotspot api for selecting the build artifacts, really, needs to be improved. - # JDK-7195896 will fix this on the hotspot side by using the JVM_VARIANT_* variables to - # determine what needs to be built. All we will need to set here is all_product, all_fastdebug etc - # But until then ... HOTSPOT_TARGET="" if test "x$JVM_VARIANT_SERVER" = xtrue; then @@ -213,27 +387,19 @@ AC_DEFUN_ONCE([HOTSPOT_SETUP_DEBUG_LEVEL], HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}core " fi - HOTSPOT_TARGET="$HOTSPOT_TARGET docs export_$HOTSPOT_EXPORT" + HOTSPOT_TARGET="$HOTSPOT_TARGET docs export_$HOTSPOT_DEBUG_LEVEL" # On Macosx universal binaries are produced, but they only contain # 64 bit intel. This invalidates control of which jvms are built # from configure, but only server is valid anyway. Fix this # when hotspot makefiles are rewritten. if test "x$MACOSX_UNIVERSAL" = xtrue; then - HOTSPOT_TARGET=universal_${HOTSPOT_EXPORT} + HOTSPOT_TARGET=universal_${HOTSPOT_DEBUG_LEVEL} fi - ##### - - AC_SUBST(DEBUG_LEVEL) - AC_SUBST(VARIANT) - AC_SUBST(FASTDEBUG) - AC_SUBST(DEBUG_CLASSFILES) - AC_SUBST(BUILD_VARIANT_RELEASE) -]) + HOTSPOT_MAKE_ARGS="$HOTSPOT_TARGET" + AC_SUBST(HOTSPOT_MAKE_ARGS) -AC_DEFUN_ONCE([HOTSPOT_SETUP_HOTSPOT_OPTIONS], -[ # Control wether Hotspot runs Queens test after build. AC_ARG_ENABLE([hotspot-test-in-build], [AS_HELP_STRING([--enable-hotspot-test-in-build], [run the Queens test after Hotspot build @<:@disabled@:>@])],, @@ -244,10 +410,29 @@ AC_DEFUN_ONCE([HOTSPOT_SETUP_HOTSPOT_OPTIONS], TEST_IN_BUILD=false fi AC_SUBST(TEST_IN_BUILD) -]) -AC_DEFUN_ONCE([HOTSPOT_SETUP_BUILD_TWEAKS], -[ - HOTSPOT_MAKE_ARGS="$HOTSPOT_TARGET" - AC_SUBST(HOTSPOT_MAKE_ARGS) + if test "x$USE_NEW_HOTSPOT_BUILD" = xfalse; then + if test "x$JVM_VARIANT_CLIENT" = xtrue; then + if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then + AC_MSG_ERROR([You cannot build a client JVM for a 64-bit machine.]) + fi + fi + if test "x$JVM_VARIANT_MINIMAL1" = xtrue; then + if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then + AC_MSG_ERROR([You cannot build a minimal JVM for a 64-bit machine.]) + fi + fi + if test "x$JVM_VARIANT_CUSTOM" = xtrue; then + AC_MSG_ERROR([You cannot build a custom JVM using the old hotspot build system.]) + fi + fi + + AC_SUBST(JVM_VARIANTS_COMMA) + AC_SUBST(JVM_VARIANT_SERVER) + AC_SUBST(JVM_VARIANT_CLIENT) + AC_SUBST(JVM_VARIANT_MINIMAL1) + AC_SUBST(JVM_VARIANT_HOTSPOT) + AC_SUBST(JVM_VARIANT_ZERO) + AC_SUBST(JVM_VARIANT_ZEROSHARK) + AC_SUBST(JVM_VARIANT_CORE) ]) diff --git a/common/autoconf/jdk-options.m4 b/common/autoconf/jdk-options.m4 index 4937c6b1ad169b5715079413030466975fe79171..e34e4d927dd1da5f171b0b698bbc19ea55a4edcc 100644 --- a/common/autoconf/jdk-options.m4 +++ b/common/autoconf/jdk-options.m4 @@ -81,6 +81,31 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_DEBUG_LEVEL], test "x$DEBUG_LEVEL" != xslowdebug; then AC_MSG_ERROR([Allowed debug levels are: release, fastdebug, slowdebug and optimized]) fi + + # Translate DEBUG_LEVEL to debug level used by Hotspot + HOTSPOT_DEBUG_LEVEL="$DEBUG_LEVEL" + if test "x$DEBUG_LEVEL" = xrelease; then + HOTSPOT_DEBUG_LEVEL="product" + elif test "x$DEBUG_LEVEL" = xslowdebug; then + HOTSPOT_DEBUG_LEVEL="debug" + fi + + if test "x$DEBUG_LEVEL" = xoptimized; then + # The debug level 'optimized' is a little special because it is currently only + # applicable to the HotSpot build where it means to build a completely + # optimized version of the VM without any debugging code (like for the + # 'release' debug level which is called 'product' in the HotSpot build) but + # with the exception that it can contain additional code which is otherwise + # protected by '#ifndef PRODUCT' macros. These 'optimized' builds are used to + # test new and/or experimental features which are not intended for customer + # shipment. Because these new features need to be tested and benchmarked in + # real world scenarios, we want to build the containing JDK at the 'release' + # debug level. + DEBUG_LEVEL="release" + fi + + AC_SUBST(HOTSPOT_DEBUG_LEVEL) + AC_SUBST(DEBUG_LEVEL) ]) ############################################################################### @@ -178,10 +203,7 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_JDK_OPTIONS], # Should we build the serviceability agent (SA)? INCLUDE_SA=true - if test "x$JVM_VARIANT_ZERO" = xtrue ; then - INCLUDE_SA=false - fi - if test "x$JVM_VARIANT_ZEROSHARK" = xtrue ; then + if HOTSPOT_CHECK_JVM_VARIANT(zero) || HOTSPOT_CHECK_JVM_VARIANT(zeroshark); then INCLUDE_SA=false fi if test "x$OPENJDK_TARGET_OS" = xaix ; then diff --git a/common/autoconf/jdk-version.m4 b/common/autoconf/jdk-version.m4 index 2dc63865c49542e25c7f23f2e2935011e067c8f8..3b2fbfb60f1560ba4f2610a82def6c4805a6095b 100644 --- a/common/autoconf/jdk-version.m4 +++ b/common/autoconf/jdk-version.m4 @@ -72,6 +72,7 @@ AC_DEFUN_ONCE([JDKVER_SETUP_JDK_VERSION_NUMBERS], AC_SUBST(PRODUCT_SUFFIX) AC_SUBST(JDK_RC_PLATFORM_NAME) AC_SUBST(COMPANY_NAME) + AC_SUBST(HOTSPOT_VM_DISTRO) AC_SUBST(MACOSX_BUNDLE_NAME_BASE) AC_SUBST(MACOSX_BUNDLE_ID_BASE) diff --git a/common/autoconf/lib-std.m4 b/common/autoconf/lib-std.m4 index d3f94609630c8995d7bb23c3845d67af9912c2be..6fa0b4844afd97005106a84ad657f5c66782c006 100644 --- a/common/autoconf/lib-std.m4 +++ b/common/autoconf/lib-std.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # 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,13 +88,25 @@ AC_DEFUN_ONCE([LIB_SETUP_STD_LIBS], # If dynamic was requested, it's available since it would fail above otherwise. # If dynamic wasn't requested, go with static unless it isn't available. AC_MSG_CHECKING([how to link with libstdc++]) - if test "x$with_stdc__lib" = xdynamic || test "x$has_static_libstdcxx" = xno || test "x$JVM_VARIANT_ZEROSHARK" = xtrue; then + if test "x$with_stdc__lib" = xdynamic || test "x$has_static_libstdcxx" = xno || HOTSPOT_CHECK_JVM_VARIANT(zeroshark); then LIBCXX="$LIBCXX -lstdc++" + # To help comparisons with old build, put stdc++ first in JVM_LIBS + JVM_LIBS="-lstdc++ $JVM_LIBS" + # Ideally, we should test stdc++ for the BUILD toolchain separately. For now + # just use the same setting as for the TARGET toolchain. + OPENJDK_BUILD_JVM_LIBS="-lstdc++ $OPENJDK_BUILD_JVM_LIBS" LDCXX="$CXX" STATIC_CXX_SETTING="STATIC_CXX=false" AC_MSG_RESULT([dynamic]) else LIBCXX="$LIBCXX $STATIC_STDCXX_FLAGS" + JVM_LDFLAGS="$JVM_LDFLAGS -static-libgcc" + # To help comparisons with old build, put stdc++ first in JVM_LIBS + JVM_LIBS="-Wl,-Bstatic -lstdc++ -Wl,-Bdynamic $JVM_LIBS" + # Ideally, we should test stdc++ for the BUILD toolchain separately. For now + # just use the same setting as for the TARGET toolchain. + OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS -static-libgcc" + OPENJDK_BUILD_JVM_LIBS="-Wl,-Bstatic -lstdc++ -Wl,-Bdynamic $OPENJDK_BUILD_JVM_LIBS" LDCXX="$CC" STATIC_CXX_SETTING="STATIC_CXX=true" AC_MSG_RESULT([static]) diff --git a/common/autoconf/libraries.m4 b/common/autoconf/libraries.m4 index a6a8bd4f19b487f3fb107d67d983fe399b18a0b4..e1e91d678d6bbad45e8440450a48acdf22ce943c 100644 --- a/common/autoconf/libraries.m4 +++ b/common/autoconf/libraries.m4 @@ -74,7 +74,7 @@ AC_DEFUN_ONCE([LIB_DETERMINE_DEPENDENCIES], fi # Check if ffi is needed - if test "x$JVM_VARIANT_ZERO" = xtrue || test "x$JVM_VARIANT_ZEROSHARK" = xtrue; then + if HOTSPOT_CHECK_JVM_VARIANT(zero) || HOTSPOT_CHECK_JVM_VARIANT(zeroshark); then NEEDS_LIB_FFI=true else NEEDS_LIB_FFI=false @@ -102,7 +102,7 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBRARIES], ################################################################################ AC_DEFUN_ONCE([LIB_SETUP_LLVM], [ - if test "x$JVM_VARIANT_ZEROSHARK" = xtrue; then + if HOTSPOT_CHECK_JVM_VARIANT(zeroshark); then AC_CHECK_PROG([LLVM_CONFIG], [llvm-config], [llvm-config]) if test "x$LLVM_CONFIG" != xllvm-config; then diff --git a/common/autoconf/platform.m4 b/common/autoconf/platform.m4 index fe5a201ecd98bbbf4aa5138342bcbf7f2e97f980..deaf22ed169616f66c5045f6efc9c9bef1e40677 100644 --- a/common/autoconf/platform.m4 +++ b/common/autoconf/platform.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -274,168 +274,172 @@ AC_DEFUN([PLATFORM_SETUP_TARGET_CPU_BITS], # AC_DEFUN([PLATFORM_SETUP_LEGACY_VARS], [ - # Also store the legacy naming of the cpu. - # Ie i586 and amd64 instead of x86 and x86_64 - OPENJDK_TARGET_CPU_LEGACY="$OPENJDK_TARGET_CPU" - if test "x$OPENJDK_TARGET_CPU" = xx86; then - OPENJDK_TARGET_CPU_LEGACY="i586" - elif test "x$OPENJDK_TARGET_OS" != xmacosx && test "x$OPENJDK_TARGET_CPU" = xx86_64; then - # On all platforms except MacOSX replace x86_64 with amd64. - OPENJDK_TARGET_CPU_LEGACY="amd64" - fi - AC_SUBST(OPENJDK_TARGET_CPU_LEGACY) + PLATFORM_SETUP_LEGACY_VARS_HELPER([TARGET]) + PLATFORM_SETUP_LEGACY_VARS_HELPER([BUILD]) - # And the second legacy naming of the cpu. - # Ie i386 and amd64 instead of x86 and x86_64. - OPENJDK_TARGET_CPU_LEGACY_LIB="$OPENJDK_TARGET_CPU" - if test "x$OPENJDK_TARGET_CPU" = xx86; then - OPENJDK_TARGET_CPU_LEGACY_LIB="i386" - elif test "x$OPENJDK_TARGET_CPU" = xx86_64; then - OPENJDK_TARGET_CPU_LEGACY_LIB="amd64" - fi - AC_SUBST(OPENJDK_TARGET_CPU_LEGACY_LIB) + # ZERO_ARCHDEF is used to enable architecture-specific code. + # This is used in legacy hotspot build. + ZERO_ARCHDEF="$HOTSPOT_TARGET_CPU_DEFINE" + AC_SUBST(ZERO_ARCHDEF) - # This is the name of the cpu (but using i386 and amd64 instead of - # x86 and x86_64, respectively), preceeded by a /, to be used when - # locating libraries. On macosx, it's empty, though. - OPENJDK_TARGET_CPU_LIBDIR="/$OPENJDK_TARGET_CPU_LEGACY_LIB" - if test "x$OPENJDK_TARGET_OS" = xmacosx; then - OPENJDK_TARGET_CPU_LIBDIR="" - fi - AC_SUBST(OPENJDK_TARGET_CPU_LIBDIR) +]) - # Now do the same for OPENJDK_BUILD_CPU... +# $1 - Either TARGET or BUILD to setup the variables for. +AC_DEFUN([PLATFORM_SETUP_LEGACY_VARS_HELPER], +[ # Also store the legacy naming of the cpu. # Ie i586 and amd64 instead of x86 and x86_64 - OPENJDK_BUILD_CPU_LEGACY="$OPENJDK_BUILD_CPU" - if test "x$OPENJDK_BUILD_CPU" = xx86; then - OPENJDK_BUILD_CPU_LEGACY="i586" - elif test "x$OPENJDK_BUILD_OS" != xmacosx && test "x$OPENJDK_BUILD_CPU" = xx86_64; then + OPENJDK_$1_CPU_LEGACY="$OPENJDK_$1_CPU" + if test "x$OPENJDK_$1_CPU" = xx86; then + OPENJDK_$1_CPU_LEGACY="i586" + elif test "x$OPENJDK_$1_OS" != xmacosx && test "x$OPENJDK_$1_CPU" = xx86_64; then # On all platforms except MacOSX replace x86_64 with amd64. - OPENJDK_BUILD_CPU_LEGACY="amd64" + OPENJDK_$1_CPU_LEGACY="amd64" fi - AC_SUBST(OPENJDK_BUILD_CPU_LEGACY) + AC_SUBST(OPENJDK_$1_CPU_LEGACY) # And the second legacy naming of the cpu. # Ie i386 and amd64 instead of x86 and x86_64. - OPENJDK_BUILD_CPU_LEGACY_LIB="$OPENJDK_BUILD_CPU" - if test "x$OPENJDK_BUILD_CPU" = xx86; then - OPENJDK_BUILD_CPU_LEGACY_LIB="i386" - elif test "x$OPENJDK_BUILD_CPU" = xx86_64; then - OPENJDK_BUILD_CPU_LEGACY_LIB="amd64" + OPENJDK_$1_CPU_LEGACY_LIB="$OPENJDK_$1_CPU" + if test "x$OPENJDK_$1_CPU" = xx86; then + OPENJDK_$1_CPU_LEGACY_LIB="i386" + elif test "x$OPENJDK_$1_CPU" = xx86_64; then + OPENJDK_$1_CPU_LEGACY_LIB="amd64" fi - AC_SUBST(OPENJDK_BUILD_CPU_LEGACY_LIB) + AC_SUBST(OPENJDK_$1_CPU_LEGACY_LIB) # This is the name of the cpu (but using i386 and amd64 instead of # x86 and x86_64, respectively), preceeded by a /, to be used when # locating libraries. On macosx, it's empty, though. - OPENJDK_BUILD_CPU_LIBDIR="/$OPENJDK_BUILD_CPU_LEGACY_LIB" - if test "x$OPENJDK_BUILD_OS" = xmacosx; then - OPENJDK_BUILD_CPU_LIBDIR="" + OPENJDK_$1_CPU_LIBDIR="/$OPENJDK_$1_CPU_LEGACY_LIB" + if test "x$OPENJDK_$1_OS" = xmacosx; then + OPENJDK_$1_CPU_LIBDIR="" fi - AC_SUBST(OPENJDK_BUILD_CPU_LIBDIR) + AC_SUBST(OPENJDK_$1_CPU_LIBDIR) - # OPENJDK_TARGET_CPU_ISADIR is normally empty. On 64-bit Solaris systems, it is set to + # OPENJDK_$1_CPU_ISADIR is normally empty. On 64-bit Solaris systems, it is set to # /amd64 or /sparcv9. This string is appended to some library paths, like this: - # /usr/lib${OPENJDK_TARGET_CPU_ISADIR}/libexample.so - OPENJDK_TARGET_CPU_ISADIR="" - if test "x$OPENJDK_TARGET_OS" = xsolaris; then - if test "x$OPENJDK_TARGET_CPU" = xx86_64; then - OPENJDK_TARGET_CPU_ISADIR="/amd64" - elif test "x$OPENJDK_TARGET_CPU" = xsparcv9; then - OPENJDK_TARGET_CPU_ISADIR="/sparcv9" + # /usr/lib${OPENJDK_$1_CPU_ISADIR}/libexample.so + OPENJDK_$1_CPU_ISADIR="" + if test "x$OPENJDK_$1_OS" = xsolaris; then + if test "x$OPENJDK_$1_CPU" = xx86_64; then + OPENJDK_$1_CPU_ISADIR="/amd64" + elif test "x$OPENJDK_$1_CPU" = xsparcv9; then + OPENJDK_$1_CPU_ISADIR="/sparcv9" fi fi - AC_SUBST(OPENJDK_TARGET_CPU_ISADIR) + AC_SUBST(OPENJDK_$1_CPU_ISADIR) - # Setup OPENJDK_TARGET_CPU_OSARCH, which is used to set the os.arch Java system property - OPENJDK_TARGET_CPU_OSARCH="$OPENJDK_TARGET_CPU" - if test "x$OPENJDK_TARGET_OS" = xlinux && test "x$OPENJDK_TARGET_CPU" = xx86; then + # Setup OPENJDK_$1_CPU_OSARCH, which is used to set the os.arch Java system property + OPENJDK_$1_CPU_OSARCH="$OPENJDK_$1_CPU" + if test "x$OPENJDK_$1_OS" = xlinux && test "x$OPENJDK_$1_CPU" = xx86; then # On linux only, we replace x86 with i386. - OPENJDK_TARGET_CPU_OSARCH="i386" - elif test "x$OPENJDK_TARGET_OS" != xmacosx && test "x$OPENJDK_TARGET_CPU" = xx86_64; then - # On all platforms except macosx, we replace x86_64 with amd64. - OPENJDK_TARGET_CPU_OSARCH="amd64" - fi - AC_SUBST(OPENJDK_TARGET_CPU_OSARCH) - - OPENJDK_TARGET_CPU_JLI="$OPENJDK_TARGET_CPU" - if test "x$OPENJDK_TARGET_CPU" = xx86; then - OPENJDK_TARGET_CPU_JLI="i386" - elif test "x$OPENJDK_TARGET_OS" != xmacosx && test "x$OPENJDK_TARGET_CPU" = xx86_64; then + OPENJDK_$1_CPU_OSARCH="i386" + elif test "x$OPENJDK_$1_OS" != xmacosx && test "x$OPENJDK_$1_CPU" = xx86_64; then # On all platforms except macosx, we replace x86_64 with amd64. - OPENJDK_TARGET_CPU_JLI="amd64" + OPENJDK_$1_CPU_OSARCH="amd64" fi - # Now setup the -D flags for building libjli. - OPENJDK_TARGET_CPU_JLI_CFLAGS="-DLIBARCHNAME='\"$OPENJDK_TARGET_CPU_JLI\"'" - if test "x$OPENJDK_TARGET_OS" = xsolaris; then - if test "x$OPENJDK_TARGET_CPU_ARCH" = xsparc; then - OPENJDK_TARGET_CPU_JLI_CFLAGS="$OPENJDK_TARGET_CPU_JLI_CFLAGS -DLIBARCH32NAME='\"sparc\"' -DLIBARCH64NAME='\"sparcv9\"'" - elif test "x$OPENJDK_TARGET_CPU_ARCH" = xx86; then - OPENJDK_TARGET_CPU_JLI_CFLAGS="$OPENJDK_TARGET_CPU_JLI_CFLAGS -DLIBARCH32NAME='\"i386\"' -DLIBARCH64NAME='\"amd64\"'" - fi - fi - AC_SUBST(OPENJDK_TARGET_CPU_JLI_CFLAGS) + AC_SUBST(OPENJDK_$1_CPU_OSARCH) - OPENJDK_BUILD_CPU_JLI="$OPENJDK_BUILD_CPU" - if test "x$OPENJDK_BUILD_CPU" = xx86; then - OPENJDK_BUILD_CPU_JLI="i386" - elif test "x$OPENJDK_BUILD_OS" != xmacosx && test "x$OPENJDK_BUILD_CPU" = xx86_64; then + OPENJDK_$1_CPU_JLI="$OPENJDK_$1_CPU" + if test "x$OPENJDK_$1_CPU" = xx86; then + OPENJDK_$1_CPU_JLI="i386" + elif test "x$OPENJDK_$1_OS" != xmacosx && test "x$OPENJDK_$1_CPU" = xx86_64; then # On all platforms except macosx, we replace x86_64 with amd64. - OPENJDK_BUILD_CPU_JLI="amd64" + OPENJDK_$1_CPU_JLI="amd64" fi # Now setup the -D flags for building libjli. - OPENJDK_BUILD_CPU_JLI_CFLAGS="-DLIBARCHNAME='\"$OPENJDK_BUILD_CPU_JLI\"'" - if test "x$OPENJDK_BUILD_OS" = xsolaris; then - if test "x$OPENJDK_BUILD_CPU_ARCH" = xsparc; then - OPENJDK_BUILD_CPU_JLI_CFLAGS="$OPENJDK_BUILD_CPU_JLI_CFLAGS -DLIBARCH32NAME='\"sparc\"' -DLIBARCH64NAME='\"sparcv9\"'" - elif test "x$OPENJDK_BUILD_CPU_ARCH" = xx86; then - OPENJDK_BUILD_CPU_JLI_CFLAGS="$OPENJDK_BUILD_CPU_JLI_CFLAGS -DLIBARCH32NAME='\"i386\"' -DLIBARCH64NAME='\"amd64\"'" + OPENJDK_$1_CPU_JLI_CFLAGS="-DLIBARCHNAME='\"$OPENJDK_$1_CPU_JLI\"'" + if test "x$OPENJDK_$1_OS" = xsolaris; then + if test "x$OPENJDK_$1_CPU_ARCH" = xsparc; then + OPENJDK_$1_CPU_JLI_CFLAGS="$OPENJDK_$1_CPU_JLI_CFLAGS -DLIBARCH32NAME='\"sparc\"' -DLIBARCH64NAME='\"sparcv9\"'" + elif test "x$OPENJDK_$1_CPU_ARCH" = xx86; then + OPENJDK_$1_CPU_JLI_CFLAGS="$OPENJDK_$1_CPU_JLI_CFLAGS -DLIBARCH32NAME='\"i386\"' -DLIBARCH64NAME='\"amd64\"'" fi fi - AC_SUBST(OPENJDK_BUILD_CPU_JLI_CFLAGS) + AC_SUBST(OPENJDK_$1_CPU_JLI_CFLAGS) - if test "x$OPENJDK_TARGET_OS" = xmacosx; then - OPENJDK_TARGET_OS_EXPORT_DIR=macosx + if test "x$OPENJDK_$1_OS" = xmacosx; then + OPENJDK_$1_OS_EXPORT_DIR=macosx else - OPENJDK_TARGET_OS_EXPORT_DIR=${OPENJDK_TARGET_OS_TYPE} + OPENJDK_$1_OS_EXPORT_DIR=${OPENJDK_$1_OS_TYPE} fi - AC_SUBST(OPENJDK_TARGET_OS_EXPORT_DIR) + AC_SUBST(OPENJDK_$1_OS_EXPORT_DIR) - if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then + if test "x$OPENJDK_$1_CPU_BITS" = x64; then A_LP64="LP64:=" # -D_LP64=1 is only set on linux and mac. Setting on windows causes diff in # unpack200.exe - if test "x$OPENJDK_TARGET_OS" = xlinux || test "x$OPENJDK_TARGET_OS" = xmacosx; then - ADD_LP64="-D_LP64=1" + if test "x$OPENJDK_$1_OS" = xlinux || test "x$OPENJDK_$1_OS" = xmacosx; then + OPENJDK_$1_ADD_LP64="-D_LP64=1" fi fi AC_SUBST(LP64,$A_LP64) - if test "x$OPENJDK_BUILD_CPU_BITS" = x64; then - if test "x$OPENJDK_BUILD_OS" = xlinux || test "x$OPENJDK_BUILD_OS" = xmacosx; then - OPENJDK_BUILD_ADD_LP64="-D_LP64=1" - fi - fi if test "x$COMPILE_TYPE" = "xcross"; then # FIXME: ... or should this include reduced builds..? - DEFINE_CROSS_COMPILE_ARCH="CROSS_COMPILE_ARCH:=$OPENJDK_TARGET_CPU_LEGACY" + DEFINE_CROSS_COMPILE_ARCH="CROSS_COMPILE_ARCH:=$OPENJDK_$1_CPU_LEGACY" else DEFINE_CROSS_COMPILE_ARCH="" fi AC_SUBST(DEFINE_CROSS_COMPILE_ARCH) - # ZERO_ARCHDEF is used to enable architecture-specific code - case "${OPENJDK_TARGET_CPU}" in - ppc) ZERO_ARCHDEF=PPC32 ;; - ppc64) ZERO_ARCHDEF=PPC64 ;; - s390*) ZERO_ARCHDEF=S390 ;; - sparc*) ZERO_ARCHDEF=SPARC ;; - x86_64*) ZERO_ARCHDEF=AMD64 ;; - x86) ZERO_ARCHDEF=IA32 ;; - *) ZERO_ARCHDEF=$(echo "${OPENJDK_TARGET_CPU_LEGACY_LIB}" | tr a-z A-Z) - esac - AC_SUBST(ZERO_ARCHDEF) + # Convert openjdk platform names to hotspot names + + HOTSPOT_$1_OS=${OPENJDK_$1_OS} + if test "x$OPENJDK_$1_OS" = xmacosx; then + HOTSPOT_$1_OS=bsd + fi + AC_SUBST(HOTSPOT_$1_OS) + + HOTSPOT_$1_OS_TYPE=${OPENJDK_$1_OS_TYPE} + if test "x$OPENJDK_$1_OS_TYPE" = xunix; then + HOTSPOT_$1_OS_TYPE=posix + fi + AC_SUBST(HOTSPOT_$1_OS_TYPE) + + HOTSPOT_$1_CPU=${OPENJDK_$1_CPU} + if test "x$OPENJDK_$1_CPU" = xx86; then + HOTSPOT_$1_CPU=x86_32 + elif test "x$OPENJDK_$1_CPU" = xsparcv9; then + HOTSPOT_$1_CPU=sparc + elif test "x$OPENJDK_$1_CPU" = xppc64; then + HOTSPOT_$1_CPU=ppc_64 + elif test "x$OPENJDK_$1_CPU" = xppc64le; then + HOTSPOT_$1_CPU=ppc_64 + fi + AC_SUBST(HOTSPOT_$1_CPU) + + # This is identical with OPENJDK_*, but define anyway for consistency. + HOTSPOT_$1_CPU_ARCH=${OPENJDK_$1_CPU_ARCH} + AC_SUBST(HOTSPOT_$1_CPU_ARCH) + + # Setup HOTSPOT_$1_CPU_DEFINE + if test "x$OPENJDK_$1_CPU" = xx86; then + HOTSPOT_$1_CPU_DEFINE=IA32 + elif test "x$OPENJDK_$1_CPU" = xx86_64; then + HOTSPOT_$1_CPU_DEFINE=AMD64 + elif test "x$OPENJDK_$1_CPU" = xsparcv9; then + HOTSPOT_$1_CPU_DEFINE=SPARC + elif test "x$OPENJDK_$1_CPU" = xaarch64; then + HOTSPOT_$1_CPU_DEFINE=AARCH64 + elif test "x$OPENJDK_$1_CPU" = xppc64; then + HOTSPOT_$1_CPU_DEFINE=PPC64 + elif test "x$OPENJDK_$1_CPU" = xppc64le; then + HOTSPOT_$1_CPU_DEFINE=PPC64 + + # The cpu defines below are for zero, we don't support them directly. + elif test "x$OPENJDK_$1_CPU" = xsparc; then + HOTSPOT_$1_CPU_DEFINE=SPARC + elif test "x$OPENJDK_$1_CPU" = xppc; then + HOTSPOT_$1_CPU_DEFINE=PPC32 + elif test "x$OPENJDK_$1_CPU" = xs390; then + HOTSPOT_$1_CPU_DEFINE=S390 + elif test "x$OPENJDK_$1_CPU" = ss390x; then + HOTSPOT_$1_CPU_DEFINE=S390 + fi + AC_SUBST(HOTSPOT_$1_CPU_DEFINE) + ]) AC_DEFUN([PLATFORM_SET_RELEASE_FILE_OS_VALUES], @@ -521,6 +525,10 @@ AC_DEFUN([PLATFORM_SET_COMPILER_TARGET_BITS_FLAGS], CFLAGS_JDK="${CFLAGS_JDK}${ADDED_CFLAGS}" CXXFLAGS_JDK="${CXXFLAGS_JDK}${ADDED_CXXFLAGS}" LDFLAGS_JDK="${LDFLAGS_JDK}${ADDED_LDFLAGS}" + + JVM_CFLAGS="$JVM_CFLAGS $ADDED_CFLAGS" + JVM_LDFLAGS="$JVM_LDFLAGS $ADDED_LDFLAGS" + JVM_ASFLAGS="$JVM_ASFLAGS $ADDED_CFLAGS" ]) AC_DEFUN_ONCE([PLATFORM_SETUP_OPENJDK_TARGET_BITS], @@ -542,6 +550,11 @@ AC_DEFUN_ONCE([PLATFORM_SETUP_OPENJDK_TARGET_BITS], PLATFORM_SET_COMPILER_TARGET_BITS_FLAGS fi fi + if test "x$OPENJDK_TARGET_OS" = xmacosx; then + JVM_CFLAGS="$JVM_CFLAGS ${COMPILER_TARGET_BITS_FLAG}${OPENJDK_TARGET_CPU_BITS}" + JVM_LDFLAGS="$JVM_LDFLAGS ${COMPILER_TARGET_BITS_FLAG}${OPENJDK_TARGET_CPU_BITS}" + JVM_ASFLAGS="$JVM_ASFLAGS ${COMPILER_TARGET_BITS_FLAG}${OPENJDK_TARGET_CPU_BITS}" + fi # Make compilation sanity check AC_CHECK_HEADERS([stdio.h], , [ diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in index 3b6cbd5cbaa7327fb5fda59ca84fcd041f2074de..c72e9d541005e281d18cef8b569177f007420324 100644 --- a/common/autoconf/spec.gmk.in +++ b/common/autoconf/spec.gmk.in @@ -82,6 +82,13 @@ OPENJDK_TARGET_CPU_OSARCH:=@OPENJDK_TARGET_CPU_OSARCH@ OPENJDK_TARGET_CPU_JLI_CFLAGS:=@OPENJDK_TARGET_CPU_JLI_CFLAGS@ OPENJDK_TARGET_OS_EXPORT_DIR:=@OPENJDK_TARGET_OS_EXPORT_DIR@ +HOTSPOT_TARGET_OS := @HOTSPOT_TARGET_OS@ +HOTSPOT_TARGET_OS_TYPE := @HOTSPOT_TARGET_OS_TYPE@ + +HOTSPOT_TARGET_CPU := @HOTSPOT_TARGET_CPU@ +HOTSPOT_TARGET_CPU_ARCH := @HOTSPOT_TARGET_CPU_ARCH@ +HOTSPOT_TARGET_CPU_DEFINE := @HOTSPOT_TARGET_CPU_DEFINE@ + # We are building on this build system. # When not cross-compiling, it is the same as the target. OPENJDK_BUILD_OS:=@OPENJDK_BUILD_OS@ @@ -192,6 +199,7 @@ PRODUCT_NAME:=@PRODUCT_NAME@ PRODUCT_SUFFIX:=@PRODUCT_SUFFIX@ JDK_RC_PLATFORM_NAME:=@JDK_RC_PLATFORM_NAME@ COMPANY_NAME:=@COMPANY_NAME@ +HOTSPOT_VM_DISTRO:=@HOTSPOT_VM_DISTRO@ MACOSX_BUNDLE_NAME_BASE=@MACOSX_BUNDLE_NAME_BASE@ MACOSX_BUNDLE_ID_BASE=@MACOSX_BUNDLE_ID_BASE@ USERNAME:=@USERNAME@ @@ -201,11 +209,32 @@ RUNTIME_NAME=$(PRODUCT_NAME) $(PRODUCT_SUFFIX) # How to compile the code: release, fastdebug or slowdebug DEBUG_LEVEL:=@DEBUG_LEVEL@ +HOTSPOT_DEBUG_LEVEL:=@HOTSPOT_DEBUG_LEVEL@ # This is the JDK variant to build. # The JDK variant is a name for a specific set of modules to be compiled for the JDK. JDK_VARIANT:=@JDK_VARIANT@ +# Which JVM variants to build (space-separated list) +JVM_VARIANTS := @JVM_VARIANTS@ + +# Lists of features per variant. Only relevant for the variants listed in +# JVM_VARIANTS. +JVM_FEATURES_server := @JVM_FEATURES_server@ +JVM_FEATURES_client := @JVM_FEATURES_client@ +JVM_FEATURES_core := @JVM_FEATURES_core@ +JVM_FEATURES_minimal := @JVM_FEATURES_minimal@ +JVM_FEATURES_zero := @JVM_FEATURES_zero@ +JVM_FEATURES_zeroshark := @JVM_FEATURES_zeroshark@ +JVM_FEATURES_custom := @JVM_FEATURES_custom@ + +# Used for make-time verifications +VALID_JVM_FEATURES := @VALID_JVM_FEATURES@ +VALID_JVM_VARIANTS := @VALID_JVM_VARIANTS@ + +# Control use of precompiled header in hotspot libjvm build +USE_PRECOMPILED_HEADER := @USE_PRECOMPILED_HEADER@ + # Should we compile support for running with a graphical UI? (ie headful) # Should we compile support for running without? (ie headless) SUPPORT_HEADFUL:=@SUPPORT_HEADFUL@ @@ -213,24 +242,10 @@ SUPPORT_HEADLESS:=@SUPPORT_HEADLESS@ # Legacy defines controlled by the SUPPORT_HEADLESS and SUPPORT_HEADFUL options. @BUILD_HEADLESS@ -# These are the libjvms that we want to build. -# The java launcher uses the default. -# The others can be selected by specifying -client -server -minimal1 -zero or -zeroshark -# on the java launcher command line. -JVM_VARIANTS:=@JVM_VARIANTS@ -JVM_VARIANT_SERVER:=@JVM_VARIANT_SERVER@ -JVM_VARIANT_CLIENT:=@JVM_VARIANT_CLIENT@ -JVM_VARIANT_MINIMAL1:=@JVM_VARIANT_MINIMAL1@ -JVM_VARIANT_ZERO:=@JVM_VARIANT_ZERO@ -JVM_VARIANT_ZEROSHARK:=@JVM_VARIANT_ZEROSHARK@ -JVM_VARIANT_CORE:=@JVM_VARIANT_CORE@ - -# Universal binaries on macosx -MACOSX_UNIVERSAL=@MACOSX_UNIVERSAL@ +# Legacy support +USE_NEW_HOTSPOT_BUILD:=@USE_NEW_HOTSPOT_BUILD@ -# Legacy setting: -debug or -fastdebug -# Still used in version string... -BUILD_VARIANT_RELEASE:=@BUILD_VARIANT_RELEASE@ +MACOSX_UNIVERSAL=@MACOSX_UNIVERSAL@ # JDK_OUTPUTDIR specifies where a working jvm is built. # You can run $(JDK_OUTPUTDIR)/bin/java @@ -320,6 +335,11 @@ MACOSX_VERSION_MIN=@MACOSX_VERSION_MIN@ # Toolchain type: gcc, clang, solstudio, lxc, microsoft... TOOLCHAIN_TYPE:=@TOOLCHAIN_TYPE@ TOOLCHAIN_VERSION := @TOOLCHAIN_VERSION@ +CC_VERSION_NUMBER := @CC_VERSION_NUMBER@ +CXX_VERSION_NUMBER := @CXX_VERSION_NUMBER@ + +# Legacy support +HOTSPOT_TOOLCHAIN_TYPE := @HOTSPOT_TOOLCHAIN_TYPE@ # Option used to tell the compiler whether to create 32- or 64-bit executables COMPILER_TARGET_BITS_FLAG:=@COMPILER_TARGET_BITS_FLAG@ @@ -338,14 +358,18 @@ LD_OUT_OPTION:=@LD_OUT_OPTION@ AR_OUT_OPTION:=@AR_OUT_OPTION@ # Flags used for overriding the default opt setting for a C/C++ source file. +C_O_FLAG_HIGHEST_JVM:=@C_O_FLAG_HIGHEST_JVM@ C_O_FLAG_HIGHEST:=@C_O_FLAG_HIGHEST@ C_O_FLAG_HI:=@C_O_FLAG_HI@ C_O_FLAG_NORM:=@C_O_FLAG_NORM@ C_O_FLAG_NONE:=@C_O_FLAG_NONE@ +C_O_FLAG_SIZE:=@C_O_FLAG_SIZE@ +CXX_O_FLAG_HIGHEST_JVM:=@CXX_O_FLAG_HIGHEST_JVM@ CXX_O_FLAG_HIGHEST:=@CXX_O_FLAG_HIGHEST@ CXX_O_FLAG_HI:=@CXX_O_FLAG_HI@ CXX_O_FLAG_NORM:=@CXX_O_FLAG_NORM@ CXX_O_FLAG_NONE:=@CXX_O_FLAG_NONE@ +CXX_O_FLAG_SIZE:=@CXX_O_FLAG_SIZE@ C_FLAG_DEPS:=@C_FLAG_DEPS@ CXX_FLAG_DEPS:=@CXX_FLAG_DEPS@ @@ -374,6 +398,23 @@ CXXFLAGS_JDKEXE:=@CXXFLAGS_JDKEXE@ LDFLAGS_HASH_STYLE := @LDFLAGS_HASH_STYLE@ +JVM_CFLAGS := @JVM_CFLAGS@ +JVM_CFLAGS_SYMBOLS := @JVM_CFLAGS_SYMBOLS@ +JVM_LDFLAGS := @JVM_LDFLAGS@ +JVM_ASFLAGS := @JVM_ASFLAGS@ +JVM_LIBS := @JVM_LIBS@ +JVM_RCFLAGS := @JVM_RCFLAGS@ + +# Flags for zeroshark +LLVM_CFLAGS := @LLVM_CFLAGS@ +LLVM_LIBS := @LLVM_LIBS@ +LLVM_LDFLAGS := @LLVM_LDFLAGS@ + +# These flags might contain variables set by a custom extension that is included later. +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +EXTRA_CXXFLAGS = @EXTRA_CXXFLAGS@ +EXTRA_LDFLAGS = @EXTRA_LDFLAGS@ + CXX:=@FIXPATH@ @CCACHE@ @ICECC@ @CXX@ CPP:=@FIXPATH@ @CPP@ @@ -630,6 +671,7 @@ XATTR:=@XATTR@ JT_HOME:=@JT_HOME@ JTREGEXE:=@JTREGEXE@ XCODEBUILD=@XCODEBUILD@ +DTRACE := @DTRACE@ FIXPATH:=@FIXPATH@ # Build setup diff --git a/common/autoconf/toolchain.m4 b/common/autoconf/toolchain.m4 index 263c0a8ff2c69f2327f1c18fc1444f1ae0281fb6..7e7a07c5d8b6d463fcfc1cf461b16a94f8fd364b 100644 --- a/common/autoconf/toolchain.m4 +++ b/common/autoconf/toolchain.m4 @@ -930,6 +930,17 @@ AC_DEFUN_ONCE([TOOLCHAIN_MISC_CHECKS], rm -rf version-script.map main.c a.out fi AC_SUBST(USING_BROKEN_SUSE_LD) + + # Setup hotspot lecagy names for toolchains + HOTSPOT_TOOLCHAIN_TYPE=$TOOLCHAIN_TYPE + if test "x$TOOLCHAIN_TYPE" = xclang; then + HOTSPOT_TOOLCHAIN_TYPE=gcc + elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then + HOTSPOT_TOOLCHAIN_TYPE=sparcWorks + elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then + HOTSPOT_TOOLCHAIN_TYPE=visCPP + fi + AC_SUBST(HOTSPOT_TOOLCHAIN_TYPE) ]) # Setup the JTReg Regression Test Harness. diff --git a/common/autoconf/version-numbers b/common/autoconf/version-numbers index dcde2286a298dc59dfa49d96903c0219ab804800..98f106680b511f4dec233fd1f4e99e6d213b41e7 100644 --- a/common/autoconf/version-numbers +++ b/common/autoconf/version-numbers @@ -32,6 +32,7 @@ PRODUCT_NAME=OpenJDK PRODUCT_SUFFIX="Runtime Environment" JDK_RC_PLATFORM_NAME=Platform COMPANY_NAME=N/A +HOTSPOT_VM_DISTRO="OpenJDK" # Might need better names for these MACOSX_BUNDLE_NAME_BASE="OpenJDK" diff --git a/common/conf/jib-profiles.js b/common/conf/jib-profiles.js index d6f86f2e2ac99fa4e68273d15813863f3d996095..9ca454e51d1ca9a67e17b3a992eeced71a43c5ad 100644 --- a/common/conf/jib-profiles.js +++ b/common/conf/jib-profiles.js @@ -241,7 +241,7 @@ var getJibProfilesProfiles = function (input, common) { target_os: "linux", target_cpu: "x64", dependencies: concat(common.dependencies, "devkit"), - configure_args: concat(common.configure_args, "--with-zlib=system"), + configure_args: concat(common.configure_args, "--with-zlib=system"), make_args: common.make_args }, @@ -259,7 +259,7 @@ var getJibProfilesProfiles = function (input, common) { target_os: "macosx", target_cpu: "x64", dependencies: concat(common.dependencies, "devkit"), - configure_args: concat(common.configure_args, "--with-zlib=system"), + configure_args: concat(common.configure_args, "--with-zlib=system"), make_args: common.make_args }, @@ -267,7 +267,7 @@ var getJibProfilesProfiles = function (input, common) { target_os: "solaris", target_cpu: "x64", dependencies: concat(common.dependencies, "devkit", "cups"), - configure_args: concat(common.configure_args, "--with-zlib=system"), + configure_args: concat(common.configure_args, "--with-zlib=system"), make_args: common.make_args }, @@ -275,7 +275,7 @@ var getJibProfilesProfiles = function (input, common) { target_os: "solaris", target_cpu: "sparcv9", dependencies: concat(common.dependencies, "devkit", "cups"), - configure_args: concat(common.configure_args, "--with-zlib=system"), + configure_args: concat(common.configure_args, "--with-zlib=system"), make_args: common.make_args }, diff --git a/corba/.hgtags b/corba/.hgtags index df49fd73654d4c8b654e8d5b8dfe541aac115429..dd25acb220b6d5033664cce5a749f8c9331db377 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -357,3 +357,4 @@ b75afa17aefe480c23c616a6a2497063312f7189 jdk-9+109 780d0620add32bf545471cf65038c9ac6d9c036d jdk-9+112 cc30faa2da498c478e89ab062ff160653ca1b170 jdk-9+113 10d175b0368c30f54350fc648adc41b94ce357ee jdk-9+114 +7bab1b1b36824924b1c657a8419369ba93d198d3 jdk-9+115 diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/corba/RequestImpl.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/corba/RequestImpl.java index 3c357f61c38eb41f689e9f8a41b67f34b032c2c3..69b58393d9539fcb4490e8fc912595f76fa4e910 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/corba/RequestImpl.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/corba/RequestImpl.java @@ -255,7 +255,7 @@ public class RequestImpl public synchronized void send_deferred() { AsynchInvoke invokeObject = new AsynchInvoke(_orb, this, false); - new sun.misc.ManagedLocalsThread(invokeObject).start(); + new Thread(null, invokeObject, "Async-Request-Invoker-Thread", 0, false).start(); } public synchronized boolean poll_response() diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/javax/rmi/CORBA/Util.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/javax/rmi/CORBA/Util.java index d9dceac7ba8d963381d6aafd3e0fc1bb264d6b55..a9ae337883e702b9ac13fd60317552128805166b 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/javax/rmi/CORBA/Util.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/javax/rmi/CORBA/Util.java @@ -751,12 +751,13 @@ public class Util implements javax.rmi.CORBA.UtilDelegate } } -class KeepAlive extends sun.misc.ManagedLocalsThread +class KeepAlive extends Thread { boolean quit = false; public KeepAlive () { + super(null, null, "Servant-KeepAlive-Thread", 0, false); setDaemon(false); } diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAImpl.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAImpl.java index 546914d623d8139e8a212f81612f17cb369182a9..3205a5c24be77d1ea460281e364e7ad816775a2a 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAImpl.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAImpl.java @@ -516,7 +516,7 @@ public class POAImpl extends ObjectAdapterBase implements POA // Converted from anonymous class to local class // so that we can call performDestroy() directly. - static class DestroyThread extends sun.misc.ManagedLocalsThread { + static class DestroyThread extends Thread { private boolean wait ; private boolean etherealize ; private boolean debug ; @@ -524,6 +524,7 @@ public class POAImpl extends ObjectAdapterBase implements POA public DestroyThread( boolean etherealize, boolean debug ) { + super(null, null, "POA-Destroy-Thread", 0, false); this.etherealize = etherealize ; this.debug = debug ; } diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAManagerImpl.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAManagerImpl.java index 22610dda9babb88c09c9623e28d377c05a0430ef..eb51310fcd3a1dcad9b71f16e6c41d94408119ac 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAManagerImpl.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAManagerImpl.java @@ -357,7 +357,7 @@ public class POAManagerImpl extends org.omg.CORBA.LocalObject implements if (wait_for_completion) deactivator.run() ; else { - Thread thr = new sun.misc.ManagedLocalsThread(deactivator) ; + Thread thr = new Thread(null, deactivator, "POA-Deactivator-Thread", 0, false) ; thr.start() ; } } finally { diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorImpl_R_USM.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorImpl_R_USM.java index 9e9fce8a47df302e82aea15cfdcc984cf1b3ff99..1a8badc0930673a28e3d3ca237bb22a9b6270d9e 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorImpl_R_USM.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorImpl_R_USM.java @@ -302,7 +302,7 @@ public class POAPolicyMediatorImpl_R_USM extends POAPolicyMediatorBase_R { throw new WrongPolicy(); } - class Etherealizer extends sun.misc.ManagedLocalsThread { + class Etherealizer extends Thread { private POAPolicyMediatorImpl_R_USM mediator ; private ActiveObjectMap.Key key ; private AOMEntry entry ; @@ -314,6 +314,7 @@ public class POAPolicyMediatorImpl_R_USM extends POAPolicyMediatorBase_R { ActiveObjectMap.Key key, AOMEntry entry, Servant servant, boolean debug ) { + super(null, null, "PAO-Etherealizer-Thread", 0, false); this.mediator = mediator ; this.key = key ; this.entry = entry; diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java index 82da35a79214bf4732bc1f20c08c504b2d57adb1..007e6b8dc28e5750730b2cfdfe29dcfdd1ee056e 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java @@ -691,7 +691,7 @@ public class ORBImpl extends com.sun.corba.se.spi.orb.ORB for (int i = 0; i < req.length; i++) { AsynchInvoke invokeObject = new AsynchInvoke( this, (com.sun.corba.se.impl.corba.RequestImpl)req[i], true); - new sun.misc.ManagedLocalsThread(invokeObject).start(); + new Thread(null, invokeObject, "ORB-Request-Thread", 0, false).start(); } } diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orbutil/threadpool/ThreadPoolImpl.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orbutil/threadpool/ThreadPoolImpl.java index 9a0e56afc4f66463bea63f89930c7337c57c6cbc..7f3ad89869ce4a715c5ec0324b5ae1f89f378b30 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orbutil/threadpool/ThreadPoolImpl.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orbutil/threadpool/ThreadPoolImpl.java @@ -459,7 +459,7 @@ public class ThreadPoolImpl implements ThreadPool } - private class WorkerThread extends sun.misc.ManagedLocalsThread implements Closeable + private class WorkerThread extends Thread implements Closeable { private Work currentWork; private int threadId = 0; // unique id for the thread @@ -469,7 +469,7 @@ public class ThreadPoolImpl implements ThreadPool private StringBuffer workerThreadName = new StringBuffer(); WorkerThread(ThreadGroup tg, String threadPoolName) { - super(tg, "Idle"); + super(tg, null, "Idle", 0, false); this.threadId = ThreadPoolImpl.getUniqueThreadId(); this.threadPoolName = threadPoolName; setName(composeWorkerThreadName(threadPoolName, "Idle")); diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java index 016fd945abf711d6f1ffd3e674ddc5d43e94d236..ac87ef9c932f8d85c5c416cd6b7f37cd2b2dd89d 100644 --- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java +++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java @@ -61,7 +61,7 @@ import com.sun.corba.se.impl.orbutil.ORBUtility; */ class SelectorImpl extends - sun.misc.ManagedLocalsThread + Thread implements com.sun.corba.se.pept.transport.Selector { @@ -79,6 +79,7 @@ class SelectorImpl public SelectorImpl(ORB orb) { + super(null, null, "ORB-Selector-Thread", 0, false); this.orb = orb; selector = null; selectorStarted = false; @@ -277,7 +278,6 @@ class SelectorImpl public void run() { - setName("SelectorThread"); while (!closed) { try { int n = 0; diff --git a/corba/src/java.corba/share/classes/module-info.java b/corba/src/java.corba/share/classes/module-info.java index 25f79def5cb5aec09992f34253dc8b0b27d4ef20..23da4b785a9df4965467ef1f457e9069bee6a959 100644 --- a/corba/src/java.corba/share/classes/module-info.java +++ b/corba/src/java.corba/share/classes/module-info.java @@ -29,8 +29,6 @@ module java.corba { requires java.logging; requires java.naming; requires java.transaction; - // 8148863 - requires jdk.unsupported; exports javax.activity; exports javax.rmi; diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 472e51852903c14773c87eee7991bf86c7f636c0..11405727ce0330570a1f1316191f0c9060c2a0ca 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -517,3 +517,4 @@ c558850fac5750d8ca98a45180121980f57cdd28 jdk-9+111 76582e8dc9e6374e4f99ab797c8d364b6e9449b4 jdk-9+112 c569f8d89269fb6205b90f727581eb8cc04132f9 jdk-9+113 b64432bae5271735fd53300b2005b713e98ef411 jdk-9+114 +88dd08d7be0fe7fb9f1914b1628f0aae9bf56e25 jdk-9+115 diff --git a/hotspot/make/Makefile b/hotspot/make/Makefile index 4312c7975790c7c3cf7addb4935acf9cfd2cd5cf..db2b96e25e03ae0798db2e8415a93c731382eee1 100644 --- a/hotspot/make/Makefile +++ b/hotspot/make/Makefile @@ -237,19 +237,21 @@ else $(MAKE_ARGS) $(VM_TARGET) endif +# NOTE: Changes in this file was just to facilitate comparison when +# developing the new build, and should not be integrated. generic_buildcore: $(HOTSPOT_SCRIPT) -ifeq ($(HS_ARCH),ppc) - ifeq ($(ARCH_DATA_MODEL),64) +#ifeq ($(HS_ARCH),ppc) +# ifeq ($(ARCH_DATA_MODEL),64) $(MKDIR) -p $(OUTPUTDIR) $(CD) $(OUTPUTDIR); \ $(MAKE) -f $(ABS_OS_MAKEFILE) \ $(MAKE_ARGS) $(VM_TARGET) - else - @$(ECHO) "No ($(VM_TARGET)) for ppc ARCH_DATA_MODEL=$(ARCH_DATA_MODEL)" - endif -else - @$(ECHO) "No ($(VM_TARGET)) for $(HS_ARCH)" -endif +# else +# @$(ECHO) "No ($(VM_TARGET)) for ppc ARCH_DATA_MODEL=$(ARCH_DATA_MODEL)" +# endif +#else +# @$(ECHO) "No ($(VM_TARGET)) for $(HS_ARCH)" +#endif generic_buildzero: $(HOTSPOT_SCRIPT) $(MKDIR) -p $(OUTPUTDIR) diff --git a/hotspot/make/aix/makefiles/trace.make b/hotspot/make/aix/makefiles/trace.make index f4f9e7f8e6c72985b20a426b64a6c687a36822da..f17e75e1f4f9c89cc24606a48f2218ce1ce057fb 100644 --- a/hotspot/make/aix/makefiles/trace.make +++ b/hotspot/make/aix/makefiles/trace.make @@ -53,13 +53,13 @@ VPATH += $(Src_Dirs_V:%=%:) TraceGeneratedNames = \ traceEventClasses.hpp \ - traceEventIds.hpp \ - traceTypes.hpp + traceEventIds.hpp \ + traceTypes.hpp ifeq ($(HAS_ALT_SRC), true) - TraceGeneratedNames += \ - traceRequestables.hpp \ - traceEventControl.hpp +TraceGeneratedNames += \ + traceRequestables.hpp \ + traceEventControl.hpp endif TraceGeneratedFiles = $(TraceGeneratedNames:%=$(TraceOutDir)/%) diff --git a/hotspot/make/bsd/makefiles/trace.make b/hotspot/make/bsd/makefiles/trace.make index af46df58ce00910597aaad9671c8be136c315444..37df4425f5005286ff4f010f981b613358dcb9c8 100644 --- a/hotspot/make/bsd/makefiles/trace.make +++ b/hotspot/make/bsd/makefiles/trace.make @@ -53,13 +53,13 @@ VPATH += $(Src_Dirs_V:%=%:) TraceGeneratedNames = \ traceEventClasses.hpp \ - traceEventIds.hpp \ - traceTypes.hpp + traceEventIds.hpp \ + traceTypes.hpp ifeq ($(HAS_ALT_SRC), true) - TraceGeneratedNames += \ - traceRequestables.hpp \ - traceEventControl.hpp +TraceGeneratedNames += \ + traceRequestables.hpp \ + traceEventControl.hpp endif TraceGeneratedFiles = $(TraceGeneratedNames:%=$(TraceOutDir)/%) diff --git a/hotspot/make/linux/makefiles/gcc.make b/hotspot/make/linux/makefiles/gcc.make index a2e5c6c03b6282e70b7d1e7a09c8d7acb54ea9aa..75dcaeb2c347a90ff170736f1a6733dc69674a97 100644 --- a/hotspot/make/linux/makefiles/gcc.make +++ b/hotspot/make/linux/makefiles/gcc.make @@ -221,7 +221,7 @@ ifeq ($(USE_CLANG),) ifeq "$(shell expr \( $(CC_VER_MAJOR) \> 4 \) \| \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 3 \) \))" "0" # GCC < 4.3 WARNING_FLAGS += -Wconversion - endif + endif ifeq "$(shell expr \( $(CC_VER_MAJOR) \> 4 \) \| \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 8 \) \))" "1" # GCC >= 4.8 # This flag is only known since GCC 4.3. Gcc 4.8 contains a fix so that with templates no @@ -260,7 +260,7 @@ endif OPT_CFLAGS = $(OPT_CFLAGS/$(OPT_CFLAGS_DEFAULT)) $(OPT_EXTRAS) -# Variable tracking size limit exceeded for VMStructs::init() +# Variable tracking size limit exceeded for VMStructs::init() ifeq "$(shell expr \( $(CC_VER_MAJOR) \> 4 \) \| \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 3 \) \))" "1" # GCC >= 4.3 # Gcc 4.1.2 does not support this flag, nor does it have problems compiling the file. diff --git a/hotspot/make/linux/makefiles/trace.make b/hotspot/make/linux/makefiles/trace.make index 09cb921094ef57cd65b52026552e1bb4fff8b510..2209716d35b6df504c4abc02b8e8eb90fb5e6f14 100644 --- a/hotspot/make/linux/makefiles/trace.make +++ b/hotspot/make/linux/makefiles/trace.make @@ -53,13 +53,13 @@ VPATH += $(Src_Dirs_V:%=%:) TraceGeneratedNames = \ traceEventClasses.hpp \ - traceEventIds.hpp \ - traceTypes.hpp + traceEventIds.hpp \ + traceTypes.hpp ifeq ($(HAS_ALT_SRC), true) - TraceGeneratedNames += \ - traceRequestables.hpp \ - traceEventControl.hpp +TraceGeneratedNames += \ + traceRequestables.hpp \ + traceEventControl.hpp endif TraceGeneratedFiles = $(TraceGeneratedNames:%=$(TraceOutDir)/%) diff --git a/hotspot/make/linux/makefiles/zero.make b/hotspot/make/linux/makefiles/zero.make index 0270711f5cbed6d9006b5c36d3675187745ebfd8..622710f4dfa995c06c7a3bf594217b87d57b51c0 100644 --- a/hotspot/make/linux/makefiles/zero.make +++ b/hotspot/make/linux/makefiles/zero.make @@ -30,3 +30,8 @@ TYPE = ZERO # Install libjvm.so, etc in in server directory. VM_SUBDIR = server + +# Disable trace for zero builds +# NOTE: This is used for simple comparison with the new build system, and +# should not be merged into mainline with build-infra. +INCLUDE_TRACE := false diff --git a/hotspot/make/share/makefiles/mapfile-vers b/hotspot/make/share/makefiles/mapfile-vers index a937f93b84c10b96486607393f5e255bc81d43d2..f7d08e50b9871cc48ef1eb117430e4f881d821e4 100644 --- a/hotspot/make/share/makefiles/mapfile-vers +++ b/hotspot/make/share/makefiles/mapfile-vers @@ -41,7 +41,6 @@ JVM_DumpAllStacks; JVM_DumpThreads; JVM_FillInStackTrace; - JVM_FillStackFrames; JVM_FindClassFromCaller; JVM_FindClassFromClass; JVM_FindClassFromBootLoader; @@ -157,13 +156,13 @@ JVM_SetClassSigners; JVM_SetNativeThreadName; JVM_SetPrimitiveArrayElement; - JVM_SetMethodInfo; JVM_SetThreadPriority; JVM_Sleep; JVM_StartThread; JVM_StopThread; JVM_SuspendThread; JVM_SupportsCX8; + JVM_ToStackTraceElement; JVM_TotalMemory; JVM_UnloadLibrary; JVM_Yield; diff --git a/hotspot/make/solaris/makefiles/dtrace.make b/hotspot/make/solaris/makefiles/dtrace.make index 376732d0e6bb92bf2385b9ff226c81314e5847cb..2c65059a213deb3e95210cd498e33f1fd781d9ec 100644 --- a/hotspot/make/solaris/makefiles/dtrace.make +++ b/hotspot/make/solaris/makefiles/dtrace.make @@ -270,7 +270,7 @@ $(DTRACE.o): $(DTRACE).d $(DTraced_Files) @echo $(LOG_INFO) Compiling $(DTRACE).d $(QUIETLY) $(DTRACE_PROG) $(DTRACE_OPTS) -C -I. -G -xlazyload -o $@ -s $(DTRACE).d \ - $(DTraced_Files) ||\ + $(sort $(DTraced_Files)) ||\ STATUS=$$?;\ if [ x"$$STATUS" = x"1" ]; then \ if [ x`uname -r` = x"5.10" -a \ diff --git a/hotspot/make/solaris/makefiles/trace.make b/hotspot/make/solaris/makefiles/trace.make index ed7046295b34b497bc614c205005c681ac654c5b..effe34061ce6469c2a13336a7d5e81e79368b6e7 100644 --- a/hotspot/make/solaris/makefiles/trace.make +++ b/hotspot/make/solaris/makefiles/trace.make @@ -53,13 +53,13 @@ VPATH += $(Src_Dirs_V:%=%:) TraceGeneratedNames = \ traceEventClasses.hpp \ - traceEventIds.hpp \ - traceTypes.hpp + traceEventIds.hpp \ + traceTypes.hpp ifeq ($(HAS_ALT_SRC), true) - TraceGeneratedNames += \ - traceRequestables.hpp \ - traceEventControl.hpp +TraceGeneratedNames += \ + traceRequestables.hpp \ + traceEventControl.hpp endif TraceGeneratedFiles = $(TraceGeneratedNames:%=$(TraceOutDir)/%) diff --git a/hotspot/make/test/JtregNative.gmk b/hotspot/make/test/JtregNative.gmk index 95c6bf242b7186b4fccd5cee533262ae98e275e3..62478ce69233ec178ffb3f17f74981d553e27688 100644 --- a/hotspot/make/test/JtregNative.gmk +++ b/hotspot/make/test/JtregNative.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -47,6 +47,7 @@ BUILD_HOTSPOT_JTREG_NATIVE_SRC := \ $(HOTSPOT_TOPDIR)/test/runtime/jni/ToStringInInterfaceTest \ $(HOTSPOT_TOPDIR)/test/runtime/modules/getModuleJNI \ $(HOTSPOT_TOPDIR)/test/runtime/SameObject \ + $(HOTSPOT_TOPDIR)/test/runtime/BoolReturn \ $(HOTSPOT_TOPDIR)/test/compiler/floatingpoint/ \ $(HOTSPOT_TOPDIR)/test/compiler/calls \ $(HOTSPOT_TOPDIR)/test/compiler/native \ diff --git a/hotspot/make/windows/makefiles/debug.make b/hotspot/make/windows/makefiles/debug.make index f2ecd269887f99fbdada99946872f94abe8e71f2..3ad45627467184646ac11adc07594343f4b66486 100644 --- a/hotspot/make/windows/makefiles/debug.make +++ b/hotspot/make/windows/makefiles/debug.make @@ -48,10 +48,10 @@ HS_BUILD_ID=$(HOTSPOT_VERSION_STRING)-debug # Force resources to be rebuilt every time $(Res_Files): FORCE +# NOTE: Changes in this file was just to give a proper command line when linking +# for use when developing the new build, and should not be integrated. $(AOUT): $(Res_Files) $(Obj_Files) vm.def - $(LD) @<< - $(LD_FLAGS) /out:$@ /implib:$*.lib /def:vm.def $(Obj_Files) $(Res_Files) -<< + $(LD) $(LD_FLAGS) /out:$@ /implib:$*.lib /def:vm.def $(Obj_Files) $(Res_Files) !if "$(MT)" != "" # The previous link command created a .manifest file that we want to # insert into the linked artifact so we do not need to track it diff --git a/hotspot/make/windows/makefiles/fastdebug.make b/hotspot/make/windows/makefiles/fastdebug.make index cbcfd5abb0483809bf55e3194b3fb7ca4d525f74..ea6fc41a42a6a6b7791bc4698fa0df4575e2c3dd 100644 --- a/hotspot/make/windows/makefiles/fastdebug.make +++ b/hotspot/make/windows/makefiles/fastdebug.make @@ -47,10 +47,10 @@ HS_BUILD_ID=$(HOTSPOT_VERSION_STRING)-fastdebug # Force resources to be rebuilt every time $(Res_Files): FORCE +# NOTE: Changes in this file was just to give a proper command line when linking +# for use when developing the new build, and should not be integrated. $(AOUT): $(Res_Files) $(Obj_Files) vm.def - $(LD) @<< - $(LD_FLAGS) /out:$@ /implib:$*.lib /def:vm.def $(Obj_Files) $(Res_Files) -<< + $(LD) $(LD_FLAGS) /out:$@ /implib:$*.lib /def:vm.def $(Obj_Files) $(Res_Files) !if "$(MT)" != "" # The previous link command created a .manifest file that we want to # insert into the linked artifact so we do not need to track it diff --git a/hotspot/make/windows/makefiles/product.make b/hotspot/make/windows/makefiles/product.make index cd3a4e70bc57954eaa8450270de0c32ca899e191..09e750acc07dbb196fe20de3d084eaf80f5d8d10 100644 --- a/hotspot/make/windows/makefiles/product.make +++ b/hotspot/make/windows/makefiles/product.make @@ -51,10 +51,11 @@ HS_BUILD_ID=$(HOTSPOT_VERSION_STRING) # Force resources to be rebuilt every time $(Res_Files): FORCE +# NOTE: Changes in this file was just to give a proper command line when linking +# for use when developing the new build, and should not be integrated. $(AOUT): $(Res_Files) $(Obj_Files) vm.def - $(LD) @<< - $(LD_FLAGS) /out:$@ /implib:$*.lib /def:vm.def $(Obj_Files) $(Res_Files) -<< + $(LD) $(LD_FLAGS) /out:$@ /implib:$*.lib /def:vm.def $(Obj_Files) $(Res_Files) + !if "$(MT)" != "" # The previous link command created a .manifest file that we want to # insert into the linked artifact so we do not need to track it diff --git a/hotspot/make/windows/makefiles/trace.make b/hotspot/make/windows/makefiles/trace.make index eecc890663f68227ed48f3285ec9bab6b269bf8b..d52391386d004b2e60583d657a9b08cd013694f5 100644 --- a/hotspot/make/windows/makefiles/trace.make +++ b/hotspot/make/windows/makefiles/trace.make @@ -41,6 +41,12 @@ HAS_ALT_SRC = true !endif !endif +!ifndef OPENJDK +!if EXISTS($(TraceAltSrcDir)) +HAS_ALT_SRC = true +!endif +!endif + TraceGeneratedNames = \ traceEventClasses.hpp \ traceEventIds.hpp \ diff --git a/hotspot/make/windows/makefiles/vm.make b/hotspot/make/windows/makefiles/vm.make index fd42111866b35dbdb1ead62e82ed8fac1dcb718e..a1391a04413b38b16d6bb97b63f35adac36fbd5f 100644 --- a/hotspot/make/windows/makefiles/vm.make +++ b/hotspot/make/windows/makefiles/vm.make @@ -305,8 +305,10 @@ bytecodeInterpreterWithChecks.obj: ..\generated\jvmtifiles\bytecodeInterpreterWi # This guy should remain a single colon rule because # otherwise we can't specify the output filename. +# NOTE: Changes in this file was just to give a proper command line when linking +# for use when developing the new build, and should not be integrated. {$(COMMONSRC)\os\windows\vm}.rc.res: - @$(RC) $(RC_FLAGS) /fo"$@" $< + $(RC) $(RC_FLAGS) /fo"$@" $< {$(COMMONSRC)\cpu\$(Platform_arch)\vm}.cpp.obj:: $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $< diff --git a/hotspot/makefiles/BuildHotspot.gmk b/hotspot/makefiles/BuildHotspot.gmk new file mode 100644 index 0000000000000000000000000000000000000000..4ae7b84c387ac9f774be1e0e1798e9cc2887a683 --- /dev/null +++ b/hotspot/makefiles/BuildHotspot.gmk @@ -0,0 +1,54 @@ +# +# Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved. +# 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 must be the first rule +default: all + +include $(SPEC) +include MakeBase.gmk + +VARIANT_TARGETS := $(foreach v, $(JVM_VARIANTS), variant-$v) +VARIANT_GENSRC_TARGETS := $(addsuffix -gensrc, $(VARIANT_TARGETS)) +VARIANT_LIBS_TARGETS := $(addsuffix -libs, $(VARIANT_TARGETS)) + +$(VARIANT_GENSRC_TARGETS): variant-%-gensrc: + $(call LogWarn, Building JVM variant '$*' with features '$(JVM_FEATURES_$*)') + +$(MAKE) -f gensrc/GenerateSources.gmk JVM_VARIANT=$* + +$(VARIANT_LIBS_TARGETS): variant-%-libs: variant-%-gensrc + +$(MAKE) -f lib/CompileLibraries.gmk JVM_VARIANT=$* + +$(VARIANT_TARGETS): variant-%: variant-%-gensrc variant-%-libs + +jsig: + +$(MAKE) -f lib/CompileLibjsig.gmk + +dist: $(VARIANT_TARGETS) jsig + +$(MAKE) -f Dist.gmk + +all: dist + +.PHONY: $(VARIANT_TARGETS) $(VARIANT_GENSRC_TARGETS) $(VARIANT_LIBS_TARGETS) \ + jsig dist all diff --git a/hotspot/makefiles/Dist.gmk b/hotspot/makefiles/Dist.gmk new file mode 100644 index 0000000000000000000000000000000000000000..bfe3daf20624c20ef076fef09d1fa2df737c0999 --- /dev/null +++ b/hotspot/makefiles/Dist.gmk @@ -0,0 +1,239 @@ +# +# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# 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. +# + +################################################################################ +# Copy the generated output into well-defined places in the dist directory. + +# This must be the first rule +default: all + +include $(SPEC) +include MakeBase.gmk + +$(eval $(call IncludeCustomExtension, hotspot, Dist.gmk)) + +DIST_OUTPUTDIR := $(HOTSPOT_OUTPUTDIR)/dist + +# Unfortunately, all platforms have different target subdirs. +ifeq ($(OPENJDK_TARGET_OS), windows) + LIB_SUBDIR := bin +else ifeq ($(OPENJDK_TARGET_OS), macosx) + LIB_SUBDIR := lib +else + LIB_SUBDIR := lib$(OPENJDK_TARGET_CPU_LIBDIR) +endif + +################################################################################ +# Functions to setup copying of files for variants + +# Support macro for SetupDistLibFile +define macosx_universalize + $(MKDIR) -p $(@D) + $(LIPO) -create -output $@ $< +endef + +################################################################################ +# Setup make rules to copy a native library and associated data. +# +# Parameter 1 is the name of the rule. This name is used as variable prefix, +# and the targets generated are listed in a variable by that name. +# +# Remaining parameters are named arguments. These include: +# NAME -- The base name of the native library (e.g. 'jvm') +# VARIANT -- The variant to copy from +# VARIANT_TARGET_DIR -- The variant target sub dir, with trailing slash, optional +SetupDistLibFile = $(NamedParamsMacroTemplate) +define SetupDistLibFileBody + ifneq ($$($1_VARIANT), ) + $1_SRC_DIR := $$(HOTSPOT_OUTPUTDIR)/variant-$$($1_VARIANT)/lib$$($1_NAME) + else + $1_SRC_DIR := $$(HOTSPOT_OUTPUTDIR)/lib$$($1_NAME) + endif + $1_LIB_NAME := $(LIBRARY_PREFIX)$$($1_NAME) + $1_TARGET_DIR := $$(DIST_OUTPUTDIR)/$$(LIB_SUBDIR)/$$($1_VARIANT_TARGET_DIR) + + ifeq ($(OPENJDK_TARGET_OS), macosx) + # We must use the 'universalize' macro to run lipo on shared libraries, at + # least until JDK-8069540 is fixed. + $1_MACRO := macosx_universalize + endif + + # Copy the the native library. + $$(eval $$(call SetupCopyFiles, $1_COPY_LIB, \ + DEST := $$($1_TARGET_DIR), \ + MACRO := $$($1_MACRO), \ + FILES := $$(wildcard \ + $$($1_SRC_DIR)/$$($1_LIB_NAME)$(SHARED_LIBRARY_SUFFIX)), \ + )) + + TARGETS += $$($1_COPY_LIB) + + # Copy related data (debug symbols, static-build symbols file etc) + $$(eval $$(call SetupCopyFiles, $1_COPY_FILES, \ + DEST := $$($1_TARGET_DIR), \ + FILES := $$(wildcard \ + $$(addprefix $$($1_SRC_DIR)/$$($1_LIB_NAME), \ + .diz .debuginfo .pdb .map .symbols)), \ + )) + + TARGETS += $$($1_COPY_FILES) + + ifeq ($(OPENJDK_TARGET_OS), macosx) + # Debug symbols on macosx is a directory, not a single file, per library. + $1_DSYM_SRC := $$($1_SRC_DIR)/$$($1_LIB_NAME)$(SHARED_LIBRARY_SUFFIX).dSYM) + ifneq ($$(wildcard $$($1_DSYM_SRC)), ) + $$(eval $$(call SetupCopyFiles, $1_COPY_DSYM_DIR, \ + DEST := $$($1_TARGET_DIR), \ + SRC := $$($1_SRC_DIR), \ + FILES := $$(shell $(FIND) $$($1_DSYM_SRC) -type f), \ + )) + TARGETS += $$($1_COPY_DSYM_DIR) + endif + endif +endef + +################################################################################ +# Copy common files, which are independent on the jvm variant(s) being built. +# For files that were generated during the build, we assume all versions of +# these files are identical, and just pick one arbitrarily to use as source. + +ANY_JVM_VARIANT := $(firstword $(JVM_VARIANTS)) +JVM_VARIANT_OUTPUTDIR := $(HOTSPOT_OUTPUTDIR)/variant-$(ANY_JVM_VARIANT) + +### Copy platform-independent .h files +INCLUDE_FILES_SRC_DIR := $(HOTSPOT_TOPDIR)/src/share/vm +$(eval $(call SetupCopyFiles, COPY_INCLUDE, \ + SRC := $(INCLUDE_FILES_SRC_DIR), \ + DEST := $(DIST_OUTPUTDIR)/include, \ + FLATTEN := true, \ + FILES := $(INCLUDE_FILES_SRC_DIR)/prims/jni.h \ + $(INCLUDE_FILES_SRC_DIR)/code/jvmticmlr.h \ + $(INCLUDE_FILES_SRC_DIR)/services/jmm.h)) + +TARGETS += $(COPY_INCLUDE) + +### Copy jni_md.h + +# This might have been defined in a custom extension +ifeq ($(JNI_MD_H_SRC), ) + JNI_MD_H_SRC := $(HOTSPOT_TOPDIR)/src/cpu/$(HOTSPOT_TARGET_CPU_ARCH)/vm/jni_$(HOTSPOT_TARGET_CPU_ARCH).h +endif + +ifeq ($(OPENJDK_TARGET_OS), macosx) + # NOTE: This should most likely be darwin, but the old hotspot build uses bsd + JNI_MD_SUBDIR := bsd +else ifeq ($(OPENJDK_TARGET_OS), windows) + JNI_MD_SUBDIR := win32 +else + JNI_MD_SUBDIR := $(OPENJDK_TARGET_OS) +endif + +# SetupCopyFiles is not used here since it's non-trivial to copy a single +# file with a different target name. +$(DIST_OUTPUTDIR)/include/$(JNI_MD_SUBDIR)/jni_md.h: $(JNI_MD_H_SRC) + $(call LogInfo, Copying hotspot/dist/include/$(JNI_MD_SUBDIR)/jni_md.h) + $(install-file) + +TARGETS += $(DIST_OUTPUTDIR)/include/$(JNI_MD_SUBDIR)/jni_md.h + +$(eval $(call SetupCopyFiles, COPY_JVMTI_H, \ + DEST := $(DIST_OUTPUTDIR)/include, \ + FLATTEN := true, \ + FILES := $(JVM_VARIANT_OUTPUTDIR)/gensrc/jvmtifiles/jvmti.h)) + +TARGETS += $(COPY_JVMTI_H) + +# NOTE: In the old build, this file was not copied on Windows. +ifneq ($(OPENJDK_TARGET_OS), windows) + $(eval $(call SetupCopyFiles, COPY_JVMTI_HTML, \ + DEST := $(DIST_OUTPUTDIR)/docs/platform/jvmti, \ + FILES := $(JVM_VARIANT_OUTPUTDIR)/gensrc/jvmtifiles/jvmti.html)) +endif + +TARGETS += $(COPY_JVMTI_HTML) + +ifeq ($(OPENJDK_TARGET_OS), windows) + $(eval $(call SetupCopyFiles, COPY_JVM_LIB, \ + DEST := $(DIST_OUTPUTDIR)/lib, \ + FILES :=$(JVM_VARIANT_OUTPUTDIR)/libjvm/objs/jvm.lib)) + + TARGETS += $(COPY_JVM_LIB) +endif + +# Copy libjsig, if it exists +$(eval $(call SetupDistLibFile, DIST_jsig, \ + NAME := jsig, \ +)) + +################################################################################ +# Copy variant-specific files + +# Setup make rules to copy a single variant to dist. +# $1: The name of the variant +define SetupDistForVariant + ifneq ($$(filter client minimal, $1), ) + VARIANT_TARGET_DIR := $1 + else + # Use 'server' as default target directory name for all other variants. + VARIANT_TARGET_DIR := server + endif + + $$(eval $$(call SetupDistLibFile, DIST_$(strip $1)_jvm, \ + NAME := jvm, \ + VARIANT := $1, \ + VARIANT_TARGET_DIR := $$(VARIANT_TARGET_DIR)/, \ + )) + + # Copy the dtrace libraries, if they exist + $$(eval $$(call SetupDistLibFile, DIST_$(strip $1)_jvm_db, \ + NAME := jvm_db, \ + VARIANT := $1, \ + VARIANT_TARGET_DIR := $$(VARIANT_TARGET_DIR)/, \ + )) + + $$(eval $$(call SetupDistLibFile, DIST_$(strip $1)_jvm_dtrace, \ + NAME := jvm_dtrace, \ + VARIANT := $1, \ + VARIANT_TARGET_DIR := $$(VARIANT_TARGET_DIR)/, \ + )) + + # Copy the Xusage.txt file + $$(eval $$(call SetupCopyFiles, DIST_$(strip $1)_Xusage, \ + DEST := $$(DIST_OUTPUTDIR)/$$(LIB_SUBDIR)/$(strip $1), \ + FILES := $$(HOTSPOT_OUTPUTDIR)/variant-$(strip $1)/support/misc/Xusage.txt, \ + )) + + TARGETS += $$(DIST_$(strip $1)_Xusage) +endef + +$(foreach variant, $(JVM_VARIANTS), \ + $(eval $(call SetupDistForVariant, $(variant))) \ +) + +################################################################################ + +all: $(TARGETS) + +.PHONY: all diff --git a/hotspot/makefiles/HotspotCommon.gmk b/hotspot/makefiles/HotspotCommon.gmk new file mode 100644 index 0000000000000000000000000000000000000000..1df3f4fa9b331fed642393bb9f96e3af9d42a20b --- /dev/null +++ b/hotspot/makefiles/HotspotCommon.gmk @@ -0,0 +1,45 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# 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. +# + +ifeq ($(JVM_VARIANT), ) + $(error This makefile must be called with JVM_VARIANT set) +endif + +JVM_VARIANT_OUTPUTDIR := $(HOTSPOT_OUTPUTDIR)/variant-$(JVM_VARIANT) +JVM_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/libjvm +JVM_SUPPORT_DIR := $(JVM_VARIANT_OUTPUTDIR)/support + +DTRACE_SUPPORT_DIR := $(JVM_SUPPORT_DIR)/dtrace + +################################################################################ + +# Test if a feature is available in the present build of JVM_VARIANT. Will return +# 'true' or 'false'. +# $1 - the feature to test for +check-jvm-feature = \ + $(strip \ + $(if $(filter-out $(VALID_JVM_FEATURES), $1), \ + $(error Internal error: Invalid feature tested: $1)) \ + $(if $(filter $1, $(JVM_FEATURES_$(JVM_VARIANT))), true, false)) diff --git a/hotspot/makefiles/gensrc/GenerateSources.gmk b/hotspot/makefiles/gensrc/GenerateSources.gmk new file mode 100644 index 0000000000000000000000000000000000000000..b91f2d0c864b07b6fc26182564f0fffd289cb2da --- /dev/null +++ b/hotspot/makefiles/gensrc/GenerateSources.gmk @@ -0,0 +1,75 @@ +# +# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# 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. +# + +default: all + +include $(SPEC) +include MakeBase.gmk +include JavaCompilation.gmk +include NativeCompilation.gmk +include TextFileProcessing.gmk + +include HotspotCommon.gmk + +# The real work is done in these files + +include gensrc/GensrcAdlc.gmk +include gensrc/GensrcDtrace.gmk +include gensrc/GensrcJvmti.gmk + +$(eval $(call IncludeCustomExtension, hotspot, gensrc/GenerateSources.gmk)) + +# While technically the rules below are "gendata" which can be done in parallel +# with native compilation, let's keep it here for simplicity. + +# The Xusage.txt file needs to have platform specific path separator +$(eval $(call SetupTextFileProcessing, CREATE_XUSAGE, \ + SOURCE_FILES := $(HOTSPOT_TOPDIR)/src/share/vm/Xusage.txt, \ + OUTPUT_FILE := $(JVM_SUPPORT_DIR)/misc/Xusage.txt, \ + REPLACEMENTS := separated by ;> => separated by $(PATH_SEP)> ; , \ +)) + +TARGETS += $(CREATE_XUSAGE) + +# Setup the hotspot launcher script for developer use +$(eval $(call SetupTextFileProcessing, CREATE_HOTSPOT_LAUNCHER, \ + SOURCE_FILES := $(HOTSPOT_TOPDIR)/make/hotspot.script, \ + OUTPUT_FILE := $(JVM_OUTPUTDIR)/hotspot, \ + REPLACEMENTS := \ + @@LIBARCH@@ => $(OPENJDK_TARGET_CPU_LEGACY_LIB) ; \ + @@JDK_IMPORT_PATH@@ => $(JDK_OUTPUTDIR) ; , \ +)) + +CHMOD_HOTSPOT_LAUNCHER := $(JVM_VARIANT_OUTPUTDIR)/libjvm/_hotspot-script-chmod.marker + +$(CHMOD_HOTSPOT_LAUNCHER): $(CREATE_HOTSPOT_LAUNCHER) + $(CHMOD) +x $< + $(TOUCH) $@ + +TARGETS += $(CREATE_HOTSPOT_LAUNCHER) $(CHMOD_HOTSPOT_LAUNCHER) + +all: $(TARGETS) + +.PHONY: all diff --git a/hotspot/makefiles/gensrc/GensrcAdlc.gmk b/hotspot/makefiles/gensrc/GensrcAdlc.gmk new file mode 100644 index 0000000000000000000000000000000000000000..a33d42db2066763724e14bfbb3e767bafd2f667d --- /dev/null +++ b/hotspot/makefiles/gensrc/GensrcAdlc.gmk @@ -0,0 +1,191 @@ +# +# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# 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. +# + +$(eval $(call IncludeCustomExtension, hotspot, gensrc/GensrcAdlc.gmk)) + +ifeq ($(call check-jvm-feature, compiler2), true) + + ADLC_SUPPORT_DIR := $(JVM_SUPPORT_DIR)/adlc + + ############################################################################## + # Build the ad compiler (the adlc build tool) + + # Flags depending on the build platform/tool chain + # NOTE: No optimization or debug flags set here + ifeq ($(OPENJDK_BUILD_OS), linux) + ADLC_CFLAGS := -fno-exceptions -DLINUX + else ifeq ($(OPENJDK_BUILD_OS), solaris) + ADLC_LDFLAGS := -m64 + ADLC_CFLAGS := -m64 + ADLC_CFLAGS_WARNINGS := +w + else ifeq ($(OPENJDK_BUILD_OS), aix) + ADLC_LDFLAGS := -q64 + ADLC_CFLAGS := -qnortti -qeh -q64 -DAIX + else ifeq ($(OPENJDK_BUILD_OS), windows) + ADLC_LDFLAGS := -nologo + ADLC_CFLAGS := -nologo -EHsc + # NOTE: The old build also have -D_CRT_SECURE_NO_DEPRECATE but it doesn't + # seem needed any more. + ADLC_CFLAGS_WARNINGS := -W3 -D_CRT_SECURE_NO_WARNINGS + endif + + # NOTE: The old build didn't set -DASSERT for windows but it doesn't seem to + # hurt. + ADLC_CFLAGS += -DASSERT + + ADLC_CFLAGS += -D$(HOTSPOT_TARGET_CPU_DEFINE) + + ADLC_CFLAGS += -I$(HOTSPOT_TOPDIR)/src/share/vm + + $(eval $(call SetupNativeCompilation, BUILD_ADLC, \ + TOOLCHAIN := TOOLCHAIN_BUILD_LINK_CXX, \ + SRC := $(HOTSPOT_TOPDIR)/src/share/vm/adlc, \ + EXTRA_FILES := $(HOTSPOT_TOPDIR)/src/share/vm/opto/opcodes.cpp, \ + CFLAGS := $(ADLC_CFLAGS) $(ADLC_CFLAGS_WARNINGS), \ + LDFLAGS := $(ADLC_LDFLAGS), \ + LIBS := $(ADLC_LIBS), \ + OBJECT_DIR := $(JVM_VARIANT_OUTPUTDIR)/tools/adlc/objs, \ + OUTPUT_DIR := $(JVM_VARIANT_OUTPUTDIR)/tools/adlc, \ + PROGRAM := adlc, \ + DEBUG_SYMBOLS := false, \ + DISABLED_WARNINGS_clang := parentheses tautological-compare, \ + DISABLED_WARNINGS_solstudio := notemsource, \ + )) + + ADLC_TOOL := $(BUILD_ADLC_TARGET) + + ############################################################################## + # Transform the ad source files into C++ source files using adlc + + # Setup flags for the adlc build tool (ADLCFLAGS). + ADLCFLAGS += -q -T + + # ADLC flags depending on target OS + ifeq ($(OPENJDK_TARGET_OS), linux) + ADLCFLAGS += -DLINUX=1 -D_GNU_SOURCE=1 + else ifeq ($(OPENJDK_TARGET_OS), solaris) + ADLCFLAGS += -DSOLARIS=1 -DSPARC_WORKS=1 + else ifeq ($(OPENJDK_TARGET_OS), aix) + ADLCFLAGS += -DAIX=1 + else ifeq ($(OPENJDK_TARGET_OS), macosx) + ADLCFLAGS += -D_ALLBSD_SOURCE=1 -D_GNU_SOURCE=1 + endif + + ifneq ($(OPENJDK_TARGET_OS), windows) + # NOTE: Windows adlc flags was different in the old build. Is this really + # correct? + + # -g makes #line directives in the generated C++ files. + ADLCFLAGS += -g + + ADLCFLAGS += -D$(HOTSPOT_TARGET_CPU_DEFINE)=1 + endif + + # This generates checks in the generated C++ files that _LP64 is correctly + # (un)defined when compiling them. + ifeq ($(OPENJDK_TARGET_CPU_BITS), 64) + ADLCFLAGS += -D_LP64=1 + else + ADLCFLAGS += -U_LP64 + endif + + ############################################################################## + # Concatenate all ad source files into a single file, which will be fed to + # adlc. Also include a #line directive at the start of every included file + # (after the initial header block), stating the original source file name. + # + # Normally, debugging is done directly on the ad_*.cpp files, but the + # #line directives in those files will be pointing back to .ad. + + # AD_SRC_ROOTS might have been added to by a custom extension + AD_SRC_ROOTS += $(HOTSPOT_TOPDIR)/src + + AD_SRC_FILES := $(call uniq, $(wildcard $(foreach d, $(AD_SRC_ROOTS), \ + $d/cpu/$(HOTSPOT_TARGET_CPU_ARCH)/vm/$(HOTSPOT_TARGET_CPU).ad \ + $d/cpu/$(HOTSPOT_TARGET_CPU_ARCH)/vm/$(HOTSPOT_TARGET_CPU_ARCH).ad \ + $d/os_cpu/$(HOTSPOT_TARGET_OS)_$(HOTSPOT_TARGET_CPU_ARCH)/vm/$(HOTSPOT_TARGET_OS)_$(HOTSPOT_TARGET_CPU_ARCH).ad \ + ))) + + SINGLE_AD_SRCFILE := $(ADLC_SUPPORT_DIR)/all-ad-src.ad + + INSERT_FILENAME_AWK_SCRIPT := \ + '{ \ + if (CUR_FN != FILENAME) { CUR_FN=FILENAME; NR_BASE=NR-1; need_lineno=1 } \ + if (need_lineno && $$0 !~ /\/\//) \ + { print "\n\n\#line " (NR-NR_BASE) " \"" FILENAME "\""; need_lineno=0 }; \ + print \ + }' + + $(SINGLE_AD_SRCFILE): $(AD_SRC_FILES) + $(call LogInfo, Preprocessing adlc files $(^F)) + $(call MakeDir, $(@D)) + $(NAWK) $(INSERT_FILENAME_AWK_SCRIPT) $^ > $@ + + ############################################################################## + # Run the adlc tool on the single concatenated ad source file, and store the + # output in support/adlc for further processing. + ADLC_RUN_MARKER := $(ADLC_SUPPORT_DIR)/_adlc_run.marker + + $(ADLC_RUN_MARKER): $(BUILD_ADLC) $(SINGLE_AD_SRCFILE) + $(call LogInfo, Generating adlc files) + $(call MakeDir, $(@D)) + $(call ExecuteWithLog, $(ADLC_SUPPORT_DIR)/adlc_run, \ + $(FIXPATH) $(ADLC_TOOL) $(ADLCFLAGS) $(SINGLE_AD_SRCFILE) \ + -c$(ADLC_SUPPORT_DIR)/ad_$(HOTSPOT_TARGET_CPU).cpp \ + -h$(ADLC_SUPPORT_DIR)/ad_$(HOTSPOT_TARGET_CPU).hpp \ + -a$(ADLC_SUPPORT_DIR)/dfa_$(HOTSPOT_TARGET_CPU).cpp \ + -v$(ADLC_SUPPORT_DIR)/adGlobals_$(HOTSPOT_TARGET_CPU).hpp) + $(TOUCH) $@ + + ############################################################################## + # Finally copy the generated files from support/adlc into gensrc/adfiles, + # and postprocess them by fixing dummy #line directives. + + ADLC_GENERATED_FILES := $(addprefix $(JVM_VARIANT_OUTPUTDIR)/gensrc/adfiles/, \ + ad_$(HOTSPOT_TARGET_CPU).cpp \ + ad_$(HOTSPOT_TARGET_CPU).hpp \ + ad_$(HOTSPOT_TARGET_CPU)_clone.cpp \ + ad_$(HOTSPOT_TARGET_CPU)_expand.cpp \ + ad_$(HOTSPOT_TARGET_CPU)_format.cpp \ + ad_$(HOTSPOT_TARGET_CPU)_gen.cpp \ + ad_$(HOTSPOT_TARGET_CPU)_misc.cpp \ + ad_$(HOTSPOT_TARGET_CPU)_peephole.cpp \ + ad_$(HOTSPOT_TARGET_CPU)_pipeline.cpp \ + adGlobals_$(HOTSPOT_TARGET_CPU).hpp \ + dfa_$(HOTSPOT_TARGET_CPU).cpp \ + ) + + $(JVM_VARIANT_OUTPUTDIR)/gensrc/adfiles/%: $(ADLC_RUN_MARKER) + $(call LogInfo, Postprocessing adlc file $*) + $(call MakeDir, $(@D)) + $(NAWK) \ + 'BEGIN { print "#line 1 \"$*\""; } \ + /^#line 999999$$/ {print "#line " (NR+1) " \"$*\""; next} \ + {print}' \ + < $(ADLC_SUPPORT_DIR)/$* > $@ + + TARGETS := $(ADLC_GENERATED_FILES) + +endif diff --git a/hotspot/makefiles/gensrc/GensrcDtrace.gmk b/hotspot/makefiles/gensrc/GensrcDtrace.gmk new file mode 100644 index 0000000000000000000000000000000000000000..563f22112fb801207052a00444b1d09e55df92f4 --- /dev/null +++ b/hotspot/makefiles/gensrc/GensrcDtrace.gmk @@ -0,0 +1,56 @@ +# +# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# 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. +# + +################################################################################ +# Gensrc support for dtrace. The files generated here are included by dtrace.hpp + +ifeq ($(call check-jvm-feature, dtrace), true) + + ifeq ($(OPENJDK_TARGET_OS), solaris) + DTRACE_FLAGS := -64 + DTRACE_CPP_FLAGS := -D_LP64 + else ifeq ($(OPENJDK_TARGET_OS), macosx) + DTRACE_CPP_FLAGS := -D_LP64 -x c + else ifeq ($(OPENJDK_TARGET_OS), linux) + DTRACE_CPP_FLAGS := -x c + endif + + DTRACE_SOURCE_DIR := $(HOTSPOT_TOPDIR)/src/os/posix/dtrace + DTRACE_GENSRC_DIR := $(JVM_VARIANT_OUTPUTDIR)/gensrc/dtracefiles + + # Make sure we run our selected compiler for preprocessing instead of letting + # the dtrace tool pick it on it's own. + $(DTRACE_GENSRC_DIR)/%.h: $(DTRACE_SOURCE_DIR)/%.d + $(call LogInfo, Generating dtrace header file $(@F)) + $(call MakeDir, $(@D) $(DTRACE_SUPPORT_DIR)) + $(call ExecuteWithLog, $(DTRACE_SUPPORT_DIR)/$(@F).d, $(CC) -E $(DTRACE_CPP_FLAGS) $< > $(DTRACE_SUPPORT_DIR)/$(@F).d) + $(call ExecuteWithLog, $@, $(DTRACE) $(DTRACE_FLAGS) -h -o $@ -s $(DTRACE_SUPPORT_DIR)/$(@F).d) + + # Process all .d files in DTRACE_SOURCE_DIR. They are: + # hotspot_jni.d hotspot.d hs_private.d + TARGETS += $(patsubst $(DTRACE_SOURCE_DIR)/%.d, \ + $(DTRACE_GENSRC_DIR)/%.h, $(wildcard $(DTRACE_SOURCE_DIR)/*.d)) + +endif diff --git a/hotspot/makefiles/gensrc/GensrcJvmti.gmk b/hotspot/makefiles/gensrc/GensrcJvmti.gmk new file mode 100644 index 0000000000000000000000000000000000000000..25f569dc119771d3acdc25655701b94b3737362e --- /dev/null +++ b/hotspot/makefiles/gensrc/GensrcJvmti.gmk @@ -0,0 +1,174 @@ +# +# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# 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. +# + +$(eval $(call IncludeCustomExtension, hotspot, gensrc/GensrcJvmti.gmk)) + +################################################################################ +# Build tools needed for the JVMTI source code generation + +JVMTI_TOOLS_SRCDIR := $(HOTSPOT_TOPDIR)/src/share/vm/prims +JVMTI_TOOLS_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/tools/jvmti + +$(eval $(call SetupJavaCompiler, GENERATE_OLDBYTECODE, \ + JAVAC := $(JAVAC), \ + FLAGS := $(DISABLE_WARNINGS), \ + SERVER_DIR := $(SJAVAC_SERVER_DIR), \ + SERVER_JVM := $(SJAVAC_SERVER_JAVA), \ + DISABLE_SJAVAC := true, \ +)) + +$(eval $(call SetupJavaCompilation, BUILD_JVMTI_TOOLS, \ + SETUP := GENERATE_OLDBYTECODE, \ + SRC := $(JVMTI_TOOLS_SRCDIR), \ + INCLUDE_FILES := jvmtiGen.java jvmtiEnvFill.java, \ + BIN := $(JVMTI_TOOLS_OUTPUTDIR), \ +)) + +TOOL_JVMTI_GEN := $(JAVA_SMALL) -cp $(JVMTI_TOOLS_OUTPUTDIR) jvmtiGen +TOOL_JVMTI_ENV_FILL := $(JAVA_SMALL) -cp $(JVMTI_TOOLS_OUTPUTDIR) jvmtiEnvFill + +################################################################################ +# Setup make rules for an xml transform for jvmti/trace file generation. +# +# Parameter 1 is the name of the rule. This name is used as variable prefix, +# and the targets generated are listed in a variable by that name. This name is +# also used as the name of the output file. +# +# Remaining parameters are named arguments. These include: +# XML_FILE -- The input source file to use +# XSL_FILE -- The xsl file to use +# OUTPUT_DIR -- The directory to put the generated file in +# ARGS -- Additional arguments to the jvmtiGen tool +# DEPS -- Additional dependencies +SetupXslTransform = $(NamedParamsMacroTemplate) +define SetupXslTransformBody + $$($1_OUTPUT_DIR)/$1: $$($1_XML_FILE) $$($1_XSL_FILE) $$($1_DEPS) $$(BUILD_JVMTI_TOOLS) + $$(call LogInfo, Generating $$(@F)) + $$(call MakeDir, $$(@D)) + $$(call ExecuteWithLog, $$@, $$(TOOL_JVMTI_GEN) -IN $$($1_XML_FILE) -XSL $$($1_XSL_FILE) -OUT $$@ $$($1_ARGS)) + # jvmtiGen does not return error code properly on fail. + # NOTE: We should really fix jvmtiGen.java instead. + test -f $$@ + + TARGETS += $$($1_OUTPUT_DIR)/$1 +endef + +################################################################################ +# Create JVMTI files in gensrc/jvmtifiles + +JVMTI_SRCDIR := $(HOTSPOT_TOPDIR)/src/share/vm/prims +JVMTI_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/gensrc/jvmtifiles + +# Setup rule for generating a jvmti file +# +# $1 is generated source file name in $(JVMTI_OUTPUTDIR) +# $2 is XSL file to use in $(JVMTI_SRCDIR) +# $3 is optional extra arguments to jvmtiGen +define SetupJvmtiGeneration + $$(eval $$(call SetupXslTransform, $1, \ + XML_FILE := $$(JVMTI_SRCDIR)/jvmti.xml, \ + XSL_FILE := $$(JVMTI_SRCDIR)/$(strip $2), \ + OUTPUT_DIR := $$(JVMTI_OUTPUTDIR), \ + ARGS := $3, \ + DEPS := $$(JVMTI_SRCDIR)/jvmtiLib.xsl, \ + )) +endef + +$(eval $(call SetupJvmtiGeneration, jvmtiEnter.cpp, jvmtiEnter.xsl, \ + -PARAM interface jvmti)) +$(eval $(call SetupJvmtiGeneration, jvmtiEnterTrace.cpp, jvmtiEnter.xsl, \ + -PARAM interface jvmti -PARAM trace Trace)) +$(eval $(call SetupJvmtiGeneration, jvmtiEnv.hpp, jvmtiHpp.xsl)) +$(eval $(call SetupJvmtiGeneration, jvmti.h, jvmtiH.xsl)) +$(eval $(call SetupJvmtiGeneration, jvmti.html, jvmti.xsl)) +$(eval $(call SetupJvmtiGeneration, jvmtiEnvStub.cpp, jvmtiEnv.xsl)) + +JVMTI_BC_SRCDIR := $(HOTSPOT_TOPDIR)/src/share/vm/interpreter + +$(eval $(call SetupXslTransform, bytecodeInterpreterWithChecks.cpp, \ + XML_FILE := $(JVMTI_BC_SRCDIR)/bytecodeInterpreterWithChecks.xml, \ + XSL_FILE := $(JVMTI_BC_SRCDIR)/bytecodeInterpreterWithChecks.xsl, \ + OUTPUT_DIR := $(JVMTI_OUTPUTDIR), \ + DEPS := $(JVMTI_BC_SRCDIR)/bytecodeInterpreter.cpp, \ +)) + +# We need $(JVMTI_OUTPUTDIR)/jvmtiEnvStub.cpp (generated above) as input +$(JVMTI_OUTPUTDIR)/jvmtiEnvRecommended.cpp: $(JVMTI_SRCDIR)/jvmtiEnv.cpp \ + $(JVMTI_OUTPUTDIR)/jvmtiEnvStub.cpp $(BUILD_JVMTI_TOOLS) + $(call LogInfo, Generating $(@F)) + $(call MakeDir, $(@D)) + $(call ExecuteWithLog, $@, $(TOOL_JVMTI_ENV_FILL) $(JVMTI_SRCDIR)/jvmtiEnv.cpp \ + $(JVMTI_OUTPUTDIR)/jvmtiEnvStub.cpp \ + $(JVMTI_OUTPUTDIR)/jvmtiEnvRecommended.cpp) + # jvmtiEnvFill does not necessarily return an error code on failure. + # NOTE: We should really fix jvmtiEnvFill.java instead. + test -f $@ + +TARGETS += $(JVMTI_OUTPUTDIR)/jvmtiEnvRecommended.cpp + +################################################################################ +# Create trace files in gensrc/tracefiles + +TRACE_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/gensrc/tracefiles +TRACE_SRCDIR := $(HOTSPOT_TOPDIR)/src/share/vm/trace + +# Append directories to search (might have been set by custom extensions) +TRACE_SEARCH_DIRS += $(TRACE_SRCDIR) + +TRACE_XML ?= $(TRACE_SRCDIR)/trace.xml + +# Changing these will trigger a rebuild of generated trace files. +TRACE_DEPS += \ + $(TRACE_XML) \ + $(TRACE_SRCDIR)/tracetypes.xml \ + $(TRACE_SRCDIR)/tracerelationdecls.xml \ + $(TRACE_SRCDIR)/traceevents.xml \ + $(TRACE_SRCDIR)/trace.dtd \ + $(TRACE_SRCDIR)/xinclude.mod \ + # + +# Setup rule for generating a trace file +# +# $1 is generated source file name in $(TRACE_OUTPUTDIR) +define SetupTraceGeneration + $$(eval $$(call SetupXslTransform, $1, \ + XML_FILE := $$(TRACE_XML), \ + XSL_FILE := $$(firstword $$(wildcard $$(addsuffix /$$(basename $1).xsl, $$(TRACE_SEARCH_DIRS)))), \ + OUTPUT_DIR := $$(TRACE_OUTPUTDIR), \ + DEPS := $$(TRACE_DEPS), \ + )) +endef + +# Append files to generated (might have been set by custom extensions) +TRACE_GENSRC_FILES += \ + traceEventClasses.hpp \ + traceEventIds.hpp \ + traceTypes.hpp \ + # + +# Call SetupTraceGeneration for all trace gensrc files +$(foreach tracefile, $(TRACE_GENSRC_FILES), \ + $(eval $(call SetupTraceGeneration, $(tracefile))) \ +) diff --git a/hotspot/makefiles/ide/CreateVSProject.gmk b/hotspot/makefiles/ide/CreateVSProject.gmk new file mode 100644 index 0000000000000000000000000000000000000000..d804dcce9a8231c60b0e73b03b4f76ef9ca5ce06 --- /dev/null +++ b/hotspot/makefiles/ide/CreateVSProject.gmk @@ -0,0 +1,153 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# 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 must be the first rule +default: all + +include $(SPEC) +include MakeBase.gmk +include JavaCompilation.gmk +include SetupJavaCompilers.gmk + +ifeq ($(OPENJDK_TARGET_OS), windows) + # The next part is a bit hacky. We include the CompileJvm.gmk to be + # able to extact flags, but we do not wish to execute the rules. + + # Use client as base for defines and includes + JVM_VARIANT=client + + include HotspotCommon.gmk + include lib/CompileJvm.gmk + + # Reset targets so we don't build libjvm. + TARGETS := + + # Helper macro to convert a unix path to a Windows path, suitable for + # inclusion in a command line. + FixPath = \ + $(strip $(subst \,\\,$(shell $(CYGPATH) -w $1))) + + JVM_DEFINES_client := $(patsubst -D%,%, $(filter -D%, $(JVM_CFLAGS))) + EXTRACTED_DEFINES_client := $(addprefix -define , $(JVM_DEFINES_client)) + + JVM_INCLUDES_client := $(patsubst -I%,%, $(filter -I%, $(JVM_CFLAGS))) + EXTRACTED_INCLUDES_client := $(foreach path, $(JVM_INCLUDES_client), -absoluteInclude $(call FixPath, $(path))) + + # Hand-code variant-specific arguments, based on the fact that we use + # client for general arguments. Not optimal but other solutions require + # major changes in ProjectCreator. + ADDITIONAL_VARIANT_ARGS := \ + -define_server COMPILER2 \ + -ignorePath_client adfiles \ + -ignorePath_client c2_ \ + -ignorePath_client runtime_ \ + -ignorePath_client libadt \ + -ignorePath_client opto \ + # + + IGNORED_PLATFORMS_ARGS := \ + -ignorePath aarch64 \ + -ignorePath aix \ + -ignorePath arm \ + -ignorePath bsd \ + -ignorePath linux \ + -ignorePath posix \ + -ignorePath ppc \ + -ignorePath shark \ + -ignorePath solaris \ + -ignorePath sparc \ + -ignorePath x86_32 \ + -ignorePath zero \ + # + + ################################################################################ + # Build the ProjectCreator java tool. + + TOOLS_OUTPUTDIR := $(HOTSPOT_OUTPUTDIR)/support/tools_classes + + $(eval $(call SetupJavaCompilation, BUILD_PROJECT_CREATOR, \ + SETUP := GENERATE_OLDBYTECODE, \ + ADD_JAVAC_FLAGS := -Xlint:-auxiliaryclass, \ + SRC := $(HOTSPOT_TOPDIR)/makefiles/src/classes, \ + BIN := $(TOOLS_OUTPUTDIR), \ + )) + + TARGETS += $(BUILD_PROJECT_CREATOR) + + # Run the ProjectCreator tool + PROJECT_CREATOR_TOOL := $(JAVA_SMALL) -cp $(TOOLS_OUTPUTDIR) build.tools.projectcreator.ProjectCreator + + IDE_OUTPUTDIR := $(BUILD_OUTPUT)/ide/hotspot-visualstudio + + VCPROJ_FILE := $(IDE_OUTPUTDIR)/jvm.vcxproj + + PROJECT_CREATOR_CLASS := build.tools.projectcreator.WinGammaPlatformVC10 + + # We hard-code gensrc dir to server (since this includes adfiles) + PROJECT_CREATOR_ARGS := \ + -sourceBase $(call FixPath, $(HOTSPOT_TOPDIR)) \ + -startAt src \ + -relativeSrcInclude src \ + -hidePath .hg \ + -hidePath .jcheck \ + -hidePath jdk.hotspot.agent \ + -hidePath jdk.vm.ci \ + -hidePath jdk.jfr \ + -compiler VC10 \ + -jdkTargetRoot $(call FixPath, $(JDK_OUTPUTDIR)) \ + -platformName x64 \ + -buildBase $(call FixPath, $(IDE_OUTPUTDIR)/vs-output) \ + -buildSpace $(call FixPath, $(IDE_OUTPUTDIR)) \ + -makeBinary $(call FixPath, $(MAKE)) \ + -makeOutput $(call FixPath, $(HOTSPOT_OUTPUTDIR)/variant-%f/libjvm) \ + -absoluteInclude $(call FixPath, $(HOTSPOT_OUTPUTDIR)/variant-server/gensrc) \ + -absoluteSrcInclude $(call FixPath, $(HOTSPOT_OUTPUTDIR)/variant-server/gensrc) \ + $(EXTRACTED_DEFINES_client) \ + $(EXTRACTED_INCLUDES_client) \ + $(ADDITIONAL_VARIANT_ARGS) \ + $(IGNORED_PLATFORMS_ARGS) \ + # + + VCPROJ_VARDEPS := $(PROJECT_CREATOR_CLASS) $(PROJECT_CREATOR_ARGS) + VCPROJ_VARDEPS_FILE := $(call DependOnVariable, VCPROJ_VARDEPS, \ + $(VCPROJ_FILE).vardeps) + + $(VCPROJ_FILE): $(BUILD_PROJECT_CREATOR) $(VCPROJ_VARDEPS_FILE) + $(call MakeDir, $(@D)) + $(call ExecuteWithLog, $@, \ + $(PROJECT_CREATOR_TOOL) $(PROJECT_CREATOR_CLASS) \ + $(PROJECT_CREATOR_ARGS) -projectFileName $(call FixPath, $@)) \ + $(LOG_INFO) + + TARGETS += $(VCPROJ_FILE) + + all: $(TARGETS) + +else + all: + $(info Hotspot Visual Studio generation only supported on Windows) +endif + +.PHONY: all diff --git a/hotspot/makefiles/lib/CompileDtracePostJvm.gmk b/hotspot/makefiles/lib/CompileDtracePostJvm.gmk new file mode 100644 index 0000000000000000000000000000000000000000..127460a562e9629348d6987f1777182a0603978f --- /dev/null +++ b/hotspot/makefiles/lib/CompileDtracePostJvm.gmk @@ -0,0 +1,217 @@ +# +# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# 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. +# + +################################################################################ +# Support for dtrace integration with libjvm, and stand-alone dtrace library +# compilation. + +ifeq ($(call check-jvm-feature, dtrace), true) + ############################################################################## + + ifeq ($(OPENJDK_TARGET_OS), solaris) + ############################################################################ + # Integrate with libjvm. Here we generate three object files which are + # linked with libjvm.so. This step is complicated from a dependency + # perspective, since it needs the rest of the compiled object files from the + # libjvm compilation, but the output is object files that are to be included + # when linking libjvm.so. So this generation must happen as a part of the + # libjvm compilation. + + # First we need to generate the dtraceGenOffsets tool. When run, this will + # produce more header files and a C++ file. + + # Note that generateJvmOffsets.cpp must be compiled as if it were a file + # in the libjvm.so, using JVM_CFLAGS as setup in CompileJvm.gmk. Otherwise + # this would preferrably have been done as a part of GensrcDtrace.gmk. + $(eval $(call SetupNativeCompilation, BUILD_DTRACE_GEN_OFFSETS, \ + SRC := $(HOTSPOT_TOPDIR)/src/os/$(OPENJDK_TARGET_OS)/dtrace, \ + INCLUDE_FILES := generateJvmOffsets.cpp generateJvmOffsetsMain.c, \ + CC := $(BUILD_CXX), \ + CXX := $(BUILD_CXX), \ + LDEXE := $(BUILD_CXX), \ + generateJvmOffsets.cpp_CXXFLAGS := $(JVM_CFLAGS) -mt -xnolib -norunpath, \ + generateJvmOffsetsMain.c_CFLAGS := -library=%none -mt -m64 -norunpath -z nodefs, \ + LDFLAGS := -m64, \ + LIBS := -lc, \ + OBJECT_DIR := $(JVM_VARIANT_OUTPUTDIR)/tools/dtrace-gen-offsets/objs, \ + OUTPUT_DIR := $(JVM_VARIANT_OUTPUTDIR)/tools/dtrace-gen-offsets, \ + PROGRAM := dtraceGenOffsets, \ + )) + + DTRACE_GEN_OFFSETS_TOOL := $(BUILD_DTRACE_GEN_OFFSETS_TARGET) + + # Argument 1: Output filename + # Argument 2: dtrace-gen-offset tool command line option + define SetupDtraceOffsetsGeneration + $1: $$(BUILD_DTRACE_GEN_OFFSETS) + $$(call LogInfo, Generating dtrace $2 file $$(@F)) + $$(call MakeDir, $$(@D)) + $$(call ExecuteWithLog, $$@, $$(DTRACE_GEN_OFFSETS_TOOL) -$$(strip $2) > $$@) + + TARGETS += $1 + endef + + JVM_OFFSETS_H := $(DTRACE_SUPPORT_DIR)/JvmOffsets.h + JVM_OFFSETS_CPP := $(DTRACE_SUPPORT_DIR)/JvmOffsets.cpp + JVM_OFFSETS_INDEX_H := $(DTRACE_SUPPORT_DIR)/JvmOffsetsIndex.h + + # Run the dtrace-gen-offset tool to generate these three files. + $(eval $(call SetupDtraceOffsetsGeneration, $(JVM_OFFSETS_H), header)) + $(eval $(call SetupDtraceOffsetsGeneration, $(JVM_OFFSETS_INDEX_H), index)) + $(eval $(call SetupDtraceOffsetsGeneration, $(JVM_OFFSETS_CPP), table)) + + ############################################################################ + # Compile JVM_OFFSETS_OBJ which is linked with libjvm.so. + + # JvmOffsets.cpp is compiled without the common JVM_CFLAGS. Otherwise, the + # natural way would have been to included this source code in BUILD_LIBJVM. + JVM_OFFSETS_CFLAGS := -m64 + ifeq ($(OPENJDK_TARGET_CPU), sparcv9) + JVM_OFFSETS_CFLAGS += -xarch=sparc + endif + + $(JVM_OFFSETS_OBJ): $(JVM_OFFSETS_CPP) $(JVM_OFFSETS_H) + $(call LogInfo, Compiling dtrace file JvmOffsets.cpp (for libjvm.so)) + $(call ExecuteWithLog, $@, $(CXX) -c -I$( $@ + + DTRACE_INSTRUMENTED_OBJS := $(addprefix $(JVM_OUTPUTDIR)/objs/, \ + ciEnv.o \ + classLoadingService.o \ + compileBroker.o \ + hashtable.o \ + instanceKlass.o \ + java.o \ + jni.o \ + jvm.o \ + memoryManager.o \ + nmethod.o \ + objectMonitor.o \ + runtimeService.o \ + sharedRuntime.o \ + synchronizer.o \ + thread.o \ + unsafe.o \ + vmThread.o \ + vmGCOperations.o \ + ) + + ifeq ($(call check-jvm-feature, all-gcs), true) + DTRACE_INSTRUMENTED_OBJS += $(addprefix $(JVM_OUTPUTDIR)/objs/, \ + vmCMSOperations.o \ + vmPSOperations.o \ + ) + endif + + DTRACE_FLAGS := -64 -G + DTRACE_CPP_FLAGS := -D_LP64 + + # Make sure we run our selected compiler for preprocessing instead of letting + # the dtrace tool pick it on it's own. + $(DTRACE_OBJ): $(JVM_OUTPUTDIR)/objs/dtrace.d $(DTRACE_INSTRUMENTED_OBJS) + $(call LogInfo, Generating $(@F) from $( $(DTRACE_SUPPORT_DIR)/$(@F).d) + $(call ExecuteWithLog, $@, $(DTRACE) $(DTRACE_FLAGS) -xlazyload -o $@ \ + -s $(DTRACE_SUPPORT_DIR)/$(@F).d $(sort $(DTRACE_INSTRUMENTED_OBJS))) + + ############################################################################ + # Generate DTRACE_JHELPER_OBJ which is linked with libjvm.so. + + # Unfortunately dtrace generates incorrect types for some symbols in + # dtrace_jhelper.o, resulting in "warning: symbol X has differing types" + # This is tracked in JDK-6890703. + $(DTRACE_JHELPER_OBJ): $(HOTSPOT_TOPDIR)/src/os/solaris/dtrace/jhelper.d \ + $(JVM_OFFSETS_INDEX_H) + $(call LogInfo, Running dtrace for $( $(DTRACE_SUPPORT_DIR)/$(@F).d) + # $(call ExecuteWithLog, $@, $(DTRACE) $(DTRACE_FLAGS) -o $@ \ + # -s $(DTRACE_SUPPORT_DIR)/$(@F).d) + + ############################################################################ + # Build the stand-alone dtrace libraries + + LIBJVM_DTRACE_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/libjvm_dtrace + + $(eval $(call SetupNativeCompilation, BUILD_LIBJVM_DTRACE, \ + LIBRARY := jvm_dtrace, \ + OUTPUT_DIR := $(LIBJVM_DTRACE_OUTPUTDIR), \ + SRC := $(HOTSPOT_TOPDIR)/src/os/solaris/dtrace, \ + INCLUDE_FILES := jvm_dtrace.c, \ + CFLAGS := -m64 -G -mt -KPIC, \ + LDFLAGS := -m64 -mt -xnolib $(SHARED_LIBRARY_FLAGS), \ + LIBS := $(LIBDL) -lc -lthread -ldoor, \ + MAPFILE := $(HOTSPOT_TOPDIR)/makefiles/mapfiles/libjvm_dtrace/mapfile-vers, \ + OBJECT_DIR := $(LIBJVM_DTRACE_OUTPUTDIR)/objs, \ + STRIP_SYMBOLS := true, \ + )) + + LIBJVM_DB_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/libjvm_db + + # Note that libjvm_db.c has tests for COMPILER2, but this was never set by + # the old build. + $(eval $(call SetupNativeCompilation, BUILD_LIBJVM_DB, \ + LIBRARY := jvm_db, \ + OUTPUT_DIR := $(LIBJVM_DB_OUTPUTDIR), \ + SRC := $(HOTSPOT_TOPDIR)/src/os/solaris/dtrace, \ + INCLUDE_FILES := libjvm_db.c, \ + CFLAGS := -I$(JVM_VARIANT_OUTPUTDIR)/gensrc -I$(DTRACE_SUPPORT_DIR) \ + -m64 -G -mt -KPIC, \ + LDFLAGS := -m64 -mt -xnolib $(SHARED_LIBRARY_FLAGS), \ + LIBS := -lc, \ + MAPFILE := $(HOTSPOT_TOPDIR)/makefiles/mapfiles/libjvm_db/mapfile-vers, \ + OBJECT_DIR := $(LIBJVM_DB_OUTPUTDIR)/objs, \ + STRIP_SYMBOLS := true, \ + )) + + # We need the generated JvmOffsets.h before we can compile the libjvm_db source code. + $(BUILD_LIBJVM_DB_ALL_OBJS): $(JVM_OFFSETS_H) + + TARGETS += $(BUILD_LIBJVM_DTRACE) $(BUILD_LIBJVM_DB) + endif +endif diff --git a/hotspot/makefiles/lib/CompileDtracePreJvm.gmk b/hotspot/makefiles/lib/CompileDtracePreJvm.gmk new file mode 100644 index 0000000000000000000000000000000000000000..20e3aa9be7d0da594283ab0ab0940b8fe4bc90a8 --- /dev/null +++ b/hotspot/makefiles/lib/CompileDtracePreJvm.gmk @@ -0,0 +1,36 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# 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. +# + +ifeq ($(call check-jvm-feature, dtrace), true) + ifeq ($(OPENJDK_TARGET_OS), solaris) + # These files are are generated by CompileDtrace.gmk but consumed by + # CompileJvm.gmk + DTRACE_OBJ := $(JVM_OUTPUTDIR)/objs/dtrace.o + DTRACE_JHELPER_OBJ := $(JVM_OUTPUTDIR)/objs/dtrace_jhelper.o + JVM_OFFSETS_OBJ := $(JVM_OUTPUTDIR)/objs/JvmOffsets.o + + DTRACE_EXTRA_OBJECT_FILES := $(DTRACE_OBJ) $(DTRACE_JHELPER_OBJ) $(JVM_OFFSETS_OBJ) + endif +endif diff --git a/hotspot/makefiles/lib/CompileJvm.gmk b/hotspot/makefiles/lib/CompileJvm.gmk new file mode 100644 index 0000000000000000000000000000000000000000..b6404cf74b1c550fdfb025c23acd8c84a91c8eec --- /dev/null +++ b/hotspot/makefiles/lib/CompileJvm.gmk @@ -0,0 +1,242 @@ +# +# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# 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. +# + +# Include support files that will setup compiler flags due to the selected +# jvm feature set, and specific file overrides. +include lib/JvmFeatures.gmk +include lib/JvmOverrideFiles.gmk + +$(eval $(call IncludeCustomExtension, hotspot, lib/CompileJvm.gmk)) + +################################################################################ +# Setup compilation of the main Hotspot native library (libjvm). + +JVM_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/libjvm +JVM_MAPFILE := $(JVM_OUTPUTDIR)/mapfile + +################################################################################ +# Platform independent setup + +# This variable may be added to by a custom extension +JVM_SRC_ROOTS += $(HOTSPOT_TOPDIR)/src + +JVM_SRC_DIRS += $(call uniq, $(wildcard $(foreach d, $(JVM_SRC_ROOTS), \ + $d/share/vm \ + $d/os/$(HOTSPOT_TARGET_OS)/vm \ + $d/os/$(HOTSPOT_TARGET_OS_TYPE)/vm \ + $d/cpu/$(HOTSPOT_TARGET_CPU_ARCH)/vm \ + $d/os_cpu/$(HOTSPOT_TARGET_OS)_$(HOTSPOT_TARGET_CPU_ARCH)/vm \ + ))) \ + $(JVM_VARIANT_OUTPUTDIR)/gensrc/jvmtifiles \ + $(JVM_VARIANT_OUTPUTDIR)/gensrc/tracefiles \ + # + +JVM_CFLAGS_INCLUDES += \ + $(patsubst %,-I%,$(filter-out $(JVM_VARIANT_OUTPUTDIR)/gensrc/%, $(JVM_SRC_DIRS))) \ + -I$(JVM_VARIANT_OUTPUTDIR)/gensrc \ + -I$(HOTSPOT_TOPDIR)/src/share/vm/precompiled \ + -I$(HOTSPOT_TOPDIR)/src/share/vm/prims \ + # + +JVM_CFLAGS_TARGET_DEFINES += \ + -DTARGET_OS_FAMILY_$(HOTSPOT_TARGET_OS) \ + -DTARGET_ARCH_MODEL_$(HOTSPOT_TARGET_CPU) \ + -DTARGET_ARCH_$(HOTSPOT_TARGET_CPU_ARCH) \ + -DTARGET_OS_ARCH_MODEL_$(HOTSPOT_TARGET_OS)_$(HOTSPOT_TARGET_CPU) \ + -DTARGET_OS_ARCH_$(HOTSPOT_TARGET_OS)_$(HOTSPOT_TARGET_CPU_ARCH) \ + -DTARGET_COMPILER_$(HOTSPOT_TOOLCHAIN_TYPE) \ + -D$(HOTSPOT_TARGET_CPU_DEFINE) \ + -DHOTSPOT_LIB_ARCH='"$(OPENJDK_TARGET_CPU_LEGACY_LIB)"' \ + # + +ifeq ($(DEBUG_LEVEL), release) + # For hotspot, release builds differ internally between "optimized" and "product" + # in that "optimize" does not define PRODUCT. + ifneq ($(HOTSPOT_DEBUG_LEVEL), optimized) + JVM_CFLAGS_DEBUGLEVEL := -DPRODUCT + endif +else ifeq ($(DEBUG_LEVEL), fastdebug) + JVM_CFLAGS_DEBUGLEVEL := -DASSERT + ifeq ($(filter $(OPENJDK_TARGET_OS), windows aix), ) + # NOTE: Old build did not define CHECK_UNHANDLED_OOPS on Windows and AIX. + JVM_CFLAGS_DEBUGLEVEL += -DCHECK_UNHANDLED_OOPS + endif +else ifeq ($(DEBUG_LEVEL), slowdebug) + # _NMT_NOINLINE_ informs NMT that no inlining is done by the compiler + JVM_CFLAGS_DEBUGLEVEL := -DASSERT -D_NMT_NOINLINE_ +endif + +JVM_CFLAGS += \ + $(JVM_CFLAGS_DEBUGLEVEL) \ + $(JVM_CFLAGS_TARGET_DEFINES) \ + $(JVM_CFLAGS_FEATURES) \ + $(JVM_CFLAGS_INCLUDES) \ + $(EXTRA_CFLAGS) \ + # + +JVM_LDFLAGS += \ + $(SHARED_LIBRARY_FLAGS) \ + $(JVM_LDFLAGS_FEATURES) \ + $(EXTRA_LDFLAGS) \ + # + +JVM_LIBS += \ + $(JVM_LIBS_FEATURES) \ + # + +# These files and directories are always excluded +JVM_EXCLUDE_FILES += jsig.c jvmtiEnvRecommended.cpp jvmtiEnvStub.cpp args.cc +JVM_EXCLUDES += adlc + +# Needed by vm_version.cpp +ifeq ($(OPENJDK_TARGET_CPU), x86_64) + OPENJDK_TARGET_CPU_VM_VERSION := amd64 +else ifeq ($(OPENJDK_TARGET_CPU), sparcv9) + OPENJDK_TARGET_CPU_VM_VERSION := sparc +else + OPENJDK_TARGET_CPU_VM_VERSION := $(OPENJDK_TARGET_CPU) +endif + +CFLAGS_VM_VERSION := \ + $(VERSION_CFLAGS) \ + -DHOTSPOT_VERSION_STRING='"$(VERSION_STRING)"' \ + -DDEBUG_LEVEL='"$(DEBUG_LEVEL)"' \ + -DHOTSPOT_BUILD_USER='"$(USERNAME)"' \ + -DHOTSPOT_VM_DISTRO='"$(HOTSPOT_VM_DISTRO)"' \ + -DCPU='"$(OPENJDK_TARGET_CPU_VM_VERSION)"' \ + # + +# -DDONT_USE_PRECOMPILED_HEADER will exclude all includes in precompiled.hpp. +ifeq ($(USE_PRECOMPILED_HEADER), 0) + JVM_CFLAGS += -DDONT_USE_PRECOMPILED_HEADER +endif + +################################################################################ +# Platform specific setup + +ifneq ($(filter $(OPENJDK_TARGET_OS), linux macosx windows), ) + JVM_PRECOMPILED_HEADER := $(HOTSPOT_TOPDIR)/src/share/vm/precompiled/precompiled.hpp +endif + +ifneq ($(filter $(OPENJDK_TARGET_OS), macosx aix solaris), ) + # On macosx, aix and solaris we have to link with the C++ compiler + JVM_TOOLCHAIN := TOOLCHAIN_LINK_CXX +else + JVM_TOOLCHAIN := TOOLCHAIN_DEFAULT +endif + +ifeq ($(OPENJDK_TARGET_CPU), x86) + JVM_EXCLUDE_PATTERNS += x86_64 +else ifeq ($(OPENJDK_TARGET_CPU), x86_64) + JVM_EXCLUDE_PATTERNS += x86_32 +endif + +# Inline assembly for solaris +ifeq ($(OPENJDK_TARGET_OS), solaris) + ifeq ($(OPENJDK_TARGET_CPU), x86_64) + JVM_CFLAGS += $(HOTSPOT_TOPDIR)/src/os_cpu/solaris_x86/vm/solaris_x86_64.il + else ifeq ($(OPENJDK_TARGET_CPU), sparcv9) + JVM_CFLAGS += $(HOTSPOT_TOPDIR)/src/os_cpu/solaris_sparc/vm/solaris_sparc.il + endif +endif + +ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU), solaris-sparcv9) + ifeq ($(COMPILE_WITH_DEBUG_SYMBOLS), false) + # NOTE: In the old build, we weirdly enough set -g/-g0 always, regardless + # of if debug symbols were needed. Without it, compilation fails on + # sparc! :-( + JVM_CFLAGS += -g0 + endif +endif + +ifeq ($(OPENJDK_TARGET_OS), windows) + ifeq ($(OPENJDK_TARGET_CPU_BITS), 64) + RC_DESC := 64-Bit$(SPACE) + endif + JVM_RCFLAGS += -D"HS_FILEDESC=$(HOTSPOT_VM_DISTRO) $(RC_DESC)$(JVM_VARIANT) VM" +endif + +ifeq ($(OPENJDK_TARGET_OS), macosx) + # NOTE: The old build did not strip binaries on macosx. + JVM_STRIP_SYMBOLS := false +else + JVM_STRIP_SYMBOLS := true +endif + +JVM_OPTIMIZATION ?= HIGHEST_JVM + +################################################################################ +# Now set up the actual compilation of the main hotspot native library + +$(eval $(call SetupNativeCompilation, BUILD_LIBJVM, \ + TOOLCHAIN := $(JVM_TOOLCHAIN), \ + LIBRARY := jvm, \ + OUTPUT_DIR := $(JVM_OUTPUTDIR), \ + SRC := $(JVM_SRC_DIRS), \ + EXCLUDES := $(JVM_EXCLUDES), \ + EXCLUDE_FILES := $(JVM_EXCLUDE_FILES), \ + EXCLUDE_PATTERNS := $(JVM_EXCLUDE_PATTERNS), \ + EXTRA_OBJECT_FILES := $(DTRACE_EXTRA_OBJECT_FILES), \ + CFLAGS := $(JVM_CFLAGS), \ + CFLAGS_DEBUG_SYMBOLS := $(JVM_CFLAGS_SYMBOLS), \ + CXXFLAGS_DEBUG_SYMBOLS := $(JVM_CFLAGS_SYMBOLS), \ + vm_version.cpp_CXXFLAGS := $(CFLAGS_VM_VERSION), \ + DISABLED_WARNINGS_clang := delete-non-virtual-dtor dynamic-class-memaccess \ + empty-body format logical-op-parentheses parentheses \ + parentheses-equality switch tautological-compare, \ + DISABLED_WARNINGS_xlc := 1540-0216 1540-0198 1540-1090 1540-1639 \ + 1540-1088 1500-010, \ + ASFLAGS := $(JVM_ASFLAGS), \ + LDFLAGS := $(JVM_LDFLAGS), \ + LIBS := $(JVM_LIBS), \ + OPTIMIZATION := $(JVM_OPTIMIZATION), \ + OBJECT_DIR := $(JVM_OUTPUTDIR)/objs, \ + MAPFILE := $(JVM_MAPFILE), \ + USE_MAPFILE_FOR_SYMBOLS := true, \ + STRIP_SYMBOLS := $(JVM_STRIP_SYMBOLS), \ + EMBED_MANIFEST := true, \ + RC_FLAGS := $(JVM_RCFLAGS), \ + VERSIONINFO_RESOURCE := $(HOTSPOT_TOPDIR)/src/os/windows/vm/version.rc, \ + PRECOMPILED_HEADER := $(JVM_PRECOMPILED_HEADER), \ + PRECOMPILED_HEADER_EXCLUDE := $(JVM_PRECOMPILED_HEADER_EXCLUDE), \ +)) + +# AIX warning explanation: +# 1500-010 : (W) WARNING in ...: Infinite loop. Program may not stop. +# There are several infinite loops in the vm, so better suppress. +# 1540-0198 : (W) The omitted keyword "private" is assumed for base class "...". +# 1540-0216 : (W) An expression of type .. cannot be converted to type .. +# In hotspot this fires for functionpointer to pointer conversions +# 1540-1088 : (W) The exception specification is being ignored. +# In hotspot this is caused by throw() in declaration of new() in nmethod.hpp. +# 1540-1090 : (I) The destructor of "..." might not be called. +# 1540-1639 : (I) The behavior of long type bit fields has changed ... + +# Include mapfile generation. It relies on BUILD_LIBJVM_ALL_OBJS which is only +# defined after the above call to BUILD_LIBJVM. Mapfile will be generated +# after all object files are built, but before the jvm library is linked. +include lib/JvmMapfile.gmk + +TARGETS += $(BUILD_LIBJVM) diff --git a/hotspot/makefiles/lib/CompileLibjsig.gmk b/hotspot/makefiles/lib/CompileLibjsig.gmk new file mode 100644 index 0000000000000000000000000000000000000000..ba9791cdef8aa19e181a6050e01f2dd758ac6470 --- /dev/null +++ b/hotspot/makefiles/lib/CompileLibjsig.gmk @@ -0,0 +1,106 @@ +# +# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# 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. +# + +################################################################################ +# Create the libjsig.so shared library + +default: all + +include $(SPEC) +include MakeBase.gmk +include NativeCompilation.gmk + +ifneq ($(OPENJDK_TARGET_OS), windows) + ifeq ($(STATIC_BUILD), false) + LIBJSIG_STRIP_SYMBOLS := true + ifeq ($(OPENJDK_TARGET_OS), linux) + LIBJSIG_CFLAGS := -fPIC -D_GNU_SOURCE -D_REENTRANT $(EXTRA_CFLAGS) + LIBJSIG_LDFLAGS := $(LDFLAGS_HASH_STYLE) $(EXTRA_CFLAGS) + LIBJSIG_LIBS := $(LIBDL) + + # NOTE: The old build compiled this library without -soname. + # To emulate this, we need to clear out SET_SHARED_LIBRARY_NAME. + SET_SHARED_LIBRARY_NAME := + + # Flags for other CPUs can be provided in EXTRA_CFLAGS + ifeq ($(OPENJDK_TARGET_CPU), x86_64) + LIBJSIG_CPU_FLAGS := -m64 + else ifeq ($(OPENJDK_TARGET_CPU), x86) + LIBJSIG_CPU_FLAGS := -m32 -march=i586 + endif + + else ifeq ($(OPENJDK_TARGET_OS), solaris) + LIBJSIG_CFLAGS := -m64 -KPIC -mt + LIBJSIG_LDFLAGS := -m64 -mt -xnolib + LIBJSIG_LIBS := $(LIBDL) + + # NOTE: The old build compiled this library without -soname. + # To emulate this, we need to clear out SET_SHARED_LIBRARY_NAME. + SET_SHARED_LIBRARY_NAME := + + else ifeq ($(OPENJDK_TARGET_OS), aix) + LIBJSIG_CFLAGS := -q64 -D_GNU_SOURCE -D_REENTRANT -qpic=large + LIBJSIG_LDFLAGS := -b64 -bexpall -G -bnoentry -qmkshrobj -brtl -bnolibpath -bernotok + LIBJSIG_LIBS := $(LIBDL) + + # NOTE: The old build compiled this library without -soname. + # To emulate this, we need to clear out SET_SHARED_LIBRARY_NAME. + SET_SHARED_LIBRARY_NAME := + + else ifeq ($(OPENJDK_TARGET_OS), macosx) + LIBJSIG_CFLAGS := -m64 -D_GNU_SOURCE -pthread -mno-omit-leaf-frame-pointer -mstack-alignment=16 -fPIC + LIBJSIG_LDFLAGS := $(LDFLAGS_HASH_STYLE) + # NOTE: This lib is not stripped on macosx in old build. Looks like a mistake. + LIBJSIG_STRIP_SYMBOLS := false + else + $(error Unknown target OS $(OPENJDK_TARGET_OS) in CompileLibjsig.gmk) + endif + + LIBJSIG_SRC_FILE := $(HOTSPOT_TOPDIR)/src/os/$(HOTSPOT_TARGET_OS)/vm/jsig.c + LIBJSIG_MAPFILE := $(wildcard $(HOTSPOT_TOPDIR)/makefiles/mapfiles/libjsig/mapfile-vers-$(OPENJDK_TARGET_OS)) + LIBJSIG_OUTPUTDIR := $(HOTSPOT_OUTPUTDIR)/libjsig + + LIBJSIG_LDFLAGS += $(SHARED_LIBRARY_FLAGS) + + $(eval $(call SetupNativeCompilation, BUILD_LIBJSIG, \ + LIBRARY := jsig, \ + EXTRA_FILES := $(LIBJSIG_SRC_FILE), \ + OUTPUT_DIR := $(LIBJSIG_OUTPUTDIR), \ + LANG := C, \ + CFLAGS := $(LIBJSIG_CFLAGS) $(LIBJSIG_CPU_FLAGS), \ + LDFLAGS := $(LIBJSIG_LDFLAGS) $(LIBJSIG_CPU_FLAGS), \ + LIBS := $(LIBJSIG_LIBS), \ + MAPFILE := $(LIBJSIG_MAPFILE), \ + OBJECT_DIR := $(LIBJSIG_OUTPUTDIR)/objs, \ + STRIP_SYMBOLS := $(LIBJSIG_STRIP_SYMBOLS), \ + )) + + TARGETS += $(BUILD_LIBJSIG) + endif +endif + +all: $(TARGETS) + +.PHONY: all diff --git a/hotspot/makefiles/lib/CompileLibraries.gmk b/hotspot/makefiles/lib/CompileLibraries.gmk new file mode 100644 index 0000000000000000000000000000000000000000..7a7a1651194528bf5f15c4ca09bd5440372e0dfa --- /dev/null +++ b/hotspot/makefiles/lib/CompileLibraries.gmk @@ -0,0 +1,42 @@ +# +# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# 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. +# + +default: all + +include $(SPEC) +include MakeBase.gmk +include NativeCompilation.gmk + +include HotspotCommon.gmk + +# The dtrace setup must be done both before and after CompileJvm.gmk, due to +# intricate dependencies. +include lib/CompileDtracePreJvm.gmk +include lib/CompileJvm.gmk +include lib/CompileDtracePostJvm.gmk + +all: $(TARGETS) + +.PHONY: all diff --git a/hotspot/makefiles/lib/JvmFeatures.gmk b/hotspot/makefiles/lib/JvmFeatures.gmk new file mode 100644 index 0000000000000000000000000000000000000000..40a3247c9a78d3fbbf07fc5a62fa896080c7ccd5 --- /dev/null +++ b/hotspot/makefiles/lib/JvmFeatures.gmk @@ -0,0 +1,144 @@ +# +# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# 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. +# + +$(eval $(call IncludeCustomExtension, hotspot, lib/JvmFeatures.gmk)) + +################################################################################ +# Setup CFLAGS and EXCLUDES for the libjvm compilation, depending on which +# jvm features are selected for this jvm variant. + +ifeq ($(call check-jvm-feature, compiler1), true) + JVM_CFLAGS_FEATURES += -DCOMPILER1 +else + JVM_EXCLUDE_PATTERNS += c1_ +endif + +ifeq ($(call check-jvm-feature, compiler2), true) + JVM_CFLAGS_FEATURES += -DCOMPILER2 + JVM_SRC_DIRS += $(JVM_VARIANT_OUTPUTDIR)/gensrc/adfiles +else + JVM_EXCLUDES += opto libadt + JVM_EXCLUDE_FILES += bcEscapeAnalyzer.cpp ciTypeFlow.cpp + JVM_EXCLUDE_PATTERNS += c2_ runtime_ +endif + +ifeq ($(call check-jvm-feature, zero), true) + JVM_CFLAGS_FEATURES += -DZERO -DCC_INTERP -DZERO_LIBARCH='"$(OPENJDK_TARGET_CPU_LEGACY_LIB)"' $(LIBFFI_CFLAGS) + JVM_LIBS_FEATURES += $(LIBFFI_LIBS) +endif + +ifeq ($(call check-jvm-feature, shark), true) + JVM_CFLAGS_FEATURES += -DSHARK $(LLVM_CFLAGS) + JVM_LDFLAGS_FEATURES += $(LLVM_LDFLAGS) + JVM_LIBS_FEATURES += $(LLVM_LIBS) +else + JVM_EXCLUDES += shark +endif + +ifeq ($(call check-jvm-feature, minimal), true) + JVM_CFLAGS_FEATURES += -DMINIMAL_JVM -DVMTYPE=\"Minimal\" +endif + +ifeq ($(call check-jvm-feature, dtrace), true) + JVM_CFLAGS_FEATURES += -DDTRACE_ENABLED +endif + +ifeq ($(call check-jvm-feature, static-build), true) + JVM_CFLAGS_FEATURES += -DSTATIC_BUILD=1 +endif + +ifneq ($(call check-jvm-feature, jvmti), true) + JVM_CFLAGS_FEATURES += -DINCLUDE_JVMTI=0 + JVM_EXCLUDE_FILES += jvmtiGetLoadedClasses.cpp jvmtiThreadState.cpp jvmtiExtensions.cpp \ + jvmtiImpl.cpp jvmtiManageCapabilities.cpp jvmtiRawMonitor.cpp jvmtiUtil.cpp jvmtiTrace.cpp \ + jvmtiCodeBlobEvents.cpp jvmtiEnv.cpp jvmtiRedefineClasses.cpp jvmtiEnvBase.cpp jvmtiEnvThreadState.cpp \ + jvmtiTagMap.cpp jvmtiEventController.cpp evmCompat.cpp jvmtiEnter.xsl jvmtiExport.cpp \ + jvmtiClassFileReconstituter.cpp +endif + +ifneq ($(call check-jvm-feature, jvmci), true) + JVM_CFLAGS_FEATURES += -DINCLUDE_JVMCI=0 + JVM_EXCLUDES += jvmci + JVM_EXCLUDE_FILES += jvmciCodeInstaller_$(HOTSPOT_TARGET_CPU_ARCH).cpp +endif + +ifneq ($(call check-jvm-feature, fprof), true) + JVM_CFLAGS_FEATURES += -DINCLUDE_FPROF=0 + JVM_EXCLUDE_FILES += fprofiler.cpp +endif + +ifneq ($(call check-jvm-feature, vm-structs), true) + JVM_CFLAGS_FEATURES += -DINCLUDE_VM_STRUCTS=0 + JVM_EXCLUDE_FILES += vmStructs.cpp +endif + +ifneq ($(call check-jvm-feature, jni-check), true) + JVM_CFLAGS_FEATURES += -DINCLUDE_JNI_CHECK=0 + JVM_EXCLUDE_FILES += jniCheck.cpp +endif + +ifneq ($(call check-jvm-feature, services), true) + JVM_CFLAGS_FEATURES += -DINCLUDE_SERVICES=0 + JVM_EXCLUDE_FILES += heapDumper.cpp heapInspection.cpp \ + attachListener_$(HOTSPOT_TARGET_OS).cpp attachListener.cpp +endif + +ifneq ($(call check-jvm-feature, management), true) + JVM_CFLAGS_FEATURES += -DINCLUDE_MANAGEMENT=0 +endif + +ifneq ($(call check-jvm-feature, cds), true) + JVM_CFLAGS_FEATURES += -DINCLUDE_CDS=0 + JVM_EXCLUDE_FILES += \ + classListParser.cpp \ + classLoaderExt.cpp \ + filemap.cpp \ + metaspaceShared.cpp \ + metaspaceShared_$(HOTSPOT_TARGET_CPU).cpp \ + metaspaceShared_$(HOTSPOT_TARGET_CPU_ARCH).cpp \ + sharedClassUtil.cpp \ + sharedPathsMiscInfo.cpp \ + systemDictionaryShared.cpp \ + # +endif + +ifneq ($(call check-jvm-feature, all-gcs), true) + JVM_CFLAGS_FEATURES += -DINCLUDE_ALL_GCS=0 + JVM_EXCLUDE_PATTERNS += \ + cms/ g1/ parallel/ + JVM_EXCLUDE_FILES += \ + concurrentGCThread.cpp \ + plab.cpp + JVM_EXCLUDE_FILES += \ + g1MemoryPool.cpp \ + psMemoryPool.cpp +endif + +ifneq ($(call check-jvm-feature, nmt), true) + JVM_CFLAGS_FEATURES += -DINCLUDE_NMT=0 + JVM_EXCLUDE_FILES += \ + memBaseline.cpp memReporter.cpp mallocTracker.cpp virtualMemoryTracker.cpp nmtCommon.cpp \ + memTracker.cpp nmtDCmd.cpp mallocSiteTable.cpp +endif diff --git a/hotspot/makefiles/lib/JvmMapfile.gmk b/hotspot/makefiles/lib/JvmMapfile.gmk new file mode 100644 index 0000000000000000000000000000000000000000..9d7655b26eed330b636898502d310efa3de2c326 --- /dev/null +++ b/hotspot/makefiles/lib/JvmMapfile.gmk @@ -0,0 +1,172 @@ +# +# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# 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. +# + +$(eval $(call IncludeCustomExtension, hotspot, lib/JvmMapfile.gmk)) + +################################################################################ +# Combine a list of static symbols + +ifneq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU), windows-x86_64) + # On Windows x86_64, we should not have any symbols at all, since that + # results in duplicate warnings from the linker (JDK-8043491). + SYMBOLS_SRC += $(HOTSPOT_TOPDIR)/makefiles/symbols/symbols-shared +endif + +ifeq ($(OPENJDK_TARGET_OS_TYPE), unix) + SYMBOLS_SRC += $(HOTSPOT_TOPDIR)/makefiles/symbols/symbols-unix +endif + +ifneq ($(wildcard $(HOTSPOT_TOPDIR)/makefiles/symbols/symbols-$(OPENJDK_TARGET_OS)), ) + SYMBOLS_SRC += $(HOTSPOT_TOPDIR)/makefiles/symbols/symbols-$(OPENJDK_TARGET_OS) +endif + +ifneq ($(findstring debug, $(DEBUG_LEVEL)), ) + ifneq ($(wildcard $(HOTSPOT_TOPDIR)/makefiles/symbols/symbols-$(OPENJDK_TARGET_OS)-debug), ) + SYMBOLS_SRC += $(HOTSPOT_TOPDIR)/makefiles/symbols/symbols-$(OPENJDK_TARGET_OS)-debug + endif +endif + +ifeq ($(OPENJDK_TARGET_OS), solaris) + ifeq ($(call check-jvm-feature, dtrace), true) + # Additional mapfiles that are only used when dtrace is enabled + ifeq ($(call check-jvm-feature, compiler2), true) + # This also covers the case of compiler1+compiler2. + SYMBOLS_SRC += $(HOTSPOT_TOPDIR)/makefiles/symbols/symbols-solaris-dtrace-compiler2 + else ifeq ($(call check-jvm-feature, compiler1), true) + SYMBOLS_SRC += $(HOTSPOT_TOPDIR)/makefiles/symbols/symbols-solaris-dtrace-compiler1 + endif + endif +endif + +################################################################################ +# Create a dynamic list of symbols from the built object files. This is highly +# platform dependent. + +ifeq ($(OPENJDK_TARGET_OS), linux) + DUMP_SYMBOLS_CMD := $(NM) --defined-only *.o + ifneq ($(FILTER_SYMBOLS_PATTERN), ) + FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)| + endif + FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)^_ZTV|^gHotSpotVM|^UseSharedSpaces$$ + FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)|^_ZN9Arguments17SharedArchivePathE$$ + FILTER_SYMBOLS_AWK_SCRIPT := \ + '{ \ + if ($$3 ~ /$(FILTER_SYMBOLS_PATTERN)/) print $$3; \ + }' + +else ifeq ($(OPENJDK_TARGET_OS), solaris) + DUMP_SYMBOLS_CMD := $(NM) -p *.o + ifneq ($(FILTER_SYMBOLS_PATTERN), ) + FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)| + endif + FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)^__1c.*__vtbl_$$|^gHotSpotVM + FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)|^UseSharedSpaces$$ + FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)|^__1cJArgumentsRSharedArchivePath_$$ + FILTER_SYMBOLS_AWK_SCRIPT := \ + '{ \ + if ($$2 == "U") next; \ + if ($$3 ~ /$(FILTER_SYMBOLS_PATTERN)/) print $$3; \ + }' + +else ifeq ($(OPENJDK_TARGET_OS), macosx) + # nm on macosx prints out "warning: nm: no name list" to stderr for + # files without symbols. Hide this, even at the expense of hiding real errors. + DUMP_SYMBOLS_CMD := $(NM) -Uj *.o 2> /dev/null + ifneq ($(FILTER_SYMBOLS_PATTERN), ) + FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)| + endif + FILTER_SYMBOLS_PATTERN := $(FILTER_SYMBOLS_PATTERN)^_ZTV|^gHotSpotVM + FILTER_SYMBOLS_AWK_SCRIPT := \ + '{ \ + if ($$3 ~ /$(FILTER_SYMBOLS_PATTERN)/) print $$3; \ + }' + +# NOTE: The script is from the old build. It is broken and finds no symbols. +# The script below might be what was intended, but it failes to link with tons +# of 'cannot export hidden symbol vtable for X'. +# '{ if ($$1 ~ /^__ZTV/ || $$1 ~ /^_gHotSpotVM/) print substr($$1, 2) }' +else ifeq ($(OPENJDK_TARGET_OS), aix) + # NOTE: The old build had the solution below. This should to be fixed in + # configure instead. + + # On AIX we have to prevent that we pick up the 'nm' version from the GNU binutils + # which may be installed under /opt/freeware/bin. So better use an absolute path here! + # NM=/usr/bin/nm + + DUMP_SYMBOLS_CMD := $(NM) -X64 -B -C *.o + FILTER_SYMBOLS_AWK_SCRIPT := \ + '{ \ + if (($$2="d" || $$2="D") && ($$3 ~ /^__vft/ || $$3 ~ /^gHotSpotVM/)) print $$3; \ + if ($$3 ~ /^UseSharedSpaces$$/) print $$3; \ + if ($$3 ~ /^SharedArchivePath__9Arguments$$/) print $$3; \ + }' + +else ifeq ($(OPENJDK_TARGET_OS), windows) + DUMP_SYMBOLS_CMD := $(DUMPBIN) -symbols *.obj + FILTER_SYMBOLS_AWK_SCRIPT := \ + '{ \ + if ($$7 ~ /??_7.*@@6B@/ && $$7 !~ /type_info/) print $$7; \ + }' + +else + $(error Unknown target OS $(OPENJDK_TARGET_OS) in JvmMapfile.gmk) +endif + +# A more correct solution would be to send BUILD_LIBJVM_ALL_OBJS instead of +# cd && *.o, but this will result in very long command lines, which is +# problematic on some platforms. +$(JVM_OUTPUTDIR)/symbols-objects: $(BUILD_LIBJVM_ALL_OBJS) + $(call LogInfo, Generating symbol list from object files) + $(CD) $(JVM_OUTPUTDIR)/objs && \ + $(DUMP_SYMBOLS_CMD) | $(NAWK) $(FILTER_SYMBOLS_AWK_SCRIPT) | $(SORT) -u > $@ + +SYMBOLS_SRC += $(JVM_OUTPUTDIR)/symbols-objects + +################################################################################ +# Now concatenate all symbol lists into a single file and remove comments. + +$(JVM_OUTPUTDIR)/symbols: $(SYMBOLS_SRC) + $(SED) -e '/^#/d' $^ > $@ + +################################################################################ +# Finally convert the symbol list into a platform-specific mapfile + +$(JVM_MAPFILE): $(JVM_OUTPUTDIR)/symbols + $(call LogInfo, Creating mapfile) + $(RM) $@ + ifeq ($(OPENJDK_TARGET_OS), macosx) + # On macosx, we need to add a leading underscore + $(AWK) '{ if ($$0 ~ ".") { print " _" $$0 } }' < $^ > $@.tmp + else ifeq ($(OPENJDK_TARGET_OS), windows) + # On windows, add an 'EXPORTS' header + $(ECHO) "EXPORTS" > $@.tmp + $(AWK) '{ if ($$0 ~ ".") { print " " $$0 } }' < $^ >> $@.tmp + else + # Assume standard linker script + $(PRINTF) "SUNWprivate_1.1 { \n global: \n" > $@.tmp + $(AWK) '{ if ($$0 ~ ".") { print " " $$0 ";" } }' < $^ >> $@.tmp + $(PRINTF) " local: \n *; \n }; \n" >> $@.tmp + endif + $(MV) $@.tmp $@ diff --git a/hotspot/makefiles/lib/JvmOverrideFiles.gmk b/hotspot/makefiles/lib/JvmOverrideFiles.gmk new file mode 100644 index 0000000000000000000000000000000000000000..1ffcb7455ce701c6feea02af1e93d0abd7b2b20c --- /dev/null +++ b/hotspot/makefiles/lib/JvmOverrideFiles.gmk @@ -0,0 +1,168 @@ +# +# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# 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. +# + +$(eval $(call IncludeCustomExtension, hotspot, lib/JvmOverrideFiles.gmk)) + +################################################################################ +# This file contains explicit overrides of CFLAGS and/or precompiled header +# status for individual files on specific platforms. + +ifeq ($(TOOLCHAIN_TYPE), gcc) + BUILD_LIBJVM_vmStructs.cpp_CXXFLAGS := -fno-var-tracking-assignments -O0 +endif + +ifeq ($(OPENJDK_TARGET_OS), linux) + BUILD_LIBJVM_ostream.cpp_CXXFLAGS := -D_FILE_OFFSET_BITS=64 + + ifeq ($(OPENJDK_TARGET_CPU_ARCH), x86) + BUILD_LIBJVM_sharedRuntimeTrig.cpp_CXXFLAGS := -DNO_PCH $(CXX_O_FLAG_NONE) + BUILD_LIBJVM_sharedRuntimeTrans.cpp_CXXFLAGS := -DNO_PCH $(CXX_O_FLAG_NONE) + + ifeq ($(TOOLCHAIN_TYPE), clang) + JVM_PRECOMPILED_HEADER_EXCLUDE := \ + sharedRuntimeTrig.cpp \ + sharedRuntimeTrans.cpp \ + # + endif + endif + + ifeq ($(OPENJDK_TARGET_CPU), x86) + # Performance measurements show that by compiling GC related code, we could + # significantly reduce the GC pause time on 32 bit Linux/Unix platforms by + # compiling without the PIC flag (-fPIC on linux). + # See 6454213 for more details. + ALL_SRC := $(filter %.cpp, $(call CacheFind, $(HOTSPOT_TOPDIR)/src/share/vm)) + NONPIC_FILTER := $(addsuffix %, $(addprefix $(HOTSPOT_TOPDIR)/src/share/vm/, \ + memory oops gc)) + # Due to what looks like a bug in the old build implementation of this, add a + # couple of more files that were accidentally matched as substrings of GC related + # files. + NONPIC_SRC := $(filter $(NONPIC_FILTER), $(ALL_SRC)) globals.cpp location.cpp + # Declare variables for each source file that needs the pic flag like this: + # BUILD_JVM__CXXFLAGS := -fno-PIC + # This will get implicitly picked up by SetupNativeCompilation below. + $(foreach s, $(NONPIC_SRC), $(eval BUILD_LIBJVM_$(notdir $s)_CXXFLAGS := -fno-PIC)) + endif + +else ifeq ($(OPENJDK_TARGET_OS), solaris) + ifneq ($(DEBUG_LEVEL), slowdebug) + # Workaround for a bug in dtrace. If ciEnv::post_compiled_method_load_event() + # is inlined, the resulting dtrace object file needs a reference to this + # function, whose symbol name is too long for dtrace. So disable inlining + # for this method for now. (fix this when dtrace bug 6258412 is fixed) + BUILD_LIBJVM_ciEnv.cpp_CXXFLAGS := \ + -xinline=no%__1cFciEnvbFpost_compiled_method_load_event6MpnHnmethod__v_ + # dtrace cannot handle tail call optimization (6672627, 6693876) + BUILD_LIBJVM_jni.cpp_CXXFLAGS := -Qoption ube -O~yz + BUILD_LIBJVM_stubGenerator_$(HOTSPOT_TARGET_CPU).cpp_CXXFLAGS := -xspace + + ifeq ($(OPENJDK_TARGET_CPU), x86_64) + # Temporary until SS10 C++ compiler is fixed + BUILD_LIBJVM_generateOptoStub.cpp_CXXFLAGS := -xO2 + # Temporary util SS12u1 C++ compiler is fixed + BUILD_LIBJVM_c1_LinearScan.cpp_CXXFLAGS := -xO2 + endif + endif + + # Need extra inlining to get oop_ps_push_contents functions to perform well enough. + ifeq ($(DEBUG_LEVEL),release) + BUILD_LIBJVM_psPromotionManager.cpp_CXXFLAGS := -W2,-Ainline:inc=1000 + endif + + ifeq ($(DEBUG_LEVEL), fastdebug) + # this hangs in iropt now (7113504) + BUILD_LIBJVM_compileBroker.cpp_CXXFLAGS := -xO2 + + # Frame size > 100k if we allow inlining via -g0! + BUILD_LIBJVM_bytecodeInterpreter.cpp_CXXFLAGS := +d + BUILD_LIBJVM_bytecodeInterpreterWithChecks.cpp_CXXFLAGS := +d + + ifeq ($(OPENJDK_TARGET_CPU_ARCH), x86) + # ube explodes on x86 + BUILD_LIBJVM_bytecodeInterpreter.cpp_CXXFLAGS += -xO1 + BUILD_LIBJVM_bytecodeInterpreterWithChecks.cpp_CXXFLAGS += -xO1 + endif + + endif + +else ifeq ($(OPENJDK_TARGET_OS), macosx) + # The copied fdlibm routines in these files must not be optimized + BUILD_LIBJVM_sharedRuntimeTrans.cpp_CXXFLAGS := $(CXX_O_FLAG_NONE) + BUILD_LIBJVM_sharedRuntimeTrig.cpp_CXXFLAGS := $(CXX_O_FLAG_NONE) + ifeq ($(TOOLCHAIN_TYPE), clang) + # NOTE: The old build tested clang version to make sure this workaround + # for the clang bug was still needed. + BUILD_LIBJVM_loopTransform.cpp_CXXFLAGS := $(CXX_O_FLAG_NONE) + ifneq ($(DEBUG_LEVEL), slowdebug) + BUILD_LIBJVM_unsafe.cpp_CXXFLAGS := -O1 + endif + + # The following files are compiled at various optimization + # levels due to optimization issues encountered at the + # default level. The Clang compiler issues a compile + # time error if there is an optimization level specification + # skew between the PCH file and the C++ file. Especially if the + # PCH file is compiled at a higher optimization level than + # the C++ file. One solution might be to prepare extra optimization + # level specific PCH files for the opt build and use them here, but + # it's probably not worth the effort as long as only a few files + # need this special handling. + JVM_PRECOMPILED_HEADER_EXCLUDE := \ + sharedRuntimeTrig.cpp \ + sharedRuntimeTrans.cpp \ + loopTransform.cpp \ + unsafe.cpp \ + jvmciCompilerToVM.cpp \ + # + endif + +else ifeq ($(OPENJDK_TARGET_OS), aix) + BUILD_LIBJVM_synchronizer.cpp_CXXFLAGS := -qnoinline + BUILD_LIBJVM_sharedRuntimeTrans.cpp_CXXFLAGS := $(CXX_O_FLAG_NONE) + # Disable aggressive optimizations for functions in sharedRuntimeTrig.cpp + # and sharedRuntimeTrans.cpp on ppc64. + # -qstrict turns off the following optimizations: + # * Performing code motion and scheduling on computations such as loads + # and floating-point computations that may trigger an exception. + # * Relaxing conformance to IEEE rules. + # * Reassociating floating-point expressions. + # When using '-qstrict' there still remains one problem + # in javasoft.sqe.tests.api.java.lang.Math.sin5Tests when run in compile-all + # mode, so don't optimize sharedRuntimeTrig.cpp at all. + BUILD_LIBJVM_sharedRuntimeTrig.cpp_CXXFLAGS := $(CXX_O_FLAG_NONE) + + # Disable ELF decoder on AIX (AIX uses XCOFF). + JVM_EXCLUDE_PATTERNS += elf + +else ifeq ($(OPENJDK_TARGET_OS), windows) + JVM_PRECOMPILED_HEADER_EXCLUDE := \ + bytecodeInterpreter.cpp \ + bytecodeInterpreterWithChecks.cpp \ + opcodes.cpp \ + os_windows.cpp \ + os_windows_x86.cpp \ + osThread_windows.cpp \ + # +endif diff --git a/hotspot/makefiles/mapfiles/libjsig/mapfile-vers-solaris b/hotspot/makefiles/mapfiles/libjsig/mapfile-vers-solaris new file mode 100644 index 0000000000000000000000000000000000000000..ddb46c050ec8d18220d35bceb9125d43f7fea3c3 --- /dev/null +++ b/hotspot/makefiles/mapfiles/libjsig/mapfile-vers-solaris @@ -0,0 +1,38 @@ +# +# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# + +# Define library interface. + +SUNWprivate_1.1 { + global: + JVM_begin_signal_setting; + JVM_end_signal_setting; + JVM_get_libjsig_version; + JVM_get_signal_action; + sigaction; + signal; + sigset; + local: + *; +}; diff --git a/hotspot/makefiles/mapfiles/libjvm_db/mapfile-vers b/hotspot/makefiles/mapfiles/libjvm_db/mapfile-vers new file mode 100644 index 0000000000000000000000000000000000000000..9ee418d01a258eb0b10a2a9e42227c3a2ec81cbd --- /dev/null +++ b/hotspot/makefiles/mapfiles/libjvm_db/mapfile-vers @@ -0,0 +1,38 @@ +# + +# +# Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. +# 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. +# +# + +# Define library interface. + +SUNWprivate_1.1 { + global: + Jagent_create; + Jagent_destroy; + Jframe_iter; + #Jget_vframe; + #Jlookup_by_regs; + local: + *; +}; diff --git a/hotspot/makefiles/mapfiles/libjvm_dtrace/mapfile-vers b/hotspot/makefiles/mapfiles/libjvm_dtrace/mapfile-vers new file mode 100644 index 0000000000000000000000000000000000000000..f9aaa19ba9d592e195cdb5c8c8053f32ce120d74 --- /dev/null +++ b/hotspot/makefiles/mapfiles/libjvm_dtrace/mapfile-vers @@ -0,0 +1,37 @@ +# + +# +# Copyright (c) 2006, 2008, Oracle and/or its affiliates. All rights reserved. +# 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. +# +# + +# Define library interface for JVM-DTrace interface + +SUNWprivate_1.1 { + global: + jvm_attach; + jvm_get_last_error; + jvm_enable_dtprobes; + jvm_detach; + local: + *; +}; diff --git a/hotspot/makefiles/symbols/symbols-aix b/hotspot/makefiles/symbols/symbols-aix new file mode 100644 index 0000000000000000000000000000000000000000..0efd2dba97f21609342e4695864be82f26cf3602 --- /dev/null +++ b/hotspot/makefiles/symbols/symbols-aix @@ -0,0 +1,27 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# 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. +# + +JVM_handle_linux_signal +numa_error +numa_warn +sysThreadAvailableStackWithSlack diff --git a/hotspot/makefiles/symbols/symbols-aix-debug b/hotspot/makefiles/symbols/symbols-aix-debug new file mode 100644 index 0000000000000000000000000000000000000000..10887ab2b61fbd3272b23b1dc5c9d97ffbeee354 --- /dev/null +++ b/hotspot/makefiles/symbols/symbols-aix-debug @@ -0,0 +1,26 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# 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. +# + +JVM_AccessVMBooleanFlag +JVM_AccessVMIntFlag +JVM_VMBreakPoint diff --git a/hotspot/makefiles/symbols/symbols-linux b/hotspot/makefiles/symbols/symbols-linux new file mode 100644 index 0000000000000000000000000000000000000000..0efd2dba97f21609342e4695864be82f26cf3602 --- /dev/null +++ b/hotspot/makefiles/symbols/symbols-linux @@ -0,0 +1,27 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# 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. +# + +JVM_handle_linux_signal +numa_error +numa_warn +sysThreadAvailableStackWithSlack diff --git a/hotspot/makefiles/symbols/symbols-macosx b/hotspot/makefiles/symbols/symbols-macosx new file mode 100644 index 0000000000000000000000000000000000000000..d0243562b67f9d2806ae3737934dc22334cfea95 --- /dev/null +++ b/hotspot/makefiles/symbols/symbols-macosx @@ -0,0 +1,24 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# 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. +# + +JVM_handle_bsd_signal diff --git a/hotspot/makefiles/symbols/symbols-shared b/hotspot/makefiles/symbols/symbols-shared new file mode 100644 index 0000000000000000000000000000000000000000..5d26d1028c723e890d3699049d3869aab5b8ab6b --- /dev/null +++ b/hotspot/makefiles/symbols/symbols-shared @@ -0,0 +1,35 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# 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. +# + +AsyncGetCallTrace +jio_fprintf +jio_printf +jio_snprintf +jio_vfprintf +jio_vsnprintf +JNI_CreateJavaVM +JNI_GetCreatedJavaVMs +JNI_GetDefaultJavaVMInitArgs +JVM_FindClassFromBootLoader +JVM_GetVersionInfo +JVM_InitAgentProperties diff --git a/hotspot/makefiles/symbols/symbols-solaris b/hotspot/makefiles/symbols/symbols-solaris new file mode 100644 index 0000000000000000000000000000000000000000..bc6124f83a30c9ca8bcdc52e370331fd8d4969ea --- /dev/null +++ b/hotspot/makefiles/symbols/symbols-solaris @@ -0,0 +1,25 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# 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. +# + +JVM_handle_solaris_signal +sysThreadAvailableStackWithSlack diff --git a/hotspot/makefiles/symbols/symbols-solaris-dtrace-compiler1 b/hotspot/makefiles/symbols/symbols-solaris-dtrace-compiler1 new file mode 100644 index 0000000000000000000000000000000000000000..4ce7d8e30b2b4147eea509fdf55099043683b7c2 --- /dev/null +++ b/hotspot/makefiles/symbols/symbols-solaris-dtrace-compiler1 @@ -0,0 +1,34 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# 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. +# + +__1cGMethodG__vtbl_ +__1cHnmethodG__vtbl_ +__1cICodeBlobG__vtbl_ +__1cIUniverseO_collectedHeap_ +__1cJCodeCacheG_heaps_ +__1cKBufferBlobG__vtbl_ +__1cLRuntimeStubG__vtbl_ +__1cNSafepointBlobG__vtbl_ +__1cSDeoptimizationBlobG__vtbl_ + +__JvmOffsets diff --git a/hotspot/makefiles/symbols/symbols-solaris-dtrace-compiler2 b/hotspot/makefiles/symbols/symbols-solaris-dtrace-compiler2 new file mode 100644 index 0000000000000000000000000000000000000000..306345e5c290fa890dedd2815a8258423d9a0ef4 --- /dev/null +++ b/hotspot/makefiles/symbols/symbols-solaris-dtrace-compiler2 @@ -0,0 +1,36 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# 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. +# + +__1cGMethodG__vtbl_ +__1cHnmethodG__vtbl_ +__1cICodeBlobG__vtbl_ +__1cIUniverseO_collectedHeap_ +__1cJCodeCacheG_heaps_ +__1cKBufferBlobG__vtbl_ +__1cLRuntimeStubG__vtbl_ +__1cNSafepointBlobG__vtbl_ +__1cSDeoptimizationBlobG__vtbl_ +__1cNExceptionBlobG__vtbl_ +__1cQUncommonTrapBlobG__vtbl_ + +__JvmOffsets diff --git a/hotspot/makefiles/symbols/symbols-unix b/hotspot/makefiles/symbols/symbols-unix new file mode 100644 index 0000000000000000000000000000000000000000..406d6f99db3673ff07c782cdf5f38cd555873ba2 --- /dev/null +++ b/hotspot/makefiles/symbols/symbols-unix @@ -0,0 +1,194 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# 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. +# + +JVM_ActiveProcessorCount +JVM_ArrayCopy +JVM_AssertionStatusDirectives +JVM_CallStackWalk +JVM_ClassDepth +JVM_ClassLoaderDepth +JVM_Clone +JVM_ConstantPoolGetClassAt +JVM_ConstantPoolGetClassAtIfLoaded +JVM_ConstantPoolGetClassRefIndexAt +JVM_ConstantPoolGetDoubleAt +JVM_ConstantPoolGetFieldAt +JVM_ConstantPoolGetFieldAtIfLoaded +JVM_ConstantPoolGetFloatAt +JVM_ConstantPoolGetIntAt +JVM_ConstantPoolGetLongAt +JVM_ConstantPoolGetMemberRefInfoAt +JVM_ConstantPoolGetMethodAt +JVM_ConstantPoolGetMethodAtIfLoaded +JVM_ConstantPoolGetNameAndTypeRefIndexAt +JVM_ConstantPoolGetNameAndTypeRefInfoAt +JVM_ConstantPoolGetSize +JVM_ConstantPoolGetStringAt +JVM_ConstantPoolGetTagAt +JVM_ConstantPoolGetUTF8At +JVM_CountStackFrames +JVM_CurrentClassLoader +JVM_CurrentLoadedClass +JVM_CurrentThread +JVM_CurrentTimeMillis +JVM_DefineClass +JVM_DefineClassWithSource +JVM_DesiredAssertionStatus +JVM_DoPrivileged +JVM_DumpAllStacks +JVM_DumpThreads +JVM_FillInStackTrace +JVM_FindClassFromCaller +JVM_FindClassFromClass +JVM_FindLibraryEntry +JVM_FindLoadedClass +JVM_FindPrimitiveClass +JVM_FindSignal +JVM_FreeMemory +JVM_GC +JVM_GetAllThreads +JVM_GetArrayElement +JVM_GetArrayLength +JVM_GetCallerClass +JVM_GetClassAccessFlags +JVM_GetClassAnnotations +JVM_GetClassConstantPool +JVM_GetClassContext +JVM_GetClassCPEntriesCount +JVM_GetClassCPTypes +JVM_GetClassDeclaredConstructors +JVM_GetClassDeclaredFields +JVM_GetClassDeclaredMethods +JVM_GetClassFieldsCount +JVM_GetClassInterfaces +JVM_GetClassMethodsCount +JVM_GetClassModifiers +JVM_GetClassName +JVM_GetClassNameUTF +JVM_GetClassSignature +JVM_GetClassSigners +JVM_GetClassTypeAnnotations +JVM_GetCPClassNameUTF +JVM_GetCPFieldClassNameUTF +JVM_GetCPFieldModifiers +JVM_GetCPFieldNameUTF +JVM_GetCPFieldSignatureUTF +JVM_GetCPMethodClassNameUTF +JVM_GetCPMethodModifiers +JVM_GetCPMethodNameUTF +JVM_GetCPMethodSignatureUTF +JVM_GetDeclaredClasses +JVM_GetDeclaringClass +JVM_GetEnclosingMethodInfo +JVM_GetFieldIxModifiers +JVM_GetFieldTypeAnnotations +JVM_GetInheritedAccessControlContext +JVM_GetInterfaceVersion +JVM_GetManagement +JVM_GetMethodIxArgsSize +JVM_GetMethodIxByteCode +JVM_GetMethodIxByteCodeLength +JVM_GetMethodIxExceptionIndexes +JVM_GetMethodIxExceptionsCount +JVM_GetMethodIxExceptionTableEntry +JVM_GetMethodIxExceptionTableLength +JVM_GetMethodIxLocalsCount +JVM_GetMethodIxMaxStack +JVM_GetMethodIxModifiers +JVM_GetMethodIxNameUTF +JVM_GetMethodIxSignatureUTF +JVM_GetMethodParameters +JVM_GetMethodTypeAnnotations +JVM_GetNanoTimeAdjustment +JVM_GetPrimitiveArrayElement +JVM_GetProtectionDomain +JVM_GetSimpleBinaryName +JVM_GetStackAccessControlContext +JVM_GetStackTraceElements +JVM_GetSystemPackage +JVM_GetSystemPackages +JVM_GetTemporaryDirectory +JVM_GetVmArguments +JVM_Halt +JVM_HoldsLock +JVM_IHashCode +JVM_InitProperties +JVM_InternString +JVM_Interrupt +JVM_InvokeMethod +JVM_IsArrayClass +JVM_IsConstructorIx +JVM_IsInterface +JVM_IsInterrupted +JVM_IsPrimitiveClass +JVM_IsSameClassPackage +JVM_IsSupportedJNIVersion +JVM_IsThreadAlive +JVM_IsVMGeneratedMethodIx +JVM_LatestUserDefinedLoader +JVM_LoadLibrary +JVM_MaxMemory +JVM_MaxObjectInspectionAge +JVM_MonitorNotify +JVM_MonitorNotifyAll +JVM_MonitorWait +JVM_MoreStackWalk +JVM_NanoTime +JVM_NativePath +JVM_NewArray +JVM_NewInstanceFromConstructor +JVM_NewMultiArray +JVM_RaiseSignal +JVM_RawMonitorCreate +JVM_RawMonitorDestroy +JVM_RawMonitorEnter +JVM_RawMonitorExit +JVM_RegisterSignal +JVM_ReleaseUTF +JVM_ResumeThread +JVM_SetArrayElement +JVM_SetClassSigners +JVM_SetNativeThreadName +JVM_SetPrimitiveArrayElement +JVM_SetThreadPriority +JVM_Sleep +JVM_StartThread +JVM_StopThread +JVM_SupportsCX8 +JVM_SuspendThread +JVM_ToStackTraceElement +JVM_TotalMemory +JVM_UnloadLibrary +JVM_Yield + +# Module related API's +JVM_AddModuleExports +JVM_AddModuleExportsToAll +JVM_AddModuleExportsToAllUnnamed +JVM_AddModulePackage +JVM_AddReadsModule +JVM_CanReadModule +JVM_DefineModule +JVM_IsExportedToModule +JVM_SetBootLoaderUnnamedModule +JVM_GetModuleByPackageName diff --git a/hotspot/src/cpu/aarch64/vm/debug_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/debug_aarch64.cpp index 107f6085474f5ff0c6c32d4c6499af310289f8e9..72fc4d7df63d6db28bf189e0c6937b3dda21f0c5 100644 --- a/hotspot/src/cpu/aarch64/vm/debug_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/debug_aarch64.cpp @@ -30,6 +30,5 @@ #include "runtime/init.hpp" #include "runtime/os.hpp" #include "utilities/debug.hpp" -#include "utilities/top.hpp" void pd_ps(frame f) {} diff --git a/hotspot/src/cpu/aarch64/vm/frame_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/frame_aarch64.hpp index d267036974ee69a2b19cea6ec3820330ea1e95e5..4332abce9f43d664f64d8a8e230af2dea93889d0 100644 --- a/hotspot/src/cpu/aarch64/vm/frame_aarch64.hpp +++ b/hotspot/src/cpu/aarch64/vm/frame_aarch64.hpp @@ -27,7 +27,6 @@ #define CPU_AARCH64_VM_FRAME_AARCH64_HPP #include "runtime/synchronizer.hpp" -#include "utilities/top.hpp" // A frame represents a physical stack frame (an activation). Frames can be // C or Java frames, and the Java frames can be interpreted or compiled. diff --git a/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp index d83017c1770792d68eef84df100c52283fdb3edb..a3a6d6a1302d33a3b2919d2f0a7f601a489a0df8 100644 --- a/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp +++ b/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp @@ -30,7 +30,6 @@ #include "memory/allocation.hpp" #include "runtime/icache.hpp" #include "runtime/os.hpp" -#include "utilities/top.hpp" // We have interfaces for the following instructions: // - NativeInstruction diff --git a/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp index 0aeba4cb33c79858a653554406d24f6fd7a81267..760256da3786acf626d3d22c63296455d35b0dd7 100644 --- a/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp @@ -198,6 +198,16 @@ void RegisterSaver::restore_result_registers(MacroAssembler* masm) { bool SharedRuntime::is_wide_vector(int size) { return size > 8; } + +size_t SharedRuntime::trampoline_size() { + return 16; +} + +void SharedRuntime::generate_trampoline(MacroAssembler *masm, address destination) { + __ mov(rscratch1, destination); + __ br(rscratch1); +} + // The java_calling_convention describes stack locations as ideal slots on // a frame with no abi restrictions. Since we must observe abi restrictions // (like the placement of the register window) the slots must be biased by diff --git a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp index d618c0351f74a0ba1d377f9a79084d13ef6445b1..b0787ddf4a9a530d8f96a66bcff7cf9eefd5a70e 100644 --- a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp @@ -39,7 +39,6 @@ #include "runtime/stubCodeGenerator.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/thread.inline.hpp" -#include "utilities/top.hpp" #ifdef COMPILER2 #include "opto/runtime.hpp" #endif diff --git a/hotspot/src/cpu/ppc/vm/c1_LIRGenerator_ppc.cpp b/hotspot/src/cpu/ppc/vm/c1_LIRGenerator_ppc.cpp index cba04106f8cfb049b4b96c2d4267c6ce7a5ff9e2..0d1cb4711bde93cb8d0855ee647eba404690487e 100644 --- a/hotspot/src/cpu/ppc/vm/c1_LIRGenerator_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/c1_LIRGenerator_ppc.cpp @@ -360,7 +360,7 @@ void LIRGenerator::do_StoreIndexed(StoreIndexed* x) { length.set_instruction(x->length()); length.load_item(); } - if (needs_store_check) { + if (needs_store_check || x->check_boolean()) { value.load_item(); } else { value.load_for_store(x->elt_type()); @@ -407,7 +407,8 @@ void LIRGenerator::do_StoreIndexed(StoreIndexed* x) { pre_barrier(LIR_OprFact::address(array_addr), LIR_OprFact::illegalOpr /* pre_val */, true /* do_load */, false /* patch */, NULL); } - __ move(value.result(), array_addr, null_check_info); + LIR_Opr result = maybe_mask_boolean(x, array.result(), value.result(), null_check_info); + __ move(result, array_addr, null_check_info); if (obj_store) { // Precise card mark. post_barrier(LIR_OprFact::address(array_addr), value.result()); diff --git a/hotspot/src/cpu/ppc/vm/debug_ppc.cpp b/hotspot/src/cpu/ppc/vm/debug_ppc.cpp index 5427a1e464426bed9d54a98633f6aa65d7b6b4ec..ff92dd4e50da1c8823413dfd83ecb50213de2d87 100644 --- a/hotspot/src/cpu/ppc/vm/debug_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/debug_ppc.cpp @@ -30,6 +30,5 @@ #include "runtime/init.hpp" #include "runtime/os.hpp" #include "utilities/debug.hpp" -#include "utilities/top.hpp" void pd_ps(frame f) {} diff --git a/hotspot/src/cpu/ppc/vm/frame_ppc.hpp b/hotspot/src/cpu/ppc/vm/frame_ppc.hpp index 8115a20640edda959307a9f9e1f8fc6223f58fb7..6f8f0296f83e5a1a265a693601644f2e673f5446 100644 --- a/hotspot/src/cpu/ppc/vm/frame_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/frame_ppc.hpp @@ -27,7 +27,6 @@ #define CPU_PPC_VM_FRAME_PPC_HPP #include "runtime/synchronizer.hpp" -#include "utilities/top.hpp" // C frame layout on PPC-64. // diff --git a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp index 9c7128da0b4f3925fb6daf76c3e2048e8f4118a6..cedc1e08c1ce3928314a1c488e88f396b8eb5fc4 100644 --- a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp +++ b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp @@ -169,6 +169,7 @@ void InterpreterMacroAssembler::load_earlyret_value(TosState state, Register Rsc case ltos: ld(R17_tos, in_bytes(JvmtiThreadState::earlyret_value_offset()), RjvmtiState); break; case btos: // fall through + case ztos: // fall through case ctos: // fall through case stos: // fall through case itos: lwz(R17_tos, in_bytes(JvmtiThreadState::earlyret_value_offset()), RjvmtiState); @@ -294,6 +295,7 @@ void InterpreterMacroAssembler::push(TosState state) { switch (state) { case atos: push_ptr(); break; case btos: + case ztos: case ctos: case stos: case itos: push_i(); break; @@ -309,6 +311,7 @@ void InterpreterMacroAssembler::pop(TosState state) { switch (state) { case atos: pop_ptr(); break; case btos: + case ztos: case ctos: case stos: case itos: pop_i(); break; @@ -749,6 +752,43 @@ void InterpreterMacroAssembler::merge_frames(Register Rsender_sp, Register retur stdux(Rscratch2, R1_SP, Rscratch1); // atomically set *(SP = top_frame_sp) = **SP } +void InterpreterMacroAssembler::narrow(Register result) { + Register ret_type = R11_scratch1; + ld(R11_scratch1, in_bytes(Method::const_offset()), R19_method); + lbz(ret_type, in_bytes(ConstMethod::result_type_offset()), R11_scratch1); + + Label notBool, notByte, notChar, done; + + // common case first + cmpwi(CCR0, ret_type, T_INT); + beq(CCR0, done); + + cmpwi(CCR0, ret_type, T_BOOLEAN); + bne(CCR0, notBool); + andi(result, result, 0x1); + b(done); + + bind(notBool); + cmpwi(CCR0, ret_type, T_BYTE); + bne(CCR0, notByte); + extsb(result, result); + b(done); + + bind(notByte); + cmpwi(CCR0, ret_type, T_CHAR); + bne(CCR0, notChar); + andi(result, result, 0xffff); + b(done); + + bind(notChar); + // cmpwi(CCR0, ret_type, T_SHORT); // all that's left + // bne(CCR0, done); + extsh(result, result); + + // Nothing to do for T_INT + bind(done); +} + // Remove activation. // // Unlock the receiver if this is a synchronized method. diff --git a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp index 8a75af011bdd5c6f28d5b4a83be7325cec88e31d..05bd3aa0bddd286467183f664fc295407ba7076b 100644 --- a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp +++ b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp @@ -140,6 +140,8 @@ class InterpreterMacroAssembler: public MacroAssembler { void get_cpool_and_tags(Register Rcpool, Register Rtags); void is_a(Label& L); + void narrow(Register result); + // Java Call Helpers void call_from_interpreter(Register Rtarget_method, Register Rret_addr, Register Rscratch1, Register Rscratch2); diff --git a/hotspot/src/cpu/ppc/vm/nativeInst_ppc.hpp b/hotspot/src/cpu/ppc/vm/nativeInst_ppc.hpp index 586dcaa93805915c115b1dff5f7d739ed72e79c2..99aa11c4b20343792d37a2aba8e889c8e501598c 100644 --- a/hotspot/src/cpu/ppc/vm/nativeInst_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/nativeInst_ppc.hpp @@ -31,7 +31,6 @@ #include "memory/allocation.hpp" #include "runtime/icache.hpp" #include "runtime/os.hpp" -#include "utilities/top.hpp" // We have interfaces for the following instructions: // diff --git a/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp b/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp index 49df282945dbd4dd93e4d538e4cf566a9f8305fe..ee8685f4f0a72579b3fdb1860492821e1b65d394 100644 --- a/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp @@ -483,6 +483,18 @@ bool SharedRuntime::is_wide_vector(int size) { assert(size <= 8, "%d bytes vectors are not supported", size); return size > 8; } + +size_t SharedRuntime::trampoline_size() { + return Assembler::load_const_size + 8; +} + +void SharedRuntime::generate_trampoline(MacroAssembler *masm, address destination) { + Register Rtemp = R12; + __ load_const(Rtemp, destination); + __ mtctr(Rtemp); + __ bctr(); +} + #ifdef COMPILER2 static int reg2slot(VMReg r) { return r->reg2stack() + SharedRuntime::out_preserve_stack_slots(); diff --git a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp index 0f6c6f77fdb0bdf4065746295010f8b1b5a21717..2eba3edacefbba5b7d9e10ab2c84ec92fc3af863 100644 --- a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp @@ -37,7 +37,6 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/stubCodeGenerator.hpp" #include "runtime/stubRoutines.hpp" -#include "utilities/top.hpp" #include "runtime/thread.inline.hpp" #define __ _masm-> diff --git a/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp b/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp index 8979e213acf8df6ae78932db49a80f64d14af1f9..3602c646192b694ad6b8e783d0c3e46c9a902ab9 100644 --- a/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp @@ -655,6 +655,7 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, switch (state) { case ltos: case btos: + case ztos: case ctos: case stos: case atos: @@ -701,6 +702,7 @@ address TemplateInterpreterGenerator::generate_deopt_entry_for(TosState state, i switch (state) { case ltos: case btos: + case ztos: case ctos: case stos: case atos: @@ -2092,12 +2094,14 @@ address TemplateInterpreterGenerator::generate_earlyret_entry_for(TosState state // Copied from TemplateTable::_return. // Restoration of lr done by remove_activation. switch (state) { + // Narrow result if state is itos but result type is smaller. + case itos: __ narrow(R17_tos); /* fall through */ case ltos: case btos: + case ztos: case ctos: case stos: - case atos: - case itos: __ mr(R3_RET, R17_tos); break; + case atos: __ mr(R3_RET, R17_tos); break; case ftos: case dtos: __ fmr(F1_RET, F15_ftos); break; case vtos: // This might be a constructor. Final fields (and volatile fields on PPC64) need @@ -2157,6 +2161,10 @@ address TemplateInterpreterGenerator::generate_trace_code(TosState state) { bname = "trace_code_btos {"; tsize = 2; break; + case ztos: + bname = "trace_code_ztos {"; + tsize = 2; + break; case ctos: bname = "trace_code_ctos {"; tsize = 2; diff --git a/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp b/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp index c59e7b4b38b4cae459789aaa4735820cc60e4fe1..6b8f658ff09b48d42e3f630583a4c59a3613708f 100644 --- a/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp +++ b/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp @@ -170,6 +170,7 @@ void TemplateTable::patch_bytecode(Bytecodes::Code new_bc, Register Rnew_bc, Reg switch (new_bc) { case Bytecodes::_fast_aputfield: case Bytecodes::_fast_bputfield: + case Bytecodes::_fast_zputfield: case Bytecodes::_fast_cputfield: case Bytecodes::_fast_dputfield: case Bytecodes::_fast_fputfield: @@ -981,9 +982,21 @@ void TemplateTable::bastore() { Rarray = R12_scratch2, Rscratch = R3_ARG1; __ pop_i(Rindex); + __ pop_ptr(Rarray); // tos: val - // Rarray: array ptr (popped by index_check) - __ index_check(Rarray, Rindex, 0, Rscratch, Rarray); + + // Need to check whether array is boolean or byte + // since both types share the bastore bytecode. + __ load_klass(Rscratch, Rarray); + __ lwz(Rscratch, in_bytes(Klass::layout_helper_offset()), Rscratch); + int diffbit = exact_log2(Klass::layout_helper_boolean_diffbit()); + __ testbitdi(CCR0, R0, Rscratch, diffbit); + Label L_skip; + __ bfalse(CCR0, L_skip); + __ andi(R17_tos, R17_tos, 1); // if it is a T_BOOLEAN array, mask the stored value to 0/1 + __ bind(L_skip); + + __ index_check_without_pop(Rarray, Rindex, 0, Rscratch, Rarray); __ stb(R17_tos, arrayOopDesc::base_offset_in_bytes(T_BYTE), Rarray); } @@ -2108,12 +2121,16 @@ void TemplateTable::_return(TosState state) { __ remove_activation(state, /* throw_monitor_exception */ true); // Restoration of lr done by remove_activation. switch (state) { + // Narrow result if state is itos but result type is smaller. + // Need to narrow in the return bytecode rather than in generate_return_entry + // since compiled code callers expect the result to already be narrowed. + case itos: __ narrow(R17_tos); /* fall through */ case ltos: case btos: + case ztos: case ctos: case stos: - case atos: - case itos: __ mr(R3_RET, R17_tos); break; + case atos: __ mr(R3_RET, R17_tos); break; case ftos: case dtos: __ fmr(F1_RET, F15_ftos); break; case vtos: // This might be a constructor. Final fields (and volatile fields on PPC64) need @@ -2518,6 +2535,21 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr __ beq(CCR6, Lacquire); // Volatile? __ dispatch_epilog(vtos, Bytecodes::length_for(bytecode())); + __ align(32, 28, 28); // Align load. + // __ bind(Lztos); (same code as btos) + __ fence(); // Volatile entry point (one instruction before non-volatile_entry point). + assert(branch_table[ztos] == 0, "can't compute twice"); + branch_table[ztos] = __ pc(); // non-volatile_entry point + __ lbzx(R17_tos, Rclass_or_obj, Roffset); + __ extsb(R17_tos, R17_tos); + __ push(ztos); + if (!is_static) { + // use btos rewriting, no truncating to t/f bit is needed for getfield. + patch_bytecode(Bytecodes::_fast_bgetfield, Rbc, Rscratch); + } + __ beq(CCR6, Lacquire); // Volatile? + __ dispatch_epilog(vtos, Bytecodes::length_for(bytecode())); + __ align(32, 28, 28); // Align load. // __ bind(Lctos); __ fence(); // Volatile entry point (one instruction before non-volatile_entry point). @@ -2618,6 +2650,7 @@ void TemplateTable::jvmti_post_field_mod(Register Rcache, Register Rscratch, boo case Bytecodes::_fast_aputfield: __ push_ptr(); offs+= Interpreter::stackElementSize; break; case Bytecodes::_fast_iputfield: // Fall through case Bytecodes::_fast_bputfield: // Fall through + case Bytecodes::_fast_zputfield: // Fall through case Bytecodes::_fast_cputfield: // Fall through case Bytecodes::_fast_sputfield: __ push_i(); offs+= Interpreter::stackElementSize; break; case Bytecodes::_fast_lputfield: __ push_l(); offs+=2*Interpreter::stackElementSize; break; @@ -2658,6 +2691,7 @@ void TemplateTable::jvmti_post_field_mod(Register Rcache, Register Rscratch, boo case Bytecodes::_fast_aputfield: __ pop_ptr(); break; case Bytecodes::_fast_iputfield: // Fall through case Bytecodes::_fast_bputfield: // Fall through + case Bytecodes::_fast_zputfield: // Fall through case Bytecodes::_fast_cputfield: // Fall through case Bytecodes::_fast_sputfield: __ pop_i(); break; case Bytecodes::_fast_lputfield: __ pop_l(); break; @@ -2824,6 +2858,21 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteContr } __ dispatch_epilog(vtos, Bytecodes::length_for(bytecode())); + __ align(32, 28, 28); // Align pop. + // __ bind(Lztos); + __ release(); // Volatile entry point (one instruction before non-volatile_entry point). + assert(branch_table[ztos] == 0, "can't compute twice"); + branch_table[ztos] = __ pc(); // non-volatile_entry point + __ pop(ztos); + if (!is_static) { pop_and_check_object(Rclass_or_obj); } // Kills R11_scratch1. + __ andi(R17_tos, R17_tos, 0x1); + __ stbx(R17_tos, Rclass_or_obj, Roffset); + if (!is_static) { patch_bytecode(Bytecodes::_fast_zputfield, Rbc, Rscratch, true, byte_no); } + if (!support_IRIW_for_not_multiple_copy_atomic_cpu) { + __ beq(CR_is_vol, Lvolatile); // Volatile? + } + __ dispatch_epilog(vtos, Bytecodes::length_for(bytecode())); + __ align(32, 28, 28); // Align pop. // __ bind(Lctos); __ release(); // Volatile entry point (one instruction before non-volatile_entry point). @@ -2949,6 +2998,9 @@ void TemplateTable::fast_storefield(TosState state) { __ stdx(R17_tos, Rclass_or_obj, Roffset); break; + case Bytecodes::_fast_zputfield: + __ andi(R17_tos, R17_tos, 0x1); // boolean is true if LSB is 1 + // fall through to bputfield case Bytecodes::_fast_bputfield: __ stbx(R17_tos, Rclass_or_obj, Roffset); break; diff --git a/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp index 6185a1d59cdd20a51a55f37c573e8981bd58ecea..de568fd7693a570afdfecacd64a74b316912e0d1 100644 --- a/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp @@ -344,7 +344,7 @@ void LIRGenerator::do_StoreIndexed(StoreIndexed* x) { length.set_instruction(x->length()); length.load_item(); } - if (needs_store_check) { + if (needs_store_check || x->check_boolean()) { value.load_item(); } else { value.load_for_store(x->elt_type()); @@ -389,7 +389,8 @@ void LIRGenerator::do_StoreIndexed(StoreIndexed* x) { pre_barrier(LIR_OprFact::address(array_addr), LIR_OprFact::illegalOpr /* pre_val */, true /* do_load */, false /* patch */, NULL); } - __ move(value.result(), array_addr, null_check_info); + LIR_Opr result = maybe_mask_boolean(x, array.result(), value.result(), null_check_info); + __ move(result, array_addr, null_check_info); if (obj_store) { // Precise card mark post_barrier(LIR_OprFact::address(array_addr), value.result()); diff --git a/hotspot/src/cpu/sparc/vm/debug_sparc.cpp b/hotspot/src/cpu/sparc/vm/debug_sparc.cpp index 8be1072fc65022f30971564ce5356d578fe7c51b..9f3f40ada7c676c0b94ba401fe9f82691760f812 100644 --- a/hotspot/src/cpu/sparc/vm/debug_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/debug_sparc.cpp @@ -29,7 +29,6 @@ #include "runtime/init.hpp" #include "runtime/os.hpp" #include "utilities/debug.hpp" -#include "utilities/top.hpp" #ifndef PRODUCT diff --git a/hotspot/src/cpu/sparc/vm/frame_sparc.hpp b/hotspot/src/cpu/sparc/vm/frame_sparc.hpp index 5de8ad4bf1d750043d7812299bc087bf235a6e95..cd91f52fd17317358b81cd007cc8043b5bdebc0d 100644 --- a/hotspot/src/cpu/sparc/vm/frame_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/frame_sparc.hpp @@ -26,7 +26,6 @@ #define CPU_SPARC_VM_FRAME_SPARC_HPP #include "runtime/synchronizer.hpp" -#include "utilities/top.hpp" // A frame represents a physical stack frame (an activation). Frames can be // C or Java frames, and the Java frames can be interpreted or compiled. diff --git a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp index 4e0b6d504f68ea9b0ea65a0e3d67264fc8e0cf3e..580b1336bf36f23018b3294ae60ae3c5c98b600d 100644 --- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp @@ -208,6 +208,7 @@ void InterpreterMacroAssembler::load_earlyret_value(TosState state) { case atos: ld_ptr(oop_addr, Otos_l); st_ptr(G0, oop_addr); break; case btos: // fall through + case ztos: // fall through case ctos: // fall through case stos: // fall through case itos: ld(val_addr, Otos_l1); break; @@ -452,9 +453,10 @@ void InterpreterMacroAssembler::push(TosState state) { interp_verify_oop(Otos_i, state, __FILE__, __LINE__); switch (state) { case atos: push_ptr(); break; - case btos: push_i(); break; - case ctos: - case stos: push_i(); break; + case btos: // fall through + case ztos: // fall through + case ctos: // fall through + case stos: // fall through case itos: push_i(); break; case ltos: push_l(); break; case ftos: push_f(); break; @@ -468,9 +470,10 @@ void InterpreterMacroAssembler::push(TosState state) { void InterpreterMacroAssembler::pop(TosState state) { switch (state) { case atos: pop_ptr(); break; - case btos: pop_i(); break; - case ctos: - case stos: pop_i(); break; + case btos: // fall through + case ztos: // fall through + case ctos: // fall through + case stos: // fall through case itos: pop_i(); break; case ltos: pop_l(); break; case ftos: pop_f(); break; @@ -1103,6 +1106,49 @@ void InterpreterMacroAssembler::unlock_if_synchronized_method(TosState state, interp_verify_oop(Otos_i, state, __FILE__, __LINE__); } +void InterpreterMacroAssembler::narrow(Register result) { + + ld_ptr(Address(Lmethod, Method::const_offset()), G3_scratch); + ldub(G3_scratch, in_bytes(ConstMethod::result_type_offset()), G3_scratch); + + Label notBool, notByte, notChar, done; + + // common case first + cmp(G3_scratch, T_INT); + br(Assembler::equal, true, pn, done); + delayed()->nop(); + + cmp(G3_scratch, T_BOOLEAN); + br(Assembler::notEqual, true, pn, notBool); + delayed()->cmp(G3_scratch, T_BYTE); + and3(result, 1, result); + ba(done); + delayed()->nop(); + + bind(notBool); + // cmp(G3_scratch, T_BYTE); + br(Assembler::notEqual, true, pn, notByte); + delayed()->cmp(G3_scratch, T_CHAR); + sll(result, 24, result); + sra(result, 24, result); + ba(done); + delayed()->nop(); + + bind(notByte); + // cmp(G3_scratch, T_CHAR); + sll(result, 16, result); + br(Assembler::notEqual, true, pn, done); + delayed()->sra(result, 16, result); + // sll(result, 16, result); + srl(result, 16, result); + + // bind(notChar); + // must be short, instructions already executed in delay slot + // sll(result, 16, result); + // sra(result, 16, result); + + bind(done); +} // remove activation // @@ -1151,6 +1197,7 @@ void InterpreterMacroAssembler::remove_activation(TosState state, case ltos: mov(Otos_l2, Otos_l2->after_save()); // fall through // O1 -> I1 #endif case btos: // fall through + case ztos: // fall through case ctos: case stos: // fall through case atos: // fall through diff --git a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp index 4fa3b09b3a92ef73fe68b08aff2b6fb0fdab65a6..1baceb1233cd661e38f1ccbb1d13e9a5570c3b92 100644 --- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp @@ -103,6 +103,8 @@ class InterpreterMacroAssembler: public MacroAssembler { void dispatch_via (TosState state, address* table); + void narrow(Register result); + // Removes the current activation (incl. unlocking of monitors). // Additionally this code is used for earlyReturn in which case we // want to skip throwing an exception and installing an exception. diff --git a/hotspot/src/cpu/sparc/vm/metaspaceShared_sparc.cpp b/hotspot/src/cpu/sparc/vm/metaspaceShared_sparc.cpp index 28f606be3b0b8a5ed16961c857e411518e367094..cc0141c283e63f94a15d3ea15525f60767f89897 100644 --- a/hotspot/src/cpu/sparc/vm/metaspaceShared_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/metaspaceShared_sparc.cpp @@ -65,8 +65,6 @@ void MetaspaceShared::generate_vtable_methods(void** vtbl_list, *vtable = dummy_vtable; *md_top += vtable_bytes; - guarantee(*md_top <= md_end, "Insufficient space for vtables."); - // Get ready to generate dummy methods. CodeBuffer cb((unsigned char*)*mc_top, mc_end - *mc_top); diff --git a/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp index a5f04a8f5b9b2cbf0929dd684f9d43e5309e432a..d0582f34265406316a29b026b58cd32dadb6249a 100644 --- a/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp @@ -29,7 +29,6 @@ #include "memory/allocation.hpp" #include "runtime/icache.hpp" #include "runtime/os.hpp" -#include "utilities/top.hpp" // We have interface for the following instructions: // - NativeInstruction diff --git a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp index ab9fed0d5d1c23e7f2fe0f60c7f0cfad2304ed84..6727c14d63be47bf8fa49542b7be618347ac8ee2 100644 --- a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp @@ -324,6 +324,16 @@ bool SharedRuntime::is_wide_vector(int size) { return size > 8; } +size_t SharedRuntime::trampoline_size() { + return 40; +} + +void SharedRuntime::generate_trampoline(MacroAssembler *masm, address destination) { + __ set((intptr_t)destination, G3_scratch); + __ JMP(G3_scratch, 0); + __ delayed()->nop(); +} + // The java_calling_convention describes stack locations as ideal slots on // a frame with no abi restrictions. Since we must observe abi restrictions // (like the placement of the register window) the slots must be biased by diff --git a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp index 98d82ee07e5448acd1b481a499df1c2fed3d0ca0..db2c5eefac8c6117d8172701c22377a5d64ca9d2 100644 --- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp @@ -37,7 +37,6 @@ #include "runtime/stubCodeGenerator.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/thread.inline.hpp" -#include "utilities/top.hpp" #ifdef COMPILER2 #include "opto/runtime.hpp" #endif diff --git a/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp index 153bd2b23195483810dac677c71e879e482e8df0..008fcee7a6a70481519d7ac7187a7662ae3214e1 100644 --- a/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp @@ -616,7 +616,7 @@ void TemplateInterpreterGenerator::generate_stack_overflow_check(Register Rframe // compute the beginning of the protected zone minus the requested frame size __ sub( Rscratch, Rscratch2, Rscratch ); - __ set( JavaThread::stack_red_zone_size() + JavaThread::stack_yellow_zone_size(), Rscratch2 ); + __ set(MAX2(JavaThread::stack_shadow_zone_size(), JavaThread::stack_guard_zone_size()), Rscratch2 ); __ add( Rscratch, Rscratch2, Rscratch ); // Add in the size of the frame (which is the same as subtracting it from the diff --git a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp index 1315f7c8d6028daca464d395e32fe10568e354d7..2976383f7674faeb47c8bb96a3815b4b9a4ffdd0 100644 --- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp @@ -165,6 +165,7 @@ void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg, switch (bc) { case Bytecodes::_fast_aputfield: case Bytecodes::_fast_bputfield: + case Bytecodes::_fast_zputfield: case Bytecodes::_fast_cputfield: case Bytecodes::_fast_dputfield: case Bytecodes::_fast_fputfield: @@ -922,8 +923,20 @@ void TemplateTable::bastore() { transition(itos, vtos); __ pop_i(O2); // index // Otos_i: val + // O2: index // O3: array __ index_check(O3, O2, 0, G3_scratch, O2); + // Need to check whether array is boolean or byte + // since both types share the bastore bytecode. + __ load_klass(O3, G4_scratch); + __ ld(G4_scratch, in_bytes(Klass::layout_helper_offset()), G4_scratch); + __ set(Klass::layout_helper_boolean_diffbit(), G3_scratch); + __ andcc(G3_scratch, G4_scratch, G0); + Label L_skip; + __ br(Assembler::zero, false, Assembler::pn, L_skip); + __ delayed()->nop(); + __ and3(Otos_i, 1, Otos_i); // if it is a T_BOOLEAN array, mask the stored value to 0/1 + __ bind(L_skip); __ stb(Otos_i, O2, arrayOopDesc::base_offset_in_bytes(T_BYTE)); } @@ -2008,6 +2021,12 @@ void TemplateTable::_return(TosState state) { __ bind(skip_register_finalizer); } + // Narrow result if state is itos but result type is smaller. + // Need to narrow in the return bytecode rather than in generate_return_entry + // since compiled code callers expect the result to already be narrowed. + if (state == itos) { + __ narrow(Otos_i); + } __ remove_activation(state, /* throw_monitor_exception */ true); // The caller's SP was adjusted upon method entry to accomodate @@ -2218,7 +2237,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr Label checkVolatile; // compute field type - Label notByte, notInt, notShort, notChar, notLong, notFloat, notObj; + Label notByte, notBool, notInt, notShort, notChar, notLong, notFloat, notObj; __ srl(Rflags, ConstantPoolCacheEntry::tos_state_shift, Rflags); // Make sure we don't need to mask Rflags after the above shift ConstantPoolCacheEntry::verify_tos_state_shift(); @@ -2273,7 +2292,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr // cmp(Rflags, btos); __ br(Assembler::notEqual, false, Assembler::pt, notByte); - __ delayed() ->cmp(Rflags, ctos); + __ delayed() ->cmp(Rflags, ztos); // btos __ ldsb(Rclass, Roffset, Otos_i); @@ -2286,6 +2305,22 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr __ bind(notByte); + // cmp(Rflags, ztos); + __ br(Assembler::notEqual, false, Assembler::pt, notBool); + __ delayed() ->cmp(Rflags, ctos); + + // ztos + __ ldsb(Rclass, Roffset, Otos_i); + __ push(itos); + if (!is_static && rc == may_rewrite) { + // use btos rewriting, no truncating to t/f bit is needed for getfield. + patch_bytecode(Bytecodes::_fast_bgetfield, G3_scratch, G4_scratch); + } + __ ba(checkVolatile); + __ delayed()->tst(Lscratch); + + __ bind(notBool); + // cmp(Rflags, ctos); __ br(Assembler::notEqual, false, Assembler::pt, notChar); __ delayed() ->cmp(Rflags, stos); @@ -2449,6 +2484,7 @@ void TemplateTable::jvmti_post_fast_field_mod() { switch (bytecode()) { // save tos values before call_VM() clobbers them case Bytecodes::_fast_aputfield: __ push_ptr(Otos_i); break; case Bytecodes::_fast_bputfield: // fall through + case Bytecodes::_fast_zputfield: // fall through case Bytecodes::_fast_sputfield: // fall through case Bytecodes::_fast_cputfield: // fall through case Bytecodes::_fast_iputfield: __ push_i(Otos_i); break; @@ -2466,6 +2502,7 @@ void TemplateTable::jvmti_post_fast_field_mod() { switch (bytecode()) { // restore tos values case Bytecodes::_fast_aputfield: __ pop_ptr(Otos_i); break; case Bytecodes::_fast_bputfield: // fall through + case Bytecodes::_fast_zputfield: // fall through case Bytecodes::_fast_sputfield: // fall through case Bytecodes::_fast_cputfield: // fall through case Bytecodes::_fast_iputfield: __ pop_i(Otos_i); break; @@ -2581,7 +2618,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteContr ConstantPoolCacheEntry::verify_tos_state_shift(); // compute field type - Label notInt, notShort, notChar, notObj, notByte, notLong, notFloat; + Label notInt, notShort, notChar, notObj, notByte, notBool, notLong, notFloat; if (is_static) { // putstatic with object type most likely, check that first @@ -2649,7 +2686,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteContr // cmp(Rflags, btos); __ br(Assembler::notEqual, false, Assembler::pt, notByte); - __ delayed()->cmp(Rflags, ltos); + __ delayed()->cmp(Rflags, ztos); // btos { @@ -2664,6 +2701,25 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteContr } __ bind(notByte); + + // cmp(Rflags, btos); + __ br(Assembler::notEqual, false, Assembler::pt, notBool); + __ delayed()->cmp(Rflags, ltos); + + // ztos + { + __ pop_i(); + if (!is_static) pop_and_check_object(Rclass); + __ and3(Otos_i, 1, Otos_i); + __ stb(Otos_i, Rclass, Roffset); + if (!is_static && rc == may_rewrite) { + patch_bytecode(Bytecodes::_fast_zputfield, G3_scratch, G4_scratch, true, byte_no); + } + __ ba(checkVolatile); + __ delayed()->tst(Lscratch); + } + + __ bind(notBool); // cmp(Rflags, ltos); __ br(Assembler::notEqual, false, Assembler::pt, notLong); __ delayed()->cmp(Rflags, ctos); @@ -2787,6 +2843,7 @@ void TemplateTable::fast_storefield(TosState state) { pop_and_check_object(Rclass); switch (bytecode()) { + case Bytecodes::_fast_zputfield: __ and3(Otos_i, 1, Otos_i); // fall through to bputfield case Bytecodes::_fast_bputfield: __ stb(Otos_i, Rclass, Roffset); break; case Bytecodes::_fast_cputfield: /* fall through */ case Bytecodes::_fast_sputfield: __ sth(Otos_i, Rclass, Roffset); break; diff --git a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp index 34041ed994340bef30293b2d859e814ca184b525..93c8d40891e96266ff7a780f1c382649d283ca58 100644 --- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "asm/macroAssembler.inline.hpp" +#include "logging/log.hpp" #include "memory/resourceArea.hpp" #include "runtime/java.hpp" #include "runtime/os.hpp" @@ -368,36 +369,38 @@ void VM_Version::initialize() { FLAG_SET_DEFAULT(UseUnalignedAccesses, false); } - if (PrintMiscellaneous && Verbose) { - tty->print_cr("L1 data cache line size: %u", L1_data_cache_line_size()); - tty->print_cr("L2 data cache line size: %u", L2_data_cache_line_size()); - tty->print("Allocation"); + if (log_is_enabled(Info, os, cpu)) { + ResourceMark rm; + outputStream* log = Log(os, cpu)::info_stream(); + log->print_cr("L1 data cache line size: %u", L1_data_cache_line_size()); + log->print_cr("L2 data cache line size: %u", L2_data_cache_line_size()); + log->print("Allocation"); if (AllocatePrefetchStyle <= 0) { - tty->print_cr(": no prefetching"); + log->print(": no prefetching"); } else { - tty->print(" prefetching: "); + log->print(" prefetching: "); if (AllocatePrefetchInstr == 0) { - tty->print("PREFETCH"); + log->print("PREFETCH"); } else if (AllocatePrefetchInstr == 1) { - tty->print("BIS"); + log->print("BIS"); } if (AllocatePrefetchLines > 1) { - tty->print_cr(" at distance %d, %d lines of %d bytes", (int) AllocatePrefetchDistance, (int) AllocatePrefetchLines, (int) AllocatePrefetchStepSize); + log->print_cr(" at distance %d, %d lines of %d bytes", (int) AllocatePrefetchDistance, (int) AllocatePrefetchLines, (int) AllocatePrefetchStepSize); } else { - tty->print_cr(" at distance %d, one line of %d bytes", (int) AllocatePrefetchDistance, (int) AllocatePrefetchStepSize); + log->print_cr(" at distance %d, one line of %d bytes", (int) AllocatePrefetchDistance, (int) AllocatePrefetchStepSize); } } if (PrefetchCopyIntervalInBytes > 0) { - tty->print_cr("PrefetchCopyIntervalInBytes %d", (int) PrefetchCopyIntervalInBytes); + log->print_cr("PrefetchCopyIntervalInBytes %d", (int) PrefetchCopyIntervalInBytes); } if (PrefetchScanIntervalInBytes > 0) { - tty->print_cr("PrefetchScanIntervalInBytes %d", (int) PrefetchScanIntervalInBytes); + log->print_cr("PrefetchScanIntervalInBytes %d", (int) PrefetchScanIntervalInBytes); } if (PrefetchFieldsAhead > 0) { - tty->print_cr("PrefetchFieldsAhead %d", (int) PrefetchFieldsAhead); + log->print_cr("PrefetchFieldsAhead %d", (int) PrefetchFieldsAhead); } if (ContendedPaddingWidth > 0) { - tty->print_cr("ContendedPaddingWidth %d", (int) ContendedPaddingWidth); + log->print_cr("ContendedPaddingWidth %d", (int) ContendedPaddingWidth); } } } @@ -408,7 +411,7 @@ void VM_Version::print_features() { int VM_Version::determine_features() { if (UseV8InstrsOnly) { - if (PrintMiscellaneous && Verbose) { tty->print_cr("Version is Forced-V8"); } + log_info(os, cpu)("Version is Forced-V8"); return generic_v8_m; } @@ -416,7 +419,7 @@ int VM_Version::determine_features() { if (features == unknown_m) { features = generic_v9_m; - warning("Cannot recognize SPARC version. Default to V9"); + log_info(os)("Cannot recognize SPARC version. Default to V9"); } assert(is_T_family(features) == is_niagara(features), "Niagara should be T series"); @@ -424,12 +427,12 @@ int VM_Version::determine_features() { if (is_T_family(features)) { // Happy to accomodate... } else { - if (PrintMiscellaneous && Verbose) { tty->print_cr("Version is Forced-Niagara"); } + log_info(os, cpu)("Version is Forced-Niagara"); features |= T_family_m; } } else { if (is_T_family(features) && !FLAG_IS_DEFAULT(UseNiagaraInstrs)) { - if (PrintMiscellaneous && Verbose) { tty->print_cr("Version is Forced-Not-Niagara"); } + log_info(os, cpu)("Version is Forced-Not-Niagara"); features &= ~(T_family_m | T1_model_m); } else { // Happy to accomodate... diff --git a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp index b545d0b698928f2b11bd7d70b1f4d7ca02d78964..20c1932546340f3a0a5b914fa93d79c9ca62324f 100644 --- a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp @@ -284,7 +284,7 @@ void LIRGenerator::do_StoreIndexed(StoreIndexed* x) { length.load_item(); } - if (needs_store_check) { + if (needs_store_check || x->check_boolean()) { value.load_item(); } else { value.load_for_store(x->elt_type()); @@ -332,7 +332,8 @@ void LIRGenerator::do_StoreIndexed(StoreIndexed* x) { // Seems to be a precise post_barrier(LIR_OprFact::address(array_addr), value.result()); } else { - __ move(value.result(), array_addr, null_check_info); + LIR_Opr result = maybe_mask_boolean(x, array.result(), value.result(), null_check_info); + __ move(result, array_addr, null_check_info); } } diff --git a/hotspot/src/cpu/x86/vm/debug_x86.cpp b/hotspot/src/cpu/x86/vm/debug_x86.cpp index b128439ef23f3a13c58e0d4beda11dad5e840337..0bde483a7898cb80cd94600bd00243a07d288dcb 100644 --- a/hotspot/src/cpu/x86/vm/debug_x86.cpp +++ b/hotspot/src/cpu/x86/vm/debug_x86.cpp @@ -29,6 +29,5 @@ #include "runtime/init.hpp" #include "runtime/os.hpp" #include "utilities/debug.hpp" -#include "utilities/top.hpp" void pd_ps(frame f) {} diff --git a/hotspot/src/cpu/x86/vm/frame_x86.hpp b/hotspot/src/cpu/x86/vm/frame_x86.hpp index 6c85be06a81daf2bb0d9ae3dcadd96dc749851b8..b10f9ce37e683d19a99c7f61cd482b62bfab82c2 100644 --- a/hotspot/src/cpu/x86/vm/frame_x86.hpp +++ b/hotspot/src/cpu/x86/vm/frame_x86.hpp @@ -26,7 +26,6 @@ #define CPU_X86_VM_FRAME_X86_HPP #include "runtime/synchronizer.hpp" -#include "utilities/top.hpp" // A frame represents a physical stack frame (an activation). Frames can be // C or Java frames, and the Java frames can be interpreted or compiled. diff --git a/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp b/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp index 8dc3084c4425e214b25abb0d2ca97204f9d594de..f8578f9f420a07ac03ebcfd22d9bc7f4e1ddc587 100644 --- a/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp +++ b/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp @@ -349,6 +349,7 @@ void InterpreterMacroAssembler::load_earlyret_value(TosState state) { verify_oop(rax, state); break; case ltos: movptr(rax, val_addr); break; case btos: // fall through + case ztos: // fall through case ctos: // fall through case stos: // fall through case itos: movl(rax, val_addr); break; @@ -370,6 +371,7 @@ void InterpreterMacroAssembler::load_earlyret_value(TosState state) { case ltos: movl(rdx, val_addr1); // fall through case btos: // fall through + case ztos: // fall through case ctos: // fall through case stos: // fall through case itos: movl(rax, val_addr); break; @@ -616,6 +618,7 @@ void InterpreterMacroAssembler::pop(TosState state) { switch (state) { case atos: pop_ptr(); break; case btos: + case ztos: case ctos: case stos: case itos: pop_i(); break; @@ -633,6 +636,7 @@ void InterpreterMacroAssembler::push(TosState state) { switch (state) { case atos: push_ptr(); break; case btos: + case ztos: case ctos: case stos: case itos: push_i(); break; @@ -668,6 +672,7 @@ void InterpreterMacroAssembler::pop(TosState state) { switch (state) { case atos: pop_ptr(rax); break; case btos: // fall through + case ztos: // fall through case ctos: // fall through case stos: // fall through case itos: pop_i(rax); break; @@ -716,6 +721,7 @@ void InterpreterMacroAssembler::push(TosState state) { switch (state) { case atos: push_ptr(rax); break; case btos: // fall through + case ztos: // fall through case ctos: // fall through case stos: // fall through case itos: push_i(rax); break; @@ -849,6 +855,51 @@ void InterpreterMacroAssembler::dispatch_via(TosState state, address* table) { dispatch_base(state, table); } +void InterpreterMacroAssembler::narrow(Register result) { + + // Get method->_constMethod->_result_type + movptr(rcx, Address(rbp, frame::interpreter_frame_method_offset * wordSize)); + movptr(rcx, Address(rcx, Method::const_offset())); + load_unsigned_byte(rcx, Address(rcx, ConstMethod::result_type_offset())); + + Label done, notBool, notByte, notChar; + + // common case first + cmpl(rcx, T_INT); + jcc(Assembler::equal, done); + + // mask integer result to narrower return type. + cmpl(rcx, T_BOOLEAN); + jcc(Assembler::notEqual, notBool); + andl(result, 0x1); + jmp(done); + + bind(notBool); + cmpl(rcx, T_BYTE); + jcc(Assembler::notEqual, notByte); + LP64_ONLY(movsbl(result, result);) + NOT_LP64(shll(result, 24);) // truncate upper 24 bits + NOT_LP64(sarl(result, 24);) // and sign-extend byte + jmp(done); + + bind(notByte); + cmpl(rcx, T_CHAR); + jcc(Assembler::notEqual, notChar); + LP64_ONLY(movzwl(result, result);) + NOT_LP64(andl(result, 0xFFFF);) // truncate upper 16 bits + jmp(done); + + bind(notChar); + // cmpl(rcx, T_SHORT); // all that's left + // jcc(Assembler::notEqual, done); + LP64_ONLY(movswl(result, result);) + NOT_LP64(shll(result, 16);) // truncate upper 16 bits + NOT_LP64(sarl(result, 16);) // and sign-extend short + + // Nothing to do for T_INT + bind(done); +} + // remove activation // // Unlock the receiver if this is a synchronized method. diff --git a/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp b/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp index 470ac6e6399d371c88ee26190ce1d70d74012827..9ed5c2c9ad349001676cc92705930881a4d70f4d 100644 --- a/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp +++ b/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp @@ -192,6 +192,9 @@ class InterpreterMacroAssembler: public MacroAssembler { void prepare_to_jump_from_interpreted(); void jump_from_interpreted(Register method, Register temp); + // narrow int return value + void narrow(Register result); + // Returning from interpreted functions // // Removes the current activation (incl. unlocking of monitors) diff --git a/hotspot/src/cpu/x86/vm/nativeInst_x86.hpp b/hotspot/src/cpu/x86/vm/nativeInst_x86.hpp index 6c527d499919e688d2afc4538aac13f4e85b2096..1bb1c6c8aff77270083a2566e64e509a35c66837 100644 --- a/hotspot/src/cpu/x86/vm/nativeInst_x86.hpp +++ b/hotspot/src/cpu/x86/vm/nativeInst_x86.hpp @@ -29,7 +29,6 @@ #include "memory/allocation.hpp" #include "runtime/icache.hpp" #include "runtime/os.hpp" -#include "utilities/top.hpp" // We have interfaces for the following instructions: // - NativeInstruction diff --git a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp index abe9a369eaafe1b429f1032e1636939d497fe04e..3763b058b8be749c942c0d67b2d3d47e61f009e7 100644 --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp @@ -355,6 +355,14 @@ bool SharedRuntime::is_wide_vector(int size) { return size > 16; } +size_t SharedRuntime::trampoline_size() { + return 16; +} + +void SharedRuntime::generate_trampoline(MacroAssembler *masm, address destination) { + __ jump(RuntimeAddress(destination)); +} + // The java_calling_convention describes stack locations as ideal slots on // a frame with no abi restrictions. Since we must observe abi restrictions // (like the placement of the register window) the slots must be biased by diff --git a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp index a5c8f82e6ef70f8c46cfb1f26af9c8b441f73ba2..8fca552dd3458218c717cfc5bb01527b4e6fec20 100644 --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp @@ -391,6 +391,14 @@ bool SharedRuntime::is_wide_vector(int size) { return size > 16; } +size_t SharedRuntime::trampoline_size() { + return 16; +} + +void SharedRuntime::generate_trampoline(MacroAssembler *masm, address destination) { + __ jump(RuntimeAddress(destination)); +} + // The java_calling_convention describes stack locations as ideal slots on // a frame with no abi restrictions. Since we must observe abi restrictions // (like the placement of the register window) the slots must be biased by diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp index 756c032861e9a2f78a5dbb864eb79a0b6bb36074..0f11b9c03717f1d106a9f6d6e9f2ab9470ff277a 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp @@ -38,7 +38,6 @@ #include "runtime/stubCodeGenerator.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/thread.inline.hpp" -#include "utilities/top.hpp" #ifdef COMPILER2 #include "opto/runtime.hpp" #endif diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp index 882969c569531031495c4c3d5b7979ac560c7286..d51f3a696a05b6983017ff770c89150909a7eb26 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp @@ -38,7 +38,6 @@ #include "runtime/stubCodeGenerator.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/thread.inline.hpp" -#include "utilities/top.hpp" #ifdef COMPILER2 #include "opto/runtime.hpp" #endif diff --git a/hotspot/src/cpu/x86/vm/templateTable_x86.cpp b/hotspot/src/cpu/x86/vm/templateTable_x86.cpp index 42520c7e418f5663c2703fa9ab487139effa4cba..9f99613b1e6f0132cc674fcadbbeac975bfdce19 100644 --- a/hotspot/src/cpu/x86/vm/templateTable_x86.cpp +++ b/hotspot/src/cpu/x86/vm/templateTable_x86.cpp @@ -243,6 +243,7 @@ void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg, switch (bc) { case Bytecodes::_fast_aputfield: case Bytecodes::_fast_bputfield: + case Bytecodes::_fast_zputfield: case Bytecodes::_fast_cputfield: case Bytecodes::_fast_dputfield: case Bytecodes::_fast_fputfield: @@ -1082,6 +1083,16 @@ void TemplateTable::bastore() { // rbx: index // rdx: array index_check(rdx, rbx); // prefer index in rbx + // Need to check whether array is boolean or byte + // since both types share the bastore bytecode. + __ load_klass(rcx, rdx); + __ movl(rcx, Address(rcx, Klass::layout_helper_offset())); + int diffbit = Klass::layout_helper_boolean_diffbit(); + __ testl(rcx, diffbit); + Label L_skip; + __ jccb(Assembler::zero, L_skip); + __ andl(rax, 1); // if it is a T_BOOLEAN array, mask the stored value to 0/1 + __ bind(L_skip); __ movb(Address(rdx, rbx, Address::times_1, arrayOopDesc::base_offset_in_bytes(T_BYTE)), @@ -2540,13 +2551,12 @@ void TemplateTable::fast_binaryswitch() { void TemplateTable::_return(TosState state) { transition(state, state); - Register robj = LP64_ONLY(c_rarg1) NOT_LP64(rax); - assert(_desc->calls_vm(), "inconsistent calls_vm information"); // call in remove_activation if (_desc->bytecode() == Bytecodes::_return_register_finalizer) { assert(state == vtos, "only valid state"); + Register robj = LP64_ONLY(c_rarg1) NOT_LP64(rax); __ movptr(robj, aaddress(0)); __ load_klass(rdi, robj); __ movl(rdi, Address(rdi, Klass::access_flags_offset())); @@ -2559,7 +2569,14 @@ void TemplateTable::_return(TosState state) { __ bind(skip_register_finalizer); } + // Narrow result if state is itos but result type is smaller. + // Need to narrow in the return bytecode rather than in generate_return_entry + // since compiled code callers expect the result to already be narrowed. + if (state == itos) { + __ narrow(rax); + } __ remove_activation(state, rbcp); + __ jmp(rbcp); } @@ -2754,7 +2771,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr const Address field(obj, off, Address::times_1, 0*wordSize); NOT_LP64(const Address hi(obj, off, Address::times_1, 1*wordSize)); - Label Done, notByte, notInt, notShort, notChar, notLong, notFloat, notObj, notDouble; + Label Done, notByte, notBool, notInt, notShort, notChar, notLong, notFloat, notObj, notDouble; __ shrl(flags, ConstantPoolCacheEntry::tos_state_shift); // Make sure we don't need to mask edx after the above shift @@ -2773,6 +2790,20 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr __ jmp(Done); __ bind(notByte); + __ cmpl(flags, ztos); + __ jcc(Assembler::notEqual, notBool); + + // ztos (same code as btos) + __ load_signed_byte(rax, field); + __ push(ztos); + // Rewrite bytecode to be faster + if (!is_static && rc == may_rewrite) { + // use btos rewriting, no truncating to t/f bit is needed for getfield. + patch_bytecode(Bytecodes::_fast_bgetfield, bc, rbx); + } + __ jmp(Done); + + __ bind(notBool); __ cmpl(flags, atos); __ jcc(Assembler::notEqual, notObj); // atos @@ -3006,7 +3037,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteContr const Address field(obj, off, Address::times_1, 0*wordSize); NOT_LP64( const Address hi(obj, off, Address::times_1, 1*wordSize);) - Label notByte, notInt, notShort, notChar, + Label notByte, notBool, notInt, notShort, notChar, notLong, notFloat, notObj, notDouble; __ shrl(flags, ConstantPoolCacheEntry::tos_state_shift); @@ -3027,6 +3058,22 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteContr } __ bind(notByte); + __ cmpl(flags, ztos); + __ jcc(Assembler::notEqual, notBool); + + // ztos + { + __ pop(ztos); + if (!is_static) pop_and_check_object(obj); + __ andl(rax, 0x1); + __ movb(field, rax); + if (!is_static && rc == may_rewrite) { + patch_bytecode(Bytecodes::_fast_zputfield, bc, rbx, true, byte_no); + } + __ jmp(Done); + } + + __ bind(notBool); __ cmpl(flags, atos); __ jcc(Assembler::notEqual, notObj); @@ -3214,6 +3261,7 @@ void TemplateTable::jvmti_post_fast_field_mod() { switch (bytecode()) { // load values into the jvalue object case Bytecodes::_fast_aputfield: __ push_ptr(rax); break; case Bytecodes::_fast_bputfield: // fall through + case Bytecodes::_fast_zputfield: // fall through case Bytecodes::_fast_sputfield: // fall through case Bytecodes::_fast_cputfield: // fall through case Bytecodes::_fast_iputfield: __ push_i(rax); break; @@ -3238,6 +3286,7 @@ void TemplateTable::jvmti_post_fast_field_mod() { switch (bytecode()) { // restore tos values case Bytecodes::_fast_aputfield: __ pop_ptr(rax); break; case Bytecodes::_fast_bputfield: // fall through + case Bytecodes::_fast_zputfield: // fall through case Bytecodes::_fast_sputfield: // fall through case Bytecodes::_fast_cputfield: // fall through case Bytecodes::_fast_iputfield: __ pop_i(rax); break; @@ -3297,6 +3346,9 @@ void TemplateTable::fast_storefield(TosState state) { case Bytecodes::_fast_iputfield: __ movl(field, rax); break; + case Bytecodes::_fast_zputfield: + __ andl(rax, 0x1); // boolean is true if LSB is 1 + // fall through to bputfield case Bytecodes::_fast_bputfield: __ movb(field, rax); break; diff --git a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp index 94c7e156d7e339e1962d20a3eb01c1dbc9637456..6d871ce92deee70ceec6811bdc43c792392d4319 100644 --- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp +++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "asm/macroAssembler.hpp" #include "asm/macroAssembler.inline.hpp" +#include "logging/log.hpp" #include "memory/resourceArea.hpp" #include "runtime/java.hpp" #include "runtime/os.hpp" @@ -1223,59 +1224,60 @@ void VM_Version::get_processor_features() { } #ifndef PRODUCT - if (PrintMiscellaneous && Verbose) { - tty->print_cr("Logical CPUs per core: %u", + if (log_is_enabled(Info, os, cpu)) { + outputStream* log = Log(os, cpu)::info_stream(); + log->print_cr("Logical CPUs per core: %u", logical_processors_per_package()); - tty->print_cr("L1 data cache line size: %u", L1_data_cache_line_size()); - tty->print("UseSSE=%d", (int) UseSSE); + log->print_cr("L1 data cache line size: %u", L1_data_cache_line_size()); + log->print("UseSSE=%d", (int) UseSSE); if (UseAVX > 0) { - tty->print(" UseAVX=%d", (int) UseAVX); + log->print(" UseAVX=%d", (int) UseAVX); } if (UseAES) { - tty->print(" UseAES=1"); + log->print(" UseAES=1"); } #ifdef COMPILER2 if (MaxVectorSize > 0) { - tty->print(" MaxVectorSize=%d", (int) MaxVectorSize); + log->print(" MaxVectorSize=%d", (int) MaxVectorSize); } #endif - tty->cr(); - tty->print("Allocation"); + log->cr(); + log->print("Allocation"); if (AllocatePrefetchStyle <= 0 || UseSSE == 0 && !supports_3dnow_prefetch()) { - tty->print_cr(": no prefetching"); + log->print_cr(": no prefetching"); } else { - tty->print(" prefetching: "); + log->print(" prefetching: "); if (UseSSE == 0 && supports_3dnow_prefetch()) { - tty->print("PREFETCHW"); + log->print("PREFETCHW"); } else if (UseSSE >= 1) { if (AllocatePrefetchInstr == 0) { - tty->print("PREFETCHNTA"); + log->print("PREFETCHNTA"); } else if (AllocatePrefetchInstr == 1) { - tty->print("PREFETCHT0"); + log->print("PREFETCHT0"); } else if (AllocatePrefetchInstr == 2) { - tty->print("PREFETCHT2"); + log->print("PREFETCHT2"); } else if (AllocatePrefetchInstr == 3) { - tty->print("PREFETCHW"); + log->print("PREFETCHW"); } } if (AllocatePrefetchLines > 1) { - tty->print_cr(" at distance %d, %d lines of %d bytes", (int) AllocatePrefetchDistance, (int) AllocatePrefetchLines, (int) AllocatePrefetchStepSize); + log->print_cr(" at distance %d, %d lines of %d bytes", (int) AllocatePrefetchDistance, (int) AllocatePrefetchLines, (int) AllocatePrefetchStepSize); } else { - tty->print_cr(" at distance %d, one line of %d bytes", (int) AllocatePrefetchDistance, (int) AllocatePrefetchStepSize); + log->print_cr(" at distance %d, one line of %d bytes", (int) AllocatePrefetchDistance, (int) AllocatePrefetchStepSize); } } if (PrefetchCopyIntervalInBytes > 0) { - tty->print_cr("PrefetchCopyIntervalInBytes %d", (int) PrefetchCopyIntervalInBytes); + log->print_cr("PrefetchCopyIntervalInBytes %d", (int) PrefetchCopyIntervalInBytes); } if (PrefetchScanIntervalInBytes > 0) { - tty->print_cr("PrefetchScanIntervalInBytes %d", (int) PrefetchScanIntervalInBytes); + log->print_cr("PrefetchScanIntervalInBytes %d", (int) PrefetchScanIntervalInBytes); } if (PrefetchFieldsAhead > 0) { - tty->print_cr("PrefetchFieldsAhead %d", (int) PrefetchFieldsAhead); + log->print_cr("PrefetchFieldsAhead %d", (int) PrefetchFieldsAhead); } if (ContendedPaddingWidth > 0) { - tty->print_cr("ContendedPaddingWidth %d", (int) ContendedPaddingWidth); + log->print_cr("ContendedPaddingWidth %d", (int) ContendedPaddingWidth); } } #endif // !PRODUCT diff --git a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp index 4dc68335b6ac97210449e9c8bdb3364f9ab8dada..e05e6d65bc08090530ea6d1af70292a47c420530 100644 --- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp +++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp @@ -82,6 +82,30 @@ int CppInterpreter::normal_entry(Method* method, intptr_t UNUSED, TRAPS) { return 0; } +intptr_t narrow(BasicType type, intptr_t result) { + // mask integer result to narrower return type. + switch (type) { + case T_BOOLEAN: + return result&1; + case T_BYTE: + return (intptr_t)(jbyte)result; + case T_CHAR: + return (intptr_t)(uintptr_t)(jchar)result; + case T_SHORT: + return (intptr_t)(jshort)result; + case T_OBJECT: // nothing to do fall through + case T_ARRAY: + case T_LONG: + case T_INT: + case T_FLOAT: + case T_DOUBLE: + case T_VOID: + return result; + default : ShouldNotReachHere(); + } +} + + void CppInterpreter::main_loop(int recurse, TRAPS) { JavaThread *thread = (JavaThread *) THREAD; ZeroStack *stack = thread->zero_stack(); @@ -161,7 +185,7 @@ void CppInterpreter::main_loop(int recurse, TRAPS) { } else if (istate->msg() == BytecodeInterpreter::return_from_method) { // Copy the result into the caller's frame - result_slots = type2size[result_type_of(method)]; + result_slots = type2size[method->result_type()]; assert(result_slots >= 0 && result_slots <= 2, "what?"); result = istate->stack() + result_slots; break; @@ -195,8 +219,14 @@ void CppInterpreter::main_loop(int recurse, TRAPS) { stack->set_sp(stack->sp() + method->max_locals()); // Push our result - for (int i = 0; i < result_slots; i++) - stack->push(result[-i]); + for (int i = 0; i < result_slots; i++) { + // Adjust result to smaller + intptr_t res = result[-i]; + if (result_slots == 1) { + res = narrow(method->result_type(), res); + } + stack->push(res); + } } int CppInterpreter::native_entry(Method* method, intptr_t UNUSED, TRAPS) { @@ -407,7 +437,7 @@ int CppInterpreter::native_entry(Method* method, intptr_t UNUSED, TRAPS) { // Push our result if (!HAS_PENDING_EXCEPTION) { - BasicType type = result_type_of(method); + BasicType type = method->result_type(); stack->set_sp(stack->sp() - type2size[type]); switch (type) { @@ -532,6 +562,7 @@ int CppInterpreter::accessor_entry(Method* method, intptr_t UNUSED, TRAPS) { break; case btos: + case ztos: SET_LOCALS_INT(object->byte_field_acquire(entry->f2_as_index()), 0); break; @@ -570,6 +601,7 @@ int CppInterpreter::accessor_entry(Method* method, intptr_t UNUSED, TRAPS) { break; case btos: + case ztos: SET_LOCALS_INT(object->byte_field(entry->f2_as_index()), 0); break; @@ -772,26 +804,6 @@ InterpreterFrame *InterpreterFrame::build(int size, TRAPS) { return (InterpreterFrame *) fp; } -BasicType CppInterpreter::result_type_of(Method* method) { - BasicType t = T_ILLEGAL; // silence compiler warnings - switch (method->result_index()) { - case 0 : t = T_BOOLEAN; break; - case 1 : t = T_CHAR; break; - case 2 : t = T_BYTE; break; - case 3 : t = T_SHORT; break; - case 4 : t = T_INT; break; - case 5 : t = T_LONG; break; - case 6 : t = T_VOID; break; - case 7 : t = T_FLOAT; break; - case 8 : t = T_DOUBLE; break; - case 9 : t = T_OBJECT; break; - default: ShouldNotReachHere(); - } - assert(AbstractInterpreter::BasicType_as_index(t) == method->result_index(), - "out of step with AbstractInterpreter::BasicType_as_index"); - return t; -} - address CppInterpreter::return_entry(TosState state, int length, Bytecodes::Code code) { ShouldNotCallThis(); return NULL; diff --git a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.hpp b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.hpp index 3a6bd52f2cbb0a100c0aa5362150155db4a89ec4..9c0a2a010910327510e70961ed63a1bbd0fb6427 100644 --- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.hpp +++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2010, 2011 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -49,8 +49,4 @@ static intptr_t* calculate_unwind_sp(ZeroStack* stack, oop method_handle); static void throw_exception(JavaThread* thread, Symbol* name,char *msg=NULL); - private: - // Fast result type determination - static BasicType result_type_of(Method* method); - #endif // CPU_ZERO_VM_CPPINTERPRETER_ZERO_HPP diff --git a/hotspot/src/cpu/zero/vm/debug_zero.cpp b/hotspot/src/cpu/zero/vm/debug_zero.cpp index 19d00e33cdc0b3e3c589d75fdf660e1f19fddb09..24580fecf5f9b2d4e4659acf7342de4d5adcbcaa 100644 --- a/hotspot/src/cpu/zero/vm/debug_zero.cpp +++ b/hotspot/src/cpu/zero/vm/debug_zero.cpp @@ -30,7 +30,6 @@ #include "runtime/init.hpp" #include "runtime/os.hpp" #include "utilities/debug.hpp" -#include "utilities/top.hpp" void pd_ps(frame f) { ShouldNotCallThis(); diff --git a/hotspot/src/cpu/zero/vm/frame_zero.hpp b/hotspot/src/cpu/zero/vm/frame_zero.hpp index 56f0a1716b0d0e4eedb31773d68a20e22686f154..2f1c931c69015f55df9d94828ae3612f5185b279 100644 --- a/hotspot/src/cpu/zero/vm/frame_zero.hpp +++ b/hotspot/src/cpu/zero/vm/frame_zero.hpp @@ -27,7 +27,6 @@ #define CPU_ZERO_VM_FRAME_ZERO_HPP #include "runtime/synchronizer.hpp" -#include "utilities/top.hpp" // A frame represents a physical stack frame on the Zero stack. diff --git a/hotspot/src/cpu/zero/vm/nativeInst_zero.hpp b/hotspot/src/cpu/zero/vm/nativeInst_zero.hpp index 559bde79ab6110f6727315cc83d79dbffa5dd369..8b60b358f5ee7262a0b279574464eecea689c3f5 100644 --- a/hotspot/src/cpu/zero/vm/nativeInst_zero.hpp +++ b/hotspot/src/cpu/zero/vm/nativeInst_zero.hpp @@ -30,7 +30,6 @@ #include "memory/allocation.hpp" #include "runtime/icache.hpp" #include "runtime/os.hpp" -#include "utilities/top.hpp" // We have interfaces for the following instructions: // - NativeInstruction diff --git a/hotspot/src/cpu/zero/vm/sharedRuntime_zero.cpp b/hotspot/src/cpu/zero/vm/sharedRuntime_zero.cpp index 3fbe12e94f92b1759fb9cca6cd0d144c047ca7dc..0fb36b01b751d681b8ca88e4d7fc56dcd8126a0c 100644 --- a/hotspot/src/cpu/zero/vm/sharedRuntime_zero.cpp +++ b/hotspot/src/cpu/zero/vm/sharedRuntime_zero.cpp @@ -132,6 +132,15 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const cha return generate_empty_runtime_stub("resolve_blob"); } +size_t SharedRuntime::trampoline_size() { + ShouldNotCallThis(); + return 0; +} + +void SharedRuntime::generate_trampoline(MacroAssembler *masm, address destination) { + ShouldNotCallThis(); + return; +} int SharedRuntime::c_calling_convention(const BasicType *sig_bt, VMRegPair *regs, diff --git a/hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp b/hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp index 9d999a8c805d357ad2902276b01f43bf796cb7fc..bdaec67cd733e34fbfbc5e918236e7f952403a30 100644 --- a/hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp +++ b/hotspot/src/cpu/zero/vm/stubGenerator_zero.cpp @@ -40,7 +40,6 @@ #include "runtime/stubRoutines.hpp" #include "runtime/thread.inline.hpp" #include "stack_zero.inline.hpp" -#include "utilities/top.hpp" #ifdef COMPILER2 #include "opto/runtime.hpp" #endif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SAGetopt.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SAGetopt.java index 3d4ffb0171ba0c61fce87302fe4b5e2d1cb4a230..d23a057f5848ed307e8cd9db99e1977fc451146f 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SAGetopt.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SAGetopt.java @@ -55,11 +55,11 @@ public class SAGetopt { private void extractOptarg(String opt) { // Argument expected if (_optind > _argv.length) { - throw new RuntimeException("Not enough arguments for '" + opt + "'"); + throw new SAGetoptException("Not enough arguments for '" + opt + "'"); } if (! _argv[_optind].isEmpty() && _argv[_optind].charAt(0) == '-') { - throw new RuntimeException("Argument is expected for '" + opt + "'"); + throw new SAGetoptException("Argument is expected for '" + opt + "'"); } _optarg = _argv[_optind]; @@ -72,7 +72,7 @@ public class SAGetopt { if (los.contains(ca[0])) { if (ca.length > 1) { - throw new RuntimeException("Argument is not expected for '" + ca[0] + "'"); + throw new SAGetoptException("Argument is not expected for '" + ca[0] + "'"); } return carg; } @@ -87,14 +87,14 @@ public class SAGetopt { try { extractOptarg(ca[0]); } catch (ArrayIndexOutOfBoundsException e) { - throw new RuntimeException("Argument is expected for '" + ca[0] + "'"); + throw new SAGetoptException("Argument is expected for '" + ca[0] + "'"); } } return ca[0]; } - throw new RuntimeException("Invalid option '" + ca[0] + "'"); + throw new SAGetoptException("Invalid option '" + ca[0] + "'"); } public String next(String optStr, String[] longOptStr) { @@ -148,7 +148,7 @@ public class SAGetopt { int chIndex = optStr.indexOf(ch); if (chIndex == -1) { - throw new RuntimeException("Invalid option '" + ch + "'"); + throw new SAGetoptException("Invalid option '" + ch + "'"); } if (_optopt >= carg.length()) { diff --git a/hotspot/src/share/vm/utilities/top.hpp b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SAGetoptException.java similarity index 54% rename from hotspot/src/share/vm/utilities/top.hpp rename to hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SAGetoptException.java index de26d52bc0297916ba4c0576f99fc2c1e7c7770b..f6ba480ca33c3462b0e93803dd12b19edae89c1b 100644 --- a/hotspot/src/share/vm/utilities/top.hpp +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SAGetoptException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,31 +22,12 @@ * */ -#ifndef SHARE_VM_UTILITIES_TOP_HPP -#define SHARE_VM_UTILITIES_TOP_HPP +package sun.jvm.hotspot; -#include "oops/oopsHierarchy.hpp" -#include "runtime/globals.hpp" -#include "utilities/debug.hpp" -#include "utilities/exceptions.hpp" -#include "utilities/globalDefinitions.hpp" -#include "utilities/macros.hpp" -#include "utilities/ostream.hpp" -#include "utilities/sizes.hpp" -#if INCLUDE_ALL_GCS -#include "gc/g1/g1_globals.hpp" -#endif // INCLUDE_ALL_GCS -#ifdef COMPILER1 -#include "c1/c1_globals.hpp" -#endif -#ifdef COMPILER2 -#include "opto/c2_globals.hpp" -#endif -#if INCLUDE_JVMCI -#include "jvmci/jvmci_globals.hpp" -#endif +public class SAGetoptException extends IllegalArgumentException { -// THIS FILE IS INTESIONALLY LEFT EMPTY -// IT IS USED TO MINIMIZE THE NUMBER OF DEPENDENCIES IN includeDB + public SAGetoptException(String message) { + super(message); + } -#endif // SHARE_VM_UTILITIES_TOP_HPP +} diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SALauncher.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SALauncher.java index 4b1f280a6d73d2ed049106acaa2d47828e0acd4a..dfbbb6ff440ff23be88e62029acea3325dada709 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SALauncher.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SALauncher.java @@ -111,34 +111,31 @@ public class SALauncher { return launcherHelp(); } - private static void buildAttachArgs(ArrayList newArgs, - String pid, String exe, String core) { - if ((pid == null) && (exe == null)) { - throw new IllegalArgumentException( - "You have to set --pid or --exe."); + private static void buildAttachArgs(ArrayList newArgs, String pid, + String exe, String core, boolean allowEmpty) { + if (!allowEmpty && (pid == null) && (exe == null)) { + throw new SAGetoptException("You have to set --pid or --exe."); } if (pid != null) { // Attach to live process if (exe != null) { - throw new IllegalArgumentException( - "Unnecessary argument: --exe"); + throw new SAGetoptException("Unnecessary argument: --exe"); } else if (core != null) { - throw new IllegalArgumentException( - "Unnecessary argument: --core"); + throw new SAGetoptException("Unnecessary argument: --core"); } else if (!pid.matches("^\\d+$")) { - throw new IllegalArgumentException("Invalid pid: " + pid); + throw new SAGetoptException("Invalid pid: " + pid); } newArgs.add(pid); - } else { + } else if (exe != null) { if (exe.length() == 0) { - throw new IllegalArgumentException("You have to set --exe."); + throw new SAGetoptException("You have to set --exe."); } newArgs.add(exe); if ((core == null) || (core.length() == 0)) { - throw new IllegalArgumentException("You have to set --core."); + throw new SAGetoptException("You have to set --core."); } newArgs.add(core); @@ -170,7 +167,7 @@ public class SALauncher { } } - buildAttachArgs(newArgs, pid, exe, core); + buildAttachArgs(newArgs, pid, exe, core, true); CLHSDB.main(newArgs.toArray(new String[newArgs.size()])); } @@ -199,7 +196,7 @@ public class SALauncher { } } - buildAttachArgs(newArgs, pid, exe, core); + buildAttachArgs(newArgs, pid, exe, core, true); HSDB.main(newArgs.toArray(new String[newArgs.size()])); } @@ -237,7 +234,7 @@ public class SALauncher { } } - buildAttachArgs(newArgs, pid, exe, core); + buildAttachArgs(newArgs, pid, exe, core, false); JStack.main(newArgs.toArray(new String[newArgs.size()])); } @@ -287,7 +284,7 @@ public class SALauncher { } } - buildAttachArgs(newArgs, pid, exe, core); + buildAttachArgs(newArgs, pid, exe, core, false); JMap.main(newArgs.toArray(new String[newArgs.size()])); } @@ -325,7 +322,7 @@ public class SALauncher { } } - buildAttachArgs(newArgs, pid, exe, core); + buildAttachArgs(newArgs, pid, exe, core, false); JInfo.main(newArgs.toArray(new String[newArgs.size()])); } @@ -358,7 +355,7 @@ public class SALauncher { } } - buildAttachArgs(newArgs, pid, exe, core); + buildAttachArgs(newArgs, pid, exe, core, false); JSnap.main(newArgs.toArray(new String[newArgs.size()])); } @@ -416,8 +413,8 @@ public class SALauncher { return; } - throw new IllegalArgumentException("Unknown tool: " + args[0]); - } catch (Exception e) { + throw new SAGetoptException("Unknown tool: " + args[0]); + } catch (SAGetoptException e) { System.err.println(e.getMessage()); toolHelp(args[0]); } diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/interpreter/Bytecodes.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/interpreter/Bytecodes.java index 3f09ee30c198593b2f321ce45ba92edd1b7273ff..8f51fb8cb8b90a15f864b43e176f4ba5660eb9e9 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/interpreter/Bytecodes.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/interpreter/Bytecodes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -253,29 +253,30 @@ public class Bytecodes { public static final int _fast_sgetfield = 210; public static final int _fast_aputfield = 211; public static final int _fast_bputfield = 212; - public static final int _fast_cputfield = 213; - public static final int _fast_dputfield = 214; - public static final int _fast_fputfield = 215; - public static final int _fast_iputfield = 216; - public static final int _fast_lputfield = 217; - public static final int _fast_sputfield = 218; - public static final int _fast_aload_0 = 219; - public static final int _fast_iaccess_0 = 220; - public static final int _fast_aaccess_0 = 221; - public static final int _fast_faccess_0 = 222; - public static final int _fast_iload = 223; - public static final int _fast_iload2 = 224; - public static final int _fast_icaload = 225; - public static final int _fast_invokevfinal = 226; - public static final int _fast_linearswitch = 227; - public static final int _fast_binaryswitch = 228; - public static final int _fast_aldc = 229; - public static final int _fast_aldc_w = 230; - public static final int _return_register_finalizer = 231; - public static final int _invokehandle = 232; - public static final int _shouldnotreachhere = 233; // For debugging - - public static final int number_of_codes = 234; + public static final int _fast_zputfield = 213; + public static final int _fast_cputfield = 214; + public static final int _fast_dputfield = 215; + public static final int _fast_fputfield = 216; + public static final int _fast_iputfield = 217; + public static final int _fast_lputfield = 218; + public static final int _fast_sputfield = 219; + public static final int _fast_aload_0 = 220; + public static final int _fast_iaccess_0 = 221; + public static final int _fast_aaccess_0 = 222; + public static final int _fast_faccess_0 = 223; + public static final int _fast_iload = 224; + public static final int _fast_iload2 = 225; + public static final int _fast_icaload = 226; + public static final int _fast_invokevfinal = 227; + public static final int _fast_linearswitch = 228; + public static final int _fast_binaryswitch = 229; + public static final int _fast_aldc = 230; + public static final int _fast_aldc_w = 231; + public static final int _return_register_finalizer = 232; + public static final int _invokehandle = 233; + public static final int _shouldnotreachhere = 234; // For debugging + + public static final int number_of_codes = 235; // Flag bits derived from format strings, can_trap, can_rewrite, etc.: // semantic flags: @@ -776,6 +777,7 @@ public class Bytecodes { def(_fast_aputfield , "fast_aputfield" , "bJJ" , null , BasicType.getTObject() , 0, true , _putfield ); def(_fast_bputfield , "fast_bputfield" , "bJJ" , null , BasicType.getTInt() , 0, true , _putfield ); + def(_fast_zputfield , "fast_zputfield" , "bJJ" , null , BasicType.getTInt() , 0, true , _putfield ); def(_fast_cputfield , "fast_cputfield" , "bJJ" , null , BasicType.getTChar() , 0, true , _putfield ); def(_fast_dputfield , "fast_dputfield" , "bJJ" , null , BasicType.getTDouble() , 0, true , _putfield ); def(_fast_fputfield , "fast_fputfield" , "bJJ" , null , BasicType.getTFloat() , 0, true , _putfield ); diff --git a/hotspot/src/os/aix/vm/os_aix.cpp b/hotspot/src/os/aix/vm/os_aix.cpp index 31002c5bd608f161a38e7ff7ccfd6f3353f3d5aa..22e016b65f233eb9bb7553bd48de5a5de3070172 100644 --- a/hotspot/src/os/aix/vm/os_aix.cpp +++ b/hotspot/src/os/aix/vm/os_aix.cpp @@ -3612,14 +3612,12 @@ jint os::init_2(void) { struct rlimit nbr_files; int status = getrlimit(RLIMIT_NOFILE, &nbr_files); if (status != 0) { - if (PrintMiscellaneous && (Verbose || WizardMode)) - perror("os::init_2 getrlimit failed"); + log_info(os)("os::init_2 getrlimit failed: %s", os::strerror(errno)); } else { nbr_files.rlim_cur = nbr_files.rlim_max; status = setrlimit(RLIMIT_NOFILE, &nbr_files); if (status != 0) { - if (PrintMiscellaneous && (Verbose || WizardMode)) - perror("os::init_2 setrlimit failed"); + log_info(os)("os::init_2 setrlimit failed: %s", os::strerror(errno)); } } } diff --git a/hotspot/src/os/aix/vm/perfMemory_aix.cpp b/hotspot/src/os/aix/vm/perfMemory_aix.cpp index e9621012b7bb694d56f4e70890195245e2423c8e..62212be7175c7562805a785bf1e0ec97126e5255 100644 --- a/hotspot/src/os/aix/vm/perfMemory_aix.cpp +++ b/hotspot/src/os/aix/vm/perfMemory_aix.cpp @@ -956,7 +956,7 @@ static int open_sharedmem_file(const char* filename, int oflags, TRAPS) { #ifdef O_NOFOLLOW RESTARTABLE(::open(filename, oflags), result); #else - open_o_nofollow(filename, oflags); + result = open_o_nofollow(filename, oflags); #endif if (result == OS_ERR) { diff --git a/hotspot/src/os/bsd/vm/os_bsd.cpp b/hotspot/src/os/bsd/vm/os_bsd.cpp index 9cf4f74d2cf42430b59dadaf2dfffe0f1805c629..78def166e5838a0e9dae709780161ae1eefd0e01 100644 --- a/hotspot/src/os/bsd/vm/os_bsd.cpp +++ b/hotspot/src/os/bsd/vm/os_bsd.cpp @@ -3459,25 +3459,13 @@ jint os::init_2(void) { guarantee(polling_page != MAP_FAILED, "os::init_2: failed to allocate polling page"); os::set_polling_page(polling_page); - -#ifndef PRODUCT - if (Verbose && PrintMiscellaneous) { - tty->print("[SafePoint Polling address: " INTPTR_FORMAT "]\n", - (intptr_t)polling_page); - } -#endif + log_info(os)("SafePoint Polling address: " INTPTR_FORMAT, p2i(polling_page)); if (!UseMembar) { address mem_serialize_page = (address) ::mmap(NULL, Bsd::page_size(), PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); guarantee(mem_serialize_page != MAP_FAILED, "mmap Failed for memory serialize page"); os::set_memory_serialize_page(mem_serialize_page); - -#ifndef PRODUCT - if (Verbose && PrintMiscellaneous) { - tty->print("[Memory Serialize Page address: " INTPTR_FORMAT "]\n", - (intptr_t)mem_serialize_page); - } -#endif + log_info(os)("Memory Serialize Page address: " INTPTR_FORMAT, p2i(mem_serialize_page)); } // initialize suspend/resume support - must do this before signal_sets_init() @@ -3519,9 +3507,7 @@ jint os::init_2(void) { struct rlimit nbr_files; int status = getrlimit(RLIMIT_NOFILE, &nbr_files); if (status != 0) { - if (PrintMiscellaneous && (Verbose || WizardMode)) { - perror("os::init_2 getrlimit failed"); - } + log_info(os)("os::init_2 getrlimit failed: %s", os::strerror(errno)); } else { nbr_files.rlim_cur = nbr_files.rlim_max; @@ -3534,9 +3520,7 @@ jint os::init_2(void) { status = setrlimit(RLIMIT_NOFILE, &nbr_files); if (status != 0) { - if (PrintMiscellaneous && (Verbose || WizardMode)) { - perror("os::init_2 setrlimit failed"); - } + log_info(os)("os::init_2 setrlimit failed: %s", os::strerror(errno)); } } } @@ -3748,6 +3732,28 @@ int os::stat(const char *path, struct stat *sbuf) { return ::stat(pathbuf, sbuf); } +static inline struct timespec get_mtime(const char* filename) { + struct stat st; + int ret = os::stat(filename, &st); + assert(ret == 0, "failed to stat() file '%s': %s", filename, strerror(errno)); +#ifdef __APPLE__ + return st.st_mtimespec; +#else + return st.st_mtim; +#endif +} + +int os::compare_file_modified_times(const char* file1, const char* file2) { + struct timespec filetime1 = get_mtime(file1); + struct timespec filetime2 = get_mtime(file2); + int diff = filetime1.tv_sec - filetime2.tv_sec; + if (diff == 0) { + return filetime1.tv_nsec - filetime2.tv_nsec; + } + return diff; +} + + bool os::check_heap(bool force) { return true; } diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index d8811d4652803787ced0df0cafed93ac9cc2bb1f..4889870e8f43c3fd1c358a5a0b011c4110c52096 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -2163,7 +2163,7 @@ static bool print_model_name_and_flags(outputStream* st, char* buf, size_t bufle bool model_name_printed = false; if (strstr(buf, "model name") != NULL) { if (!model_name_printed) { - st->print_raw("\nCPU Model and flags from /proc/cpuinfo:\n"); + st->print_raw("CPU Model and flags from /proc/cpuinfo:\n"); st->print_raw(buf); model_name_printed = true; } else { @@ -4671,25 +4671,13 @@ jint os::init_2(void) { guarantee(polling_page != MAP_FAILED, "os::init_2: failed to allocate polling page"); os::set_polling_page(polling_page); - -#ifndef PRODUCT - if (Verbose && PrintMiscellaneous) { - tty->print("[SafePoint Polling address: " INTPTR_FORMAT "]\n", - (intptr_t)polling_page); - } -#endif + log_info(os)("SafePoint Polling address: " INTPTR_FORMAT, p2i(polling_page)); if (!UseMembar) { address mem_serialize_page = (address) ::mmap(NULL, Linux::page_size(), PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); guarantee(mem_serialize_page != MAP_FAILED, "mmap Failed for memory serialize page"); os::set_memory_serialize_page(mem_serialize_page); - -#ifndef PRODUCT - if (Verbose && PrintMiscellaneous) { - tty->print("[Memory Serialize Page address: " INTPTR_FORMAT "]\n", - (intptr_t)mem_serialize_page); - } -#endif + log_info(os)("Memory Serialize Page address: " INTPTR_FORMAT, p2i(mem_serialize_page)); } // initialize suspend/resume support - must do this before signal_sets_init() @@ -4732,10 +4720,8 @@ jint os::init_2(void) { #endif Linux::libpthread_init(); - if (PrintMiscellaneous && (Verbose || WizardMode)) { - tty->print_cr("[HotSpot is running with %s, %s]\n", - Linux::glibc_version(), Linux::libpthread_version()); - } + log_info(os)("HotSpot is running with %s, %s", + Linux::glibc_version(), Linux::libpthread_version()); if (UseNUMA) { if (!Linux::libnuma_init()) { @@ -4776,16 +4762,12 @@ jint os::init_2(void) { struct rlimit nbr_files; int status = getrlimit(RLIMIT_NOFILE, &nbr_files); if (status != 0) { - if (PrintMiscellaneous && (Verbose || WizardMode)) { - perror("os::init_2 getrlimit failed"); - } + log_info(os)("os::init_2 getrlimit failed: %s", os::strerror(errno)); } else { nbr_files.rlim_cur = nbr_files.rlim_max; status = setrlimit(RLIMIT_NOFILE, &nbr_files); if (status != 0) { - if (PrintMiscellaneous && (Verbose || WizardMode)) { - perror("os::init_2 setrlimit failed"); - } + log_info(os)("os::init_2 setrlimit failed: %s", os::strerror(errno)); } } } @@ -6026,7 +6008,22 @@ bool os::start_debugging(char *buf, int buflen) { return yes; } +static inline struct timespec get_mtime(const char* filename) { + struct stat st; + int ret = os::stat(filename, &st); + assert(ret == 0, "failed to stat() file '%s': %s", filename, strerror(errno)); + return st.st_mtim; +} +int os::compare_file_modified_times(const char* file1, const char* file2) { + struct timespec filetime1 = get_mtime(file1); + struct timespec filetime2 = get_mtime(file2); + int diff = filetime1.tv_sec - filetime2.tv_sec; + if (diff == 0) { + return filetime1.tv_nsec - filetime2.tv_nsec; + } + return diff; +} /////////////// Unit tests /////////////// diff --git a/hotspot/src/os/posix/vm/os_posix.cpp b/hotspot/src/os/posix/vm/os_posix.cpp index 6d683eec70674bf3c2806dd7f84c51f6cd4fd915..1c6efe5b5132902d246587b7626427baabada76c 100644 --- a/hotspot/src/os/posix/vm/os_posix.cpp +++ b/hotspot/src/os/posix/vm/os_posix.cpp @@ -181,6 +181,10 @@ int os::log_vsnprintf(char* buf, size_t len, const char* fmt, va_list args) { return vsnprintf(buf, len, fmt, args); } +int os::fileno(FILE* fp) { + return ::fileno(fp); +} + void os::Posix::print_load_average(outputStream* st) { st->print("load average:"); double loadavg[3]; diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index d64b56a3a5a7ebaeb02fc346fa916e8e7de6efa2..1d68dcc77211776f49fa558c4ddbf96929211730 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -161,6 +161,7 @@ address os::Solaris::handler_end; // end pc of thr_sighndlrinfo address os::Solaris::_main_stack_base = NULL; // 4352906 workaround +os::Solaris::pthread_setname_np_func_t os::Solaris::_pthread_setname_np = NULL; // "default" initializers for missing libc APIs extern "C" { @@ -441,8 +442,15 @@ static bool assign_distribution(processorid_t* id_array, } void os::set_native_thread_name(const char *name) { - // Not yet implemented. - return; + if (Solaris::_pthread_setname_np != NULL) { + // Only the first 31 bytes of 'name' are processed by pthread_setname_np + // but we explicitly copy into a size-limited buffer to avoid any + // possible overflow. + char buf[32]; + snprintf(buf, sizeof(buf), "%s", name); + buf[sizeof(buf) - 1] = '\0'; + Solaris::_pthread_setname_np(pthread_self(), buf); + } } bool os::distribute_processes(uint length, uint* distribution) { @@ -1819,6 +1827,19 @@ int os::stat(const char *path, struct stat *sbuf) { return ::stat(pathbuf, sbuf); } +static inline time_t get_mtime(const char* filename) { + struct stat st; + int ret = os::stat(filename, &st); + assert(ret == 0, "failed to stat() file '%s': %s", filename, strerror(errno)); + return st.st_mtime; +} + +int os::compare_file_modified_times(const char* file1, const char* file2) { + time_t t1 = get_mtime(file1); + time_t t2 = get_mtime(file2); + return t1 - t2; +} + static bool _print_ascii_file(const char* filename, outputStream* st) { int fd = ::open(filename, O_RDONLY); if (fd == -1) { @@ -2754,13 +2775,13 @@ char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr) { pd_unmap_memory(addr, bytes); } - if (PrintMiscellaneous && Verbose) { + if (log_is_enabled(Warning, os)) { char buf[256]; buf[0] = '\0'; if (addr == NULL) { jio_snprintf(buf, sizeof(buf), ": %s", os::strerror(err)); } - warning("attempt_reserve_memory_at: couldn't reserve " SIZE_FORMAT " bytes at " + log_info(os)("attempt_reserve_memory_at: couldn't reserve " SIZE_FORMAT " bytes at " PTR_FORMAT ": reserve_memory_helper returned " PTR_FORMAT "%s", bytes, requested_addr, addr, buf); } @@ -2790,9 +2811,7 @@ char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr) { assert(i > 0, "gap adjustment code problem"); have_adjusted_gap = true; // adjust the gap only once, just in case gap = actual_gap; - if (PrintMiscellaneous && Verbose) { - warning("attempt_reserve_memory_at: adjusted gap to 0x%lx", gap); - } + log_info(os)("attempt_reserve_memory_at: adjusted gap to 0x%lx", gap); unmap_memory(base[i], bytes); unmap_memory(base[i-1], size[i-1]); i-=2; @@ -2824,8 +2843,8 @@ char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr) { } else { size_t bottom_overlap = base[i] + bytes - requested_addr; if (bottom_overlap >= 0 && bottom_overlap < bytes) { - if (PrintMiscellaneous && Verbose && bottom_overlap == 0) { - warning("attempt_reserve_memory_at: possible alignment bug"); + if (bottom_overlap == 0) { + log_info(os)("attempt_reserve_memory_at: possible alignment bug"); } unmap_memory(requested_addr, bottom_overlap); size[i] = bytes - bottom_overlap; @@ -4355,8 +4374,8 @@ static pset_getloadavg_type pset_getloadavg_ptr = NULL; void init_pset_getloadavg_ptr(void) { pset_getloadavg_ptr = (pset_getloadavg_type)dlsym(RTLD_DEFAULT, "pset_getloadavg"); - if (PrintMiscellaneous && Verbose && pset_getloadavg_ptr == NULL) { - warning("pset_getloadavg function not found"); + if (pset_getloadavg_ptr == NULL) { + log_warning(os)("pset_getloadavg function not found"); } } @@ -4412,6 +4431,13 @@ void os::init(void) { // the minimum of what the OS supports (thr_min_stack()), and // enough to allow the thread to get to user bytecode execution. Solaris::min_stack_allowed = MAX2(thr_min_stack(), Solaris::min_stack_allowed); + + // retrieve entry point for pthread_setname_np + void * handle = dlopen("libc.so.1", RTLD_LAZY); + if (handle != NULL) { + Solaris::_pthread_setname_np = + (Solaris::pthread_setname_np_func_t)dlsym(handle, "pthread_setname_np"); + } } // To install functions for atexit system call @@ -4439,25 +4465,13 @@ jint os::init_2(void) { } os::set_polling_page(polling_page); - -#ifndef PRODUCT - if (Verbose && PrintMiscellaneous) { - tty->print("[SafePoint Polling address: " INTPTR_FORMAT "]\n", - (intptr_t)polling_page); - } -#endif + log_info(os)("SafePoint Polling address: " INTPTR_FORMAT, p2i(polling_page)); if (!UseMembar) { address mem_serialize_page = (address)Solaris::mmap_chunk(NULL, page_size, MAP_PRIVATE, PROT_READ | PROT_WRITE); guarantee(mem_serialize_page != NULL, "mmap Failed for memory serialize page"); os::set_memory_serialize_page(mem_serialize_page); - -#ifndef PRODUCT - if (Verbose && PrintMiscellaneous) { - tty->print("[Memory Serialize Page address: " INTPTR_FORMAT "]\n", - (intptr_t)mem_serialize_page); - } -#endif + log_info(os)("Memory Serialize Page address: " INTPTR_FORMAT, p2i(mem_serialize_page)); } // Check minimum allowable stack size for thread creation and to initialize @@ -4537,16 +4551,12 @@ jint os::init_2(void) { struct rlimit nbr_files; int status = getrlimit(RLIMIT_NOFILE, &nbr_files); if (status != 0) { - if (PrintMiscellaneous && (Verbose || WizardMode)) { - perror("os::init_2 getrlimit failed"); - } + log_info(os)("os::init_2 getrlimit failed: %s", os::strerror(errno)); } else { nbr_files.rlim_cur = nbr_files.rlim_max; status = setrlimit(RLIMIT_NOFILE, &nbr_files); if (status != 0) { - if (PrintMiscellaneous && (Verbose || WizardMode)) { - perror("os::init_2 setrlimit failed"); - } + log_info(os)("os::init_2 setrlimit failed: %s", os::strerror(errno)); } } } diff --git a/hotspot/src/os/solaris/vm/os_solaris.hpp b/hotspot/src/os/solaris/vm/os_solaris.hpp index 777e63c8f7563b588133fc740ea0a3e900dd765e..12f72247168b02632c4eaba69bc32894eb6907e7 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.hpp +++ b/hotspot/src/os/solaris/vm/os_solaris.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -122,6 +122,9 @@ class Solaris { static int _SIGasync; // user-overridable ASYNC_SIGNAL static void set_SIGasync(int newsig) { _SIGasync = newsig; } + typedef int (*pthread_setname_np_func_t)(pthread_t, const char*); + static pthread_setname_np_func_t _pthread_setname_np; + public: // Large Page Support--ISM. static bool largepage_range(char* addr, size_t size); diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index f85eb0f273c6cea5e98e0907f838a6185865eb4a..fa401527ed752f9195a0208d09622dc3a1c8b003 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -1594,6 +1594,19 @@ int os::log_vsnprintf(char* buf, size_t len, const char* fmt, va_list args) { return ret; } +static inline time_t get_mtime(const char* filename) { + struct stat st; + int ret = os::stat(filename, &st); + assert(ret == 0, "failed to stat() file '%s': %s", filename, strerror(errno)); + return st.st_mtime; +} + +int os::compare_file_modified_times(const char* file1, const char* file2) { + time_t t1 = get_mtime(file1); + time_t t2 = get_mtime(file2); + return t1 - t2; +} + void os::print_os_info_brief(outputStream* st) { os::print_os_info(st); } @@ -2436,14 +2449,10 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { bool res = os::protect_memory((char*) page_start, page_size, os::MEM_PROT_RWX); - if (PrintMiscellaneous && Verbose) { - char buf[256]; - jio_snprintf(buf, sizeof(buf), "Execution protection violation " - "at " INTPTR_FORMAT - ", unguarding " INTPTR_FORMAT ": %s", addr, - page_start, (res ? "success" : os::strerror(errno))); - tty->print_raw_cr(buf); - } + log_debug(os)("Execution protection violation " + "at " INTPTR_FORMAT + ", unguarding " INTPTR_FORMAT ": %s", p2i(addr), + p2i(page_start), (res ? "success" : os::strerror(errno))); // Set last_addr so if we fault again at the same address, we don't // end up in an endless loop. @@ -2896,12 +2905,12 @@ static bool numa_interleaving_init() { NUMAInterleaveGranularity = align_size_up(NUMAInterleaveGranularity, min_interleave_granularity); if (numa_node_list_holder.build()) { - if (PrintMiscellaneous && Verbose) { - tty->print("NUMA UsedNodeCount=%d, namely ", numa_node_list_holder.get_count()); + if (log_is_enabled(Debug, os, cpu)) { + Log(os, cpu) log; + log.debug("NUMA UsedNodeCount=%d, namely ", numa_node_list_holder.get_count()); for (int i = 0; i < numa_node_list_holder.get_count(); i++) { - tty->print("%d ", numa_node_list_holder.get_node_list_entry(i)); + log.debug(" %d ", numa_node_list_holder.get_node_list_entry(i)); } - tty->print("\n"); } success = true; } else { @@ -3010,9 +3019,7 @@ static char* allocate_pages_individually(size_t bytes, char* addr, DWORD flags, } #ifdef ASSERT if (should_inject_error) { - if (TracePageSizes && Verbose) { - tty->print_cr("Reserving pages individually failed."); - } + log_develop_debug(pagesize)("Reserving pages individually failed."); } #endif return NULL; @@ -3196,9 +3203,8 @@ char* os::reserve_memory_special(size_t bytes, size_t alignment, char* addr, // 1) the UseLargePagesIndividualAllocation flag is set (set by default on WS2003) // 2) NUMA Interleaving is enabled, in which case we use a different node for each page if (UseLargePagesIndividualAllocation || UseNUMAInterleaving) { - if (TracePageSizes && Verbose) { - tty->print_cr("Reserving large pages individually."); - } + log_debug(pagesize)("Reserving large pages individually."); + char * p_buf = allocate_pages_individually(bytes, addr, flags, prot, LargePagesIndividualAllocationInjectError); if (p_buf == NULL) { // give an appropriate warning message @@ -3215,9 +3221,8 @@ char* os::reserve_memory_special(size_t bytes, size_t alignment, char* addr, return p_buf; } else { - if (TracePageSizes && Verbose) { - tty->print_cr("Reserving large pages in a single large chunk."); - } + log_debug(pagesize)("Reserving large pages in a single large chunk."); + // normal policy just allocate it all at once DWORD flag = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES; char * res = (char *)VirtualAlloc(addr, bytes, flag, prot); @@ -4119,13 +4124,7 @@ jint os::init_2(void) { guarantee(return_page != NULL, "Commit Failed for polling page"); os::set_polling_page(polling_page); - -#ifndef PRODUCT - if (Verbose && PrintMiscellaneous) { - tty->print("[SafePoint Polling address: " INTPTR_FORMAT "]\n", - (intptr_t)polling_page); - } -#endif + log_info(os)("SafePoint Polling address: " INTPTR_FORMAT, p2i(polling_page)); if (!UseMembar) { address mem_serialize_page = (address)VirtualAlloc(NULL, os::vm_page_size(), MEM_RESERVE, PAGE_READWRITE); @@ -4135,13 +4134,7 @@ jint os::init_2(void) { guarantee(return_page != NULL, "Commit Failed for memory serialize page"); os::set_memory_serialize_page(mem_serialize_page); - -#ifndef PRODUCT - if (Verbose && PrintMiscellaneous) { - tty->print("[Memory Serialize Page address: " INTPTR_FORMAT "]\n", - (intptr_t)mem_serialize_page); - } -#endif + log_info(os)("Memory Serialize Page address: " INTPTR_FORMAT, p2i(mem_serialize_page)); } // Setup Windows Exceptions @@ -4609,6 +4602,9 @@ int os::ftruncate(int fd, jlong length) { return 0; } +int os::fileno(FILE* fp) { + return _fileno(fp); +} // This code is a copy of JDK's sysSync // from src/windows/hpi/src/sys_api_md.c @@ -4769,10 +4765,7 @@ char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset, hFile = CreateFile(file_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == NULL) { - if (PrintMiscellaneous && Verbose) { - DWORD err = GetLastError(); - tty->print_cr("CreateFile() failed: GetLastError->%ld.", err); - } + log_info(os)("CreateFile() failed: GetLastError->%ld.", GetLastError()); return NULL; } @@ -4790,10 +4783,7 @@ char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset, base = (char*) VirtualAlloc(addr, bytes, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); if (base == NULL) { - if (PrintMiscellaneous && Verbose) { - DWORD err = GetLastError(); - tty->print_cr("VirtualAlloc() failed: GetLastError->%ld.", err); - } + log_info(os)("VirtualAlloc() failed: GetLastError->%ld.", GetLastError()); CloseHandle(hFile); return NULL; } @@ -4807,10 +4797,7 @@ char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset, // number of bytes were read before returning. bool res = ReadFile(hFile, base, (DWORD)bytes, &bytes_read, &overlapped) != 0; if (!res) { - if (PrintMiscellaneous && Verbose) { - DWORD err = GetLastError(); - tty->print_cr("ReadFile() failed: GetLastError->%ld.", err); - } + log_info(os)("ReadFile() failed: GetLastError->%ld.", GetLastError()); release_memory(base, bytes); CloseHandle(hFile); return NULL; @@ -4819,10 +4806,7 @@ char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset, HANDLE hMap = CreateFileMapping(hFile, NULL, PAGE_WRITECOPY, 0, 0, NULL /* file_name */); if (hMap == NULL) { - if (PrintMiscellaneous && Verbose) { - DWORD err = GetLastError(); - tty->print_cr("CreateFileMapping() failed: GetLastError->%ld.", err); - } + log_info(os)("CreateFileMapping() failed: GetLastError->%ld.", GetLastError()); CloseHandle(hFile); return NULL; } @@ -4831,20 +4815,14 @@ char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset, base = (char*)MapViewOfFileEx(hMap, access, 0, (DWORD)file_offset, (DWORD)bytes, addr); if (base == NULL) { - if (PrintMiscellaneous && Verbose) { - DWORD err = GetLastError(); - tty->print_cr("MapViewOfFileEx() failed: GetLastError->%ld.", err); - } + log_info(os)("MapViewOfFileEx() failed: GetLastError->%ld.", GetLastError()); CloseHandle(hMap); CloseHandle(hFile); return NULL; } if (CloseHandle(hMap) == 0) { - if (PrintMiscellaneous && Verbose) { - DWORD err = GetLastError(); - tty->print_cr("CloseHandle(hMap) failed: GetLastError->%ld.", err); - } + log_info(os)("CloseHandle(hMap) failed: GetLastError->%ld.", GetLastError()); CloseHandle(hFile); return base; } @@ -4856,10 +4834,7 @@ char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset, bool res = VirtualProtect(base, bytes, exec_access, &old_protect) != 0; if (!res) { - if (PrintMiscellaneous && Verbose) { - DWORD err = GetLastError(); - tty->print_cr("VirtualProtect() failed: GetLastError->%ld.", err); - } + log_info(os)("VirtualProtect() failed: GetLastError->%ld.", GetLastError()); // Don't consider this a hard error, on IA32 even if the // VirtualProtect fails, we should still be able to execute CloseHandle(hFile); @@ -4868,10 +4843,7 @@ char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset, } if (CloseHandle(hFile) == 0) { - if (PrintMiscellaneous && Verbose) { - DWORD err = GetLastError(); - tty->print_cr("CloseHandle(hFile) failed: GetLastError->%ld.", err); - } + log_info(os)("CloseHandle(hFile) failed: GetLastError->%ld.", GetLastError()); return base; } @@ -4904,10 +4876,7 @@ char* os::pd_remap_memory(int fd, const char* file_name, size_t file_offset, bool os::pd_unmap_memory(char* addr, size_t bytes) { MEMORY_BASIC_INFORMATION mem_info; if (VirtualQuery(addr, &mem_info, sizeof(mem_info)) == 0) { - if (PrintMiscellaneous && Verbose) { - DWORD err = GetLastError(); - tty->print_cr("VirtualQuery() failed: GetLastError->%ld.", err); - } + log_info(os)("VirtualQuery() failed: GetLastError->%ld.", GetLastError()); return false; } @@ -4924,10 +4893,7 @@ bool os::pd_unmap_memory(char* addr, size_t bytes) { BOOL result = UnmapViewOfFile(addr); if (result == 0) { - if (PrintMiscellaneous && Verbose) { - DWORD err = GetLastError(); - tty->print_cr("UnmapViewOfFile() failed: GetLastError->%ld.", err); - } + log_info(os)("UnmapViewOfFile() failed: GetLastError->%ld.", GetLastError()); return false; } return true; diff --git a/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp b/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp index f109a111047b22b9b186346184cb41ff7d9837ca..537595f95ad933df3dd68e661c17be29d2d6d867 100644 --- a/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp +++ b/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2014 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -184,9 +184,7 @@ JVM_handle_aix_signal(int sig, siginfo_t* info, void* ucVoid, int abort_if_unrec if (os::Aix::chained_handler(sig, info, ucVoid)) { return 1; } else { - if (PrintMiscellaneous && (WizardMode || Verbose)) { - warning("Ignoring SIGPIPE - see bug 4229104"); - } + // Ignoring SIGPIPE - see bugs 4229104 return 1; } } diff --git a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp index f8e7dc509b9d61937dfc2cc5fd4f5fa296ab2387..73acdebfb47e11f11f09bec1a2541282e521bbf9 100644 --- a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp +++ b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -469,11 +469,7 @@ JVM_handle_bsd_signal(int sig, if (os::Bsd::chained_handler(sig, info, ucVoid)) { return true; } else { - if (PrintMiscellaneous && (WizardMode || Verbose)) { - char buf[64]; - warning("Ignoring %s - see bugs 4229104 or 646499219", - os::exception_name(sig, buf, sizeof(buf))); - } + // Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219 return true; } } @@ -728,14 +724,10 @@ JVM_handle_bsd_signal(int sig, bool res = os::protect_memory((char*) page_start, page_size, os::MEM_PROT_RWX); - if (PrintMiscellaneous && Verbose) { - char buf[256]; - jio_snprintf(buf, sizeof(buf), "Execution protection violation " - "at " INTPTR_FORMAT - ", unguarding " INTPTR_FORMAT ": %s, errno=%d", addr, - page_start, (res ? "success" : "failed"), errno); - tty->print_raw_cr(buf); - } + log_debug(os)("Execution protection violation " + "at " INTPTR_FORMAT + ", unguarding " INTPTR_FORMAT ": %s, errno=%d", p2i(addr), + p2i(page_start), (res ? "success" : "failed"), errno); stub = pc; // Set last_addr so if we fault again at the same address, we don't end diff --git a/hotspot/src/os_cpu/bsd_x86/vm/thread_bsd_x86.cpp b/hotspot/src/os_cpu/bsd_x86/vm/thread_bsd_x86.cpp index c4f991aa65025e51876cc8aa36701e94bf88848b..df36e6edbe1ac34e2bf14bdcfe8231a5de9cdaa1 100644 --- a/hotspot/src/os_cpu/bsd_x86/vm/thread_bsd_x86.cpp +++ b/hotspot/src/os_cpu/bsd_x86/vm/thread_bsd_x86.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "memory/metaspaceShared.hpp" #include "runtime/frame.inline.hpp" #include "runtime/thread.inline.hpp" @@ -64,6 +65,14 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) return false; } +#if INCLUDE_CDS + if (UseSharedSpaces && MetaspaceShared::is_in_shared_region(addr.pc(), MetaspaceShared::md)) { + // In the middle of a trampoline call. Bail out for safety. + // This happens rarely so shouldn't affect profiling. + return false; + } +#endif + frame ret_frame(ret_sp, ret_fp, addr.pc()); if (!ret_frame.safe_for_sender(jt)) { #if defined(COMPILER2) || INCLUDE_JVMCI diff --git a/hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp b/hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp index c3801dfab64ad0023123ec6b96ae1a6c049b300b..72d57858e0945497e47594389d1157a3ca694b6e 100644 --- a/hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp +++ b/hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2009, 2010 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -159,11 +159,7 @@ JVM_handle_bsd_signal(int sig, if (os::Bsd::chained_handler(sig, info, ucVoid)) { return true; } else { - if (PrintMiscellaneous && (WizardMode || Verbose)) { - char buf[64]; - warning("Ignoring %s - see bugs 4229104 or 646499219", - os::exception_name(sig, buf, sizeof(buf))); - } + // Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219 return true; } } diff --git a/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp b/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp index 4e47e27628fcb02238f142036aeee6f77af48a59..2a354fbb72ce74f0c6afb9c6e1c11530c7a46e88 100644 --- a/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp +++ b/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -270,11 +270,7 @@ JVM_handle_linux_signal(int sig, if (os::Linux::chained_handler(sig, info, ucVoid)) { return true; } else { - if (PrintMiscellaneous && (WizardMode || Verbose)) { - char buf[64]; - warning("Ignoring %s - see bugs 4229104 or 646499219", - os::exception_name(sig, buf, sizeof(buf))); - } + // Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219 return true; } } diff --git a/hotspot/src/os_cpu/linux_aarch64/vm/thread_linux_aarch64.cpp b/hotspot/src/os_cpu/linux_aarch64/vm/thread_linux_aarch64.cpp index cd6f71efe2c0a575643b0b431c24924d7bc158d3..07206d873d705ea3ed6c66fb90b6f52fe3e89346 100644 --- a/hotspot/src/os_cpu/linux_aarch64/vm/thread_linux_aarch64.cpp +++ b/hotspot/src/os_cpu/linux_aarch64/vm/thread_linux_aarch64.cpp @@ -24,6 +24,7 @@ */ #include "precompiled.hpp" +#include "memory/metaspaceShared.hpp" #include "runtime/frame.inline.hpp" #include "runtime/thread.inline.hpp" @@ -66,6 +67,14 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) return false; } +#if INCLUDE_CDS + if (UseSharedSpaces && MetaspaceShared::is_in_shared_region(addr.pc(), MetaspaceShared::md)) { + // In the middle of a trampoline call. Bail out for safety. + // This happens rarely so shouldn't affect profiling. + return false; + } +#endif + frame ret_frame(ret_sp, ret_fp, addr.pc()); if (!ret_frame.safe_for_sender(jt)) { #ifdef COMPILER2 diff --git a/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp b/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp index b7318c22c08e82a3188b9f63bffe4833ba3443ba..117bf1067f3e8612239c9b54d002c4b5417f779c 100644 --- a/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp +++ b/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2015 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -198,9 +198,7 @@ JVM_handle_linux_signal(int sig, if (os::Linux::chained_handler(sig, info, ucVoid)) { return true; } else { - if (PrintMiscellaneous && (WizardMode || Verbose)) { - warning("Ignoring SIGPIPE - see bug 4229104"); - } + // Ignoring SIGPIPE - see bugs 4229104 return true; } } diff --git a/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp b/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp index 30b321dc228ae08ebccf4c5e35b8a617e2c9501f..44a5a7df1f9e60121b17ac7099a4bcd0d9c7b65e 100644 --- a/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp +++ b/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -561,11 +561,7 @@ JVM_handle_linux_signal(int sig, if (os::Linux::chained_handler(sig, info, ucVoid)) { return true; } else { - if (PrintMiscellaneous && (WizardMode || Verbose)) { - char buf[64]; - warning("Ignoring %s - see bugs 4229104 or 646499219", - os::exception_name(sig, buf, sizeof(buf))); - } + // Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219 return true; } } diff --git a/hotspot/src/os_cpu/linux_sparc/vm/thread_linux_sparc.cpp b/hotspot/src/os_cpu/linux_sparc/vm/thread_linux_sparc.cpp index dac85519a0cc3f239c4b8a476e7855cbdf720003..c571507e675edbad795ebb73f3e8dce610023696 100644 --- a/hotspot/src/os_cpu/linux_sparc/vm/thread_linux_sparc.cpp +++ b/hotspot/src/os_cpu/linux_sparc/vm/thread_linux_sparc.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "memory/metaspaceShared.hpp" #include "runtime/frame.inline.hpp" #include "runtime/thread.inline.hpp" @@ -64,6 +65,14 @@ bool JavaThread::pd_get_top_frame_for_signal_handler(frame* fr_addr, return false; } +#if INCLUDE_CDS + if (UseSharedSpaces && MetaspaceShared::is_in_shared_region(addr.pc(), MetaspaceShared::md)) { + // In the middle of a trampoline call. Bail out for safety. + // This happens rarely so shouldn't affect profiling. + return false; + } +#endif + // we were running Java code when SIGPROF came in if (isInJava) { // If we have a last_Java_sp, then the SIGPROF signal caught us diff --git a/hotspot/src/os_cpu/linux_sparc/vm/vm_version_linux_sparc.cpp b/hotspot/src/os_cpu/linux_sparc/vm/vm_version_linux_sparc.cpp index f9c596e4d79f08c555d3fc34f7ee38a862ad17a2..c6bb5033db632259df22f7e6402a5e51c8773049 100644 --- a/hotspot/src/os_cpu/linux_sparc/vm/vm_version_linux_sparc.cpp +++ b/hotspot/src/os_cpu/linux_sparc/vm/vm_version_linux_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -66,12 +66,12 @@ int VM_Version::platform_features(int features) { features = generic_v9_m; if (detect_niagara()) { - if (PrintMiscellaneous && Verbose) { tty->print_cr("Detected Linux on Niagara"); } + log_info(os, cpu)("Detected Linux on Niagara"); features = niagara1_m | T_family_m; } if (detect_M_family()) { - if (PrintMiscellaneous && Verbose) { tty->print_cr("Detected Linux on M family"); } + log_info(os, cpu)("Detected Linux on M family"); features = sun4v_m | generic_v9_m | M_family_m | T_family_m; } diff --git a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp index ec6ba97235af4622c46b9c6a1cb55ed8cda8b110..0eb7a9e511fba5ffd16317a7692df107778b3eeb 100644 --- a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp +++ b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -287,11 +287,7 @@ JVM_handle_linux_signal(int sig, if (os::Linux::chained_handler(sig, info, ucVoid)) { return true; } else { - if (PrintMiscellaneous && (WizardMode || Verbose)) { - char buf[64]; - warning("Ignoring %s - see bugs 4229104 or 646499219", - os::exception_name(sig, buf, sizeof(buf))); - } + // Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219 return true; } } @@ -542,14 +538,10 @@ JVM_handle_linux_signal(int sig, bool res = os::protect_memory((char*) page_start, page_size, os::MEM_PROT_RWX); - if (PrintMiscellaneous && Verbose) { - char buf[256]; - jio_snprintf(buf, sizeof(buf), "Execution protection violation " - "at " INTPTR_FORMAT - ", unguarding " INTPTR_FORMAT ": %s, errno=%d", addr, - page_start, (res ? "success" : "failed"), errno); - tty->print_raw_cr(buf); - } + log_debug(os)("Execution protection violation " + "at " INTPTR_FORMAT + ", unguarding " INTPTR_FORMAT ": %s, errno=%d", p2i(addr), + p2i(page_start), (res ? "success" : "failed"), errno); stub = pc; // Set last_addr so if we fault again at the same address, we don't end @@ -645,12 +637,8 @@ bool os::supports_sse() { int major = strtol(uts.release,&minor_string,10); int minor = strtol(minor_string+1,NULL,10); bool result = (major > 2 || (major==2 && minor >= 4)); -#ifndef PRODUCT - if (PrintMiscellaneous && Verbose) { - tty->print("OS version is %d.%d, which %s support SSE/SSE2\n", + log_info(os)("OS version is %d.%d, which %s support SSE/SSE2", major,minor, result ? "DOES" : "does NOT"); - } -#endif return result; #endif // AMD64 } @@ -939,9 +927,7 @@ void os::workaround_expand_exec_shield_cs_limit() { MemTracker::record_virtual_memory_type((address)codebuf, mtInternal); - if (PrintMiscellaneous && (Verbose || WizardMode)) { - tty->print_cr("[CS limit NX emulation work-around, exec code at: %p]", codebuf); - } + log_info(os)("[CS limit NX emulation work-around, exec code at: %p]", codebuf); // Some code to exec: the 'ret' instruction codebuf[0] = 0xC3; diff --git a/hotspot/src/os_cpu/linux_x86/vm/thread_linux_x86.cpp b/hotspot/src/os_cpu/linux_x86/vm/thread_linux_x86.cpp index 55e5bbac4e281ce6d093d1be3286fd59c1dc0a64..3075dd19dd366c197947a4bcaeeacc36847da389 100644 --- a/hotspot/src/os_cpu/linux_x86/vm/thread_linux_x86.cpp +++ b/hotspot/src/os_cpu/linux_x86/vm/thread_linux_x86.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "memory/metaspaceShared.hpp" #include "runtime/frame.inline.hpp" #include "runtime/thread.inline.hpp" @@ -65,6 +66,14 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) return false; } +#if INCLUDE_CDS + if (UseSharedSpaces && MetaspaceShared::is_in_shared_region(addr.pc(), MetaspaceShared::md)) { + // In the middle of a trampoline call. Bail out for safety. + // This happens rarely so shouldn't affect profiling. + return false; + } +#endif + frame ret_frame(ret_sp, ret_fp, addr.pc()); if (!ret_frame.safe_for_sender(jt)) { #if defined(COMPILER2) || INCLUDE_JVMCI diff --git a/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp b/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp index b1e93a82dc81521bdfb19bb24c9660479fc5bcc6..abd5296197682834febbd148290a3ee37d9d1163 100644 --- a/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp +++ b/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp @@ -154,11 +154,7 @@ JVM_handle_linux_signal(int sig, if (os::Linux::chained_handler(sig, info, ucVoid)) { return true; } else { - if (PrintMiscellaneous && (WizardMode || Verbose)) { - char buf[64]; - warning("Ignoring %s - see bugs 4229104 or 646499219", - os::exception_name(sig, buf, sizeof(buf))); - } + // Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219 return true; } } diff --git a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp index f6a8ad3d53d493594e85a46ea2930551d251d120..389f2b3a59dbe63d5d26531f613214c438a436b2 100644 --- a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp +++ b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -338,12 +338,7 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid, if (os::Solaris::chained_handler(sig, info, ucVoid)) { return true; } else { - if (PrintMiscellaneous && (WizardMode || Verbose)) { - char buf[64]; - warning("Ignoring %s - see 4229104 or 6499219", - os::exception_name(sig, buf, sizeof(buf))); - - } + // Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219 return true; } } diff --git a/hotspot/src/os_cpu/solaris_sparc/vm/thread_solaris_sparc.cpp b/hotspot/src/os_cpu/solaris_sparc/vm/thread_solaris_sparc.cpp index 9964114a78702a2b58d45feae3298b8bc36d5d6e..ddbaa7020636bf7be1c6027510c2b885f3e9ef2a 100644 --- a/hotspot/src/os_cpu/solaris_sparc/vm/thread_solaris_sparc.cpp +++ b/hotspot/src/os_cpu/solaris_sparc/vm/thread_solaris_sparc.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "memory/metaspaceShared.hpp" #include "runtime/frame.inline.hpp" #include "runtime/thread.inline.hpp" @@ -77,6 +78,14 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, return false; } +#if INCLUDE_CDS + if (UseSharedSpaces && MetaspaceShared::is_in_shared_region(addr.pc(), MetaspaceShared::md)) { + // In the middle of a trampoline call. Bail out for safety. + // This happens rarely so shouldn't affect profiling. + return false; + } +#endif + frame ret_frame(ret_sp, frame::unpatchable, addr.pc()); // we were running Java code when SIGPROF came in diff --git a/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp b/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp index 837607e6781c1bbfd59ae66a3280116b3973ceb5..def37cd0b635cc13061f3bac7b0ce8ecb53b9d6e 100644 --- a/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp +++ b/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "logging/log.hpp" #include "memory/allocation.hpp" #include "memory/allocation.inline.hpp" #include "runtime/os.hpp" @@ -361,15 +362,10 @@ int VM_Version::platform_features(int features) { assert(avn <= 2, "should return two or less av's"); uint_t av = avs[0]; -#ifndef PRODUCT - if (PrintMiscellaneous && Verbose) { - tty->print("getisax(2) returned: " PTR32_FORMAT, av); - if (avn > 1) { - tty->print(", " PTR32_FORMAT, avs[1]); - } - tty->cr(); + log_info(os, cpu)("getisax(2) returned: " PTR32_FORMAT, av); + if (avn > 1) { + log_info(os, cpu)(" " PTR32_FORMAT, avs[1]); } -#endif if (av & AV_SPARC_MUL32) features |= hardware_mul32_m; if (av & AV_SPARC_DIV32) features |= hardware_div32_m; @@ -464,11 +460,7 @@ int VM_Version::platform_features(int features) { if (strcmp((const char*)&(knm[i].name),"implementation") == 0) { implementation = KSTAT_NAMED_STR_PTR(&knm[i]); has_implementation = true; -#ifndef PRODUCT - if (PrintMiscellaneous && Verbose) { - tty->print_cr("cpu_info.implementation: %s", implementation); - } -#endif + log_info(os, cpu)("cpu_info.implementation: %s", implementation); features |= parse_features(implementation); break; } diff --git a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp index 79a7f19a281c3a56a6197118729a970568011e47..0784f3f25f7f42941ed0bdb2826d89438d47428e 100644 --- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp +++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -403,12 +403,7 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid, if (os::Solaris::chained_handler(sig, info, ucVoid)) { return true; } else { - if (PrintMiscellaneous && (WizardMode || Verbose)) { - char buf[64]; - warning("Ignoring %s - see 4229104 or 6499219", - os::exception_name(sig, buf, sizeof(buf))); - - } + // Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219 return true; } } @@ -640,14 +635,10 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid, bool res = os::protect_memory((char*) page_start, page_size, os::MEM_PROT_RWX); - if (PrintMiscellaneous && Verbose) { - char buf[256]; - jio_snprintf(buf, sizeof(buf), "Execution protection violation " - "at " INTPTR_FORMAT - ", unguarding " INTPTR_FORMAT ": %s, errno=%d", addr, - page_start, (res ? "success" : "failed"), errno); - tty->print_raw_cr(buf); - } + log_debug(os)("Execution protection violation " + "at " INTPTR_FORMAT + ", unguarding " INTPTR_FORMAT ": %s, errno=%d", p2i(addr), + p2i(page_start), (res ? "success" : "failed"), errno); stub = pc; // Set last_addr so if we fault again at the same address, we don't end diff --git a/hotspot/src/os_cpu/solaris_x86/vm/thread_solaris_x86.cpp b/hotspot/src/os_cpu/solaris_x86/vm/thread_solaris_x86.cpp index d41f3e7167f7e4fa5b42db5c1b2ce66e1d613cbb..48af49f7497aa34f3596a7633e7dd39fcd8921be 100644 --- a/hotspot/src/os_cpu/solaris_x86/vm/thread_solaris_x86.cpp +++ b/hotspot/src/os_cpu/solaris_x86/vm/thread_solaris_x86.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "memory/metaspaceShared.hpp" #include "runtime/frame.inline.hpp" #include "runtime/thread.inline.hpp" @@ -70,6 +71,14 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, return false; } +#if INCLUDE_CDS + if (UseSharedSpaces && MetaspaceShared::is_in_shared_region(addr.pc(), MetaspaceShared::md)) { + // In the middle of a trampoline call. Bail out for safety. + // This happens rarely so shouldn't affect profiling. + return false; + } +#endif + // If sp and fp are nonsense just leave them out if (!jt->on_local_stack((address)ret_sp)) { diff --git a/hotspot/src/os_cpu/windows_x86/vm/thread_windows_x86.cpp b/hotspot/src/os_cpu/windows_x86/vm/thread_windows_x86.cpp index 08afec248349137b27e7364286d1e0edd0893bee..ba5be5736cf014515d7becb3bf54ed6dbfd806c8 100644 --- a/hotspot/src/os_cpu/windows_x86/vm/thread_windows_x86.cpp +++ b/hotspot/src/os_cpu/windows_x86/vm/thread_windows_x86.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "memory/metaspaceShared.hpp" #include "runtime/frame.inline.hpp" #include "runtime/thread.inline.hpp" @@ -72,6 +73,14 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) return false; } +#if INCLUDE_CDS + if (UseSharedSpaces && MetaspaceShared::is_in_shared_region(addr.pc(), MetaspaceShared::md)) { + // In the middle of a trampoline call. Bail out for safety. + // This happens rarely so shouldn't affect profiling. + return false; + } +#endif + frame ret_frame(ret_sp, ret_fp, addr.pc()); if (!ret_frame.safe_for_sender(jt)) { #if defined(COMPILER2) || INCLUDE_JVMCI diff --git a/hotspot/src/share/vm/asm/assembler.hpp b/hotspot/src/share/vm/asm/assembler.hpp index 40bd5d379e04b944335fb95798a900923093896c..2ef9d993721777d5a7ffbefe367d215b6fd2e84f 100644 --- a/hotspot/src/share/vm/asm/assembler.hpp +++ b/hotspot/src/share/vm/asm/assembler.hpp @@ -33,7 +33,6 @@ #include "runtime/vm_version.hpp" #include "utilities/debug.hpp" #include "utilities/growableArray.hpp" -#include "utilities/top.hpp" // This file contains platform-independent assembler declarations. diff --git a/hotspot/src/share/vm/asm/register.hpp b/hotspot/src/share/vm/asm/register.hpp index 5e43cfa68fdc43b0661fffbc534630afda25a2fd..e258e867c1d05cc8dec3361165f0de733ff48657 100644 --- a/hotspot/src/share/vm/asm/register.hpp +++ b/hotspot/src/share/vm/asm/register.hpp @@ -25,7 +25,8 @@ #ifndef SHARE_VM_ASM_REGISTER_HPP #define SHARE_VM_ASM_REGISTER_HPP -#include "utilities/top.hpp" +#include "utilities/debug.hpp" +#include "utilities/globalDefinitions.hpp" // Use AbstractRegister as shortcut class AbstractRegisterImpl; diff --git a/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp b/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp index c4a084a451877d683538fe8b9e46c7160917b6cf..2b01e3ae04c88c63d52f25a31c82a0d803f77798 100644 --- a/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp +++ b/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp @@ -305,7 +305,8 @@ void Canonicalizer::do_StoreIndexed (StoreIndexed* x) { // limit this optimization to current block if (value != NULL && in_current_block(conv)) { set_canonical(new StoreIndexed(x->array(), x->index(), x->length(), - x->elt_type(), value, x->state_before())); + x->elt_type(), value, x->state_before(), + x->check_boolean())); return; } } diff --git a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp index 172e26eb4d916a68b2fbe38e50f5ac69fdcc0b7e..7eacc2c952db38f760408fba4ccfc536505a659d 100644 --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp @@ -976,7 +976,19 @@ void GraphBuilder::store_indexed(BasicType type) { (array->as_NewArray() && array->as_NewArray()->length() && array->as_NewArray()->length()->type()->is_constant())) { length = append(new ArrayLength(array, state_before)); } - StoreIndexed* result = new StoreIndexed(array, index, length, type, value, state_before); + ciType* array_type = array->declared_type(); + bool check_boolean = false; + if (array_type != NULL) { + if (array_type->is_loaded() && + array_type->as_array_klass()->element_type()->basic_type() == T_BOOLEAN) { + assert(type == T_BYTE, "boolean store uses bastore"); + Value mask = append(new Constant(new IntConstant(1))); + value = append(new LogicOp(Bytecodes::_iand, value, mask)); + } + } else if (type == T_BYTE) { + check_boolean = true; + } + StoreIndexed* result = new StoreIndexed(array, index, length, type, value, state_before, check_boolean); append(result); _memory->store_value(value); @@ -1443,6 +1455,36 @@ void GraphBuilder::method_return(Value x) { need_mem_bar = true; } + BasicType bt = method()->return_type()->basic_type(); + switch (bt) { + case T_BYTE: + { + Value shift = append(new Constant(new IntConstant(24))); + x = append(new ShiftOp(Bytecodes::_ishl, x, shift)); + x = append(new ShiftOp(Bytecodes::_ishr, x, shift)); + break; + } + case T_SHORT: + { + Value shift = append(new Constant(new IntConstant(16))); + x = append(new ShiftOp(Bytecodes::_ishl, x, shift)); + x = append(new ShiftOp(Bytecodes::_ishr, x, shift)); + break; + } + case T_CHAR: + { + Value mask = append(new Constant(new IntConstant(0xFFFF))); + x = append(new LogicOp(Bytecodes::_iand, x, mask)); + break; + } + case T_BOOLEAN: + { + Value mask = append(new Constant(new IntConstant(1))); + x = append(new LogicOp(Bytecodes::_iand, x, mask)); + break; + } + } + // Check to see whether we are inlining. If so, Return // instructions become Gotos to the continuation point. if (continuation() != NULL) { @@ -1611,6 +1653,10 @@ void GraphBuilder::access_field(Bytecodes::Code code) { if (state_before == NULL) { state_before = copy_state_for_exception(); } + if (field->type()->basic_type() == T_BOOLEAN) { + Value mask = append(new Constant(new IntConstant(1))); + val = append(new LogicOp(Bytecodes::_iand, val, mask)); + } append(new StoreField(append(obj), offset, field, val, true, state_before, needs_patching)); break; } @@ -1672,6 +1718,10 @@ void GraphBuilder::access_field(Bytecodes::Code code) { if (state_before == NULL) { state_before = copy_state_for_exception(); } + if (field->type()->basic_type() == T_BOOLEAN) { + Value mask = append(new Constant(new IntConstant(1))); + val = append(new LogicOp(Bytecodes::_iand, val, mask)); + } StoreField* store = new StoreField(obj, offset, field, val, false, state_before, needs_patching); if (!needs_patching) store = _memory->store(store); if (store != NULL) { @@ -4134,7 +4184,12 @@ void GraphBuilder::append_unsafe_put_obj(ciMethod* callee, BasicType t, bool is_ #ifndef _LP64 offset = append(new Convert(Bytecodes::_l2i, offset, as_ValueType(T_INT))); #endif - Instruction* op = append(new UnsafePutObject(t, args->at(1), offset, args->at(3), is_volatile)); + Value val = args->at(3); + if (t == T_BOOLEAN) { + Value mask = append(new Constant(new IntConstant(1))); + val = append(new LogicOp(Bytecodes::_iand, val, mask)); + } + Instruction* op = append(new UnsafePutObject(t, args->at(1), offset, val, is_volatile)); compilation()->set_has_unsafe_access(true); kill_all(); } @@ -4208,7 +4263,7 @@ void GraphBuilder::append_char_access(ciMethod* callee, bool is_store) { Value index = args->at(1); if (is_store) { Value value = args->at(2); - Instruction* store = append(new StoreIndexed(array, index, NULL, T_CHAR, value, state_before)); + Instruction* store = append(new StoreIndexed(array, index, NULL, T_CHAR, value, state_before, false)); store->set_flag(Instruction::NeedsRangeCheckFlag, false); _memory->store_value(value); } else { diff --git a/hotspot/src/share/vm/c1/c1_Instruction.hpp b/hotspot/src/share/vm/c1/c1_Instruction.hpp index 8f6bf233f3dd776cf2f0af1ee55758fff803ebf8..38fcc56ae754bbdab873cebb20381f372c2a4bb1 100644 --- a/hotspot/src/share/vm/c1/c1_Instruction.hpp +++ b/hotspot/src/share/vm/c1/c1_Instruction.hpp @@ -974,11 +974,13 @@ LEAF(StoreIndexed, AccessIndexed) ciMethod* _profiled_method; int _profiled_bci; + bool _check_boolean; + public: // creation - StoreIndexed(Value array, Value index, Value length, BasicType elt_type, Value value, ValueStack* state_before) + StoreIndexed(Value array, Value index, Value length, BasicType elt_type, Value value, ValueStack* state_before, bool check_boolean) : AccessIndexed(array, index, length, elt_type, state_before) - , _value(value), _profiled_method(NULL), _profiled_bci(0) + , _value(value), _profiled_method(NULL), _profiled_bci(0), _check_boolean(check_boolean) { set_flag(NeedsWriteBarrierFlag, (as_ValueType(elt_type)->is_object())); set_flag(NeedsStoreCheckFlag, (as_ValueType(elt_type)->is_object())); @@ -990,6 +992,7 @@ LEAF(StoreIndexed, AccessIndexed) Value value() const { return _value; } bool needs_write_barrier() const { return check_flag(NeedsWriteBarrierFlag); } bool needs_store_check() const { return check_flag(NeedsStoreCheckFlag); } + bool check_boolean() const { return _check_boolean; } // Helpers for MethodData* profiling void set_should_profile(bool value) { set_flag(ProfileMDOFlag, value); } void set_profiled_method(ciMethod* method) { _profiled_method = method; } diff --git a/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp b/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp index 8c2c97ece41e01ddfaf13dbdf9b7341d20741bd1..42e6f6642d3698f1b56fd95169c007f0dbd194bf 100644 --- a/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp +++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp @@ -28,7 +28,6 @@ #include "c1/c1_CodeStubs.hpp" #include "ci/ciMethodData.hpp" #include "oops/methodData.hpp" -#include "utilities/top.hpp" class Compilation; class ScopeValue; diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp index 3c8454e5260adfbbf2de5471f409c6376f58c04f..956bb657ed6f38fa1718313ea282718be4d54753 100644 --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp @@ -3680,3 +3680,26 @@ void LIRGenerator::do_MemBar(MemBar* x) { } } } + +LIR_Opr LIRGenerator::maybe_mask_boolean(StoreIndexed* x, LIR_Opr array, LIR_Opr value, CodeEmitInfo*& null_check_info) { + if (x->check_boolean()) { + LIR_Opr value_fixed = rlock_byte(T_BYTE); + if (TwoOperandLIRForm) { + __ move(value, value_fixed); + __ logical_and(value_fixed, LIR_OprFact::intConst(1), value_fixed); + } else { + __ logical_and(value, LIR_OprFact::intConst(1), value_fixed); + } + LIR_Opr klass = new_register(T_METADATA); + __ move(new LIR_Address(array, oopDesc::klass_offset_in_bytes(), T_ADDRESS), klass, null_check_info); + null_check_info = NULL; + LIR_Opr layout = new_register(T_INT); + __ move(new LIR_Address(klass, in_bytes(Klass::layout_helper_offset()), T_INT), layout); + int diffbit = Klass::layout_helper_boolean_diffbit(); + __ logical_and(layout, LIR_OprFact::intConst(diffbit), layout); + __ cmp(lir_cond_notEqual, layout, LIR_OprFact::intConst(0)); + __ cmove(lir_cond_notEqual, value_fixed, value, value_fixed, T_BYTE); + value = value_fixed; + } + return value; +} diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp index bf36d7dc10e81589e4da2186cff374bc22215a6f..6885ff6186c5caaf89063cfc10de65b0e0f64003 100644 --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp @@ -448,6 +448,7 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure { void profile_arguments(ProfileCall* x); void profile_parameters(Base* x); void profile_parameters_at_call(ProfileCall* x); + LIR_Opr maybe_mask_boolean(StoreIndexed* x, LIR_Opr array, LIR_Opr value, CodeEmitInfo*& null_check_info); public: Compilation* compilation() const { return _compilation; } diff --git a/hotspot/src/share/vm/ci/ciFlags.hpp b/hotspot/src/share/vm/ci/ciFlags.hpp index 60d5632f4bb374797784e228a036297f2970f35e..783064253c133b82b88d08005425fc38c8e91f80 100644 --- a/hotspot/src/share/vm/ci/ciFlags.hpp +++ b/hotspot/src/share/vm/ci/ciFlags.hpp @@ -29,6 +29,7 @@ #include "memory/allocation.hpp" #include "prims/jvm.h" #include "utilities/accessFlags.hpp" +#include "utilities/ostream.hpp" // ciFlags // diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index cedf1b4850974b2ed2ece37a91dcbd86278c1592..5a735d525e559490757865b1f44ac803787bb877 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -2713,11 +2713,9 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs, m->set_constants(_cp); m->set_name_index(name_index); m->set_signature_index(signature_index); -#ifdef CC_INTERP - // hmm is there a gc issue here?? + ResultTypeFinder rtf(cp->symbol_at(signature_index)); - m->set_result_index(rtf.type()); -#endif + m->constMethod()->set_result_type(rtf.type()); if (args_size >= 0) { m->set_size_of_parameters(args_size); diff --git a/hotspot/src/share/vm/classfile/classFileStream.hpp b/hotspot/src/share/vm/classfile/classFileStream.hpp index 2d69de74b3a5cb73e678ff2ac19c3441fa3c1f0c..90ae4e9d34ab819aecbac03605e7cf6794e7b237 100644 --- a/hotspot/src/share/vm/classfile/classFileStream.hpp +++ b/hotspot/src/share/vm/classfile/classFileStream.hpp @@ -25,8 +25,9 @@ #ifndef SHARE_VM_CLASSFILE_CLASSFILESTREAM_HPP #define SHARE_VM_CLASSFILE_CLASSFILESTREAM_HPP +#include "memory/allocation.hpp" #include "utilities/bytes.hpp" -#include "utilities/top.hpp" +#include "utilities/exceptions.hpp" // Input stream for reading .class file // diff --git a/hotspot/src/share/vm/classfile/classLoader.cpp b/hotspot/src/share/vm/classfile/classLoader.cpp index bdf18bc55e067d7720ddc684ead55e5003ccf341..19b0f460a9d4aa86e9554c29ffe10fa50c0c0a70 100644 --- a/hotspot/src/share/vm/classfile/classLoader.cpp +++ b/hotspot/src/share/vm/classfile/classLoader.cpp @@ -98,12 +98,13 @@ static Crc32_t Crc32 = NULL; // Entry points for jimage.dll for loading jimage file entries -static JImageOpen_t JImageOpen = NULL; -static JImageClose_t JImageClose = NULL; -static JImagePackageToModule_t JImagePackageToModule = NULL; -static JImageFindResource_t JImageFindResource = NULL; -static JImageGetResource_t JImageGetResource = NULL; -static JImageResourceIterator_t JImageResourceIterator = NULL; +static JImageOpen_t JImageOpen = NULL; +static JImageClose_t JImageClose = NULL; +static JImagePackageToModule_t JImagePackageToModule = NULL; +static JImageFindResource_t JImageFindResource = NULL; +static JImageGetResource_t JImageGetResource = NULL; +static JImageResourceIterator_t JImageResourceIterator = NULL; +static JImage_ResourcePath_t JImageResourcePath = NULL; // Globals @@ -233,6 +234,7 @@ ClassPathZipEntry::ClassPathZipEntry(jzfile* zip, const char* zip_name, bool is_ strcpy(copy, zip_name); _zip_name = copy; _is_boot_append = is_boot_append; + _multi_versioned = _unknown; } ClassPathZipEntry::~ClassPathZipEntry() { @@ -330,13 +332,20 @@ u1* ClassPathZipEntry::open_versioned_entry(const char* name, jint* filesize, TR bool ClassPathZipEntry::is_multiple_versioned(TRAPS) { assert(DumpSharedSpaces, "called only at dump time"); + if (_multi_versioned != _unknown) { + return (_multi_versioned == _yes) ? true : false; + } jint size; - char* buffer = (char*)open_entry("META-INF/MANIFEST.MF", &size, false, CHECK_false); + char* buffer = (char*)open_entry("META-INF/MANIFEST.MF", &size, true, CHECK_false); if (buffer != NULL) { - if (strstr(buffer, "Multi-Release: true") != NULL) { + char* p = buffer; + for ( ; *p; ++p) *p = tolower(*p); + if (strstr(buffer, "multi-release: true") != NULL) { + _multi_versioned = _yes; return true; } } + _multi_versioned = _no; return false; } #endif // INCLUDE_CDS @@ -917,6 +926,8 @@ void ClassLoader::load_jimage_library() { guarantee(JImageGetResource != NULL, "function JIMAGE_GetResource not found"); JImageResourceIterator = CAST_TO_FN_PTR(JImageResourceIterator_t, os::dll_lookup(handle, "JIMAGE_ResourceIterator")); guarantee(JImageResourceIterator != NULL, "function JIMAGE_ResourceIterator not found"); + JImageResourcePath = CAST_TO_FN_PTR(JImage_ResourcePath_t, os::dll_lookup(handle, "JIMAGE_ResourcePath")); + guarantee(JImageResourcePath != NULL, "function JIMAGE_ResourcePath not found"); } jboolean ClassLoader::decompress(void *in, u8 inSize, void *out, u8 outSize, char **pmsg) { diff --git a/hotspot/src/share/vm/classfile/classLoader.hpp b/hotspot/src/share/vm/classfile/classLoader.hpp index 8ac282727d5b83fd769e187a08e6715ebfafa578..fc1d335b7ab987ece8834445ffa4f99184317d9f 100644 --- a/hotspot/src/share/vm/classfile/classLoader.hpp +++ b/hotspot/src/share/vm/classfile/classLoader.hpp @@ -101,10 +101,17 @@ typedef struct { class ClassPathZipEntry: public ClassPathEntry { + enum { + _unknown = 0, + _yes = 1, + _no = 2 + }; private: jzfile* _zip; // The zip archive const char* _zip_name; // Name of zip archive bool _is_boot_append; // entry coming from -Xbootclasspath/a + u1 _multi_versioned; // indicates if the jar file has multi-versioned entries. + // It can have value of "_unknown", "_yes", or "_no" public: bool is_jrt() { return false; } bool is_jar_file() const { return true; } diff --git a/hotspot/src/share/vm/classfile/classLoaderData.cpp b/hotspot/src/share/vm/classfile/classLoaderData.cpp index 0fb7a86af4fe8492c44e03c01c46eaf7c1efd077..0c0eb37196f44bab2ec28ca4dede336d9ffb6beb 100644 --- a/hotspot/src/share/vm/classfile/classLoaderData.cpp +++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp @@ -373,13 +373,10 @@ PackageEntryTable* ClassLoaderData::packages() { // Lazily create the package entry table at first request. if (_packages == NULL) { MutexLockerEx m1(metaspace_lock(), Mutex::_no_safepoint_check_flag); - // Check again if _packages has been allocated while we were getting this lock. - if (_packages != NULL) { - return _packages; + // Check if _packages got allocated while we were waiting for this lock. + if (_packages == NULL) { + _packages = new PackageEntryTable(PackageEntryTable::_packagetable_entry_size); } - // Ensure _packages is stable, since it is examined without a lock - OrderAccess::storestore(); - _packages = new PackageEntryTable(PackageEntryTable::_packagetable_entry_size); } return _packages; } diff --git a/hotspot/src/share/vm/classfile/defaultMethods.cpp b/hotspot/src/share/vm/classfile/defaultMethods.cpp index 65d546e249c39b8dda875a0a976cb93040758fbc..1b8cf3084ed19ab93f05553724aed5834f7ef004 100644 --- a/hotspot/src/share/vm/classfile/defaultMethods.cpp +++ b/hotspot/src/share/vm/classfile/defaultMethods.cpp @@ -860,10 +860,8 @@ static Method* new_method( m->set_constants(NULL); // This will get filled in later m->set_name_index(cp->utf8(name)); m->set_signature_index(cp->utf8(sig)); -#ifdef CC_INTERP ResultTypeFinder rtf(sig); - m->set_result_index(rtf.type()); -#endif + m->constMethod()->set_result_type(rtf.type()); m->set_size_of_parameters(params); m->set_max_stack(max_stack); m->set_max_locals(params); diff --git a/hotspot/src/share/vm/classfile/javaClasses.cpp b/hotspot/src/share/vm/classfile/javaClasses.cpp index b5230c844850af5773ecbc0504f9efda8b52e4e5..6b3e45c85d837db4409621cb78194fcfd6da4ce5 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.cpp +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp @@ -2187,43 +2187,19 @@ void java_lang_StackTraceElement::fill_in(Handle element, } Method* java_lang_StackFrameInfo::get_method(Handle stackFrame, InstanceKlass* holder, TRAPS) { - if (MemberNameInStackFrame) { - Handle mname(THREAD, stackFrame->obj_field(_memberName_offset)); - Method* method = (Method*)java_lang_invoke_MemberName::vmtarget(mname()); - // we should expand MemberName::name when Throwable uses StackTrace - // MethodHandles::expand_MemberName(mname, MethodHandles::_suppress_defc|MethodHandles::_suppress_type, CHECK_NULL); - return method; - } else { - short mid = stackFrame->short_field(_mid_offset); - short version = stackFrame->short_field(_version_offset); - return holder->method_with_orig_idnum(mid, version); - } -} - -Symbol* java_lang_StackFrameInfo::get_file_name(Handle stackFrame, InstanceKlass* holder) { - if (MemberNameInStackFrame) { - return holder->source_file_name(); - } else { - short version = stackFrame->short_field(_version_offset); - return Backtrace::get_source_file_name(holder, version); - } + Handle mname(THREAD, stackFrame->obj_field(_memberName_offset)); + Method* method = (Method*)java_lang_invoke_MemberName::vmtarget(mname()); + // we should expand MemberName::name when Throwable uses StackTrace + // MethodHandles::expand_MemberName(mname, MethodHandles::_suppress_defc|MethodHandles::_suppress_type, CHECK_NULL); + return method; } void java_lang_StackFrameInfo::set_method_and_bci(Handle stackFrame, const methodHandle& method, int bci) { // set Method* or mid/cpref - if (MemberNameInStackFrame) { - oop mname = stackFrame->obj_field(_memberName_offset); - InstanceKlass* ik = method->method_holder(); - CallInfo info(method(), ik); - MethodHandles::init_method_MemberName(mname, info); - } else { - int mid = method->orig_method_idnum(); - int cpref = method->name_index(); - assert((jushort)mid == mid, "mid should be short"); - assert((jushort)cpref == cpref, "cpref should be short"); - java_lang_StackFrameInfo::set_mid(stackFrame(), (short)mid); - java_lang_StackFrameInfo::set_cpref(stackFrame(), (short)cpref); - } + oop mname = stackFrame->obj_field(_memberName_offset); + InstanceKlass* ik = method->method_holder(); + CallInfo info(method(), ik); + MethodHandles::init_method_MemberName(mname, info); // set bci java_lang_StackFrameInfo::set_bci(stackFrame(), bci); // method may be redefined; store the version @@ -2232,52 +2208,23 @@ void java_lang_StackFrameInfo::set_method_and_bci(Handle stackFrame, const metho java_lang_StackFrameInfo::set_version(stackFrame(), (short)version); } -void java_lang_StackFrameInfo::fill_methodInfo(Handle stackFrame, TRAPS) { +void java_lang_StackFrameInfo::to_stack_trace_element(Handle stackFrame, Handle stack_trace_element, TRAPS) { ResourceMark rm(THREAD); - oop k = stackFrame->obj_field(_declaringClass_offset); - InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(k)); + Handle k (THREAD, stackFrame->obj_field(_declaringClass_offset)); + InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(k())); Method* method = java_lang_StackFrameInfo::get_method(stackFrame, holder, CHECK); - int bci = stackFrame->int_field(_bci_offset); - - // The method can be NULL if the requested class version is gone - Symbol* sym = (method != NULL) ? method->name() : NULL; - if (MemberNameInStackFrame) { - assert(sym != NULL, "MemberName must have method name"); - } else { - // The method can be NULL if the requested class version is gone - if (sym == NULL) { - short cpref = stackFrame->short_field(_cpref_offset); - sym = holder->constants()->symbol_at(cpref); - } - } - - // set method name - oop methodname = StringTable::intern(sym, CHECK); - java_lang_StackFrameInfo::set_methodName(stackFrame(), methodname); - - // set file name and line number - Symbol* source = get_file_name(stackFrame, holder); - if (source != NULL) { - oop filename = StringTable::intern(source, CHECK); - java_lang_StackFrameInfo::set_fileName(stackFrame(), filename); - } - // if the method has been redefined, the bci is no longer applicable short version = stackFrame->short_field(_version_offset); - if (version_matches(method, version)) { - int line_number = Backtrace::get_line_number(method, bci); - java_lang_StackFrameInfo::set_lineNumber(stackFrame(), line_number); - } + short bci = stackFrame->short_field(_bci_offset); + int cpref = method->name_index(); + java_lang_StackTraceElement::fill_in(stack_trace_element, holder, method, version, bci, cpref, CHECK); } void java_lang_StackFrameInfo::compute_offsets() { Klass* k = SystemDictionary::StackFrameInfo_klass(); compute_offset(_declaringClass_offset, k, vmSymbols::declaringClass_name(), vmSymbols::class_signature()); compute_offset(_memberName_offset, k, vmSymbols::memberName_name(), vmSymbols::object_signature()); - compute_offset(_bci_offset, k, vmSymbols::bci_name(), vmSymbols::int_signature()); - compute_offset(_methodName_offset, k, vmSymbols::methodName_name(), vmSymbols::string_signature()); - compute_offset(_fileName_offset, k, vmSymbols::fileName_name(), vmSymbols::string_signature()); - compute_offset(_lineNumber_offset, k, vmSymbols::lineNumber_name(), vmSymbols::int_signature()); + compute_offset(_bci_offset, k, vmSymbols::bci_name(), vmSymbols::short_signature()); STACKFRAMEINFO_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET); } @@ -3690,12 +3637,7 @@ int java_lang_StackTraceElement::moduleVersion_offset; int java_lang_StackFrameInfo::_declaringClass_offset; int java_lang_StackFrameInfo::_memberName_offset; int java_lang_StackFrameInfo::_bci_offset; -int java_lang_StackFrameInfo::_methodName_offset; -int java_lang_StackFrameInfo::_fileName_offset; -int java_lang_StackFrameInfo::_lineNumber_offset; -int java_lang_StackFrameInfo::_mid_offset; int java_lang_StackFrameInfo::_version_offset; -int java_lang_StackFrameInfo::_cpref_offset; int java_lang_LiveStackFrameInfo::_monitors_offset; int java_lang_LiveStackFrameInfo::_locals_offset; int java_lang_LiveStackFrameInfo::_operands_offset; @@ -3741,34 +3683,14 @@ void java_lang_StackFrameInfo::set_declaringClass(oop element, oop value) { element->obj_field_put(_declaringClass_offset, value); } -void java_lang_StackFrameInfo::set_mid(oop element, short value) { - element->short_field_put(_mid_offset, value); -} - void java_lang_StackFrameInfo::set_version(oop element, short value) { element->short_field_put(_version_offset, value); } -void java_lang_StackFrameInfo::set_cpref(oop element, short value) { - element->short_field_put(_cpref_offset, value); -} - void java_lang_StackFrameInfo::set_bci(oop element, int value) { element->int_field_put(_bci_offset, value); } -void java_lang_StackFrameInfo::set_fileName(oop element, oop value) { - element->obj_field_put(_fileName_offset, value); -} - -void java_lang_StackFrameInfo::set_methodName(oop element, oop value) { - element->obj_field_put(_methodName_offset, value); -} - -void java_lang_StackFrameInfo::set_lineNumber(oop element, int value) { - element->int_field_put(_lineNumber_offset, value); -} - void java_lang_LiveStackFrameInfo::set_monitors(oop element, oop value) { element->obj_field_put(_monitors_offset, value); } diff --git a/hotspot/src/share/vm/classfile/javaClasses.hpp b/hotspot/src/share/vm/classfile/javaClasses.hpp index 7245a9f0bb12e74dc11a48e0894d04444d22fd38..2cf71baf2c7e38f00c15c49a31cd4cb9362a5da4 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.hpp +++ b/hotspot/src/share/vm/classfile/javaClasses.hpp @@ -1364,25 +1364,16 @@ class Backtrace: AllStatic { // Interface to java.lang.StackFrameInfo objects #define STACKFRAMEINFO_INJECTED_FIELDS(macro) \ - macro(java_lang_StackFrameInfo, mid, short_signature, false) \ - macro(java_lang_StackFrameInfo, version, short_signature, false) \ - macro(java_lang_StackFrameInfo, cpref, short_signature, false) + macro(java_lang_StackFrameInfo, version, short_signature, false) class java_lang_StackFrameInfo: AllStatic { private: static int _declaringClass_offset; static int _memberName_offset; static int _bci_offset; - static int _methodName_offset; - static int _fileName_offset; - static int _lineNumber_offset; - - static int _mid_offset; static int _version_offset; - static int _cpref_offset; static Method* get_method(Handle stackFrame, InstanceKlass* holder, TRAPS); - static Symbol* get_file_name(Handle stackFrame, InstanceKlass* holder); public: // Setters @@ -1390,19 +1381,12 @@ public: static void set_method_and_bci(Handle stackFrame, const methodHandle& method, int bci); static void set_bci(oop info, int value); - // set method info in an instance of StackFrameInfo - static void fill_methodInfo(Handle info, TRAPS); - static void set_methodName(oop info, oop value); - static void set_fileName(oop info, oop value); - static void set_lineNumber(oop info, int value); - - // these injected fields are only used if -XX:-MemberNameInStackFrame set - static void set_mid(oop info, short value); static void set_version(oop info, short value); - static void set_cpref(oop info, short value); static void compute_offsets(); + static void to_stack_trace_element(Handle stackFrame, Handle stack_trace_element, TRAPS); + // Debugging friend class JavaClasses; }; diff --git a/hotspot/src/share/vm/classfile/javaClasses.inline.hpp b/hotspot/src/share/vm/classfile/javaClasses.inline.hpp index 1aba5b8f8c19b07eb5198e067171ccfe913399eb..180bc5b40a41aea67500605c20e50d3288f42f2c 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.inline.hpp +++ b/hotspot/src/share/vm/classfile/javaClasses.inline.hpp @@ -222,20 +222,17 @@ inline int Backtrace::get_line_number(const methodHandle& method, int bci) { return line_number; } -/* - * Returns the source file name of a given InstanceKlass and version - */ inline Symbol* Backtrace::get_source_file_name(InstanceKlass* holder, int version) { - // Find the specific ik version that contains this source_file_name_index - // via the previous versions list, but use the current version's - // constant pool to look it up. The previous version's index has been - // merged for the current constant pool. - InstanceKlass* ik = holder->get_klass_version(version); - // This version has been cleaned up. - if (ik == NULL) return NULL; - int source_file_name_index = ik->source_file_name_index(); - return (source_file_name_index == 0) ? - (Symbol*)NULL : holder->constants()->symbol_at(source_file_name_index); + // RedefineClasses() currently permits redefine operations to + // happen in parallel using a "last one wins" philosophy. That + // spec laxness allows the constant pool entry associated with + // the source_file_name_index for any older constant pool version + // to be unstable so we shouldn't try to use it. + if (holder->constants()->version() != version) { + return NULL; + } else { + return holder->source_file_name(); + } } #endif // SHARE_VM_CLASSFILE_JAVACLASSES_INLINE_HPP diff --git a/hotspot/src/share/vm/classfile/jimage.hpp b/hotspot/src/share/vm/classfile/jimage.hpp index e538ac805f8a584918f0e321560bb04790ad1daf..f34ba6efde9312d2ac2e70e21bce85960f0518fa 100644 --- a/hotspot/src/share/vm/classfile/jimage.hpp +++ b/hotspot/src/share/vm/classfile/jimage.hpp @@ -30,7 +30,7 @@ class JImageFile; typedef jlong JImageLocationRef; // Max path length limit independent of platform. Windows max path is 1024, -// other platforms use 4096. The JCK fails several tests when 1024 is used. +// other platforms use 4096. #define JIMAGE_MAX_PATH 4096 // JImage Error Codes @@ -113,7 +113,8 @@ typedef const char* (*JImagePackageToModule_t)(JImageFile* jimage, const char* p * * Ex. * jlong size; - * JImageLocationRef location = (*JImageFindResource)(image, "java.base", "9.0", "java/lang/String.class", &size); + * JImageLocationRef location = (*JImageFindResource)(image, + * "java.base", "9.0", "java/lang/String.class", &size); */ extern "C" JImageLocationRef JIMAGE_FindResource(JImageFile* jimage, const char* module_name, const char* version, const char* name, @@ -134,7 +135,8 @@ typedef JImageLocationRef(*JImageFindResource_t)(JImageFile* jimage, * * Ex. * jlong size; - * JImageLocationRef location = (*JImageFindResource)(image, "java.base", "9.0", "java/lang/String.class", &size); + * JImageLocationRef location = (*JImageFindResource)(image, + * "java.base", "9.0", "java/lang/String.class", &size); * char* buffer = new char[size]; * (*JImageGetResource)(image, location, buffer, size); */ @@ -154,7 +156,8 @@ typedef jlong(*JImageGetResource_t)(JImageFile* jimage, JImageLocationRef locati * required. All strings are utf-8, zero byte terminated.file. * * Ex. - * bool ctw_visitor(JImageFile* jimage, const char* module_name, const char* version, const char* package, const char* name, const char* extension, void* arg) { + * bool ctw_visitor(JImageFile* jimage, const char* module_name, const char* version, + * const char* package, const char* name, const char* extension, void* arg) { * if (strcmp(extension, “class”) == 0) { * char path[JIMAGE_MAX_PATH]; * Thread* THREAD = Thread::current(); @@ -176,3 +179,20 @@ extern "C" void JIMAGE_ResourceIterator(JImageFile* jimage, typedef void (*JImageResourceIterator_t)(JImageFile* jimage, JImageResourceVisitor_t visitor, void* arg); + +/* + * JIMAGE_ResourcePath- Given an open image file, a location reference, a buffer + * and a maximum buffer size, copy the path of the resource into the buffer. + * Returns false if not a valid location reference. + * + * Ex. + * JImageLocationRef location = ... + * char path[JIMAGE_MAX_PATH]; + * (*JImageResourcePath)(image, location, path, JIMAGE_MAX_PATH); + */ +extern "C" bool JIMAGE_ResourcePath(JImageFile* image, JImageLocationRef locationRef, + char* path, size_t max); + +typedef bool (*JImage_ResourcePath_t)(JImageFile* jimage, JImageLocationRef location, + char* buffer, jlong size); + diff --git a/hotspot/src/share/vm/classfile/moduleEntry.cpp b/hotspot/src/share/vm/classfile/moduleEntry.cpp index e86ed6acabf26d78ac574494a5c5ade892e36bda..3386dc43c1ea2c065b2b3198527eaabd64c4b62e 100644 --- a/hotspot/src/share/vm/classfile/moduleEntry.cpp +++ b/hotspot/src/share/vm/classfile/moduleEntry.cpp @@ -36,6 +36,7 @@ #include "utilities/events.hpp" #include "utilities/growableArray.hpp" #include "utilities/hashtable.inline.hpp" +#include "utilities/ostream.hpp" ModuleEntry* ModuleEntryTable::_javabase_module = NULL; @@ -359,31 +360,29 @@ void ModuleEntryTable::patch_javabase_entries(Handle module_handle) { java_lang_Class::set_fixup_module_field_list(NULL); } -#ifndef PRODUCT -void ModuleEntryTable::print() { - tty->print_cr("Module Entry Table (table_size=%d, entries=%d)", - table_size(), number_of_entries()); +void ModuleEntryTable::print(outputStream* st) { + st->print_cr("Module Entry Table (table_size=%d, entries=%d)", + table_size(), number_of_entries()); for (int i = 0; i < table_size(); i++) { for (ModuleEntry* probe = bucket(i); probe != NULL; probe = probe->next()) { - probe->print(); + probe->print(st); } } } -void ModuleEntry::print() { +void ModuleEntry::print(outputStream* st) { ResourceMark rm; - tty->print_cr("entry "PTR_FORMAT" name %s module "PTR_FORMAT" loader %s version %s location %s strict %s next "PTR_FORMAT, - p2i(this), - name() == NULL ? UNNAMED_MODULE : name()->as_C_string(), - p2i(module()), - loader()->loader_name(), - version() != NULL ? version()->as_C_string() : "NULL", - location() != NULL ? location()->as_C_string() : "NULL", - BOOL_TO_STR(!can_read_all_unnamed()), p2i(next())); + st->print_cr("entry "PTR_FORMAT" name %s module "PTR_FORMAT" loader %s version %s location %s strict %s next "PTR_FORMAT, + p2i(this), + name() == NULL ? UNNAMED_MODULE : name()->as_C_string(), + p2i(module()), + loader()->loader_name(), + version() != NULL ? version()->as_C_string() : "NULL", + location() != NULL ? location()->as_C_string() : "NULL", + BOOL_TO_STR(!can_read_all_unnamed()), p2i(next())); } -#endif void ModuleEntryTable::verify() { int element_count = 0; diff --git a/hotspot/src/share/vm/classfile/moduleEntry.hpp b/hotspot/src/share/vm/classfile/moduleEntry.hpp index d67251c1869e7bf084ba6a128b739ca70f6aff04..87accbeab41ee730fde08e91e29207e96e61ff76 100644 --- a/hotspot/src/share/vm/classfile/moduleEntry.hpp +++ b/hotspot/src/share/vm/classfile/moduleEntry.hpp @@ -33,6 +33,7 @@ #include "trace/traceMacros.hpp" #include "utilities/growableArray.hpp" #include "utilities/hashtable.hpp" +#include "utilities/ostream.hpp" #define UNNAMED_MODULE "Unnamed Module" @@ -141,7 +142,7 @@ public: void purge_reads(); void delete_reads(); - void print() PRODUCT_RETURN; + void print(outputStream* st = tty); void verify(); }; @@ -223,7 +224,7 @@ public: static void finalize_javabase(Handle module_handle, Symbol* version, Symbol* location); static void patch_javabase_entries(Handle module_handle); - void print() PRODUCT_RETURN; + void print(outputStream* st = tty); void verify(); }; diff --git a/hotspot/src/share/vm/classfile/packageEntry.cpp b/hotspot/src/share/vm/classfile/packageEntry.cpp index b3117d483c1aca4679b7dbc43f29625a1ba5fc35..ec6d4d08428e35490398ff70bcf3fc0a9c7c3390 100644 --- a/hotspot/src/share/vm/classfile/packageEntry.cpp +++ b/hotspot/src/share/vm/classfile/packageEntry.cpp @@ -32,6 +32,7 @@ #include "utilities/events.hpp" #include "utilities/growableArray.hpp" #include "utilities/hashtable.inline.hpp" +#include "utilities/ostream.hpp" // Return true if this package is exported to m. bool PackageEntry::is_qexported_to(ModuleEntry* m) const { @@ -265,28 +266,26 @@ void PackageEntryTable::purge_all_package_exports() { } } -#ifndef PRODUCT -void PackageEntryTable::print() { - tty->print_cr("Package Entry Table (table_size=%d, entries=%d)", - table_size(), number_of_entries()); +void PackageEntryTable::print(outputStream* st) { + st->print_cr("Package Entry Table (table_size=%d, entries=%d)", + table_size(), number_of_entries()); for (int i = 0; i < table_size(); i++) { for (PackageEntry* probe = bucket(i); probe != NULL; probe = probe->next()) { - probe->print(); + probe->print(st); } } } -void PackageEntry::print() { +void PackageEntry::print(outputStream* st) { ResourceMark rm; - tty->print_cr("package entry "PTR_FORMAT" name %s module %s classpath_index " - INT32_FORMAT " is_exported %d is_exported_allUnnamed %d " "next "PTR_FORMAT, - p2i(this), name()->as_C_string(), - (module()->is_named() ? module()->name()->as_C_string() : UNNAMED_MODULE), - _classpath_index, _is_exported, _is_exported_allUnnamed, p2i(next())); + st->print_cr("package entry "PTR_FORMAT" name %s module %s classpath_index " + INT32_FORMAT " is_exported %d is_exported_allUnnamed %d " "next "PTR_FORMAT, + p2i(this), name()->as_C_string(), + (module()->is_named() ? module()->name()->as_C_string() : UNNAMED_MODULE), + _classpath_index, _is_exported, _is_exported_allUnnamed, p2i(next())); } -#endif void PackageEntryTable::verify() { int element_count = 0; diff --git a/hotspot/src/share/vm/classfile/packageEntry.hpp b/hotspot/src/share/vm/classfile/packageEntry.hpp index 368609c21b652cd2db7e7dd2fa4b329bf460d809..00b7b9d160f5b786e560e07a99a9211381d62d09 100644 --- a/hotspot/src/share/vm/classfile/packageEntry.hpp +++ b/hotspot/src/share/vm/classfile/packageEntry.hpp @@ -29,6 +29,7 @@ #include "oops/symbol.hpp" #include "utilities/growableArray.hpp" #include "utilities/hashtable.hpp" +#include "utilities/ostream.hpp" // A PackageEntry basically represents a Java package. It contains: // - Symbol* containing the package's name. @@ -144,7 +145,7 @@ public: void purge_qualified_exports(); void delete_qualified_exports(); - void print() PRODUCT_RETURN; + void print(outputStream* st = tty); void verify(); }; @@ -195,7 +196,7 @@ public: // purge dead weak references out of exported list void purge_all_package_exports(); - void print() PRODUCT_RETURN; + void print(outputStream* st = tty); void verify(); }; diff --git a/hotspot/src/share/vm/code/relocInfo.hpp b/hotspot/src/share/vm/code/relocInfo.hpp index b399c09375909e59a0358ffebdc9b639729548a7..86a454c153fb35eeab701703924790cd7bfaca21 100644 --- a/hotspot/src/share/vm/code/relocInfo.hpp +++ b/hotspot/src/share/vm/code/relocInfo.hpp @@ -26,8 +26,9 @@ #define SHARE_VM_CODE_RELOCINFO_HPP #include "memory/allocation.hpp" -#include "utilities/top.hpp" +#include "runtime/os.hpp" +class Metadata; class NativeMovConstReg; // Types in this file: diff --git a/hotspot/src/share/vm/code/vmreg.hpp b/hotspot/src/share/vm/code/vmreg.hpp index fb9228c3ee948a1edff16a979bb7a2ef8f8f6f72..e6bc343c07d58c229fee6c05fb0ef0d0333b63f4 100644 --- a/hotspot/src/share/vm/code/vmreg.hpp +++ b/hotspot/src/share/vm/code/vmreg.hpp @@ -28,10 +28,9 @@ #include "asm/register.hpp" #include "memory/allocation.hpp" #include "utilities/globalDefinitions.hpp" - +#include "utilities/ostream.hpp" #ifdef COMPILER2 #include "opto/adlcVMDeps.hpp" -#include "utilities/ostream.hpp" #endif //------------------------------VMReg------------------------------------------ diff --git a/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp index ac9d84e5d129167198666890cb7d103c9dfdb724..ad651723aefef0b7ef475a3543533285664e0097 100644 --- a/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp +++ b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp @@ -32,6 +32,7 @@ #include "gc/shared/genCollectedHeap.hpp" #include "gc/shared/space.inline.hpp" #include "gc/shared/spaceDecorator.hpp" +#include "logging/logStream.inline.hpp" #include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.inline.hpp" @@ -505,10 +506,13 @@ void CompactibleFreeListSpace::reportFreeListStatistics(const char* title) const return; } log.debug("%s", title); - _dictionary->report_statistics(log.debug_stream()); + + LogStream out(log.debug()); + _dictionary->report_statistics(&out); + if (log.is_trace()) { - ResourceMark rm; - reportIndexedFreeListStatistics(log.trace_stream()); + LogStream trace_out(log.trace()); + reportIndexedFreeListStatistics(&trace_out); size_t total_size = totalSizeInIndexedFreeLists() + _dictionary->total_chunk_size(DEBUG_ONLY(freelistLock())); log.trace(" free=" SIZE_FORMAT " frag=%1.4f", total_size, flsFrag()); @@ -2836,6 +2840,11 @@ void CompactibleFreeListSpace:: par_get_chunk_of_blocks(size_t word_sz, size_t n par_get_chunk_of_blocks_dictionary(word_sz, n, fl); } +const size_t CompactibleFreeListSpace::max_flag_size_for_task_size() const { + const size_t ergo_max = _old_gen->reserved().word_size() / (CardTableModRefBS::card_size_in_words * BitsPerWord); + return ergo_max; +} + // Set up the space's par_seq_tasks structure for work claiming // for parallel rescan. See CMSParRemarkTask where this is currently used. // XXX Need to suitably abstract and generalize this and the next diff --git a/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.hpp b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.hpp index eeaa07ce280640af971d239ecf7d63d503e38af0..d8f8e89b6841df6ae5a0218ff44cff96ef8f0b9f 100644 --- a/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.hpp +++ b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.hpp @@ -82,6 +82,8 @@ class CompactibleFreeListSpace: public CompactibleSpace { template friend void CompactibleSpace::scan_and_compact(SpaceType* space); template + friend void CompactibleSpace::verify_up_to_first_dead(SpaceType* space); + template friend void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* cp); // "Size" of chunks of work (executed during parallel remark phases @@ -345,6 +347,8 @@ class CompactibleFreeListSpace: public CompactibleSpace { // Support for parallelization of rescan and marking. const size_t rescan_task_size() const { return _rescan_task_size; } const size_t marking_task_size() const { return _marking_task_size; } + // Return ergonomic max size for CMSRescanMultiple and CMSConcMarkMultiple. + const size_t max_flag_size_for_task_size() const; SequentialSubTasksDone* conc_par_seq_tasks() {return &_conc_par_seq_tasks; } void initialize_sequential_subtasks_for_rescan(int n_threads); void initialize_sequential_subtasks_for_marking(int n_threads, diff --git a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp index 42fd21dc65d80cf17b70caf87f9b32689271db7f..9e67c9b39e380cd95e38a754c3e2c227cb503f81 100644 --- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp +++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp @@ -425,7 +425,7 @@ void CMSStats::print_on(outputStream *st) const { st->print(",cms_consumption_rate=%g,time_until_full=%g", cms_consumption_rate(), time_until_cms_gen_full()); } - st->print(" "); + st->cr(); } #endif // #ifndef PRODUCT @@ -1108,8 +1108,10 @@ bool ConcurrentMarkSweepGeneration::should_collect(bool full, } bool CMSCollector::shouldConcurrentCollect() { + LogTarget(Trace, gc) log; + if (_full_gc_requested) { - log_trace(gc)("CMSCollector: collect because of explicit gc request (or GCLocker)"); + log.print("CMSCollector: collect because of explicit gc request (or GCLocker)"); return true; } @@ -1117,21 +1119,22 @@ bool CMSCollector::shouldConcurrentCollect() { // ------------------------------------------------------------------ // Print out lots of information which affects the initiation of // a collection. - Log(gc) log; - if (log.is_trace() && stats().valid()) { - log.trace("CMSCollector shouldConcurrentCollect: "); - ResourceMark rm; - stats().print_on(log.debug_stream()); - log.trace("time_until_cms_gen_full %3.7f", stats().time_until_cms_gen_full()); - log.trace("free=" SIZE_FORMAT, _cmsGen->free()); - log.trace("contiguous_available=" SIZE_FORMAT, _cmsGen->contiguous_available()); - log.trace("promotion_rate=%g", stats().promotion_rate()); - log.trace("cms_allocation_rate=%g", stats().cms_allocation_rate()); - log.trace("occupancy=%3.7f", _cmsGen->occupancy()); - log.trace("initiatingOccupancy=%3.7f", _cmsGen->initiating_occupancy()); - log.trace("cms_time_since_begin=%3.7f", stats().cms_time_since_begin()); - log.trace("cms_time_since_end=%3.7f", stats().cms_time_since_end()); - log.trace("metadata initialized %d", MetaspaceGC::should_concurrent_collect()); + if (log.is_enabled() && stats().valid()) { + log.print("CMSCollector shouldConcurrentCollect: "); + + LogStream out(log); + stats().print_on(&out); + + log.print("time_until_cms_gen_full %3.7f", stats().time_until_cms_gen_full()); + log.print("free=" SIZE_FORMAT, _cmsGen->free()); + log.print("contiguous_available=" SIZE_FORMAT, _cmsGen->contiguous_available()); + log.print("promotion_rate=%g", stats().promotion_rate()); + log.print("cms_allocation_rate=%g", stats().cms_allocation_rate()); + log.print("occupancy=%3.7f", _cmsGen->occupancy()); + log.print("initiatingOccupancy=%3.7f", _cmsGen->initiating_occupancy()); + log.print("cms_time_since_begin=%3.7f", stats().cms_time_since_begin()); + log.print("cms_time_since_end=%3.7f", stats().cms_time_since_end()); + log.print("metadata initialized %d", MetaspaceGC::should_concurrent_collect()); } // ------------------------------------------------------------------ @@ -1149,8 +1152,8 @@ bool CMSCollector::shouldConcurrentCollect() { // this branch will not fire after the first successful CMS // collection because the stats should then be valid. if (_cmsGen->occupancy() >= _bootstrap_occupancy) { - log_trace(gc)(" CMSCollector: collect for bootstrapping statistics: occupancy = %f, boot occupancy = %f", - _cmsGen->occupancy(), _bootstrap_occupancy); + log.print(" CMSCollector: collect for bootstrapping statistics: occupancy = %f, boot occupancy = %f", + _cmsGen->occupancy(), _bootstrap_occupancy); return true; } } @@ -1162,7 +1165,7 @@ bool CMSCollector::shouldConcurrentCollect() { // XXX We need to make sure that the gen expansion // criterion dovetails well with this. XXX NEED TO FIX THIS if (_cmsGen->should_concurrent_collect()) { - log_trace(gc)("CMS old gen initiated"); + log.print("CMS old gen initiated"); return true; } @@ -1173,12 +1176,12 @@ bool CMSCollector::shouldConcurrentCollect() { assert(gch->collector_policy()->is_generation_policy(), "You may want to check the correctness of the following"); if (gch->incremental_collection_will_fail(true /* consult_young */)) { - log_trace(gc)("CMSCollector: collect because incremental collection will fail "); + log.print("CMSCollector: collect because incremental collection will fail "); return true; } if (MetaspaceGC::should_concurrent_collect()) { - log_trace(gc)("CMSCollector: collect for metadata allocation "); + log.print("CMSCollector: collect for metadata allocation "); return true; } @@ -1193,10 +1196,10 @@ bool CMSCollector::shouldConcurrentCollect() { // as we want to be able to trigger the first CMS cycle as well) if (stats().cms_time_since_begin() >= (CMSTriggerInterval / ((double) MILLIUNITS))) { if (stats().valid()) { - log_trace(gc)("CMSCollector: collect because of trigger interval (time since last begin %3.7f secs)", - stats().cms_time_since_begin()); + log.print("CMSCollector: collect because of trigger interval (time since last begin %3.7f secs)", + stats().cms_time_since_begin()); } else { - log_trace(gc)("CMSCollector: collect because of trigger interval (first collection)"); + log.print("CMSCollector: collect because of trigger interval (first collection)"); } return true; } @@ -3598,7 +3601,7 @@ void CMSCollector::preclean() { size_t capacity = get_eden_capacity(); // Don't start sampling unless we will get sufficiently // many samples. - if (used < (capacity/(CMSScheduleRemarkSamplingRatio * 100) + if (used < (((capacity / CMSScheduleRemarkSamplingRatio) / 100) * CMSScheduleRemarkEdenPenetration)) { _start_sampling = true; } else { diff --git a/hotspot/src/share/vm/gc/g1/concurrentG1Refine.cpp b/hotspot/src/share/vm/gc/g1/concurrentG1Refine.cpp index 3a4d5ede251adfc02621354a997ae546ac661e56..e67c8932a8bb934e307af66cf6474401d7a0243f 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentG1Refine.cpp +++ b/hotspot/src/share/vm/gc/g1/concurrentG1Refine.cpp @@ -29,42 +29,174 @@ #include "gc/g1/g1HotCardCache.hpp" #include "gc/g1/g1Predictions.hpp" #include "runtime/java.hpp" +#include "utilities/debug.hpp" +#include "utilities/globalDefinitions.hpp" +#include "utilities/pair.hpp" +#include -ConcurrentG1Refine::ConcurrentG1Refine(G1CollectedHeap* g1h, const G1Predictions* predictor) : +// Arbitrary but large limits, to simplify some of the zone calculations. +// The general idea is to allow expressions like +// MIN2(x OP y, max_XXX_zone) +// without needing to check for overflow in "x OP y", because the +// ranges for x and y have been restricted. +STATIC_ASSERT(sizeof(LP64_ONLY(jint) NOT_LP64(jshort)) <= (sizeof(size_t)/2)); +const size_t max_yellow_zone = LP64_ONLY(max_jint) NOT_LP64(max_jshort); +const size_t max_green_zone = max_yellow_zone / 2; +const size_t max_red_zone = INT_MAX; // For dcqs.set_max_completed_queue. +STATIC_ASSERT(max_yellow_zone <= max_red_zone); + +// Range check assertions for green zone values. +#define assert_zone_constraints_g(green) \ + do { \ + size_t azc_g_green = (green); \ + assert(azc_g_green <= max_green_zone, \ + "green exceeds max: " SIZE_FORMAT, azc_g_green); \ + } while (0) + +// Range check assertions for green and yellow zone values. +#define assert_zone_constraints_gy(green, yellow) \ + do { \ + size_t azc_gy_green = (green); \ + size_t azc_gy_yellow = (yellow); \ + assert_zone_constraints_g(azc_gy_green); \ + assert(azc_gy_yellow <= max_yellow_zone, \ + "yellow exceeds max: " SIZE_FORMAT, azc_gy_yellow); \ + assert(azc_gy_green <= azc_gy_yellow, \ + "green (" SIZE_FORMAT ") exceeds yellow (" SIZE_FORMAT ")", \ + azc_gy_green, azc_gy_yellow); \ + } while (0) + +// Range check assertions for green, yellow, and red zone values. +#define assert_zone_constraints_gyr(green, yellow, red) \ + do { \ + size_t azc_gyr_green = (green); \ + size_t azc_gyr_yellow = (yellow); \ + size_t azc_gyr_red = (red); \ + assert_zone_constraints_gy(azc_gyr_green, azc_gyr_yellow); \ + assert(azc_gyr_red <= max_red_zone, \ + "red exceeds max: " SIZE_FORMAT, azc_gyr_red); \ + assert(azc_gyr_yellow <= azc_gyr_red, \ + "yellow (" SIZE_FORMAT ") exceeds red (" SIZE_FORMAT ")", \ + azc_gyr_yellow, azc_gyr_red); \ + } while (0) + +// Logging tag sequence for refinement control updates. +#define CTRL_TAGS gc, ergo, refine + +// For logging zone values, ensuring consistency of level and tags. +#define LOG_ZONES(...) log_debug( CTRL_TAGS )(__VA_ARGS__) + +// Package for pair of refinement thread activation and deactivation +// thresholds. The activation and deactivation levels are resp. the first +// and second values of the pair. +typedef Pair Thresholds; +inline size_t activation_level(const Thresholds& t) { return t.first; } +inline size_t deactivation_level(const Thresholds& t) { return t.second; } + +static Thresholds calc_thresholds(size_t green_zone, + size_t yellow_zone, + uint worker_i) { + double yellow_size = yellow_zone - green_zone; + double step = yellow_size / ConcurrentG1Refine::thread_num(); + if (worker_i == 0) { + // Potentially activate worker 0 more aggressively, to keep + // available buffers near green_zone value. When yellow_size is + // large we don't want to allow a full step to accumulate before + // doing any processing, as that might lead to significantly more + // than green_zone buffers to be processed by update_rs. + step = MIN2(step, ParallelGCThreads / 2.0); + } + size_t activate_offset = static_cast(ceil(step * (worker_i + 1))); + size_t deactivate_offset = static_cast(floor(step * worker_i)); + return Thresholds(green_zone + activate_offset, + green_zone + deactivate_offset); +} + +ConcurrentG1Refine::ConcurrentG1Refine(G1CollectedHeap* g1h, + size_t green_zone, + size_t yellow_zone, + size_t red_zone, + size_t min_yellow_zone_size) : _threads(NULL), _sample_thread(NULL), - _predictor_sigma(predictor->sigma()), + _n_worker_threads(thread_num()), + _green_zone(green_zone), + _yellow_zone(yellow_zone), + _red_zone(red_zone), + _min_yellow_zone_size(min_yellow_zone_size), _hot_card_cache(g1h) { - // Ergonomically select initial concurrent refinement parameters + assert_zone_constraints_gyr(green_zone, yellow_zone, red_zone); +} + +static size_t calc_min_yellow_zone_size() { + size_t step = G1ConcRefinementThresholdStep; + uint n_workers = ConcurrentG1Refine::thread_num(); + if ((max_yellow_zone / step) < n_workers) { + return max_yellow_zone; + } else { + return step * n_workers; + } +} + +static size_t calc_init_green_zone() { + size_t green = G1ConcRefinementGreenZone; if (FLAG_IS_DEFAULT(G1ConcRefinementGreenZone)) { - FLAG_SET_DEFAULT(G1ConcRefinementGreenZone, ParallelGCThreads); + green = ParallelGCThreads; } - set_green_zone(G1ConcRefinementGreenZone); + return MIN2(green, max_green_zone); +} +static size_t calc_init_yellow_zone(size_t green, size_t min_size) { + size_t config = G1ConcRefinementYellowZone; + size_t size = 0; if (FLAG_IS_DEFAULT(G1ConcRefinementYellowZone)) { - FLAG_SET_DEFAULT(G1ConcRefinementYellowZone, green_zone() * 3); + size = green * 2; + } else if (green < config) { + size = config - green; } - set_yellow_zone(MAX2(G1ConcRefinementYellowZone, green_zone())); + size = MAX2(size, min_size); + size = MIN2(size, max_yellow_zone); + return MIN2(green + size, max_yellow_zone); +} - if (FLAG_IS_DEFAULT(G1ConcRefinementRedZone)) { - FLAG_SET_DEFAULT(G1ConcRefinementRedZone, yellow_zone() * 2); +static size_t calc_init_red_zone(size_t green, size_t yellow) { + size_t size = yellow - green; + if (!FLAG_IS_DEFAULT(G1ConcRefinementRedZone)) { + size_t config = G1ConcRefinementRedZone; + if (yellow < config) { + size = MAX2(size, config - yellow); + } } - set_red_zone(MAX2(G1ConcRefinementRedZone, yellow_zone())); - + return MIN2(yellow + size, max_red_zone); } -ConcurrentG1Refine* ConcurrentG1Refine::create(G1CollectedHeap* g1h, CardTableEntryClosure* refine_closure, jint* ecode) { - G1CollectorPolicy* policy = g1h->g1_policy(); - ConcurrentG1Refine* cg1r = new ConcurrentG1Refine(g1h, &policy->predictor()); +ConcurrentG1Refine* ConcurrentG1Refine::create(G1CollectedHeap* g1h, + CardTableEntryClosure* refine_closure, + jint* ecode) { + size_t min_yellow_zone_size = calc_min_yellow_zone_size(); + size_t green_zone = calc_init_green_zone(); + size_t yellow_zone = calc_init_yellow_zone(green_zone, min_yellow_zone_size); + size_t red_zone = calc_init_red_zone(green_zone, yellow_zone); + + LOG_ZONES("Initial Refinement Zones: " + "green: " SIZE_FORMAT ", " + "yellow: " SIZE_FORMAT ", " + "red: " SIZE_FORMAT ", " + "min yellow size: " SIZE_FORMAT, + green_zone, yellow_zone, red_zone, min_yellow_zone_size); + + ConcurrentG1Refine* cg1r = new ConcurrentG1Refine(g1h, + green_zone, + yellow_zone, + red_zone, + min_yellow_zone_size); + if (cg1r == NULL) { *ecode = JNI_ENOMEM; vm_shutdown_during_initialization("Could not create ConcurrentG1Refine"); return NULL; } - cg1r->_n_worker_threads = thread_num(); - - cg1r->reset_threshold_step(); cg1r->_threads = NEW_C_HEAP_ARRAY_RETURN_NULL(ConcurrentG1RefineThread*, cg1r->_n_worker_threads, mtGC); if (cg1r->_threads == NULL) { @@ -77,7 +209,15 @@ ConcurrentG1Refine* ConcurrentG1Refine::create(G1CollectedHeap* g1h, CardTableEn ConcurrentG1RefineThread *next = NULL; for (uint i = cg1r->_n_worker_threads - 1; i != UINT_MAX; i--) { - ConcurrentG1RefineThread* t = new ConcurrentG1RefineThread(cg1r, next, refine_closure, worker_id_offset, i); + Thresholds thresholds = calc_thresholds(green_zone, yellow_zone, i); + ConcurrentG1RefineThread* t = + new ConcurrentG1RefineThread(cg1r, + next, + refine_closure, + worker_id_offset, + i, + activation_level(thresholds), + deactivation_level(thresholds)); assert(t != NULL, "Conc refine should have been created"); if (t->osthread() == NULL) { *ecode = JNI_ENOMEM; @@ -101,14 +241,6 @@ ConcurrentG1Refine* ConcurrentG1Refine::create(G1CollectedHeap* g1h, CardTableEn return cg1r; } -void ConcurrentG1Refine::reset_threshold_step() { - if (FLAG_IS_DEFAULT(G1ConcRefinementThresholdStep)) { - _thread_threshold_step = (yellow_zone() - green_zone()) / (worker_thread_num() + 1); - } else { - _thread_threshold_step = G1ConcRefinementThresholdStep; - } -} - void ConcurrentG1Refine::init(G1RegionToSpaceMapper* card_counts_storage) { _hot_card_cache.initialize(card_counts_storage); } @@ -120,10 +252,11 @@ void ConcurrentG1Refine::stop() { _sample_thread->stop(); } -void ConcurrentG1Refine::reinitialize_threads() { - reset_threshold_step(); +void ConcurrentG1Refine::update_thread_thresholds() { for (uint i = 0; i < _n_worker_threads; i++) { - _threads[i]->initialize(); + Thresholds thresholds = calc_thresholds(_green_zone, _yellow_zone, i); + _threads[i]->update_thresholds(activation_level(thresholds), + deactivation_level(thresholds)); } } @@ -142,7 +275,7 @@ void ConcurrentG1Refine::threads_do(ThreadClosure *tc) { } void ConcurrentG1Refine::worker_threads_do(ThreadClosure * tc) { - for (uint i = 0; i < worker_thread_num(); i++) { + for (uint i = 0; i < _n_worker_threads; i++) { tc->do_thread(_threads[i]); } } @@ -160,34 +293,80 @@ void ConcurrentG1Refine::print_worker_threads_on(outputStream* st) const { st->cr(); } +static size_t calc_new_green_zone(size_t green, + double update_rs_time, + size_t update_rs_processed_buffers, + double goal_ms) { + // Adjust green zone based on whether we're meeting the time goal. + // Limit to max_green_zone. + const double inc_k = 1.1, dec_k = 0.9; + if (update_rs_time > goal_ms) { + if (green > 0) { + green = static_cast(green * dec_k); + } + } else if (update_rs_time < goal_ms && + update_rs_processed_buffers > green) { + green = static_cast(MAX2(green * inc_k, green + 1.0)); + green = MIN2(green, max_green_zone); + } + return green; +} + +static size_t calc_new_yellow_zone(size_t green, size_t min_yellow_size) { + size_t size = green * 2; + size = MAX2(size, min_yellow_size); + return MIN2(green + size, max_yellow_zone); +} + +static size_t calc_new_red_zone(size_t green, size_t yellow) { + return MIN2(yellow + (yellow - green), max_red_zone); +} + +void ConcurrentG1Refine::update_zones(double update_rs_time, + size_t update_rs_processed_buffers, + double goal_ms) { + log_trace( CTRL_TAGS )("Updating Refinement Zones: " + "update_rs time: %.3fms, " + "update_rs buffers: " SIZE_FORMAT ", " + "update_rs goal time: %.3fms", + update_rs_time, + update_rs_processed_buffers, + goal_ms); + + _green_zone = calc_new_green_zone(_green_zone, + update_rs_time, + update_rs_processed_buffers, + goal_ms); + _yellow_zone = calc_new_yellow_zone(_green_zone, _min_yellow_zone_size); + _red_zone = calc_new_red_zone(_green_zone, _yellow_zone); + + assert_zone_constraints_gyr(_green_zone, _yellow_zone, _red_zone); + LOG_ZONES("Updated Refinement Zones: " + "green: " SIZE_FORMAT ", " + "yellow: " SIZE_FORMAT ", " + "red: " SIZE_FORMAT, + _green_zone, _yellow_zone, _red_zone); +} + void ConcurrentG1Refine::adjust(double update_rs_time, - double update_rs_processed_buffers, + size_t update_rs_processed_buffers, double goal_ms) { DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); if (G1UseAdaptiveConcRefinement) { - const int k_gy = 3, k_gr = 6; - const double inc_k = 1.1, dec_k = 0.9; + update_zones(update_rs_time, update_rs_processed_buffers, goal_ms); + update_thread_thresholds(); - size_t g = green_zone(); - if (update_rs_time > goal_ms) { - g = (size_t)(g * dec_k); // Can become 0, that's OK. That would mean a mutator-only processing. + // Change the barrier params + if (_n_worker_threads == 0) { + // Disable dcqs notification when there are no threads to notify. + dcqs.set_process_completed_threshold(INT_MAX); } else { - if (update_rs_time < goal_ms && update_rs_processed_buffers > g) { - g = (size_t)MAX2(g * inc_k, g + 1.0); - } + // Worker 0 is the primary; wakeup is via dcqs notification. + STATIC_ASSERT(max_yellow_zone <= INT_MAX); + size_t activate = _threads[0]->activation_threshold(); + dcqs.set_process_completed_threshold((int)activate); } - // Change the refinement threads params - set_green_zone(g); - set_yellow_zone(g * k_gy); - set_red_zone(g * k_gr); - reinitialize_threads(); - - size_t processing_threshold_delta = MAX2(green_zone() * _predictor_sigma, 1); - size_t processing_threshold = MIN2(green_zone() + processing_threshold_delta, - yellow_zone()); - // Change the barrier params - dcqs.set_process_completed_threshold((int)processing_threshold); dcqs.set_max_completed_queue((int)red_zone()); } diff --git a/hotspot/src/share/vm/gc/g1/concurrentG1Refine.hpp b/hotspot/src/share/vm/gc/g1/concurrentG1Refine.hpp index 3161f62f2b2e3d364ddaab5ebae4465741352f26..098d49e801dd2b24bdb413caf9e83b427b906aed 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentG1Refine.hpp +++ b/hotspot/src/share/vm/gc/g1/concurrentG1Refine.hpp @@ -65,18 +65,24 @@ class ConcurrentG1Refine: public CHeapObj { size_t _green_zone; size_t _yellow_zone; size_t _red_zone; - - size_t _thread_threshold_step; - - double _predictor_sigma; + size_t _min_yellow_zone_size; // We delay the refinement of 'hot' cards using the hot card cache. G1HotCardCache _hot_card_cache; - // Reset the threshold step value based of the current zone boundaries. - void reset_threshold_step(); + ConcurrentG1Refine(G1CollectedHeap* g1h, + size_t green_zone, + size_t yellow_zone, + size_t red_zone, + size_t min_yellow_zone_size); - ConcurrentG1Refine(G1CollectedHeap* g1h, const G1Predictions* predictions); + // Update green/yellow/red zone values based on how well goals are being met. + void update_zones(double update_rs_time, + size_t update_rs_processed_buffers, + double goal_ms); + + // Update thread thresholds to account for updated zone values. + void update_thread_thresholds(); public: ~ConcurrentG1Refine(); @@ -88,9 +94,7 @@ class ConcurrentG1Refine: public CHeapObj { void init(G1RegionToSpaceMapper* card_counts_storage); void stop(); - void adjust(double update_rs_time, double update_rs_processed_buffers, double goal_ms); - - void reinitialize_threads(); + void adjust(double update_rs_time, size_t update_rs_processed_buffers, double goal_ms); // Iterate over all concurrent refinement threads void threads_do(ThreadClosure *tc); @@ -105,18 +109,10 @@ class ConcurrentG1Refine: public CHeapObj { void print_worker_threads_on(outputStream* st) const; - void set_green_zone(size_t x) { _green_zone = x; } - void set_yellow_zone(size_t x) { _yellow_zone = x; } - void set_red_zone(size_t x) { _red_zone = x; } - size_t green_zone() const { return _green_zone; } size_t yellow_zone() const { return _yellow_zone; } size_t red_zone() const { return _red_zone; } - uint worker_thread_num() const { return _n_worker_threads; } - - size_t thread_threshold_step() const { return _thread_threshold_step; } - G1HotCardCache* hot_card_cache() { return &_hot_card_cache; } static bool hot_card_cache_enabled() { return G1HotCardCache::default_use_cache(); } diff --git a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp index 78bea91e71bd8437d7d4b29e42e30afb8d1d82f0..8f9ebfbfb684f60b174845c4778862e802adec7e 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp +++ b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp @@ -36,7 +36,8 @@ ConcurrentG1RefineThread:: ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread *next, CardTableEntryClosure* refine_closure, - uint worker_id_offset, uint worker_id) : + uint worker_id_offset, uint worker_id, + size_t activate, size_t deactivate) : ConcurrentGCThread(), _refine_closure(refine_closure), _worker_id_offset(worker_id_offset), @@ -45,7 +46,9 @@ ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread *nex _next(next), _monitor(NULL), _cg1r(cg1r), - _vtime_accum(0.0) + _vtime_accum(0.0), + _activation_threshold(activate), + _deactivation_threshold(deactivate) { // Each thread has its own monitor. The i-th thread is responsible for signaling @@ -58,21 +61,17 @@ ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread *nex } else { _monitor = DirtyCardQ_CBL_mon; } - initialize(); // set name set_name("G1 Refine#%d", worker_id); create_and_start(); } -void ConcurrentG1RefineThread::initialize() { - // Current thread activation threshold - _threshold = MIN2(cg1r()->thread_threshold_step() * (_worker_id + 1) + cg1r()->green_zone(), - cg1r()->yellow_zone()); - // A thread deactivates once the number of buffer reached a deactivation threshold - _deactivation_threshold = - MAX2(_threshold - MIN2(_threshold, cg1r()->thread_threshold_step()), - cg1r()->green_zone()); +void ConcurrentG1RefineThread::update_thresholds(size_t activate, + size_t deactivate) { + assert(deactivate < activate, "precondition"); + _activation_threshold = activate; + _deactivation_threshold = deactivate; } void ConcurrentG1RefineThread::wait_for_completed_buffers() { @@ -118,9 +117,10 @@ void ConcurrentG1RefineThread::run_service() { break; } + size_t buffers_processed = 0; DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); log_debug(gc, refine)("Activated %d, on threshold: " SIZE_FORMAT ", current: " SIZE_FORMAT, - _worker_id, _threshold, dcqs.completed_buffers_num()); + _worker_id, _activation_threshold, dcqs.completed_buffers_num()); { SuspendibleThreadSetJoiner sts_join; @@ -139,7 +139,9 @@ void ConcurrentG1RefineThread::run_service() { } // Check if we need to activate the next thread. - if (_next != NULL && !_next->is_active() && curr_buffer_num > _next->_threshold) { + if ((_next != NULL) && + !_next->is_active() && + (curr_buffer_num > _next->_activation_threshold)) { _next->activate(); } @@ -150,14 +152,16 @@ void ConcurrentG1RefineThread::run_service() { false /* during_pause */)) { break; // Deactivate, number of buffers fell below threshold. } + ++buffers_processed; } } deactivate(); log_debug(gc, refine)("Deactivated %d, off threshold: " SIZE_FORMAT - ", current: " SIZE_FORMAT, + ", current: " SIZE_FORMAT ", processed: " SIZE_FORMAT, _worker_id, _deactivation_threshold, - dcqs.completed_buffers_num()); + dcqs.completed_buffers_num(), + buffers_processed); if (os::supports_vtime()) { _vtime_accum = (os::elapsedVTime() - _vtime_start); diff --git a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.hpp b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.hpp index 9f325599cfccb72f86c501fbb7738bd036f1b557..902d77cb9f6c9bb988e29c742c63b954d8e96195 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.hpp +++ b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.hpp @@ -53,10 +53,8 @@ class ConcurrentG1RefineThread: public ConcurrentGCThread { // The closure applied to completed log buffers. CardTableEntryClosure* _refine_closure; - size_t _thread_threshold_step; - // This thread activation threshold - size_t _threshold; - // This thread deactivation threshold + // This thread's activation/deactivation thresholds + size_t _activation_threshold; size_t _deactivation_threshold; void wait_for_completed_buffers(); @@ -75,9 +73,11 @@ public: // Constructor ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread* next, CardTableEntryClosure* refine_closure, - uint worker_id_offset, uint worker_id); + uint worker_id_offset, uint worker_id, + size_t activate, size_t deactivate); - void initialize(); + void update_thresholds(size_t activate, size_t deactivate); + size_t activation_threshold() const { return _activation_threshold; } // Total virtual time so far. double vtime_accum() { return _vtime_accum; } diff --git a/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp index c72cbae14749d33026deb2c091813cc2db85bc14..9727b0232682bbd96fe026d171b47b6b55398654 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp +++ b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp @@ -28,6 +28,7 @@ #include "gc/g1/g1Analytics.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1CollectorPolicy.hpp" +#include "gc/g1/g1ConcurrentMark.inline.hpp" #include "gc/g1/g1MMUTracker.hpp" #include "gc/g1/suspendibleThreadSet.hpp" #include "gc/g1/vm_operations_g1.hpp" @@ -183,6 +184,11 @@ void ConcurrentMarkThread::run_service() { } } while (cm()->restart_for_overflow()); + if (!cm()->has_aborted()) { + G1ConcPhaseTimer t(_cm, "Concurrent Create Live Data"); + cm()->create_live_data(); + } + double end_time = os::elapsedVTime(); // Update the total virtual time before doing this, since it will try // to measure it to get the vtime for this marking. We purposely diff --git a/hotspot/src/share/vm/gc/g1/g1CardLiveData.cpp b/hotspot/src/share/vm/gc/g1/g1CardLiveData.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0a2ed25a29bfe4bc957b8a63a5d5aab2820b0a51 --- /dev/null +++ b/hotspot/src/share/vm/gc/g1/g1CardLiveData.cpp @@ -0,0 +1,558 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "gc/g1/g1CollectedHeap.inline.hpp" +#include "gc/g1/g1ConcurrentMark.inline.hpp" +#include "gc/g1/g1CardLiveData.inline.hpp" +#include "gc/g1/suspendibleThreadSet.hpp" +#include "gc/shared/workgroup.hpp" +#include "memory/universe.hpp" +#include "runtime/atomic.inline.hpp" +#include "runtime/globals.hpp" +#include "runtime/os.hpp" +#include "utilities/bitMap.inline.hpp" +#include "utilities/debug.hpp" + +G1CardLiveData::G1CardLiveData() : + _max_capacity(0), + _cards_per_region(0), + _live_regions(NULL), + _live_regions_size_in_bits(0), + _live_cards(NULL), + _live_cards_size_in_bits(0) { +} + +G1CardLiveData::~G1CardLiveData() { + free_large_bitmap(_live_cards, _live_cards_size_in_bits); + free_large_bitmap(_live_regions, _live_regions_size_in_bits); +} + +G1CardLiveData::bm_word_t* G1CardLiveData::allocate_large_bitmap(size_t size_in_bits) { + size_t size_in_words = BitMap::calc_size_in_words(size_in_bits); + + bm_word_t* map = MmapArrayAllocator::allocate(size_in_words); + + return map; +} + +void G1CardLiveData::free_large_bitmap(bm_word_t* bitmap, size_t size_in_bits) { + MmapArrayAllocator::free(bitmap, size_in_bits / BitsPerWord); +} + +void G1CardLiveData::initialize(size_t max_capacity, uint num_max_regions) { + assert(max_capacity % num_max_regions == 0, + "Given capacity must be evenly divisible by region size."); + size_t region_size = max_capacity / num_max_regions; + assert(region_size % (G1SATBCardTableModRefBS::card_size * BitsPerWord) == 0, + "Region size must be evenly divisible by area covered by a single word."); + _max_capacity = max_capacity; + _cards_per_region = region_size / G1SATBCardTableModRefBS::card_size; + + _live_regions_size_in_bits = live_region_bitmap_size_in_bits(); + _live_regions = allocate_large_bitmap(_live_regions_size_in_bits); + _live_cards_size_in_bits = live_card_bitmap_size_in_bits(); + _live_cards = allocate_large_bitmap(_live_cards_size_in_bits); +} + +void G1CardLiveData::pretouch() { + live_cards_bm().pretouch(); + live_regions_bm().pretouch(); +} + +size_t G1CardLiveData::live_region_bitmap_size_in_bits() const { + return _max_capacity / (_cards_per_region << G1SATBCardTableModRefBS::card_shift); +} + +size_t G1CardLiveData::live_card_bitmap_size_in_bits() const { + return _max_capacity >> G1SATBCardTableModRefBS::card_shift; +} + +// Helper class that provides functionality to generate the Live Data Count +// information. +class G1CardLiveDataHelper VALUE_OBJ_CLASS_SPEC { +private: + BitMap _region_bm; + BitMap _card_bm; + + // The card number of the bottom of the G1 heap. + // Used in biasing indices into accounting card bitmaps. + BitMap::idx_t _heap_card_bias; + + // Utility routine to set an exclusive range of bits on the given + // bitmap, optimized for very small ranges. + // There must be at least one bit to set. + void set_card_bitmap_range(BitMap::idx_t start_idx, + BitMap::idx_t end_idx) { + + // Set the exclusive bit range [start_idx, end_idx). + assert((end_idx - start_idx) > 0, "at least one bit"); + + // For small ranges use a simple loop; otherwise use set_range. + // The range is made up of the cards that are spanned by an object/mem + // region so 8 cards will allow up to object sizes up to 4K to be handled + // using the loop. + if ((end_idx - start_idx) <= 8) { + for (BitMap::idx_t i = start_idx; i < end_idx; i += 1) { + _card_bm.set_bit(i); + } + } else { + _card_bm.set_range(start_idx, end_idx); + } + } + + // We cache the last mark set. This avoids setting the same bit multiple times. + // This is particularly interesting for dense bitmaps, as this avoids doing + // lots of work most of the time. + BitMap::idx_t _last_marked_bit_idx; + + // Mark the card liveness bitmap for the object spanning from start to end. + void mark_card_bitmap_range(HeapWord* start, HeapWord* end) { + BitMap::idx_t start_idx = card_live_bitmap_index_for(start); + BitMap::idx_t end_idx = card_live_bitmap_index_for((HeapWord*)align_ptr_up(end, CardTableModRefBS::card_size)); + + assert((end_idx - start_idx) > 0, "Trying to mark zero sized range."); + + if (start_idx == _last_marked_bit_idx) { + start_idx++; + } + if (start_idx == end_idx) { + return; + } + + // Set the bits in the card bitmap for the cards spanned by this object. + set_card_bitmap_range(start_idx, end_idx); + _last_marked_bit_idx = end_idx - 1; + } + + void reset_mark_cache() { + _last_marked_bit_idx = (BitMap::idx_t)-1; + } + +public: + // Returns the index in the per-card liveness count bitmap + // for the given address + inline BitMap::idx_t card_live_bitmap_index_for(HeapWord* addr) { + // Below, the term "card num" means the result of shifting an address + // by the card shift -- address 0 corresponds to card number 0. One + // must subtract the card num of the bottom of the heap to obtain a + // card table index. + BitMap::idx_t card_num = uintptr_t(addr) >> CardTableModRefBS::card_shift; + return card_num - _heap_card_bias; + } + + // Takes a region that's not empty (i.e., it has at least one + // live object in it and sets its corresponding bit on the region + // bitmap to 1. + void set_bit_for_region(HeapRegion* hr) { + _region_bm.par_set_bit(hr->hrm_index()); + } + + // Mark the range of bits covered by allocations done since the last marking + // in the given heap region, i.e. from NTAMS to top of the given region. + // Returns if there has been some allocation in this region since the last marking. + bool mark_allocated_since_marking(HeapRegion* hr) { + reset_mark_cache(); + + HeapWord* ntams = hr->next_top_at_mark_start(); + HeapWord* top = hr->top(); + + assert(hr->bottom() <= ntams && ntams <= hr->end(), "Preconditions."); + + // Mark the allocated-since-marking portion... + if (ntams < top) { + mark_card_bitmap_range(ntams, top); + return true; + } else { + return false; + } + } + + // Mark the range of bits covered by live objects on the mark bitmap between + // bottom and NTAMS of the given region. + // Returns the number of live bytes marked within that area for the given + // heap region. + size_t mark_marked_during_marking(G1CMBitMap* mark_bitmap, HeapRegion* hr) { + reset_mark_cache(); + + size_t marked_bytes = 0; + + HeapWord* ntams = hr->next_top_at_mark_start(); + HeapWord* start = hr->bottom(); + + if (ntams <= start) { + // Skip empty regions. + return 0; + } + if (hr->is_humongous()) { + HeapRegion* start_region = hr->humongous_start_region(); + if (mark_bitmap->isMarked(start_region->bottom())) { + mark_card_bitmap_range(start, hr->top()); + return pointer_delta(hr->top(), start, 1); + } else { + // Humongous start object was actually dead. + return 0; + } + } + + assert(start <= hr->end() && start <= ntams && ntams <= hr->end(), + "Preconditions not met - " + "start: " PTR_FORMAT ", ntams: " PTR_FORMAT ", end: " PTR_FORMAT, + p2i(start), p2i(ntams), p2i(hr->end())); + + // Find the first marked object at or after "start". + start = mark_bitmap->getNextMarkedWordAddress(start, ntams); + while (start < ntams) { + oop obj = oop(start); + size_t obj_size = obj->size(); + HeapWord* obj_end = start + obj_size; + + assert(obj_end <= hr->end(), "Humongous objects must have been handled elsewhere."); + + mark_card_bitmap_range(start, obj_end); + + // Add the size of this object to the number of marked bytes. + marked_bytes += obj_size * HeapWordSize; + + // Find the next marked object after this one. + start = mark_bitmap->getNextMarkedWordAddress(obj_end, ntams); + } + + return marked_bytes; + } + + G1CardLiveDataHelper(G1CardLiveData* live_data, HeapWord* base_address) : + _region_bm(live_data->live_regions_bm()), + _card_bm(live_data->live_cards_bm()) { + // Calculate the card number for the bottom of the heap. Used + // in biasing indexes into the accounting card bitmaps. + _heap_card_bias = + uintptr_t(base_address) >> CardTableModRefBS::card_shift; + } +}; + +class G1CreateCardLiveDataTask: public AbstractGangTask { + // Aggregate the counting data that was constructed concurrently + // with marking. + class G1CreateLiveDataClosure : public HeapRegionClosure { + G1CardLiveDataHelper _helper; + + G1CMBitMap* _mark_bitmap; + + G1ConcurrentMark* _cm; + public: + G1CreateLiveDataClosure(G1CollectedHeap* g1h, + G1ConcurrentMark* cm, + G1CMBitMap* mark_bitmap, + G1CardLiveData* live_data) : + HeapRegionClosure(), + _helper(live_data, g1h->reserved_region().start()), + _mark_bitmap(mark_bitmap), + _cm(cm) { } + + bool doHeapRegion(HeapRegion* hr) { + size_t marked_bytes = _helper.mark_marked_during_marking(_mark_bitmap, hr); + if (marked_bytes > 0) { + hr->add_to_marked_bytes(marked_bytes); + } + + return (_cm->do_yield_check() && _cm->has_aborted()); + } + }; + + G1ConcurrentMark* _cm; + G1CardLiveData* _live_data; + HeapRegionClaimer _hr_claimer; + +public: + G1CreateCardLiveDataTask(G1CMBitMap* bitmap, + G1CardLiveData* live_data, + uint n_workers) : + AbstractGangTask("G1 Create Live Data"), + _live_data(live_data), + _hr_claimer(n_workers) { + } + + void work(uint worker_id) { + SuspendibleThreadSetJoiner sts_join; + + G1CollectedHeap* g1h = G1CollectedHeap::heap(); + G1ConcurrentMark* cm = g1h->concurrent_mark(); + G1CreateLiveDataClosure cl(g1h, cm, cm->nextMarkBitMap(), _live_data); + g1h->heap_region_par_iterate(&cl, worker_id, &_hr_claimer); + } +}; + +void G1CardLiveData::create(WorkGang* workers, G1CMBitMap* mark_bitmap) { + uint n_workers = workers->active_workers(); + + G1CreateCardLiveDataTask cl(mark_bitmap, + this, + n_workers); + workers->run_task(&cl); +} + +class G1FinalizeCardLiveDataTask: public AbstractGangTask { + // Finalizes the liveness counting data. + // Sets the bits corresponding to the interval [NTAMS, top] + // (which contains the implicitly live objects) in the + // card liveness bitmap. Also sets the bit for each region + // containing live data, in the region liveness bitmap. + class G1FinalizeCardLiveDataClosure: public HeapRegionClosure { + private: + G1CardLiveDataHelper _helper; + public: + G1FinalizeCardLiveDataClosure(G1CollectedHeap* g1h, + G1CMBitMap* bitmap, + G1CardLiveData* live_data) : + HeapRegionClosure(), + _helper(live_data, g1h->reserved_region().start()) { } + + bool doHeapRegion(HeapRegion* hr) { + bool allocated_since_marking = _helper.mark_allocated_since_marking(hr); + if (allocated_since_marking || hr->next_marked_bytes() > 0) { + _helper.set_bit_for_region(hr); + } + return false; + } + }; + + G1CMBitMap* _bitmap; + + G1CardLiveData* _live_data; + + HeapRegionClaimer _hr_claimer; + +public: + G1FinalizeCardLiveDataTask(G1CMBitMap* bitmap, G1CardLiveData* live_data, uint n_workers) : + AbstractGangTask("G1 Finalize Card Live Data"), + _bitmap(bitmap), + _live_data(live_data), + _hr_claimer(n_workers) { + } + + void work(uint worker_id) { + G1FinalizeCardLiveDataClosure cl(G1CollectedHeap::heap(), _bitmap, _live_data); + + G1CollectedHeap::heap()->heap_region_par_iterate(&cl, worker_id, &_hr_claimer); + } +}; + +void G1CardLiveData::finalize(WorkGang* workers, G1CMBitMap* mark_bitmap) { + // Finalize the live data. + G1FinalizeCardLiveDataTask cl(mark_bitmap, + this, + workers->active_workers()); + workers->run_task(&cl); +} + +class G1ClearCardLiveDataTask : public AbstractGangTask { + BitMap _bitmap; + size_t _num_chunks; + size_t _cur_chunk; +public: + G1ClearCardLiveDataTask(BitMap bitmap, size_t num_tasks) : + AbstractGangTask("G1 Clear Card Live Data"), + _bitmap(bitmap), + _num_chunks(num_tasks), + _cur_chunk(0) { + } + + static size_t chunk_size() { return M; } + + virtual void work(uint worker_id) { + while (true) { + size_t to_process = Atomic::add(1, &_cur_chunk) - 1; + if (to_process >= _num_chunks) { + break; + } + + BitMap::idx_t start = M * BitsPerByte * to_process; + BitMap::idx_t end = MIN2(start + M * BitsPerByte, _bitmap.size()); + _bitmap.clear_range(start, end); + } + } +}; + +void G1CardLiveData::clear(WorkGang* workers) { + guarantee(Universe::is_fully_initialized(), "Should not call this during initialization."); + + size_t const num_chunks = align_size_up(live_cards_bm().size_in_bytes(), G1ClearCardLiveDataTask::chunk_size()) / G1ClearCardLiveDataTask::chunk_size(); + + G1ClearCardLiveDataTask cl(live_cards_bm(), num_chunks); + workers->run_task(&cl); + + // The region live bitmap is always very small, even for huge heaps. Clear + // directly. + live_regions_bm().clear(); +} + +class G1VerifyCardLiveDataTask: public AbstractGangTask { + // Heap region closure used for verifying the live count data + // that was created concurrently and finalized during + // the remark pause. This closure is applied to the heap + // regions during the STW cleanup pause. + class G1VerifyCardLiveDataClosure: public HeapRegionClosure { + private: + G1CollectedHeap* _g1h; + G1CMBitMap* _mark_bitmap; + G1CardLiveDataHelper _helper; + + G1CardLiveData* _act_live_data; + + G1CardLiveData* _exp_live_data; + + int _failures; + + // Completely recreates the live data count for the given heap region and + // returns the number of bytes marked. + size_t create_live_data_count(HeapRegion* hr) { + size_t bytes_marked = _helper.mark_marked_during_marking(_mark_bitmap, hr); + bool allocated_since_marking = _helper.mark_allocated_since_marking(hr); + if (allocated_since_marking || bytes_marked > 0) { + _helper.set_bit_for_region(hr); + } + return bytes_marked; + } + public: + G1VerifyCardLiveDataClosure(G1CollectedHeap* g1h, + G1CMBitMap* mark_bitmap, + G1CardLiveData* act_live_data, + G1CardLiveData* exp_live_data) : + _g1h(g1h), + _mark_bitmap(mark_bitmap), + _helper(exp_live_data, g1h->reserved_region().start()), + _act_live_data(act_live_data), + _exp_live_data(exp_live_data), + _failures(0) { } + + int failures() const { return _failures; } + + bool doHeapRegion(HeapRegion* hr) { + int failures = 0; + + // Walk the marking bitmap for this region and set the corresponding bits + // in the expected region and card bitmaps. + size_t exp_marked_bytes = create_live_data_count(hr); + size_t act_marked_bytes = hr->next_marked_bytes(); + // Verify the marked bytes for this region. + + if (exp_marked_bytes != act_marked_bytes) { + failures += 1; + } else if (exp_marked_bytes > HeapRegion::GrainBytes) { + failures += 1; + } + + // Verify the bit, for this region, in the actual and expected + // (which was just calculated) region bit maps. + // We're not OK if the bit in the calculated expected region + // bitmap is set and the bit in the actual region bitmap is not. + uint index = hr->hrm_index(); + + bool expected = _exp_live_data->is_region_live(index); + bool actual = _act_live_data->is_region_live(index); + if (expected && !actual) { + failures += 1; + } + + // Verify that the card bit maps for the cards spanned by the current + // region match. We have an error if we have a set bit in the expected + // bit map and the corresponding bit in the actual bitmap is not set. + + BitMap::idx_t start_idx = _helper.card_live_bitmap_index_for(hr->bottom()); + BitMap::idx_t end_idx = _helper.card_live_bitmap_index_for(hr->top()); + + for (BitMap::idx_t i = start_idx; i < end_idx; i+=1) { + expected = _exp_live_data->is_card_live_at(i); + actual = _act_live_data->is_card_live_at(i); + + if (expected && !actual) { + failures += 1; + } + } + + _failures += failures; + + // We could stop iteration over the heap when we + // find the first violating region by returning true. + return false; + } + }; +protected: + G1CollectedHeap* _g1h; + G1CMBitMap* _mark_bitmap; + + G1CardLiveData* _act_live_data; + + G1CardLiveData _exp_live_data; + + int _failures; + + HeapRegionClaimer _hr_claimer; + +public: + G1VerifyCardLiveDataTask(G1CMBitMap* bitmap, + G1CardLiveData* act_live_data, + uint n_workers) + : AbstractGangTask("G1 Verify Card Live Data"), + _g1h(G1CollectedHeap::heap()), + _mark_bitmap(bitmap), + _act_live_data(act_live_data), + _exp_live_data(), + _failures(0), + _hr_claimer(n_workers) { + assert(VerifyDuringGC, "don't call this otherwise"); + _exp_live_data.initialize(_g1h->max_capacity(), _g1h->max_regions()); + } + + void work(uint worker_id) { + G1VerifyCardLiveDataClosure cl(_g1h, + _mark_bitmap, + _act_live_data, + &_exp_live_data); + _g1h->heap_region_par_iterate(&cl, worker_id, &_hr_claimer); + + Atomic::add(cl.failures(), &_failures); + } + + int failures() const { return _failures; } +}; + +void G1CardLiveData::verify(WorkGang* workers, G1CMBitMap* actual_bitmap) { + ResourceMark rm; + + G1VerifyCardLiveDataTask cl(actual_bitmap, + this, + workers->active_workers()); + workers->run_task(&cl); + + guarantee(cl.failures() == 0, "Unexpected accounting failures"); +} + +#ifndef PRODUCT +void G1CardLiveData::verify_is_clear() { + assert(live_cards_bm().count_one_bits() == 0, "Live cards bitmap must be clear."); + assert(live_regions_bm().count_one_bits() == 0, "Live regions bitmap must be clear."); +} +#endif diff --git a/hotspot/src/share/vm/gc/g1/g1CardLiveData.hpp b/hotspot/src/share/vm/gc/g1/g1CardLiveData.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d76fa66d3c49902f05b1d984395476add0786209 --- /dev/null +++ b/hotspot/src/share/vm/gc/g1/g1CardLiveData.hpp @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_GC_G1_G1CARDLIVEDATA_HPP +#define SHARE_VM_GC_G1_G1CARDLIVEDATA_HPP + +#include "gc/g1/g1CollectedHeap.hpp" +#include "utilities/bitMap.hpp" +#include "utilities/globalDefinitions.hpp" + +class G1CollectedHeap; +class G1CMBitMap; +class WorkGang; + +// Information about object liveness on the Java heap on a "card" basis. +// Can be used for various purposes, like as remembered set for completely +// coarsened remembered sets, scrubbing remembered sets or estimating liveness. +// This information is created as part of the concurrent marking cycle. +class G1CardLiveData VALUE_OBJ_CLASS_SPEC { + friend class G1CardLiveDataHelper; + friend class G1VerifyCardLiveDataTask; +private: + typedef BitMap::bm_word_t bm_word_t; + // Store some additional information about the covered area to be able to test. + size_t _max_capacity; + size_t _cards_per_region; + + // The per-card liveness bitmap. + bm_word_t* _live_cards; + size_t _live_cards_size_in_bits; + // The per-region liveness bitmap. + bm_word_t* _live_regions; + size_t _live_regions_size_in_bits; + // The bits in this bitmap contain for every card whether it contains + // at least part of at least one live object. + BitMap live_cards_bm() const { return BitMap(_live_cards, _live_cards_size_in_bits); } + // The bits in this bitmap indicate that a given region contains some live objects. + BitMap live_regions_bm() const { return BitMap(_live_regions, _live_regions_size_in_bits); } + + // Allocate a "large" bitmap from virtual memory with the given size in bits. + bm_word_t* allocate_large_bitmap(size_t size_in_bits); + void free_large_bitmap(bm_word_t* map, size_t size_in_bits); + + inline BitMap live_card_bitmap(uint region); + + inline bool is_card_live_at(BitMap::idx_t idx) const; + + size_t live_region_bitmap_size_in_bits() const; + size_t live_card_bitmap_size_in_bits() const; +public: + inline bool is_region_live(uint region) const; + + inline void remove_nonlive_cards(uint region, BitMap* bm); + inline void remove_nonlive_regions(BitMap* bm); + + G1CardLiveData(); + ~G1CardLiveData(); + + void initialize(size_t max_capacity, uint num_max_regions); + void pretouch(); + + // Create the initial liveness data based on the marking result from the bottom + // to the ntams of every region in the heap and the marks in the given bitmap. + void create(WorkGang* workers, G1CMBitMap* mark_bitmap); + // Finalize the liveness data. + void finalize(WorkGang* workers, G1CMBitMap* mark_bitmap); + + // Verify that the liveness count data created concurrently matches one created + // during this safepoint. + void verify(WorkGang* workers, G1CMBitMap* actual_bitmap); + // Clear all data structures, prepare for next processing. + void clear(WorkGang* workers); + + void verify_is_clear() PRODUCT_RETURN; +}; + +#endif /* SHARE_VM_GC_G1_G1CARDLIVEDATA_HPP */ + diff --git a/hotspot/src/share/vm/gc/g1/g1CardLiveData.inline.hpp b/hotspot/src/share/vm/gc/g1/g1CardLiveData.inline.hpp new file mode 100644 index 0000000000000000000000000000000000000000..fc14ed8bcf3c73be708cf4eda311a1918418b7d9 --- /dev/null +++ b/hotspot/src/share/vm/gc/g1/g1CardLiveData.inline.hpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_GC_G1_G1CARDLIVEDATA_INLINE_HPP +#define SHARE_VM_GC_G1_G1CARDLIVEDATA_INLINE_HPP + +#include "gc/g1/g1CardLiveData.hpp" +#include "utilities/bitMap.inline.hpp" +#include "utilities/globalDefinitions.hpp" + +inline BitMap G1CardLiveData::live_card_bitmap(uint region) { + return BitMap(_live_cards + ((size_t)region * _cards_per_region >> LogBitsPerWord), _cards_per_region); +} + +inline bool G1CardLiveData::is_card_live_at(BitMap::idx_t idx) const { + return live_cards_bm().at(idx); +} + +inline bool G1CardLiveData::is_region_live(uint region) const { + return live_regions_bm().at(region); +} + +inline void G1CardLiveData::remove_nonlive_cards(uint region, BitMap* bm) { + bm->set_intersection(live_card_bitmap(region)); +} + +inline void G1CardLiveData::remove_nonlive_regions(BitMap* bm) { + bm->set_intersection(live_regions_bm()); +} + +#endif /* SHARE_VM_GC_G1_G1CARDLIVEDATA_INLINE_HPP */ diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index 03d4e76f3a8853b03808fd3ae07ff6d6c5fd6dcf..3a775d5bca103e030b9a9d125f864e867f0c53ee 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -1425,6 +1425,7 @@ bool G1CollectedHeap::do_full_collection(bool explicit_gc, // the full GC has compacted objects and updated TAMS but not updated // the prev bitmap. if (G1VerifyBitmaps) { + GCTraceTime(Debug, gc)("Clear Bitmap for Verification"); _cm->clear_prev_bitmap(workers()); } _verifier->check_bitmaps("Full GC End"); @@ -1828,10 +1829,14 @@ G1RegionToSpaceMapper* G1CollectedHeap::create_aux_memory_mapper(const char* des HeapRegion::GrainBytes, translation_factor, mtGC); - if (TracePageSizes) { - tty->print_cr("G1 '%s': pg_sz=" SIZE_FORMAT " base=" PTR_FORMAT " size=" SIZE_FORMAT " alignment=" SIZE_FORMAT " reqsize=" SIZE_FORMAT, - description, preferred_page_size, p2i(rs.base()), rs.size(), rs.alignment(), size); - } + + os::trace_page_sizes_for_requested_size(description, + size, + preferred_page_size, + rs.alignment(), + rs.base(), + rs.size()); + return result; } @@ -1905,26 +1910,28 @@ jint G1CollectedHeap::initialize() { HeapRegion::GrainBytes, 1, mtJavaHeap); - os::trace_page_sizes("G1 Heap", collector_policy()->min_heap_byte_size(), - max_byte_size, page_size, + os::trace_page_sizes("Heap", + collector_policy()->min_heap_byte_size(), + max_byte_size, + page_size, heap_rs.base(), heap_rs.size()); heap_storage->set_mapping_changed_listener(&_listener); // Create storage for the BOT, card table, card counts table (hot card cache) and the bitmaps. G1RegionToSpaceMapper* bot_storage = - create_aux_memory_mapper("Block offset table", + create_aux_memory_mapper("Block Offset Table", G1BlockOffsetTable::compute_size(g1_rs.size() / HeapWordSize), G1BlockOffsetTable::heap_map_factor()); ReservedSpace cardtable_rs(G1SATBCardTableLoggingModRefBS::compute_size(g1_rs.size() / HeapWordSize)); G1RegionToSpaceMapper* cardtable_storage = - create_aux_memory_mapper("Card table", + create_aux_memory_mapper("Card Table", G1SATBCardTableLoggingModRefBS::compute_size(g1_rs.size() / HeapWordSize), G1SATBCardTableLoggingModRefBS::heap_map_factor()); G1RegionToSpaceMapper* card_counts_storage = - create_aux_memory_mapper("Card counts table", + create_aux_memory_mapper("Card Counts Table", G1CardCounts::compute_size(g1_rs.size() / HeapWordSize), G1CardCounts::heap_map_factor()); @@ -1944,7 +1951,7 @@ jint G1CollectedHeap::initialize() { const uint max_region_idx = (1U << (sizeof(RegionIdx_t)*BitsPerByte-1)) - 1; guarantee((max_regions() - 1) <= max_region_idx, "too many regions"); - G1RemSet::initialize(max_regions()); + g1_rem_set()->initialize(max_capacity(), max_regions()); size_t max_cards_per_region = ((size_t)1 << (sizeof(CardIdx_t)*BitsPerByte-1)) - 1; guarantee(HeapRegion::CardsPerRegion > 0, "make sure it's initialized"); @@ -2735,7 +2742,7 @@ void G1CollectedHeap::print_gc_threads_on(outputStream* st) const { _cmThread->print_on(st); st->cr(); _cm->print_worker_threads_on(st); - _cg1r->print_worker_threads_on(st); + _cg1r->print_worker_threads_on(st); // also prints the sample thread if (G1StringDedup::is_enabled()) { G1StringDedup::print_worker_threads_on(st); } @@ -2744,7 +2751,8 @@ void G1CollectedHeap::print_gc_threads_on(outputStream* st) const { void G1CollectedHeap::gc_threads_do(ThreadClosure* tc) const { workers()->threads_do(tc); tc->do_thread(_cmThread); - _cg1r->threads_do(tc); + _cm->threads_do(tc); + _cg1r->threads_do(tc); // also iterates over the sample thread if (G1StringDedup::is_enabled()) { G1StringDedup::threads_do(tc); } @@ -2939,13 +2947,17 @@ class RegisterHumongousWithInCSetFastTestClosure : public HeapRegionClosure { : rset->is_empty(); } - bool is_typeArray_region(HeapRegion* region) const { - return oop(region->bottom())->is_typeArray(); - } - bool humongous_region_is_candidate(G1CollectedHeap* heap, HeapRegion* region) const { assert(region->is_starts_humongous(), "Must start a humongous object"); + oop obj = oop(region->bottom()); + + // Dead objects cannot be eager reclaim candidates. Due to class + // unloading it is unsafe to query their classes so we return early. + if (heap->is_obj_dead(obj, region)) { + return false; + } + // Candidate selection must satisfy the following constraints // while concurrent marking is in progress: // @@ -2982,7 +2994,7 @@ class RegisterHumongousWithInCSetFastTestClosure : public HeapRegionClosure { // important use case for eager reclaim, and this special handling // may reduce needed headroom. - return is_typeArray_region(region) && is_remset_small(region); + return obj->is_typeArray() && is_remset_small(region); } public: @@ -4440,7 +4452,6 @@ void G1CollectedHeap::process_weak_jni_handles() { } void G1CollectedHeap::preserve_cm_referents(G1ParScanThreadStateSet* per_thread_states) { - double preserve_cm_referents_start = os::elapsedTime(); // Any reference objects, in the collection set, that were 'discovered' // by the CM ref processor should have already been copied (either by // applying the external root copy closure to the discovered lists, or @@ -4461,16 +4472,24 @@ void G1CollectedHeap::preserve_cm_referents(G1ParScanThreadStateSet* per_thread_ // objects discovered by the STW ref processor in case one of these // referents points to another object which is also referenced by an // object discovered by the STW ref processor. + double preserve_cm_referents_time = 0.0; + + // To avoid spawning task when there is no work to do, check that + // a concurrent cycle is active and that some references have been + // discovered. + if (concurrent_mark()->cmThread()->during_cycle() && + ref_processor_cm()->has_discovered_references()) { + double preserve_cm_referents_start = os::elapsedTime(); + uint no_of_gc_workers = workers()->active_workers(); + G1ParPreserveCMReferentsTask keep_cm_referents(this, + per_thread_states, + no_of_gc_workers, + _task_queues); + workers()->run_task(&keep_cm_referents); + preserve_cm_referents_time = os::elapsedTime() - preserve_cm_referents_start; + } - uint no_of_gc_workers = workers()->active_workers(); - - G1ParPreserveCMReferentsTask keep_cm_referents(this, - per_thread_states, - no_of_gc_workers, - _task_queues); - workers()->run_task(&keep_cm_referents); - - g1_policy()->phase_times()->record_preserve_cm_referents_time_ms((os::elapsedTime() - preserve_cm_referents_start) * 1000.0); + g1_policy()->phase_times()->record_preserve_cm_referents_time_ms(preserve_cm_referents_time * 1000.0); } // Weak Reference processing during an evacuation pause (part 1). @@ -4787,27 +4806,23 @@ public: class G1ParScrubRemSetTask: public AbstractGangTask { protected: G1RemSet* _g1rs; - BitMap* _region_bm; - BitMap* _card_bm; HeapRegionClaimer _hrclaimer; public: - G1ParScrubRemSetTask(G1RemSet* g1_rs, BitMap* region_bm, BitMap* card_bm, uint num_workers) : + G1ParScrubRemSetTask(G1RemSet* g1_rs, uint num_workers) : AbstractGangTask("G1 ScrubRS"), _g1rs(g1_rs), - _region_bm(region_bm), - _card_bm(card_bm), _hrclaimer(num_workers) { } void work(uint worker_id) { - _g1rs->scrub(_region_bm, _card_bm, worker_id, &_hrclaimer); + _g1rs->scrub(worker_id, &_hrclaimer); } }; -void G1CollectedHeap::scrub_rem_set(BitMap* region_bm, BitMap* card_bm) { +void G1CollectedHeap::scrub_rem_set() { uint num_workers = workers()->active_workers(); - G1ParScrubRemSetTask g1_par_scrub_rs_task(g1_rem_set(), region_bm, card_bm, num_workers); + G1ParScrubRemSetTask g1_par_scrub_rs_task(g1_rem_set(), num_workers); workers()->run_task(&g1_par_scrub_rs_task); } @@ -4821,6 +4836,9 @@ void G1CollectedHeap::cleanUpCardTable() { workers()->run_task(&cleanup_task); #ifndef PRODUCT + // Need to synchronize with concurrent cleanup since it needs to + // finish its card table clearing before we can verify. + wait_while_free_regions_coming(); _verifier->verify_card_table_cleanup(); #endif } diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp index 4bde7c70d04f91d5302377cfebd5f6d1496e09d4..e98d57af7fbf059d871b97d6e06ff78683a9ce36 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp @@ -992,7 +992,8 @@ public: // The rem set and barrier set. G1RemSet* g1_rem_set() const { return _g1_rem_set; } - void scrub_rem_set(BitMap* region_bm, BitMap* card_bm); + // Try to minimize the remembered set. + void scrub_rem_set(); unsigned get_gc_time_stamp() { return _gc_time_stamp; diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp index eaf329b3acd4d6beef85397ad46f9c1920ffb62b..040367b5be199bb4aba610526531d4d290b83639 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp @@ -28,7 +28,7 @@ #include "gc/g1/g1CollectedHeap.hpp" #include "gc/g1/g1CollectorPolicy.hpp" #include "gc/g1/g1CollectorState.hpp" -#include "gc/g1/g1ConcurrentMark.hpp" +#include "gc/g1/g1ConcurrentMark.inline.hpp" #include "gc/g1/g1SATBCardTableModRefBS.hpp" #include "gc/g1/heapRegionManager.inline.hpp" #include "gc/g1/heapRegionSet.inline.hpp" diff --git a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp index 2ed3dd0f4edcef6b786f07693dc247caeaa255ae..b36583e98227c39a5798b677278218c2c9546638 100644 --- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp @@ -33,6 +33,7 @@ #include "gc/g1/g1ConcurrentMark.inline.hpp" #include "gc/g1/g1HeapVerifier.hpp" #include "gc/g1/g1OopClosures.inline.hpp" +#include "gc/g1/g1CardLiveData.inline.hpp" #include "gc/g1/g1StringDedup.hpp" #include "gc/g1/heapRegion.inline.hpp" #include "gc/g1/heapRegionRemSet.hpp" @@ -355,10 +356,6 @@ G1ConcurrentMark::G1ConcurrentMark(G1CollectedHeap* g1h, G1RegionToSpaceMapper* _sleep_factor(0.0), _marking_task_overhead(1.0), _cleanup_list("Cleanup List"), - _region_bm((BitMap::idx_t)(g1h->max_regions()), false /* in_resource_area*/), - _card_bm((g1h->reserved_region().byte_size() + CardTableModRefBS::card_size - 1) >> - CardTableModRefBS::card_shift, - false /* in_resource_area*/), _prevMarkBitMap(&_markBitMap1), _nextMarkBitMap(&_markBitMap2), @@ -390,8 +387,6 @@ G1ConcurrentMark::G1ConcurrentMark(G1CollectedHeap* g1h, G1RegionToSpaceMapper* _parallel_workers(NULL), - _count_card_bitmaps(NULL), - _count_marked_bytes(NULL), _completed_initialization(false) { _markBitMap1.initialize(g1h->reserved_region(), prev_bitmap_storage); @@ -505,40 +500,19 @@ G1ConcurrentMark::G1ConcurrentMark(G1CollectedHeap* g1h, G1RegionToSpaceMapper* _tasks = NEW_C_HEAP_ARRAY(G1CMTask*, _max_worker_id, mtGC); _accum_task_vtime = NEW_C_HEAP_ARRAY(double, _max_worker_id, mtGC); - _count_card_bitmaps = NEW_C_HEAP_ARRAY(BitMap, _max_worker_id, mtGC); - _count_marked_bytes = NEW_C_HEAP_ARRAY(size_t*, _max_worker_id, mtGC); - - BitMap::idx_t card_bm_size = _card_bm.size(); - // so that the assertion in MarkingTaskQueue::task_queue doesn't fail _active_tasks = _max_worker_id; - uint max_regions = _g1h->max_regions(); for (uint i = 0; i < _max_worker_id; ++i) { G1CMTaskQueue* task_queue = new G1CMTaskQueue(); task_queue->initialize(); _task_queues->register_queue(i, task_queue); - _count_card_bitmaps[i] = BitMap(card_bm_size, false); - _count_marked_bytes[i] = NEW_C_HEAP_ARRAY(size_t, max_regions, mtGC); - - _tasks[i] = new G1CMTask(i, this, - _count_marked_bytes[i], - &_count_card_bitmaps[i], - task_queue, _task_queues); + _tasks[i] = new G1CMTask(i, this, task_queue, _task_queues); _accum_task_vtime[i] = 0.0; } - // Calculate the card number for the bottom of the heap. Used - // in biasing indexes into the accounting card bitmaps. - _heap_bottom_card_num = - intptr_t(uintptr_t(_g1h->reserved_region().start()) >> - CardTableModRefBS::card_shift); - - // Clear all the liveness counting data - clear_all_count_data(); - // so that the call below can read a sensible value _heap_start = g1h->reserved_region().start(); set_non_marking_state(); @@ -716,10 +690,11 @@ void G1ConcurrentMark::cleanup_for_next_mark() { clear_bitmap(_nextMarkBitMap, _parallel_workers, true); - // Clear the liveness counting data. If the marking has been aborted, the abort() + // Clear the live count data. If the marking has been aborted, the abort() // call already did that. if (!has_aborted()) { - clear_all_count_data(); + clear_live_data(_parallel_workers); + DEBUG_ONLY(verify_live_data_clear()); } // Repeat the asserts from above. @@ -901,7 +876,7 @@ public: double elapsed_vtime_sec = end_vtime_sec - start_vtime_sec; _cm->clear_has_overflown(); - _cm->do_yield_check(worker_id); + _cm->do_yield_check(); jlong sleep_time_ms; if (!_cm->has_aborted() && the_task->has_aborted()) { @@ -951,10 +926,10 @@ uint G1ConcurrentMark::calc_parallel_marking_threads() { return n_conc_workers; } -void G1ConcurrentMark::scanRootRegion(HeapRegion* hr, uint worker_id) { +void G1ConcurrentMark::scanRootRegion(HeapRegion* hr) { // Currently, only survivors can be root regions. assert(hr->next_top_at_mark_start() == hr->bottom(), "invariant"); - G1RootRegionScanClosure cl(_g1h, this, worker_id); + G1RootRegionScanClosure cl(_g1h, this); const uintx interval = PrefetchScanIntervalInBytes; HeapWord* curr = hr->bottom(); @@ -983,7 +958,7 @@ public: G1CMRootRegions* root_regions = _cm->root_regions(); HeapRegion* hr = root_regions->claim_next(); while (hr != NULL) { - _cm->scanRootRegion(hr, worker_id); + _cm->scanRootRegion(hr); hr = root_regions->claim_next(); } } @@ -1107,14 +1082,6 @@ void G1ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) { // marking due to overflowing the global mark stack. reset_marking_state(); } else { - { - GCTraceTime(Debug, gc, phases) trace("Aggregate Data", _gc_timer_cm); - - // Aggregate the per-task counting data that we have accumulated - // while marking. - aggregate_count_data(); - } - SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); // We're done with marking. // This is the end of the marking cycle, we're expected all @@ -1150,363 +1117,6 @@ void G1ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) { _gc_tracer_cm->report_object_count_after_gc(&is_alive); } -// Base class of the closures that finalize and verify the -// liveness counting data. -class G1CMCountDataClosureBase: public HeapRegionClosure { -protected: - G1CollectedHeap* _g1h; - G1ConcurrentMark* _cm; - CardTableModRefBS* _ct_bs; - - BitMap* _region_bm; - BitMap* _card_bm; - - // Takes a region that's not empty (i.e., it has at least one - // live object in it and sets its corresponding bit on the region - // bitmap to 1. - void set_bit_for_region(HeapRegion* hr) { - BitMap::idx_t index = (BitMap::idx_t) hr->hrm_index(); - _region_bm->par_at_put(index, true); - } - -public: - G1CMCountDataClosureBase(G1CollectedHeap* g1h, - BitMap* region_bm, BitMap* card_bm): - _g1h(g1h), _cm(g1h->concurrent_mark()), - _ct_bs(barrier_set_cast(g1h->barrier_set())), - _region_bm(region_bm), _card_bm(card_bm) { } -}; - -// Closure that calculates the # live objects per region. Used -// for verification purposes during the cleanup pause. -class CalcLiveObjectsClosure: public G1CMCountDataClosureBase { - G1CMBitMapRO* _bm; - size_t _region_marked_bytes; - -public: - CalcLiveObjectsClosure(G1CMBitMapRO *bm, G1CollectedHeap* g1h, - BitMap* region_bm, BitMap* card_bm) : - G1CMCountDataClosureBase(g1h, region_bm, card_bm), - _bm(bm), _region_marked_bytes(0) { } - - bool doHeapRegion(HeapRegion* hr) { - HeapWord* ntams = hr->next_top_at_mark_start(); - HeapWord* start = hr->bottom(); - - assert(start <= hr->end() && start <= ntams && ntams <= hr->end(), - "Preconditions not met - " - "start: " PTR_FORMAT ", ntams: " PTR_FORMAT ", end: " PTR_FORMAT, - p2i(start), p2i(ntams), p2i(hr->end())); - - // Find the first marked object at or after "start". - start = _bm->getNextMarkedWordAddress(start, ntams); - - size_t marked_bytes = 0; - - while (start < ntams) { - oop obj = oop(start); - int obj_sz = obj->size(); - HeapWord* obj_end = start + obj_sz; - - BitMap::idx_t start_idx = _cm->card_bitmap_index_for(start); - BitMap::idx_t end_idx = _cm->card_bitmap_index_for(obj_end); - - // Note: if we're looking at the last region in heap - obj_end - // could be actually just beyond the end of the heap; end_idx - // will then correspond to a (non-existent) card that is also - // just beyond the heap. - if (_g1h->is_in_g1_reserved(obj_end) && !_ct_bs->is_card_aligned(obj_end)) { - // end of object is not card aligned - increment to cover - // all the cards spanned by the object - end_idx += 1; - } - - // Set the bits in the card BM for the cards spanned by this object. - _cm->set_card_bitmap_range(_card_bm, start_idx, end_idx, true /* is_par */); - - // Add the size of this object to the number of marked bytes. - marked_bytes += (size_t)obj_sz * HeapWordSize; - - // This will happen if we are handling a humongous object that spans - // several heap regions. - if (obj_end > hr->end()) { - break; - } - // Find the next marked object after this one. - start = _bm->getNextMarkedWordAddress(obj_end, ntams); - } - - // Mark the allocated-since-marking portion... - HeapWord* top = hr->top(); - if (ntams < top) { - BitMap::idx_t start_idx = _cm->card_bitmap_index_for(ntams); - BitMap::idx_t end_idx = _cm->card_bitmap_index_for(top); - - // Note: if we're looking at the last region in heap - top - // could be actually just beyond the end of the heap; end_idx - // will then correspond to a (non-existent) card that is also - // just beyond the heap. - if (_g1h->is_in_g1_reserved(top) && !_ct_bs->is_card_aligned(top)) { - // end of object is not card aligned - increment to cover - // all the cards spanned by the object - end_idx += 1; - } - _cm->set_card_bitmap_range(_card_bm, start_idx, end_idx, true /* is_par */); - - // This definitely means the region has live objects. - set_bit_for_region(hr); - } - - // Update the live region bitmap. - if (marked_bytes > 0) { - set_bit_for_region(hr); - } - - // Set the marked bytes for the current region so that - // it can be queried by a calling verification routine - _region_marked_bytes = marked_bytes; - - return false; - } - - size_t region_marked_bytes() const { return _region_marked_bytes; } -}; - -// Heap region closure used for verifying the counting data -// that was accumulated concurrently and aggregated during -// the remark pause. This closure is applied to the heap -// regions during the STW cleanup pause. - -class VerifyLiveObjectDataHRClosure: public HeapRegionClosure { - G1CollectedHeap* _g1h; - G1ConcurrentMark* _cm; - CalcLiveObjectsClosure _calc_cl; - BitMap* _region_bm; // Region BM to be verified - BitMap* _card_bm; // Card BM to be verified - - BitMap* _exp_region_bm; // Expected Region BM values - BitMap* _exp_card_bm; // Expected card BM values - - int _failures; - -public: - VerifyLiveObjectDataHRClosure(G1CollectedHeap* g1h, - BitMap* region_bm, - BitMap* card_bm, - BitMap* exp_region_bm, - BitMap* exp_card_bm) : - _g1h(g1h), _cm(g1h->concurrent_mark()), - _calc_cl(_cm->nextMarkBitMap(), g1h, exp_region_bm, exp_card_bm), - _region_bm(region_bm), _card_bm(card_bm), - _exp_region_bm(exp_region_bm), _exp_card_bm(exp_card_bm), - _failures(0) { } - - int failures() const { return _failures; } - - bool doHeapRegion(HeapRegion* hr) { - int failures = 0; - - // Call the CalcLiveObjectsClosure to walk the marking bitmap for - // this region and set the corresponding bits in the expected region - // and card bitmaps. - bool res = _calc_cl.doHeapRegion(hr); - assert(res == false, "should be continuing"); - - // Verify the marked bytes for this region. - size_t exp_marked_bytes = _calc_cl.region_marked_bytes(); - size_t act_marked_bytes = hr->next_marked_bytes(); - - if (exp_marked_bytes > act_marked_bytes) { - if (hr->is_starts_humongous()) { - // For start_humongous regions, the size of the whole object will be - // in exp_marked_bytes. - HeapRegion* region = hr; - int num_regions; - for (num_regions = 0; region != NULL; num_regions++) { - region = _g1h->next_region_in_humongous(region); - } - if ((num_regions-1) * HeapRegion::GrainBytes >= exp_marked_bytes) { - failures += 1; - } else if (num_regions * HeapRegion::GrainBytes < exp_marked_bytes) { - failures += 1; - } - } else { - // We're not OK if expected marked bytes > actual marked bytes. It means - // we have missed accounting some objects during the actual marking. - failures += 1; - } - } - - // Verify the bit, for this region, in the actual and expected - // (which was just calculated) region bit maps. - // We're not OK if the bit in the calculated expected region - // bitmap is set and the bit in the actual region bitmap is not. - BitMap::idx_t index = (BitMap::idx_t) hr->hrm_index(); - - bool expected = _exp_region_bm->at(index); - bool actual = _region_bm->at(index); - if (expected && !actual) { - failures += 1; - } - - // Verify that the card bit maps for the cards spanned by the current - // region match. We have an error if we have a set bit in the expected - // bit map and the corresponding bit in the actual bitmap is not set. - - BitMap::idx_t start_idx = _cm->card_bitmap_index_for(hr->bottom()); - BitMap::idx_t end_idx = _cm->card_bitmap_index_for(hr->top()); - - for (BitMap::idx_t i = start_idx; i < end_idx; i+=1) { - expected = _exp_card_bm->at(i); - actual = _card_bm->at(i); - - if (expected && !actual) { - failures += 1; - } - } - - _failures += failures; - - // We could stop iteration over the heap when we - // find the first violating region by returning true. - return false; - } -}; - -class G1ParVerifyFinalCountTask: public AbstractGangTask { -protected: - G1CollectedHeap* _g1h; - G1ConcurrentMark* _cm; - BitMap* _actual_region_bm; - BitMap* _actual_card_bm; - - uint _n_workers; - - BitMap* _expected_region_bm; - BitMap* _expected_card_bm; - - int _failures; - - HeapRegionClaimer _hrclaimer; - -public: - G1ParVerifyFinalCountTask(G1CollectedHeap* g1h, - BitMap* region_bm, BitMap* card_bm, - BitMap* expected_region_bm, BitMap* expected_card_bm) - : AbstractGangTask("G1 verify final counting"), - _g1h(g1h), _cm(_g1h->concurrent_mark()), - _actual_region_bm(region_bm), _actual_card_bm(card_bm), - _expected_region_bm(expected_region_bm), _expected_card_bm(expected_card_bm), - _failures(0), - _n_workers(_g1h->workers()->active_workers()), _hrclaimer(_n_workers) { - assert(VerifyDuringGC, "don't call this otherwise"); - assert(_expected_card_bm->size() == _actual_card_bm->size(), "sanity"); - assert(_expected_region_bm->size() == _actual_region_bm->size(), "sanity"); - } - - void work(uint worker_id) { - assert(worker_id < _n_workers, "invariant"); - - VerifyLiveObjectDataHRClosure verify_cl(_g1h, - _actual_region_bm, _actual_card_bm, - _expected_region_bm, - _expected_card_bm); - - _g1h->heap_region_par_iterate(&verify_cl, worker_id, &_hrclaimer); - - Atomic::add(verify_cl.failures(), &_failures); - } - - int failures() const { return _failures; } -}; - -// Closure that finalizes the liveness counting data. -// Used during the cleanup pause. -// Sets the bits corresponding to the interval [NTAMS, top] -// (which contains the implicitly live objects) in the -// card liveness bitmap. Also sets the bit for each region, -// containing live data, in the region liveness bitmap. - -class FinalCountDataUpdateClosure: public G1CMCountDataClosureBase { - public: - FinalCountDataUpdateClosure(G1CollectedHeap* g1h, - BitMap* region_bm, - BitMap* card_bm) : - G1CMCountDataClosureBase(g1h, region_bm, card_bm) { } - - bool doHeapRegion(HeapRegion* hr) { - HeapWord* ntams = hr->next_top_at_mark_start(); - HeapWord* top = hr->top(); - - assert(hr->bottom() <= ntams && ntams <= hr->end(), "Preconditions."); - - // Mark the allocated-since-marking portion... - if (ntams < top) { - // This definitely means the region has live objects. - set_bit_for_region(hr); - - // Now set the bits in the card bitmap for [ntams, top) - BitMap::idx_t start_idx = _cm->card_bitmap_index_for(ntams); - BitMap::idx_t end_idx = _cm->card_bitmap_index_for(top); - - // Note: if we're looking at the last region in heap - top - // could be actually just beyond the end of the heap; end_idx - // will then correspond to a (non-existent) card that is also - // just beyond the heap. - if (_g1h->is_in_g1_reserved(top) && !_ct_bs->is_card_aligned(top)) { - // end of object is not card aligned - increment to cover - // all the cards spanned by the object - end_idx += 1; - } - - assert(end_idx <= _card_bm->size(), - "oob: end_idx= " SIZE_FORMAT ", bitmap size= " SIZE_FORMAT, - end_idx, _card_bm->size()); - assert(start_idx < _card_bm->size(), - "oob: start_idx= " SIZE_FORMAT ", bitmap size= " SIZE_FORMAT, - start_idx, _card_bm->size()); - - _cm->set_card_bitmap_range(_card_bm, start_idx, end_idx, true /* is_par */); - } - - // Set the bit for the region if it contains live data - if (hr->next_marked_bytes() > 0) { - set_bit_for_region(hr); - } - - return false; - } -}; - -class G1ParFinalCountTask: public AbstractGangTask { -protected: - G1CollectedHeap* _g1h; - G1ConcurrentMark* _cm; - BitMap* _actual_region_bm; - BitMap* _actual_card_bm; - - uint _n_workers; - HeapRegionClaimer _hrclaimer; - -public: - G1ParFinalCountTask(G1CollectedHeap* g1h, BitMap* region_bm, BitMap* card_bm) - : AbstractGangTask("G1 final counting"), - _g1h(g1h), _cm(_g1h->concurrent_mark()), - _actual_region_bm(region_bm), _actual_card_bm(card_bm), - _n_workers(_g1h->workers()->active_workers()), _hrclaimer(_n_workers) { - } - - void work(uint worker_id) { - assert(worker_id < _n_workers, "invariant"); - - FinalCountDataUpdateClosure final_update_cl(_g1h, - _actual_region_bm, - _actual_card_bm); - - _g1h->heap_region_par_iterate(&final_update_cl, worker_id, &_hrclaimer); - } -}; - class G1NoteEndOfConcMarkClosure : public HeapRegionClosure { G1CollectedHeap* _g1; size_t _freed_bytes; @@ -1637,31 +1247,16 @@ void G1ConcurrentMark::cleanup() { HeapRegionRemSet::reset_for_cleanup_tasks(); - // Do counting once more with the world stopped for good measure. - G1ParFinalCountTask g1_par_count_task(g1h, &_region_bm, &_card_bm); - - g1h->workers()->run_task(&g1_par_count_task); + { + GCTraceTime(Debug, gc)("Finalize Live Data"); + finalize_live_data(); + } if (VerifyDuringGC) { - // Verify that the counting data accumulated during marking matches - // that calculated by walking the marking bitmap. - - // Bitmaps to hold expected values - BitMap expected_region_bm(_region_bm.size(), true); - BitMap expected_card_bm(_card_bm.size(), true); - - G1ParVerifyFinalCountTask g1_par_verify_task(g1h, - &_region_bm, - &_card_bm, - &expected_region_bm, - &expected_card_bm); - - g1h->workers()->run_task(&g1_par_verify_task); - - guarantee(g1_par_verify_task.failures() == 0, "Unexpected accounting failures"); + GCTraceTime(Debug, gc)("Verify Live Data"); + verify_live_data(); } - size_t start_used_bytes = g1h->used(); g1h->collector_state()->set_mark_in_progress(false); double count_end = os::elapsedTime(); @@ -1696,7 +1291,7 @@ void G1ConcurrentMark::cleanup() { // regions. if (G1ScrubRemSets) { double rs_scrub_start = os::elapsedTime(); - g1h->scrub_rem_set(&_region_bm, &_card_bm); + g1h->scrub_rem_set(); _total_rs_scrub_time += (os::elapsedTime() - rs_scrub_start); } @@ -2160,7 +1755,7 @@ private: oop obj = static_cast(entry); assert(obj->is_oop(true /* ignore mark word */), "Invalid oop in SATB buffer: " PTR_FORMAT, p2i(obj)); - _task->make_reference_grey(obj, hr); + _task->make_reference_grey(obj); } } @@ -2401,167 +1996,27 @@ void G1ConcurrentMark::verify_no_cset_oops() { } } #endif // PRODUCT - -// Aggregate the counting data that was constructed concurrently -// with marking. -class AggregateCountDataHRClosure: public HeapRegionClosure { - G1CollectedHeap* _g1h; - G1ConcurrentMark* _cm; - CardTableModRefBS* _ct_bs; - BitMap* _cm_card_bm; - uint _max_worker_id; - - public: - AggregateCountDataHRClosure(G1CollectedHeap* g1h, - BitMap* cm_card_bm, - uint max_worker_id) : - _g1h(g1h), _cm(g1h->concurrent_mark()), - _ct_bs(barrier_set_cast(g1h->barrier_set())), - _cm_card_bm(cm_card_bm), _max_worker_id(max_worker_id) { } - - bool doHeapRegion(HeapRegion* hr) { - HeapWord* start = hr->bottom(); - HeapWord* limit = hr->next_top_at_mark_start(); - HeapWord* end = hr->end(); - - assert(start <= limit && limit <= hr->top() && hr->top() <= hr->end(), - "Preconditions not met - " - "start: " PTR_FORMAT ", limit: " PTR_FORMAT ", " - "top: " PTR_FORMAT ", end: " PTR_FORMAT, - p2i(start), p2i(limit), p2i(hr->top()), p2i(hr->end())); - - assert(hr->next_marked_bytes() == 0, "Precondition"); - - if (start == limit) { - // NTAMS of this region has not been set so nothing to do. - return false; - } - - // 'start' should be in the heap. - assert(_g1h->is_in_g1_reserved(start) && _ct_bs->is_card_aligned(start), "sanity"); - // 'end' *may* be just beyond the end of the heap (if hr is the last region) - assert(!_g1h->is_in_g1_reserved(end) || _ct_bs->is_card_aligned(end), "sanity"); - - BitMap::idx_t start_idx = _cm->card_bitmap_index_for(start); - BitMap::idx_t limit_idx = _cm->card_bitmap_index_for(limit); - BitMap::idx_t end_idx = _cm->card_bitmap_index_for(end); - - // If ntams is not card aligned then we bump card bitmap index - // for limit so that we get the all the cards spanned by - // the object ending at ntams. - // Note: if this is the last region in the heap then ntams - // could be actually just beyond the end of the the heap; - // limit_idx will then correspond to a (non-existent) card - // that is also outside the heap. - if (_g1h->is_in_g1_reserved(limit) && !_ct_bs->is_card_aligned(limit)) { - limit_idx += 1; - } - - assert(limit_idx <= end_idx, "or else use atomics"); - - // Aggregate the "stripe" in the count data associated with hr. - uint hrm_index = hr->hrm_index(); - size_t marked_bytes = 0; - - for (uint i = 0; i < _max_worker_id; i += 1) { - size_t* marked_bytes_array = _cm->count_marked_bytes_array_for(i); - BitMap* task_card_bm = _cm->count_card_bitmap_for(i); - - // Fetch the marked_bytes in this region for task i and - // add it to the running total for this region. - marked_bytes += marked_bytes_array[hrm_index]; - - // Now union the bitmaps[0,max_worker_id)[start_idx..limit_idx) - // into the global card bitmap. - BitMap::idx_t scan_idx = task_card_bm->get_next_one_offset(start_idx, limit_idx); - - while (scan_idx < limit_idx) { - assert(task_card_bm->at(scan_idx) == true, "should be"); - _cm_card_bm->set_bit(scan_idx); - assert(_cm_card_bm->at(scan_idx) == true, "should be"); - - // BitMap::get_next_one_offset() can handle the case when - // its left_offset parameter is greater than its right_offset - // parameter. It does, however, have an early exit if - // left_offset == right_offset. So let's limit the value - // passed in for left offset here. - BitMap::idx_t next_idx = MIN2(scan_idx + 1, limit_idx); - scan_idx = task_card_bm->get_next_one_offset(next_idx, limit_idx); - } - } - - // Update the marked bytes for this region. - hr->add_to_marked_bytes(marked_bytes); - - // Next heap region - return false; - } -}; - -class G1AggregateCountDataTask: public AbstractGangTask { -protected: - G1CollectedHeap* _g1h; - G1ConcurrentMark* _cm; - BitMap* _cm_card_bm; - uint _max_worker_id; - uint _active_workers; - HeapRegionClaimer _hrclaimer; - -public: - G1AggregateCountDataTask(G1CollectedHeap* g1h, - G1ConcurrentMark* cm, - BitMap* cm_card_bm, - uint max_worker_id, - uint n_workers) : - AbstractGangTask("Count Aggregation"), - _g1h(g1h), _cm(cm), _cm_card_bm(cm_card_bm), - _max_worker_id(max_worker_id), - _active_workers(n_workers), - _hrclaimer(_active_workers) { - } - - void work(uint worker_id) { - AggregateCountDataHRClosure cl(_g1h, _cm_card_bm, _max_worker_id); - - _g1h->heap_region_par_iterate(&cl, worker_id, &_hrclaimer); - } -}; - - -void G1ConcurrentMark::aggregate_count_data() { - uint n_workers = _g1h->workers()->active_workers(); - - G1AggregateCountDataTask g1_par_agg_task(_g1h, this, &_card_bm, - _max_worker_id, n_workers); - - _g1h->workers()->run_task(&g1_par_agg_task); +void G1ConcurrentMark::create_live_data() { + _g1h->g1_rem_set()->create_card_live_data(_parallel_workers, _nextMarkBitMap); } -// Clear the per-worker arrays used to store the per-region counting data -void G1ConcurrentMark::clear_all_count_data() { - // Clear the global card bitmap - it will be filled during - // liveness count aggregation (during remark) and the - // final counting task. - _card_bm.clear(); - - // Clear the global region bitmap - it will be filled as part - // of the final counting task. - _region_bm.clear(); - - uint max_regions = _g1h->max_regions(); - assert(_max_worker_id > 0, "uninitialized"); +void G1ConcurrentMark::finalize_live_data() { + _g1h->g1_rem_set()->finalize_card_live_data(_g1h->workers(), _nextMarkBitMap); +} - for (uint i = 0; i < _max_worker_id; i += 1) { - BitMap* task_card_bm = count_card_bitmap_for(i); - size_t* marked_bytes_array = count_marked_bytes_array_for(i); +void G1ConcurrentMark::verify_live_data() { + _g1h->g1_rem_set()->verify_card_live_data(_g1h->workers(), _nextMarkBitMap); +} - assert(task_card_bm->size() == _card_bm.size(), "size mismatch"); - assert(marked_bytes_array != NULL, "uninitialized"); +void G1ConcurrentMark::clear_live_data(WorkGang* workers) { + _g1h->g1_rem_set()->clear_card_live_data(workers); +} - memset(marked_bytes_array, 0, (size_t) max_regions * sizeof(size_t)); - task_card_bm->clear(); - } +#ifdef ASSERT +void G1ConcurrentMark::verify_live_data_clear() { + _g1h->g1_rem_set()->verify_card_live_data_is_clear(); } +#endif void G1ConcurrentMark::print_stats() { if (!log_is_enabled(Debug, gc, stats)) { @@ -2574,7 +2029,6 @@ void G1ConcurrentMark::print_stats() { } } -// abandon current marking iteration due to a Full GC void G1ConcurrentMark::abort() { if (!cmThread()->during_cycle() || _has_aborted) { // We haven't started a concurrent cycle or we have already aborted it. No need to do anything. @@ -2583,14 +2037,22 @@ void G1ConcurrentMark::abort() { // Clear all marks in the next bitmap for the next marking cycle. This will allow us to skip the next // concurrent bitmap clearing. - clear_bitmap(_nextMarkBitMap, _g1h->workers(), false); - + { + GCTraceTime(Debug, gc)("Clear Next Bitmap"); + clear_bitmap(_nextMarkBitMap, _g1h->workers(), false); + } // Note we cannot clear the previous marking bitmap here // since VerifyDuringGC verifies the objects marked during // a full GC against the previous bitmap. - // Clear the liveness counting data - clear_all_count_data(); + { + GCTraceTime(Debug, gc)("Clear Live Data"); + clear_live_data(_g1h->workers()); + } + DEBUG_ONLY({ + GCTraceTime(Debug, gc)("Verify Live Data Clear"); + verify_live_data_clear(); + }) // Empty mark stack reset_marking_state(); for (uint i = 0; i < _max_worker_id; ++i) { @@ -2634,7 +2096,7 @@ void G1ConcurrentMark::print_summary_info() { } print_ms_time_info(" ", "cleanups", _cleanup_times); - log.trace(" Final counting total time = %8.2f s (avg = %8.2f ms).", + log.trace(" Finalize live data total time = %8.2f s (avg = %8.2f ms).", _total_counting_time, (_cleanup_times.num() > 0 ? _total_counting_time * 1000.0 / (double)_cleanup_times.num() : 0.0)); if (G1ScrubRemSets) { log.trace(" RS scrub total time = %8.2f s (avg = %8.2f ms).", @@ -2650,6 +2112,10 @@ void G1ConcurrentMark::print_worker_threads_on(outputStream* st) const { _parallel_workers->print_worker_threads_on(st); } +void G1ConcurrentMark::threads_do(ThreadClosure* tc) const { + _parallel_workers->threads_do(tc); +} + void G1ConcurrentMark::print_on_error(outputStream* st) const { st->print_cr("Marking Bits (Prev, Next): (CMBitMap*) " PTR_FORMAT ", (CMBitMap*) " PTR_FORMAT, p2i(_prevMarkBitMap), p2i(_nextMarkBitMap)); @@ -2657,16 +2123,6 @@ void G1ConcurrentMark::print_on_error(outputStream* st) const { _nextMarkBitMap->print_on_error(st, " Next Bits: "); } -// We take a break if someone is trying to stop the world. -bool G1ConcurrentMark::do_yield_check(uint worker_id) { - if (SuspendibleThreadSet::should_yield()) { - SuspendibleThreadSet::yield(); - return true; - } else { - return false; - } -} - // Closure for iteration over bitmaps class G1CMBitMapClosure : public BitMapClosure { private: @@ -3473,8 +2929,6 @@ void G1CMTask::do_marking_step(double time_target_ms, G1CMTask::G1CMTask(uint worker_id, G1ConcurrentMark* cm, - size_t* marked_bytes, - BitMap* card_bm, G1CMTaskQueue* task_queue, G1CMTaskQueueSet* task_queues) : _g1h(G1CollectedHeap::heap()), @@ -3483,9 +2937,7 @@ G1CMTask::G1CMTask(uint worker_id, _nextMarkBitMap(NULL), _hash_seed(17), _task_queue(task_queue), _task_queues(task_queues), - _cm_oop_closure(NULL), - _marked_bytes_array(marked_bytes), - _card_bm(card_bm) { + _cm_oop_closure(NULL) { guarantee(task_queue != NULL, "invariant"); guarantee(task_queues != NULL, "invariant"); diff --git a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp index 1608c81f96fef2adbedef65cd7d206ea68d59b03..3b077d97a8a9cd17fab0aad75fd440c7938f88a1 100644 --- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.hpp @@ -266,7 +266,7 @@ class ConcurrentMarkThread; class G1ConcurrentMark: public CHeapObj { friend class ConcurrentMarkThread; friend class G1ParNoteEndTask; - friend class CalcLiveObjectsClosure; + friend class G1VerifyLiveDataClosure; friend class G1CMRefProcTaskProxy; friend class G1CMRefProcTaskExecutor; friend class G1CMKeepAliveAndDrainClosure; @@ -298,9 +298,6 @@ protected: G1CMBitMapRO* _prevMarkBitMap; // Completed mark bitmap G1CMBitMap* _nextMarkBitMap; // Under-construction mark bitmap - BitMap _region_bm; - BitMap _card_bm; - // Heap bounds HeapWord* _heap_start; HeapWord* _heap_end; @@ -461,23 +458,6 @@ protected: void enter_first_sync_barrier(uint worker_id); void enter_second_sync_barrier(uint worker_id); - // Live Data Counting data structures... - // These data structures are initialized at the start of - // marking. They are written to while marking is active. - // They are aggregated during remark; the aggregated values - // are then used to populate the _region_bm, _card_bm, and - // the total live bytes, which are then subsequently updated - // during cleanup. - - // An array of bitmaps (one bit map per task). Each bitmap - // is used to record the cards spanned by the live objects - // marked by that task/worker. - BitMap* _count_card_bitmaps; - - // Used to record the number of marked live bytes - // (for each region, by worker thread). - size_t** _count_marked_bytes; - // Card index of the bottom of the G1 heap. Used for biasing indices into // the card bitmaps. intptr_t _heap_bottom_card_num; @@ -563,18 +543,10 @@ public: // G1CollectedHeap // This notifies CM that a root during initial-mark needs to be - // grayed. It is MT-safe. word_size is the size of the object in - // words. It is passed explicitly as sometimes we cannot calculate - // it from the given object because it might be in an inconsistent - // state (e.g., in to-space and being copied). So the caller is - // responsible for dealing with this issue (e.g., get the size from - // the from-space image when the to-space image might be - // inconsistent) and always passing the size. hr is the region that + // grayed. It is MT-safe. hr is the region that // contains the object and it's passed optionally from callers who // might already have it (no point in recalculating it). inline void grayRoot(oop obj, - size_t word_size, - uint worker_id, HeapRegion* hr = NULL); // Prepare internal data structures for the next mark cycle. This includes clearing @@ -603,7 +575,7 @@ public: void scan_root_regions(); // Scan a single root region and mark everything reachable from it. - void scanRootRegion(HeapRegion* hr, uint worker_id); + void scanRootRegion(HeapRegion* hr); // Do concurrent phase of marking, to a tentative transitive closure. void mark_from_roots(); @@ -639,9 +611,9 @@ public: inline bool isPrevMarked(oop p) const; - inline bool do_yield_check(uint worker_i = 0); + inline bool do_yield_check(); - // Called to abort the marking cycle after a Full GC takes place. + // Abandon current marking iteration due to a Full GC. void abort(); bool has_aborted() { return _has_aborted; } @@ -649,78 +621,12 @@ public: void print_summary_info(); void print_worker_threads_on(outputStream* st) const; + void threads_do(ThreadClosure* tc) const; void print_on_error(outputStream* st) const; - // Liveness counting - - // Utility routine to set an exclusive range of cards on the given - // card liveness bitmap - inline void set_card_bitmap_range(BitMap* card_bm, - BitMap::idx_t start_idx, - BitMap::idx_t end_idx, - bool is_par); - - // Returns the card number of the bottom of the G1 heap. - // Used in biasing indices into accounting card bitmaps. - intptr_t heap_bottom_card_num() const { - return _heap_bottom_card_num; - } - - // Returns the card bitmap for a given task or worker id. - BitMap* count_card_bitmap_for(uint worker_id) { - assert(worker_id < _max_worker_id, "oob"); - assert(_count_card_bitmaps != NULL, "uninitialized"); - BitMap* task_card_bm = &_count_card_bitmaps[worker_id]; - assert(task_card_bm->size() == _card_bm.size(), "size mismatch"); - return task_card_bm; - } - - // Returns the array containing the marked bytes for each region, - // for the given worker or task id. - size_t* count_marked_bytes_array_for(uint worker_id) { - assert(worker_id < _max_worker_id, "oob"); - assert(_count_marked_bytes != NULL, "uninitialized"); - size_t* marked_bytes_array = _count_marked_bytes[worker_id]; - assert(marked_bytes_array != NULL, "uninitialized"); - return marked_bytes_array; - } - - // Returns the index in the liveness accounting card table bitmap - // for the given address - inline BitMap::idx_t card_bitmap_index_for(HeapWord* addr); - - // Counts the size of the given memory region in the the given - // marked_bytes array slot for the given HeapRegion. - // Sets the bits in the given card bitmap that are associated with the - // cards that are spanned by the memory region. - inline void count_region(MemRegion mr, - HeapRegion* hr, - size_t* marked_bytes_array, - BitMap* task_card_bm); - - // Counts the given object in the given task/worker counting - // data structures. - inline void count_object(oop obj, - HeapRegion* hr, - size_t* marked_bytes_array, - BitMap* task_card_bm, - size_t word_size); - - // Attempts to mark the given object and, if successful, counts - // the object in the given task/worker counting structures. - inline bool par_mark_and_count(oop obj, - HeapRegion* hr, - size_t* marked_bytes_array, - BitMap* task_card_bm); - - // Attempts to mark the given object and, if successful, counts - // the object in the task/worker counting structures for the - // given worker id. - inline bool par_mark_and_count(oop obj, - size_t word_size, - HeapRegion* hr, - uint worker_id); + // Attempts to mark the given object on the next mark bitmap. + inline bool par_mark(oop obj); // Returns true if initialization was successfully completed. bool completed_initialization() const { @@ -730,19 +636,22 @@ public: ConcurrentGCTimer* gc_timer_cm() const { return _gc_timer_cm; } G1OldTracer* gc_tracer_cm() const { return _gc_tracer_cm; } -protected: - // Clear all the per-task bitmaps and arrays used to store the - // counting data. - void clear_all_count_data(); - - // Aggregates the counting data for each worker/task - // that was constructed while marking. Also sets - // the amount of marked bytes for each region and - // the top at concurrent mark count. - void aggregate_count_data(); - - // Verification routine - void verify_count_data(); +private: + // Clear (Reset) all liveness count data. + void clear_live_data(WorkGang* workers); + +#ifdef ASSERT + // Verify all of the above data structures that they are in initial state. + void verify_live_data_clear(); +#endif + + // Aggregates the per-card liveness data based on the current marking. Also sets + // the amount of marked bytes for each region. + void create_live_data(); + + void finalize_live_data(); + + void verify_live_data(); }; // A class representing a marking task. @@ -844,12 +753,6 @@ private: TruncatedSeq _marking_step_diffs_ms; - // Counting data structures. Embedding the task's marked_bytes_array - // and card bitmap into the actual task saves having to go through - // the ConcurrentMark object. - size_t* _marked_bytes_array; - BitMap* _card_bm; - // it updates the local fields after this task has claimed // a new region to scan void setup_for_region(HeapRegion* hr); @@ -936,9 +839,8 @@ public: // Grey the object by marking it. If not already marked, push it on // the local queue if below the finger. - // Precondition: obj is in region. - // Precondition: obj is below region's NTAMS. - inline void make_reference_grey(oop obj, HeapRegion* region); + // obj is below its region's NTAMS. + inline void make_reference_grey(oop obj); // Grey the object (by calling make_grey_reference) if required, // e.g. obj is below its containing region's NTAMS. @@ -976,8 +878,6 @@ public: G1CMTask(uint worker_id, G1ConcurrentMark *cm, - size_t* marked_bytes, - BitMap* card_bm, G1CMTaskQueue* task_queue, G1CMTaskQueueSet* task_queues); diff --git a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.inline.hpp b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.inline.hpp index 4a934e0b15e7ec826c8be450428710adef6edf41..b0401d35935dd6ed047cb574a6ef0577007b248f 100644 --- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.inline.hpp @@ -27,140 +27,11 @@ #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1ConcurrentMark.hpp" +#include "gc/g1/suspendibleThreadSet.hpp" #include "gc/shared/taskqueue.inline.hpp" -// Utility routine to set an exclusive range of cards on the given -// card liveness bitmap -inline void G1ConcurrentMark::set_card_bitmap_range(BitMap* card_bm, - BitMap::idx_t start_idx, - BitMap::idx_t end_idx, - bool is_par) { - - // Set the exclusive bit range [start_idx, end_idx). - assert((end_idx - start_idx) > 0, "at least one card"); - assert(end_idx <= card_bm->size(), "sanity"); - - // Silently clip the end index - end_idx = MIN2(end_idx, card_bm->size()); - - // For small ranges use a simple loop; otherwise use set_range or - // use par_at_put_range (if parallel). The range is made up of the - // cards that are spanned by an object/mem region so 8 cards will - // allow up to object sizes up to 4K to be handled using the loop. - if ((end_idx - start_idx) <= 8) { - for (BitMap::idx_t i = start_idx; i < end_idx; i += 1) { - if (is_par) { - card_bm->par_set_bit(i); - } else { - card_bm->set_bit(i); - } - } - } else { - // Note BitMap::par_at_put_range() and BitMap::set_range() are exclusive. - if (is_par) { - card_bm->par_at_put_range(start_idx, end_idx, true); - } else { - card_bm->set_range(start_idx, end_idx); - } - } -} - -// Returns the index in the liveness accounting card bitmap -// for the given address -inline BitMap::idx_t G1ConcurrentMark::card_bitmap_index_for(HeapWord* addr) { - // Below, the term "card num" means the result of shifting an address - // by the card shift -- address 0 corresponds to card number 0. One - // must subtract the card num of the bottom of the heap to obtain a - // card table index. - intptr_t card_num = intptr_t(uintptr_t(addr) >> CardTableModRefBS::card_shift); - return card_num - heap_bottom_card_num(); -} - -// Counts the given memory region in the given task/worker -// counting data structures. -inline void G1ConcurrentMark::count_region(MemRegion mr, HeapRegion* hr, - size_t* marked_bytes_array, - BitMap* task_card_bm) { - G1CollectedHeap* g1h = _g1h; - CardTableModRefBS* ct_bs = g1h->g1_barrier_set(); - - HeapWord* start = mr.start(); - HeapWord* end = mr.end(); - size_t region_size_bytes = mr.byte_size(); - uint index = hr->hrm_index(); - - assert(hr == g1h->heap_region_containing(start), "sanity"); - assert(marked_bytes_array != NULL, "pre-condition"); - assert(task_card_bm != NULL, "pre-condition"); - - // Add to the task local marked bytes for this region. - marked_bytes_array[index] += region_size_bytes; - - BitMap::idx_t start_idx = card_bitmap_index_for(start); - BitMap::idx_t end_idx = card_bitmap_index_for(end); - - // Note: if we're looking at the last region in heap - end - // could be actually just beyond the end of the heap; end_idx - // will then correspond to a (non-existent) card that is also - // just beyond the heap. - if (g1h->is_in_g1_reserved(end) && !ct_bs->is_card_aligned(end)) { - // end of region is not card aligned - increment to cover - // all the cards spanned by the region. - end_idx += 1; - } - // The card bitmap is task/worker specific => no need to use - // the 'par' BitMap routines. - // Set bits in the exclusive bit range [start_idx, end_idx). - set_card_bitmap_range(task_card_bm, start_idx, end_idx, false /* is_par */); -} - -// Counts the given object in the given task/worker counting data structures. -inline void G1ConcurrentMark::count_object(oop obj, - HeapRegion* hr, - size_t* marked_bytes_array, - BitMap* task_card_bm, - size_t word_size) { - assert(!hr->is_continues_humongous(), "Cannot enter count_object with continues humongous"); - if (!hr->is_starts_humongous()) { - MemRegion mr((HeapWord*)obj, word_size); - count_region(mr, hr, marked_bytes_array, task_card_bm); - } else { - do { - MemRegion mr(hr->bottom(), hr->top()); - count_region(mr, hr, marked_bytes_array, task_card_bm); - hr = _g1h->next_region_in_humongous(hr); - } while (hr != NULL); - } -} - -// Attempts to mark the given object and, if successful, counts -// the object in the given task/worker counting structures. -inline bool G1ConcurrentMark::par_mark_and_count(oop obj, - HeapRegion* hr, - size_t* marked_bytes_array, - BitMap* task_card_bm) { - if (_nextMarkBitMap->parMark((HeapWord*)obj)) { - // Update the task specific count data for the object. - count_object(obj, hr, marked_bytes_array, task_card_bm, obj->size()); - return true; - } - return false; -} - -// Attempts to mark the given object and, if successful, counts -// the object in the task/worker counting structures for the -// given worker id. -inline bool G1ConcurrentMark::par_mark_and_count(oop obj, - size_t word_size, - HeapRegion* hr, - uint worker_id) { - if (_nextMarkBitMap->parMark((HeapWord*)obj)) { - size_t* marked_bytes_array = count_marked_bytes_array_for(worker_id); - BitMap* task_card_bm = count_card_bitmap_for(worker_id); - count_object(obj, hr, marked_bytes_array, task_card_bm, word_size); - return true; - } - return false; +inline bool G1ConcurrentMark::par_mark(oop obj) { + return _nextMarkBitMap->parMark((HeapWord*)obj); } inline bool G1CMBitMapRO::iterate(BitMapClosure* cl, MemRegion mr) { @@ -294,10 +165,8 @@ inline void G1CMTask::process_grey_object(oop obj) { check_limits(); } - - -inline void G1CMTask::make_reference_grey(oop obj, HeapRegion* hr) { - if (_cm->par_mark_and_count(obj, hr, _marked_bytes_array, _card_bm)) { +inline void G1CMTask::make_reference_grey(oop obj) { + if (_cm->par_mark(obj)) { // No OrderAccess:store_load() is needed. It is implicit in the // CAS done in G1CMBitMap::parMark() call in the routine above. HeapWord* global_finger = _cm->finger(); @@ -348,7 +217,7 @@ inline void G1CMTask::deal_with_reference(oop obj) { // anything with it). HeapRegion* hr = _g1h->heap_region_containing(obj); if (!hr->obj_allocated_since_next_marking(obj)) { - make_reference_grey(obj, hr); + make_reference_grey(obj); } } } @@ -370,8 +239,7 @@ bool G1ConcurrentMark::isPrevMarked(oop p) const { return _prevMarkBitMap->isMarked(addr); } -inline void G1ConcurrentMark::grayRoot(oop obj, size_t word_size, - uint worker_id, HeapRegion* hr) { +inline void G1ConcurrentMark::grayRoot(oop obj, HeapRegion* hr) { assert(obj != NULL, "pre-condition"); HeapWord* addr = (HeapWord*) obj; if (hr == NULL) { @@ -386,9 +254,18 @@ inline void G1ConcurrentMark::grayRoot(oop obj, size_t word_size, if (addr < hr->next_top_at_mark_start()) { if (!_nextMarkBitMap->isMarked(addr)) { - par_mark_and_count(obj, word_size, hr, worker_id); + par_mark(obj); } } } +inline bool G1ConcurrentMark::do_yield_check() { + if (SuspendibleThreadSet::should_yield()) { + SuspendibleThreadSet::yield(); + return true; + } else { + return false; + } +} + #endif // SHARE_VM_GC_G1_G1CONCURRENTMARK_INLINE_HPP diff --git a/hotspot/src/share/vm/gc/g1/g1EvacFailure.cpp b/hotspot/src/share/vm/gc/g1/g1EvacFailure.cpp index 06721ee929541409df2177242de80915e41df2c1..82d655ed2329ea8c80192d18754872501cb6d181 100644 --- a/hotspot/src/share/vm/gc/g1/g1EvacFailure.cpp +++ b/hotspot/src/share/vm/gc/g1/g1EvacFailure.cpp @@ -95,8 +95,6 @@ public: void do_object(oop obj) { HeapWord* obj_addr = (HeapWord*) obj; assert(_hr->is_in(obj_addr), "sanity"); - size_t obj_size = obj->size(); - HeapWord* obj_end = obj_addr + obj_size; if (obj->is_forwarded() && obj->forwardee() == obj) { // The object failed to move. @@ -119,8 +117,10 @@ public: // explicitly and all objects in the CSet are considered // (implicitly) live. So, we won't mark them explicitly and // we'll leave them over NTAMS. - _cm->grayRoot(obj, obj_size, _worker_id, _hr); + _cm->grayRoot(obj, _hr); } + size_t obj_size = obj->size(); + _marked_bytes += (obj_size * HeapWordSize); obj->set_mark(markOopDesc::prototype()); @@ -138,6 +138,7 @@ public: // the collection set. So, we'll recreate such entries now. obj->oop_iterate(_update_rset_cl); + HeapWord* obj_end = obj_addr + obj_size; _last_forwarded_object_end = obj_end; _hr->cross_threshold(obj_addr, obj_end); } diff --git a/hotspot/src/share/vm/gc/g1/g1OopClosures.hpp b/hotspot/src/share/vm/gc/g1/g1OopClosures.hpp index 05f90f75f4e87565eba738d39f8c83391bdd4f29..5de38f71bd2195b29bc445e706c4c9843e2a041e 100644 --- a/hotspot/src/share/vm/gc/g1/g1OopClosures.hpp +++ b/hotspot/src/share/vm/gc/g1/g1OopClosures.hpp @@ -186,11 +186,9 @@ class G1RootRegionScanClosure : public MetadataAwareOopClosure { private: G1CollectedHeap* _g1h; G1ConcurrentMark* _cm; - uint _worker_id; public: - G1RootRegionScanClosure(G1CollectedHeap* g1h, G1ConcurrentMark* cm, - uint worker_id) : - _g1h(g1h), _cm(cm), _worker_id(worker_id) { } + G1RootRegionScanClosure(G1CollectedHeap* g1h, G1ConcurrentMark* cm) : + _g1h(g1h), _cm(cm) { } template void do_oop_nv(T* p); virtual void do_oop( oop* p) { do_oop_nv(p); } virtual void do_oop(narrowOop* p) { do_oop_nv(p); } diff --git a/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp b/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp index 932bcbbfc4c070792f545f4aac537a3c9626428c..34db8d6c207b4e1c8e2b07eebcb1b35f88cc8090 100644 --- a/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp @@ -131,7 +131,7 @@ inline void G1RootRegionScanClosure::do_oop_nv(T* p) { if (!oopDesc::is_null(heap_oop)) { oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); HeapRegion* hr = _g1h->heap_region_containing((HeapWord*) obj); - _cm->grayRoot(obj, obj->size(), _worker_id, hr); + _cm->grayRoot(obj, hr); } } @@ -246,7 +246,7 @@ void G1ParCopyHelper::mark_object(oop obj) { assert(!_g1->heap_region_containing(obj)->in_collection_set(), "should not mark objects in the CSet"); // We know that the object is not moving so it's safe to read its size. - _cm->grayRoot(obj, (size_t) obj->size(), _worker_id); + _cm->grayRoot(obj); } void G1ParCopyHelper::mark_forwarded_object(oop from_obj, oop to_obj) { @@ -261,7 +261,7 @@ void G1ParCopyHelper::mark_forwarded_object(oop from_obj, oop to_obj) { // worker so we cannot trust that its to-space image is // well-formed. So we have to read its size from its from-space // image which we know should not be changing. - _cm->grayRoot(to_obj, (size_t) from_obj->size(), _worker_id); + _cm->grayRoot(to_obj); } template diff --git a/hotspot/src/share/vm/gc/g1/g1RemSet.cpp b/hotspot/src/share/vm/gc/g1/g1RemSet.cpp index eb09144388757962ecad8f141a7651987c870db2..12ed0506d945806ce4a1647de5f8b20fb083773f 100644 --- a/hotspot/src/share/vm/gc/g1/g1RemSet.cpp +++ b/hotspot/src/share/vm/gc/g1/g1RemSet.cpp @@ -38,6 +38,7 @@ #include "gc/g1/heapRegion.inline.hpp" #include "gc/g1/heapRegionManager.inline.hpp" #include "gc/g1/heapRegionRemSet.hpp" +#include "gc/shared/gcTraceTime.inline.hpp" #include "memory/iterator.hpp" #include "memory/resourceArea.hpp" #include "oops/oop.inline.hpp" @@ -84,8 +85,16 @@ uint G1RemSet::num_par_rem_sets() { return MAX2(DirtyCardQueueSet::num_par_ids() + ConcurrentG1Refine::thread_num(), ParallelGCThreads); } -void G1RemSet::initialize(uint max_regions) { +void G1RemSet::initialize(size_t capacity, uint max_regions) { G1FromCardCache::initialize(num_par_rem_sets(), max_regions); + { + GCTraceTime(Debug, gc, marking)("Initialize Card Live Data"); + _card_live_data.initialize(capacity, max_regions); + } + if (G1PretouchAuxiliaryMemory) { + GCTraceTime(Debug, gc, marking)("Pre-Touch Card Live Data"); + _card_live_data.pretouch(); + } } ScanRSClosure::ScanRSClosure(G1ParPushHeapRSClosure* oc, @@ -312,27 +321,24 @@ void G1RemSet::cleanup_after_oops_into_collection_set_do() { _into_cset_dirty_card_queue_set.clear_n_completed_buffers(); } -class ScrubRSClosure: public HeapRegionClosure { +class G1ScrubRSClosure: public HeapRegionClosure { G1CollectedHeap* _g1h; - BitMap* _region_bm; - BitMap* _card_bm; - CardTableModRefBS* _ctbs; + G1CardLiveData* _live_data; public: - ScrubRSClosure(BitMap* region_bm, BitMap* card_bm) : + G1ScrubRSClosure(G1CardLiveData* live_data) : _g1h(G1CollectedHeap::heap()), - _region_bm(region_bm), _card_bm(card_bm), - _ctbs(_g1h->g1_barrier_set()) {} + _live_data(live_data) { } bool doHeapRegion(HeapRegion* r) { if (!r->is_continues_humongous()) { - r->rem_set()->scrub(_ctbs, _region_bm, _card_bm); + r->rem_set()->scrub(_live_data); } return false; } }; -void G1RemSet::scrub(BitMap* region_bm, BitMap* card_bm, uint worker_num, HeapRegionClaimer *hrclaimer) { - ScrubRSClosure scrub_cl(region_bm, card_bm); +void G1RemSet::scrub(uint worker_num, HeapRegionClaimer *hrclaimer) { + G1ScrubRSClosure scrub_cl(&_card_live_data); _g1->heap_region_par_iterate(&scrub_cl, worker_num, hrclaimer); } @@ -580,3 +586,25 @@ void G1RemSet::prepare_for_verify() { assert(JavaThread::dirty_card_queue_set().completed_buffers_num() == 0, "All should be consumed"); } } + +void G1RemSet::create_card_live_data(WorkGang* workers, G1CMBitMap* mark_bitmap) { + _card_live_data.create(workers, mark_bitmap); +} + +void G1RemSet::finalize_card_live_data(WorkGang* workers, G1CMBitMap* mark_bitmap) { + _card_live_data.finalize(workers, mark_bitmap); +} + +void G1RemSet::verify_card_live_data(WorkGang* workers, G1CMBitMap* bitmap) { + _card_live_data.verify(workers, bitmap); +} + +void G1RemSet::clear_card_live_data(WorkGang* workers) { + _card_live_data.clear(workers); +} + +#ifdef ASSERT +void G1RemSet::verify_card_live_data_is_clear() { + _card_live_data.verify_is_clear(); +} +#endif diff --git a/hotspot/src/share/vm/gc/g1/g1RemSet.hpp b/hotspot/src/share/vm/gc/g1/g1RemSet.hpp index 8aab4ca498c4cd4cabc421c5f2c96191ffe0d5cc..381d5fd8f7283beecf0f822629a239e3acdfd57a 100644 --- a/hotspot/src/share/vm/gc/g1/g1RemSet.hpp +++ b/hotspot/src/share/vm/gc/g1/g1RemSet.hpp @@ -26,6 +26,7 @@ #define SHARE_VM_GC_G1_G1REMSET_HPP #include "gc/g1/dirtyCardQueue.hpp" +#include "gc/g1/g1CardLiveData.hpp" #include "gc/g1/g1RemSetSummary.hpp" #include "gc/g1/heapRegion.hpp" #include "memory/allocation.hpp" @@ -48,9 +49,10 @@ class HeapRegionClaimer; // A G1RemSet in which each heap region has a rem set that records the // external heap references into it. Uses a mod ref bs to track updates, // so that they can be used to update the individual region remsets. - class G1RemSet: public CHeapObj { private: + G1CardLiveData _card_live_data; + G1RemSetSummary _prev_period_summary; // A DirtyCardQueueSet that is used to hold cards that contain @@ -83,7 +85,7 @@ public: static uint num_par_rem_sets(); // Initialize data that depends on the heap size being known. - static void initialize(uint max_regions); + void initialize(size_t capacity, uint max_regions); // This is called to reset dual hash tables after the gc pause // is finished and the initial hash table is no longer being @@ -140,7 +142,7 @@ public: // set entries that correspond to dead heap ranges. "worker_num" is the // parallel thread id of the current thread, and "hrclaimer" is the // HeapRegionClaimer that should be used. - void scrub(BitMap* region_bm, BitMap* card_bm, uint worker_num, HeapRegionClaimer* hrclaimer); + void scrub(uint worker_num, HeapRegionClaimer* hrclaimer); // Refine the card corresponding to "card_ptr". // If check_for_refs_into_cset is true, a true result is returned @@ -162,6 +164,19 @@ public: size_t conc_refine_cards() const { return _conc_refine_cards; } + + void create_card_live_data(WorkGang* workers, G1CMBitMap* mark_bitmap); + void finalize_card_live_data(WorkGang* workers, G1CMBitMap* mark_bitmap); + + // Verify that the liveness count data created concurrently matches one created + // during this safepoint. + void verify_card_live_data(WorkGang* workers, G1CMBitMap* actual_bitmap); + + void clear_card_live_data(WorkGang* workers); + +#ifdef ASSERT + void verify_card_live_data_is_clear(); +#endif }; class ScanRSClosure : public HeapRegionClosure { diff --git a/hotspot/src/share/vm/gc/g1/g1YoungGenSizer.cpp b/hotspot/src/share/vm/gc/g1/g1YoungGenSizer.cpp index cf7866770d518983234a12f51ea5b7de5ddd7fc4..e049f4da6390783469f3c2592c22bef82486e3b8 100644 --- a/hotspot/src/share/vm/gc/g1/g1YoungGenSizer.cpp +++ b/hotspot/src/share/vm/gc/g1/g1YoungGenSizer.cpp @@ -25,12 +25,13 @@ #include "precompiled.hpp" #include "gc/g1/g1YoungGenSizer.hpp" #include "gc/g1/heapRegion.hpp" +#include "logging/log.hpp" G1YoungGenSizer::G1YoungGenSizer() : _sizer_kind(SizerDefaults), _adaptive_size(true), _min_desired_young_length(0), _max_desired_young_length(0) { if (FLAG_IS_CMDLINE(NewRatio)) { if (FLAG_IS_CMDLINE(NewSize) || FLAG_IS_CMDLINE(MaxNewSize)) { - warning("-XX:NewSize and -XX:MaxNewSize override -XX:NewRatio"); + log_warning(gc, ergo)("-XX:NewSize and -XX:MaxNewSize override -XX:NewRatio"); } else { _sizer_kind = SizerNewRatio; _adaptive_size = false; @@ -40,9 +41,9 @@ G1YoungGenSizer::G1YoungGenSizer() : _sizer_kind(SizerDefaults), _adaptive_size( if (NewSize > MaxNewSize) { if (FLAG_IS_CMDLINE(MaxNewSize)) { - warning("NewSize (" SIZE_FORMAT "k) is greater than the MaxNewSize (" SIZE_FORMAT "k). " - "A new max generation size of " SIZE_FORMAT "k will be used.", - NewSize/K, MaxNewSize/K, NewSize/K); + log_warning(gc, ergo)("NewSize (" SIZE_FORMAT "k) is greater than the MaxNewSize (" SIZE_FORMAT "k). " + "A new max generation size of " SIZE_FORMAT "k will be used.", + NewSize/K, MaxNewSize/K, NewSize/K); } MaxNewSize = NewSize; } diff --git a/hotspot/src/share/vm/gc/g1/g1_globals.hpp b/hotspot/src/share/vm/gc/g1/g1_globals.hpp index ac78d2b0e8a06ce17ab6262799bccdb409a85ffb..ce8d96ea3ec2acfc1c0c35ab381c949acf95c867 100644 --- a/hotspot/src/share/vm/gc/g1/g1_globals.hpp +++ b/hotspot/src/share/vm/gc/g1/g1_globals.hpp @@ -112,8 +112,7 @@ product(size_t, G1ConcRefinementRedZone, 0, \ "Maximum number of enqueued update buffers before mutator " \ "threads start processing new ones instead of enqueueing them. " \ - "Will be selected ergonomically by default. Zero will disable " \ - "concurrent processing.") \ + "Will be selected ergonomically by default.") \ range(0, max_intx) \ \ product(size_t, G1ConcRefinementGreenZone, 0, \ @@ -127,11 +126,12 @@ "specified number of milliseconds to do miscellaneous work.") \ range(0, max_jint) \ \ - product(size_t, G1ConcRefinementThresholdStep, 0, \ + product(size_t, G1ConcRefinementThresholdStep, 2, \ "Each time the rset update queue increases by this amount " \ "activate the next refinement thread if available. " \ - "Will be selected ergonomically by default.") \ - range(0, SIZE_MAX) \ + "The actual step size will be selected ergonomically by " \ + "default, with this value used to determine a lower bound.") \ + range(1, SIZE_MAX) \ \ product(intx, G1RSetUpdatingPauseTimePercent, 10, \ "A target percentage of time that is allowed to be spend on " \ @@ -201,9 +201,9 @@ range(0, 32*M) \ constraint(G1HeapRegionSizeConstraintFunc,AfterMemoryInit) \ \ - product(uintx, G1ConcRefinementThreads, 0, \ - "If non-0 is the number of parallel rem set update threads, " \ - "otherwise the value is determined ergonomically.") \ + product(uint, G1ConcRefinementThreads, 0, \ + "The number of parallel rem set update threads. " \ + "Will be set ergonomically by default.") \ range(0, (max_jint-1)/wordSize) \ \ develop(bool, G1VerifyCTCleanup, false, \ @@ -260,6 +260,9 @@ "The target number of mixed GCs after a marking cycle.") \ range(0, max_uintx) \ \ + experimental(bool, G1PretouchAuxiliaryMemory, false, \ + "Pre-touch large auxiliary data structures used by the GC.") \ + \ experimental(bool, G1EagerReclaimHumongousObjects, true, \ "Try to reclaim dead large objects at every young GC.") \ \ diff --git a/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp b/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp index 26d5ce3e7e01b5bd9957543e529de691e19a4ea8..4fee9c4ecfc6eedec800a4279318e3273e262863 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp +++ b/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp @@ -26,6 +26,7 @@ #include "gc/g1/concurrentG1Refine.hpp" #include "gc/g1/g1BlockOffsetTable.inline.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" +#include "gc/g1/g1CardLiveData.inline.hpp" #include "gc/g1/heapRegionManager.inline.hpp" #include "gc/g1/heapRegionRemSet.hpp" #include "gc/shared/space.inline.hpp" @@ -141,10 +142,8 @@ public: add_reference_work(from, /*parallel*/ false); } - void scrub(CardTableModRefBS* ctbs, BitMap* card_bm) { - HeapWord* hr_bot = hr()->bottom(); - size_t hr_first_card_index = ctbs->index_for(hr_bot); - bm()->set_intersection_at_offset(*card_bm, hr_first_card_index); + void scrub(G1CardLiveData* live_data) { + live_data->remove_nonlive_cards(hr()->hrm_index(), &_bm); recount_occupied(); } @@ -515,14 +514,12 @@ PerRegionTable* OtherRegionsTable::delete_region_table() { return max; } -void OtherRegionsTable::scrub(CardTableModRefBS* ctbs, - BitMap* region_bm, BitMap* card_bm) { +void OtherRegionsTable::scrub(G1CardLiveData* live_data) { // First eliminated garbage regions from the coarse map. log_develop_trace(gc, remset, scrub)("Scrubbing region %u:", _hr->hrm_index()); - assert(_coarse_map.size() == region_bm->size(), "Precondition"); log_develop_trace(gc, remset, scrub)(" Coarse map: before = " SIZE_FORMAT "...", _n_coarse_entries); - _coarse_map.set_intersection(*region_bm); + live_data->remove_nonlive_regions(&_coarse_map); _n_coarse_entries = _coarse_map.count_one_bits(); log_develop_trace(gc, remset, scrub)(" after = " SIZE_FORMAT ".", _n_coarse_entries); @@ -534,7 +531,7 @@ void OtherRegionsTable::scrub(CardTableModRefBS* ctbs, PerRegionTable* nxt = cur->collision_list_next(); // If the entire region is dead, eliminate. log_develop_trace(gc, remset, scrub)(" For other region %u:", cur->hr()->hrm_index()); - if (!region_bm->at((size_t) cur->hr()->hrm_index())) { + if (!live_data->is_region_live(cur->hr()->hrm_index())) { *prev = nxt; cur->set_collision_list_next(NULL); _n_fine_entries--; @@ -544,7 +541,7 @@ void OtherRegionsTable::scrub(CardTableModRefBS* ctbs, } else { // Do fine-grain elimination. log_develop_trace(gc, remset, scrub)(" occ: before = %4d.", cur->occupied()); - cur->scrub(ctbs, card_bm); + cur->scrub(live_data); log_develop_trace(gc, remset, scrub)(" after = %4d.", cur->occupied()); // Did that empty the table completely? if (cur->occupied() == 0) { @@ -773,9 +770,8 @@ void HeapRegionRemSet::reset_for_par_iteration() { assert(verify_ready_for_par_iteration(), "post-condition"); } -void HeapRegionRemSet::scrub(CardTableModRefBS* ctbs, - BitMap* region_bm, BitMap* card_bm) { - _other_regions.scrub(ctbs, region_bm, card_bm); +void HeapRegionRemSet::scrub(G1CardLiveData* live_data) { + _other_regions.scrub(live_data); } // Code roots support diff --git a/hotspot/src/share/vm/gc/g1/heapRegionRemSet.hpp b/hotspot/src/share/vm/gc/g1/heapRegionRemSet.hpp index 5a286bc28369233a9149efd1ac1af85f8f6296dc..c884dab24847e735af5b23d58727e1b58374a89b 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegionRemSet.hpp +++ b/hotspot/src/share/vm/gc/g1/heapRegionRemSet.hpp @@ -35,6 +35,7 @@ class G1CollectedHeap; class G1BlockOffsetTable; +class G1CardLiveData; class HeapRegion; class HeapRegionRemSetIterator; class PerRegionTable; @@ -143,7 +144,7 @@ public: // Removes any entries shown by the given bitmaps to contain only dead // objects. Not thread safe. // Set bits in the bitmaps indicate that the given region or card is live. - void scrub(CardTableModRefBS* ctbs, BitMap* region_bm, BitMap* card_bm); + void scrub(G1CardLiveData* live_data); // Returns whether this remembered set (and all sub-sets) does not contain any entry. bool is_empty() const; @@ -230,10 +231,9 @@ public: _other_regions.add_reference(from, tid); } - // Removes any entries in the remembered set shown by the given bitmaps to + // Removes any entries in the remembered set shown by the given card live data to // contain only dead objects. Not thread safe. - // One bits in the bitmaps indicate that the given region or card is live. - void scrub(CardTableModRefBS* ctbs, BitMap* region_bm, BitMap* card_bm); + void scrub(G1CardLiveData* live_data); // The region is being reclaimed; clear its remset, and any mention of // entries for this region in other remsets. diff --git a/hotspot/src/share/vm/gc/parallel/generationSizer.cpp b/hotspot/src/share/vm/gc/parallel/generationSizer.cpp index 03067d9bdae6c5fb8c0ddb417f1bbec18ad3d83e..565bb31043f19983b17dcc8ab9d8d349e7a1d418 100644 --- a/hotspot/src/share/vm/gc/parallel/generationSizer.cpp +++ b/hotspot/src/share/vm/gc/parallel/generationSizer.cpp @@ -26,18 +26,6 @@ #include "gc/parallel/generationSizer.hpp" #include "gc/shared/collectorPolicy.hpp" -void GenerationSizer::trace_gen_sizes(const char* const str) { - if (TracePageSizes) { - tty->print_cr("%s: " SIZE_FORMAT "," SIZE_FORMAT " " - SIZE_FORMAT "," SIZE_FORMAT " " - SIZE_FORMAT, - str, - _min_old_size / K, _max_old_size / K, - _min_young_size / K, _max_young_size / K, - _max_heap_byte_size / K); - } -} - void GenerationSizer::initialize_alignments() { _space_alignment = _gen_alignment = default_gen_alignment(); _heap_alignment = compute_heap_alignment(); @@ -60,7 +48,6 @@ void GenerationSizer::initialize_flags() { } void GenerationSizer::initialize_size_info() { - trace_gen_sizes("ps heap raw"); const size_t max_page_sz = os::page_size_for_region_aligned(_max_heap_byte_size, 8); const size_t min_pages = 4; // 1 for eden + 1 for each survivor + 1 for old const size_t min_page_sz = os::page_size_for_region_aligned(_min_heap_byte_size, min_pages); @@ -76,6 +63,4 @@ void GenerationSizer::initialize_size_info() { initialize_flags(); } GenCollectorPolicy::initialize_size_info(); - - trace_gen_sizes("ps heap rnd"); } diff --git a/hotspot/src/share/vm/gc/parallel/generationSizer.hpp b/hotspot/src/share/vm/gc/parallel/generationSizer.hpp index 9db480f0bb7aaa1eaa4a16250d771ef0590d4d40..539629b1c96b344f9f8330d16e42764cdea86f90 100644 --- a/hotspot/src/share/vm/gc/parallel/generationSizer.hpp +++ b/hotspot/src/share/vm/gc/parallel/generationSizer.hpp @@ -33,8 +33,6 @@ class GenerationSizer : public GenCollectorPolicy { private: - void trace_gen_sizes(const char* const str); - // The alignment used for boundary between young gen and old gen static size_t default_gen_alignment() { return 64 * K * HeapWordSize; } diff --git a/hotspot/src/share/vm/gc/parallel/parMarkBitMap.cpp b/hotspot/src/share/vm/gc/parallel/parMarkBitMap.cpp index 569ff9ecbb1fd0e74b17b3990f8496c62756a10f..76241d9269260350226a40d3b18670dfa4d62cac 100644 --- a/hotspot/src/share/vm/gc/parallel/parMarkBitMap.cpp +++ b/hotspot/src/share/vm/gc/parallel/parMarkBitMap.cpp @@ -49,7 +49,7 @@ ParMarkBitMap::initialize(MemRegion covered_region) const size_t rs_align = page_sz == (size_t) os::vm_page_size() ? 0 : MAX2(page_sz, granularity); ReservedSpace rs(_reserved_byte_size, rs_align, rs_align > 0); - os::trace_page_sizes("par bitmap", raw_bytes, raw_bytes, page_sz, + os::trace_page_sizes("Mark Bitmap", raw_bytes, raw_bytes, page_sz, rs.base(), rs.size()); MemTracker::record_virtual_memory_type((address)rs.base(), mtGC); diff --git a/hotspot/src/share/vm/gc/parallel/parallelScavengeHeap.cpp b/hotspot/src/share/vm/gc/parallel/parallelScavengeHeap.cpp index eb4b07f04109e6e32b119ef4c1e6d87e08a40562..89f384cb6a8d8ba01bda4587fdee51edf52f322d 100644 --- a/hotspot/src/share/vm/gc/parallel/parallelScavengeHeap.cpp +++ b/hotspot/src/share/vm/gc/parallel/parallelScavengeHeap.cpp @@ -60,8 +60,10 @@ jint ParallelScavengeHeap::initialize() { ReservedSpace heap_rs = Universe::reserve_heap(heap_size, _collector_policy->heap_alignment()); - os::trace_page_sizes("ps main", _collector_policy->min_heap_byte_size(), - heap_size, generation_alignment(), + os::trace_page_sizes("Heap", + _collector_policy->min_heap_byte_size(), + heap_size, + generation_alignment(), heap_rs.base(), heap_rs.size()); diff --git a/hotspot/src/share/vm/gc/parallel/psAdaptiveSizePolicy.cpp b/hotspot/src/share/vm/gc/parallel/psAdaptiveSizePolicy.cpp index 4506ed67ee3a4b15cfffdd498b6f0cdef735ec19..c8554287512a15c7562d57cddf4c254dadcc253b 100644 --- a/hotspot/src/share/vm/gc/parallel/psAdaptiveSizePolicy.cpp +++ b/hotspot/src/share/vm/gc/parallel/psAdaptiveSizePolicy.cpp @@ -32,7 +32,6 @@ #include "gc/shared/gcPolicyCounters.hpp" #include "logging/log.hpp" #include "runtime/timer.hpp" -#include "utilities/top.hpp" #include diff --git a/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp b/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp index a309ccd0c7dc6766183683c25b410eb99adbf7e3..6b145d17c00ee579e7e2cfa245aa2cf406858bc5 100644 --- a/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp +++ b/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp @@ -426,7 +426,7 @@ ParallelCompactData::create_vspace(size_t count, size_t element_size) const size_t rs_align = page_sz == (size_t) os::vm_page_size() ? 0 : MAX2(page_sz, granularity); ReservedSpace rs(_reserved_byte_size, rs_align, rs_align > 0); - os::trace_page_sizes("par compact", raw_bytes, raw_bytes, page_sz, rs.base(), + os::trace_page_sizes("Parallel Compact Data", raw_bytes, raw_bytes, page_sz, rs.base(), rs.size()); MemTracker::record_virtual_memory_type((address)rs.base(), mtGC); diff --git a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp index a9b404604b03825177268d8c373a0ee5c11139da..247c7e3e49af0c6e2eb1fb922890464589e35d8c 100644 --- a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp +++ b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp @@ -692,7 +692,7 @@ void DefNewGeneration::collect(bool full, _promo_failure_scan_stack.clear(true); // Clear cached segments. remove_forwarding_pointers(); - log_debug(gc)("Promotion failed"); + log_info(gc, promotion)("Promotion failed"); // Add to-space to the list of space to compact // when a promotion failure has occurred. In that // case there can be live objects in to-space @@ -739,8 +739,7 @@ void DefNewGeneration::remove_forwarding_pointers() { eden()->object_iterate(&rspc); from()->object_iterate(&rspc); - // Now restore saved marks, if any. - _preserved_marks_set.restore(); + _preserved_marks_set.restore(GenCollectedHeap::heap()->workers()); } void DefNewGeneration::handle_promotion_failure(oop old) { diff --git a/hotspot/src/share/vm/gc/shared/cardTableModRefBS.cpp b/hotspot/src/share/vm/gc/shared/cardTableModRefBS.cpp index e40cc62ca47ce39291ed320a0162d4ebb5277a0f..9053dedba0fc86cb938297fc44e2d68001e6294f 100644 --- a/hotspot/src/share/vm/gc/shared/cardTableModRefBS.cpp +++ b/hotspot/src/share/vm/gc/shared/cardTableModRefBS.cpp @@ -93,7 +93,7 @@ void CardTableModRefBS::initialize() { MemTracker::record_virtual_memory_type((address)heap_rs.base(), mtGC); - os::trace_page_sizes("card table", _guard_index + 1, _guard_index + 1, + os::trace_page_sizes("Card Table", _guard_index + 1, _guard_index + 1, _page_size, heap_rs.base(), heap_rs.size()); if (!heap_rs.is_reserved()) { vm_exit_during_initialization("Could not reserve enough space for the " diff --git a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp index 7f76efbcd10e4a92e854fd737acd5846ba6b1798..c60e3a02092373f4ffee3646aec3f47916417a93 100644 --- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp @@ -167,6 +167,14 @@ char* GenCollectedHeap::allocate(size_t alignment, SIZE_FORMAT, total_reserved, alignment); *heap_rs = Universe::reserve_heap(total_reserved, alignment); + + os::trace_page_sizes("Heap", + collector_policy()->min_heap_byte_size(), + total_reserved, + alignment, + heap_rs->base(), + heap_rs->size()); + return heap_rs->base(); } diff --git a/hotspot/src/share/vm/gc/shared/preservedMarks.cpp b/hotspot/src/share/vm/gc/shared/preservedMarks.cpp index e6950ff78b6b08950398020d3b11b334553d44ec..96d124e225917e23187db43580d68f0b548267fa 100644 --- a/hotspot/src/share/vm/gc/shared/preservedMarks.cpp +++ b/hotspot/src/share/vm/gc/shared/preservedMarks.cpp @@ -24,24 +24,30 @@ #include "precompiled.hpp" #include "gc/shared/preservedMarks.inline.hpp" +#include "gc/shared/workgroup.hpp" #include "memory/allocation.inline.hpp" -#include "oops/oop.inline.hpp" void PreservedMarks::restore() { - // First, iterate over the stack and restore all marks. - StackIterator iter(_stack); - while (!iter.is_empty()) { - OopAndMarkOop elem = iter.next(); + while (!_stack.is_empty()) { + const OopAndMarkOop elem = _stack.pop(); elem.set_mark(); } + assert_empty(); +} - // Second, reclaim all the stack memory - _stack.clear(true /* clear_cache */); +#ifndef PRODUCT +void PreservedMarks::assert_empty() { + assert(_stack.is_empty(), "stack expected to be empty, size = "SIZE_FORMAT, + _stack.size()); + assert(_stack.cache_size() == 0, + "stack expected to have no cached segments, cache size = "SIZE_FORMAT, + _stack.cache_size()); } +#endif // ndef PRODUCT void RemoveForwardedPointerClosure::do_object(oop obj) { if (obj->is_forwarded()) { - obj->init_mark(); + PreservedMarks::init_forwarded_mark(obj); } } @@ -61,15 +67,48 @@ void PreservedMarksSet::init(uint num) { assert_empty(); } -void PreservedMarksSet::restore() { - size_t total_size = 0; - for (uint i = 0; i < _num; i += 1) { - total_size += get(i)->size(); - get(i)->restore(); +class ParRestoreTask : public AbstractGangTask { +private: + PreservedMarksSet* const _preserved_marks_set; + SequentialSubTasksDone _sub_tasks; + volatile size_t* const _total_size_addr; + +public: + virtual void work(uint worker_id) { + uint task_id = 0; + while (!_sub_tasks.is_task_claimed(/* reference */ task_id)) { + PreservedMarks* const preserved_marks = _preserved_marks_set->get(task_id); + const size_t size = preserved_marks->size(); + preserved_marks->restore(); + // Only do the atomic add if the size is > 0. + if (size > 0) { + Atomic::add(size, _total_size_addr); + } + } + _sub_tasks.all_tasks_completed(); } - assert_empty(); - log_trace(gc)("Restored " SIZE_FORMAT " marks", total_size); + ParRestoreTask(uint worker_num, + PreservedMarksSet* preserved_marks_set, + volatile size_t* total_size_addr) + : AbstractGangTask("Parallel Preserved Mark Restoration"), + _preserved_marks_set(preserved_marks_set), + _total_size_addr(total_size_addr) { + _sub_tasks.set_n_threads(worker_num); + _sub_tasks.set_n_tasks(preserved_marks_set->num()); + } +}; + +void PreservedMarksSet::restore_internal(WorkGang* workers, + volatile size_t* total_size_addr) { + assert(workers != NULL, "pre-condition"); + ParRestoreTask task(workers->active_workers(), this, total_size_addr); + workers->run_task(&task); +} + +// temporary, used by PS +void PreservedMarksSet::restore() { + restore(NULL); } void PreservedMarksSet::reclaim() { @@ -92,7 +131,7 @@ void PreservedMarksSet::reclaim() { void PreservedMarksSet::assert_empty() { assert(_stacks != NULL && _num > 0, "should have been initialized"); for (uint i = 0; i < _num; i += 1) { - assert(get(i)->is_empty(), "stack should be empty"); + get(i)->assert_empty(); } } #endif // ndef PRODUCT diff --git a/hotspot/src/share/vm/gc/shared/preservedMarks.hpp b/hotspot/src/share/vm/gc/shared/preservedMarks.hpp index 729f0666b17ad004e0b65e75f32651620636e127..6ab52ba0fb445b87db4536f950e2a6e225c2ba10 100644 --- a/hotspot/src/share/vm/gc/shared/preservedMarks.hpp +++ b/hotspot/src/share/vm/gc/shared/preservedMarks.hpp @@ -44,6 +44,8 @@ public: }; typedef Stack OopAndMarkOopStack; +class WorkGang; + class PreservedMarks VALUE_OBJ_CLASS_SPEC { private: OopAndMarkOopStack _stack; @@ -52,13 +54,19 @@ private: inline void push(oop obj, markOop m); public: - bool is_empty() const { return _stack.is_empty(); } size_t size() const { return _stack.size(); } inline void push_if_necessary(oop obj, markOop m); - // Iterate over the stack, restore the preserved marks, then reclaim - // the memory taken up by stack chunks. + // Iterate over the stack, restore all preserved marks, and + // reclaim the memory taken up by the stack segments. void restore(); - ~PreservedMarks() { assert(is_empty(), "should have been cleared"); } + + inline static void init_forwarded_mark(oop obj); + + // Assert the stack is empty and has no cached segments. + void assert_empty() PRODUCT_RETURN; + + inline PreservedMarks(); + ~PreservedMarks() { assert_empty(); } }; class RemoveForwardedPointerClosure: public ObjectClosure { @@ -82,7 +90,12 @@ private: // or == NULL if they have not. Padded* _stacks; + // Internal version of restore() that uses a WorkGang for parallelism. + void restore_internal(WorkGang* workers, volatile size_t* total_size_addr); + public: + uint num() const { return _num; } + // Return the i'th stack. PreservedMarks* get(uint i = 0) const { assert(_num > 0 && _stacks != NULL, "stacks should have been initialized"); @@ -92,13 +105,23 @@ public: // Allocate stack array. void init(uint num); - // Iterate over all stacks, restore all preserved marks, then - // reclaim the memory taken up by stack chunks. + + // Itrerate over all stacks, restore all presered marks, and reclaim + // the memory taken up by the stack segments. If the executor is + // NULL, restoration will be done serially. If the executor is not + // NULL, restoration could be done in parallel (when it makes + // sense). Supported executors: WorkGang (Serial, CMS, G1) + template + inline void restore(E* executor); + + // Do the restoration serially. Temporary, to be used by PS until we + // can support GCTaskManager in restore(E*). void restore(); + // Reclaim stack array. void reclaim(); - // Assert all the stacks are empty. + // Assert all the stacks are empty and have no cached segments. void assert_empty() PRODUCT_RETURN; PreservedMarksSet(bool in_c_heap) diff --git a/hotspot/src/share/vm/gc/shared/preservedMarks.inline.hpp b/hotspot/src/share/vm/gc/shared/preservedMarks.inline.hpp index 32c83115a69d6e5190ebcc7b75826bc514a4765a..fc1039ad40b7207aff8b496afc22ae80fcf744d5 100644 --- a/hotspot/src/share/vm/gc/shared/preservedMarks.inline.hpp +++ b/hotspot/src/share/vm/gc/shared/preservedMarks.inline.hpp @@ -22,13 +22,13 @@ * */ -#include "gc/shared/preservedMarks.hpp" -#include "oops/markOop.inline.hpp" -#include "utilities/stack.inline.hpp" - #ifndef SHARE_VM_GC_SHARED_PRESERVEDMARKS_INLINE_HPP #define SHARE_VM_GC_SHARED_PRESERVEDMARKS_INLINE_HPP +#include "gc/shared/preservedMarks.hpp" +#include "oops/oop.inline.hpp" +#include "utilities/stack.inline.hpp" + inline bool PreservedMarks::should_preserve_mark(oop obj, markOop m) const { return m->must_be_preserved_for_promotion_failure(obj); } @@ -45,4 +45,48 @@ inline void PreservedMarks::push_if_necessary(oop obj, markOop m) { } } +inline void PreservedMarks::init_forwarded_mark(oop obj) { + obj->init_mark(); +} + +template +inline void PreservedMarksSet::restore(E* executor) { + volatile size_t total_size = 0; + +#ifdef ASSERT + // This is to make sure the total_size we'll calculate below is correct. + size_t total_size_before = 0; + for (uint i = 0; i < _num; i += 1) { + total_size_before += get(i)->size(); + } +#endif // def ASSERT + + if (executor == NULL) { + for (uint i = 0; i < _num; i += 1) { + total_size += get(i)->size(); + get(i)->restore(); + } + } else { + // Right now, if the executor is not NULL we do the work in + // parallel. In the future we might want to do the restoration + // serially, if there's only a small number of marks per stack. + restore_internal(executor, &total_size); + } + assert_empty(); + + assert(total_size == total_size_before, + "total_size = " SIZE_FORMAT " before = " SIZE_FORMAT, + total_size, total_size_before); + + log_trace(gc)("Restored " SIZE_FORMAT " marks", total_size); +} + +inline PreservedMarks::PreservedMarks() + : _stack(OopAndMarkOopStack::default_segment_size(), + // This stack should be used very infrequently so there's + // no point in caching stack segments (there will be a + // waste of space most of the time). So we set the max + // cache size to 0. + 0 /* max_cache_size */) { } + #endif // SHARE_VM_GC_SHARED_PRESERVEDMARKS_INLINE_HPP diff --git a/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp b/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp index 22ed7b25d81beed654105d15477aa99b07abba0a..2200e7620a4345c1f4b46465b2e8d3d257401462 100644 --- a/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp +++ b/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp @@ -1090,6 +1090,15 @@ bool ReferenceProcessor::discover_reference(oop obj, ReferenceType rt) { return true; } +bool ReferenceProcessor::has_discovered_references() { + for (uint i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) { + if (!_discovered_refs[i].is_empty()) { + return true; + } + } + return false; +} + // Preclean the discovered references by removing those // whose referents are alive, and by marking from those that // are not active. These lists can be handled here diff --git a/hotspot/src/share/vm/gc/shared/referenceProcessor.hpp b/hotspot/src/share/vm/gc/shared/referenceProcessor.hpp index 125f55bde72b1c8806a46347e52b85f68a3514bf..c5d0f5f8321a5bd2ec04fbcb624c9fcb5304f895 100644 --- a/hotspot/src/share/vm/gc/shared/referenceProcessor.hpp +++ b/hotspot/src/share/vm/gc/shared/referenceProcessor.hpp @@ -412,6 +412,9 @@ class ReferenceProcessor : public CHeapObj { // Discover a Reference object, using appropriate discovery criteria bool discover_reference(oop obj, ReferenceType rt); + // Has discovered references that need handling + bool has_discovered_references(); + // Process references found during GC (called by the garbage collector) ReferenceProcessorStats process_discovered_references(BoolObjectClosure* is_alive, diff --git a/hotspot/src/share/vm/gc/shared/space.cpp b/hotspot/src/share/vm/gc/shared/space.cpp index 5a020b1f74f5387aee7a776baa8e158b0bee657f..c207dcd74b56770e804e30f369c8842ac0706ac8 100644 --- a/hotspot/src/share/vm/gc/shared/space.cpp +++ b/hotspot/src/share/vm/gc/shared/space.cpp @@ -411,22 +411,6 @@ HeapWord* CompactibleSpace::forward(oop q, size_t size, return compact_top; } - -bool CompactibleSpace::insert_deadspace(size_t& allowed_deadspace_words, - HeapWord* q, size_t deadlength) { - if (allowed_deadspace_words >= deadlength) { - allowed_deadspace_words -= deadlength; - CollectedHeap::fill_with_object(q, deadlength); - oop(q)->set_mark(oop(q)->mark()->set_marked()); - assert((int) deadlength == oop(q)->size(), "bad filler object size"); - // Recall that we required "q == compaction_top". - return true; - } else { - allowed_deadspace_words = 0; - return false; - } -} - void ContiguousSpace::prepare_for_compaction(CompactPoint* cp) { scan_and_forward(this, cp); } diff --git a/hotspot/src/share/vm/gc/shared/space.hpp b/hotspot/src/share/vm/gc/shared/space.hpp index 465dca90eb6d9bdb77a1bf397ae28fbbb3e55d55..05eb3e1f27c49db55f07bf7303b507f9951bfb5c 100644 --- a/hotspot/src/share/vm/gc/shared/space.hpp +++ b/hotspot/src/share/vm/gc/shared/space.hpp @@ -362,6 +362,12 @@ private: inline size_t obj_size(const HeapWord* addr) const; + template + static inline void verify_up_to_first_dead(SpaceType* space) NOT_DEBUG_RETURN; + + template + static inline void clear_empty_region(SpaceType* space); + public: CompactibleSpace() : _compaction_top(NULL), _next_compaction_space(NULL) {} @@ -455,16 +461,6 @@ protected: return end(); } - // Requires "allowed_deadspace_words > 0", that "q" is the start of a - // free block of the given "word_len", and that "q", were it an object, - // would not move if forwarded. If the size allows, fill the free - // block with an object, to prevent excessive compaction. Returns "true" - // iff the free region was made deadspace, and modifies - // "allowed_deadspace_words" to reflect the number of available deadspace - // words remaining after this operation. - bool insert_deadspace(size_t& allowed_deadspace_words, HeapWord* q, - size_t word_len); - // Below are template functions for scan_and_* algorithms (avoiding virtual calls). // The space argument should be a subclass of CompactibleSpace, implementing // scan_limit(), scanned_block_is_obj(), and scanned_block_size(), diff --git a/hotspot/src/share/vm/gc/shared/space.inline.hpp b/hotspot/src/share/vm/gc/shared/space.inline.hpp index 24cfb6213e87de3230b32637dec854b34d627b85..3943a6da5dc6d3cd78bc54026f199e834eaf7956 100644 --- a/hotspot/src/share/vm/gc/shared/space.inline.hpp +++ b/hotspot/src/share/vm/gc/shared/space.inline.hpp @@ -31,6 +31,7 @@ #include "gc/shared/space.hpp" #include "gc/shared/spaceDecorator.hpp" #include "memory/universe.hpp" +#include "oops/oopsHierarchy.hpp" #include "runtime/prefetch.inline.hpp" #include "runtime/safepoint.hpp" @@ -75,11 +76,61 @@ size_t CompactibleSpace::obj_size(const HeapWord* addr) const { return oop(addr)->size(); } +class DeadSpacer : StackObj { + size_t _allowed_deadspace_words; + bool _active; + CompactibleSpace* _space; + +public: + DeadSpacer(CompactibleSpace* space) : _space(space), _allowed_deadspace_words(0) { + size_t ratio = _space->allowed_dead_ratio(); + _active = ratio > 0; + + if (_active) { + assert(!UseG1GC, "G1 should not be using dead space"); + + // We allow some amount of garbage towards the bottom of the space, so + // we don't start compacting before there is a significant gain to be made. + // Occasionally, we want to ensure a full compaction, which is determined + // by the MarkSweepAlwaysCompactCount parameter. + if ((MarkSweep::total_invocations() % MarkSweepAlwaysCompactCount) != 0) { + _allowed_deadspace_words = (space->capacity() * ratio / 100) / HeapWordSize; + } else { + _active = false; + } + } + } + + + bool insert_deadspace(HeapWord* dead_start, HeapWord* dead_end) { + if (!_active) { + return false; + } + + size_t dead_length = pointer_delta(dead_end, dead_start); + if (_allowed_deadspace_words >= dead_length) { + _allowed_deadspace_words -= dead_length; + CollectedHeap::fill_with_object(dead_start, dead_length); + oop obj = oop(dead_start); + obj->set_mark(obj->mark()->set_marked()); + + assert(dead_length == (size_t)obj->size(), "bad filler object size"); + log_develop_trace(gc, compaction)("Inserting object to dead space: " PTR_FORMAT ", " PTR_FORMAT ", " SIZE_FORMAT "b", + p2i(dead_start), p2i(dead_end), dead_length * HeapWordSize); + + return true; + } else { + _active = false; + return false; + } + } + +}; + template inline void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* cp) { // Compute the new addresses for the live objects and store it in the mark // Used by universe::mark_sweep_phase2() - HeapWord* compact_top; // This is where we are currently compacting to. // We're sure to be here before any objects are compacted into this // space, so this is a good time to initialize this: @@ -90,89 +141,73 @@ inline void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* c assert(cp->threshold == NULL, "just checking"); assert(cp->gen->first_compaction_space() == space, "just checking"); cp->space = cp->gen->first_compaction_space(); - compact_top = cp->space->bottom(); - cp->space->set_compaction_top(compact_top); cp->threshold = cp->space->initialize_threshold(); - } else { - compact_top = cp->space->compaction_top(); + cp->space->set_compaction_top(cp->space->bottom()); } - // We allow some amount of garbage towards the bottom of the space, so - // we don't start compacting before there is a significant gain to be made. - // Occasionally, we want to ensure a full compaction, which is determined - // by the MarkSweepAlwaysCompactCount parameter. - uint invocations = MarkSweep::total_invocations(); - bool skip_dead = ((invocations % MarkSweepAlwaysCompactCount) != 0); - - size_t allowed_deadspace = 0; - if (skip_dead) { - const size_t ratio = space->allowed_dead_ratio(); - allowed_deadspace = (space->capacity() * ratio / 100) / HeapWordSize; - } + HeapWord* compact_top = cp->space->compaction_top(); // This is where we are currently compacting to. - HeapWord* q = space->bottom(); - HeapWord* t = space->scan_limit(); + DeadSpacer dead_spacer(space); - HeapWord* end_of_live= q; // One byte beyond the last byte of the last - // live object. - HeapWord* first_dead = space->end(); // The first dead object. + HeapWord* end_of_live = space->bottom(); // One byte beyond the last byte of the last live object. + HeapWord* first_dead = NULL; // The first dead object. const intx interval = PrefetchScanIntervalInBytes; - while (q < t) { - assert(!space->scanned_block_is_obj(q) || - oop(q)->mark()->is_marked() || oop(q)->mark()->is_unlocked() || - oop(q)->mark()->has_bias_pattern(), + HeapWord* cur_obj = space->bottom(); + HeapWord* scan_limit = space->scan_limit(); + + while (cur_obj < scan_limit) { + assert(!space->scanned_block_is_obj(cur_obj) || + oop(cur_obj)->mark()->is_marked() || oop(cur_obj)->mark()->is_unlocked() || + oop(cur_obj)->mark()->has_bias_pattern(), "these are the only valid states during a mark sweep"); - if (space->scanned_block_is_obj(q) && oop(q)->is_gc_marked()) { - // prefetch beyond q - Prefetch::write(q, interval); - size_t size = space->scanned_block_size(q); - compact_top = cp->space->forward(oop(q), size, cp, compact_top); - q += size; - end_of_live = q; + if (space->scanned_block_is_obj(cur_obj) && oop(cur_obj)->is_gc_marked()) { + // prefetch beyond cur_obj + Prefetch::write(cur_obj, interval); + size_t size = space->scanned_block_size(cur_obj); + compact_top = cp->space->forward(oop(cur_obj), size, cp, compact_top); + cur_obj += size; + end_of_live = cur_obj; } else { // run over all the contiguous dead objects - HeapWord* end = q; + HeapWord* end = cur_obj; do { // prefetch beyond end Prefetch::write(end, interval); end += space->scanned_block_size(end); - } while (end < t && (!space->scanned_block_is_obj(end) || !oop(end)->is_gc_marked())); + } while (end < scan_limit && (!space->scanned_block_is_obj(end) || !oop(end)->is_gc_marked())); // see if we might want to pretend this object is alive so that // we don't have to compact quite as often. - if (allowed_deadspace > 0 && q == compact_top) { - size_t sz = pointer_delta(end, q); - if (space->insert_deadspace(allowed_deadspace, q, sz)) { - compact_top = cp->space->forward(oop(q), sz, cp, compact_top); - q = end; - end_of_live = end; - continue; + if (cur_obj == compact_top && dead_spacer.insert_deadspace(cur_obj, end)) { + oop obj = oop(cur_obj); + compact_top = cp->space->forward(obj, obj->size(), cp, compact_top); + end_of_live = end; + } else { + // otherwise, it really is a free region. + + // cur_obj is a pointer to a dead object. Use this dead memory to store a pointer to the next live object. + *(HeapWord**)cur_obj = end; + + // see if this is the first dead region. + if (first_dead == NULL) { + first_dead = cur_obj; } } - // otherwise, it really is a free region. - - // q is a pointer to a dead object. Use this dead memory to store a pointer to the next live object. - (*(HeapWord**)q) = end; - - // see if this is the first dead region. - if (q < first_dead) { - first_dead = q; - } - // move on to the next object - q = end; + cur_obj = end; } } - assert(q == t, "just checking"); + assert(cur_obj == scan_limit, "just checking"); space->_end_of_live = end_of_live; - if (end_of_live < first_dead) { - first_dead = end_of_live; + if (first_dead != NULL) { + space->_first_dead = first_dead; + } else { + space->_first_dead = end_of_live; } - space->_first_dead = first_dead; // save the compaction_top of the compaction space. cp->space->set_compaction_top(compact_top); @@ -183,63 +218,72 @@ inline void CompactibleSpace::scan_and_adjust_pointers(SpaceType* space) { // adjust all the interior pointers to point at the new locations of objects // Used by MarkSweep::mark_sweep_phase3() - HeapWord* q = space->bottom(); - HeapWord* t = space->_end_of_live; // Established by "prepare_for_compaction". + HeapWord* cur_obj = space->bottom(); + HeapWord* const end_of_live = space->_end_of_live; // Established by "scan_and_forward". + HeapWord* const first_dead = space->_first_dead; // Established by "scan_and_forward". - assert(space->_first_dead <= space->_end_of_live, "Stands to reason, no?"); + assert(first_dead <= end_of_live, "Stands to reason, no?"); - if (q < t && space->_first_dead > q && !oop(q)->is_gc_marked()) { - // we have a chunk of the space which hasn't moved and we've - // reinitialized the mark word during the previous pass, so we can't - // use is_gc_marked for the traversal. - HeapWord* end = space->_first_dead; - - while (q < end) { - // I originally tried to conjoin "block_start(q) == q" to the - // assertion below, but that doesn't work, because you can't - // accurately traverse previous objects to get to the current one - // after their pointers have been - // updated, until the actual compaction is done. dld, 4/00 - assert(space->block_is_obj(q), "should be at block boundaries, and should be looking at objs"); + const intx interval = PrefetchScanIntervalInBytes; + debug_only(HeapWord* prev_obj = NULL); + while (cur_obj < end_of_live) { + Prefetch::write(cur_obj, interval); + if (cur_obj < first_dead || oop(cur_obj)->is_gc_marked()) { + // cur_obj is alive // point all the oops to the new location - size_t size = MarkSweep::adjust_pointers(oop(q)); + size_t size = MarkSweep::adjust_pointers(oop(cur_obj)); size = space->adjust_obj_size(size); - - q += size; - } - - if (space->_first_dead == t) { - q = t; + debug_only(prev_obj = cur_obj); + cur_obj += size; } else { - // The first dead object is no longer an object. At that memory address, - // there is a pointer to the first live object that the previous phase found. - q = *((HeapWord**)(space->_first_dead)); + debug_only(prev_obj = cur_obj); + // cur_obj is not a live object, instead it points at the next live object + cur_obj = *(HeapWord**)cur_obj; + assert(cur_obj > prev_obj, "we should be moving forward through memory, cur_obj: " PTR_FORMAT ", prev_obj: " PTR_FORMAT, p2i(cur_obj), p2i(prev_obj)); } } - const intx interval = PrefetchScanIntervalInBytes; + assert(cur_obj == end_of_live, "just checking"); +} - debug_only(HeapWord* prev_q = NULL); - while (q < t) { - // prefetch beyond q - Prefetch::write(q, interval); - if (oop(q)->is_gc_marked()) { - // q is alive - // point all the oops to the new location - size_t size = MarkSweep::adjust_pointers(oop(q)); - size = space->adjust_obj_size(size); - debug_only(prev_q = q); - q += size; - } else { - debug_only(prev_q = q); - // q is not a live object, instead it points at the next live object - q = *(HeapWord**)q; - assert(q > prev_q, "we should be moving forward through memory, q: " PTR_FORMAT ", prev_q: " PTR_FORMAT, p2i(q), p2i(prev_q)); - } +#ifdef ASSERT +template +inline void CompactibleSpace::verify_up_to_first_dead(SpaceType* space) { + HeapWord* cur_obj = space->bottom(); + + if (cur_obj < space->_end_of_live && space->_first_dead > cur_obj && !oop(cur_obj)->is_gc_marked()) { + // we have a chunk of the space which hasn't moved and we've reinitialized + // the mark word during the previous pass, so we can't use is_gc_marked for + // the traversal. + HeapWord* prev_obj = NULL; + + while (cur_obj < space->_first_dead) { + size_t size = space->obj_size(cur_obj); + assert(!oop(cur_obj)->is_gc_marked(), "should be unmarked (special dense prefix handling)"); + prev_obj = cur_obj; + cur_obj += size; + } } +} +#endif - assert(q == t, "just checking"); +template +inline void CompactibleSpace::clear_empty_region(SpaceType* space) { + // Let's remember if we were empty before we did the compaction. + bool was_empty = space->used_region().is_empty(); + // Reset space after compaction is complete + space->reset_after_compaction(); + // We do this clear, below, since it has overloaded meanings for some + // space subtypes. For example, OffsetTableContigSpace's that were + // compacted into will have had their offset table thresholds updated + // continuously, but those that weren't need to have their thresholds + // re-initialized. Also mangles unused area for debugging. + if (space->used_region().is_empty()) { + if (!was_empty) space->clear(SpaceDecorator::Mangle); + } else { + if (ZapUnusedHeapArea) space->mangle_unused_area(); + } } template @@ -247,77 +291,58 @@ inline void CompactibleSpace::scan_and_compact(SpaceType* space) { // Copy all live objects to their new location // Used by MarkSweep::mark_sweep_phase4() - HeapWord* q = space->bottom(); - HeapWord* const t = space->_end_of_live; - debug_only(HeapWord* prev_q = NULL); - - if (q < t && space->_first_dead > q && !oop(q)->is_gc_marked()) { - #ifdef ASSERT // Debug only - // we have a chunk of the space which hasn't moved and we've reinitialized - // the mark word during the previous pass, so we can't use is_gc_marked for - // the traversal. - HeapWord* const end = space->_first_dead; - - while (q < end) { - size_t size = space->obj_size(q); - assert(!oop(q)->is_gc_marked(), "should be unmarked (special dense prefix handling)"); - prev_q = q; - q += size; - } - #endif + verify_up_to_first_dead(space); - if (space->_first_dead == t) { - q = t; - } else { - // $$$ Funky - q = (HeapWord*) oop(space->_first_dead)->mark()->decode_pointer(); - } + HeapWord* const end_of_live = space->_end_of_live; + + assert(space->_first_dead <= end_of_live, "Invariant. _first_dead: " PTR_FORMAT " <= end_of_live: " PTR_FORMAT, p2i(space->_first_dead), p2i(end_of_live)); + if (space->_first_dead == end_of_live && !oop(space->bottom())->is_gc_marked()) { + // Nothing to compact. The space is either empty or all live object should be left in place. + clear_empty_region(space); + return; } const intx scan_interval = PrefetchScanIntervalInBytes; const intx copy_interval = PrefetchCopyIntervalInBytes; - while (q < t) { - if (!oop(q)->is_gc_marked()) { - // mark is pointer to next marked oop - debug_only(prev_q = q); - q = (HeapWord*) oop(q)->mark()->decode_pointer(); - assert(q > prev_q, "we should be moving forward through memory"); + + assert(space->bottom() < end_of_live, "bottom: " PTR_FORMAT " should be < end_of_live: " PTR_FORMAT, p2i(space->bottom()), p2i(end_of_live)); + HeapWord* cur_obj = space->bottom(); + if (space->_first_dead > cur_obj && !oop(cur_obj)->is_gc_marked()) { + // All object before _first_dead can be skipped. They should not be moved. + // A pointer to the first live object is stored at the memory location for _first_dead. + cur_obj = *(HeapWord**)(space->_first_dead); + } + + debug_only(HeapWord* prev_obj = NULL); + while (cur_obj < end_of_live) { + if (!oop(cur_obj)->is_gc_marked()) { + debug_only(prev_obj = cur_obj); + // The first word of the dead object contains a pointer to the next live object or end of space. + cur_obj = *(HeapWord**)cur_obj; + assert(cur_obj > prev_obj, "we should be moving forward through memory"); } else { // prefetch beyond q - Prefetch::read(q, scan_interval); + Prefetch::read(cur_obj, scan_interval); // size and destination - size_t size = space->obj_size(q); - HeapWord* compaction_top = (HeapWord*)oop(q)->forwardee(); + size_t size = space->obj_size(cur_obj); + HeapWord* compaction_top = (HeapWord*)oop(cur_obj)->forwardee(); // prefetch beyond compaction_top Prefetch::write(compaction_top, copy_interval); // copy object and reinit its mark - assert(q != compaction_top, "everything in this pass should be moving"); - Copy::aligned_conjoint_words(q, compaction_top, size); + assert(cur_obj != compaction_top, "everything in this pass should be moving"); + Copy::aligned_conjoint_words(cur_obj, compaction_top, size); oop(compaction_top)->init_mark(); assert(oop(compaction_top)->klass() != NULL, "should have a class"); - debug_only(prev_q = q); - q += size; + debug_only(prev_obj = cur_obj); + cur_obj += size; } } - // Let's remember if we were empty before we did the compaction. - bool was_empty = space->used_region().is_empty(); - // Reset space after compaction is complete - space->reset_after_compaction(); - // We do this clear, below, since it has overloaded meanings for some - // space subtypes. For example, OffsetTableContigSpace's that were - // compacted into will have had their offset table thresholds updated - // continuously, but those that weren't need to have their thresholds - // re-initialized. Also mangles unused area for debugging. - if (space->used_region().is_empty()) { - if (!was_empty) space->clear(SpaceDecorator::Mangle); - } else { - if (ZapUnusedHeapArea) space->mangle_unused_area(); - } + clear_empty_region(space); } size_t ContiguousSpace::scanned_block_size(const HeapWord* addr) const { diff --git a/hotspot/src/share/vm/interpreter/abstractInterpreter.cpp b/hotspot/src/share/vm/interpreter/abstractInterpreter.cpp index 96fb64403cd96e45d923944cd8db39246bcdabd7..3717ae061d98ba93dc969d6c86fff983b1c7323f 100644 --- a/hotspot/src/share/vm/interpreter/abstractInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/abstractInterpreter.cpp @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "asm/macroAssembler.hpp" #include "asm/macroAssembler.inline.hpp" +#include "compiler/disassembler.hpp" #include "interpreter/bytecodeHistogram.hpp" #include "interpreter/bytecodeInterpreter.hpp" #include "interpreter/interpreter.hpp" @@ -32,6 +33,7 @@ #include "interpreter/interp_masm.hpp" #include "interpreter/templateTable.hpp" #include "memory/allocation.inline.hpp" +#include "memory/metaspaceShared.hpp" #include "memory/resourceArea.hpp" #include "oops/arrayOop.hpp" #include "oops/methodData.hpp" @@ -93,6 +95,7 @@ address AbstractInterpreter::_native_entry_begin = NU address AbstractInterpreter::_native_entry_end = NULL; address AbstractInterpreter::_slow_signature_handler; address AbstractInterpreter::_entry_table [AbstractInterpreter::number_of_method_entries]; +address AbstractInterpreter::_cds_entry_table [AbstractInterpreter::number_of_method_entries]; address AbstractInterpreter::_native_abi_to_tosca [AbstractInterpreter::number_of_result_handlers]; //------------------------------------------------------------------------------------------------------------------------ @@ -204,14 +207,41 @@ AbstractInterpreter::MethodKind AbstractInterpreter::method_kind(methodHandle m) return zerolocals; } +#if INCLUDE_CDS + +address AbstractInterpreter::get_trampoline_code_buffer(AbstractInterpreter::MethodKind kind) { + const size_t trampoline_size = SharedRuntime::trampoline_size(); + address addr = MetaspaceShared::cds_i2i_entry_code_buffers((size_t)(AbstractInterpreter::number_of_method_entries) * trampoline_size); + addr += (size_t)(kind) * trampoline_size; + + return addr; +} + +void AbstractInterpreter::update_cds_entry_table(AbstractInterpreter::MethodKind kind) { + if (DumpSharedSpaces || UseSharedSpaces) { + address trampoline = get_trampoline_code_buffer(kind); + _cds_entry_table[kind] = trampoline; + + CodeBuffer buffer(trampoline, (int)(SharedRuntime::trampoline_size())); + MacroAssembler _masm(&buffer); + SharedRuntime::generate_trampoline(&_masm, _entry_table[kind]); + + if (PrintInterpreter) { + Disassembler::decode(buffer.insts_begin(), buffer.insts_end()); + } + } +} + +#endif void AbstractInterpreter::set_entry_for_kind(AbstractInterpreter::MethodKind kind, address entry) { assert(kind >= method_handle_invoke_FIRST && kind <= method_handle_invoke_LAST, "late initialization only for MH entry points"); assert(_entry_table[kind] == _entry_table[abstract], "previous value must be AME entry"); _entry_table[kind] = entry; -} + update_cds_entry_table(kind); +} // Return true if the interpreter can prove that the given bytecode has // not yet been executed (in Java semantics, not in actual operation). @@ -416,5 +446,6 @@ void AbstractInterpreter::initialize_method_handle_entries() { for (int i = method_handle_invoke_FIRST; i <= method_handle_invoke_LAST; i++) { MethodKind kind = (MethodKind) i; _entry_table[kind] = _entry_table[Interpreter::abstract]; + Interpreter::update_cds_entry_table(kind); } } diff --git a/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp b/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp index 8be852bae608e79edc2003ca6253038c9b929f05..8ec0db7e0de07b8a6d641a893c53b5044b04d519 100644 --- a/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp +++ b/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp @@ -28,9 +28,8 @@ #include "asm/macroAssembler.hpp" #include "code/stubs.hpp" #include "interpreter/bytecodes.hpp" -#include "runtime/thread.inline.hpp" +#include "runtime/thread.hpp" #include "runtime/vmThread.hpp" -#include "utilities/top.hpp" // This file contains the platform-independent parts // of the abstract interpreter and the abstract interpreter generator. @@ -113,6 +112,7 @@ class AbstractInterpreter: AllStatic { // method entry points static address _entry_table[number_of_method_entries]; // entry points for a given method + static address _cds_entry_table[number_of_method_entries]; // entry points for methods in the CDS archive static address _native_abi_to_tosca[number_of_result_handlers]; // for native method result handlers static address _slow_signature_handler; // the native method generic (slow) signature handler @@ -132,6 +132,17 @@ class AbstractInterpreter: AllStatic { static address entry_for_kind(MethodKind k) { assert(0 <= k && k < number_of_method_entries, "illegal kind"); return _entry_table[k]; } static address entry_for_method(methodHandle m) { return entry_for_kind(method_kind(m)); } + static address entry_for_cds_method(methodHandle m) { + MethodKind k = method_kind(m); + assert(0 <= k && k < number_of_method_entries, "illegal kind"); + return _cds_entry_table[k]; + } + + // used by class data sharing + static void update_cds_entry_table(MethodKind kind) NOT_CDS_RETURN; + + static address get_trampoline_code_buffer(AbstractInterpreter::MethodKind kind) NOT_CDS_RETURN_(0); + // used for bootstrapping method handles: static void set_entry_for_kind(MethodKind k, address e); diff --git a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp index dbe5355b1df3a1c2dea628a7bb75ab078fe334f7..2b42fab10b92d3b6d8bd8be420b4d20af22f0e42 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp @@ -1767,8 +1767,19 @@ run: ((objArrayOop) arrObj)->obj_at_put(index, rhsObject); UPDATE_PC_AND_TOS_AND_CONTINUE(1, -3); } - CASE(_bastore): - ARRAY_STOREFROM32(T_BYTE, jbyte, "%d", STACK_INT, 0); + CASE(_bastore): { + ARRAY_INTRO(-3); + int item = STACK_INT(-1); + // if it is a T_BOOLEAN array, mask the stored value to 0/1 + if (arrObj->klass() == Universe::boolArrayKlassObj()) { + item &= 1; + } else { + assert(arrObj->klass() == Universe::byteArrayKlassObj(), + "should be byte array otherwise"); + } + ((typeArrayOop)arrObj)->byte_at_put(index, item); + UPDATE_PC_AND_TOS_AND_CONTINUE(1, -3); + } CASE(_castore): ARRAY_STOREFROM32(T_CHAR, jchar, "%d", STACK_INT, 0); CASE(_sastore): @@ -1999,7 +2010,7 @@ run: } else if (tos_type == ltos) { SET_STACK_LONG(obj->long_field_acquire(field_offset), 0); MORE_STACK(1); - } else if (tos_type == btos) { + } else if (tos_type == btos || tos_type == ztos) { SET_STACK_INT(obj->byte_field_acquire(field_offset), -1); } else if (tos_type == ctos) { SET_STACK_INT(obj->char_field_acquire(field_offset), -1); @@ -2020,7 +2031,7 @@ run: } else if (tos_type == ltos) { SET_STACK_LONG(obj->long_field(field_offset), 0); MORE_STACK(1); - } else if (tos_type == btos) { + } else if (tos_type == btos || tos_type == ztos) { SET_STACK_INT(obj->byte_field(field_offset), -1); } else if (tos_type == ctos) { SET_STACK_INT(obj->char_field(field_offset), -1); @@ -2109,6 +2120,9 @@ run: obj->release_obj_field_put(field_offset, STACK_OBJECT(-1)); } else if (tos_type == btos) { obj->release_byte_field_put(field_offset, STACK_INT(-1)); + } else if (tos_type == ztos) { + int bool_field = STACK_INT(-1); // only store LSB + obj->release_byte_field_put(field_offset, (bool_field & 1)); } else if (tos_type == ltos) { obj->release_long_field_put(field_offset, STACK_LONG(-1)); } else if (tos_type == ctos) { @@ -2129,6 +2143,9 @@ run: obj->obj_field_put(field_offset, STACK_OBJECT(-1)); } else if (tos_type == btos) { obj->byte_field_put(field_offset, STACK_INT(-1)); + } else if (tos_type == ztos) { + int bool_field = STACK_INT(-1); // only store LSB + obj->byte_field_put(field_offset, (bool_field & 1)); } else if (tos_type == ltos) { obj->long_field_put(field_offset, STACK_LONG(-1)); } else if (tos_type == ctos) { diff --git a/hotspot/src/share/vm/interpreter/bytecodeTracer.hpp b/hotspot/src/share/vm/interpreter/bytecodeTracer.hpp index 06d2a1d8899db5048a3984dd73139d0b25e75dde..dff27c66022c8eddf0de8f06ef247a4e1155402f 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeTracer.hpp +++ b/hotspot/src/share/vm/interpreter/bytecodeTracer.hpp @@ -26,6 +26,7 @@ #define SHARE_VM_INTERPRETER_BYTECODETRACER_HPP #include "memory/allocation.hpp" +#include "utilities/ostream.hpp" // The BytecodeTracer is a helper class used by the interpreter for run-time // bytecode tracing. If bytecode tracing is turned on, trace() will be called diff --git a/hotspot/src/share/vm/interpreter/bytecodes.cpp b/hotspot/src/share/vm/interpreter/bytecodes.cpp index 78ef212d9bf33ce6567739d24336a38c64fa3dc4..863c85fae632b744b574b7b138a9d4820c6d32e8 100644 --- a/hotspot/src/share/vm/interpreter/bytecodes.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodes.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -496,6 +496,7 @@ void Bytecodes::initialize() { def(_fast_aputfield , "fast_aputfield" , "bJJ" , NULL , T_OBJECT , 0, true , _putfield ); def(_fast_bputfield , "fast_bputfield" , "bJJ" , NULL , T_INT , 0, true , _putfield ); + def(_fast_zputfield , "fast_zputfield" , "bJJ" , NULL , T_INT , 0, true , _putfield ); def(_fast_cputfield , "fast_cputfield" , "bJJ" , NULL , T_CHAR , 0, true , _putfield ); def(_fast_dputfield , "fast_dputfield" , "bJJ" , NULL , T_DOUBLE , 0, true , _putfield ); def(_fast_fputfield , "fast_fputfield" , "bJJ" , NULL , T_FLOAT , 0, true , _putfield ); diff --git a/hotspot/src/share/vm/interpreter/bytecodes.hpp b/hotspot/src/share/vm/interpreter/bytecodes.hpp index 20990d64b9e618994b9ebab04c2e1a46a415b647..86e88d4b5164876f28b16a911801fff7923b7f3b 100644 --- a/hotspot/src/share/vm/interpreter/bytecodes.hpp +++ b/hotspot/src/share/vm/interpreter/bytecodes.hpp @@ -26,11 +26,12 @@ #define SHARE_VM_INTERPRETER_BYTECODES_HPP #include "memory/allocation.hpp" -#include "utilities/top.hpp" // Bytecodes specifies all bytecodes used in the VM and // provides utility functions to get bytecode attributes. +class Method; + // NOTE: replicated in SA in vm/agent/sun/jvm/hotspot/interpreter/Bytecodes.java class Bytecodes: AllStatic { public: @@ -256,6 +257,7 @@ class Bytecodes: AllStatic { _fast_aputfield , _fast_bputfield , + _fast_zputfield , _fast_cputfield , _fast_dputfield , _fast_fputfield , diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp index e36b76dda607c525821d20300d556c75df884af5..cd1d88926aa92023ffeea71b5d35bebbd2c27bbc 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp @@ -313,18 +313,7 @@ IRT_ENTRY(void, InterpreterRuntime::throw_StackOverflowError(JavaThread* thread) THROW_HANDLE(exception); IRT_END -IRT_ENTRY(address, InterpreterRuntime::check_ReservedStackAccess_annotated_methods(JavaThread* thread)) - frame fr = thread->last_frame(); - assert(fr.is_java_frame(), "Must be a Java frame"); - frame activation = SharedRuntime::look_for_reserved_stack_annotated_method(thread, fr); - if (activation.sp() != NULL) { - thread->disable_stack_reserved_zone(); - thread->set_reserved_stack_activation((address)activation.unextended_sp()); - } - return (address)activation.sp(); -IRT_END - - IRT_ENTRY(void, InterpreterRuntime::throw_delayed_StackOverflowError(JavaThread* thread)) +IRT_ENTRY(void, InterpreterRuntime::throw_delayed_StackOverflowError(JavaThread* thread)) Handle exception = get_preinitialized_exception( SystemDictionary::StackOverflowError_klass(), CHECK); @@ -1088,7 +1077,8 @@ IRT_ENTRY(void, InterpreterRuntime::post_field_modification(JavaThread *thread, char sig_type = '\0'; switch(cp_entry->flag_state()) { - case btos: sig_type = 'Z'; break; + case btos: sig_type = 'B'; break; + case ztos: sig_type = 'Z'; break; case ctos: sig_type = 'C'; break; case stos: sig_type = 'S'; break; case itos: sig_type = 'I'; break; diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp index 02fc2cf3b2e5b5fa86cc4cd64b25f378c7de7580..d8ef297e21d10d539e4aadd10baed33f5848b22c 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp @@ -31,8 +31,7 @@ #include "oops/method.hpp" #include "runtime/frame.inline.hpp" #include "runtime/signature.hpp" -#include "runtime/thread.inline.hpp" -#include "utilities/top.hpp" +#include "runtime/thread.hpp" // The InterpreterRuntime is called by the interpreter for everything // that cannot/should not be dealt with in assembly and needs C support. @@ -91,8 +90,6 @@ class InterpreterRuntime: AllStatic { // Quicken instance-of and check-cast bytecodes static void quicken_io_cc(JavaThread* thread); - static address check_ReservedStackAccess_annotated_methods(JavaThread* thread); - // Exceptions thrown by the interpreter static void throw_AbstractMethodError(JavaThread* thread); static void throw_IncompatibleClassChangeError(JavaThread* thread); diff --git a/hotspot/src/share/vm/interpreter/linkResolver.hpp b/hotspot/src/share/vm/interpreter/linkResolver.hpp index a197070dadd833d6bb1336e578465f7bc53a349e..4dae8111e182c205c39ae75ab7b040df202a76a5 100644 --- a/hotspot/src/share/vm/interpreter/linkResolver.hpp +++ b/hotspot/src/share/vm/interpreter/linkResolver.hpp @@ -26,7 +26,6 @@ #define SHARE_VM_INTERPRETER_LINKRESOLVER_HPP #include "oops/method.hpp" -#include "utilities/top.hpp" // All the necessary definitions for run-time link resolution. diff --git a/hotspot/src/share/vm/interpreter/templateInterpreter.cpp b/hotspot/src/share/vm/interpreter/templateInterpreter.cpp index a059bd5871f9dfdefe81ea50923f541f71b2c3df..8b368a12d79c17f9189719ed69eb739c3399cc0f 100644 --- a/hotspot/src/share/vm/interpreter/templateInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/templateInterpreter.cpp @@ -89,8 +89,9 @@ void TemplateInterpreter::initialize() { // Implementation of EntryPoint EntryPoint::EntryPoint() { - assert(number_of_states == 9, "check the code below"); + assert(number_of_states == 10, "check the code below"); _entry[btos] = NULL; + _entry[ztos] = NULL; _entry[ctos] = NULL; _entry[stos] = NULL; _entry[atos] = NULL; @@ -102,9 +103,10 @@ EntryPoint::EntryPoint() { } -EntryPoint::EntryPoint(address bentry, address centry, address sentry, address aentry, address ientry, address lentry, address fentry, address dentry, address ventry) { - assert(number_of_states == 9, "check the code below"); +EntryPoint::EntryPoint(address bentry, address zentry, address centry, address sentry, address aentry, address ientry, address lentry, address fentry, address dentry, address ventry) { + assert(number_of_states == 10, "check the code below"); _entry[btos] = bentry; + _entry[ztos] = zentry; _entry[ctos] = centry; _entry[stos] = sentry; _entry[atos] = aentry; @@ -155,6 +157,7 @@ EntryPoint DispatchTable::entry(int i) const { return EntryPoint( _table[btos][i], + _table[ztos][i], _table[ctos][i], _table[stos][i], _table[atos][i], @@ -169,8 +172,9 @@ EntryPoint DispatchTable::entry(int i) const { void DispatchTable::set_entry(int i, EntryPoint& entry) { assert(0 <= i && i < length, "index out of bounds"); - assert(number_of_states == 9, "check the code below"); + assert(number_of_states == 10, "check the code below"); _table[btos][i] = entry.entry(btos); + _table[ztos][i] = entry.entry(ztos); _table[ctos][i] = entry.entry(ctos); _table[stos][i] = entry.entry(stos); _table[atos][i] = entry.entry(atos); diff --git a/hotspot/src/share/vm/interpreter/templateInterpreter.hpp b/hotspot/src/share/vm/interpreter/templateInterpreter.hpp index 1955cae20cb2976868f8094080a8d8b997c9df32..f9d008d5c92cc3207b3670a6094ca4875da1bb5e 100644 --- a/hotspot/src/share/vm/interpreter/templateInterpreter.hpp +++ b/hotspot/src/share/vm/interpreter/templateInterpreter.hpp @@ -47,7 +47,7 @@ class EntryPoint VALUE_OBJ_CLASS_SPEC { public: // Construction EntryPoint(); - EntryPoint(address bentry, address centry, address sentry, address aentry, address ientry, address lentry, address fentry, address dentry, address ventry); + EntryPoint(address bentry, address zentry, address centry, address sentry, address aentry, address ientry, address lentry, address fentry, address dentry, address ventry); // Attributes address entry(TosState state) const; // return target address for a given tosca state diff --git a/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.cpp b/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.cpp index 0fbe6f8ddacf1b06bee28b2378952ff24f2c13cd..a2c427f4aa84319924bc240130fc8ccb1ff1c92d 100644 --- a/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.cpp +++ b/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.cpp @@ -74,6 +74,7 @@ void TemplateInterpreterGenerator::generate_all() { Interpreter::_trace_code = EntryPoint( generate_trace_code(btos), + generate_trace_code(ztos), generate_trace_code(ctos), generate_trace_code(stos), generate_trace_code(atos), @@ -94,6 +95,7 @@ void TemplateInterpreterGenerator::generate_all() { generate_return_entry_for(itos, i, index_size), generate_return_entry_for(itos, i, index_size), generate_return_entry_for(itos, i, index_size), + generate_return_entry_for(itos, i, index_size), generate_return_entry_for(atos, i, index_size), generate_return_entry_for(itos, i, index_size), generate_return_entry_for(ltos, i, index_size), @@ -105,13 +107,16 @@ void TemplateInterpreterGenerator::generate_all() { } { CodeletMark cm(_masm, "invoke return entry points"); - const TosState states[] = {itos, itos, itos, itos, ltos, ftos, dtos, atos, vtos}; + // These states are in order specified in TosState, except btos/ztos/ctos/stos are + // really the same as itos since there is no top of stack optimization for these types + const TosState states[] = {itos, itos, itos, itos, itos, ltos, ftos, dtos, atos, vtos, ilgl}; const int invoke_length = Bytecodes::length_for(Bytecodes::_invokestatic); const int invokeinterface_length = Bytecodes::length_for(Bytecodes::_invokeinterface); const int invokedynamic_length = Bytecodes::length_for(Bytecodes::_invokedynamic); for (int i = 0; i < Interpreter::number_of_return_addrs; i++) { TosState state = states[i]; + assert(state != ilgl, "states array is wrong above"); Interpreter::_invoke_return_entry[i] = generate_return_entry_for(state, invoke_length, sizeof(u2)); Interpreter::_invokeinterface_return_entry[i] = generate_return_entry_for(state, invokeinterface_length, sizeof(u2)); Interpreter::_invokedynamic_return_entry[i] = generate_return_entry_for(state, invokedynamic_length, sizeof(u4)); @@ -122,6 +127,7 @@ void TemplateInterpreterGenerator::generate_all() { Interpreter::_earlyret_entry = EntryPoint( generate_earlyret_entry_for(btos), + generate_earlyret_entry_for(ztos), generate_earlyret_entry_for(ctos), generate_earlyret_entry_for(stos), generate_earlyret_entry_for(atos), @@ -140,6 +146,7 @@ void TemplateInterpreterGenerator::generate_all() { generate_deopt_entry_for(itos, i), generate_deopt_entry_for(itos, i), generate_deopt_entry_for(itos, i), + generate_deopt_entry_for(itos, i), generate_deopt_entry_for(atos, i), generate_deopt_entry_for(itos, i), generate_deopt_entry_for(ltos, i), @@ -167,6 +174,7 @@ void TemplateInterpreterGenerator::generate_all() { Interpreter::_continuation_entry = EntryPoint( generate_continuation_for(btos), + generate_continuation_for(ztos), generate_continuation_for(ctos), generate_continuation_for(stos), generate_continuation_for(atos), @@ -182,6 +190,7 @@ void TemplateInterpreterGenerator::generate_all() { Interpreter::_safept_entry = EntryPoint( generate_safept_entry_for(btos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), + generate_safept_entry_for(ztos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), generate_safept_entry_for(ctos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), generate_safept_entry_for(stos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), generate_safept_entry_for(atos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), @@ -212,6 +221,7 @@ void TemplateInterpreterGenerator::generate_all() { #define method_entry(kind) \ { CodeletMark cm(_masm, "method entry point (kind = " #kind ")"); \ Interpreter::_entry_table[Interpreter::kind] = generate_method_entry(Interpreter::kind); \ + Interpreter::update_cds_entry_table(Interpreter::kind); \ } // all non-native method kinds @@ -300,7 +310,7 @@ void TemplateInterpreterGenerator::set_safepoints_for_all_bytes() { void TemplateInterpreterGenerator::set_unimplemented(int i) { address e = _unimplemented_bytecode; - EntryPoint entry(e, e, e, e, e, e, e, e, e); + EntryPoint entry(e, e, e, e, e, e, e, e, e, e); Interpreter::_normal_table.set_entry(i, entry); Interpreter::_wentry_point[i] = _unimplemented_bytecode; } @@ -315,6 +325,7 @@ void TemplateInterpreterGenerator::set_entry_points(Bytecodes::Code code) { assert(_unimplemented_bytecode != NULL, "should have been generated before"); assert(_illegal_bytecode_sequence != NULL, "should have been generated before"); address bep = _illegal_bytecode_sequence; + address zep = _illegal_bytecode_sequence; address cep = _illegal_bytecode_sequence; address sep = _illegal_bytecode_sequence; address aep = _illegal_bytecode_sequence; @@ -336,7 +347,7 @@ void TemplateInterpreterGenerator::set_entry_points(Bytecodes::Code code) { set_wide_entry_point(t, wep); } // set entry points - EntryPoint entry(bep, cep, sep, aep, iep, lep, fep, dep, vep); + EntryPoint entry(bep, zep, cep, sep, aep, iep, lep, fep, dep, vep); Interpreter::_normal_table.set_entry(code, entry); Interpreter::_wentry_point[code] = wep; CodeCacheExtensions::completed_template_interpreter_entries(_masm, code); @@ -354,6 +365,7 @@ void TemplateInterpreterGenerator::set_short_entry_points(Template* t, address& assert(t->is_valid(), "template must exist"); switch (t->tos_in()) { case btos: + case ztos: case ctos: case stos: ShouldNotReachHere(); // btos/ctos/stos should use itos. diff --git a/hotspot/src/share/vm/interpreter/templateTable.cpp b/hotspot/src/share/vm/interpreter/templateTable.cpp index ebca67320bd01d674c788be51b98ebabe026ef68..4672a1ee4eb8808f868a74f392dcb7aa6efc77ab 100644 --- a/hotspot/src/share/vm/interpreter/templateTable.cpp +++ b/hotspot/src/share/vm/interpreter/templateTable.cpp @@ -488,6 +488,7 @@ void TemplateTable::initialize() { def(Bytecodes::_fast_aputfield , ubcp|____|____|____, atos, vtos, fast_storefield , atos ); def(Bytecodes::_fast_bputfield , ubcp|____|____|____, itos, vtos, fast_storefield , itos ); + def(Bytecodes::_fast_zputfield , ubcp|____|____|____, itos, vtos, fast_storefield , itos ); def(Bytecodes::_fast_cputfield , ubcp|____|____|____, itos, vtos, fast_storefield , itos ); def(Bytecodes::_fast_dputfield , ubcp|____|____|____, dtos, vtos, fast_storefield , dtos ); def(Bytecodes::_fast_fputfield , ubcp|____|____|____, ftos, vtos, fast_storefield , ftos ); diff --git a/hotspot/src/share/vm/logging/log.cpp b/hotspot/src/share/vm/logging/log.cpp index 3d676219d89a2e6d828f93b0aa48d5827ec084bd..cdef6d8a7abb2900b3b2e088a4a28f7c940d41f0 100644 --- a/hotspot/src/share/vm/logging/log.cpp +++ b/hotspot/src/share/vm/logging/log.cpp @@ -31,7 +31,10 @@ #include "gc/shared/gcTraceTime.inline.hpp" #include "logging/log.hpp" #include "logging/logConfiguration.hpp" +#include "logging/logFileOutput.hpp" #include "logging/logOutput.hpp" +#include "logging/logTagLevelExpression.hpp" +#include "logging/logTagSet.hpp" #include "logging/logStream.inline.hpp" #include "memory/resourceArea.hpp" @@ -44,6 +47,13 @@ #define assert_char_not_in(c, s) \ assert(strchr(s, c) == NULL, "Expected '%s' to *not* contain character '%c'", s, c) +void Test_log_tag_combinations_limit() { + assert(LogTagLevelExpression::MaxCombinations > LogTagSet::ntagsets(), + "Combination limit (" SIZE_FORMAT ") not sufficient " + "for configuring all available tag sets (" SIZE_FORMAT ")", + LogTagLevelExpression::MaxCombinations, LogTagSet::ntagsets()); +} + class TestLogFile { private: char file_name[256]; @@ -129,6 +139,131 @@ void Test_configure_stdout() { assert_str_eq("all=off", stdoutput->config_string()); } +static size_t number_of_lines_with_substring_in_file(const char* filename, + const char* substr) { + ResourceMark rm; + size_t ret = 0; + FILE* fp = fopen(filename, "r"); + assert(fp != NULL, "error opening file %s: %s", filename, strerror(errno)); + + int buflen = 512; + char* buf = NEW_RESOURCE_ARRAY(char, buflen); + long pos = 0; + + while (fgets(buf, buflen, fp) != NULL) { + if (buf[strlen(buf) - 1] != '\n' && !feof(fp)) { + // retry with a larger buffer + buf = REALLOC_RESOURCE_ARRAY(char, buf, buflen, buflen * 2); + buflen *= 2; + // rewind to beginning of line + fseek(fp, pos, SEEK_SET); + continue; + } + pos = ftell(fp); + if (strstr(buf, substr) != NULL) { + ret++; + } + } + + fclose(fp); + return ret; +} + +static bool file_exists(const char* filename) { + struct stat st; + return os::stat(filename, &st) == 0; +} + +static void delete_file(const char* filename) { + if (!file_exists(filename)) { + return; + } + int ret = remove(filename); + assert(ret == 0, "failed to remove file '%s': %s", filename, strerror(errno)); +} + +static void create_directory(const char* name) { + assert(!file_exists(name), "can't create directory: %s already exists", name); + bool failed; +#ifdef _WINDOWS + failed = !CreateDirectory(name, NULL); +#else + failed = mkdir(name, 0777); +#endif + assert(!failed, "failed to create directory %s", name); +} + +static const char* ExpectedLine = "a (hopefully) unique log line for testing"; + +static void init_file(const char* filename, const char* options = "") { + LogConfiguration::parse_log_arguments(filename, "logging=trace", "", options, + Log(logging)::error_stream()); + log_debug(logging)("%s", ExpectedLine); + LogConfiguration::parse_log_arguments(filename, "all=off", "", "", + Log(logging)::error_stream()); +} + +void Test_log_file_startup_rotation() { + ResourceMark rm; + const size_t rotations = 5; + const char* filename = "start-rotate-test"; + char* rotated_file[rotations]; + for (size_t i = 0; i < rotations; i++) { + size_t len = strlen(filename) + 3; + rotated_file[i] = NEW_RESOURCE_ARRAY(char, len); + jio_snprintf(rotated_file[i], len, "%s." SIZE_FORMAT, filename, i); + delete_file(rotated_file[i]); + }; + + delete_file(filename); + init_file(filename); + assert(file_exists(filename), + "configured logging to file '%s' but file was not found", filename); + + // Initialize the same file a bunch more times to trigger rotations + for (size_t i = 0; i < rotations; i++) { + init_file(filename); + assert(file_exists(rotated_file[i]), "existing file was not rotated"); + } + + // Remove a file and expect its slot to be re-used + delete_file(rotated_file[1]); + init_file(filename); + assert(file_exists(rotated_file[1]), "log file not properly rotated"); + + // Clean up after test + delete_file(filename); + for (size_t i = 0; i < rotations; i++) { + delete_file(rotated_file[i]); + } +} + +void Test_log_file_startup_truncation() { + ResourceMark rm; + const char* filename = "start-truncate-test"; + const char* archived_filename = "start-truncate-test.0"; + + delete_file(filename); + delete_file(archived_filename); + + // Use the same log file twice and expect it to be overwritten/truncated + init_file(filename, "filecount=0"); + assert(file_exists(filename), "couldn't find log file: %s", filename); + + init_file(filename, "filecount=0"); + assert(file_exists(filename), "couldn't find log file: %s", filename); + assert(!file_exists(archived_filename), + "existing log file %s was not properly truncated when filecount was 0", + filename); + + // Verify that the file was really truncated and not just appended + assert(number_of_lines_with_substring_in_file(filename, ExpectedLine) == 1, + "log file %s appended rather than truncated", filename); + + delete_file(filename); + delete_file(archived_filename); +} + static int Test_logconfiguration_subscribe_triggered = 0; static void Test_logconfiguration_subscribe_helper() { @@ -361,11 +496,32 @@ static void Test_logstream_no_rm() { Test_logstream_helper(stream); } +static void Test_logstreamcheap_log() { + Log(gc) log; + LogStreamCHeap stream(log.debug()); + + Test_logstream_helper(&stream); +} + +static void Test_logstreamcheap_logtarget() { + LogTarget(Debug, gc) log; + LogStreamCHeap stream(log); + + Test_logstream_helper(&stream); +} + void Test_logstream() { + // Test LogStreams with embedded ResourceMark. Test_logstream_log(); Test_logstream_logtarget(); Test_logstream_logstreamhandle(); + + // Test LogStreams without embedded ResourceMark. Test_logstream_no_rm(); + + // Test LogStreams backed by CHeap memory. + Test_logstreamcheap_log(); + Test_logstreamcheap_logtarget(); } void Test_loghandle_on() { @@ -377,7 +533,7 @@ void Test_loghandle_on() { assert(log_handle.is_debug(), "assert"); - // Try to log trough a LogHandle. + // Try to log through a LogHandle. log_handle.debug("%d workers", 3); FILE* fp = fopen(log_file.name(), "r"); @@ -408,7 +564,7 @@ void Test_loghandle_off() { return; } - // Try to log trough a LogHandle. Should fail, since only info is turned on. + // Try to log through a LogHandle. Should fail, since only info is turned on. log_handle.debug("%d workers", 3); // Log a dummy line so that fgets doesn't return NULL because the file is empty. @@ -440,7 +596,7 @@ static void Test_logtargethandle_on() { assert(log_handle.is_enabled(), "assert"); - // Try to log trough a LogHandle. + // Try to log through a LogHandle. log_handle.print("%d workers", 3); FILE* fp = fopen(log_file.name(), "r"); @@ -471,7 +627,7 @@ static void Test_logtargethandle_off() { return; } - // Try to log trough a LogHandle. Should fail, since only info is turned on. + // Try to log through a LogHandle. Should fail, since only info is turned on. log_handle.print("%d workers", 3); // Log a dummy line so that fgets doesn't return NULL because the file is empty. @@ -711,4 +867,20 @@ void Test_log_gctracetime() { Test_log_gctracetime_no_heap_no_cause(); } +void Test_invalid_log_file() { + ResourceMark rm; + stringStream ss; + const char* target_name = "tmplogdir"; + + // Attempt to log to a directory (existing log not a regular file) + create_directory(target_name); + LogFileOutput bad_file("tmplogdir"); + assert(bad_file.initialize("", &ss) == false, "file was initialized " + "when there was an existing directory with the same name"); + assert(strstr(ss.as_string(), "tmplogdir is not a regular file") != NULL, + "missing expected error message, received msg: %s", ss.as_string()); + ss.reset(); + remove(target_name); +} + #endif // PRODUCT diff --git a/hotspot/src/share/vm/logging/logConfiguration.cpp b/hotspot/src/share/vm/logging/logConfiguration.cpp index 67b63b782d9ad449c6496608d6c481a8903b12c4..6f9f7bb2a278c90f0582a4c8f02846d78828124d 100644 --- a/hotspot/src/share/vm/logging/logConfiguration.cpp +++ b/hotspot/src/share/vm/logging/logConfiguration.cpp @@ -145,7 +145,7 @@ LogOutput* LogConfiguration::new_output(char* name, const char* options, outputS return NULL; } - bool success = output->initialize(options); + bool success = output->initialize(options, errstream); if (!success) { errstream->print_cr("Initialization of output '%s' using options '%s' failed.", name, options); delete output; diff --git a/hotspot/src/share/vm/logging/logFileOutput.cpp b/hotspot/src/share/vm/logging/logFileOutput.cpp index 4084d5d2ce18543b307a0459d8cd8f83c248e01a..7f41bd995fb7f120e6cbe19a97bb87fe4a41157e 100644 --- a/hotspot/src/share/vm/logging/logFileOutput.cpp +++ b/hotspot/src/share/vm/logging/logFileOutput.cpp @@ -41,8 +41,9 @@ char LogFileOutput::_vm_start_time_str[StartTimeBufferSize]; LogFileOutput::LogFileOutput(const char* name) : LogFileStreamOutput(NULL), _name(os::strdup_check_oom(name, mtLogging)), - _file_name(NULL), _archive_name(NULL), _archive_name_len(0), _current_size(0), - _rotate_size(0), _current_file(1), _file_count(0), _rotation_semaphore(1) { + _file_name(NULL), _archive_name(NULL), _archive_name_len(0), + _rotate_size(DefaultFileSize), _file_count(DefaultFileCount), + _current_size(0), _current_file(0), _rotation_semaphore(1) { _file_name = make_file_name(name, _pid_str, _vm_start_time_str); } @@ -59,9 +60,6 @@ void LogFileOutput::set_file_name_parameters(jlong vm_start_time) { LogFileOutput::~LogFileOutput() { if (_stream != NULL) { - if (_archive_name != NULL) { - archive(); - } if (fclose(_stream) != 0) { jio_fprintf(defaultStream::error_stream(), "Could not close log file '%s' (%s).\n", _file_name, os::strerror(errno)); @@ -72,7 +70,7 @@ LogFileOutput::~LogFileOutput() { os::free(const_cast(_name)); } -size_t LogFileOutput::parse_value(const char* value_str) { +static size_t parse_value(const char* value_str) { char* end; unsigned long long value = strtoull(value_str, &end, 10); if (!isdigit(*value_str) || end != value_str + strlen(value_str) || value >= SIZE_MAX) { @@ -81,7 +79,80 @@ size_t LogFileOutput::parse_value(const char* value_str) { return value; } -bool LogFileOutput::configure_rotation(const char* options) { +static bool file_exists(const char* filename) { + struct stat dummy_stat; + return os::stat(filename, &dummy_stat) == 0; +} + +static uint number_of_digits(uint number) { + return number < 10 ? 1 : (number < 100 ? 2 : 3); +} + +static bool is_regular_file(const char* filename) { + struct stat st; + int ret = os::stat(filename, &st); + if (ret != 0) { + return false; + } +#ifdef _WINDOWS + return (st.st_mode & S_IFMT) == _S_IFREG; +#else + return S_ISREG(st.st_mode); +#endif +} + +// Try to find the next number that should be used for file rotation. +// Return UINT_MAX on error. +static uint next_file_number(const char* filename, + uint number_of_digits, + uint filecount, + outputStream* errstream) { + bool found = false; + uint next_num = 0; + + // len is filename + dot + digits + null char + size_t len = strlen(filename) + number_of_digits + 2; + char* archive_name = NEW_C_HEAP_ARRAY(char, len, mtLogging); + char* oldest_name = NEW_C_HEAP_ARRAY(char, len, mtLogging); + + for (uint i = 0; i < filecount; i++) { + int ret = jio_snprintf(archive_name, len, "%s.%0*u", + filename, number_of_digits, i); + assert(ret > 0 && static_cast(ret) == len - 1, + "incorrect buffer length calculation"); + + if (file_exists(archive_name) && !is_regular_file(archive_name)) { + // We've encountered something that's not a regular file among the + // possible file rotation targets. Fail immediately to prevent + // problems later. + errstream->print_cr("Possible rotation target file '%s' already exists " + "but is not a regular file.", archive_name); + next_num = UINT_MAX; + break; + } + + // Stop looking if we find an unused file name + if (!file_exists(archive_name)) { + next_num = i; + found = true; + break; + } + + // Keep track of oldest existing log file + if (!found + || os::compare_file_modified_times(oldest_name, archive_name) > 0) { + strcpy(oldest_name, archive_name); + next_num = i; + found = true; + } + } + + FREE_C_HEAP_ARRAY(char, oldest_name); + FREE_C_HEAP_ARRAY(char, archive_name); + return next_num; +} + +bool LogFileOutput::parse_options(const char* options, outputStream* errstream) { if (options == NULL || strlen(options) == 0) { return true; } @@ -107,22 +178,25 @@ bool LogFileOutput::configure_rotation(const char* options) { if (strcmp(FileCountOptionKey, key) == 0) { size_t value = parse_value(value_str); - if (value == SIZE_MAX || value >= UINT_MAX) { + if (value > MaxRotationFileCount) { + errstream->print_cr("Invalid option: %s must be in range [0, %u]", + FileCountOptionKey, + MaxRotationFileCount); success = false; break; } _file_count = static_cast(value); - _file_count_max_digits = static_cast(log10(static_cast(_file_count)) + 1); - _archive_name_len = 2 + strlen(_file_name) + _file_count_max_digits; - _archive_name = NEW_C_HEAP_ARRAY(char, _archive_name_len, mtLogging); } else if (strcmp(FileSizeOptionKey, key) == 0) { size_t value = parse_value(value_str); if (value == SIZE_MAX || value > SIZE_MAX / K) { + errstream->print_cr("Invalid option: %s must be in range [0, " + SIZE_FORMAT "]", FileSizeOptionKey, SIZE_MAX / K); success = false; break; } _rotate_size = value * K; } else { + errstream->print_cr("Invalid option '%s' for log file output.", key); success = false; break; } @@ -133,15 +207,54 @@ bool LogFileOutput::configure_rotation(const char* options) { return success; } -bool LogFileOutput::initialize(const char* options) { - if (!configure_rotation(options)) { +bool LogFileOutput::initialize(const char* options, outputStream* errstream) { + if (!parse_options(options, errstream)) { return false; } + + if (_file_count > 0) { + // compute digits with filecount - 1 since numbers will start from 0 + _file_count_max_digits = number_of_digits(_file_count - 1); + _archive_name_len = 2 + strlen(_file_name) + _file_count_max_digits; + _archive_name = NEW_C_HEAP_ARRAY(char, _archive_name_len, mtLogging); + } + + log_trace(logging)("Initializing logging to file '%s' (filecount: %u" + ", filesize: " SIZE_FORMAT " KiB).", + _file_name, _file_count, _rotate_size / K); + + if (_file_count > 0 && file_exists(_file_name)) { + if (!is_regular_file(_file_name)) { + errstream->print_cr("Unable to log to file %s with log file rotation: " + "%s is not a regular file", + _file_name, _file_name); + return false; + } + _current_file = next_file_number(_file_name, + _file_count_max_digits, + _file_count, + errstream); + if (_current_file == UINT_MAX) { + return false; + } + log_trace(logging)("Existing log file found, saving it as '%s.%0*u'", + _file_name, _file_count_max_digits, _current_file); + archive(); + increment_file_count(); + } + _stream = fopen(_file_name, FileOpenMode); if (_stream == NULL) { - log_error(logging)("Could not open log file '%s' (%s).\n", _file_name, os::strerror(errno)); + errstream->print_cr("Error opening log file '%s': %s", + _file_name, strerror(errno)); return false; } + + if (_file_count == 0 && is_regular_file(_file_name)) { + log_trace(logging)("Truncating log file"); + os::ftruncate(os::fileno(_stream), 0); + } + return true; } @@ -210,7 +323,7 @@ void LogFileOutput::rotate() { // Reset accumulated size, increase current file counter, and check for file count wrap-around. _current_size = 0; - _current_file = (_current_file >= _file_count ? 1 : _current_file + 1); + increment_file_count(); } char* LogFileOutput::make_file_name(const char* file_name, diff --git a/hotspot/src/share/vm/logging/logFileOutput.hpp b/hotspot/src/share/vm/logging/logFileOutput.hpp index 935a176a5e3c92c74e5a2b6500b1e135a0a597fd..adfd3722cefaad173415d90c1d4d425a47d3e5f1 100644 --- a/hotspot/src/share/vm/logging/logFileOutput.hpp +++ b/hotspot/src/share/vm/logging/logFileOutput.hpp @@ -39,8 +39,11 @@ class LogFileOutput : public LogFileStreamOutput { static const char* PidFilenamePlaceholder; static const char* TimestampFilenamePlaceholder; static const char* TimestampFormat; + static const size_t DefaultFileCount = 5; + static const size_t DefaultFileSize = 20 * M; static const size_t StartTimeBufferSize = 20; - static const size_t PidBufferSize = 21; + static const size_t PidBufferSize = 21; + static const uint MaxRotationFileCount = 1000; static char _pid_str[PidBufferSize]; static char _vm_start_time_str[StartTimeBufferSize]; @@ -61,18 +64,24 @@ class LogFileOutput : public LogFileStreamOutput { void archive(); void rotate(); - bool configure_rotation(const char* options); + bool parse_options(const char* options, outputStream* errstream); char *make_file_name(const char* file_name, const char* pid_string, const char* timestamp_string); - static size_t parse_value(const char* value_str); bool should_rotate() { return _file_count > 0 && _rotate_size > 0 && _current_size >= _rotate_size; } + void increment_file_count() { + _current_file++; + if (_current_file == _file_count) { + _current_file = 0; + } + } + public: LogFileOutput(const char *name); virtual ~LogFileOutput(); - virtual bool initialize(const char* options); + virtual bool initialize(const char* options, outputStream* errstream); virtual int write(const LogDecorations& decorations, const char* msg); virtual void force_rotate(); diff --git a/hotspot/src/share/vm/logging/logFileStreamOutput.hpp b/hotspot/src/share/vm/logging/logFileStreamOutput.hpp index 9c4ddf7b9c5e5d2a36b6e90cc0c02aec29206826..a4c739cfcfa0669daaea7d538d3fdc72d98e759c 100644 --- a/hotspot/src/share/vm/logging/logFileStreamOutput.hpp +++ b/hotspot/src/share/vm/logging/logFileStreamOutput.hpp @@ -53,7 +53,7 @@ class LogStdoutOutput : public LogFileStreamOutput { LogStdoutOutput() : LogFileStreamOutput(stdout) { set_config_string("all=off"); } - virtual bool initialize(const char* options) { + virtual bool initialize(const char* options, outputStream* errstream) { return false; } public: @@ -69,7 +69,7 @@ class LogStderrOutput : public LogFileStreamOutput { LogStderrOutput() : LogFileStreamOutput(stderr) { set_config_string("all=warning"); } - virtual bool initialize(const char* options) { + virtual bool initialize(const char* options, outputStream* errstream) { return false; } public: diff --git a/hotspot/src/share/vm/logging/logHandle.hpp b/hotspot/src/share/vm/logging/logHandle.hpp index 1f62d96e6f9d5b45bbc096e7031d5f17e45f8e6d..41d20609a7387d5c7b92547c16988c236ee2b91e 100644 --- a/hotspot/src/share/vm/logging/logHandle.hpp +++ b/hotspot/src/share/vm/logging/logHandle.hpp @@ -67,13 +67,13 @@ public: // This can be used to pass a Log instance as a parameter without // polluting the surrounding API with template functions. class LogTargetHandle { - friend class LogStream; - private: const LogLevelType _level; LogTagSet* _tagset; public: + LogTargetHandle(LogLevelType level, LogTagSet* tagset) : _level(level), _tagset(tagset) {} + template LogTargetHandle(const LogTargetImpl& type_carrier) : _level(level), diff --git a/hotspot/src/share/vm/logging/logOutput.hpp b/hotspot/src/share/vm/logging/logOutput.hpp index 1ca598c357fa7b5cff9acd5aaf8ab4dba77bf1ca..5f06f388efd3bf01d8871e99ee0d315aaf3034a2 100644 --- a/hotspot/src/share/vm/logging/logOutput.hpp +++ b/hotspot/src/share/vm/logging/logOutput.hpp @@ -82,7 +82,7 @@ class LogOutput : public CHeapObj { } virtual const char* name() const = 0; - virtual bool initialize(const char* options) = 0; + virtual bool initialize(const char* options, outputStream* errstream) = 0; virtual int write(const LogDecorations &decorations, const char* msg) = 0; }; diff --git a/hotspot/src/share/vm/logging/logPrefix.hpp b/hotspot/src/share/vm/logging/logPrefix.hpp index 48d342d1ba89e6278bb6665ebb9998644197d9dc..8d2ae12adf3850cb085668fb792b0423f9c1d6c1 100644 --- a/hotspot/src/share/vm/logging/logPrefix.hpp +++ b/hotspot/src/share/vm/logging/logPrefix.hpp @@ -55,6 +55,7 @@ DEBUG_ONLY(size_t Test_log_prefix_prefixer(char* buf, size_t len);) LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, ergo, cset)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, ergo, heap)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, ergo, ihop)) \ + LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, ergo, refine)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, heap)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, heap, region)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, freelist)) \ diff --git a/hotspot/src/share/vm/logging/logStream.cpp b/hotspot/src/share/vm/logging/logStream.cpp index b68dca7f056754f59908d7ceaaa8eff703728d6e..5c980a7b2ce13ed2cf2df5b522eded5525b19398 100644 --- a/hotspot/src/share/vm/logging/logStream.cpp +++ b/hotspot/src/share/vm/logging/logStream.cpp @@ -24,7 +24,7 @@ #include "precompiled.hpp" #include "logging/log.hpp" -#include "logging/logStream.hpp" +#include "logging/logStream.inline.hpp" // Create a log stream without an embedded ResourceMark. // The function is placed here to be called out-of-line in log.hpp. diff --git a/hotspot/src/share/vm/logging/logStream.hpp b/hotspot/src/share/vm/logging/logStream.hpp index 38ba83ab3eeefacb834c2e72933a579268681423..6e7a28ac5d2657763becfec4363e9fbe197027f8 100644 --- a/hotspot/src/share/vm/logging/logStream.hpp +++ b/hotspot/src/share/vm/logging/logStream.hpp @@ -26,23 +26,100 @@ #define SHARE_VM_LOGGING_LOGSTREAM_HPP #include "logging/log.hpp" +#include "logging/logHandle.hpp" +#include "memory/resourceArea.hpp" #include "utilities/ostream.hpp" -// An output stream that logs to the logging framework. -// Requires a ResourceMark on the stack. -class LogStreamNoResourceMark : public outputStream { -private: - stringStream _current_line; - LogLevelType _level; - LogTagSet* _tagset; +// The base class of an output stream that logs to the logging framework. +template +class LogStreamBase : public outputStream { + streamClass _current_line; + LogTargetHandle _log_handle; public: - LogStreamNoResourceMark(LogLevelType level, LogTagSet* tagset) : _level(level), _tagset(tagset) {} - ~LogStreamNoResourceMark() { + // Constructor to support creation from a LogTarget instance. + // + // LogTarget(Debug, gc) log; + // LogStreamBase(log) stream; + template + LogStreamBase(const LogTargetImpl& type_carrier) : + _log_handle(level, &LogTagSetMapping::tagset()) {} + + // Constructor to support creation from typed (likely NULL) pointer. Mostly used by the logging framework. + // + // LogStreamBase stream(log.debug()); + // or + // LogStreamBase stream((LogTargetImpl*)NULL); + template + LogStreamBase(const LogTargetImpl* type_carrier) : + _log_handle(level, &LogTagSetMapping::tagset()) {} + + // Constructor to support creation from a LogTargetHandle. + // + // LogTarget(Debug, gc) log; + // LogTargetHandle(log) handle; + // LogStreamBase stream(handle); + LogStreamBase(LogTargetHandle handle) : _log_handle(handle) {} + + // Constructor to support creation from a log level and tagset. + // + // LogStreamBase(level, tageset); + LogStreamBase(LogLevelType level, LogTagSet* tagset) : _log_handle(level, tagset) {} + + ~LogStreamBase() { guarantee(_current_line.size() == 0, "Buffer not flushed. Missing call to print_cr()?"); } +public: void write(const char* s, size_t len); }; +// A stringStream with an embedded ResourceMark. +class stringStreamWithResourceMark : outputStream { + private: + // The stringStream Resource allocate in the constructor, + // so the order of the fields is important. + ResourceMark _embedded_resource_mark; + stringStream _stream; + + public: + stringStreamWithResourceMark(size_t initial_bufsize = 256) : + _embedded_resource_mark(), + _stream(initial_bufsize) {} + + virtual void write(const char* c, size_t len) { _stream.write(c, len); } + size_t size() { return _stream.size(); } + const char* base() { return _stream.base(); } + void reset() { _stream.reset(); } + char* as_string() { return _stream.as_string(); } +}; + +// An output stream that logs to the logging framework. +// +// The backing buffer is allocated in Resource memory. +// The caller is required to have a ResourceMark on the stack. +typedef LogStreamBase LogStreamNoResourceMark; + +// An output stream that logs to the logging framework. +// +// The backing buffer is allocated in CHeap memory. +typedef LogStreamBase LogStreamCHeap; + +// An output stream that logs to the logging framework, and embeds a ResourceMark. +// +// The backing buffer is allocated in Resource memory. +// The class is intended to be stack allocated. +// The class provides its own ResourceMark, +// so care needs to be taken when nested ResourceMarks are used. +typedef LogStreamBase LogStream; + +// Support creation of a LogStream without having to provide a LogTarget pointer. +#define LogStreamHandle(level, ...) LogStreamTemplate + +template +class LogStreamTemplate : public LogStream { +public: + LogStreamTemplate() : LogStream((LogTargetImpl*)NULL) {} +}; + #endif // SHARE_VM_LOGGING_LOGSTREAM_HPP diff --git a/hotspot/src/share/vm/logging/logStream.inline.hpp b/hotspot/src/share/vm/logging/logStream.inline.hpp index b1bff8b53bdda3a72a230f697741f5eda93c92a2..5660a5616bb79cb5a231d1660afa25353563b204 100644 --- a/hotspot/src/share/vm/logging/logStream.inline.hpp +++ b/hotspot/src/share/vm/logging/logStream.inline.hpp @@ -30,10 +30,12 @@ #include "memory/resourceArea.hpp" #include "utilities/ostream.hpp" -inline void LogStreamNoResourceMark::write(const char* s, size_t len) { +template +inline void LogStreamBase::write(const char* s, size_t len) { if (len > 0 && s[len - 1] == '\n') { _current_line.write(s, len - 1); - _tagset->write(_level, "%s", _current_line.as_string()); + _current_line.write("\0", 1); + _log_handle.print("%s", _current_line.base()); _current_line.reset(); } else { _current_line.write(s, len); @@ -41,54 +43,4 @@ inline void LogStreamNoResourceMark::write(const char* s, size_t len) { update_position(s, len); } -// An output stream that logs to the logging framework, and embeds a ResourceMark. -// -// The class is intended to be stack allocated. -// Care needs to be taken when nested ResourceMarks are used. -class LogStream : public outputStream { -private: - ResourceMark _embedded_resource_mark; - LogStreamNoResourceMark _stream; - -public: - // Constructor to support creation from a LogTarget instance. - // - // LogTarget(Debug, gc) log; - // LogStream(log) stream; - template - LogStream(const LogTargetImpl& type_carrier) : - _embedded_resource_mark(), - _stream(level, &LogTagSetMapping::tagset()) {} - - // Constructor to support creation from typed (likely NULL) pointer. Mostly used by the logging framework. - // - // LogStream stream(log.debug()); - // LogStream stream((LogTargetImpl*)NULL); - template - LogStream(const LogTargetImpl* type_carrier) : - _embedded_resource_mark(), - _stream(level, &LogTagSetMapping::tagset()) {} - - // Constructor to support creation from a LogTargetHandle. - // - // LogTarget(Debug, gc) log; - // LogTargetHandle(log) handle; - // LogStream stream(handle); - LogStream(LogTargetHandle handle) : - _embedded_resource_mark(), - _stream(handle._level, handle._tagset) {} - - // Override of outputStream::write. - void write(const char* s, size_t len) { _stream.write(s, len); } -}; - -// Support creation of a LogStream without having to provide a LogTarget pointer. -#define LogStreamHandle(level, ...) LogStreamTemplate - -template -class LogStreamTemplate : public LogStream { -public: - LogStreamTemplate() : LogStream((LogTargetImpl*)NULL) {} -}; - #endif // SHARE_VM_LOGGING_LOGSTREAM_INLINE_HPP diff --git a/hotspot/src/share/vm/logging/logTag.hpp b/hotspot/src/share/vm/logging/logTag.hpp index 78cb944c345ab53d9519b4fda7a83fad6ba10b34..ede507df24230ed86eebeb3a22cac0af50bddb9d 100644 --- a/hotspot/src/share/vm/logging/logTag.hpp +++ b/hotspot/src/share/vm/logging/logTag.hpp @@ -48,6 +48,7 @@ LOG_TAG(classpath) \ LOG_TAG(compaction) \ LOG_TAG(constraints) \ + LOG_TAG(coops) \ LOG_TAG(cpu) \ LOG_TAG(cset) \ LOG_TAG(defaultmethods) \ @@ -69,6 +70,7 @@ LOG_TAG(monitorinflation) \ LOG_TAG(monitormismatch) \ LOG_TAG(os) \ + LOG_TAG(pagesize) \ LOG_TAG(phases) \ LOG_TAG(plab) \ LOG_TAG(promotion) \ diff --git a/hotspot/src/share/vm/logging/logTagLevelExpression.hpp b/hotspot/src/share/vm/logging/logTagLevelExpression.hpp index 1eb27f0751706b55c2671900933435eaebc7a54e..9a0d7c9cd7972390286465e86691492ee3f82efe 100644 --- a/hotspot/src/share/vm/logging/logTagLevelExpression.hpp +++ b/hotspot/src/share/vm/logging/logTagLevelExpression.hpp @@ -36,9 +36,12 @@ class LogTagSet; // Class used to temporary encode a 'what'-expression during log configuration. // Consists of a combination of tags and levels, e.g. "tag1+tag2=level1,tag3*=level2". class LogTagLevelExpression : public StackObj { - friend void LogConfiguration::configure_stdout(LogLevelType, bool, ...); + public: + static const size_t MaxCombinations = 256; + private: - static const size_t MaxCombinations = 32; + friend void LogConfiguration::configure_stdout(LogLevelType, bool, ...); + static const char* DefaultExpressionString; size_t _ntags, _ncombinations; diff --git a/hotspot/src/share/vm/logging/logTagSet.cpp b/hotspot/src/share/vm/logging/logTagSet.cpp index db675a268541779cc9983af9e7071557703be0de..96aae628857af39e827fb52d01559e6532e13382 100644 --- a/hotspot/src/share/vm/logging/logTagSet.cpp +++ b/hotspot/src/share/vm/logging/logTagSet.cpp @@ -98,6 +98,7 @@ void LogTagSet::write(LogLevelType level, const char* fmt, ...) { const size_t vwrite_buffer_size = 512; void LogTagSet::vwrite(LogLevelType level, const char* fmt, va_list args) { + assert(level >= LogLevel::First && level <= LogLevel::Last, "Log level:%d is incorrect", level); char buf[vwrite_buffer_size]; va_list saved_args; // For re-format on buf overflow. va_copy(saved_args, args); diff --git a/hotspot/src/share/vm/logging/logTagSet.hpp b/hotspot/src/share/vm/logging/logTagSet.hpp index 7b193fc9751e8082846828d608f47f42709bc9a2..60080700d7973e24b12faa45dce7fd97990440d5 100644 --- a/hotspot/src/share/vm/logging/logTagSet.hpp +++ b/hotspot/src/share/vm/logging/logTagSet.hpp @@ -64,6 +64,10 @@ class LogTagSet VALUE_OBJ_CLASS_SPEC { return _list; } + static size_t ntagsets() { + return _ntagsets; + } + LogTagSet* next() { return _next; } diff --git a/hotspot/src/share/vm/memory/allocation.hpp b/hotspot/src/share/vm/memory/allocation.hpp index 2705c6d8994d9bcd3c3afdea402930930aecc19a..ec0e53977d63b22737b918943975b9f9b1905636 100644 --- a/hotspot/src/share/vm/memory/allocation.hpp +++ b/hotspot/src/share/vm/memory/allocation.hpp @@ -143,8 +143,9 @@ enum MemoryType { mtTest = 0x0D, // Test type for verifying NMT mtTracing = 0x0E, // memory used for Tracing mtLogging = 0x0F, // memory for logging - mtNone = 0x10, // undefined - mt_number_of_types = 0x11 // number of memory types (mtDontTrack + mtArguments = 0x10, // memory for argument processing + mtNone = 0x11, // undefined + mt_number_of_types = 0x12 // number of memory types (mtDontTrack // is not included as validate type) }; diff --git a/hotspot/src/share/vm/memory/filemap.cpp b/hotspot/src/share/vm/memory/filemap.cpp index 606b7bd696041aeb737c22c2820c5d5ea3f8013e..ec3b946295988f9c68f143bff87fbe13a68bcd7c 100644 --- a/hotspot/src/share/vm/memory/filemap.cpp +++ b/hotspot/src/share/vm/memory/filemap.cpp @@ -959,6 +959,16 @@ bool FileMapInfo::is_in_shared_space(const void* p) { return false; } +// Check if a given address is within one of the shared regions (ro, rw, md, mc) +bool FileMapInfo::is_in_shared_region(const void* p, int idx) { + assert((idx >= MetaspaceShared::ro) && (idx <= MetaspaceShared::mc), "invalid region index"); + char* base = _header->region_addr(idx); + if (p >= base && p < base + _header->_space[idx]._used) { + return true; + } + return false; +} + void FileMapInfo::print_shared_spaces() { tty->print_cr("Shared Spaces:"); for (int i = 0; i < MetaspaceShared::n_regions; i++) { diff --git a/hotspot/src/share/vm/memory/filemap.hpp b/hotspot/src/share/vm/memory/filemap.hpp index 7cb179434b9d716155259a387729269da2a32c59..2c02b427f0b0a4ce2994ceef14c219d0bc7c6ba5 100644 --- a/hotspot/src/share/vm/memory/filemap.hpp +++ b/hotspot/src/share/vm/memory/filemap.hpp @@ -107,6 +107,8 @@ public: int _narrow_klass_shift; // save narrow klass base and shift address _narrow_klass_base; char* _misc_data_patching_start; + address _cds_i2i_entry_code_buffers; + size_t _cds_i2i_entry_code_buffers_size; struct space_info { int _crc; // crc checksum of the current space @@ -195,6 +197,19 @@ public: char* misc_data_patching_start() { return _header->_misc_data_patching_start; } void set_misc_data_patching_start(char* p) { _header->_misc_data_patching_start = p; } + address cds_i2i_entry_code_buffers() { + return _header->_cds_i2i_entry_code_buffers; + } + void set_cds_i2i_entry_code_buffers(address addr) { + _header->_cds_i2i_entry_code_buffers = addr; + } + size_t cds_i2i_entry_code_buffers_size() { + return _header->_cds_i2i_entry_code_buffers_size; + } + void set_cds_i2i_entry_code_buffers_size(size_t s) { + _header->_cds_i2i_entry_code_buffers_size = s; + } + static FileMapInfo* current_info() { CDS_ONLY(return _current_info;) NOT_CDS(return NULL;) @@ -234,6 +249,7 @@ public: // Return true if given address is in the mapped shared space. bool is_in_shared_space(const void* p) NOT_CDS_RETURN_(false); + bool is_in_shared_region(const void* p, int idx) NOT_CDS_RETURN_(false); void print_shared_spaces() NOT_CDS_RETURN; static size_t shared_spaces_size() { diff --git a/hotspot/src/share/vm/memory/iterator.hpp b/hotspot/src/share/vm/memory/iterator.hpp index 6d7d9d4fece1d2459b75c292bd252d4e1c757334..3a36dc6d5f5aea9c3a8f8ba0420c20f8494dd292 100644 --- a/hotspot/src/share/vm/memory/iterator.hpp +++ b/hotspot/src/share/vm/memory/iterator.hpp @@ -27,7 +27,7 @@ #include "memory/allocation.hpp" #include "memory/memRegion.hpp" -#include "utilities/top.hpp" +#include "oops/oopsHierarchy.hpp" class CodeBlob; class nmethod; @@ -35,6 +35,7 @@ class ReferenceProcessor; class DataLayout; class KlassClosure; class ClassLoaderData; +class Symbol; // The following classes are C++ `closures` for iterating over objects, roots and spaces diff --git a/hotspot/src/share/vm/memory/metaspaceShared.cpp b/hotspot/src/share/vm/memory/metaspaceShared.cpp index 36efacfc4abf5d9bf412bd01df8bea438acc246a..fa4d31a54bed8fd5193995f640dbae1c6d6c363e 100644 --- a/hotspot/src/share/vm/memory/metaspaceShared.cpp +++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp @@ -59,6 +59,8 @@ bool MetaspaceShared::_link_classes_made_progress; bool MetaspaceShared::_check_classes_made_progress; bool MetaspaceShared::_has_error_classes; bool MetaspaceShared::_archive_loading_failed = false; +address MetaspaceShared::_cds_i2i_entry_code_buffers = NULL; +size_t MetaspaceShared::_cds_i2i_entry_code_buffers_size = 0; SharedMiscRegion MetaspaceShared::_mc; SharedMiscRegion MetaspaceShared::_md; @@ -129,6 +131,21 @@ void MetaspaceShared::serialize(SerializeClosure* soc) { soc->do_tag(666); } +address MetaspaceShared::cds_i2i_entry_code_buffers(size_t total_size) { + if (DumpSharedSpaces) { + if (_cds_i2i_entry_code_buffers == NULL) { + _cds_i2i_entry_code_buffers = (address)misc_data_space_alloc(total_size); + _cds_i2i_entry_code_buffers_size = total_size; + } + } else if (UseSharedSpaces) { + assert(_cds_i2i_entry_code_buffers != NULL, "must already been initialized"); + } else { + return NULL; + } + + assert(_cds_i2i_entry_code_buffers_size == total_size, "must not change"); + return _cds_i2i_entry_code_buffers; +} // CDS code for dumping shared archive. @@ -576,6 +593,8 @@ void VM_PopulateDumpSharedSpace::doit() { &md_top, md_end, &mc_top, mc_end); + guarantee(md_top <= md_end, "Insufficient space for vtables."); + // Reorder the system dictionary. (Moving the symbols affects // how the hash table indices are calculated.) // Not doing this either. @@ -668,6 +687,8 @@ void VM_PopulateDumpSharedSpace::doit() { FileMapInfo* mapinfo = new FileMapInfo(); mapinfo->populate_header(MetaspaceShared::max_alignment()); mapinfo->set_misc_data_patching_start((char*)vtbl_list); + mapinfo->set_cds_i2i_entry_code_buffers(MetaspaceShared::cds_i2i_entry_code_buffers()); + mapinfo->set_cds_i2i_entry_code_buffers_size(MetaspaceShared::cds_i2i_entry_code_buffers_size()); for (int pass=1; pass<=2; pass++) { if (pass == 1) { @@ -686,7 +707,7 @@ void VM_PopulateDumpSharedSpace::doit() { mapinfo->write_region(MetaspaceShared::md, _md_vs.low(), pointer_delta(md_top, _md_vs.low(), sizeof(char)), SharedMiscDataSize, - false, false); + false, true); mapinfo->write_region(MetaspaceShared::mc, _mc_vs.low(), pointer_delta(mc_top, _mc_vs.low(), sizeof(char)), SharedMiscCodeSize, @@ -980,6 +1001,11 @@ bool MetaspaceShared::is_in_shared_space(const void* p) { return UseSharedSpaces && FileMapInfo::current_info()->is_in_shared_space(p); } +// Return true if given address is in the misc data region +bool MetaspaceShared::is_in_shared_region(const void* p, int idx) { + return UseSharedSpaces && FileMapInfo::current_info()->is_in_shared_region(p, idx); +} + bool MetaspaceShared::is_string_region(int idx) { return (idx >= MetaspaceShared::first_string && idx < MetaspaceShared::first_string + MetaspaceShared::max_strings); @@ -1053,6 +1079,8 @@ bool MetaspaceShared::map_shared_spaces(FileMapInfo* mapinfo) { void MetaspaceShared::initialize_shared_spaces() { FileMapInfo *mapinfo = FileMapInfo::current_info(); + _cds_i2i_entry_code_buffers = mapinfo->cds_i2i_entry_code_buffers(); + _cds_i2i_entry_code_buffers_size = mapinfo->cds_i2i_entry_code_buffers_size(); char* buffer = mapinfo->misc_data_patching_start(); // Skip over (reserve space for) a list of addresses of C++ vtables diff --git a/hotspot/src/share/vm/memory/metaspaceShared.hpp b/hotspot/src/share/vm/memory/metaspaceShared.hpp index c78f78122cfce059166fe113d59425349942152b..e759464591d1350f608a7c9ae69b505c6e8808ea 100644 --- a/hotspot/src/share/vm/memory/metaspaceShared.hpp +++ b/hotspot/src/share/vm/memory/metaspaceShared.hpp @@ -50,17 +50,14 @@ #define MIN_SHARED_READ_ONLY_SIZE (NOT_LP64(8*M) LP64_ONLY(9*M)) // the MIN_SHARED_MISC_DATA_SIZE and MIN_SHARED_MISC_CODE_SIZE estimates are based on -// MetaspaceShared::generate_vtable_methods(). -// The minimum size only accounts for the vtable methods. Any size less than the -// minimum required size would cause vm crash when allocating the vtable methods. -#define SHARED_MISC_SIZE_FOR(size) (DEFAULT_VTBL_VIRTUALS_COUNT*DEFAULT_VTBL_LIST_SIZE*size) +// the sizes required for dumping the archive using the default classlist. The sizes +// are multiplied by 1.5 for a safety margin. #define DEFAULT_SHARED_MISC_DATA_SIZE (NOT_LP64(2*M) LP64_ONLY(4*M)) -#define MIN_SHARED_MISC_DATA_SIZE (SHARED_MISC_SIZE_FOR(sizeof(void*))) +#define MIN_SHARED_MISC_DATA_SIZE (NOT_LP64(1*M) LP64_ONLY(1200*K)) #define DEFAULT_SHARED_MISC_CODE_SIZE (120*K) -#define MIN_SHARED_MISC_CODE_SIZE (SHARED_MISC_SIZE_FOR(sizeof(void*))+SHARED_MISC_SIZE_FOR(DEFAULT_VTBL_METHOD_SIZE)+DEFAULT_VTBL_COMMON_CODE_SIZE) - +#define MIN_SHARED_MISC_CODE_SIZE (NOT_LP64(63*K) LP64_ONLY(69*K)) #define DEFAULT_COMBINED_SIZE (DEFAULT_SHARED_READ_WRITE_SIZE+DEFAULT_SHARED_READ_ONLY_SIZE+DEFAULT_SHARED_MISC_DATA_SIZE+DEFAULT_SHARED_MISC_CODE_SIZE) // the max size is the MAX size (ie. 0x7FFFFFFF) - the total size of @@ -128,6 +125,8 @@ class MetaspaceShared : AllStatic { static bool _check_classes_made_progress; static bool _has_error_classes; static bool _archive_loading_failed; + static address _cds_i2i_entry_code_buffers; + static size_t _cds_i2i_entry_code_buffers_size; // Used only during dumping. static SharedMiscRegion _md; @@ -185,6 +184,9 @@ class MetaspaceShared : AllStatic { // Return true if given address is in the mapped shared space. static bool is_in_shared_space(const void* p) NOT_CDS_RETURN_(false); + // Return true if given address is in the shared region corresponding to the idx + static bool is_in_shared_region(const void* p, int idx) NOT_CDS_RETURN_(false); + static bool is_string_region(int idx) NOT_CDS_RETURN_(false); static void generate_vtable_methods(void** vtbl_list, @@ -218,6 +220,15 @@ class MetaspaceShared : AllStatic { static char* misc_code_space_alloc(size_t num_bytes) { return _mc.alloc(num_bytes); } static char* misc_data_space_alloc(size_t num_bytes) { return _md.alloc(num_bytes); } + static address cds_i2i_entry_code_buffers(size_t total_size); + + static address cds_i2i_entry_code_buffers() { + return _cds_i2i_entry_code_buffers; + } + static size_t cds_i2i_entry_code_buffers_size() { + return _cds_i2i_entry_code_buffers_size; + } + static SharedMiscRegion* misc_code_region() { assert(DumpSharedSpaces, "used during dumping only"); return &_mc; diff --git a/hotspot/src/share/vm/memory/resourceArea.hpp b/hotspot/src/share/vm/memory/resourceArea.hpp index 65ae36a16460b96840aba036363938aab8d0e49d..89ad74573147301b35fca50e96b141eb37d9f5fd 100644 --- a/hotspot/src/share/vm/memory/resourceArea.hpp +++ b/hotspot/src/share/vm/memory/resourceArea.hpp @@ -26,7 +26,7 @@ #define SHARE_VM_MEMORY_RESOURCEAREA_HPP #include "memory/allocation.hpp" -#include "runtime/thread.inline.hpp" +#include "runtime/thread.hpp" // The resource area holds temporary data structures in the VM. // The actual allocation areas are thread local. Typical usage: diff --git a/hotspot/src/share/vm/memory/universe.cpp b/hotspot/src/share/vm/memory/universe.cpp index f33afa87ea2a9c50e7001878e43b9dd0f0528c41..11037c539f0757bc23a4c5ff57e291230c869b9c 100644 --- a/hotspot/src/share/vm/memory/universe.cpp +++ b/hotspot/src/share/vm/memory/universe.cpp @@ -747,8 +747,10 @@ jint Universe::initialize_heap() { Universe::set_narrow_ptrs_base(Universe::narrow_oop_base()); - if (PrintCompressedOopsMode || (PrintMiscellaneous && Verbose)) { - Universe::print_compressed_oops_mode(tty); + if (log_is_enabled(Info, gc, heap, coops)) { + ResourceMark rm; + outputStream* logst = Log(gc, heap, coops)::info_stream(); + Universe::print_compressed_oops_mode(logst); } // Tell tests in which mode we run. @@ -776,8 +778,8 @@ jint Universe::initialize_heap() { } void Universe::print_compressed_oops_mode(outputStream* st) { - st->print("heap address: " PTR_FORMAT ", size: " SIZE_FORMAT " MB", - p2i(Universe::heap()->base()), Universe::heap()->reserved_region().byte_size()/M); + st->print("Heap address: " PTR_FORMAT ", size: " SIZE_FORMAT " MB", + p2i(Universe::heap()->base()), Universe::heap()->reserved_region().byte_size()/M); st->print(", Compressed Oops mode: %s", narrow_oop_mode_to_string(narrow_oop_mode())); diff --git a/hotspot/src/share/vm/memory/virtualspace.cpp b/hotspot/src/share/vm/memory/virtualspace.cpp index 76f45090ec27c3b262c5e087672c9be83e65a2fb..31fddb745c7adea403fa88afdc967808b8bdc194 100644 --- a/hotspot/src/share/vm/memory/virtualspace.cpp +++ b/hotspot/src/share/vm/memory/virtualspace.cpp @@ -24,6 +24,8 @@ #include "precompiled.hpp" #include "code/codeCacheExtensions.hpp" +#include "logging/log.hpp" +#include "memory/resourceArea.hpp" #include "memory/virtualspace.hpp" #include "oops/markOop.hpp" #include "oops/oop.inline.hpp" @@ -78,10 +80,7 @@ static bool failed_to_reserve_as_requested(char* base, char* requested_address, // Different reserve address may be acceptable in other cases // but for compressed oops heap should be at requested address. assert(UseCompressedOops, "currently requested address used only for compressed oops"); - if (PrintCompressedOopsMode) { - tty->cr(); - tty->print_cr("Reserved memory not at requested address: " PTR_FORMAT " vs " PTR_FORMAT, p2i(base), p2i(requested_address)); - } + log_debug(gc, heap, coops)("Reserved memory not at requested address: " PTR_FORMAT " vs " PTR_FORMAT, p2i(base), p2i(requested_address)); // OS ignored requested address. Try different address. if (special) { if (!os::release_memory_special(base, size)) { @@ -143,10 +142,7 @@ void ReservedSpace::initialize(size_t size, size_t alignment, bool large, // failed; try to reserve regular memory below if (UseLargePages && (!FLAG_IS_DEFAULT(UseLargePages) || !FLAG_IS_DEFAULT(LargePageSizeInBytes))) { - if (PrintCompressedOopsMode) { - tty->cr(); - tty->print_cr("Reserve regular memory without large pages."); - } + log_debug(gc, heap, coops)("Reserve regular memory without large pages"); } } } @@ -286,11 +282,10 @@ void ReservedHeapSpace::establish_noaccess_prefix() { if (!os::protect_memory(_base, _noaccess_prefix, os::MEM_PROT_NONE, _special)) { fatal("cannot protect protection page"); } - if (PrintCompressedOopsMode) { - tty->cr(); - tty->print_cr("Protected page at the reserved heap base: " - PTR_FORMAT " / " INTX_FORMAT " bytes", p2i(_base), _noaccess_prefix); - } + log_debug(gc, heap, coops)("Protected page at the reserved heap base: " + PTR_FORMAT " / " INTX_FORMAT " bytes", + p2i(_base), + _noaccess_prefix); assert(Universe::narrow_oop_use_implicit_null_checks() == true, "not initialized?"); } else { Universe::set_narrow_oop_use_implicit_null_checks(false); @@ -321,10 +316,10 @@ void ReservedHeapSpace::try_reserve_heap(size_t size, bool special = large && !os::can_commit_large_page_memory(); char* base = NULL; - if (PrintCompressedOopsMode && Verbose) { - tty->print("Trying to allocate at address " PTR_FORMAT " heap of size " SIZE_FORMAT_HEX ".\n", - p2i(requested_address), size); - } + log_trace(gc, heap, coops)("Trying to allocate at address " PTR_FORMAT + " heap of size " SIZE_FORMAT_HEX, + p2i(requested_address), + size); if (special) { base = os::reserve_memory_special(size, alignment, requested_address, false); @@ -343,10 +338,7 @@ void ReservedHeapSpace::try_reserve_heap(size_t size, // Failed; try to reserve regular memory below if (UseLargePages && (!FLAG_IS_DEFAULT(UseLargePages) || !FLAG_IS_DEFAULT(LargePageSizeInBytes))) { - if (PrintCompressedOopsMode) { - tty->cr(); - tty->print_cr("Reserve regular memory without large pages."); - } + log_debug(gc, heap, coops)("Reserve regular memory without large pages"); } // Optimistically assume that the OSes returns an aligned base pointer. @@ -558,9 +550,7 @@ void ReservedHeapSpace::initialize_compressed_heap(const size_t size, size_t ali // Last, desperate try without any placement. if (_base == NULL) { - if (PrintCompressedOopsMode && Verbose) { - tty->print("Trying to allocate at address NULL heap of size " SIZE_FORMAT_HEX ".\n", size + noaccess_prefix); - } + log_trace(gc, heap, coops)("Trying to allocate at address NULL heap of size " SIZE_FORMAT_HEX, size + noaccess_prefix); initialize(size + noaccess_prefix, alignment, large, NULL, false); } } diff --git a/hotspot/src/share/vm/oops/constMethod.cpp b/hotspot/src/share/vm/oops/constMethod.cpp index 5ffc8e03e81c10114e25e8da6de3f29b58937cb1..8de67525a274bfa388741b41d5739173b1758c6e 100644 --- a/hotspot/src/share/vm/oops/constMethod.cpp +++ b/hotspot/src/share/vm/oops/constMethod.cpp @@ -66,6 +66,7 @@ ConstMethod::ConstMethod(int byte_code_size, set_max_locals(0); set_method_idnum(0); set_size_of_parameters(0); + set_result_type(T_VOID); } // Accessor that copies to metadata. diff --git a/hotspot/src/share/vm/oops/constMethod.hpp b/hotspot/src/share/vm/oops/constMethod.hpp index 7d959fb516bc3c7fd452dee1d41ea27491fb6329..7f63d9e2b38ad3b0957fb4ee3367aa35957d79b9 100644 --- a/hotspot/src/share/vm/oops/constMethod.hpp +++ b/hotspot/src/share/vm/oops/constMethod.hpp @@ -121,6 +121,7 @@ class MethodParametersElement VALUE_OBJ_CLASS_SPEC { }; class KlassSizeStats; +class AdapterHandlerEntry; // Class to collect the sizes of ConstMethod inline tables #define INLINE_TABLES_DO(do_element) \ @@ -201,8 +202,15 @@ private: // Raw stackmap data for the method Array* _stackmap_data; + // Adapter blob (i2c/c2i) for this Method*. Set once when method is linked. + union { + AdapterHandlerEntry* _adapter; + AdapterHandlerEntry** _adapter_trampoline; + }; + int _constMethod_size; u2 _flags; + u1 _result_type; // BasicType of result // Size of Java bytecodes allocated immediately after Method*. u2 _code_size; @@ -276,6 +284,29 @@ public: void copy_stackmap_data(ClassLoaderData* loader_data, u1* sd, int length, TRAPS); bool has_stackmap_table() const { return _stackmap_data != NULL; } + // adapter + void set_adapter_entry(AdapterHandlerEntry* adapter) { + assert(!is_shared(), "shared methods have fixed adapter_trampoline"); + _adapter = adapter; + } + void set_adapter_trampoline(AdapterHandlerEntry** trampoline) { + assert(DumpSharedSpaces, "must be"); + assert(*trampoline == NULL, "must be NULL during dump time, to be initialized at run time"); + _adapter_trampoline = trampoline; + } + void update_adapter_trampoline(AdapterHandlerEntry* adapter) { + assert(is_shared(), "must be"); + *_adapter_trampoline = adapter; + assert(this->adapter() == adapter, "must be"); + } + AdapterHandlerEntry* adapter() { + if (is_shared()) { + return *_adapter_trampoline; + } else { + return _adapter; + } + } + void init_fingerprint() { const uint64_t initval = UCONST64(0x8000000000000000); _fingerprint = initval; @@ -464,6 +495,8 @@ public: static ByteSize size_of_parameters_offset() { return byte_offset_of(ConstMethod, _size_of_parameters); } + static ByteSize result_type_offset() + { return byte_offset_of(ConstMethod, _result_type); } // Unique id for the method static const u2 MAX_IDNUM; @@ -486,6 +519,8 @@ public: int size_of_parameters() const { return _size_of_parameters; } void set_size_of_parameters(int size) { _size_of_parameters = size; } + void set_result_type(BasicType rt) { assert(rt < 16, "result type too large"); + _result_type = (u1)rt; } // Deallocation for RedefineClasses void deallocate_contents(ClassLoaderData* loader_data); bool is_klass() const { return false; } diff --git a/hotspot/src/share/vm/oops/constantPool.cpp b/hotspot/src/share/vm/oops/constantPool.cpp index 75a2bf970da1ec4bb898a3ea14fbe48be8496518..708c2f77d862c13abdb31cf8dd1719f3611bddc0 100644 --- a/hotspot/src/share/vm/oops/constantPool.cpp +++ b/hotspot/src/share/vm/oops/constantPool.cpp @@ -283,8 +283,9 @@ Klass* ConstantPool::klass_at_impl(const constantPoolHandle& this_cp, int which, this_key->record_dependency(k(), CHECK_NULL); // Can throw OOM // logging for classresolve tag. - trace_class_resolution(this_cp, k); - + if (log_is_enabled(Debug, classresolve)){ + trace_class_resolution(this_cp, k); + } this_cp->klass_at_put(which, k()); entry = this_cp->resolved_klass_at(which); assert(entry.is_resolved() && entry.get_klass()->is_klass(), "must be resolved at this point"); @@ -340,9 +341,7 @@ Method* ConstantPool::method_at_if_loaded(const constantPoolHandle& cpool, int cache_index = decode_cpcache_index(which, true); if (!(cache_index >= 0 && cache_index < cpool->cache()->length())) { // FIXME: should be an assert - if (PrintMiscellaneous && (Verbose||WizardMode)) { - tty->print_cr("bad operand %d in:", which); cpool->print(); - } + log_debug(classresolve)("bad operand %d in:", which); cpool->print(); return NULL; } ConstantPoolCacheEntry* e = cpool->cache()->entry_at(cache_index); @@ -396,7 +395,7 @@ int ConstantPool::impl_name_and_type_ref_index_at(int which, bool uncached) { int i = which; if (!uncached && cache() != NULL) { if (ConstantPool::is_invokedynamic_index(which)) { - // Invokedynamic index is index into resolved_references + // Invokedynamic index is index into the constant pool cache int pool_index = invokedynamic_cp_cache_entry_at(which)->constant_pool_index(); pool_index = invoke_dynamic_name_and_type_ref_index_at(pool_index); assert(tag_at(pool_index).is_name_and_type(), ""); @@ -672,10 +671,11 @@ oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp, in int callee_index = this_cp->method_handle_klass_index_at(index); Symbol* name = this_cp->method_handle_name_ref_at(index); Symbol* signature = this_cp->method_handle_signature_ref_at(index); - if (PrintMiscellaneous) - tty->print_cr("resolve JVM_CONSTANT_MethodHandle:%d [%d/%d/%d] %s.%s", - ref_kind, index, this_cp->method_handle_index_at(index), - callee_index, name->as_C_string(), signature->as_C_string()); + { ResourceMark rm(THREAD); + log_debug(classresolve)("resolve JVM_CONSTANT_MethodHandle:%d [%d/%d/%d] %s.%s", + ref_kind, index, this_cp->method_handle_index_at(index), + callee_index, name->as_C_string(), signature->as_C_string()); + } KlassHandle callee; { Klass* k = klass_at_impl(this_cp, callee_index, true, CHECK_NULL); callee = KlassHandle(THREAD, k); @@ -694,10 +694,11 @@ oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp, in case JVM_CONSTANT_MethodType: { Symbol* signature = this_cp->method_type_signature_at(index); - if (PrintMiscellaneous) - tty->print_cr("resolve JVM_CONSTANT_MethodType [%d/%d] %s", - index, this_cp->method_type_index_at(index), - signature->as_C_string()); + { ResourceMark rm(THREAD); + log_debug(classresolve)("resolve JVM_CONSTANT_MethodType [%d/%d] %s", + index, this_cp->method_type_index_at(index), + signature->as_C_string()); + } KlassHandle klass(THREAD, this_cp->pool_holder()); Handle value = SystemDictionary::find_method_handle_type(signature, klass, THREAD); result_oop = value(); @@ -964,8 +965,8 @@ bool ConstantPool::compare_entry_to(int index1, const constantPoolHandle& cp2, case JVM_CONSTANT_MethodType: { - int k1 = method_type_index_at_error_ok(index1); - int k2 = cp2->method_type_index_at_error_ok(index2); + int k1 = method_type_index_at(index1); + int k2 = cp2->method_type_index_at(index2); bool match = compare_entry_to(k1, cp2, k2, CHECK_false); if (match) { return true; @@ -974,11 +975,11 @@ bool ConstantPool::compare_entry_to(int index1, const constantPoolHandle& cp2, case JVM_CONSTANT_MethodHandle: { - int k1 = method_handle_ref_kind_at_error_ok(index1); - int k2 = cp2->method_handle_ref_kind_at_error_ok(index2); + int k1 = method_handle_ref_kind_at(index1); + int k2 = cp2->method_handle_ref_kind_at(index2); if (k1 == k2) { - int i1 = method_handle_index_at_error_ok(index1); - int i2 = cp2->method_handle_index_at_error_ok(index2); + int i1 = method_handle_index_at(index1); + int i2 = cp2->method_handle_index_at(index2); bool match = compare_entry_to(i1, cp2, i2, CHECK_false); if (match) { return true; @@ -1310,15 +1311,15 @@ void ConstantPool::copy_entry_to(const constantPoolHandle& from_cp, int from_i, case JVM_CONSTANT_MethodType: case JVM_CONSTANT_MethodTypeInError: { - jint k = from_cp->method_type_index_at_error_ok(from_i); + jint k = from_cp->method_type_index_at(from_i); to_cp->method_type_index_at_put(to_i, k); } break; case JVM_CONSTANT_MethodHandle: case JVM_CONSTANT_MethodHandleInError: { - int k1 = from_cp->method_handle_ref_kind_at_error_ok(from_i); - int k2 = from_cp->method_handle_index_at_error_ok(from_i); + int k1 = from_cp->method_handle_ref_kind_at(from_i); + int k2 = from_cp->method_handle_index_at(from_i); to_cp->method_handle_index_at_put(to_i, k1, k2); } break; @@ -1754,8 +1755,8 @@ int ConstantPool::copy_cpool_bytes(int cpool_size, case JVM_CONSTANT_MethodHandle: case JVM_CONSTANT_MethodHandleInError: { *bytes = JVM_CONSTANT_MethodHandle; - int kind = method_handle_ref_kind_at_error_ok(idx); - idx1 = method_handle_index_at_error_ok(idx); + int kind = method_handle_ref_kind_at(idx); + idx1 = method_handle_index_at(idx); *(bytes+1) = (unsigned char) kind; Bytes::put_Java_u2((address) (bytes+2), idx1); DBG(printf("JVM_CONSTANT_MethodHandle: %d %hd", kind, idx1)); @@ -1764,7 +1765,7 @@ int ConstantPool::copy_cpool_bytes(int cpool_size, case JVM_CONSTANT_MethodType: case JVM_CONSTANT_MethodTypeInError: { *bytes = JVM_CONSTANT_MethodType; - idx1 = method_type_index_at_error_ok(idx); + idx1 = method_type_index_at(idx); Bytes::put_Java_u2((address) (bytes+1), idx1); DBG(printf("JVM_CONSTANT_MethodType: %hd", idx1)); break; @@ -1952,12 +1953,12 @@ void ConstantPool::print_entry_on(const int index, outputStream* st) { break; case JVM_CONSTANT_MethodHandle : case JVM_CONSTANT_MethodHandleInError : - st->print("ref_kind=%d", method_handle_ref_kind_at_error_ok(index)); - st->print(" ref_index=%d", method_handle_index_at_error_ok(index)); + st->print("ref_kind=%d", method_handle_ref_kind_at(index)); + st->print(" ref_index=%d", method_handle_index_at(index)); break; case JVM_CONSTANT_MethodType : case JVM_CONSTANT_MethodTypeInError : - st->print("signature_index=%d", method_type_index_at_error_ok(index)); + st->print("signature_index=%d", method_type_index_at(index)); break; case JVM_CONSTANT_InvokeDynamic : { diff --git a/hotspot/src/share/vm/oops/constantPool.hpp b/hotspot/src/share/vm/oops/constantPool.hpp index 9ed795cb30308a69bfede51c338a459666f7b08e..75bca62917b8e79dd6124930e126b773c99f142b 100644 --- a/hotspot/src/share/vm/oops/constantPool.hpp +++ b/hotspot/src/share/vm/oops/constantPool.hpp @@ -460,41 +460,21 @@ class ConstantPool : public Metadata { return *int_at_addr(which); } - private: - int method_handle_ref_kind_at(int which, bool error_ok) { + int method_handle_ref_kind_at(int which) { assert(tag_at(which).is_method_handle() || - (error_ok && tag_at(which).is_method_handle_in_error()), "Corrupted constant pool"); + tag_at(which).is_method_handle_in_error(), "Corrupted constant pool"); return extract_low_short_from_int(*int_at_addr(which)); // mask out unwanted ref_index bits } - int method_handle_index_at(int which, bool error_ok) { + int method_handle_index_at(int which) { assert(tag_at(which).is_method_handle() || - (error_ok && tag_at(which).is_method_handle_in_error()), "Corrupted constant pool"); + tag_at(which).is_method_handle_in_error(), "Corrupted constant pool"); return extract_high_short_from_int(*int_at_addr(which)); // shift out unwanted ref_kind bits } - int method_type_index_at(int which, bool error_ok) { + int method_type_index_at(int which) { assert(tag_at(which).is_method_type() || - (error_ok && tag_at(which).is_method_type_in_error()), "Corrupted constant pool"); + tag_at(which).is_method_type_in_error(), "Corrupted constant pool"); return *int_at_addr(which); } - public: - int method_handle_ref_kind_at(int which) { - return method_handle_ref_kind_at(which, false); - } - int method_handle_ref_kind_at_error_ok(int which) { - return method_handle_ref_kind_at(which, true); - } - int method_handle_index_at(int which) { - return method_handle_index_at(which, false); - } - int method_handle_index_at_error_ok(int which) { - return method_handle_index_at(which, true); - } - int method_type_index_at(int which) { - return method_type_index_at(which, false); - } - int method_type_index_at_error_ok(int which) { - return method_type_index_at(which, true); - } // Derived queries: Symbol* method_handle_name_ref_at(int which) { diff --git a/hotspot/src/share/vm/oops/cpCache.hpp b/hotspot/src/share/vm/oops/cpCache.hpp index 33828d52f6a2cffc49d509a40f10c72c24617a12..840177a10cdac6cdfc46379320a20f6008a55a35 100644 --- a/hotspot/src/share/vm/oops/cpCache.hpp +++ b/hotspot/src/share/vm/oops/cpCache.hpp @@ -77,18 +77,19 @@ class PSPromotionManager; // f2 flag true if f2 contains an oop (e.g., virtual final method) // fv flag true if invokeinterface used for method in class Object // -// The flags 31, 30, 29, 28 together build a 4 bit number 0 to 8 with the +// The flags 31, 30, 29, 28 together build a 4 bit number 0 to 16 with the // following mapping to the TosState states: // // btos: 0 -// ctos: 1 -// stos: 2 -// itos: 3 -// ltos: 4 -// ftos: 5 -// dtos: 6 -// atos: 7 -// vtos: 8 +// ztos: 1 +// ctos: 2 +// stos: 3 +// itos: 4 +// ltos: 5 +// ftos: 6 +// dtos: 7 +// atos: 8 +// vtos: 9 // // Entry specific: field entries: // _indices = get (b1 section) and put (b2 section) bytecodes, original constant pool index @@ -352,14 +353,8 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC { bool has_method_type() const { return (!is_f1_null()) && (_flags & (1 << has_method_type_shift)) != 0; } bool is_method_entry() const { return (_flags & (1 << is_field_entry_shift)) == 0; } bool is_field_entry() const { return (_flags & (1 << is_field_entry_shift)) != 0; } - bool is_byte() const { return flag_state() == btos; } - bool is_char() const { return flag_state() == ctos; } - bool is_short() const { return flag_state() == stos; } - bool is_int() const { return flag_state() == itos; } bool is_long() const { return flag_state() == ltos; } - bool is_float() const { return flag_state() == ftos; } bool is_double() const { return flag_state() == dtos; } - bool is_object() const { return flag_state() == atos; } TosState flag_state() const { assert((uint)number_of_states <= (uint)tos_state_mask+1, ""); return (TosState)((_flags >> tos_state_shift) & tos_state_mask); } diff --git a/hotspot/src/share/vm/oops/klass.hpp b/hotspot/src/share/vm/oops/klass.hpp index cff1d74d6ef91c4ebc9b4a7f893e3e589e00b3ec..14675aa81ee2d128d6436176d5173921ab6961af 100644 --- a/hotspot/src/share/vm/oops/klass.hpp +++ b/hotspot/src/share/vm/oops/klass.hpp @@ -342,6 +342,21 @@ protected: assert(btvalue >= T_BOOLEAN && btvalue <= T_OBJECT, "sanity"); return (BasicType) btvalue; } + + // Want a pattern to quickly diff against layout header in register + // find something less clever! + static int layout_helper_boolean_diffbit() { + jint zlh = array_layout_helper(T_BOOLEAN); + jint blh = array_layout_helper(T_BYTE); + assert(zlh != blh, "array layout helpers must differ"); + int diffbit = 1; + while ((diffbit & (zlh ^ blh)) == 0 && (diffbit & zlh) == 0) { + diffbit <<= 1; + assert(diffbit != 0, "make sure T_BOOLEAN has a different bit than T_BYTE"); + } + return diffbit; + } + static int layout_helper_log2_element_size(jint lh) { assert(lh < (jint)_lh_neutral_value, "must be array"); int l2esz = (lh >> _lh_log2_element_size_shift) & _lh_log2_element_size_mask; diff --git a/hotspot/src/share/vm/oops/method.cpp b/hotspot/src/share/vm/oops/method.cpp index efaaaa5009a1aa369fbed8de2e1c0fdc57583d28..3491bda1c695e80a5c7bf2c3260437c6ce55d3c5 100644 --- a/hotspot/src/share/vm/oops/method.cpp +++ b/hotspot/src/share/vm/oops/method.cpp @@ -38,6 +38,7 @@ #include "interpreter/oopMapCache.hpp" #include "memory/heapInspection.hpp" #include "memory/metadataFactory.hpp" +#include "memory/metaspaceShared.hpp" #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" #include "oops/constMethod.hpp" @@ -83,9 +84,6 @@ Method::Method(ConstMethod* xconst, AccessFlags access_flags) { NoSafepointVerifier no_safepoint; set_constMethod(xconst); set_access_flags(access_flags); -#ifdef CC_INTERP - set_result_index(T_VOID); -#endif set_intrinsic_id(vmIntrinsics::_none); set_jfr_towrite(false); set_force_inline(false); @@ -123,18 +121,18 @@ void Method::deallocate_contents(ClassLoaderData* loader_data) { } address Method::get_i2c_entry() { - assert(_adapter != NULL, "must have"); - return _adapter->get_i2c_entry(); + assert(adapter() != NULL, "must have"); + return adapter()->get_i2c_entry(); } address Method::get_c2i_entry() { - assert(_adapter != NULL, "must have"); - return _adapter->get_c2i_entry(); + assert(adapter() != NULL, "must have"); + return adapter()->get_c2i_entry(); } address Method::get_c2i_unverified_entry() { - assert(_adapter != NULL, "must have"); - return _adapter->get_c2i_unverified_entry(); + assert(adapter() != NULL, "must have"); + return adapter()->get_c2i_unverified_entry(); } char* Method::name_and_sig_as_C_string() const { @@ -444,12 +442,6 @@ void Method::compute_size_of_parameters(Thread *thread) { set_size_of_parameters(asc.size() + (is_static() ? 0 : 1)); } -#ifdef CC_INTERP -void Method::set_result_index(BasicType type) { - _result_index = Interpreter::BasicType_as_index(type); -} -#endif - BasicType Method::result_type() const { ResultTypeFinder rtf(signature()); return rtf.type(); @@ -892,10 +884,10 @@ void Method::clear_code() { // this may be NULL if c2i adapters have not been made yet // Only should happen at allocate time. - if (_adapter == NULL) { + if (adapter() == NULL) { _from_compiled_entry = NULL; } else { - _from_compiled_entry = _adapter->get_c2i_entry(); + _from_compiled_entry = adapter()->get_c2i_entry(); } OrderAccess::storestore(); _from_interpreted_entry = _i2i_entry; @@ -903,47 +895,68 @@ void Method::clear_code() { _code = NULL; } +#if INCLUDE_CDS // Called by class data sharing to remove any entry points (which are not shared) void Method::unlink_method() { _code = NULL; - _i2i_entry = NULL; - _from_interpreted_entry = NULL; + + assert(DumpSharedSpaces, "dump time only"); + // Set the values to what they should be at run time. Note that + // this Method can no longer be executed during dump time. + _i2i_entry = Interpreter::entry_for_cds_method(this); + _from_interpreted_entry = _i2i_entry; + if (is_native()) { *native_function_addr() = NULL; set_signature_handler(NULL); } NOT_PRODUCT(set_compiled_invocation_count(0);) - _adapter = NULL; - _from_compiled_entry = NULL; + + CDSAdapterHandlerEntry* cds_adapter = (CDSAdapterHandlerEntry*)adapter(); + constMethod()->set_adapter_trampoline(cds_adapter->get_adapter_trampoline()); + _from_compiled_entry = cds_adapter->get_c2i_entry_trampoline(); + assert(*((int*)_from_compiled_entry) == 0, "must be NULL during dump time, to be initialized at run time"); + // In case of DumpSharedSpaces, _method_data should always be NULL. - // - // During runtime (!DumpSharedSpaces), when we are cleaning a - // shared class that failed to load, this->link_method() may - // have already been called (before an exception happened), so - // this->_method_data may not be NULL. - assert(!DumpSharedSpaces || _method_data == NULL, "unexpected method data?"); + assert(_method_data == NULL, "unexpected method data?"); set_method_data(NULL); clear_method_counters(); } +#endif // Called when the method_holder is getting linked. Setup entrypoints so the method // is ready to be called from interpreter, compiler, and vtables. void Method::link_method(const methodHandle& h_method, TRAPS) { // If the code cache is full, we may reenter this function for the // leftover methods that weren't linked. - if (_i2i_entry != NULL) return; + if (is_shared()) { + if (adapter() != NULL) return; + } else { + if (_i2i_entry != NULL) return; - assert(_adapter == NULL, "init'd to NULL" ); + assert(adapter() == NULL, "init'd to NULL" ); + } assert( _code == NULL, "nothing compiled yet" ); // Setup interpreter entrypoint assert(this == h_method(), "wrong h_method()" ); - address entry = Interpreter::entry_for_method(h_method); + address entry; + + if (this->is_shared()) { + entry = Interpreter::entry_for_cds_method(h_method); + } else { + entry = Interpreter::entry_for_method(h_method); + } assert(entry != NULL, "interpreter entry must be non-null"); - // Sets both _i2i_entry and _from_interpreted_entry - set_interpreter_entry(entry); + if (is_shared()) { + assert(entry == _i2i_entry && entry == _from_interpreted_entry, + "should be correctly set during dump time"); + } else { + // Sets both _i2i_entry and _from_interpreted_entry + set_interpreter_entry(entry); + } // Don't overwrite already registered native entries. if (is_native() && !has_native_function()) { @@ -975,8 +988,13 @@ address Method::make_adapters(methodHandle mh, TRAPS) { THROW_MSG_NULL(vmSymbols::java_lang_VirtualMachineError(), "Out of space in CodeCache for adapters"); } - mh->set_adapter_entry(adapter); - mh->_from_compiled_entry = adapter->get_c2i_entry(); + if (mh->is_shared()) { + assert(mh->adapter() == adapter, "must be"); + assert(mh->_from_compiled_entry != NULL, "must be"); // FIXME, the instructions also not NULL + } else { + mh->set_adapter_entry(adapter); + mh->_from_compiled_entry = adapter->get_c2i_entry(); + } return adapter->get_c2i_entry(); } @@ -992,6 +1010,14 @@ void Method::restore_unshareable_info(TRAPS) { } } +volatile address Method::from_compiled_entry_no_trampoline() const { + nmethod *code = (nmethod *)OrderAccess::load_ptr_acquire(&_code); + if (code) { + return code->verified_entry_point(); + } else { + return adapter()->get_c2i_entry(); + } +} // The verified_code_entry() must be called when a invoke is resolved // on this method. @@ -1185,10 +1211,8 @@ methodHandle Method::make_method_handle_intrinsic(vmIntrinsics::ID iid, m->set_signature_index(_imcp_invoke_signature); assert(MethodHandles::is_signature_polymorphic_name(m->name()), ""); assert(m->signature() == signature, ""); -#ifdef CC_INTERP ResultTypeFinder rtf(signature); - m->set_result_index(rtf.type()); -#endif + m->constMethod()->set_result_type(rtf.type()); m->compute_size_of_parameters(THREAD); m->init_intrinsic_id(); assert(m->is_method_handle_intrinsic(), ""); diff --git a/hotspot/src/share/vm/oops/method.hpp b/hotspot/src/share/vm/oops/method.hpp index 732de6cdba3ea0a2e0d5e2a21fdfbed7980785e4..264a07db004e7cb2794beb53b92bcde19d63d3b0 100644 --- a/hotspot/src/share/vm/oops/method.hpp +++ b/hotspot/src/share/vm/oops/method.hpp @@ -69,9 +69,6 @@ class Method : public Metadata { AccessFlags _access_flags; // Access flags int _vtable_index; // vtable index of this method (see VtableIndexFlag) // note: can have vtables with >2**16 elements (because of inheritance) -#ifdef CC_INTERP - int _result_index; // C++ interpreter needs for converting results to/from stack -#endif u2 _intrinsic_id; // vmSymbols::intrinsic_id (0 == _none) // Flags @@ -93,8 +90,6 @@ class Method : public Metadata { #endif // Entry point for calling both from and to the interpreter. address _i2i_entry; // All-args-on-stack calling convention - // Adapter blob (i2c/c2i) for this Method*. Set once when method is linked. - AdapterHandlerEntry* _adapter; // Entry point for calling from compiled code, to compiled code if it exists // or else the interpreter. volatile address _from_compiled_entry; // Cache of: _code ? _code->entry_point() : _adapter->c2i_entry() @@ -137,6 +132,7 @@ class Method : public Metadata { static address make_adapters(methodHandle mh, TRAPS); volatile address from_compiled_entry() const { return (address)OrderAccess::load_ptr_acquire(&_from_compiled_entry); } + volatile address from_compiled_entry_no_trampoline() const; volatile address from_interpreted_entry() const{ return (address)OrderAccess::load_ptr_acquire(&_from_interpreted_entry); } // access flag @@ -172,11 +168,6 @@ class Method : public Metadata { return constMethod()->type_annotations(); } -#ifdef CC_INTERP - void set_result_index(BasicType type); - int result_index() { return _result_index; } -#endif - // Helper routine: get klass name + "." + method name + signature as // C string, for the purpose of providing more useful NoSuchMethodErrors // and fatal error handling. The string is allocated in resource @@ -435,15 +426,23 @@ class Method : public Metadata { nmethod* volatile code() const { assert( check_code(), "" ); return (nmethod *)OrderAccess::load_ptr_acquire(&_code); } void clear_code(); // Clear out any compiled code static void set_code(methodHandle mh, nmethod* code); - void set_adapter_entry(AdapterHandlerEntry* adapter) { _adapter = adapter; } + void set_adapter_entry(AdapterHandlerEntry* adapter) { + constMethod()->set_adapter_entry(adapter); + } + void update_adapter_trampoline(AdapterHandlerEntry* adapter) { + constMethod()->update_adapter_trampoline(adapter); + } + address get_i2c_entry(); address get_c2i_entry(); address get_c2i_unverified_entry(); - AdapterHandlerEntry* adapter() { return _adapter; } + AdapterHandlerEntry* adapter() const { + return constMethod()->adapter(); + } // setup entry points void link_method(const methodHandle& method, TRAPS); - // clear entry points. Used by sharing code - void unlink_method(); + // clear entry points. Used by sharing code during dump time + void unlink_method() NOT_CDS_RETURN; // vtable index enum VtableIndexFlag { @@ -469,7 +468,15 @@ class Method : public Metadata { // interpreter entry address interpreter_entry() const { return _i2i_entry; } // Only used when first initialize so we can set _i2i_entry and _from_interpreted_entry - void set_interpreter_entry(address entry) { _i2i_entry = entry; _from_interpreted_entry = entry; } + void set_interpreter_entry(address entry) { + assert(!is_shared(), "shared method's interpreter entry should not be changed at run time"); + if (_i2i_entry != entry) { + _i2i_entry = entry; + } + if (_from_interpreted_entry != entry) { + _from_interpreted_entry = entry; + } + } // native function (used for native methods only) enum { @@ -537,7 +544,6 @@ class Method : public Metadata { void compute_size_of_parameters(Thread *thread); // word size of parameters (receiver if any + arguments) Symbol* klass_name() const; // returns the name of the method holder BasicType result_type() const; // type of the method result - int result_type_index() const; // type index of the method result bool is_returning_oop() const { BasicType r = result_type(); return (r == T_OBJECT || r == T_ARRAY); } bool is_returning_fp() const { BasicType r = result_type(); return (r == T_FLOAT || r == T_DOUBLE); } @@ -638,9 +644,6 @@ class Method : public Metadata { // interpreter support static ByteSize const_offset() { return byte_offset_of(Method, _constMethod ); } static ByteSize access_flags_offset() { return byte_offset_of(Method, _access_flags ); } -#ifdef CC_INTERP - static ByteSize result_index_offset() { return byte_offset_of(Method, _result_index ); } -#endif /* CC_INTERP */ static ByteSize from_compiled_offset() { return byte_offset_of(Method, _from_compiled_entry); } static ByteSize code_offset() { return byte_offset_of(Method, _code); } static ByteSize method_data_offset() { diff --git a/hotspot/src/share/vm/oops/methodData.cpp b/hotspot/src/share/vm/oops/methodData.cpp index d5f5d6ad454beb05b552b1b4b20392694e294f0c..85f7c9b6098ef48bfe8f8670848ed25ca16ba9a7 100644 --- a/hotspot/src/share/vm/oops/methodData.cpp +++ b/hotspot/src/share/vm/oops/methodData.cpp @@ -1729,6 +1729,7 @@ void MethodData::verify_extra_data_clean(CleanExtraDataClosure* cl) { } void MethodData::clean_method_data(BoolObjectClosure* is_alive) { + ResourceMark rm; for (ProfileData* data = first_data(); is_valid(data); data = next_data(data)) { @@ -1745,6 +1746,7 @@ void MethodData::clean_method_data(BoolObjectClosure* is_alive) { } void MethodData::clean_weak_method_links() { + ResourceMark rm; for (ProfileData* data = first_data(); is_valid(data); data = next_data(data)) { @@ -1758,6 +1760,7 @@ void MethodData::clean_weak_method_links() { #ifdef ASSERT void MethodData::verify_clean_weak_method_links() { + ResourceMark rm; for (ProfileData* data = first_data(); is_valid(data); data = next_data(data)) { diff --git a/hotspot/src/share/vm/oops/oop.hpp b/hotspot/src/share/vm/oops/oop.hpp index d154f966568d6bad12f9cbcdc2742562a2d7c6ac..23d73067178b96e6cb54895d803c0c21ea215b3e 100644 --- a/hotspot/src/share/vm/oops/oop.hpp +++ b/hotspot/src/share/vm/oops/oop.hpp @@ -30,7 +30,6 @@ #include "memory/memRegion.hpp" #include "oops/metadata.hpp" #include "utilities/macros.hpp" -#include "utilities/top.hpp" // oopDesc is the top baseclass for objects classes. The {name}Desc classes describe // the format of Java objects so the fields can be accessed from C++. diff --git a/hotspot/src/share/vm/oops/oop.inline.hpp b/hotspot/src/share/vm/oops/oop.inline.hpp index 5f896346986f96626fcacb3a09c6b9a89200ffa4..c3072a1b21cd4c9e05bcfebcbe27df16e5bf0f1e 100644 --- a/hotspot/src/share/vm/oops/oop.inline.hpp +++ b/hotspot/src/share/vm/oops/oop.inline.hpp @@ -443,7 +443,7 @@ jchar oopDesc::char_field(int offset) const { return (jchar) * void oopDesc::char_field_put(int offset, jchar contents) { *char_field_addr(offset) = (jint) contents; } jboolean oopDesc::bool_field(int offset) const { return (jboolean) *bool_field_addr(offset); } -void oopDesc::bool_field_put(int offset, jboolean contents) { *bool_field_addr(offset) = (jint) contents; } +void oopDesc::bool_field_put(int offset, jboolean contents) { *bool_field_addr(offset) = (((jint) contents) & 1); } jint oopDesc::int_field(int offset) const { return *int_field_addr(offset); } void oopDesc::int_field_put(int offset, jint contents) { *int_field_addr(offset) = contents; } @@ -483,7 +483,7 @@ jchar oopDesc::char_field_acquire(int offset) const { return O void oopDesc::release_char_field_put(int offset, jchar contents) { OrderAccess::release_store(char_field_addr(offset), contents); } jboolean oopDesc::bool_field_acquire(int offset) const { return OrderAccess::load_acquire(bool_field_addr(offset)); } -void oopDesc::release_bool_field_put(int offset, jboolean contents) { OrderAccess::release_store(bool_field_addr(offset), contents); } +void oopDesc::release_bool_field_put(int offset, jboolean contents) { OrderAccess::release_store(bool_field_addr(offset), (contents & 1)); } jint oopDesc::int_field_acquire(int offset) const { return OrderAccess::load_acquire(int_field_addr(offset)); } void oopDesc::release_int_field_put(int offset, jint contents) { OrderAccess::release_store(int_field_addr(offset), contents); } diff --git a/hotspot/src/share/vm/oops/symbol.hpp b/hotspot/src/share/vm/oops/symbol.hpp index f4241d3ad8ded542d240dff78a658f1680811e96..b2d71d51335cd2a5c5488ba42aec84107af071f2 100644 --- a/hotspot/src/share/vm/oops/symbol.hpp +++ b/hotspot/src/share/vm/oops/symbol.hpp @@ -25,9 +25,10 @@ #ifndef SHARE_VM_OOPS_SYMBOL_HPP #define SHARE_VM_OOPS_SYMBOL_HPP -#include "utilities/utf8.hpp" #include "memory/allocation.hpp" #include "runtime/atomic.hpp" +#include "utilities/exceptions.hpp" +#include "utilities/utf8.hpp" // A Symbol is a canonicalized string. // All Symbols reside in global SymbolTable and are reference counted. diff --git a/hotspot/src/share/vm/oops/typeArrayOop.hpp b/hotspot/src/share/vm/oops/typeArrayOop.hpp index 8ab2f4d1f746085f7c82adcca8d3f42e89b55735..adf99a30fe4aeeb04147c72fa20f7c8e69793465 100644 --- a/hotspot/src/share/vm/oops/typeArrayOop.hpp +++ b/hotspot/src/share/vm/oops/typeArrayOop.hpp @@ -96,7 +96,7 @@ class typeArrayOopDesc : public arrayOopDesc { void byte_at_put(int which, jbyte contents) { *byte_at_addr(which) = contents; } jboolean bool_at(int which) const { return *bool_at_addr(which); } - void bool_at_put(int which, jboolean contents) { *bool_at_addr(which) = contents; } + void bool_at_put(int which, jboolean contents) { *bool_at_addr(which) = (((jint)contents) & 1); } jchar char_at(int which) const { return *char_at_addr(which); } void char_at_put(int which, jchar contents) { *char_at_addr(which) = contents; } diff --git a/hotspot/src/share/vm/opto/memnode.cpp b/hotspot/src/share/vm/opto/memnode.cpp index d6b3c9394ad2e9a683408eb3cf18fd6e3d548d88..5580c7901d4fe462c23c8d23c52e10741c82fe83 100644 --- a/hotspot/src/share/vm/opto/memnode.cpp +++ b/hotspot/src/share/vm/opto/memnode.cpp @@ -2389,7 +2389,7 @@ StoreNode* StoreNode::make(PhaseGVN& gvn, Node* ctl, Node* mem, Node* adr, const ctl != NULL, "raw memory operations should have control edge"); switch (bt) { - case T_BOOLEAN: + case T_BOOLEAN: val = gvn.transform(new AndINode(val, gvn.intcon(0x1))); // Fall through to T_BYTE case case T_BYTE: return new StoreBNode(ctl, mem, adr, adr_type, val, mo); case T_INT: return new StoreINode(ctl, mem, adr, adr_type, val, mo); case T_CHAR: diff --git a/hotspot/src/share/vm/opto/parse1.cpp b/hotspot/src/share/vm/opto/parse1.cpp index 833f0a66adde2c57c951cab76505fa41e4ec5a3e..22b3e27292e6557828ed488976e79fc4b7fad8eb 100644 --- a/hotspot/src/share/vm/opto/parse1.cpp +++ b/hotspot/src/share/vm/opto/parse1.cpp @@ -730,6 +730,26 @@ void Parse::do_all_blocks() { #endif } +static Node* mask_int_value(Node* v, BasicType bt, PhaseGVN* gvn) { + switch (bt) { + case T_BYTE: + v = gvn->transform(new LShiftINode(v, gvn->intcon(24))); + v = gvn->transform(new RShiftINode(v, gvn->intcon(24))); + break; + case T_SHORT: + v = gvn->transform(new LShiftINode(v, gvn->intcon(16))); + v = gvn->transform(new RShiftINode(v, gvn->intcon(16))); + break; + case T_CHAR: + v = gvn->transform(new AndINode(v, gvn->intcon(0xFFFF))); + break; + case T_BOOLEAN: + v = gvn->transform(new AndINode(v, gvn->intcon(0x1))); + break; + } + return v; +} + //-------------------------------build_exits---------------------------------- // Build normal and exceptional exit merge points. void Parse::build_exits() { @@ -754,6 +774,16 @@ void Parse::build_exits() { // Add a return value to the exit state. (Do not push it yet.) if (tf()->range()->cnt() > TypeFunc::Parms) { const Type* ret_type = tf()->range()->field_at(TypeFunc::Parms); + if (ret_type->isa_int()) { + BasicType ret_bt = method()->return_type()->basic_type(); + if (ret_bt == T_BOOLEAN || + ret_bt == T_CHAR || + ret_bt == T_BYTE || + ret_bt == T_SHORT) { + ret_type = TypeInt::INT; + } + } + // Don't "bind" an unloaded return klass to the ret_phi. If the klass // becomes loaded during the subsequent parsing, the loaded and unloaded // types will not join when we transform and push in do_exits(). @@ -1014,6 +1044,10 @@ void Parse::do_exits() { } return; } + if (ret_type->isa_int()) { + BasicType ret_bt = method()->return_type()->basic_type(); + ret_phi = mask_int_value(ret_phi, ret_bt, &_gvn); + } _exits.push_node(ret_type->basic_type(), ret_phi); } diff --git a/hotspot/src/share/vm/opto/parse2.cpp b/hotspot/src/share/vm/opto/parse2.cpp index 6c0c2bec44f7207bcdbd95d31abb4a7cc1f1bff5..c8553ce798bf75c92f84ffd380c3ca7654a26a88 100644 --- a/hotspot/src/share/vm/opto/parse2.cpp +++ b/hotspot/src/share/vm/opto/parse2.cpp @@ -64,11 +64,15 @@ void Parse::array_load(BasicType elem_type) { //--------------------------------array_store---------------------------------- void Parse::array_store(BasicType elem_type) { - Node* adr = array_addressing(elem_type, 1); + const Type* elem = Type::TOP; + Node* adr = array_addressing(elem_type, 1, &elem); if (stopped()) return; // guaranteed null or range check Node* val = pop(); dec_sp(2); // Pop array and index const TypeAryPtr* adr_type = TypeAryPtr::get_array_body_type(elem_type); + if (elem == TypeInt::BOOL) { + elem_type = T_BOOLEAN; + } store_to_memory(control(), adr, val, elem_type, adr_type, StoreNode::release_if_reference(elem_type)); } diff --git a/hotspot/src/share/vm/opto/type.cpp b/hotspot/src/share/vm/opto/type.cpp index 42b290bd29e5a4c5d1050502424ddbb94edb5041..babc67b24336a2fc0dccdd334e097029d7c1996e 100644 --- a/hotspot/src/share/vm/opto/type.cpp +++ b/hotspot/src/share/vm/opto/type.cpp @@ -1820,13 +1820,15 @@ const TypeTuple *TypeTuple::make_domain(ciInstanceKlass* recv, ciSignature* sig) break; case T_OBJECT: case T_ARRAY: + case T_FLOAT: + case T_INT: + field_array[pos++] = get_const_type(type); + break; case T_BOOLEAN: case T_CHAR: - case T_FLOAT: case T_BYTE: case T_SHORT: - case T_INT: - field_array[pos++] = get_const_type(type); + field_array[pos++] = TypeInt::INT; break; default: ShouldNotReachHere(); diff --git a/hotspot/src/share/vm/precompiled/precompiled.hpp b/hotspot/src/share/vm/precompiled/precompiled.hpp index f3e0fea113ff655e90f0bf5568260f622c19758d..81bd00eaaf84d5fa883b6ec398f30112aedfb00b 100644 --- a/hotspot/src/share/vm/precompiled/precompiled.hpp +++ b/hotspot/src/share/vm/precompiled/precompiled.hpp @@ -242,7 +242,6 @@ # include "utilities/ostream.hpp" # include "utilities/preserveException.hpp" # include "utilities/sizes.hpp" -# include "utilities/top.hpp" # include "utilities/utf8.hpp" #ifdef COMPILER2 # include "libadt/dict.hpp" diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp index 80dc866f136ecb3a4428e7e6f18b80688b9a0383..8c1a020ac0f6a89ecbdd0f07f8bc396b96b7eb39 100644 --- a/hotspot/src/share/vm/prims/jni.cpp +++ b/hotspot/src/share/vm/prims/jni.cpp @@ -919,7 +919,14 @@ class JNI_ArgumentPusherVaArg : public JNI_ArgumentPusher { protected: va_list _ap; - inline void get_bool() { _arguments->push_int(va_arg(_ap, jint)); } // bool is coerced to int when using va_arg + inline void get_bool() { + // Normalize boolean arguments from native code by converting 1-255 to JNI_TRUE and + // 0 to JNI_FALSE. Boolean return values from native are normalized the same in + // TemplateInterpreterGenerator::generate_result_handler_for and + // SharedRuntime::generate_native_wrapper. + jboolean b = va_arg(_ap, jint); + _arguments->push_int((jint)(b == 0 ? JNI_FALSE : JNI_TRUE)); + } inline void get_char() { _arguments->push_int(va_arg(_ap, jint)); } // char is coerced to int when using va_arg inline void get_short() { _arguments->push_int(va_arg(_ap, jint)); } // short is coerced to int when using va_arg inline void get_byte() { _arguments->push_int(va_arg(_ap, jint)); } // byte is coerced to int when using va_arg @@ -960,9 +967,17 @@ class JNI_ArgumentPusherVaArg : public JNI_ArgumentPusher { while ( 1 ) { switch ( fingerprint & parameter_feature_mask ) { case bool_parm: + get_bool(); + break; case char_parm: + get_char(); + break; case short_parm: + get_short(); + break; case byte_parm: + get_byte(); + break; case int_parm: get_int(); break; @@ -996,7 +1011,14 @@ class JNI_ArgumentPusherArray : public JNI_ArgumentPusher { protected: const jvalue *_ap; - inline void get_bool() { _arguments->push_int((jint)(_ap++)->z); } + inline void get_bool() { + // Normalize boolean arguments from native code by converting 1-255 to JNI_TRUE and + // 0 to JNI_FALSE. Boolean return values from native are normalized the same in + // TemplateInterpreterGenerator::generate_result_handler_for and + // SharedRuntime::generate_native_wrapper. + jboolean b = (_ap++)->z; + _arguments->push_int((jint)(b == 0 ? JNI_FALSE : JNI_TRUE)); + } inline void get_char() { _arguments->push_int((jint)(_ap++)->c); } inline void get_short() { _arguments->push_int((jint)(_ap++)->s); } inline void get_byte() { _arguments->push_int((jint)(_ap++)->b); } @@ -2188,6 +2210,7 @@ JNI_QUICK_ENTRY(void, jni_Set##Result##Field(JNIEnv *env, jobject obj, jfieldID field_value.unionType = value; \ o = JvmtiExport::jni_SetField_probe_nh(thread, obj, o, k, fieldID, false, SigType, (jvalue *)&field_value); \ } \ + if (SigType == 'Z') { value = ((jboolean)value) & 1; } \ o->Fieldname##_field_put(offset, value); \ ReturnProbe; \ JNI_END @@ -2387,6 +2410,7 @@ JNI_ENTRY(void, jni_SetStatic##Result##Field(JNIEnv *env, jclass clazz, jfieldID field_value.unionType = value; \ JvmtiExport::jni_SetField_probe(thread, NULL, NULL, id->holder(), fieldID, true, SigType, (jvalue *)&field_value); \ } \ + if (SigType == 'Z') { value = ((jboolean)value) & 1; } \ id->holder()->java_mirror()-> Fieldname##_field_put (id->offset(), value); \ ReturnProbe;\ JNI_END diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp index 6c77385568cfb28f720dd6a08b879c4bfde0b53e..5166478e5e78a8302ad468d10774e6cc25211521 100644 --- a/hotspot/src/share/vm/prims/jvm.cpp +++ b/hotspot/src/share/vm/prims/jvm.cpp @@ -79,7 +79,6 @@ #include "utilities/events.hpp" #include "utilities/histogram.hpp" #include "utilities/macros.hpp" -#include "utilities/top.hpp" #include "utilities/utf8.hpp" #if INCLUDE_CDS #include "classfile/sharedClassUtil.hpp" @@ -534,7 +533,6 @@ JVM_END JVM_ENTRY(jobject, JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jlong mode, jint skip_frames, jint frame_count, jint start_index, - jobjectArray classes, jobjectArray frames)) JVMWrapper("JVM_CallStackWalk"); JavaThread* jt = (JavaThread*) THREAD; @@ -543,78 +541,51 @@ JVM_ENTRY(jobject, JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jlong mod } Handle stackStream_h(THREAD, JNIHandles::resolve_non_null(stackStream)); - objArrayOop ca = objArrayOop(JNIHandles::resolve_non_null(classes)); - objArrayHandle classes_array_h(THREAD, ca); - // frames array is null when only getting caller reference - objArrayOop fa = objArrayOop(JNIHandles::resolve(frames)); + // frames array is a Class[] array when only getting caller reference, + // and a StackFrameInfo[] array (or derivative) otherwise. It should never + // be null. + objArrayOop fa = objArrayOop(JNIHandles::resolve_non_null(frames)); objArrayHandle frames_array_h(THREAD, fa); int limit = start_index + frame_count; - if (classes_array_h->length() < limit) { + if (frames_array_h->length() < limit) { THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), "not enough space in buffers", NULL); } Handle result = StackWalk::walk(stackStream_h, mode, skip_frames, frame_count, - start_index, classes_array_h, - frames_array_h, CHECK_NULL); + start_index, frames_array_h, CHECK_NULL); return JNIHandles::make_local(env, result()); JVM_END JVM_ENTRY(jint, JVM_MoreStackWalk(JNIEnv *env, jobject stackStream, jlong mode, jlong anchor, jint frame_count, jint start_index, - jobjectArray classes, jobjectArray frames)) JVMWrapper("JVM_MoreStackWalk"); JavaThread* jt = (JavaThread*) THREAD; - objArrayOop ca = objArrayOop(JNIHandles::resolve_non_null(classes)); - objArrayHandle classes_array_h(THREAD, ca); - // frames array is null when only getting caller reference - objArrayOop fa = objArrayOop(JNIHandles::resolve(frames)); + // frames array is a Class[] array when only getting caller reference, + // and a StackFrameInfo[] array (or derivative) otherwise. It should never + // be null. + objArrayOop fa = objArrayOop(JNIHandles::resolve_non_null(frames)); objArrayHandle frames_array_h(THREAD, fa); int limit = start_index+frame_count; - if (classes_array_h->length() < limit) { + if (frames_array_h->length() < limit) { THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "not enough space in buffers"); } Handle stackStream_h(THREAD, JNIHandles::resolve_non_null(stackStream)); return StackWalk::moreFrames(stackStream_h, mode, anchor, frame_count, - start_index, classes_array_h, - frames_array_h, THREAD); + start_index, frames_array_h, THREAD); JVM_END -JVM_ENTRY(void, JVM_FillStackFrames(JNIEnv *env, jclass stackStream, - jint start_index, - jobjectArray frames, - jint from_index, jint to_index)) - JVMWrapper("JVM_FillStackFrames"); - if (TraceStackWalk) { - tty->print("JVM_FillStackFrames() start_index=%d from_index=%d to_index=%d\n", - start_index, from_index, to_index); - } - - JavaThread* jt = (JavaThread*) THREAD; - - objArrayOop fa = objArrayOop(JNIHandles::resolve_non_null(frames)); - objArrayHandle frames_array_h(THREAD, fa); - - if (frames_array_h->length() < to_index) { - THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "array length not matched"); - } - - for (int i = from_index; i < to_index; i++) { - Handle stackFrame(THREAD, frames_array_h->obj_at(i)); - java_lang_StackFrameInfo::fill_methodInfo(stackFrame, CHECK); - } -JVM_END - -JVM_ENTRY(void, JVM_SetMethodInfo(JNIEnv *env, jobject frame)) - JVMWrapper("JVM_SetMethodInfo"); - Handle stackFrame(THREAD, JNIHandles::resolve(frame)); - java_lang_StackFrameInfo::fill_methodInfo(stackFrame, THREAD); +JVM_ENTRY(void, JVM_ToStackTraceElement(JNIEnv *env, jobject frame, jobject stack)) + JVMWrapper("JVM_ToStackTraceElement"); + Handle stack_frame_info(THREAD, JNIHandles::resolve_non_null(frame)); + Handle stack_trace_element(THREAD, JNIHandles::resolve_non_null(stack)); + java_lang_StackFrameInfo::to_stack_trace_element(stack_frame_info, stack_trace_element, THREAD); JVM_END // java.lang.Object /////////////////////////////////////////////// @@ -1818,9 +1789,6 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, // Ensure class is linked k->link_class(CHECK_NULL); - // 4496456 We need to filter out java.lang.Throwable.backtrace - bool skip_backtrace = false; - // Allocate result int num_fields; @@ -1831,11 +1799,6 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, } } else { num_fields = k->java_fields_count(); - - if (k() == SystemDictionary::Throwable_klass()) { - num_fields--; - skip_backtrace = true; - } } objArrayOop r = oopFactory::new_objArray(SystemDictionary::reflect_Field_klass(), num_fields, CHECK_NULL); @@ -1844,12 +1807,6 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, int out_idx = 0; fieldDescriptor fd; for (JavaFieldStream fs(k); !fs.done(); fs.next()) { - if (skip_backtrace) { - // 4496456 skip java.lang.Throwable.backtrace - int offset = fs.offset(); - if (offset == java_lang_Throwable::get_backtrace_offset()) continue; - } - if (!publicOnly || fs.access_flags().is_public()) { fd.reinitialize(k(), fs.index()); oop field = Reflection::new_field(&fd, CHECK_NULL); diff --git a/hotspot/src/share/vm/prims/jvm.h b/hotspot/src/share/vm/prims/jvm.h index dafc3955101a5c26a4ff5deaa62f7b97d3314e33..5a055995d1c12221add09b43d31f2e77102c31af 100644 --- a/hotspot/src/share/vm/prims/jvm.h +++ b/hotspot/src/share/vm/prims/jvm.h @@ -209,7 +209,6 @@ JVM_GetStackTraceElements(JNIEnv *env, jobject throwable, jobjectArray elements) */ enum { JVM_STACKWALK_FILL_CLASS_REFS_ONLY = 0x2, - JVM_STACKWALK_FILTER_FILL_IN_STACK_TRACE = 0x10, JVM_STACKWALK_SHOW_HIDDEN_FRAMES = 0x20, JVM_STACKWALK_FILL_LIVE_STACK_FRAMES = 0x100 }; @@ -217,23 +216,15 @@ enum { JNIEXPORT jobject JNICALL JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jlong mode, jint skip_frames, jint frame_count, jint start_index, - jobjectArray classes, jobjectArray frames); JNIEXPORT jint JNICALL JVM_MoreStackWalk(JNIEnv *env, jobject stackStream, jlong mode, jlong anchor, jint frame_count, jint start_index, - jobjectArray classes, jobjectArray frames); JNIEXPORT void JNICALL -JVM_FillStackFrames(JNIEnv* env, jclass cls, - jint start_index, - jobjectArray frames, - jint from_index, jint toIndex); - -JNIEXPORT void JNICALL -JVM_SetMethodInfo(JNIEnv* env, jobject frame); +JVM_ToStackTraceElement(JNIEnv* env, jobject frame, jobject stackElement); /* * java.lang.Thread diff --git a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp index 96ee3a19adb2419a6acec28219eb6e1951bab144..dd241a014d7bff7d33fb3d7866e7197f9bdf5a2a 100644 --- a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp +++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp @@ -1354,7 +1354,7 @@ JvmtiEnvBase::check_top_frame(JavaThread* current_thread, JavaThread* java_threa ResultTypeFinder rtf(signature); TosState fr_tos = as_TosState(rtf.type()); if (fr_tos != tos) { - if (tos != itos || (fr_tos != btos && fr_tos != ctos && fr_tos != stos)) { + if (tos != itos || (fr_tos != btos && fr_tos != ztos && fr_tos != ctos && fr_tos != stos)) { return JVMTI_ERROR_TYPE_MISMATCH; } } diff --git a/hotspot/src/share/vm/prims/jvmtiExport.cpp b/hotspot/src/share/vm/prims/jvmtiExport.cpp index 20de3f979cb4a1cf695a30118c869e1a90094a30..984c5f910d28f8bd10b3a875a86c31b0f7310220 100644 --- a/hotspot/src/share/vm/prims/jvmtiExport.cpp +++ b/hotspot/src/share/vm/prims/jvmtiExport.cpp @@ -1702,7 +1702,7 @@ void JvmtiExport::post_raw_field_modification(JavaThread *thread, Method* method address location, KlassHandle field_klass, Handle object, jfieldID field, char sig_type, jvalue *value) { - if (sig_type == 'I' || sig_type == 'Z' || sig_type == 'C' || sig_type == 'S') { + if (sig_type == 'I' || sig_type == 'Z' || sig_type == 'B' || sig_type == 'C' || sig_type == 'S') { // 'I' instructions are used for byte, char, short and int. // determine which it really is, and convert fieldDescriptor fd; @@ -2260,7 +2260,7 @@ void JvmtiExport::post_vm_object_alloc(JavaThread *thread, oop object) { if (env->is_enabled(JVMTI_EVENT_VM_OBJECT_ALLOC)) { EVT_TRACE(JVMTI_EVENT_VM_OBJECT_ALLOC, ("JVMTI [%s] Evt vmobject alloc sent %s", JvmtiTrace::safe_get_thread_name(thread), - object==NULL? "NULL" : java_lang_Class::as_Klass(object)->external_name())); + object==NULL? "NULL" : object->klass()->external_name())); JvmtiVMObjectAllocEventMark jem(thread, h()); JvmtiJavaThreadEventTransition jet(thread); diff --git a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp index 3410d9566c93fb3f9ef56e1027069348bd962701..c6737e73617f0c94732192e6b6e0b5cce9e09747 100644 --- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp +++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp @@ -1443,8 +1443,9 @@ jvmtiError VM_RedefineClasses::merge_cp_and_rewrite( return JVMTI_ERROR_INTERNAL; } - // Update the version number of the constant pool + // Update the version number of the constant pools (may keep scratch_cp) merge_cp->increment_and_save_version(old_cp->version()); + scratch_cp->increment_and_save_version(old_cp->version()); ResourceMark rm(THREAD); _index_map_count = 0; @@ -3911,6 +3912,11 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass, method->set_constants(scratch_class->constants()); } + // NOTE: this doesn't work because you can redefine the same class in two + // threads, each getting their own constant pool data appended to the + // original constant pool. In order for the new methods to work when they + // become old methods, they need to keep their updated copy of the constant pool. + { // walk all previous versions of the klass InstanceKlass *ik = (InstanceKlass *)the_class(); diff --git a/hotspot/src/share/vm/prims/nativeLookup.hpp b/hotspot/src/share/vm/prims/nativeLookup.hpp index d1cfcb9259a46e042e0d2e08581bb5c88ba99260..3afc5039eb2e8aea6a45d4919cfa3ed9ee6ef625 100644 --- a/hotspot/src/share/vm/prims/nativeLookup.hpp +++ b/hotspot/src/share/vm/prims/nativeLookup.hpp @@ -25,8 +25,8 @@ #ifndef SHARE_VM_PRIMS_NATIVELOOKUP_HPP #define SHARE_VM_PRIMS_NATIVELOOKUP_HPP +#include "memory/allocation.hpp" #include "runtime/handles.hpp" -#include "utilities/top.hpp" // NativeLookup provides an interface for finding DLL entry points for // Java native functions. diff --git a/hotspot/src/share/vm/prims/stackwalk.cpp b/hotspot/src/share/vm/prims/stackwalk.cpp index 3e292641a7992cfe2a193aada8fe770de8082e78..d772620dcf547a2e44ec7aba39bbad2f5b0d297c 100644 --- a/hotspot/src/share/vm/prims/stackwalk.cpp +++ b/hotspot/src/share/vm/prims/stackwalk.cpp @@ -37,22 +37,22 @@ #include "utilities/globalDefinitions.hpp" // setup and cleanup actions -void StackWalkAnchor::setup_magic_on_entry(objArrayHandle classes_array) { - classes_array->obj_at_put(magic_pos, _thread->threadObj()); +void StackWalkAnchor::setup_magic_on_entry(objArrayHandle frames_array) { + frames_array->obj_at_put(magic_pos, _thread->threadObj()); _anchor = address_value(); - assert(check_magic(classes_array), "invalid magic"); + assert(check_magic(frames_array), "invalid magic"); } -bool StackWalkAnchor::check_magic(objArrayHandle classes_array) { - oop m1 = classes_array->obj_at(magic_pos); +bool StackWalkAnchor::check_magic(objArrayHandle frames_array) { + oop m1 = frames_array->obj_at(magic_pos); jlong m2 = _anchor; if (m1 == _thread->threadObj() && m2 == address_value()) return true; return false; } -bool StackWalkAnchor::cleanup_magic_on_exit(objArrayHandle classes_array) { - bool ok = check_magic(classes_array); - classes_array->obj_at_put(magic_pos, NULL); +bool StackWalkAnchor::cleanup_magic_on_exit(objArrayHandle frames_array) { + bool ok = check_magic(frames_array); + frames_array->obj_at_put(magic_pos, NULL); _anchor = 0L; return ok; } @@ -62,18 +62,18 @@ bool StackWalkAnchor::cleanup_magic_on_exit(objArrayHandle classes_array) { // Parameters: // thread Current Java thread. // magic Magic value used for each stack walking -// classes_array User-supplied buffers. The 0th element is reserved +// frames_array User-supplied buffers. The 0th element is reserved // to this StackWalkAnchor to use // StackWalkAnchor* StackWalkAnchor::from_current(JavaThread* thread, jlong magic, - objArrayHandle classes_array) + objArrayHandle frames_array) { assert(thread != NULL && thread->is_Java_thread(), ""); - oop m1 = classes_array->obj_at(magic_pos); + oop m1 = frames_array->obj_at(magic_pos); if (m1 != thread->threadObj()) return NULL; if (magic == 0L) return NULL; StackWalkAnchor* anchor = (StackWalkAnchor*) (intptr_t) magic; - if (!anchor->is_valid_in(thread, classes_array)) return NULL; + if (!anchor->is_valid_in(thread, frames_array)) return NULL; return anchor; } @@ -88,24 +88,24 @@ StackWalkAnchor* StackWalkAnchor::from_current(JavaThread* thread, jlong magic, // vfst vFrameStream. // max_nframes Maximum number of frames to be filled. // start_index Start index to the user-supplied buffers. -// classes_array Buffer to store classes in, starting at start_index. -// frames_array Buffer to store StackFrame in, starting at start_index. -// NULL if not used. +// frames_array Buffer to store Class or StackFrame in, starting at start_index. +// frames array is a Class[] array when only getting caller +// reference, and a StackFrameInfo[] array (or derivative) +// otherwise. It should never be null. // end_index End index to the user-supplied buffers with unpacked frames. // // Returns the number of frames whose information was transferred into the buffers. // int StackWalk::fill_in_frames(jlong mode, vframeStream& vfst, int max_nframes, int start_index, - objArrayHandle classes_array, objArrayHandle frames_array, int& end_index, TRAPS) { if (TraceStackWalk) { tty->print_cr("fill_in_frames limit=%d start=%d frames length=%d", - max_nframes, start_index, classes_array->length()); + max_nframes, start_index, frames_array->length()); } assert(max_nframes > 0, "invalid max_nframes"); - assert(start_index + max_nframes <= classes_array->length(), "oob"); + assert(start_index + max_nframes <= frames_array->length(), "oob"); int frames_decoded = 0; for (; !vfst.at_end(); vfst.next()) { @@ -129,14 +129,18 @@ int StackWalk::fill_in_frames(jlong mode, vframeStream& vfst, tty->print_cr(" bci=%d", bci); } - classes_array->obj_at_put(index, method->method_holder()->java_mirror()); // fill in StackFrameInfo and initialize MemberName if (live_frame_info(mode)) { + assert (use_frames_array(mode), "Bad mode for get live frame"); Handle stackFrame(frames_array->obj_at(index)); fill_live_stackframe(stackFrame, method, bci, vfst.java_frame(), CHECK_0); } else if (need_method_info(mode)) { + assert (use_frames_array(mode), "Bad mode for get stack frame"); Handle stackFrame(frames_array->obj_at(index)); fill_stackframe(stackFrame, method, bci); + } else { + assert (use_frames_array(mode) == false, "Bad mode for get caller class"); + frames_array->obj_at_put(index, method->method_holder()->java_mirror()); } if (++frames_decoded >= max_nframes) break; } @@ -279,15 +283,15 @@ void StackWalk::fill_live_stackframe(Handle stackFrame, const methodHandle& meth // skip_frames Number of frames to be skipped. // frame_count Number of frames to be traversed. // start_index Start index to the user-supplied buffers. -// classes_array Buffer to store classes in, starting at start_index. // frames_array Buffer to store StackFrame in, starting at start_index. -// NULL if not used. +// frames array is a Class[] array when only getting caller +// reference, and a StackFrameInfo[] array (or derivative) +// otherwise. It should never be null. // // Returns Object returned from AbstractStackWalker::doStackWalk call. // oop StackWalk::walk(Handle stackStream, jlong mode, int skip_frames, int frame_count, int start_index, - objArrayHandle classes_array, objArrayHandle frames_array, TRAPS) { JavaThread* jt = (JavaThread*)THREAD; @@ -296,10 +300,8 @@ oop StackWalk::walk(Handle stackStream, jlong mode, mode, skip_frames, frame_count); } - if (need_method_info(mode)) { - if (frames_array.is_null()) { - THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", NULL); - } + if (frames_array.is_null()) { + THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", NULL); } Klass* stackWalker_klass = SystemDictionary::StackWalker_klass(); @@ -313,48 +315,17 @@ oop StackWalk::walk(Handle stackStream, jlong mode, vframeStream& vfst = anchor.vframe_stream(); { - // Skip all methods from AbstractStackWalker and StackWalk (enclosing method) - if (!fill_in_stacktrace(mode)) { - while (!vfst.at_end()) { - InstanceKlass* ik = vfst.method()->method_holder(); - if (ik != stackWalker_klass && - ik != abstractStackWalker_klass && ik->super() != abstractStackWalker_klass) { - break; - } - - if (TraceStackWalk) { - tty->print(" skip "); vfst.method()->print_short_name(); tty->print("\n"); - } - vfst.next(); + while (!vfst.at_end()) { + InstanceKlass* ik = vfst.method()->method_holder(); + if (ik != stackWalker_klass && + ik != abstractStackWalker_klass && ik->super() != abstractStackWalker_klass) { + break; } - } - - // For exceptions, skip Throwable::fillInStackTrace and methods - // of the exception class and superclasses - if (fill_in_stacktrace(mode)) { - bool skip_to_fillInStackTrace = false; - bool skip_throwableInit_check = false; - while (!vfst.at_end() && !skip_throwableInit_check) { - InstanceKlass* ik = vfst.method()->method_holder(); - Method* method = vfst.method(); - if (!skip_to_fillInStackTrace) { - if (ik == SystemDictionary::Throwable_klass() && - method->name() == vmSymbols::fillInStackTrace_name()) { - // this frame will be skipped - skip_to_fillInStackTrace = true; - } - } else if (!(ik->is_subclass_of(SystemDictionary::Throwable_klass()) && - method->name() == vmSymbols::object_initializer_name())) { - // there are none or we've seen them all - either way stop checking - skip_throwableInit_check = true; - break; - } - if (TraceStackWalk) { - tty->print("stack walk: skip "); vfst.method()->print_short_name(); tty->print("\n"); - } - vfst.next(); + if (TraceStackWalk) { + tty->print(" skip "); vfst.method()->print_short_name(); tty->print("\n"); } + vfst.next(); } // stack frame has been traversed individually and resume stack walk @@ -372,7 +343,7 @@ oop StackWalk::walk(Handle stackStream, jlong mode, int end_index = start_index; int numFrames = 0; if (!vfst.at_end()) { - numFrames = fill_in_frames(mode, vfst, frame_count, start_index, classes_array, + numFrames = fill_in_frames(mode, vfst, frame_count, start_index, frames_array, end_index, CHECK_NULL); if (numFrames < 1) { THROW_MSG_(vmSymbols::java_lang_InternalError(), "stack walk: decode failed", NULL); @@ -392,12 +363,12 @@ oop StackWalk::walk(Handle stackStream, jlong mode, args.push_int(end_index); // Link the thread and vframe stream into the callee-visible object - anchor.setup_magic_on_entry(classes_array); + anchor.setup_magic_on_entry(frames_array); JavaCalls::call(&result, m_doStackWalk, &args, THREAD); // Do this before anything else happens, to disable any lingering stream objects - bool ok = anchor.cleanup_magic_on_exit(classes_array); + bool ok = anchor.cleanup_magic_on_exit(frames_array); // Throw pending exception if we must (void) (CHECK_NULL); @@ -419,31 +390,28 @@ oop StackWalk::walk(Handle stackStream, jlong mode, // magic Must be valid value to continue the stack walk // frame_count Number of frames to be decoded. // start_index Start index to the user-supplied buffers. -// classes_array Buffer to store classes in, starting at start_index. // frames_array Buffer to store StackFrame in, starting at start_index. -// NULL if not used. // // Returns the end index of frame filled in the buffer. // jint StackWalk::moreFrames(Handle stackStream, jlong mode, jlong magic, int frame_count, int start_index, - objArrayHandle classes_array, objArrayHandle frames_array, TRAPS) { JavaThread* jt = (JavaThread*)THREAD; - StackWalkAnchor* existing_anchor = StackWalkAnchor::from_current(jt, magic, classes_array); + StackWalkAnchor* existing_anchor = StackWalkAnchor::from_current(jt, magic, frames_array); if (existing_anchor == NULL) { THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers", 0L); } - if ((need_method_info(mode) || live_frame_info(mode)) && frames_array.is_null()) { + if (frames_array.is_null()) { THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", 0L); } if (TraceStackWalk) { tty->print_cr("StackWalk::moreFrames frame_count %d existing_anchor " PTR_FORMAT " start %d frames %d", - frame_count, p2i(existing_anchor), start_index, classes_array->length()); + frame_count, p2i(existing_anchor), start_index, frames_array->length()); } int end_index = start_index; if (frame_count <= 0) { @@ -451,14 +419,14 @@ jint StackWalk::moreFrames(Handle stackStream, jlong mode, jlong magic, } int count = frame_count + start_index; - assert (classes_array->length() >= count, "not enough space in buffers"); + assert (frames_array->length() >= count, "not enough space in buffers"); StackWalkAnchor& anchor = (*existing_anchor); vframeStream& vfst = anchor.vframe_stream(); if (!vfst.at_end()) { vfst.next(); // this was the last frame decoded in the previous batch if (!vfst.at_end()) { - int n = fill_in_frames(mode, vfst, frame_count, start_index, classes_array, + int n = fill_in_frames(mode, vfst, frame_count, start_index, frames_array, end_index, CHECK_0); if (n < 1) { THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: later decode failed", 0L); diff --git a/hotspot/src/share/vm/prims/stackwalk.hpp b/hotspot/src/share/vm/prims/stackwalk.hpp index 1fa906815bebcdab1592cc910c073c6003c94bee..2eb41aeb71148d7fe3f961cdbe0b6ccbef171b29 100644 --- a/hotspot/src/share/vm/prims/stackwalk.hpp +++ b/hotspot/src/share/vm/prims/stackwalk.hpp @@ -45,12 +45,12 @@ public: vframeStream& vframe_stream() { return _vfst; } JavaThread* thread() { return _thread; } - void setup_magic_on_entry(objArrayHandle classes_array); - bool check_magic(objArrayHandle classes_array); - bool cleanup_magic_on_exit(objArrayHandle classes_array); + void setup_magic_on_entry(objArrayHandle frames_array); + bool check_magic(objArrayHandle frames_array); + bool cleanup_magic_on_exit(objArrayHandle frames_array); - bool is_valid_in(Thread* thread, objArrayHandle classes_array) { - return (_thread == thread && check_magic(classes_array)); + bool is_valid_in(Thread* thread, objArrayHandle frames_array) { + return (_thread == thread && check_magic(frames_array)); } jlong address_value() { @@ -64,7 +64,6 @@ class StackWalk : public AllStatic { private: static int fill_in_frames(jlong mode, vframeStream& vfst, int max_nframes, int start_index, - objArrayHandle classes_array, objArrayHandle frames_array, int& end_index, TRAPS); @@ -82,20 +81,18 @@ private: static inline bool live_frame_info(int mode) { return (mode & JVM_STACKWALK_FILL_LIVE_STACK_FRAMES) != 0; } - static inline bool fill_in_stacktrace(int mode) { - return (mode & JVM_STACKWALK_FILTER_FILL_IN_STACK_TRACE) != 0; - } public: + static inline bool use_frames_array(int mode) { + return (mode & JVM_STACKWALK_FILL_CLASS_REFS_ONLY) == 0; + } static oop walk(Handle stackStream, jlong mode, int skip_frames, int frame_count, int start_index, - objArrayHandle classes_array, objArrayHandle frames_array, TRAPS); static jint moreFrames(Handle stackStream, jlong mode, jlong magic, int frame_count, int start_index, - objArrayHandle classes_array, objArrayHandle frames_array, TRAPS); }; diff --git a/hotspot/src/share/vm/prims/unsafe.cpp b/hotspot/src/share/vm/prims/unsafe.cpp index f951f694f1d4f9d6a09cc69d5df2d3edd1b66e6a..72226385d3e3a7383dd0d4c8f949e8e55e9425a5 100644 --- a/hotspot/src/share/vm/prims/unsafe.cpp +++ b/hotspot/src/share/vm/prims/unsafe.cpp @@ -133,13 +133,22 @@ jlong Unsafe_field_offset_from_byte_offset(jlong byte_offset) { ///// Data in the Java heap. +#define truncate_jboolean(x) ((x) & 1) +#define truncate_jbyte(x) (x) +#define truncate_jshort(x) (x) +#define truncate_jchar(x) (x) +#define truncate_jint(x) (x) +#define truncate_jlong(x) (x) +#define truncate_jfloat(x) (x) +#define truncate_jdouble(x) (x) + #define GET_FIELD(obj, offset, type_name, v) \ oop p = JNIHandles::resolve(obj); \ type_name v = *(type_name*)index_oop_from_field_offset_long(p, offset) #define SET_FIELD(obj, offset, type_name, x) \ oop p = JNIHandles::resolve(obj); \ - *(type_name*)index_oop_from_field_offset_long(p, offset) = x + *(type_name*)index_oop_from_field_offset_long(p, offset) = truncate_##type_name(x) #define GET_FIELD_VOLATILE(obj, offset, type_name, v) \ oop p = JNIHandles::resolve(obj); \ @@ -150,7 +159,7 @@ jlong Unsafe_field_offset_from_byte_offset(jlong byte_offset) { #define SET_FIELD_VOLATILE(obj, offset, type_name, x) \ oop p = JNIHandles::resolve(obj); \ - OrderAccess::release_store_fence((volatile type_name*)index_oop_from_field_offset_long(p, offset), x); + OrderAccess::release_store_fence((volatile type_name*)index_oop_from_field_offset_long(p, offset), truncate_##type_name(x)); // Get/SetObject must be special-cased, since it works with handles. diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 948f80789e45ab36c31e5c00e904a4431a711d45..7fa2ea8a7ad7a88758c5e1e6c764424e668ef240 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -407,7 +407,9 @@ static AliasedFlag const aliased_jvm_flags[] = { { NULL, NULL} }; +// NOTE: A compatibility request will be necessary for each alias to be removed. static AliasedLoggingFlag const aliased_logging_flags[] = { + { "PrintCompressedOopsMode", LogLevel::Info, true, LOG_TAGS(gc, heap, coops) }, { "TraceBiasedLocking", LogLevel::Info, true, LOG_TAGS(biasedlocking) }, { "TraceClassLoading", LogLevel::Info, true, LOG_TAGS(classload) }, { "TraceClassLoadingPreorder", LogLevel::Debug, true, LOG_TAGS(classload, preorder) }, @@ -696,7 +698,7 @@ char* ArgumentBootClassPath::combined_path() { assert(total_len > 0, "empty sysclasspath not allowed"); // Copy the _items to a single string. - char* cp = NEW_C_HEAP_ARRAY(char, total_len, mtInternal); + char* cp = NEW_C_HEAP_ARRAY(char, total_len, mtArguments); char* cp_tmp = cp; for (i = 0; i < _bcp_nitems; ++i) { if (_items[i] != NULL) { @@ -717,7 +719,7 @@ ArgumentBootClassPath::add_to_path(const char* path, const char* str, bool prepe assert(str != NULL, "just checking"); if (path == NULL) { size_t len = strlen(str) + 1; - cp = NEW_C_HEAP_ARRAY(char, len, mtInternal); + cp = NEW_C_HEAP_ARRAY(char, len, mtArguments); memcpy(cp, str, len); // copy the trailing null } else { const char separator = *os::path_separator(); @@ -726,7 +728,7 @@ ArgumentBootClassPath::add_to_path(const char* path, const char* str, bool prepe size_t len = old_len + str_len + 2; if (prepend) { - cp = NEW_C_HEAP_ARRAY(char, len, mtInternal); + cp = NEW_C_HEAP_ARRAY(char, len, mtArguments); char* cp_tmp = cp; memcpy(cp_tmp, str, str_len); cp_tmp += str_len; @@ -734,7 +736,7 @@ ArgumentBootClassPath::add_to_path(const char* path, const char* str, bool prepe memcpy(++cp_tmp, path, old_len + 1); // copy the trailing null FREE_C_HEAP_ARRAY(char, path); } else { - cp = REALLOC_C_HEAP_ARRAY(char, path, len, mtInternal); + cp = REALLOC_C_HEAP_ARRAY(char, path, len, mtArguments); char* cp_tmp = cp + old_len; *cp_tmp = separator; memcpy(++cp_tmp, str, str_len + 1); // copy the trailing null @@ -756,7 +758,7 @@ char* ArgumentBootClassPath::add_jars_to_path(char* path, const char* directory) /* Scan the directory for jars/zips, appending them to path. */ struct dirent *entry; - char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(directory), mtInternal); + char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(directory), mtArguments); while ((entry = os::readdir(dir, (dirent *) dbuf)) != NULL) { const char* name = entry->d_name; const char* ext = name + strlen(name) - 4; @@ -764,7 +766,7 @@ char* ArgumentBootClassPath::add_jars_to_path(char* path, const char* directory) (os::file_name_strcmp(ext, ".jar") == 0 || os::file_name_strcmp(ext, ".zip") == 0); if (isJarOrZip) { - char* jarpath = NEW_C_HEAP_ARRAY(char, directory_len + 2 + strlen(name), mtInternal); + char* jarpath = NEW_C_HEAP_ARRAY(char, directory_len + 2 + strlen(name), mtArguments); sprintf(jarpath, "%s%s%s", directory, dir_sep, name); path = add_to_path(path, jarpath, false); FREE_C_HEAP_ARRAY(char, jarpath); @@ -941,7 +943,7 @@ static bool append_to_string_flag(const char* name, const char* new_value, Flag: } else if (new_len == 0) { value = old_value; } else { - char* buf = NEW_C_HEAP_ARRAY(char, old_len + 1 + new_len + 1, mtInternal); + char* buf = NEW_C_HEAP_ARRAY(char, old_len + 1 + new_len + 1, mtArguments); // each new setting adds another LINE to the switch: sprintf(buf, "%s\n%s", old_value, new_value); value = buf; @@ -1132,9 +1134,9 @@ void Arguments::add_string(char*** bldarray, int* count, const char* arg) { // expand the array and add arg to the last element if (*bldarray == NULL) { - *bldarray = NEW_C_HEAP_ARRAY(char*, new_count, mtInternal); + *bldarray = NEW_C_HEAP_ARRAY(char*, new_count, mtArguments); } else { - *bldarray = REALLOC_C_HEAP_ARRAY(char*, *bldarray, new_count, mtInternal); + *bldarray = REALLOC_C_HEAP_ARRAY(char*, *bldarray, new_count, mtArguments); } (*bldarray)[*count] = os::strdup_check_oom(arg); *count = new_count; @@ -1398,7 +1400,7 @@ bool Arguments::add_property(const char* prop) { // property have a value, thus extract it and save to the // allocated string size_t key_len = eq - prop; - char* tmp_key = AllocateHeap(key_len + 1, mtInternal); + char* tmp_key = AllocateHeap(key_len + 1, mtArguments); strncpy(tmp_key, prop, key_len); tmp_key[key_len] = '\0'; @@ -1420,7 +1422,7 @@ bool Arguments::add_property(const char* prop) { } else { if (strcmp(key, "sun.java.command") == 0) { char *old_java_command = _java_command; - _java_command = os::strdup_check_oom(value, mtInternal); + _java_command = os::strdup_check_oom(value, mtArguments); if (old_java_command != NULL) { os::free(old_java_command); } @@ -1428,7 +1430,7 @@ bool Arguments::add_property(const char* prop) { const char* old_java_vendor_url_bug = _java_vendor_url_bug; // save it in _java_vendor_url_bug, so JVM fatal error handler can access // its value without going through the property list or making a Java call. - _java_vendor_url_bug = os::strdup_check_oom(value, mtInternal); + _java_vendor_url_bug = os::strdup_check_oom(value, mtArguments); if (old_java_vendor_url_bug != DEFAULT_VENDOR_URL_BUG) { assert(old_java_vendor_url_bug != NULL, "_java_vendor_url_bug is NULL"); os::free((void *)old_java_vendor_url_bug); @@ -1456,7 +1458,7 @@ bool Arguments::append_to_addmods_property(const char* module_name) { if (old_value != NULL) { buf_len += strlen(old_value) + 1; } - char* new_value = AllocateHeap(buf_len, mtInternal); + char* new_value = AllocateHeap(buf_len, mtArguments); if (new_value == NULL) { return false; } @@ -2093,8 +2095,8 @@ void Arguments::set_g1_gc_flags() { } #if INCLUDE_ALL_GCS - if (G1ConcRefinementThreads == 0) { - FLAG_SET_DEFAULT(G1ConcRefinementThreads, ParallelGCThreads); + if (FLAG_IS_DEFAULT(G1ConcRefinementThreads)) { + FLAG_SET_ERGO(uint, G1ConcRefinementThreads, ParallelGCThreads); } #endif @@ -2184,15 +2186,11 @@ void Arguments::set_heap_size() { if (!FLAG_IS_DEFAULT(HeapBaseMinAddress)) { if (HeapBaseMinAddress < DefaultHeapBaseMinAddress) { // matches compressed oops printing flags - if (PrintCompressedOopsMode || (PrintMiscellaneous && Verbose)) { - jio_fprintf(defaultStream::error_stream(), - "HeapBaseMinAddress must be at least " SIZE_FORMAT - " (" SIZE_FORMAT "G) which is greater than value given " - SIZE_FORMAT "\n", - DefaultHeapBaseMinAddress, - DefaultHeapBaseMinAddress/G, - HeapBaseMinAddress); - } + log_debug(gc, heap, coops)("HeapBaseMinAddress must be at least " SIZE_FORMAT + " (" SIZE_FORMAT "G) which is greater than value given " SIZE_FORMAT, + DefaultHeapBaseMinAddress, + DefaultHeapBaseMinAddress/G, + HeapBaseMinAddress); FLAG_SET_ERGO(size_t, HeapBaseMinAddress, DefaultHeapBaseMinAddress); } } @@ -2854,13 +2852,13 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, if (tail != NULL) { const char* pos = strchr(tail, ':'); size_t len = (pos == NULL) ? strlen(tail) : pos - tail; - char* name = (char*)memcpy(NEW_C_HEAP_ARRAY(char, len + 1, mtInternal), tail, len); + char* name = (char*)memcpy(NEW_C_HEAP_ARRAY(char, len + 1, mtArguments), tail, len); name[len] = '\0'; char *options = NULL; if(pos != NULL) { size_t len2 = strlen(pos+1) + 1; // options start after ':'. Final zero must be copied. - options = (char*)memcpy(NEW_C_HEAP_ARRAY(char, len2, mtInternal), pos+1, len2); + options = (char*)memcpy(NEW_C_HEAP_ARRAY(char, len2, mtArguments), pos+1, len2); } #if !INCLUDE_JVMTI if (strcmp(name, "jdwp") == 0) { @@ -2877,12 +2875,12 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, if(tail != NULL) { const char* pos = strchr(tail, '='); size_t len = (pos == NULL) ? strlen(tail) : pos - tail; - char* name = strncpy(NEW_C_HEAP_ARRAY(char, len + 1, mtInternal), tail, len); + char* name = strncpy(NEW_C_HEAP_ARRAY(char, len + 1, mtArguments), tail, len); name[len] = '\0'; char *options = NULL; if(pos != NULL) { - options = os::strdup_check_oom(pos + 1, mtInternal); + options = os::strdup_check_oom(pos + 1, mtArguments); } #if !INCLUDE_JVMTI if (valid_jdwp_agent(name, is_absolute_path)) { @@ -2901,7 +2899,7 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, return JNI_ERR; #else if (tail != NULL) { - char *options = strcpy(NEW_C_HEAP_ARRAY(char, strlen(tail) + 1, mtInternal), tail); + char *options = strcpy(NEW_C_HEAP_ARRAY(char, strlen(tail) + 1, mtArguments), tail); add_init_agent("instrument", options, false); // java agents need module java.instrument. Also -addmods ALL-SYSTEM because // the java agent is in the unmamed module of the application class loader @@ -3203,7 +3201,7 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, size_t len = strlen(patch_dirs[x]); if (len != 0) { // Ignore empty strings. len += 11; // file_sep + "java.base" + null terminator. - char* dir = NEW_C_HEAP_ARRAY(char, len, mtInternal); + char* dir = NEW_C_HEAP_ARRAY(char, len, mtArguments); jio_snprintf(dir, len, "%s%cjava.base", patch_dirs[x], file_sep); // See if Xpatch module path exists. @@ -3509,7 +3507,7 @@ void Arguments::fix_appclasspath() { src ++; } - char* copy = os::strdup_check_oom(src, mtInternal); + char* copy = os::strdup_check_oom(src, mtArguments); // trim all trailing empty paths for (char* tail = copy + strlen(copy) - 1; tail >= copy && *tail == separator; tail--) { @@ -3533,7 +3531,7 @@ static bool has_jar_files(const char* directory) { if (dir == NULL) return false; struct dirent *entry; - char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(directory), mtInternal); + char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(directory), mtArguments); bool hasJarFile = false; while (!hasJarFile && (entry = os::readdir(dir, (dirent *) dbuf)) != NULL) { const char* name = entry->d_name; @@ -3559,7 +3557,7 @@ static int check_non_empty_dirs(const char* path) { } path = end; } else { - char* dirpath = NEW_C_HEAP_ARRAY(char, tmp_end - path + 1, mtInternal); + char* dirpath = NEW_C_HEAP_ARRAY(char, tmp_end - path + 1, mtArguments); memcpy(dirpath, path, tmp_end - path); dirpath[tmp_end - path] = '\0'; if (has_jar_files(dirpath)) { @@ -3731,7 +3729,7 @@ class ScopedVMInitArgs : public StackObj { jint set_args(GrowableArray* options) { _is_set = true; JavaVMOption* options_arr = NEW_C_HEAP_ARRAY_RETURN_NULL( - JavaVMOption, options->length(), mtInternal); + JavaVMOption, options->length(), mtArguments); if (options_arr == NULL) { return JNI_ENOMEM; } @@ -3786,7 +3784,7 @@ class ScopedVMInitArgs : public StackObj { assert(vm_options_file_pos != -1, "vm_options_file_pos should be set"); int length = args->nOptions + args_to_insert->nOptions - 1; - GrowableArray *options = new (ResourceObj::C_HEAP, mtInternal) + GrowableArray *options = new (ResourceObj::C_HEAP, mtArguments) GrowableArray(length, true); // Construct new option array for (int i = 0; i < args->nOptions; i++) { if (i == vm_options_file_pos) { @@ -3863,7 +3861,7 @@ jint Arguments::parse_vm_options_file(const char* file_name, ScopedVMInitArgs* v // '+ 1' for NULL termination even with max bytes size_t bytes_alloc = stbuf.st_size + 1; - char *buf = NEW_C_HEAP_ARRAY_RETURN_NULL(char, bytes_alloc, mtInternal); + char *buf = NEW_C_HEAP_ARRAY_RETURN_NULL(char, bytes_alloc, mtArguments); if (NULL == buf) { jio_fprintf(defaultStream::error_stream(), "Could not allocate read buffer for options file parse\n"); @@ -3900,7 +3898,7 @@ jint Arguments::parse_vm_options_file(const char* file_name, ScopedVMInitArgs* v } jint Arguments::parse_options_buffer(const char* name, char* buffer, const size_t buf_len, ScopedVMInitArgs* vm_args) { - GrowableArray *options = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(2, true); // Construct option array + GrowableArray *options = new (ResourceObj::C_HEAP, mtArguments) GrowableArray(2, true); // Construct option array // some pointers to help with parsing char *buffer_end = buffer + buf_len; @@ -4004,13 +4002,13 @@ static char* get_shared_archive_path() { size_t jvm_path_len = strlen(jvm_path); size_t file_sep_len = strlen(os::file_separator()); const size_t len = jvm_path_len + file_sep_len + 20; - shared_archive_path = NEW_C_HEAP_ARRAY(char, len, mtInternal); + shared_archive_path = NEW_C_HEAP_ARRAY(char, len, mtArguments); if (shared_archive_path != NULL) { jio_snprintf(shared_archive_path, len, "%s%sclasses.jsa", jvm_path, os::file_separator()); } } else { - shared_archive_path = os::strdup_check_oom(SharedArchiveFile, mtInternal); + shared_archive_path = os::strdup_check_oom(SharedArchiveFile, mtArguments); } return shared_archive_path; } diff --git a/hotspot/src/share/vm/runtime/arguments.hpp b/hotspot/src/share/vm/runtime/arguments.hpp index 1dc3135aff630890f10e404024f773b307b0936a..4df23a5b48505b3f230d987ab9c05a4576f2d49b 100644 --- a/hotspot/src/share/vm/runtime/arguments.hpp +++ b/hotspot/src/share/vm/runtime/arguments.hpp @@ -31,7 +31,6 @@ #include "runtime/os.hpp" #include "runtime/perfData.hpp" #include "utilities/debug.hpp" -#include "utilities/top.hpp" // Arguments parses the command line and recognizes options @@ -48,7 +47,7 @@ class ArgumentBootClassPath; // PathString is used as the underlying value container for a // SystemProperty and for the string that represents the system // boot class path, Arguments::_system_boot_class_path. -class PathString : public CHeapObj { +class PathString : public CHeapObj { protected: char* _value; public: @@ -58,7 +57,7 @@ class PathString : public CHeapObj { if (_value != NULL) { FreeHeap(_value); } - _value = AllocateHeap(strlen(value)+1, mtInternal); + _value = AllocateHeap(strlen(value)+1, mtArguments); assert(_value != NULL, "Unable to allocate space for new path value"); if (_value != NULL) { strcpy(_value, value); @@ -77,7 +76,7 @@ class PathString : public CHeapObj { if (_value != NULL) { len += strlen(_value); } - sp = AllocateHeap(len+2, mtInternal); + sp = AllocateHeap(len+2, mtArguments); assert(sp != NULL, "Unable to allocate space for new append path value"); if (sp != NULL) { if (_value != NULL) { @@ -98,7 +97,7 @@ class PathString : public CHeapObj { if (value == NULL) { _value = NULL; } else { - _value = AllocateHeap(strlen(value)+1, mtInternal); + _value = AllocateHeap(strlen(value)+1, mtArguments); strcpy(_value, value); } } @@ -144,7 +143,7 @@ class SystemProperty : public PathString { if (key == NULL) { _key = NULL; } else { - _key = AllocateHeap(strlen(key)+1, mtInternal); + _key = AllocateHeap(strlen(key)+1, mtArguments); strcpy(_key, key); } _next = NULL; @@ -155,7 +154,7 @@ class SystemProperty : public PathString { // For use by -agentlib, -agentpath and -Xrun -class AgentLibrary : public CHeapObj { +class AgentLibrary : public CHeapObj { friend class AgentLibraryList; public: // Is this library valid or not. Don't rely on os_lib == NULL as statically @@ -190,12 +189,12 @@ public: // Constructor AgentLibrary(const char* name, const char* options, bool is_absolute_path, void* os_lib) { - _name = AllocateHeap(strlen(name)+1, mtInternal); + _name = AllocateHeap(strlen(name)+1, mtArguments); strcpy(_name, name); if (options == NULL) { _options = NULL; } else { - _options = AllocateHeap(strlen(options)+1, mtInternal); + _options = AllocateHeap(strlen(options)+1, mtArguments); strcpy(_options, options); } _is_absolute_path = is_absolute_path; diff --git a/hotspot/src/share/vm/runtime/basicLock.hpp b/hotspot/src/share/vm/runtime/basicLock.hpp index cc4e37eed52b7dec7d3b012976f78a7bde0436ef..f47c5add571a1da97e3d1a980a1a26e960fb3c26 100644 --- a/hotspot/src/share/vm/runtime/basicLock.hpp +++ b/hotspot/src/share/vm/runtime/basicLock.hpp @@ -27,7 +27,6 @@ #include "oops/markOop.hpp" #include "runtime/handles.hpp" -#include "utilities/top.hpp" class BasicLock VALUE_OBJ_CLASS_SPEC { friend class VMStructs; diff --git a/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.cpp b/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.cpp index 2e0139c39e5e74b17ff4ee14f9016e7da633f797..c79a48c9700a999416fc7dd2f52edeac9c9ea78e 100644 --- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.cpp +++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.cpp @@ -226,7 +226,7 @@ CommandLineFlagConstraint::ConstraintType CommandLineFlagConstraintList::_valida // Check the ranges of all flags that have them or print them out and exit if requested void CommandLineFlagConstraintList::init(void) { - _constraints = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(INITIAL_CONSTRAINTS_SIZE, true); + _constraints = new (ResourceObj::C_HEAP, mtArguments) GrowableArray(INITIAL_CONSTRAINTS_SIZE, true); emit_constraint_no(NULL RUNTIME_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG, EMIT_CONSTRAINT_PD_DEVELOPER_FLAG, diff --git a/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.hpp b/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.hpp index 5affa729c343e433be6f8f49cd9e8837d90b4ee6..e7df3e9d5512bcfe9a210bdec1f5d05685f6766d 100644 --- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.hpp +++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.hpp @@ -48,7 +48,7 @@ typedef Flag::Error (*CommandLineFlagConstraintFunc_uint64_t)(uint64_t value, bo typedef Flag::Error (*CommandLineFlagConstraintFunc_size_t)(size_t value, bool verbose); typedef Flag::Error (*CommandLineFlagConstraintFunc_double)(double value, bool verbose); -class CommandLineFlagConstraint : public CHeapObj { +class CommandLineFlagConstraint : public CHeapObj { public: // During VM initialization, constraint validation will be done order of ConstraintType. enum ConstraintType { diff --git a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.cpp b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.cpp index 4390644d708bb95eca9060859230b09180aa6c87..5dce24113afde948c7228be99c5271fe1240f13f 100644 --- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.cpp +++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.cpp @@ -457,6 +457,51 @@ Flag::Error MarkStackSizeConstraintFunc(size_t value, bool verbose) { } } +static Flag::Error CMSReservedAreaConstraintFunc(const char* name, size_t value, bool verbose) { +#if INCLUDE_ALL_GCS + if (UseConcMarkSweepGC) { + ConcurrentMarkSweepGeneration* cms = (ConcurrentMarkSweepGeneration*)GenCollectedHeap::heap()->old_gen(); + const size_t ergo_max = cms->cmsSpace()->max_flag_size_for_task_size(); + if (value > ergo_max) { + CommandLineError::print(verbose, + "%s (" SIZE_FORMAT ") must be " + "less than or equal to ergonomic maximum (" SIZE_FORMAT ") " + "which is based on the maximum size of the old generation of the Java heap\n", + name, value, ergo_max); + return Flag::VIOLATES_CONSTRAINT; + } + } +#endif + + return Flag::SUCCESS; +} + +Flag::Error CMSRescanMultipleConstraintFunc(size_t value, bool verbose) { + Flag::Error status = CMSReservedAreaConstraintFunc("CMSRescanMultiple", value, verbose); + +#if INCLUDE_ALL_GCS + if (status == Flag::SUCCESS && UseConcMarkSweepGC) { + // CMSParRemarkTask::do_dirty_card_rescan_tasks requires CompactibleFreeListSpace::rescan_task_size() + // to be aligned to CardTableModRefBS::card_size * BitsPerWord. + // Note that rescan_task_size() will be aligned if CMSRescanMultiple is a multiple of 'HeapWordSize' + // because rescan_task_size() is CardTableModRefBS::card_size / HeapWordSize * BitsPerWord. + if (value % HeapWordSize != 0) { + CommandLineError::print(verbose, + "CMSRescanMultiple (" SIZE_FORMAT ") must be " + "a multiple of " SIZE_FORMAT "\n", + value, HeapWordSize); + status = Flag::VIOLATES_CONSTRAINT; + } + } +#endif + + return status; +} + +Flag::Error CMSConcMarkMultipleConstraintFunc(size_t value, bool verbose) { + return CMSReservedAreaConstraintFunc("CMSConcMarkMultiple", value, verbose); +} + Flag::Error CMSPrecleanDenominatorConstraintFunc(uintx value, bool verbose) { #if INCLUDE_ALL_GCS if (UseConcMarkSweepGC && (value <= CMSPrecleanNumerator)) { diff --git a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.hpp b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.hpp index ee8bf3f668b6093a6fb8bf14125d481767f32245..9470a1c4ec4a5626d2d5ffe88dc5d4678cfccc18 100644 --- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.hpp +++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.hpp @@ -60,6 +60,8 @@ Flag::Error ParGCCardsPerStrideChunkConstraintFunc(intx value, bool verbose); Flag::Error CMSOldPLABMinConstraintFunc(size_t value, bool verbose); Flag::Error CMSOldPLABMaxConstraintFunc(size_t value, bool verbose); Flag::Error MarkStackSizeConstraintFunc(size_t value, bool verbose); +Flag::Error CMSRescanMultipleConstraintFunc(size_t value, bool verbose); +Flag::Error CMSConcMarkMultipleConstraintFunc(size_t value, bool verbose); Flag::Error CMSPrecleanDenominatorConstraintFunc(uintx value, bool verbose); Flag::Error CMSPrecleanNumeratorConstraintFunc(uintx value, bool verbose); Flag::Error CMSSamplingGrainConstraintFunc(uintx value, bool verbose); diff --git a/hotspot/src/share/vm/runtime/commandLineFlagRangeList.cpp b/hotspot/src/share/vm/runtime/commandLineFlagRangeList.cpp index 2af4847d67a71b19518d0c56392a580ea79856f5..89acace33f7ab3354b77315d50d0d20975f3597f 100644 --- a/hotspot/src/share/vm/runtime/commandLineFlagRangeList.cpp +++ b/hotspot/src/share/vm/runtime/commandLineFlagRangeList.cpp @@ -292,7 +292,7 @@ GrowableArray* CommandLineFlagRangeList::_ranges = NULL; // Check the ranges of all flags that have them void CommandLineFlagRangeList::init(void) { - _ranges = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(INITIAL_RANGES_SIZE, true); + _ranges = new (ResourceObj::C_HEAP, mtArguments) GrowableArray(INITIAL_RANGES_SIZE, true); emit_range_no(NULL RUNTIME_FLAGS(EMIT_RANGE_DEVELOPER_FLAG, EMIT_RANGE_PD_DEVELOPER_FLAG, diff --git a/hotspot/src/share/vm/runtime/commandLineFlagRangeList.hpp b/hotspot/src/share/vm/runtime/commandLineFlagRangeList.hpp index 4b2c1ea7caa13ec681e622edcdda1f6b6490681d..bc299d4f2a5864e5771221b8160d737e7c7f7284 100644 --- a/hotspot/src/share/vm/runtime/commandLineFlagRangeList.hpp +++ b/hotspot/src/share/vm/runtime/commandLineFlagRangeList.hpp @@ -44,7 +44,7 @@ public: static void print(bool verbose, const char* msg, ...); }; -class CommandLineFlagRange : public CHeapObj { +class CommandLineFlagRange : public CHeapObj { private: const char* _name; public: diff --git a/hotspot/src/share/vm/runtime/deoptimization.cpp b/hotspot/src/share/vm/runtime/deoptimization.cpp index 9c038d74c483f7cfdae4add82ab27cfbbc9ba8d0..d380bf6d518d4f0bfe07a9f7e37f873e23e83216 100644 --- a/hotspot/src/share/vm/runtime/deoptimization.cpp +++ b/hotspot/src/share/vm/runtime/deoptimization.cpp @@ -896,13 +896,25 @@ void Deoptimization::reassign_type_array_elements(frame* fr, RegisterMap* reg_ma break; } - case T_SHORT: case T_CHAR: // 2 bytes + case T_SHORT: assert(value->type() == T_INT, "Agreement."); val = value->get_int(); obj->short_at_put(index, (jshort)*((jint*)&val)); break; - case T_BOOLEAN: case T_BYTE: // 1 byte + case T_CHAR: + assert(value->type() == T_INT, "Agreement."); + val = value->get_int(); + obj->char_at_put(index, (jchar)*((jint*)&val)); + break; + + case T_BYTE: + assert(value->type() == T_INT, "Agreement."); + val = value->get_int(); + obj->byte_at_put(index, (jbyte)*((jint*)&val)); + break; + + case T_BOOLEAN: assert(value->type() == T_INT, "Agreement."); val = value->get_int(); obj->bool_at_put(index, (jboolean)*((jint*)&val)); @@ -1017,13 +1029,25 @@ static int reassign_fields_by_klass(InstanceKlass* klass, frame* fr, RegisterMap break; } - case T_SHORT: case T_CHAR: // 2 bytes + case T_SHORT: assert(value->type() == T_INT, "Agreement."); val = value->get_int(); obj->short_field_put(offset, (jshort)*((jint*)&val)); break; - case T_BOOLEAN: case T_BYTE: // 1 byte + case T_CHAR: + assert(value->type() == T_INT, "Agreement."); + val = value->get_int(); + obj->char_field_put(offset, (jchar)*((jint*)&val)); + break; + + case T_BYTE: + assert(value->type() == T_INT, "Agreement."); + val = value->get_int(); + obj->byte_field_put(offset, (jbyte)*((jint*)&val)); + break; + + case T_BOOLEAN: assert(value->type() == T_INT, "Agreement."); val = value->get_int(); obj->bool_field_put(offset, (jboolean)*((jint*)&val)); diff --git a/hotspot/src/share/vm/runtime/frame.hpp b/hotspot/src/share/vm/runtime/frame.hpp index cbd63cd20b29472e175fe00e15d19d85ac394722..0bb1d8750717ad3dd56bf5c39238f202805e7295 100644 --- a/hotspot/src/share/vm/runtime/frame.hpp +++ b/hotspot/src/share/vm/runtime/frame.hpp @@ -29,7 +29,6 @@ #include "runtime/basicLock.hpp" #include "runtime/monitorChunk.hpp" #include "runtime/registerMap.hpp" -#include "utilities/top.hpp" #ifdef TARGET_ARCH_zero # include "stack_zero.hpp" #endif diff --git a/hotspot/src/share/vm/runtime/globals.cpp b/hotspot/src/share/vm/runtime/globals.cpp index 1728da3e857678e4ff196ef5ba3b6ea8ef29437a..ef98dd77f9452ee8bfca25d0de9660a6126414b1 100644 --- a/hotspot/src/share/vm/runtime/globals.cpp +++ b/hotspot/src/share/vm/runtime/globals.cpp @@ -35,7 +35,6 @@ #include "trace/tracing.hpp" #include "utilities/macros.hpp" #include "utilities/ostream.hpp" -#include "utilities/top.hpp" #if INCLUDE_ALL_GCS #include "gc/g1/g1_globals.hpp" #endif // INCLUDE_ALL_GCS @@ -1293,7 +1292,7 @@ void CommandLineFlags::printSetFlags(outputStream* out) { const size_t length = Flag::numFlags - 1; // Sort - Flag** array = NEW_C_HEAP_ARRAY(Flag*, length, mtInternal); + Flag** array = NEW_C_HEAP_ARRAY(Flag*, length, mtArguments); for (size_t i = 0; i < length; i++) { array[i] = &flagTable[i]; } @@ -1327,7 +1326,7 @@ void CommandLineFlags::printFlags(outputStream* out, bool withComments, bool pri const size_t length = Flag::numFlags - 1; // Sort - Flag** array = NEW_C_HEAP_ARRAY(Flag*, length, mtInternal); + Flag** array = NEW_C_HEAP_ARRAY(Flag*, length, mtArguments); for (size_t i = 0; i < length; i++) { array[i] = &flagTable[i]; } diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index a5b73c81d90c189a9b34f26bfb8ca1531bf0dcd5..fe2d2e615f06910ce90ef48e3094087a62c791e7 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -641,9 +641,6 @@ public: "region.") \ range(1, max_uintx) \ \ - diagnostic(bool, PrintCompressedOopsMode, false, \ - "Print compressed oops base address and encoding mode") \ - \ lp64_product(intx, ObjectAlignmentInBytes, 8, \ "Default object alignment in bytes, 8 is minimum") \ range(8, 256) \ @@ -688,9 +685,6 @@ public: "Use large page memory in metaspace. " \ "Only used if UseLargePages is enabled.") \ \ - develop(bool, TracePageSizes, false, \ - "Trace page size selection and usage") \ - \ product(bool, UseNUMA, false, \ "Use NUMA if available") \ \ @@ -1809,13 +1803,17 @@ public: "enough work per iteration") \ range(0, max_intx) \ \ + /* 4096 = CardTableModRefBS::card_size_in_words * BitsPerWord */ \ product(size_t, CMSRescanMultiple, 32, \ "Size (in cards) of CMS parallel rescan task") \ - range(1, max_uintx) \ + range(1, SIZE_MAX / 4096) \ + constraint(CMSRescanMultipleConstraintFunc,AfterMemoryInit) \ \ + /* 4096 = CardTableModRefBS::card_size_in_words * BitsPerWord */ \ product(size_t, CMSConcMarkMultiple, 32, \ "Size (in cards) of CMS concurrent MT marking task") \ - range(1, max_uintx) \ + range(1, SIZE_MAX / 4096) \ + constraint(CMSConcMarkMultipleConstraintFunc,AfterMemoryInit) \ \ product(bool, CMSAbortSemantics, false, \ "Whether abort-on-overflow semantics is implemented") \ @@ -2954,9 +2952,6 @@ public: develop(bool, TraceStackWalk, false, \ "Trace stack walking") \ \ - product(bool, MemberNameInStackFrame, true, \ - "Use MemberName in StackFrame") \ - \ /* notice: the max range value here is max_jint, not max_intx */ \ /* because of overflow issue */ \ NOT_EMBEDDED(diagnostic(intx, GuaranteedSafepointInterval, 1000, \ diff --git a/hotspot/src/share/vm/runtime/globals_extension.hpp b/hotspot/src/share/vm/runtime/globals_extension.hpp index 45830e56623b21ff156173b27da6ca528f2727e4..b550f2360425d58caaa93e596ff62b2d6a42524e 100644 --- a/hotspot/src/share/vm/runtime/globals_extension.hpp +++ b/hotspot/src/share/vm/runtime/globals_extension.hpp @@ -27,7 +27,19 @@ #include "runtime/globals.hpp" #include "utilities/macros.hpp" -#include "utilities/top.hpp" +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS +#include "gc/g1/g1_globals.hpp" +#endif +#if INCLUDE_JVMCI +#include "jvmci/jvmci_globals.hpp" +#endif +#ifdef COMPILER1 +#include "c1/c1_globals.hpp" +#endif +#ifdef COMPILER2 +#include "opto/c2_globals.hpp" +#endif // Construct enum of Flag_ constants. diff --git a/hotspot/src/share/vm/runtime/init.hpp b/hotspot/src/share/vm/runtime/init.hpp index fd9fdf6f64a81a7c23f0ce03cf6abce15bb747b9..77158f5a937af47d795274a300c947a98b90e7f6 100644 --- a/hotspot/src/share/vm/runtime/init.hpp +++ b/hotspot/src/share/vm/runtime/init.hpp @@ -25,7 +25,7 @@ #ifndef SHARE_VM_RUNTIME_INIT_HPP #define SHARE_VM_RUNTIME_INIT_HPP -#include "utilities/top.hpp" +#include "utilities/globalDefinitions.hpp" // init_globals replaces C++ global objects so we can use the standard linker // to link Delta (which is at least twice as fast as using the GNU C++ linker). diff --git a/hotspot/src/share/vm/runtime/interfaceSupport.hpp b/hotspot/src/share/vm/runtime/interfaceSupport.hpp index 8dbc6be317cc98d9acac91fb0a2a336508618079..de3ef8f648b1d734debdb454c9e87faa6616f598 100644 --- a/hotspot/src/share/vm/runtime/interfaceSupport.hpp +++ b/hotspot/src/share/vm/runtime/interfaceSupport.hpp @@ -35,7 +35,6 @@ #include "runtime/vmThread.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/preserveException.hpp" -#include "utilities/top.hpp" // Wrapper for all entry points to the virtual machine. // The HandleMarkCleaner is a faster version of HandleMark. diff --git a/hotspot/src/share/vm/runtime/javaCalls.hpp b/hotspot/src/share/vm/runtime/javaCalls.hpp index 543e58f0dde2b5c1a2e518cc44b7079e3fb603f3..0d885686de84f81a7b340402daced0d32a772ff7 100644 --- a/hotspot/src/share/vm/runtime/javaCalls.hpp +++ b/hotspot/src/share/vm/runtime/javaCalls.hpp @@ -29,7 +29,7 @@ #include "oops/method.hpp" #include "runtime/handles.hpp" #include "runtime/javaFrameAnchor.hpp" -#include "runtime/thread.inline.hpp" +#include "runtime/thread.hpp" #include "runtime/vmThread.hpp" #ifdef TARGET_ARCH_x86 # include "jniTypes_x86.hpp" diff --git a/hotspot/src/share/vm/runtime/jniHandles.hpp b/hotspot/src/share/vm/runtime/jniHandles.hpp index 1503a3696b61adfb24d4ada4c7dec5c21c99a141..ce37d940d7c887ce5f37b97229ea1cd68b266493 100644 --- a/hotspot/src/share/vm/runtime/jniHandles.hpp +++ b/hotspot/src/share/vm/runtime/jniHandles.hpp @@ -25,8 +25,8 @@ #ifndef SHARE_VM_RUNTIME_JNIHANDLES_HPP #define SHARE_VM_RUNTIME_JNIHANDLES_HPP +#include "memory/allocation.hpp" #include "runtime/handles.hpp" -#include "utilities/top.hpp" class JNIHandleBlock; diff --git a/hotspot/src/share/vm/runtime/os.cpp b/hotspot/src/share/vm/runtime/os.cpp index 1644e43eb0e7b54f117a6d1f60de1420ed082f1d..ec10343626922a0aad8da55dd8f511fbc816fdec 100644 --- a/hotspot/src/share/vm/runtime/os.cpp +++ b/hotspot/src/share/vm/runtime/os.cpp @@ -33,6 +33,7 @@ #include "gc/shared/vmGCOperations.hpp" #include "interpreter/interpreter.hpp" #include "logging/log.hpp" +#include "logging/logStream.inline.hpp" #include "memory/allocation.inline.hpp" #ifdef ASSERT #include "memory/guardedMemory.hpp" @@ -1494,31 +1495,63 @@ const char* os::errno_name(int e) { return errno_to_string(e, true); } -#ifndef PRODUCT -void os::trace_page_sizes(const char* str, const size_t* page_sizes, int count) -{ - if (TracePageSizes) { - tty->print("%s: ", str); +void os::trace_page_sizes(const char* str, const size_t* page_sizes, int count) { + LogTarget(Info, pagesize) log; + if (log.is_enabled()) { + LogStreamCHeap out(log); + + out.print("%s: ", str); for (int i = 0; i < count; ++i) { - tty->print(" " SIZE_FORMAT, page_sizes[i]); + out.print(" " SIZE_FORMAT, page_sizes[i]); } - tty->cr(); - } + out.cr(); + } +} + +#define trace_page_size_params(size) byte_size_in_exact_unit(size), exact_unit_for_byte_size(size) + +void os::trace_page_sizes(const char* str, + const size_t region_min_size, + const size_t region_max_size, + const size_t page_size, + const char* base, + const size_t size) { + + log_info(pagesize)("%s: " + " min=" SIZE_FORMAT "%s" + " max=" SIZE_FORMAT "%s" + " base=" PTR_FORMAT + " page_size=" SIZE_FORMAT "%s" + " size=" SIZE_FORMAT "%s", + str, + trace_page_size_params(region_min_size), + trace_page_size_params(region_max_size), + p2i(base), + trace_page_size_params(page_size), + trace_page_size_params(size)); +} + +void os::trace_page_sizes_for_requested_size(const char* str, + const size_t requested_size, + const size_t page_size, + const size_t alignment, + const char* base, + const size_t size) { + + log_info(pagesize)("%s:" + " req_size=" SIZE_FORMAT "%s" + " base=" PTR_FORMAT + " page_size=" SIZE_FORMAT "%s" + " alignment=" SIZE_FORMAT "%s" + " size=" SIZE_FORMAT "%s", + str, + trace_page_size_params(requested_size), + p2i(base), + trace_page_size_params(page_size), + trace_page_size_params(alignment), + trace_page_size_params(size)); } -void os::trace_page_sizes(const char* str, const size_t region_min_size, - const size_t region_max_size, const size_t page_size, - const char* base, const size_t size) -{ - if (TracePageSizes) { - tty->print_cr("%s: min=" SIZE_FORMAT " max=" SIZE_FORMAT - " pg_sz=" SIZE_FORMAT " base=" PTR_FORMAT - " size=" SIZE_FORMAT, - str, region_min_size, region_max_size, - page_size, p2i(base), size); - } -} -#endif // #ifndef PRODUCT // This is the working definition of a server class machine: // >= 2 physical CPU's and >=2GB of memory, with some fuzz diff --git a/hotspot/src/share/vm/runtime/os.hpp b/hotspot/src/share/vm/runtime/os.hpp index 04b19698cf343d351fb45d840530bc2f0aa6f25c..d1ac2b45870e532176a95f597525b0bccdc85575 100644 --- a/hotspot/src/share/vm/runtime/os.hpp +++ b/hotspot/src/share/vm/runtime/os.hpp @@ -28,7 +28,6 @@ #include "jvmtifiles/jvmti.h" #include "runtime/extendedPC.hpp" #include "runtime/handles.hpp" -#include "utilities/top.hpp" #ifdef TARGET_OS_FAMILY_linux # include "jvm_linux.h" # include @@ -286,18 +285,24 @@ class os: AllStatic { return _page_sizes[0]; } - // Methods for tracing page sizes returned by the above method; enabled by - // TracePageSizes. The region_{min,max}_size parameters should be the values + // Methods for tracing page sizes returned by the above method. + // The region_{min,max}_size parameters should be the values // passed to page_size_for_region() and page_size should be the result of that // call. The (optional) base and size parameters should come from the // ReservedSpace base() and size() methods. - static void trace_page_sizes(const char* str, const size_t* page_sizes, - int count) PRODUCT_RETURN; - static void trace_page_sizes(const char* str, const size_t region_min_size, + static void trace_page_sizes(const char* str, const size_t* page_sizes, int count); + static void trace_page_sizes(const char* str, + const size_t region_min_size, const size_t region_max_size, const size_t page_size, - const char* base = NULL, - const size_t size = 0) PRODUCT_RETURN; + const char* base, + const size_t size); + static void trace_page_sizes_for_requested_size(const char* str, + const size_t requested_size, + const size_t page_size, + const size_t alignment, + const char* base, + const size_t size); static int vm_allocation_granularity(); static char* reserve_memory(size_t bytes, char* addr = 0, @@ -515,6 +520,9 @@ class os: AllStatic { static int ftruncate(int fd, jlong length); static int fsync(int fd); static int available(int fd, jlong *bytes); + static int fileno(FILE* fp); + + static int compare_file_modified_times(const char* file1, const char* file2); //File i/o operations diff --git a/hotspot/src/share/vm/runtime/osThread.hpp b/hotspot/src/share/vm/runtime/osThread.hpp index 29912bd5187130d13b21171b71293addad1b3bdc..16cc2e8055e754400347a870b7f30bf2e45072bf 100644 --- a/hotspot/src/share/vm/runtime/osThread.hpp +++ b/hotspot/src/share/vm/runtime/osThread.hpp @@ -29,7 +29,6 @@ #include "runtime/handles.hpp" #include "runtime/javaFrameAnchor.hpp" #include "runtime/objectMonitor.hpp" -#include "utilities/top.hpp" // The OSThread class holds OS-specific thread information. It is equivalent // to the sys_thread_t structure of the classic JVM implementation. diff --git a/hotspot/src/share/vm/runtime/reflection.cpp b/hotspot/src/share/vm/runtime/reflection.cpp index 1832711848b6b78df2c5e37b4ba310093e4e8896..625d55830dee9876b80d52bb2fea44774851d49d 100644 --- a/hotspot/src/share/vm/runtime/reflection.cpp +++ b/hotspot/src/share/vm/runtime/reflection.cpp @@ -1025,7 +1025,7 @@ static BasicType basic_type_mirror_to_basic_type(oop basic_type_mirror, TRAPS) { static void narrow(jvalue* value, BasicType narrow_type, TRAPS) { switch (narrow_type) { case T_BOOLEAN: - value->z = (jboolean)value->i; + value->z = (jboolean) (value->i & 1); return; case T_BYTE: value->b = (jbyte)value->i; diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.cpp b/hotspot/src/share/vm/runtime/sharedRuntime.cpp index 89d0f2c66d38ab9ceac80c763097815f0572a565..d38d493f19848d8c7cc48a4884b36bf20a4c2701 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp @@ -38,6 +38,7 @@ #include "interpreter/interpreter.hpp" #include "interpreter/interpreterRuntime.hpp" #include "logging/log.hpp" +#include "memory/metaspaceShared.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.inline.hpp" #include "oops/klass.hpp" @@ -1788,7 +1789,7 @@ void SharedRuntime::check_member_name_argument_is_last_argument(const methodHand IRT_LEAF(void, SharedRuntime::fixup_callers_callsite(Method* method, address caller_pc)) Method* moop(method); - address entry_point = moop->from_compiled_entry(); + address entry_point = moop->from_compiled_entry_no_trampoline(); // It's possible that deoptimization can occur at a call site which hasn't // been resolved yet, in which case this function will be called from @@ -2351,12 +2352,15 @@ class AdapterHandlerTable : public BasicHashtable { public: AdapterHandlerTable() - : BasicHashtable(293, sizeof(AdapterHandlerEntry)) { } + : BasicHashtable(293, (DumpSharedSpaces ? sizeof(CDSAdapterHandlerEntry) : sizeof(AdapterHandlerEntry))) { } // Create a new entry suitable for insertion in the table AdapterHandlerEntry* new_entry(AdapterFingerPrint* fingerprint, address i2c_entry, address c2i_entry, address c2i_unverified_entry) { AdapterHandlerEntry* entry = (AdapterHandlerEntry*)BasicHashtable::new_entry(fingerprint->compute_hash()); entry->init(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry); + if (DumpSharedSpaces) { + ((CDSAdapterHandlerEntry*)entry)->init(); + } return entry; } @@ -2519,6 +2523,28 @@ AdapterHandlerEntry* AdapterHandlerLibrary::new_entry(AdapterFingerPrint* finger } AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(const methodHandle& method) { + AdapterHandlerEntry* entry = get_adapter0(method); + if (method->is_shared()) { + MutexLocker mu(AdapterHandlerLibrary_lock); + if (method->adapter() == NULL) { + method->update_adapter_trampoline(entry); + } + address trampoline = method->from_compiled_entry(); + if (*(int*)trampoline == 0) { + CodeBuffer buffer(trampoline, (int)SharedRuntime::trampoline_size()); + MacroAssembler _masm(&buffer); + SharedRuntime::generate_trampoline(&_masm, entry->get_c2i_entry()); + + if (PrintInterpreter) { + Disassembler::decode(buffer.insts_begin(), buffer.insts_end()); + } + } + } + + return entry; +} + +AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter0(const methodHandle& method) { // Use customized signature handler. Need to lock around updates to // the AdapterHandlerTable (it is not safe for concurrent readers // and a single writer: this could be fixed if it becomes a @@ -2535,7 +2561,9 @@ AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(const methodHandle& meth // make sure data structure is initialized initialize(); - if (CodeCacheExtensions::skip_compiler_support()) { + // during dump time, always generate adapters, even if the + // compiler has been turned off. + if (!DumpSharedSpaces && CodeCacheExtensions::skip_compiler_support()) { // adapters are useless and should not be used, including the // abstract_method_handler. However, some callers check that // an adapter was installed. @@ -3017,6 +3045,17 @@ void AdapterHandlerEntry::print_adapter_on(outputStream* st) const { } +#if INCLUDE_CDS + +void CDSAdapterHandlerEntry::init() { + assert(DumpSharedSpaces, "used during dump time only"); + _c2i_entry_trampoline = (address)MetaspaceShared::misc_data_space_alloc(SharedRuntime::trampoline_size()); + _adapter_trampoline = (AdapterHandlerEntry**)MetaspaceShared::misc_data_space_alloc(sizeof(AdapterHandlerEntry*)); +}; + +#endif // INCLUDE_CDS + + #ifndef PRODUCT void AdapterHandlerLibrary::print_statistics() { diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.hpp b/hotspot/src/share/vm/runtime/sharedRuntime.hpp index b3f87cdc7c6365a385a71c5dbd1a2c9878145469..68baebc4686ad89fc6567cae39c788fae7d17b50 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp @@ -398,6 +398,10 @@ class SharedRuntime: AllStatic { static void convert_ints_to_longints(int i2l_argcnt, int& in_args_count, BasicType*& in_sig_bt, VMRegPair*& in_regs); + static size_t trampoline_size(); + + static void generate_trampoline(MacroAssembler *masm, address destination); + // Generate I2C and C2I adapters. These adapters are simple argument marshalling // blobs. Unlike adapters in the tiger and earlier releases the code in these // blobs does not create a new frame and are therefore virtually invisible @@ -680,6 +684,17 @@ class AdapterHandlerEntry : public BasicHashtableEntry { void print_adapter_on(outputStream* st) const; }; +class CDSAdapterHandlerEntry: public AdapterHandlerEntry { + address _c2i_entry_trampoline; // allocated from shared spaces "MC" region + AdapterHandlerEntry** _adapter_trampoline; // allocated from shared spaces "MD" region + +public: + address get_c2i_entry_trampoline() const { return _c2i_entry_trampoline; } + AdapterHandlerEntry** get_adapter_trampoline() const { return _adapter_trampoline; } + void init() NOT_CDS_RETURN; +}; + + class AdapterHandlerLibrary: public AllStatic { private: static BufferBlob* _buffer; // the temporary code buffer in CodeCache @@ -687,6 +702,7 @@ class AdapterHandlerLibrary: public AllStatic { static AdapterHandlerEntry* _abstract_method_handler; static BufferBlob* buffer_blob(); static void initialize(); + static AdapterHandlerEntry* get_adapter0(const methodHandle& method); public: diff --git a/hotspot/src/share/vm/runtime/signature.hpp b/hotspot/src/share/vm/runtime/signature.hpp index 46e36e9f5324e74b55fa97405322f0e38dd94dca..3e0bb829cfc0b8723498b8e7ee015e7e7c885c77 100644 --- a/hotspot/src/share/vm/runtime/signature.hpp +++ b/hotspot/src/share/vm/runtime/signature.hpp @@ -27,7 +27,6 @@ #include "memory/allocation.hpp" #include "oops/method.hpp" -#include "utilities/top.hpp" // SignatureIterators iterate over a Java signature (or parts of it). // (Syntax according to: "The Java Virtual Machine Specification" by diff --git a/hotspot/src/share/vm/runtime/stackValue.hpp b/hotspot/src/share/vm/runtime/stackValue.hpp index a7698f50b7490037b7a56eb612461a0809872f06..569ef58f89a30cdda3ca61ca5603814705652dd4 100644 --- a/hotspot/src/share/vm/runtime/stackValue.hpp +++ b/hotspot/src/share/vm/runtime/stackValue.hpp @@ -27,7 +27,6 @@ #include "code/location.hpp" #include "runtime/handles.hpp" -#include "utilities/top.hpp" class StackValue : public ResourceObj { private: diff --git a/hotspot/src/share/vm/runtime/stubRoutines.hpp b/hotspot/src/share/vm/runtime/stubRoutines.hpp index 38fe86e631ba00fd615ac2e2faa5ecd0097e77ab..55cd9934bd00830f8fdc1bc17fbeaa730ccc8c1e 100644 --- a/hotspot/src/share/vm/runtime/stubRoutines.hpp +++ b/hotspot/src/share/vm/runtime/stubRoutines.hpp @@ -30,7 +30,6 @@ #include "runtime/frame.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/stubCodeGenerator.hpp" -#include "utilities/top.hpp" // StubRoutines provides entry points to assembly routines used by // compiled code and the run-time system. Platform-specific entry diff --git a/hotspot/src/share/vm/runtime/synchronizer.hpp b/hotspot/src/share/vm/runtime/synchronizer.hpp index ab3d145842ca45201ad9b926699c8416894a00a3..777317b927cd8626b59bfdcef7d99851329ca252 100644 --- a/hotspot/src/share/vm/runtime/synchronizer.hpp +++ b/hotspot/src/share/vm/runtime/synchronizer.hpp @@ -29,8 +29,6 @@ #include "runtime/basicLock.hpp" #include "runtime/handles.hpp" #include "runtime/perfData.hpp" -#include "utilities/top.hpp" - class ObjectMonitor; diff --git a/hotspot/src/share/vm/runtime/task.hpp b/hotspot/src/share/vm/runtime/task.hpp index c7181089ee20704e423eb386101b482069620fc1..b3e5f927aee21b4ec3a2a7c4067391e9b4951357 100644 --- a/hotspot/src/share/vm/runtime/task.hpp +++ b/hotspot/src/share/vm/runtime/task.hpp @@ -25,7 +25,8 @@ #ifndef SHARE_VM_RUNTIME_TASK_HPP #define SHARE_VM_RUNTIME_TASK_HPP -#include "utilities/top.hpp" +#include "memory/allocation.hpp" +#include "runtime/timer.hpp" // A PeriodicTask has the sole purpose of executing its task // function with regular intervals. diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index b08d6b6b1f25560e5cace36d2461d8ff062e37c1..719eb74b0188ad864ab390979b1883544c273adb 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -818,13 +818,17 @@ void Thread::print_on(outputStream* st) const { // Thread::print_on_error() is called by fatal error handler. Don't use // any lock or allocate memory. void Thread::print_on_error(outputStream* st, char* buf, int buflen) const { - if (is_VM_thread()) st->print("VMThread"); - else if (is_Compiler_thread()) st->print("CompilerThread"); - else if (is_Java_thread()) st->print("JavaThread"); - else if (is_GC_task_thread()) st->print("GCTaskThread"); - else if (is_Watcher_thread()) st->print("WatcherThread"); - else if (is_ConcurrentGC_thread()) st->print("ConcurrentGCThread"); - else st->print("Thread"); + assert(!(is_Compiler_thread() || is_Java_thread()), "Can't call name() here if it allocates"); + + if (is_VM_thread()) { st->print("VMThread"); } + else if (is_GC_task_thread()) { st->print("GCTaskThread"); } + else if (is_Watcher_thread()) { st->print("WatcherThread"); } + else if (is_ConcurrentGC_thread()) { st->print("ConcurrentGCThread"); } + else { st->print("Thread"); } + + if (is_Named_thread()) { + st->print(" \"%s\"", name()); + } st->print(" [stack: " PTR_FORMAT "," PTR_FORMAT "]", p2i(stack_end()), p2i(stack_base())); @@ -4498,6 +4502,36 @@ void Threads::print_on(outputStream* st, bool print_stacks, st->flush(); } +void Threads::print_on_error(Thread* this_thread, outputStream* st, Thread* current, char* buf, + int buflen, bool* found_current) { + if (this_thread != NULL) { + bool is_current = (current == this_thread); + *found_current = *found_current || is_current; + st->print("%s", is_current ? "=>" : " "); + + st->print(PTR_FORMAT, p2i(this_thread)); + st->print(" "); + this_thread->print_on_error(st, buf, buflen); + st->cr(); + } +} + +class PrintOnErrorClosure : public ThreadClosure { + outputStream* _st; + Thread* _current; + char* _buf; + int _buflen; + bool* _found_current; + public: + PrintOnErrorClosure(outputStream* st, Thread* current, char* buf, + int buflen, bool* found_current) : + _st(st), _current(current), _buf(buf), _buflen(buflen), _found_current(found_current) {} + + virtual void do_thread(Thread* thread) { + Threads::print_on_error(thread, _st, _current, _buf, _buflen, _found_current); + } +}; + // Threads::print_on_error() is called by fatal error handler. It's possible // that VM is not at safepoint and/or current thread is inside signal handler. // Don't print stack trace, as the stack may not be walkable. Don't allocate @@ -4507,40 +4541,17 @@ void Threads::print_on_error(outputStream* st, Thread* current, char* buf, bool found_current = false; st->print_cr("Java Threads: ( => current thread )"); ALL_JAVA_THREADS(thread) { - bool is_current = (current == thread); - found_current = found_current || is_current; - - st->print("%s", is_current ? "=>" : " "); - - st->print(PTR_FORMAT, p2i(thread)); - st->print(" "); - thread->print_on_error(st, buf, buflen); - st->cr(); + print_on_error(thread, st, current, buf, buflen, &found_current); } st->cr(); st->print_cr("Other Threads:"); - if (VMThread::vm_thread()) { - bool is_current = (current == VMThread::vm_thread()); - found_current = found_current || is_current; - st->print("%s", current == VMThread::vm_thread() ? "=>" : " "); + print_on_error(VMThread::vm_thread(), st, current, buf, buflen, &found_current); + print_on_error(WatcherThread::watcher_thread(), st, current, buf, buflen, &found_current); - st->print(PTR_FORMAT, p2i(VMThread::vm_thread())); - st->print(" "); - VMThread::vm_thread()->print_on_error(st, buf, buflen); - st->cr(); - } - WatcherThread* wt = WatcherThread::watcher_thread(); - if (wt != NULL) { - bool is_current = (current == wt); - found_current = found_current || is_current; - st->print("%s", is_current ? "=>" : " "); + PrintOnErrorClosure print_closure(st, current, buf, buflen, &found_current); + Universe::heap()->gc_threads_do(&print_closure); - st->print(PTR_FORMAT, p2i(wt)); - st->print(" "); - wt->print_on_error(st, buf, buflen); - st->cr(); - } if (!found_current) { st->cr(); st->print("=>" PTR_FORMAT " (exited) ", p2i(current)); diff --git a/hotspot/src/share/vm/runtime/thread.hpp b/hotspot/src/share/vm/runtime/thread.hpp index 4f993ab8fa181d401eee1932646d3f8fa02edab8..f5d7ac5b74d61d843c098b0fd75e4e1e3828e586 100644 --- a/hotspot/src/share/vm/runtime/thread.hpp +++ b/hotspot/src/share/vm/runtime/thread.hpp @@ -46,7 +46,6 @@ #include "trace/traceMacros.hpp" #include "utilities/exceptions.hpp" #include "utilities/macros.hpp" -#include "utilities/top.hpp" #if INCLUDE_ALL_GCS #include "gc/g1/dirtyCardQueue.hpp" #include "gc/g1/satbMarkQueue.hpp" @@ -2157,6 +2156,8 @@ class Threads: AllStatic { print_on(tty, print_stacks, internal_format, false /* no concurrent lock printed */); } static void print_on_error(outputStream* st, Thread* current, char* buf, int buflen); + static void print_on_error(Thread* this_thread, outputStream* st, Thread* current, char* buf, + int buflen, bool* found_current); static void print_threads_compiling(outputStream* st, char* buf, int buflen); // Get Java threads that are waiting to enter a monitor. If doLock diff --git a/hotspot/src/share/vm/runtime/threadLocalStorage.hpp b/hotspot/src/share/vm/runtime/threadLocalStorage.hpp index 016e1fc119674fb90ccca0ccc837a2e7dbb38d51..fbd370ed867529648ceef21659036ac94055bbc8 100644 --- a/hotspot/src/share/vm/runtime/threadLocalStorage.hpp +++ b/hotspot/src/share/vm/runtime/threadLocalStorage.hpp @@ -25,7 +25,7 @@ #ifndef SHARE_VM_RUNTIME_THREADLOCALSTORAGE_HPP #define SHARE_VM_RUNTIME_THREADLOCALSTORAGE_HPP -#include "utilities/top.hpp" +#include "memory/allocation.hpp" // forward-decl as we can't have an include cycle class Thread; diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index 0e9c451a621a4a43aade9f4d85f873083587ed06..3cd5d1687cb1fd6bde8915d60afd9a3707b4e060 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -400,7 +400,6 @@ typedef CompactHashtable SymbolCompactHashTable; nonproduct_nonstatic_field(Method, _compiled_invocation_count, int) \ volatile_nonstatic_field(Method, _code, nmethod*) \ nonstatic_field(Method, _i2i_entry, address) \ - nonstatic_field(Method, _adapter, AdapterHandlerEntry*) \ volatile_nonstatic_field(Method, _from_compiled_entry, address) \ volatile_nonstatic_field(Method, _from_interpreted_entry, address) \ volatile_nonstatic_field(ConstMethod, _fingerprint, uint64_t) \ diff --git a/hotspot/src/share/vm/runtime/vmThread.hpp b/hotspot/src/share/vm/runtime/vmThread.hpp index 43147e53c36104a9aca10a492b3a5f6c036ea741..692fbdd164df72761c93f6548129c452e237fe16 100644 --- a/hotspot/src/share/vm/runtime/vmThread.hpp +++ b/hotspot/src/share/vm/runtime/vmThread.hpp @@ -26,7 +26,7 @@ #define SHARE_VM_RUNTIME_VMTHREAD_HPP #include "runtime/perfData.hpp" -#include "runtime/thread.inline.hpp" +#include "runtime/thread.hpp" #include "runtime/vm_operations.hpp" // diff --git a/hotspot/src/share/vm/runtime/vm_operations.hpp b/hotspot/src/share/vm/runtime/vm_operations.hpp index 22626d2c2a8194f4bf772df5d7401f1aa8c18f0a..2807768339fac0bd92492dcb0cba526d1d31695c 100644 --- a/hotspot/src/share/vm/runtime/vm_operations.hpp +++ b/hotspot/src/share/vm/runtime/vm_operations.hpp @@ -29,7 +29,6 @@ #include "memory/allocation.hpp" #include "oops/oop.hpp" #include "runtime/thread.hpp" -#include "utilities/top.hpp" #include "code/codeCache.hpp" // The following classes are used for operations diff --git a/hotspot/src/share/vm/runtime/vm_version.cpp b/hotspot/src/share/vm/runtime/vm_version.cpp index cf2bf5a464463d99f1d6d1a350562ab868c5076a..c36098a31f7d7d7b0754a02ce74f52c083bc6014 100644 --- a/hotspot/src/share/vm/runtime/vm_version.cpp +++ b/hotspot/src/share/vm/runtime/vm_version.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "code/codeCacheExtensions.hpp" +#include "logging/log.hpp" #include "memory/universe.hpp" #include "oops/oop.inline.hpp" #include "runtime/arguments.hpp" @@ -274,12 +275,12 @@ unsigned int Abstract_VM_Version::jvm_version() { void VM_Version_init() { VM_Version::initialize(); -#ifndef PRODUCT - if (PrintMiscellaneous && Verbose) { - char buf[512]; - os::print_cpu_info(tty, buf, sizeof(buf)); + if (log_is_enabled(Info, os, cpu)) { + char buf[1024]; + ResourceMark rm; + outputStream* log = Log(os, cpu)::info_stream(); + os::print_cpu_info(log, buf, sizeof(buf)); } -#endif } unsigned int Abstract_VM_Version::nof_parallel_worker_threads( diff --git a/hotspot/src/share/vm/services/nmtCommon.cpp b/hotspot/src/share/vm/services/nmtCommon.cpp index cffce8c709954327141ebcfb1b0cae995297e8c8..8633bbe301eb4f07243862be8efb315ae15562c2 100644 --- a/hotspot/src/share/vm/services/nmtCommon.cpp +++ b/hotspot/src/share/vm/services/nmtCommon.cpp @@ -41,6 +41,7 @@ const char* NMTUtil::_memory_type_names[] = { "Test", "Tracing", "Logging", + "Arguments", "Unknown" }; diff --git a/hotspot/src/share/vm/utilities/accessFlags.hpp b/hotspot/src/share/vm/utilities/accessFlags.hpp index 8e9219fe8bcd8e5d1b42a28db4ee39592f88eda9..d9c1685e2b90204011d84a177c4dcb956853de35 100644 --- a/hotspot/src/share/vm/utilities/accessFlags.hpp +++ b/hotspot/src/share/vm/utilities/accessFlags.hpp @@ -25,8 +25,9 @@ #ifndef SHARE_VM_UTILITIES_ACCESSFLAGS_HPP #define SHARE_VM_UTILITIES_ACCESSFLAGS_HPP +#include "memory/allocation.hpp" #include "prims/jvm.h" -#include "utilities/top.hpp" +#include "utilities/macros.hpp" // AccessFlags is an abstraction over Java access flags. diff --git a/hotspot/src/share/vm/utilities/bitMap.cpp b/hotspot/src/share/vm/utilities/bitMap.cpp index fced8fbb522a5d9ec8b049b90548beeaee66113a..bb7ae8ede14e8afb686e24be58b8a87c6c4cab92 100644 --- a/hotspot/src/share/vm/utilities/bitMap.cpp +++ b/hotspot/src/share/vm/utilities/bitMap.cpp @@ -68,6 +68,10 @@ void BitMap::resize(idx_t size_in_bits, bool in_resource_area) { } } +void BitMap::pretouch() { + os::pretouch_memory(word_addr(0), word_addr(size())); +} + void BitMap::set_range_within_word(idx_t beg, idx_t end) { // With a valid range (beg <= end), this test ensures that end != 0, as // required by inverted_bit_mask_for_range. Also avoids an unnecessary write. diff --git a/hotspot/src/share/vm/utilities/bitMap.hpp b/hotspot/src/share/vm/utilities/bitMap.hpp index e57264b2e9aa3ad50363725722fb1cac7465d257..b41cc12062e5db58d2b64955bdd902f0a851bf31 100644 --- a/hotspot/src/share/vm/utilities/bitMap.hpp +++ b/hotspot/src/share/vm/utilities/bitMap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,6 @@ #define SHARE_VM_UTILITIES_BITMAP_HPP #include "memory/allocation.hpp" -#include "utilities/top.hpp" // Forward decl; class BitMapClosure; @@ -135,10 +134,18 @@ class BitMap VALUE_OBJ_CLASS_SPEC { // use the same value for "in_resource_area".) void resize(idx_t size_in_bits, bool in_resource_area = true); + // Pretouch the entire range of memory this BitMap covers. + void pretouch(); + // Accessing idx_t size() const { return _size; } + idx_t size_in_bytes() const { return size_in_words() * BytesPerWord; } idx_t size_in_words() const { - return word_index(size() + BitsPerWord - 1); + return calc_size_in_words(size()); + } + + static idx_t calc_size_in_words(size_t size_in_bits) { + return word_index(size_in_bits + BitsPerWord - 1); } bool at(idx_t index) const { diff --git a/hotspot/src/share/vm/utilities/constantTag.cpp b/hotspot/src/share/vm/utilities/constantTag.cpp index 1495a42e6243092f96795d68421fd6bc2b044ec3..187bb5ed20078ed05d5cd3b969440b3a2ff4f3d7 100644 --- a/hotspot/src/share/vm/utilities/constantTag.cpp +++ b/hotspot/src/share/vm/utilities/constantTag.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "utilities/constantTag.hpp" +#include "utilities/ostream.hpp" #ifndef PRODUCT diff --git a/hotspot/src/share/vm/utilities/constantTag.hpp b/hotspot/src/share/vm/utilities/constantTag.hpp index ae99d5706935d1e6989ff76b99c94f4bbf95d9c6..c083848c0bd9e4292984cac5e283065c84a46d29 100644 --- a/hotspot/src/share/vm/utilities/constantTag.hpp +++ b/hotspot/src/share/vm/utilities/constantTag.hpp @@ -25,8 +25,8 @@ #ifndef SHARE_VM_UTILITIES_CONSTANTTAG_HPP #define SHARE_VM_UTILITIES_CONSTANTTAG_HPP +#include "memory/allocation.hpp" #include "prims/jvm.h" -#include "utilities/top.hpp" // constant tags in Java .class files diff --git a/hotspot/src/share/vm/utilities/debug.cpp b/hotspot/src/share/vm/utilities/debug.cpp index f6fd336bca85b4c606f04b0d78b2ccd606678059..ad1e9e43a78ce98ea10dde17a24be7040e1fbff2 100644 --- a/hotspot/src/share/vm/utilities/debug.cpp +++ b/hotspot/src/share/vm/utilities/debug.cpp @@ -52,7 +52,6 @@ #include "utilities/defaultStream.hpp" #include "utilities/events.hpp" #include "utilities/macros.hpp" -#include "utilities/top.hpp" #include "utilities/vmError.hpp" #if INCLUDE_TRACE diff --git a/hotspot/src/share/vm/utilities/events.hpp b/hotspot/src/share/vm/utilities/events.hpp index 5b65fcc1a6ffcd1fd53082d062ddc491d63ca41a..3ff1e52a1b4f3226c84953440d047908a456f5fd 100644 --- a/hotspot/src/share/vm/utilities/events.hpp +++ b/hotspot/src/share/vm/utilities/events.hpp @@ -28,7 +28,6 @@ #include "memory/allocation.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/thread.hpp" -#include "utilities/top.hpp" #include "utilities/vmError.hpp" // Events and EventMark provide interfaces to log events taking place in the vm. diff --git a/hotspot/src/share/vm/utilities/exceptions.hpp b/hotspot/src/share/vm/utilities/exceptions.hpp index cdfa0bdf817ff08d9777e063f1d523657eae0183..e7aaf800237ab47ff582d47567d542cb30477f75 100644 --- a/hotspot/src/share/vm/utilities/exceptions.hpp +++ b/hotspot/src/share/vm/utilities/exceptions.hpp @@ -47,7 +47,6 @@ // Forward declarations to be independent of the include structure. -// This allows us to have exceptions.hpp included in top.hpp. class Thread; class Handle; diff --git a/hotspot/src/share/vm/utilities/globalDefinitions.cpp b/hotspot/src/share/vm/utilities/globalDefinitions.cpp index 98abb71dbe1876f6889d1e9c10e6979cb97fa8d8..7f69396d84d342a421cdb830d6b655075ddde1df 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions.cpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions.cpp @@ -25,7 +25,6 @@ #include "precompiled.hpp" #include "runtime/os.hpp" #include "utilities/globalDefinitions.hpp" -#include "utilities/top.hpp" // Basic error support @@ -374,39 +373,89 @@ STATIC_ASSERT(left_n_bits(1|2) == (intptr_t) LP64_ONLY(0xE000000000000000) NOT_L #ifndef PRODUCT // For unit testing only -class GlobalDefinitions { -public: - static void test_globals(); -}; +class TestGlobalDefinitions { +private: -void GlobalDefinitions::test_globals() { - intptr_t page_sizes[] = { os::vm_page_size(), 4096, 8192, 65536, 2*1024*1024 }; - const int num_page_sizes = sizeof(page_sizes) / sizeof(page_sizes[0]); + static void test_clamp_address_in_page() { + intptr_t page_sizes[] = { os::vm_page_size(), 4096, 8192, 65536, 2*1024*1024 }; + const int num_page_sizes = sizeof(page_sizes) / sizeof(page_sizes[0]); - for (int i = 0; i < num_page_sizes; i++) { - intptr_t page_size = page_sizes[i]; + for (int i = 0; i < num_page_sizes; i++) { + intptr_t page_size = page_sizes[i]; - address a_page = (address)(10*page_size); + address a_page = (address)(10*page_size); - // Check that address within page is returned as is - assert(clamp_address_in_page(a_page, a_page, page_size) == a_page, "incorrect"); - assert(clamp_address_in_page(a_page + 128, a_page, page_size) == a_page + 128, "incorrect"); - assert(clamp_address_in_page(a_page + page_size - 1, a_page, page_size) == a_page + page_size - 1, "incorrect"); + // Check that address within page is returned as is + assert(clamp_address_in_page(a_page, a_page, page_size) == a_page, "incorrect"); + assert(clamp_address_in_page(a_page + 128, a_page, page_size) == a_page + 128, "incorrect"); + assert(clamp_address_in_page(a_page + page_size - 1, a_page, page_size) == a_page + page_size - 1, "incorrect"); - // Check that address above page returns start of next page - assert(clamp_address_in_page(a_page + page_size, a_page, page_size) == a_page + page_size, "incorrect"); - assert(clamp_address_in_page(a_page + page_size + 1, a_page, page_size) == a_page + page_size, "incorrect"); - assert(clamp_address_in_page(a_page + page_size*5 + 1, a_page, page_size) == a_page + page_size, "incorrect"); + // Check that address above page returns start of next page + assert(clamp_address_in_page(a_page + page_size, a_page, page_size) == a_page + page_size, "incorrect"); + assert(clamp_address_in_page(a_page + page_size + 1, a_page, page_size) == a_page + page_size, "incorrect"); + assert(clamp_address_in_page(a_page + page_size*5 + 1, a_page, page_size) == a_page + page_size, "incorrect"); - // Check that address below page returns start of page - assert(clamp_address_in_page(a_page - 1, a_page, page_size) == a_page, "incorrect"); - assert(clamp_address_in_page(a_page - 2*page_size - 1, a_page, page_size) == a_page, "incorrect"); - assert(clamp_address_in_page(a_page - 5*page_size - 1, a_page, page_size) == a_page, "incorrect"); + // Check that address below page returns start of page + assert(clamp_address_in_page(a_page - 1, a_page, page_size) == a_page, "incorrect"); + assert(clamp_address_in_page(a_page - 2*page_size - 1, a_page, page_size) == a_page, "incorrect"); + assert(clamp_address_in_page(a_page - 5*page_size - 1, a_page, page_size) == a_page, "incorrect"); + } } -} -void GlobalDefinitions_test() { - GlobalDefinitions::test_globals(); + static void test_exact_unit_for_byte_size() { + assert(strcmp(exact_unit_for_byte_size(0), "B") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(1), "B") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(K - 1), "B") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(K), "K") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(K + 1), "B") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(M - 1), "B") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(M), "M") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(M + 1), "B") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(M + K), "K") == 0, "incorrect"); +#ifdef LP64 + assert(strcmp(exact_unit_for_byte_size(G - 1), "B") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(G), "G") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(G + 1), "B") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(G + K), "K") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(G + M), "M") == 0, "incorrect"); + assert(strcmp(exact_unit_for_byte_size(G + M + K), "K") == 0, "incorrect"); +#endif + } + + static void test_byte_size_in_exact_unit() { + assert(byte_size_in_exact_unit(0) == 0, "incorrect"); + assert(byte_size_in_exact_unit(1) == 1, "incorrect"); + assert(byte_size_in_exact_unit(K - 1) == K - 1, "incorrect"); + assert(byte_size_in_exact_unit(K) == 1, "incorrect"); + assert(byte_size_in_exact_unit(K + 1) == K + 1, "incorrect"); + assert(byte_size_in_exact_unit(M - 1) == M - 1, "incorrect"); + assert(byte_size_in_exact_unit(M) == 1, "incorrect"); + assert(byte_size_in_exact_unit(M + 1) == M + 1, "incorrect"); + assert(byte_size_in_exact_unit(M + K) == K + 1, "incorrect"); +#ifdef LP64 + assert(byte_size_in_exact_unit(G - 1) == G - 1, "incorrect"); + assert(byte_size_in_exact_unit(G) == 1, "incorrect"); + assert(byte_size_in_exact_unit(G + 1) == G + 1, "incorrect"); + assert(byte_size_in_exact_unit(G + K) == M + 1, "incorrect"); + assert(byte_size_in_exact_unit(G + M) == K + 1, "incorrect"); + assert(byte_size_in_exact_unit(G + M + K) == M + K + 1, "incorrect"); +#endif + } + + static void test_exact_units() { + test_exact_unit_for_byte_size(); + test_byte_size_in_exact_unit(); + } + +public: + static void test() { + test_clamp_address_in_page(); + test_exact_units(); + } +}; + +void TestGlobalDefinitions_test() { + TestGlobalDefinitions::test(); } #endif // PRODUCT diff --git a/hotspot/src/share/vm/utilities/globalDefinitions.hpp b/hotspot/src/share/vm/utilities/globalDefinitions.hpp index 3fa2c942f13e0c5dd9eebb0efbcecc10b0aca79e..36846d92f0c13a34962ad5123874979c5e54d2c4 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp @@ -199,9 +199,6 @@ const size_t M = K*K; const size_t G = M*K; const size_t HWperKB = K / sizeof(HeapWord); -const jint min_jint = (jint)1 << (sizeof(jint)*BitsPerByte-1); // 0x80000000 == smallest jint -const jint max_jint = (juint)min_jint - 1; // 0x7FFFFFFF == largest jint - // Constants for converting from a base unit to milli-base units. For // example from seconds to milliseconds and microseconds @@ -243,6 +240,36 @@ inline T byte_size_in_proper_unit(T s) { } } +inline const char* exact_unit_for_byte_size(size_t s) { +#ifdef _LP64 + if (s >= G && (s % G) == 0) { + return "G"; + } +#endif + if (s >= M && (s % M) == 0) { + return "M"; + } + if (s >= K && (s % K) == 0) { + return "K"; + } + return "B"; +} + +inline size_t byte_size_in_exact_unit(size_t s) { +#ifdef _LP64 + if (s >= G && (s % G) == 0) { + return s / G; + } +#endif + if (s >= M && (s % M) == 0) { + return s / M; + } + if (s >= K && (s % K) == 0) { + return s / K; + } + return s; +} + //---------------------------------------------------------------------------------------------------- // VM type definitions @@ -328,7 +355,7 @@ inline size_t pointer_delta(const MetaWord* left, const MetaWord* right) { // so far from the middle of the road that it is likely to be problematic in // many C++ compilers. // -#define CAST_TO_FN_PTR(func_type, value) ((func_type)(castable_address(value))) +#define CAST_TO_FN_PTR(func_type, value) (reinterpret_cast(value)) #define CAST_FROM_FN_PTR(new_type, func_ptr) ((new_type)((address_word)(func_ptr))) // Unsigned byte types for os and stream.hpp @@ -351,6 +378,14 @@ typedef jshort s2; typedef jint s4; typedef jlong s8; +const jbyte min_jbyte = -(1 << 7); // smallest jbyte +const jbyte max_jbyte = (1 << 7) - 1; // largest jbyte +const jshort min_jshort = -(1 << 15); // smallest jshort +const jshort max_jshort = (1 << 15) - 1; // largest jshort + +const jint min_jint = (jint)1 << (sizeof(jint)*BitsPerByte-1); // 0x80000000 == smallest jint +const jint max_jint = (juint)min_jint - 1; // 0x7FFFFFFF == largest jint + //---------------------------------------------------------------------------------------------------- // JVM spec restrictions @@ -816,14 +851,15 @@ class JavaValue { enum TosState { // describes the tos cache contents btos = 0, // byte, bool tos cached - ctos = 1, // char tos cached - stos = 2, // short tos cached - itos = 3, // int tos cached - ltos = 4, // long tos cached - ftos = 5, // float tos cached - dtos = 6, // double tos cached - atos = 7, // object cached - vtos = 8, // tos not cached + ztos = 1, // byte, bool tos cached + ctos = 2, // char tos cached + stos = 3, // short tos cached + itos = 4, // int tos cached + ltos = 5, // long tos cached + ftos = 6, // float tos cached + dtos = 7, // double tos cached + atos = 8, // object cached + vtos = 9, // tos not cached number_of_states, ilgl // illegal state: should not occur }; @@ -832,7 +868,7 @@ enum TosState { // describes the tos cache contents inline TosState as_TosState(BasicType type) { switch (type) { case T_BYTE : return btos; - case T_BOOLEAN: return btos; // FIXME: Add ztos + case T_BOOLEAN: return ztos; case T_CHAR : return ctos; case T_SHORT : return stos; case T_INT : return itos; @@ -848,8 +884,8 @@ inline TosState as_TosState(BasicType type) { inline BasicType as_BasicType(TosState state) { switch (state) { - //case ztos: return T_BOOLEAN;//FIXME case btos : return T_BYTE; + case ztos : return T_BOOLEAN; case ctos : return T_CHAR; case stos : return T_SHORT; case itos : return T_INT; diff --git a/hotspot/src/share/vm/utilities/growableArray.hpp b/hotspot/src/share/vm/utilities/growableArray.hpp index a2780fecca55d727eea1d8e7dd8d1957676df176..fccbad3645f778eda55b26f30d0c5e8bceaeb165 100644 --- a/hotspot/src/share/vm/utilities/growableArray.hpp +++ b/hotspot/src/share/vm/utilities/growableArray.hpp @@ -29,7 +29,6 @@ #include "memory/allocation.inline.hpp" #include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" -#include "utilities/top.hpp" // A growable array. diff --git a/hotspot/src/share/vm/utilities/internalVMTests.cpp b/hotspot/src/share/vm/utilities/internalVMTests.cpp index 4adaf3074252be7c0bd47583efd460f726b6b5a2..985885c2edd989b45eb4d8b432c125fd477829ec 100644 --- a/hotspot/src/share/vm/utilities/internalVMTests.cpp +++ b/hotspot/src/share/vm/utilities/internalVMTests.cpp @@ -50,7 +50,7 @@ void InternalVMTests::run() { run_unit_test(TestMetaspaceAux_test); run_unit_test(TestMetachunk_test); run_unit_test(TestVirtualSpaceNode_test); - run_unit_test(GlobalDefinitions_test); + run_unit_test(TestGlobalDefinitions_test); run_unit_test(GCTimer_test); run_unit_test(arrayOopDesc_test); run_unit_test(CollectedHeap_test); @@ -67,6 +67,7 @@ void InternalVMTests::run() { run_unit_test(Test_linked_list); run_unit_test(TestChunkedList_test); run_unit_test(JSON_test); + run_unit_test(Test_log_tag_combinations_limit); run_unit_test(Test_logtarget); run_unit_test(Test_logstream); run_unit_test(Test_loghandle); @@ -77,6 +78,9 @@ void InternalVMTests::run() { run_unit_test(Test_log_prefix); run_unit_test(Test_log_big); run_unit_test(Test_logtagset_duplicates); + run_unit_test(Test_log_file_startup_rotation); + run_unit_test(Test_log_file_startup_truncation); + run_unit_test(Test_invalid_log_file); run_unit_test(DirectivesParser_test); run_unit_test(Test_TempNewSymbol); #if INCLUDE_VM_STRUCTS diff --git a/hotspot/src/share/vm/utilities/ostream.cpp b/hotspot/src/share/vm/utilities/ostream.cpp index 0f1057ed1ce62e789196af26ac75761265a9e281..e9cc5fc2f089a2595396582a7f53ea8678538940 100644 --- a/hotspot/src/share/vm/utilities/ostream.cpp +++ b/hotspot/src/share/vm/utilities/ostream.cpp @@ -31,7 +31,6 @@ #include "utilities/defaultStream.hpp" #include "utilities/macros.hpp" #include "utilities/ostream.hpp" -#include "utilities/top.hpp" #include "utilities/xmlstream.hpp" extern "C" void jio_print(const char* s); // Declarationtion of jvm method diff --git a/hotspot/src/share/vm/utilities/pair.hpp b/hotspot/src/share/vm/utilities/pair.hpp index d0bb5d65c4b80a6e116e173be666db977e765b1c..7c901539c5682818b75b7f6df681a781110146f7 100644 --- a/hotspot/src/share/vm/utilities/pair.hpp +++ b/hotspot/src/share/vm/utilities/pair.hpp @@ -26,7 +26,6 @@ #define SHARE_VM_UTILITIES_PAIR_HPP #include "memory/allocation.hpp" -#include "utilities/top.hpp" template class Pair : public ALLOC_BASE { diff --git a/hotspot/src/share/vm/utilities/preserveException.hpp b/hotspot/src/share/vm/utilities/preserveException.hpp index 58f92a876abc912e156b2915782d358192d8d0ad..09b3664ef9a5762d25d0f5bd1aca24c8537e153e 100644 --- a/hotspot/src/share/vm/utilities/preserveException.hpp +++ b/hotspot/src/share/vm/utilities/preserveException.hpp @@ -26,7 +26,7 @@ #define SHARE_VM_UTILITIES_PRESERVEEXCEPTION_HPP #include "runtime/handles.hpp" -#include "runtime/thread.inline.hpp" +#include "runtime/thread.hpp" // This file provides more support for exception handling; see also exceptions.hpp class PreserveExceptionMark { diff --git a/hotspot/src/share/vm/utilities/resourceHash.hpp b/hotspot/src/share/vm/utilities/resourceHash.hpp index 82c1219b465dfeb64e9528fc37320121d00f6cce..bfd0a1f2d94cf13d21ba9d1b4cd090ab2029b1c0 100644 --- a/hotspot/src/share/vm/utilities/resourceHash.hpp +++ b/hotspot/src/share/vm/utilities/resourceHash.hpp @@ -26,7 +26,6 @@ #define SHARE_VM_UTILITIES_RESOURCEHASH_HPP #include "memory/allocation.hpp" -#include "utilities/top.hpp" template struct ResourceHashtableFns { typedef unsigned (*hash_fn)(K const&); diff --git a/hotspot/src/share/vm/utilities/utf8.hpp b/hotspot/src/share/vm/utilities/utf8.hpp index 1a30cb456fcc529819008fd9156e179a56416c38..34deeb953f7725c5bff857ef43d6addeb84c5a39 100644 --- a/hotspot/src/share/vm/utilities/utf8.hpp +++ b/hotspot/src/share/vm/utilities/utf8.hpp @@ -26,7 +26,6 @@ #define SHARE_VM_UTILITIES_UTF8_HPP #include "memory/allocation.hpp" -#include "utilities/top.hpp" // Low-level interface for UTF8 strings diff --git a/hotspot/src/share/vm/utilities/vmError.cpp b/hotspot/src/share/vm/utilities/vmError.cpp index 0f128c1f2860ea47011859cb964196e95b46d539..4ca94f391a45d10bf94d77f9362ce59d2669e82b 100644 --- a/hotspot/src/share/vm/utilities/vmError.cpp +++ b/hotspot/src/share/vm/utilities/vmError.cpp @@ -43,7 +43,6 @@ #include "utilities/defaultStream.hpp" #include "utilities/errorReporter.hpp" #include "utilities/events.hpp" -#include "utilities/top.hpp" #include "utilities/vmError.hpp" // List of environment variables that should be reported in error log file. diff --git a/hotspot/test/TEST.ROOT b/hotspot/test/TEST.ROOT index 55979b0a554ee6f7967cebc1a2c60f1708c170d0..29c9696e7beba1ec169f6492b8970a97cc051499 100644 --- a/hotspot/test/TEST.ROOT +++ b/hotspot/test/TEST.ROOT @@ -30,6 +30,10 @@ keys=cte_test jcmd nmt regression gc stress groups=TEST.groups [closed/TEST.groups] + +# Source files for classes that will be used at the beginning of each test suite run, +# to determine additional characteristics of the system for use with the @requires tag. +requires.extraPropDefns = ../../test/jtreg-ext/requires/VMProps.java requires.properties=sun.arch.data.model # Tests using jtreg 4.2 b01 features diff --git a/hotspot/test/TEST.groups b/hotspot/test/TEST.groups index e74ab567871aecc2412d8711a131d465b77896dc..18dc949a02493e59d705dc73a0e1d9220421968f 100644 --- a/hotspot/test/TEST.groups +++ b/hotspot/test/TEST.groups @@ -338,6 +338,7 @@ hotspot_fast_gc_2 = \ sanity/ExecuteInternalVMTests.java \ gc/ \ -gc/g1/ \ + -gc/stress \ -gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java \ -gc/cms/TestMBeanCMS.java \ -gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java @@ -346,7 +347,7 @@ hotspot_fast_gc_closed = \ sanity/ExecuteInternalVMTests.java hotspot_fast_gc_gcold = \ - stress/gc/TestGCOld.java + gc/stress/TestGCOld.java hotspot_fast_runtime = \ runtime/ \ @@ -387,7 +388,8 @@ hotspot_jprt = \ :hotspot_fast_compiler_2 \ :hotspot_fast_compiler_3 \ :hotspot_fast_compiler_closed \ - :hotspot_fast_gc \ + :hotspot_fast_gc_1 \ + :hotspot_fast_gc_2 \ :hotspot_fast_gc_closed \ :hotspot_fast_gc_gcold \ :hotspot_fast_runtime \ diff --git a/hotspot/test/gc/TestHumongousReferenceObject.java b/hotspot/test/gc/TestHumongousReferenceObject.java index 728b8911de8d42d63e523e97af4ab8bf59fac386..7e09abfe274c6e0c970486231710810fd1ca6a75 100644 --- a/hotspot/test/gc/TestHumongousReferenceObject.java +++ b/hotspot/test/gc/TestHumongousReferenceObject.java @@ -27,26 +27,26 @@ import jdk.internal.vm.annotation.Contended; * @test * @summary Test that verifies that iteration over large, plain Java objects, that potentially cross region boundaries on G1, with references in them works. * @requires vm.gc == "null" - * @bug 8151499 + * @bug 8151499 8153734 * @modules java.base/jdk.internal.vm.annotation - * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xmx1g -XX:+UseParallelGC -XX:ContendedPaddingWidth=8192 TestHumongousReferenceObject - * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xmx1g -XX:+UseG1GC -XX:G1HeapRegionSize=1M -XX:ContendedPaddingWidth=8192 TestHumongousReferenceObject - * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xmx1g -XX:+UseG1GC -XX:G1HeapRegionSize=2M -XX:ContendedPaddingWidth=8192 TestHumongousReferenceObject - * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xmx1g -XX:+UseG1GC -XX:G1HeapRegionSize=4M -XX:ContendedPaddingWidth=8192 TestHumongousReferenceObject - * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xmx1g -XX:+UseG1GC -XX:G1HeapRegionSize=8M -XX:ContendedPaddingWidth=8192 TestHumongousReferenceObject + * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xmx128m -XX:+UseParallelGC -XX:ContendedPaddingWidth=8192 TestHumongousReferenceObject + * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xmx128m -XX:+UseG1GC -XX:G1HeapRegionSize=1M -XX:ContendedPaddingWidth=8192 TestHumongousReferenceObject + * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xmx128m -XX:+UseG1GC -XX:G1HeapRegionSize=2M -XX:ContendedPaddingWidth=8192 TestHumongousReferenceObject + * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xmx128m -XX:+UseG1GC -XX:G1HeapRegionSize=4M -XX:ContendedPaddingWidth=8192 TestHumongousReferenceObject + * @run main/othervm -XX:+EnableContended -XX:-RestrictContended -Xmx128m -XX:+UseG1GC -XX:G1HeapRegionSize=8M -XX:ContendedPaddingWidth=8192 TestHumongousReferenceObject */ public class TestHumongousReferenceObject { /* Due to 300 fields with 8K @Contended padding around each field, it takes 2.4M bytes per instance. With small G1 regions, it is bound to cross regions. G1 should properly (card) mark the object nevertheless. - With 1G heap, it is enough to allocate ~400 of these objects to provoke at least one GC. + With 128M heap, it is enough to allocate ~100 of these objects to provoke at least one GC. */ static volatile Object instance; public static void main(String[] args) { - for (int c = 0; c < 400; c++) { + for (int c = 0; c < 100; c++) { instance = new TestHumongousReferenceObject(); } } diff --git a/hotspot/test/gc/arguments/TestG1ConcRefinementThreads.java b/hotspot/test/gc/arguments/TestG1ConcRefinementThreads.java index 0a470191560d2a18267465a85cdcf855f23f1a96..25b8e34414a5cde8961b59e05f2602774267cd76 100644 --- a/hotspot/test/gc/arguments/TestG1ConcRefinementThreads.java +++ b/hotspot/test/gc/arguments/TestG1ConcRefinementThreads.java @@ -38,7 +38,7 @@ import java.util.regex.*; public class TestG1ConcRefinementThreads { - static final int AUTO_SELECT_THREADS_COUNT = 0; + static final int AUTO_SELECT_THREADS_COUNT = -1; static final int PASSED_THREADS_COUNT = 11; public static void main(String args[]) throws Exception { @@ -49,8 +49,8 @@ public class TestG1ConcRefinementThreads { // zero setting case runG1ConcRefinementThreadsTest( - new String[]{"-XX:G1ConcRefinementThreads=0"}, // automatically selected - AUTO_SELECT_THREADS_COUNT /* set to zero */); + new String[]{"-XX:G1ConcRefinementThreads=0"}, + 0); // non-zero sestting case runG1ConcRefinementThreadsTest( @@ -77,7 +77,7 @@ public class TestG1ConcRefinementThreads { private static void checkG1ConcRefinementThreadsConsistency(String output, int expectedValue) { int actualValue = getIntValue("G1ConcRefinementThreads", output); - if (expectedValue == 0) { + if (expectedValue == AUTO_SELECT_THREADS_COUNT) { // If expectedValue is automatically selected, set it same as ParallelGCThreads. expectedValue = getIntValue("ParallelGCThreads", output); } diff --git a/hotspot/test/gc/arguments/TestMaxMinHeapFreeRatioFlags.java b/hotspot/test/gc/arguments/TestMaxMinHeapFreeRatioFlags.java index d77449e8d348091b9ebaa9eb5a0216a49aa370fe..19d03b28c979142eee3811169736dd59fa87f65a 100644 --- a/hotspot/test/gc/arguments/TestMaxMinHeapFreeRatioFlags.java +++ b/hotspot/test/gc/arguments/TestMaxMinHeapFreeRatioFlags.java @@ -168,6 +168,11 @@ public class TestMaxMinHeapFreeRatioFlags { long maxHeapSize = getMax(); int gcTries = (shrinkHeapInSteps ? GC_TRIES : 1); + // Initial checks. This also links up everything in these helper methods, + // in case it brings more garbage. + forceGC(gcTries); + verifyRatio(minRatio, maxRatio); + // commit 0.5 of total heap size to have enough space // to both shink and expand while (getCommitted() < maxHeapSize / 2) { @@ -215,7 +220,6 @@ public class TestMaxMinHeapFreeRatioFlags { if (previouslyCommitted <= getCommitted()) { throw new RuntimeException("Heap was not shrinked."); } - } public static void forceGC(int gcTries) { diff --git a/hotspot/test/gc/g1/Test2GbHeap.java b/hotspot/test/gc/g1/Test2GbHeap.java index 7ec0b58ee13beb4fd93e3146eb480b41fa1637b9..9ef0f1a754437294cb054effa60ad1f568cdd5a4 100644 --- a/hotspot/test/gc/g1/Test2GbHeap.java +++ b/hotspot/test/gc/g1/Test2GbHeap.java @@ -25,6 +25,9 @@ * @test Test2GbHeap * @bug 8031686 * @summary Regression test to ensure we can start G1 with 2gb heap. + * Skip test on 32 bit Windows: it typically does not support the many and large virtual memory reservations needed. + * @requires (vm.gc == "G1" | vm.gc == "null") + * @requires !((sun.arch.data.model == "32") & (os.family == "windows")) * @key gc * @key regression * @library /testlibrary @@ -48,17 +51,6 @@ public class Test2GbHeap { ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(testArguments.toArray(new String[0])); OutputAnalyzer output = new OutputAnalyzer(pb.start()); - - // Avoid failing test for setups not supported. - if (output.getOutput().contains("Could not reserve enough space for 2097152KB object heap")) { - // Will fail on machines with too little memory (and Windows 32-bit VM), ignore such failures. - output.shouldHaveExitValue(1); - } else if (output.getOutput().contains("-XX:+UseG1GC not supported in this VM")) { - // G1 is not supported on embedded, ignore such failures. - output.shouldHaveExitValue(1); - } else { - // Normally everything should be fine. - output.shouldHaveExitValue(0); - } + output.shouldHaveExitValue(0); } } diff --git a/hotspot/test/gc/g1/TestLargePageUseForAuxMemory.java b/hotspot/test/gc/g1/TestLargePageUseForAuxMemory.java index 03d214d19ec38f30629a43e5c78d4f6631ecb72d..28f1b166a4dc1db830b06a62ff99c004345bde87 100644 --- a/hotspot/test/gc/g1/TestLargePageUseForAuxMemory.java +++ b/hotspot/test/gc/g1/TestLargePageUseForAuxMemory.java @@ -36,6 +36,8 @@ */ import java.lang.Math; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import jdk.test.lib.*; import jdk.test.lib.Asserts; @@ -47,14 +49,29 @@ public class TestLargePageUseForAuxMemory { static long smallPageSize; static long allocGranularity; + static void checkSize(OutputAnalyzer output, long expectedSize, String pattern) { + String pageSizeStr = output.firstMatch(pattern, 1); + + if (pageSizeStr == null) { + output.reportDiagnosticSummary(); + throw new RuntimeException("Match from '" + pattern + "' got 'null' expected: " + expectedSize); + } + + long size = parseMemoryString(pageSizeStr); + if (size != expectedSize) { + output.reportDiagnosticSummary(); + throw new RuntimeException("Match from '" + pattern + "' got " + size + " expected: " + expectedSize); + } + } + static void checkSmallTables(OutputAnalyzer output, long expectedPageSize) throws Exception { - output.shouldContain("G1 'Block offset table': pg_sz=" + expectedPageSize); - output.shouldContain("G1 'Card counts table': pg_sz=" + expectedPageSize); + checkSize(output, expectedPageSize, "Block Offset Table: .*page_size=([^ ]+)"); + checkSize(output, expectedPageSize, "Card Counts Table: .*page_size=([^ ]+)"); } static void checkBitmaps(OutputAnalyzer output, long expectedPageSize) throws Exception { - output.shouldContain("G1 'Prev Bitmap': pg_sz=" + expectedPageSize); - output.shouldContain("G1 'Next Bitmap': pg_sz=" + expectedPageSize); + checkSize(output, expectedPageSize, "Prev Bitmap: .*page_size=([^ ]+)"); + checkSize(output, expectedPageSize, "Next Bitmap: .*page_size=([^ ]+)"); } static void testVM(String what, long heapsize, boolean cardsShouldUseLargePages, boolean bitmapShouldUseLargePages) throws Exception { @@ -66,7 +83,7 @@ public class TestLargePageUseForAuxMemory { "-XX:G1HeapRegionSize=" + HEAP_REGION_SIZE, "-Xms" + heapsize, "-Xmx" + heapsize, - "-XX:+TracePageSizes", + "-Xlog:pagesize", "-XX:+UseLargePages", "-XX:+IgnoreUnrecognizedVMOptions", // there is no ObjectAlignmentInBytes in 32 bit builds "-XX:ObjectAlignmentInBytes=8", @@ -82,7 +99,7 @@ public class TestLargePageUseForAuxMemory { "-XX:G1HeapRegionSize=" + HEAP_REGION_SIZE, "-Xms" + heapsize, "-Xmx" + heapsize, - "-XX:+TracePageSizes", + "-Xlog:pagesize", "-XX:-UseLargePages", "-XX:+IgnoreUnrecognizedVMOptions", // there is no ObjectAlignmentInBytes in 32 bit builds "-XX:ObjectAlignmentInBytes=8", @@ -108,11 +125,6 @@ public class TestLargePageUseForAuxMemory { } public static void main(String[] args) throws Exception { - if (!Platform.isDebugBuild()) { - System.out.println("Skip tests on non-debug builds because the required option TracePageSizes is a debug-only option."); - return; - } - // Size that a single card covers. final int cardSize = 512; WhiteBox wb = WhiteBox.getWhiteBox(); @@ -159,4 +171,24 @@ public class TestLargePageUseForAuxMemory { testVM("case5: only bitmap uses large pages (extra slack)", heapSizeForBitmapUsingLargePages + heapSizeDiffForBitmap, false, true); testVM("case6: nothing uses large pages (barely not)", heapSizeForBitmapUsingLargePages - heapSizeDiffForBitmap, false, false); } + + public static long parseMemoryString(String value) { + long multiplier = 1; + + if (value.endsWith("B")) { + multiplier = 1; + } else if (value.endsWith("K")) { + multiplier = 1024; + } else if (value.endsWith("M")) { + multiplier = 1024 * 1024; + } else if (value.endsWith("G")) { + multiplier = 1024 * 1024 * 1024; + } else { + throw new IllegalArgumentException("Expected memory string '" + value + "'to end with either of: B, K, M, G"); + } + + long longValue = Long.parseUnsignedLong(value.substring(0, value.length() - 1)); + + return longValue * multiplier; + } } diff --git a/hotspot/test/gc/g1/humongousObjects/TestHumongousThreshold.java b/hotspot/test/gc/g1/humongousObjects/TestHumongousThreshold.java index a9a8372819592d1a2998cd5f18517d49235c13bc..3b66bc7507ca9c60850324ee0915c69e38dc660c 100644 --- a/hotspot/test/gc/g1/humongousObjects/TestHumongousThreshold.java +++ b/hotspot/test/gc/g1/humongousObjects/TestHumongousThreshold.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015,2016 Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -70,7 +70,7 @@ public class TestHumongousThreshold { private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); private static final int REGION_SIZE = WHITE_BOX.g1RegionSize(); private static final int MAX_CONTINUOUS_SIZE_CHECK = 129; - private static final int NON_HUMONGOUS_DIVIDER = 10; + private static final int NON_HUMONGOUS_STEPS = 10; /** * The method allocates byte[] with specified size and checks that: @@ -84,7 +84,7 @@ public class TestHumongousThreshold { * @return allocated byte array */ - private static byte[] allocateAndCheck(int arraySize, boolean expectedHumongous) { + private static void allocateAndCheck(int arraySize, boolean expectedHumongous) { byte[] storage = new byte[arraySize]; long objectSize = WHITE_BOX.getObjectSize(storage); boolean shouldBeHumongous = objectSize > (REGION_SIZE / 2); @@ -98,7 +98,6 @@ public class TestHumongousThreshold { "Object should be allocated as " + (shouldBeHumongous ? "humongous" : "non-humongous") + " but it wasn't; Allocation size = " + arraySize + "; Object size = " + objectSize + "; region size = " + REGION_SIZE); - return storage; } public static void main(String[] args) { @@ -108,7 +107,7 @@ public class TestHumongousThreshold { int maxByteArrayNonHumongousSize = (REGION_SIZE / 2) - byteArrayMemoryOverhead; // Increment for non-humongous testing - int nonHumongousStep = maxByteArrayNonHumongousSize / NON_HUMONGOUS_DIVIDER; + int nonHumongousStep = maxByteArrayNonHumongousSize / NON_HUMONGOUS_STEPS; // Maximum byte[] that takes one region int maxByteArrayOneRegionSize = REGION_SIZE - byteArrayMemoryOverhead; @@ -131,10 +130,10 @@ public class TestHumongousThreshold { allocateAndCheck(i, false); } - // Testing allocations with byte[] with length from 0 to nonHumongousStep * NON_HUMONGOUS_DIVIDER + // Testing allocations with byte[] with length from 0 to nonHumongousStep * NON_HUMONGOUS_STEPS System.out.format("Testing allocations with byte[] with length from 0 to %d with step %d%n", - nonHumongousStep * NON_HUMONGOUS_DIVIDER, nonHumongousStep); - for (int i = 0; i < NON_HUMONGOUS_DIVIDER; ++i) { + nonHumongousStep * NON_HUMONGOUS_STEPS, nonHumongousStep); + for (int i = 0; i < NON_HUMONGOUS_STEPS; ++i) { allocateAndCheck(i * nonHumongousStep, false); } diff --git a/hotspot/test/gc/g1/plab/TestPLABEvacuationFailure.java b/hotspot/test/gc/g1/plab/TestPLABEvacuationFailure.java new file mode 100644 index 0000000000000000000000000000000000000000..5bcad7f2404cc1cfeedf1525e3fb24e1b85c30ec --- /dev/null +++ b/hotspot/test/gc/g1/plab/TestPLABEvacuationFailure.java @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 TestPLABEvacuationFailure + * @bug 8148376 + * @summary Checks PLAB statistics on evacuation failure + * @requires vm.gc=="G1" | vm.gc=="null" + * @library /testlibrary / + * @modules java.management + * @build gc.g1.plab.lib.LogParser + * gc.g1.plab.lib.AppPLABEvacuationFailure + * @run main gc.g1.plab.TestPLABEvacuationFailure + */ +package gc.g1.plab; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.ArrayList; +import java.util.Collections; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import jdk.test.lib.OutputAnalyzer; +import jdk.test.lib.ProcessTools; +import jdk.test.lib.Utils; + +import gc.g1.plab.lib.LogParser; +import gc.g1.plab.lib.AppPLABEvacuationFailure; +import gc.g1.plab.lib.PlabInfo; + +/** + * The test runs the AppPLABEvacuationFailure application to provoke a number of + * Evacuation Failures, parses GC log and analyzes PLAB statistics. The test checks + * that both fields 'failure_waste' and 'failure_used' for Evacuation Failure statistic + * are non zero, and zero for other statistics. + */ +public class TestPLABEvacuationFailure { + + /* PLAB statistics fields which are checked. + * Test expects to find 0 in this fields in survivor statistics. + * Expects to find 0 in old statistics for GC when evacuation failure + * did not happen. And expects to find not 0 in old statistics in case when + * GC causes to evacuation failure. + */ + private static final List FAILURE_STAT_FIELDS = new ArrayList<>(Arrays.asList( + "failure used", + "failure wasted")); + + private static final String[] COMMON_OPTIONS = { + "-Xlog:gc=debug,gc+plab=debug,gc+phases=trace", + "-XX:+UseG1GC", + "-XX:InitiatingHeapOccupancyPercent=100", + "-XX:-G1UseAdaptiveIHOP", + "-XX:G1HeapRegionSize=1m"}; + + private static final Pattern GC_ID_PATTERN = Pattern.compile("GC\\((\\d+)\\)"); + private static List evacuationFailureIDs; + private static LogParser logParser; + private static String appPlabEvacFailureOutput; + + public static void main(String[] args) throws Throwable { + // ParallelGCBufferWastePct, PLAB Size, ParallelGCBufferWastePct, MaxHeapSize, is plab fixed. + runTest(10, 1024, 3, 16, true); + runTest(15, 2048, 4, 256, true); + runTest(20, 65536, 7, 128, false); + runTest(25, 1024, 3, 16, true); + runTest(30, 16384, 7, 256, false); + runTest(10, 65536, 4, 32, false); + } + + private static void runTest(int wastePct, int plabSize, int parGCThreads, int heapSize, boolean plabIsFixed) throws Throwable { + System.out.println("Test case details:"); + System.out.println(" Heap size : " + heapSize + "M"); + System.out.println(" Initial PLAB size : " + plabSize); + System.out.println(" Parallel GC buffer waste pct : " + wastePct); + System.out.println(" Parallel GC threads : " + parGCThreads); + System.out.println(" PLAB size is fixed: " + (plabIsFixed ? "yes" : "no")); + // Set up test GC and PLAB options + List testOptions = new ArrayList<>(); + Collections.addAll(testOptions, COMMON_OPTIONS); + Collections.addAll(testOptions, Utils.getTestJavaOpts()); + Collections.addAll(testOptions, + "-XX:ParallelGCThreads=" + parGCThreads, + "-XX:ParallelGCBufferWastePct=" + wastePct, + "-XX:OldPLABSize=" + plabSize, + "-XX:YoungPLABSize=" + plabSize, + "-XX:" + (plabIsFixed ? "-" : "+") + "ResizePLAB", + "-XX:MaxHeapSize=" + heapSize + "m"); + testOptions.add(AppPLABEvacuationFailure.class.getName()); + OutputAnalyzer out = ProcessTools.executeTestJvm(testOptions.toArray(new String[testOptions.size()])); + + appPlabEvacFailureOutput = out.getOutput(); + if (out.getExitValue() != 0) { + System.out.println(appPlabEvacFailureOutput); + throw new RuntimeException("Expect exit code 0."); + } + // Get list of GC ID on evacuation failure + evacuationFailureIDs = getGcIdPlabEvacFailures(out); + logParser = new LogParser(appPlabEvacFailureOutput); + checkResults(); + } + + private static void checkResults() { + + if (evacuationFailureIDs.isEmpty()) { + System.out.println(appPlabEvacFailureOutput); + throw new RuntimeException("AppPLABEvacuationFailure did not reach Evacuation Failure."); + } + + Map valuesToCheck = getNonEvacFailureSurvivorStats(); + checkValuesIsZero(valuesToCheck, "Expect that SURVIVOR PLAB failure statistics should be 0 when no evacuation failure"); + + valuesToCheck = getNonEvacFailureOldStats(); + checkValuesIsZero(valuesToCheck, "Expect that OLD PLAB failure statistics should be 0 when no evacuation failure"); + + valuesToCheck = getEvacFailureSurvivorStats(); + checkValuesIsZero(valuesToCheck, "Expect that failure statistics should be 0 in SURVIVOR PLAB statistics at evacuation failure"); + + valuesToCheck = getEvacFailureOldStats(); + checkValuesIsNotZero(valuesToCheck, "Expect that failure statistics should not be 0 in OLD PLAB statistics at evacuation failure"); + } + + /** + * Checks logItems for non-zero values. Throws RuntimeException if found. + * + * @param logItems + * @param errorMessage + */ + private static void checkValuesIsZero(Map logItems, String errorMessage) { + checkValues(logItems, errorMessage, true); + } + + /** + * Checks logItems for zero values. Throws RuntimeException if found. + * + * @param logItems + * @param errorMessage + */ + private static void checkValuesIsNotZero(Map logItems, String errorMessage) { + checkValues(logItems, errorMessage, false); + } + + private static void checkValues(Map logItems, String errorMessage, boolean expectZero) { + logItems.entrySet() + .forEach(item -> item.getValue() + .values() + .forEach(items -> { + if (expectZero != (items == 0)) { + System.out.println(appPlabEvacFailureOutput); + throw new RuntimeException(errorMessage); + } + }) + ); + } + + /** + * For tracking PLAB statistics for specified PLAB type - survivor and old + */ + private static Map getNonEvacFailureSurvivorStats() { + return logParser.getExcludedSpecifiedStats(evacuationFailureIDs, LogParser.ReportType.SURVIVOR_STATS, FAILURE_STAT_FIELDS); + } + + private static Map getNonEvacFailureOldStats() { + return logParser.getExcludedSpecifiedStats(evacuationFailureIDs, LogParser.ReportType.OLD_STATS, FAILURE_STAT_FIELDS); + } + + private static Map getEvacFailureSurvivorStats() { + return logParser.getSpecifiedStats(evacuationFailureIDs, LogParser.ReportType.SURVIVOR_STATS, FAILURE_STAT_FIELDS); + } + + private static Map getEvacFailureOldStats() { + return logParser.getSpecifiedStats(evacuationFailureIDs, LogParser.ReportType.OLD_STATS, FAILURE_STAT_FIELDS); + } + + private static List getGcIdPlabEvacFailures(OutputAnalyzer out) { + return out.asLines().stream() + .filter(line -> line.contains("Evacuation Failure")) + .map(line -> LogParser.getGcIdFromLine(line, GC_ID_PATTERN)) + .collect(Collectors.toList()); + } +} diff --git a/hotspot/test/gc/g1/plab/lib/AppPLABEvacuationFailure.java b/hotspot/test/gc/g1/plab/lib/AppPLABEvacuationFailure.java new file mode 100644 index 0000000000000000000000000000000000000000..25d797ecda5c4f7ba5e645a17e262bc9ee3c90d5 --- /dev/null +++ b/hotspot/test/gc/g1/plab/lib/AppPLABEvacuationFailure.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 gc.g1.plab.lib; + +import java.util.ArrayList; + +/** + * Application that provokes Evacuation Failure + */ +public class AppPLABEvacuationFailure { + + public static final int CHUNK = 10000; + public static ArrayList arr = new ArrayList<>(); + + public static void main(String[] args) { + System.gc(); + // First attempt. + try { + while (true) { + arr.add(new byte[CHUNK]); + } + } catch (OutOfMemoryError oome) { + arr.clear(); + } + // Second attempt. + try { + while (true) { + arr.add(new byte[CHUNK]); + } + } catch (OutOfMemoryError oome) { + arr.clear(); + } + } +} diff --git a/hotspot/test/stress/gc/TestGCOld.java b/hotspot/test/gc/stress/TestGCOld.java similarity index 100% rename from hotspot/test/stress/gc/TestGCOld.java rename to hotspot/test/gc/stress/TestGCOld.java diff --git a/hotspot/test/stress/gc/TestMultiThreadStressRSet.java b/hotspot/test/gc/stress/TestMultiThreadStressRSet.java similarity index 100% rename from hotspot/test/stress/gc/TestMultiThreadStressRSet.java rename to hotspot/test/gc/stress/TestMultiThreadStressRSet.java diff --git a/hotspot/test/stress/gc/TestStressIHOPMultiThread.java b/hotspot/test/gc/stress/TestStressIHOPMultiThread.java similarity index 100% rename from hotspot/test/stress/gc/TestStressIHOPMultiThread.java rename to hotspot/test/gc/stress/TestStressIHOPMultiThread.java diff --git a/hotspot/test/stress/gc/TestStressRSetCoarsening.java b/hotspot/test/gc/stress/TestStressRSetCoarsening.java similarity index 90% rename from hotspot/test/stress/gc/TestStressRSetCoarsening.java rename to hotspot/test/gc/stress/TestStressRSetCoarsening.java index e7ce522c9e238f33c16d4088f3ad6b2f7d690705..7ab74a4d2d1338d3e08f90288a84c7433706430f 100644 --- a/hotspot/test/stress/gc/TestStressRSetCoarsening.java +++ b/hotspot/test/gc/stress/TestStressRSetCoarsening.java @@ -38,29 +38,29 @@ import sun.hotspot.WhiteBox; * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm/timeout=300 - * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC - * -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc - * -Xmx500m -XX:G1HeapRegionSize=1m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 1 0 300 + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+UseG1GC -Xlog:gc* -XX:MaxGCPauseMillis=1000 + * -Xmx500m -XX:G1HeapRegionSize=1m TestStressRSetCoarsening 1 0 300 * @run main/othervm/timeout=300 - * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC - * -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc - * -Xmx500m -XX:G1HeapRegionSize=8m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 1 10 300 + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+UseG1GC -Xlog:gc* -XX:MaxGCPauseMillis=1000 + * -Xmx500m -XX:G1HeapRegionSize=8m TestStressRSetCoarsening 1 10 300 * @run main/othervm/timeout=300 - * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC - * -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc - * -Xmx500m -XX:G1HeapRegionSize=32m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 42 10 300 + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+UseG1GC -Xlog:gc* -XX:MaxGCPauseMillis=1000 + * -Xmx500m -XX:G1HeapRegionSize=32m TestStressRSetCoarsening 42 10 300 * @run main/othervm/timeout=300 - * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC - * -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc - * -Xmx500m -XX:G1HeapRegionSize=1m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 2 0 300 + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+UseG1GC -Xlog:gc* -XX:MaxGCPauseMillis=1000 + * -Xmx500m -XX:G1HeapRegionSize=1m TestStressRSetCoarsening 2 0 300 * @run main/othervm/timeout=1800 - * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC - * -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc - * -Xmx1G -XX:G1HeapRegionSize=1m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 500 0 1800 + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+UseG1GC -Xlog:gc* -XX:MaxGCPauseMillis=1000 + * -Xmx1G -XX:G1HeapRegionSize=1m TestStressRSetCoarsening 500 0 1800 * @run main/othervm/timeout=1800 - * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC - * -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintGC -XX:+PrintGCTimeStamps -Xlog:gc - * -Xmx1G -XX:G1HeapRegionSize=1m -XX:MaxGCPauseMillis=1000 TestStressRSetCoarsening 10 10 1800 + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+UseG1GC -Xlog:gc* -XX:MaxGCPauseMillis=1000 + * -Xmx1G -XX:G1HeapRegionSize=1m TestStressRSetCoarsening 10 10 1800 */ /** @@ -179,7 +179,13 @@ public class TestStressRSetCoarsening { // sizeOf(Object[N]) ~= (N+4)*refSize // ==> // N = regionSize / K / refSize - 4; - N = (int) ((regionSize / K) / refSize) - 5; + int n = (int) ((regionSize / K) / refSize) - 5; // best guess + long objSize = WB.getObjectSize(new Object[n]); + while (K*objSize > regionSize) { // adjust to avoid OOME + n = n - 1; + objSize = WB.getObjectSize(new Object[n]); + } + N = n; /* * -------------- @@ -202,8 +208,9 @@ public class TestStressRSetCoarsening { System.out.println("%% Objects"); System.out.println("%% N (array length) : " + N); System.out.println("%% K (objects in regions): " + K); + System.out.println("%% Object size : " + objSize + + " (sizeOf(new Object[" + N + "])"); System.out.println("%% Reference size : " + refSize); - System.out.println("%% Approximate obj size : " + (N + 2) * refSize / KB + "K)"); storage = new Object[regionCount * K][]; for (int i = 0; i < storage.length; i++) { diff --git a/hotspot/test/runtime/BoolReturn/BoolConstructor.java b/hotspot/test/runtime/BoolReturn/BoolConstructor.java new file mode 100644 index 0000000000000000000000000000000000000000..c870a4e63662ecf365a857ccde0781e73a8c1429 --- /dev/null +++ b/hotspot/test/runtime/BoolReturn/BoolConstructor.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 jdk.test.lib.Asserts; + +public class BoolConstructor { + + boolean field; + BoolConstructor(boolean b, boolean expected) { + field = b; + // System.out.println("b is " + b + " field is " + field); + Asserts.assertTrue(field == b, "BoolConstructor argument not converted correctly"); + Asserts.assertTrue(field == expected, "BoolConstructor argument not stored correctly"); + } +} diff --git a/hotspot/test/runtime/BoolReturn/NativeSmallIntCallsTest.java b/hotspot/test/runtime/BoolReturn/NativeSmallIntCallsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..d911435382a1b4fd30cd6a52ab547aec15f02abf --- /dev/null +++ b/hotspot/test/runtime/BoolReturn/NativeSmallIntCallsTest.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 8149170 + * @summary Test native functions return booleans as 0/1 but differently than java functions + * @library /testlibrary + * @compile BoolConstructor.java + * @run main/native NativeSmallIntCallsTest + */ + +// This test shows that returns from native calls for boolean truncate to JNI_TRUE if value != 0 +// and JNI_FALSE if value returned is 0. + +import jdk.test.lib.Asserts; + +public class NativeSmallIntCallsTest { + static native boolean nativeCastToBoolCallTrue(); + static native boolean nativeCastToBoolCallFalse(); + static native boolean nativeCallBoolConstructor(int visible, boolean expected); + static { + System.loadLibrary("NativeSmallIntCalls"); + } + + public static void main(java.lang.String[] unused) throws Exception { + // Call through jni + // JNI makes all results != 0 true for compatibility + boolean nativeTrueVal = nativeCastToBoolCallTrue(); + Asserts.assertTrue(nativeTrueVal, "trueval is false!"); + + boolean nativeFalseVal = nativeCastToBoolCallFalse(); + Asserts.assertTrue(nativeFalseVal, "falseval is false in native!"); + + // Call a constructor or method that passes jboolean values into Java from native + nativeCallBoolConstructor(1, true); + nativeCallBoolConstructor(0x10, true); + nativeCallBoolConstructor(0x100, false); + nativeCallBoolConstructor(0x1000, false); + } +} diff --git a/hotspot/test/runtime/BoolReturn/libNativeSmallIntCalls.c b/hotspot/test/runtime/BoolReturn/libNativeSmallIntCalls.c new file mode 100644 index 0000000000000000000000000000000000000000..acf09ac41f8d73a0af9164d2132b85b848c7c188 --- /dev/null +++ b/hotspot/test/runtime/BoolReturn/libNativeSmallIntCalls.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include + +JNIEXPORT void JNICALL +Java_NativeSmallIntCallsTest_nativeCallBoolConstructor(JNIEnv* env, jobject obj, int visible, int expected) { + jclass cls; + jmethodID ctor; + + cls = (*env)->FindClass(env, "BoolConstructor"); + if(NULL == cls) { + return; + } + + ctor = (*env)->GetMethodID(env, cls, "", "(ZZ)V"); + if(NULL == ctor) { + return; + } + + // printf("visible 0x%x expected %d\n", visible, expected); + + (*env)->NewObject(env, cls, ctor, (jboolean) visible, expected); +} + +JNIEXPORT jboolean JNICALL +Java_NativeSmallIntCallsTest_nativeCastToBoolCallTrue(JNIEnv* env, jobject obj) { + + return 55; +} + +JNIEXPORT jboolean JNICALL +Java_NativeSmallIntCallsTest_nativeCastToBoolCallFalse(JNIEnv* env, jobject obj) { + + return 44; +} + diff --git a/hotspot/test/runtime/CompressedOops/CompressedClassPointers.java b/hotspot/test/runtime/CompressedOops/CompressedClassPointers.java index 62a2cc2dd485a23bdf8765dfc195bd1040d24fff..ea0dbc2ec8c4f8dc89d17d21bb9aae912102762b 100644 --- a/hotspot/test/runtime/CompressedOops/CompressedClassPointers.java +++ b/hotspot/test/runtime/CompressedOops/CompressedClassPointers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -85,8 +85,7 @@ public class CompressedClassPointers { public static void heapBaseMinAddressTest() throws Exception { ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( "-XX:HeapBaseMinAddress=1m", - "-XX:+UnlockDiagnosticVMOptions", - "-XX:+PrintCompressedOopsMode", + "-Xlog:gc+heap+coops=debug", "-version"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldContain("HeapBaseMinAddress must be at least"); diff --git a/hotspot/test/runtime/CompressedOops/UseCompressedOops.java b/hotspot/test/runtime/CompressedOops/UseCompressedOops.java index b0aa61ce105448d72c7c58abc6cef17b460f0dee..7c43cda4e89370980cd9802bf8d987bc389b2bce 100644 --- a/hotspot/test/runtime/CompressedOops/UseCompressedOops.java +++ b/hotspot/test/runtime/CompressedOops/UseCompressedOops.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -169,7 +169,6 @@ public class UseCompressedOops { ArrayList args = new ArrayList<>(); // Always run with these three: - args.add("-XX:+UnlockDiagnosticVMOptions"); args.add("-XX:+PrintCompressedOopsMode"); args.add("-Xms32m"); diff --git a/hotspot/test/runtime/Throwable/ThrowableIntrospectionSegfault.java b/hotspot/test/runtime/Throwable/ThrowableIntrospectionSegfault.java new file mode 100644 index 0000000000000000000000000000000000000000..fd4be6c88e1e2bca66fd56801898ea94327adf5f --- /dev/null +++ b/hotspot/test/runtime/Throwable/ThrowableIntrospectionSegfault.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 8033735 + * @summary check backtrace field introspection + * @library /testlibrary + * @run main ThrowableIntrospectionSegfault + */ + +import java.lang.reflect.*; + +public class ThrowableIntrospectionSegfault { + public static void main(java.lang.String[] unused) { + // Construct a throwable object. + Throwable throwable = new Throwable(); + throwable.fillInStackTrace(); + + // Retrieve a reflection handle to the private backtrace field. + Class class1 = throwable.getClass(); + Field field; + try { + field = class1.getDeclaredField("backtrace"); + } + catch (NoSuchFieldException e) { + System.err.println("Can't retrieve field handle Throwable.backtrace: " + e.toString()); + return; + } + field.setAccessible(true); + + // Retrieve the value of the backtrace field. + Object backtrace; + try { + backtrace = field.get(throwable); + } + catch (IllegalAccessException e) { + System.err.println( "Can't retrieve field value for Throwable.backtrace: " + e.toString()); + return; + } + + try { + + // Retrieve the class of throwable.backtrace[0][0]. + Class class2 = ((Object[]) ((Object[]) backtrace)[2])[0].getClass(); + + // Segfault occurs while executing this line, to retrieve the name of + // this class. + String class2Name = class2.getName(); + + System.err.println("class2Name=" + class2Name); + return; // pass! Passes if it doesn't crash. + } catch (ClassCastException e) { + // Passes if it doesn't crash. Also if the backtrace changes this test might get + // ClassCastException and that's ok too. + System.out.println("Catch exception " + e); + return; // pass! Passes if it doesn't crash. + } + } +} diff --git a/hotspot/test/runtime/logging/ClassInitializationTest.java b/hotspot/test/runtime/logging/ClassInitializationTest.java index f465ab5775d3940f34bc7182ac259ed945295d8d..a95cc489a3eec6011b4e4391e84ab826dc681176 100644 --- a/hotspot/test/runtime/logging/ClassInitializationTest.java +++ b/hotspot/test/runtime/logging/ClassInitializationTest.java @@ -62,6 +62,16 @@ public class ClassInitializationTest { out.shouldContain("[Initialized").shouldContain("without side effects]"); out.shouldHaveExitValue(0); } + + // (3) classinit should turn off. + pb = ProcessTools.createJavaProcessBuilder("-Xlog:classinit=off", + "-Xverify:all", + "-Xmx64m", + "BadMap50"); + out = new OutputAnalyzer(pb.start()); + out.shouldNotContain("[classinit]"); + out.shouldNotContain("Fail over class verification to old verifier for: BadMap50"); + } public static class InnerClass { public static void main(String[] args) throws Exception { diff --git a/hotspot/test/runtime/logging/ClassResolutionTest.java b/hotspot/test/runtime/logging/ClassResolutionTest.java index 3c8d6dd7f09c23bac2f8ef83a632ca75201752a9..700fc77cb29e8d29a3ea8969f25964d59233009d 100644 --- a/hotspot/test/runtime/logging/ClassResolutionTest.java +++ b/hotspot/test/runtime/logging/ClassResolutionTest.java @@ -51,7 +51,8 @@ public class ClassResolutionTest { }; public static void main(String... args) throws Exception { - Thing1Handler.getThingNumber(); + int x = Thing1Handler.getThingNumber(); + System.out.println("ThingNumber: "+Integer.toString(x)); } } @@ -62,6 +63,7 @@ public class ClassResolutionTest { ClassResolutionTestMain.class.getName()); OutputAnalyzer o = new OutputAnalyzer(pb.start()); o.shouldContain("[classresolve] ClassResolutionTest$ClassResolutionTestMain$Thing1Handler ClassResolutionTest$ClassResolutionTestMain$Thing1"); + o.shouldContain("[classresolve] resolve JVM_CONSTANT_MethodHandle"); // (2) classresolve should turn off. pb = ProcessTools.createJavaProcessBuilder("-Xlog:classresolve=debug", diff --git a/hotspot/test/runtime/logging/CompressedOopsTest.java b/hotspot/test/runtime/logging/CompressedOopsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..2216f957d8c899f71eff27e452a6f28a565750ac --- /dev/null +++ b/hotspot/test/runtime/logging/CompressedOopsTest.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 8149991 + * @requires (sun.arch.data.model == "64") + * @summary -Xlog:gc+heap+coops=info should have output from the code + * @library /testlibrary + * @modules java.base/jdk.internal.misc + * java.management + * @build jdk.test.lib.OutputAnalyzer jdk.test.lib.Platform jdk.test.lib.ProcessTools + * @run driver CompressedOopsTest + */ + +import jdk.test.lib.OutputAnalyzer; +import jdk.test.lib.Platform; +import jdk.test.lib.ProcessTools; + +public class CompressedOopsTest { + static void analyzeOutputOn(ProcessBuilder pb) throws Exception { + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("[gc,heap,coops] Heap address"); + output.shouldHaveExitValue(0); + } + + static void analyzeOutputOff(ProcessBuilder pb) throws Exception { + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("[gc,heap,coops]"); + output.shouldHaveExitValue(0); + } + + public static void main(String[] args) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseCompressedOops", + "-Xlog:gc+heap+coops=info", + InnerClass.class.getName()); + analyzeOutputOn(pb); + + pb = ProcessTools.createJavaProcessBuilder("-XX:+UseCompressedOops", + "-XX:+PrintCompressedOopsMode", + InnerClass.class.getName()); + analyzeOutputOn(pb); + + pb = ProcessTools.createJavaProcessBuilder("-XX:+UseCompressedOops", + "-XX:+PrintCompressedOopsMode", + "-Xlog:gc+heap+coops=off", + InnerClass.class.getName()); + analyzeOutputOff(pb); + + pb = ProcessTools.createJavaProcessBuilder("-XX:+UseCompressedOops", + "-Xlog:gc+heap+coops=info", + "-XX:-PrintCompressedOopsMode", + InnerClass.class.getName()); + analyzeOutputOff(pb); + } + + public static class InnerClass { + public static void main(String[] args) throws Exception { + System.out.println("Compressed Oops (gc+heap+coops) test"); + } + } +} diff --git a/hotspot/test/runtime/logging/OsCpuLoggingTest.java b/hotspot/test/runtime/logging/OsCpuLoggingTest.java new file mode 100644 index 0000000000000000000000000000000000000000..94aba04f7b0dfb6a303a3141774cbaa2d449663b --- /dev/null +++ b/hotspot/test/runtime/logging/OsCpuLoggingTest.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 8151939 + * @summary os+cpu output should contain some os,cpu information + * @library /testlibrary + * @modules java.base/jdk.internal.misc + * java.management + * @build jdk.test.lib.OutputAnalyzer jdk.test.lib.ProcessTools + * @run driver OsCpuLoggingTest + */ + +import java.io.File; +import java.util.Map; +import jdk.test.lib.*; + +public class OsCpuLoggingTest { + + static void analyzeOutputForOsLog(OutputAnalyzer output) throws Exception { + // Aix has it's own logging + if (!Platform.isAix()) { + output.shouldContain("SafePoint Polling address"); + } + output.shouldHaveExitValue(0); + } + + static void analyzeOutputForOsCpuLog(OutputAnalyzer output) throws Exception { + output.shouldContain("CPU:total"); + output.shouldHaveExitValue(0); + } + + public static void main(String[] args) throws Exception { + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:os+cpu", "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + analyzeOutputForOsCpuLog(output); + + pb = ProcessTools.createJavaProcessBuilder("-Xlog:os", "-version"); + output = new OutputAnalyzer(pb.start()); + analyzeOutputForOsLog(output); + } +} diff --git a/hotspot/test/runtime/modules/AccessCheck/ExportAllUnnamed.java b/hotspot/test/runtime/modules/AccessCheck/ExportAllUnnamed.java index cb09a5315d60057b2f76ca0c63e69826c366a3e1..a75fda9668f4c3f30fd00477f2e8fcca5192b61a 100644 --- a/hotspot/test/runtime/modules/AccessCheck/ExportAllUnnamed.java +++ b/hotspot/test/runtime/modules/AccessCheck/ExportAllUnnamed.java @@ -28,11 +28,12 @@ * @summary Test if package p2 in module m2 is exported to all unnamed, * then class p1.c1 in an unnamed module can read p2.c2 in module m2. * @library /testlibrary /test/lib + * @modules java.base/jdk.internal.module * @compile myloaders/MySameClassLoader.java * @compile p2/c2.java * @compile p1/c1.java - * @compile -XaddExports:java.base/jdk.internal.module=ALL-UNNAMED ExportAllUnnamed.java - * @run main/othervm -XaddExports:java.base/jdk.internal.module=ALL-UNNAMED -Xbootclasspath/a:. ExportAllUnnamed + * @build ExportAllUnnamed + * @run main/othervm -Xbootclasspath/a:. ExportAllUnnamed */ import static jdk.test.lib.Asserts.*; diff --git a/hotspot/test/serviceability/logging/TestLogRotation.java b/hotspot/test/serviceability/logging/TestLogRotation.java index 6ad0b1dad790c1d79f4d0bfd253ae4319e398391..ca59cf6e4a481ae682c7f32f0cf5c12aec8aba1f 100644 --- a/hotspot/test/serviceability/logging/TestLogRotation.java +++ b/hotspot/test/serviceability/logging/TestLogRotation.java @@ -102,8 +102,10 @@ public class TestLogRotation { smallFilesNumber++; } } - if (logs.length != numberOfFiles) { - throw new Error("There are only " + logs.length + " logs instead " + numberOfFiles); + // Expect one more log file since the number-of-files doesn't include the active log file + int expectedNumberOfFiles = numberOfFiles + 1; + if (logs.length != expectedNumberOfFiles) { + throw new Error("There are " + logs.length + " logs instead of the expected " + expectedNumberOfFiles); } if (smallFilesNumber > 1) { throw new Error("There should maximum one log with size < " + logFileSizeK + "K"); diff --git a/hotspot/test/serviceability/logging/TestQuotedLogOutputs.java b/hotspot/test/serviceability/logging/TestQuotedLogOutputs.java index be2e76d9c51077038a5785d3fdcc7b84bda5a105..39789ea01dfa3bbcee6964a768beb16081732361 100644 --- a/hotspot/test/serviceability/logging/TestQuotedLogOutputs.java +++ b/hotspot/test/serviceability/logging/TestQuotedLogOutputs.java @@ -101,7 +101,7 @@ public class TestQuotedLogOutputs { output.shouldHaveExitValue(1); // Ensure error message was logged output.shouldMatch("([Mm]issing terminating quote)" - + "|(Could not open log file '')" + + "|(Error opening log file '')" + "|(Output name can not be partially quoted)"); } } diff --git a/hotspot/test/serviceability/sa/DeadlockDetectionTest.java b/hotspot/test/serviceability/sa/DeadlockDetectionTest.java index aff1aaf156a73db94b3ff129f17352e289991ad4..23ce96f639972f442d51443440b1a33b156529b6 100644 --- a/hotspot/test/serviceability/sa/DeadlockDetectionTest.java +++ b/hotspot/test/serviceability/sa/DeadlockDetectionTest.java @@ -80,6 +80,12 @@ public class DeadlockDetectionTest { return; } + if (Platform.isOSX()) { + // Coredump stackwalking is not implemented for Darwin + System.out.println("This test is not expected to work on OS X. Skipping"); + return; + } + if (!LingeredApp.isLastModifiedWorking()) { // Exact behaviour of the test depends on operating system and the test nature, diff --git a/hotspot/test/serviceability/tmtools/jstack/JstackThreadTest.java b/hotspot/test/serviceability/tmtools/jstack/JstackThreadTest.java index b1e3ed3f2a833ad3f8cc3dcba9c531eabd05fe74..6ca81885814c3d483abbc0d154a16dc1d90effcb 100644 --- a/hotspot/test/serviceability/tmtools/jstack/JstackThreadTest.java +++ b/hotspot/test/serviceability/tmtools/jstack/JstackThreadTest.java @@ -25,6 +25,8 @@ import java.util.Arrays; import jdk.test.lib.JDKToolLauncher; import jdk.test.lib.OutputAnalyzer; import jdk.test.lib.ProcessTools; +import utils.Utils; +import java.util.concurrent.CountDownLatch; /* * @test JstackThreadTest @@ -32,23 +34,22 @@ import jdk.test.lib.ProcessTools; * @summary jstack doesn't close quotation marks properly with threads' name greater than 1996 characters * @library /testlibrary * @build jdk.test.lib.* - * @ignore 8153319 * @run main JstackThreadTest */ public class JstackThreadTest { static class NamedThread extends Thread { - NamedThread(String name) { + CountDownLatch latch; + NamedThread(String name, CountDownLatch latch) { + this.latch = latch; setName(name); + } @Override public void run() { - try { - Thread.sleep(2000); - } catch(Exception e){ - e.printStackTrace(); - } - } + latch.countDown(); + Utils.sleep(); } + } public static void main(String[] args) throws Exception { StringBuilder sb = new StringBuilder(); @@ -60,8 +61,11 @@ public class JstackThreadTest { } private static void testWithName(String name) throws Exception { + //parent thread countDown latch + CountDownLatch latch = new CountDownLatch(1); // Start a thread with a long thread name - NamedThread thread = new NamedThread(name); + NamedThread thread = new NamedThread(name, latch); + thread.setDaemon(true); thread.start(); ProcessBuilder processBuilder = new ProcessBuilder(); JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jstack"); @@ -69,6 +73,8 @@ public class JstackThreadTest { launcher.addToolArg(Long.toString(ProcessTools.getProcessId())); processBuilder.command(launcher.getCommand()); System.out.println(Arrays.toString(processBuilder.command().toArray()).replace(",", "")); + // Ensuring that Jstack will always run after NamedThread + latch.await(); OutputAnalyzer output = ProcessTools.executeProcess(processBuilder); System.out.println(output.getOutput()); output.shouldContain("\""+ name + "\""); diff --git a/hotspot/test/serviceability/tmtools/jstat/GcCapacityTest.java b/hotspot/test/serviceability/tmtools/jstat/GcCapacityTest.java index 6ec4db9829bc94ba28254c9b81834b3ee06901ae..ec6d1bc2f4df5bf96e47687433a3aaa5c3c202f8 100644 --- a/hotspot/test/serviceability/tmtools/jstat/GcCapacityTest.java +++ b/hotspot/test/serviceability/tmtools/jstat/GcCapacityTest.java @@ -27,13 +27,13 @@ import utils.*; * @test * @summary Test checks the consistency of the output * displayed with jstat -gccapacity. - * @ignore 8149778 * @library /test/lib/share/classes * @library ../share * @requires vm.opt.ExplicitGCInvokesConcurrent != true * @build common.* * @build utils.* - * @run main/othervm -XX:+UsePerfData GcCapacityTest + * @ignore 8149778 + * @run main/othervm -XX:+UsePerfData -Xmx128M GcCapacityTest */ public class GcCapacityTest { diff --git a/hotspot/test/serviceability/tmtools/jstat/GcCauseTest01.java b/hotspot/test/serviceability/tmtools/jstat/GcCauseTest01.java index 55ee941e38c27d8756fa771557aae6c6f9728e9d..508b7865a3c7e88602ba44693686f926f0ed770a 100644 --- a/hotspot/test/serviceability/tmtools/jstat/GcCauseTest01.java +++ b/hotspot/test/serviceability/tmtools/jstat/GcCauseTest01.java @@ -34,7 +34,7 @@ * @build common.* * @build utils.* * - * @run main/othervm -XX:+UsePerfData GcCauseTest01 + * @run main/othervm -XX:+UsePerfData -Xmx128M GcCauseTest01 */ import utils.*; diff --git a/hotspot/test/serviceability/tmtools/jstat/GcCauseTest02.java b/hotspot/test/serviceability/tmtools/jstat/GcCauseTest02.java index bc8f005803435c9436ed5721338cef2063a4c12e..95200d453c56ccb22aa44a07f9d902f6c57027de 100644 --- a/hotspot/test/serviceability/tmtools/jstat/GcCauseTest02.java +++ b/hotspot/test/serviceability/tmtools/jstat/GcCauseTest02.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,7 @@ * @build common.* * @build utils.* * - * @run main/othervm -XX:+UsePerfData -Xms128M -XX:MaxMetaspaceSize=128M GcCauseTest02 + * @run main/othervm -XX:+UsePerfData -Xmx128M -XX:MaxMetaspaceSize=128M GcCauseTest02 */ import utils.*; diff --git a/hotspot/test/serviceability/tmtools/jstat/GcCauseTest03.java b/hotspot/test/serviceability/tmtools/jstat/GcCauseTest03.java index 1ebb98b00b5602f8a8721d99edbe2d14d06ec606..94514d4b6349578b003009516cee752767efe1f5 100644 --- a/hotspot/test/serviceability/tmtools/jstat/GcCauseTest03.java +++ b/hotspot/test/serviceability/tmtools/jstat/GcCauseTest03.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,7 @@ * @build common.* * @build utils.* * - * @run main/othervm -XX:+UsePerfData -Xms128M -XX:MaxMetaspaceSize=128M GcCauseTest03 + * @run main/othervm -XX:+UsePerfData -Xmx128M -XX:MaxMetaspaceSize=128M GcCauseTest03 */ import utils.*; diff --git a/hotspot/test/serviceability/tmtools/jstat/GcNewTest.java b/hotspot/test/serviceability/tmtools/jstat/GcNewTest.java index e91ee8ecdf6c2198953822a61e307719f8f55488..bdb06c1e6b277fbf0aed3c37598ec27a38ae5bba 100644 --- a/hotspot/test/serviceability/tmtools/jstat/GcNewTest.java +++ b/hotspot/test/serviceability/tmtools/jstat/GcNewTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,7 +33,7 @@ import utils.*; * @library ../share * @build common.* * @build utils.* - * @run main/othervm -XX:+UsePerfData GcNewTest + * @run main/othervm -XX:+UsePerfData -Xmx128M GcNewTest */ public class GcNewTest { diff --git a/hotspot/test/serviceability/tmtools/jstat/GcTest01.java b/hotspot/test/serviceability/tmtools/jstat/GcTest01.java index ee731adb1447b75b53ab47b702304a8af10ba43d..2a6b0c544a8564cd2b25a29ac626f0300546b2f2 100644 --- a/hotspot/test/serviceability/tmtools/jstat/GcTest01.java +++ b/hotspot/test/serviceability/tmtools/jstat/GcTest01.java @@ -37,7 +37,7 @@ * @build common.* * @build utils.* * - * @run main/othervm -XX:+UsePerfData GcTest01 + * @run main/othervm -XX:+UsePerfData -Xmx128M GcTest01 */ import utils.*; diff --git a/hotspot/test/serviceability/tmtools/jstat/GcTest02.java b/hotspot/test/serviceability/tmtools/jstat/GcTest02.java index c2e55229688ee80b2b6965b5c44493a9c1967779..bcdc258c93465d12b8e90768f956f2cd83521cac 100644 --- a/hotspot/test/serviceability/tmtools/jstat/GcTest02.java +++ b/hotspot/test/serviceability/tmtools/jstat/GcTest02.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,7 @@ import utils.*; * @library ../share * @build common.* * @build utils.* - * @run main/othervm -XX:+UsePerfData -Xms128M -XX:MaxMetaspaceSize=128M GcTest02 + * @run main/othervm -XX:+UsePerfData -Xmx128M -XX:MaxMetaspaceSize=128M GcTest02 */ public class GcTest02 { @@ -58,10 +58,4 @@ public class GcTest02 { // Assert that space has been utilized acordingly JstatResults.assertSpaceUtilization(measurement2, targetMemoryUsagePercent); } - - private static void assertThat(boolean result, String message) { - if (!result) { - throw new RuntimeException(message); - }; - } } diff --git a/hotspot/test/testlibrary/jdk/test/lib/OutputAnalyzer.java b/hotspot/test/testlibrary/jdk/test/lib/OutputAnalyzer.java index 37f0209b288a14379f16860c4028ef486f24a570..15f6f53157b1eb5619d5bdc183eb45cbdff0142c 100644 --- a/hotspot/test/testlibrary/jdk/test/lib/OutputAnalyzer.java +++ b/hotspot/test/testlibrary/jdk/test/lib/OutputAnalyzer.java @@ -378,14 +378,14 @@ public final class OutputAnalyzer { * - exit code * Note: the command line is printed by the ProcessTools */ - private void reportDiagnosticSummary() { - String msg = - " stdout: [" + stdout + "];\n" + - " stderr: [" + stderr + "]\n" + - " exitValue = " + getExitValue() + "\n"; + public void reportDiagnosticSummary() { + String msg = + " stdout: [" + stdout + "];\n" + + " stderr: [" + stderr + "]\n" + + " exitValue = " + getExitValue() + "\n"; - System.err.println(msg); - } + System.err.println(msg); + } /** diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 99d74713f24ab049ff0fa1da7635e286ef84aed2..07b1b9985f70e23893b487195c03da62db634861 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -357,3 +357,4 @@ bdbf2342b21bd8ecad1b4e6499a0dfb314952bd7 jdk-9+103 36326537f929d20cc5885b93939f90c0efcc4681 jdk-9+112 28626780e245fccbfb9bad8e3b05f62357958038 jdk-9+113 147114dd0641cd7c9fe6e81642eb993a7b9c6f0b jdk-9+114 +1902a5bda18e794b31fc5f520f5e7d827714b50d jdk-9+115 diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11EntityScanner.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11EntityScanner.java index a425067224c13ab19e9eb66ea9528dfed0ea34d2..8e1eaef54e10ad54a9417cf54c7daeabafea8ab7 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11EntityScanner.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11EntityScanner.java @@ -1,15 +1,16 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */ /* - * Copyright 2005 The Apache Software Foundation. + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -24,7 +25,6 @@ import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter; import com.sun.org.apache.xerces.internal.util.XML11Char; import com.sun.org.apache.xerces.internal.util.XMLChar; import com.sun.org.apache.xerces.internal.util.XMLStringBuffer; -import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager.Limit; import com.sun.org.apache.xerces.internal.xni.QName; import com.sun.org.apache.xerces.internal.xni.XMLString; @@ -815,7 +815,7 @@ public class XML11EntityScanner load(0, true, true); } else if (fCurrentEntity.position == fCurrentEntity.count - 1) { - invokeListeners(0); + invokeListeners(1); fCurrentEntity.ch[0] = fCurrentEntity.ch[fCurrentEntity.count - 1]; load(1, false, false); fCurrentEntity.position = 0; @@ -960,7 +960,7 @@ public class XML11EntityScanner load(0, true, true); } else if (fCurrentEntity.position == fCurrentEntity.count - 1) { - invokeListeners(0); + invokeListeners(1); fCurrentEntity.ch[0] = fCurrentEntity.ch[fCurrentEntity.count - 1]; load(1, false, false); fCurrentEntity.startPosition = 0; @@ -1397,7 +1397,7 @@ public class XML11EntityScanner fCurrentEntity.lineNumber++; fCurrentEntity.columnNumber = 1; if (fCurrentEntity.position == fCurrentEntity.count - 1) { - invokeListeners(0); + invokeListeners(1); fCurrentEntity.ch[0] = (char)c; entityChanged = load(1, true, false); if (!entityChanged) { @@ -1446,8 +1446,9 @@ public class XML11EntityScanner fCurrentEntity.lineNumber++; fCurrentEntity.columnNumber = 1; if (fCurrentEntity.position == fCurrentEntity.count - 1) { + invokeListeners(1); fCurrentEntity.ch[0] = (char)c; - entityChanged = load(1, true, true); + entityChanged = load(1, true, false); if (!entityChanged) { // the load change the position to be 1, // need to restore it when entity not changed diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDTDScannerImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDTDScannerImpl.java index 4daa5f0e333eb779666239daf436a862861c215c..d695936f67d4d19e240c53a115e690977a07c99f 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDTDScannerImpl.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDTDScannerImpl.java @@ -3,13 +3,14 @@ */ /* - * Copyright 2005 The Apache Software Foundation. + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -19,17 +20,17 @@ */ package com.sun.org.apache.xerces.internal.impl; -import com.sun.xml.internal.stream.dtd.nonvalidating.DTDGrammar; -import java.io.EOFException; -import java.io.IOException; +import com.sun.org.apache.xerces.internal.impl.Constants; import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter; - +import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter; +import com.sun.org.apache.xerces.internal.impl.XMLEntityHandler; import com.sun.org.apache.xerces.internal.util.SymbolTable; import com.sun.org.apache.xerces.internal.util.XMLAttributesImpl; import com.sun.org.apache.xerces.internal.util.XMLChar; import com.sun.org.apache.xerces.internal.util.XMLStringBuffer; - +import com.sun.org.apache.xerces.internal.utils.XMLLimitAnalyzer; +import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; import com.sun.org.apache.xerces.internal.xni.XMLDTDContentModelHandler; import com.sun.org.apache.xerces.internal.xni.XMLDTDHandler; import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier; @@ -41,11 +42,9 @@ import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException; import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDScanner; import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource; import com.sun.org.apache.xerces.internal.xni.Augmentations; -import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter; -import com.sun.org.apache.xerces.internal.impl.XMLEntityHandler; -import com.sun.org.apache.xerces.internal.impl.Constants; -import com.sun.org.apache.xerces.internal.utils.XMLLimitAnalyzer; -import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; +import com.sun.xml.internal.stream.dtd.nonvalidating.DTDGrammar; +import java.io.EOFException; +import java.io.IOException; /** * This class is responsible for scanning the declarations found @@ -387,15 +386,25 @@ implements XMLDTDScanner, XMLComponent, XMLEntityHandler { */ @Override public boolean skipDTD(boolean supportDTD) throws IOException { - if (!supportDTD) { - fStringBuffer.clear(); - if (!fEntityScanner.scanData("]", fStringBuffer)) { - fEntityScanner.fCurrentEntity.position--; + if (supportDTD) + return false; + + fStringBuffer.clear(); + while (fEntityScanner.scanData("]", fStringBuffer)) { + int c = fEntityScanner.peekChar(); + if (c != -1) { + if (XMLChar.isHighSurrogate(c)) { + scanSurrogates(fStringBuffer); + } + if (isInvalidLiteral(c)) { + reportFatalError("InvalidCharInDTD", + new Object[] { Integer.toHexString(c) }); + fEntityScanner.scanChar(); + } } - - return true; } - return false; + fEntityScanner.fCurrentEntity.position--; + return true; } // 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 e31e838c8e800f0cad48da897082be0f4ab504cf..c817111e067c1106e88e77dfaba4f6717b730ded 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 @@ -3,13 +3,14 @@ */ /* - * Copyright 2005 The Apache Software Foundation. + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -18,7 +19,6 @@ * limitations under the License. */ - package com.sun.org.apache.xerces.internal.impl; import com.sun.xml.internal.stream.XMLBufferListener; 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 7f1bbf10226b86814eac4095f0c33c5b6ba65a5d..235d27ba5d8512d262b9cdbaecb19bf1d1a508ab 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 @@ -3,13 +3,14 @@ */ /* - * Copyright 2005 The Apache Software Foundation. + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -20,7 +21,6 @@ package com.sun.org.apache.xerces.internal.impl; - import com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDDescription; import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager; import com.sun.org.apache.xerces.internal.util.NamespaceSupport; @@ -1106,8 +1106,7 @@ public class XMLDocumentScannerImpl if (!moreToScan) { // end doctype declaration if (!fEntityScanner.skipChar(']')) { - reportFatalError("EXPECTED_SQUARE_BRACKET_TO_CLOSE_INTERNAL_SUBSET", - null); + reportFatalError("DoctypedeclNotClosed", new Object[]{fDoctypeName}); } fEntityScanner.skipSpaces(); if (!fEntityScanner.skipChar('>')) { diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityScanner.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityScanner.java index 1c0eca636a8b721c257d7ac5d34be2fea8e8289a..b79223123712316cabd61fdf1bfa03b20e2658e6 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityScanner.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityScanner.java @@ -1,15 +1,16 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. */ /* - * Copyright 2005 The Apache Software Foundation. + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -20,8 +21,6 @@ package com.sun.org.apache.xerces.internal.impl; - - import com.sun.org.apache.xerces.internal.impl.io.ASCIIReader; import com.sun.org.apache.xerces.internal.impl.io.UCSReader; import com.sun.org.apache.xerces.internal.impl.io.UTF8Reader; @@ -44,8 +43,8 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; +import java.util.ArrayList; import java.util.Locale; -import java.util.Vector; /** * Implements the entity scanner methods. @@ -58,11 +57,10 @@ import java.util.Vector; */ public class XMLEntityScanner implements XMLLocator { - - protected Entity.ScannedEntity fCurrentEntity = null ; + protected Entity.ScannedEntity fCurrentEntity = null; protected int fBufferSize = XMLEntityManager.DEFAULT_BUFFER_SIZE; - protected XMLEntityManager fEntityManager ; + protected XMLEntityManager fEntityManager; /** Security manager. */ protected XMLSecurityManager fSecurityManager = null; @@ -72,8 +70,9 @@ public class XMLEntityScanner implements XMLLocator { /** Debug switching readers for encodings. */ private static final boolean DEBUG_ENCODINGS = false; + /** Listeners which should know when load is being called */ - private Vector listeners = new Vector(); + private ArrayList listeners = new ArrayList<>(); private static final boolean [] VALID_NAMES = new boolean[127]; @@ -140,9 +139,11 @@ public class XMLEntityScanner implements XMLLocator { VALID_NAMES[58]=true; VALID_NAMES[95]=true; } - // SAPJVM: Remember, that the XML version has explicitly been set, + + // Remember, that the XML version has explicitly been set, // so that XMLStreamReader.getVersion() can find that out. - boolean xmlVersionSetExplicitly = false; + protected boolean xmlVersionSetExplicitly = false; + // // Constructors // @@ -257,7 +258,7 @@ public class XMLEntityScanner implements XMLLocator { * @param xmlVersion the XML version of the current entity */ public final void setXMLVersion(String xmlVersion) { - xmlVersionSetExplicitly = true; // SAPJVM + xmlVersionSetExplicitly = true; fCurrentEntity.xmlVersion = xmlVersion; } // setXMLVersion(String) @@ -546,8 +547,7 @@ public class XMLEntityScanner implements XMLLocator { // scan character int c = fCurrentEntity.ch[fCurrentEntity.position++]; - if (c == '\n' || - (c == '\r' && isExternal)) { + if (c == '\n' || (c == '\r' && isExternal)) { fCurrentEntity.lineNumber++; fCurrentEntity.columnNumber = 1; if (fCurrentEntity.position == fCurrentEntity.count) { @@ -953,7 +953,7 @@ public class XMLEntityScanner implements XMLLocator { if (fCurrentEntity.position == fCurrentEntity.count) { load(0, true, true); } else if (fCurrentEntity.position == fCurrentEntity.count - 1) { - invokeListeners(0); + invokeListeners(1); fCurrentEntity.ch[0] = fCurrentEntity.ch[fCurrentEntity.count - 1]; load(1, false, false); fCurrentEntity.position = 0; @@ -1105,7 +1105,7 @@ public class XMLEntityScanner implements XMLLocator { if (fCurrentEntity.position == fCurrentEntity.count) { load(0, true, true); } else if (fCurrentEntity.position == fCurrentEntity.count - 1) { - invokeListeners(0); + invokeListeners(1); fCurrentEntity.ch[0] = fCurrentEntity.ch[fCurrentEntity.count - 1]; load(1, false, false); fCurrentEntity.position = 0; @@ -1256,8 +1256,8 @@ public class XMLEntityScanner implements XMLLocator { *

* Note: The characters are consumed. *

- * Note: This assumes that the length of the delimiter - * and that the delimiter contains at least one character. + * Note: This assumes that the delimiter contains at + * least one character. *

* Note: This method does not guarantee to return * the longest run of character data. This method may return before @@ -1436,7 +1436,7 @@ public class XMLEntityScanner implements XMLLocator { } while (!done); return !done; - } // scanData(String,XMLString) + } // scanData(String, XMLStringBuffer) /** * Skips a character appearing immediately on the input. @@ -1558,7 +1558,7 @@ public class XMLEntityScanner implements XMLLocator { fCurrentEntity.lineNumber++; fCurrentEntity.columnNumber = 1; if (fCurrentEntity.position == fCurrentEntity.count - 1) { - invokeListeners(0); + invokeListeners(1); fCurrentEntity.ch[0] = (char)c; entityChanged = load(1, true, false); if (!entityChanged){ @@ -1727,8 +1727,7 @@ public class XMLEntityScanner implements XMLLocator { final int length = s.length; //first make sure that required capacity is avaible if(arrangeCapacity(length, false)){ - int beforeSkip = fCurrentEntity.position ; - int afterSkip = fCurrentEntity.position + length ; + int beforeSkip = fCurrentEntity.position; if(DEBUG_SKIP_STRING){ System.out.println("skipString,length = " + new String(s) + "," + length); @@ -2107,8 +2106,9 @@ public class XMLEntityScanner implements XMLLocator { * is being changed. */ public void registerListener(XMLBufferListener listener) { - if(!listeners.contains(listener)) + if (!listeners.contains(listener)) { listeners.add(listener); + } } /** @@ -2116,9 +2116,8 @@ public class XMLEntityScanner implements XMLLocator { * @param loadPos Starting position from which new data is being loaded into scanner buffer. */ public void invokeListeners(int loadPos){ - for(int i=0;i''. + DoctypedeclNotClosed = The document type declaration for root element type \"{0}\" must be closed with '']''. PEReferenceWithinMarkup = The parameter entity reference \"%{0};\" cannot occur within markup in the internal subset of the DTD. MSG_MARKUP_NOT_RECOGNIZED_IN_DTD = The markup declarations contained or pointed to by the document type declaration must be well-formed. # 2.10 White Space Handling diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_de.properties b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_de.properties index c82bc5b80d0cbbd1a41662caa9aef0f640b1b5b6..55c9d3a3c920b263204ba7acdeb2797f6ad23dc3 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_de.properties +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_de.properties @@ -145,6 +145,7 @@ MSG_SPACE_REQUIRED_BEFORE_ROOT_ELEMENT_TYPE_IN_DOCTYPEDECL = Leerstelle nach "" enden. + DoctypedeclNotClosed = Dokumenttypdeklaration f\u00FCr Root-Elementtyp "{0}" muss mit "]" abgeschlossen werden. PEReferenceWithinMarkup = Parameterentit\u00E4tsreferenz "%{0};" darf nicht in Markup in der internen Teilmenge der DTD vorkommen. MSG_MARKUP_NOT_RECOGNIZED_IN_DTD = Die Markup-Deklarationen, die in der Dokumenttypdeklaration enthalten sind bzw. auf die von der Dokumenttypdeklaration verwiesen wird, m\u00FCssen ordnungsgem\u00E4\u00DF formatiert sein. # 2.10 White Space Handling diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_es.properties b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_es.properties index 1243b215cec1a37e330cdc6716acdc9e60e59c10..51491f8407542fa8a3e0c04d2f549e5737042969 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_es.properties +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_es.properties @@ -145,6 +145,7 @@ MSG_SPACE_REQUIRED_BEFORE_ROOT_ELEMENT_TYPE_IN_DOCTYPEDECL = Es necesario un espacio en blanco despu\u00E9s de "''. + DoctypedeclNotClosed = La declaraci\u00F3n de tipo de documento para el tipo de elemento ra\u00EDz "{0}" debe cerrar en '']''. PEReferenceWithinMarkup = La referencia de entidad del par\u00E1metro "%{0};" no puede producirse en el marcador en el subconjunto interno del DTD. MSG_MARKUP_NOT_RECOGNIZED_IN_DTD = Las declaraciones de marcador que se incluyen o a las que apunta la declaraci\u00F3n de tipo de documento deben tener el formato correcto. # 2.10 White Space Handling diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_fr.properties b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_fr.properties index 5a2b76c13b77c29b605b382f5235a1ce3a5689ea..2be672257f394dc372fd4302fed1efab3bd47ec8 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_fr.properties +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_fr.properties @@ -145,6 +145,7 @@ MSG_SPACE_REQUIRED_BEFORE_ROOT_ELEMENT_TYPE_IN_DOCTYPEDECL = Un espace est obligatoire apr\u00E8s "''. + DoctypedeclNotClosed = La d\u00E9claration de type de document pour le type d''\u00E9l\u00E9ment racine "{0}" doit se conclure par '']''. PEReferenceWithinMarkup = La r\u00E9f\u00E9rence d''entit\u00E9 de param\u00E8tre "%{0};" ne peut pas survenir dans le balisage du sous-ensemble interne de la DTD. MSG_MARKUP_NOT_RECOGNIZED_IN_DTD = Les d\u00E9clarations de balisage contenues dans la d\u00E9claration de type de document ou sur lesquelles pointe cette derni\u00E8re doivent avoir un format correct. # 2.10 White Space Handling diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_it.properties b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_it.properties index 1f8ec89276aba2f9eecfc30caed3e386aa449518..aa229f49bf2a5b5c8fb3d4557f353c31bf46c7cd 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_it.properties +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_it.properties @@ -145,6 +145,7 @@ MSG_SPACE_REQUIRED_BEFORE_ROOT_ELEMENT_TYPE_IN_DOCTYPEDECL = \u00C8 richiesto uno spazio dopo "''. + DoctypedeclNotClosed = La dichiarazione del tipo di documento per il tipo di elemento radice "{0}" deve chiudere con '']''. PEReferenceWithinMarkup = Il riferimento di entit\u00E0 di parametro "%{0};" non pu\u00F2 essere presente nel markup del set secondario interno del DTD. MSG_MARKUP_NOT_RECOGNIZED_IN_DTD = Le dichiarazioni di markup contenute o indicate dalla dichiarazione del tipo di documento devono avere un formato corretto. # 2.10 White Space Handling diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/HTTPInputSource.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/HTTPInputSource.java index bdd0750d0faaf041feb6979e6f5714fcffdd3a23..c9bbed93511c2bfd528389043aec74eb2024d87c 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/HTTPInputSource.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/HTTPInputSource.java @@ -1,15 +1,16 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. */ + /* - * Copyright 2004,2005 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -17,18 +18,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package com.sun.org.apache.xerces.internal.util; +import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier; +import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource; import java.io.InputStream; import java.io.Reader; - import java.util.HashMap; import java.util.Iterator; import java.util.Map; -import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier; -import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource; - /** * This class represents an input source for an XML resource * retrievable over HTTP. In addition to the properties diff --git a/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/Asserts.java b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/Asserts.java new file mode 100644 index 0000000000000000000000000000000000000000..594b12e3edeec87fbbeb13b4130d418d5648daae --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/Asserts.java @@ -0,0 +1,566 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.testlibrary; + +import java.util.Objects; + +/** + * Asserts that can be used for verifying assumptions in tests. + * + * An assertion will throw a {@link RuntimeException} if the assertion isn't true. + * All the asserts can be imported into a test by using a static import: + * + *

+ * {@code
+ * import static jdk.testlibrary.Asserts.*;
+ * }
+ *
+ * Always provide a message describing the assumption if the line number of the
+ * failing assertion isn't enough to understand why the assumption failed. For
+ * example, if the assertion is in a loop or in a method that is called
+ * multiple times, then the line number won't provide enough context to
+ * understand the failure.
+ * 
+ * + * @deprecated This class is deprecated. Use the one from + * {@code /test/lib/share/classes/jdk/test/lib} + */ +@Deprecated +public class Asserts { + + /** + * Shorthand for {@link #assertLessThan(Comparable, Comparable)}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertLessThan(Comparable, Comparable) + */ + public static > void assertLT(T lhs, T rhs) { + assertLessThan(lhs, rhs); + } + + /** + * Shorthand for {@link #assertLessThan(Comparable, Comparable, String)}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @see #assertLessThan(Comparable, Comparable, String) + */ + public static > void assertLT(T lhs, T rhs, String msg) { + assertLessThan(lhs, rhs, msg); + } + + /** + * Calls {@link #assertLessThan(Comparable, Comparable, String)} with a default message. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertLessThan(Comparable, Comparable, String) + */ + public static > void assertLessThan(T lhs, T rhs) { + assertLessThan(lhs, rhs, null); + } + + /** + * Asserts that {@code lhs} is less than {@code rhs}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static >void assertLessThan(T lhs, T rhs, String msg) { + if (!(compare(lhs, rhs, msg) < 0)) { + msg = Objects.toString(msg, "assertLessThan") + + ": expected that " + Objects.toString(lhs) + + " < " + Objects.toString(rhs); + fail(msg); + } + } + + /** + * Shorthand for {@link #assertLessThanOrEqual(Comparable, Comparable)}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertLessThanOrEqual(Comparable, Comparable) + */ + public static > void assertLTE(T lhs, T rhs) { + assertLessThanOrEqual(lhs, rhs); + } + + /** + * Shorthand for {@link #assertLessThanOrEqual(Comparable, Comparable, String)}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @see #assertLessThanOrEqual(Comparable, Comparable, String) + */ + public static > void assertLTE(T lhs, T rhs, String msg) { + assertLessThanOrEqual(lhs, rhs, msg); + } + + /** + * Calls {@link #assertLessThanOrEqual(Comparable, Comparable, String)} with a default message. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertLessThanOrEqual(Comparable, Comparable, String) + */ + public static > void assertLessThanOrEqual(T lhs, T rhs) { + assertLessThanOrEqual(lhs, rhs, null); + } + + /** + * Asserts that {@code lhs} is less than or equal to {@code rhs}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static > void assertLessThanOrEqual(T lhs, T rhs, String msg) { + if (!(compare(lhs, rhs, msg) <= 0)) { + msg = Objects.toString(msg, "assertLessThanOrEqual") + + ": expected that " + Objects.toString(lhs) + + " <= " + Objects.toString(rhs); + fail(msg); + } + } + + /** + * Shorthand for {@link #assertEquals(Object, Object)}. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertEquals(Object, Object) + */ + public static void assertEQ(Object lhs, Object rhs) { + assertEquals(lhs, rhs); + } + + /** + * Shorthand for {@link #assertEquals(Object, Object, String)}. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @see #assertEquals(Object, Object, String) + */ + public static void assertEQ(Object lhs, Object rhs, String msg) { + assertEquals(lhs, rhs, msg); + } + + /** + * Calls {@link #assertEquals(java.lang.Object, java.lang.Object, java.lang.String)} with a default message. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertEquals(Object, Object, String) + */ + public static void assertEquals(Object lhs, Object rhs) { + assertEquals(lhs, rhs, null); + } + + /** + * Asserts that {@code lhs} is equal to {@code rhs}. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static void assertEquals(Object lhs, Object rhs, String msg) { + if ((lhs != rhs) && ((lhs == null) || !(lhs.equals(rhs)))) { + msg = Objects.toString(msg, "assertEquals") + + ": expected " + Objects.toString(lhs) + + " to equal " + Objects.toString(rhs); + fail(msg); + } + } + + /** + * Calls {@link #assertSame(java.lang.Object, java.lang.Object, java.lang.String)} with a default message. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertSame(Object, Object, String) + */ + public static void assertSame(Object lhs, Object rhs) { + assertSame(lhs, rhs, null); + } + + /** + * Asserts that {@code lhs} is the same as {@code rhs}. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static void assertSame(Object lhs, Object rhs, String msg) { + if (lhs != rhs) { + msg = Objects.toString(msg, "assertSame") + + ": expected " + Objects.toString(lhs) + + " to equal " + Objects.toString(rhs); + fail(msg); + } + } + + /** + * Shorthand for {@link #assertGreaterThanOrEqual(Comparable, Comparable)}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertGreaterThanOrEqual(Comparable, Comparable) + */ + public static > void assertGTE(T lhs, T rhs) { + assertGreaterThanOrEqual(lhs, rhs); + } + + /** + * Shorthand for {@link #assertGreaterThanOrEqual(Comparable, Comparable, String)}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @see #assertGreaterThanOrEqual(Comparable, Comparable, String) + */ + public static > void assertGTE(T lhs, T rhs, String msg) { + assertGreaterThanOrEqual(lhs, rhs, msg); + } + + /** + * Calls {@link #assertGreaterThanOrEqual(Comparable, Comparable, String)} with a default message. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertGreaterThanOrEqual(Comparable, Comparable, String) + */ + public static > void assertGreaterThanOrEqual(T lhs, T rhs) { + assertGreaterThanOrEqual(lhs, rhs, null); + } + + /** + * Asserts that {@code lhs} is greater than or equal to {@code rhs}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static > void assertGreaterThanOrEqual(T lhs, T rhs, String msg) { + if (!(compare(lhs, rhs, msg) >= 0)) { + msg = Objects.toString(msg, "assertGreaterThanOrEqual") + + ": expected " + Objects.toString(lhs) + + " >= " + Objects.toString(rhs); + fail(msg); + } + } + + /** + * Shorthand for {@link #assertGreaterThan(Comparable, Comparable)}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertGreaterThan(Comparable, Comparable) + */ + public static > void assertGT(T lhs, T rhs) { + assertGreaterThan(lhs, rhs); + } + + /** + * Shorthand for {@link #assertGreaterThan(Comparable, Comparable, String)}. + * + * @param a type + * @param lhs the left hand value + * @param rhs the right hand value + * @param msg A description of the assumption; {@code null} for a default message. + * @see #assertGreaterThan(Comparable, Comparable, String) + */ + public static > void assertGT(T lhs, T rhs, String msg) { + assertGreaterThan(lhs, rhs, msg); + } + + /** + * Calls {@link #assertGreaterThan(Comparable, Comparable, String)} with a default message. + * + * @param a type + * @param lhs the left hand value + * @param rhs the right hand value + * @see #assertGreaterThan(Comparable, Comparable, String) + */ + public static > void assertGreaterThan(T lhs, T rhs) { + assertGreaterThan(lhs, rhs, null); + } + + /** + * Asserts that {@code lhs} is greater than {@code rhs}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static > void assertGreaterThan(T lhs, T rhs, String msg) { + if (!(compare(lhs, rhs, msg) > 0)) { + msg = Objects.toString(msg, "assertGreaterThan") + + ": expected " + Objects.toString(lhs) + + " > " + Objects.toString(rhs); + fail(msg); + } + } + + /** + * Shorthand for {@link #assertNotEquals(Object, Object)}. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertNotEquals(Object, Object) + */ + public static void assertNE(Object lhs, Object rhs) { + assertNotEquals(lhs, rhs); + } + + /** + * Shorthand for {@link #assertNotEquals(Object, Object, String)}. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @see #assertNotEquals(Object, Object, String) + */ + public static void assertNE(Object lhs, Object rhs, String msg) { + assertNotEquals(lhs, rhs, msg); + } + + /** + * Calls {@link #assertNotEquals(Object, Object, String)} with a default message. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertNotEquals(Object, Object, String) + */ + public static void assertNotEquals(Object lhs, Object rhs) { + assertNotEquals(lhs, rhs, null); + } + + /** + * Asserts that {@code lhs} is not equal to {@code rhs}. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static void assertNotEquals(Object lhs, Object rhs, String msg) { + if ((lhs == rhs) || (lhs != null && lhs.equals(rhs))) { + msg = Objects.toString(msg, "assertNotEquals") + + ": expected " + Objects.toString(lhs) + + " to not equal " + Objects.toString(rhs); + fail(msg); + } + } + + /** + * Calls {@link #assertNull(Object, String)} with a default message. + * + * @param o The reference assumed to be null. + * @see #assertNull(Object, String) + */ + public static void assertNull(Object o) { + assertNull(o, null); + } + + /** + * Asserts that {@code o} is null. + * + * @param o The reference assumed to be null. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static void assertNull(Object o, String msg) { + assertEquals(o, null, msg); + } + + /** + * Calls {@link #assertNotNull(Object, String)} with a default message. + * + * @param o The reference assumed not to be null, + * @see #assertNotNull(Object, String) + */ + public static void assertNotNull(Object o) { + assertNotNull(o, null); + } + + /** + * Asserts that {@code o} is not null. + * + * @param o The reference assumed not to be null, + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static void assertNotNull(Object o, String msg) { + assertNotEquals(o, null, msg); + } + + /** + * Calls {@link #assertFalse(boolean, String)} with a default message. + * + * @param value The value assumed to be false. + * @see #assertFalse(boolean, String) + */ + public static void assertFalse(boolean value) { + assertFalse(value, null); + } + + /** + * Asserts that {@code value} is {@code false}. + * + * @param value The value assumed to be false. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static void assertFalse(boolean value, String msg) { + if (value) { + msg = Objects.toString(msg, "assertFalse") + + ": expected false, was true"; + fail(msg); + } + } + + /** + * Calls {@link #assertTrue(boolean, String)} with a default message. + * + * @param value The value assumed to be true. + * @see #assertTrue(boolean, String) + */ + public static void assertTrue(boolean value) { + assertTrue(value, null); + } + + /** + * Asserts that {@code value} is {@code true}. + * + * @param value The value assumed to be true. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static void assertTrue(boolean value, String msg) { + if (!value) { + msg = Objects.toString(msg, "assertTrue") + + ": expected true, was false"; + fail(msg); + } + } + + private static > int compare(T lhs, T rhs, String msg) { + if (lhs == null || rhs == null) { + fail(lhs, rhs, msg + ": values must be non-null:", ","); + } + return lhs.compareTo(rhs); + } + + /** + * Returns a string formatted with a message and expected and actual values. + * @param lhs the actual value + * @param rhs the expected value + * @param message the actual value + * @param relation the asserted relationship between lhs and rhs + * @return a formatted string + */ + public static String format(Object lhs, Object rhs, String message, String relation) { + StringBuilder sb = new StringBuilder(80); + if (message != null) { + sb.append(message); + sb.append(' '); + } + sb.append("<"); + sb.append(Objects.toString(lhs)); + sb.append("> "); + sb.append(Objects.toString(relation, ",")); + sb.append(" <"); + sb.append(Objects.toString(rhs)); + sb.append(">"); + return sb.toString(); + } + + /** + * Fail reports a failure with message fail. + * + * @throws RuntimeException always + */ + public static void fail() { + fail("fail"); + } + + /** + * Fail reports a failure with a message. + * @param message for the failure + * @throws RuntimeException always + */ + public static void fail(String message) { + throw new RuntimeException(message); + } + + /** + * Fail reports a failure with a formatted message. + * + * @param lhs the actual value + * @param rhs the expected value + * @param message to be format before the expected and actual values + * @param relation the asserted relationship between lhs and rhs + * @throws RuntimeException always + */ + public static void fail(Object lhs, Object rhs, String message, String relation) { + throw new RuntimeException(format(lhs, rhs, message, relation)); + } + + /** + * Fail reports a failure with a message and a cause. + * @param message to be format before the expected and actual values + * @param cause the exception that caused this failure + * @throws RuntimeException always + */ + public static void fail(String message, Throwable cause) { + throw new RuntimeException(message, cause); + } + +} diff --git a/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/CompilerUtils.java b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/CompilerUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..afabfd7cc52515e0a927473af3b7978840b2bf50 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/CompilerUtils.java @@ -0,0 +1,81 @@ +/* + * 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 jdk.testlibrary; + +import javax.tools.JavaCompiler; +import javax.tools.StandardJavaFileManager; +import javax.tools.StandardLocation; +import javax.tools.ToolProvider; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +/** + * This class consists exclusively of static utility methods for invoking the + * java compiler. + */ + +public final class CompilerUtils { + private CompilerUtils() { } + + /** + * Compile all the java sources in {@code /**} to + * {@code /**}. The destination directory will be created if + * it doesn't exist. + * + * All warnings/errors emitted by the compiler are output to System.out/err. + * + * @return true if the compilation is successful + * + * @throws IOException if there is an I/O error scanning the source tree or + * creating the destination directory + */ + public static boolean compile(Path source, Path destination, String ... options) + throws IOException + { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + StandardJavaFileManager jfm = compiler.getStandardFileManager(null, null, null); + + List sources + = Files.find(source, Integer.MAX_VALUE, + (file, attrs) -> (file.toString().endsWith(".java"))) + .collect(Collectors.toList()); + + Files.createDirectories(destination); + jfm.setLocation(StandardLocation.CLASS_PATH, Collections.EMPTY_LIST); + jfm.setLocationFromPaths(StandardLocation.CLASS_OUTPUT, + Arrays.asList(destination)); + + List opts = Arrays.asList(options); + JavaCompiler.CompilationTask task + = compiler.getTask(null, jfm, null, opts, null, + jfm.getJavaFileObjectsFromPaths(sources)); + + return task.call(); + } +} diff --git a/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/JDKToolFinder.java b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/JDKToolFinder.java new file mode 100644 index 0000000000000000000000000000000000000000..c4815229eb721efe5b36747f71a3f25df49ac10f --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/JDKToolFinder.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.testlibrary; + +import java.io.FileNotFoundException; +import java.nio.file.Path; +import java.nio.file.Paths; + +/** + * @deprecated This class is deprecated. Use the one from + * {@code /test/lib/share/classes/jdk/test/lib} + */ +@Deprecated +public final class JDKToolFinder { + + private JDKToolFinder() { + } + + /** + * Returns the full path to an executable in jdk/bin based on System + * property {@code test.jdk} or {@code compile.jdk} (both are set by the jtreg test suite) + * + * @return Full path to an executable in jdk/bin + */ + public static String getJDKTool(String tool) { + + // First try to find the executable in test.jdk + try { + return getTool(tool, "test.jdk"); + } catch (FileNotFoundException e) { + + } + + // Now see if it's available in compile.jdk + try { + return getTool(tool, "compile.jdk"); + } catch (FileNotFoundException e) { + throw new RuntimeException("Failed to find " + tool + + ", looked in test.jdk (" + System.getProperty("test.jdk") + + ") and compile.jdk (" + System.getProperty("compile.jdk") + ")"); + } + } + + /** + * Returns the full path to an executable in jdk/bin based on System + * property {@code compile.jdk} + * + * @return Full path to an executable in jdk/bin + */ + public static String getCompileJDKTool(String tool) { + try { + return getTool(tool, "compile.jdk"); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } + } + + /** + * Returns the full path to an executable in jdk/bin based on System + * property {@code test.jdk} + * + * @return Full path to an executable in jdk/bin + */ + public static String getTestJDKTool(String tool) { + try { + return getTool(tool, "test.jdk"); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } + } + + private static String getTool(String tool, String property) throws FileNotFoundException { + String jdkPath = System.getProperty(property); + + if (jdkPath == null) { + throw new RuntimeException( + "System property '" + property + "' not set. This property is normally set by jtreg. " + + "When running test separately, set this property using '-D" + property + "=/path/to/jdk'."); + } + + Path toolName = Paths.get("bin", tool + (Platform.isWindows() ? ".exe" : "")); + + Path jdkTool = Paths.get(jdkPath, toolName.toString()); + if (!jdkTool.toFile().exists()) { + throw new FileNotFoundException("Could not find file " + jdkTool.toAbsolutePath()); + } + + return jdkTool.toAbsolutePath().toString(); + } +} diff --git a/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/JDKToolLauncher.java b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/JDKToolLauncher.java new file mode 100644 index 0000000000000000000000000000000000000000..777e8cf53363eb418b7c882d9c652c9ea4fff792 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/JDKToolLauncher.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.testlibrary; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * A utility for constructing command lines for starting JDK tool processes. + * + * The JDKToolLauncher can in particular be combined with a + * java.lang.ProcessBuilder to easily run a JDK tool. For example, the following + * code run {@code jmap -heap} against a process with GC logging turned on for + * the {@code jmap} process: + * + *
+ * {@code
+ * JDKToolLauncher jmap = JDKToolLauncher.create("jmap")
+ *                                       .addVMArg("-Xlog:gc*=debug")
+ *                                       .addToolArg("-heap")
+ *                                       .addToolArg(pid);
+ * ProcessBuilder pb = new ProcessBuilder(jmap.getCommand());
+ * Process p = pb.start();
+ * }
+ * 
+ * @deprecated This class is deprecated. Use the one from + * {@code /test/lib/share/classes/jdk/test/lib} + */ +@Deprecated +public class JDKToolLauncher { + private final String executable; + private final List vmArgs = new ArrayList(); + private final List toolArgs = new ArrayList(); + + private JDKToolLauncher(String tool, boolean useCompilerJDK) { + if (useCompilerJDK) { + executable = JDKToolFinder.getJDKTool(tool); + } else { + executable = JDKToolFinder.getTestJDKTool(tool); + } + vmArgs.addAll(Arrays.asList(ProcessTools.getPlatformSpecificVMArgs())); + } + + /** + * Creates a new JDKToolLauncher for the specified tool. Using tools path + * from the compiler JDK. + * + * @param tool + * The name of the tool + * @return A new JDKToolLauncher + */ + public static JDKToolLauncher create(String tool) { + return new JDKToolLauncher(tool, true); + } + + /** + * Creates a new JDKToolLauncher for the specified tool in the Tested JDK. + * + * @param tool + * The name of the tool + * + * @return A new JDKToolLauncher + */ + public static JDKToolLauncher createUsingTestJDK(String tool) { + return new JDKToolLauncher(tool, false); + } + + /** + * Adds an argument to the JVM running the tool. + * + * The JVM arguments are passed to the underlying JVM running the tool. + * Arguments will automatically be prepended with "-J". + * + * Any platform specific arguments required for running the tool are + * automatically added. + * + * + * @param arg + * The argument to VM running the tool + * @return The JDKToolLauncher instance + */ + public JDKToolLauncher addVMArg(String arg) { + vmArgs.add(arg); + return this; + } + + /** + * Adds an argument to the tool. + * + * @param arg + * The argument to the tool + * @return The JDKToolLauncher instance + */ + public JDKToolLauncher addToolArg(String arg) { + toolArgs.add(arg); + return this; + } + + /** + * Returns the command that can be used for running the tool. + * + * @return An array whose elements are the arguments of the command. + */ + public String[] getCommand() { + List command = new ArrayList(); + command.add(executable); + // Add -J in front of all vmArgs + for (String arg : vmArgs) { + command.add("-J" + arg); + } + command.addAll(toolArgs); + return command.toArray(new String[command.size()]); + } +} diff --git a/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/OutputAnalyzer.java b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/OutputAnalyzer.java new file mode 100644 index 0000000000000000000000000000000000000000..839c3228294a7b859c684bd616f99d7b78c2b65d --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/OutputAnalyzer.java @@ -0,0 +1,576 @@ +/* + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.testlibrary; + +import static jdk.testlibrary.Asserts.*; + +import java.io.IOException; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Utility class for verifying output and exit value from a {@code Process}. + * + * @deprecated This class is deprecated. Use the one from + * {@code /test/lib/share/classes/jdk/test/lib/process} + * + */ +@Deprecated +public final class OutputAnalyzer { + private final OutputBuffer output; + private final String stdout; + private final String stderr; + private final int exitValue; // useless now. output contains exit value. + + /** + * Create an OutputAnalyzer, a utility class for verifying output and exit + * value from a Process. + *

+ * OutputAnalyzer should never be instantiated directly - + * use {@linkplain ProcessTools#executeProcess(ProcessBuilder)} instead + * + * @param process + * Process to analyze + * @throws IOException + * If an I/O error occurs. + */ + OutputAnalyzer(Process process) throws IOException { + output = new OutputBuffer(process); + exitValue = -1; + this.stdout = null; + this.stderr = null; + } + + /** + * Create an OutputAnalyzer, a utility class for verifying output. + * + * @param buf + * String buffer to analyze + */ + OutputAnalyzer(String buf) { + this(buf, buf); + } + + /** + * Create an OutputAnalyzer, a utility class for verifying output + * + * @param stdout + * stdout buffer to analyze + * @param stderr + * stderr buffer to analyze + */ + OutputAnalyzer(String stdout, String stderr) { + this.output = null; + this.stdout = stdout; + this.stderr = stderr; + exitValue = -1; + } + + /** + * Verify that the stdout and stderr contents of output buffer contains the + * string + * + * @param expectedString + * String that buffer should contain + * @throws RuntimeException + * If the string was not found + */ + public OutputAnalyzer shouldContain(String expectedString) { + if (!getStdout().contains(expectedString) + && !getStderr().contains(expectedString)) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + expectedString + + "' missing from stdout/stderr \n"); + } + return this; + } + + /** + * Verify that the stdout contents of output buffer contains the string + * + * @param expectedString + * String that buffer should contain + * @throws RuntimeException + * If the string was not found + */ + public OutputAnalyzer stdoutShouldContain(String expectedString) { + if (!getStdout().contains(expectedString)) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + expectedString + + "' missing from stdout \n"); + } + return this; + } + + /** + * Verify that the stderr contents of output buffer contains the string + * + * @param expectedString + * String that buffer should contain + * @throws RuntimeException + * If the string was not found + */ + public OutputAnalyzer stderrShouldContain(String expectedString) { + if (!getStderr().contains(expectedString)) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + expectedString + + "' missing from stderr \n"); + } + return this; + } + + /** + * Verify that the stdout and stderr contents of output buffer does not + * contain the string + * + * @param notExpectedString + * String that the buffer should not contain + * @throws RuntimeException + * If the string was found + */ + public OutputAnalyzer shouldNotContain(String notExpectedString) { + if (getStdout().contains(notExpectedString)) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + notExpectedString + + "' found in stdout \n"); + } + if (getStderr().contains(notExpectedString)) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + notExpectedString + + "' found in stderr \n"); + } + return this; + } + + /** + * Verify that the stdout contents of output buffer does not contain the + * string + * + * @param notExpectedString + * String that the buffer should not contain + * @throws RuntimeException + * If the string was found + */ + public OutputAnalyzer stdoutShouldNotContain(String notExpectedString) { + if (getStdout().contains(notExpectedString)) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + notExpectedString + + "' found in stdout \n"); + } + return this; + } + + /** + * Verify that the stderr contents of output buffer does not contain the + * string + * + * @param notExpectedString + * String that the buffer should not contain + * @throws RuntimeException + * If the string was found + */ + public OutputAnalyzer stderrShouldNotContain(String notExpectedString) { + if (getStderr().contains(notExpectedString)) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + notExpectedString + + "' found in stderr \n"); + } + return this; + } + + /** + * Verify that the stdout and stderr contents of output buffer matches the + * pattern + * + * @param pattern + * @throws RuntimeException + * If the pattern was not found + */ + public OutputAnalyzer shouldMatch(String pattern) { + Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE) + .matcher(getStdout()); + Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE) + .matcher(getStderr()); + if (!stdoutMatcher.find() && !stderrMatcher.find()) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + pattern + + "' missing from stdout/stderr \n"); + } + return this; + } + + /** + * Verify that the stdout contents of output buffer matches the pattern + * + * @param pattern + * @throws RuntimeException + * If the pattern was not found + */ + public OutputAnalyzer stdoutShouldMatch(String pattern) { + Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher( + getStdout()); + if (!matcher.find()) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + pattern + + "' missing from stdout \n"); + } + return this; + } + + /** + * Verify that the stderr contents of output buffer matches the pattern + * + * @param pattern + * @throws RuntimeException + * If the pattern was not found + */ + public OutputAnalyzer stderrShouldMatch(String pattern) { + Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher( + getStderr()); + if (!matcher.find()) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + pattern + + "' missing from stderr \n"); + } + return this; + } + + /** + * Verify that the stdout and stderr contents of output buffer does not + * match the pattern + * + * @param pattern + * @throws RuntimeException + * If the pattern was found + */ + public OutputAnalyzer shouldNotMatch(String pattern) { + Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher( + getStdout()); + if (matcher.find()) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + pattern + "' found in stdout: '" + + matcher.group() + "' \n"); + } + matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(getStderr()); + if (matcher.find()) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + pattern + "' found in stderr: '" + + matcher.group() + "' \n"); + } + return this; + } + + /** + * Verify that the stdout contents of output buffer does not match the + * pattern + * + * @param pattern + * @throws RuntimeException + * If the pattern was found + */ + public OutputAnalyzer stdoutShouldNotMatch(String pattern) { + Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher( + getStdout()); + if (matcher.find()) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + pattern + "' found in stdout \n"); + } + return this; + } + + /** + * Verify that the stderr contents of output buffer does not match the + * pattern + * + * @param pattern + * @throws RuntimeException + * If the pattern was found + */ + public OutputAnalyzer stderrShouldNotMatch(String pattern) { + Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher( + getStderr()); + if (matcher.find()) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + pattern + "' found in stderr \n"); + } + return this; + } + + /** + * Get the captured group of the first string matching the pattern. stderr + * is searched before stdout. + * + * @param pattern + * The multi-line pattern to match + * @param group + * The group to capture + * @return The matched string or null if no match was found + */ + public String firstMatch(String pattern, int group) { + Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE) + .matcher(getStderr()); + Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE) + .matcher(getStdout()); + if (stderrMatcher.find()) { + return stderrMatcher.group(group); + } + if (stdoutMatcher.find()) { + return stdoutMatcher.group(group); + } + return null; + } + + /** + * Get the first string matching the pattern. stderr is searched before + * stdout. + * + * @param pattern + * The multi-line pattern to match + * @return The matched string or null if no match was found + */ + public String firstMatch(String pattern) { + return firstMatch(pattern, 0); + } + + /** + * Verify the exit value of the process + * + * @param expectedExitValue + * Expected exit value from process + * @throws RuntimeException + * If the exit value from the process did not match the expected + * value + */ + public OutputAnalyzer shouldHaveExitValue(int expectedExitValue) { + if (getExitValue() != expectedExitValue) { + reportDiagnosticSummary(); + throw new RuntimeException("Expected to get exit value of [" + + expectedExitValue + "]\n"); + } + return this; + } + + /** + * Report summary that will help to diagnose the problem Currently includes: + * - standard input produced by the process under test - standard output - + * exit code Note: the command line is printed by the ProcessTools + */ + private OutputAnalyzer reportDiagnosticSummary() { + String msg = " stdout: [" + getStdout() + "];\n" + " stderr: [" + getStderr() + + "]\n" + " exitValue = " + getExitValue() + "\n"; + + System.err.println(msg); + return this; + } + + /** + * Get the contents of the output buffer (stdout and stderr) + * + * @return Content of the output buffer + */ + public String getOutput() { + return getStdout() + getStderr(); + } + + /** + * Get the contents of the stdout buffer + * + * @return Content of the stdout buffer + */ + public String getStdout() { + return output == null ? stdout : output.getStdout(); + } + + /** + * Get the contents of the stderr buffer + * + * @return Content of the stderr buffer + */ + public String getStderr() { + return output == null ? stderr : output.getStderr(); + } + + /** + * Get the process exit value + * + * @return Process exit value + */ + public int getExitValue() { + return output == null ? exitValue : output.getExitValue(); + } + + + /** + * Print the stdout buffer to the given {@code PrintStream}. + * + * @return this OutputAnalyzer + */ + public OutputAnalyzer outputTo(PrintStream out) { + out.println(getStdout()); + return this; + } + + /** + * Print the stderr buffer to the given {@code PrintStream}. + * + * @return this OutputAnalyzer + */ + public OutputAnalyzer errorTo(PrintStream out) { + out.println(getStderr()); + return this; + } + + + /** + * Get the contents of the output buffer (stdout and stderr) as list of strings. + * Output will be split by system property 'line.separator'. + * + * @return Contents of the output buffer as list of strings + */ + public List asLines() { + return asLines(getOutput()); + } + + private List asLines(String buffer) { + List l = new ArrayList<>(); + String[] a = buffer.split(Utils.NEW_LINE); + for (String string : a) { + l.add(string); + } + return l; + } + + /** + * Check if there is a line matching {@code pattern} and return its index + * + * @param pattern Matching pattern + * @return Index of first matching line + */ + private int indexOf(List lines, String pattern) { + for (int i = 0; i < lines.size(); i++) { + if (lines.get(i).matches(pattern)) { + return i; + } + } + return -1; + } + + /** + * @see #shouldMatchByLine(String, String, String) + */ + public int shouldMatchByLine(String pattern) { + return shouldMatchByLine(null, null, pattern); + } + + /** + * @see #stdoutShouldMatchByLine(String, String, String) + */ + public int stdoutShouldMatchByLine(String pattern) { + return stdoutShouldMatchByLine(null, null, pattern); + } + + /** + * @see #shouldMatchByLine(String, String, String) + */ + public int shouldMatchByLineFrom(String from, String pattern) { + return shouldMatchByLine(from, null, pattern); + } + + /** + * @see #shouldMatchByLine(String, String, String) + */ + public int shouldMatchByLineTo(String to, String pattern) { + return shouldMatchByLine(null, to, pattern); + } + + /** + * Verify that the stdout and stderr contents of output buffer match the + * {@code pattern} line by line. The whole output could be matched or + * just a subset of it. + * + * @param from + * The line from where output will be matched. + * Set {@code from} to null for matching from the first line. + * @param to + * The line until where output will be matched. + * Set {@code to} to null for matching until the last line. + * @param pattern + * Matching pattern + * @return Count of lines which match the {@code pattern} + */ + public int shouldMatchByLine(String from, String to, String pattern) { + return shouldMatchByLine(getOutput(), from, to, pattern); + } + + /** + * Verify that the stdout contents of output buffer matches the + * {@code pattern} line by line. The whole stdout could be matched or + * just a subset of it. + * + * @param from + * The line from where stdout will be matched. + * Set {@code from} to null for matching from the first line. + * @param to + * The line until where stdout will be matched. + * Set {@code to} to null for matching until the last line. + * @param pattern + * Matching pattern + * @return Count of lines which match the {@code pattern} + */ + public int stdoutShouldMatchByLine(String from, String to, String pattern) { + return shouldMatchByLine(getStdout(), from, to, pattern); + } + + private int shouldMatchByLine(String buffer, String from, String to, String pattern) { + List lines = asLines(buffer); + + int fromIndex = 0; + if (from != null) { + fromIndex = indexOf(lines, from); + assertGreaterThan(fromIndex, -1, + "The line/pattern '" + from + "' from where the output should match can not be found"); + } + + int toIndex = lines.size(); + if (to != null) { + toIndex = indexOf(lines, to); + assertGreaterThan(toIndex, -1, + "The line/pattern '" + to + "' until where the output should match can not be found"); + } + + List subList = lines.subList(fromIndex, toIndex); + int matchedCount = 0; + for (String line : subList) { + assertTrue(line.matches(pattern), + "The line '" + line + "' does not match pattern '" + pattern + "'"); + matchedCount++; + } + + return matchedCount; + } + +} diff --git a/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/OutputBuffer.java b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/OutputBuffer.java new file mode 100644 index 0000000000000000000000000000000000000000..c8a5d7aab12a347fde990462b43857323732d5c7 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/OutputBuffer.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.testlibrary; + +import java.io.ByteArrayOutputStream; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + +/** + * @deprecated This class is deprecated. Use the one from + * {@code /test/lib/share/classes/jdk/test/lib/process} + */ +@Deprecated +class OutputBuffer { + private static class OutputBufferException extends RuntimeException { + private static final long serialVersionUID = 8528687792643129571L; + + public OutputBufferException(Throwable cause) { + super(cause); + } + } + + private final Process p; + private final Future outTask; + private final Future errTask; + private final ByteArrayOutputStream stderrBuffer = new ByteArrayOutputStream(); + private final ByteArrayOutputStream stdoutBuffer = new ByteArrayOutputStream(); + + /** + * Create an OutputBuffer, a class for storing and managing stdout and + * stderr results separately + * + * @param stdout + * stdout result + * @param stderr + * stderr result + */ + OutputBuffer(Process p) { + this.p = p; + StreamPumper outPumper = new StreamPumper(p.getInputStream(), + stdoutBuffer); + StreamPumper errPumper = new StreamPumper(p.getErrorStream(), + stderrBuffer); + + outTask = outPumper.process(); + errTask = errPumper.process(); + } + + /** + * Returns the stdout result + * + * @return stdout result + */ + public String getStdout() { + try { + outTask.get(); + return stdoutBuffer.toString(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new OutputBufferException(e); + } catch (ExecutionException | CancellationException e) { + throw new OutputBufferException(e); + } + } + + /** + * Returns the stderr result + * + * @return stderr result + */ + public String getStderr() { + try { + errTask.get(); + return stderrBuffer.toString(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new OutputBufferException(e); + } catch (ExecutionException | CancellationException e) { + throw new OutputBufferException(e); + } + } + + public int getExitValue() { + try { + return p.waitFor(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new OutputBufferException(e); + } + } +} diff --git a/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/Platform.java b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/Platform.java new file mode 100644 index 0000000000000000000000000000000000000000..523e6e6a074babee965f0ed1bab1671d8b5c9570 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/Platform.java @@ -0,0 +1,213 @@ +/* + * 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 + * 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 jdk.testlibrary; +import java.util.regex.Pattern; +import java.io.RandomAccessFile; +import java.io.FileNotFoundException; +import java.io.IOException; + +/** + * @deprecated This class is deprecated. Use the one from + * {@code /test/lib/share/classes/jdk/test/lib} + */ +@Deprecated +public class Platform { + private static final String osName = System.getProperty("os.name"); + private static final String dataModel = System.getProperty("sun.arch.data.model"); + private static final String vmVersion = System.getProperty("java.vm.version"); + private static final String jdkDebug = System.getProperty("jdk.debug"); + private static final String osArch = System.getProperty("os.arch"); + private static final String vmName = System.getProperty("java.vm.name"); + private static final String userName = System.getProperty("user.name"); + private static final String compiler = System.getProperty("sun.management.compiler"); + + public static boolean isClient() { + return vmName.endsWith(" Client VM"); + } + + public static boolean isServer() { + return vmName.endsWith(" Server VM"); + } + + public static boolean isGraal() { + return vmName.endsWith(" Graal VM"); + } + + public static boolean isMinimal() { + return vmName.endsWith(" Minimal VM"); + } + + public static boolean isEmbedded() { + return vmName.contains("Embedded"); + } + + public static boolean isTieredSupported() { + return compiler.contains("Tiered Compilers"); + } + + + public static boolean is32bit() { + return dataModel.equals("32"); + } + + public static boolean is64bit() { + return dataModel.equals("64"); + } + + public static boolean isAix() { + return isOs("aix"); + } + + public static boolean isLinux() { + return isOs("linux"); + } + + public static boolean isOSX() { + return isOs("mac"); + } + + public static boolean isSolaris() { + return isOs("sunos"); + } + + public static boolean isWindows() { + return isOs("win"); + } + + private static boolean isOs(String osname) { + return osName.toLowerCase().startsWith(osname.toLowerCase()); + } + + public static String getOsName() { + return osName; + } + + public static boolean isDebugBuild() { + return (jdkDebug.toLowerCase().contains("debug")); + } + + public static String getVMVersion() { + return vmVersion; + } + + // Returns true for sparc and sparcv9. + public static boolean isSparc() { + return isArch("sparc.*"); + } + + public static boolean isARM() { + return isArch("arm.*"); + } + + public static boolean isPPC() { + return isArch("ppc.*"); + } + + public static boolean isX86() { + // On Linux it's 'i386', Windows 'x86' without '_64' suffix. + return isArch("(i386)|(x86(?!_64))"); + } + + public static boolean isX64() { + // On OSX it's 'x86_64' and on other (Linux, Windows and Solaris) platforms it's 'amd64' + return isArch("(amd64)|(x86_64)"); + } + + private static boolean isArch(String archnameRE) { + return Pattern.compile(archnameRE, Pattern.CASE_INSENSITIVE) + .matcher(osArch) + .matches(); + } + + public static String getOsArch() { + return osArch; + } + + /** + * Return a boolean for whether we expect to be able to attach + * the SA to our own processes on this system. + */ + public static boolean shouldSAAttach() + throws IOException { + + if (isAix()) { + return false; // SA not implemented. + } else if (isLinux()) { + return canPtraceAttachLinux(); + } else if (isOSX()) { + return canAttachOSX(); + } else { + // Other platforms expected to work: + return true; + } + } + + /** + * On Linux, first check the SELinux boolean "deny_ptrace" and return false + * as we expect to be denied if that is "1". + */ + public static boolean canPtraceAttachLinux() + throws IOException { + + // SELinux deny_ptrace: + try(RandomAccessFile file = new RandomAccessFile("/sys/fs/selinux/booleans/deny_ptrace", "r")) { + if (file.readByte() != '0') { + return false; + } + } + catch(FileNotFoundException ex) { + // Ignored + } + + // YAMA enhanced security ptrace_scope: + // 0 - a process can PTRACE_ATTACH to any other process running under the same uid + // 1 - restricted ptrace: a process must be a children of the inferior or user is root + // 2 - only processes with CAP_SYS_PTRACE may use ptrace or user is root + // 3 - no attach: no processes may use ptrace with PTRACE_ATTACH + + try(RandomAccessFile file = new RandomAccessFile("/proc/sys/kernel/yama/ptrace_scope", "r")) { + byte yama_scope = file.readByte(); + if (yama_scope == '3') { + return false; + } + + if (!userName.equals("root") && yama_scope != '0') { + return false; + } + } + catch(FileNotFoundException ex) { + // Ignored + } + + // Otherwise expect to be permitted: + return true; + } + + /** + * On OSX, expect permission to attach only if we are root. + */ + public static boolean canAttachOSX() { + return userName.equals("root"); + } +} diff --git a/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/ProcessTools.java b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/ProcessTools.java new file mode 100644 index 0000000000000000000000000000000000000000..35cffc1c994d0eda488985d0f77f3f4811fedfac --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/ProcessTools.java @@ -0,0 +1,579 @@ +/* + * 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 + * 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 jdk.testlibrary; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.concurrent.CountDownLatch; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.function.Predicate; +import java.util.function.Consumer; +import java.util.stream.Collectors; + + +/** + * @deprecated This class is deprecated. Use the one from + * {@code /test/lib/share/classes/jdk/test/lib/process} + */ +@Deprecated +public final class ProcessTools { + private static final class LineForwarder extends StreamPumper.LinePump { + private final PrintStream ps; + private final String prefix; + LineForwarder(String prefix, PrintStream os) { + this.ps = os; + this.prefix = prefix; + } + @Override + protected void processLine(String line) { + ps.println("[" + prefix + "] " + line); + } + } + + private ProcessTools() { + } + + /** + *

Starts a process from its builder.

+ * The default redirects of STDOUT and STDERR are started + * @param name The process name + * @param processBuilder The process builder + * @return Returns the initialized process + * @throws IOException + */ + public static Process startProcess(String name, + ProcessBuilder processBuilder) + throws IOException { + return startProcess(name, processBuilder, (Consumer)null); + } + + /** + *

Starts a process from its builder.

+ * The default redirects of STDOUT and STDERR are started + *

It is possible to monitor the in-streams via the provided {@code consumer} + * @param name The process name + * @param consumer {@linkplain Consumer} instance to process the in-streams + * @param processBuilder The process builder + * @return Returns the initialized process + * @throws IOException + */ + @SuppressWarnings("overloads") + public static Process startProcess(String name, + ProcessBuilder processBuilder, + Consumer consumer) + throws IOException { + try { + return startProcess(name, processBuilder, consumer, null, -1, TimeUnit.NANOSECONDS); + } catch (InterruptedException | TimeoutException e) { + // will never happen + throw new RuntimeException(e); + } + } + + /** + *

Starts a process from its builder.

+ * The default redirects of STDOUT and STDERR are started + *

+ * It is possible to wait for the process to get to a warmed-up state + * via {@linkplain Predicate} condition on the STDOUT + *

+ * @param name The process name + * @param processBuilder The process builder + * @param linePredicate The {@linkplain Predicate} to use on the STDOUT + * Used to determine the moment the target app is + * properly warmed-up. + * It can be null - in that case the warmup is skipped. + * @param timeout The timeout for the warmup waiting; -1 = no wait; 0 = wait forever + * @param unit The timeout {@linkplain TimeUnit} + * @return Returns the initialized {@linkplain Process} + * @throws IOException + * @throws InterruptedException + * @throws TimeoutException + */ + public static Process startProcess(String name, + ProcessBuilder processBuilder, + final Predicate linePredicate, + long timeout, + TimeUnit unit) + throws IOException, InterruptedException, TimeoutException { + return startProcess(name, processBuilder, null, linePredicate, timeout, unit); + } + + /** + *

Starts a process from its builder.

+ * The default redirects of STDOUT and STDERR are started + *

+ * It is possible to wait for the process to get to a warmed-up state + * via {@linkplain Predicate} condition on the STDOUT and monitor the + * in-streams via the provided {@linkplain Consumer} + *

+ * @param name The process name + * @param processBuilder The process builder + * @param lineConsumer The {@linkplain Consumer} the lines will be forwarded to + * @param linePredicate The {@linkplain Predicate} to use on the STDOUT + * Used to determine the moment the target app is + * properly warmed-up. + * It can be null - in that case the warmup is skipped. + * @param timeout The timeout for the warmup waiting; -1 = no wait; 0 = wait forever + * @param unit The timeout {@linkplain TimeUnit} + * @return Returns the initialized {@linkplain Process} + * @throws IOException + * @throws InterruptedException + * @throws TimeoutException + */ + public static Process startProcess(String name, + ProcessBuilder processBuilder, + final Consumer lineConsumer, + final Predicate linePredicate, + long timeout, + TimeUnit unit) + throws IOException, InterruptedException, TimeoutException { + System.out.println("["+name+"]:" + processBuilder.command().stream().collect(Collectors.joining(" "))); + Process p = processBuilder.start(); + StreamPumper stdout = new StreamPumper(p.getInputStream()); + StreamPumper stderr = new StreamPumper(p.getErrorStream()); + + stdout.addPump(new LineForwarder(name, System.out)); + stderr.addPump(new LineForwarder(name, System.err)); + if (lineConsumer != null) { + StreamPumper.LinePump pump = new StreamPumper.LinePump() { + @Override + protected void processLine(String line) { + lineConsumer.accept(line); + } + }; + stdout.addPump(pump); + stderr.addPump(pump); + } + + + CountDownLatch latch = new CountDownLatch(1); + if (linePredicate != null) { + StreamPumper.LinePump pump = new StreamPumper.LinePump() { + @Override + protected void processLine(String line) { + if (latch.getCount() > 0 && linePredicate.test(line)) { + latch.countDown(); + } + } + }; + stdout.addPump(pump); + stderr.addPump(pump); + } else { + latch.countDown(); + } + final Future stdoutTask = stdout.process(); + final Future stderrTask = stderr.process(); + + try { + if (timeout > -1) { + if (timeout == 0) { + latch.await(); + } else { + if (!latch.await(Utils.adjustTimeout(timeout), unit)) { + throw new TimeoutException(); + } + } + } + } catch (TimeoutException | InterruptedException e) { + System.err.println("Failed to start a process (thread dump follows)"); + for(Map.Entry s : Thread.getAllStackTraces().entrySet()) { + printStack(s.getKey(), s.getValue()); + } + + if (p.isAlive()) { + p.destroyForcibly(); + } + + stdoutTask.cancel(true); + stderrTask.cancel(true); + throw e; + } + + return new ProcessImpl(p, stdoutTask, stderrTask); + } + + /** + *

Starts a process from its builder.

+ * The default redirects of STDOUT and STDERR are started + *

+ * It is possible to wait for the process to get to a warmed-up state + * via {@linkplain Predicate} condition on the STDOUT. The warm-up will + * wait indefinitely. + *

+ * @param name The process name + * @param processBuilder The process builder + * @param linePredicate The {@linkplain Predicate} to use on the STDOUT + * Used to determine the moment the target app is + * properly warmed-up. + * It can be null - in that case the warmup is skipped. + * @return Returns the initialized {@linkplain Process} + * @throws IOException + * @throws InterruptedException + * @throws TimeoutException + */ + @SuppressWarnings("overloads") + public static Process startProcess(String name, + ProcessBuilder processBuilder, + final Predicate linePredicate) + throws IOException, InterruptedException, TimeoutException { + return startProcess(name, processBuilder, linePredicate, 0, TimeUnit.SECONDS); + } + + /** + * Get the process id of the current running Java process + * + * @return Process id + */ + public static long getProcessId() { + return ProcessHandle.current().getPid(); + } + + /** + * Get platform specific VM arguments (e.g. -d64 on 64bit Solaris) + * + * @return String[] with platform specific arguments, empty if there are + * none + */ + public static String[] getPlatformSpecificVMArgs() { + String osName = System.getProperty("os.name"); + String dataModel = System.getProperty("sun.arch.data.model"); + + if (osName.equals("SunOS") && dataModel.equals("64")) { + return new String[] { "-d64" }; + } + + return new String[] {}; + } + + /** + * Create ProcessBuilder using the java launcher from the jdk to be tested, + * and with any platform specific arguments prepended. + * + * @param command Arguments to pass to the java command. + * @return The ProcessBuilder instance representing the java command. + */ + public static ProcessBuilder createJavaProcessBuilder(String... command) + throws Exception { + return createJavaProcessBuilder(false, command); + } + + /** + * Create ProcessBuilder using the java launcher from the jdk to be tested, + * and with any platform specific arguments prepended. + * + * @param addTestVmAndJavaOptions If true, adds test.vm.opts and test.java.opts + * to the java arguments. + * @param command Arguments to pass to the java command. + * @return The ProcessBuilder instance representing the java command. + */ + public static ProcessBuilder createJavaProcessBuilder(boolean addTestVmAndJavaOptions, String... command) throws Exception { + String javapath = JDKToolFinder.getJDKTool("java"); + + ArrayList args = new ArrayList<>(); + args.add(javapath); + Collections.addAll(args, getPlatformSpecificVMArgs()); + + if (addTestVmAndJavaOptions) { + // -cp is needed to make sure the same classpath is used whether the test is + // run in AgentVM mode or OtherVM mode. It was added to the hotspot version + // of this API as part of 8077608. However, for the jdk version it is only + // added when addTestVmAndJavaOptions is true in order to minimize + // disruption to existing JDK tests, which have yet to be tested with -cp + // being added. At some point -cp should always be added to be consistent + // with what the hotspot version does. + args.add("-cp"); + args.add(System.getProperty("java.class.path")); + Collections.addAll(args, Utils.getTestJavaOpts()); + } + + Collections.addAll(args, command); + + // Reporting + StringBuilder cmdLine = new StringBuilder(); + for (String cmd : args) + cmdLine.append(cmd).append(' '); + System.out.println("Command line: [" + cmdLine.toString() + "]"); + + return new ProcessBuilder(args.toArray(new String[args.size()])); + } + + private static void printStack(Thread t, StackTraceElement[] stack) { + System.out.println("\t" + t + + " stack: (length = " + stack.length + ")"); + if (t != null) { + for (StackTraceElement stack1 : stack) { + System.out.println("\t" + stack1); + } + System.out.println(); + } + } + + /** + * Executes a test java process, waits for it to finish and returns the process output. + * The default options from jtreg, test.vm.opts and test.java.opts, are added. + * The java from the test.jdk is used to execute the command. + * + * The command line will be like: + * {test.jdk}/bin/java {test.vm.opts} {test.java.opts} cmds + * + * The java process will have exited before this method returns. + * + * @param cmds User specifed arguments. + * @return The output from the process. + */ + public static OutputAnalyzer executeTestJava(String... options) throws Exception { + ProcessBuilder pb = createJavaProcessBuilder(Utils.addTestJavaOpts(options)); + return executeProcess(pb); + } + + /** + * @deprecated Use executeTestJava instead + */ + public static OutputAnalyzer executeTestJvm(String... options) throws Exception { + return executeTestJava(options); + } + + /** + * Executes a process, waits for it to finish and returns the process output. + * The process will have exited before this method returns. + * @param pb The ProcessBuilder to execute. + * @return The {@linkplain OutputAnalyzer} instance wrapping the process. + */ + public static OutputAnalyzer executeProcess(ProcessBuilder pb) throws Exception { + return executeProcess(pb, null); + } + + /** + * Executes a process, pipe some text into its STDIN, waits for it + * to finish and returns the process output. The process will have exited + * before this method returns. + * @param pb The ProcessBuilder to execute. + * @param input The text to pipe into STDIN. Can be null. + * @return The {@linkplain OutputAnalyzer} instance wrapping the process. + */ + public static OutputAnalyzer executeProcess(ProcessBuilder pb, String input) + throws Exception { + OutputAnalyzer output = null; + Process p = null; + boolean failed = false; + try { + p = pb.start(); + if (input != null) { + try (OutputStream os = p.getOutputStream(); + PrintStream ps = new PrintStream(os)) { + ps.print(input); + ps.flush(); + } + } + output = new OutputAnalyzer(p); + p.waitFor(); + + return output; + } catch (Throwable t) { + if (p != null) { + p.destroyForcibly().waitFor(); + } + + failed = true; + System.out.println("executeProcess() failed: " + t); + throw t; + } finally { + if (failed) { + System.err.println(getProcessLog(pb, output)); + } + } + } + + /** + * Executes a process, waits for it to finish and returns the process output. + * + * The process will have exited before this method returns. + * + * @param cmds The command line to execute. + * @return The output from the process. + */ + public static OutputAnalyzer executeProcess(String... cmds) throws Throwable { + return executeProcess(new ProcessBuilder(cmds)); + } + + /** + * Used to log command line, stdout, stderr and exit code from an executed process. + * @param pb The executed process. + * @param output The output from the process. + */ + public static String getProcessLog(ProcessBuilder pb, OutputAnalyzer output) { + String stderr = output == null ? "null" : output.getStderr(); + String stdout = output == null ? "null" : output.getStdout(); + String exitValue = output == null ? "null": Integer.toString(output.getExitValue()); + StringBuilder logMsg = new StringBuilder(); + final String nl = System.getProperty("line.separator"); + logMsg.append("--- ProcessLog ---" + nl); + logMsg.append("cmd: " + getCommandLine(pb) + nl); + logMsg.append("exitvalue: " + exitValue + nl); + logMsg.append("stderr: " + stderr + nl); + logMsg.append("stdout: " + stdout + nl); + + return logMsg.toString(); + } + + /** + * @return The full command line for the ProcessBuilder. + */ + public static String getCommandLine(ProcessBuilder pb) { + if (pb == null) { + return "null"; + } + StringBuilder cmd = new StringBuilder(); + for (String s : pb.command()) { + cmd.append(s).append(" "); + } + return cmd.toString().trim(); + } + + /** + * Executes a process, waits for it to finish, prints the process output + * to stdout, and returns the process output. + * + * The process will have exited before this method returns. + * + * @param cmds The command line to execute. + * @return The {@linkplain OutputAnalyzer} instance wrapping the process. + */ + public static OutputAnalyzer executeCommand(String... cmds) + throws Throwable { + String cmdLine = Arrays.stream(cmds).collect(Collectors.joining(" ")); + System.out.println("Command line: [" + cmdLine + "]"); + OutputAnalyzer analyzer = ProcessTools.executeProcess(cmds); + System.out.println(analyzer.getOutput()); + return analyzer; + } + + /** + * Executes a process, waits for it to finish, prints the process output + * to stdout and returns the process output. + * + * The process will have exited before this method returns. + * + * @param pb The ProcessBuilder to execute. + * @return The {@linkplain OutputAnalyzer} instance wrapping the process. + */ + public static OutputAnalyzer executeCommand(ProcessBuilder pb) + throws Throwable { + String cmdLine = pb.command().stream().collect(Collectors.joining(" ")); + System.out.println("Command line: [" + cmdLine + "]"); + OutputAnalyzer analyzer = ProcessTools.executeProcess(pb); + System.out.println(analyzer.getOutput()); + return analyzer; + } + + private static class ProcessImpl extends Process { + + private final Process p; + private final Future stdoutTask; + private final Future stderrTask; + + public ProcessImpl(Process p, Future stdoutTask, Future stderrTask) { + this.p = p; + this.stdoutTask = stdoutTask; + this.stderrTask = stderrTask; + } + + @Override + public OutputStream getOutputStream() { + return p.getOutputStream(); + } + + @Override + public InputStream getInputStream() { + return p.getInputStream(); + } + + @Override + public InputStream getErrorStream() { + return p.getErrorStream(); + } + + @Override + public int waitFor() throws InterruptedException { + int rslt = p.waitFor(); + waitForStreams(); + return rslt; + } + + @Override + public int exitValue() { + return p.exitValue(); + } + + @Override + public void destroy() { + p.destroy(); + } + + @Override + public long getPid() { + return p.getPid(); + } + + @Override + public boolean isAlive() { + return p.isAlive(); + } + + @Override + public Process destroyForcibly() { + return p.destroyForcibly(); + } + + @Override + public boolean waitFor(long timeout, TimeUnit unit) throws InterruptedException { + boolean rslt = p.waitFor(timeout, unit); + if (rslt) { + waitForStreams(); + } + return rslt; + } + + private void waitForStreams() throws InterruptedException { + try { + stdoutTask.get(); + } catch (ExecutionException e) { + } + try { + stderrTask.get(); + } catch (ExecutionException e) { + } + } + } +} diff --git a/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/README.txt b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/README.txt new file mode 100644 index 0000000000000000000000000000000000000000..c4fd572cd04aec2a9a3a8b07d2b695352f235572 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/README.txt @@ -0,0 +1 @@ +These files are copies of the corresponding files in test/lib/testlibrary/ from jdk repo. diff --git a/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/StreamPumper.java b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/StreamPumper.java new file mode 100644 index 0000000000000000000000000000000000000000..2f3c205db3c20a2ce0bc58fbb6ed82f00d8f4bff --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/StreamPumper.java @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.testlibrary; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; +import java.io.InputStream; +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.Future; +import java.util.concurrent.FutureTask; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * @deprecated This class is deprecated. Use the one from + * {@code /test/lib/share/classes/jdk/test/lib/process} + */ +@Deprecated +public final class StreamPumper implements Runnable { + + private static final int BUF_SIZE = 256; + + /** + * Pump will be called by the StreamPumper to process the incoming data + */ + abstract public static class Pump { + abstract void register(StreamPumper d); + } + + /** + * OutputStream -> Pump adapter + */ + final public static class StreamPump extends Pump { + private final OutputStream out; + public StreamPump(OutputStream out) { + this.out = out; + } + + @Override + void register(StreamPumper sp) { + sp.addOutputStream(out); + } + } + + /** + * Used to process the incoming data line-by-line + */ + abstract public static class LinePump extends Pump { + @Override + final void register(StreamPumper sp) { + sp.addLineProcessor(this); + } + + abstract protected void processLine(String line); + } + + private final InputStream in; + private final Set outStreams = new HashSet<>(); + private final Set linePumps = new HashSet<>(); + + private final AtomicBoolean processing = new AtomicBoolean(false); + private final FutureTask processingTask = new FutureTask<>(this, null); + + public StreamPumper(InputStream in) { + this.in = in; + } + + /** + * Create a StreamPumper that reads from in and writes to out. + * + * @param in + * The stream to read from. + * @param out + * The stream to write to. + */ + public StreamPumper(InputStream in, OutputStream out) { + this(in); + this.addOutputStream(out); + } + + /** + * Implements Thread.run(). Continuously read from {@code in} and write to + * {@code out} until {@code in} has reached end of stream. Abort on + * interruption. Abort on IOExceptions. + */ + @Override + public void run() { + try (BufferedInputStream is = new BufferedInputStream(in)) { + ByteArrayOutputStream lineBos = new ByteArrayOutputStream(); + byte[] buf = new byte[BUF_SIZE]; + int len = 0; + int linelen = 0; + + while ((len = is.read(buf)) > 0 && !Thread.interrupted()) { + for(OutputStream out : outStreams) { + out.write(buf, 0, len); + } + if (!linePumps.isEmpty()) { + int i = 0; + int lastcrlf = -1; + while (i < len) { + if (buf[i] == '\n' || buf[i] == '\r') { + int bufLinelen = i - lastcrlf - 1; + if (bufLinelen > 0) { + lineBos.write(buf, lastcrlf + 1, bufLinelen); + } + linelen += bufLinelen; + + if (linelen > 0) { + lineBos.flush(); + final String line = lineBos.toString(); + linePumps.stream().forEach((lp) -> { + lp.processLine(line); + }); + lineBos.reset(); + linelen = 0; + } + lastcrlf = i; + } + + i++; + } + if (lastcrlf == -1) { + lineBos.write(buf, 0, len); + linelen += len; + } else if (lastcrlf < len - 1) { + lineBos.write(buf, lastcrlf + 1, len - lastcrlf - 1); + linelen += len - lastcrlf - 1; + } + } + } + + } catch (IOException e) { + e.printStackTrace(); + } finally { + for(OutputStream out : outStreams) { + try { + out.flush(); + } catch (IOException e) {} + } + try { + in.close(); + } catch (IOException e) {} + } + } + + final void addOutputStream(OutputStream out) { + outStreams.add(out); + } + + final void addLineProcessor(LinePump lp) { + linePumps.add(lp); + } + + final public StreamPumper addPump(Pump ... pump) { + if (processing.get()) { + throw new IllegalStateException("Can not modify pumper while " + + "processing is in progress"); + } + for(Pump p : pump) { + p.register(this); + } + return this; + } + + final public Future process() { + if (!processing.compareAndSet(false, true)) { + throw new IllegalStateException("Can not re-run the processing"); + } + Thread t = new Thread(new Runnable() { + @Override + public void run() { + processingTask.run(); + } + }); + t.setDaemon(true); + t.start(); + + return processingTask; + } +} diff --git a/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/Utils.java b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/Utils.java new file mode 100644 index 0000000000000000000000000000000000000000..c76339107c8cf7b9efffe8468d374ef65430e0e5 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/libs/jdk/testlibrary/Utils.java @@ -0,0 +1,365 @@ +/* + * 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 + * 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 jdk.testlibrary; + +import static jdk.testlibrary.Asserts.assertTrue; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.List; +import java.util.Arrays; +import java.util.Collections; +import java.util.regex.Pattern; +import java.util.regex.Matcher; +import java.util.concurrent.TimeUnit; +import java.util.function.BooleanSupplier; +import java.util.function.Function; + +/** + * Common library for various test helper functions. + * + * @deprecated This class is deprecated. Use the one from + * {@code /test/lib/share/classes/jdk/test/lib} + */ +@Deprecated +public final class Utils { + + /** + * Returns the sequence used by operating system to separate lines. + */ + public static final String NEW_LINE = System.getProperty("line.separator"); + + /** + * Returns the value of 'test.vm.opts'system property. + */ + public static final String VM_OPTIONS = System.getProperty("test.vm.opts", "").trim(); + + /** + * Returns the value of 'test.java.opts'system property. + */ + public static final String JAVA_OPTIONS = System.getProperty("test.java.opts", "").trim(); + + /** + * Returns the value of 'test.timeout.factor' system property + * converted to {@code double}. + */ + public static final double TIMEOUT_FACTOR; + static { + String toFactor = System.getProperty("test.timeout.factor", "1.0"); + TIMEOUT_FACTOR = Double.parseDouble(toFactor); + } + + /** + * Returns the value of JTREG default test timeout in milliseconds + * converted to {@code long}. + */ + public static final long DEFAULT_TEST_TIMEOUT = TimeUnit.SECONDS.toMillis(120); + + private Utils() { + // Private constructor to prevent class instantiation + } + + /** + * Returns the list of VM options. + * + * @return List of VM options + */ + public static List getVmOptions() { + return Arrays.asList(safeSplitString(VM_OPTIONS)); + } + + /** + * Returns the list of VM options with -J prefix. + * + * @return The list of VM options with -J prefix + */ + public static List getForwardVmOptions() { + String[] opts = safeSplitString(VM_OPTIONS); + for (int i = 0; i < opts.length; i++) { + opts[i] = "-J" + opts[i]; + } + return Arrays.asList(opts); + } + + /** + * Returns the default JTReg arguments for a jvm running a test. + * This is the combination of JTReg arguments test.vm.opts and test.java.opts. + * @return An array of options, or an empty array if no opptions. + */ + public static String[] getTestJavaOpts() { + List opts = new ArrayList(); + Collections.addAll(opts, safeSplitString(VM_OPTIONS)); + Collections.addAll(opts, safeSplitString(JAVA_OPTIONS)); + return opts.toArray(new String[0]); + } + + /** + * Combines given arguments with default JTReg arguments for a jvm running a test. + * This is the combination of JTReg arguments test.vm.opts and test.java.opts + * @return The combination of JTReg test java options and user args. + */ + public static String[] addTestJavaOpts(String... userArgs) { + List opts = new ArrayList(); + Collections.addAll(opts, getTestJavaOpts()); + Collections.addAll(opts, userArgs); + return opts.toArray(new String[0]); + } + + /** + * Removes any options specifying which GC to use, for example "-XX:+UseG1GC". + * Removes any options matching: -XX:(+/-)Use*GC + * Used when a test need to set its own GC version. Then any + * GC specified by the framework must first be removed. + * @return A copy of given opts with all GC options removed. + */ + private static final Pattern useGcPattern = Pattern.compile( + "(?:\\-XX\\:[\\+\\-]Use.+GC)" + + "|(?:\\-Xconcgc)"); + public static List removeGcOpts(List opts) { + List optsWithoutGC = new ArrayList(); + for (String opt : opts) { + if (useGcPattern.matcher(opt).matches()) { + System.out.println("removeGcOpts: removed " + opt); + } else { + optsWithoutGC.add(opt); + } + } + return optsWithoutGC; + } + + /** + * Splits a string by white space. + * Works like String.split(), but returns an empty array + * if the string is null or empty. + */ + private static String[] safeSplitString(String s) { + if (s == null || s.trim().isEmpty()) { + return new String[] {}; + } + return s.trim().split("\\s+"); + } + + /** + * @return The full command line for the ProcessBuilder. + */ + public static String getCommandLine(ProcessBuilder pb) { + StringBuilder cmd = new StringBuilder(); + for (String s : pb.command()) { + cmd.append(s).append(" "); + } + return cmd.toString(); + } + + /** + * Returns the free port on the local host. + * The function will spin until a valid port number is found. + * + * @return The port number + * @throws InterruptedException if any thread has interrupted the current thread + * @throws IOException if an I/O error occurs when opening the socket + */ + public static int getFreePort() throws InterruptedException, IOException { + int port = -1; + + while (port <= 0) { + Thread.sleep(100); + + ServerSocket serverSocket = null; + try { + serverSocket = new ServerSocket(0); + port = serverSocket.getLocalPort(); + } finally { + serverSocket.close(); + } + } + + return port; + } + + /** + * Returns the name of the local host. + * + * @return The host name + * @throws UnknownHostException if IP address of a host could not be determined + */ + public static String getHostname() throws UnknownHostException { + InetAddress inetAddress = InetAddress.getLocalHost(); + String hostName = inetAddress.getHostName(); + + assertTrue((hostName != null && !hostName.isEmpty()), + "Cannot get hostname"); + + return hostName; + } + + /** + * Uses "jcmd -l" to search for a jvm pid. This function will wait + * forever (until jtreg timeout) for the pid to be found. + * @param key Regular expression to search for + * @return The found pid. + */ + public static int waitForJvmPid(String key) throws Throwable { + final long iterationSleepMillis = 250; + System.out.println("waitForJvmPid: Waiting for key '" + key + "'"); + System.out.flush(); + while (true) { + int pid = tryFindJvmPid(key); + if (pid >= 0) { + return pid; + } + Thread.sleep(iterationSleepMillis); + } + } + + /** + * Searches for a jvm pid in the output from "jcmd -l". + * + * Example output from jcmd is: + * 12498 sun.tools.jcmd.JCmd -l + * 12254 /tmp/jdk8/tl/jdk/JTwork/classes/com/sun/tools/attach/Application.jar + * + * @param key A regular expression to search for. + * @return The found pid, or -1 if Enot found. + * @throws Exception If multiple matching jvms are found. + */ + public static int tryFindJvmPid(String key) throws Throwable { + OutputAnalyzer output = null; + try { + JDKToolLauncher jcmdLauncher = JDKToolLauncher.create("jcmd"); + jcmdLauncher.addToolArg("-l"); + output = ProcessTools.executeProcess(jcmdLauncher.getCommand()); + output.shouldHaveExitValue(0); + + // Search for a line starting with numbers (pid), follwed by the key. + Pattern pattern = Pattern.compile("([0-9]+)\\s.*(" + key + ").*\\r?\\n"); + Matcher matcher = pattern.matcher(output.getStdout()); + + int pid = -1; + if (matcher.find()) { + pid = Integer.parseInt(matcher.group(1)); + System.out.println("findJvmPid.pid: " + pid); + if (matcher.find()) { + throw new Exception("Found multiple JVM pids for key: " + key); + } + } + return pid; + } catch (Throwable t) { + System.out.println(String.format("Utils.findJvmPid(%s) failed: %s", key, t)); + throw t; + } + } + + /** + * Adjusts the provided timeout value for the TIMEOUT_FACTOR + * @param tOut the timeout value to be adjusted + * @return The timeout value adjusted for the value of "test.timeout.factor" + * system property + */ + public static long adjustTimeout(long tOut) { + return Math.round(tOut * Utils.TIMEOUT_FACTOR); + } + + /** + * Wait for condition to be true + * + * @param condition, a condition to wait for + */ + public static final void waitForCondition(BooleanSupplier condition) { + waitForCondition(condition, -1L, 100L); + } + + /** + * Wait until timeout for condition to be true + * + * @param condition, a condition to wait for + * @param timeout a time in milliseconds to wait for condition to be true + * specifying -1 will wait forever + * @return condition value, to determine if wait was successfull + */ + public static final boolean waitForCondition(BooleanSupplier condition, + long timeout) { + return waitForCondition(condition, timeout, 100L); + } + + /** + * Wait until timeout for condition to be true for specified time + * + * @param condition, a condition to wait for + * @param timeout a time in milliseconds to wait for condition to be true, + * specifying -1 will wait forever + * @param sleepTime a time to sleep value in milliseconds + * @return condition value, to determine if wait was successfull + */ + public static final boolean waitForCondition(BooleanSupplier condition, + long timeout, long sleepTime) { + long startTime = System.currentTimeMillis(); + while (!(condition.getAsBoolean() || (timeout != -1L + && ((System.currentTimeMillis() - startTime) > timeout)))) { + try { + Thread.sleep(sleepTime); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new Error(e); + } + } + return condition.getAsBoolean(); + } + + /** + * Interface same as java.lang.Runnable but with + * method {@code run()} able to throw any Throwable. + */ + public static interface ThrowingRunnable { + void run() throws Throwable; + } + + /** + * Filters out an exception that may be thrown by the given + * test according to the given filter. + * + * @param test - method that is invoked and checked for exception. + * @param filter - function that checks if the thrown exception matches + * criteria given in the filter's implementation. + * @return - exception that matches the filter if it has been thrown or + * {@code null} otherwise. + * @throws Throwable - if test has thrown an exception that does not + * match the filter. + */ + public static Throwable filterException(ThrowingRunnable test, + Function filter) throws Throwable { + try { + test.run(); + } catch (Throwable t) { + if (filter.apply(t)) { + return t; + } else { + throw t; + } + } + return null; + } +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/BasicModularXMLParserTest.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/BasicModularXMLParserTest.java new file mode 100644 index 0000000000000000000000000000000000000000..c3403f9d1d0cb06f63cd0ea36b6b55489218b228 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/BasicModularXMLParserTest.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 static org.testng.Assert.assertTrue; + +import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; + +import static jdk.testlibrary.ProcessTools.executeTestJava; +import jdk.testlibrary.CompilerUtils; + +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +/* + * @test + * @library /javax/xml/jaxp/libs + * @build jdk.testlibrary.* + * @run testng BasicModularXMLParserTest + * @bug 8078820 + * @summary Tests JAXP lib can instantiate the following interfaces + * with customized provider module on boot layer + * + * javax.xml.datatype.DatatypeFactory + * javax.xml.parsers.DocumentBuilderFactory + * javax.xml.parsers.SAXParserFactory + * javax.xml.stream.XMLEventFactory + * javax.xml.stream.XMLInputFactory + * javax.xml.stream.XMLOutputFactory + * javax.xml.transform.TransformerFactory + * javax.xml.validation.SchemaFactory + * javax.xml.xpath.XPathFactory + */ + +@Test +public class BasicModularXMLParserTest { + + private static final String TEST_SRC = System.getProperty("test.src"); + + private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); + private static final Path MOD_DIR1 = Paths.get("mod1"); + private static final Path MOD_DIR2 = Paths.get("mod2"); + private static final Path CLASSES_DIR = Paths.get("classes"); + + /* + * Compiles all modules used by the test + */ + @BeforeTest + public void compileAll() throws Exception { + assertTrue(CompilerUtils.compile(SRC_DIR.resolve("xmlprovider1"), MOD_DIR1.resolve("xmlprovider1"))); + assertTrue(CompilerUtils.compile(SRC_DIR.resolve("xmlprovider2"), MOD_DIR2.resolve("xmlprovider2"))); + assertTrue(CompilerUtils.compile(SRC_DIR.resolve("unnamed"), CLASSES_DIR)); + } + + /* + * test the default JAXP implementation + */ + public void testDefault() throws Exception { + int exitValue + = executeTestJava("-cp", CLASSES_DIR.toString(), + "Main") + .outputTo(System.out) + .errorTo(System.out) + .getExitValue(); + + assertTrue(exitValue == 0); + } + + /* + * test loading one provider module + */ + public void testWithOneProvider() throws Exception { + int exitValue + = executeTestJava("-mp", MOD_DIR1.toString(), + "-cp", CLASSES_DIR.toString(), + "Main", "xmlprovider1") + .outputTo(System.out) + .errorTo(System.out) + .getExitValue(); + + assertTrue(exitValue == 0); + } + + /* + * test loading both provider modules + */ + public void testWithTwoProvider() throws Exception { + int exitValue + = executeTestJava("-mp", MOD_DIR1.toString() + File.pathSeparator + MOD_DIR2.toString(), + "-cp", CLASSES_DIR.toString(), + "Main", "xmlprovider1", "xmlprovider2") + .outputTo(System.out) + .errorTo(System.out) + .getExitValue(); + + assertTrue(exitValue == 0); + } + +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/LayerModularXMLParserTest.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/LayerModularXMLParserTest.java new file mode 100644 index 0000000000000000000000000000000000000000..45f240012788615314488eb8a8c63cbfb525925d --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/LayerModularXMLParserTest.java @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 static java.lang.module.ModuleFinder.empty; +import static org.testng.Assert.assertSame; +import static org.testng.Assert.assertTrue; + +import java.lang.ClassLoader; +import java.lang.String; +import java.lang.System; +import java.lang.module.Configuration; +import java.lang.module.ModuleFinder; +import java.lang.reflect.Layer; +import java.lang.reflect.Method; +import java.lang.reflect.Module; +import java.nio.file.Paths; +import java.nio.file.Path; +import java.util.Collections; +import java.util.Iterator; +import java.util.ServiceLoader; +import java.util.Set; + +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import jdk.testlibrary.CompilerUtils; + +/* + * @test + * @library /javax/xml/jaxp/libs + * @build jdk.testlibrary.* + * @run testng LayerModularXMLParserTest + * @bug 8078820 + * @summary Tests JAXP lib works with layer and TCCL + */ + +@Test +public class LayerModularXMLParserTest { + + private static final String TEST_SRC = System.getProperty("test.src"); + + private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); + private static final Path MOD_DIR1 = Paths.get("mod1"); + private static final Path MOD_DIR2 = Paths.get("mod2"); + + /* + * services provided by provider1 + */ + private static final String[] services1 = { "javax.xml.parsers.DocumentBuilderFactory", + "javax.xml.parsers.SAXParserFactory", "javax.xml.stream.XMLInputFactory", + "javax.xml.stream.XMLOutputFactory", "javax.xml.transform.TransformerFactory", + "javax.xml.validation.SchemaFactory", "javax.xml.xpath.XPathFactory" }; + + /* + * services provided by provider2 + */ + private static final String[] services2 = { "javax.xml.datatype.DatatypeFactory", + "javax.xml.stream.XMLEventFactory" }; + + /* + * Compiles all modules used by the test + */ + @BeforeTest + public void compileAll() throws Exception { + assertTrue(CompilerUtils.compile(SRC_DIR.resolve("xmlprovider1"), MOD_DIR1.resolve("xmlprovider1"))); + assertTrue(CompilerUtils.compile(SRC_DIR.resolve("xmlprovider2"), MOD_DIR2.resolve("xmlprovider2"))); + assertTrue(CompilerUtils.compile(SRC_DIR.resolve("test"), MOD_DIR1.resolve("test"))); + assertTrue(CompilerUtils.compile(SRC_DIR.resolve("test"), MOD_DIR2.resolve("test"))); + } + + /* + * layer 1 is created on top of boot layer, layer1 includes module provider1. + * + * Instantiate each XML service, verify the services provided by provider1 + * are loaded from layer 1, the other services are loaded from boot layer + */ + public void testOneLayer() throws Exception { + ModuleFinder finder1 = ModuleFinder.of(MOD_DIR1); + Configuration cf1 = Layer.boot().configuration() + .resolveRequiresAndUses(finder1, empty(), Set.of("test")); + ClassLoader scl = ClassLoader.getSystemClassLoader(); + Layer layer1 = Layer.boot().defineModulesWithManyLoaders(cf1, scl); + ClassLoader cl1 = layer1.findLoader("test"); + + Method m = cl1.loadClass("test.XMLFactoryHelper").getMethod("instantiateXMLService", String.class); + for (String service : services1) { + Object o = m.invoke(null, service); + Layer providerLayer = o.getClass().getModule().getLayer(); + assertSame(providerLayer, layer1); + } + + for (String service : services2) { + Object o = m.invoke(null, service); + Layer providerLayer = o.getClass().getModule().getLayer(); + assertSame(providerLayer, Layer.boot()); + } + + } + + /* + * layer 1 is created on top of boot layer, layer 1 includes module provider1. + * layer 2 is created on top of layer 1, layer 2 includes module provider2. + * + * Instantiate each XML service, verify the services provided by provider1 + * are loaded from layer 1, the services provided by provider2 are loaded from layer 2 + */ + public void testTwoLayer() throws Exception { + ModuleFinder finder1 = ModuleFinder.of(MOD_DIR1); + Configuration cf1 = Layer.boot().configuration() + .resolveRequiresAndUses(finder1, empty(), Set.of("test")); + ClassLoader scl = ClassLoader.getSystemClassLoader(); + Layer layer1 = Layer.boot().defineModulesWithManyLoaders(cf1, scl); + + ModuleFinder finder2 = ModuleFinder.of(MOD_DIR2); + Configuration cf2 = cf1.resolveRequiresAndUses(finder2, empty(), Set.of("test")); + Layer layer2 = layer1.defineModulesWithOneLoader(cf2, layer1.findLoader("test")); + ClassLoader cl2 = layer2.findLoader("test"); + + Method m = cl2.loadClass("test.XMLFactoryHelper").getMethod("instantiateXMLService", String.class); + for (String service : services1) { + Object o = m.invoke(null, service); + Layer providerLayer = o.getClass().getModule().getLayer(); + assertSame(providerLayer, layer1); + } + + for (String service : services2) { + Object o = m.invoke(null, service); + Layer providerLayer = o.getClass().getModule().getLayer(); + assertSame(providerLayer, layer2); + } + + } + + /* + * layer 1 is created on top of boot layer, layer 1 includes module provider1 and provider2. + * layer 2 is created on top of layer 1, layer 2 includes module provider2. + * + * Instantiate each XML service, verify the services provided by provider1 + * are loaded from layer 1, the services provided by provider2 are loaded from layer 2 + */ + public void testTwoLayerWithDuplicate() throws Exception { + ModuleFinder finder1 = ModuleFinder.of(MOD_DIR1, MOD_DIR2); + Configuration cf1 = Layer.boot().configuration() + .resolveRequiresAndUses(finder1, empty(), Set.of("test")); + ClassLoader scl = ClassLoader.getSystemClassLoader(); + Layer layer1 = Layer.boot().defineModulesWithManyLoaders(cf1, scl); + + ModuleFinder finder2 = ModuleFinder.of(MOD_DIR2); + Configuration cf2 = cf1.resolveRequiresAndUses(finder2, empty(), Set.of("test")); + Layer layer2 = layer1.defineModulesWithOneLoader(cf2, layer1.findLoader("test")); + ClassLoader cl2 = layer2.findLoader("test"); + + Method m = cl2.loadClass("test.XMLFactoryHelper").getMethod("instantiateXMLService", String.class); + for (String service : services1) { + Object o = m.invoke(null, service); + Layer providerLayer = o.getClass().getModule().getLayer(); + assertSame(providerLayer, layer1); + } + + for (String service : services2) { + Object o = m.invoke(null, service); + Layer providerLayer = o.getClass().getModule().getLayer(); + assertSame(providerLayer, layer2); + } + + } +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/test/module-info.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/test/module-info.java new file mode 100644 index 0000000000000000000000000000000000000000..9a1caa4e1f93a625af0b06cb11fe73e501b77f12 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/test/module-info.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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. + */ + +module test { + requires java.xml; + exports test; +} \ No newline at end of file diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/test/test/XMLFactoryHelper.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/test/test/XMLFactoryHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..6dfaec5cedf52f3e835a970987408bafc34e2f41 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/test/test/XMLFactoryHelper.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 test; + +import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI; + +import java.lang.Class; +import java.lang.String; +import java.lang.System; +import java.util.Iterator; +import java.util.ServiceLoader; + +public class XMLFactoryHelper { + /* + * instantiate a xml factory by reflection e.g. + * DocumentBuilderFactory.newInstance() + */ + public static Object instantiateXMLService(String serviceName) throws Exception { + ClassLoader backup = Thread.currentThread().getContextClassLoader(); + try { + // set thread context class loader to module class loader + Thread.currentThread().setContextClassLoader(XMLFactoryHelper.class.getClassLoader()); + if (serviceName.equals("javax.xml.validation.SchemaFactory")) + return Class.forName(serviceName).getMethod("newInstance", String.class) + .invoke(null, W3C_XML_SCHEMA_NS_URI); + else + return Class.forName(serviceName).getMethod("newInstance").invoke(null); + } finally { + Thread.currentThread().setContextClassLoader(backup); + } + + } + +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/unnamed/Main.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/unnamed/Main.java new file mode 100644 index 0000000000000000000000000000000000000000..cb0a37e916b55ce17ded96ee0e2d51afeae20757 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/unnamed/Main.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI; + +import java.lang.reflect.Layer; +import java.lang.reflect.Module; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Stream; + +public class Main { + /* + * @param args, the names of provider modules, which have been loaded + */ + public static void main(String[] args) throws Exception { + Module xml = Layer.boot().findModule("java.xml").get(); + + Set allServices = new HashSet<>(Arrays.asList(expectedAllServices)); + if (!allServices.equals(xml.getDescriptor().uses())) + throw new AssertionError("Expect xml module uses: " + allServices + " But actually uses: " + + xml.getDescriptor().uses()); + + long violationCount = Stream.of(args) + .map(xmlProviderName -> Layer.boot().findModule(xmlProviderName).get()) + .mapToLong( + // services provided by the implementation in provider module + provider -> provider.getDescriptor().provides().keySet().stream() + .filter(serviceName -> { + allServices.remove(serviceName); // remove service provided by + // customized module from allServices + return !belongToModule(serviceName, instantiateXMLService(serviceName), provider); + }).count()) + .sum(); + + // the remaining services should be provided by the default implementation + violationCount += allServices.stream() + .filter(serviceName -> !belongToModule(serviceName, instantiateXMLService(serviceName), xml)) + .count(); + + if (violationCount > 0) + throw new AssertionError(violationCount + " services are not provided by expected module"); + } + + /* + * instantiate a xml factory by reflection e.g. + * DocumentBuilderFactory.newInstance() + */ + private static Object instantiateXMLService(String serviceName) { + try { + if (serviceName.equals("javax.xml.validation.SchemaFactory")) + return Class.forName(serviceName).getMethod("newInstance", String.class) + .invoke(null, W3C_XML_SCHEMA_NS_URI); + else + return Class.forName(serviceName).getMethod("newInstance").invoke(null); + } catch (Exception e) { + e.printStackTrace(System.err); + throw new RuntimeException(e); + } + } + + /* + * verify which module provides the xml factory + */ + private static boolean belongToModule(String factoryName, Object factory, Module expected) { + Module actual = factory.getClass().getModule(); + if (!actual.equals(expected)) { + System.err.println("Expect " + factoryName + " is provided by " + expected + + ", but actual implementation " + factory.getClass() + " is provided by " + actual); + return false; + } else { + System.out.println(factory.getClass() + " is provided by " + expected); + return true; + } + } + + /* + * This list equals the declarations in java.xml module-info.java + */ + private static final String[] expectedAllServices = { "javax.xml.datatype.DatatypeFactory", + "javax.xml.parsers.DocumentBuilderFactory", "javax.xml.parsers.SAXParserFactory", + "javax.xml.stream.XMLEventFactory", "javax.xml.stream.XMLInputFactory", + "javax.xml.stream.XMLOutputFactory", "javax.xml.transform.TransformerFactory", + "javax.xml.validation.SchemaFactory", "javax.xml.xpath.XPathFactory" }; + +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/module-info.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/module-info.java new file mode 100644 index 0000000000000000000000000000000000000000..5a5b1b01447251c3674fb756764978af416ca049 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/module-info.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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. + */ + +module xmlprovider1 { + requires java.xml; + + provides javax.xml.parsers.DocumentBuilderFactory with xp1.DocumentBuilderFactoryImpl; + provides javax.xml.parsers.SAXParserFactory with xp1.SAXParserFactoryImpl; + provides javax.xml.stream.XMLInputFactory with xp1.XMLInputFactoryImpl; + provides javax.xml.stream.XMLOutputFactory with xp1.XMLOutputFactoryImpl; + provides javax.xml.transform.TransformerFactory with xp1.TransformerFactoryImpl; + provides javax.xml.validation.SchemaFactory with xp1.SchemaFactoryImpl; + provides javax.xml.xpath.XPathFactory with xp1.XPathFactoryImpl; +} \ No newline at end of file diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/DocumentBuilderFactoryImpl.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/DocumentBuilderFactoryImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..7e302b9630cf6d0c8e0ce42428fd286eb2e0990c --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/DocumentBuilderFactoryImpl.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 xp1; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +public class DocumentBuilderFactoryImpl extends DocumentBuilderFactory { + + @Override + public DocumentBuilder newDocumentBuilder() throws ParserConfigurationException { + return null; + } + + @Override + public void setAttribute(String name, Object value) throws IllegalArgumentException { + + } + + @Override + public Object getAttribute(String name) throws IllegalArgumentException { + return null; + } + + @Override + public void setFeature(String name, boolean value) throws ParserConfigurationException { + + } + + @Override + public boolean getFeature(String name) throws ParserConfigurationException { + return false; + } + +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/SAXParserFactoryImpl.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/SAXParserFactoryImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..5d4ce0602f39dd4f8cf1912b2bd34fc8597b8baf --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/SAXParserFactoryImpl.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 xp1; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.SAXException; +import org.xml.sax.SAXNotRecognizedException; +import org.xml.sax.SAXNotSupportedException; + +public class SAXParserFactoryImpl extends SAXParserFactory { + + @Override + public SAXParser newSAXParser() throws ParserConfigurationException, SAXException { + return null; + } + + @Override + public void setFeature(String name, boolean value) throws ParserConfigurationException, + SAXNotRecognizedException, SAXNotSupportedException { + + } + + @Override + public boolean getFeature(String name) throws ParserConfigurationException, SAXNotRecognizedException, + SAXNotSupportedException { + return false; + } + +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/SchemaFactoryImpl.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/SchemaFactoryImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..ca0cb3be8c74073c3b28348c767166dab5ab6f65 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/SchemaFactoryImpl.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 xp1; + +import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI; + +import javax.xml.transform.Source; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; + +import org.w3c.dom.ls.LSResourceResolver; +import org.xml.sax.ErrorHandler; +import org.xml.sax.SAXException; + +public class SchemaFactoryImpl extends SchemaFactory { + + @Override + public boolean isSchemaLanguageSupported(String schemaLanguage) { + // must be true, otherwise JAXP library will deny this impl + if (schemaLanguage.equals(W3C_XML_SCHEMA_NS_URI)) + return true; + else + return false; + } + + @Override + public void setErrorHandler(ErrorHandler errorHandler) { + + } + + @Override + public ErrorHandler getErrorHandler() { + return null; + } + + @Override + public void setResourceResolver(LSResourceResolver resourceResolver) { + + } + + @Override + public LSResourceResolver getResourceResolver() { + return null; + } + + @Override + public Schema newSchema(Source[] schemas) throws SAXException { + return null; + } + + @Override + public Schema newSchema() throws SAXException { + return null; + } + +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/TransformerFactoryImpl.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/TransformerFactoryImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..0feabb6b21f9c79bc1bcd6b44c7c4c8f0561a852 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/TransformerFactoryImpl.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 xp1; + +import javax.xml.transform.ErrorListener; +import javax.xml.transform.Source; +import javax.xml.transform.Templates; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.URIResolver; + +public class TransformerFactoryImpl extends TransformerFactory { + + @Override + public Transformer newTransformer(Source source) throws TransformerConfigurationException { + return null; + } + + @Override + public Transformer newTransformer() throws TransformerConfigurationException { + return null; + } + + @Override + public Templates newTemplates(Source source) throws TransformerConfigurationException { + return null; + } + + @Override + public Source getAssociatedStylesheet(Source source, String media, String title, String charset) + throws TransformerConfigurationException { + return null; + } + + @Override + public void setURIResolver(URIResolver resolver) { + + } + + @Override + public URIResolver getURIResolver() { + return null; + } + + @Override + public void setFeature(String name, boolean value) throws TransformerConfigurationException { + + } + + @Override + public boolean getFeature(String name) { + return false; + } + + @Override + public void setAttribute(String name, Object value) { + + } + + @Override + public Object getAttribute(String name) { + return null; + } + + @Override + public void setErrorListener(ErrorListener listener) { + + } + + @Override + public ErrorListener getErrorListener() { + return null; + } + +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/XMLInputFactoryImpl.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/XMLInputFactoryImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..de4f6cbe07519b2ed9318ba4b6f5f5ff750dca48 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/XMLInputFactoryImpl.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 xp1; + +import java.io.InputStream; +import java.io.Reader; + +import javax.xml.stream.EventFilter; +import javax.xml.stream.StreamFilter; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLReporter; +import javax.xml.stream.XMLResolver; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.util.XMLEventAllocator; +import javax.xml.transform.Source; + +public class XMLInputFactoryImpl extends XMLInputFactory { + + @Override + public XMLStreamReader createXMLStreamReader(Reader reader) throws XMLStreamException { + return null; + } + + @Override + public XMLStreamReader createXMLStreamReader(Source source) throws XMLStreamException { + return null; + } + + @Override + public XMLStreamReader createXMLStreamReader(InputStream stream) throws XMLStreamException { + return null; + } + + @Override + public XMLStreamReader createXMLStreamReader(InputStream stream, String encoding) + throws XMLStreamException { + return null; + } + + @Override + public XMLStreamReader createXMLStreamReader(String systemId, InputStream stream) + throws XMLStreamException { + return null; + } + + @Override + public XMLStreamReader createXMLStreamReader(String systemId, Reader reader) throws XMLStreamException { + return null; + } + + @Override + public XMLEventReader createXMLEventReader(Reader reader) throws XMLStreamException { + return null; + } + + @Override + public XMLEventReader createXMLEventReader(String systemId, Reader reader) throws XMLStreamException { + return null; + } + + @Override + public XMLEventReader createXMLEventReader(XMLStreamReader reader) throws XMLStreamException { + return null; + } + + @Override + public XMLEventReader createXMLEventReader(Source source) throws XMLStreamException { + return null; + } + + @Override + public XMLEventReader createXMLEventReader(InputStream stream) throws XMLStreamException { + return null; + } + + @Override + public XMLEventReader createXMLEventReader(InputStream stream, String encoding) throws XMLStreamException { + return null; + } + + @Override + public XMLEventReader createXMLEventReader(String systemId, InputStream stream) throws XMLStreamException { + return null; + } + + @Override + public XMLStreamReader createFilteredReader(XMLStreamReader reader, StreamFilter filter) + throws XMLStreamException { + return null; + } + + @Override + public XMLEventReader createFilteredReader(XMLEventReader reader, EventFilter filter) + throws XMLStreamException { + return null; + } + + @Override + public XMLResolver getXMLResolver() { + return null; + } + + @Override + public void setXMLResolver(XMLResolver resolver) { + + } + + @Override + public XMLReporter getXMLReporter() { + return null; + } + + @Override + public void setXMLReporter(XMLReporter reporter) { + + } + + @Override + public void setProperty(String name, Object value) throws IllegalArgumentException { + + } + + @Override + public Object getProperty(String name) throws IllegalArgumentException { + return null; + } + + @Override + public boolean isPropertySupported(String name) { + return false; + } + + @Override + public void setEventAllocator(XMLEventAllocator allocator) { + + } + + @Override + public XMLEventAllocator getEventAllocator() { + return null; + } + +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/XMLOutputFactoryImpl.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/XMLOutputFactoryImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..7042ca1af60c03ade13f1d4337449c128060cd51 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/XMLOutputFactoryImpl.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 xp1; + +import java.io.OutputStream; +import java.io.Writer; + +import javax.xml.stream.XMLEventWriter; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; +import javax.xml.transform.Result; + +public class XMLOutputFactoryImpl extends XMLOutputFactory { + + @Override + public XMLStreamWriter createXMLStreamWriter(Writer stream) throws XMLStreamException { + return null; + } + + @Override + public XMLStreamWriter createXMLStreamWriter(OutputStream stream) throws XMLStreamException { + return null; + } + + @Override + public XMLStreamWriter createXMLStreamWriter(OutputStream stream, String encoding) + throws XMLStreamException { + return null; + } + + @Override + public XMLStreamWriter createXMLStreamWriter(Result result) throws XMLStreamException { + return null; + } + + @Override + public XMLEventWriter createXMLEventWriter(Result result) throws XMLStreamException { + return null; + } + + @Override + public XMLEventWriter createXMLEventWriter(OutputStream stream) throws XMLStreamException { + return null; + } + + @Override + public XMLEventWriter createXMLEventWriter(OutputStream stream, String encoding) + throws XMLStreamException { + return null; + } + + @Override + public XMLEventWriter createXMLEventWriter(Writer stream) throws XMLStreamException { + return null; + } + + @Override + public void setProperty(String name, Object value) throws IllegalArgumentException { + + } + + @Override + public Object getProperty(String name) throws IllegalArgumentException { + return null; + } + + @Override + public boolean isPropertySupported(String name) { + return false; + } + +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/XPathFactoryImpl.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/XPathFactoryImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..bf5aa7aa20ef1cb2a9204f91df9fc15ed2110265 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider1/xp1/XPathFactoryImpl.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 xp1; + +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathFactory; +import javax.xml.xpath.XPathFactoryConfigurationException; +import javax.xml.xpath.XPathFunctionResolver; +import javax.xml.xpath.XPathVariableResolver; + +public class XPathFactoryImpl extends XPathFactory { + + @Override + public boolean isObjectModelSupported(String objectModel) { + // must be true, otherwise JAXP library will deny this impl + return true; + } + + @Override + public void setFeature(String name, boolean value) throws XPathFactoryConfigurationException { + + } + + @Override + public boolean getFeature(String name) throws XPathFactoryConfigurationException { + return false; + } + + @Override + public void setXPathVariableResolver(XPathVariableResolver resolver) { + + } + + @Override + public void setXPathFunctionResolver(XPathFunctionResolver resolver) { + + } + + @Override + public XPath newXPath() { + return null; + } + +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/module-info.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/module-info.java new file mode 100644 index 0000000000000000000000000000000000000000..d55645e58e9a1c575b4ede70dcd16eee3806cb1a --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/module-info.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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. + */ + +module xmlprovider2 { + requires java.xml; + + provides javax.xml.datatype.DatatypeFactory with xp2.DatatypeFactoryImpl; + provides javax.xml.stream.XMLEventFactory with xp2.XMLEventFactoryImpl; +} \ No newline at end of file diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/xp2/DatatypeFactoryImpl.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/xp2/DatatypeFactoryImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..e4a38886dccc99a5d9ce17f868d476e95ee033ca --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/xp2/DatatypeFactoryImpl.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 xp2; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.GregorianCalendar; + +import javax.xml.datatype.DatatypeFactory; +import javax.xml.datatype.Duration; +import javax.xml.datatype.XMLGregorianCalendar; + +public class DatatypeFactoryImpl extends DatatypeFactory { + + @Override + public Duration newDuration(String lexicalRepresentation) { + return null; + } + + @Override + public Duration newDuration(long durationInMilliSeconds) { + return null; + } + + @Override + public Duration newDuration(boolean isPositive, BigInteger years, BigInteger months, BigInteger days, + BigInteger hours, BigInteger minutes, BigDecimal seconds) { + return null; + } + + @Override + public XMLGregorianCalendar newXMLGregorianCalendar() { + return null; + } + + @Override + public XMLGregorianCalendar newXMLGregorianCalendar(String lexicalRepresentation) { + return null; + } + + @Override + public XMLGregorianCalendar newXMLGregorianCalendar(GregorianCalendar cal) { + return null; + } + + @Override + public XMLGregorianCalendar newXMLGregorianCalendar(BigInteger year, int month, int day, int hour, + int minute, int second, BigDecimal fractionalSecond, int timezone) { + return null; + } + +} diff --git a/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/xp2/XMLEventFactoryImpl.java b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/xp2/XMLEventFactoryImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..e4e89c8383be87768006c835573794baaca467e5 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/ServiceProviderTest/src/xmlprovider2/xp2/XMLEventFactoryImpl.java @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 xp2; + +import java.util.Iterator; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLEventFactory; +import javax.xml.stream.events.Attribute; +import javax.xml.stream.events.Characters; +import javax.xml.stream.events.Comment; +import javax.xml.stream.events.DTD; +import javax.xml.stream.events.EndDocument; +import javax.xml.stream.events.EndElement; +import javax.xml.stream.events.EntityDeclaration; +import javax.xml.stream.events.EntityReference; +import javax.xml.stream.events.Namespace; +import javax.xml.stream.events.ProcessingInstruction; +import javax.xml.stream.events.StartDocument; +import javax.xml.stream.events.StartElement; + +public class XMLEventFactoryImpl extends XMLEventFactory { + + @Override + public void setLocation(Location location) { + + } + + @Override + public Attribute createAttribute(String prefix, String namespaceURI, String localName, String value) { + return null; + } + + @Override + public Attribute createAttribute(String localName, String value) { + return null; + } + + @Override + public Attribute createAttribute(QName name, String value) { + return null; + } + + @Override + public Namespace createNamespace(String namespaceURI) { + return null; + } + + @Override + public Namespace createNamespace(String prefix, String namespaceUri) { + return null; + } + + @Override + public StartElement createStartElement(QName name, Iterator attributes, Iterator namespaces) { + return null; + } + + @Override + public StartElement createStartElement(String prefix, String namespaceUri, String localName) { + return null; + } + + @Override + public StartElement createStartElement(String prefix, String namespaceUri, String localName, + Iterator attributes, Iterator namespaces) { + return null; + } + + @Override + public StartElement createStartElement(String prefix, String namespaceUri, String localName, + Iterator attributes, Iterator namespaces, NamespaceContext context) { + return null; + } + + @Override + public EndElement createEndElement(QName name, Iterator namespaces) { + return null; + } + + @Override + public EndElement createEndElement(String prefix, String namespaceUri, String localName) { + return null; + } + + @Override + public EndElement createEndElement(String prefix, String namespaceUri, String localName, + Iterator namespaces) { + return null; + } + + @Override + public Characters createCharacters(String content) { + return null; + } + + @Override + public Characters createCData(String content) { + return null; + } + + @Override + public Characters createSpace(String content) { + return null; + } + + @Override + public Characters createIgnorableSpace(String content) { + return null; + } + + @Override + public StartDocument createStartDocument() { + return null; + } + + @Override + public StartDocument createStartDocument(String encoding, String version, boolean standalone) { + return null; + } + + @Override + public StartDocument createStartDocument(String encoding, String version) { + return null; + } + + @Override + public StartDocument createStartDocument(String encoding) { + return null; + } + + @Override + public EndDocument createEndDocument() { + return null; + } + + @Override + public EntityReference createEntityReference(String name, EntityDeclaration declaration) { + return null; + } + + @Override + public Comment createComment(String text) { + return null; + } + + @Override + public ProcessingInstruction createProcessingInstruction(String target, String data) { + return null; + } + + @Override + public DTD createDTD(String dtd) { + return null; + } + +} diff --git a/jaxp/test/javax/xml/jaxp/module/TEST.properties b/jaxp/test/javax/xml/jaxp/module/TEST.properties new file mode 100644 index 0000000000000000000000000000000000000000..85a3ae5f5c710a51fd1be33c1e11d97be4de59a7 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/module/TEST.properties @@ -0,0 +1,5 @@ +# Tests that must run in othervm mode +othervm.dirs= . + +# Declare module dependency +modules=java.xml diff --git a/jaxp/test/javax/xml/jaxp/unittest/TEST.properties b/jaxp/test/javax/xml/jaxp/unittest/TEST.properties index 93da2fdba82be9603f58780503a295ead35d98cb..b6e235b5124103423d2eb0173db6be20a432f297 100644 --- a/jaxp/test/javax/xml/jaxp/unittest/TEST.properties +++ b/jaxp/test/javax/xml/jaxp/unittest/TEST.properties @@ -4,5 +4,6 @@ TestNG.dirs = . lib.dirs = /javax/xml/jaxp/libs # Declare module dependency -modules=java.xml/com.sun.org.apache.xerces.internal.jaxp \ +modules=java.xml/com.sun.org.apache.xerces.internal.impl \ + java.xml/com.sun.org.apache.xerces.internal.jaxp \ java.xml/com.sun.org.apache.xml.internal.serialize diff --git a/jaxp/test/javax/xml/jaxp/unittest/stream/XMLEventReaderTest/Bug6668115Test.java b/jaxp/test/javax/xml/jaxp/unittest/stream/XMLEventReaderTest/Bug6668115Test.java index c56e7569c3c3359bccbddc0489e1b6c7a7841e8a..188d003621a4e79eccc4e3c7587beed89caf96ce 100644 --- a/jaxp/test/javax/xml/jaxp/unittest/stream/XMLEventReaderTest/Bug6668115Test.java +++ b/jaxp/test/javax/xml/jaxp/unittest/stream/XMLEventReaderTest/Bug6668115Test.java @@ -28,7 +28,6 @@ import java.io.File; import javax.xml.stream.XMLEventReader; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLOutputFactory; -import javax.xml.stream.events.XMLEvent; import org.testng.Assert; import org.testng.annotations.Test; @@ -74,7 +73,7 @@ public class Bug6668115Test { er.nextTag(); er.nextTag(); - XMLEvent event = er.peek(); + er.peek(); System.out.println(er.getElementText()); er.nextTag(); System.out.println(er.getElementText()); diff --git a/jaxp/test/javax/xml/jaxp/unittest/stream/XMLEventReaderTest/Bug8153781.java b/jaxp/test/javax/xml/jaxp/unittest/stream/XMLEventReaderTest/Bug8153781.java new file mode 100644 index 0000000000000000000000000000000000000000..f973b3bf33dad91e3ffa43eba3de94c9ad88460e --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/unittest/stream/XMLEventReaderTest/Bug8153781.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 stream.XMLEventReaderTest; + +import java.io.StringReader; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.XMLEvent; + +import org.testng.Assert; +import org.testng.annotations.Test; + +import com.sun.org.apache.xerces.internal.impl.XMLEntityManager; + +/* + * @bug 8153781 + * @summary Test if method skipDTD of class XMLDTDScannerImpl will correctly skip the DTD section, + * even if a call to XMLEntityScanner.scanData for skipping to the closing ']' returns true. + */ +public class Bug8153781 { + public static int DOCTYPE_SECTION_LENGTH = XMLEntityManager.DEFAULT_BUFFER_SIZE * 2; + public static int DOCUMENT_LENGTH = DOCTYPE_SECTION_LENGTH + 4096; + + public String createXMLDocument(int doctypeoffset) { + StringBuilder xmlcontentbuilder = new StringBuilder(DOCUMENT_LENGTH); + xmlcontentbuilder.append("\r\n"); + xmlcontentbuilder.append("\r\n"); + xmlcontentbuilder.append(" \r\n"); + xmlcontentbuilder.append(" ]\r\n"); + xmlcontentbuilder.append(">\r\n"); + xmlcontentbuilder.append("\r\n"); + xmlcontentbuilder.append("\r\n"); + System.out.println("Document length:" + xmlcontentbuilder.length()); + return xmlcontentbuilder.toString(); + } + + public void runReader(XMLInputFactory factory, int offset) throws XMLStreamException { + StringReader stringReader = new StringReader(createXMLDocument(offset)); + XMLEventReader reader = factory.createXMLEventReader(stringReader); + + while (reader.hasNext()) { + XMLEvent event = reader.nextEvent(); + System.out.println("Event Type: " + event.getEventType()); + } + } + + @Test + public void test() { + try { + XMLInputFactory factory = XMLInputFactory.newInstance(); + factory.setProperty(XMLInputFactory.SUPPORT_DTD, false); + for (int i = 0; i < 3; i++) { + runReader(factory, i); + } + } catch (XMLStreamException xe) { + xe.printStackTrace(); + Assert.fail(xe.getMessage()); + } + } +} diff --git a/jaxws/.hgtags b/jaxws/.hgtags index c0e2ef494a3881b518fed33cbc4d866d90a1c16b..7781746dc33ed5701535abb733983ad9112a63f6 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -360,3 +360,4 @@ fafd694e801f0f5a7c737fb08630ced3ca8f772c jdk-9+107 21274e7937bae291658d68143aca0e3ee9296db0 jdk-9+112 e980062475c10d21137051045bf95ee229db9b27 jdk-9+113 b314bb02182b9ca94708a91f312c377f5435f740 jdk-9+114 +4ff86e5489e4c0513dadfa69def8601c110ca5cd jdk-9+115 diff --git a/jdk/.hgtags b/jdk/.hgtags index e9974a728e5a1062812fa76a6f6e3e7c53b8bc6c..74ad9bf9055ccbb419b308fb2f541522fb177ad9 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -357,3 +357,4 @@ b2a69d66dc65ad1d3aeb3bd362cf5bb0deba040e jdk-9+111 1565a0efe6f0ca411a6df277df1e069431c60988 jdk-9+112 68f8be44b6a6b33dfa841ec671c0ba6e4056b372 jdk-9+113 bb8379287f3736f38c52b2d1418784e2592461d1 jdk-9+114 +35225b837d66582037eeadeb471c13235dfd793d jdk-9+115 diff --git a/jdk/make/Import.gmk b/jdk/make/Import.gmk index 42155494fb28627247b8784f6c02f1b75223f141..d479b09551410fa67319b44396920bcd26fbca5d 100644 --- a/jdk/make/Import.gmk +++ b/jdk/make/Import.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -83,20 +83,20 @@ ifneq ($(STATIC_BUILD), true) endif ifneq ($(OPENJDK_TARGET_OS), windows) - ifeq ($(JVM_VARIANT_SERVER), true) + ifeq ($(call check-jvm-variant, server), true) BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/server/$(LIBRARY_PREFIX)jsig$(SHARED_LIBRARY_SUFFIX) ifneq (, $(JSIG_DEBUGINFO)) BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/server/$(foreach I,$(JSIG_DEBUGINFO),$(notdir $I)) endif endif - ifeq ($(JVM_VARIANT_CLIENT), true) + ifeq ($(call check-jvm-variant, client), true) BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/client/$(LIBRARY_PREFIX)jsig$(SHARED_LIBRARY_SUFFIX) ifneq (, $(JSIG_DEBUGINFO)) BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/client/$(foreach I,$(JSIG_DEBUGINFO),$(notdir $I)) endif endif ifneq ($(OPENJDK_TARGET_OS), macosx) - ifeq ($(JVM_VARIANT_MINIMAL1), true) + ifeq ($(call check-jvm-variant, minimal), true) BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/minimal/$(LIBRARY_PREFIX)jsig$(SHARED_LIBRARY_SUFFIX) ifneq (,$(JSIG_DEBUGINFO)) BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/minimal/$(foreach I,$(JSIG_DEBUGINFO),$(notdir $I)) diff --git a/jdk/make/copy/Copy-java.base.gmk b/jdk/make/copy/Copy-java.base.gmk index 04988de5f855d90b0c1188d15ff72ee55cfc75f4..d50b52378f9770e89e509ac607cb7d6279b80d29 100644 --- a/jdk/make/copy/Copy-java.base.gmk +++ b/jdk/make/copy/Copy-java.base.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. # 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 @@ endif # # How to install jvm.cfg. # -ifeq ($(JVM_VARIANT_ZERO), true) +ifeq ($(call check-jvm-variant, zero zeroshark), true) JVMCFG_ARCH := zero else JVMCFG_ARCH := $(OPENJDK_TARGET_CPU_LEGACY) @@ -99,7 +99,7 @@ ifeq ($(OPENJDK_TARGET_OS), macosx) else JVMCFG_SRC := $(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/conf/$(JVMCFG_ARCH)/jvm.cfg # Allow override by ALT_JVMCFG_SRC if it exists - JVMCFG_SRC := $(if $(wildcard $(ALT_JVMCFG_SRC)),$(ALT_JVMCFG_SRC),$(JVMCFG_SRC)) + JVMCFG_SRC := $(if $(wildcard $(ALT_JVMCFG_SRC)),$(ALT_JVMCFG_SRC),$(JVMCFG_SRC)) endif JVMCFG_DIR := $(LIB_DST_DIR)$(OPENJDK_TARGET_CPU_LIBDIR) JVMCFG := $(JVMCFG_DIR)/jvm.cfg @@ -117,12 +117,12 @@ else # The main problem is deciding whether to use aliases for the VMs that are not # present and the current position is that we add aliases for client and server, but # not for minimal. - CLIENT_AND_SERVER := $(and $(findstring true, $(JVM_VARIANT_SERVER)), $(findstring true, $(JVM_VARIANT_CLIENT))) - ifeq ($(CLIENT_AND_SERVER), true) + CLIENT_AND_SERVER := $(call check-jvm-variant, client)+$(call check-jvm-variant, server) + ifeq ($(CLIENT_AND_SERVER), true+true) COPY_JVM_CFG_FILE := true else # For zero, the default jvm.cfg file is sufficient - ifeq ($(JVM_VARIANT_ZERO), true) + ifeq ($(call check-jvm-variant, zero zeroshark), true) COPY_JVM_CFG_FILE := true endif endif @@ -136,21 +136,21 @@ else $(MKDIR) -p $(@D) $(RM) $(@) # Now check for other permutations - ifeq ($(JVM_VARIANT_SERVER), true) + ifeq ($(call check-jvm-variant, server), true) $(PRINTF) "-server KNOWN\n">>$(@) $(PRINTF) "-client ALIASED_TO -server\n">>$(@) - ifeq ($(JVM_VARIANT_MINIMAL1), true) + ifeq ($(call check-jvm-variant, minimal), true) $(PRINTF) "-minimal KNOWN\n">>$(@) endif else - ifeq ($(JVM_VARIANT_CLIENT), true) + ifeq ($(call check-jvm-variant, client), true) $(PRINTF) "-client KNOWN\n">>$(@) $(PRINTF) "-server ALIASED_TO -client\n">>$(@) - ifeq ($(JVM_VARIANT_MINIMAL1), true) + ifeq ($(call check-jvm-variant, minimal), true) $(PRINTF) "-minimal KNOWN\n">>$(@) endif else - ifeq ($(JVM_VARIANT_MINIMAL1), true) + ifeq ($(call check-jvm-variant, minimal), true) $(PRINTF) "-minimal KNOWN\n">>$(@) $(PRINTF) "-server ALIASED_TO -minimal\n">>$(@) $(PRINTF) "-client ALIASED_TO -minimal\n">>$(@) diff --git a/jdk/make/data/fontconfig/windows.fontconfig.properties b/jdk/make/data/fontconfig/windows.fontconfig.properties index 9d3fa4a8315aa8582e2843510ef4946162520bf8..fcfcb8f51908f459964ef292c41823aa04e96bcd 100644 --- a/jdk/make/data/fontconfig/windows.fontconfig.properties +++ b/jdk/make/data/fontconfig/windows.fontconfig.properties @@ -37,6 +37,7 @@ allfonts.chinese-gb18030-extb=SimSun-ExtB allfonts.chinese-hkscs=MingLiU_HKSCS allfonts.chinese-ms950-extb=MingLiU-ExtB allfonts.devanagari=Mangal +allfonts.kannada=Tunga allfonts.dingbats=Wingdings allfonts.lucida=Lucida Sans Regular allfonts.symbol=Symbol @@ -239,11 +240,11 @@ sequence.allfonts.x-windows-874=alphabetic,thai,dingbats,symbol sequence.fallback=lucida,symbols,\ chinese-ms950,chinese-hkscs,chinese-ms936,chinese-gb18030,\ - japanese,korean,chinese-ms950-extb,chinese-ms936-extb,georgian + japanese,korean,chinese-ms950-extb,chinese-ms936-extb,georgian,kannada # Exclusion Ranges -exclusion.alphabetic=0700-1e9f,1f00-20ab,20ad-f8ff +exclusion.alphabetic=0700-1e9f,1f00-2017,2020-20ab,20ad-20b8,20bb-20bc,20be-f8ff exclusion.chinese-gb18030=0390-03d6,2200-22ef,2701-27be exclusion.hebrew=0041-005a,0060-007a,007f-00ff,20ac-20ac @@ -295,6 +296,7 @@ filename.GulimChe=gulim.TTC filename.Lucida_Sans_Regular=LucidaSansRegular.ttf filename.Mangal=MANGAL.TTF +filename.Tunga=TUNGA.TTF filename.Symbol=SYMBOL.TTF filename.Wingdings=WINGDING.TTF diff --git a/jdk/make/lib/Awt2dLibraries.gmk b/jdk/make/lib/Awt2dLibraries.gmk index d563935683c7e077cebe37b31bfc9afee15237b6..7215f351700584427bf6e5d6a2b7b4b982c7f5bd 100644 --- a/jdk/make/lib/Awt2dLibraries.gmk +++ b/jdk/make/lib/Awt2dLibraries.gmk @@ -375,6 +375,7 @@ ifeq ($(findstring $(OPENJDK_TARGET_OS),windows macosx),) OPTIMIZATION := LOW, \ CFLAGS := $(CFLAGS_JDKLIB) $(LIBAWT_XAWT_CFLAGS) \ $(X_CFLAGS), \ + WARNINGS_AS_ERRORS_xlc := false, \ DISABLED_WARNINGS_gcc := type-limits pointer-to-int-cast \ deprecated-declarations unused-result maybe-uninitialized format \ format-security int-to-pointer-cast parentheses, \ @@ -587,6 +588,7 @@ ifeq ($(BUILD_HEADLESS), true) $(CUPS_CFLAGS) \ $(X_CFLAGS) \ $(LIBAWT_HEADLESS_CFLAGS), \ + DISABLED_WARNINGS_xlc := 1506-356, \ DISABLED_WARNINGS_gcc := maybe-uninitialized int-to-pointer-cast, \ DISABLED_WARNINGS_solstudio := E_DECLARATION_IN_CODE \ E_EMPTY_TRANSLATION_UNIT, \ @@ -603,6 +605,10 @@ ifeq ($(BUILD_HEADLESS), true) OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libawt_headless, \ )) + # AIX warning explanation: + # 1506-356 : (W) Compilation unit is empty. + # This happens during the headless build + $(BUILD_LIBAWT_HEADLESS): $(BUILD_LIBAWT) TARGETS += $(BUILD_LIBAWT_HEADLESS) @@ -700,6 +706,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBFONTMANAGER, \ CXXFLAGS := $(CXXFLAGS_JDKLIB) $(LIBFONTMANAGER_CFLAGS), \ OPTIMIZATION := $(LIBFONTMANAGER_OPTIMIZATION), \ CFLAGS_windows = -DCC_NOEX, \ + WARNINGS_AS_ERRORS_xlc := false, \ DISABLED_WARNINGS_gcc := sign-compare int-to-pointer-cast \ type-limits missing-field-initializers, \ DISABLED_WARNINGS_CXX_gcc := reorder delete-non-virtual-dtor strict-overflow \ diff --git a/jdk/make/lib/CoreLibraries.gmk b/jdk/make/lib/CoreLibraries.gmk index f114c9b7d33774ce76136dee69f0a10721721f1a..3cb135253ea01ac6b03bac7481f426ad67823c37 100644 --- a/jdk/make/lib/CoreLibraries.gmk +++ b/jdk/make/lib/CoreLibraries.gmk @@ -146,6 +146,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJAVA, \ $(LIBJAVA_CFLAGS), \ System.c_CFLAGS := $(VERSION_CFLAGS), \ jdk_util.c_CFLAGS := $(VERSION_CFLAGS), \ + WARNINGS_AS_ERRORS_xlc := false, \ DISABLED_WARNINGS_gcc := unused-result, \ DISABLED_WARNINGS_solstudio := E_STATEMENT_NOT_REACHED, \ MAPFILE := $(LIBJAVA_MAPFILE), \ @@ -266,7 +267,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJIMAGE, \ LDFLAGS_windows := -export:JIMAGE_Open -export:JIMAGE_Close \ -export:JIMAGE_PackageToModule \ -export:JIMAGE_FindResource -export:JIMAGE_GetResource \ - -export:JIMAGE_ResourceIterator, \ + -export:JIMAGE_ResourceIterator -export:JIMAGE_ResourcePath, \ LIBS_unix := -ljvm -ldl $(LIBCXX), \ LIBS_solaris := -lc, \ LIBS_macosx := -lc++, \ @@ -289,7 +290,7 @@ LIBJLI_SRC_DIRS := $(call FindSrcDirsForLib, java.base, jli) LIBJLI_CFLAGS := $(CFLAGS_JDKLIB) -ifeq ($(JVM_VARIANT_ZERO), true) +ifeq ($(call check-jvm-variant, zero zeroshark), true) ERGO_FAMILY := zero else ifeq ($(OPENJDK_TARGET_CPU_ARCH), x86) diff --git a/jdk/make/lib/NioLibraries.gmk b/jdk/make/lib/NioLibraries.gmk index de2cdea072746da1c0269008f2e0e1699c4f2425..203447c513f48b119ef3d68294227c2a98fd43d9 100644 --- a/jdk/make/lib/NioLibraries.gmk +++ b/jdk/make/lib/NioLibraries.gmk @@ -70,6 +70,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBNIO, \ SRC := $(BUILD_LIBNIO_SRC), \ EXCLUDE_FILES := $(BUILD_LIBNIO_EXFILES), \ OPTIMIZATION := HIGH, \ + WARNINGS_AS_ERRORS_xlc := false, \ CFLAGS := $(CFLAGS_JDKLIB) \ $(BUILD_LIBNIO_CFLAGS), \ MAPFILE := $(BUILD_LIBNIO_MAPFILE), \ diff --git a/jdk/make/mapfiles/libjava/mapfile-vers b/jdk/make/mapfiles/libjava/mapfile-vers index 45ca0da9630f9453e8598c75e6b0a0b1303128cf..118b0fd3ddfd17fd7bc5ee4f2977302e65f78df4 100644 --- a/jdk/make/mapfiles/libjava/mapfile-vers +++ b/jdk/make/mapfiles/libjava/mapfile-vers @@ -139,8 +139,7 @@ SUNWprivate_1.1 { Java_java_lang_Double_doubleToRawLongBits; Java_java_lang_Float_intBitsToFloat; Java_java_lang_Float_floatToRawIntBits; - Java_java_lang_StackFrameInfo_fillInStackFrames; - Java_java_lang_StackFrameInfo_setMethodInfo; + Java_java_lang_StackFrameInfo_toStackTraceElement0; Java_java_lang_StackStreamFactory_checkStackWalkModes; Java_java_lang_StackStreamFactory_00024AbstractStackWalker_callStackWalk; Java_java_lang_StackStreamFactory_00024AbstractStackWalker_fetchStackFrames; diff --git a/jdk/make/mapfiles/libjimage/mapfile-vers b/jdk/make/mapfiles/libjimage/mapfile-vers index 48eac21b53adfac9e88e601156f8969aaac0eb67..a4de5f82f3c627836343380a4d7ee6d128036d29 100644 --- a/jdk/make/mapfiles/libjimage/mapfile-vers +++ b/jdk/make/mapfiles/libjimage/mapfile-vers @@ -34,6 +34,7 @@ SUNWprivate_1.1 { JIMAGE_FindResource; JIMAGE_GetResource; JIMAGE_ResourceIterator; + JIMAGE_ResourcePath; local: *; }; diff --git a/jdk/src/java.base/aix/native/libnet/aix_close.c b/jdk/src/java.base/aix/native/libnet/aix_close.c index 0165c9a1959ddf08abf4f719f526dfa6bb5e49fc..77b5daecf60352625a1efaa70b8282b94c045cb1 100644 --- a/jdk/src/java.base/aix/native/libnet/aix_close.c +++ b/jdk/src/java.base/aix/native/libnet/aix_close.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, SAP SE and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,6 +51,8 @@ ... */ +#include +#include #include #include #include @@ -86,10 +89,35 @@ typedef struct { static int sigWakeup = (SIGRTMAX - 1); /* - * The fd table and the number of file descriptors + * fdTable holds one entry per file descriptor, up to a certain + * maximum. + * Theoretically, the number of possible file descriptors can get + * large, though usually it does not. Entries for small value file + * descriptors are kept in a simple table, which covers most scenarios. + * Entries for large value file descriptors are kept in an overflow + * table, which is organized as a sparse two dimensional array whose + * slabs are allocated on demand. This covers all corner cases while + * keeping memory consumption reasonable. */ -static fdEntry_t *fdTable = NULL; -static int fdCount = 0; + +/* Base table for low value file descriptors */ +static fdEntry_t* fdTable = NULL; +/* Maximum size of base table (in number of entries). */ +static const int fdTableMaxSize = 0x1000; /* 4K */ +/* Actual size of base table (in number of entries) */ +static int fdTableLen = 0; +/* Max. theoretical number of file descriptors on system. */ +static int fdLimit = 0; + +/* Overflow table, should base table not be large enough. Organized as + * an array of n slabs, each holding 64k entries. + */ +static fdEntry_t** fdOverflowTable = NULL; +/* Number of slabs in the overflow table */ +static int fdOverflowTableLen = 0; +/* Number of entries in one slab */ +static const int fdOverflowTableSlabSize = 0x10000; /* 64k */ +pthread_mutex_t fdOverflowTableLock = PTHREAD_MUTEX_INITIALIZER; /* * Null signal handler @@ -108,42 +136,42 @@ void aix_close_init() { struct rlimit nbr_files; sigset_t sigset; struct sigaction sa; + int i = 0; - /* Check already initialized */ - if (fdCount > 0 && fdTable != NULL) { - return; - } - - /* - * Allocate table based on the maximum number of - * file descriptors. - */ + /* Determine the maximum number of possible file descriptors. */ if (-1 == getrlimit(RLIMIT_NOFILE, &nbr_files)) { fprintf(stderr, "library initialization failed - " "unable to get max # of allocated fds\n"); abort(); } - fdCount = nbr_files.rlim_max; - /* - * We have a conceptual problem here, when the number of files is - * unlimited. As a kind of workaround, we ensure the table is big - * enough for handle even a large number of files. Since SAP itself - * recommends a limit of 32000 files, we just use 64000 as 'infinity'. - */ - if (nbr_files.rlim_max == RLIM_INFINITY) { - fdCount = 64000; + if (nbr_files.rlim_max != RLIM_INFINITY) { + fdLimit = nbr_files.rlim_max; + } else { + /* We just do not know. */ + fdLimit = INT_MAX; } - fdTable = (fdEntry_t *)calloc(fdCount, sizeof(fdEntry_t)); + + /* Allocate table for low value file descriptors. */ + fdTableLen = fdLimit < fdTableMaxSize ? fdLimit : fdTableMaxSize; + fdTable = (fdEntry_t*) calloc(fdTableLen, sizeof(fdEntry_t)); if (fdTable == NULL) { fprintf(stderr, "library initialization failed - " "unable to allocate file descriptor table - out of memory"); abort(); + } else { + for (i = 0; i < fdTableLen; i ++) { + pthread_mutex_init(&fdTable[i].lock, NULL); + } } - { - int i; - for (i=0; i < fdCount; i++) { - pthread_mutex_init(&fdTable[i].lock, NULL); + /* Allocate overflow table, if needed */ + if (fdLimit > fdTableMaxSize) { + fdOverflowTableLen = ((fdLimit - fdTableMaxSize) / fdOverflowTableSlabSize) + 1; + fdOverflowTable = (fdEntry_t**) calloc(fdOverflowTableLen, sizeof(fdEntry_t*)); + if (fdOverflowTable == NULL) { + fprintf(stderr, "library initialization failed - " + "unable to allocate file descriptor overflow table - out of memory"); + abort(); } } @@ -161,17 +189,60 @@ void aix_close_init() { } /* - * Return the fd table for this fd or NULL is fd out - * of range. + * Return the fd table for this fd. */ static inline fdEntry_t *getFdEntry(int fd) { - if (fd < 0 || fd >= fdCount) { + fdEntry_t* result = NULL; + + if (fd < 0) { return NULL; } - return &fdTable[fd]; + + /* This should not happen. If it does, our assumption about + * max. fd value was wrong. */ + assert(fd < fdLimit); + + if (fd < fdTableMaxSize) { + /* fd is in base table. */ + assert(fd < fdTableLen); + result = &fdTable[fd]; + } else { + /* fd is in overflow table. */ + const int indexInOverflowTable = fd - fdTableMaxSize; + const int rootindex = indexInOverflowTable / fdOverflowTableSlabSize; + const int slabindex = indexInOverflowTable % fdOverflowTableSlabSize; + fdEntry_t* slab = NULL; + assert(rootindex < fdOverflowTableLen); + assert(slabindex < fdOverflowTableSlabSize); + pthread_mutex_lock(&fdOverflowTableLock); + /* Allocate new slab in overflow table if needed */ + if (fdOverflowTable[rootindex] == NULL) { + fdEntry_t* const newSlab = + (fdEntry_t*)calloc(fdOverflowTableSlabSize, sizeof(fdEntry_t)); + if (newSlab == NULL) { + fprintf(stderr, "Unable to allocate file descriptor overflow" + " table slab - out of memory"); + pthread_mutex_unlock(&fdOverflowTableLock); + abort(); + } else { + int i; + for (i = 0; i < fdOverflowTableSlabSize; i ++) { + pthread_mutex_init(&newSlab[i].lock, NULL); + } + fdOverflowTable[rootindex] = newSlab; + } + } + pthread_mutex_unlock(&fdOverflowTableLock); + slab = fdOverflowTable[rootindex]; + result = &slab[slabindex]; + } + + return result; + } + /* * Start a blocking operation :- * Insert thread onto thread list for the fd. diff --git a/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystemProvider.java b/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystemProvider.java index f6abaf69d7e1fc5ca29138e47cb0f6cc5f9727b1..8a2307d2ff6c1a32c20b3c103d0e8341a0d62119 100644 --- a/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystemProvider.java +++ b/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystemProvider.java @@ -102,8 +102,8 @@ public class LinuxFileSystemProvider extends UnixFileSystemProvider { @Override FileTypeDetector getFileTypeDetector() { - Path userMimeTypes = Paths.get(AccessController.doPrivileged( - new GetPropertyAction("user.home")), ".mime.types"); + String userHome = GetPropertyAction.getProperty("user.home"); + Path userMimeTypes = Paths.get(userHome, ".mime.types"); Path etcMimeTypes = Paths.get("/etc/mime.types"); return chain(new GioFileTypeDetector(), diff --git a/jdk/src/java.base/linux/native/libnet/linux_close.c b/jdk/src/java.base/linux/native/libnet/linux_close.c index f2e186f731ec4f945a90e6192d7ffee665381b49..45ab7b4dc1b1369f0254a427825a428c9d104a05 100644 --- a/jdk/src/java.base/linux/native/libnet/linux_close.c +++ b/jdk/src/java.base/linux/native/libnet/linux_close.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,8 @@ * questions. */ +#include +#include #include #include #include @@ -59,10 +61,35 @@ typedef struct { static int sigWakeup = (__SIGRTMAX - 2); /* - * The fd table and the number of file descriptors + * fdTable holds one entry per file descriptor, up to a certain + * maximum. + * Theoretically, the number of possible file descriptors can get + * large, though usually it does not. Entries for small value file + * descriptors are kept in a simple table, which covers most scenarios. + * Entries for large value file descriptors are kept in an overflow + * table, which is organized as a sparse two dimensional array whose + * slabs are allocated on demand. This covers all corner cases while + * keeping memory consumption reasonable. */ -static fdEntry_t *fdTable; -static int fdCount; + +/* Base table for low value file descriptors */ +static fdEntry_t* fdTable = NULL; +/* Maximum size of base table (in number of entries). */ +static const int fdTableMaxSize = 0x1000; /* 4K */ +/* Actual size of base table (in number of entries) */ +static int fdTableLen = 0; +/* Max. theoretical number of file descriptors on system. */ +static int fdLimit = 0; + +/* Overflow table, should base table not be large enough. Organized as + * an array of n slabs, each holding 64k entries. + */ +static fdEntry_t** fdOverflowTable = NULL; +/* Number of slabs in the overflow table */ +static int fdOverflowTableLen = 0; +/* Number of entries in one slab */ +static const int fdOverflowTableSlabSize = 0x10000; /* 64k */ +pthread_mutex_t fdOverflowTableLock = PTHREAD_MUTEX_INITIALIZER; /* * Null signal handler @@ -78,18 +105,43 @@ static void __attribute((constructor)) init() { struct rlimit nbr_files; sigset_t sigset; struct sigaction sa; + int i = 0; - /* - * Allocate table based on the maximum number of - * file descriptors. - */ - getrlimit(RLIMIT_NOFILE, &nbr_files); - fdCount = nbr_files.rlim_max; - fdTable = (fdEntry_t *)calloc(fdCount, sizeof(fdEntry_t)); + /* Determine the maximum number of possible file descriptors. */ + if (-1 == getrlimit(RLIMIT_NOFILE, &nbr_files)) { + fprintf(stderr, "library initialization failed - " + "unable to get max # of allocated fds\n"); + abort(); + } + if (nbr_files.rlim_max != RLIM_INFINITY) { + fdLimit = nbr_files.rlim_max; + } else { + /* We just do not know. */ + fdLimit = INT_MAX; + } + + /* Allocate table for low value file descriptors. */ + fdTableLen = fdLimit < fdTableMaxSize ? fdLimit : fdTableMaxSize; + fdTable = (fdEntry_t*) calloc(fdTableLen, sizeof(fdEntry_t)); if (fdTable == NULL) { fprintf(stderr, "library initialization failed - " "unable to allocate file descriptor table - out of memory"); abort(); + } else { + for (i = 0; i < fdTableLen; i ++) { + pthread_mutex_init(&fdTable[i].lock, NULL); + } + } + + /* Allocate overflow table, if needed */ + if (fdLimit > fdTableMaxSize) { + fdOverflowTableLen = ((fdLimit - fdTableMaxSize) / fdOverflowTableSlabSize) + 1; + fdOverflowTable = (fdEntry_t**) calloc(fdOverflowTableLen, sizeof(fdEntry_t*)); + if (fdOverflowTable == NULL) { + fprintf(stderr, "library initialization failed - " + "unable to allocate file descriptor overflow table - out of memory"); + abort(); + } } /* @@ -106,15 +158,57 @@ static void __attribute((constructor)) init() { } /* - * Return the fd table for this fd or NULL is fd out - * of range. + * Return the fd table for this fd. */ static inline fdEntry_t *getFdEntry(int fd) { - if (fd < 0 || fd >= fdCount) { + fdEntry_t* result = NULL; + + if (fd < 0) { return NULL; } - return &fdTable[fd]; + + /* This should not happen. If it does, our assumption about + * max. fd value was wrong. */ + assert(fd < fdLimit); + + if (fd < fdTableMaxSize) { + /* fd is in base table. */ + assert(fd < fdTableLen); + result = &fdTable[fd]; + } else { + /* fd is in overflow table. */ + const int indexInOverflowTable = fd - fdTableMaxSize; + const int rootindex = indexInOverflowTable / fdOverflowTableSlabSize; + const int slabindex = indexInOverflowTable % fdOverflowTableSlabSize; + fdEntry_t* slab = NULL; + assert(rootindex < fdOverflowTableLen); + assert(slabindex < fdOverflowTableSlabSize); + pthread_mutex_lock(&fdOverflowTableLock); + /* Allocate new slab in overflow table if needed */ + if (fdOverflowTable[rootindex] == NULL) { + fdEntry_t* const newSlab = + (fdEntry_t*)calloc(fdOverflowTableSlabSize, sizeof(fdEntry_t)); + if (newSlab == NULL) { + fprintf(stderr, "Unable to allocate file descriptor overflow" + " table slab - out of memory"); + pthread_mutex_unlock(&fdOverflowTableLock); + abort(); + } else { + int i; + for (i = 0; i < fdOverflowTableSlabSize; i ++) { + pthread_mutex_init(&newSlab[i].lock, NULL); + } + fdOverflowTable[rootindex] = newSlab; + } + } + pthread_mutex_unlock(&fdOverflowTableLock); + slab = fdOverflowTable[rootindex]; + result = &slab[slabindex]; + } + + return result; + } /* diff --git a/jdk/src/java.base/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java b/jdk/src/java.base/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java index 2aa3fbcbaa298e00afdb6de7ded9c225c156fb43..7598cf9e37f847ccf478a1b7a5d4bab1452f4629 100644 --- a/jdk/src/java.base/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java +++ b/jdk/src/java.base/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java @@ -32,9 +32,9 @@ package sun.nio.ch; import java.io.IOException; -import java.io.FileDescriptor; import java.util.Iterator; import java.util.LinkedList; +import sun.security.action.GetPropertyAction; /* * struct kevent { // 32-bit 64-bit @@ -84,10 +84,8 @@ class KQueueArrayWrapper { static { IOUtil.load(); initStructSizes(); - String datamodel = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("sun.arch.data.model") - ); - is64bit = datamodel.equals("64"); + String datamodel = GetPropertyAction.getProperty("sun.arch.data.model"); + is64bit = "64".equals(datamodel); } KQueueArrayWrapper() { diff --git a/jdk/src/java.base/macosx/classes/sun/nio/fs/MacOSXFileSystemProvider.java b/jdk/src/java.base/macosx/classes/sun/nio/fs/MacOSXFileSystemProvider.java index 0dcee95bfc3547232afe1dc2428987e6e1daf952..6b9a56a9fa774f23a76cca9569024cc6ec2efcbf 100644 --- a/jdk/src/java.base/macosx/classes/sun/nio/fs/MacOSXFileSystemProvider.java +++ b/jdk/src/java.base/macosx/classes/sun/nio/fs/MacOSXFileSystemProvider.java @@ -28,7 +28,6 @@ package sun.nio.fs; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.spi.FileTypeDetector; -import java.security.AccessController; import sun.security.action.GetPropertyAction; /** @@ -47,8 +46,8 @@ public class MacOSXFileSystemProvider extends BsdFileSystemProvider { @Override FileTypeDetector getFileTypeDetector() { - Path userMimeTypes = Paths.get(AccessController.doPrivileged( - new GetPropertyAction("user.home")), ".mime.types"); + Path userMimeTypes = Paths.get( + GetPropertyAction.getProperty("user.home"), ".mime.types"); return chain(new MimeTypesFileTypeDetector(userMimeTypes), new UTIFileTypeDetector()); diff --git a/jdk/src/java.base/macosx/native/libnet/bsd_close.c b/jdk/src/java.base/macosx/native/libnet/bsd_close.c index 21478ce6e5fe73339068a94be5b3d2163c60aef6..728ea8bf1d7cc3b259d3c4bbda76a963c5c82633 100644 --- a/jdk/src/java.base/macosx/native/libnet/bsd_close.c +++ b/jdk/src/java.base/macosx/native/libnet/bsd_close.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,8 @@ * questions. */ +#include +#include #include #include #include @@ -61,18 +63,35 @@ typedef struct { static int sigWakeup = SIGIO; /* - * The fd table and the number of file descriptors + * fdTable holds one entry per file descriptor, up to a certain + * maximum. + * Theoretically, the number of possible file descriptors can get + * large, though usually it does not. Entries for small value file + * descriptors are kept in a simple table, which covers most scenarios. + * Entries for large value file descriptors are kept in an overflow + * table, which is organized as a sparse two dimensional array whose + * slabs are allocated on demand. This covers all corner cases while + * keeping memory consumption reasonable. */ -static fdEntry_t *fdTable; -static int fdCount; -/* - * This limit applies if getlimit() returns unlimited. - * Unfortunately, this means if someone wants a higher limit - * then they have to set an explicit limit, higher than this, - * which is probably counter-intuitive. +/* Base table for low value file descriptors */ +static fdEntry_t* fdTable = NULL; +/* Maximum size of base table (in number of entries). */ +static const int fdTableMaxSize = 0x1000; /* 4K */ +/* Actual size of base table (in number of entries) */ +static int fdTableLen = 0; +/* Max. theoretical number of file descriptors on system. */ +static int fdLimit = 0; + +/* Overflow table, should base table not be large enough. Organized as + * an array of n slabs, each holding 64k entries. */ -#define MAX_FD_COUNT 4096 +static fdEntry_t** fdOverflowTable = NULL; +/* Number of slabs in the overflow table */ +static int fdOverflowTableLen = 0; +/* Number of entries in one slab */ +static const int fdOverflowTableSlabSize = 0x10000; /* 64k */ +pthread_mutex_t fdOverflowTableLock = PTHREAD_MUTEX_INITIALIZER; /* * Null signal handler @@ -88,26 +107,43 @@ static void __attribute((constructor)) init() { struct rlimit nbr_files; sigset_t sigset; struct sigaction sa; - int i; + int i = 0; - /* - * Allocate table based on the maximum number of - * file descriptors. - */ - getrlimit(RLIMIT_NOFILE, &nbr_files); - if (nbr_files.rlim_max == RLIM_INFINITY) { - fdCount = MAX_FD_COUNT; + /* Determine the maximum number of possible file descriptors. */ + if (-1 == getrlimit(RLIMIT_NOFILE, &nbr_files)) { + fprintf(stderr, "library initialization failed - " + "unable to get max # of allocated fds\n"); + abort(); + } + if (nbr_files.rlim_max != RLIM_INFINITY) { + fdLimit = nbr_files.rlim_max; } else { - fdCount = nbr_files.rlim_max; + /* We just do not know. */ + fdLimit = INT_MAX; } - fdTable = (fdEntry_t *)calloc(fdCount, sizeof(fdEntry_t)); + + /* Allocate table for low value file descriptors. */ + fdTableLen = fdLimit < fdTableMaxSize ? fdLimit : fdTableMaxSize; + fdTable = (fdEntry_t*) calloc(fdTableLen, sizeof(fdEntry_t)); if (fdTable == NULL) { fprintf(stderr, "library initialization failed - " "unable to allocate file descriptor table - out of memory"); abort(); + } else { + for (i = 0; i < fdTableLen; i ++) { + pthread_mutex_init(&fdTable[i].lock, NULL); + } } - for (i=0; i fdTableMaxSize) { + fdOverflowTableLen = ((fdLimit - fdTableMaxSize) / fdOverflowTableSlabSize) + 1; + fdOverflowTable = (fdEntry_t**) calloc(fdOverflowTableLen, sizeof(fdEntry_t*)); + if (fdOverflowTable == NULL) { + fprintf(stderr, "library initialization failed - " + "unable to allocate file descriptor overflow table - out of memory"); + abort(); + } } /* @@ -124,17 +160,60 @@ static void __attribute((constructor)) init() { } /* - * Return the fd table for this fd or NULL is fd out - * of range. + * Return the fd table for this fd. */ static inline fdEntry_t *getFdEntry(int fd) { - if (fd < 0 || fd >= fdCount) { + fdEntry_t* result = NULL; + + if (fd < 0) { return NULL; } - return &fdTable[fd]; + + /* This should not happen. If it does, our assumption about + * max. fd value was wrong. */ + assert(fd < fdLimit); + + if (fd < fdTableMaxSize) { + /* fd is in base table. */ + assert(fd < fdTableLen); + result = &fdTable[fd]; + } else { + /* fd is in overflow table. */ + const int indexInOverflowTable = fd - fdTableMaxSize; + const int rootindex = indexInOverflowTable / fdOverflowTableSlabSize; + const int slabindex = indexInOverflowTable % fdOverflowTableSlabSize; + fdEntry_t* slab = NULL; + assert(rootindex < fdOverflowTableLen); + assert(slabindex < fdOverflowTableSlabSize); + pthread_mutex_lock(&fdOverflowTableLock); + /* Allocate new slab in overflow table if needed */ + if (fdOverflowTable[rootindex] == NULL) { + fdEntry_t* const newSlab = + (fdEntry_t*)calloc(fdOverflowTableSlabSize, sizeof(fdEntry_t)); + if (newSlab == NULL) { + fprintf(stderr, "Unable to allocate file descriptor overflow" + " table slab - out of memory"); + pthread_mutex_unlock(&fdOverflowTableLock); + abort(); + } else { + int i; + for (i = 0; i < fdOverflowTableSlabSize; i ++) { + pthread_mutex_init(&newSlab[i].lock, NULL); + } + fdOverflowTable[rootindex] = newSlab; + } + } + pthread_mutex_unlock(&fdOverflowTableLock); + slab = fdOverflowTable[rootindex]; + result = &slab[slabindex]; + } + + return result; + } + /* * Start a blocking operation :- * Insert thread onto thread list for the fd. diff --git a/jdk/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java b/jdk/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java index 9f8f54a182391bb6ffd2aab94ec5838a8391824f..87fa4a383f3d2c17123c6b63bffde7f2ebd38b83 100644 --- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java +++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java @@ -512,11 +512,17 @@ final class GaloisCounterMode extends FeedbackCipher { byte[] sOut = new byte[s.length]; GCTR gctrForSToTag = new GCTR(embeddedCipher, this.preCounterBlock); gctrForSToTag.doFinal(s, 0, s.length, sOut, 0); + + // check entire authentication tag for time-consistency + int mismatch = 0; for (int i = 0; i < tagLenBytes; i++) { - if (tag[i] != sOut[i]) { - throw new AEADBadTagException("Tag mismatch!"); - } + mismatch |= tag[i] ^ sOut[i]; } + + if (mismatch != 0) { + throw new AEADBadTagException("Tag mismatch!"); + } + return len; } diff --git a/jdk/src/java.base/share/classes/java/io/DataInput.java b/jdk/src/java.base/share/classes/java/io/DataInput.java index dca9187d4a7c12d016a166d299e8371f87c2dda5..60e03c2173c5e75f1e2aaa724ebb77a099b4b694 100644 --- a/jdk/src/java.base/share/classes/java/io/DataInput.java +++ b/jdk/src/java.base/share/classes/java/io/DataInput.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -182,10 +182,11 @@ interface DataInput { * not all bytes of {@code b} have been * updated with data from the input stream. * - * @param b the buffer into which the data is read. - * @exception EOFException if this stream reaches the end before reading - * all the bytes. - * @exception IOException if an I/O error occurs. + * @param b the buffer into which the data is read. + * @throws NullPointerException if {@code b} is {@code null}. + * @throws EOFException if this stream reaches the end before reading + * all the bytes. + * @throws IOException if an I/O error occurs. */ void readFully(byte b[]) throws IOException; @@ -226,12 +227,16 @@ interface DataInput { * and so on. The number of bytes read is, * at most, equal to {@code len}. * - * @param b the buffer into which the data is read. - * @param off an int specifying the offset into the data. - * @param len an int specifying the number of bytes to read. - * @exception EOFException if this stream reaches the end before reading - * all the bytes. - * @exception IOException if an I/O error occurs. + * @param b the buffer into which the data is read. + * @param off an int specifying the offset in the data array {@code b}. + * @param len an int specifying the number of bytes to read. + * @throws NullPointerException if {@code b} is {@code null}. + * @throws IndexOutOfBoundsException if {@code off} is negative, + * {@code len} is negative, or {@code len} is greater than + * {@code b.length - off}. + * @throws EOFException if this stream reaches the end before reading + * all the bytes. + * @throws IOException if an I/O error occurs. */ void readFully(byte b[], int off, int len) throws IOException; diff --git a/jdk/src/java.base/share/classes/java/io/DataInputStream.java b/jdk/src/java.base/share/classes/java/io/DataInputStream.java index 6ce6b233ee6c071de1c32280827218be16001973..f92c4f91b0c5ecaeb0e9a1772b7c51914572668e 100644 --- a/jdk/src/java.base/share/classes/java/io/DataInputStream.java +++ b/jdk/src/java.base/share/classes/java/io/DataInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -150,38 +150,43 @@ class DataInputStream extends FilterInputStream implements DataInput { } /** - * See the general contract of the readFully - * method of DataInput. + * See the general contract of the {@code readFully} + * method of {@code DataInput}. *

* Bytes * for this operation are read from the contained * input stream. * - * @param b the buffer into which the data is read. - * @exception EOFException if this input stream reaches the end before - * reading all the bytes. - * @exception IOException the stream has been closed and the contained - * input stream does not support reading after close, or - * another I/O error occurs. - * @see java.io.FilterInputStream#in + * @param b the buffer into which the data is read. + * @throws NullPointerException if {@code b} is {@code null}. + * @throws EOFException if this input stream reaches the end before + * reading all the bytes. + * @throws IOException the stream has been closed and the contained + * input stream does not support reading after close, or + * another I/O error occurs. + * @see java.io.FilterInputStream#in */ public final void readFully(byte b[]) throws IOException { readFully(b, 0, b.length); } /** - * See the general contract of the readFully - * method of DataInput. + * See the general contract of the {@code readFully} + * method of {@code DataInput}. *

* Bytes * for this operation are read from the contained * input stream. * * @param b the buffer into which the data is read. - * @param off the start offset of the data. + * @param off the start offset in the data array {@code b}. * @param len the number of bytes to read. + * @exception NullPointerException if {@code b} is {@code null}. + * @exception IndexOutOfBoundsException if {@code off} is negative, + * {@code len} is negative, or {@code len} is greater than + * {@code b.length - off}. * @exception EOFException if this input stream reaches the end before - * reading all the bytes. + * reading all the bytes. * @exception IOException the stream has been closed and the contained * input stream does not support reading after close, or * another I/O error occurs. diff --git a/jdk/src/java.base/share/classes/java/io/File.java b/jdk/src/java.base/share/classes/java/io/File.java index 089171bab9e70e20d15cc229f97e053849d58981..7f23340920b41d8664db31f510066d59eac1af80 100644 --- a/jdk/src/java.base/share/classes/java/io/File.java +++ b/jdk/src/java.base/share/classes/java/io/File.java @@ -31,7 +31,6 @@ import java.net.MalformedURLException; import java.net.URISyntaxException; import java.util.List; import java.util.ArrayList; -import java.security.AccessController; import java.security.SecureRandom; import java.nio.file.Path; import java.nio.file.FileSystems; @@ -1896,8 +1895,8 @@ public class File private TempDirectory() { } // temporary directory location - private static final File tmpdir = new File(AccessController - .doPrivileged(new GetPropertyAction("java.io.tmpdir"))); + private static final File tmpdir = new File( + GetPropertyAction.getProperty("java.io.tmpdir")); static File location() { return tmpdir; } diff --git a/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java b/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java index dbf10bd757d1791eb88fa6b9029b4e1818071fb6..a591136419d436464a8a5ec00089d8bd6d80c58b 100644 --- a/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java +++ b/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java @@ -40,6 +40,9 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import static java.io.ObjectStreamClass.processQueue; +import jdk.internal.misc.JavaObjectInputStreamAccess; +import jdk.internal.misc.ObjectStreamClassValidator; +import jdk.internal.misc.SharedSecrets; import jdk.internal.misc.Unsafe; import sun.reflect.misc.ReflectUtil; @@ -853,10 +856,14 @@ public class ObjectInputStream * exactly 'length' bytes. * * @param buf the buffer into which the data is read - * @param off the start offset of the data + * @param off the start offset in the destination array {@code buf} * @param len the maximum number of bytes read * @return the actual number of bytes read, -1 is returned when the end of * the stream is reached. + * @throws NullPointerException if {@code buf} is {@code null}. + * @throws IndexOutOfBoundsException if {@code off} is negative, + * {@code len} is negative, or {@code len} is greater than + * {@code buf.length - off}. * @throws IOException If an I/O error has occurred. * @see java.io.DataInputStream#readFully(byte[],int,int) */ @@ -1014,6 +1021,7 @@ public class ObjectInputStream * Reads bytes, blocking until all bytes are read. * * @param buf the buffer into which the data is read + * @throws NullPointerException If {@code buf} is {@code null}. * @throws EOFException If end of file is reached. * @throws IOException If other I/O error has occurred. */ @@ -1025,8 +1033,12 @@ public class ObjectInputStream * Reads bytes, blocking until all bytes are read. * * @param buf the buffer into which the data is read - * @param off the start offset of the data + * @param off the start offset into the data array {@code buf} * @param len the maximum number of bytes to read + * @throws NullPointerException If {@code buf} is {@code null}. + * @throws IndexOutOfBoundsException If {@code off} is negative, + * {@code len} is negative, or {@code len} is greater than + * {@code buf.length - off}. * @throws EOFException If end of file is reached. * @throws IOException If other I/O error has occurred. */ @@ -1509,23 +1521,28 @@ public class ObjectInputStream throws IOException { byte tc = bin.peekByte(); + ObjectStreamClass descriptor; switch (tc) { case TC_NULL: - return (ObjectStreamClass) readNull(); - + descriptor = (ObjectStreamClass) readNull(); + break; case TC_REFERENCE: - return (ObjectStreamClass) readHandle(unshared); - + descriptor = (ObjectStreamClass) readHandle(unshared); + break; case TC_PROXYCLASSDESC: - return readProxyDesc(unshared); - + descriptor = readProxyDesc(unshared); + break; case TC_CLASSDESC: - return readNonProxyDesc(unshared); - + descriptor = readNonProxyDesc(unshared); + break; default: throw new StreamCorruptedException( String.format("invalid type code: %02X", tc)); } + if (descriptor != null) { + validateDescriptor(descriptor); + } + return descriptor; } private boolean isCustomSubclass() { @@ -1915,6 +1932,8 @@ public class ObjectInputStream if (obj == null || handles.lookupException(passHandle) != null) { defaultReadFields(null, slotDesc); // skip field values } else if (slotDesc.hasReadObjectMethod()) { + ThreadDeath t = null; + boolean reset = false; SerialCallbackContext oldContext = curContext; if (oldContext != null) oldContext.check(); @@ -1933,10 +1952,19 @@ public class ObjectInputStream */ handles.markException(passHandle, ex); } finally { - curContext.setUsed(); - if (oldContext!= null) - oldContext.check(); - curContext = oldContext; + do { + try { + curContext.setUsed(); + if (oldContext!= null) + oldContext.check(); + curContext = oldContext; + reset = true; + } catch (ThreadDeath x) { + t = x; // defer until reset is true + } + } while (!reset); + if (t != null) + throw t; } /* @@ -3647,4 +3675,20 @@ public class ObjectInputStream } } + private void validateDescriptor(ObjectStreamClass descriptor) { + ObjectStreamClassValidator validating = validator; + if (validating != null) { + validating.validateDescriptor(descriptor); + } + } + + // controlled access to ObjectStreamClassValidator + private volatile ObjectStreamClassValidator validator; + + private static void setValidator(ObjectInputStream ois, ObjectStreamClassValidator validator) { + ois.validator = validator; + } + static { + SharedSecrets.setJavaObjectInputStreamAccess(ObjectInputStream::setValidator); + } } diff --git a/jdk/src/java.base/share/classes/java/io/RandomAccessFile.java b/jdk/src/java.base/share/classes/java/io/RandomAccessFile.java index db6ae71f89fa5b5fda31fe6338d6c36f933efcf2..1a8344df88bb2dfb28c3c95268dc89252198bc2f 100644 --- a/jdk/src/java.base/share/classes/java/io/RandomAccessFile.java +++ b/jdk/src/java.base/share/classes/java/io/RandomAccessFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -418,10 +418,11 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable { * read. This method blocks until the requested number of bytes are * read, the end of the stream is detected, or an exception is thrown. * - * @param b the buffer into which the data is read. - * @exception EOFException if this file reaches the end before reading - * all the bytes. - * @exception IOException if an I/O error occurs. + * @param b the buffer into which the data is read. + * @throws NullPointerException if {@code b} is {@code null}. + * @throws EOFException if this file reaches the end before reading + * all the bytes. + * @throws IOException if an I/O error occurs. */ public final void readFully(byte b[]) throws IOException { readFully(b, 0, b.length); @@ -434,12 +435,16 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable { * read. This method blocks until the requested number of bytes are * read, the end of the stream is detected, or an exception is thrown. * - * @param b the buffer into which the data is read. - * @param off the start offset of the data. - * @param len the number of bytes to read. - * @exception EOFException if this file reaches the end before reading - * all the bytes. - * @exception IOException if an I/O error occurs. + * @param b the buffer into which the data is read. + * @param off the start offset into the data array {@code b}. + * @param len the number of bytes to read. + * @throws NullPointerException if {@code b} is {@code null}. + * @throws IndexOutOfBoundsException if {@code off} is negative, + * {@code len} is negative, or {@code len} is greater than + * {@code b.length - off}. + * @throws EOFException if this file reaches the end before reading + * all the bytes. + * @throws IOException if an I/O error occurs. */ public final void readFully(byte b[], int off, int len) throws IOException { int n = 0; diff --git a/jdk/src/java.base/share/classes/java/lang/Boolean.java b/jdk/src/java.base/share/classes/java/lang/Boolean.java index b53995193f12fc98bdfb5222b843da2397523ebc..eeda751719c29f837359fadfcfab40127e82f0fc 100644 --- a/jdk/src/java.base/share/classes/java/lang/Boolean.java +++ b/jdk/src/java.base/share/classes/java/lang/Boolean.java @@ -79,13 +79,16 @@ public final class Boolean implements java.io.Serializable, * Allocates a {@code Boolean} object representing the * {@code value} argument. * - *

Note: It is rarely appropriate to use this constructor. - * Unless a new instance is required, the static factory - * {@link #valueOf(boolean)} is generally a better choice. It is - * likely to yield significantly better space and time performance. - * * @param value the value of the {@code Boolean}. + * + * @deprecated + * It is rarely appropriate to use this constructor. The static factory + * {@link #valueOf(boolean)} is generally a better choice, as it is + * likely to yield significantly better space and time performance. + * Also consider using the final fields {@link #TRUE} and {@link #FALSE} + * if possible. */ + @Deprecated(since="9") public Boolean(boolean value) { this.value = value; } @@ -94,15 +97,18 @@ public final class Boolean implements java.io.Serializable, * Allocates a {@code Boolean} object representing the value * {@code true} if the string argument is not {@code null} * and is equal, ignoring case, to the string {@code "true"}. - * Otherwise, allocate a {@code Boolean} object representing the - * value {@code false}. Examples:

- * {@code new Boolean("True")} produces a {@code Boolean} object - * that represents {@code true}.
- * {@code new Boolean("yes")} produces a {@code Boolean} object - * that represents {@code false}. + * Otherwise, allocates a {@code Boolean} object representing the + * value {@code false}. * * @param s the string to be converted to a {@code Boolean}. + * + * @deprecated + * It is rarely appropriate to use this constructor. + * Use {@link #parseBoolean(String)} to convert a string to a + * {@code boolean} primitive, or use {@link #valueOf(String)} + * to convert a string to a {@code Boolean} object. */ + @Deprecated(since="9") public Boolean(String s) { this(parseBoolean(s)); } diff --git a/jdk/src/java.base/share/classes/java/lang/Byte.java b/jdk/src/java.base/share/classes/java/lang/Byte.java index 51f687cb3894a63daa44b9663161e6b7fc6271c2..877af6895560d71c4f13e4f6365f715c9eb7b0e1 100644 --- a/jdk/src/java.base/share/classes/java/lang/Byte.java +++ b/jdk/src/java.base/share/classes/java/lang/Byte.java @@ -297,7 +297,13 @@ public final class Byte extends Number implements Comparable { * * @param value the value to be represented by the * {@code Byte}. + * + * @deprecated + * It is rarely appropriate to use this constructor. The static factory + * {@link #valueOf(byte)} is generally a better choice, as it is + * likely to yield significantly better space and time performance. */ + @Deprecated(since="9") public Byte(byte value) { this.value = value; } @@ -311,10 +317,16 @@ public final class Byte extends Number implements Comparable { * * @param s the {@code String} to be converted to a * {@code Byte} - * @throws NumberFormatException If the {@code String} + * @throws NumberFormatException if the {@code String} * does not contain a parsable {@code byte}. - * @see java.lang.Byte#parseByte(java.lang.String, int) + * + * @deprecated + * It is rarely appropriate to use this constructor. + * Use {@link #parseByte(String)} to convert a string to a + * {@code byte} primitive, or use {@link #valueOf(String)} + * to convert a string to a {@code Byte} object. */ + @Deprecated(since="9") public Byte(String s) throws NumberFormatException { this.value = parseByte(s, 10); } diff --git a/jdk/src/java.base/share/classes/java/lang/Character.java b/jdk/src/java.base/share/classes/java/lang/Character.java index ea42bfb3d6e0e291e7badb447a873c2f0517100a..9f9e4de1972ce15e4b20b5271659a5e7868feb6e 100644 --- a/jdk/src/java.base/share/classes/java/lang/Character.java +++ b/jdk/src/java.base/share/classes/java/lang/Character.java @@ -1256,14 +1256,14 @@ class Character implements java.io.Serializable, Comparable { new UnicodeBlock("SPECIALS"); /** - * @deprecated As of J2SE 5, use {@link #HIGH_SURROGATES}, - * {@link #HIGH_PRIVATE_USE_SURROGATES}, and - * {@link #LOW_SURROGATES}. These new constants match - * the block definitions of the Unicode Standard. - * The {@link #of(char)} and {@link #of(int)} methods - * return the new constants, not SURROGATES_AREA. - */ - @Deprecated + * @deprecated + * Instead of {@code SURROGATES_AREA}, use {@link #HIGH_SURROGATES}, + * {@link #HIGH_PRIVATE_USE_SURROGATES}, and {@link #LOW_SURROGATES}. + * These constants match the block definitions of the Unicode Standard. + * The {@link #of(char)} and {@link #of(int)} methods return the + * standard constants. + */ + @Deprecated(since="1.5") public static final UnicodeBlock SURROGATES_AREA = new UnicodeBlock("SURROGATES_AREA"); @@ -7451,7 +7451,13 @@ class Character implements java.io.Serializable, Comparable { * * @param value the value to be represented by the * {@code Character} object. + * + * @deprecated + * It is rarely appropriate to use this constructor. The static factory + * {@link #valueOf(char)} is generally a better choice, as it is + * likely to yield significantly better space and time performance. */ + @Deprecated(since="9") public Character(char value) { this.value = value; } @@ -8799,7 +8805,7 @@ class Character implements java.io.Serializable, Comparable { * @since 1.0.2 * @deprecated Replaced by isJavaIdentifierStart(char). */ - @Deprecated + @Deprecated(since="1.1") public static boolean isJavaLetter(char ch) { return isJavaIdentifierStart(ch); } @@ -8835,7 +8841,7 @@ class Character implements java.io.Serializable, Comparable { * @since 1.0.2 * @deprecated Replaced by isJavaIdentifierPart(char). */ - @Deprecated + @Deprecated(since="1.1") public static boolean isJavaLetterOrDigit(char ch) { return isJavaIdentifierPart(ch); } @@ -9580,7 +9586,7 @@ class Character implements java.io.Serializable, Comparable { * @see Character#isWhitespace(char) * @deprecated Replaced by isWhitespace(char). */ - @Deprecated + @Deprecated(since="1.1") public static boolean isSpace(char ch) { return (ch <= 0x0020) && (((((1L << 0x0009) | diff --git a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java index 33e5105bb3da8c8983de64f7d6fd9c77e44c5c6e..61123302a3c3a56affb70267a4283cff3153d29c 100644 --- a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java +++ b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java @@ -727,7 +727,7 @@ public abstract class ClassLoader { * @deprecated Replaced by {@link #defineClass(String, byte[], int, int) * defineClass(String, byte[], int, int)} */ - @Deprecated + @Deprecated(since="1.1") protected final Class defineClass(byte[] b, int off, int len) throws ClassFormatError { @@ -817,6 +817,9 @@ public abstract class ClassLoader { if (!checkName(name)) throw new NoClassDefFoundError("IllegalName: " + name); + // Note: Checking logic in java.lang.invoke.MemberName.checkForTypeAlias + // relies on the fact that spoofing is impossible if a class has a name + // of the form "java.*" if ((name != null) && name.startsWith("java.") && this != getBuiltinPlatformClassLoader()) { throw new SecurityException @@ -2012,7 +2015,7 @@ public abstract class ClassLoader { * * @since 1.2 */ - @Deprecated + @Deprecated(since="9") protected Package getPackage(String name) { Package pkg = getDefinedPackage(name); if (pkg == null) { diff --git a/jdk/src/java.base/share/classes/java/lang/Double.java b/jdk/src/java.base/share/classes/java/lang/Double.java index 473b86dd90905c6ca9c718c99696beb9310389d3..75a227e5282a717af777de1d078f559f51f3e0ac 100644 --- a/jdk/src/java.base/share/classes/java/lang/Double.java +++ b/jdk/src/java.base/share/classes/java/lang/Double.java @@ -589,7 +589,13 @@ public final class Double extends Number implements Comparable { * represents the primitive {@code double} argument. * * @param value the value to be represented by the {@code Double}. + * + * @deprecated + * It is rarely appropriate to use this constructor. The static factory + * {@link #valueOf(double)} is generally a better choice, as it is + * likely to yield significantly better space and time performance. */ + @Deprecated(since="9") public Double(double value) { this.value = value; } @@ -601,10 +607,16 @@ public final class Double extends Number implements Comparable { * {@code double} value as if by the {@code valueOf} method. * * @param s a string to be converted to a {@code Double}. - * @throws NumberFormatException if the string does not contain a + * @throws NumberFormatException if the string does not contain a * parsable number. - * @see java.lang.Double#valueOf(java.lang.String) + * + * @deprecated + * It is rarely appropriate to use this constructor. + * Use {@link #parseDouble(String)} to convert a string to a + * {@code double} primitive, or use {@link #valueOf(String)} + * to convert a string to a {@code Double} object. */ + @Deprecated(since="9") public Double(String s) throws NumberFormatException { value = parseDouble(s); } diff --git a/jdk/src/java.base/share/classes/java/lang/Float.java b/jdk/src/java.base/share/classes/java/lang/Float.java index 334d3d033dab4879bfae9b59cfc37b570f3280c5..60e08db7ad5976d3868cae268560a3e6d52fc025 100644 --- a/jdk/src/java.base/share/classes/java/lang/Float.java +++ b/jdk/src/java.base/share/classes/java/lang/Float.java @@ -502,7 +502,13 @@ public final class Float extends Number implements Comparable { * represents the primitive {@code float} argument. * * @param value the value to be represented by the {@code Float}. + * + * @deprecated + * It is rarely appropriate to use this constructor. The static factory + * {@link #valueOf(float)} is generally a better choice, as it is + * likely to yield significantly better space and time performance. */ + @Deprecated(since="9") public Float(float value) { this.value = value; } @@ -512,7 +518,13 @@ public final class Float extends Number implements Comparable { * represents the argument converted to type {@code float}. * * @param value the value to be represented by the {@code Float}. + * + * @deprecated + * It is rarely appropriate to use this constructor. Instead, use the + * static factory method {@link #valueOf(float)} method as follows: + * {@code Float.valueOf((float)value)}. */ + @Deprecated(since="9") public Float(double value) { this.value = (float)value; } @@ -523,11 +535,17 @@ public final class Float extends Number implements Comparable { * represented by the string. The string is converted to a * {@code float} value as if by the {@code valueOf} method. * - * @param s a string to be converted to a {@code Float}. - * @throws NumberFormatException if the string does not contain a - * parsable number. - * @see java.lang.Float#valueOf(java.lang.String) + * @param s a string to be converted to a {@code Float}. + * @throws NumberFormatException if the string does not contain a + * parsable number. + * + * @deprecated + * It is rarely appropriate to use this constructor. + * Use {@link #parseFloat(String)} to convert a string to a + * {@code float} primitive, or use {@link #valueOf(String)} + * to convert a string to a {@code Float} object. */ + @Deprecated(since="9") public Float(String s) throws NumberFormatException { value = parseFloat(s); } diff --git a/jdk/src/java.base/share/classes/java/lang/Integer.java b/jdk/src/java.base/share/classes/java/lang/Integer.java index 2a846c4d07f0f6cd85c36ef9a3d819f4e862f9db..7765d784e079800304d3a52cb515ff24227ac446 100644 --- a/jdk/src/java.base/share/classes/java/lang/Integer.java +++ b/jdk/src/java.base/share/classes/java/lang/Integer.java @@ -1106,7 +1106,13 @@ public final class Integer extends Number implements Comparable { * * @param value the value to be represented by the * {@code Integer} object. + * + * @deprecated + * It is rarely appropriate to use this constructor. The static factory + * {@link #valueOf(int)} is generally a better choice, as it is + * likely to yield significantly better space and time performance. */ + @Deprecated(since="9") public Integer(int value) { this.value = value; } @@ -1118,12 +1124,17 @@ public final class Integer extends Number implements Comparable { * {@code int} value in exactly the manner used by the * {@code parseInt} method for radix 10. * - * @param s the {@code String} to be converted to an - * {@code Integer}. - * @exception NumberFormatException if the {@code String} does not - * contain a parsable integer. - * @see java.lang.Integer#parseInt(java.lang.String, int) + * @param s the {@code String} to be converted to an {@code Integer}. + * @throws NumberFormatException if the {@code String} does not + * contain a parsable integer. + * + * @deprecated + * It is rarely appropriate to use this constructor. + * Use {@link #parseInt(String)} to convert a string to a + * {@code int} primitive, or use {@link #valueOf(String)} + * to convert a string to an {@code Integer} object. */ + @Deprecated(since="9") public Integer(String s) throws NumberFormatException { this.value = parseInt(s, 10); } diff --git a/jdk/src/java.base/share/classes/java/lang/Long.java b/jdk/src/java.base/share/classes/java/lang/Long.java index ae93a7ca8278d7368d4a044d19f84bb212336701..793d15e53b214b93c4d9e9aaf8cf494cd7e39676 100644 --- a/jdk/src/java.base/share/classes/java/lang/Long.java +++ b/jdk/src/java.base/share/classes/java/lang/Long.java @@ -1340,7 +1340,13 @@ public final class Long extends Number implements Comparable { * * @param value the value to be represented by the * {@code Long} object. + * + * @deprecated + * It is rarely appropriate to use this constructor. The static factory + * {@link #valueOf(long)} is generally a better choice, as it is + * likely to yield significantly better space and time performance. */ + @Deprecated(since="9") public Long(long value) { this.value = value; } @@ -1356,8 +1362,14 @@ public final class Long extends Number implements Comparable { * {@code Long}. * @throws NumberFormatException if the {@code String} does not * contain a parsable {@code long}. - * @see java.lang.Long#parseLong(java.lang.String, int) + * + * @deprecated + * It is rarely appropriate to use this constructor. + * Use {@link #parseLong(String)} to convert a string to a + * {@code long} primitive, or use {@link #valueOf(String)} + * to convert a string to a {@code Long} object. */ + @Deprecated(since="9") public Long(String s) throws NumberFormatException { this.value = parseLong(s, 10); } diff --git a/jdk/src/java.base/share/classes/java/lang/Package.java b/jdk/src/java.base/share/classes/java/lang/Package.java index 3b328ca199f5cb055af13e0919cba05a7f53533b..1aa9e98fbf25286fc2234bc4bf39a86bca8218d4 100644 --- a/jdk/src/java.base/share/classes/java/lang/Package.java +++ b/jdk/src/java.base/share/classes/java/lang/Package.java @@ -333,7 +333,7 @@ public class Package extends NamedPackage implements java.lang.reflect.Annotated * @see ClassLoader#getDefinedPackage */ @CallerSensitive - @Deprecated + @Deprecated(since="9") @SuppressWarnings("deprecation") public static Package getPackage(String name) { ClassLoader l = ClassLoader.getClassLoader(Reflection.getCallerClass()); diff --git a/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java b/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java index ebd47fcfe87ddaf5e80c3ddeaec7dab4d21ab4e3..638be0e9f7207adffb9c84f334123f5bab931016 100644 --- a/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java +++ b/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java @@ -30,13 +30,12 @@ import java.io.FileDescriptor; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.nio.channels.Pipe; import java.util.Arrays; import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.security.AccessController; -import java.security.PrivilegedAction; +import sun.security.action.GetPropertyAction; + /** * This class is used to create operating system processes. * @@ -468,11 +467,9 @@ public final class ProcessBuilder * @since 1.7 */ public abstract static class Redirect { - private static final File NULL_FILE = AccessController.doPrivileged( - (PrivilegedAction) () -> { - return new File((System.getProperty("os.name") - .startsWith("Windows") ? "NUL" : "/dev/null")); - } + private static final File NULL_FILE = new File( + (GetPropertyAction.getProperty("os.name") + .startsWith("Windows") ? "NUL" : "/dev/null") ); /** diff --git a/jdk/src/java.base/share/classes/java/lang/Runtime.java b/jdk/src/java.base/share/classes/java/lang/Runtime.java index 64b22de4bd678da7091ffbd60273d561d9b0cf78..3c73d5b61a3e44f18e0ebbe44382f598bd83cf84 100644 --- a/jdk/src/java.base/share/classes/java/lang/Runtime.java +++ b/jdk/src/java.base/share/classes/java/lang/Runtime.java @@ -289,6 +289,7 @@ public class Runtime { * finalizers being called on live objects while other threads are * concurrently manipulating those objects, resulting in erratic * behavior or deadlock. + * This method is subject to removal in a future version of Java SE. * * @throws SecurityException * if a security manager exists and its {@code checkExit} @@ -299,7 +300,7 @@ public class Runtime { * @see java.lang.SecurityManager#checkExit(int) * @since 1.1 */ - @Deprecated + @Deprecated(since="1.2", forRemoval=true) public static void runFinalizersOnExit(boolean value) { SecurityManager security = System.getSecurityManager(); if (security != null) { @@ -717,41 +718,27 @@ public class Runtime { } /** - * Enables/Disables tracing of instructions. - * If the {@code boolean} argument is {@code true}, this - * method suggests that the Java virtual machine emit debugging - * information for each instruction in the virtual machine as it - * is executed. The format of this information, and the file or other - * output stream to which it is emitted, depends on the host environment. - * The virtual machine may ignore this request if it does not support - * this feature. The destination of the trace output is system - * dependent. - *

- * If the {@code boolean} argument is {@code false}, this - * method causes the virtual machine to stop performing the - * detailed instruction trace it is performing. + * Not implemented, does nothing. + * + * @deprecated + * This method was intended to control instruction tracing. + * It has been superseded by JVM-specific tracing mechanisms. * - * @param on {@code true} to enable instruction tracing; - * {@code false} to disable this feature. + * @param on ignored */ + @Deprecated(since="9", forRemoval=true) public void traceInstructions(boolean on) { } /** - * Enables/Disables tracing of method calls. - * If the {@code boolean} argument is {@code true}, this - * method suggests that the Java virtual machine emit debugging - * information for each method in the virtual machine as it is - * called. The format of this information, and the file or other output - * stream to which it is emitted, depends on the host environment. The - * virtual machine may ignore this request if it does not support - * this feature. - *

- * Calling this method with argument false suggests that the - * virtual machine cease emitting per-call debugging information. + * Not implemented, does nothing. + * + * @deprecated + * This method was intended to control method call tracing. + * It has been superseded by JVM-specific tracing mechanisms. * - * @param on {@code true} to enable instruction tracing; - * {@code false} to disable this feature. + * @param on ignored */ + @Deprecated(since="9", forRemoval=true) public void traceMethodCalls(boolean on) { } /** @@ -894,8 +881,9 @@ public class Runtime { * stream in the local encoding into a character stream in Unicode is via * the {@code InputStreamReader} and {@code BufferedReader} * classes. + * This method is subject to removal in a future version of Java SE. */ - @Deprecated + @Deprecated(since="1.1", forRemoval=true) public InputStream getLocalizedInputStream(InputStream in) { return in; } @@ -915,6 +903,7 @@ public class Runtime { * Unicode character stream into a byte stream in the local encoding is via * the {@code OutputStreamWriter}, {@code BufferedWriter}, and * {@code PrintWriter} classes. + * This method is subject to removal in a future version of Java SE. * * @param out OutputStream to localize * @return a localized output stream @@ -923,7 +912,7 @@ public class Runtime { * @see java.io.OutputStreamWriter#OutputStreamWriter(java.io.OutputStream) * @see java.io.PrintWriter#PrintWriter(java.io.OutputStream) */ - @Deprecated + @Deprecated(since="1.1", forRemoval=true) public OutputStream getLocalizedOutputStream(OutputStream out) { return out; } diff --git a/jdk/src/java.base/share/classes/java/lang/SecurityManager.java b/jdk/src/java.base/share/classes/java/lang/SecurityManager.java index 8ea8f09d1035bbab0688c9044dfdb8ee86678d80..e88a5eaa181f849160f566b38f20506c5ed57071 100644 --- a/jdk/src/java.base/share/classes/java/lang/SecurityManager.java +++ b/jdk/src/java.base/share/classes/java/lang/SecurityManager.java @@ -229,7 +229,7 @@ class SecurityManager { * It is recommended that the checkPermission * call be used instead. */ - @Deprecated + @Deprecated(since="1.2") protected boolean inCheck; /* @@ -262,7 +262,7 @@ class SecurityManager { * It is recommended that the checkPermission * call be used instead. */ - @Deprecated + @Deprecated(since="1.2") public boolean getInCheck() { return inCheck; } @@ -345,7 +345,7 @@ class SecurityManager { * @see java.lang.ClassLoader#getSystemClassLoader() getSystemClassLoader * @see #checkPermission(java.security.Permission) checkPermission */ - @Deprecated + @Deprecated(since="1.2") protected ClassLoader currentClassLoader() { ClassLoader cl = currentClassLoader0(); if ((cl != null) && hasAllPermission()) @@ -391,7 +391,7 @@ class SecurityManager { * @see java.lang.ClassLoader#getSystemClassLoader() getSystemClassLoader * @see #checkPermission(java.security.Permission) checkPermission */ - @Deprecated + @Deprecated(since="1.2") protected Class currentLoadedClass() { Class c = currentLoadedClass0(); if ((c != null) && hasAllPermission()) @@ -411,7 +411,7 @@ class SecurityManager { * call be used instead. * */ - @Deprecated + @Deprecated(since="1.2") protected native int classDepth(String name); /** @@ -449,7 +449,7 @@ class SecurityManager { * @see java.lang.ClassLoader#getSystemClassLoader() getSystemClassLoader * @see #checkPermission(java.security.Permission) checkPermission */ - @Deprecated + @Deprecated(since="1.2") protected int classLoaderDepth() { int depth = classLoaderDepth0(); if (depth != -1) { @@ -474,7 +474,7 @@ class SecurityManager { * It is recommended that the checkPermission * call be used instead. */ - @Deprecated + @Deprecated(since="1.2") protected boolean inClass(String name) { return classDepth(name) >= 0; } @@ -491,7 +491,7 @@ class SecurityManager { * call be used instead. * @see #currentClassLoader() currentClassLoader */ - @Deprecated + @Deprecated(since="1.2") protected boolean inClassLoader() { return currentClassLoader() != null; } @@ -1217,7 +1217,7 @@ class SecurityManager { * @deprecated Use #checkPermission(java.security.Permission) instead * @see #checkPermission(java.security.Permission) checkPermission */ - @Deprecated + @Deprecated(since="1.4") public void checkMulticast(InetAddress maddr, byte ttl) { String host = maddr.getHostAddress(); if (!host.startsWith("[") && host.indexOf(':') != -1) { @@ -1297,9 +1297,10 @@ class SecurityManager { * was trusted to bring up a top-level window. The method has been * obsoleted and code should instead use {@link #checkPermission} * to check {@code AWTPermission("showWindowWithoutWarningBanner")}. + * This method is subject to removal in a future version of Java SE. * @see #checkPermission(java.security.Permission) checkPermission */ - @Deprecated + @Deprecated(since="1.8", forRemoval=true) public boolean checkTopLevelWindow(Object window) { if (window == null) { throw new NullPointerException("window can't be null"); @@ -1340,9 +1341,10 @@ class SecurityManager { * thread could access the system clipboard. The method has been * obsoleted and code should instead use {@link #checkPermission} * to check {@code AWTPermission("accessClipboard")}. + * This method is subject to removal in a future version of Java SE. * @see #checkPermission(java.security.Permission) checkPermission */ - @Deprecated + @Deprecated(since="1.8", forRemoval=true) public void checkSystemClipboardAccess() { checkPermission(SecurityConstants.ALL_PERMISSION); } @@ -1358,9 +1360,10 @@ class SecurityManager { * thread could access the AWT event queue. The method has been * obsoleted and code should instead use {@link #checkPermission} * to check {@code AWTPermission("accessEventQueue")}. + * This method is subject to removal in a future version of Java SE. * @see #checkPermission(java.security.Permission) checkPermission */ - @Deprecated + @Deprecated(since="1.8", forRemoval=true) public void checkAwtEventQueueAccess() { checkPermission(SecurityConstants.ALL_PERMISSION); } @@ -1626,12 +1629,13 @@ class SecurityManager { * Users of this method should instead invoke {@link #checkPermission} * directly. This method will be changed in a future release * to check the permission {@code java.security.AllPermission}. + * This method is subject to removal in a future version of Java SE. * * @see java.lang.reflect.Member * @since 1.1 * @see #checkPermission(java.security.Permission) checkPermission */ - @Deprecated + @Deprecated(since="1.8", forRemoval=true) @CallerSensitive public void checkMemberAccess(Class clazz, int which) { if (clazz == null) { diff --git a/jdk/src/java.base/share/classes/java/lang/Short.java b/jdk/src/java.base/share/classes/java/lang/Short.java index 9fa79f3d8c222b2e80f6633b63f3d61408399885..57b291fc03a35f30e9cbe1b7abcf5c1f4b87e937 100644 --- a/jdk/src/java.base/share/classes/java/lang/Short.java +++ b/jdk/src/java.base/share/classes/java/lang/Short.java @@ -302,7 +302,13 @@ public final class Short extends Number implements Comparable { * * @param value the value to be represented by the * {@code Short}. + * + * @deprecated + * It is rarely appropriate to use this constructor. The static factory + * {@link #valueOf(short)} is generally a better choice, as it is + * likely to yield significantly better space and time performance. */ + @Deprecated(since="9") public Short(short value) { this.value = value; } @@ -318,8 +324,14 @@ public final class Short extends Number implements Comparable { * {@code Short} * @throws NumberFormatException If the {@code String} * does not contain a parsable {@code short}. - * @see java.lang.Short#parseShort(java.lang.String, int) + * + * @deprecated + * It is rarely appropriate to use this constructor. + * Use {@link #parseShort(String)} to convert a string to a + * {@code short} primitive, or use {@link #valueOf(String)} + * to convert a string to a {@code Short} object. */ + @Deprecated(since="9") public Short(String s) throws NumberFormatException { this.value = parseShort(s, 10); } diff --git a/jdk/src/java.base/share/classes/java/lang/StackFrameInfo.java b/jdk/src/java.base/share/classes/java/lang/StackFrameInfo.java index 0750af15b03137d084ea0ac0a1e7968809c7be93..187a737d7c4de47646f234bcc45c627668b91ac7 100644 --- a/jdk/src/java.base/share/classes/java/lang/StackFrameInfo.java +++ b/jdk/src/java.base/share/classes/java/lang/StackFrameInfo.java @@ -37,24 +37,14 @@ class StackFrameInfo implements StackFrame { private final static JavaLangInvokeAccess jlInvokeAccess = SharedSecrets.getJavaLangInvokeAccess(); - // -XX:+MemberNameInStackFrame will initialize MemberName and all other fields; - // otherwise, VM will set the hidden fields (injected by the VM). - // -XX:+MemberNameInStackFrame is temporary to enable performance measurement - // - // Footprint improvement: MemberName::clazz and MemberName::name - // can replace StackFrameInfo::declaringClass and StackFrameInfo::methodName - // Currently VM sets StackFrameInfo::methodName instead of expanding MemberName::name + // Footprint improvement: MemberName::clazz can replace + // StackFrameInfo::declaringClass. final StackWalker walker; final Class declaringClass; final Object memberName; - final int bci; - - // methodName, fileName, and lineNumber will be lazily set by the VM - // when first requested. - private String methodName; - private String fileName = null; // default for unavailable filename - private int lineNumber = -1; // default for unavailable lineNumber + final short bci; + private volatile StackTraceElement ste; /* * Create StackFrameInfo for StackFrameTraverser and LiveStackFrameTraverser @@ -78,77 +68,53 @@ class StackFrameInfo implements StackFrame { return declaringClass; } - // Call the VM to set methodName, lineNumber, and fileName - private synchronized void ensureMethodInfoInitialized() { - if (methodName == null) { - setMethodInfo(); - } - } - @Override public String getMethodName() { - ensureMethodInfoInitialized(); - return methodName; + return jlInvokeAccess.getName(memberName); } @Override - public Optional getFileName() { - ensureMethodInfoInitialized(); - return fileName != null ? Optional.of(fileName) : Optional.empty(); + public final Optional getFileName() { + StackTraceElement ste = toStackTraceElement(); + return ste.getFileName() != null ? Optional.of(ste.getFileName()) : Optional.empty(); } @Override - public OptionalInt getLineNumber() { - ensureMethodInfoInitialized(); - return lineNumber > 0 ? OptionalInt.of(lineNumber) : OptionalInt.empty(); + public final OptionalInt getLineNumber() { + StackTraceElement ste = toStackTraceElement(); + return ste.getLineNumber() > 0 ? OptionalInt.of(ste.getLineNumber()) : OptionalInt.empty(); } @Override - public boolean isNativeMethod() { - ensureMethodInfoInitialized(); - return lineNumber == -2; + public final boolean isNativeMethod() { + StackTraceElement ste = toStackTraceElement(); + return ste.isNativeMethod(); } @Override public String toString() { - ensureMethodInfoInitialized(); - // similar format as StackTraceElement::toString - if (isNativeMethod()) { - return getClassName() + "." + getMethodName() + "(Native Method)"; - } else { - // avoid allocating Optional objects - return getClassName() + "." + getMethodName() + - "(" + (fileName != null ? fileName : "Unknown Source") + - (lineNumber > 0 ? ":" + lineNumber : " bci:" + bci) + ")"; - } + StackTraceElement ste = toStackTraceElement(); + return ste.toString(); } /** - * Lazily initialize method name, file name, line number + * Fill in the fields of the given StackTraceElement */ - private native void setMethodInfo(); - - /** - * Fill in source file name and line number of the given StackFrame array. - */ - static native void fillInStackFrames(int startIndex, - Object[] stackframes, - int fromIndex, int toIndex); + private native void toStackTraceElement0(StackTraceElement ste); @Override public StackTraceElement toStackTraceElement() { - ensureMethodInfoInitialized(); - - Module module = declaringClass.getModule(); - String moduleName = module.isNamed() ? module.getName() : null; - String moduleVersion = null; - if (module.isNamed() && module.getDescriptor().version().isPresent()) { - moduleVersion = module.getDescriptor().version().get().toString(); + StackTraceElement s = ste; + if (s == null) { + synchronized (this) { + s = ste; + if (s == null) { + s = new StackTraceElement(); + toStackTraceElement0(s); + ste = s; + } + } } - return new StackTraceElement(moduleName, moduleVersion, - getClassName(), getMethodName(), - fileName, - lineNumber); + return s; } - } diff --git a/jdk/src/java.base/share/classes/java/lang/StackStreamFactory.java b/jdk/src/java.base/share/classes/java/lang/StackStreamFactory.java index 2c59b5b60fd9f614b332cf53ecf9a87b7402579f..73446062bea4b71540dc370bbff1724afe6376cf 100644 --- a/jdk/src/java.base/share/classes/java/lang/StackStreamFactory.java +++ b/jdk/src/java.base/share/classes/java/lang/StackStreamFactory.java @@ -24,29 +24,22 @@ */ package java.lang; -import jdk.internal.misc.VM; import jdk.internal.reflect.MethodAccessor; - -import java.io.PrintStream; import java.lang.StackWalker.Option; import java.lang.StackWalker.StackFrame; import java.lang.annotation.Native; import java.lang.reflect.Method; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.Arrays; -import java.util.EnumSet; import java.util.HashSet; import java.util.NoSuchElementException; import java.util.Objects; -import java.util.Optional; import java.util.Set; import java.util.Spliterator; import java.util.function.Consumer; import java.util.function.Function; import java.util.stream.Stream; import java.util.stream.StreamSupport; +import sun.security.action.GetPropertyAction; import static java.lang.StackStreamFactory.WalkerState.*; @@ -61,8 +54,7 @@ import static java.lang.StackStreamFactory.WalkerState.*; * to avoid overhead of Stream/Lambda * 1. Support traversing Stream * 2. StackWalker::getCallerClass - * 3. Throwable::init and Throwable::getStackTrace - * 4. AccessControlContext getting ProtectionDomain + * 3. AccessControlContext getting ProtectionDomain */ final class StackStreamFactory { private StackStreamFactory() {} @@ -79,25 +71,22 @@ final class StackStreamFactory { // These flags must match the values maintained in the VM @Native private static final int DEFAULT_MODE = 0x0; @Native private static final int FILL_CLASS_REFS_ONLY = 0x2; - @Native private static final int FILTER_FILL_IN_STACKTRACE = 0x10; @Native private static final int SHOW_HIDDEN_FRAMES = 0x20; // LambdaForms are hidden by the VM @Native private static final int FILL_LIVE_STACK_FRAMES = 0x100; - /* * For Throwable to use StackWalker, set useNewThrowable to true. * Performance work and extensive testing is needed to replace the * VM built-in backtrace filled in Throwable with the StackWalker. */ - final static boolean useNewThrowable = getProperty("stackwalk.newThrowable", false); final static boolean isDebug = getProperty("stackwalk.debug", false); static StackFrameTraverser makeStackTraverser(StackWalker walker, Function, ? extends T> function) { if (walker.hasLocalsOperandsOption()) - return new LiveStackInfoTraverser(walker, function); + return new LiveStackInfoTraverser<>(walker, function); else - return new StackFrameTraverser(walker, function); + return new StackFrameTraverser<>(walker, function); } /** @@ -107,40 +96,31 @@ final class StackStreamFactory { return new CallerClassFinder(walker); } - static boolean useStackTrace(Throwable t) { - if (t instanceof VirtualMachineError) - return false; - - return VM.isBooted() && StackStreamFactory.useNewThrowable; - } - - /* - * This should only be used by Throwable::. - */ - static StackTrace makeStackTrace(Throwable ex) { - return StackTrace.dump(ex); - } - - /* - * This creates StackTrace for Thread::dumpThread to use. - */ - static StackTrace makeStackTrace() { - return StackTrace.dump(); - } - enum WalkerState { NEW, // the stream is new and stack walking has not started OPEN, // the stream is open when it is being traversed. CLOSED; // the stream is closed when the stack walking is done } - static abstract class AbstractStackWalker { + /** + * Subclass of AbstractStackWalker implements a specific stack walking logic. + * It needs to set up the frame buffer and stack walking mode. + * + * It initiates the VM stack walking via the callStackWalk method that serves + * as the anchored frame and VM will call up to AbstractStackWalker::doStackWalk. + * + * @param the type of the result returned from stack walking + * @param the type of the data gathered for each frame. + * For example, StackFrameInfo for StackWalker::walk or + * Class for StackWalker::getCallerClass + */ + static abstract class AbstractStackWalker { protected final StackWalker walker; protected final Thread thread; protected final int maxDepth; protected final long mode; - protected int depth; // traversed stack depth - protected FrameBuffer frameBuffer; // buffer for VM to fill in + protected int depth; // traversed stack depth + protected FrameBuffer frameBuffer; protected long anchor; // buffers to fill in stack frame information @@ -158,16 +138,13 @@ final class StackStreamFactory { private int toStackWalkMode(StackWalker walker, int mode) { int newMode = mode; if (walker.hasOption(Option.SHOW_HIDDEN_FRAMES) && - !fillCallerClassOnly(newMode) /* don't show hidden frames for getCallerClass */) + (mode & FILL_CLASS_REFS_ONLY) != FILL_CLASS_REFS_ONLY) newMode |= SHOW_HIDDEN_FRAMES; if (walker.hasLocalsOperandsOption()) newMode |= FILL_LIVE_STACK_FRAMES; return newMode; } - private boolean fillCallerClassOnly(int mode) { - return (mode|FILL_CLASS_REFS_ONLY) != FILL_CLASS_REFS_ONLY; - } /** * A callback method to consume the stack frames. This method is invoked * once stack walking begins (i.e. it is only invoked when walkFrames is called). @@ -180,7 +157,7 @@ final class StackStreamFactory { * * @return the number of consumed frames */ - protected abstract T consumeFrames(); + protected abstract R consumeFrames(); /** * Initialize FrameBuffer. Subclass should implement this method to @@ -253,7 +230,7 @@ final class StackStreamFactory { * Walks stack frames until {@link #consumeFrames} is done consuming * the frames it is interested in. */ - final T walk() { + final R walk() { checkState(NEW); try { // VM will need to stablize the stack before walking. It will invoke @@ -319,7 +296,7 @@ final class StackStreamFactory { } this.anchor = anchor; // set anchor for this bulk stack frame traversal - frameBuffer.setBatch(bufStartIndex, bufEndIndex); + frameBuffer.setBatch(depth, bufStartIndex, bufEndIndex); // traverse all frames and perform the action on the stack frames, if specified return consumeFrames(); @@ -382,15 +359,14 @@ final class StackStreamFactory { * If all fetched stack frames are traversed, AbstractStackWalker::fetchStackFrames will * fetch the next batch of stack frames to continue. */ - private T beginStackWalk() { + private R beginStackWalk() { // initialize buffers for VM to fill the stack frame info initFrameBuffer(); return callStackWalk(mode, 0, frameBuffer.curBatchFrameCount(), frameBuffer.startIndex(), - frameBuffer.classes, - frameBuffer.stackFrames); + frameBuffer.frames()); } /* @@ -405,8 +381,7 @@ final class StackStreamFactory { int endIndex = fetchStackFrames(mode, anchor, batchSize, startIndex, - frameBuffer.classes, - frameBuffer.stackFrames); + frameBuffer.frames()); if (isDebug) { System.out.format(" more stack walk requesting %d got %d to %d frames%n", batchSize, frameBuffer.startIndex(), endIndex); @@ -415,27 +390,26 @@ final class StackStreamFactory { if (numFrames == 0) { frameBuffer.freeze(); // done stack walking } else { - frameBuffer.setBatch(startIndex, endIndex); + frameBuffer.setBatch(depth, startIndex, endIndex); } return numFrames; } /** * Begins stack walking. This method anchors this frame and invokes - * AbstractStackWalker::doStackWalk after fetching the firt batch of stack frames. + * AbstractStackWalker::doStackWalk after fetching the first batch of stack frames. * * @param mode mode of stack walking * @param skipframes number of frames to be skipped before filling the frame buffer. * @param batchSize the batch size, max. number of elements to be filled in the frame buffers. * @param startIndex start index of the frame buffers to be filled. - * @param classes Classes buffer of the stack frames - * @param frames StackFrame buffer, or null + * @param frames Either a Class array, if mode is {@link #FILL_CLASS_REFS_ONLY} + * or a {@link StackFrameInfo} (or derivative) array otherwise. * @return Result of AbstractStackWalker::doStackWalk */ - private native T callStackWalk(long mode, int skipframes, + private native R callStackWalk(long mode, int skipframes, int batchSize, int startIndex, - Class[] classes, - StackFrame[] frames); + T[] frames); /** * Fetch the next batch of stack frames. @@ -444,185 +418,14 @@ final class StackStreamFactory { * @param anchor * @param batchSize the batch size, max. number of elements to be filled in the frame buffers. * @param startIndex start index of the frame buffers to be filled. - * @param classes Classes buffer of the stack frames - * @param frames StackFrame buffer, or null + * @param frames Either a Class array, if mode is {@link #FILL_CLASS_REFS_ONLY} + * or a {@link StackFrameInfo} (or derivative) array otherwise. * * @return the end index to the frame buffers */ private native int fetchStackFrames(long mode, long anchor, int batchSize, int startIndex, - Class[] classes, - StackFrame[] frames); - - - /* - * Frame buffer - * - * Each specialized AbstractStackWalker subclass may subclass the FrameBuffer. - */ - class FrameBuffer { - static final int START_POS = 2; // 0th and 1st elements are reserved - - // buffers for VM to fill stack frame info - int currentBatchSize; // current batch size - Class[] classes; // caller class for fast path - - StackFrame[] stackFrames; - - int origin; // index to the current traversed stack frame - int fence; // index to the last frame in the current batch - - FrameBuffer(int initialBatchSize) { - if (initialBatchSize < MIN_BATCH_SIZE) { - throw new IllegalArgumentException(initialBatchSize + " < minimum batch size: " + MIN_BATCH_SIZE); - } - this.origin = START_POS; - this.fence = 0; - this.currentBatchSize = initialBatchSize; - this.classes = new Class[currentBatchSize]; - } - - int curBatchFrameCount() { - return currentBatchSize-START_POS; - } - - /* - * Tests if this frame buffer is empty. All frames are fetched. - */ - final boolean isEmpty() { - return origin >= fence || (origin == START_POS && fence == 0); - } - - /* - * Freezes this frame buffer. The stack stream source is done fetching. - */ - final void freeze() { - origin = 0; - fence = 0; - } - - /* - * Tests if this frame buffer is active. It is inactive when - * it is done for traversal. All stack frames have been traversed. - */ - final boolean isActive() { - return origin > 0 && (fence == 0 || origin < fence || fence == currentBatchSize); - } - - /** - * Gets the class at the current frame and move to the next frame. - */ - final Class next() { - if (isEmpty()) { - throw new NoSuchElementException("origin=" + origin + " fence=" + fence); - } - Class c = classes[origin++]; - if (isDebug) { - int index = origin-1; - System.out.format(" next frame at %d: %s (origin %d fence %d)%n", index, - Objects.toString(c), index, fence); - } - return c; - } - - /** - * Gets the class at the current frame. - */ - final Class get() { - if (isEmpty()) { - throw new NoSuchElementException("origin=" + origin + " fence=" + fence); - } - return classes[origin]; - } - - /* - * Returns the index of the current frame. - */ - final int getIndex() { - return origin; - } - - /* - * Set the start and end index of a new batch of stack frames that have - * been filled in this frame buffer. - */ - final void setBatch(int startIndex, int endIndex) { - if (startIndex <= 0 || endIndex <= 0) - throw new IllegalArgumentException("startIndex=" + startIndex + " endIndex=" + endIndex); - - this.origin = startIndex; - this.fence = endIndex; - if (depth == 0 && fence > 0) { - // filter the frames due to the stack stream implementation - for (int i = START_POS; i < fence; i++) { - Class c = classes[i]; - if (isDebug) System.err.format(" frame %d: %s%n", i, c); - if (filterStackWalkImpl(c)) { - origin++; - } else { - break; - } - } - } - } - - /* - * Checks if the origin is the expected start index. - */ - final void check(int skipFrames) { - int index = skipFrames + START_POS; - if (origin != index) { - // stack walk must continue with the previous frame depth - throw new IllegalStateException("origin " + origin + " != " + index); - } - } - - // ------ subclass may override the following methods ------- - /** - * Resizes the buffers for VM to fill in the next batch of stack frames. - * The next batch will start at the given startIndex with the maximum number - * of elements. - * - *

Subclass may override this method to manage the allocated buffers. - * - * @param startIndex the start index for the first frame of the next batch to fill in. - * @param elements the number of elements for the next batch to fill in. - * - */ - void resize(int startIndex, int elements) { - if (!isActive()) - throw new IllegalStateException("inactive frame buffer can't be resized"); - - int size = startIndex+elements; - if (classes.length < size) { - // copy the elements in classes array to the newly allocated one. - // classes[0] is a Thread object - Class[] prev = classes; - classes = new Class[size]; - System.arraycopy(prev, 0, classes, 0, START_POS); - } - currentBatchSize = size; - } - - /* - * Returns the start index for this frame buffer is refilled. - * - * This implementation reuses the allocated buffer for the next batch - * of stack frames. For subclass to retain the fetched stack frames, - * it should override this method to return the index at which the frame - * should be filled in for the next batch. - */ - int startIndex() { - return START_POS; - } - - /** - * Returns next StackFrame object in the current batch of stack frames - */ - StackFrame nextStackFrame() { - throw new InternalError("should not reach here"); - } - } + T[] frames); } /* @@ -630,46 +433,66 @@ final class StackStreamFactory { * * This class implements Spliterator::forEachRemaining and Spliterator::tryAdvance. */ - static class StackFrameTraverser extends AbstractStackWalker + static class StackFrameTraverser extends AbstractStackWalker implements Spliterator { static { stackWalkImplClasses.add(StackFrameTraverser.class); } private static final int CHARACTERISTICS = Spliterator.ORDERED | Spliterator.IMMUTABLE; - class Buffer extends FrameBuffer { - Buffer(int initialBatchSize) { + + final class StackFrameBuffer extends FrameBuffer { + private StackFrameInfo[] stackFrames; + StackFrameBuffer(int initialBatchSize) { super(initialBatchSize); - this.stackFrames = new StackFrame[initialBatchSize]; + this.stackFrames = new StackFrameInfo[initialBatchSize]; for (int i = START_POS; i < initialBatchSize; i++) { stackFrames[i] = new StackFrameInfo(walker); } } + @Override + StackFrameInfo[] frames() { + return stackFrames; + } + @Override void resize(int startIndex, int elements) { - super.resize(startIndex, elements); + if (!isActive()) + throw new IllegalStateException("inactive frame buffer can't be resized"); + + assert startIndex == START_POS : + "bad start index " + startIndex + " expected " + START_POS; int size = startIndex+elements; if (stackFrames.length < size) { - stackFrames = new StackFrame[size]; + StackFrameInfo[] newFrames = new StackFrameInfo[size]; + // copy initial magic... + System.arraycopy(stackFrames, 0, newFrames, 0, startIndex); + stackFrames = newFrames; } - for (int i = startIndex(); i < size; i++) { + for (int i = startIndex; i < size; i++) { stackFrames[i] = new StackFrameInfo(walker); } + currentBatchSize = size; } @Override - StackFrame nextStackFrame() { + StackFrameInfo nextStackFrame() { if (isEmpty()) { throw new NoSuchElementException("origin=" + origin + " fence=" + fence); } - StackFrame frame = stackFrames[origin]; + StackFrameInfo frame = stackFrames[origin]; origin++; return frame; } + + @Override + final Class at(int index) { + return stackFrames[index].declaringClass; + } } final Function, ? extends T> function; // callback @@ -694,7 +517,7 @@ final class StackStreamFactory { return null; } - StackFrame frame = frameBuffer.nextStackFrame(); + StackFrameInfo frame = frameBuffer.nextStackFrame(); depth++; return frame; } @@ -711,7 +534,7 @@ final class StackStreamFactory { @Override protected void initFrameBuffer() { - this.frameBuffer = new Buffer(getNextBatchSize()); + this.frameBuffer = new StackFrameBuffer(getNextBatchSize()); } @Override @@ -782,7 +605,7 @@ final class StackStreamFactory { * CallerClassFinder is specialized to return Class for each stack frame. * StackFrame is not requested. */ - static class CallerClassFinder extends AbstractStackWalker { + static final class CallerClassFinder extends AbstractStackWalker> { static { stackWalkImplClasses.add(CallerClassFinder.class); } @@ -791,6 +614,54 @@ final class StackStreamFactory { CallerClassFinder(StackWalker walker) { super(walker, FILL_CLASS_REFS_ONLY); + assert (mode & FILL_CLASS_REFS_ONLY) == FILL_CLASS_REFS_ONLY + : "mode should contain FILL_CLASS_REFS_ONLY"; + } + + final class ClassBuffer extends FrameBuffer> { + Class[] classes; // caller class for fast path + ClassBuffer(int batchSize) { + super(batchSize); + classes = new Class[batchSize]; + } + + @Override + Class[] frames() { return classes;} + + @Override + final Class at(int index) { return classes[index];} + + + // ------ subclass may override the following methods ------- + /** + * Resizes the buffers for VM to fill in the next batch of stack frames. + * The next batch will start at the given startIndex with the maximum number + * of elements. + * + *

Subclass may override this method to manage the allocated buffers. + * + * @param startIndex the start index for the first frame of the next batch to fill in. + * @param elements the number of elements for the next batch to fill in. + * + */ + @Override + void resize(int startIndex, int elements) { + if (!isActive()) + throw new IllegalStateException("inactive frame buffer can't be resized"); + + assert startIndex == START_POS : + "bad start index " + startIndex + " expected " + START_POS; + + int size = startIndex+elements; + if (classes.length < size) { + // copy the elements in classes array to the newly allocated one. + // classes[0] is a Thread object + Class[] prev = classes; + classes = new Class[size]; + System.arraycopy(prev, 0, classes, 0, startIndex); + } + currentBatchSize = size; + } } Class findCaller() { @@ -811,15 +682,15 @@ final class StackStreamFactory { if (isMethodHandleFrame(caller)) continue; frames[n++] = caller; } - - if (frames[1] == null) + if (frames[1] == null) { throw new IllegalStateException("no caller frame"); + } return n; } @Override protected void initFrameBuffer() { - this.frameBuffer = new FrameBuffer(getNextBatchSize()); + this.frameBuffer = new ClassBuffer(getNextBatchSize()); } @Override @@ -833,225 +704,250 @@ final class StackStreamFactory { } } - /* - * StackTrace caches all frames in the buffer. StackTraceElements are - * created lazily when Throwable::getStackTrace is called. - */ - static class StackTrace extends AbstractStackWalker { + static final class LiveStackInfoTraverser extends StackFrameTraverser { static { - stackWalkImplClasses.add(StackTrace.class); + stackWalkImplClasses.add(LiveStackInfoTraverser.class); } - - class GrowableBuffer extends FrameBuffer { - GrowableBuffer(int initialBatchSize) { + // VM will fill in all method info and live stack info directly in StackFrameInfo + final class LiveStackFrameBuffer extends FrameBuffer { + private LiveStackFrameInfo[] stackFrames; + LiveStackFrameBuffer(int initialBatchSize) { super(initialBatchSize); - - this.stackFrames = new StackFrame[initialBatchSize]; + this.stackFrames = new LiveStackFrameInfo[initialBatchSize]; for (int i = START_POS; i < initialBatchSize; i++) { - stackFrames[i] = new StackFrameInfo(walker); + stackFrames[i] = new LiveStackFrameInfo(walker); } } - /* - * Returns the next index to fill - */ @Override - int startIndex() { - return origin; + LiveStackFrameInfo[] frames() { + return stackFrames; } - /** - * Initialize the buffers for VM to fill in the stack frame information. - * The next batch will start at the given startIndex to - * the length of the buffer. - */ @Override void resize(int startIndex, int elements) { - // Expand the frame buffer. - // Do not call super.resize that will reuse the filled elements - // in this frame buffer - int size = startIndex+elements; - if (classes.length < size) { - // resize the frame buffer - classes = Arrays.copyOf(classes, size); - stackFrames = Arrays.copyOf(stackFrames, size); + if (!isActive()) { + throw new IllegalStateException("inactive frame buffer can't be resized"); } - for (int i = startIndex; i < size; i++) { - stackFrames[i] = new StackFrameInfo(walker); + assert startIndex == START_POS : + "bad start index " + startIndex + " expected " + START_POS; + + int size = startIndex + elements; + if (stackFrames.length < size) { + LiveStackFrameInfo[] newFrames = new LiveStackFrameInfo[size]; + // copy initial magic... + System.arraycopy(stackFrames, 0, newFrames, 0, startIndex); + stackFrames = newFrames; } - currentBatchSize = size; - } - StackTraceElement get(int index) { - return new StackTraceElement(classes[index].getName(), "unknown", null, -1); + for (int i = startIndex(); i < size; i++) { + stackFrames[i] = new LiveStackFrameInfo(walker); + } + + currentBatchSize = size; } - /** - * Returns an array of StackTraceElement for all stack frames cached in - * this StackTrace object. - *

- * This method is intended for Throwable::getOurStackTrace use only. - */ - StackTraceElement[] toStackTraceElements() { - int startIndex = START_POS; - for (int i = startIndex; i < classes.length; i++) { - if (classes[i] != null && filterStackWalkImpl(classes[i])) { - startIndex++; - } else { - break; - } + @Override + LiveStackFrameInfo nextStackFrame() { + if (isEmpty()) { + throw new NoSuchElementException("origin=" + origin + " fence=" + fence); } - // VM fills in the method name, filename, line number info - StackFrameInfo.fillInStackFrames(0, stackFrames, startIndex, startIndex + depth); + LiveStackFrameInfo frame = stackFrames[origin]; + origin++; + return frame; + } - StackTraceElement[] stes = new StackTraceElement[depth]; - for (int i = startIndex, j = 0; i < classes.length && j < depth; i++, j++) { - if (isDebug) { - System.err.println("StackFrame: " + i + " " + stackFrames[i]); - } - stes[j] = stackFrames[i].toStackTraceElement(); - } - return stes; + @Override + final Class at(int index) { + return stackFrames[index].declaringClass; } } - private static final int MAX_STACK_FRAMES = 1024; - private static final StackWalker STACKTRACE_WALKER = - StackWalker.newInstanceNoCheck(EnumSet.of(Option.SHOW_REFLECT_FRAMES)); - - private StackTraceElement[] stes; - static StackTrace dump() { - return new StackTrace(); + LiveStackInfoTraverser(StackWalker walker, + Function, ? extends T> function) { + super(walker, function, DEFAULT_MODE); } - static StackTrace dump(Throwable ex) { - return new StackTrace(ex); + @Override + protected void initFrameBuffer() { + this.frameBuffer = new LiveStackFrameBuffer(getNextBatchSize()); } + } + + /* + * Frame buffer + * + * Each specialized AbstractStackWalker subclass may subclass the FrameBuffer. + */ + static abstract class FrameBuffer { + static final int START_POS = 2; // 0th and 1st elements are reserved - private StackTrace() { - this(STACKTRACE_WALKER, DEFAULT_MODE); + // buffers for VM to fill stack frame info + int currentBatchSize; // current batch size + int origin; // index to the current traversed stack frame + int fence; // index to the last frame in the current batch + + FrameBuffer(int initialBatchSize) { + if (initialBatchSize < MIN_BATCH_SIZE) { + throw new IllegalArgumentException(initialBatchSize + + " < minimum batch size: " + MIN_BATCH_SIZE); + } + this.origin = START_POS; + this.fence = 0; + this.currentBatchSize = initialBatchSize; } + /** + * Returns an array of frames that may be used to store frame objects + * when walking the stack. + * + * May be an array of {@code Class} if the {@code AbstractStackWalker} + * mode is {@link #FILL_CLASS_REFS_ONLY}, or an array of + * {@link StackFrameInfo} (or derivative) array otherwise. + * + * @return An array of frames that may be used to store frame objects + * when walking the stack. Must not be null. + */ + abstract F[] frames(); // must not return null + + /** + * Resizes the buffers for VM to fill in the next batch of stack frames. + * The next batch will start at the given startIndex with the maximum number + * of elements. + * + *

Subclass may override this method to manage the allocated buffers. + * + * @param startIndex the start index for the first frame of the next batch to fill in. + * @param elements the number of elements for the next batch to fill in. + * + */ + abstract void resize(int startIndex, int elements); + + /** + * Return the class at the given position in the current batch. + * @param index the position of the frame. + * @return the class at the given position in the current batch. + */ + abstract Class at(int index); + + // ------ subclass may override the following methods ------- + /* - * Throwable::fillInStackTrace and of Throwable and subclasses - * are filtered in the VM. + * Returns the start index for this frame buffer is refilled. + * + * This implementation reuses the allocated buffer for the next batch + * of stack frames. For subclass to retain the fetched stack frames, + * it should override this method to return the index at which the frame + * should be filled in for the next batch. */ - private StackTrace(Throwable ex) { - this(STACKTRACE_WALKER, FILTER_FILL_IN_STACKTRACE); // skip Throwable::init frames - if (isDebug) { - System.err.println("dump stack for " + ex.getClass().getName()); - } + int startIndex() { + return START_POS; + } + + /** + * Returns next StackFrame object in the current batch of stack frames + */ + F nextStackFrame() { + throw new InternalError("should not reach here"); } - StackTrace(StackWalker walker, int mode) { - super(walker, mode, MAX_STACK_FRAMES); + // ------ FrameBuffer implementation ------ - // snapshot the stack trace - walk(); + final int curBatchFrameCount() { + return currentBatchSize-START_POS; } - @Override - protected Integer consumeFrames() { - // traverse all frames and perform the action on the stack frames, if specified - int n = 0; - while (n < maxDepth && nextFrame() != null) { - n++; - } - return n; + /* + * Tests if this frame buffer is empty. All frames are fetched. + */ + final boolean isEmpty() { + return origin >= fence || (origin == START_POS && fence == 0); } - @Override - protected void initFrameBuffer() { - this.frameBuffer = new GrowableBuffer(getNextBatchSize()); + /* + * Freezes this frame buffer. The stack stream source is done fetching. + */ + final void freeze() { + origin = 0; + fence = 0; } - // TODO: implement better heuristic - @Override - protected int batchSize(int lastBatchFrameCount) { - // chunk size of VM backtrace is 32 - return lastBatchFrameCount == 0 ? 32 : 32; + /* + * Tests if this frame buffer is active. It is inactive when + * it is done for traversal. All stack frames have been traversed. + */ + final boolean isActive() { + return origin > 0 && (fence == 0 || origin < fence || fence == currentBatchSize); } /** - * Returns an array of StackTraceElement for all stack frames cached in - * this StackTrace object. - *

- * This method is intended for Throwable::getOurStackTrace use only. + * Gets the class at the current frame and move to the next frame. */ - synchronized StackTraceElement[] getStackTraceElements() { - if (stes == null) { - stes = ((GrowableBuffer) frameBuffer).toStackTraceElements(); - // release the frameBuffer memory - frameBuffer = null; + final Class next() { + if (isEmpty()) { + throw new NoSuchElementException("origin=" + origin + " fence=" + fence); + } + Class c = at(origin); + origin++; + if (isDebug) { + int index = origin-1; + System.out.format(" next frame at %d: %s (origin %d fence %d)%n", index, + Objects.toString(c), index, fence); } - return stes; + return c; } - /* - * Prints stack trace to the given PrintStream. - * - * Further implementation could skip creating StackTraceElement objects - * print directly to the PrintStream. + /** + * Gets the class at the current frame. */ - void printStackTrace(PrintStream s) { - StackTraceElement[] stes = getStackTraceElements(); - synchronized (s) { - s.println("Stack trace"); - for (StackTraceElement traceElement : stes) - s.println("\tat " + traceElement); + final Class get() { + if (isEmpty()) { + throw new NoSuchElementException("origin=" + origin + " fence=" + fence); } + return at(origin); } - } - static class LiveStackInfoTraverser extends StackFrameTraverser { - static { - stackWalkImplClasses.add(LiveStackInfoTraverser.class); + /* + * Returns the index of the current frame. + */ + final int getIndex() { + return origin; } - // VM will fill in all method info and live stack info directly in StackFrameInfo - class Buffer extends FrameBuffer { - Buffer(int initialBatchSize) { - super(initialBatchSize); - this.stackFrames = new StackFrame[initialBatchSize]; - for (int i = START_POS; i < initialBatchSize; i++) { - stackFrames[i] = new LiveStackFrameInfo(walker); - } - } - - @Override - void resize(int startIndex, int elements) { - super.resize(startIndex, elements); - int size = startIndex + elements; - if (stackFrames.length < size) { - this.stackFrames = new StackFrame[size]; - } - - for (int i = startIndex(); i < size; i++) { - stackFrames[i] = new LiveStackFrameInfo(walker); - } - } - - @Override - StackFrame nextStackFrame() { - if (isEmpty()) { - throw new NoSuchElementException("origin=" + origin + " fence=" + fence); + /* + * Set the start and end index of a new batch of stack frames that have + * been filled in this frame buffer. + */ + final void setBatch(int depth, int startIndex, int endIndex) { + if (startIndex <= 0 || endIndex <= 0) + throw new IllegalArgumentException("startIndex=" + startIndex + " endIndex=" + endIndex); + + this.origin = startIndex; + this.fence = endIndex; + if (depth == 0 && fence > 0) { + // filter the frames due to the stack stream implementation + for (int i = START_POS; i < fence; i++) { + Class c = at(i); + if (isDebug) System.err.format(" frame %d: %s%n", i, c); + if (filterStackWalkImpl(c)) { + origin++; + } else { + break; + } } - - StackFrame frame = stackFrames[origin]; - origin++; - return frame; } } - LiveStackInfoTraverser(StackWalker walker, - Function, ? extends T> function) { - super(walker, function, DEFAULT_MODE); - } - - @Override - protected void initFrameBuffer() { - this.frameBuffer = new Buffer(getNextBatchSize()); + /* + * Checks if the origin is the expected start index. + */ + final void check(int skipFrames) { + int index = skipFrames + START_POS; + if (origin != index) { + // stack walk must continue with the previous frame depth + throw new IllegalStateException("origin " + origin + " != " + index); + } } } @@ -1093,14 +989,9 @@ final class StackStreamFactory { } private static boolean getProperty(String key, boolean value) { - String s = AccessController.doPrivileged(new PrivilegedAction<>() { - @Override - public String run() { - return System.getProperty(key); - } - }); + String s = GetPropertyAction.getProperty(key); if (s != null) { - return Boolean.valueOf(s); + return Boolean.parseBoolean(s); } return value; } diff --git a/jdk/src/java.base/share/classes/java/lang/String.java b/jdk/src/java.base/share/classes/java/lang/String.java index a609223d42ffd9aa2398f5b031d6978f4d2690db..a1772977727eb27e0598bffb7a93da80b30a70d8 100644 --- a/jdk/src/java.base/share/classes/java/lang/String.java +++ b/jdk/src/java.base/share/classes/java/lang/String.java @@ -363,7 +363,7 @@ public final class String * @see #String(byte[], java.nio.charset.Charset) * @see #String(byte[]) */ - @Deprecated + @Deprecated(since="1.1") public String(byte ascii[], int hibyte, int offset, int count) { checkBoundsOffCount(offset, count, ascii.length); if (count == 0) { @@ -415,7 +415,7 @@ public final class String * @see #String(byte[], java.nio.charset.Charset) * @see #String(byte[]) */ - @Deprecated + @Deprecated(since="1.1") public String(byte ascii[], int hibyte) { this(ascii, hibyte, 0, ascii.length); } @@ -911,7 +911,7 @@ public final class String * dst.length} * */ - @Deprecated + @Deprecated(since="1.1") public void getBytes(int srcBegin, int srcEnd, byte dst[], int dstBegin) { checkBoundsBeginEnd(srcBegin, srcEnd, length()); Objects.requireNonNull(dst); diff --git a/jdk/src/java.base/share/classes/java/lang/System.java b/jdk/src/java.base/share/classes/java/lang/System.java index 02975912bc0fe4c63375b618c4fc3d1bf5f2944d..2ddd37f5da1170e18ab22de91f0dc2b97429ab2a 100644 --- a/jdk/src/java.base/share/classes/java/lang/System.java +++ b/jdk/src/java.base/share/classes/java/lang/System.java @@ -1715,6 +1715,7 @@ public final class System { * finalizers being called on live objects while other threads are * concurrently manipulating those objects, resulting in erratic * behavior or deadlock. + * This method is subject to removal in a future version of Java SE. * @param value indicating enabling or disabling of finalization * @throws SecurityException * if a security manager exists and its checkExit @@ -1725,7 +1726,7 @@ public final class System { * @see java.lang.SecurityManager#checkExit(int) * @since 1.1 */ - @Deprecated + @Deprecated(since="1.2", forRemoval=true) public static void runFinalizersOnExit(boolean value) { Runtime.runFinalizersOnExit(value); } diff --git a/jdk/src/java.base/share/classes/java/lang/Thread.java b/jdk/src/java.base/share/classes/java/lang/Thread.java index 9c275ac1be9e5a7ea0877058fb2b9e5b7700895b..54fc27f31b53f4aaed16c23fa3d19d7f1766ddd4 100644 --- a/jdk/src/java.base/share/classes/java/lang/Thread.java +++ b/jdk/src/java.base/share/classes/java/lang/Thread.java @@ -890,7 +890,7 @@ class Thread implements Runnable { * Why * are Thread.stop, Thread.suspend and Thread.resume Deprecated?. */ - @Deprecated + @Deprecated(since="1.2") public final void stop() { SecurityManager security = System.getSecurityManager(); if (security != null) { @@ -922,8 +922,9 @@ class Thread implements Runnable { * For more information, see * Why * are Thread.stop, Thread.suspend and Thread.resume Deprecated?. + * This method is subject to removal in a future version of Java SE. */ - @Deprecated + @Deprecated(since="1.2", forRemoval=true) public final synchronized void stop(Throwable obj) { throw new UnsupportedOperationException(); } @@ -1043,9 +1044,10 @@ class Thread implements Runnable { * "frozen" processes. For more information, see * * Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?. + * This method is subject to removal in a future version of Java SE. * @throws NoSuchMethodError always */ - @Deprecated + @Deprecated(since="1.5", forRemoval=true) public void destroy() { throw new NoSuchMethodError(); } @@ -1083,7 +1085,7 @@ class Thread implements Runnable { * Why * are Thread.stop, Thread.suspend and Thread.resume Deprecated?. */ - @Deprecated + @Deprecated(since="1.2") public final void suspend() { checkAccess(); suspend0(); @@ -1109,7 +1111,7 @@ class Thread implements Runnable { * Why * are Thread.stop, Thread.suspend and Thread.resume Deprecated?. */ - @Deprecated + @Deprecated(since="1.2") public final void resume() { checkAccess(); resume0(); @@ -1270,8 +1272,10 @@ class Thread implements Runnable { * @deprecated The definition of this call depends on {@link #suspend}, * which is deprecated. Further, the results of this call * were never well-defined. + * This method is subject to removal in a future version of Java SE. + * @see StackWalker */ - @Deprecated + @Deprecated(since="1.2", forRemoval=true) public native int countStackFrames(); /** @@ -1388,7 +1392,7 @@ class Thread implements Runnable { * This method is used only for debugging. */ public static void dumpStack() { - StackStreamFactory.makeStackTrace().printStackTrace(System.err); + new Exception("Stack trace").printStackTrace(); } /** @@ -1610,8 +1614,7 @@ class Thread implements Runnable { } return stackTrace; } else { - // Don't need JVM help for current thread - return StackStreamFactory.makeStackTrace().getStackTraceElements(); + return (new Exception()).getStackTrace(); } } diff --git a/jdk/src/java.base/share/classes/java/lang/ThreadGroup.java b/jdk/src/java.base/share/classes/java/lang/ThreadGroup.java index e477800f61c78bffb6a9174349165224e65a6bef..0a97e4cad942ce554348642b705057dd9aacc335 100644 --- a/jdk/src/java.base/share/classes/java/lang/ThreadGroup.java +++ b/jdk/src/java.base/share/classes/java/lang/ThreadGroup.java @@ -607,7 +607,7 @@ class ThreadGroup implements Thread.UncaughtExceptionHandler { * @deprecated This method is inherently unsafe. See * {@link Thread#stop} for details. */ - @Deprecated + @Deprecated(since="1.2") public final void stop() { if (stopOrSuspend(false)) Thread.currentThread().stop(); @@ -669,7 +669,7 @@ class ThreadGroup implements Thread.UncaughtExceptionHandler { * @deprecated This method is inherently deadlock-prone. See * {@link Thread#suspend} for details. */ - @Deprecated + @Deprecated(since="1.2") @SuppressWarnings("deprecation") public final void suspend() { if (stopOrSuspend(true)) @@ -732,7 +732,7 @@ class ThreadGroup implements Thread.UncaughtExceptionHandler { * both of which have been deprecated, as they are inherently * deadlock-prone. See {@link Thread#suspend} for details. */ - @Deprecated + @Deprecated(since="1.2") @SuppressWarnings("deprecation") public final void resume() { int ngroupsSnapshot; @@ -1073,7 +1073,7 @@ class ThreadGroup implements Thread.UncaughtExceptionHandler { * which is deprecated. Further, the behavior of this call * was never specified. */ - @Deprecated + @Deprecated(since="1.2") public boolean allowThreadSuspension(boolean b) { this.vmAllowSuspension = b; if (!b) { diff --git a/jdk/src/java.base/share/classes/java/lang/Throwable.java b/jdk/src/java.base/share/classes/java/lang/Throwable.java index 72a3455e637cde50df3295bde5fc0f3b8c349122..a609719c9cde262e0e931bd3194839e97894a58e 100644 --- a/jdk/src/java.base/share/classes/java/lang/Throwable.java +++ b/jdk/src/java.base/share/classes/java/lang/Throwable.java @@ -785,11 +785,7 @@ public class Throwable implements Serializable { public synchronized Throwable fillInStackTrace() { if (stackTrace != null || backtrace != null /* Out of protocol state */ ) { - if (backtrace == null && StackStreamFactory.useStackTrace(this)) { - backtrace = StackStreamFactory.makeStackTrace(this); - } else { - fillInStackTrace(0); - } + fillInStackTrace(0); stackTrace = UNASSIGNED_STACK; } return this; @@ -830,15 +826,11 @@ public class Throwable implements Serializable { // backtrace if this is the first call to this method if (stackTrace == UNASSIGNED_STACK || (stackTrace == null && backtrace != null) /* Out of protocol state */) { - if (backtrace instanceof StackStreamFactory.StackTrace) { - stackTrace = ((StackStreamFactory.StackTrace)backtrace).getStackTraceElements(); - } else { - stackTrace = new StackTraceElement[depth]; - for (int i = 0; i < depth; i++) { - stackTrace[i] = new StackTraceElement(); - } - getStackTraceElements(stackTrace); + stackTrace = new StackTraceElement[depth]; + for (int i = 0; i < depth; i++) { + stackTrace[i] = new StackTraceElement(); } + getStackTraceElements(stackTrace); } else if (stackTrace == null) { return UNASSIGNED_STACK; } diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java b/jdk/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java index 739573507abdbcc00612cdfdb460ec37969cff96..a0df622f501bd9b5e95f67f883dd00c1f12177ca 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java @@ -88,8 +88,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*; static { final String key = "jdk.internal.lambda.dumpProxyClasses"; - String path = AccessController.doPrivileged( - new GetPropertyAction(key)); + String path = GetPropertyAction.getProperty(key); dumper = (null == path) ? null : ProxyClassesDumper.getInstance(path); } diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java b/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java index c2e68753e7b282f4b4023e6e1c7ae5cc1b91b3d8..de4e3c155370861cb281935bedb94e9c99f01708 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java @@ -733,6 +733,7 @@ import java.util.Objects; } @Override + @SuppressWarnings("deprecation") public int hashCode() { // Avoid autoboxing getReferenceKind(), since this is used early and will force // early initialization of Byte$ByteCache @@ -826,7 +827,7 @@ import java.util.Objects; assert(isResolved() == isResolved); } - void checkForTypeAlias() { + void checkForTypeAlias(Class refc) { if (isInvocable()) { MethodType type; if (this.type instanceof MethodType) @@ -834,16 +835,16 @@ import java.util.Objects; else this.type = type = getMethodType(); if (type.erase() == type) return; - if (VerifyAccess.isTypeVisible(type, clazz)) return; - throw new LinkageError("bad method type alias: "+type+" not visible from "+clazz); + if (VerifyAccess.isTypeVisible(type, refc)) return; + throw new LinkageError("bad method type alias: "+type+" not visible from "+refc); } else { Class type; if (this.type instanceof Class) type = (Class) this.type; else this.type = type = getFieldType(); - if (VerifyAccess.isTypeVisible(type, clazz)) return; - throw new LinkageError("bad field type alias: "+type+" not visible from "+clazz); + if (VerifyAccess.isTypeVisible(type, refc)) return; + throw new LinkageError("bad field type alias: "+type+" not visible from "+refc); } } @@ -1015,10 +1016,25 @@ import java.util.Objects; MemberName m = ref.clone(); // JVM will side-effect the ref assert(refKind == m.getReferenceKind()); try { + // There are 4 entities in play here: + // * LC: lookupClass + // * REFC: symbolic reference class (MN.clazz before resolution); + // * DEFC: resolved method holder (MN.clazz after resolution); + // * PTYPES: parameter types (MN.type) + // + // What we care about when resolving a MemberName is consistency between DEFC and PTYPES. + // We do type alias (TA) checks on DEFC to ensure that. DEFC is not known until the JVM + // finishes the resolution, so do TA checks right after MHN.resolve() is over. + // + // All parameters passed by a caller are checked against MH type (PTYPES) on every invocation, + // so it is safe to call a MH from any context. + // + // REFC view on PTYPES doesn't matter, since it is used only as a starting point for resolution and doesn't + // participate in method selection. m = MethodHandleNatives.resolve(m, lookupClass); - m.checkForTypeAlias(); + m.checkForTypeAlias(m.getDeclaringClass()); m.resolution = null; - } catch (LinkageError ex) { + } catch (ClassNotFoundException | LinkageError ex) { // JVM reports that the "bytecode behavior" would get an error assert(!m.isResolved()); m.resolution = ex; @@ -1132,6 +1148,10 @@ import java.util.Objects; public Object newMemberName() { return new MemberName(); } + public String getName(Object mname) { + MemberName memberName = (MemberName)mname; + return memberName.getName(); + } }); } } diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java index 7a5d3f1f0b255b59744f52d0fc3c70a2a78e637c..67c197dd70943a2a4dfd62d698fabac18c273781 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java @@ -49,7 +49,7 @@ class MethodHandleNatives { static native void init(MemberName self, Object ref); static native void expand(MemberName self); - static native MemberName resolve(MemberName self, Class caller) throws LinkageError; + static native MemberName resolve(MemberName self, Class caller) throws LinkageError, ClassNotFoundException; static native int getMembers(Class defc, String matchName, String matchSig, int matchFlags, Class caller, int skip, MemberName[] results); diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java index df1cba46fa84082ec81dbc6443a98cd7bb6087e3..4fbc1d84671def4d8e208aba79ce80b38edcefd9 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java @@ -25,9 +25,9 @@ package java.lang.invoke; -import java.security.AccessController; -import java.security.PrivilegedAction; +import java.util.Properties; import jdk.internal.misc.Unsafe; +import sun.security.action.GetPropertyAction; /** * This class consists exclusively of static names internal to the @@ -53,32 +53,27 @@ import jdk.internal.misc.Unsafe; static final boolean VAR_HANDLE_GUARDS; static { - final Object[] values = new Object[10]; - AccessController.doPrivileged(new PrivilegedAction<>() { - public Void run() { - values[0] = Boolean.getBoolean("java.lang.invoke.MethodHandle.DEBUG_NAMES"); - values[1] = Boolean.getBoolean("java.lang.invoke.MethodHandle.DUMP_CLASS_FILES"); - values[2] = Boolean.getBoolean("java.lang.invoke.MethodHandle.TRACE_INTERPRETER"); - values[3] = Boolean.getBoolean("java.lang.invoke.MethodHandle.TRACE_METHOD_LINKAGE"); - values[4] = Integer.getInteger("java.lang.invoke.MethodHandle.COMPILE_THRESHOLD", 0); - values[5] = Integer.getInteger("java.lang.invoke.MethodHandle.DONT_INLINE_THRESHOLD", 30); - values[6] = Integer.getInteger("java.lang.invoke.MethodHandle.PROFILE_LEVEL", 0); - values[7] = Boolean.parseBoolean(System.getProperty("java.lang.invoke.MethodHandle.PROFILE_GWT", "true")); - values[8] = Integer.getInteger("java.lang.invoke.MethodHandle.CUSTOMIZE_THRESHOLD", 127); - values[9] = Boolean.parseBoolean(System.getProperty("java.lang.invoke.VarHandle.VAR_HANDLE_GUARDS", "true")); - return null; - } - }); - DEBUG_METHOD_HANDLE_NAMES = (Boolean) values[0]; - DUMP_CLASS_FILES = (Boolean) values[1]; - TRACE_INTERPRETER = (Boolean) values[2]; - TRACE_METHOD_LINKAGE = (Boolean) values[3]; - COMPILE_THRESHOLD = (Integer) values[4]; - DONT_INLINE_THRESHOLD = (Integer) values[5]; - PROFILE_LEVEL = (Integer) values[6]; - PROFILE_GWT = (Boolean) values[7]; - CUSTOMIZE_THRESHOLD = (Integer) values[8]; - VAR_HANDLE_GUARDS = (Boolean) values[9]; + Properties props = GetPropertyAction.getProperties(); + DEBUG_METHOD_HANDLE_NAMES = Boolean.parseBoolean( + props.getProperty("java.lang.invoke.MethodHandle.DEBUG_NAMES")); + DUMP_CLASS_FILES = Boolean.parseBoolean( + props.getProperty("java.lang.invoke.MethodHandle.DUMP_CLASS_FILES")); + TRACE_INTERPRETER = Boolean.parseBoolean( + props.getProperty("java.lang.invoke.MethodHandle.TRACE_INTERPRETER")); + TRACE_METHOD_LINKAGE = Boolean.parseBoolean( + props.getProperty("java.lang.invoke.MethodHandle.TRACE_METHOD_LINKAGE")); + COMPILE_THRESHOLD = Integer.parseInt( + props.getProperty("java.lang.invoke.MethodHandle.COMPILE_THRESHOLD", "0")); + DONT_INLINE_THRESHOLD = Integer.parseInt( + props.getProperty("java.lang.invoke.MethodHandle.DONT_INLINE_THRESHOLD", "30")); + PROFILE_LEVEL = Integer.parseInt( + props.getProperty("java.lang.invoke.MethodHandle.PROFILE_LEVEL", "0")); + PROFILE_GWT = Boolean.parseBoolean( + props.getProperty("java.lang.invoke.MethodHandle.PROFILE_GWT", "true")); + CUSTOMIZE_THRESHOLD = Integer.parseInt( + props.getProperty("java.lang.invoke.MethodHandle.CUSTOMIZE_THRESHOLD", "127")); + VAR_HANDLE_GUARDS = Boolean.parseBoolean( + props.getProperty("java.lang.invoke.VarHandle.VAR_HANDLE_GUARDS", "true")); if (CUSTOMIZE_THRESHOLD < -1 || CUSTOMIZE_THRESHOLD > 127) { throw newInternalError("CUSTOMIZE_THRESHOLD should be in [-1...127] range"); diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java index ea688b14815b106cae725c10af6a0d34d8e7dd81..6c37371a57b5a63002cea63c3ac6392e6c7c9905 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -28,6 +28,7 @@ package java.lang.invoke; import java.lang.reflect.*; import java.util.ArrayList; import java.util.BitSet; +import java.util.Iterator; import java.util.List; import java.util.Arrays; import java.util.Objects; @@ -53,6 +54,7 @@ import jdk.internal.org.objectweb.asm.ClassWriter; import jdk.internal.org.objectweb.asm.Opcodes; import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException; +import static java.lang.invoke.MethodType.methodType; /** * This class consists exclusively of static methods that operate on or return @@ -3000,7 +3002,7 @@ assert((int)twice.invokeExact(21) == 42); private static final MethodHandle[] IDENTITY_MHS = new MethodHandle[Wrapper.values().length]; private static MethodHandle makeIdentity(Class ptype) { - MethodType mtype = MethodType.methodType(ptype, ptype); + MethodType mtype = methodType(ptype, ptype); LambdaForm lform = LambdaForm.identityForm(BasicType.basicType(ptype)); return MethodHandleImpl.makeIntrinsic(mtype, lform, Intrinsic.IDENTITY); } @@ -3018,7 +3020,7 @@ assert((int)twice.invokeExact(21) == 42); } private static final MethodHandle[] ZERO_MHS = new MethodHandle[Wrapper.values().length]; private static MethodHandle makeZero(Class rtype) { - MethodType mtype = MethodType.methodType(rtype); + MethodType mtype = methodType(rtype); LambdaForm lform = LambdaForm.zeroForm(BasicType.basicType(rtype)); return MethodHandleImpl.makeIntrinsic(mtype, lform, Intrinsic.ZERO); } @@ -3929,7 +3931,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); MethodHandle throwException(Class returnType, Class exType) { if (!Throwable.class.isAssignableFrom(exType)) throw new ClassCastException(exType.getName()); - return MethodHandleImpl.throwException(MethodType.methodType(returnType, exType)); + return MethodHandleImpl.throwException(methodType(returnType, exType)); } /** @@ -4166,7 +4168,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); for (int i = 0; i < nclauses; ++i) { Class t = iterationVariableTypes.get(i); if (init.get(i) == null) { - init.set(i, empty(MethodType.methodType(t, commonSuffix))); + init.set(i, empty(methodType(t, commonSuffix))); } if (step.get(i) == null) { step.set(i, dropArgumentsToMatch(identityOrVoid(t), 0, commonParameterSequence, i)); @@ -4175,7 +4177,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); pred.set(i, dropArguments(constant(boolean.class, true), 0, commonParameterSequence)); } if (fini.get(i) == null) { - fini.set(i, empty(MethodType.methodType(t, commonParameterSequence))); + fini.set(i, empty(methodType(t, commonParameterSequence))); } } @@ -4269,7 +4271,8 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); * @since 9 */ public static MethodHandle whileLoop(MethodHandle init, MethodHandle pred, MethodHandle body) { - MethodHandle fin = init == null ? zero(void.class) : identity(init.type().returnType()); + MethodHandle fin = init == null || init.type().returnType() == void.class ? zero(void.class) : + identity(init.type().returnType()); MethodHandle[] checkExit = {null, null, pred, fin}; MethodHandle[] varBody = {init, body}; return loop(checkExit, varBody); @@ -4335,7 +4338,8 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); * @since 9 */ public static MethodHandle doWhileLoop(MethodHandle init, MethodHandle body, MethodHandle pred) { - MethodHandle fin = init == null ? zero(void.class) : identity(init.type().returnType()); + MethodHandle fin = init == null || init.type().returnType() == void.class ? zero(void.class) : + identity(init.type().returnType()); MethodHandle[] clause = {init, body, pred, fin}; return loop(clause); } @@ -4472,12 +4476,24 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); * @since 9 */ public static MethodHandle countedLoop(MethodHandle start, MethodHandle end, MethodHandle init, MethodHandle body) { - MethodHandle returnVar = dropArguments(init == null ? zero(void.class) : identity(init.type().returnType()), - 0, int.class, int.class); + Class resultType; + MethodHandle actualInit; + if (init == null) { + resultType = body == null ? void.class : body.type().returnType(); + actualInit = empty(methodType(resultType)); + } else { + resultType = init.type().returnType(); + actualInit = init; + } + MethodHandle defaultResultHandle = resultType == void.class ? zero(void.class) : identity(resultType); + MethodHandle actualBody = body == null ? dropArguments(defaultResultHandle, 0, int.class) : body; + MethodHandle returnVar = dropArguments(defaultResultHandle, 0, int.class, int.class); + MethodHandle actualEnd = end == null ? constant(int.class, 0) : end; MethodHandle[] indexVar = {start, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopStep)}; - MethodHandle[] loopLimit = {end, null, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopPred), returnVar}; - MethodHandle[] bodyClause = {init, - filterArgument(dropArguments(body, 1, int.class), 0, + MethodHandle[] loopLimit = {actualEnd, null, + MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopPred), returnVar}; + MethodHandle[] bodyClause = {actualInit, + filterArgument(dropArguments(actualBody, 1, int.class), 0, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_decrementCounter))}; return loop(indexVar, loopLimit, bodyClause); } @@ -4485,6 +4501,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); /** * Constructs a loop that ranges over the elements produced by an {@code Iterator}. * The iterator will be produced by the evaluation of the {@code iterator} handle. + * This handle must have {@link java.util.Iterator} as its return type. * If this handle is passed as {@code null} the method {@link Iterable#iterator} will be used instead, * and will be applied to a leading argument of the loop handle. * Each value produced by the iterator is passed to the {@code body}, which must accept an initial {@code T} parameter. @@ -4534,7 +4551,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); * assertEquals(reversedList, (List) loop.invoke(list)); * } *

- * @implSpec The implementation of this method is equivalent to: + * @implSpec The implementation of this method is equivalent to (excluding error handling): *

{@code
      * MethodHandle iteratedLoop(MethodHandle iterator, MethodHandle init, MethodHandle body) {
      *     // assume MH_next and MH_hasNext are handles to methods of Iterator
@@ -4550,6 +4567,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
      * }
* * @param iterator a handle to return the iterator to start the loop. + * The handle must have {@link java.util.Iterator} as its return type. * Passing {@code null} will make the loop call {@link Iterable#iterator()} on the first * incoming value. * @param init initializer for additional loop state. This determines the loop's result type. @@ -4565,21 +4583,30 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); * @since 9 */ public static MethodHandle iteratedLoop(MethodHandle iterator, MethodHandle init, MethodHandle body) { - checkIteratedLoop(body); + checkIteratedLoop(iterator, body); + Class resultType = init == null ? + body == null ? void.class : body.type().returnType() : + init.type().returnType(); + boolean voidResult = resultType == void.class; + + MethodHandle initIterator; + if (iterator == null) { + MethodHandle initit = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_initIterator); + initIterator = initit.asType(initit.type().changeParameterType(0, + body.type().parameterType(voidResult ? 1 : 2))); + } else { + initIterator = iterator.asType(iterator.type().changeReturnType(Iterator.class)); + } - MethodHandle initit = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_initIterator); - MethodHandle initIterator = iterator == null ? - initit.asType(initit.type().changeParameterType(0, body.type().parameterType(init == null ? 1 : 2))) : - iterator; - Class itype = initIterator.type().returnType(); Class ttype = body.type().parameterType(0); MethodHandle returnVar = - dropArguments(init == null ? zero(void.class) : identity(init.type().returnType()), 0, itype); + dropArguments(voidResult ? zero(void.class) : identity(resultType), 0, Iterator.class); MethodHandle initnx = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_iterateNext); MethodHandle nextVal = initnx.asType(initnx.type().changeReturnType(ttype)); - MethodHandle[] iterVar = {initIterator, null, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_iteratePred), returnVar}; + MethodHandle[] iterVar = {initIterator, null, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_iteratePred), + returnVar}; MethodHandle[] bodyClause = {init, filterArgument(body, 0, nextVal)}; return loop(iterVar, bodyClause); @@ -4833,7 +4860,10 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); } } - private static void checkIteratedLoop(MethodHandle body) { + private static void checkIteratedLoop(MethodHandle iterator, MethodHandle body) { + if (null != iterator && !Iterator.class.isAssignableFrom(iterator.type().returnType())) { + throw newIllegalArgumentException("iteratedLoop first argument must have Iterator return type"); + } if (null == body) { throw newIllegalArgumentException("iterated loop body must not be null"); } diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java b/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java index 6469a4b8a6d949c8d9840958ce50d26c8b4f08a3..44f29a4a136913cad761e16a252eee8c21b3aaef 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java @@ -33,7 +33,6 @@ import jdk.internal.vm.annotation.ForceInline; import jdk.internal.misc.Unsafe; import java.lang.invoke.MethodHandles.Lookup; -import java.security.AccessController; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -188,14 +187,15 @@ public final class StringConcatFactory { private static final ProxyClassesDumper DUMPER; static { - final String strategy = AccessController.doPrivileged( - new GetPropertyAction("java.lang.invoke.stringConcat")); - CACHE_ENABLE = Boolean.parseBoolean(AccessController.doPrivileged( - new GetPropertyAction("java.lang.invoke.stringConcat.cache"))); - DEBUG = Boolean.parseBoolean(AccessController.doPrivileged( - new GetPropertyAction("java.lang.invoke.stringConcat.debug"))); - final String dumpPath = AccessController.doPrivileged( - new GetPropertyAction("java.lang.invoke.stringConcat.dumpClasses")); + Properties props = GetPropertyAction.getProperties(); + final String strategy = + props.getProperty("java.lang.invoke.stringConcat"); + CACHE_ENABLE = Boolean.parseBoolean( + props.getProperty("java.lang.invoke.stringConcat.cache")); + DEBUG = Boolean.parseBoolean( + props.getProperty("java.lang.invoke.stringConcat.debug")); + final String dumpPath = + props.getProperty("java.lang.invoke.stringConcat.dumpClasses"); STRATEGY = (strategy == null) ? DEFAULT_STRATEGY : Strategy.valueOf(strategy); CACHE = CACHE_ENABLE ? new ConcurrentHashMap<>() : null; diff --git a/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java b/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java index 83d8fc59aafcc6063d7de99b18549c7e47f1a572..1cdd12838b17071d05d31fa0254642d1be85af32 100644 --- a/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java +++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java @@ -39,6 +39,7 @@ import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; +import sun.security.action.GetPropertyAction; /** * A finder of modules. A {@code ModuleFinder} is used to find modules during @@ -152,7 +153,7 @@ public interface ModuleFinder { SecurityManager sm = System.getSecurityManager(); if (sm != null) { - PrivilegedAction pa = () -> System.getProperty("java.home"); + PrivilegedAction pa = new GetPropertyAction("java.home"); home = AccessController.doPrivileged(pa); Permission p = new FilePermission(home + File.separator + "-", "read"); sm.checkPermission(p); diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/Proxy.java b/jdk/src/java.base/share/classes/java/lang/reflect/Proxy.java index 12abe79d4eafc2d4ef75bc9f508f89c2eeb8bfcd..8802abeda76d1e3066b93695b2b374cb24dcaf1a 100644 --- a/jdk/src/java.base/share/classes/java/lang/reflect/Proxy.java +++ b/jdk/src/java.base/share/classes/java/lang/reflect/Proxy.java @@ -50,6 +50,7 @@ import jdk.internal.misc.VM; import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.Reflection; import sun.reflect.misc.ReflectUtil; +import sun.security.action.GetPropertyAction; import sun.security.util.SecurityConstants; /** @@ -581,11 +582,7 @@ public class Proxy implements java.io.Serializable { } private static final String DEBUG = - AccessController.doPrivileged(new PrivilegedAction<>() { - public String run() { - return System.getProperty("jdk.proxy.debug", ""); - } - }); + GetPropertyAction.getProperty("jdk.proxy.debug", ""); private static boolean isDebug() { return !DEBUG.isEmpty(); diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java b/jdk/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java index 12e1723e0df6788a87d3a811ae11556cc3982eda..cc8dbbfffab54ee5096dc441dbb0a80f8b02074e 100644 --- a/jdk/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java +++ b/jdk/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java @@ -1750,7 +1750,7 @@ class ProxyGenerator { * Get or assign the index for a CONSTANT_Float entry. */ public short getFloat(float f) { - return getValue(new Float(f)); + return getValue(f); } /** diff --git a/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java b/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java index 7a9b7fc17ed873c7c99ff936e96ee3581d727dc9..debc60f74b995483e2bf2f6400330f6c2ce5ffb5 100644 --- a/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java +++ b/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java @@ -31,6 +31,7 @@ import sun.net.ResourceManager; import java.util.Set; import java.util.HashSet; import java.util.Collections; +import sun.security.action.GetPropertyAction; /** * Abstract datagram and multicast socket implementation base class. @@ -51,9 +52,7 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl protected InetAddress connectedAddress = null; private int connectedPort = -1; - private static final String os = AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("os.name") - ); + private static final String os = GetPropertyAction.getProperty("os.name"); /** * flag set if the native connect() call not to be used diff --git a/jdk/src/java.base/share/classes/java/net/InetAddress.java b/jdk/src/java.base/share/classes/java/net/InetAddress.java index 8e0d46152ffe836580a0d3c15ed18f5581553ccc..e79c5115413b059f355541f4a640400cb737238a 100644 --- a/jdk/src/java.base/share/classes/java/net/InetAddress.java +++ b/jdk/src/java.base/share/classes/java/net/InetAddress.java @@ -1123,8 +1123,8 @@ class InetAddress implements java.io.Serializable { */ private static NameService createNameService() { - String hostsFileName = AccessController - .doPrivileged(new GetPropertyAction("jdk.net.hosts.file")); + String hostsFileName = + GetPropertyAction.getProperty("jdk.net.hosts.file"); NameService theNameService; if (hostsFileName != null) { theNameService = new HostsFileNameService(hostsFileName); @@ -1643,8 +1643,7 @@ class InetAddress implements java.io.Serializable { * property can vary across implementations of the java. * classes. The default is an empty String "". */ - String prefix = AccessController.doPrivileged( - new GetPropertyAction("impl.prefix", "")); + String prefix = GetPropertyAction.getProperty("impl.prefix", ""); try { impl = Class.forName("java.net." + prefix + implName).newInstance(); } catch (ClassNotFoundException e) { diff --git a/jdk/src/java.base/share/classes/java/net/SocksSocketImpl.java b/jdk/src/java.base/share/classes/java/net/SocksSocketImpl.java index f7974d0d705fc4488f34a3fc92b7a5a4d96895d0..c3a0d1c675a011fe6efb57724b3d8affa379369f 100644 --- a/jdk/src/java.base/share/classes/java/net/SocksSocketImpl.java +++ b/jdk/src/java.base/share/classes/java/net/SocksSocketImpl.java @@ -33,6 +33,7 @@ import java.security.PrivilegedExceptionAction; import sun.net.SocksProxy; import sun.net.spi.DefaultProxySelector; import sun.net.www.ParseUtil; +import sun.security.action.GetPropertyAction; /* import org.ietf.jgss.*; */ /** @@ -177,8 +178,7 @@ class SocksSocketImpl extends PlainSocketImpl implements SocksConsts { userName = pw.getUserName(); password = new String(pw.getPassword()); } else { - userName = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("user.name")); + userName = GetPropertyAction.getProperty("user.name"); } if (userName == null) return false; @@ -1088,8 +1088,7 @@ class SocksSocketImpl extends PlainSocketImpl implements SocksConsts { userName = System.getProperty("user.name"); } catch (SecurityException se) { /* swallow Exception */ } } else { - userName = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("user.name")); + userName = GetPropertyAction.getProperty("user.name"); } return userName; } diff --git a/jdk/src/java.base/share/classes/java/net/URL.java b/jdk/src/java.base/share/classes/java/net/URL.java index cce9cf9425a04a5e3cc0bbb8a1412a64707fd42c..099e8b9e0c81480d72b42a6c89eed15a72b78c72 100644 --- a/jdk/src/java.base/share/classes/java/net/URL.java +++ b/jdk/src/java.base/share/classes/java/net/URL.java @@ -42,6 +42,7 @@ import java.util.ServiceConfigurationError; import java.util.ServiceLoader; import sun.security.util.SecurityConstants; +import sun.security.action.GetPropertyAction; /** * Class {@code URL} represents a Uniform Resource @@ -1210,12 +1211,8 @@ public final class URL implements java.io.Serializable { } private static URLStreamHandler lookupViaProperty(String protocol) { - String packagePrefixList = java.security.AccessController.doPrivileged( - new PrivilegedAction<>() { - public String run() { - return System.getProperty(protocolPathProp, null); - } - }); + String packagePrefixList = + GetPropertyAction.getProperty(protocolPathProp); if (packagePrefixList == null) { // not set return null; diff --git a/jdk/src/java.base/share/classes/java/net/URLConnection.java b/jdk/src/java.base/share/classes/java/net/URLConnection.java index 87f4378b2add27332f8f56e80aaeb700510040af..459a820bcdee34558759f83d8f931bdb57bf04eb 100644 --- a/jdk/src/java.base/share/classes/java/net/URLConnection.java +++ b/jdk/src/java.base/share/classes/java/net/URLConnection.java @@ -43,6 +43,7 @@ import java.security.Permission; import java.security.AccessController; import sun.security.util.SecurityConstants; import sun.net.www.MessageHeader; +import sun.security.action.GetPropertyAction; /** * The abstract class {@code URLConnection} is the superclass @@ -1395,8 +1396,8 @@ public abstract class URLConnection { * is always the last one on the returned package list. */ private String getContentHandlerPkgPrefixes() { - String packagePrefixList = AccessController.doPrivileged( - new sun.security.action.GetPropertyAction(contentPathProp, "")); + String packagePrefixList = + GetPropertyAction.getProperty(contentPathProp, ""); if (packagePrefixList != "") { packagePrefixList += "|"; diff --git a/jdk/src/java.base/share/classes/java/net/URLEncoder.java b/jdk/src/java.base/share/classes/java/net/URLEncoder.java index 5ad817bc72c84750d5b495e4e8e4c982313ab64a..2f2c3e6c9c408f291f1061d4a06cfbdd6a6fecfb 100644 --- a/jdk/src/java.base/share/classes/java/net/URLEncoder.java +++ b/jdk/src/java.base/share/classes/java/net/URLEncoder.java @@ -25,19 +25,12 @@ package java.net; -import java.io.ByteArrayOutputStream; -import java.io.BufferedWriter; -import java.io.OutputStreamWriter; -import java.io.IOException; import java.io.UnsupportedEncodingException; import java.io.CharArrayWriter; import java.nio.charset.Charset; import java.nio.charset.IllegalCharsetNameException; import java.nio.charset.UnsupportedCharsetException ; import java.util.BitSet; -import java.security.AccessController; -import java.security.PrivilegedAction; -import sun.security.action.GetBooleanAction; import sun.security.action.GetPropertyAction; /** @@ -140,9 +133,7 @@ public class URLEncoder { dontNeedEncoding.set('.'); dontNeedEncoding.set('*'); - dfltEncName = AccessController.doPrivileged( - new GetPropertyAction("file.encoding") - ); + dfltEncName = GetPropertyAction.getProperty("file.encoding"); } /** diff --git a/jdk/src/java.base/share/classes/java/net/URLPermission.java b/jdk/src/java.base/share/classes/java/net/URLPermission.java index 78373e1087f76a30dab7bcd22d5408c30d442001..e188c81d73b03c5763470f8bd9a427f99c7fcd94 100644 --- a/jdk/src/java.base/share/classes/java/net/URLPermission.java +++ b/jdk/src/java.base/share/classes/java/net/URLPermission.java @@ -170,7 +170,8 @@ public final class URLPermission extends Permission { parseURI(getName()); int colon = actions.indexOf(':'); if (actions.lastIndexOf(':') != colon) { - throw new IllegalArgumentException("invalid actions string"); + throw new IllegalArgumentException( + "Invalid actions string: \"" + actions + "\""); } String methods, headers; @@ -371,7 +372,8 @@ public final class URLPermission extends Permission { l.add(s); b = new StringBuilder(); } else if (c == ' ' || c == '\t') { - throw new IllegalArgumentException("white space not allowed"); + throw new IllegalArgumentException( + "White space not allowed in methods: \"" + methods + "\""); } else { if (c >= 'a' && c <= 'z') { c += 'A' - 'a'; @@ -398,7 +400,8 @@ public final class URLPermission extends Permission { } b.append(c); } else if (c == ' ' || c == '\t') { - throw new IllegalArgumentException("white space not allowed"); + throw new IllegalArgumentException( + "White space not allowed in headers: \"" + headers + "\""); } else if (c == '-') { capitalizeNext = true; b.append(c); @@ -423,14 +426,16 @@ public final class URLPermission extends Permission { int len = url.length(); int delim = url.indexOf(':'); if (delim == -1 || delim + 1 == len) { - throw new IllegalArgumentException("invalid URL string"); + throw new IllegalArgumentException( + "Invalid URL string: \"" + url + "\""); } scheme = url.substring(0, delim).toLowerCase(); this.ssp = url.substring(delim + 1); if (!ssp.startsWith("//")) { if (!ssp.equals("*")) { - throw new IllegalArgumentException("invalid URL string"); + throw new IllegalArgumentException( + "Invalid URL string: \"" + url + "\""); } this.authority = new Authority(scheme, "*"); return; diff --git a/jdk/src/java.base/share/classes/java/nio/charset/Charset.java b/jdk/src/java.base/share/classes/java/nio/charset/Charset.java index 78ee33e764adad10033c4e31229c2dcdaed9b038..de49a8c62712def27c6a4cf056b71c2f23e30219 100644 --- a/jdk/src/java.base/share/classes/java/nio/charset/Charset.java +++ b/jdk/src/java.base/share/classes/java/nio/charset/Charset.java @@ -283,8 +283,8 @@ public abstract class Charset if (level == null) { if (!VM.isBooted()) return false; - bugLevel = level = AccessController.doPrivileged( - new GetPropertyAction("sun.nio.cs.bugLevel", "")); + bugLevel = level = + GetPropertyAction.getProperty("sun.nio.cs.bugLevel", ""); } return level.equals(bl); } @@ -609,8 +609,7 @@ public abstract class Charset public static Charset defaultCharset() { if (defaultCharset == null) { synchronized (Charset.class) { - String csn = AccessController.doPrivileged( - new GetPropertyAction("file.encoding")); + String csn = GetPropertyAction.getProperty("file.encoding"); Charset cs = lookup(csn); if (cs != null) defaultCharset = cs; diff --git a/jdk/src/java.base/share/classes/java/nio/file/TempFileHelper.java b/jdk/src/java.base/share/classes/java/nio/file/TempFileHelper.java index 2bc3d992c60f0fa76cc439a70c8ca9d4b2537214..a6af1a15b1f78bbb9b577c086658609ad7b70229 100644 --- a/jdk/src/java.base/share/classes/java/nio/file/TempFileHelper.java +++ b/jdk/src/java.base/share/classes/java/nio/file/TempFileHelper.java @@ -28,7 +28,6 @@ package java.nio.file; import java.util.Set; import java.util.EnumSet; import java.security.SecureRandom; -import static java.security.AccessController.*; import java.io.IOException; import java.nio.file.attribute.FileAttribute; import java.nio.file.attribute.PosixFilePermission; @@ -47,7 +46,7 @@ class TempFileHelper { // temporary directory location private static final Path tmpdir = - Paths.get(doPrivileged(new GetPropertyAction("java.io.tmpdir"))); + Paths.get(GetPropertyAction.getProperty("java.io.tmpdir")); private static final boolean isPosix = FileSystems.getDefault().supportedFileAttributeViews().contains("posix"); diff --git a/jdk/src/java.base/share/classes/java/text/ChoiceFormat.java b/jdk/src/java.base/share/classes/java/text/ChoiceFormat.java index 8355dee87d4dd30249e458692e002b0cb7c7c1b2..98c66365c1b10aedba8ea98fb4ed34317e75c8e4 100644 --- a/jdk/src/java.base/share/classes/java/text/ChoiceFormat.java +++ b/jdk/src/java.base/share/classes/java/text/ChoiceFormat.java @@ -437,7 +437,7 @@ public class ChoiceFormat extends NumberFormat { if (status.index == start) { status.errorIndex = furthest; } - return new Double(bestNumber); + return Double.valueOf(bestNumber); } /** diff --git a/jdk/src/java.base/share/classes/java/text/DecimalFormat.java b/jdk/src/java.base/share/classes/java/text/DecimalFormat.java index a82011fd7d5dc110aff0bf633b7a5c2a346729ca..587a64e13f1e015b1fb797ddba369d3b7c125f95 100644 --- a/jdk/src/java.base/share/classes/java/text/DecimalFormat.java +++ b/jdk/src/java.base/share/classes/java/text/DecimalFormat.java @@ -1996,7 +1996,7 @@ public class DecimalFormat extends NumberFormat { // special case NaN if (text.regionMatches(pos.index, symbols.getNaN(), 0, symbols.getNaN().length())) { pos.index = pos.index + symbols.getNaN().length(); - return new Double(Double.NaN); + return Double.valueOf(Double.NaN); } boolean[] status = new boolean[STATUS_LENGTH]; @@ -2007,19 +2007,19 @@ public class DecimalFormat extends NumberFormat { // special case INFINITY if (status[STATUS_INFINITE]) { if (status[STATUS_POSITIVE] == (multiplier >= 0)) { - return new Double(Double.POSITIVE_INFINITY); + return Double.valueOf(Double.POSITIVE_INFINITY); } else { - return new Double(Double.NEGATIVE_INFINITY); + return Double.valueOf(Double.NEGATIVE_INFINITY); } } if (multiplier == 0) { if (digitList.isZero()) { - return new Double(Double.NaN); + return Double.valueOf(Double.NaN); } else if (status[STATUS_POSITIVE]) { - return new Double(Double.POSITIVE_INFINITY); + return Double.valueOf(Double.POSITIVE_INFINITY); } else { - return new Double(Double.NEGATIVE_INFINITY); + return Double.valueOf(Double.NEGATIVE_INFINITY); } } @@ -2093,8 +2093,8 @@ public class DecimalFormat extends NumberFormat { !isParseIntegerOnly(); } - return gotDouble ? - (Number)new Double(doubleResult) : (Number)Long.valueOf(longResult); + // cast inside of ?: because of binary numeric promotion, JLS 15.25 + return gotDouble ? (Number)doubleResult : (Number)longResult; } } diff --git a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java index 3478af25761fb541adb483e2f7298c5df7e3a8dd..9810a088b481b23ac3ff1468d71f6fc5dd77386b 100644 --- a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java +++ b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -284,6 +284,7 @@ import java.util.Set; * D day-of-year number 189 * M/L month-of-year number/text 7; 07; Jul; July; J * d day-of-month number 10 + * g modified-julian-day number 2451334 * * Q/q quarter-of-year number/text 3; 03; Q3; 3rd quarter * Y week-based-year year 1996; 96 @@ -308,10 +309,10 @@ import java.util.Set; * * V time-zone ID zone-id America/Los_Angeles; Z; -08:30 * z time-zone name zone-name Pacific Standard Time; PST - * O localized zone-offset offset-O GMT+8; GMT+08:00; UTC-08:00; - * X zone-offset 'Z' for zero offset-X Z; -08; -0830; -08:30; -083015; -08:30:15; - * x zone-offset offset-x +0000; -08; -0830; -08:30; -083015; -08:30:15; - * Z zone-offset offset-Z +0000; -0800; -08:00; + * O localized zone-offset offset-O GMT+8; GMT+08:00; UTC-08:00 + * X zone-offset 'Z' for zero offset-X Z; -08; -0830; -08:30; -083015; -08:30:15 + * x zone-offset offset-x +0000; -08; -0830; -08:30; -083015; -08:30:15 + * Z zone-offset offset-Z +0000; -0800; -08:00 * * p pad next pad modifier 1 * diff --git a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java index d7baf69c5b57fdb7323b27f5055940d3f7d60ab6..a36d1b5e1422de71dd26d73417d3b8fba12b046f 100644 --- a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java +++ b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -90,6 +90,7 @@ import java.time.chrono.IsoChronology; import java.time.format.DateTimeTextProvider.LocaleStore; import java.time.temporal.ChronoField; import java.time.temporal.IsoFields; +import java.time.temporal.JulianFields; import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalField; import java.time.temporal.TemporalQueries; @@ -666,8 +667,11 @@ public final class DateTimeFormatterBuilder { * No rounding occurs due to the maximum width - digits are simply dropped. *

* When parsing in strict mode, the number of parsed digits must be between - * the minimum and maximum width. When parsing in lenient mode, the minimum - * width is considered to be zero and the maximum is nine. + * the minimum and maximum width. In strict mode, if the minimum and maximum widths + * are equal and there is no decimal point then the parser will + * participate in adjacent value parsing, see + * {@link appendValue(java.time.temporal.TemporalField, int)}. When parsing in lenient mode, + * the minimum width is considered to be zero and the maximum is nine. *

* If the value cannot be obtained then an exception will be thrown. * If the value is negative an exception will be thrown. @@ -686,7 +690,12 @@ public final class DateTimeFormatterBuilder { */ public DateTimeFormatterBuilder appendFraction( TemporalField field, int minWidth, int maxWidth, boolean decimalPoint) { - appendInternal(new FractionPrinterParser(field, minWidth, maxWidth, decimalPoint)); + if (minWidth == maxWidth && decimalPoint == false) { + // adjacent parsing + appendValue(new FractionPrinterParser(field, minWidth, maxWidth, decimalPoint)); + } else { + appendInternal(new FractionPrinterParser(field, minWidth, maxWidth, decimalPoint)); + } return this; } @@ -1383,6 +1392,7 @@ public final class DateTimeFormatterBuilder { * D day-of-year number 189 * M/L month-of-year number/text 7; 07; Jul; July; J * d day-of-month number 10 + * g modified-julian-day number 2451334 * * Q/q quarter-of-year number/text 3; 03; Q3; 3rd quarter * Y week-based-year year 1996; 96 @@ -1408,9 +1418,9 @@ public final class DateTimeFormatterBuilder { * V time-zone ID zone-id America/Los_Angeles; Z; -08:30 * z time-zone name zone-name Pacific Standard Time; PST * O localized zone-offset offset-O GMT+8; GMT+08:00; UTC-08:00; - * X zone-offset 'Z' for zero offset-X Z; -08; -0830; -08:30; -083015; -08:30:15; - * x zone-offset offset-x +0000; -08; -0830; -08:30; -083015; -08:30:15; - * Z zone-offset offset-Z +0000; -0800; -08:00; + * X zone-offset 'Z' for zero offset-X Z; -08; -0830; -08:30; -083015; -08:30:15 + * x zone-offset offset-x +0000; -08; -0830; -08:30; -083015; -08:30:15 + * Z zone-offset offset-Z +0000; -0800; -08:00 * * p pad next pad modifier 1 * @@ -1437,37 +1447,37 @@ public final class DateTimeFormatterBuilder { * GGGG 4 appendText(ChronoField.ERA, TextStyle.FULL) * GGGGG 5 appendText(ChronoField.ERA, TextStyle.NARROW) * - * u 1 appendValue(ChronoField.YEAR, 1, 19, SignStyle.NORMAL); - * uu 2 appendValueReduced(ChronoField.YEAR, 2, 2000); - * uuu 3 appendValue(ChronoField.YEAR, 3, 19, SignStyle.NORMAL); - * u..u 4..n appendValue(ChronoField.YEAR, n, 19, SignStyle.EXCEEDS_PAD); - * y 1 appendValue(ChronoField.YEAR_OF_ERA, 1, 19, SignStyle.NORMAL); - * yy 2 appendValueReduced(ChronoField.YEAR_OF_ERA, 2, 2000); - * yyy 3 appendValue(ChronoField.YEAR_OF_ERA, 3, 19, SignStyle.NORMAL); - * y..y 4..n appendValue(ChronoField.YEAR_OF_ERA, n, 19, SignStyle.EXCEEDS_PAD); + * u 1 appendValue(ChronoField.YEAR, 1, 19, SignStyle.NORMAL) + * uu 2 appendValueReduced(ChronoField.YEAR, 2, 2000) + * uuu 3 appendValue(ChronoField.YEAR, 3, 19, SignStyle.NORMAL) + * u..u 4..n appendValue(ChronoField.YEAR, n, 19, SignStyle.EXCEEDS_PAD) + * y 1 appendValue(ChronoField.YEAR_OF_ERA, 1, 19, SignStyle.NORMAL) + * yy 2 appendValueReduced(ChronoField.YEAR_OF_ERA, 2, 2000) + * yyy 3 appendValue(ChronoField.YEAR_OF_ERA, 3, 19, SignStyle.NORMAL) + * y..y 4..n appendValue(ChronoField.YEAR_OF_ERA, n, 19, SignStyle.EXCEEDS_PAD) * Y 1 append special localized WeekFields element for numeric week-based-year - * YY 2 append special localized WeekFields element for reduced numeric week-based-year 2 digits; - * YYY 3 append special localized WeekFields element for numeric week-based-year (3, 19, SignStyle.NORMAL); - * Y..Y 4..n append special localized WeekFields element for numeric week-based-year (n, 19, SignStyle.EXCEEDS_PAD); + * YY 2 append special localized WeekFields element for reduced numeric week-based-year 2 digits + * YYY 3 append special localized WeekFields element for numeric week-based-year (3, 19, SignStyle.NORMAL) + * Y..Y 4..n append special localized WeekFields element for numeric week-based-year (n, 19, SignStyle.EXCEEDS_PAD) * - * Q 1 appendValue(IsoFields.QUARTER_OF_YEAR); - * QQ 2 appendValue(IsoFields.QUARTER_OF_YEAR, 2); + * Q 1 appendValue(IsoFields.QUARTER_OF_YEAR) + * QQ 2 appendValue(IsoFields.QUARTER_OF_YEAR, 2) * QQQ 3 appendText(IsoFields.QUARTER_OF_YEAR, TextStyle.SHORT) * QQQQ 4 appendText(IsoFields.QUARTER_OF_YEAR, TextStyle.FULL) * QQQQQ 5 appendText(IsoFields.QUARTER_OF_YEAR, TextStyle.NARROW) - * q 1 appendValue(IsoFields.QUARTER_OF_YEAR); - * qq 2 appendValue(IsoFields.QUARTER_OF_YEAR, 2); + * q 1 appendValue(IsoFields.QUARTER_OF_YEAR) + * qq 2 appendValue(IsoFields.QUARTER_OF_YEAR, 2) * qqq 3 appendText(IsoFields.QUARTER_OF_YEAR, TextStyle.SHORT_STANDALONE) * qqqq 4 appendText(IsoFields.QUARTER_OF_YEAR, TextStyle.FULL_STANDALONE) * qqqqq 5 appendText(IsoFields.QUARTER_OF_YEAR, TextStyle.NARROW_STANDALONE) * - * M 1 appendValue(ChronoField.MONTH_OF_YEAR); - * MM 2 appendValue(ChronoField.MONTH_OF_YEAR, 2); + * M 1 appendValue(ChronoField.MONTH_OF_YEAR) + * MM 2 appendValue(ChronoField.MONTH_OF_YEAR, 2) * MMM 3 appendText(ChronoField.MONTH_OF_YEAR, TextStyle.SHORT) * MMMM 4 appendText(ChronoField.MONTH_OF_YEAR, TextStyle.FULL) * MMMMM 5 appendText(ChronoField.MONTH_OF_YEAR, TextStyle.NARROW) - * L 1 appendValue(ChronoField.MONTH_OF_YEAR); - * LL 2 appendValue(ChronoField.MONTH_OF_YEAR, 2); + * L 1 appendValue(ChronoField.MONTH_OF_YEAR) + * LL 2 appendValue(ChronoField.MONTH_OF_YEAR, 2) * LLL 3 appendText(ChronoField.MONTH_OF_YEAR, TextStyle.SHORT_STANDALONE) * LLLL 4 appendText(ChronoField.MONTH_OF_YEAR, TextStyle.FULL_STANDALONE) * LLLLL 5 appendText(ChronoField.MONTH_OF_YEAR, TextStyle.NARROW_STANDALONE) @@ -1481,6 +1491,7 @@ public final class DateTimeFormatterBuilder { * DD 2 appendValue(ChronoField.DAY_OF_YEAR, 2) * DDD 3 appendValue(ChronoField.DAY_OF_YEAR, 3) * F 1 appendValue(ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH) + * g..g 1..n appendValue(JulianFields.MODIFIED_JULIAN_DAY, n, 19, SignStyle.NORMAL) * E 1 appendText(ChronoField.DAY_OF_WEEK, TextStyle.SHORT) * EE 2 appendText(ChronoField.DAY_OF_WEEK, TextStyle.SHORT) * EEE 3 appendText(ChronoField.DAY_OF_WEEK, TextStyle.SHORT) @@ -1539,8 +1550,8 @@ public final class DateTimeFormatterBuilder { *

      *  Pattern  Count  Equivalent builder methods
      *  -------  -----  --------------------------
-     *    O       1      appendLocalizedOffsetPrefixed(TextStyle.SHORT);
-     *    OOOO    4      appendLocalizedOffsetPrefixed(TextStyle.FULL);
+     *    O       1      appendLocalizedOffset(TextStyle.SHORT)
+     *    OOOO    4      appendLocalizedOffset(TextStyle.FULL)
      *    X       1      appendOffset("+HHmm","Z")
      *    XX      2      appendOffset("+HHMM","Z")
      *    XXX     3      appendOffset("+HH:MM","Z")
@@ -1554,7 +1565,7 @@ public final class DateTimeFormatterBuilder {
      *    Z       1      appendOffset("+HHMM","+0000")
      *    ZZ      2      appendOffset("+HHMM","+0000")
      *    ZZZ     3      appendOffset("+HHMM","+0000")
-     *    ZZZZ    4      appendLocalizedOffset(TextStyle.FULL);
+     *    ZZZZ    4      appendLocalizedOffset(TextStyle.FULL)
      *    ZZZZZ   5      appendOffset("+HH:MM:ss","Z")
      * 
*

@@ -1836,6 +1847,9 @@ public final class DateTimeFormatterBuilder { throw new IllegalArgumentException("Too many pattern letters: " + cur); } break; + case 'g': + appendValue(field, count, 19, SignStyle.NORMAL); + break; default: if (count == 1) { appendValue(field); @@ -1874,6 +1888,7 @@ public final class DateTimeFormatterBuilder { FIELD_MAP.put('A', ChronoField.MILLI_OF_DAY); // LDML FIELD_MAP.put('n', ChronoField.NANO_OF_SECOND); // 310 (proposed for LDML) FIELD_MAP.put('N', ChronoField.NANO_OF_DAY); // 310 (proposed for LDML) + FIELD_MAP.put('g', JulianFields.MODIFIED_JULIAN_DAY); // 310 - z - time-zone names, matches LDML and SimpleDateFormat 1 to 4 // 310 - Z - matches SimpleDateFormat and LDML // 310 - V - time-zone id, matches LDML @@ -1884,7 +1899,6 @@ public final class DateTimeFormatterBuilder { // LDML - U - cycle year name, not supported by 310 yet // LDML - l - deprecated // LDML - j - not relevant - // LDML - g - modified-julian-day // LDML - v,V - extended time-zone names } @@ -2919,11 +2933,8 @@ public final class DateTimeFormatterBuilder { /** * Prints and parses a numeric date-time field with optional padding. */ - static final class FractionPrinterParser implements DateTimePrinterParser { - private final TemporalField field; - private final int minWidth; - private final int maxWidth; - private final boolean decimalPoint; + static final class FractionPrinterParser extends NumberPrinterParser { + private final boolean decimalPoint; /** * Constructor. @@ -2934,6 +2945,7 @@ public final class DateTimeFormatterBuilder { * @param decimalPoint whether to output the localized decimal point symbol */ FractionPrinterParser(TemporalField field, int minWidth, int maxWidth, boolean decimalPoint) { + this(field, minWidth, maxWidth, decimalPoint, 0); Objects.requireNonNull(field, "field"); if (field.range().isFixed() == false) { throw new IllegalArgumentException("Field must have a fixed set of values: " + field); @@ -2948,12 +2960,61 @@ public final class DateTimeFormatterBuilder { throw new IllegalArgumentException("Maximum width must exceed or equal the minimum width but " + maxWidth + " < " + minWidth); } - this.field = field; - this.minWidth = minWidth; - this.maxWidth = maxWidth; + } + + /** + * Constructor. + * + * @param field the field to output, not null + * @param minWidth the minimum width to output, from 0 to 9 + * @param maxWidth the maximum width to output, from 0 to 9 + * @param decimalPoint whether to output the localized decimal point symbol + * @param subsequentWidth the subsequentWidth for this instance + */ + FractionPrinterParser(TemporalField field, int minWidth, int maxWidth, boolean decimalPoint, int subsequentWidth) { + super(field, minWidth, maxWidth, SignStyle.NOT_NEGATIVE, subsequentWidth); this.decimalPoint = decimalPoint; } + /** + * Returns a new instance with fixed width flag set. + * + * @return a new updated printer-parser, not null + */ + @Override + FractionPrinterParser withFixedWidth() { + if (subsequentWidth == -1) { + return this; + } + return new FractionPrinterParser(field, minWidth, maxWidth, decimalPoint, -1); + } + + /** + * Returns a new instance with an updated subsequent width. + * + * @param subsequentWidth the width of subsequent non-negative numbers, 0 or greater + * @return a new updated printer-parser, not null + */ + @Override + FractionPrinterParser withSubsequentWidth(int subsequentWidth) { + return new FractionPrinterParser(field, minWidth, maxWidth, decimalPoint, this.subsequentWidth + subsequentWidth); + } + + /** + * For FractionPrinterPrinterParser, the width is fixed if context is sttrict, + * minWidth equal to maxWidth and decimalpoint is absent. + * @param context the context + * @return if the field is fixed width + * @see DateTimeFormatterBuilder#appendValueFraction(java.time.temporal.TemporalField, int, int, boolean) + */ + @Override + boolean isFixedWidth(DateTimeParseContext context) { + if (context.isStrict() && minWidth == maxWidth && decimalPoint == false) { + return true; + } + return false; + } + @Override public boolean format(DateTimePrintContext context, StringBuilder buf) { Long value = context.getValue(field); @@ -2986,8 +3047,8 @@ public final class DateTimeFormatterBuilder { @Override public int parse(DateTimeParseContext context, CharSequence text, int position) { - int effectiveMin = (context.isStrict() ? minWidth : 0); - int effectiveMax = (context.isStrict() ? maxWidth : 9); + int effectiveMin = (context.isStrict() || isFixedWidth(context) ? minWidth : 0); + int effectiveMax = (context.isStrict() || isFixedWidth(context) ? maxWidth : 9); int length = text.length(); if (position == length) { // valid if whole field is optional, invalid if minimum width @@ -3519,9 +3580,7 @@ public final class DateTimeFormatterBuilder { return false; } String gmtText = "GMT"; // TODO: get localized version of 'GMT' - if (gmtText != null) { - buf.append(gmtText); - } + buf.append(gmtText); int totalSecs = Math.toIntExact(offsetSecs); if (totalSecs != 0) { int absHours = Math.abs((totalSecs / 3600) % 100); // anything larger than 99 silently dropped @@ -3565,14 +3624,12 @@ public final class DateTimeFormatterBuilder { @Override public int parse(DateTimeParseContext context, CharSequence text, int position) { int pos = position; - int end = pos + text.length(); + int end = text.length(); String gmtText = "GMT"; // TODO: get localized version of 'GMT' - if (gmtText != null) { - if (!context.subSequenceEquals(text, pos, gmtText, 0, gmtText.length())) { + if (!context.subSequenceEquals(text, pos, gmtText, 0, gmtText.length())) { return ~position; } - pos += gmtText.length(); - } + pos += gmtText.length(); // parse normal plus/minus offset int negative = 0; if (pos == end) { diff --git a/jdk/src/java.base/share/classes/java/time/temporal/JulianFields.java b/jdk/src/java.base/share/classes/java/time/temporal/JulianFields.java index 327037981eb4799666221ce3d36e7bffae6b016a..7fc501cb9dd948e206362f472c1c1e1236b8c21c 100644 --- a/jdk/src/java.base/share/classes/java/time/temporal/JulianFields.java +++ b/jdk/src/java.base/share/classes/java/time/temporal/JulianFields.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * 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,7 +117,13 @@ public final class JulianFields { * *

Astronomical and Scientific Notes

* The standard astronomical definition uses a fraction to indicate the time-of-day, - * thus 3.25 would represent the time 18:00, since days start at midday. + * where each day is counted from midday to midday. For example, + * a fraction of 0 represents midday, a fraction of 0.25 + * represents 18:00, a fraction of 0.5 represents midnight and a fraction + * of 0.75 represents 06:00. + *

+ * By contrast, this implementation has no fractional part, and counts + * days from midnight to midnight. * This implementation uses an integer and days starting at midnight. * The integer value for the Julian Day Number is the astronomical Julian Day value at midday * of the date in question. diff --git a/jdk/src/java.base/share/classes/java/util/Locale.java b/jdk/src/java.base/share/classes/java/util/Locale.java index 2d121e2e7ef3012c1a8f22512b7773f4182fdb97..e05904f6f6bdf04a1769fbd8e185d3a4ebf7ab42 100644 --- a/jdk/src/java.base/share/classes/java/util/Locale.java +++ b/jdk/src/java.base/share/classes/java/util/Locale.java @@ -45,7 +45,6 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.ObjectStreamField; import java.io.Serializable; -import java.security.AccessController; import java.text.MessageFormat; import java.util.spi.LocaleNameProvider; @@ -859,11 +858,10 @@ public final class Locale implements Cloneable, Serializable { private static Locale initDefault() { String language, region, script, country, variant; - language = AccessController.doPrivileged( - new GetPropertyAction("user.language", "en")); + Properties props = GetPropertyAction.getProperties(); + language = props.getProperty("user.language", "en"); // for compatibility, check for old user.region property - region = AccessController.doPrivileged( - new GetPropertyAction("user.region")); + region = props.getProperty("user.region"); if (region != null) { // region can be of form country, country_variant, or _variant int i = region.indexOf('_'); @@ -876,27 +874,25 @@ public final class Locale implements Cloneable, Serializable { } script = ""; } else { - script = AccessController.doPrivileged( - new GetPropertyAction("user.script", "")); - country = AccessController.doPrivileged( - new GetPropertyAction("user.country", "")); - variant = AccessController.doPrivileged( - new GetPropertyAction("user.variant", "")); + script = props.getProperty("user.script", ""); + country = props.getProperty("user.country", ""); + variant = props.getProperty("user.variant", ""); } return getInstance(language, script, country, variant, null); } private static Locale initDefault(Locale.Category category) { + Properties props = GetPropertyAction.getProperties(); return getInstance( - AccessController.doPrivileged( - new GetPropertyAction(category.languageKey, defaultLocale.getLanguage())), - AccessController.doPrivileged( - new GetPropertyAction(category.scriptKey, defaultLocale.getScript())), - AccessController.doPrivileged( - new GetPropertyAction(category.countryKey, defaultLocale.getCountry())), - AccessController.doPrivileged( - new GetPropertyAction(category.variantKey, defaultLocale.getVariant())), + props.getProperty(category.languageKey, + defaultLocale.getLanguage()), + props.getProperty(category.scriptKey, + defaultLocale.getScript()), + props.getProperty(category.countryKey, + defaultLocale.getCountry()), + props.getProperty(category.variantKey, + defaultLocale.getVariant()), null); } diff --git a/jdk/src/java.base/share/classes/java/util/PropertyResourceBundle.java b/jdk/src/java.base/share/classes/java/util/PropertyResourceBundle.java index 58ff757026970a2096bf235c4b37885a9073f091..9c20a68073313091694a4c052b9c7b68db970880 100644 --- a/jdk/src/java.base/share/classes/java/util/PropertyResourceBundle.java +++ b/jdk/src/java.base/share/classes/java/util/PropertyResourceBundle.java @@ -43,7 +43,6 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.io.IOException; -import java.nio.charset.Charset; import java.nio.charset.MalformedInputException; import java.nio.charset.StandardCharsets; import java.nio.charset.UnmappableCharacterException; @@ -142,8 +141,8 @@ public class PropertyResourceBundle extends ResourceBundle { // Check whether the strict encoding is specified. // The possible encoding is either "ISO-8859-1" or "UTF-8". private static final String encoding = - AccessController.doPrivileged( - new GetPropertyAction("java.util.PropertyResourceBundle.encoding", "")) + GetPropertyAction + .getProperty("java.util.PropertyResourceBundle.encoding", "") .toUpperCase(Locale.ROOT); /** diff --git a/jdk/src/java.base/share/classes/java/util/TimeZone.java b/jdk/src/java.base/share/classes/java/util/TimeZone.java index 3bf886b2721584170c67e522cc9bff3aa0248dd3..22c382cb0a2fa06512677afe02aee3106d803c4d 100644 --- a/jdk/src/java.base/share/classes/java/util/TimeZone.java +++ b/jdk/src/java.base/share/classes/java/util/TimeZone.java @@ -660,14 +660,12 @@ public abstract class TimeZone implements Serializable, Cloneable { private static synchronized TimeZone setDefaultZone() { TimeZone tz; // get the time zone ID from the system properties - String zoneID = AccessController.doPrivileged( - new GetPropertyAction("user.timezone")); + String zoneID = GetPropertyAction.getProperty("user.timezone"); // if the time zone ID is not set (yet), perform the // platform to Java time zone ID mapping. if (zoneID == null || zoneID.isEmpty()) { - String javaHome = AccessController.doPrivileged( - new GetPropertyAction("java.home")); + String javaHome = GetPropertyAction.getProperty("java.home"); try { zoneID = getSystemTimeZoneID(javaHome); if (zoneID == null) { diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java index 69ecc46cf6d736fd8ea2bdbbbe62ff2981b1daa0..2af74b209619027cdcc85b3584f3ab1111478816 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java @@ -455,7 +455,7 @@ public class ThreadLocalRandom extends Random { s = v1 * v1 + v2 * v2; } while (s >= 1 || s == 0); double multiplier = StrictMath.sqrt(-2 * StrictMath.log(s)/s); - nextLocalGaussian.set(new Double(v2 * multiplier)); + nextLocalGaussian.set(Double.valueOf(v2 * multiplier)); return v1 * multiplier; } 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 f28750c3a9784447ac37f89f6950adc7913cc266..ff26faad4f49f1850f2eb0a4efb08d7903e5d2ad 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 @@ -34,7 +34,6 @@ import java.util.stream.StreamSupport; import java.util.zip.*; import java.security.CodeSigner; import java.security.cert.Certificate; -import java.security.AccessController; import java.security.CodeSource; import jdk.internal.misc.SharedSecrets; import sun.security.action.GetPropertyAction; @@ -155,16 +154,16 @@ class JarFile extends ZipFile { BASE_VERSION = 8; // one less than lowest version for versioned entries int runtimeVersion = jdk.Version.current().major(); - String jarVersion = AccessController.doPrivileged( - new GetPropertyAction("jdk.util.jar.version")); + String jarVersion = + GetPropertyAction.getProperty("jdk.util.jar.version"); if (jarVersion != null) { int jarVer = Integer.parseInt(jarVersion); runtimeVersion = (jarVer > runtimeVersion) ? runtimeVersion : Math.max(jarVer, 0); } RUNTIME_VERSION = runtimeVersion; - String enableMultiRelease = AccessController.doPrivileged( - new GetPropertyAction("jdk.util.jar.enableMultiRelease", "true")); + String enableMultiRelease = GetPropertyAction + .getProperty("jdk.util.jar.enableMultiRelease", "true"); switch (enableMultiRelease) { case "true": default: diff --git a/jdk/src/java.base/share/classes/java/util/jar/Pack200.java b/jdk/src/java.base/share/classes/java/util/jar/Pack200.java index 44f1cccd0809ab67f5324696f89c7a86f9c60b9b..ac47ad12032e04cb6d20f8fae50b016873c3e6d7 100644 --- a/jdk/src/java.base/share/classes/java/util/jar/Pack200.java +++ b/jdk/src/java.base/share/classes/java/util/jar/Pack200.java @@ -29,6 +29,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.File; import java.io.IOException; +import sun.security.action.GetPropertyAction; /** @@ -694,8 +695,7 @@ public abstract class Pack200 { Class impl = (PACK_PROVIDER.equals(prop))? packerImpl: unpackerImpl; if (impl == null) { // The first time, we must decide which class to use. - implName = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction(prop,"")); + implName = GetPropertyAction.getProperty(prop,""); if (implName != null && !implName.equals("")) impl = Class.forName(implName); else if (PACK_PROVIDER.equals(prop)) diff --git a/jdk/src/java.base/share/classes/java/util/regex/PatternSyntaxException.java b/jdk/src/java.base/share/classes/java/util/regex/PatternSyntaxException.java index 94d7abc78a58104671ccd835ddff27b317a3bd76..f7768da27da30044d96d16b5450024ad2b989df8 100644 --- a/jdk/src/java.base/share/classes/java/util/regex/PatternSyntaxException.java +++ b/jdk/src/java.base/share/classes/java/util/regex/PatternSyntaxException.java @@ -94,8 +94,7 @@ public class PatternSyntaxException } private static final String nl = - java.security.AccessController - .doPrivileged(new GetPropertyAction("line.separator")); + GetPropertyAction.getProperty("line.separator"); /** * Returns a multi-line string containing the description of the syntax diff --git a/jdk/src/java.base/share/classes/java/util/zip/ZipOutputStream.java b/jdk/src/java.base/share/classes/java/util/zip/ZipOutputStream.java index 6b480aa1d5eaf7d0bf92e457d1cb41e733d145e1..ff76017651b32f8da435cbd355e3d1fd8c7af742 100644 --- a/jdk/src/java.base/share/classes/java/util/zip/ZipOutputStream.java +++ b/jdk/src/java.base/share/classes/java/util/zip/ZipOutputStream.java @@ -33,6 +33,7 @@ import java.util.Vector; import java.util.HashSet; import static java.util.zip.ZipConstants64.*; import static java.util.zip.ZipUtils.*; +import sun.security.action.GetPropertyAction; /** * This class implements an output stream filter for writing files in the @@ -54,9 +55,7 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants { */ private static final boolean inhibitZip64 = Boolean.parseBoolean( - java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction( - "jdk.util.zip.inhibitZip64", "false"))); + GetPropertyAction.getProperty("jdk.util.zip.inhibitZip64")); private static class XEntry { final ZipEntry entry; diff --git a/jdk/src/java.base/share/classes/javax/net/ssl/SSLSocketFactory.java b/jdk/src/java.base/share/classes/javax/net/ssl/SSLSocketFactory.java index 316016aac35fdde2024550beb00b15873740e84b..b436414308fe5c1a7a9c2e18641a712497913679 100644 --- a/jdk/src/java.base/share/classes/javax/net/ssl/SSLSocketFactory.java +++ b/jdk/src/java.base/share/classes/javax/net/ssl/SSLSocketFactory.java @@ -51,9 +51,9 @@ public abstract class SSLSocketFactory extends SocketFactory static final boolean DEBUG; static { - String s = java.security.AccessController.doPrivileged( - new GetPropertyAction("javax.net.debug", "")).toLowerCase( - Locale.ENGLISH); + String s = GetPropertyAction.getProperty("javax.net.debug", "") + .toLowerCase(Locale.ENGLISH); + DEBUG = s.contains("all") || s.contains("ssl"); } diff --git a/jdk/src/java.base/share/classes/jdk/Version.java b/jdk/src/java.base/share/classes/jdk/Version.java index 75c6b35c444270f02455fb1ff55d8acd42a42daa..756af9ec05171194f5bb3ada4bb75a6067e79ad1 100644 --- a/jdk/src/java.base/share/classes/jdk/Version.java +++ b/jdk/src/java.base/share/classes/jdk/Version.java @@ -26,8 +26,6 @@ package jdk; import java.math.BigInteger; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -35,6 +33,7 @@ import java.util.stream.Collectors; import java.util.Collections; import java.util.List; import java.util.Optional; +import sun.security.action.GetPropertyAction; /** * A representation of the JDK version-string which contains a version @@ -274,12 +273,7 @@ public final class Version */ public static Version current() { if (current == null) { - current = parse(AccessController.doPrivileged( - new PrivilegedAction<>() { - public String run() { - return System.getProperty("java.version"); - } - })); + current = parse(GetPropertyAction.getProperty("java.version")); } return current; } diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java index 4c70a9b15478d1a79638c6fa6756b7a76765a9bd..9b21fb6c1be39eb22fec0f761389d1d316843c20 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java +++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java @@ -183,7 +183,9 @@ public class BasicImageReader implements AutoCloseable { } public static void releaseByteBuffer(ByteBuffer buffer) { - ImageBufferCache.releaseBuffer(buffer); + if (!MAP_ALL) { + ImageBufferCache.releaseBuffer(buffer); + } } public String getName() { diff --git a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java index 41a51b88acf0c973922c37551b5933fe0001879c..2c78ea9e5d5072e6f1acaa94f0df9e612e4022f6 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java +++ b/jdk/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java @@ -25,6 +25,7 @@ package jdk.internal.jimage; import java.io.IOException; +import java.io.InputStream; import java.io.UncheckedIOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -36,8 +37,11 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.function.Consumer; /** @@ -47,80 +51,486 @@ import java.util.function.Consumer; * but also compiled and delivered as part of the jrtfs.jar to support access * to the jimage file provided by the shipped JDK by tools running on JDK 8. */ -public class ImageReader extends BasicImageReader { +public final class ImageReader implements AutoCloseable { + private SharedImageReader reader; - private static final int SIZE_OF_OFFSET = 4; + private ImageReader(SharedImageReader reader) { + this.reader = reader; + } - // Map of files opened as LITTLE_ENDIAN - private static final HashMap OPEN_LE_FILES - = new HashMap<>(); + public static ImageReader open(Path imagePath, ByteOrder byteOrder) throws IOException { + return SharedImageReader.open(imagePath, byteOrder); + } - // Map of files opened as BIG_ENDIAN - private static final HashMap OPEN_BE_FILES - = new HashMap<>(); + public static ImageReader open(Path imagePath) throws IOException { + return open(imagePath, ByteOrder.nativeOrder()); + } - private int openCount; + @Override + public void close() throws IOException { + if (reader == null) { + throw new IOException("image file already closed"); + } - // attributes of the .jimage file. jimage file does not contain - // attributes for the individual resources (yet). We use attributes - // of the jimage file itself (creation, modification, access times). - // Iniitalized lazily, see {@link #imageFileAttributes()}. - private BasicFileAttributes imageFileAttributes; + reader.close(this); + reader = null; + } - // directory management implementation - private final HashMap nodes; - private volatile Directory rootDir; + // directory management interface + public Directory getRootDirectory() throws IOException { + if (reader == null) { + throw new IOException("image file closed"); + } + return reader.getRootDirectory(); + } - private Directory packagesDir; - private Directory modulesDir; + public Node findNode(String name) throws IOException { + if (reader == null) { + throw new IOException("image file closed"); + } + return reader.findNode(name); + } - private ImageReader(Path imagePath, ByteOrder byteOrder) throws IOException { - super(imagePath, byteOrder); - this.nodes = new HashMap<>(); + public byte[] getResource(Node node) throws IOException { + if (reader == null) { + throw new IOException("image file closed"); + } + return reader.getResource(node); } - public static ImageReader open(Path imagePath, ByteOrder byteOrder) throws IOException { - HashMap openFiles = getOpenFilesMap(byteOrder); - ImageReader reader; - synchronized (openFiles) { - reader = openFiles.get(imagePath); - if (reader == null) { - reader = new ImageReader(imagePath, byteOrder); - ImageReader existingReader = openFiles.putIfAbsent(imagePath, reader); - assert (existingReader == null); - } - reader.openCount++; + public byte[] getResource(Resource rs) throws IOException { + if (reader == null) { + throw new IOException("image file closed"); } - return reader; + return reader.getResource(rs); } - private static HashMap getOpenFilesMap(ByteOrder byteOrder) { - return (byteOrder == ByteOrder.BIG_ENDIAN) ? OPEN_BE_FILES : OPEN_LE_FILES; + public ImageHeader getHeader() { + Objects.requireNonNull(reader, "image file closed"); + return reader.getHeader(); } - /** - * Opens the given file path as an image file, returning an {@code ImageReader}. - */ - public static ImageReader open(Path imagePath) throws IOException { - return open(imagePath, ByteOrder.nativeOrder()); + public static void releaseByteBuffer(ByteBuffer buffer) { + BasicImageReader.releaseByteBuffer(buffer); + } + + public String getName() { + Objects.requireNonNull(reader, "image file closed"); + return reader.getName() ; + } + + public ByteOrder getByteOrder() { + Objects.requireNonNull(reader, "image file closed"); + return reader.getByteOrder(); + } + + public Path getImagePath() { + Objects.requireNonNull(reader, "image file closed"); + return reader.getImagePath(); + } + + public ImageStringsReader getStrings() { + Objects.requireNonNull(reader, "image file closed"); + return reader.getStrings(); + } + + public ImageLocation findLocation(String mn, String rn) { + Objects.requireNonNull(reader, "image file closed"); + return reader.findLocation(mn, rn); + } + + public ImageLocation findLocation(String name) { + Objects.requireNonNull(reader, "image file closed"); + return reader.findLocation(name); + } + + public String[] getEntryNames() { + Objects.requireNonNull(reader, "image file closed"); + return reader.getEntryNames(); + } + + public long[] getAttributes(int offset) { + Objects.requireNonNull(reader, "image file closed"); + return reader.getAttributes(offset); + } + + public String getString(int offset) { + Objects.requireNonNull(reader, "image file closed"); + return reader.getString(offset); + } + + public byte[] getResource(String name) { + Objects.requireNonNull(reader, "image file closed"); + return reader.getResource(name); } - private boolean canClose() { - HashMap openFiles = getOpenFilesMap(this.getByteOrder()); - synchronized (openFiles) { - if (--this.openCount == 0) { - return openFiles.remove(this.getName(), this); + public byte[] getResource(ImageLocation loc) { + Objects.requireNonNull(reader, "image file closed"); + return reader.getResource(loc); + } + + public ByteBuffer getResourceBuffer(ImageLocation loc) { + Objects.requireNonNull(reader, "image file closed"); + return reader.getResourceBuffer(loc); + } + + public InputStream getResourceStream(ImageLocation loc) { + Objects.requireNonNull(reader, "image file closed"); + return reader.getResourceStream(loc); + } + + private final static class SharedImageReader extends BasicImageReader { + static final int SIZE_OF_OFFSET = Integer.BYTES; + + static final Map OPEN_FILES = new HashMap<>(); + + // List of openers for this shared image. + final Set openers; + + // attributes of the .jimage file. jimage file does not contain + // attributes for the individual resources (yet). We use attributes + // of the jimage file itself (creation, modification, access times). + // Iniitalized lazily, see {@link #imageFileAttributes()}. + BasicFileAttributes imageFileAttributes; + + // directory management implementation + final HashMap nodes; + volatile Directory rootDir; + + Directory packagesDir; + Directory modulesDir; + + private SharedImageReader(Path imagePath, ByteOrder byteOrder) throws IOException { + super(imagePath, byteOrder); + this.openers = new HashSet<>(); + this.nodes = new HashMap<>(); + } + + public static ImageReader open(Path imagePath, ByteOrder byteOrder) throws IOException { + synchronized (OPEN_FILES) { + SharedImageReader reader = OPEN_FILES.get(imagePath); + + if (reader == null) { + // Will fail with an IOException if wrong byteOrder. + reader = new SharedImageReader(imagePath, byteOrder); + OPEN_FILES.put(imagePath, reader); + } else if (reader.getByteOrder() != byteOrder) { + throw new IOException("\"" + reader.getName() + "\" is not an image file"); + } + + ImageReader image = new ImageReader(reader); + reader.openers.add(image); + + return image; } } - return false; - } - @Override - public void close() throws IOException { - if (canClose()) { - super.close(); - clearNodes(); - } + public void close(ImageReader image) throws IOException { + synchronized (OPEN_FILES) { + if (!openers.remove(image)) { + throw new IOException("image file already closed"); + } + + if (openers.isEmpty()) { + close(); + nodes.clear(); + rootDir = null; + + if (!OPEN_FILES.remove(this.getImagePath(), this)) { + throw new IOException("image file not found in open list"); + } + } + } + } + + void addOpener(ImageReader reader) { + synchronized (OPEN_FILES) { + openers.add(reader); + } + } + + boolean removeOpener(ImageReader reader) { + synchronized (OPEN_FILES) { + return openers.remove(reader); + } + } + + // directory management interface + Directory getRootDirectory() { + return buildRootDirectory(); + } + + /** + * Lazily build a node from a name. + */ + synchronized Node buildNode(String name) { + Node n; + boolean isPackages = name.startsWith("/packages"); + boolean isModules = !isPackages && name.startsWith("/modules"); + + if (!(isModules || isPackages)) { + return null; + } + + ImageLocation loc = findLocation(name); + + if (loc != null) { // A sub tree node + if (isPackages) { + n = handlePackages(name, loc); + } else { // modules sub tree + n = handleModulesSubTree(name, loc); + } + } else { // Asking for a resource? /modules/java.base/java/lang/Object.class + if (isModules) { + n = handleResource(name); + } else { + // Possibly ask for /packages/java.lang/java.base + // although /packages/java.base not created + n = handleModuleLink(name); + } + } + return n; + } + + synchronized Directory buildRootDirectory() { + Directory root = rootDir; // volatile read + if (root != null) { + return root; + } + + root = newDirectory(null, "/"); + root.setIsRootDir(); + + // /packages dir + packagesDir = newDirectory(root, "/packages"); + packagesDir.setIsPackagesDir(); + + // /modules dir + modulesDir = newDirectory(root, "/modules"); + modulesDir.setIsModulesDir(); + + root.setCompleted(true); + return rootDir = root; + } + + /** + * To visit sub tree resources. + */ + interface LocationVisitor { + void visit(ImageLocation loc); + } + + void visitLocation(ImageLocation loc, LocationVisitor visitor) { + byte[] offsets = getResource(loc); + ByteBuffer buffer = ByteBuffer.wrap(offsets); + buffer.order(getByteOrder()); + IntBuffer intBuffer = buffer.asIntBuffer(); + for (int i = 0; i < offsets.length / SIZE_OF_OFFSET; i++) { + int offset = intBuffer.get(i); + ImageLocation pkgLoc = getLocation(offset); + visitor.visit(pkgLoc); + } + } + + void visitPackageLocation(ImageLocation loc) { + // Retrieve package name + String pkgName = getBaseExt(loc); + // Content is array of offsets in Strings table + byte[] stringsOffsets = getResource(loc); + ByteBuffer buffer = ByteBuffer.wrap(stringsOffsets); + buffer.order(getByteOrder()); + IntBuffer intBuffer = buffer.asIntBuffer(); + // For each module, create a link node. + for (int i = 0; i < stringsOffsets.length / SIZE_OF_OFFSET; i++) { + // skip empty state, useless. + intBuffer.get(i); + i++; + int offset = intBuffer.get(i); + String moduleName = getString(offset); + Node targetNode = findNode("/modules/" + moduleName); + if (targetNode != null) { + String pkgDirName = packagesDir.getName() + "/" + pkgName; + Directory pkgDir = (Directory) nodes.get(pkgDirName); + newLinkNode(pkgDir, pkgDir.getName() + "/" + moduleName, targetNode); + } + } + } + + Node handlePackages(String name, ImageLocation loc) { + long size = loc.getUncompressedSize(); + Node n = null; + // Only possiblities are /packages, /packages/package/module + if (name.equals("/packages")) { + visitLocation(loc, (childloc) -> { + findNode(childloc.getFullName()); + }); + packagesDir.setCompleted(true); + n = packagesDir; + } else { + if (size != 0) { // children are offsets to module in StringsTable + String pkgName = getBaseExt(loc); + Directory pkgDir = newDirectory(packagesDir, packagesDir.getName() + "/" + pkgName); + visitPackageLocation(loc); + pkgDir.setCompleted(true); + n = pkgDir; + } else { // Link to module + String pkgName = loc.getParent(); + String modName = getBaseExt(loc); + Node targetNode = findNode("/modules/" + modName); + if (targetNode != null) { + String pkgDirName = packagesDir.getName() + "/" + pkgName; + Directory pkgDir = (Directory) nodes.get(pkgDirName); + Node linkNode = newLinkNode(pkgDir, pkgDir.getName() + "/" + modName, targetNode); + n = linkNode; + } + } + } + return n; + } + + // Asking for /packages/package/module although + // /packages// not yet created, need to create it + // prior to return the link to module node. + Node handleModuleLink(String name) { + // eg: unresolved /packages/package/module + // Build /packages/package node + Node ret = null; + String radical = "/packages/"; + String path = name; + if (path.startsWith(radical)) { + int start = radical.length(); + int pkgEnd = path.indexOf('/', start); + if (pkgEnd != -1) { + String pkg = path.substring(start, pkgEnd); + String pkgPath = radical + pkg; + Node n = findNode(pkgPath); + // If not found means that this is a symbolic link such as: + // /packages/java.util/java.base/java/util/Vector.class + // and will be done by a retry of the filesystem + for (Node child : n.getChildren()) { + if (child.name.equals(name)) { + ret = child; + break; + } + } + } + } + return ret; + } + + Node handleModulesSubTree(String name, ImageLocation loc) { + Node n; + assert (name.equals(loc.getFullName())); + Directory dir = makeDirectories(name); + visitLocation(loc, (childloc) -> { + String path = childloc.getFullName(); + if (path.startsWith("/modules")) { // a package + makeDirectories(path); + } else { // a resource + makeDirectories(childloc.buildName(true, true, false)); + newResource(dir, childloc); + } + }); + dir.setCompleted(true); + n = dir; + return n; + } + + Node handleResource(String name) { + Node n = null; + String locationPath = name.substring("/modules".length()); + ImageLocation resourceLoc = findLocation(locationPath); + if (resourceLoc != null) { + Directory dir = makeDirectories(resourceLoc.buildName(true, true, false)); + Resource res = newResource(dir, resourceLoc); + n = res; + } + return n; + } + + String getBaseExt(ImageLocation loc) { + String base = loc.getBase(); + String ext = loc.getExtension(); + if (ext != null && !ext.isEmpty()) { + base = base + "." + ext; + } + return base; + } + + synchronized Node findNode(String name) { + buildRootDirectory(); + Node n = nodes.get(name); + if (n == null || !n.isCompleted()) { + n = buildNode(name); + } + return n; + } + + /** + * Returns the file attributes of the image file. + */ + BasicFileAttributes imageFileAttributes() { + BasicFileAttributes attrs = imageFileAttributes; + if (attrs == null) { + try { + Path file = getImagePath(); + attrs = Files.readAttributes(file, BasicFileAttributes.class); + } catch (IOException ioe) { + throw new UncheckedIOException(ioe); + } + imageFileAttributes = attrs; + } + return attrs; + } + + Directory newDirectory(Directory parent, String name) { + Directory dir = Directory.create(parent, name, imageFileAttributes()); + nodes.put(dir.getName(), dir); + return dir; + } + + Resource newResource(Directory parent, ImageLocation loc) { + Resource res = Resource.create(parent, loc, imageFileAttributes()); + nodes.put(res.getName(), res); + return res; + } + + LinkNode newLinkNode(Directory dir, String name, Node link) { + LinkNode linkNode = LinkNode.create(dir, name, link); + nodes.put(linkNode.getName(), linkNode); + return linkNode; + } + + Directory makeDirectories(String parent) { + Directory last = rootDir; + for (int offset = parent.indexOf('/', 1); + offset != -1; + offset = parent.indexOf('/', offset + 1)) { + String dir = parent.substring(0, offset); + last = makeDirectory(dir, last); + } + return makeDirectory(parent, last); + + } + + Directory makeDirectory(String dir, Directory last) { + Directory nextDir = (Directory) nodes.get(dir); + if (nextDir == null) { + nextDir = newDirectory(last, dir); + } + return nextDir; + } + + byte[] getResource(Node node) throws IOException { + if (node.isResource()) { + return super.getResource(node.getLocation()); + } + throw new IOException("Not a resource: " + node); + } + + byte[] getResource(Resource rs) throws IOException { + return super.getResource(rs.getLocation()); + } } // jimage file does not store directory structure. We build nodes @@ -389,7 +799,7 @@ public class ImageReader extends BasicImageReader { @Override public Node resolveLink(boolean recursive) { - return recursive && (link instanceof LinkNode)? ((LinkNode)link).resolveLink(true) : link; + return (recursive && link instanceof LinkNode) ? ((LinkNode)link).resolveLink(true) : link; } @Override @@ -397,297 +807,4 @@ public class ImageReader extends BasicImageReader { return true; } } - - // directory management interface - public Directory getRootDirectory() { - return buildRootDirectory(); - } - - /** - * To visit sub tree resources. - */ - interface LocationVisitor { - - void visit(ImageLocation loc); - } - - /** - * Lazily build a node from a name. - */ - private Node buildNode(String name) { - Node n; - boolean isPackages = name.startsWith("/packages"); - boolean isModules = !isPackages && name.startsWith("/modules"); - - if (!(isModules || isPackages)) { - return null; - } - - ImageLocation loc = findLocation(name); - - if (loc != null) { // A sub tree node - if (isPackages) { - n = handlePackages(name, loc); - } else { // modules sub tree - n = handleModulesSubTree(name, loc); - } - } else { // Asking for a resource? /modules/java.base/java/lang/Object.class - if (isModules) { - n = handleResource(name); - } else { - // Possibly ask for /packages/java.lang/java.base - // although /packages/java.base not created - n = handleModuleLink(name); - } - } - return n; - } - - private void visitLocation(ImageLocation loc, LocationVisitor visitor) { - byte[] offsets = getResource(loc); - ByteBuffer buffer = ByteBuffer.wrap(offsets); - buffer.order(getByteOrder()); - IntBuffer intBuffer = buffer.asIntBuffer(); - for (int i = 0; i < offsets.length / SIZE_OF_OFFSET; i++) { - int offset = intBuffer.get(i); - ImageLocation pkgLoc = getLocation(offset); - visitor.visit(pkgLoc); - } - } - - private void visitPackageLocation(ImageLocation loc) { - // Retrieve package name - String pkgName = getBaseExt(loc); - // Content is array of offsets in Strings table - byte[] stringsOffsets = getResource(loc); - ByteBuffer buffer = ByteBuffer.wrap(stringsOffsets); - buffer.order(getByteOrder()); - IntBuffer intBuffer = buffer.asIntBuffer(); - // For each module, create a link node. - for (int i = 0; i < stringsOffsets.length / SIZE_OF_OFFSET; i++) { - // skip empty state, useless. - intBuffer.get(i); - i++; - int offset = intBuffer.get(i); - String moduleName = getString(offset); - Node targetNode = findNode("/modules/" + moduleName); - if (targetNode != null) { - String pkgDirName = packagesDir.getName() + "/" + pkgName; - Directory pkgDir = (Directory) nodes.get(pkgDirName); - newLinkNode(pkgDir, pkgDir.getName() + "/" + moduleName, targetNode); - } - } - } - - private Node handlePackages(String name, ImageLocation loc) { - long size = loc.getUncompressedSize(); - Node n = null; - // Only possiblities are /packages, /packages/package/module - if (name.equals("/packages")) { - visitLocation(loc, (childloc) -> { - findNode(childloc.getFullName()); - }); - packagesDir.setCompleted(true); - n = packagesDir; - } else { - if (size != 0) { // children are offsets to module in StringsTable - String pkgName = getBaseExt(loc); - Directory pkgDir = newDirectory(packagesDir, packagesDir.getName() + "/" + pkgName); - visitPackageLocation(loc); - pkgDir.setCompleted(true); - n = pkgDir; - } else { // Link to module - String pkgName = loc.getParent(); - String modName = getBaseExt(loc); - Node targetNode = findNode("/modules/" + modName); - if (targetNode != null) { - String pkgDirName = packagesDir.getName() + "/" + pkgName; - Directory pkgDir = (Directory) nodes.get(pkgDirName); - Node linkNode = newLinkNode(pkgDir, pkgDir.getName() + "/" + modName, targetNode); - n = linkNode; - } - } - } - return n; - } - - // Asking for /packages/package/module although - // /packages// not yet created, need to create it - // prior to return the link to module node. - private Node handleModuleLink(String name) { - // eg: unresolved /packages/package/module - // Build /packages/package node - Node ret = null; - String radical = "/packages/"; - String path = name; - if (path.startsWith(radical)) { - int start = radical.length(); - int pkgEnd = path.indexOf('/', start); - if (pkgEnd != -1) { - String pkg = path.substring(start, pkgEnd); - String pkgPath = radical + pkg; - Node n = findNode(pkgPath); - // If not found means that this is a symbolic link such as: - // /packages/java.util/java.base/java/util/Vector.class - // and will be done by a retry of the filesystem - for (Node child : n.getChildren()) { - if (child.name.equals(name)) { - ret = child; - break; - } - } - } - } - return ret; - } - - private Node handleModulesSubTree(String name, ImageLocation loc) { - Node n; - assert (name.equals(loc.getFullName())); - Directory dir = makeDirectories(name); - visitLocation(loc, (childloc) -> { - String path = childloc.getFullName(); - if (path.startsWith("/modules")) { // a package - makeDirectories(path); - } else { // a resource - makeDirectories(childloc.buildName(true, true, false)); - newResource(dir, childloc); - } - }); - dir.setCompleted(true); - n = dir; - return n; - } - - private Node handleResource(String name) { - Node n = null; - String locationPath = name.substring("/modules".length()); - ImageLocation resourceLoc = findLocation(locationPath); - if (resourceLoc != null) { - Directory dir = makeDirectories(resourceLoc.buildName(true, true, false)); - Resource res = newResource(dir, resourceLoc); - n = res; - } - return n; - } - - private String getBaseExt(ImageLocation loc) { - String base = loc.getBase(); - String ext = loc.getExtension(); - if (ext != null && !ext.isEmpty()) { - base = base + "." + ext; - } - return base; - } - - public synchronized Node findNode(String name) { - buildRootDirectory(); - Node n = nodes.get(name); - if (n == null || !n.isCompleted()) { - n = buildNode(name); - } - return n; - } - - private synchronized void clearNodes() { - nodes.clear(); - rootDir = null; - } - - /** - * Returns the file attributes of the image file. - */ - private BasicFileAttributes imageFileAttributes() { - BasicFileAttributes attrs = imageFileAttributes; - if (attrs == null) { - try { - Path file = getImagePath(); - attrs = Files.readAttributes(file, BasicFileAttributes.class); - } catch (IOException ioe) { - throw new UncheckedIOException(ioe); - } - imageFileAttributes = attrs; - } - return attrs; - } - - private Directory buildRootDirectory() { - Directory root = rootDir; // volatile read - if (root != null) { - return root; - } - - synchronized (this) { - root = rootDir; - if (root != null) { - return root; - } - - // FIXME no time information per resource in jimage file (yet?) - // we use file attributes of jimage itself. - // root directory - root = newDirectory(null, "/"); - root.setIsRootDir(); - - // /packages dir - packagesDir = newDirectory(root, "/packages"); - packagesDir.setIsPackagesDir(); - - // /modules dir - modulesDir = newDirectory(root, "/modules"); - modulesDir.setIsModulesDir(); - - root.setCompleted(true); - return rootDir = root; - } - } - - private Directory newDirectory(Directory parent, String name) { - Directory dir = Directory.create(parent, name, imageFileAttributes()); - nodes.put(dir.getName(), dir); - return dir; - } - - private Resource newResource(Directory parent, ImageLocation loc) { - Resource res = Resource.create(parent, loc, imageFileAttributes()); - nodes.put(res.getName(), res); - return res; - } - - private LinkNode newLinkNode(Directory dir, String name, Node link) { - LinkNode linkNode = LinkNode.create(dir, name, link); - nodes.put(linkNode.getName(), linkNode); - return linkNode; - } - - private Directory makeDirectories(String parent) { - Directory last = rootDir; - for (int offset = parent.indexOf('/', 1); - offset != -1; - offset = parent.indexOf('/', offset + 1)) { - String dir = parent.substring(0, offset); - last = makeDirectory(dir, last); - } - return makeDirectory(parent, last); - - } - - private Directory makeDirectory(String dir, Directory last) { - Directory nextDir = (Directory) nodes.get(dir); - if (nextDir == null) { - nextDir = newDirectory(last, dir); - } - return nextDir; - } - - public byte[] getResource(Node node) throws IOException { - if (node.isResource()) { - return super.getResource(node.getLocation()); - } - throw new IOException("Not a resource: " + node); - } - - public byte[] getResource(Resource rs) throws IOException { - return super.getResource(rs.getLocation()); - } } diff --git a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java index d5984095e998f86123c19ee6aed6be40f2789d34..5f0433b9d3bd13836774ca8a1967a13b946e933e 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java +++ b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystem.java @@ -299,13 +299,9 @@ class JrtFileSystem extends FileSystem { } // clean up this file system - called from finalize and close - void cleanup() throws IOException { - if (!isOpen) { - return; - } - synchronized (this) { + synchronized void cleanup() throws IOException { + if (isOpen) { isOpen = false; - // close image reader and null out image.close(); image = null; } @@ -461,8 +457,8 @@ class JrtFileSystem extends FileSystem { private Node lookup(String path) { try { return image.findNode(path); - } catch (RuntimeException re) { - throw new InvalidPathException(path, re.toString()); + } catch (RuntimeException | IOException ex) { + throw new InvalidPathException(path, ex.toString()); } } diff --git a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystemProvider.java b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystemProvider.java index 19edf4809616939f73525fc22747157129dc12aa..746d61a273c10f158bf8eee59e3e6b955bcf5f27 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystemProvider.java +++ b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystemProvider.java @@ -101,10 +101,10 @@ public final class JrtFileSystemProvider extends FileSystemProvider { @Override public FileSystem newFileSystem(URI uri, Map env) throws IOException { + Objects.requireNonNull(env); checkPermission(); checkUri(uri); - - if (env != null && env.containsKey("java.home")) { + if (env.containsKey("java.home")) { return newFileSystem((String)env.get("java.home"), uri, env); } else { return new JrtFileSystem(this, env); diff --git a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/SystemImage.java b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/SystemImage.java index 7b155feba884ce6fcf98234ff009af3441977e22..2da0d6ed45264ba6e6960a180634485a36ad14d1 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/SystemImage.java +++ b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/SystemImage.java @@ -49,7 +49,7 @@ import jdk.internal.jimage.ImageReader.Node; */ abstract class SystemImage { - abstract Node findNode(String path); + abstract Node findNode(String path) throws IOException; abstract byte[] getResource(Node node) throws IOException; abstract void close() throws IOException; @@ -60,7 +60,7 @@ abstract class SystemImage { image.getRootDirectory(); return new SystemImage() { @Override - Node findNode(String path) { + Node findNode(String path) throws IOException { return image.findNode(path); } @Override diff --git a/jdk/src/java.base/share/classes/jdk/internal/loader/BootLoader.java b/jdk/src/java.base/share/classes/jdk/internal/loader/BootLoader.java index 6fc5e7d4ec817af2f13d2e5aef2ed83acd9517f2..269c193dbe4360dc9b4536b1c144ca6a1f0eda6c 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/loader/BootLoader.java +++ b/jdk/src/java.base/share/classes/jdk/internal/loader/BootLoader.java @@ -30,6 +30,7 @@ import java.lang.module.ModuleReference; import java.lang.reflect.Layer; import java.lang.reflect.Module; import java.net.MalformedURLException; +import java.net.URI; import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; @@ -184,9 +185,9 @@ public class BootLoader { /** * Define the {@code Package} with the given name. The specified - * location is a jrt URL to a named module in the run-time image, a - * file path to a module in an exploded run-time image, or the file - * path to an enty on the boot class path (java agent Boot-Class-Path + * location is a jrt URL to a named module in the run-time image, + * a file URL to a module in an exploded run-time image, or a file + * path to an entry on the boot class path (java agent Boot-Class-Path * or -Xbootclasspath/a. * *

If the given location is a JAR file containing a manifest, @@ -194,7 +195,9 @@ public class BootLoader { * the manifest, if present. * * @param name package name - * @param location location where the package is (jrt URL or file path) + * @param location location where the package is (jrt URL or file URL + * for a named module in the run-time or exploded image; + * a file path for a package from -Xbootclasspath/a) */ static Package definePackage(String name, String location) { Module module = findModule(location); @@ -222,9 +225,9 @@ public class BootLoader { if (location.startsWith("jrt:/")) { // named module in runtime image ("jrt:/".length() == 5) mn = location.substring(5, location.length()); - } else { + } else if (location.startsWith("file:/")) { // named module in exploded image - Path path = Paths.get(location); + Path path = Paths.get(URI.create(location)); Path modulesDir = Paths.get(JAVA_HOME, "modules"); if (path.startsWith(modulesDir)) { mn = path.getFileName().toString(); diff --git a/jdk/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java b/jdk/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java index 15688e1a573f8bbd7cbe1b2d5541b7d3952d8ac8..234a86a9271d9943717ae4b052b245867f3bad44 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java +++ b/jdk/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java @@ -52,6 +52,7 @@ import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.NoSuchElementException; +import java.util.Properties; import java.util.Set; import java.util.Stack; import java.util.StringTokenizer; @@ -69,6 +70,7 @@ import jdk.internal.util.jar.InvalidJarIndexError; import jdk.internal.util.jar.JarIndex; import sun.net.util.URLUtil; import sun.net.www.ParseUtil; +import sun.security.action.GetPropertyAction; /** * This class is used to maintain a search path of URLs for loading classes @@ -78,20 +80,15 @@ import sun.net.www.ParseUtil; */ public class URLClassPath { private static final String USER_AGENT_JAVA_VERSION = "UA-Java-Version"; - private static final String JAVA_HOME; private static final String JAVA_VERSION; private static final boolean DEBUG; private static final boolean DISABLE_JAR_CHECKING; static { - JAVA_HOME = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("java.home")); - JAVA_VERSION = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("java.version")); - DEBUG = (java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("sun.misc.URLClassPath.debug")) != null); - String p = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("sun.misc.URLClassPath.disableJarChecking")); + Properties props = GetPropertyAction.getProperties(); + JAVA_VERSION = props.getProperty("java.version"); + DEBUG = (props.getProperty("sun.misc.URLClassPath.debug") != null); + String p = props.getProperty("sun.misc.URLClassPath.disableJarChecking"); DISABLE_JAR_CHECKING = p != null ? p.equals("true") || p.equals("") : false; } diff --git a/jdk/src/java.base/share/classes/jdk/internal/logger/LoggerFinderLoader.java b/jdk/src/java.base/share/classes/jdk/internal/logger/LoggerFinderLoader.java index 7d315ba70575e39009e75780f43321a199ea001a..58f235d6ccdd7282edfe7dbd2605d61726cc3d6b 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/logger/LoggerFinderLoader.java +++ b/jdk/src/java.base/share/classes/jdk/internal/logger/LoggerFinderLoader.java @@ -33,6 +33,7 @@ import java.util.Locale; import java.util.ServiceConfigurationError; import java.util.ServiceLoader; import sun.security.util.SecurityConstants; +import sun.security.action.GetPropertyAction; /** * Helper class used to load the {@link java.lang.System.LoggerFinder}. @@ -79,9 +80,8 @@ public final class LoggerFinderLoader { // Get configuration error policy private static ErrorPolicy configurationErrorPolicy() { - final PrivilegedAction getConfigurationErrorPolicy = - () -> System.getProperty("jdk.logger.finder.error"); - String errorPolicy = AccessController.doPrivileged(getConfigurationErrorPolicy); + String errorPolicy = + GetPropertyAction.getProperty("jdk.logger.finder.error"); if (errorPolicy == null || errorPolicy.isEmpty()) { return ErrorPolicy.WARNING; } @@ -95,9 +95,8 @@ public final class LoggerFinderLoader { // Whether multiple provider should be considered as an error. // This is further submitted to the configuration error policy. private static boolean ensureSingletonProvider() { - final PrivilegedAction ensureSingletonProvider = - () -> Boolean.getBoolean("jdk.logger.finder.singleton"); - return AccessController.doPrivileged(ensureSingletonProvider); + return Boolean.parseBoolean( + GetPropertyAction.getProperty("jdk.logger.finder.singleton")); } private static Iterator findLoggerFinderProviders() { diff --git a/jdk/src/java.base/share/classes/jdk/internal/logger/SimpleConsoleLogger.java b/jdk/src/java.base/share/classes/jdk/internal/logger/SimpleConsoleLogger.java index de4451fd35c1c0fc46392925b7d86e93c43c64df..c90a7b24e3834f126ee38f8874eb4c7684d87dd5 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/logger/SimpleConsoleLogger.java +++ b/jdk/src/java.base/share/classes/jdk/internal/logger/SimpleConsoleLogger.java @@ -55,8 +55,8 @@ public class SimpleConsoleLogger extends LoggerConfiguration PlatformLogger.toPlatformLevel(DEFAULT_LEVEL); static Level getDefaultLevel() { - String levelName = AccessController.doPrivileged( - new GetPropertyAction("jdk.system.logger.level", "INFO")); + String levelName = GetPropertyAction + .getProperty("jdk.system.logger.level", "INFO"); try { return Level.valueOf(levelName); } catch (IllegalArgumentException iae) { @@ -425,8 +425,8 @@ public class SimpleConsoleLogger extends LoggerConfiguration // Make it easier to wrap Logger... static private final String[] skips; static { - String additionalPkgs = AccessController.doPrivileged( - new GetPropertyAction("jdk.logger.packages")); + String additionalPkgs = + GetPropertyAction.getProperty("jdk.logger.packages"); skips = additionalPkgs == null ? new String[0] : additionalPkgs.split(","); } @@ -485,7 +485,7 @@ public class SimpleConsoleLogger extends LoggerConfiguration // jdk/test/java/lang/invoke/lambda/LogGeneratedClassesTest.java // to fail - because that test has a testcase which somehow references // PlatformLogger and counts the number of generated lambda classes. - String format = AccessController.doPrivileged(new GetPropertyAction(key)); + String format = GetPropertyAction.getProperty(key); if (format == null && defaultPropertyGetter != null) { format = defaultPropertyGetter.apply(key); diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangInvokeAccess.java b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangInvokeAccess.java index 776c24dc95a970f17c07782347b82f33b0407261..1a4aba5d79bf2faaf1f6efba2e571fad695bbe11 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangInvokeAccess.java +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangInvokeAccess.java @@ -30,4 +30,9 @@ public interface JavaLangInvokeAccess { * Create a new MemberName instance */ Object newMemberName(); + + /** + * Returns the name for the given MemberName + */ + String getName(Object mname); } diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaObjectInputStreamAccess.java b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaObjectInputStreamAccess.java new file mode 100644 index 0000000000000000000000000000000000000000..c344f8adc7cdd88bf80943e655278eb179c76a09 --- /dev/null +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaObjectInputStreamAccess.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.internal.misc; + +import java.io.ObjectInputStream; + +/** + * The interface to specify methods for accessing {@code ObjectInputStream} + * @author sjiang + */ +public interface JavaObjectInputStreamAccess { + /** + * Sets a descriptor validating. + * @param ois stream to have the descriptors validated + * @param validator validator used to validate a descriptor. + */ + public void setValidator(ObjectInputStream ois, ObjectStreamClassValidator validator); +} diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/ObjectStreamClassValidator.java b/jdk/src/java.base/share/classes/jdk/internal/misc/ObjectStreamClassValidator.java new file mode 100644 index 0000000000000000000000000000000000000000..2b543a307218579d4136e0f5081266498ba04ee6 --- /dev/null +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/ObjectStreamClassValidator.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.internal.misc; + +import java.io.ObjectStreamClass; + +/** + * A callback used by {@code ObjectInputStream} to do descriptor validation. + * + * @author sjiang + */ +public interface ObjectStreamClassValidator { + /** + * This method will be called by ObjectInputStream to + * check a descriptor just before creating an object described by this descriptor. + * The object will not be created if this method throws a {@code RuntimeException}. + * @param descriptor descriptor to be checked. + */ + public void validateDescriptor(ObjectStreamClass descriptor); +} diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java b/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java index 3246bde5be1928df2ab60f0bcb6d61ed02f60be3..24dc4ce43a7241b35ff320552d1adcfeb78bc6e6 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,9 +29,9 @@ import java.lang.module.ModuleDescriptor; import java.util.jar.JarFile; import java.io.Console; import java.io.FileDescriptor; +import java.io.ObjectInputStream; import java.security.ProtectionDomain; import java.security.AccessController; -import jdk.internal.misc.Unsafe; /** A repository of "shared secrets", which are a mechanism for calling implementation-private methods in another package without @@ -63,6 +63,7 @@ public class SharedSecrets { private static JavaAWTAccess javaAWTAccess; private static JavaAWTFontAccess javaAWTFontAccess; private static JavaBeansAccess javaBeansAccess; + private static JavaObjectInputStreamAccess javaObjectInputStreamAccess; public static JavaUtilJarAccess javaUtilJarAccess() { if (javaUtilJarAccess == null) { @@ -262,4 +263,15 @@ public class SharedSecrets { public static void setJavaUtilResourceBundleAccess(JavaUtilResourceBundleAccess access) { javaUtilResourceBundleAccess = access; } + + public static JavaObjectInputStreamAccess getJavaObjectInputStreamAccess() { + if (javaObjectInputStreamAccess == null) { + unsafe.ensureClassInitialized(ObjectInputStream.class); + } + return javaObjectInputStreamAccess; + } + + public static void setJavaObjectInputStreamAccess(JavaObjectInputStreamAccess access) { + javaObjectInputStreamAccess = access; + } } diff --git a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java index d40facdafa419bfff322352c75cb70ee0ca8adef..e6a7cded42f37211e0c3a4710532e26a3d6dc3b0 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java +++ b/jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java @@ -70,6 +70,7 @@ package jdk.internal.org.objectweb.asm; * @author Eric Bruneton * @author Eugene Kuleshov */ +@SuppressWarnings("deprecation") // for Integer(int) constructor public interface Opcodes { // ASM API versions @@ -176,6 +177,8 @@ public interface Opcodes { */ int F_SAME1 = 4; + // For reference comparison purposes, construct new instances + // instead of using valueOf() or autoboxing. Integer TOP = new Integer(0); Integer INTEGER = new Integer(1); Integer FLOAT = new Integer(2); diff --git a/jdk/src/java.base/share/classes/jdk/internal/reflect/Reflection.java b/jdk/src/java.base/share/classes/jdk/internal/reflect/Reflection.java index 88e6a8349cac3349543bce4a52ce1ae73d6a3541..636b09403451aaf5a11ab8d65bbef17d0fe507f6 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/reflect/Reflection.java +++ b/jdk/src/java.base/share/classes/jdk/internal/reflect/Reflection.java @@ -27,13 +27,12 @@ package jdk.internal.reflect; import java.lang.reflect.*; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.HashMap; import java.util.Map; import java.util.Objects; import jdk.internal.HotSpotIntrinsicCandidate; import jdk.internal.misc.VM; +import sun.security.action.GetPropertyAction; /** Common utility routines used by both java.lang and java.lang.reflect */ @@ -344,15 +343,10 @@ public class Reflection { private static void printStackTraceIfNeeded(Throwable e) { if (!printStackWhenAccessFailsSet && VM.initLevel() >= 1) { - // can't use method reference here, might be too early in startup - PrivilegedAction pa = new PrivilegedAction() { - public Boolean run() { - String s; - s = System.getProperty("sun.reflect.debugModuleAccessChecks"); - return (s != null && !s.equalsIgnoreCase("false")); - } - }; - printStackWhenAccessFails = AccessController.doPrivileged(pa); + String s = GetPropertyAction + .getProperty("sun.reflect.debugModuleAccessChecks"); + printStackWhenAccessFails = + (s != null && !s.equalsIgnoreCase("false")); printStackWhenAccessFailsSet = true; } if (printStackWhenAccessFails) { diff --git a/jdk/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java b/jdk/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java index 898f56c214f47863ce16af8208d590ba18b203c1..b40c584efcdf092639f0333f3837f874d94fb435 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java +++ b/jdk/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java @@ -30,10 +30,11 @@ import java.lang.reflect.Executable; import java.lang.reflect.Method; import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; -import java.security.AccessController; import java.security.Permission; import java.security.PrivilegedAction; +import java.util.Properties; import sun.reflect.misc.ReflectUtil; +import sun.security.action.GetPropertyAction; /**

The master factory for all reflective objects, both those in java.lang.reflect (Fields, Methods, Constructors) as well as their @@ -382,41 +383,37 @@ public class ReflectionFactory { run, before the system properties are set up. */ private static void checkInitted() { if (initted) return; - AccessController.doPrivileged( - new PrivilegedAction<>() { - public Void run() { - // Tests to ensure the system properties table is fully - // initialized. This is needed because reflection code is - // called very early in the initialization process (before - // command-line arguments have been parsed and therefore - // these user-settable properties installed.) We assume that - // if System.out is non-null then the System class has been - // fully initialized and that the bulk of the startup code - // has been run. - - if (System.out == null) { - // java.lang.System not yet fully initialized - return null; - } - - String val = System.getProperty("sun.reflect.noInflation"); - if (val != null && val.equals("true")) { - noInflation = true; - } - - val = System.getProperty("sun.reflect.inflationThreshold"); - if (val != null) { - try { - inflationThreshold = Integer.parseInt(val); - } catch (NumberFormatException e) { - throw new RuntimeException("Unable to parse property sun.reflect.inflationThreshold", e); - } - } - - initted = true; - return null; - } - }); + + // Tests to ensure the system properties table is fully + // initialized. This is needed because reflection code is + // called very early in the initialization process (before + // command-line arguments have been parsed and therefore + // these user-settable properties installed.) We assume that + // if System.out is non-null then the System class has been + // fully initialized and that the bulk of the startup code + // has been run. + + if (System.out == null) { + // java.lang.System not yet fully initialized + return; + } + + Properties props = GetPropertyAction.getProperties(); + String val = props.getProperty("sun.reflect.noInflation"); + if (val != null && val.equals("true")) { + noInflation = true; + } + + val = props.getProperty("sun.reflect.inflationThreshold"); + if (val != null) { + try { + inflationThreshold = Integer.parseInt(val); + } catch (NumberFormatException e) { + throw new RuntimeException("Unable to parse property sun.reflect.inflationThreshold", e); + } + } + + initted = true; } private static LangReflectAccess langReflectAccess() { diff --git a/jdk/src/java.base/share/classes/module-info.java b/jdk/src/java.base/share/classes/module-info.java index 8cc37dd7b2ded5add08c9650f49f71befacd64f8..942c0582ea08d09d50dbdd311e96cff83de08215 100644 --- a/jdk/src/java.base/share/classes/module-info.java +++ b/jdk/src/java.base/share/classes/module-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -300,9 +300,5 @@ module java.base { provides java.nio.file.spi.FileSystemProvider with jdk.internal.jrtfs.JrtFileSystemProvider; - provides java.security.Provider with sun.security.provider.Sun; - provides java.security.Provider with sun.security.rsa.SunRsaSign; - provides java.security.Provider with com.sun.crypto.provider.SunJCE; - provides java.security.Provider with com.sun.net.ssl.internal.ssl.Provider; } diff --git a/jdk/src/java.base/share/classes/sun/invoke/util/VerifyAccess.java b/jdk/src/java.base/share/classes/sun/invoke/util/VerifyAccess.java index 456909fde1cdff20b5ac49ac1f3aff1bd1ecd364..37cbede912a5985850db42b23204cb14826025b5 100644 --- a/jdk/src/java.base/share/classes/sun/invoke/util/VerifyAccess.java +++ b/jdk/src/java.base/share/classes/sun/invoke/util/VerifyAccess.java @@ -231,22 +231,66 @@ public class VerifyAccess { * @param refc the class attempting to make the reference */ public static boolean isTypeVisible(Class type, Class refc) { - if (type == refc) return true; // easy check + if (type == refc) { + return true; // easy check + } while (type.isArray()) type = type.getComponentType(); - if (type.isPrimitive() || type == Object.class) return true; - ClassLoader parent = type.getClassLoader(); - if (parent == null) return true; - ClassLoader child = refc.getClassLoader(); - if (child == null) return false; - if (parent == child || loadersAreRelated(parent, child, true)) + if (type.isPrimitive() || type == Object.class) { return true; - // Do it the hard way: Look up the type name from the refc loader. - try { - Class res = child.loadClass(type.getName()); - return (type == res); - } catch (ClassNotFoundException ex) { + } + ClassLoader typeLoader = type.getClassLoader(); + ClassLoader refcLoader = refc.getClassLoader(); + if (typeLoader == refcLoader) { + return true; + } + if (refcLoader == null && typeLoader != null) { return false; } + if (typeLoader == null && type.getName().startsWith("java.")) { + // Note: The API for actually loading classes, ClassLoader.defineClass, + // guarantees that classes with names beginning "java." cannot be aliased, + // because class loaders cannot load them directly. + return true; + } + + // Do it the hard way: Look up the type name from the refc loader. + // + // Force the refc loader to report and commit to a particular binding for this type name (type.getName()). + // + // In principle, this query might force the loader to load some unrelated class, + // which would cause this query to fail (and the original caller to give up). + // This would be wasted effort, but it is expected to be very rare, occurring + // only when an attacker is attempting to create a type alias. + // In the normal case, one class loader will simply delegate to the other, + // and the same type will be visible through both, with no extra loading. + // + // It is important to go through Class.forName instead of ClassLoader.loadClass + // because Class.forName goes through the JVM system dictionary, which records + // the class lookup once for all. This means that even if a not-well-behaved class loader + // would "change its mind" about the meaning of the name, the Class.forName request + // will use the result cached in the JVM system dictionary. Note that the JVM system dictionary + // will record the first successful result. Unsuccessful results are not stored. + // + // We use doPrivileged in order to allow an unprivileged caller to ask an arbitrary + // class loader about the binding of the proposed name (type.getName()). + // The looked up type ("res") is compared for equality against the proposed + // type ("type") and then is discarded. Thus, the worst that can happen to + // the "child" class loader is that it is bothered to load and report a class + // that differs from "type"; this happens once due to JVM system dictionary + // memoization. And the caller never gets to look at the alternate type binding + // ("res"), whether it exists or not. + final String name = type.getName(); + Class res = java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction<>() { + public Class run() { + try { + return Class.forName(name, false, refcLoader); + } catch (ClassNotFoundException | LinkageError e) { + return null; // Assume the class is not found + } + } + }); + return (type == res); } /** diff --git a/jdk/src/java.base/share/classes/sun/net/ResourceManager.java b/jdk/src/java.base/share/classes/sun/net/ResourceManager.java index 068b8484728adf9f94f030cdbee8f827c77254d8..9c68d7c6beda03bc46cc58ea5a760090bdad91e1 100644 --- a/jdk/src/java.base/share/classes/sun/net/ResourceManager.java +++ b/jdk/src/java.base/share/classes/sun/net/ResourceManager.java @@ -53,9 +53,8 @@ public class ResourceManager { private static final AtomicInteger numSockets; static { - String prop = java.security.AccessController.doPrivileged( - new GetPropertyAction("sun.net.maxDatagramSockets") - ); + String prop = + GetPropertyAction.getProperty("sun.net.maxDatagramSockets"); int defmax = DEFAULT_MAX_SOCKETS; try { if (prop != null) { diff --git a/jdk/src/java.base/share/classes/sun/net/sdp/SdpSupport.java b/jdk/src/java.base/share/classes/sun/net/sdp/SdpSupport.java index d24a7fed491fc62916d6ea2ffd82c27535a9d1b2..797bc7fed500b789dc5f6c0c57043182ebd2dc58 100644 --- a/jdk/src/java.base/share/classes/sun/net/sdp/SdpSupport.java +++ b/jdk/src/java.base/share/classes/sun/net/sdp/SdpSupport.java @@ -31,6 +31,7 @@ import java.security.AccessController; import jdk.internal.misc.SharedSecrets; import jdk.internal.misc.JavaIOFileDescriptorAccess; +import sun.security.action.GetPropertyAction; /** @@ -39,8 +40,7 @@ import jdk.internal.misc.JavaIOFileDescriptorAccess; */ public final class SdpSupport { - private static final String os = AccessController - .doPrivileged(new sun.security.action.GetPropertyAction("os.name")); + private static final String os = GetPropertyAction.getProperty("os.name"); private static final boolean isSupported = (os.equals("SunOS") || (os.equals("Linux"))); private static final JavaIOFileDescriptorAccess fdAccess = SharedSecrets.getJavaIOFileDescriptorAccess(); diff --git a/jdk/src/java.base/share/classes/sun/net/smtp/SmtpClient.java b/jdk/src/java.base/share/classes/sun/net/smtp/SmtpClient.java index fda15ea92347043503971bdcd32d067491c49c51..ac3f7b8a43f05513c740f8338c0d60491edd21ee 100644 --- a/jdk/src/java.base/share/classes/sun/net/smtp/SmtpClient.java +++ b/jdk/src/java.base/share/classes/sun/net/smtp/SmtpClient.java @@ -25,10 +25,10 @@ package sun.net.smtp; -import java.util.StringTokenizer; import java.io.*; import java.net.*; import sun.net.TransferProtocolClient; +import sun.security.action.GetPropertyAction; /** * This class implements the SMTP client. @@ -157,8 +157,7 @@ public class SmtpClient extends TransferProtocolClient { } try { String s; - mailhost = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("mail.host")); + mailhost = GetPropertyAction.getProperty("mail.host"); if (mailhost != null) { openServer(mailhost); return; @@ -184,8 +183,7 @@ public class SmtpClient extends TransferProtocolClient { setConnectTimeout(to); try { String s; - mailhost = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("mail.host")); + mailhost = GetPropertyAction.getProperty("mail.host"); if (mailhost != null) { openServer(mailhost); return; diff --git a/jdk/src/java.base/share/classes/sun/net/www/MimeLauncher.java b/jdk/src/java.base/share/classes/sun/net/www/MimeLauncher.java index d95ca3774ba862f4275529080592b4d5639103f4..ba26f96e52e4a661ae988291fc5564cd5b6c9bd0 100644 --- a/jdk/src/java.base/share/classes/sun/net/www/MimeLauncher.java +++ b/jdk/src/java.base/share/classes/sun/net/www/MimeLauncher.java @@ -27,6 +27,7 @@ package sun.net.www; import java.net.URL; import java.io.*; import java.util.StringTokenizer; +import sun.security.action.GetPropertyAction; class MimeLauncher extends Thread { java.net.URLConnection uc; @@ -182,8 +183,7 @@ class MimeLauncher extends Thread { } String execPathList; - execPathList = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("exec.path")); + execPathList = GetPropertyAction.getProperty("exec.path"); if (execPathList == null) { // exec.path property not set return false; diff --git a/jdk/src/java.base/share/classes/sun/net/www/http/HttpClient.java b/jdk/src/java.base/share/classes/sun/net/www/http/HttpClient.java index 02c9f98b7a67209b0f7d8668cc806ef927cab404..392d9ea52dc5a7a047d0cedb85c104fba3b9e998 100644 --- a/jdk/src/java.base/share/classes/sun/net/www/http/HttpClient.java +++ b/jdk/src/java.base/share/classes/sun/net/www/http/HttpClient.java @@ -28,6 +28,7 @@ package sun.net.www.http; import java.io.*; import java.net.*; import java.util.Locale; +import java.util.Properties; import sun.net.NetworkClient; import sun.net.ProgressSource; import sun.net.www.MessageHeader; @@ -37,6 +38,7 @@ import sun.net.www.ParseUtil; import sun.net.www.protocol.http.HttpURLConnection; import sun.util.logging.PlatformLogger; import static sun.net.www.protocol.http.HttpURLConnection.TunnelState.*; +import sun.security.action.GetPropertyAction; /** * @author Herb Jellinek @@ -143,20 +145,18 @@ public class HttpClient extends NetworkClient { } static { - String keepAlive = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("http.keepAlive")); - - String retryPost = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("sun.net.http.retryPost")); + Properties props = GetPropertyAction.getProperties(); + String keepAlive = props.getProperty("http.keepAlive"); + String retryPost = props.getProperty("sun.net.http.retryPost"); if (keepAlive != null) { - keepAliveProp = Boolean.valueOf(keepAlive).booleanValue(); + keepAliveProp = Boolean.parseBoolean(keepAlive); } else { keepAliveProp = true; } if (retryPost != null) { - retryPostProp = Boolean.valueOf(retryPost).booleanValue(); + retryPostProp = Boolean.parseBoolean(retryPost); } else retryPostProp = true; diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java index 38d64d23009edab85ae68756891b70764ca3ce58..b397ba1243f9d5bbe76bb9e13232575038db3e8e 100644 --- a/jdk/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java @@ -46,6 +46,7 @@ import java.net.ProxySelector; import java.util.StringTokenizer; import java.util.Iterator; import java.security.Permission; +import java.util.Properties; import sun.net.NetworkClient; import sun.net.www.MessageHeader; import sun.net.www.MeteredStream; @@ -277,11 +278,10 @@ public class FtpURLConnection extends URLConnection { if (user == null) { user = "anonymous"; - String vers = java.security.AccessController.doPrivileged( - new GetPropertyAction("java.version")); - password = java.security.AccessController.doPrivileged( - new GetPropertyAction("ftp.protocol.user", - "Java" + vers + "@")); + Properties props = GetPropertyAction.getProperties(); + String vers = props.getProperty("java.version"); + password = props.getProperty("ftp.protocol.user", + "Java" + vers + "@"); } try { ftp = FtpClient.create(); diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java index 42f692c3738ce468101b253e6a99e26f7d1db929..b6168d0c2c5ef66d61d9cc1e3a692251fd8f0532 100644 --- a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java @@ -25,9 +25,10 @@ package sun.net.www.protocol.http; -import sun.net.www.*; import java.util.Iterator; import java.util.HashMap; +import sun.net.www.*; +import sun.security.action.GetPropertyAction; /** * This class is used to parse the information in WWW-Authenticate: and Proxy-Authenticate: @@ -93,8 +94,7 @@ public class AuthenticationHeader { } static { - authPref = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("http.auth.preference")); + authPref = GetPropertyAction.getProperty("http.auth.preference"); // http.auth.preference can be set to SPNEGO or Kerberos. // In fact they means "Negotiate with SPNEGO" and "Negotiate with diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java index 5754c0472193da28b53e03aa2cbcea5d24cc1be1..ebabc26182e42668cd8242ba57b7e0350d8aae41 100644 --- a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java @@ -52,7 +52,6 @@ import java.security.AccessController; import java.security.PrivilegedExceptionAction; import java.security.PrivilegedActionException; import java.io.*; -import java.net.*; import java.util.ArrayList; import java.util.Collections; import java.util.Date; @@ -78,12 +77,15 @@ import java.text.SimpleDateFormat; import java.util.TimeZone; import java.net.MalformedURLException; import java.nio.ByteBuffer; +import java.util.Properties; import static sun.net.www.protocol.http.AuthScheme.BASIC; import static sun.net.www.protocol.http.AuthScheme.DIGEST; import static sun.net.www.protocol.http.AuthScheme.NTLM; import static sun.net.www.protocol.http.AuthScheme.NEGOTIATE; import static sun.net.www.protocol.http.AuthScheme.KERBEROS; import static sun.net.www.protocol.http.AuthScheme.UNKNOWN; +import sun.security.action.GetIntegerAction; +import sun.security.action.GetPropertyAction; /** * A class to represent an HTTP connection to a remote object. @@ -205,46 +207,38 @@ public class HttpURLConnection extends java.net.HttpURLConnection { }; static { - maxRedirects = java.security.AccessController.doPrivileged( - new sun.security.action.GetIntegerAction( - "http.maxRedirects", defaultmaxRedirects)).intValue(); - version = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("java.version")); - String agent = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("http.agent")); + Properties props = GetPropertyAction.getProperties(); + maxRedirects = GetIntegerAction.getProperty("http.maxRedirects", + defaultmaxRedirects); + version = props.getProperty("java.version"); + String agent = props.getProperty("http.agent"); if (agent == null) { agent = "Java/"+version; } else { agent = agent + " Java/"+version; } userAgent = agent; - validateProxy = java.security.AccessController.doPrivileged( - new sun.security.action.GetBooleanAction( - "http.auth.digest.validateProxy")).booleanValue(); - validateServer = java.security.AccessController.doPrivileged( - new sun.security.action.GetBooleanAction( - "http.auth.digest.validateServer")).booleanValue(); - - enableESBuffer = java.security.AccessController.doPrivileged( - new sun.security.action.GetBooleanAction( - "sun.net.http.errorstream.enableBuffering")).booleanValue(); - timeout4ESBuffer = java.security.AccessController.doPrivileged( - new sun.security.action.GetIntegerAction( - "sun.net.http.errorstream.timeout", 300)).intValue(); + validateProxy = Boolean.parseBoolean( + props.getProperty("http.auth.digest.validateProxy")); + validateServer = Boolean.parseBoolean( + props.getProperty("http.auth.digest.validateServer")); + + enableESBuffer = Boolean.parseBoolean( + props.getProperty("sun.net.http.errorstream.enableBuffering")); + timeout4ESBuffer = GetIntegerAction + .getProperty("sun.net.http.errorstream.timeout", 300); if (timeout4ESBuffer <= 0) { timeout4ESBuffer = 300; // use the default } - bufSize4ES = java.security.AccessController.doPrivileged( - new sun.security.action.GetIntegerAction( - "sun.net.http.errorstream.bufferSize", 4096)).intValue(); + bufSize4ES = GetIntegerAction + .getProperty("sun.net.http.errorstream.bufferSize", 4096); if (bufSize4ES <= 0) { bufSize4ES = 4096; // use the default } - allowRestrictedHeaders = java.security.AccessController.doPrivileged( - new sun.security.action.GetBooleanAction( - "sun.net.http.allowRestrictedHeaders")).booleanValue(); + allowRestrictedHeaders = Boolean.parseBoolean( + props.getProperty("sun.net.http.allowRestrictedHeaders")); if (!allowRestrictedHeaders) { restrictedHeaderSet = new HashSet<>(restrictedHeaders.length); for (int i=0; i < restrictedHeaders.length; i++) { diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java index 3aecc419cb264bde5faaa0ee6d1bc66204bb0a67..437c39691485021f5cf05e26e8c0e9768b746366 100644 --- a/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java @@ -41,7 +41,6 @@ import java.security.Principal; import java.security.cert.*; import java.util.StringTokenizer; import java.util.Vector; -import java.security.AccessController; import javax.security.auth.x500.X500Principal; @@ -139,8 +138,8 @@ final class HttpsClient extends HttpClient // If ciphers are assigned, sort them into an array. // String ciphers []; - String cipherString = AccessController.doPrivileged( - new GetPropertyAction("https.cipherSuites")); + String cipherString = + GetPropertyAction.getProperty("https.cipherSuites"); if (cipherString == null || "".equals(cipherString)) { ciphers = null; @@ -163,8 +162,8 @@ final class HttpsClient extends HttpClient // If protocols are assigned, sort them into an array. // String protocols []; - String protocolString = AccessController.doPrivileged( - new GetPropertyAction("https.protocols")); + String protocolString = + GetPropertyAction.getProperty("https.protocols"); if (protocolString == null || "".equals(protocolString)) { protocols = null; @@ -184,8 +183,7 @@ final class HttpsClient extends HttpClient } private String getUserAgent() { - String userAgent = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("https.agent")); + String userAgent = GetPropertyAction.getProperty("https.agent"); if (userAgent == null || userAgent.length() == 0) { userAgent = "JSSE"; } diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/jrt/JavaRuntimeURLConnection.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/jrt/JavaRuntimeURLConnection.java index cde9d43871439679ea1c83ed7a1801426f256833..f58ce457f7acfcad68202ed43a32b59bf09fa95f 100644 --- a/jdk/src/java.base/share/classes/sun/net/www/protocol/jrt/JavaRuntimeURLConnection.java +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/jrt/JavaRuntimeURLConnection.java @@ -32,10 +32,7 @@ import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; -import java.security.AccessController; import java.security.Permission; -import java.security.PrivilegedAction; -import java.util.List; import jdk.internal.jimage.ImageLocation; import jdk.internal.jimage.ImageReader; @@ -45,6 +42,7 @@ import jdk.internal.loader.URLClassPath; import jdk.internal.loader.Resource; import sun.net.www.ParseUtil; import sun.net.www.URLConnection; +import sun.security.action.GetPropertyAction; /** * URLConnection implementation that can be used to connect to resources @@ -163,11 +161,7 @@ public class JavaRuntimeURLConnection extends URLConnection { public Permission getPermission() throws IOException { Permission p = permission; if (p == null) { - // using lambda expression here leads to recursive initialization - PrivilegedAction pa = new PrivilegedAction() { - public String run() { return System.getProperty("java.home"); } - }; - String home = AccessController.doPrivileged(pa); + String home = GetPropertyAction.getProperty("java.home"); p = new FilePermission(home + File.separator + "-", "read"); permission = p; } diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/netdoc/Handler.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/netdoc/Handler.java index fbcddcb826bb60b8694b9ef3b32fb22aa0e28b82..811397076552106d3e9c958d33c033283abce0be 100644 --- a/jdk/src/java.base/share/classes/sun/net/www/protocol/netdoc/Handler.java +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/netdoc/Handler.java @@ -40,6 +40,7 @@ import java.net.MalformedURLException; import java.net.URLStreamHandler; import java.io.InputStream; import java.io.IOException; +import sun.security.action.GetPropertyAction; public class Handler extends URLStreamHandler { static URL base; @@ -54,12 +55,10 @@ public class Handler extends URLStreamHandler { URLConnection uc = null; URL ru; - Boolean tmp = java.security.AccessController.doPrivileged( - new sun.security.action.GetBooleanAction("newdoc.localonly")); - boolean localonly = tmp.booleanValue(); + boolean localonly = Boolean.parseBoolean( + GetPropertyAction.getProperty("newdoc.localonly")); - String docurl = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("doc.url")); + String docurl = GetPropertyAction.getProperty("doc.url"); String file = u.getFile(); if (!localonly) { diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java b/jdk/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java index 671fe79efcc5e5a4f02546f3ac735b74149eaeff..8a287bc2839067ae06b398f9b0353185dba8b9e3 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java @@ -1019,9 +1019,8 @@ public class FileChannelImpl if (!propertyChecked) { synchronized (FileChannelImpl.class) { if (!propertyChecked) { - String value = AccessController.doPrivileged( - new GetPropertyAction( - "sun.nio.ch.disableSystemWideOverlappingFileLockCheck")); + String value = GetPropertyAction.getProperty( + "sun.nio.ch.disableSystemWideOverlappingFileLockCheck"); isSharedFileLockTable = ((value == null) || value.equals("false")); propertyChecked = true; } diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/Net.java b/jdk/src/java.base/share/classes/sun/nio/ch/Net.java index 062ce35468e57704b90d453e7dfc002f369471a3..9a5c4dcb6f8598a3a0bd6e83c19ae31f438fe727 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/Net.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/Net.java @@ -33,6 +33,7 @@ import java.util.*; import java.security.AccessController; import java.security.PrivilegedAction; import sun.net.ExtendedOptionsImpl; +import sun.security.action.GetPropertyAction; public class Net { @@ -382,13 +383,8 @@ public class Net { } public static boolean isFastTcpLoopbackRequested() { - String loopbackProp = java.security.AccessController.doPrivileged( - new PrivilegedAction() { - @Override - public String run() { - return System.getProperty("jdk.net.useFastTcpLoopback"); - } - }); + String loopbackProp = + GetPropertyAction.getProperty("jdk.net.useFastTcpLoopback"); boolean enable; if ("".equals(loopbackProp)) { enable = true; @@ -647,16 +643,9 @@ public class Net { int availLevel = isExclusiveBindAvailable(); if (availLevel >= 0) { String exclBindProp = - java.security.AccessController.doPrivileged( - new PrivilegedAction() { - @Override - public String run() { - return System.getProperty( - "sun.net.useExclusiveBind"); - } - }); + GetPropertyAction.getProperty("sun.net.useExclusiveBind"); if (exclBindProp != null) { - exclusiveBind = exclBindProp.length() == 0 ? + exclusiveBind = exclBindProp.isEmpty() ? true : Boolean.parseBoolean(exclBindProp); } else if (availLevel == 1) { exclusiveBind = true; diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/Util.java b/jdk/src/java.base/share/classes/sun/nio/ch/Util.java index af89eca45447f5cc3b33f2c5cabe68b306d0b633..e71e628ede1c3e2b1bec3e6deea4cce4204909a3 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/Util.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/Util.java @@ -64,13 +64,7 @@ public class Util { * for potential future-proofing. */ private static long getMaxCachedBufferSize() { - String s = java.security.AccessController.doPrivileged( - new PrivilegedAction() { - @Override - public String run() { - return System.getProperty("jdk.nio.maxCachedBufferSize"); - } - }); + String s = GetPropertyAction.getProperty("jdk.nio.maxCachedBufferSize"); if (s != null) { try { long m = Long.parseLong(s); @@ -471,8 +465,7 @@ public class Util { if (bugLevel == null) { if (!jdk.internal.misc.VM.isBooted()) return false; - String value = AccessController.doPrivileged( - new GetPropertyAction("sun.nio.ch.bugLevel")); + String value = GetPropertyAction.getProperty("sun.nio.ch.bugLevel"); bugLevel = (value != null) ? value : ""; } return bugLevel.equals(bl); diff --git a/jdk/src/java.base/share/classes/sun/nio/cs/StandardCharsets.java.template b/jdk/src/java.base/share/classes/sun/nio/cs/StandardCharsets.java.template index dd4d39942400894520d2537aa5a1088427f9ddd1..2ad055e50ecbc7ab90030972a03ac1f7d7ef73fd 100644 --- a/jdk/src/java.base/share/classes/sun/nio/cs/StandardCharsets.java.template +++ b/jdk/src/java.base/share/classes/sun/nio/cs/StandardCharsets.java.template @@ -34,8 +34,7 @@ import java.nio.charset.spi.CharsetProvider; import java.util.Iterator; import java.util.Locale; import java.util.Map; -import java.security.AccessController; -import java.security.PrivilegedAction; +import sun.security.action.GetPropertyAction; public class StandardCharsets extends CharsetProvider { @@ -201,15 +200,7 @@ public class StandardCharsets extends CharsetProvider { } private static String getProperty(String key) { - // this method may be called during initialization of - // system class loader and thus not using lambda - return AccessController.doPrivileged( - new PrivilegedAction() { - @Override - public String run() { - return System.getProperty(key); - } - }); + return GetPropertyAction.getProperty(key); } diff --git a/jdk/src/java.base/share/classes/sun/nio/fs/Util.java b/jdk/src/java.base/share/classes/sun/nio/fs/Util.java index 2d5c8cb644360d2bb1e3bb96db85f0000f9de839..45d90b9922254861723cc66146326a80576ffa38 100644 --- a/jdk/src/java.base/share/classes/sun/nio/fs/Util.java +++ b/jdk/src/java.base/share/classes/sun/nio/fs/Util.java @@ -28,8 +28,7 @@ package sun.nio.fs; import java.util.*; import java.nio.file.*; import java.nio.charset.Charset; -import java.security.*; -import sun.security.action.*; +import sun.security.action.GetPropertyAction; /** * Utility methods @@ -39,7 +38,7 @@ class Util { private Util() { } private static final Charset jnuEncoding = Charset.forName( - AccessController.doPrivileged(new GetPropertyAction("sun.jnu.encoding"))); + GetPropertyAction.getProperty("sun.jnu.encoding")); /** * Returns {@code Charset} corresponding to the sun.jnu.encoding property diff --git a/jdk/src/java.base/share/classes/sun/security/action/GetIntegerAction.java b/jdk/src/java.base/share/classes/sun/security/action/GetIntegerAction.java index ff2b2019b4880ed7f8f28a1046e2dd925d56251a..c454b431861829a0ed87d628c7b64ce5e74f8419 100644 --- a/jdk/src/java.base/share/classes/sun/security/action/GetIntegerAction.java +++ b/jdk/src/java.base/share/classes/sun/security/action/GetIntegerAction.java @@ -25,6 +25,8 @@ package sun.security.action; +import java.security.AccessController; + /** * A convenience class for retrieving the integer value of a system property * as a privileged action. @@ -67,7 +69,7 @@ public class GetIntegerAction implements java.security.PrivilegedAction { private String theProp; private int defaultVal; - private boolean defaultSet = false; + private boolean defaultSet; /** * Constructor that takes the name of the system property whose integer @@ -110,4 +112,39 @@ public class GetIntegerAction return defaultVal; return value; } + + /** + * Convenience method to get a property without going through doPrivileged + * if no security manager is present. This is unsafe for inclusion in a + * public API but allowable here since this class is now encapsulated. + * + * @param theProp the name of the system property. + */ + public static Integer getProperty(String theProp) { + if (System.getSecurityManager() == null) { + return Integer.getInteger(theProp); + } else { + return AccessController.doPrivileged( + new GetIntegerAction(theProp)); + } + } + + /** + * Convenience method to get a property without going through doPrivileged + * if no security manager is present. This is unsafe for inclusion in a + * public API but allowable here since this class is now encapsulated. + * + * @param theProp the name of the system property. + * @param defaultVal the default value. + */ + public static Integer getProperty(String theProp, int defaultVal) { + Integer value; + if (System.getSecurityManager() == null) { + value = Integer.getInteger(theProp); + } else { + value = AccessController.doPrivileged( + new GetIntegerAction(theProp)); + } + return (value != null) ? value : defaultVal; + } } diff --git a/jdk/src/java.base/share/classes/sun/security/action/GetPropertyAction.java b/jdk/src/java.base/share/classes/sun/security/action/GetPropertyAction.java index 95a113c3bef85545959fe922f8b0e9f596dc90e8..bba172b06bc19dec00c2a760b11f3058b56fca73 100644 --- a/jdk/src/java.base/share/classes/sun/security/action/GetPropertyAction.java +++ b/jdk/src/java.base/share/classes/sun/security/action/GetPropertyAction.java @@ -25,6 +25,10 @@ package sun.security.action; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Properties; + /** * A convenience class for retrieving the string value of a system * property as a privileged action. @@ -46,8 +50,7 @@ package sun.security.action; * @since 1.2 */ -public class GetPropertyAction - implements java.security.PrivilegedAction { +public class GetPropertyAction implements PrivilegedAction { private String theProp; private String defaultVal; @@ -84,4 +87,57 @@ public class GetPropertyAction String value = System.getProperty(theProp); return (value == null) ? defaultVal : value; } + + /** + * Convenience method to get a property without going through doPrivileged + * if no security manager is present. This is unsafe for inclusion in a + * public API but allowable here since this class is now encapsulated. + * + * @param theProp the name of the system property. + */ + public static String getProperty(String theProp) { + if (System.getSecurityManager() == null) { + return System.getProperty(theProp); + } else { + return AccessController.doPrivileged( + new GetPropertyAction(theProp)); + } + } + + /** + * Convenience method to get a property without going through doPrivileged + * if no security manager is present. This is unsafe for inclusion in a + * public API but allowable here since this class is now encapsulated. + * + * @param theProp the name of the system property. + * @param defaultVal the default value. + */ + public static String getProperty(String theProp, String defaultVal) { + if (System.getSecurityManager() == null) { + return System.getProperty(theProp, defaultVal); + } else { + return AccessController.doPrivileged( + new GetPropertyAction(theProp, defaultVal)); + } + } + + /** + * Convenience method to call System.getProperties without + * having to go through doPrivileged if no security manager is present. + * This is unsafe for inclusion in a public API but allowable here since + * this class is now encapsulated. + */ + public static Properties getProperties() { + if (System.getSecurityManager() == null) { + return System.getProperties(); + } else { + return AccessController.doPrivileged( + new PrivilegedAction() { + public Properties run() { + return System.getProperties(); + } + } + ); + } + } } diff --git a/jdk/src/java.base/share/classes/sun/security/jca/ProviderConfig.java b/jdk/src/java.base/share/classes/sun/security/jca/ProviderConfig.java index 4ab324914bd78d792233727d3310097bb35315c4..bf65180af6f74ffd9255f27b21b9d20d904c472a 100644 --- a/jdk/src/java.base/share/classes/sun/security/jca/ProviderConfig.java +++ b/jdk/src/java.base/share/classes/sun/security/jca/ProviderConfig.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -236,9 +236,8 @@ final class ProviderConfig { if (debug != null) { debug.println("Loading provider " + ProviderConfig.this); } - ProviderLoader pl = new ProviderLoader(); try { - Provider p = pl.load(provName); + Provider p = ProviderLoader.INSTANCE.load(provName); if (p != null) { if (hasArgument()) { p = p.configure(argument); @@ -303,9 +302,11 @@ final class ProviderConfig { // Inner class for loading security providers listed in java.security file private static final class ProviderLoader { + static final ProviderLoader INSTANCE = new ProviderLoader(); + private final ServiceLoader services; - ProviderLoader() { + private ProviderLoader() { // VM should already been booted at this point, if not // - Only providers in java.base should be loaded, don't use // ServiceLoader diff --git a/jdk/src/java.base/share/classes/sun/security/provider/DSA.java b/jdk/src/java.base/share/classes/sun/security/provider/DSA.java index 6f8c27a38c0281fbec13734ec51ffe9e136a0340..a25949742bbf0d39065bf8d553b3643c9453a203 100644 --- a/jdk/src/java.base/share/classes/sun/security/provider/DSA.java +++ b/jdk/src/java.base/share/classes/sun/security/provider/DSA.java @@ -106,6 +106,18 @@ abstract class DSA extends SignatureSpi { this.p1363Format = p1363Format; } + private static void checkKey(DSAParams params, int digestLen, String mdAlgo) + throws InvalidKeyException { + // FIPS186-3 states in sec4.2 that a hash function which provides + // a lower security strength than the (L, N) pair ordinarily should + // not be used. + int valueN = params.getQ().bitLength(); + if (valueN > digestLen) { + throw new InvalidKeyException("The security strength of " + + mdAlgo + " digest algorithm is not sufficient for this key size"); + } + } + /** * Initialize the DSA object with a DSA private key. * @@ -130,6 +142,12 @@ abstract class DSA extends SignatureSpi { throw new InvalidKeyException("DSA private key lacks parameters"); } + // check key size against hash output size for signing + // skip this check for verification to minimize impact on existing apps + if (md.getAlgorithm() != "NullDigest20") { + checkKey(params, md.getDigestLength()*8, md.getAlgorithm()); + } + this.params = params; this.presetX = priv.getX(); this.presetY = null; @@ -160,7 +178,6 @@ abstract class DSA extends SignatureSpi { if (params == null) { throw new InvalidKeyException("DSA public key lacks parameters"); } - this.params = params; this.presetY = pub.getY(); this.presetX = null; @@ -406,20 +423,13 @@ abstract class DSA extends SignatureSpi { return t5.mod(q); } - // NOTE: This following impl is defined in FIPS 186-3 AppendixB.2.2. - // Original DSS algos such as SHA1withDSA and RawDSA uses a different - // algorithm defined in FIPS 186-1 Sec3.2, and thus need to override this. + // NOTE: This following impl is defined in FIPS 186-4 AppendixB.2.1. protected BigInteger generateK(BigInteger q) { SecureRandom random = getSigningRandom(); - byte[] kValue = new byte[q.bitLength()/8]; + byte[] kValue = new byte[(q.bitLength() + 7)/8 + 8]; - while (true) { - random.nextBytes(kValue); - BigInteger k = new BigInteger(1, kValue).mod(q); - if (k.signum() > 0 && k.compareTo(q) < 0) { - return k; - } - } + random.nextBytes(kValue); + return new BigInteger(1, kValue).mod(q.subtract(BigInteger.ONE)).add(BigInteger.ONE); } // Use the application-specified SecureRandom Object if provided. @@ -504,222 +514,10 @@ abstract class DSA extends SignatureSpi { } } - static class LegacyDSA extends DSA { - /* The random seed used to generate k */ - private int[] kSeed; - /* The random seed used to generate k (specified by application) */ - private byte[] kSeedAsByteArray; - /* - * The random seed used to generate k - * (prevent the same Kseed from being used twice in a row - */ - private int[] kSeedLast; - - public LegacyDSA(MessageDigest md) throws NoSuchAlgorithmException { - this(md, false); - } - - private LegacyDSA(MessageDigest md, boolean p1363Format) - throws NoSuchAlgorithmException { - super(md, p1363Format); - } - - @Deprecated - protected void engineSetParameter(String key, Object param) { - if (key.equals("KSEED")) { - if (param instanceof byte[]) { - kSeed = byteArray2IntArray((byte[])param); - kSeedAsByteArray = (byte[])param; - } else { - debug("unrecognized param: " + key); - throw new InvalidParameterException("kSeed not a byte array"); - } - } else { - throw new InvalidParameterException("Unsupported parameter"); - } - } - - @Deprecated - protected Object engineGetParameter(String key) { - if (key.equals("KSEED")) { - return kSeedAsByteArray; - } else { - return null; - } - } - - /* - * Please read bug report 4044247 for an alternative, faster, - * NON-FIPS approved method to generate K - */ - @Override - protected BigInteger generateK(BigInteger q) { - BigInteger k = null; - - // The application specified a kSeed for us to use. - // Note: we dis-allow usage of the same Kseed twice in a row - if (kSeed != null && !Arrays.equals(kSeed, kSeedLast)) { - k = generateKUsingKSeed(kSeed, q); - if (k.signum() > 0 && k.compareTo(q) < 0) { - kSeedLast = kSeed.clone(); - return k; - } - } - - // The application did not specify a Kseed for us to use. - // We'll generate a new Kseed by getting random bytes from - // a SecureRandom object. - SecureRandom random = getSigningRandom(); - - while (true) { - int[] seed = new int[5]; - - for (int i = 0; i < 5; i++) seed[i] = random.nextInt(); - - k = generateKUsingKSeed(seed, q); - if (k.signum() > 0 && k.compareTo(q) < 0) { - kSeedLast = seed; - return k; - } - } - } - - /** - * Compute k for the DSA signature as defined in the original DSS, - * i.e. FIPS186. - * - * @param seed the seed for generating k. This seed should be - * secure. This is what is referred to as the KSEED in the DSA - * specification. - * - * @param g the g parameter from the DSA key pair. - */ - private BigInteger generateKUsingKSeed(int[] seed, BigInteger q) { - - // check out t in the spec. - int[] t = { 0xEFCDAB89, 0x98BADCFE, 0x10325476, - 0xC3D2E1F0, 0x67452301 }; - // - int[] tmp = SHA_7(seed, t); - byte[] tmpBytes = new byte[tmp.length * 4]; - for (int i = 0; i < tmp.length; i++) { - int k = tmp[i]; - for (int j = 0; j < 4; j++) { - tmpBytes[(i * 4) + j] = (byte) (k >>> (24 - (j * 8))); - } - } - BigInteger k = new BigInteger(1, tmpBytes).mod(q); - return k; - } - - // Constants for each round - private static final int round1_kt = 0x5a827999; - private static final int round2_kt = 0x6ed9eba1; - private static final int round3_kt = 0x8f1bbcdc; - private static final int round4_kt = 0xca62c1d6; - - /** - * Computes set 1 thru 7 of SHA-1 on m1. */ - static int[] SHA_7(int[] m1, int[] h) { - - int[] W = new int[80]; - System.arraycopy(m1,0,W,0,m1.length); - int temp = 0; - - for (int t = 16; t <= 79; t++){ - temp = W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]; - W[t] = ((temp << 1) | (temp >>>(32 - 1))); - } - - int a = h[0],b = h[1],c = h[2], d = h[3], e = h[4]; - for (int i = 0; i < 20; i++) { - temp = ((a<<5) | (a>>>(32-5))) + - ((b&c)|((~b)&d))+ e + W[i] + round1_kt; - e = d; - d = c; - c = ((b<<30) | (b>>>(32-30))); - b = a; - a = temp; - } - - // Round 2 - for (int i = 20; i < 40; i++) { - temp = ((a<<5) | (a>>>(32-5))) + - (b ^ c ^ d) + e + W[i] + round2_kt; - e = d; - d = c; - c = ((b<<30) | (b>>>(32-30))); - b = a; - a = temp; - } - - // Round 3 - for (int i = 40; i < 60; i++) { - temp = ((a<<5) | (a>>>(32-5))) + - ((b&c)|(b&d)|(c&d)) + e + W[i] + round3_kt; - e = d; - d = c; - c = ((b<<30) | (b>>>(32-30))); - b = a; - a = temp; - } - - // Round 4 - for (int i = 60; i < 80; i++) { - temp = ((a<<5) | (a>>>(32-5))) + - (b ^ c ^ d) + e + W[i] + round4_kt; - e = d; - d = c; - c = ((b<<30) | (b>>>(32-30))); - b = a; - a = temp; - } - int[] md = new int[5]; - md[0] = h[0] + a; - md[1] = h[1] + b; - md[2] = h[2] + c; - md[3] = h[3] + d; - md[4] = h[4] + e; - return md; - } - - /* - * Utility routine for converting a byte array into an int array - */ - private int[] byteArray2IntArray(byte[] byteArray) { - - int j = 0; - byte[] newBA; - int mod = byteArray.length % 4; - - // guarantee that the incoming byteArray is a multiple of 4 - // (pad with 0's) - switch (mod) { - case 3: newBA = new byte[byteArray.length + 1]; break; - case 2: newBA = new byte[byteArray.length + 2]; break; - case 1: newBA = new byte[byteArray.length + 3]; break; - default: newBA = new byte[byteArray.length + 0]; break; - } - System.arraycopy(byteArray, 0, newBA, 0, byteArray.length); - - // copy each set of 4 bytes in the byte array into an integer - int[] newSeed = new int[newBA.length / 4]; - for (int i = 0; i < newBA.length; i += 4) { - newSeed[j] = newBA[i + 3] & 0xFF; - newSeed[j] |= (newBA[i + 2] << 8) & 0xFF00; - newSeed[j] |= (newBA[i + 1] << 16) & 0xFF0000; - newSeed[j] |= (newBA[i + 0] << 24) & 0xFF000000; - j++; - } - - return newSeed; - } - } - /** * Standard SHA1withDSA implementation. */ - public static final class SHA1withDSA extends LegacyDSA { + public static final class SHA1withDSA extends DSA { public SHA1withDSA() throws NoSuchAlgorithmException { super(MessageDigest.getInstance("SHA-1")); } @@ -728,7 +526,7 @@ abstract class DSA extends SignatureSpi { /** * SHA1withDSA implementation that uses the IEEE P1363 format. */ - public static final class SHA1withDSAinP1363Format extends LegacyDSA { + public static final class SHA1withDSAinP1363Format extends DSA { public SHA1withDSAinP1363Format() throws NoSuchAlgorithmException { super(MessageDigest.getInstance("SHA-1"), true); } @@ -741,7 +539,7 @@ abstract class DSA extends SignatureSpi { * not, a SignatureException is thrown when sign()/verify() is called * per JCA spec. */ - static class Raw extends LegacyDSA { + static class Raw extends DSA { // Internal special-purpose MessageDigest impl for RawDSA // Only override whatever methods used // NOTE: no clone support diff --git a/jdk/src/java.base/share/classes/sun/security/provider/DSAKeyFactory.java b/jdk/src/java.base/share/classes/sun/security/provider/DSAKeyFactory.java index 72797aea18becfd33476bf8965414b64740d1c14..731f6b13e4503d4d06a5762b96759ea486840e51 100644 --- a/jdk/src/java.base/share/classes/sun/security/provider/DSAKeyFactory.java +++ b/jdk/src/java.base/share/classes/sun/security/provider/DSAKeyFactory.java @@ -70,8 +70,7 @@ public class DSAKeyFactory extends KeyFactorySpi { * By default this is false. * This incompatibility was introduced by 4532506. */ - String prop = AccessController.doPrivileged - (new GetPropertyAction(SERIAL_PROP, null)); + String prop = GetPropertyAction.getProperty(SERIAL_PROP); SERIAL_INTEROP = "true".equalsIgnoreCase(prop); } diff --git a/jdk/src/java.base/share/classes/sun/security/rsa/RSAKeyFactory.java b/jdk/src/java.base/share/classes/sun/security/rsa/RSAKeyFactory.java index d869a8aaca45b7c1e90a66a1f8b1305faaab2064..d3497aea557846e3644463db37b9458cf4937b9f 100644 --- a/jdk/src/java.base/share/classes/sun/security/rsa/RSAKeyFactory.java +++ b/jdk/src/java.base/share/classes/sun/security/rsa/RSAKeyFactory.java @@ -84,9 +84,8 @@ public final class RSAKeyFactory extends KeyFactorySpi { public static final int MAX_RESTRICTED_EXPLEN = 64; private static final boolean restrictExpLen = - "true".equalsIgnoreCase(AccessController.doPrivileged( - new GetPropertyAction( - "sun.security.rsa.restrictRSAExponent", "true"))); + "true".equalsIgnoreCase(GetPropertyAction.getProperty( + "sun.security.rsa.restrictRSAExponent", "true")); // instance used for static translateKey(); private static final RSAKeyFactory INSTANCE = new RSAKeyFactory(); diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/ClientKeyExchangeService.java b/jdk/src/java.base/share/classes/sun/security/ssl/ClientKeyExchangeService.java index 8da221961a0df0dd3125fe94ab8cb9502c4aafa0..8f849f8d54f42a701707f5ec4af895d0eff85d01 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/ClientKeyExchangeService.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/ClientKeyExchangeService.java @@ -50,10 +50,7 @@ public interface ClientKeyExchangeService { providers = new HashMap<>(); static { - final String key = "java.home"; - String path = AccessController.doPrivileged( - new GetPropertyAction(key), null, - new PropertyPermission(key, "read")); + String path = GetPropertyAction.getProperty("java.home"); ServiceLoader sc = AccessController.doPrivileged( (PrivilegedAction>) diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/Debug.java b/jdk/src/java.base/share/classes/sun/security/ssl/Debug.java index 494dd3257baded06ad1e793583f3a3d313edbde0..c05505edf4aea26e8fae0d1aa7a48587d7d67ded 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/Debug.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/Debug.java @@ -26,7 +26,6 @@ package sun.security.ssl; import java.io.PrintStream; -import java.security.AccessController; import java.util.Locale; import sun.security.util.HexDumpEncoder; @@ -46,8 +45,7 @@ public class Debug { private static String args; static { - args = java.security.AccessController.doPrivileged( - new GetPropertyAction("javax.net.debug", "")); + args = GetPropertyAction.getProperty("javax.net.debug", ""); args = args.toLowerCase(Locale.ENGLISH); if (args.equals("help")) { Help(); @@ -184,8 +182,7 @@ public class Debug { */ static boolean getBooleanProperty(String propName, boolean defaultValue) { // if set, require value of either true or false - String b = AccessController.doPrivileged( - new GetPropertyAction(propName)); + String b = GetPropertyAction.getProperty(propName); if (b == null) { return defaultValue; } else if (b.equalsIgnoreCase("false")) { diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java b/jdk/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java index 903f6fb376a8ecbe60585f01f65313f1b8fefd50..f3384c5b74654097e4ec5c16c4c56dbd3efc3472 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java @@ -656,8 +656,7 @@ public abstract class SSLContextImpl extends SSLContextSpi { // the provider service. Instead, please handle the initialization // exception in the caller's constructor. static { - String property = AccessController.doPrivileged( - new GetPropertyAction(PROPERTY_NAME)); + String property = GetPropertyAction.getProperty(PROPERTY_NAME); if (property != null && property.length() != 0) { // remove double quote marks from beginning/end of the property if (property.length() > 1 && property.charAt(0) == '"' && diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java b/jdk/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java index 412c3ec854455b9359828fe97affd9c48c9c5c88..95258b2ec2b6bc67d6073436b692f525cf9de2dd 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java @@ -209,6 +209,12 @@ public final class SSLSocketImpl extends BaseSSLSocketImpl { Collection sniMatchers = Collections.emptyList(); + // Is the serverNames set to empty with SSLParameters.setServerNames()? + private boolean noSniExtension = false; + + // Is the sniMatchers set to empty with SSLParameters.setSNIMatchers()? + private boolean noSniMatcher = false; + // Configured application protocol values String[] applicationProtocols = new String[0]; @@ -642,6 +648,11 @@ public final class SSLSocketImpl extends BaseSSLSocketImpl { } super.connect(endpoint, timeout); + + if (host == null || host.length() == 0) { + useImplicitHost(false); + } + doneConnect(); } @@ -2098,41 +2109,62 @@ public final class SSLSocketImpl extends BaseSSLSocketImpl { outputRecord.setVersion(protocolVersion); } + // + // ONLY used by ClientHandshaker for the server hostname during handshaking + // synchronized String getHost() { // Note that the host may be null or empty for localhost. if (host == null || host.length() == 0) { - if (!trustNameService) { - // If the local name service is not trustworthy, reverse host - // name resolution should not be performed for endpoint - // identification. Use the application original specified - // hostname or IP address instead. - host = getOriginalHostname(getInetAddress()); - } else { - host = getInetAddress().getHostName(); - } + useImplicitHost(true); } return host; } /* - * Get the original application specified hostname. + * Try to set and use the implicit specified hostname */ - private static String getOriginalHostname(InetAddress inetAddress) { - /* - * Get the original hostname via jdk.internal.misc.SharedSecrets. - */ - JavaNetInetAddressAccess jna = SharedSecrets.getJavaNetInetAddressAccess(); + private synchronized void useImplicitHost(boolean noSniUpdate) { + + // Note: If the local name service is not trustworthy, reverse + // host name resolution should not be performed for endpoint + // identification. Use the application original specified + // hostname or IP address instead. + + // Get the original hostname via jdk.internal.misc.SharedSecrets + InetAddress inetAddress = getInetAddress(); + if (inetAddress == null) { // not connected + return; + } + + JavaNetInetAddressAccess jna = + SharedSecrets.getJavaNetInetAddressAccess(); String originalHostname = jna.getOriginalHostName(inetAddress); + if ((originalHostname != null) && + (originalHostname.length() != 0)) { - /* - * If no application specified hostname, use the IP address. - */ - if (originalHostname == null || originalHostname.length() == 0) { - originalHostname = inetAddress.getHostAddress(); + host = originalHostname; + if (!noSniUpdate && serverNames.isEmpty() && !noSniExtension) { + serverNames = + Utilities.addToSNIServerNameList(serverNames, host); + + if (!roleIsServer && + (handshaker != null) && !handshaker.started()) { + handshaker.setSNIServerNames(serverNames); + } + } + + return; } - return originalHostname; + // No explicitly specified hostname, no server name indication. + if (!trustNameService) { + // The local name service is not trustworthy, use IP address. + host = inetAddress.getHostAddress(); + } else { + // Use the underlying reverse host name resolution service. + host = getInetAddress().getHostName(); + } } // ONLY used by HttpsClient to setup the URI specified hostname @@ -2144,6 +2176,10 @@ public final class SSLSocketImpl extends BaseSSLSocketImpl { this.host = host; this.serverNames = Utilities.addToSNIServerNameList(this.serverNames, this.host); + + if (!roleIsServer && (handshaker != null) && !handshaker.started()) { + handshaker.setSNIServerNames(serverNames); + } } /** @@ -2533,8 +2569,21 @@ public final class SSLSocketImpl extends BaseSSLSocketImpl { // the super implementation does not handle the following parameters params.setEndpointIdentificationAlgorithm(identificationProtocol); params.setAlgorithmConstraints(algorithmConstraints); - params.setSNIMatchers(sniMatchers); - params.setServerNames(serverNames); + + if (sniMatchers.isEmpty() && !noSniMatcher) { + // 'null' indicates none has been set + params.setSNIMatchers(null); + } else { + params.setSNIMatchers(sniMatchers); + } + + if (serverNames.isEmpty() && !noSniExtension) { + // 'null' indicates none has been set + params.setServerNames(null); + } else { + params.setServerNames(serverNames); + } + params.setUseCipherSuitesOrder(preferLocalCipherSuites); params.setMaximumPacketSize(maximumPacketSize); params.setApplicationProtocols(applicationProtocols); @@ -2568,11 +2617,13 @@ public final class SSLSocketImpl extends BaseSSLSocketImpl { List sniNames = params.getServerNames(); if (sniNames != null) { + noSniExtension = sniNames.isEmpty(); serverNames = sniNames; } Collection matchers = params.getSNIMatchers(); if (matchers != null) { + noSniMatcher = matchers.isEmpty(); sniMatchers = matchers; } diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java b/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java index 32e434aa6b447cf0e2065b260b093c1f014dc383..5ce147a3af3d990b738852759e2a438d7cafc426 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java @@ -119,8 +119,8 @@ final class ServerHandshaker extends Handshaker { private long statusRespTimeout; static { - String property = AccessController.doPrivileged( - new GetPropertyAction("jdk.tls.ephemeralDHKeySize")); + String property = + GetPropertyAction.getProperty("jdk.tls.ephemeralDHKeySize"); if (property == null || property.length() == 0) { useLegacyEphemeralDHKeys = false; useSmartEphemeralDHKeys = false; diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/StatusResponseManager.java b/jdk/src/java.base/share/classes/sun/security/ssl/StatusResponseManager.java index b618ab31a1320d96f5857148f0b774cfe6dff6d7..3e21616e48edda2736e505781db392895340b7f8 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/StatusResponseManager.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/StatusResponseManager.java @@ -73,8 +73,8 @@ final class StatusResponseManager { DEFAULT_CACHE_LIFETIME)); cacheLifetime = life > 0 ? life : 0; - String uriStr = AccessController.doPrivileged( - new GetPropertyAction("jdk.tls.stapling.responderURI")); + String uriStr = + GetPropertyAction.getProperty("jdk.tls.stapling.responderURI"); URI tmpURI; try { tmpURI = ((uriStr != null && !uriStr.isEmpty()) ? diff --git a/jdk/src/java.base/share/classes/sun/security/util/Debug.java b/jdk/src/java.base/share/classes/sun/security/util/Debug.java index 35ce8d66348692d5087cde85d70d06fba6e9669e..514608dc73ca998abc708e216a3db357fed3feb4 100644 --- a/jdk/src/java.base/share/classes/sun/security/util/Debug.java +++ b/jdk/src/java.base/share/classes/sun/security/util/Debug.java @@ -29,6 +29,7 @@ import java.math.BigInteger; import java.util.regex.Pattern; import java.util.regex.Matcher; import java.util.Locale; +import sun.security.action.GetPropertyAction; /** * A utility class for debuging. @@ -42,13 +43,10 @@ public class Debug { private static String args; static { - args = java.security.AccessController.doPrivileged - (new sun.security.action.GetPropertyAction - ("java.security.debug")); + args = GetPropertyAction.getProperty("java.security.debug"); - String args2 = java.security.AccessController.doPrivileged - (new sun.security.action.GetPropertyAction - ("java.security.auth.debug")); + String args2 = + GetPropertyAction.getProperty("java.security.auth.debug"); if (args == null) { args = args2; diff --git a/jdk/src/java.base/share/classes/sun/util/calendar/LocalGregorianCalendar.java b/jdk/src/java.base/share/classes/sun/util/calendar/LocalGregorianCalendar.java index 10cbbdceee13b4d395aff723810d5d6ce8733be7..90389c732529f9dacbf019fc0b58fbe3e1fc896f 100644 --- a/jdk/src/java.base/share/classes/sun/util/calendar/LocalGregorianCalendar.java +++ b/jdk/src/java.base/share/classes/sun/util/calendar/LocalGregorianCalendar.java @@ -27,6 +27,7 @@ package sun.util.calendar; import java.security.AccessController; import java.util.TimeZone; +import sun.security.action.GetPropertyAction; /** * @@ -142,8 +143,8 @@ public class LocalGregorianCalendar extends BaseCalendar { } // Append an era to the predefined eras if it's given by the property. - String prop = AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("jdk.calendar.japanese.supplemental.era")); + String prop = GetPropertyAction + .getProperty("jdk.calendar.japanese.supplemental.era"); if (prop != null) { Era era = parseEraEntry(prop); if (era != null) { diff --git a/jdk/src/java.base/share/classes/sun/util/calendar/ZoneInfoFile.java b/jdk/src/java.base/share/classes/sun/util/calendar/ZoneInfoFile.java index 365e0e7967ca986411425e4e51ca40d5b29b82cc..58c0c5bbe01ae10277b6fd32d17f620bba368a93 100644 --- a/jdk/src/java.base/share/classes/sun/util/calendar/ZoneInfoFile.java +++ b/jdk/src/java.base/share/classes/sun/util/calendar/ZoneInfoFile.java @@ -245,11 +245,12 @@ public final class ZoneInfoFile { }; static { - String oldmapping = AccessController.doPrivileged( - new GetPropertyAction("sun.timezone.ids.oldmapping", "false")).toLowerCase(Locale.ROOT); + String oldmapping = GetPropertyAction + .getProperty("sun.timezone.ids.oldmapping", "false") + .toLowerCase(Locale.ROOT); USE_OLDMAPPING = (oldmapping.equals("yes") || oldmapping.equals("true")); - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { try { String libDir = System.getProperty("java.home") + File.separator + "lib"; try (DataInputStream dis = new DataInputStream( diff --git a/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java b/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java index e19a6c8c531131e852d11081c7867ac9fc7fef80..75f235c73e76a2200b917206e6639ff0f63f4072 100644 --- a/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java +++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java @@ -25,7 +25,6 @@ package sun.util.locale.provider; -import java.security.AccessController; import java.text.spi.BreakIteratorProvider; import java.text.spi.CollatorProvider; import java.text.spi.DateFormatProvider; @@ -47,6 +46,7 @@ import java.util.spi.CurrencyNameProvider; import java.util.spi.LocaleNameProvider; import java.util.spi.LocaleServiceProvider; import java.util.spi.TimeZoneNameProvider; +import sun.security.action.GetPropertyAction; import sun.util.spi.CalendarProvider; /** @@ -116,8 +116,7 @@ public abstract class LocaleProviderAdapter { adapterCache = new ConcurrentHashMap<>(); static { - String order = AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("java.locale.providers")); + String order = GetPropertyAction.getProperty("java.locale.providers"); List typeList = new ArrayList<>(); // Check user specified adapter preference diff --git a/jdk/src/java.base/share/native/include/jvm.h b/jdk/src/java.base/share/native/include/jvm.h index c5fc7e9117813ca7dc60e715bcae3b042b0af2f0..2011e58352a4fd631edf4f8b8002a34634845343 100644 --- a/jdk/src/java.base/share/native/include/jvm.h +++ b/jdk/src/java.base/share/native/include/jvm.h @@ -179,7 +179,6 @@ JVM_GetStackTraceElements(JNIEnv *env, jobject throwable, jobjectArray elements) */ enum { JVM_STACKWALK_FILL_CLASS_REFS_ONLY = 0x2, - JVM_STACKWALK_FILTER_FILL_IN_STACK_TRACE = 0x10, JVM_STACKWALK_SHOW_HIDDEN_FRAMES = 0x20, JVM_STACKWALK_FILL_LIVE_STACK_FRAMES = 0x100 }; @@ -187,23 +186,15 @@ enum { JNIEXPORT jobject JNICALL JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jlong mode, jint skip_frames, jint frame_count, jint start_index, - jobjectArray classes, jobjectArray frames); JNIEXPORT jint JNICALL JVM_MoreStackWalk(JNIEnv *env, jobject stackStream, jlong mode, jlong anchor, jint frame_count, jint start_index, - jobjectArray classes, jobjectArray frames); JNIEXPORT void JNICALL -JVM_FillStackFrames(JNIEnv* env, jclass cls, - jint start_index, - jobjectArray stackFrames, - jint from_index, jint toIndex); - -JNIEXPORT void JNICALL -JVM_SetMethodInfo(JNIEnv* env, jobject frame); +JVM_ToStackTraceElement(JNIEnv* env, jobject frame, jobject stackElement); JNIEXPORT jobjectArray JNICALL JVM_GetVmArguments(JNIEnv *env); diff --git a/jdk/src/java.base/share/native/launcher/defines.h b/jdk/src/java.base/share/native/launcher/defines.h index e3b18882df46aea66d1fdaf899621fcaeba46024..3b63e038f9d13227dc49cba1badec6ac7d17800a 100644 --- a/jdk/src/java.base/share/native/launcher/defines.h +++ b/jdk/src/java.base/share/native/launcher/defines.h @@ -45,7 +45,11 @@ #ifdef JAVA_ARGS #define HAS_JAVA_ARGS JNI_TRUE -static const char* const_progname = "java"; +#ifdef PROGNAME +static const char* const_progname = PROGNAME; +#else +static char* const_progname = NULL; +#endif static const char* const_jargs[] = JAVA_ARGS; /* * ApplicationHome is prepended to each of these entries; the resulting @@ -59,11 +63,7 @@ static const char* const_appclasspath[] = APP_CLASSPATH; #endif /* APP_CLASSPATH */ #else /* !JAVA_ARGS */ #define HAS_JAVA_ARGS JNI_FALSE -#ifdef PROGNAME -static const char* const_progname = PROGNAME; -#else -static char* const_progname = NULL; -#endif +static const char* const_progname = "java"; static const char** const_jargs = NULL; static const char* const_appclasspath[] = { NULL }; #endif /* JAVA_ARGS */ diff --git a/jdk/src/java.base/share/native/libjava/StackFrameInfo.c b/jdk/src/java.base/share/native/libjava/StackFrameInfo.c index f7930a459241b5e5b426c218fcf40a07a30e62ff..41c021a20276733ca77440094d028c6be7d21175 100644 --- a/jdk/src/java.base/share/native/libjava/StackFrameInfo.c +++ b/jdk/src/java.base/share/native/libjava/StackFrameInfo.c @@ -38,22 +38,10 @@ /* * Class: java_lang_StackFrameInfo - * Method: fillInStackFrames - * Signature: (I[Ljava/lang/Object;[Ljava/lang/Object;II)V + * Method: toStackTraceElement0 + * Signature: (Ljava/lang/StackTraceElement;)V */ -JNIEXPORT void JNICALL Java_java_lang_StackFrameInfo_fillInStackFrames - (JNIEnv *env, jclass dummy, jint startIndex, - jobjectArray stackFrames, jint fromIndex, jint toIndex) { - JVM_FillStackFrames(env, dummy, startIndex, - stackFrames, fromIndex, toIndex); -} - -/* - * Class: java_lang_StackFrameInfo - * Method: setMethodInfo - * Signature: (Ljava/lang/Class;)V - */ -JNIEXPORT void JNICALL Java_java_lang_StackFrameInfo_setMethodInfo - (JNIEnv *env, jobject stackframeinfo) { - JVM_SetMethodInfo(env, stackframeinfo); +JNIEXPORT void JNICALL Java_java_lang_StackFrameInfo_toStackTraceElement0 + (JNIEnv *env, jobject stackframeinfo, jobject stacktraceinfo) { + JVM_ToStackTraceElement(env, stackframeinfo, stacktraceinfo); } diff --git a/jdk/src/java.base/share/native/libjava/StackStreamFactory.c b/jdk/src/java.base/share/native/libjava/StackStreamFactory.c index c23e9d04918cd4fdf17fb28ad9f2f84191168d9b..099b09b3cc6ba6014206ea047dbe0932f684cb3e 100644 --- a/jdk/src/java.base/share/native/libjava/StackStreamFactory.c +++ b/jdk/src/java.base/share/native/libjava/StackStreamFactory.c @@ -45,7 +45,6 @@ JNIEXPORT jboolean JNICALL Java_java_lang_StackStreamFactory_checkStackWalkModes (JNIEnv *env, jclass dummy) { return JVM_STACKWALK_FILL_CLASS_REFS_ONLY == java_lang_StackStreamFactory_FILL_CLASS_REFS_ONLY && - JVM_STACKWALK_FILTER_FILL_IN_STACK_TRACE == java_lang_StackStreamFactory_FILTER_FILL_IN_STACKTRACE && JVM_STACKWALK_SHOW_HIDDEN_FRAMES == java_lang_StackStreamFactory_SHOW_HIDDEN_FRAMES && JVM_STACKWALK_FILL_LIVE_STACK_FRAMES == java_lang_StackStreamFactory_FILL_LIVE_STACK_FRAMES; } @@ -53,26 +52,26 @@ JNIEXPORT jboolean JNICALL Java_java_lang_StackStreamFactory_checkStackWalkModes /* * Class: java_lang_StackStreamFactory_AbstractStackWalker * Method: callStackWalk - * Signature: (JIII[Ljava/lang/Class;[Ljava/lang/StackWalker/StackFrame;)Ljava/lang/Object; + * Signature: (JIII[Ljava/lang/Object;)Ljava/lang/Object; */ JNIEXPORT jobject JNICALL Java_java_lang_StackStreamFactory_00024AbstractStackWalker_callStackWalk (JNIEnv *env, jobject stackstream, jlong mode, jint skipFrames, jint batchSize, jint startIndex, - jobjectArray classes, jobjectArray frames) + jobjectArray frames) { return JVM_CallStackWalk(env, stackstream, mode, skipFrames, batchSize, - startIndex, classes, frames); + startIndex, frames); } /* * Class: java_lang_StackStreamFactory_AbstractStackWalker * Method: fetchStackFrames - * Signature: (JJII[Ljava/lang/Class;[Ljava/lang/StackWalker/StackFrame;)I + * Signature: (JJII[Ljava/lang/Object;)I */ JNIEXPORT jint JNICALL Java_java_lang_StackStreamFactory_00024AbstractStackWalker_fetchStackFrames (JNIEnv *env, jobject stackstream, jlong mode, jlong anchor, jint batchSize, jint startIndex, - jobjectArray classes, jobjectArray frames) + jobjectArray frames) { return JVM_MoreStackWalk(env, stackstream, mode, anchor, batchSize, - startIndex, classes, frames); + startIndex, frames); } diff --git a/jdk/src/java.base/share/native/libjimage/jimage.cpp b/jdk/src/java.base/share/native/libjimage/jimage.cpp index 4816a173be9e188e9bff12da8d8214c400b03277..0c12facbc4dfe7fb1b086e16041e5bbb08887032 100644 --- a/jdk/src/java.base/share/native/libjimage/jimage.cpp +++ b/jdk/src/java.base/share/native/libjimage/jimage.cpp @@ -207,7 +207,30 @@ extern "C" void JIMAGE_ResourceIterator(JImageFile* image, if (!(*visitor)(image, module, "9", parent, base, extension, arg)) { break; } - } } +/* + * JIMAGE_ResourcePath- Given an open image file, a location reference, a buffer + * and a maximum buffer size, copy the path of the resource into the buffer. + * Returns false if not a valid location reference. + * + * Ex. + * JImageLocationRef location = ... + * char path[JIMAGE_MAX_PATH]; + * (*JImageResourcePath)(image, location, path, JIMAGE_MAX_PATH); + */ +extern "C" bool JIMAGE_ResourcePath(JImageFile* image, JImageLocationRef locationRef, + char* path, size_t max) { + ImageFileReader* imageFile = (ImageFileReader*) image; + + u4 offset = (u4) locationRef; + if (offset >= imageFile->locations_size()) { + return false; + } + + ImageLocation location(imageFile->get_location_offset_data(offset)); + imageFile->location_path(location, path, max); + + return true; +} diff --git a/jdk/src/java.base/share/native/libjimage/jimage.hpp b/jdk/src/java.base/share/native/libjimage/jimage.hpp index d215e30c2ab03458f1f471bb44fc211f2442e055..637f1689e49a3bff9e0ff695bdb16721126cef98 100644 --- a/jdk/src/java.base/share/native/libjimage/jimage.hpp +++ b/jdk/src/java.base/share/native/libjimage/jimage.hpp @@ -37,11 +37,13 @@ class JImageFile; typedef jlong JImageLocationRef; // Max path length limit independent of platform. Windows max path is 1024, -// other platforms use 4096. The JCK fails several tests when 1024 is used. +// other platforms use 4096. #define JIMAGE_MAX_PATH 4096 // JImage Error Codes +// Resource was not found +#define JIMAGE_NOT_FOUND (0) // The image file is not prefixed with 0xCAFEDADA #define JIMAGE_BAD_MAGIC (-1) // The image file does not have a compatible (translatable) version @@ -184,3 +186,20 @@ extern "C" void JIMAGE_ResourceIterator(JImageFile* jimage, typedef void (*JImageResourceIterator_t)(JImageFile* jimage, JImageResourceVisitor_t visitor, void* arg); + +/* + * JIMAGE_ResourcePath- Given an open image file, a location reference, a buffer + * and a maximum buffer size, copy the path of the resource into the buffer. + * Returns false if not a valid location reference. + * + * Ex. + * JImageLocationRef location = ... + * char path[JIMAGE_MAX_PATH]; + * (*JImageResourcePath)(image, location, path, JIMAGE_MAX_PATH); + */ +extern "C" bool JIMAGE_ResourcePath(JImageFile* image, JImageLocationRef locationRef, + char* path, size_t max); + +typedef bool (*JImage_ResourcePath_t)(JImageFile* jimage, JImageLocationRef location, + char* buffer, jlong size); + diff --git a/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystem.java b/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystem.java index 8b4177e3fde3acee41b4853fc90eea28276e6bb8..140473283c8f6a57b756448fcbd24521c5d3d9bb 100644 --- a/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystem.java +++ b/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystem.java @@ -28,7 +28,6 @@ package sun.nio.fs; import java.nio.file.*; import java.io.IOException; import java.util.*; -import java.security.AccessController; import sun.security.action.GetPropertyAction; import static sun.nio.fs.SolarisNativeDispatcher.*; @@ -43,8 +42,7 @@ class SolarisFileSystem extends UnixFileSystem { super(provider, dir); // check os.version - String osversion = AccessController - .doPrivileged(new GetPropertyAction("os.version")); + String osversion = GetPropertyAction.getProperty("os.version"); String[] vers = Util.split(osversion, '.'); assert vers.length >= 2; int majorVersion = Integer.parseInt(vers[0]); diff --git a/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java b/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java index 4fcb617a20064482b93c5123517288657e0bd580..affdfb96c7ff9785bf9bfa01ab3260387f0475fc 100644 --- a/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java +++ b/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java @@ -29,7 +29,6 @@ import java.nio.file.*; import java.nio.file.attribute.*; import java.nio.file.spi.FileTypeDetector; import java.io.IOException; -import java.security.AccessController; import sun.security.action.GetPropertyAction; /** @@ -85,8 +84,8 @@ public class SolarisFileSystemProvider extends UnixFileSystemProvider { @Override FileTypeDetector getFileTypeDetector() { - Path userMimeTypes = Paths.get(AccessController.doPrivileged( - new GetPropertyAction("user.home")), ".mime.types"); + Path userMimeTypes = Paths.get( + GetPropertyAction.getProperty("user.home"), ".mime.types"); Path etcMimeTypes = Paths.get("/etc/mime.types"); return chain(new GioFileTypeDetector(), diff --git a/jdk/src/java.base/unix/classes/java/io/UnixFileSystem.java b/jdk/src/java.base/unix/classes/java/io/UnixFileSystem.java index c0ca02dd4adf1d09c95e644237c89dd9157e71cb..c829994cc8559145601dc326069bef7637b8dffc 100644 --- a/jdk/src/java.base/unix/classes/java/io/UnixFileSystem.java +++ b/jdk/src/java.base/unix/classes/java/io/UnixFileSystem.java @@ -25,7 +25,7 @@ package java.io; -import java.security.AccessController; +import java.util.Properties; import sun.security.action.GetPropertyAction; @@ -36,12 +36,10 @@ class UnixFileSystem extends FileSystem { private final String javaHome; public UnixFileSystem() { - slash = AccessController.doPrivileged( - new GetPropertyAction("file.separator")).charAt(0); - colon = AccessController.doPrivileged( - new GetPropertyAction("path.separator")).charAt(0); - javaHome = AccessController.doPrivileged( - new GetPropertyAction("java.home")); + Properties props = GetPropertyAction.getProperties(); + slash = props.getProperty("file.separator").charAt(0); + colon = props.getProperty("path.separator").charAt(0); + javaHome = props.getProperty("java.home"); } diff --git a/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java b/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java index 5f9a546f4bd0994dc531467de79c3fa97ad5cd72..8a1b8ca085e98ba8d0046397265864c670bdc0b4 100644 --- a/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java +++ b/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java @@ -46,8 +46,10 @@ import static java.security.AccessController.doPrivileged; import java.security.PrivilegedAction; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; +import java.util.Properties; import jdk.internal.misc.JavaIOFileDescriptorAccess; import jdk.internal.misc.SharedSecrets; +import sun.security.action.GetPropertyAction; /** * java.lang.Process subclass in the UNIX environment. @@ -123,11 +125,9 @@ final class ProcessImpl extends Process { } String helperPath() { - return AccessController.doPrivileged( - (PrivilegedAction) () -> - helperPath(System.getProperty("java.home"), - System.getProperty("os.arch")) - ); + Properties props = GetPropertyAction.getProperties(); + return helperPath(props.getProperty("java.home"), + props.getProperty("os.arch")); } LaunchMechanism launchMechanism() { @@ -159,9 +159,7 @@ final class ProcessImpl extends Process { } static Platform get() { - String osName = AccessController.doPrivileged( - (PrivilegedAction) () -> System.getProperty("os.name") - ); + String osName = GetPropertyAction.getProperty("os.name"); if (osName.equals("Linux")) { return LINUX; } if (osName.contains("OS X")) { return BSD; } diff --git a/jdk/src/java.base/unix/classes/java/net/DefaultDatagramSocketImplFactory.java b/jdk/src/java.base/unix/classes/java/net/DefaultDatagramSocketImplFactory.java index ad62c582691501c8868d4181c394db6cc76c3750..dd1a6548d6ad8ceaa91a0b9dbff181d1d1b34f8f 100644 --- a/jdk/src/java.base/unix/classes/java/net/DefaultDatagramSocketImplFactory.java +++ b/jdk/src/java.base/unix/classes/java/net/DefaultDatagramSocketImplFactory.java @@ -24,7 +24,7 @@ */ package java.net; -import java.security.AccessController; +import sun.security.action.GetPropertyAction; /** * This class defines a factory for creating DatagramSocketImpls. It defaults @@ -40,8 +40,7 @@ class DefaultDatagramSocketImplFactory { static { String prefix = null; try { - prefix = AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("impl.prefix", null)); + prefix = GetPropertyAction.getProperty("impl.prefix", null); if (prefix != null) prefixImplClass = Class.forName("java.net."+prefix+"DatagramSocketImpl"); } catch (Exception e) { diff --git a/jdk/src/java.base/unix/classes/sun/net/sdp/SdpProvider.java b/jdk/src/java.base/unix/classes/sun/net/sdp/SdpProvider.java index 2b1c3fd841ef744f8e465404416287c268d22db6..a9f15a617f0633fdf971976db072b131c5ac80f1 100644 --- a/jdk/src/java.base/unix/classes/sun/net/sdp/SdpProvider.java +++ b/jdk/src/java.base/unix/classes/sun/net/sdp/SdpProvider.java @@ -34,7 +34,6 @@ import java.io.File; import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintStream; -import java.security.AccessController; import sun.net.sdp.SdpSupport; import sun.security.action.GetPropertyAction; @@ -57,8 +56,7 @@ public class SdpProvider extends NetHooks.Provider { public SdpProvider() { // if this property is not defined then there is nothing to do. - String file = AccessController.doPrivileged( - new GetPropertyAction("com.sun.sdp.conf")); + String file = GetPropertyAction.getProperty("com.sun.sdp.conf"); if (file == null) { this.enabled = false; this.rules = null; @@ -77,8 +75,7 @@ public class SdpProvider extends NetHooks.Provider { // check if debugging is enabled PrintStream out = null; - String logfile = AccessController.doPrivileged( - new GetPropertyAction("com.sun.sdp.debug")); + String logfile = GetPropertyAction.getProperty("com.sun.sdp.debug"); if (logfile != null) { out = System.out; if (logfile.length() > 0) { diff --git a/jdk/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java b/jdk/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java index 0e067d0681fa794a434609f176596472a8e978f5..f205eaf7545aa17d411b0bea8e3f503a576c9a5f 100644 --- a/jdk/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java +++ b/jdk/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java @@ -39,6 +39,7 @@ import sun.net.www.HeaderParser; import sun.net.www.protocol.http.AuthenticationInfo; import sun.net.www.protocol.http.AuthScheme; import sun.net.www.protocol.http.HttpURLConnection; +import sun.security.action.GetPropertyAction; /** * NTLMAuthentication: @@ -73,12 +74,9 @@ public class NTLMAuthentication extends AuthenticationInfo { NTLMAuthenticationCallback.getNTLMAuthenticationCallback(); private String hostname; - private static String defaultDomain; /* Domain to use if not specified by user */ - - static { - defaultDomain = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("http.auth.ntlm.domain", "")); - }; + /* Domain to use if not specified by user */ + private static String defaultDomain = + GetPropertyAction.getProperty("http.auth.ntlm.domain", ""); public static boolean supportsTransparentAuth () { return false; @@ -143,8 +141,7 @@ public class NTLMAuthentication extends AuthenticationInfo { password = pw.getPassword(); init0(); try { - String version = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("ntlm.version")); + String version = GetPropertyAction.getProperty("ntlm.version"); client = new Client(version, hostname, username, ntdomain, password); } catch (NTLMException ne) { try { diff --git a/jdk/src/java.base/unix/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java b/jdk/src/java.base/unix/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java index 7a0ce39229982a4871535660bd607a8f1c359ccb..9018f0fe6a092a7cdf2d2d2970d2eeee8bf4060e 100644 --- a/jdk/src/java.base/unix/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java +++ b/jdk/src/java.base/unix/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java @@ -26,7 +26,6 @@ package sun.nio.ch; import java.nio.channels.spi.AsynchronousChannelProvider; -import java.security.AccessController; import sun.security.action.GetPropertyAction; /** @@ -60,8 +59,7 @@ public class DefaultAsynchronousChannelProvider { * Returns the default AsynchronousChannelProvider. */ public static AsynchronousChannelProvider create() { - String osname = AccessController - .doPrivileged(new GetPropertyAction("os.name")); + String osname = GetPropertyAction.getProperty("os.name"); if (osname.equals("SunOS")) return createProvider("sun.nio.ch.SolarisAsynchronousChannelProvider"); if (osname.equals("Linux")) diff --git a/jdk/src/java.base/unix/classes/sun/nio/ch/InheritedChannel.java b/jdk/src/java.base/unix/classes/sun/nio/ch/InheritedChannel.java index 2bb712e7867c70d79a4fd2346a1a49cf46bee516..8e52936ccb0cda60bb29dbc088fd22ce71d6f625 100644 --- a/jdk/src/java.base/unix/classes/sun/nio/ch/InheritedChannel.java +++ b/jdk/src/java.base/unix/classes/sun/nio/ch/InheritedChannel.java @@ -168,7 +168,7 @@ class InheritedChannel { Class paramTypes[] = { int.class }; Constructor ctr = Reflect.lookupConstructor("java.io.FileDescriptor", paramTypes); - Object args[] = { new Integer(fdVal) }; + Object args[] = { Integer.valueOf(fdVal) }; FileDescriptor fd = (FileDescriptor)Reflect.invoke(ctr, args); diff --git a/jdk/src/java.base/unix/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java b/jdk/src/java.base/unix/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java index 3307c40d8c51487d3b4777795b1349c73cda678f..f8c31b5ac94b331af3001c78c43ec3f98872b05f 100644 --- a/jdk/src/java.base/unix/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java +++ b/jdk/src/java.base/unix/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java @@ -31,7 +31,6 @@ import java.net.*; import java.util.concurrent.*; import java.io.IOException; import java.io.FileDescriptor; -import java.security.AccessController; import sun.net.NetHooks; import sun.security.action.GetPropertyAction; @@ -47,8 +46,8 @@ class UnixAsynchronousSocketChannelImpl private static final boolean disableSynchronousRead; static { - String propValue = AccessController.doPrivileged( - new GetPropertyAction("sun.nio.ch.disableSynchronousRead", "false")); + String propValue = GetPropertyAction + .getProperty("sun.nio.ch.disableSynchronousRead", "false"); disableSynchronousRead = (propValue.length() == 0) ? true : Boolean.valueOf(propValue); } diff --git a/jdk/src/java.base/unix/classes/sun/nio/fs/DefaultFileSystemProvider.java b/jdk/src/java.base/unix/classes/sun/nio/fs/DefaultFileSystemProvider.java index 595f3c6d18766590cafcda0c0449a02b26d5c589..62f6d5ce1450e2d82734dcdecec4c88183593720 100644 --- a/jdk/src/java.base/unix/classes/sun/nio/fs/DefaultFileSystemProvider.java +++ b/jdk/src/java.base/unix/classes/sun/nio/fs/DefaultFileSystemProvider.java @@ -26,7 +26,6 @@ package sun.nio.fs; import java.nio.file.spi.FileSystemProvider; -import java.security.AccessController; import sun.security.action.GetPropertyAction; /** @@ -55,8 +54,7 @@ public class DefaultFileSystemProvider { * Returns the default FileSystemProvider. */ public static FileSystemProvider create() { - String osname = AccessController - .doPrivileged(new GetPropertyAction("os.name")); + String osname = GetPropertyAction.getProperty("os.name"); if (osname.equals("SunOS")) return createProvider("sun.nio.fs.SolarisFileSystemProvider"); if (osname.equals("Linux")) diff --git a/jdk/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java b/jdk/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java index d394ac1017300c3dda66fa091f003df2a1a58dc4..7cf295b0d6d158cee932437b166259a160c50d2e 100644 --- a/jdk/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java +++ b/jdk/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java @@ -31,7 +31,6 @@ import java.nio.file.spi.*; import java.io.IOException; import java.util.*; import java.util.regex.Pattern; -import java.security.AccessController; import sun.security.action.GetPropertyAction; /** @@ -57,8 +56,8 @@ abstract class UnixFileSystem // if process-wide chdir is allowed or default directory is not the // process working directory then paths must be resolved against the // default directory. - String propValue = AccessController.doPrivileged( - new GetPropertyAction("sun.nio.fs.chdirAllowed", "false")); + String propValue = GetPropertyAction + .getProperty("sun.nio.fs.chdirAllowed", "false"); boolean chdirAllowed = (propValue.length() == 0) ? true : Boolean.valueOf(propValue); if (chdirAllowed) { diff --git a/jdk/src/java.base/windows/classes/java/io/WinNTFileSystem.java b/jdk/src/java.base/windows/classes/java/io/WinNTFileSystem.java index 9ee66bf4169b24eecd64ecbc3d308f4d2e2ed8b8..50ccacc3d1e41b3be128dd29a311098d708612e0 100644 --- a/jdk/src/java.base/windows/classes/java/io/WinNTFileSystem.java +++ b/jdk/src/java.base/windows/classes/java/io/WinNTFileSystem.java @@ -25,8 +25,8 @@ package java.io; -import java.security.AccessController; import java.util.Locale; +import java.util.Properties; import sun.security.action.GetPropertyAction; /** @@ -42,10 +42,9 @@ class WinNTFileSystem extends FileSystem { private final char semicolon; public WinNTFileSystem() { - slash = AccessController.doPrivileged( - new GetPropertyAction("file.separator")).charAt(0); - semicolon = AccessController.doPrivileged( - new GetPropertyAction("path.separator")).charAt(0); + Properties props = GetPropertyAction.getProperties(); + slash = props.getProperty("file.separator").charAt(0); + semicolon = props.getProperty("path.separator").charAt(0); altSlash = (this.slash == '\\') ? '/' : '\\'; } diff --git a/jdk/src/java.base/windows/classes/java/net/DefaultDatagramSocketImplFactory.java b/jdk/src/java.base/windows/classes/java/net/DefaultDatagramSocketImplFactory.java index fb632a4a816d164e02ad84798d098454c56d1071..c12378da67dcf95285e870d2d26df8a4f01f1c30 100644 --- a/jdk/src/java.base/windows/classes/java/net/DefaultDatagramSocketImplFactory.java +++ b/jdk/src/java.base/windows/classes/java/net/DefaultDatagramSocketImplFactory.java @@ -24,8 +24,7 @@ */ package java.net; -import java.security.AccessController; -import java.security.PrivilegedAction; +import java.util.Properties; import sun.security.action.GetPropertyAction; /** @@ -57,12 +56,11 @@ class DefaultDatagramSocketImplFactory static { Class prefixImplClassLocal = null; + Properties props = GetPropertyAction.getProperties(); preferIPv4Stack = Boolean.parseBoolean( - AccessController.doPrivileged( - new GetPropertyAction("java.net.preferIPv4Stack"))); + props.getProperty("java.net.preferIPv4Stack")); - String exclBindProp = AccessController.doPrivileged( - new GetPropertyAction("sun.net.useExclusiveBind", "")); + String exclBindProp = props.getProperty("sun.net.useExclusiveBind", ""); exclusiveBind = (exclBindProp.isEmpty()) ? true : Boolean.parseBoolean(exclBindProp); @@ -70,8 +68,7 @@ class DefaultDatagramSocketImplFactory // impl.prefix String prefix = null; try { - prefix = AccessController.doPrivileged( - new GetPropertyAction("impl.prefix", null)); + prefix = props.getProperty("impl.prefix"); if (prefix != null) prefixImplClassLocal = Class.forName("java.net."+prefix+"DatagramSocketImpl"); } catch (Exception e) { diff --git a/jdk/src/java.base/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java b/jdk/src/java.base/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java index 8f464ddfd07a059dfe5ef3eb23c6c6366a005a36..294cd5985bf4e72faea77c34a0fe90d3b902a2dc 100644 --- a/jdk/src/java.base/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java +++ b/jdk/src/java.base/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java @@ -220,7 +220,7 @@ class DualStackPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl case IP_TOS : case SO_RCVBUF : case SO_SNDBUF : - returnValue = new Integer(value); + returnValue = Integer.valueOf(value); break; default: /* shouldn't get here */ throw new SocketException("Option not supported"); diff --git a/jdk/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java b/jdk/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java index 0e17de44b4c1614df6dd816d153583e945cc2741..5583842d0cbadfedcec70cef297f2d49671dcb8c 100644 --- a/jdk/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java +++ b/jdk/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java @@ -34,6 +34,7 @@ import sun.net.www.HeaderParser; import sun.net.www.protocol.http.AuthenticationInfo; import sun.net.www.protocol.http.AuthScheme; import sun.net.www.protocol.http.HttpURLConnection; +import sun.security.action.GetPropertyAction; /** * NTLMAuthentication: @@ -52,9 +53,8 @@ public class NTLMAuthentication extends AuthenticationInfo { private static String defaultDomain; /* Domain to use if not specified by user */ static { - defaultDomain = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("http.auth.ntlm.domain", - "domain")); + defaultDomain = GetPropertyAction.getProperty("http.auth.ntlm.domain", + "domain"); }; private void init0() { diff --git a/jdk/src/java.base/windows/classes/sun/nio/ch/FileDispatcherImpl.java b/jdk/src/java.base/windows/classes/sun/nio/ch/FileDispatcherImpl.java index 4b812d35a4dfda5366a82ea0d993193dbf43aad4..5390b55a3abeecfbefa40930062aad3cac382ac4 100644 --- a/jdk/src/java.base/windows/classes/sun/nio/ch/FileDispatcherImpl.java +++ b/jdk/src/java.base/windows/classes/sun/nio/ch/FileDispatcherImpl.java @@ -27,9 +27,9 @@ package sun.nio.ch; import java.io.FileDescriptor; import java.io.IOException; -import java.security.PrivilegedAction; import jdk.internal.misc.SharedSecrets; import jdk.internal.misc.JavaIOFileDescriptorAccess; +import sun.security.action.GetPropertyAction; class FileDispatcherImpl extends FileDispatcher { @@ -119,13 +119,8 @@ class FileDispatcherImpl extends FileDispatcher { } static boolean isFastFileTransferRequested() { - String fileTransferProp = java.security.AccessController.doPrivileged( - new PrivilegedAction() { - @Override - public String run() { - return System.getProperty("jdk.nio.enableFastFileTransfer"); - } - }); + String fileTransferProp = GetPropertyAction + .getProperty("jdk.nio.enableFastFileTransfer"); boolean enable; if ("".equals(fileTransferProp)) { enable = true; diff --git a/jdk/src/java.base/windows/classes/sun/nio/ch/WindowsSelectorImpl.java b/jdk/src/java.base/windows/classes/sun/nio/ch/WindowsSelectorImpl.java index cb74298d3dc35a5a19eacffe93655ed8c70b0df6..8e01c9e73329fe9aadead68016516757075c4777 100644 --- a/jdk/src/java.base/windows/classes/sun/nio/ch/WindowsSelectorImpl.java +++ b/jdk/src/java.base/windows/classes/sun/nio/ch/WindowsSelectorImpl.java @@ -87,13 +87,13 @@ final class WindowsSelectorImpl extends SelectorImpl { private static final class FdMap extends HashMap { static final long serialVersionUID = 0L; private MapEntry get(int desc) { - return get(new Integer(desc)); + return get(Integer.valueOf(desc)); } private MapEntry put(SelectionKeyImpl ski) { - return put(new Integer(ski.channel.getFDVal()), new MapEntry(ski)); + return put(Integer.valueOf(ski.channel.getFDVal()), new MapEntry(ski)); } private MapEntry remove(SelectionKeyImpl ski) { - Integer fd = new Integer(ski.channel.getFDVal()); + Integer fd = Integer.valueOf(ski.channel.getFDVal()); MapEntry x = get(fd); if ((x != null) && (x.ski.channel == ski.channel)) return remove(fd); diff --git a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsFileAttributes.java b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsFileAttributes.java index 02226053f8d4188c6618d299d3b86d9debaccfa9..4d2d3e97c4ccc63fd9dd8563d4b96c65278b4880 100644 --- a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsFileAttributes.java +++ b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsFileAttributes.java @@ -27,7 +27,6 @@ package sun.nio.fs; import java.nio.file.attribute.*; import java.util.concurrent.TimeUnit; -import java.security.AccessController; import jdk.internal.misc.Unsafe; import sun.security.action.GetPropertyAction; @@ -115,8 +114,8 @@ class WindowsFileAttributes // indicates if accurate metadata is required (interesting on NTFS only) private static final boolean ensureAccurateMetadata; static { - String propValue = AccessController.doPrivileged( - new GetPropertyAction("sun.nio.fs.ensureAccurateMetadata", "false")); + String propValue = GetPropertyAction + .getProperty("sun.nio.fs.ensureAccurateMetadata", "false"); ensureAccurateMetadata = (propValue.length() == 0) ? true : Boolean.valueOf(propValue); } diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaFileSystemModel.java b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaFileSystemModel.java index 05eddcea4d852c9c97db0030a46c502d95b4f3d5..f6f1df47ff7070f9ad8205c05b9f9d3f7534cb5b 100644 --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaFileSystemModel.java +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaFileSystemModel.java @@ -35,7 +35,6 @@ import javax.swing.event.ListDataEvent; import javax.swing.filechooser.FileSystemView; import javax.swing.table.AbstractTableModel; -import sun.misc.ManagedLocalsThread; /** * NavServices-like implementation of a file Table * @@ -393,7 +392,7 @@ class AquaFileSystemModel extends AbstractTableModel implements PropertyChangeLi this.currentDirectory = currentDirectory; this.fid = fid; String name = "Aqua L&F File Loading Thread"; - this.loadThread = new ManagedLocalsThread(this, name); + this.loadThread = new Thread(null, this, name, 0, false); this.loadThread.start(); } diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameDockIconUI.java b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameDockIconUI.java index a24faef499a640e7bfd79184fc3c1901165fefb1..af2aaf05ed61b735663681ba4ed89cc558480d49 100644 --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameDockIconUI.java +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameDockIconUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,28 +40,28 @@ import sun.swing.SwingUtilities2; * From MacDockIconUI * * A JRSUI L&F implementation of JInternalFrame.JDesktopIcon - * @author - * @version */ -public class AquaInternalFrameDockIconUI extends DesktopIconUI implements MouseListener, MouseMotionListener, ComponentListener { - private static final String CACHED_FRAME_ICON_KEY = "apple.laf.internal.frameIcon"; +public final class AquaInternalFrameDockIconUI extends DesktopIconUI + implements MouseListener, MouseMotionListener { - protected JInternalFrame.JDesktopIcon fDesktopIcon; - protected JInternalFrame fFrame; - protected ScaledImageLabel fIconPane; - protected DockLabel fDockLabel; - protected boolean fTrackingIcon = false; + private JInternalFrame.JDesktopIcon fDesktopIcon; + private JInternalFrame fFrame; + private ScaledImageLabel fIconPane; + private DockLabel fDockLabel; + private boolean fTrackingIcon; public static ComponentUI createUI(final JComponent c) { return new AquaInternalFrameDockIconUI(); } + @Override public void installUI(final JComponent c) { fDesktopIcon = (JInternalFrame.JDesktopIcon)c; installComponents(); installListeners(); } + @Override public void uninstallUI(final JComponent c) { uninstallComponents(); uninstallListeners(); @@ -69,55 +69,54 @@ public class AquaInternalFrameDockIconUI extends DesktopIconUI implements MouseL fFrame = null; } - protected void installComponents() { + private void installComponents() { fFrame = fDesktopIcon.getInternalFrame(); fIconPane = new ScaledImageLabel(); fDesktopIcon.setLayout(new BorderLayout()); fDesktopIcon.add(fIconPane, BorderLayout.CENTER); } - protected void uninstallComponents() { + private void uninstallComponents() { fDesktopIcon.setLayout(null); fDesktopIcon.remove(fIconPane); } - protected void installListeners() { + private void installListeners() { fDesktopIcon.addMouseListener(this); fDesktopIcon.addMouseMotionListener(this); - fFrame.addComponentListener(this); } - protected void uninstallListeners() { - fFrame.removeComponentListener(this); + private void uninstallListeners() { fDesktopIcon.removeMouseMotionListener(this); fDesktopIcon.removeMouseListener(this); } + @Override public Dimension getMinimumSize(final JComponent c) { return new Dimension(32, 32); } + @Override public Dimension getMaximumSize(final JComponent c) { return new Dimension(128, 128); } + @Override public Dimension getPreferredSize(final JComponent c) { return new Dimension(64, 64); //$ Dock preferred size } - public Insets getInsets(final JComponent c) { - return new Insets(0, 0, 0, 0); - } - void updateIcon() { fIconPane.updateIcon(); } + @Override public void mousePressed(final MouseEvent e) { fTrackingIcon = fIconPane.mouseInIcon(e); if (fTrackingIcon) fIconPane.repaint(); } + @Override public void mouseReleased(final MouseEvent e) {// only when it's actually in the image if (fFrame.isIconifiable() && fFrame.isIcon()) { if (fTrackingIcon) { @@ -137,6 +136,7 @@ public class AquaInternalFrameDockIconUI extends DesktopIconUI implements MouseL if (fDockLabel != null && !fIconPane.getBounds().contains(e.getX(), e.getY())) fDockLabel.hide(); } + @Override public void mouseEntered(final MouseEvent e) { if ((e.getModifiers() & InputEvent.BUTTON1_MASK) != 0) return; String title = fFrame.getTitle(); @@ -145,41 +145,27 @@ public class AquaInternalFrameDockIconUI extends DesktopIconUI implements MouseL fDockLabel.show(fDesktopIcon); } + @Override public void mouseExited(final MouseEvent e) { if (fDockLabel != null && (e.getModifiers() & InputEvent.BUTTON1_MASK) == 0) fDockLabel.hide(); } + @Override public void mouseClicked(final MouseEvent e) { } + @Override public void mouseDragged(final MouseEvent e) { } + @Override public void mouseMoved(final MouseEvent e) { } - public void componentHidden(final ComponentEvent e) { } - - public void componentMoved(final ComponentEvent e) { } - - public void componentResized(final ComponentEvent e) { - fFrame.putClientProperty(CACHED_FRAME_ICON_KEY, null); - } - - public void componentShown(final ComponentEvent e) { - fFrame.putClientProperty(CACHED_FRAME_ICON_KEY, null); - } - @SuppressWarnings("serial") // Superclass is not serializable across versions - class ScaledImageLabel extends JLabel { + private final class ScaledImageLabel extends JLabel { ScaledImageLabel() { super(null, null, CENTER); } void updateIcon() { - final Object priorIcon = fFrame.getClientProperty(CACHED_FRAME_ICON_KEY); - if (priorIcon instanceof ImageIcon) { - setIcon((ImageIcon)priorIcon); - return; - } - int width = fFrame.getWidth(); int height = fFrame.getHeight(); @@ -196,11 +182,10 @@ public class AquaInternalFrameDockIconUI extends DesktopIconUI implements MouseL final float scale = (float)fDesktopIcon.getWidth() / (float)Math.max(width, height) * 0.89f; // Sending in -1 for width xor height causes it to maintain aspect ratio - final ImageIcon icon = new ImageIcon(fImage.getScaledInstance((int)(width * scale), -1, Image.SCALE_SMOOTH)); - fFrame.putClientProperty(CACHED_FRAME_ICON_KEY, icon); - setIcon(icon); + setIcon(new ImageIcon(fImage.getScaledInstance((int)(width * scale), -1, Image.SCALE_SMOOTH))); } + @Override public void paint(final Graphics g) { if (getIcon() == null) updateIcon(); @@ -222,13 +207,14 @@ public class AquaInternalFrameDockIconUI extends DesktopIconUI implements MouseL return getBounds().contains(e.getX(), e.getY()); } + @Override public Dimension getPreferredSize() { return new Dimension(64, 64); //$ Dock preferred size } } @SuppressWarnings("serial") // Superclass is not serializable across versions - class DockLabel extends JLabel { + private static final class DockLabel extends JLabel { static final int NUB_HEIGHT = 7; static final int ROUND_ADDITIONAL_HEIGHT = 8; static final int ROUND_ADDITIONAL_WIDTH = 12; @@ -243,6 +229,7 @@ public class AquaInternalFrameDockIconUI extends DesktopIconUI implements MouseL setSize(SwingUtilities.computeStringWidth(metrics, getText()) + ROUND_ADDITIONAL_WIDTH * 2, metrics.getAscent() + NUB_HEIGHT + ROUND_ADDITIONAL_HEIGHT); } + @Override public void paint(final Graphics g) { final int width = getWidth(); final int height = getHeight(); @@ -303,6 +290,7 @@ public class AquaInternalFrameDockIconUI extends DesktopIconUI implements MouseL } } + @Override @Deprecated public void hide() { final Container parent = getParent(); diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java index 92df95b6db211414a345a02a42ce680087827c65..d85ed9e8f67525f0d61ca16db0a39606fb10562f 100644 --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java @@ -2183,50 +2183,21 @@ public class AquaTabbedPaneCopyFromBasicUI extends TabbedPaneUI implements Swing } protected int preferredTabAreaHeight(final int tabPlacement, final int width) { - final FontMetrics metrics = getFontMetrics(); final int tabCount = tabPane.getTabCount(); int total = 0; if (tabCount > 0) { - int rows = 1; - int x = 0; - final int maxTabHeight = calculateMaxTabHeight(tabPlacement); - - for (int i = 0; i < tabCount; i++) { - final int tabWidth = calculateTabWidth(tabPlacement, i, metrics); - - if (x != 0 && x + tabWidth > width) { - rows++; - x = 0; - } - x += tabWidth; - } - total = calculateTabAreaHeight(tabPlacement, rows, maxTabHeight); + total = calculateTabAreaHeight(tabPlacement, 1, maxTabHeight); } return total; } protected int preferredTabAreaWidth(final int tabPlacement, final int height) { - final FontMetrics metrics = getFontMetrics(); final int tabCount = tabPane.getTabCount(); int total = 0; if (tabCount > 0) { - int columns = 1; - int y = 0; - final int fontHeight = metrics.getHeight(); - maxTabWidth = calculateMaxTabWidth(tabPlacement); - - for (int i = 0; i < tabCount; i++) { - final int tabHeight = calculateTabHeight(tabPlacement, i, fontHeight); - - if (y != 0 && y + tabHeight > height) { - columns++; - y = 0; - } - y += tabHeight; - } - total = calculateTabAreaWidth(tabPlacement, columns, maxTabWidth); + total = calculateTabAreaWidth(tabPlacement, 1, maxTabWidth); } return total; } diff --git a/jdk/src/java.desktop/macosx/classes/sun/font/CFontManager.java b/jdk/src/java.desktop/macosx/classes/sun/font/CFontManager.java index 9e883938e46f0af2054da570918769180622fbdb..0c505b2857616c90a56e8f0f465adfda9760d7da 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/font/CFontManager.java +++ b/jdk/src/java.desktop/macosx/classes/sun/font/CFontManager.java @@ -42,7 +42,6 @@ import sun.awt.FontConfiguration; import sun.awt.HeadlessToolkit; import sun.awt.util.ThreadGroupUtils; import sun.lwawt.macosx.*; -import sun.misc.ManagedLocalsThread; public final class CFontManager extends SunFontManager { private static Hashtable genericFonts = new Hashtable(); diff --git a/jdk/src/java.desktop/macosx/classes/sun/java2d/IntegerNIORaster.java b/jdk/src/java.desktop/macosx/classes/sun/java2d/IntegerNIORaster.java index 59101b7400649c91dc5cd27624ce038d6dde8ae6..e2dfcf20d73e200a507d0c4c203f0105cde8eb43 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/java2d/IntegerNIORaster.java +++ b/jdk/src/java.desktop/macosx/classes/sun/java2d/IntegerNIORaster.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,7 @@ public class IntegerNIORaster extends SunWritableRaster { ") cannot be <= 0"); } // This is cribbed from java.awt.image.Raster. - DataBuffer db = new DataBufferNIOInt(w * h); + DataBufferNIOInt db = new DataBufferNIOInt(w * h); if (location == null) { location = new Point(0, 0); } @@ -48,13 +48,11 @@ public class IntegerNIORaster extends SunWritableRaster { return new IntegerNIORaster(sppsm, db, location); } - public IntegerNIORaster(SampleModel sampleModel, DataBuffer dataBuffer, Point origin) { + public IntegerNIORaster(SampleModel sampleModel, DataBufferNIOInt dataBuffer, Point origin) { // This is all cribbed from sun.awt.image.IntegerInterleavedRaster & sun.awt.image.IntegerComponentRaster super(sampleModel, dataBuffer, new Rectangle(origin.x, origin.y, sampleModel.getWidth(), sampleModel.getHeight()), origin, null); - if (!(dataBuffer instanceof DataBufferNIOInt)) { - throw new RasterFormatException("IntegerNIORasters must have DataBufferNIOInt DataBuffers"); - } - this.data = ((DataBufferNIOInt)dataBuffer).getBuffer(); + + this.data = dataBuffer.getBuffer(); } public WritableRaster createCompatibleWritableRaster() { diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWToolkit.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWToolkit.java index b74719f149ba19b17eb4da31107632ae381eec27..b7262a5a402311100e498c5178f8dc3a03cce0d6 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWToolkit.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWToolkit.java @@ -35,7 +35,6 @@ import java.security.*; import java.util.*; import sun.awt.*; -import sun.misc.ManagedLocalsThread; import sun.print.*; import sun.awt.util.ThreadGroupUtils; @@ -77,13 +76,14 @@ public abstract class LWToolkit extends SunToolkit implements Runnable { shutdown(); waitForRunState(STATE_CLEANUP); }; - Thread shutdown = new ManagedLocalsThread( - ThreadGroupUtils.getRootThreadGroup(), shutdownRunnable); + Thread shutdown = new Thread( + ThreadGroupUtils.getRootThreadGroup(), shutdownRunnable, + "AWT-Shutdown", 0, false); shutdown.setContextClassLoader(null); Runtime.getRuntime().addShutdownHook(shutdown); String name = "AWT-LW"; - Thread toolkitThread = new ManagedLocalsThread( - ThreadGroupUtils.getRootThreadGroup(), this, name); + Thread toolkitThread = new Thread( + ThreadGroupUtils.getRootThreadGroup(), this, name, 0, false); toolkitThread.setDaemon(true); toolkitThread.setPriority(Thread.NORM_PRIORITY + 1); toolkitThread.start(); diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDragSourceContextPeer.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDragSourceContextPeer.java index 10aef016b0c8aece734fb177a06f859add939d22..0c8d4afc08f2ca0a08ed75b3cf4ef0692dabfb57 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDragSourceContextPeer.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDragSourceContextPeer.java @@ -44,7 +44,6 @@ import sun.awt.dnd.*; import sun.lwawt.LWComponentPeer; import sun.lwawt.LWWindowPeer; import sun.lwawt.PlatformWindow; -import sun.misc.ManagedLocalsThread; public final class CDragSourceContextPeer extends SunDragSourceContextPeer { @@ -181,7 +180,7 @@ public final class CDragSourceContextPeer extends SunDragSourceContextPeer { } } }; - new ManagedLocalsThread(dragRunnable).start(); + new Thread(null, dragRunnable, "Drag", 0, false).start(); } catch (Exception e) { final long nativeDragSource = getNativeContext(); setNativeContext(0); diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFileDialog.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFileDialog.java index 459afae179dde6ae4d07180b1b3103c275301a39..34651baba7033a1f5f9220030a0b22c8f60601ae 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFileDialog.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFileDialog.java @@ -37,7 +37,6 @@ import java.io.*; import sun.awt.CausedFocusEvent.Cause; import sun.awt.AWTAccessor; import sun.java2d.pipe.Region; -import sun.misc.ManagedLocalsThread; import sun.security.action.GetBooleanAction; class CFileDialog implements FileDialogPeer { @@ -120,7 +119,7 @@ class CFileDialog implements FileDialogPeer { if (visible) { // Java2 Dialog class requires peer to run code in a separate thread // and handles keeping the call modal - new ManagedLocalsThread(new Task()).start(); + new Thread(null, new Task(), "FileDialog", 0, false).start(); } // We hide ourself before "show" returns - setVisible(false) // doesn't apply diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterDialogPeer.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterDialogPeer.java index 1837feb0ccd96351c5487665f166d8944a765b7a..cb1ee14870728c04985bf02c03c85e2c96df37ba 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterDialogPeer.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterDialogPeer.java @@ -29,7 +29,6 @@ import java.awt.*; import java.awt.dnd.*; import sun.lwawt.*; -import sun.misc.ManagedLocalsThread; public class CPrinterDialogPeer extends LWWindowPeer { static { @@ -59,7 +58,7 @@ public class CPrinterDialogPeer extends LWWindowPeer { printerDialog.setRetVal(printerDialog.showDialog()); printerDialog.setVisible(false); }; - new ManagedLocalsThread(task).start(); + new Thread(null, task, "PrintDialog", 0, false).start(); } } diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java index 491b257765f2a271e534d65c00ea0d1b3431fce0..a22f0c3d15ef21c3cd833b7d3aed7b01e253cf8f 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java @@ -36,6 +36,7 @@ import java.security.PrivilegedAction; import javax.print.*; import javax.print.attribute.PrintRequestAttributeSet; import javax.print.attribute.HashPrintRequestAttributeSet; +import javax.print.attribute.standard.Copies; import javax.print.attribute.standard.Media; import javax.print.attribute.standard.MediaPrintableArea; import javax.print.attribute.standard.MediaSize; @@ -43,7 +44,6 @@ import javax.print.attribute.standard.MediaSizeName; import javax.print.attribute.standard.PageRanges; import sun.java2d.*; -import sun.misc.ManagedLocalsThread; import sun.print.*; public final class CPrinterJob extends RasterPrinterJob { @@ -194,10 +194,37 @@ public final class CPrinterJob extends RasterPrinterJob { // setPageRange will set firstPage and lastPage as called in getFirstPage // and getLastPage setPageRange(range[0][0] - 1, range[0][1] - 1); + } else { + // if rangeSelect is SunPageSelection.ALL + // then setPageRange appropriately + setPageRange(-1, -1); } } } + private void setPageRangeAttribute(int from, int to, boolean isRangeSet) { + if (attributes != null) { + // since native Print use zero-based page indices, + // we need to store in 1-based format in attributes set + // but setPageRange again uses zero-based indices so it should be + // 1 less than pageRanges attribute + if (isRangeSet) { + attributes.add(new PageRanges(from+1, to+1)); + attributes.add(SunPageSelection.RANGE); + setPageRange(from, to); + } else { + attributes.add(SunPageSelection.ALL); + } + } + } + + private void setCopiesAttribute(int copies) { + if (attributes != null) { + attributes.add(new Copies(copies)); + super.setCopies(copies); + } + } + volatile boolean onEventThread; @Override @@ -691,9 +718,15 @@ public final class CPrinterJob extends RasterPrinterJob { if (pageFormat != null) { Printable printable = pageable.getPrintable(pageIndex); if (printable != null) { - BufferedImage bimg = new BufferedImage((int)Math.round(pageFormat.getWidth()), (int)Math.round(pageFormat.getHeight()), BufferedImage.TYPE_INT_ARGB_PRE); - PeekGraphics peekGraphics = createPeekGraphics(bimg.createGraphics(), printerJob); - Rectangle2D pageFormatArea = getPageFormatArea(pageFormat); + BufferedImage bimg = + new BufferedImage( + (int)Math.round(pageFormat.getWidth()), + (int)Math.round(pageFormat.getHeight()), + BufferedImage.TYPE_INT_ARGB_PRE); + PeekGraphics peekGraphics = + createPeekGraphics(bimg.createGraphics(), printerJob); + Rectangle2D pageFormatArea = + getPageFormatArea(pageFormat); initPrinterGraphics(peekGraphics, pageFormatArea); // Do the assignment here! @@ -741,7 +774,8 @@ public final class CPrinterJob extends RasterPrinterJob { // upcall from native private static void detachPrintLoop(final long target, final long arg) { - new ManagedLocalsThread(() -> _safePrintLoop(target, arg)).start(); + new Thread(null, () -> _safePrintLoop(target, arg), + "PrintLoop", 0, false).start(); } private static native void _safePrintLoop(long target, long arg); diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CPrinterJob.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CPrinterJob.m index 165e70294976f36289797421597bd47d93b1eb2c..03a32ddd8e7172bd85a37e31ff6b7c84f2be9653 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CPrinterJob.m +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CPrinterJob.m @@ -312,9 +312,9 @@ static void javaPageFormatToNSPrintInfo(JNIEnv* env, jobject srcPrintJob, jobjec static void nsPrintInfoToJavaPrinterJob(JNIEnv* env, NSPrintInfo* src, jobject dstPrinterJob, jobject dstPageable) { static JNF_MEMBER_CACHE(jm_setService, sjc_CPrinterJob, "setPrinterServiceFromNative", "(Ljava/lang/String;)V"); - static JNF_MEMBER_CACHE(jm_setCopies, sjc_CPrinterJob, "setCopies", "(I)V"); + static JNF_MEMBER_CACHE(jm_setCopiesAttribute, sjc_CPrinterJob, "setCopiesAttribute", "(I)V"); static JNF_MEMBER_CACHE(jm_setCollated, sjc_CPrinterJob, "setCollated", "(Z)V"); - static JNF_MEMBER_CACHE(jm_setPageRange, sjc_CPrinterJob, "setPageRange", "(II)V"); + static JNF_MEMBER_CACHE(jm_setPageRangeAttribute, sjc_CPrinterJob, "setPageRangeAttribute", "(IIZ)V"); // get the selected printer's name, and set the appropriate PrintService on the Java side NSString *name = [[src printer] name]; @@ -327,7 +327,7 @@ static void nsPrintInfoToJavaPrinterJob(JNIEnv* env, NSPrintInfo* src, jobject d NSNumber* nsCopies = [printingDictionary objectForKey:NSPrintCopies]; if ([nsCopies respondsToSelector:@selector(integerValue)]) { - JNFCallVoidMethod(env, dstPrinterJob, jm_setCopies, [nsCopies integerValue]); // AWT_THREADING Safe (known object) + JNFCallVoidMethod(env, dstPrinterJob, jm_setCopiesAttribute, [nsCopies integerValue]); // AWT_THREADING Safe (known object) } NSNumber* nsCollated = [printingDictionary objectForKey:NSPrintMustCollate]; @@ -340,6 +340,7 @@ static void nsPrintInfoToJavaPrinterJob(JNIEnv* env, NSPrintInfo* src, jobject d if ([nsPrintAllPages respondsToSelector:@selector(boolValue)]) { jint jFirstPage = 0, jLastPage = java_awt_print_Pageable_UNKNOWN_NUMBER_OF_PAGES; + jboolean isRangeSet = false; if (![nsPrintAllPages boolValue]) { NSNumber* nsFirstPage = [printingDictionary objectForKey:NSPrintFirstPage]; @@ -353,9 +354,12 @@ static void nsPrintInfoToJavaPrinterJob(JNIEnv* env, NSPrintInfo* src, jobject d { jLastPage = [nsLastPage integerValue] - 1; } - } + isRangeSet = true; + } + JNFCallVoidMethod(env, dstPrinterJob, jm_setPageRangeAttribute, + jFirstPage, jLastPage, isRangeSet); + // AWT_THREADING Safe (known object) - JNFCallVoidMethod(env, dstPrinterJob, jm_setPageRange, jFirstPage, jLastPage); // AWT_THREADING Safe (known object) } } @@ -368,6 +372,8 @@ static void javaPrinterJobToNSPrintInfo(JNIEnv* env, jobject srcPrinterJob, jobj static JNF_MEMBER_CACHE(jm_isCollated, sjc_CPrinterJob, "isCollated", "()Z"); static JNF_MEMBER_CACHE(jm_getFromPage, sjc_CPrinterJob, "getFromPageAttrib", "()I"); static JNF_MEMBER_CACHE(jm_getToPage, sjc_CPrinterJob, "getToPageAttrib", "()I"); + static JNF_MEMBER_CACHE(jm_getMinPage, sjc_CPrinterJob, "getMinPageAttrib", "()I"); + static JNF_MEMBER_CACHE(jm_getMaxPage, sjc_CPrinterJob, "getMaxPageAttrib", "()I"); static JNF_MEMBER_CACHE(jm_getSelectAttrib, sjc_CPrinterJob, "getSelectAttrib", "()I"); static JNF_MEMBER_CACHE(jm_getNumberOfPages, jc_Pageable, "getNumberOfPages", "()I"); static JNF_MEMBER_CACHE(jm_getPageFormat, sjc_CPrinterJob, "getPageFormatFromAttributes", "()Ljava/awt/print/PageFormat;"); @@ -379,31 +385,33 @@ static void javaPrinterJobToNSPrintInfo(JNIEnv* env, jobject srcPrinterJob, jobj jboolean collated = JNFCallBooleanMethod(env, srcPrinterJob, jm_isCollated); // AWT_THREADING Safe (known object) [printingDictionary setObject:[NSNumber numberWithBool:collated ? YES : NO] forKey:NSPrintMustCollate]; - jint jNumPages = JNFCallIntMethod(env, srcPageable, jm_getNumberOfPages); // AWT_THREADING Safe (!appKit) - if (jNumPages != java_awt_print_Pageable_UNKNOWN_NUMBER_OF_PAGES) - { - jint selectID = JNFCallIntMethod(env, srcPrinterJob, jm_getSelectAttrib); - if (selectID ==0) { - [printingDictionary setObject:[NSNumber numberWithBool:YES] forKey:NSPrintAllPages]; - } else if (selectID == 2) { - // In Mac 10.7, Print ALL is deselected if PrintSelection is YES whether - // NSPrintAllPages is YES or NO + jint selectID = JNFCallIntMethod(env, srcPrinterJob, jm_getSelectAttrib); + jint fromPage = JNFCallIntMethod(env, srcPrinterJob, jm_getFromPage); + jint toPage = JNFCallIntMethod(env, srcPrinterJob, jm_getToPage); + if (selectID ==0) { + [printingDictionary setObject:[NSNumber numberWithBool:YES] forKey:NSPrintAllPages]; + } else if (selectID == 2) { + // In Mac 10.7, Print ALL is deselected if PrintSelection is YES whether + // NSPrintAllPages is YES or NO + [printingDictionary setObject:[NSNumber numberWithBool:NO] forKey:NSPrintAllPages]; + [printingDictionary setObject:[NSNumber numberWithBool:YES] forKey:NSPrintSelectionOnly]; + } else { + jint minPage = JNFCallIntMethod(env, srcPrinterJob, jm_getMinPage); + jint maxPage = JNFCallIntMethod(env, srcPrinterJob, jm_getMaxPage); + + // for PD_SELECTION or PD_NOSELECTION, check from/to page + // to determine which radio button to select + if (fromPage > minPage || toPage < maxPage) { [printingDictionary setObject:[NSNumber numberWithBool:NO] forKey:NSPrintAllPages]; - [printingDictionary setObject:[NSNumber numberWithBool:YES] forKey:NSPrintSelectionOnly]; } else { - [printingDictionary setObject:[NSNumber numberWithBool:NO] forKey:NSPrintAllPages]; + [printingDictionary setObject:[NSNumber numberWithBool:YES] forKey:NSPrintAllPages]; } - - jint fromPage = JNFCallIntMethod(env, srcPrinterJob, jm_getFromPage); - jint toPage = JNFCallIntMethod(env, srcPrinterJob, jm_getToPage); - // setting fromPage and toPage will not be shown in the dialog if printing All pages - [printingDictionary setObject:[NSNumber numberWithInteger:fromPage] forKey:NSPrintFirstPage]; - [printingDictionary setObject:[NSNumber numberWithInteger:toPage] forKey:NSPrintLastPage]; - } - else - { - [printingDictionary setObject:[NSNumber numberWithBool:YES] forKey:NSPrintAllPages]; } + + // setting fromPage and toPage will not be shown in the dialog if printing All pages + [printingDictionary setObject:[NSNumber numberWithInteger:fromPage] forKey:NSPrintFirstPage]; + [printingDictionary setObject:[NSNumber numberWithInteger:toPage] forKey:NSPrintLastPage]; + jobject page = JNFCallObjectMethod(env, srcPrinterJob, jm_getPageFormat); if (page != NULL) { javaPageFormatToNSPrintInfo(env, NULL, page, dst); diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CTrayIcon.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CTrayIcon.m index 73d4c2f7896951741b40023fc91d3f2a780f7fc0..36d13667f5501b685bed2ebe9786e2ad58662c59 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CTrayIcon.m +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CTrayIcon.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,18 +39,21 @@ * If the image of the specified size won't fit into the status bar, * then scale it down proprtionally. Otherwise, leave it as is. */ -static NSSize ScaledImageSizeForStatusBar(NSSize imageSize) { +static NSSize ScaledImageSizeForStatusBar(NSSize imageSize, BOOL autosize) { NSRect imageRect = NSMakeRect(0.0, 0.0, imageSize.width, imageSize.height); // There is a black line at the bottom of the status bar // that we don't want to cover with image pixels. - CGFloat desiredHeight = [[NSStatusBar systemStatusBar] thickness] - 1.0; - CGFloat scaleFactor = MIN(1.0, desiredHeight/imageSize.height); - - imageRect.size.width *= scaleFactor; - imageRect.size.height *= scaleFactor; + CGFloat desiredSize = [[NSStatusBar systemStatusBar] thickness] - 1.0; + if (autosize) { + imageRect.size.width = desiredSize; + imageRect.size.height = desiredSize; + } else { + CGFloat scaleFactor = MIN(1.0, desiredSize/imageSize.height); + imageRect.size.width *= scaleFactor; + imageRect.size.height *= scaleFactor; + } imageRect = NSIntegralRect(imageRect); - return imageRect.size; } @@ -101,9 +104,9 @@ static NSSize ScaledImageSizeForStatusBar(NSSize imageSize) { return peer; } -- (void) setImage:(NSImage *) imagePtr sizing:(BOOL)autosize{ +- (void) setImage:(NSImage *) imagePtr sizing:(BOOL)autosize { NSSize imageSize = [imagePtr size]; - NSSize scaledSize = ScaledImageSizeForStatusBar(imageSize); + NSSize scaledSize = ScaledImageSizeForStatusBar(imageSize, autosize); if (imageSize.width != scaledSize.width || imageSize.height != scaledSize.height) { [imagePtr setSize: scaledSize]; diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/stream/StreamCloser.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/stream/StreamCloser.java index 32fa02fe1757809bf8b94db24880d6d1f0ff832d..f71a481a700bf8f27d177d0f1b7e4ecce0e7da7d 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/stream/StreamCloser.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/stream/StreamCloser.java @@ -26,7 +26,6 @@ package com.sun.imageio.stream; import sun.awt.util.ThreadGroupUtils; -import sun.misc.ManagedLocalsThread; import java.io.IOException; import java.security.AccessController; @@ -92,8 +91,8 @@ public class StreamCloser { * Make its parent the top-level thread group. */ ThreadGroup tg = ThreadGroupUtils.getRootThreadGroup(); - streamCloser = new ManagedLocalsThread(tg, - streamCloserRunnable); + streamCloser = new Thread(tg, streamCloserRunnable, + "StreamCloser", 0, false); /* Set context class loader to null in order to avoid * keeping a strong reference to an application classloader. */ diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java index 5b57582bee97d5d0cc447c1f03a67c44e0220a7f..d27205f3eaf49af98847443727df3d2c8dce4fa2 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java +++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java @@ -64,7 +64,6 @@ import sun.awt.SunToolkit; import sun.awt.OSInfo; import sun.awt.shell.ShellFolder; import sun.font.FontUtilities; -import sun.misc.ManagedLocalsThread; import sun.security.action.GetPropertyAction; import sun.swing.DefaultLayoutStyle; @@ -2053,7 +2052,7 @@ public class WindowsLookAndFeel extends BasicLookAndFeel if (audioRunnable != null) { // Runnable appears to block until completed playing, hence // start up another thread to handle playing. - new ManagedLocalsThread(audioRunnable).start(); + new Thread(null, audioRunnable, "Audio", 0, false).start(); } } } diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AudioFloatConverter.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AudioFloatConverter.java index 910e2dc8352b2833f970852caa4d9ffdeb792979..77930d05657dca6cd48a3860fd24d4c85b2ee97b 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AudioFloatConverter.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AudioFloatConverter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,6 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ + package com.sun.media.sound; import java.nio.ByteBuffer; @@ -319,8 +320,10 @@ public abstract class AudioFloatConverter { float[] out_buff, int out_offset, int out_len) { int ix = in_offset; int ox = out_offset; - for (int i = 0; i < out_len; i++) - out_buff[ox++] = in_buff[ix++] * (1.0f / 127.0f); + for (int i = 0; i < out_len; i++) { + byte x = in_buff[ix++]; + out_buff[ox++] = x > 0 ? x / 127.0f : x / 128.0f; + } return out_buff; } @@ -328,8 +331,10 @@ public abstract class AudioFloatConverter { byte[] out_buff, int out_offset) { int ix = in_offset; int ox = out_offset; - for (int i = 0; i < in_len; i++) - out_buff[ox++] = (byte) (in_buff[ix++] * 127.0f); + for (int i = 0; i < in_len; i++) { + final float x = in_buff[ix++]; + out_buff[ox++] = (byte) (x > 0 ? x * 127 : x * 128); + } return out_buff; } } @@ -340,9 +345,10 @@ public abstract class AudioFloatConverter { float[] out_buff, int out_offset, int out_len) { int ix = in_offset; int ox = out_offset; - for (int i = 0; i < out_len; i++) - out_buff[ox++] = ((in_buff[ix++] & 0xFF) - 127) - * (1.0f / 127.0f); + for (int i = 0; i < out_len; i++) { + byte x = (byte) (in_buff[ix++] - 128); + out_buff[ox++] = x > 0 ? x / 127.0f : x / 128.0f; + } return out_buff; } @@ -350,8 +356,10 @@ public abstract class AudioFloatConverter { byte[] out_buff, int out_offset) { int ix = in_offset; int ox = out_offset; - for (int i = 0; i < in_len; i++) - out_buff[ox++] = (byte) (127 + in_buff[ix++] * 127.0f); + for (int i = 0; i < in_len; i++) { + float x = in_buff[ix++]; + out_buff[ox++] = (byte) (128 + (x > 0 ? x * 127 : x * 128)); + } return out_buff; } } @@ -369,10 +377,9 @@ public abstract class AudioFloatConverter { int ix = in_offset; int len = out_offset + out_len; for (int ox = out_offset; ox < len; ox++) { - out_buff[ox] = ((short) ((in_buff[ix++] & 0xFF) | - (in_buff[ix++] << 8))) * (1.0f / 32767.0f); + short x = (short) (in_buff[ix++] & 0xFF | (in_buff[ix++] << 8)); + out_buff[ox] = x > 0 ? x / 32767.0f : x / 32768.0f; } - return out_buff; } @@ -381,7 +388,8 @@ public abstract class AudioFloatConverter { int ox = out_offset; int len = in_offset + in_len; for (int ix = in_offset; ix < len; ix++) { - int x = (int) (in_buff[ix] * 32767.0); + float f = in_buff[ix]; + short x = (short) (f > 0 ? f * 32767 : f * 32768); out_buff[ox++] = (byte) x; out_buff[ox++] = (byte) (x >>> 8); } @@ -396,8 +404,8 @@ public abstract class AudioFloatConverter { int ix = in_offset; int ox = out_offset; for (int i = 0; i < out_len; i++) { - out_buff[ox++] = ((short) ((in_buff[ix++] << 8) | - (in_buff[ix++] & 0xFF))) * (1.0f / 32767.0f); + short x = (short) ((in_buff[ix++] << 8) | (in_buff[ix++] & 0xFF)); + out_buff[ox++] = x > 0 ? x / 32767.0f : x / 32768.0f; } return out_buff; } @@ -407,7 +415,8 @@ public abstract class AudioFloatConverter { int ix = in_offset; int ox = out_offset; for (int i = 0; i < in_len; i++) { - int x = (int) (in_buff[ix++] * 32767.0); + float f = in_buff[ix++]; + short x = (short) (f > 0 ? f * 32767.0f : f * 32768.0f); out_buff[ox++] = (byte) (x >>> 8); out_buff[ox++] = (byte) x; } @@ -423,7 +432,8 @@ public abstract class AudioFloatConverter { int ox = out_offset; for (int i = 0; i < out_len; i++) { int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8); - out_buff[ox++] = (x - 32767) * (1.0f / 32767.0f); + x -= 32768; + out_buff[ox++] = x > 0 ? x / 32767.0f : x / 32768.0f; } return out_buff; } @@ -433,7 +443,8 @@ public abstract class AudioFloatConverter { int ix = in_offset; int ox = out_offset; for (int i = 0; i < in_len; i++) { - int x = 32767 + (int) (in_buff[ix++] * 32767.0); + float f = in_buff[ix++]; + int x = 32768 + (int) (f > 0 ? f * 32767 : f * 32768); out_buff[ox++] = (byte) x; out_buff[ox++] = (byte) (x >>> 8); } @@ -449,7 +460,8 @@ public abstract class AudioFloatConverter { int ox = out_offset; for (int i = 0; i < out_len; i++) { int x = ((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF); - out_buff[ox++] = (x - 32767) * (1.0f / 32767.0f); + x -= 32768; + out_buff[ox++] = x > 0 ? x / 32767.0f : x / 32768.0f; } return out_buff; } @@ -459,7 +471,8 @@ public abstract class AudioFloatConverter { int ix = in_offset; int ox = out_offset; for (int i = 0; i < in_len; i++) { - int x = 32767 + (int) (in_buff[ix++] * 32767.0); + float f = in_buff[ix++]; + int x = 32768 + (int) (f > 0 ? f * 32767 : f * 32768); out_buff[ox++] = (byte) (x >>> 8); out_buff[ox++] = (byte) x; } @@ -484,7 +497,7 @@ public abstract class AudioFloatConverter { | ((in_buff[ix++] & 0xFF) << 16); if (x > 0x7FFFFF) x -= 0x1000000; - out_buff[ox++] = x * (1.0f / (float)0x7FFFFF); + out_buff[ox++] = x > 0 ? x / 8388607.0f : x / 8388608.0f; } return out_buff; } @@ -494,7 +507,8 @@ public abstract class AudioFloatConverter { int ix = in_offset; int ox = out_offset; for (int i = 0; i < in_len; i++) { - int x = (int) (in_buff[ix++] * (float)0x7FFFFF); + float f = in_buff[ix++]; + int x = (int) (f > 0 ? f * 8388607.0f : f * 8388608.0f); if (x < 0) x += 0x1000000; out_buff[ox++] = (byte) x; @@ -516,7 +530,7 @@ public abstract class AudioFloatConverter { | ((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF); if (x > 0x7FFFFF) x -= 0x1000000; - out_buff[ox++] = x * (1.0f / (float)0x7FFFFF); + out_buff[ox++] = x > 0 ? x / 8388607.0f : x / 8388608.0f; } return out_buff; } @@ -526,7 +540,8 @@ public abstract class AudioFloatConverter { int ix = in_offset; int ox = out_offset; for (int i = 0; i < in_len; i++) { - int x = (int) (in_buff[ix++] * (float)0x7FFFFF); + float f = in_buff[ix++]; + int x = (int) (f > 0 ? f * 8388607.0f : f * 8388608.0f); if (x < 0) x += 0x1000000; out_buff[ox++] = (byte) (x >>> 16); @@ -546,8 +561,8 @@ public abstract class AudioFloatConverter { for (int i = 0; i < out_len; i++) { int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8) | ((in_buff[ix++] & 0xFF) << 16); - x -= 0x7FFFFF; - out_buff[ox++] = x * (1.0f / (float)0x7FFFFF); + x -= 0x800000; + out_buff[ox++] = x > 0 ? x / 8388607.0f : x / 8388608.0f; } return out_buff; } @@ -557,8 +572,9 @@ public abstract class AudioFloatConverter { int ix = in_offset; int ox = out_offset; for (int i = 0; i < in_len; i++) { - int x = (int) (in_buff[ix++] * (float)0x7FFFFF); - x += 0x7FFFFF; + float f = in_buff[ix++]; + int x = (int) (f > 0 ? f * 8388607.0f : f * 8388608.0f); + x += 0x800000; out_buff[ox++] = (byte) x; out_buff[ox++] = (byte) (x >>> 8); out_buff[ox++] = (byte) (x >>> 16); @@ -576,8 +592,8 @@ public abstract class AudioFloatConverter { for (int i = 0; i < out_len; i++) { int x = ((in_buff[ix++] & 0xFF) << 16) | ((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF); - x -= 0x7FFFFF; - out_buff[ox++] = x * (1.0f / (float)0x7FFFFF); + x -= 0x800000; + out_buff[ox++] = x > 0 ? x / 8388607.0f : x / 8388608.0f; } return out_buff; } @@ -587,8 +603,9 @@ public abstract class AudioFloatConverter { int ix = in_offset; int ox = out_offset; for (int i = 0; i < in_len; i++) { - int x = (int) (in_buff[ix++] * (float)0x7FFFFF); - x += 0x7FFFFF; + float f = in_buff[ix++]; + int x = (int) (f > 0 ? f * 8388607.0f : f * 8388608.0f); + x += 8388608; out_buff[ox++] = (byte) (x >>> 16); out_buff[ox++] = (byte) (x >>> 8); out_buff[ox++] = (byte) x; @@ -673,7 +690,7 @@ public abstract class AudioFloatConverter { int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8) | ((in_buff[ix++] & 0xFF) << 16) | ((in_buff[ix++] & 0xFF) << 24); - x -= 0x7FFFFFFF; + x -= 0x80000000; out_buff[ox++] = x * (1.0f / (float)0x7FFFFFFF); } return out_buff; @@ -685,7 +702,7 @@ public abstract class AudioFloatConverter { int ox = out_offset; for (int i = 0; i < in_len; i++) { int x = (int) (in_buff[ix++] * (float)0x7FFFFFFF); - x += 0x7FFFFFFF; + x += 0x80000000; out_buff[ox++] = (byte) x; out_buff[ox++] = (byte) (x >>> 8); out_buff[ox++] = (byte) (x >>> 16); @@ -706,7 +723,7 @@ public abstract class AudioFloatConverter { int x = ((in_buff[ix++] & 0xFF) << 24) | ((in_buff[ix++] & 0xFF) << 16) | ((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF); - x -= 0x7FFFFFFF; + x -= 0x80000000; out_buff[ox++] = x * (1.0f / (float)0x7FFFFFFF); } return out_buff; @@ -718,7 +735,7 @@ public abstract class AudioFloatConverter { int ox = out_offset; for (int i = 0; i < in_len; i++) { int x = (int) (in_buff[ix++] * (float)0x7FFFFFFF); - x += 0x7FFFFFFF; + x += 0x80000000; out_buff[ox++] = (byte) (x >>> 24); out_buff[ox++] = (byte) (x >>> 16); out_buff[ox++] = (byte) (x >>> 8); @@ -737,7 +754,7 @@ public abstract class AudioFloatConverter { // PCM 32+ bit, signed, little-endian private static class AudioFloatConversion32xSL extends AudioFloatConverter { - final int xbytes; + private final int xbytes; AudioFloatConversion32xSL(int xbytes) { this.xbytes = xbytes; @@ -778,7 +795,7 @@ public abstract class AudioFloatConverter { // PCM 32+ bit, signed, big-endian private static class AudioFloatConversion32xSB extends AudioFloatConverter { - final int xbytes; + private final int xbytes; AudioFloatConversion32xSB(int xbytes) { this.xbytes = xbytes; @@ -820,7 +837,7 @@ public abstract class AudioFloatConverter { // PCM 32+ bit, unsigned, little-endian private static class AudioFloatConversion32xUL extends AudioFloatConverter { - final int xbytes; + private final int xbytes; AudioFloatConversion32xUL(int xbytes) { this.xbytes = xbytes; @@ -835,7 +852,7 @@ public abstract class AudioFloatConverter { int x = (in_buff[ix++] & 0xFF) | ((in_buff[ix++] & 0xFF) << 8) | ((in_buff[ix++] & 0xFF) << 16) | ((in_buff[ix++] & 0xFF) << 24); - x -= 0x7FFFFFFF; + x -= 0x80000000; out_buff[ox++] = x * (1.0f / (float)0x7FFFFFFF); } return out_buff; @@ -847,7 +864,7 @@ public abstract class AudioFloatConverter { int ox = out_offset; for (int i = 0; i < in_len; i++) { int x = (int) (in_buff[ix++] * (float)0x7FFFFFFF); - x += 0x7FFFFFFF; + x += 0x80000000; for (int j = 0; j < xbytes; j++) { out_buff[ox++] = 0; } @@ -863,7 +880,7 @@ public abstract class AudioFloatConverter { // PCM 32+ bit, unsigned, big-endian private static class AudioFloatConversion32xUB extends AudioFloatConverter { - final int xbytes; + private final int xbytes; AudioFloatConversion32xUB(int xbytes) { this.xbytes = xbytes; @@ -878,7 +895,7 @@ public abstract class AudioFloatConverter { ((in_buff[ix++] & 0xFF) << 16) | ((in_buff[ix++] & 0xFF) << 8) | (in_buff[ix++] & 0xFF); ix += xbytes; - x -= 2147483647; + x -= 0x80000000; out_buff[ox++] = x * (1.0f / 2147483647.0f); } return out_buff; @@ -889,8 +906,8 @@ public abstract class AudioFloatConverter { int ix = in_offset; int ox = out_offset; for (int i = 0; i < in_len; i++) { - int x = (int) (in_buff[ix++] * 2147483647.0); - x += 2147483647; + int x = (int) (in_buff[ix++] * 2147483647.0f); + x += 0x80000000; out_buff[ox++] = (byte) (x >>> 24); out_buff[ox++] = (byte) (x >>> 16); out_buff[ox++] = (byte) (x >>> 8); diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/JSSecurityManager.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/JSSecurityManager.java index 738704facf416c6f2d7be80da2af95d9cec38279..d59118889c27987a05b71fbd059b300e7f319855 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/JSSecurityManager.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/JSSecurityManager.java @@ -25,8 +25,6 @@ package com.sun.media.sound; -import sun.misc.ManagedLocalsThread; - import java.io.BufferedInputStream; import java.io.InputStream; import java.io.File; @@ -145,12 +143,11 @@ final class JSSecurityManager { static Thread createThread(final Runnable runnable, final String threadName, final boolean isDaemon, final int priority, - final boolean doStart) { - Thread thread = new ManagedLocalsThread(runnable); + final boolean doStart) + { + String name = (threadName != null) ? threadName : "JSSM Thread"; + Thread thread = new Thread(null, runnable, threadName, 0, false); - if (threadName != null) { - thread.setName(threadName); - } thread.setDaemon(isDaemon); if (priority >= 0) { thread.setPriority(priority); diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/JavaSoundAudioClip.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/JavaSoundAudioClip.java index 1ac0a54a3d84f42070226c1a7625d779b672d906..ca9ac9c9122a086ac36390a0a2517967386cb146 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/JavaSoundAudioClip.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/JavaSoundAudioClip.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -232,7 +232,7 @@ public final class JavaSoundAudioClip implements AudioClip, MetaEventListener, L } else if (sequencer != null) { try { sequencerloop = false; - sequencer.addMetaEventListener(this); + sequencer.removeMetaEventListener(this); sequencer.stop(); } catch (Exception e3) { if (Printer.err) e3.printStackTrace(); diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftAudioPusher.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftAudioPusher.java index 87f4852714c1a14ba1f82d3dd809a3be0a6db718..3a5e6d9dc1b8ca2096fcbb4993dda04a23fa9cee 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftAudioPusher.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftAudioPusher.java @@ -24,8 +24,6 @@ */ package com.sun.media.sound; -import sun.misc.ManagedLocalsThread; - import java.io.IOException; import javax.sound.sampled.AudioInputStream; @@ -55,7 +53,7 @@ public final class SoftAudioPusher implements Runnable { if (active) return; active = true; - audiothread = new ManagedLocalsThread(this); + audiothread = new Thread(null, this, "AudioPusher", 0, false); audiothread.setDaemon(true); audiothread.setPriority(Thread.MAX_PRIORITY); audiothread.start(); diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftJitterCorrector.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftJitterCorrector.java index f845a369e0bfb84c5dde407f3879ca5cc49d7aef..61cdf7cdf251edef21f90f4f509a263256f500e1 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftJitterCorrector.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftJitterCorrector.java @@ -24,8 +24,6 @@ */ package com.sun.media.sound; -import sun.misc.ManagedLocalsThread; - import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; import java.io.EOFException; @@ -216,7 +214,7 @@ public final class SoftJitterCorrector extends AudioInputStream { } }; - thread = new ManagedLocalsThread(runnable); + thread = new Thread(null, runnable, "JitterCorrector", 0, false); thread.setDaemon(true); thread.setPriority(Thread.MAX_PRIORITY); thread.start(); diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftSynthesizer.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftSynthesizer.java index ef2182d6c9eef31cd26ec513466d319d3008e160..41b0cffa3df2bdba99a2725887cd9595d33ca50d 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftSynthesizer.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftSynthesizer.java @@ -25,8 +25,6 @@ package com.sun.media.sound; -import sun.misc.ManagedLocalsThread; - import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; @@ -141,7 +139,7 @@ public final class SoftSynthesizer implements AudioSynthesizer, pusher = null; jitter_stream = null; sourceDataLine = null; - new ManagedLocalsThread(runnable).start(); + new Thread(null, runnable, "Synthesizer",0,false).start(); } return len; } diff --git a/jdk/src/java.desktop/share/classes/java/awt/EventDispatchThread.java b/jdk/src/java.desktop/share/classes/java/awt/EventDispatchThread.java index 67b4ad852dfaa204a62ae403a24476f95301e68e..d4bead313602d3d7805795b8af74a4a6ec546dd1 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/EventDispatchThread.java +++ b/jdk/src/java.desktop/share/classes/java/awt/EventDispatchThread.java @@ -31,7 +31,6 @@ import java.awt.event.WindowEvent; import java.util.ArrayList; -import sun.misc.ManagedLocalsThread; import sun.util.logging.PlatformLogger; import sun.awt.dnd.SunDragSourceContextPeer; @@ -55,7 +54,7 @@ import sun.awt.dnd.SunDragSourceContextPeer; * * @since 1.1 */ -class EventDispatchThread extends ManagedLocalsThread { +class EventDispatchThread extends Thread { private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.EventDispatchThread"); @@ -66,8 +65,16 @@ class EventDispatchThread extends ManagedLocalsThread { private ArrayList eventFilters = new ArrayList(); + /** + * Must always call 5 args super-class constructor passing false + * to indicate not to inherit locals. + */ + private EventDispatchThread() { + throw new UnsupportedOperationException("Must erase locals"); + } + EventDispatchThread(ThreadGroup group, String name, EventQueue queue) { - super(group, name); + super(group, null, name, 0, false); setEventQueue(queue); } diff --git a/jdk/src/java.desktop/share/classes/java/awt/Font.java b/jdk/src/java.desktop/share/classes/java/awt/Font.java index 8edd2227badad92e9735a146653b53dcb86f25d3..29ce9f1a084ffbeca355f1629b6a36c10430c11f 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/Font.java +++ b/jdk/src/java.desktop/share/classes/java/awt/Font.java @@ -765,6 +765,49 @@ public class Font implements java.io.Serializable this.hasLayoutAttributes = values.anyNonDefault(LAYOUT_MASK); } + /** + * Returns true if any part of the specified text is from a + * complex script for which the implementation will need to invoke + * layout processing in order to render correctly when using + * {@link Graphics#drawString(String,int,int) drawString(String,int,int)} + * and other text rendering methods. Measurement of the text + * may similarly need the same extra processing. + * The {@code start} and {@code end} indices are provided so that + * the application can request only a subset of the text be considered. + * The last char index examined is at {@code "end-1"}, + * i.e a request to examine the entire array would be + *
+     * {@code Font.textRequiresLayout(chars, 0, chars.length);}
+     * 
+ * An application may find this information helpful in + * performance sensitive code. + *

+ * Note that even if this method returns {@code false}, layout processing + * may still be invoked when used with any {@code Font} + * for which {@link #hasLayoutAttributes()} returns {@code true}, + * so that method will need to be consulted for the specific font, + * in order to obtain an answer which accounts for such font attributes. + * + * @param chars the text. + * @param start the index of the first char to examine. + * @param end the ending index, exclusive. + * @return {@code true} if the specified text will need special layout. + * @throws NullPointerException if {@code chars} is null. + * @throws ArrayIndexOutOfBoundsException if {@code start} is negative or + * {@code end} is greater than the length of the {@code chars} array. + * @since 9 + */ + public static boolean textRequiresLayout(char[] chars, + int start, int end) { + if (chars == null) { + throw new NullPointerException("null char array"); + } + if (start < 0 || end > chars.length) { + throw new ArrayIndexOutOfBoundsException("start < 0 or end > len"); + } + return FontUtilities.isComplexScript(chars, start, end); + } + /** * Returns a {@code Font} appropriate to the attributes. * If {@code attributes} contains a {@code FONT} attribute diff --git a/jdk/src/java.desktop/share/classes/java/awt/image/PackedColorModel.java b/jdk/src/java.desktop/share/classes/java/awt/image/PackedColorModel.java index c5e8ec8d3ab84a2008c2f2b0f19d52d666576754..0db6ff174415436f814d5cc1b2c241ffb717bce2 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/image/PackedColorModel.java +++ b/jdk/src/java.desktop/share/classes/java/awt/image/PackedColorModel.java @@ -404,9 +404,6 @@ public abstract class PackedColorModel extends ColorModel { PackedColorModel cm = (PackedColorModel) obj; int numC = cm.getNumComponents(); - if (numC != numComponents) { - return false; - } for(int i=0; i < numC; i++) { if (maskArray[i] != cm.getMask(i)) { return false; diff --git a/jdk/src/java.desktop/share/classes/java/awt/image/Raster.java b/jdk/src/java.desktop/share/classes/java/awt/image/Raster.java index f5a36d10a47b799c35d4176c47abaf8da949620c..c7aca57eed834bd2a9d4fc730f7eb95daa4d453f 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/image/Raster.java +++ b/jdk/src/java.desktop/share/classes/java/awt/image/Raster.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -629,7 +629,8 @@ public class Raster { int scanlineStride, int pixelStride, int bandOffsets[], - Point location) { + Point location) + { if (dataBuffer == null) { throw new NullPointerException("DataBuffer cannot be null"); } @@ -645,15 +646,26 @@ public class Raster { bandOffsets); switch(dataType) { case DataBuffer.TYPE_BYTE: - return new ByteInterleavedRaster(csm, dataBuffer, location); + if (dataBuffer instanceof DataBufferByte) { + return new ByteInterleavedRaster(csm, + (DataBufferByte) dataBuffer, location); + } + break; case DataBuffer.TYPE_USHORT: - return new ShortInterleavedRaster(csm, dataBuffer, location); + if (dataBuffer instanceof DataBufferUShort) { + return new ShortInterleavedRaster(csm, + (DataBufferUShort) dataBuffer, location); + } + break; default: throw new IllegalArgumentException("Unsupported data type " + dataType); } + + // Create the generic raster + return new SunWritableRaster(csm, dataBuffer, location); } /** @@ -691,7 +703,8 @@ public class Raster { int scanlineStride, int bankIndices[], int bandOffsets[], - Point location) { + Point location) + { if (dataBuffer == null) { throw new NullPointerException("DataBuffer cannot be null"); } @@ -713,18 +726,29 @@ public class Raster { switch(dataType) { case DataBuffer.TYPE_BYTE: - return new ByteBandedRaster(bsm, dataBuffer, location); + if (dataBuffer instanceof DataBufferByte) { + return new ByteBandedRaster(bsm, + (DataBufferByte) dataBuffer, location); + } + break; case DataBuffer.TYPE_USHORT: - return new ShortBandedRaster(bsm, dataBuffer, location); + if (dataBuffer instanceof DataBufferUShort) { + return new ShortBandedRaster(bsm, + (DataBufferUShort) dataBuffer, location); + } + break; case DataBuffer.TYPE_INT: - return new SunWritableRaster(bsm, dataBuffer, location); + break; default: throw new IllegalArgumentException("Unsupported data type " + dataType); } + + // Create the generic raster + return new SunWritableRaster(bsm, dataBuffer, location); } /** @@ -761,7 +785,8 @@ public class Raster { int w, int h, int scanlineStride, int bandMasks[], - Point location) { + Point location) + { if (dataBuffer == null) { throw new NullPointerException("DataBuffer cannot be null"); } @@ -776,18 +801,33 @@ public class Raster { switch(dataType) { case DataBuffer.TYPE_BYTE: - return new ByteInterleavedRaster(sppsm, dataBuffer, location); + if (dataBuffer instanceof DataBufferByte) { + return new ByteInterleavedRaster(sppsm, + (DataBufferByte) dataBuffer, location); + } + break; case DataBuffer.TYPE_USHORT: - return new ShortInterleavedRaster(sppsm, dataBuffer, location); + if (dataBuffer instanceof DataBufferUShort) { + return new ShortInterleavedRaster(sppsm, + (DataBufferUShort) dataBuffer, location); + } + break; case DataBuffer.TYPE_INT: - return new IntegerInterleavedRaster(sppsm, dataBuffer, location); + if (dataBuffer instanceof DataBufferInt) { + return new IntegerInterleavedRaster(sppsm, + (DataBufferInt) dataBuffer, location); + } + break; default: throw new IllegalArgumentException("Unsupported data type " + dataType); } + + // Create the generic raster + return new SunWritableRaster(sppsm, dataBuffer, location); } /** @@ -821,7 +861,8 @@ public class Raster { public static WritableRaster createPackedRaster(DataBuffer dataBuffer, int w, int h, int bitsPerPixel, - Point location) { + Point location) + { if (dataBuffer == null) { throw new NullPointerException("DataBuffer cannot be null"); } @@ -846,9 +887,10 @@ public class Raster { MultiPixelPackedSampleModel mppsm = new MultiPixelPackedSampleModel(dataType, w, h, bitsPerPixel); - if (dataType == DataBuffer.TYPE_BYTE && - (bitsPerPixel == 1 || bitsPerPixel == 2 || bitsPerPixel == 4)) { - return new BytePackedRaster(mppsm, dataBuffer, location); + if (dataBuffer instanceof DataBufferByte && + (bitsPerPixel == 1 || bitsPerPixel == 2 || bitsPerPixel == 4)) + { + return new BytePackedRaster(mppsm, (DataBufferByte) dataBuffer, location); } else { return new SunWritableRaster(mppsm, dataBuffer, location); } @@ -878,7 +920,8 @@ public class Raster { */ public static Raster createRaster(SampleModel sm, DataBuffer db, - Point location) { + Point location) + { if ((sm == null) || (db == null)) { throw new NullPointerException("SampleModel and DataBuffer cannot be null"); } @@ -890,32 +933,53 @@ public class Raster { if (sm instanceof PixelInterleavedSampleModel) { switch(dataType) { - case DataBuffer.TYPE_BYTE: - return new ByteInterleavedRaster(sm, db, location); + case DataBuffer.TYPE_BYTE: + if (db instanceof DataBufferByte) { + return new ByteInterleavedRaster(sm, + (DataBufferByte) db, location); + } + break; - case DataBuffer.TYPE_USHORT: - return new ShortInterleavedRaster(sm, db, location); + case DataBuffer.TYPE_USHORT: + if (db instanceof DataBufferUShort) { + return new ShortInterleavedRaster(sm, + (DataBufferUShort) db, location); + } + break; } } else if (sm instanceof SinglePixelPackedSampleModel) { switch(dataType) { - case DataBuffer.TYPE_BYTE: - return new ByteInterleavedRaster(sm, db, location); + case DataBuffer.TYPE_BYTE: + if (db instanceof DataBufferByte) { + return new ByteInterleavedRaster(sm, + (DataBufferByte) db, location); + } + break; - case DataBuffer.TYPE_USHORT: - return new ShortInterleavedRaster(sm, db, location); + case DataBuffer.TYPE_USHORT: + if (db instanceof DataBufferUShort) { + return new ShortInterleavedRaster(sm, + (DataBufferUShort) db, location); + } + break; - case DataBuffer.TYPE_INT: - return new IntegerInterleavedRaster(sm, db, location); + case DataBuffer.TYPE_INT: + if (db instanceof DataBufferInt) { + return new IntegerInterleavedRaster(sm, + (DataBufferInt) db, location); + } + break; } } else if (sm instanceof MultiPixelPackedSampleModel && dataType == DataBuffer.TYPE_BYTE && - sm.getSampleSize(0) < 8) { - return new BytePackedRaster(sm, db, location); + db instanceof DataBufferByte && + sm.getSampleSize(0) < 8) + { + return new BytePackedRaster(sm, (DataBufferByte) db, location); } // we couldn't do anything special - do the generic thing - - return new Raster(sm,db,location); + return new Raster(sm, db, location); } /** @@ -964,7 +1028,8 @@ public class Raster { */ public static WritableRaster createWritableRaster(SampleModel sm, DataBuffer db, - Point location) { + Point location) + { if ((sm == null) || (db == null)) { throw new NullPointerException("SampleModel and DataBuffer cannot be null"); } @@ -976,32 +1041,53 @@ public class Raster { if (sm instanceof PixelInterleavedSampleModel) { switch(dataType) { - case DataBuffer.TYPE_BYTE: - return new ByteInterleavedRaster(sm, db, location); + case DataBuffer.TYPE_BYTE: + if (db instanceof DataBufferByte) { + return new ByteInterleavedRaster(sm, + (DataBufferByte) db, location); + } + break; - case DataBuffer.TYPE_USHORT: - return new ShortInterleavedRaster(sm, db, location); + case DataBuffer.TYPE_USHORT: + if (db instanceof DataBufferUShort) { + return new ShortInterleavedRaster(sm, + (DataBufferUShort) db, location); + } + break; } } else if (sm instanceof SinglePixelPackedSampleModel) { switch(dataType) { - case DataBuffer.TYPE_BYTE: - return new ByteInterleavedRaster(sm, db, location); + case DataBuffer.TYPE_BYTE: + if (db instanceof DataBufferByte) { + return new ByteInterleavedRaster(sm, + (DataBufferByte) db, location); + } + break; - case DataBuffer.TYPE_USHORT: - return new ShortInterleavedRaster(sm, db, location); + case DataBuffer.TYPE_USHORT: + if (db instanceof DataBufferUShort) { + return new ShortInterleavedRaster(sm, + (DataBufferUShort) db, location); + } + break; - case DataBuffer.TYPE_INT: - return new IntegerInterleavedRaster(sm, db, location); + case DataBuffer.TYPE_INT: + if (db instanceof DataBufferInt) { + return new IntegerInterleavedRaster(sm, + (DataBufferInt) db, location); + } + break; } } else if (sm instanceof MultiPixelPackedSampleModel && dataType == DataBuffer.TYPE_BYTE && - sm.getSampleSize(0) < 8) { - return new BytePackedRaster(sm, db, location); + db instanceof DataBufferByte && + sm.getSampleSize(0) < 8) + { + return new BytePackedRaster(sm, (DataBufferByte) db, location); } // we couldn't do anything special - do the generic thing - - return new SunWritableRaster(sm,db,location); + return new SunWritableRaster(sm, db, location); } /** diff --git a/jdk/src/java.desktop/share/classes/java/awt/image/renderable/RenderableImageProducer.java b/jdk/src/java.desktop/share/classes/java/awt/image/renderable/RenderableImageProducer.java index 77d0b281b43bcace425fcf2f50f601d490473f82..3eccc740aab4ea77c0192e666bdbff39023a5a23 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/image/renderable/RenderableImageProducer.java +++ b/jdk/src/java.desktop/share/classes/java/awt/image/renderable/RenderableImageProducer.java @@ -35,8 +35,6 @@ package java.awt.image.renderable; -import sun.misc.ManagedLocalsThread; - import java.awt.image.ColorModel; import java.awt.image.DataBuffer; import java.awt.image.ImageConsumer; @@ -137,7 +135,7 @@ public class RenderableImageProducer implements ImageProducer, Runnable { addConsumer(ic); // Need to build a runnable object for the Thread. String name = "RenderableImageProducer Thread"; - Thread thread = new ManagedLocalsThread(this, name); + Thread thread = new Thread(null, this, name, 0, false); thread.start(); } diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/ImageIO.java b/jdk/src/java.desktop/share/classes/javax/imageio/ImageIO.java index ae480b9c0023e5c357f5cfe7aa452822999dc1f9..7af7b77be774652c3986446b9c2675c469742a27 100644 --- a/jdk/src/java.desktop/share/classes/javax/imageio/ImageIO.java +++ b/jdk/src/java.desktop/share/classes/javax/imageio/ImageIO.java @@ -1294,7 +1294,8 @@ public final class ImageIO { * * @exception IllegalArgumentException if {@code input} is * {@code null}. - * @exception IOException if an error occurs during reading. + * @exception IOException if an error occurs during reading or when not + * able to create required ImageInputStream. */ public static BufferedImage read(File input) throws IOException { if (input == null) { @@ -1344,7 +1345,8 @@ public final class ImageIO { * * @exception IllegalArgumentException if {@code input} is * {@code null}. - * @exception IOException if an error occurs during reading. + * @exception IOException if an error occurs during reading or when not + * able to create required ImageInputStream. */ public static BufferedImage read(InputStream input) throws IOException { if (input == null) { @@ -1352,6 +1354,9 @@ public final class ImageIO { } ImageInputStream stream = createImageInputStream(input); + if (stream == null) { + throw new IIOException("Can't create an ImageInputStream!"); + } BufferedImage bi = read(stream); if (bi == null) { stream.close(); @@ -1384,7 +1389,8 @@ public final class ImageIO { * * @exception IllegalArgumentException if {@code input} is * {@code null}. - * @exception IOException if an error occurs during reading. + * @exception IOException if an error occurs during reading or when not + * able to create required ImageInputStream. */ public static BufferedImage read(URL input) throws IOException { if (input == null) { @@ -1398,6 +1404,14 @@ public final class ImageIO { throw new IIOException("Can't get input stream from URL!", e); } ImageInputStream stream = createImageInputStream(istream); + if (stream == null) { + /* close the istream when stream is null so that if user has + * given filepath as URL he can delete it, otherwise stream will + * be open to that file and he will not be able to delete it. + */ + istream.close(); + throw new IIOException("Can't create an ImageInputStream!"); + } BufferedImage bi; try { bi = read(stream); @@ -1510,7 +1524,8 @@ public final class ImageIO { * * @exception IllegalArgumentException if any parameter is * {@code null}. - * @exception IOException if an error occurs during writing. + * @exception IOException if an error occurs during writing or when not + * able to create required ImageOutputStream. */ public static boolean write(RenderedImage im, String formatName, @@ -1518,7 +1533,6 @@ public final class ImageIO { if (output == null) { throw new IllegalArgumentException("output == null!"); } - ImageOutputStream stream = null; ImageWriter writer = getWriter(im, formatName); if (writer == null) { @@ -1528,13 +1542,11 @@ public final class ImageIO { return false; } - try { - output.delete(); - stream = createImageOutputStream(output); - } catch (IOException e) { - throw new IIOException("Can't create output stream!", e); + output.delete(); + ImageOutputStream stream = createImageOutputStream(output); + if (stream == null) { + throw new IIOException("Can't create an ImageOutputStream!"); } - try { return doWrite(im, writer, stream); } finally { @@ -1562,7 +1574,8 @@ public final class ImageIO { * * @exception IllegalArgumentException if any parameter is * {@code null}. - * @exception IOException if an error occurs during writing. + * @exception IOException if an error occurs during writing or when not + * able to create required ImageOutputStream. */ public static boolean write(RenderedImage im, String formatName, @@ -1570,13 +1583,10 @@ public final class ImageIO { if (output == null) { throw new IllegalArgumentException("output == null!"); } - ImageOutputStream stream = null; - try { - stream = createImageOutputStream(output); - } catch (IOException e) { - throw new IIOException("Can't create output stream!", e); + ImageOutputStream stream = createImageOutputStream(output); + if (stream == null) { + throw new IIOException("Can't create an ImageOutputStream!"); } - try { return doWrite(im, getWriter(im, formatName), stream); } finally { diff --git a/jdk/src/java.desktop/share/classes/javax/swing/JFileChooser.java b/jdk/src/java.desktop/share/classes/javax/swing/JFileChooser.java index 01edf5d04860928fe0b93159ec5b71cfeda961e6..b37dd05050affee8e64e68c9dec172f65ad21533 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/JFileChooser.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/JFileChooser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * 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,13 +26,12 @@ package javax.swing; import javax.swing.event.*; import javax.swing.filechooser.*; +import javax.swing.filechooser.FileFilter; import javax.swing.plaf.FileChooserUI; import javax.accessibility.*; -import java.io.File; -import java.io.ObjectOutputStream; -import java.io.IOException; +import java.io.*; import java.util.Vector; import java.awt.AWTEvent; @@ -51,8 +50,6 @@ import java.beans.JavaBean; import java.beans.BeanProperty; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeEvent; -import java.io.InvalidObjectException; -import java.io.ObjectInputStream; import java.lang.ref.WeakReference; /** @@ -390,19 +387,7 @@ public class JFileChooser extends JComponent implements Accessible { } private void installHierarchyListener() { - addHierarchyListener(new HierarchyListener() { - @Override - public void hierarchyChanged(HierarchyEvent e) { - if ((e.getChangeFlags() & HierarchyEvent.PARENT_CHANGED) - == HierarchyEvent.PARENT_CHANGED) { - JFileChooser fc = JFileChooser.this; - JRootPane rootPane = SwingUtilities.getRootPane(fc); - if (rootPane != null) { - rootPane.setDefaultButton(fc.getUI().getDefaultButton(fc)); - } - } - } - }); + addHierarchyListener(new FCHierarchyListener()); } private void installShowFilesListener() { @@ -2055,4 +2040,18 @@ public class JFileChooser extends JComponent implements Accessible { } // inner class AccessibleJFileChooser + private class FCHierarchyListener implements HierarchyListener, + Serializable { + @Override + public void hierarchyChanged(HierarchyEvent e) { + if ((e.getChangeFlags() & HierarchyEvent.PARENT_CHANGED) + == HierarchyEvent.PARENT_CHANGED) { + JFileChooser fc = JFileChooser.this; + JRootPane rootPane = SwingUtilities.getRootPane(fc); + if (rootPane != null) { + rootPane.setDefaultButton(fc.getUI().getDefaultButton(fc)); + } + } + } + } } diff --git a/jdk/src/java.desktop/share/classes/javax/swing/JMenu.java b/jdk/src/java.desktop/share/classes/javax/swing/JMenu.java index c9a279a5ed0975e133b18482de334acb9c2ec733..643f2c85ecb00b6f86939d8f7c769f5792396dd9 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/JMenu.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/JMenu.java @@ -1296,7 +1296,7 @@ public class JMenu extends JMenuItem implements Accessible,MenuElement * @return the array of menu items */ private MenuElement[] buildMenuElementArray(JMenu leaf) { - Vector elements = new Vector(); + Vector elements = new Vector<>(); Component current = leaf.getPopupMenu(); JPopupMenu pop; JMenu menu; @@ -1314,11 +1314,14 @@ public class JMenu extends JMenuItem implements Accessible,MenuElement } else if (current instanceof JMenuBar) { bar = (JMenuBar) current; elements.insertElementAt(bar, 0); - MenuElement me[] = new MenuElement[elements.size()]; - elements.copyInto(me); - return me; + break; + } else { + break; } } + MenuElement me[] = new MenuElement[elements.size()]; + elements.copyInto(me); + return me; } diff --git a/jdk/src/java.desktop/share/classes/javax/swing/JTable.java b/jdk/src/java.desktop/share/classes/javax/swing/JTable.java index a0111c36c0d57e96f43006303b1605b64fb15b96..9ca12ea6ee187b1b8d3b6b90d18708dadcc4166a 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/JTable.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/JTable.java @@ -56,7 +56,6 @@ import java.util.List; import javax.print.attribute.*; import javax.print.PrintService; -import sun.misc.ManagedLocalsThread; import sun.reflect.misc.ReflectUtil; import sun.swing.SwingUtilities2; @@ -6375,7 +6374,7 @@ public class JTable extends JComponent implements TableModelListener, Scrollable }; // start printing on another thread - Thread th = new ManagedLocalsThread(runnable); + Thread th = new Thread(null, runnable, "JTablePrint", 0, false); th.start(); printingStatus.showModal(true); diff --git a/jdk/src/java.desktop/share/classes/javax/swing/TimerQueue.java b/jdk/src/java.desktop/share/classes/javax/swing/TimerQueue.java index 5f05a3b6beb3518b09fe2721f6fd5780ecc513b5..9160b956e95b57d8c5b6477ca959d31b18676cb5 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/TimerQueue.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/TimerQueue.java @@ -36,7 +36,6 @@ import java.util.concurrent.*; import java.util.concurrent.locks.*; import java.util.concurrent.atomic.AtomicLong; import sun.awt.AppContext; -import sun.misc.ManagedLocalsThread; /** * Internal class to manage all Timers using one thread. @@ -101,8 +100,8 @@ class TimerQueue implements Runnable final ThreadGroup threadGroup = AppContext.getAppContext().getThreadGroup(); AccessController.doPrivileged((PrivilegedAction) () -> { String name = "TimerQueue"; - Thread timerThread = new ManagedLocalsThread(threadGroup, - this, name); + Thread timerThread = + new Thread(threadGroup, this, name, 0, false); timerThread.setDaemon(true); timerThread.setPriority(Thread.NORM_PRIORITY); timerThread.start(); diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java index d263907f742b8197d20f34cfafeb39b06bab9dd6..a95c82d20fec265eadce86fc1a83284a0d69da21 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java @@ -26,7 +26,6 @@ package javax.swing.plaf.basic; import sun.awt.shell.ShellFolder; -import sun.misc.ManagedLocalsThread; import javax.swing.*; import javax.swing.event.ListDataEvent; @@ -271,7 +270,7 @@ public class BasicDirectoryModel extends AbstractListModel implements Pr this.currentDirectory = currentDirectory; this.fid = fid; String name = "Basic L&F File Loading Thread"; - this.loadThread = new ManagedLocalsThread(this, name); + this.loadThread = new Thread(null, this, name, 0, false); this.loadThread.start(); } diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPopupMenuUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPopupMenuUI.java index 4a4d0baf32b761ba69d7aadd5f6c7287d8b42707..1b6c56c2fc01763b4d4ce9d7f450a83e342e8201 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPopupMenuUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPopupMenuUI.java @@ -797,9 +797,11 @@ public class BasicPopupMenuUI extends PopupMenuUI { if (invoker instanceof JPopupMenu) { invoker = ((JPopupMenu)invoker).getInvoker(); } - grabbedWindow = invoker instanceof Window? - (Window)invoker : - SwingUtilities.getWindowAncestor(invoker); + grabbedWindow = (invoker == null) + ? null + : ((invoker instanceof Window) + ? (Window) invoker + : SwingUtilities.getWindowAncestor(invoker)); if(grabbedWindow != null) { if(tk instanceof sun.awt.SunToolkit) { ((sun.awt.SunToolkit)tk).grab(grabbedWindow); diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/nimbus/NimbusStyle.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/nimbus/NimbusStyle.java index 7fdbe384f57a55cb528f689d59f7724a73a89715..ef49aab21a42879d1a25ca78ed817280c9c0f8c1 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/nimbus/NimbusStyle.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/nimbus/NimbusStyle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -995,16 +995,7 @@ public final class NimbusStyle extends SynthStyle { // StateInfo match, otherwise a StateInfo with // SELECTED | ENABLED would match ENABLED, which we // don't want. - - // This comes from BigInteger.bitCnt - int bitCount = oState; - bitCount -= (0xaaaaaaaa & bitCount) >>> 1; - bitCount = (bitCount & 0x33333333) + ((bitCount >>> 2) & - 0x33333333); - bitCount = bitCount + (bitCount >>> 4) & 0x0f0f0f0f; - bitCount += bitCount >>> 8; - bitCount += bitCount >>> 16; - bitCount = bitCount & 0xff; + int bitCount = Integer.bitCount(oState); if (bitCount > bestCount) { bestIndex = counter; bestCount = bitCount; diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthStyle.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthStyle.java index bf41d10dff16c449ea5dcc8676b03c646dc9e30e..56744c2a03b544287ea11388f83c62549f0fcd4a 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthStyle.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthStyle.java @@ -775,7 +775,7 @@ public abstract class SynthStyle { if (disabledColor == null || disabledColor instanceof UIResource) { return getColorForState(context, type); } - } else if (c instanceof JLabel && + } else if ((c instanceof JLabel || c instanceof JMenuItem) && (type == ColorType.FOREGROUND || type == ColorType.TEXT_FOREGROUND)) { return getColorForState(context, type); diff --git a/jdk/src/java.desktop/share/classes/javax/swing/text/JTextComponent.java b/jdk/src/java.desktop/share/classes/javax/swing/text/JTextComponent.java index 571745be89df4dfc724ed3ea4c7c1f2c5f0641b8..3d31a0d1936a287ab17050078948a6066d3f5676 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/text/JTextComponent.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/text/JTextComponent.java @@ -70,7 +70,6 @@ import javax.print.attribute.*; import sun.awt.AppContext; -import sun.misc.ManagedLocalsThread; import sun.swing.PrintingStatus; import sun.swing.SwingUtilities2; import sun.swing.text.TextComponentPrintable; @@ -2353,7 +2352,8 @@ public abstract class JTextComponent extends JComponent implements Scrollable, A runnablePrinting.run(); } else { if (isEventDispatchThread) { - new ManagedLocalsThread(runnablePrinting).start(); + new Thread(null, runnablePrinting, + "JTextComponentPrint", 0, false ).start(); printingStatus.showModal(true); } else { printingStatus.showModal(false); diff --git a/jdk/src/java.desktop/share/classes/javax/swing/text/LayoutQueue.java b/jdk/src/java.desktop/share/classes/javax/swing/text/LayoutQueue.java index 7109005c7217b5c58305afcfdc4b983b94ed819d..6801a84da5b50635c448dc61a0ba039258b7f099 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/text/LayoutQueue.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/text/LayoutQueue.java @@ -26,7 +26,6 @@ package javax.swing.text; import java.util.Vector; import sun.awt.AppContext; -import sun.misc.ManagedLocalsThread; /** * A queue of text layout tasks. @@ -92,7 +91,7 @@ public class LayoutQueue { } } while (work != null); }; - worker = new ManagedLocalsThread(workerRunnable, "text-layout"); + worker = new Thread(null, workerRunnable, "text-layout", 0, false); worker.setPriority(Thread.MIN_PRIORITY); worker.start(); } diff --git a/jdk/src/java.desktop/share/classes/javax/swing/text/html/CSS.java b/jdk/src/java.desktop/share/classes/javax/swing/text/html/CSS.java index 85cf2a8d16f0372206d29cbd01760a23d703d94b..06a8ebf653456d22ee46cc5bd3565dd1437200ee 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/text/html/CSS.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/text/html/CSS.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1522,8 +1522,16 @@ public class CSS implements Serializable { current++; } last = current; - while (current < length && !Character.isWhitespace - (value.charAt(current))) { + int inParentheses = 0; + char ch; + while (current < length && ( + !Character.isWhitespace(ch = value.charAt(current)) + || inParentheses > 0)) { + if (ch == '(') { + inParentheses++; + } else if (ch == ')') { + inParentheses--; + } current++; } if (last != current) { diff --git a/jdk/src/java.desktop/share/classes/sun/applet/AppletClassLoader.java b/jdk/src/java.desktop/share/classes/sun/applet/AppletClassLoader.java index a778ca6c769ed759e8ff54031eaf14264d31b62c..38a4e93415e698a748327b7399805488a354f7c5 100644 --- a/jdk/src/java.desktop/share/classes/sun/applet/AppletClassLoader.java +++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletClassLoader.java @@ -52,7 +52,6 @@ import java.security.Permission; import java.security.PermissionCollection; import sun.awt.AppContext; import sun.awt.SunToolkit; -import sun.misc.ManagedLocalsThread; import sun.net.www.ParseUtil; import sun.security.util.SecurityConstants; @@ -858,13 +857,20 @@ public void grab() { * this operation to complete before continuing, wait for the notifyAll() * operation on the syncObject to occur. */ -class AppContextCreator extends ManagedLocalsThread { +class AppContextCreator extends Thread { Object syncObject = new Object(); AppContext appContext = null; volatile boolean created = false; + /** + * Must call the 5-args super-class constructor to erase locals. + */ + private AppContextCreator() { + throw new UnsupportedOperationException("Must erase locals"); + } + AppContextCreator(ThreadGroup group) { - super(group, "AppContextCreator"); + super(group, null, "AppContextCreator", 0, false); } public void run() { diff --git a/jdk/src/java.desktop/share/classes/sun/applet/AppletPanel.java b/jdk/src/java.desktop/share/classes/sun/applet/AppletPanel.java index 7ef9e1111716e659f3ebb80353208386a03da24e..404131827feaaa3eeb9941c9ab3dc407420e6c8b 100644 --- a/jdk/src/java.desktop/share/classes/sun/applet/AppletPanel.java +++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletPanel.java @@ -44,7 +44,6 @@ import sun.awt.AppContext; import sun.awt.EmbeddedFrame; import sun.awt.SunToolkit; import sun.awt.util.PerformanceLogger; -import sun.misc.ManagedLocalsThread; import sun.security.util.SecurityConstants; /** @@ -166,7 +165,7 @@ abstract class AppletPanel extends Panel implements AppletStub, Runnable { ThreadGroup appletGroup = loader.getThreadGroup(); - handler = new ManagedLocalsThread(appletGroup, this, "thread " + nm); + handler = new Thread(appletGroup, this, "thread " + nm, 0, false); // set the context class loader for this thread AccessController.doPrivileged(new PrivilegedAction() { @Override @@ -396,9 +395,8 @@ abstract class AppletPanel extends Panel implements AppletStub, Runnable { // until the loader thread terminates. // (one way or another). if (loaderThread == null) { - // REMIND: do we want a name? - //System.out.println("------------------- loading applet"); - setLoaderThread(new ManagedLocalsThread(this)); + setLoaderThread(new Thread(null, this, + "AppletLoader", 0, false)); loaderThread.start(); // we get to go to sleep while this runs loaderThread.join(); diff --git a/jdk/src/java.desktop/share/classes/sun/applet/AppletViewer.java b/jdk/src/java.desktop/share/classes/sun/applet/AppletViewer.java index b310b277f93d272652aef661fa3710b10ca661ec..d613fc9434125238c35fbe1e95baf797e4781111 100644 --- a/jdk/src/java.desktop/share/classes/sun/applet/AppletViewer.java +++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletViewer.java @@ -38,7 +38,6 @@ import java.security.AccessController; import java.security.PrivilegedAction; import sun.awt.SunToolkit; import sun.awt.AppContext; -import sun.misc.ManagedLocalsThread; /** * A frame to show the applet tag in. @@ -854,7 +853,7 @@ public class AppletViewer extends Frame implements AppletContext, Printable { // final AppletPanel p = panel; - new ManagedLocalsThread(new Runnable() + new Thread(null, new Runnable() { @Override public void run() @@ -867,7 +866,8 @@ public class AppletViewer extends Frame implements AppletContext, Printable { appletSystemExit(); } } - }).start(); + }, + "AppletCloser", 0, false).start(); } /** @@ -890,7 +890,7 @@ public class AppletViewer extends Frame implements AppletContext, Printable { // spawn a new thread to avoid blocking the event queue // when calling appletShutdown. // - new ManagedLocalsThread(new Runnable() + new Thread(null, new Runnable() { @Override public void run() @@ -901,7 +901,8 @@ public class AppletViewer extends Frame implements AppletContext, Printable { } appletSystemExit(); } - }).start(); + }, + "AppletQuit", 0, false).start(); } /** diff --git a/jdk/src/java.desktop/share/classes/sun/awt/AWTAutoShutdown.java b/jdk/src/java.desktop/share/classes/sun/awt/AWTAutoShutdown.java index 1ecef9162ca9f5a285b059133f8541c9f84e83d3..8dd14c7844438f73c70e18d3f21680345cfbc7f4 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/AWTAutoShutdown.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/AWTAutoShutdown.java @@ -34,7 +34,6 @@ import java.util.Map; import java.util.Set; import sun.awt.util.ThreadGroupUtils; -import sun.misc.ManagedLocalsThread; import sun.util.logging.PlatformLogger; /** @@ -337,8 +336,8 @@ public final class AWTAutoShutdown implements Runnable { private void activateBlockerThread() { AccessController.doPrivileged((PrivilegedAction) () -> { String name = "AWT-Shutdown"; - Thread thread = new ManagedLocalsThread( - ThreadGroupUtils.getRootThreadGroup(), this, name); + Thread thread = new Thread( + ThreadGroupUtils.getRootThreadGroup(), this, name, 0, false); thread.setContextClassLoader(null); thread.setDaemon(false); blockerThread = thread; diff --git a/jdk/src/java.desktop/share/classes/sun/awt/AppContext.java b/jdk/src/java.desktop/share/classes/sun/awt/AppContext.java index b4bc32996b28de27aeb7e6a27287177550e0589f..e966905d2e06d7244551a39f80461710f9b5ed67 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/AppContext.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/AppContext.java @@ -46,7 +46,6 @@ import java.lang.ref.SoftReference; import jdk.internal.misc.JavaAWTAccess; import jdk.internal.misc.SharedSecrets; -import sun.misc.ManagedLocalsThread; import sun.util.logging.PlatformLogger; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; @@ -598,8 +597,8 @@ public final class AppContext { } public Thread run() { - Thread t = new ManagedLocalsThread(appContext.getThreadGroup(), - runnable, "AppContext Disposer"); + Thread t = new Thread(appContext.getThreadGroup(), + runnable, "AppContext Disposer", 0, false); t.setContextClassLoader(appContext.getContextClassLoader()); t.setPriority(Thread.NORM_PRIORITY + 1); t.setDaemon(true); diff --git a/jdk/src/java.desktop/share/classes/sun/awt/im/InputMethodManager.java b/jdk/src/java.desktop/share/classes/sun/awt/im/InputMethodManager.java index 14221d8a9091d22fd05b430ea1c4a59050df19c0..f61825d8ddf2211494d5d5a06de0910e2f51462d 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/im/InputMethodManager.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/im/InputMethodManager.java @@ -55,7 +55,6 @@ import java.util.prefs.BackingStoreException; import java.util.prefs.Preferences; import sun.awt.InputMethodSupport; import sun.awt.SunToolkit; -import sun.misc.ManagedLocalsThread; /** * {@code InputMethodManager} is an abstract class that manages the input @@ -166,7 +165,8 @@ public abstract class InputMethodManager { // to choose from. Otherwise, just keep the instance. if (imm.hasMultipleInputMethods()) { imm.initialize(); - Thread immThread = new ManagedLocalsThread(imm, threadName); + Thread immThread = + new Thread(null, imm, threadName, 0, false); immThread.setDaemon(true); immThread.setPriority(Thread.NORM_PRIORITY + 1); immThread.start(); diff --git a/jdk/src/java.desktop/share/classes/sun/awt/image/ByteBandedRaster.java b/jdk/src/java.desktop/share/classes/sun/awt/image/ByteBandedRaster.java index 699c1ea2f435b6f46d6899909f6cf4845e8e4673..1123a9f69fdc485c41665738b8a167ddfb337dc1 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/image/ByteBandedRaster.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/image/ByteBandedRaster.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,6 @@ import java.awt.image.WritableRaster; import java.awt.image.RasterFormatException; import java.awt.image.SampleModel; import java.awt.image.BandedSampleModel; -import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.Rectangle; import java.awt.Point; @@ -74,10 +73,9 @@ public class ByteBandedRaster extends SunWritableRaster { * @param sampleModel The SampleModel that specifies the layout. * @param origin The Point that specifies the origin. */ - public ByteBandedRaster(SampleModel sampleModel, - Point origin) { + public ByteBandedRaster(SampleModel sampleModel, Point origin) { this(sampleModel, - sampleModel.createDataBuffer(), + (DataBufferByte) sampleModel.createDataBuffer(), new Rectangle(origin.x, origin.y, sampleModel.getWidth(), @@ -93,12 +91,13 @@ public class ByteBandedRaster extends SunWritableRaster { * initialized and must be a DataBufferShort compatible with SampleModel. * SampleModel must be of type BandedSampleModel. * @param sampleModel The SampleModel that specifies the layout. - * @param dataBuffer The DataBufferShort that contains the image data. + * @param dataBuffer The DataBufferByte that contains the image data. * @param origin The Point that specifies the origin. */ public ByteBandedRaster(SampleModel sampleModel, - DataBuffer dataBuffer, - Point origin) { + DataBufferByte dataBuffer, + Point origin) + { this(sampleModel, dataBuffer, new Rectangle(origin.x , origin.y, sampleModel.getWidth(), @@ -119,39 +118,33 @@ public class ByteBandedRaster extends SunWritableRaster { * Note that this constructor should generally be called by other * constructors or create methods, it should not be used directly. * @param sampleModel The SampleModel that specifies the layout. - * @param dataBuffer The DataBufferShort that contains the image data. + * @param dataBuffer The DataBufferByte that contains the image data. * @param aRegion The Rectangle that specifies the image area. * @param origin The Point that specifies the origin. * @param parent The parent (if any) of this raster. */ public ByteBandedRaster(SampleModel sampleModel, - DataBuffer dataBuffer, + DataBufferByte dataBuffer, Rectangle aRegion, Point origin, - ByteBandedRaster parent) { - + ByteBandedRaster parent) + { super(sampleModel, dataBuffer, aRegion, origin, parent); this.maxX = minX + width; this.maxY = minY + height; - if (!(dataBuffer instanceof DataBufferByte)) { - throw new RasterFormatException("ByteBandedRaster must have" + - "byte DataBuffers"); - } - DataBufferByte dbb = (DataBufferByte)dataBuffer; - if (sampleModel instanceof BandedSampleModel) { BandedSampleModel bsm = (BandedSampleModel)sampleModel; this.scanlineStride = bsm.getScanlineStride(); int bankIndices[] = bsm.getBankIndices(); int bandOffsets[] = bsm.getBandOffsets(); - int dOffsets[] = dbb.getOffsets(); + int dOffsets[] = dataBuffer.getOffsets(); dataOffsets = new int[bankIndices.length]; data = new byte[bankIndices.length][]; int xOffset = aRegion.x - origin.x; int yOffset = aRegion.y - origin.y; for (int i = 0; i < bankIndices.length; i++) { - data[i] = stealData(dbb, bankIndices[i]); + data[i] = stealData(dataBuffer, bankIndices[i]); dataOffsets[i] = dOffsets[bankIndices[i]] + xOffset + yOffset*scanlineStride + bandOffsets[i]; } @@ -672,7 +665,7 @@ public class ByteBandedRaster extends SunWritableRaster { int deltaY = y0 - y; return new ByteBandedRaster(sm, - dataBuffer, + (DataBufferByte) dataBuffer, new Rectangle(x0,y0,width,height), new Point(sampleModelTranslateX+deltaX, sampleModelTranslateY+deltaY), diff --git a/jdk/src/java.desktop/share/classes/sun/awt/image/ByteComponentRaster.java b/jdk/src/java.desktop/share/classes/sun/awt/image/ByteComponentRaster.java index 673e51d8518b6daa2b6e2569b63bfa7b8e3ce104..f284e3b1fc4bc3da7672b5a492a02dae37cb85fa 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/image/ByteComponentRaster.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/image/ByteComponentRaster.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,6 @@ import java.awt.image.RasterFormatException; import java.awt.image.SampleModel; import java.awt.image.ComponentSampleModel; import java.awt.image.SinglePixelPackedSampleModel; -import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.Rectangle; import java.awt.Point; @@ -94,7 +93,7 @@ public class ByteComponentRaster extends SunWritableRaster { */ public ByteComponentRaster(SampleModel sampleModel, Point origin) { this(sampleModel, - sampleModel.createDataBuffer(), + (DataBufferByte) sampleModel.createDataBuffer(), new Rectangle(origin.x, origin.y, sampleModel.getWidth(), @@ -111,12 +110,13 @@ public class ByteComponentRaster extends SunWritableRaster { * SampleModel must be of type SinglePixelPackedSampleModel * or ComponentSampleModel. * @param sampleModel The SampleModel that specifies the layout. - * @param dataBuffer The DataBufferShort that contains the image data. + * @param dataBuffer The DataBufferByte that contains the image data. * @param origin The Point that specifies the origin. */ public ByteComponentRaster(SampleModel sampleModel, - DataBuffer dataBuffer, - Point origin) { + DataBufferByte dataBuffer, + Point origin) + { this(sampleModel, dataBuffer, new Rectangle(origin.x, @@ -141,33 +141,28 @@ public class ByteComponentRaster extends SunWritableRaster { * Note that this constructor should generally be called by other * constructors or create methods, it should not be used directly. * @param sampleModel The SampleModel that specifies the layout. - * @param dataBuffer The DataBufferShort that contains the image data. + * @param dataBuffer The DataBufferByte that contains the image data. * @param aRegion The Rectangle that specifies the image area. * @param origin The Point that specifies the origin. * @param parent The parent (if any) of this raster. */ public ByteComponentRaster(SampleModel sampleModel, - DataBuffer dataBuffer, - Rectangle aRegion, - Point origin, - ByteComponentRaster parent) { + DataBufferByte dataBuffer, + Rectangle aRegion, + Point origin, + ByteComponentRaster parent) + { super(sampleModel, dataBuffer, aRegion, origin, parent); this.maxX = minX + width; this.maxY = minY + height; - if (!(dataBuffer instanceof DataBufferByte)) { - throw new RasterFormatException("ByteComponentRasters must have " + - "byte DataBuffers"); - } - - DataBufferByte dbb = (DataBufferByte)dataBuffer; - this.data = stealData(dbb, 0); - if (dbb.getNumBanks() != 1) { + this.data = stealData(dataBuffer, 0); + if (dataBuffer.getNumBanks() != 1) { throw new RasterFormatException("DataBuffer for ByteComponentRasters"+ " must only have 1 bank."); } - int dbOffset = dbb.getOffset(); + int dbOffset = dataBuffer.getOffset(); if (sampleModel instanceof ComponentSampleModel) { ComponentSampleModel ism = (ComponentSampleModel)sampleModel; @@ -823,7 +818,7 @@ public class ByteComponentRaster extends SunWritableRaster { int deltaY = y0 - y; return new ByteComponentRaster(sm, - dataBuffer, + (DataBufferByte) dataBuffer, new Rectangle(x0, y0, width, height), new Point(sampleModelTranslateX+deltaX, sampleModelTranslateY+deltaY), diff --git a/jdk/src/java.desktop/share/classes/sun/awt/image/ByteInterleavedRaster.java b/jdk/src/java.desktop/share/classes/sun/awt/image/ByteInterleavedRaster.java index 52f01b30b635e585c59d50085f6a4408ba1289c0..b406fb6521189ba00f7e0d910dcedd2a49d41fa5 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/image/ByteInterleavedRaster.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/image/ByteInterleavedRaster.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * 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,6 @@ import java.awt.image.SampleModel; import java.awt.image.ComponentSampleModel; import java.awt.image.PixelInterleavedSampleModel; import java.awt.image.SinglePixelPackedSampleModel; -import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.Rectangle; import java.awt.Point; @@ -87,7 +86,7 @@ public class ByteInterleavedRaster extends ByteComponentRaster { */ public ByteInterleavedRaster(SampleModel sampleModel, Point origin) { this(sampleModel, - sampleModel.createDataBuffer(), + (DataBufferByte) sampleModel.createDataBuffer(), new Rectangle(origin.x, origin.y, sampleModel.getWidth(), @@ -104,12 +103,13 @@ public class ByteInterleavedRaster extends ByteComponentRaster { * SampleModel must be of type SinglePixelPackedSampleModel * or InterleavedSampleModel. * @param sampleModel The SampleModel that specifies the layout. - * @param dataBuffer The DataBufferShort that contains the image data. + * @param dataBuffer The DataBufferByte that contains the image data. * @param origin The Point that specifies the origin. */ public ByteInterleavedRaster(SampleModel sampleModel, - DataBuffer dataBuffer, - Point origin) { + DataBufferByte dataBuffer, + Point origin) + { this(sampleModel, dataBuffer, new Rectangle(origin.x, @@ -178,27 +178,22 @@ public class ByteInterleavedRaster extends ByteComponentRaster { * Note that this constructor should generally be called by other * constructors or create methods, it should not be used directly. * @param sampleModel The SampleModel that specifies the layout. - * @param dataBuffer The DataBufferShort that contains the image data. + * @param dataBuffer The DataBufferByte that contains the image data. * @param aRegion The Rectangle that specifies the image area. * @param origin The Point that specifies the origin. * @param parent The parent (if any) of this raster. */ public ByteInterleavedRaster(SampleModel sampleModel, - DataBuffer dataBuffer, - Rectangle aRegion, - Point origin, - ByteInterleavedRaster parent) { + DataBufferByte dataBuffer, + Rectangle aRegion, + Point origin, + ByteInterleavedRaster parent) + { super(sampleModel, dataBuffer, aRegion, origin, parent); this.maxX = minX + width; this.maxY = minY + height; - if (!(dataBuffer instanceof DataBufferByte)) { - throw new RasterFormatException("ByteInterleavedRasters must have " + - "byte DataBuffers"); - } - - DataBufferByte dbb = (DataBufferByte)dataBuffer; - this.data = stealData(dbb, 0); + this.data = stealData(dataBuffer, 0); int xOffset = aRegion.x - origin.x; int yOffset = aRegion.y - origin.y; @@ -221,7 +216,7 @@ public class ByteInterleavedRaster extends ByteComponentRaster { this.scanlineStride = sppsm.getScanlineStride(); this.pixelStride = 1; this.dataOffsets = new int[1]; - this.dataOffsets[0] = dbb.getOffset(); + this.dataOffsets[0] = dataBuffer.getOffset(); dataOffsets[0] += xOffset*pixelStride+yOffset*scanlineStride; } else { throw new RasterFormatException("ByteInterleavedRasters must " + @@ -1259,7 +1254,7 @@ public class ByteInterleavedRaster extends ByteComponentRaster { int deltaY = y0 - y; return new ByteInterleavedRaster(sm, - dataBuffer, + (DataBufferByte) dataBuffer, new Rectangle(x0, y0, width, height), new Point(sampleModelTranslateX+deltaX, sampleModelTranslateY+deltaY), diff --git a/jdk/src/java.desktop/share/classes/sun/awt/image/BytePackedRaster.java b/jdk/src/java.desktop/share/classes/sun/awt/image/BytePackedRaster.java index f9696c17eb82719aed0ffe87251d1b0ecfbe7867..ac00075c16a2591f83c56f8e589b760049a9d2b4 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/image/BytePackedRaster.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/image/BytePackedRaster.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,6 @@ import java.awt.image.WritableRaster; import java.awt.image.RasterFormatException; import java.awt.image.SampleModel; import java.awt.image.MultiPixelPackedSampleModel; -import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.Rectangle; import java.awt.Point; @@ -89,10 +88,9 @@ public class BytePackedRaster extends SunWritableRaster { * @param sampleModel The SampleModel that specifies the layout. * @param origin The Point that specified the origin. */ - public BytePackedRaster(SampleModel sampleModel, - Point origin) { + public BytePackedRaster(SampleModel sampleModel, Point origin) { this(sampleModel, - sampleModel.createDataBuffer(), + (DataBufferByte) sampleModel.createDataBuffer(), new Rectangle(origin.x, origin.y, sampleModel.getWidth(), @@ -108,12 +106,13 @@ public class BytePackedRaster extends SunWritableRaster { * initialized and must be a DataBufferByte compatible with SampleModel. * SampleModel must be of type MultiPixelPackedSampleModel. * @param sampleModel The SampleModel that specifies the layout. - * @param dataBuffer The DataBufferShort that contains the image data. + * @param dataBuffer The DataBufferByte that contains the image data. * @param origin The Point that specifies the origin. */ public BytePackedRaster(SampleModel sampleModel, - DataBuffer dataBuffer, - Point origin) { + DataBufferByte dataBuffer, + Point origin) + { this(sampleModel, dataBuffer, new Rectangle(origin.x, @@ -137,7 +136,7 @@ public class BytePackedRaster extends SunWritableRaster { * Note that this constructor should generally be called by other * constructors or create methods, it should not be used directly. * @param sampleModel The SampleModel that specifies the layout. - * @param dataBuffer The DataBufferShort that contains the image data. + * @param dataBuffer The DataBufferByte that contains the image data. * @param aRegion The Rectangle that specifies the image area. * @param origin The Point that specifies the origin. * @param parent The parent (if any) of this raster. @@ -146,26 +145,22 @@ public class BytePackedRaster extends SunWritableRaster { * to requirements of this Raster type. */ public BytePackedRaster(SampleModel sampleModel, - DataBuffer dataBuffer, + DataBufferByte dataBuffer, Rectangle aRegion, Point origin, - BytePackedRaster parent){ + BytePackedRaster parent) + { super(sampleModel,dataBuffer,aRegion,origin, parent); this.maxX = minX + width; this.maxY = minY + height; - if (!(dataBuffer instanceof DataBufferByte)) { - throw new RasterFormatException("BytePackedRasters must have" + - "byte DataBuffers"); - } - DataBufferByte dbb = (DataBufferByte)dataBuffer; - this.data = stealData(dbb, 0); - if (dbb.getNumBanks() != 1) { + this.data = stealData(dataBuffer, 0); + if (dataBuffer.getNumBanks() != 1) { throw new RasterFormatException("DataBuffer for BytePackedRasters"+ " must only have 1 bank."); } - int dbOffset = dbb.getOffset(); + int dbOffset = dataBuffer.getOffset(); if (sampleModel instanceof MultiPixelPackedSampleModel) { MultiPixelPackedSampleModel mppsm = @@ -1322,7 +1317,7 @@ public class BytePackedRaster extends SunWritableRaster { int deltaY = y0 - y; return new BytePackedRaster(sm, - dataBuffer, + (DataBufferByte) dataBuffer, new Rectangle(x0, y0, width, height), new Point(sampleModelTranslateX+deltaX, sampleModelTranslateY+deltaY), diff --git a/jdk/src/java.desktop/share/classes/sun/awt/image/ImageFetcher.java b/jdk/src/java.desktop/share/classes/sun/awt/image/ImageFetcher.java index 4ad7eea16828972a89913b0a6808598c1e10b6f3..2aca4285977b15e310c0f8daa077929b21418518 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/image/ImageFetcher.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/image/ImageFetcher.java @@ -27,7 +27,6 @@ package sun.awt.image; import java.util.Vector; import sun.awt.AppContext; -import sun.misc.ManagedLocalsThread; /** * An ImageFetcher is a thread used to fetch ImageFetchable objects. @@ -42,7 +41,7 @@ import sun.misc.ManagedLocalsThread; * @author Jim Graham * @author Fred Ecks */ -class ImageFetcher extends ManagedLocalsThread { +class ImageFetcher extends Thread { static final int HIGH_PRIORITY = 8; static final int LOW_PRIORITY = 3; static final int ANIM_PRIORITY = 2; @@ -51,11 +50,18 @@ class ImageFetcher extends ManagedLocalsThread { // ImageFetchable to be added to the // queue before an ImageFetcher dies + /** + * We must only call the 5 args super() constructor passing + * in "false" to indicate to not inherit locals. + */ + private ImageFetcher() { + throw new UnsupportedOperationException("Must erase locals"); + } /** * Constructor for ImageFetcher -- only called by add() below. */ private ImageFetcher(ThreadGroup threadGroup, int index) { - super(threadGroup, "Image Fetcher " + index); + super(threadGroup, null, "Image Fetcher " + index, 0, false); setDaemon(true); } diff --git a/jdk/src/java.desktop/share/classes/sun/awt/image/IntegerComponentRaster.java b/jdk/src/java.desktop/share/classes/sun/awt/image/IntegerComponentRaster.java index cd84986b77f604db0306b5a8801d78074cae582a..44ab725308372c7d020e6df4521809886c108698 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/image/IntegerComponentRaster.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/image/IntegerComponentRaster.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,6 @@ import java.awt.image.WritableRaster; import java.awt.image.RasterFormatException; import java.awt.image.SampleModel; import java.awt.image.SinglePixelPackedSampleModel; -import java.awt.image.DataBuffer; import java.awt.image.DataBufferInt; import java.awt.Rectangle; import java.awt.Point; @@ -107,10 +106,9 @@ public class IntegerComponentRaster extends SunWritableRaster { * @param sampleModel The SampleModel that specifies the layout. * @param origin The Point that specified the origin. */ - public IntegerComponentRaster(SampleModel sampleModel, - Point origin) { + public IntegerComponentRaster(SampleModel sampleModel, Point origin) { this(sampleModel, - sampleModel.createDataBuffer(), + (DataBufferInt) sampleModel.createDataBuffer(), new Rectangle(origin.x, origin.y, sampleModel.getWidth(), @@ -130,8 +128,9 @@ public class IntegerComponentRaster extends SunWritableRaster { * @param origin The Point that specifies the origin. */ public IntegerComponentRaster(SampleModel sampleModel, - DataBuffer dataBuffer, - Point origin) { + DataBufferInt dataBuffer, + Point origin) + { this(sampleModel, dataBuffer, new Rectangle(origin.x, @@ -161,24 +160,21 @@ public class IntegerComponentRaster extends SunWritableRaster { * @param parent The parent (if any) of this raster. */ public IntegerComponentRaster(SampleModel sampleModel, - DataBuffer dataBuffer, - Rectangle aRegion, - Point origin, - IntegerComponentRaster parent){ + DataBufferInt dataBuffer, + Rectangle aRegion, + Point origin, + IntegerComponentRaster parent) + { super(sampleModel,dataBuffer,aRegion,origin,parent); this.maxX = minX + width; this.maxY = minY + height; - if (!(dataBuffer instanceof DataBufferInt)) { - throw new RasterFormatException("IntegerComponentRasters must have" + - "integer DataBuffers"); - } - DataBufferInt dbi = (DataBufferInt)dataBuffer; - if (dbi.getNumBanks() != 1) { + + if (dataBuffer.getNumBanks() != 1) { throw new RasterFormatException("DataBuffer for IntegerComponentRasters"+ " must only have 1 bank."); } - this.data = stealData(dbi, 0); + this.data = stealData(dataBuffer, 0); if (sampleModel instanceof SinglePixelPackedSampleModel) { SinglePixelPackedSampleModel sppsm = @@ -197,7 +193,7 @@ public class IntegerComponentRaster extends SunWritableRaster { this.scanlineStride = sppsm.getScanlineStride(); this.pixelStride = 1; this.dataOffsets = new int[1]; - this.dataOffsets[0] = dbi.getOffset(); + this.dataOffsets[0] = dataBuffer.getOffset(); this.bandOffset = this.dataOffsets[0]; int xOffset = aRegion.x - origin.x; int yOffset = aRegion.y - origin.y; @@ -569,7 +565,7 @@ public class IntegerComponentRaster extends SunWritableRaster { int deltaY = y0 - y; return new IntegerComponentRaster(sm, - dataBuffer, + (DataBufferInt) dataBuffer, new Rectangle(x0,y0,width,height), new Point(sampleModelTranslateX+deltaX, sampleModelTranslateY+deltaY), diff --git a/jdk/src/java.desktop/share/classes/sun/awt/image/IntegerInterleavedRaster.java b/jdk/src/java.desktop/share/classes/sun/awt/image/IntegerInterleavedRaster.java index a852080a7015f2b92ebe876cf4499203b4a11b8d..48ec3eed7ad1323ab06b18ac4796dea6307075de 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/image/IntegerInterleavedRaster.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/image/IntegerInterleavedRaster.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,6 @@ import java.awt.image.WritableRaster; import java.awt.image.RasterFormatException; import java.awt.image.SampleModel; import java.awt.image.SinglePixelPackedSampleModel; -import java.awt.image.DataBuffer; import java.awt.image.DataBufferInt; import java.awt.Rectangle; import java.awt.Point; @@ -67,10 +66,9 @@ public class IntegerInterleavedRaster extends IntegerComponentRaster { * @param sampleModel The SampleModel that specifies the layout. * @param origin The Point that specified the origin. */ - public IntegerInterleavedRaster(SampleModel sampleModel, - Point origin) { + public IntegerInterleavedRaster(SampleModel sampleModel, Point origin) { this(sampleModel, - sampleModel.createDataBuffer(), + (DataBufferInt) sampleModel.createDataBuffer(), new Rectangle(origin.x, origin.y, sampleModel.getWidth(), @@ -90,8 +88,9 @@ public class IntegerInterleavedRaster extends IntegerComponentRaster { * @param origin The Point that specifies the origin. */ public IntegerInterleavedRaster(SampleModel sampleModel, - DataBuffer dataBuffer, - Point origin) { + DataBufferInt dataBuffer, + Point origin) + { this(sampleModel, dataBuffer, new Rectangle(origin.x, @@ -121,19 +120,16 @@ public class IntegerInterleavedRaster extends IntegerComponentRaster { * @param parent The parent (if any) of this raster. */ public IntegerInterleavedRaster(SampleModel sampleModel, - DataBuffer dataBuffer, - Rectangle aRegion, - Point origin, - IntegerInterleavedRaster parent){ + DataBufferInt dataBuffer, + Rectangle aRegion, + Point origin, + IntegerInterleavedRaster parent) + { super(sampleModel,dataBuffer,aRegion,origin,parent); this.maxX = minX + width; this.maxY = minY + height; - if (!(dataBuffer instanceof DataBufferInt)) { - throw new RasterFormatException("IntegerInterleavedRasters must have" + - "integer DataBuffers"); - } - DataBufferInt dbi = (DataBufferInt)dataBuffer; - this.data = stealData(dbi, 0); + + this.data = stealData(dataBuffer, 0); if (sampleModel instanceof SinglePixelPackedSampleModel) { SinglePixelPackedSampleModel sppsm = @@ -141,7 +137,7 @@ public class IntegerInterleavedRaster extends IntegerComponentRaster { this.scanlineStride = sppsm.getScanlineStride(); this.pixelStride = 1; this.dataOffsets = new int[1]; - this.dataOffsets[0] = dbi.getOffset(); + this.dataOffsets[0] = dataBuffer.getOffset(); this.bandOffset = this.dataOffsets[0]; int xOffset = aRegion.x - origin.x; int yOffset = aRegion.y - origin.y; @@ -481,7 +477,7 @@ public class IntegerInterleavedRaster extends IntegerComponentRaster { int deltaY = y0 - y; return new IntegerInterleavedRaster(sm, - dataBuffer, + (DataBufferInt) dataBuffer, new Rectangle(x0,y0,width,height), new Point(sampleModelTranslateX+deltaX, sampleModelTranslateY+deltaY), diff --git a/jdk/src/java.desktop/share/classes/sun/awt/image/ShortBandedRaster.java b/jdk/src/java.desktop/share/classes/sun/awt/image/ShortBandedRaster.java index fd5c610504de6a6e9f976d28c3b225acba255cfd..6222c61b5e951efe14a14a29795cde1056bc8d2f 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/image/ShortBandedRaster.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/image/ShortBandedRaster.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,6 @@ import java.awt.image.WritableRaster; import java.awt.image.RasterFormatException; import java.awt.image.SampleModel; import java.awt.image.BandedSampleModel; -import java.awt.image.DataBuffer; import java.awt.image.DataBufferUShort; import java.awt.Rectangle; import java.awt.Point; @@ -72,10 +71,9 @@ public class ShortBandedRaster extends SunWritableRaster { * @param sampleModel The SampleModel that specifies the layout. * @param origin The Point that specified the origin. */ - public ShortBandedRaster(SampleModel sampleModel, - Point origin) { + public ShortBandedRaster(SampleModel sampleModel, Point origin) { this(sampleModel, - sampleModel.createDataBuffer(), + (DataBufferUShort) sampleModel.createDataBuffer(), new Rectangle(origin.x, origin.y, sampleModel.getWidth(), @@ -95,8 +93,9 @@ public class ShortBandedRaster extends SunWritableRaster { * @param origin The Point that specifies the origin. */ public ShortBandedRaster(SampleModel sampleModel, - DataBuffer dataBuffer, - Point origin) { + DataBufferUShort dataBuffer, + Point origin) + { this(sampleModel, dataBuffer, new Rectangle(origin.x, origin.y, sampleModel.getWidth(), @@ -123,32 +122,27 @@ public class ShortBandedRaster extends SunWritableRaster { * @param parent The parent (if any) of this raster. */ public ShortBandedRaster(SampleModel sampleModel, - DataBuffer dataBuffer, - Rectangle aRegion, - Point origin, - ShortBandedRaster parent) { - + DataBufferUShort dataBuffer, + Rectangle aRegion, + Point origin, + ShortBandedRaster parent) + { super(sampleModel, dataBuffer, aRegion, origin, parent); this.maxX = minX + width; this.maxY = minY + height; - if (!(dataBuffer instanceof DataBufferUShort)) { - throw new RasterFormatException("ShortBandedRaster must have " + - "ushort DataBuffers"); - } - DataBufferUShort dbus = (DataBufferUShort)dataBuffer; if (sampleModel instanceof BandedSampleModel) { BandedSampleModel bsm = (BandedSampleModel)sampleModel; this.scanlineStride = bsm.getScanlineStride(); int bankIndices[] = bsm.getBankIndices(); int bandOffsets[] = bsm.getBandOffsets(); - int dOffsets[] = dbus.getOffsets(); + int dOffsets[] = dataBuffer.getOffsets(); dataOffsets = new int[bankIndices.length]; data = new short[bankIndices.length][]; int xOffset = aRegion.x - origin.x; int yOffset = aRegion.y - origin.y; for (int i = 0; i < bankIndices.length; i++) { - data[i] = stealData(dbus, bankIndices[i]); + data[i] = stealData(dataBuffer, bankIndices[i]); dataOffsets[i] = dOffsets[bankIndices[i]] + xOffset + yOffset*scanlineStride + bandOffsets[i]; } @@ -670,7 +664,7 @@ public class ShortBandedRaster extends SunWritableRaster { int deltaY = y0 - y; return new ShortBandedRaster(sm, - dataBuffer, + (DataBufferUShort) dataBuffer, new Rectangle(x0, y0, width, height), new Point(sampleModelTranslateX+deltaX, sampleModelTranslateY+deltaY), diff --git a/jdk/src/java.desktop/share/classes/sun/awt/image/ShortComponentRaster.java b/jdk/src/java.desktop/share/classes/sun/awt/image/ShortComponentRaster.java index 76ab7d75ce467eb55af560572c6daf585708a5db..79016e9df5a915d8596e317d870dd6c9ef500525 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/image/ShortComponentRaster.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/image/ShortComponentRaster.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,6 @@ import java.awt.image.RasterFormatException; import java.awt.image.SampleModel; import java.awt.image.ComponentSampleModel; import java.awt.image.SinglePixelPackedSampleModel; -import java.awt.image.DataBuffer; import java.awt.image.DataBufferUShort; import java.awt.Rectangle; import java.awt.Point; @@ -94,7 +93,7 @@ public class ShortComponentRaster extends SunWritableRaster { */ public ShortComponentRaster(SampleModel sampleModel, Point origin) { this(sampleModel, - sampleModel.createDataBuffer(), + (DataBufferUShort) sampleModel.createDataBuffer(), new Rectangle(origin.x, origin.y, sampleModel.getWidth(), @@ -115,8 +114,9 @@ public class ShortComponentRaster extends SunWritableRaster { * @param origin The Point that specifies the origin. */ public ShortComponentRaster(SampleModel sampleModel, - DataBuffer dataBuffer, - Point origin) { + DataBufferUShort dataBuffer, + Point origin) + { this(sampleModel, dataBuffer, new Rectangle(origin.x, @@ -146,28 +146,22 @@ public class ShortComponentRaster extends SunWritableRaster { * @param parent The parent (if any) of this raster. */ public ShortComponentRaster(SampleModel sampleModel, - DataBuffer dataBuffer, - Rectangle aRegion, - Point origin, - ShortComponentRaster parent) { - + DataBufferUShort dataBuffer, + Rectangle aRegion, + Point origin, + ShortComponentRaster parent) + { super(sampleModel, dataBuffer, aRegion, origin, parent); this.maxX = minX + width; this.maxY = minY + height; - if(!(dataBuffer instanceof DataBufferUShort)) { - throw new RasterFormatException("ShortComponentRasters must have "+ - "short DataBuffers"); - } - - DataBufferUShort dbus = (DataBufferUShort)dataBuffer; - this.data = stealData(dbus, 0); - if (dbus.getNumBanks() != 1) { + this.data = stealData(dataBuffer, 0); + if (dataBuffer.getNumBanks() != 1) { throw new RasterFormatException("DataBuffer for ShortComponentRasters"+ " must only have 1 bank."); } - int dbOffset = dbus.getOffset(); + int dbOffset = dataBuffer.getOffset(); if (sampleModel instanceof ComponentSampleModel) { ComponentSampleModel csm = (ComponentSampleModel)sampleModel; @@ -758,7 +752,7 @@ public class ShortComponentRaster extends SunWritableRaster { int deltaY = y0 - y; return new ShortComponentRaster(sm, - dataBuffer, + (DataBufferUShort) dataBuffer, new Rectangle(x0, y0, width, height), new Point(sampleModelTranslateX+deltaX, sampleModelTranslateY+deltaY), diff --git a/jdk/src/java.desktop/share/classes/sun/awt/image/ShortInterleavedRaster.java b/jdk/src/java.desktop/share/classes/sun/awt/image/ShortInterleavedRaster.java index 05310891fe59ba2c5400d5b53a144d5567615383..7a1644b62755abd9b4a10ddf8f8834ecda2c3ff6 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/image/ShortInterleavedRaster.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/image/ShortInterleavedRaster.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * 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,6 @@ import java.awt.image.SampleModel; import java.awt.image.ComponentSampleModel; import java.awt.image.PixelInterleavedSampleModel; import java.awt.image.SinglePixelPackedSampleModel; -import java.awt.image.DataBuffer; import java.awt.image.DataBufferUShort; import java.awt.Rectangle; import java.awt.Point; @@ -71,7 +70,7 @@ public class ShortInterleavedRaster extends ShortComponentRaster { */ public ShortInterleavedRaster(SampleModel sampleModel, Point origin) { this(sampleModel, - sampleModel.createDataBuffer(), + (DataBufferUShort) sampleModel.createDataBuffer(), new Rectangle(origin.x, origin.y, sampleModel.getWidth(), @@ -92,8 +91,9 @@ public class ShortInterleavedRaster extends ShortComponentRaster { * @param origin The Point that specifies the origin. */ public ShortInterleavedRaster(SampleModel sampleModel, - DataBuffer dataBuffer, - Point origin) { + DataBufferUShort dataBuffer, + Point origin) + { this(sampleModel, dataBuffer, new Rectangle(origin.x, @@ -123,22 +123,17 @@ public class ShortInterleavedRaster extends ShortComponentRaster { * @param parent The parent (if any) of this raster. */ public ShortInterleavedRaster(SampleModel sampleModel, - DataBuffer dataBuffer, - Rectangle aRegion, - Point origin, - ShortInterleavedRaster parent) { + DataBufferUShort dataBuffer, + Rectangle aRegion, + Point origin, + ShortInterleavedRaster parent) + { super(sampleModel, dataBuffer, aRegion, origin, parent); this.maxX = minX + width; this.maxY = minY + height; - if(!(dataBuffer instanceof DataBufferUShort)) { - throw new RasterFormatException("ShortInterleavedRasters must "+ - "have ushort DataBuffers"); - } - - DataBufferUShort dbus = (DataBufferUShort)dataBuffer; - this.data = stealData(dbus, 0); + this.data = stealData(dataBuffer, 0); // REMIND: need case for interleaved ComponentSampleModel if ((sampleModel instanceof PixelInterleavedSampleModel) || @@ -160,7 +155,7 @@ public class ShortInterleavedRaster extends ShortComponentRaster { this.scanlineStride = sppsm.getScanlineStride(); this.pixelStride = 1; this.dataOffsets = new int[1]; - this.dataOffsets[0] = dbus.getOffset(); + this.dataOffsets[0] = dataBuffer.getOffset(); int xOffset = aRegion.x - origin.x; int yOffset = aRegion.y - origin.y; dataOffsets[0] += xOffset+yOffset*scanlineStride; @@ -730,7 +725,7 @@ public class ShortInterleavedRaster extends ShortComponentRaster { int deltaY = y0 - y; return new ShortInterleavedRaster(sm, - dataBuffer, + (DataBufferUShort) dataBuffer, new Rectangle(x0, y0, width, height), new Point(sampleModelTranslateX+deltaX, sampleModelTranslateY+deltaY), diff --git a/jdk/src/java.desktop/share/classes/sun/font/CreatedFontTracker.java b/jdk/src/java.desktop/share/classes/sun/font/CreatedFontTracker.java index 0ce75a7b23506a723af419cff127db55d7f81a6c..2e239528c71fea4f92ac65622ffa847a1825d204 100644 --- a/jdk/src/java.desktop/share/classes/sun/font/CreatedFontTracker.java +++ b/jdk/src/java.desktop/share/classes/sun/font/CreatedFontTracker.java @@ -36,7 +36,6 @@ import java.util.concurrent.TimeUnit; import sun.awt.AppContext; import sun.awt.util.ThreadGroupUtils; -import sun.misc.ManagedLocalsThread; public class CreatedFontTracker { @@ -122,8 +121,8 @@ public class CreatedFontTracker { * Make its parent the top-level thread group. */ ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup(); - t = new ManagedLocalsThread(rootTG, - TempFileDeletionHook::runHooks); + t = new Thread(rootTG, TempFileDeletionHook::runHooks, + "TempFontFileDeleter", 0, false); /* Set context class loader to null in order to avoid * keeping a strong reference to an application classloader. */ diff --git a/jdk/src/java.desktop/share/classes/sun/font/FontUtilities.java b/jdk/src/java.desktop/share/classes/sun/font/FontUtilities.java index 3aec0a72d89455d2a75a61b1a494c1f9af8e5ef2..bfbd45594486e7e7c69a5fe6447e61c71d2a46f6 100644 --- a/jdk/src/java.desktop/share/classes/sun/font/FontUtilities.java +++ b/jdk/src/java.desktop/share/classes/sun/font/FontUtilities.java @@ -182,6 +182,25 @@ public final class FontUtilities { return FontAccess.getFontAccess().getFont2D(font); } + /** + * Return true if there any characters which would trigger layout. + * This method considers supplementary characters to be simple, + * since we do not presently invoke layout on any code points in + * outside the BMP. + */ + public static boolean isComplexScript(char [] chs, int start, int limit) { + + for (int i = start; i < limit; i++) { + if (chs[i] < MIN_LAYOUT_CHARCODE) { + continue; + } + else if (isComplexCharCode(chs[i])) { + return true; + } + } + return false; + } + /** * If there is anything in the text which triggers a case * where char->glyph does not map 1:1 in straightforward diff --git a/jdk/src/java.desktop/share/classes/sun/font/SunFontManager.java b/jdk/src/java.desktop/share/classes/sun/font/SunFontManager.java index 67bb3fd383a0176a8e7135f76b70470d1a1d40ee..19200c8282b142e88b4c9006dd59905b26090f78 100644 --- a/jdk/src/java.desktop/share/classes/sun/font/SunFontManager.java +++ b/jdk/src/java.desktop/share/classes/sun/font/SunFontManager.java @@ -55,7 +55,6 @@ import sun.awt.FontConfiguration; import sun.awt.SunToolkit; import sun.awt.util.ThreadGroupUtils; import sun.java2d.FontSupport; -import sun.misc.ManagedLocalsThread; import sun.util.logging.PlatformLogger; /** @@ -2513,8 +2512,8 @@ public abstract class SunFontManager implements FontSupport, FontManagerForSGE { }; AccessController.doPrivileged((PrivilegedAction) () -> { ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup(); - fileCloser = new ManagedLocalsThread(rootTG, - fileCloserRunnable); + fileCloser = new Thread(rootTG, fileCloserRunnable, + "FileCloser", 0, false); fileCloser.setContextClassLoader(null); Runtime.getRuntime().addShutdownHook(fileCloser); return null; diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/Disposer.java b/jdk/src/java.desktop/share/classes/sun/java2d/Disposer.java index 01336443bb1a2907efb082d29c8a6e0a7ac33880..e63da023936b44e7ce9e3f93b18d4fa95d0ffed3 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/Disposer.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/Disposer.java @@ -26,7 +26,6 @@ package sun.java2d; import sun.awt.util.ThreadGroupUtils; -import sun.misc.ManagedLocalsThread; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; @@ -85,7 +84,7 @@ public class Disposer implements Runnable { AccessController.doPrivileged((PrivilegedAction) () -> { String name = "Java2D Disposer"; ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup(); - Thread t = new ManagedLocalsThread(rootTG, disposerInstance, name); + Thread t = new Thread(rootTG, disposerInstance, name, 0, false); t.setContextClassLoader(null); t.setDaemon(true); t.setPriority(Thread.MAX_PRIORITY); diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/loops/GraphicsPrimitive.java b/jdk/src/java.desktop/share/classes/sun/java2d/loops/GraphicsPrimitive.java index 38bbaeb5178be31c0115df695d5cb3d64f901746..a71978a10ac38eb84358c96e1a70791c4c5dedb9 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/loops/GraphicsPrimitive.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/loops/GraphicsPrimitive.java @@ -48,7 +48,6 @@ import java.io.FileNotFoundException; import java.security.AccessController; import java.security.PrivilegedAction; -import sun.misc.ManagedLocalsThread; import sun.security.action.GetPropertyAction; /** @@ -420,8 +419,9 @@ public abstract class GraphicsPrimitive { public static void setShutdownHook() { AccessController.doPrivileged((PrivilegedAction) () -> { TraceReporter t = new TraceReporter(); - Thread thread = new ManagedLocalsThread( - ThreadGroupUtils.getRootThreadGroup(), t); + Thread thread = new Thread( + ThreadGroupUtils.getRootThreadGroup(), t, + "TraceReporter", 0, false); thread.setContextClassLoader(null); Runtime.getRuntime().addShutdownHook(thread); return null; diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/opengl/OGLRenderQueue.java b/jdk/src/java.desktop/share/classes/sun/java2d/opengl/OGLRenderQueue.java index 27abcbd86f813ce1389a268cf91db3871b6e7c21..5a843792f370ee6071f11a4f836c6aabf76774fc 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/opengl/OGLRenderQueue.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/opengl/OGLRenderQueue.java @@ -28,7 +28,6 @@ package sun.java2d.opengl; import sun.awt.util.ThreadGroupUtils; import sun.java2d.pipe.RenderBuffer; import sun.java2d.pipe.RenderQueue; -import sun.misc.ManagedLocalsThread; import static sun.java2d.pipe.BufferedOpCodes.*; import java.security.AccessController; @@ -161,7 +160,8 @@ public class OGLRenderQueue extends RenderQueue { public QueueFlusher() { String name = "Java2D Queue Flusher"; - thread = new ManagedLocalsThread(ThreadGroupUtils.getRootThreadGroup(), this, name); + thread = new Thread(ThreadGroupUtils.getRootThreadGroup(), + this, name, 0, false); thread.setDaemon(true); thread.setPriority(Thread.MAX_PRIORITY); thread.start(); diff --git a/jdk/src/java.desktop/share/classes/sun/print/PrintJob2D.java b/jdk/src/java.desktop/share/classes/sun/print/PrintJob2D.java index 0d3df28921cf7d4b89419ccb46bb47a45a3ae33a..b62c4eb1298f39592f8288e6ec12dfe9760cf8a6 100644 --- a/jdk/src/java.desktop/share/classes/sun/print/PrintJob2D.java +++ b/jdk/src/java.desktop/share/classes/sun/print/PrintJob2D.java @@ -71,7 +71,6 @@ import javax.print.attribute.standard.OrientationRequested; import javax.print.attribute.standard.MediaSizeName; import javax.print.attribute.standard.PageRanges; -import sun.misc.ManagedLocalsThread; import sun.print.SunPageSelection; import sun.print.SunMinMaxPage; @@ -483,8 +482,30 @@ public class PrintJob2D extends PrintJob implements Printable, Runnable { pageFormat.setOrientation(PageFormat.LANDSCAPE); } else { pageFormat.setOrientation(PageFormat.PORTRAIT); - } + } + + PageRanges pageRangesAttr + = (PageRanges) attributes.get(PageRanges.class); + if (pageRangesAttr != null) { + // Get the PageRanges from print dialog. + int[][] range = pageRangesAttr.getMembers(); + + int prevFromPage = this.jobAttributes.getFromPage(); + int prevToPage = this.jobAttributes.getToPage(); + int currFromPage = range[0][0]; + int currToPage = range[range.length - 1][1]; + + // if from < to update fromPage first followed by toPage + // else update toPage first followed by fromPage + if (currFromPage < prevToPage) { + this.jobAttributes.setFromPage(currFromPage); + this.jobAttributes.setToPage(currToPage); + } else { + this.jobAttributes.setToPage(currToPage); + this.jobAttributes.setFromPage(currFromPage); + } + } printerJob.setPrintable(this, pageFormat); } @@ -987,7 +1008,8 @@ public class PrintJob2D extends PrintJob implements Printable, Runnable { } private void startPrinterJobThread() { - printerJobThread = new ManagedLocalsThread(this, "printerJobThread"); + printerJobThread = + new Thread(null, this, "printerJobThread", 0, false); printerJobThread.start(); } diff --git a/jdk/src/java.desktop/share/classes/sun/print/ServiceNotifier.java b/jdk/src/java.desktop/share/classes/sun/print/ServiceNotifier.java index 573684a604863fa01c991230d5814b19dfcd7030..8df17defd05381d38b5656a85ce339a143a761c7 100644 --- a/jdk/src/java.desktop/share/classes/sun/print/ServiceNotifier.java +++ b/jdk/src/java.desktop/share/classes/sun/print/ServiceNotifier.java @@ -25,8 +25,6 @@ package sun.print; -import sun.misc.ManagedLocalsThread; - import java.util.Vector; import javax.print.PrintService; @@ -42,15 +40,19 @@ import javax.print.event.PrintServiceAttributeListener; * to obtain the state of the attributes and notifies the listeners of * any changes. */ -class ServiceNotifier extends ManagedLocalsThread { +class ServiceNotifier extends Thread { private PrintService service; private Vector listeners; private boolean stop = false; private PrintServiceAttributeSet lastSet; + /* + * If adding any other constructors, always call the 5-args + * super-class constructor passing "false" for inherit-locals. + */ ServiceNotifier(PrintService service) { - super(service.getName() + " notifier"); + super(null, null, service.getName() + " notifier", 0, false); this.service = service; listeners = new Vector<>(); try { @@ -70,7 +72,7 @@ class ServiceNotifier extends ManagedLocalsThread { } } - void removeListener(PrintServiceAttributeListener listener) { + void removeListener(PrintServiceAttributeListener listener) { synchronized (this) { if (listener == null || listeners == null) { return; diff --git a/jdk/src/java.desktop/share/classes/sun/swing/plaf/synth/DefaultSynthStyle.java b/jdk/src/java.desktop/share/classes/sun/swing/plaf/synth/DefaultSynthStyle.java index 8e4c2159679df67781e2ff6772d90546b0791051..587aceb454fedabba9cd2f7386549af6096aa0e2 100644 --- a/jdk/src/java.desktop/share/classes/sun/swing/plaf/synth/DefaultSynthStyle.java +++ b/jdk/src/java.desktop/share/classes/sun/swing/plaf/synth/DefaultSynthStyle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -645,16 +645,7 @@ public class DefaultSynthStyle extends SynthStyle implements Cloneable { // StateInfo match, otherwise a StateInfo with // SELECTED | ENABLED would match ENABLED, which we // don't want. - - // This comes from BigInteger.bitCnt - int bitCount = oState; - bitCount -= (0xaaaaaaaa & bitCount) >>> 1; - bitCount = (bitCount & 0x33333333) + ((bitCount >>> 2) & - 0x33333333); - bitCount = bitCount + (bitCount >>> 4) & 0x0f0f0f0f; - bitCount += bitCount >>> 8; - bitCount += bitCount >>> 16; - bitCount = bitCount & 0xff; + int bitCount = Integer.bitCount(oState); if (bitCount > bestCount) { bestIndex = counter; bestCount = bitCount; @@ -882,21 +873,6 @@ public class DefaultSynthStyle extends SynthStyle implements Cloneable { return state; } - /** - * Returns the number of states that are similar between the - * ComponentState this StateInfo represents and val. - */ - private int getMatchCount(int val) { - // This comes from BigInteger.bitCnt - val &= state; - val -= (0xaaaaaaaa & val) >>> 1; - val = (val & 0x33333333) + ((val >>> 2) & 0x33333333); - val = val + (val >>> 4) & 0x0f0f0f0f; - val += val >>> 8; - val += val >>> 16; - return val & 0xff; - } - /** * Creates and returns a copy of this StateInfo. * diff --git a/jdk/src/java.desktop/share/native/libfontmanager/layout/DeviceTables.cpp b/jdk/src/java.desktop/share/native/libfontmanager/layout/DeviceTables.cpp index df4df194fcfb3e29222897e16764b5a939c9f016..7ea3032fe9777a4a7f2067596c19d456f3ead5bd 100644 --- a/jdk/src/java.desktop/share/native/libfontmanager/layout/DeviceTables.cpp +++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/DeviceTables.cpp @@ -45,9 +45,12 @@ const le_uint16 DeviceTable::fieldBits[] = { 2, 4, 8}; le_int16 DeviceTable::getAdjustment(const LEReferenceTo&base, le_uint16 ppem, LEErrorCode &success) const { + le_int16 result = 0; + if (LE_FAILURE(success)) { + return result; + } le_uint16 start = SWAPW(startSize); le_uint16 format = SWAPW(deltaFormat) - 1; - le_int16 result = 0; if (ppem >= start && ppem <= SWAPW(endSize) && format < FORMAT_COUNT) { le_uint16 sizeIndex = ppem - start; diff --git a/jdk/src/java.desktop/share/native/libfontmanager/layout/LigatureSubstProc.cpp b/jdk/src/java.desktop/share/native/libfontmanager/layout/LigatureSubstProc.cpp index 5a94563fa5b0129eab3c0a37ffe1aa73ca75e526..76131fd219392c30dbecd155560cac3277cf4129 100644 --- a/jdk/src/java.desktop/share/native/libfontmanager/layout/LigatureSubstProc.cpp +++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/LigatureSubstProc.cpp @@ -71,6 +71,10 @@ ByteOffset LigatureSubstitutionProcessor::processStateEntry(LEGlyphStorage &glyp { LEErrorCode success = LE_NO_ERROR; const LigatureSubstitutionStateEntry *entry = entryTable.getAlias(index, success); + if (LE_FAILURE(success)) { + currGlyph++; + return 0; + } ByteOffset newState = SWAPW(entry->newStateOffset); le_uint16 flags = SWAPW(entry->flags); @@ -91,6 +95,10 @@ ByteOffset LigatureSubstitutionProcessor::processStateEntry(LEGlyphStorage &glyp if (actionOffset != 0) { LEReferenceTo ap(stHeader, success, actionOffset); + if (LE_FAILURE(success)) { + currGlyph++; + return newState; + } LigatureActionEntry action; le_int32 offset, i = 0, j = 0; le_int32 stack[nComponents]; @@ -101,6 +109,10 @@ ByteOffset LigatureSubstitutionProcessor::processStateEntry(LEGlyphStorage &glyp if (j++ > 0) { ap.addObject(success); + if (LE_FAILURE(success)) { + currGlyph++; + return newState; + } } action = SWAPL(*ap.getAlias()); @@ -124,9 +136,17 @@ ByteOffset LigatureSubstitutionProcessor::processStateEntry(LEGlyphStorage &glyp return newState; // get out! bad font } i += SWAPW(offsetTable.getObject(LE_GET_GLYPH(glyphStorage[componentGlyph]), success)); + if (LE_FAILURE(success)) { + currGlyph++; + return newState; + } if (action & (lafLast | lafStore)) { LEReferenceTo ligatureOffset(stHeader, success, i); + if (LE_FAILURE(success)) { + currGlyph++; + return newState; + } TTGlyphID ligatureGlyph = SWAPW(*ligatureOffset.getAlias()); glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], ligatureGlyph); diff --git a/jdk/src/java.desktop/share/native/libfontmanager/layout/LigatureSubstProc2.cpp b/jdk/src/java.desktop/share/native/libfontmanager/layout/LigatureSubstProc2.cpp index 77e907322ed1375a270b7aeacda4779b3993a44f..1a4709e1d81801fd6b960d1b2a9de2ec031dd128 100644 --- a/jdk/src/java.desktop/share/native/libfontmanager/layout/LigatureSubstProc2.cpp +++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/LigatureSubstProc2.cpp @@ -95,6 +95,10 @@ le_uint16 LigatureSubstitutionProcessor2::processStateEntry(LEGlyphStorage &glyp if (actionOffset != 0) { LEReferenceTo ap(stHeader, success, ligActionOffset); // byte offset + if (LE_FAILURE(success)) { + currGlyph+= dir; + return nextStateIndex; + } ap.addObject(ligActionIndex, success); LEReferenceToArrayOf ligatureTable(stHeader, success, ligatureOffset, LE_UNBOUNDED_ARRAY); LigatureActionEntry action; @@ -104,8 +108,8 @@ le_uint16 LigatureSubstitutionProcessor2::processStateEntry(LEGlyphStorage &glyp LEReferenceToArrayOf componentTable(stHeader, success, componentOffset, LE_UNBOUNDED_ARRAY); if(LE_FAILURE(success)) { - currGlyph+= dir; - return nextStateIndex; // get out! bad font + currGlyph+= dir; + return nextStateIndex; // get out! bad font } do { @@ -114,6 +118,10 @@ le_uint16 LigatureSubstitutionProcessor2::processStateEntry(LEGlyphStorage &glyp if (j++ > 0) { ap.addObject(success); } + if (LE_FAILURE(success)) { + currGlyph+= dir; + return nextStateIndex; + } action = SWAPL(*ap.getAlias()); @@ -129,9 +137,17 @@ le_uint16 LigatureSubstitutionProcessor2::processStateEntry(LEGlyphStorage &glyp return nextStateIndex; // get out! bad font } i += SWAPW(componentTable(LE_GET_GLYPH(glyphStorage[componentGlyph]) + (SignExtend(offset, lafComponentOffsetMask)),success)); + if (LE_FAILURE(success)) { + currGlyph+= dir; + return nextStateIndex; + } if (action & (lafLast | lafStore)) { TTGlyphID ligatureGlyph = SWAPW(ligatureTable(i,success)); + if (LE_FAILURE(success)) { + currGlyph+= dir; + return nextStateIndex; + } glyphStorage[componentGlyph] = LE_SET_GLYPH(glyphStorage[componentGlyph], ligatureGlyph); if(mm==nComponents) { LE_DEBUG_BAD_FONT("exceeded nComponents"); diff --git a/jdk/src/java.desktop/share/native/libfontmanager/layout/StateTableProcessor2.cpp b/jdk/src/java.desktop/share/native/libfontmanager/layout/StateTableProcessor2.cpp index 9aa097a6f5246d59d529c94a7df56c128447f104..ab74b239d760d8fc9903614903f645cde476bdd8 100644 --- a/jdk/src/java.desktop/share/native/libfontmanager/layout/StateTableProcessor2.cpp +++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/StateTableProcessor2.cpp @@ -60,6 +60,7 @@ StateTableProcessor2::StateTableProcessor2(const LEReferenceToentryTableOffset); classTable = LEReferenceTo(stHeader, success, classTableOffset); + if (LE_FAILURE(success)) return; format = SWAPW(classTable->format); stateArray = LEReferenceToArrayOf(stHeader, success, stateArrayOffset, LE_UNBOUNDED_ARRAY); diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/GtkFileDialogPeer.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/GtkFileDialogPeer.java index d6ef132fede2dd4aa7a9de5cc82ace5118076d75..fb7688f9b8e4737bfd57150986e8b7ea742a3da3 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/GtkFileDialogPeer.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/GtkFileDialogPeer.java @@ -29,7 +29,6 @@ import java.awt.peer.FileDialogPeer; import java.io.File; import java.io.FilenameFilter; import sun.awt.AWTAccessor; -import sun.misc.ManagedLocalsThread; /** * FileDialogPeer for the GtkFileChooser. @@ -120,7 +119,7 @@ final class GtkFileDialogPeer extends XDialogPeer implements FileDialogPeer { standaloneWindow = 0; fd.setVisible(false); }; - new ManagedLocalsThread(task).start(); + new Thread(null, task, "ShowDialog", 0, false).start(); } else { quit(); fd.setVisible(false); diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/InfoWindow.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/InfoWindow.java index a7870a95b6a34916223cfa6e09a06fb508d5bdc5..62658c7e92e405caa98779857b3f3941ac9e93ed 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/InfoWindow.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/InfoWindow.java @@ -29,7 +29,6 @@ import java.awt.*; import java.awt.event.*; import java.awt.peer.TrayIconPeer; import sun.awt.*; -import sun.misc.ManagedLocalsThread; import java.awt.image.*; import java.text.BreakIterator; @@ -452,7 +451,7 @@ public abstract class InfoWindow extends Window { final Thread thread; Displayer() { - this.thread = new ManagedLocalsThread(this); + this.thread = new Thread(null, this, "Displayer", 0, false); this.thread.setDaemon(true); } diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XBaseMenuWindow.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XBaseMenuWindow.java index 85481f55c46ea14d5c74fca9e51ab845807e22b1..bb74478d29947653de7d12503cf4d2b96e48ab79 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XBaseMenuWindow.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XBaseMenuWindow.java @@ -1087,7 +1087,7 @@ public abstract class XBaseMenuWindow extends XWindow { } } else { //Invoke action event - item.action(mouseEvent.getWhen()); + item.action(mouseEvent.getWhen(), mouseEvent.getModifiers()); ungrabInput(); } } else { @@ -1200,7 +1200,7 @@ public abstract class XBaseMenuWindow extends XWindow { if (citem instanceof XMenuPeer) { cwnd.selectItem(citem, true); } else if (citem != null) { - citem.action(event.getWhen()); + citem.action(event.getWhen(), event.getModifiers()); ungrabInput(); } break; diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XMenuItemPeer.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XMenuItemPeer.java index aa1c85d7908fcefcccdd6aa08180f59084a90c50..d4e578961be4d9918e66efd58c0d332b266879ce 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XMenuItemPeer.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XMenuItemPeer.java @@ -323,11 +323,11 @@ public class XMenuItemPeer implements MenuItemPeer { * on menu item. * @param when the timestamp of action event */ - void action(long when) { + void action(long when, int modifiers) { if (!isSeparator() && isTargetItemEnabled()) { XWindow.postEventStatic(new ActionEvent(target, ActionEvent.ACTION_PERFORMED, getTargetActionCommand(), when, - 0)); + modifiers)); } } /************************************************ diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTaskbarPeer.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTaskbarPeer.java index bfb964c9b7c0aa3f078c7eb843081ab70ec19871..fa23ae0b66e5dba922a86d2dd55b10154cad5331 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTaskbarPeer.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTaskbarPeer.java @@ -29,7 +29,6 @@ import java.awt.PopupMenu; import java.awt.Taskbar.Feature; import java.awt.peer.TaskbarPeer; import java.awt.event.ActionEvent; -import sun.misc.ManagedLocalsThread; import java.security.AccessController; import sun.security.action.GetPropertyAction; @@ -48,10 +47,8 @@ final class XTaskbarPeer implements TaskbarPeer { new GetPropertyAction("java.desktop.appName", "")); nativeLibraryLoaded = init(dname); if (nativeLibraryLoaded) { - ManagedLocalsThread t - = new ManagedLocalsThread(() -> { - runloop(); - }); + Thread t = new Thread(null, () -> { runloop(); }, + "TaskBar", 0, false); t.setDaemon(true); t.start(); } diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java index f1904e0762616b8902eaaf7442189359efdd4b51..aa460f9f636cdc4ba008cd8ee675955e9adceb07 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java @@ -284,8 +284,8 @@ public final class XToolkit extends UNIXToolkit implements Runnable { } }; String name = "XToolkt-Shutdown-Thread"; - Thread shutdownThread = new ManagedLocalsThread( - ThreadGroupUtils.getRootThreadGroup(), r, name); + Thread shutdownThread = new Thread( + ThreadGroupUtils.getRootThreadGroup(), r, name, 0, false); shutdownThread.setContextClassLoader(null); Runtime.getRuntime().addShutdownHook(shutdownThread); return null; @@ -332,8 +332,9 @@ public final class XToolkit extends UNIXToolkit implements Runnable { toolkitThread = AccessController.doPrivileged((PrivilegedAction) () -> { String name = "AWT-XAWT"; - Thread thread = new ManagedLocalsThread( - ThreadGroupUtils.getRootThreadGroup(), this, name); + Thread thread = new Thread( + ThreadGroupUtils.getRootThreadGroup(), this, name, + 0, false); thread.setContextClassLoader(null); thread.setPriority(Thread.NORM_PRIORITY + 1); thread.setDaemon(true); diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java index 9f35f17201418d1b7d370426171a37598ed0efd0..14ff9a5d45bf70a1aef471ae2123a7c6b36cdc7c 100644 --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java @@ -44,7 +44,6 @@ import sun.java2d.loops.SurfaceType; import sun.awt.util.ThreadGroupUtils; import sun.java2d.SunGraphicsEnvironment; -import sun.misc.ManagedLocalsThread; /** * This is an implementation of a GraphicsDevice object for a single @@ -442,8 +441,8 @@ public final class X11GraphicsDevice extends GraphicsDevice } }; String name = "Display-Change-Shutdown-Thread-" + screen; - Thread t = new ManagedLocalsThread( - ThreadGroupUtils.getRootThreadGroup(), r, name); + Thread t = new Thread( + ThreadGroupUtils.getRootThreadGroup(), r, name, 0, false); t.setContextClassLoader(null); Runtime.getRuntime().addShutdownHook(t); return null; diff --git a/jdk/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java b/jdk/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java index 7cf6bf0acedb366338a42b7c35043fe91ec85eb6..4da098d504ebffea37f18073e6d2e7a1a5cd0422 100644 --- a/jdk/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java +++ b/jdk/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java @@ -25,8 +25,6 @@ package sun.print; -import sun.misc.ManagedLocalsThread; - import java.io.BufferedReader; import java.io.FileInputStream; import java.io.InputStream; @@ -213,7 +211,8 @@ public class PrintServiceLookupProvider extends PrintServiceLookup public PrintServiceLookupProvider() { // start the printer listener thread if (pollServices) { - Thread thr = new ManagedLocalsThread(new PrinterChangeListener()); + Thread thr = new Thread(null, new PrinterChangeListener(), + "PrinterListener", 0, false); thr.setDaemon(true); thr.start(); IPPPrintService.debug_println(debugPrefix+"polling turned on"); diff --git a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c index 7d2b8b0dbd0821ce1710c03586b50bcf1003decc..8b64034a295548385acefa6985a80ad03c2dcc4d 100644 --- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c +++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1877,31 +1877,34 @@ Java_sun_awt_X11GraphicsDevice_getCurrentDisplayMode AWT_LOCK(); - config = awt_XRRGetScreenInfo(awt_display, - RootWindow(awt_display, screen)); - if (config != NULL) { - Rotation rotation; - short curRate; - SizeID curSizeIndex; - XRRScreenSize *sizes; - int nsizes; + if (screen < ScreenCount(awt_display)) { - curSizeIndex = awt_XRRConfigCurrentConfiguration(config, &rotation); - sizes = awt_XRRConfigSizes(config, &nsizes); - curRate = awt_XRRConfigCurrentRate(config); + config = awt_XRRGetScreenInfo(awt_display, + RootWindow(awt_display, screen)); + if (config != NULL) { + Rotation rotation; + short curRate; + SizeID curSizeIndex; + XRRScreenSize *sizes; + int nsizes; - if ((sizes != NULL) && - (curSizeIndex < nsizes)) - { - XRRScreenSize curSize = sizes[curSizeIndex]; - displayMode = X11GD_CreateDisplayMode(env, - curSize.width, - curSize.height, - BIT_DEPTH_MULTI, - curRate); - } + curSizeIndex = awt_XRRConfigCurrentConfiguration(config, &rotation); + sizes = awt_XRRConfigSizes(config, &nsizes); + curRate = awt_XRRConfigCurrentRate(config); - awt_XRRFreeScreenConfigInfo(config); + if ((sizes != NULL) && + (curSizeIndex < nsizes)) + { + XRRScreenSize curSize = sizes[curSizeIndex]; + displayMode = X11GD_CreateDisplayMode(env, + curSize.width, + curSize.height, + BIT_DEPTH_MULTI, + curRate); + } + + awt_XRRFreeScreenConfigInfo(config); + } } AWT_FLUSH_UNLOCK(); diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java b/jdk/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java index b01d04443df2fa19316d7558ef7dd05ae565a620..1e20c3582f78a4c48913bf155c2bc0712350a69d 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java @@ -41,7 +41,6 @@ import java.util.stream.Stream; import static sun.awt.shell.Win32ShellFolder2.*; import sun.awt.OSInfo; import sun.awt.util.ThreadGroupUtils; -import sun.misc.ManagedLocalsThread; // NOTE: This class supersedes Win32ShellFolderManager, which was removed // from distribution after version 1.4.2. @@ -524,8 +523,9 @@ final class Win32ShellFolderManager2 extends ShellFolderManager { return null; }); AccessController.doPrivileged((PrivilegedAction) () -> { - Thread t = new ManagedLocalsThread( - ThreadGroupUtils.getRootThreadGroup(), shutdownHook); + Thread t = new Thread( + ThreadGroupUtils.getRootThreadGroup(), shutdownHook, + "ShellFolder", 0, false); Runtime.getRuntime().addShutdownHook(t); return null; }); @@ -548,8 +548,9 @@ final class Win32ShellFolderManager2 extends ShellFolderManager { * which will not get GCed before VM exit. * Make its parent the top-level thread group. */ - Thread thread = new ManagedLocalsThread( - ThreadGroupUtils.getRootThreadGroup(), comRun, name); + Thread thread = new Thread( + ThreadGroupUtils.getRootThreadGroup(), comRun, name, + 0, false); thread.setDaemon(true); return thread; }); diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WFileDialogPeer.java b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WFileDialogPeer.java index e75f3b9f48657440a687c8a0a40f9918b0b52c1f..383254b815aa7d717129f7c4ea58a3a85af9ecbf 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WFileDialogPeer.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WFileDialogPeer.java @@ -36,7 +36,6 @@ import java.util.MissingResourceException; import java.util.Vector; import sun.awt.CausedFocusEvent; import sun.awt.AWTAccessor; -import sun.misc.ManagedLocalsThread; final class WFileDialogPeer extends WWindowPeer implements FileDialogPeer { @@ -98,7 +97,7 @@ final class WFileDialogPeer extends WWindowPeer implements FileDialogPeer { @Override public void show() { - new ManagedLocalsThread(this::_show).start(); + new Thread(null, this::_show, "FileDialog", 0, false).start(); } @Override diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPageDialogPeer.java b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPageDialogPeer.java index 10d99948b1085b37b50095dc9aa2506b5cbfccae..5e7303b1af196f446b5f4fd37f5e482fa658974f 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPageDialogPeer.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPageDialogPeer.java @@ -25,8 +25,6 @@ package sun.awt.windows; -import sun.misc.ManagedLocalsThread; - final class WPageDialogPeer extends WPrintDialogPeer { WPageDialogPeer(WPageDialog target) { @@ -53,6 +51,6 @@ final class WPageDialogPeer extends WPrintDialogPeer { } ((WPrintDialog)target).setVisible(false); }; - new ManagedLocalsThread(runnable).start(); + new Thread(null, runnable, "PageDialog", 0, false).start(); } } diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPrintDialogPeer.java b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPrintDialogPeer.java index 99c727493d1d600a2421ff1585a4276d2bf029e9..a80e7dd6d13c1459cd86549ca54489385732102a 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPrintDialogPeer.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPrintDialogPeer.java @@ -32,7 +32,6 @@ import java.awt.dnd.DropTarget; import java.util.Vector; import sun.awt.CausedFocusEvent; import sun.awt.AWTAccessor; -import sun.misc.ManagedLocalsThread; class WPrintDialogPeer extends WWindowPeer implements DialogPeer { @@ -78,7 +77,7 @@ class WPrintDialogPeer extends WWindowPeer implements DialogPeer { } ((WPrintDialog)target).setVisible(false); }; - new ManagedLocalsThread(runnable).start(); + new Thread(null, runnable, "PrintDialog", 0, false).start(); } synchronized void setHWnd(long hwnd) { diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java index 8fb6f386474cb8c812ee2eb35b4be0b3d1763b74..097f68dac3196b75a3d32a51dc8fb67bc785b456 100644 --- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java +++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java @@ -52,7 +52,6 @@ import sun.awt.datatransfer.DataTransferer; import sun.java2d.d3d.D3DRenderQueue; import sun.java2d.opengl.OGLRenderQueue; -import sun.misc.ManagedLocalsThread; import sun.print.PrintJob2D; import java.awt.dnd.DragSource; @@ -256,7 +255,7 @@ public final class WToolkit extends SunToolkit implements Runnable { (PrivilegedAction) ThreadGroupUtils::getRootThreadGroup); if (!startToolkitThread(this, rootTG)) { String name = "AWT-Windows"; - Thread toolkitThread = new ManagedLocalsThread(rootTG, this, name); + Thread toolkitThread = new Thread(rootTG, this, name, 0, false); toolkitThread.setDaemon(true); toolkitThread.start(); } @@ -283,8 +282,9 @@ public final class WToolkit extends SunToolkit implements Runnable { private void registerShutdownHook() { AccessController.doPrivileged((PrivilegedAction) () -> { - Thread shutdown = new ManagedLocalsThread( - ThreadGroupUtils.getRootThreadGroup(), this::shutdown); + Thread shutdown = new Thread( + ThreadGroupUtils.getRootThreadGroup(), this::shutdown, + "ToolkitShutdown", 0, false); shutdown.setContextClassLoader(null); Runtime.getRuntime().addShutdownHook(shutdown); return null; diff --git a/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java b/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java index 4b112b9fcc73a225d3591749bbd559e333cf8593..62be1e84f1b697aca3906d4f150ef628316320a8 100644 --- a/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java +++ b/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java @@ -49,7 +49,6 @@ import sun.java2d.SurfaceData; import sun.java2d.windows.GDIWindowSurfaceData; import sun.java2d.d3d.D3DSurfaceData.D3DWindowSurfaceData; import sun.java2d.windows.WindowsFlags; -import sun.misc.ManagedLocalsThread; /** * This class handles rendering to the screen with the D3D pipeline. @@ -99,8 +98,9 @@ public class D3DScreenUpdateManager extends ScreenUpdateManager done = true; wakeUpUpdateThread(); }; - Thread shutdown = new ManagedLocalsThread( - ThreadGroupUtils.getRootThreadGroup(), shutdownRunnable); + Thread shutdown = new Thread( + ThreadGroupUtils.getRootThreadGroup(), shutdownRunnable, + "ScreenUpdater", 0, false); shutdown.setContextClassLoader(null); try { Runtime.getRuntime().addShutdownHook(shutdown); @@ -348,8 +348,9 @@ public class D3DScreenUpdateManager extends ScreenUpdateManager if (screenUpdater == null) { screenUpdater = AccessController.doPrivileged((PrivilegedAction) () -> { String name = "D3D Screen Updater"; - Thread t = new ManagedLocalsThread( - ThreadGroupUtils.getRootThreadGroup(), this, name); + Thread t = new Thread( + ThreadGroupUtils.getRootThreadGroup(), this, name, + 0, false); // REMIND: should it be higher? t.setPriority(Thread.NORM_PRIORITY + 2); t.setDaemon(true); diff --git a/jdk/src/java.desktop/windows/classes/sun/print/PrintServiceLookupProvider.java b/jdk/src/java.desktop/windows/classes/sun/print/PrintServiceLookupProvider.java index e9139b465252aaed3763789c500c5851f9eb2ccf..347336bcb7ad3dc2b94ce9c4fa638e9e09654946 100644 --- a/jdk/src/java.desktop/windows/classes/sun/print/PrintServiceLookupProvider.java +++ b/jdk/src/java.desktop/windows/classes/sun/print/PrintServiceLookupProvider.java @@ -25,8 +25,6 @@ package sun.print; -import sun.misc.ManagedLocalsThread; - import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; @@ -99,7 +97,8 @@ public class PrintServiceLookupProvider extends PrintServiceLookup { return; } // start the printer listener thread - Thread thr = new ManagedLocalsThread(new PrinterChangeListener()); + Thread thr = new Thread(null, new PrinterChangeListener(), + "PrinterListener", 0, false); thr.setDaemon(true); thr.start(); } /* else condition ought to never happen! */ diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Button.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Button.cpp index f0550a9aa5d085c68c1a2539d1912d8046d343e1..e76582bf363445ba43abc79ae5e4c781fdf8fcd0 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Button.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Button.cpp @@ -187,7 +187,7 @@ void AwtButton::NotifyListeners() { DoCallback("handleAction", "(JI)V", ::JVM_CurrentTimeMillis(NULL, 0), - (jint)AwtComponent::GetJavaModifiers()); + (jint)AwtComponent::GetActionModifiers()); } MsgRouting diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp index d5224df0b62b9ceb748ef08c8f592b159534c12b..746b1114488ee1948859cc61232ac8b909e8167e 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp @@ -60,6 +60,7 @@ #include #include #include +#include #include #include #include @@ -2587,6 +2588,27 @@ jint AwtComponent::GetShiftKeyLocation(UINT vkey, UINT flags) return java_awt_event_KeyEvent_KEY_LOCATION_LEFT; } +/* Returns Java ActionEvent modifieres. + * When creating ActionEvent, modifiers provided by ActionEvent + * class should be set. + */ +jint +AwtComponent::GetActionModifiers() +{ + jint modifiers = GetJavaModifiers(); + + if (modifiers & java_awt_event_InputEvent_CTRL_DOWN_MASK) { + modifiers |= java_awt_event_ActionEvent_CTRL_MASK; + } + if (modifiers & java_awt_event_InputEvent_SHIFT_DOWN_MASK) { + modifiers |= java_awt_event_ActionEvent_SHIFT_MASK; + } + if (modifiers & java_awt_event_InputEvent_ALT_DOWN_MASK) { + modifiers |= java_awt_event_ActionEvent_ALT_MASK; + } + return modifiers; +} + /* Returns Java extended InputEvent modifieres. * Since ::GetKeyState returns current state and Java modifiers represent * state before event, modifier on changed key are inverted. diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.h b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.h index 83c6d8b8a4e51aa38b6ec28857cb337d7e61df1a..135ac39b8740df7cb26a6127ef0b28328b17f716 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.h +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.h @@ -438,6 +438,7 @@ public: static void InitDynamicKeyMapTable(); static void BuildDynamicKeyMapTable(); static jint GetJavaModifiers(); + static jint GetActionModifiers(); static jint GetButton(int mouseButton); static UINT GetButtonMK(int mouseButton); static UINT WindowsKeyToJavaKey(UINT windowsKey, UINT modifiers, UINT character, BOOL isDeadKey); diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_List.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_List.cpp index 39016b9ab59606752693e1b13fd15552a10985f3..4c32a472996c87ee3576194499b4c0e737300668 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_List.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_List.cpp @@ -536,7 +536,7 @@ AwtList::WmNotify(UINT notifyCode) else if (notifyCode == LBN_DBLCLK) { DoCallback("handleAction", "(IJI)V", nCurrentSelection, ::JVM_CurrentTimeMillis(NULL, 0), - (jint)AwtComponent::GetJavaModifiers()); + (jint)AwtComponent::GetActionModifiers()); } } } diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_List.h b/jdk/src/java.desktop/windows/native/libawt/windows/awt_List.h index 73effc3a56e76045c43ab1cae586debb235bb9a8..3450089b5091722bff979292bc0455d7d7cbad8f 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_List.h +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_List.h @@ -56,6 +56,7 @@ public: } INLINE void Deselect(int pos) { if (isMultiSelect) { + SendListMessage(LB_SETCARETINDEX, pos, FALSE); SendListMessage(LB_SETSEL, FALSE, pos); } else { diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_MenuItem.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_MenuItem.cpp index ba0488187c56f11d4a60f1c3700b0d4a18c3cc62..80fc977e00d168dc100f3f8fb1e9acd5f32d8b5f 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_MenuItem.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_MenuItem.cpp @@ -667,7 +667,7 @@ void AwtMenuItem::DoCommand() DoCallback("handleAction", "(Z)V", ((nState & MF_CHECKED) == 0)); } else { DoCallback("handleAction", "(JI)V", ::JVM_CurrentTimeMillis(NULL, 0), - (jint)AwtComponent::GetJavaModifiers()); + (jint)AwtComponent::GetActionModifiers()); } } diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_TrayIcon.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_TrayIcon.cpp index ef376f31a3be95a9f5e8d0439e8f1cd8527f3870..56280a583ac307db4014bc5345f3f94e278c022b 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_TrayIcon.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_TrayIcon.cpp @@ -409,7 +409,7 @@ MsgRouting AwtTrayIcon::WmBalloonUserClick(UINT flags, int x, int y) MSG msg; AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y); SendActionEvent(java_awt_event_ActionEvent_ACTION_PERFORMED, ::JVM_CurrentTimeMillis(NULL, 0), - AwtComponent::GetJavaModifiers(), &msg); + AwtComponent::GetActionModifiers(), &msg); } return mrConsume; } @@ -425,7 +425,7 @@ MsgRouting AwtTrayIcon::WmKeySelect(UINT flags, int x, int y) MSG msg; AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y); SendActionEvent(java_awt_event_ActionEvent_ACTION_PERFORMED, ::JVM_CurrentTimeMillis(NULL, 0), - AwtComponent::GetJavaModifiers(), &msg); + AwtComponent::GetActionModifiers(), &msg); } lastKeySelectTime = now; @@ -442,7 +442,7 @@ MsgRouting AwtTrayIcon::WmSelect(UINT flags, int x, int y) MSG msg; AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y); SendActionEvent(java_awt_event_ActionEvent_ACTION_PERFORMED, ::JVM_CurrentTimeMillis(NULL, 0), - AwtComponent::GetJavaModifiers(), &msg); + AwtComponent::GetActionModifiers(), &msg); } return mrConsume; } diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/BinaryRepresentationWriter.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/BinaryRepresentationWriter.java new file mode 100644 index 0000000000000000000000000000000000000000..de60d58f6aca1c487f14b0a3e3a35486b4db7096 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/BinaryRepresentationWriter.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import java.nio.ByteBuffer; + +interface BinaryRepresentationWriter { + + boolean write(HeaderTable table, ByteBuffer destination); + + BinaryRepresentationWriter reset(); +} diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/BulkSizeUpdateWriter.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/BulkSizeUpdateWriter.java new file mode 100644 index 0000000000000000000000000000000000000000..1c064f627f57439d070cec79d8c4f8c16896f339 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/BulkSizeUpdateWriter.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import java.nio.ByteBuffer; +import java.util.Iterator; + +import static java.util.Objects.requireNonNull; + +final class BulkSizeUpdateWriter implements BinaryRepresentationWriter { + + private final SizeUpdateWriter writer = new SizeUpdateWriter(); + private Iterator maxSizes; + private boolean writing; + private boolean configured; + + BulkSizeUpdateWriter maxHeaderTableSizes(Iterable sizes) { + if (configured) { + throw new IllegalStateException("Already configured"); + } + requireNonNull(sizes, "sizes"); + maxSizes = sizes.iterator(); + configured = true; + return this; + } + + @Override + public boolean write(HeaderTable table, ByteBuffer destination) { + if (!configured) { + throw new IllegalStateException("Configure first"); + } + while (true) { + if (writing) { + if (!writer.write(table, destination)) { + return false; + } + writing = false; + } else if (maxSizes.hasNext()) { + writing = true; + writer.reset(); + writer.maxHeaderTableSize(maxSizes.next()); + } else { + configured = false; + return true; + } + } + } + + @Override + public BulkSizeUpdateWriter reset() { + maxSizes = null; + writing = false; + configured = false; + return this; + } +} diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/Decoder.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/Decoder.java new file mode 100644 index 0000000000000000000000000000000000000000..afff906424af06ae3cfb98953094c5ad9fd140f6 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/Decoder.java @@ -0,0 +1,506 @@ +/* + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.net.ProtocolException; +import java.nio.ByteBuffer; + +import static java.lang.String.format; +import static java.util.Objects.requireNonNull; + +/** + * Decodes headers from their binary representation. + * + *

Typical lifecycle looks like this: + * + *

{@link #Decoder(int) new Decoder} + * ({@link #setMaxCapacity(int) setMaxCapacity}? + * {@link #decode(ByteBuffer, boolean, DecodingCallback) decode})* + * + * @apiNote + * + *

The design intentions behind Decoder were to facilitate flexible and + * incremental style of processing. + * + *

{@code Decoder} does not require a complete header block in a single + * {@code ByteBuffer}. The header block can be spread across many buffers of any + * size and decoded one-by-one the way it makes most sense for the user. This + * way also allows not to limit the size of the header block. + * + *

Headers are delivered to the {@linkplain DecodingCallback callback} as + * soon as they become decoded. Using the callback also gives the user a freedom + * to decide how headers are processed. The callback does not limit the number + * of headers decoded during single decoding operation. + * + * @since 9 + */ +public final class Decoder { + + private static final State[] states = new State[256]; + + static { + // To be able to do a quick lookup, each of 256 possibilities are mapped + // to corresponding states. + // + // We can safely do this since patterns 1, 01, 001, 0001, 0000 are + // Huffman prefixes and therefore are inherently not ambiguous. + // + // I do it mainly for better debugging (to not go each time step by step + // through if...else tree). As for performance win for the decoding, I + // believe is negligible. + for (int i = 0; i < states.length; i++) { + if ((i & 0b1000_0000) == 0b1000_0000) { + states[i] = State.INDEXED; + } else if ((i & 0b1100_0000) == 0b0100_0000) { + states[i] = State.LITERAL_WITH_INDEXING; + } else if ((i & 0b1110_0000) == 0b0010_0000) { + states[i] = State.SIZE_UPDATE; + } else if ((i & 0b1111_0000) == 0b0001_0000) { + states[i] = State.LITERAL_NEVER_INDEXED; + } else if ((i & 0b1111_0000) == 0b0000_0000) { + states[i] = State.LITERAL; + } else { + throw new InternalError(String.valueOf(i)); + } + } + } + + private final HeaderTable table; + + private State state = State.READY; + private final IntegerReader integerReader; + private final StringReader stringReader; + private final StringBuilder name; + private final StringBuilder value; + private int intValue; + private boolean firstValueRead; + private boolean firstValueIndex; + private boolean nameHuffmanEncoded; + private boolean valueHuffmanEncoded; + private int capacity; + + /** + * Constructs a {@code Decoder} with the specified initial capacity of the + * header table. + * + *

The value has to be agreed between decoder and encoder out-of-band, + * e.g. by a protocol that uses HPACK (see 4.2. Maximum Table + * Size). + * + * @param capacity + * a non-negative integer + * + * @throws IllegalArgumentException + * if capacity is negative + */ + public Decoder(int capacity) { + setMaxCapacity(capacity); + table = new HeaderTable(capacity); + integerReader = new IntegerReader(); + stringReader = new StringReader(); + name = new StringBuilder(512); + value = new StringBuilder(1024); + } + + /** + * Sets a maximum capacity of the header table. + * + *

The value has to be agreed between decoder and encoder out-of-band, + * e.g. by a protocol that uses HPACK (see 4.2. Maximum Table + * Size). + * + * @param capacity + * a non-negative integer + * + * @throws IllegalArgumentException + * if capacity is negative + */ + public void setMaxCapacity(int capacity) { + if (capacity < 0) { + throw new IllegalArgumentException("capacity >= 0: " + capacity); + } + // FIXME: await capacity update if less than what was prior to it + this.capacity = capacity; + } + + /** + * Decodes a header block from the given buffer to the given callback. + * + *

Suppose a header block is represented by a sequence of {@code + * ByteBuffer}s in the form of {@code Iterator}. And the + * consumer of decoded headers is represented by the callback. Then to + * decode the header block, the following approach might be used: + * + *

{@code
+     * while (buffers.hasNext()) {
+     *     ByteBuffer input = buffers.next();
+     *     decoder.decode(input, callback, !buffers.hasNext());
+     * }
+     * }
+ * + *

The decoder reads as much as possible of the header block from the + * given buffer, starting at the buffer's position, and increments its + * position to reflect the bytes read. The buffer's mark and limit will not + * be modified. + * + *

Once the method is invoked with {@code endOfHeaderBlock == true}, the + * current header block is deemed ended, and inconsistencies, if any, are + * reported immediately by throwing an {@code UncheckedIOException}. + * + *

Each callback method is called only after the implementation has + * processed the corresponding bytes. If the bytes revealed a decoding + * error, the callback method is not called. + * + *

In addition to exceptions thrown directly by the method, any + * exceptions thrown from the {@code callback} will bubble up. + * + * @apiNote The method asks for {@code endOfHeaderBlock} flag instead of + * returning it for two reasons. The first one is that the user of the + * decoder always knows which chunk is the last. The second one is to throw + * the most detailed exception possible, which might be useful for + * diagnosing issues. + * + * @implNote This implementation is not atomic in respect to decoding + * errors. In other words, if the decoding operation has thrown a decoding + * error, the decoder is no longer usable. + * + * @param headerBlock + * the chunk of the header block, may be empty + * @param endOfHeaderBlock + * true if the chunk is the final (or the only one) in the sequence + * + * @param consumer + * the callback + * @throws UncheckedIOException + * in case of a decoding error + * @throws NullPointerException + * if either headerBlock or consumer are null + */ + public void decode(ByteBuffer headerBlock, boolean endOfHeaderBlock, + DecodingCallback consumer) { + requireNonNull(headerBlock, "headerBlock"); + requireNonNull(consumer, "consumer"); + while (headerBlock.hasRemaining()) { + proceed(headerBlock, consumer); + } + if (endOfHeaderBlock && state != State.READY) { + throw new UncheckedIOException( + new ProtocolException("Unexpected end of header block")); + } + } + + private void proceed(ByteBuffer input, DecodingCallback action) { + switch (state) { + case READY: + resumeReady(input); + break; + case INDEXED: + resumeIndexed(input, action); + break; + case LITERAL: + resumeLiteral(input, action); + break; + case LITERAL_WITH_INDEXING: + resumeLiteralWithIndexing(input, action); + break; + case LITERAL_NEVER_INDEXED: + resumeLiteralNeverIndexed(input, action); + break; + case SIZE_UPDATE: + resumeSizeUpdate(input, action); + break; + default: + throw new InternalError( + "Unexpected decoder state: " + String.valueOf(state)); + } + } + + private void resumeReady(ByteBuffer input) { + int b = input.get(input.position()) & 0xff; // absolute read + State s = states[b]; + switch (s) { + case INDEXED: + integerReader.configure(7); + state = State.INDEXED; + firstValueIndex = true; + break; + case LITERAL: + state = State.LITERAL; + firstValueIndex = (b & 0b0000_1111) != 0; + if (firstValueIndex) { + integerReader.configure(4); + } + break; + case LITERAL_WITH_INDEXING: + state = State.LITERAL_WITH_INDEXING; + firstValueIndex = (b & 0b0011_1111) != 0; + if (firstValueIndex) { + integerReader.configure(6); + } + break; + case LITERAL_NEVER_INDEXED: + state = State.LITERAL_NEVER_INDEXED; + firstValueIndex = (b & 0b0000_1111) != 0; + if (firstValueIndex) { + integerReader.configure(4); + } + break; + case SIZE_UPDATE: + integerReader.configure(5); + state = State.SIZE_UPDATE; + firstValueIndex = true; + break; + default: + throw new InternalError(String.valueOf(s)); + } + if (!firstValueIndex) { + input.get(); // advance, next stop: "String Literal" + } + } + + // 0 1 2 3 4 5 6 7 + // +---+---+---+---+---+---+---+---+ + // | 1 | Index (7+) | + // +---+---------------------------+ + // + private void resumeIndexed(ByteBuffer input, DecodingCallback action) { + if (!integerReader.read(input)) { + return; + } + intValue = integerReader.get(); + integerReader.reset(); + try { + HeaderTable.HeaderField f = table.get(intValue); + action.onIndexed(intValue, f.name, f.value); + } finally { + state = State.READY; + } + } + + // 0 1 2 3 4 5 6 7 + // +---+---+---+---+---+---+---+---+ + // | 0 | 0 | 0 | 0 | Index (4+) | + // +---+---+-----------------------+ + // | H | Value Length (7+) | + // +---+---------------------------+ + // | Value String (Length octets) | + // +-------------------------------+ + // + // 0 1 2 3 4 5 6 7 + // +---+---+---+---+---+---+---+---+ + // | 0 | 0 | 0 | 0 | 0 | + // +---+---+-----------------------+ + // | H | Name Length (7+) | + // +---+---------------------------+ + // | Name String (Length octets) | + // +---+---------------------------+ + // | H | Value Length (7+) | + // +---+---------------------------+ + // | Value String (Length octets) | + // +-------------------------------+ + // + private void resumeLiteral(ByteBuffer input, DecodingCallback action) { + if (!completeReading(input)) { + return; + } + try { + if (firstValueIndex) { + HeaderTable.HeaderField f = table.get(intValue); + action.onLiteral(intValue, f.name, value, valueHuffmanEncoded); + } else { + action.onLiteral(name, nameHuffmanEncoded, value, valueHuffmanEncoded); + } + } finally { + cleanUpAfterReading(); + } + } + + // + // 0 1 2 3 4 5 6 7 + // +---+---+---+---+---+---+---+---+ + // | 0 | 1 | Index (6+) | + // +---+---+-----------------------+ + // | H | Value Length (7+) | + // +---+---------------------------+ + // | Value String (Length octets) | + // +-------------------------------+ + // + // 0 1 2 3 4 5 6 7 + // +---+---+---+---+---+---+---+---+ + // | 0 | 1 | 0 | + // +---+---+-----------------------+ + // | H | Name Length (7+) | + // +---+---------------------------+ + // | Name String (Length octets) | + // +---+---------------------------+ + // | H | Value Length (7+) | + // +---+---------------------------+ + // | Value String (Length octets) | + // +-------------------------------+ + // + private void resumeLiteralWithIndexing(ByteBuffer input, DecodingCallback action) { + if (!completeReading(input)) { + return; + } + try { + // + // 1. (name, value) will be stored in the table as strings + // 2. Most likely the callback will also create strings from them + // ------------------------------------------------------------------------ + // Let's create those string beforehand (and only once!) to benefit everyone + // + String n; + String v = value.toString(); + if (firstValueIndex) { + HeaderTable.HeaderField f = table.get(intValue); + n = f.name; + action.onLiteralWithIndexing(intValue, n, v, valueHuffmanEncoded); + } else { + n = name.toString(); + action.onLiteralWithIndexing(n, nameHuffmanEncoded, v, valueHuffmanEncoded); + } + table.put(n, v); + } catch (IllegalArgumentException | IllegalStateException e) { + throw new UncheckedIOException( + (IOException) new ProtocolException().initCause(e)); + } finally { + cleanUpAfterReading(); + } + } + + // 0 1 2 3 4 5 6 7 + // +---+---+---+---+---+---+---+---+ + // | 0 | 0 | 0 | 1 | Index (4+) | + // +---+---+-----------------------+ + // | H | Value Length (7+) | + // +---+---------------------------+ + // | Value String (Length octets) | + // +-------------------------------+ + // + // 0 1 2 3 4 5 6 7 + // +---+---+---+---+---+---+---+---+ + // | 0 | 0 | 0 | 1 | 0 | + // +---+---+-----------------------+ + // | H | Name Length (7+) | + // +---+---------------------------+ + // | Name String (Length octets) | + // +---+---------------------------+ + // | H | Value Length (7+) | + // +---+---------------------------+ + // | Value String (Length octets) | + // +-------------------------------+ + // + private void resumeLiteralNeverIndexed(ByteBuffer input, DecodingCallback action) { + if (!completeReading(input)) { + return; + } + try { + if (firstValueIndex) { + HeaderTable.HeaderField f = table.get(intValue); + action.onLiteralNeverIndexed(intValue, f.name, value, valueHuffmanEncoded); + } else { + action.onLiteralNeverIndexed(name, nameHuffmanEncoded, value, valueHuffmanEncoded); + } + } finally { + cleanUpAfterReading(); + } + } + + // 0 1 2 3 4 5 6 7 + // +---+---+---+---+---+---+---+---+ + // | 0 | 0 | 1 | Max size (5+) | + // +---+---------------------------+ + // + private void resumeSizeUpdate(ByteBuffer input, DecodingCallback action) { + if (!integerReader.read(input)) { + return; + } + intValue = integerReader.get(); + assert intValue >= 0; + if (intValue > capacity) { + throw new UncheckedIOException(new ProtocolException( + format("Received capacity exceeds expected: " + + "capacity=%s, expected=%s", intValue, capacity))); + } + integerReader.reset(); + try { + action.onSizeUpdate(intValue); + table.setMaxSize(intValue); + } finally { + state = State.READY; + } + } + + private boolean completeReading(ByteBuffer input) { + if (!firstValueRead) { + if (firstValueIndex) { + if (!integerReader.read(input)) { + return false; + } + intValue = integerReader.get(); + integerReader.reset(); + } else { + if (!stringReader.read(input, name)) { + return false; + } + nameHuffmanEncoded = stringReader.isHuffmanEncoded(); + stringReader.reset(); + } + firstValueRead = true; + return false; + } else { + if (!stringReader.read(input, value)) { + return false; + } + } + valueHuffmanEncoded = stringReader.isHuffmanEncoded(); + stringReader.reset(); + return true; + } + + private void cleanUpAfterReading() { + name.setLength(0); + value.setLength(0); + firstValueRead = false; + state = State.READY; + } + + private enum State { + READY, + INDEXED, + LITERAL_NEVER_INDEXED, + LITERAL, + LITERAL_WITH_INDEXING, + SIZE_UPDATE + } + + HeaderTable getTable() { + return table; + } +} diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/DecodingCallback.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/DecodingCallback.java new file mode 100644 index 0000000000000000000000000000000000000000..d0d1ce5d5d5762fb6d3544e50cf90c2468d2681d --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/DecodingCallback.java @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import java.nio.ByteBuffer; + +/** + * Delivers results of the {@link Decoder#decode(ByteBuffer, boolean, + * DecodingCallback) decoding operation}. + * + *

Methods of the callback are never called by a decoder with any of the + * arguments being {@code null}. + * + * @apiNote + * + *

The callback provides methods for all possible binary + * representations. This could be useful for implementing an intermediary, + * logging, debugging, etc. + * + *

The callback is an interface in order to interoperate with lambdas (in + * the most common use case): + *

{@code
+ *     DecodingCallback callback = (name, value) -> System.out.println(name + ", " + value);
+ * }
+ * + *

Names and values are {@link CharSequence}s rather than {@link String}s in + * order to allow users to decide whether or not they need to create objects. A + * {@code CharSequence} might be used in-place, for example, to be appended to + * an {@link Appendable} (e.g. {@link StringBuilder}) and then discarded. + * + *

That said, if a passed {@code CharSequence} needs to outlast the method + * call, it needs to be copied. + * + * @since 9 + */ +@FunctionalInterface +public interface DecodingCallback { + + /** + * A method the more specific methods of the callback forward their calls + * to. + * + * @param name + * header name + * @param value + * header value + */ + void onDecoded(CharSequence name, CharSequence value); + + /** + * A more finer-grained version of {@link #onDecoded(CharSequence, + * CharSequence)} that also reports on value sensitivity. + * + *

Value sensitivity must be considered, for example, when implementing + * an intermediary. A {@code value} is sensitive if it was represented as Literal Header + * Field Never Indexed. + * + *

It is required that intermediaries MUST use the {@linkplain + * Encoder#header(CharSequence, CharSequence, boolean) same representation} + * for encoding this header field in order to protect its value which is not + * to be put at risk by compressing it. + * + * @implSpec + * + *

The default implementation invokes {@code onDecoded(name, value)}. + * + * @param name + * header name + * @param value + * header value + * @param sensitive + * whether or not the value is sensitive + * + * @see #onLiteralNeverIndexed(int, CharSequence, CharSequence, boolean) + * @see #onLiteralNeverIndexed(CharSequence, boolean, CharSequence, boolean) + */ + default void onDecoded(CharSequence name, CharSequence value, + boolean sensitive) { + onDecoded(name, value); + } + + /** + * An Indexed + * Header Field decoded. + * + * @implSpec + * + *

The default implementation invokes + * {@code onDecoded(name, value, false)}. + * + * @param index + * index of an entry in the table + * @param name + * header name + * @param value + * header value + */ + default void onIndexed(int index, CharSequence name, CharSequence value) { + onDecoded(name, value, false); + } + + /** + * A Literal + * Header Field without Indexing decoded, where a {@code name} was + * referred by an {@code index}. + * + * @implSpec + * + *

The default implementation invokes + * {@code onDecoded(name, value, false)}. + * + * @param index + * index of an entry in the table + * @param name + * header name + * @param value + * header value + * @param valueHuffman + * if the {@code value} was Huffman encoded + */ + default void onLiteral(int index, CharSequence name, + CharSequence value, boolean valueHuffman) { + onDecoded(name, value, false); + } + + /** + * A Literal + * Header Field without Indexing decoded, where both a {@code name} and + * a {@code value} were literal. + * + * @implSpec + * + *

The default implementation invokes + * {@code onDecoded(name, value, false)}. + * + * @param name + * header name + * @param nameHuffman + * if the {@code name} was Huffman encoded + * @param value + * header value + * @param valueHuffman + * if the {@code value} was Huffman encoded + */ + default void onLiteral(CharSequence name, boolean nameHuffman, + CharSequence value, boolean valueHuffman) { + onDecoded(name, value, false); + } + + /** + * A Literal + * Header Field Never Indexed decoded, where a {@code name} + * was referred by an {@code index}. + * + * @implSpec + * + *

The default implementation invokes + * {@code onDecoded(name, value, true)}. + * + * @param index + * index of an entry in the table + * @param name + * header name + * @param value + * header value + * @param valueHuffman + * if the {@code value} was Huffman encoded + */ + default void onLiteralNeverIndexed(int index, CharSequence name, + CharSequence value, + boolean valueHuffman) { + onDecoded(name, value, true); + } + + /** + * A Literal + * Header Field Never Indexed decoded, where both a {@code + * name} and a {@code value} were literal. + * + * @implSpec + * + *

The default implementation invokes + * {@code onDecoded(name, value, true)}. + * + * @param name + * header name + * @param nameHuffman + * if the {@code name} was Huffman encoded + * @param value + * header value + * @param valueHuffman + * if the {@code value} was Huffman encoded + */ + default void onLiteralNeverIndexed(CharSequence name, boolean nameHuffman, + CharSequence value, boolean valueHuffman) { + onDecoded(name, value, true); + } + + /** + * A Literal + * Header Field with Incremental Indexing decoded, where a {@code name} + * was referred by an {@code index}. + * + * @implSpec + * + *

The default implementation invokes + * {@code onDecoded(name, value, false)}. + * + * @param index + * index of an entry in the table + * @param name + * header name + * @param value + * header value + * @param valueHuffman + * if the {@code value} was Huffman encoded + */ + default void onLiteralWithIndexing(int index, + CharSequence name, + CharSequence value, boolean valueHuffman) { + onDecoded(name, value, false); + } + + /** + * A Literal + * Header Field with Incremental Indexing decoded, where both a {@code + * name} and a {@code value} were literal. + * + * @implSpec + * + *

The default implementation invokes + * {@code onDecoded(name, value, false)}. + * + * @param name + * header name + * @param nameHuffman + * if the {@code name} was Huffman encoded + * @param value + * header value + * @param valueHuffman + * if the {@code value} was Huffman encoded + */ + default void onLiteralWithIndexing(CharSequence name, boolean nameHuffman, + CharSequence value, boolean valueHuffman) { + onDecoded(name, value, false); + } + + /** + * A Dynamic Table + * Size Update decoded. + * + * @implSpec + * + *

The default implementation does nothing. + * + * @param capacity + * new capacity of the header table + */ + default void onSizeUpdate(int capacity) { } +} diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/Encoder.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/Encoder.java new file mode 100644 index 0000000000000000000000000000000000000000..75ab8653457c3dfbcc9f1918b01ba3487a31133b --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/Encoder.java @@ -0,0 +1,429 @@ +/* + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import java.nio.ByteBuffer; +import java.nio.ReadOnlyBufferException; +import java.util.LinkedList; +import java.util.List; + +import static java.lang.String.format; +import static java.util.Objects.requireNonNull; + +/** + * Encodes headers to their binary representation. + * + *

Typical lifecycle looks like this: + * + *

{@link #Encoder(int) new Encoder} + * ({@link #setMaxCapacity(int) setMaxCapacity}? + * {@link #encode(ByteBuffer) encode})* + * + *

Suppose headers are represented by {@code Map>}. A + * supplier and a consumer of {@link ByteBuffer}s in forms of {@code + * Supplier} and {@code Consumer} respectively. Then to + * encode headers, the following approach might be used: + * + *

{@code
+ *     for (Map.Entry> h : headers.entrySet()) {
+ *         String name = h.getKey();
+ *         for (String value : h.getValue()) {
+ *             encoder.header(name, value);        // Set up header
+ *             boolean encoded;
+ *             do {
+ *                 ByteBuffer b = buffersSupplier.get();
+ *                 encoded = encoder.encode(b);    // Encode the header
+ *                 buffersConsumer.accept(b);
+ *             } while (!encoded);
+ *         }
+ *     }
+ * }
+ * + *

Though the specification does not define how + * an encoder is to be implemented, a default implementation is provided by the + * method {@link #header(CharSequence, CharSequence, boolean)}. + * + *

To provide a custom encoding implementation, {@code Encoder} has to be + * extended. A subclass then can access methods for encoding using specific + * representations (e.g. {@link #literal(int, CharSequence, boolean) literal}, + * {@link #indexed(int) indexed}, etc.) + * + * @apiNote + * + *

An Encoder provides an incremental way of encoding headers. + * {@link #encode(ByteBuffer)} takes a buffer a returns a boolean indicating + * whether, or not, the buffer was sufficiently sized to hold the + * remaining of the encoded representation. + * + *

This way, there's no need to provide a buffer of a specific size, or to + * resize (and copy) the buffer on demand, when the remaining encoded + * representation will not fit in the buffer's remaining space. Instead, an + * array of existing buffers can be used, prepended with a frame that encloses + * the resulting header block afterwards. + * + *

Splitting the encoding operation into header set up and header encoding, + * separates long lived arguments ({@code name}, {@code value}, {@code + * sensitivity}, etc.) from the short lived ones (e.g. {@code buffer}), + * simplifying each operation itself. + * + * @implNote + * + *

The default implementation does not use dynamic table. It reports to a + * coupled Decoder a size update with the value of {@code 0}, and never changes + * it afterwards. + * + * @since 9 + */ +public class Encoder { + + // TODO: enum: no huffman/smart huffman/always huffman + private static final boolean DEFAULT_HUFFMAN = true; + + private final IndexedWriter indexedWriter = new IndexedWriter(); + private final LiteralWriter literalWriter = new LiteralWriter(); + private final LiteralNeverIndexedWriter literalNeverIndexedWriter + = new LiteralNeverIndexedWriter(); + private final LiteralWithIndexingWriter literalWithIndexingWriter + = new LiteralWithIndexingWriter(); + private final SizeUpdateWriter sizeUpdateWriter = new SizeUpdateWriter(); + private final BulkSizeUpdateWriter bulkSizeUpdateWriter + = new BulkSizeUpdateWriter(); + + private BinaryRepresentationWriter writer; + private final HeaderTable headerTable; + + private boolean encoding; + + private int maxCapacity; + private int currCapacity; + private int lastCapacity; + private long minCapacity; + private boolean capacityUpdate; + private boolean configuredCapacityUpdate; + + /** + * Constructs an {@code Encoder} with the specified maximum capacity of the + * header table. + * + *

The value has to be agreed between decoder and encoder out-of-band, + * e.g. by a protocol that uses HPACK (see 4.2. Maximum Table + * Size). + * + * @param maxCapacity + * a non-negative integer + * + * @throws IllegalArgumentException + * if maxCapacity is negative + */ + public Encoder(int maxCapacity) { + if (maxCapacity < 0) { + throw new IllegalArgumentException("maxCapacity >= 0: " + maxCapacity); + } + // Initial maximum capacity update mechanics + minCapacity = Long.MAX_VALUE; + currCapacity = -1; + setMaxCapacity(maxCapacity); + headerTable = new HeaderTable(lastCapacity); + } + + /** + * Sets up the given header {@code (name, value)}. + * + *

Fixates {@code name} and {@code value} for the duration of encoding. + * + * @param name + * the name + * @param value + * the value + * + * @throws NullPointerException + * if any of the arguments are {@code null} + * @throws IllegalStateException + * if the encoder hasn't fully encoded the previous header, or + * hasn't yet started to encode it + * @see #header(CharSequence, CharSequence, boolean) + */ + public void header(CharSequence name, CharSequence value) + throws IllegalStateException { + header(name, value, false); + } + + /** + * Sets up the given header {@code (name, value)} with possibly sensitive + * value. + * + *

Fixates {@code name} and {@code value} for the duration of encoding. + * + * @param name + * the name + * @param value + * the value + * @param sensitive + * whether or not the value is sensitive + * + * @throws NullPointerException + * if any of the arguments are {@code null} + * @throws IllegalStateException + * if the encoder hasn't fully encoded the previous header, or + * hasn't yet started to encode it + * @see #header(CharSequence, CharSequence) + * @see DecodingCallback#onDecoded(CharSequence, CharSequence, boolean) + */ + public void header(CharSequence name, CharSequence value, + boolean sensitive) throws IllegalStateException { + // Arguably a good balance between complexity of implementation and + // efficiency of encoding + requireNonNull(name, "name"); + requireNonNull(value, "value"); + HeaderTable t = getHeaderTable(); + int index = t.indexOf(name, value); + if (index > 0) { + indexed(index); + } else if (index < 0) { + if (sensitive) { + literalNeverIndexed(-index, value, DEFAULT_HUFFMAN); + } else { + literal(-index, value, DEFAULT_HUFFMAN); + } + } else { + if (sensitive) { + literalNeverIndexed(name, DEFAULT_HUFFMAN, value, DEFAULT_HUFFMAN); + } else { + literal(name, DEFAULT_HUFFMAN, value, DEFAULT_HUFFMAN); + } + } + } + + /** + * Sets a maximum capacity of the header table. + * + *

The value has to be agreed between decoder and encoder out-of-band, + * e.g. by a protocol that uses HPACK (see 4.2. Maximum Table + * Size). + * + *

May be called any number of times after or before a complete header + * has been encoded. + * + *

If the encoder decides to change the actual capacity, an update will + * be encoded before a new encoding operation starts. + * + * @param capacity + * a non-negative integer + * + * @throws IllegalArgumentException + * if capacity is negative + * @throws IllegalStateException + * if the encoder hasn't fully encoded the previous header, or + * hasn't yet started to encode it + */ + public void setMaxCapacity(int capacity) { + checkEncoding(); + if (capacity < 0) { + throw new IllegalArgumentException("capacity >= 0: " + capacity); + } + int calculated = calculateCapacity(capacity); + if (calculated < 0 || calculated > capacity) { + throw new IllegalArgumentException( + format("0 <= calculated <= capacity: calculated=%s, capacity=%s", + calculated, capacity)); + } + capacityUpdate = true; + // maxCapacity needs to be updated unconditionally, so the encoder + // always has the newest one (in case it decides to update it later + // unsolicitedly) + // Suppose maxCapacity = 4096, and the encoder has decided to use only + // 2048. It later can choose anything else from the region [0, 4096]. + maxCapacity = capacity; + lastCapacity = calculated; + minCapacity = Math.min(minCapacity, lastCapacity); + } + + protected int calculateCapacity(int maxCapacity) { + // Default implementation of the Encoder won't add anything to the + // table, therefore no need for a table space + return 0; + } + + /** + * Encodes the {@linkplain #header(CharSequence, CharSequence) set up} + * header into the given buffer. + * + *

The encoder writes as much as possible of the header's binary + * representation into the given buffer, starting at the buffer's position, + * and increments its position to reflect the bytes written. The buffer's + * mark and limit will not be modified. + * + *

Once the method has returned {@code true}, the current header is + * deemed encoded. A new header may be set up. + * + * @param headerBlock + * the buffer to encode the header into, may be empty + * + * @return {@code true} if the current header has been fully encoded, + * {@code false} otherwise + * + * @throws NullPointerException + * if the buffer is {@code null} + * @throws ReadOnlyBufferException + * if this buffer is read-only + * @throws IllegalStateException + * if there is no set up header + */ + public final boolean encode(ByteBuffer headerBlock) { + if (!encoding) { + throw new IllegalStateException("A header hasn't been set up"); + } + if (!prependWithCapacityUpdate(headerBlock)) { + return false; + } + boolean done = writer.write(headerTable, headerBlock); + if (done) { + writer.reset(); // FIXME: WHY? + encoding = false; + } + return done; + } + + private boolean prependWithCapacityUpdate(ByteBuffer headerBlock) { + if (capacityUpdate) { + if (!configuredCapacityUpdate) { + List sizes = new LinkedList<>(); + if (minCapacity < currCapacity) { + sizes.add((int) minCapacity); + if (minCapacity != lastCapacity) { + sizes.add(lastCapacity); + } + } else if (lastCapacity != currCapacity) { + sizes.add(lastCapacity); + } + bulkSizeUpdateWriter.maxHeaderTableSizes(sizes); + configuredCapacityUpdate = true; + } + boolean done = bulkSizeUpdateWriter.write(headerTable, headerBlock); + if (done) { + minCapacity = lastCapacity; + currCapacity = lastCapacity; + bulkSizeUpdateWriter.reset(); + capacityUpdate = false; + configuredCapacityUpdate = false; + } + return done; + } + return true; + } + + protected final void indexed(int index) throws IndexOutOfBoundsException { + checkEncoding(); + encoding = true; + writer = indexedWriter.index(index); + } + + protected final void literal(int index, CharSequence value, + boolean useHuffman) + throws IndexOutOfBoundsException { + checkEncoding(); + encoding = true; + writer = literalWriter + .index(index).value(value, useHuffman); + } + + protected final void literal(CharSequence name, boolean nameHuffman, + CharSequence value, boolean valueHuffman) { + checkEncoding(); + encoding = true; + writer = literalWriter + .name(name, nameHuffman).value(value, valueHuffman); + } + + protected final void literalNeverIndexed(int index, + CharSequence value, + boolean valueHuffman) + throws IndexOutOfBoundsException { + checkEncoding(); + encoding = true; + writer = literalNeverIndexedWriter + .index(index).value(value, valueHuffman); + } + + protected final void literalNeverIndexed(CharSequence name, + boolean nameHuffman, + CharSequence value, + boolean valueHuffman) { + checkEncoding(); + encoding = true; + writer = literalNeverIndexedWriter + .name(name, nameHuffman).value(value, valueHuffman); + } + + protected final void literalWithIndexing(int index, + CharSequence value, + boolean valueHuffman) + throws IndexOutOfBoundsException { + checkEncoding(); + encoding = true; + writer = literalWithIndexingWriter + .index(index).value(value, valueHuffman); + } + + protected final void literalWithIndexing(CharSequence name, + boolean nameHuffman, + CharSequence value, + boolean valueHuffman) { + checkEncoding(); + encoding = true; + writer = literalWithIndexingWriter + .name(name, nameHuffman).value(value, valueHuffman); + } + + protected final void sizeUpdate(int capacity) + throws IllegalArgumentException { + checkEncoding(); + // Ensure subclass follows the contract + if (capacity > this.maxCapacity) { + throw new IllegalArgumentException( + format("capacity <= maxCapacity: capacity=%s, maxCapacity=%s", + capacity, maxCapacity)); + } + writer = sizeUpdateWriter.maxHeaderTableSize(capacity); + } + + protected final int getMaxCapacity() { + return maxCapacity; + } + + protected final HeaderTable getHeaderTable() { + return headerTable; + } + + protected final void checkEncoding() { + if (encoding) { + throw new IllegalStateException( + "Previous encoding operation hasn't finished yet"); + } + } +} diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/HeaderTable.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/HeaderTable.java new file mode 100644 index 0000000000000000000000000000000000000000..ab824a3df88b422e2e52b05f5ee1e763d74c1eb9 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/HeaderTable.java @@ -0,0 +1,511 @@ +/* + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.NoSuchElementException; + +import static java.lang.String.format; + +// +// Header Table combined from two tables: static and dynamic. +// +// There is a single address space for index values. Index-aware methods +// correspond to the table as a whole. Size-aware methods only to the dynamic +// part of it. +// +final class HeaderTable { + + private static final HeaderField[] staticTable = { + null, // To make index 1-based, instead of 0-based + new HeaderField(":authority"), + new HeaderField(":method", "GET"), + new HeaderField(":method", "POST"), + new HeaderField(":path", "/"), + new HeaderField(":path", "/index.html"), + new HeaderField(":scheme", "http"), + new HeaderField(":scheme", "https"), + new HeaderField(":status", "200"), + new HeaderField(":status", "204"), + new HeaderField(":status", "206"), + new HeaderField(":status", "304"), + new HeaderField(":status", "400"), + new HeaderField(":status", "404"), + new HeaderField(":status", "500"), + new HeaderField("accept-charset"), + new HeaderField("accept-encoding", "gzip, deflate"), + new HeaderField("accept-language"), + new HeaderField("accept-ranges"), + new HeaderField("accept"), + new HeaderField("access-control-allow-origin"), + new HeaderField("age"), + new HeaderField("allow"), + new HeaderField("authorization"), + new HeaderField("cache-control"), + new HeaderField("content-disposition"), + new HeaderField("content-encoding"), + new HeaderField("content-language"), + new HeaderField("content-length"), + new HeaderField("content-location"), + new HeaderField("content-range"), + new HeaderField("content-type"), + new HeaderField("cookie"), + new HeaderField("date"), + new HeaderField("etag"), + new HeaderField("expect"), + new HeaderField("expires"), + new HeaderField("from"), + new HeaderField("host"), + new HeaderField("if-match"), + new HeaderField("if-modified-since"), + new HeaderField("if-none-match"), + new HeaderField("if-range"), + new HeaderField("if-unmodified-since"), + new HeaderField("last-modified"), + new HeaderField("link"), + new HeaderField("location"), + new HeaderField("max-forwards"), + new HeaderField("proxy-authenticate"), + new HeaderField("proxy-authorization"), + new HeaderField("range"), + new HeaderField("referer"), + new HeaderField("refresh"), + new HeaderField("retry-after"), + new HeaderField("server"), + new HeaderField("set-cookie"), + new HeaderField("strict-transport-security"), + new HeaderField("transfer-encoding"), + new HeaderField("user-agent"), + new HeaderField("vary"), + new HeaderField("via"), + new HeaderField("www-authenticate") + }; + + private static final int STATIC_TABLE_LENGTH = staticTable.length - 1; + private static final int ENTRY_SIZE = 32; + private static final Map> staticIndexes; + + static { + staticIndexes = new HashMap<>(STATIC_TABLE_LENGTH); + for (int i = 1; i <= STATIC_TABLE_LENGTH; i++) { + HeaderField f = staticTable[i]; + Map values = staticIndexes + .computeIfAbsent(f.name, k -> new LinkedHashMap<>()); + values.put(f.value, i); + } + } + + private final Table dynamicTable = new Table(0); + private int maxSize; + private int size; + + public HeaderTable(int maxSize) { + setMaxSize(maxSize); + } + + // + // The method returns: + // + // * a positive integer i where i (i = [1..Integer.MAX_VALUE]) is an + // index of an entry with a header (n, v), where n.equals(name) && + // v.equals(value) + // + // * a negative integer j where j (j = [-Integer.MAX_VALUE..-1]) is an + // index of an entry with a header (n, v), where n.equals(name) + // + // * 0 if there's no entry e such that e.getName().equals(name) + // + // The rationale behind this design is to allow to pack more useful data + // into a single invocation, facilitating a single pass where possible + // (the idea is the same as in java.util.Arrays.binarySearch(int[], int)). + // + public int indexOf(CharSequence name, CharSequence value) { + // Invoking toString() will possibly allocate Strings for the sake of + // the search, which doesn't feel right. + String n = name.toString(); + String v = value.toString(); + + // 1. Try exact match in the static region + Map values = staticIndexes.get(n); + if (values != null) { + Integer idx = values.get(v); + if (idx != null) { + return idx; + } + } + // 2. Try exact match in the dynamic region + int didx = dynamicTable.indexOf(n, v); + if (didx > 0) { + return STATIC_TABLE_LENGTH + didx; + } else if (didx < 0) { + if (values != null) { + // 3. Return name match from the static region + return -values.values().iterator().next(); // Iterator allocation + } else { + // 4. Return name match from the dynamic region + return -STATIC_TABLE_LENGTH + didx; + } + } else { + if (values != null) { + // 3. Return name match from the static region + return -values.values().iterator().next(); // Iterator allocation + } else { + return 0; + } + } + } + + public int size() { + return size; + } + + public int maxSize() { + return maxSize; + } + + public int length() { + return STATIC_TABLE_LENGTH + dynamicTable.size(); + } + + HeaderField get(int index) { + checkIndex(index); + if (index <= STATIC_TABLE_LENGTH) { + return staticTable[index]; + } else { + return dynamicTable.get(index - STATIC_TABLE_LENGTH); + } + } + + void put(CharSequence name, CharSequence value) { + // Invoking toString() will possibly allocate Strings. But that's + // unavoidable at this stage. If a CharSequence is going to be stored in + // the table, it must not be mutable (e.g. for the sake of hashing). + put(new HeaderField(name.toString(), value.toString())); + } + + private void put(HeaderField h) { + int entrySize = sizeOf(h); + while (entrySize > maxSize - size && size != 0) { + evictEntry(); + } + if (entrySize > maxSize - size) { + return; + } + size += entrySize; + dynamicTable.add(h); + } + + void setMaxSize(int maxSize) { + if (maxSize < 0) { + throw new IllegalArgumentException + ("maxSize >= 0: maxSize=" + maxSize); + } + while (maxSize < size && size != 0) { + evictEntry(); + } + this.maxSize = maxSize; + int upperBound = (maxSize / ENTRY_SIZE) + 1; + this.dynamicTable.setCapacity(upperBound); + } + + HeaderField evictEntry() { + HeaderField f = dynamicTable.remove(); + size -= sizeOf(f); + return f; + } + + @Override + public String toString() { + double used = maxSize == 0 ? 0 : 100 * (((double) size) / maxSize); + return format("entries: %d; used %s/%s (%.1f%%)", dynamicTable.size(), + size, maxSize, used); + } + + int checkIndex(int index) { + if (index < 1 || index > STATIC_TABLE_LENGTH + dynamicTable.size()) { + throw new IllegalArgumentException( + format("1 <= index <= length(): index=%s, length()=%s", + index, length())); + } + return index; + } + + int sizeOf(HeaderField f) { + return f.name.length() + f.value.length() + ENTRY_SIZE; + } + + // + // Diagnostic information in the form used in the RFC 7541 + // + String getStateString() { + if (size == 0) { + return "empty."; + } + + StringBuilder b = new StringBuilder(); + for (int i = 1, size = dynamicTable.size(); i <= size; i++) { + HeaderField e = dynamicTable.get(i); + b.append(format("[%3d] (s = %3d) %s: %s\n", i, + sizeOf(e), e.name, e.value)); + } + b.append(format(" Table size:%4s", this.size)); + return b.toString(); + } + + // Convert to a Value Object (JDK-8046159)? + static final class HeaderField { + + final String name; + final String value; + + public HeaderField(String name) { + this(name, ""); + } + + public HeaderField(String name, String value) { + this.name = name; + this.value = value; + } + + @Override + public String toString() { + return value.isEmpty() ? name : name + ": " + value; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + HeaderField that = (HeaderField) o; + return name.equals(that.name) && value.equals(that.value); + } + + @Override + public int hashCode() { + return 31 * (name.hashCode()) + value.hashCode(); + } + } + + // + // In order to be able to find an index of an entry with the given contents + // in the dynamic table an effective inverse mapping is needed. Here's a + // simple idea behind such a mapping. + // + // # The problem: + // + // We have a queue with an O(1) lookup by index: + // + // get: index -> x + // + // What we also want is an O(1) reverse lookup: + // + // indexOf: x -> index + // + // # Solution: + // + // Let's store an inverse mapping as a Map. This have a problem + // that when a new element is added to the queue all indexes in the map + // becomes invalid. Namely, each i becomes shifted by 1 to the right: + // + // i -> i + 1 + // + // And the new element is assigned with an index of 1. This would seem to + // require a pass through the map incrementing all indexes (map values) by + // 1, which is O(n). + // + // The good news is we can do much better then this! + // + // Let's create a single field of type long, called 'counter'. Then each + // time a new element 'x' is added to the queue, a value of this field gets + // incremented. Then the resulting value of the 'counter_x' is then put as a + // value under key 'x' to the map: + // + // map.put(x, counter_x) + // + // It gives us a map that maps an element to a value the counter had at the + // time the element had been added. + // + // In order to retrieve an index of any element 'x' in the queue (at any + // given time) we simply need to subtract the value (the snapshot of the + // counter at the time when the 'x' was added) from the current value of the + // counter. This operation basically answers the question: + // + // How many elements ago 'x' was the tail of the queue? + // + // Which is the same as its index in the queue now. Given, of course, it's + // still in the queue. + // + // I'm pretty sure in a real life long overflow will never happen, so it's + // not too practical to add recalibrating code, but a pedantic person might + // want to do so: + // + // if (counter == Long.MAX_VALUE) { + // recalibrate(); + // } + // + // Where 'recalibrate()' goes through the table doing this: + // + // value -= counter + // + // That's given, of course, the size of the table itself is less than + // Long.MAX_VALUE :-) + // + private static final class Table { + + private final Map> map; + private final CircularBuffer buffer; + private long counter = 1; + + Table(int capacity) { + buffer = new CircularBuffer<>(capacity); + map = new HashMap<>(capacity); + } + + void add(HeaderField f) { + buffer.add(f); + Map values = map.computeIfAbsent(f.name, k -> new HashMap<>()); + values.put(f.value, counter++); + } + + HeaderField get(int index) { + return buffer.get(index - 1); + } + + int indexOf(String name, String value) { + Map values = map.get(name); + if (values == null) { + return 0; + } + Long index = values.get(value); + if (index != null) { + return (int) (counter - index); + } else { + assert !values.isEmpty(); + Long any = values.values().iterator().next(); // Iterator allocation + return -(int) (counter - any); + } + } + + HeaderField remove() { + HeaderField f = buffer.remove(); + Map values = map.get(f.name); + Long index = values.remove(f.value); + assert index != null; + if (values.isEmpty()) { + map.remove(f.name); + } + return f; + } + + int size() { + return buffer.size; + } + + public void setCapacity(int capacity) { + buffer.resize(capacity); + } + } + + // head + // v + // [ ][ ][A][B][C][D][ ][ ][ ] + // ^ + // tail + // + // |<- size ->| (4) + // |<------ capacity ------->| (9) + // + static final class CircularBuffer { + + int tail, head, size, capacity; + Object[] elements; + + CircularBuffer(int capacity) { + this.capacity = capacity; + elements = new Object[capacity]; + } + + void add(E elem) { + if (size == capacity) { + throw new IllegalStateException( + format("No room for '%s': capacity=%s", elem, capacity)); + } + elements[head] = elem; + head = (head + 1) % capacity; + size++; + } + + @SuppressWarnings("unchecked") + E remove() { + if (size == 0) { + throw new NoSuchElementException("Empty"); + } + E elem = (E) elements[tail]; + elements[tail] = null; + tail = (tail + 1) % capacity; + size--; + return elem; + } + + @SuppressWarnings("unchecked") + E get(int index) { + if (index < 0 || index >= size) { + throw new IndexOutOfBoundsException( + format("0 <= index <= capacity: index=%s, capacity=%s", + index, capacity)); + } + int idx = (tail + (size - index - 1)) % capacity; + return (E) elements[idx]; + } + + public void resize(int newCapacity) { + if (newCapacity < size) { + throw new IllegalStateException( + format("newCapacity >= size: newCapacity=%s, size=%s", + newCapacity, size)); + } + + Object[] newElements = new Object[newCapacity]; + + if (tail < head || size == 0) { + System.arraycopy(elements, tail, newElements, 0, size); + } else { + System.arraycopy(elements, tail, newElements, 0, elements.length - tail); + System.arraycopy(elements, 0, newElements, elements.length - tail, head); + } + + elements = newElements; + tail = 0; + head = size; + this.capacity = newCapacity; + } + } +} diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/Huffman.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/Huffman.java new file mode 100644 index 0000000000000000000000000000000000000000..9c58cc3acc2b5f23d19c6d2fc32ac192ecc81921 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/Huffman.java @@ -0,0 +1,676 @@ +/* + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.ByteBuffer; + +import static java.lang.String.format; + +/** + * Huffman coding table. + * + *

Instances of this class are safe for use by multiple threads. + * + * @since 9 + */ +public final class Huffman { + + // TODO: check if reset is done in both reader and writer + + static final class Reader { + + private Node curr; // position in the trie + private int len; // length of the path from the root to 'curr' + private int p; // byte probe + + { + reset(); + } + + public void read(ByteBuffer source, Appendable destination, + boolean isLast) { + read(source, destination, true, isLast); + } + + // Takes 'isLast' rather than returns whether the reading is done or + // not, for more informative exceptions. + void read(ByteBuffer source, Appendable destination, boolean reportEOS, + boolean isLast) { + + Node c = curr; + int l = len; + /* + Since ByteBuffer is itself stateful, its position is + remembered here NOT as a part of Reader's state, + but to set it back in the case of a failure + */ + int pos = source.position(); + + while (source.hasRemaining()) { + int d = source.get(); + for (; p != 0; p >>= 1) { + c = c.getChild(p & d); + l++; + if (c.isLeaf()) { + if (reportEOS && c.isEOSPath) { + throw new IllegalArgumentException("Encountered EOS"); + } + try { + destination.append(c.getChar()); + } catch (RuntimeException | Error e) { + source.position(pos); + throw e; + } catch (IOException e) { + source.position(pos); + throw new UncheckedIOException(e); + } + c = INSTANCE.root; + l = 0; + } + curr = c; + len = l; + } + resetProbe(); + pos++; + } + if (!isLast) { + return; // it's too early to jump to any conclusions, let's wait + } + if (c.isLeaf()) { + return; // it's perfectly ok, no extra padding bits + } + if (c.isEOSPath && len <= 7) { + return; // it's ok, some extra padding bits + } + if (c.isEOSPath) { + throw new IllegalArgumentException( + "Padding is too long (len=" + len + ") " + + "or unexpected end of data"); + } + throw new IllegalArgumentException( + "Not a EOS prefix padding or unexpected end of data"); + } + + public void reset() { + curr = INSTANCE.root; + len = 0; + resetProbe(); + } + + private void resetProbe() { + p = 0x80; + } + } + + static final class Writer { + + private int pos; // position in 'source' + private int avail = 8; // number of least significant bits available in 'curr' + private int curr; // next byte to put to the destination + private int rem; // number of least significant bits in 'code' yet to be processed + private int code; // current code being written + + private CharSequence source; + private int end; + + public Writer from(CharSequence input, int start, int end) { + if (start < 0 || end < 0 || end > input.length() || start > end) { + throw new IndexOutOfBoundsException( + String.format("input.length()=%s, start=%s, end=%s", + input.length(), start, end)); + } + pos = start; + this.end = end; + this.source = input; + return this; + } + + public boolean write(ByteBuffer destination) { + for (; pos < end; pos++) { + if (rem == 0) { + Code desc = INSTANCE.codeOf(source.charAt(pos)); + rem = desc.length; + code = desc.code; + } + while (rem > 0) { + if (rem < avail) { + curr |= (code << (avail - rem)); + avail -= rem; + rem = 0; + } else { + int c = (curr | (code >>> (rem - avail))); + if (destination.hasRemaining()) { + destination.put((byte) c); + } else { + return false; + } + curr = c; + code <<= (32 - rem + avail); // throw written bits off the cliff (is this Sparta?) + code >>>= (32 - rem + avail); // return to the position + rem -= avail; + curr = 0; + avail = 8; + } + } + } + + if (avail < 8) { // have to pad + if (destination.hasRemaining()) { + destination.put((byte) (curr | (INSTANCE.EOS.code >>> (INSTANCE.EOS.length - avail)))); + avail = 8; + } else { + return false; + } + } + + return true; + } + + public Writer reset() { + source = null; + end = -1; + pos = -1; + avail = 8; + curr = 0; + code = 0; + return this; + } + } + + /** + * Shared instance. + */ + public static final Huffman INSTANCE = new Huffman(); + + private final Code EOS = new Code(0x3fffffff, 30); + private final Code[] codes = new Code[257]; + private final Node root = new Node() { + @Override + public String toString() { return "root"; } + }; + + // TODO: consider builder and immutable trie + private Huffman() { + // @formatter:off + addChar(0, 0x1ff8, 13); + addChar(1, 0x7fffd8, 23); + addChar(2, 0xfffffe2, 28); + addChar(3, 0xfffffe3, 28); + addChar(4, 0xfffffe4, 28); + addChar(5, 0xfffffe5, 28); + addChar(6, 0xfffffe6, 28); + addChar(7, 0xfffffe7, 28); + addChar(8, 0xfffffe8, 28); + addChar(9, 0xffffea, 24); + addChar(10, 0x3ffffffc, 30); + addChar(11, 0xfffffe9, 28); + addChar(12, 0xfffffea, 28); + addChar(13, 0x3ffffffd, 30); + addChar(14, 0xfffffeb, 28); + addChar(15, 0xfffffec, 28); + addChar(16, 0xfffffed, 28); + addChar(17, 0xfffffee, 28); + addChar(18, 0xfffffef, 28); + addChar(19, 0xffffff0, 28); + addChar(20, 0xffffff1, 28); + addChar(21, 0xffffff2, 28); + addChar(22, 0x3ffffffe, 30); + addChar(23, 0xffffff3, 28); + addChar(24, 0xffffff4, 28); + addChar(25, 0xffffff5, 28); + addChar(26, 0xffffff6, 28); + addChar(27, 0xffffff7, 28); + addChar(28, 0xffffff8, 28); + addChar(29, 0xffffff9, 28); + addChar(30, 0xffffffa, 28); + addChar(31, 0xffffffb, 28); + addChar(32, 0x14, 6); + addChar(33, 0x3f8, 10); + addChar(34, 0x3f9, 10); + addChar(35, 0xffa, 12); + addChar(36, 0x1ff9, 13); + addChar(37, 0x15, 6); + addChar(38, 0xf8, 8); + addChar(39, 0x7fa, 11); + addChar(40, 0x3fa, 10); + addChar(41, 0x3fb, 10); + addChar(42, 0xf9, 8); + addChar(43, 0x7fb, 11); + addChar(44, 0xfa, 8); + addChar(45, 0x16, 6); + addChar(46, 0x17, 6); + addChar(47, 0x18, 6); + addChar(48, 0x0, 5); + addChar(49, 0x1, 5); + addChar(50, 0x2, 5); + addChar(51, 0x19, 6); + addChar(52, 0x1a, 6); + addChar(53, 0x1b, 6); + addChar(54, 0x1c, 6); + addChar(55, 0x1d, 6); + addChar(56, 0x1e, 6); + addChar(57, 0x1f, 6); + addChar(58, 0x5c, 7); + addChar(59, 0xfb, 8); + addChar(60, 0x7ffc, 15); + addChar(61, 0x20, 6); + addChar(62, 0xffb, 12); + addChar(63, 0x3fc, 10); + addChar(64, 0x1ffa, 13); + addChar(65, 0x21, 6); + addChar(66, 0x5d, 7); + addChar(67, 0x5e, 7); + addChar(68, 0x5f, 7); + addChar(69, 0x60, 7); + addChar(70, 0x61, 7); + addChar(71, 0x62, 7); + addChar(72, 0x63, 7); + addChar(73, 0x64, 7); + addChar(74, 0x65, 7); + addChar(75, 0x66, 7); + addChar(76, 0x67, 7); + addChar(77, 0x68, 7); + addChar(78, 0x69, 7); + addChar(79, 0x6a, 7); + addChar(80, 0x6b, 7); + addChar(81, 0x6c, 7); + addChar(82, 0x6d, 7); + addChar(83, 0x6e, 7); + addChar(84, 0x6f, 7); + addChar(85, 0x70, 7); + addChar(86, 0x71, 7); + addChar(87, 0x72, 7); + addChar(88, 0xfc, 8); + addChar(89, 0x73, 7); + addChar(90, 0xfd, 8); + addChar(91, 0x1ffb, 13); + addChar(92, 0x7fff0, 19); + addChar(93, 0x1ffc, 13); + addChar(94, 0x3ffc, 14); + addChar(95, 0x22, 6); + addChar(96, 0x7ffd, 15); + addChar(97, 0x3, 5); + addChar(98, 0x23, 6); + addChar(99, 0x4, 5); + addChar(100, 0x24, 6); + addChar(101, 0x5, 5); + addChar(102, 0x25, 6); + addChar(103, 0x26, 6); + addChar(104, 0x27, 6); + addChar(105, 0x6, 5); + addChar(106, 0x74, 7); + addChar(107, 0x75, 7); + addChar(108, 0x28, 6); + addChar(109, 0x29, 6); + addChar(110, 0x2a, 6); + addChar(111, 0x7, 5); + addChar(112, 0x2b, 6); + addChar(113, 0x76, 7); + addChar(114, 0x2c, 6); + addChar(115, 0x8, 5); + addChar(116, 0x9, 5); + addChar(117, 0x2d, 6); + addChar(118, 0x77, 7); + addChar(119, 0x78, 7); + addChar(120, 0x79, 7); + addChar(121, 0x7a, 7); + addChar(122, 0x7b, 7); + addChar(123, 0x7ffe, 15); + addChar(124, 0x7fc, 11); + addChar(125, 0x3ffd, 14); + addChar(126, 0x1ffd, 13); + addChar(127, 0xffffffc, 28); + addChar(128, 0xfffe6, 20); + addChar(129, 0x3fffd2, 22); + addChar(130, 0xfffe7, 20); + addChar(131, 0xfffe8, 20); + addChar(132, 0x3fffd3, 22); + addChar(133, 0x3fffd4, 22); + addChar(134, 0x3fffd5, 22); + addChar(135, 0x7fffd9, 23); + addChar(136, 0x3fffd6, 22); + addChar(137, 0x7fffda, 23); + addChar(138, 0x7fffdb, 23); + addChar(139, 0x7fffdc, 23); + addChar(140, 0x7fffdd, 23); + addChar(141, 0x7fffde, 23); + addChar(142, 0xffffeb, 24); + addChar(143, 0x7fffdf, 23); + addChar(144, 0xffffec, 24); + addChar(145, 0xffffed, 24); + addChar(146, 0x3fffd7, 22); + addChar(147, 0x7fffe0, 23); + addChar(148, 0xffffee, 24); + addChar(149, 0x7fffe1, 23); + addChar(150, 0x7fffe2, 23); + addChar(151, 0x7fffe3, 23); + addChar(152, 0x7fffe4, 23); + addChar(153, 0x1fffdc, 21); + addChar(154, 0x3fffd8, 22); + addChar(155, 0x7fffe5, 23); + addChar(156, 0x3fffd9, 22); + addChar(157, 0x7fffe6, 23); + addChar(158, 0x7fffe7, 23); + addChar(159, 0xffffef, 24); + addChar(160, 0x3fffda, 22); + addChar(161, 0x1fffdd, 21); + addChar(162, 0xfffe9, 20); + addChar(163, 0x3fffdb, 22); + addChar(164, 0x3fffdc, 22); + addChar(165, 0x7fffe8, 23); + addChar(166, 0x7fffe9, 23); + addChar(167, 0x1fffde, 21); + addChar(168, 0x7fffea, 23); + addChar(169, 0x3fffdd, 22); + addChar(170, 0x3fffde, 22); + addChar(171, 0xfffff0, 24); + addChar(172, 0x1fffdf, 21); + addChar(173, 0x3fffdf, 22); + addChar(174, 0x7fffeb, 23); + addChar(175, 0x7fffec, 23); + addChar(176, 0x1fffe0, 21); + addChar(177, 0x1fffe1, 21); + addChar(178, 0x3fffe0, 22); + addChar(179, 0x1fffe2, 21); + addChar(180, 0x7fffed, 23); + addChar(181, 0x3fffe1, 22); + addChar(182, 0x7fffee, 23); + addChar(183, 0x7fffef, 23); + addChar(184, 0xfffea, 20); + addChar(185, 0x3fffe2, 22); + addChar(186, 0x3fffe3, 22); + addChar(187, 0x3fffe4, 22); + addChar(188, 0x7ffff0, 23); + addChar(189, 0x3fffe5, 22); + addChar(190, 0x3fffe6, 22); + addChar(191, 0x7ffff1, 23); + addChar(192, 0x3ffffe0, 26); + addChar(193, 0x3ffffe1, 26); + addChar(194, 0xfffeb, 20); + addChar(195, 0x7fff1, 19); + addChar(196, 0x3fffe7, 22); + addChar(197, 0x7ffff2, 23); + addChar(198, 0x3fffe8, 22); + addChar(199, 0x1ffffec, 25); + addChar(200, 0x3ffffe2, 26); + addChar(201, 0x3ffffe3, 26); + addChar(202, 0x3ffffe4, 26); + addChar(203, 0x7ffffde, 27); + addChar(204, 0x7ffffdf, 27); + addChar(205, 0x3ffffe5, 26); + addChar(206, 0xfffff1, 24); + addChar(207, 0x1ffffed, 25); + addChar(208, 0x7fff2, 19); + addChar(209, 0x1fffe3, 21); + addChar(210, 0x3ffffe6, 26); + addChar(211, 0x7ffffe0, 27); + addChar(212, 0x7ffffe1, 27); + addChar(213, 0x3ffffe7, 26); + addChar(214, 0x7ffffe2, 27); + addChar(215, 0xfffff2, 24); + addChar(216, 0x1fffe4, 21); + addChar(217, 0x1fffe5, 21); + addChar(218, 0x3ffffe8, 26); + addChar(219, 0x3ffffe9, 26); + addChar(220, 0xffffffd, 28); + addChar(221, 0x7ffffe3, 27); + addChar(222, 0x7ffffe4, 27); + addChar(223, 0x7ffffe5, 27); + addChar(224, 0xfffec, 20); + addChar(225, 0xfffff3, 24); + addChar(226, 0xfffed, 20); + addChar(227, 0x1fffe6, 21); + addChar(228, 0x3fffe9, 22); + addChar(229, 0x1fffe7, 21); + addChar(230, 0x1fffe8, 21); + addChar(231, 0x7ffff3, 23); + addChar(232, 0x3fffea, 22); + addChar(233, 0x3fffeb, 22); + addChar(234, 0x1ffffee, 25); + addChar(235, 0x1ffffef, 25); + addChar(236, 0xfffff4, 24); + addChar(237, 0xfffff5, 24); + addChar(238, 0x3ffffea, 26); + addChar(239, 0x7ffff4, 23); + addChar(240, 0x3ffffeb, 26); + addChar(241, 0x7ffffe6, 27); + addChar(242, 0x3ffffec, 26); + addChar(243, 0x3ffffed, 26); + addChar(244, 0x7ffffe7, 27); + addChar(245, 0x7ffffe8, 27); + addChar(246, 0x7ffffe9, 27); + addChar(247, 0x7ffffea, 27); + addChar(248, 0x7ffffeb, 27); + addChar(249, 0xffffffe, 28); + addChar(250, 0x7ffffec, 27); + addChar(251, 0x7ffffed, 27); + addChar(252, 0x7ffffee, 27); + addChar(253, 0x7ffffef, 27); + addChar(254, 0x7fffff0, 27); + addChar(255, 0x3ffffee, 26); + addEOS (256, EOS.code, EOS.length); + // @formatter:on + } + + + /** + * Calculates the number of bytes required to represent the given {@code + * CharSequence} with the Huffman coding. + * + * @param value + * characters + * + * @return number of bytes + * + * @throws NullPointerException + * if the value is null + */ + public int lengthOf(CharSequence value) { + return lengthOf(value, 0, value.length()); + } + + /** + * Calculates the number of bytes required to represent a subsequence of the + * given {@code CharSequence} with the Huffman coding. + * + * @param value + * characters + * @param start + * the start index, inclusive + * @param end + * the end index, exclusive + * + * @return number of bytes + * + * @throws NullPointerException + * if the value is null + * @throws IndexOutOfBoundsException + * if any invocation of {@code value.charAt(i)}, where {@code start + * <= i < end} would throw an IndexOutOfBoundsException + */ + public int lengthOf(CharSequence value, int start, int end) { + int len = 0; + for (int i = start; i < end; i++) { + char c = value.charAt(i); + len += INSTANCE.codeOf(c).length; + } + // Integer division with ceiling, assumption: + assert (len / 8 + (len % 8 != 0 ? 1 : 0)) == (len + 7) / 8 : len; + return (len + 7) / 8; + } + + private void addChar(int c, int code, int bitLength) { + addLeaf(c, code, bitLength, false); + codes[c] = new Code(code, bitLength); + } + + private void addEOS(int c, int code, int bitLength) { + addLeaf(c, code, bitLength, true); + codes[c] = new Code(code, bitLength); + } + + private void addLeaf(int c, int code, int bitLength, boolean isEOS) { + if (bitLength < 1) { + throw new IllegalArgumentException("bitLength < 1"); + } + Node curr = root; + for (int p = 1 << bitLength - 1; p != 0 && !curr.isLeaf(); p = p >> 1) { + curr.isEOSPath |= isEOS; // If it's already true, it can't become false + curr = curr.addChildIfAbsent(p & code); + } + curr.isEOSPath |= isEOS; // The last one needs to have this property as well + if (curr.isLeaf()) { + throw new IllegalStateException("Specified code is already taken"); + } + curr.setChar((char) c); + } + + private Code codeOf(char c) { + if (c > 255) { + throw new IllegalArgumentException("char=" + ((int) c)); + } + return codes[c]; + } + + // + // For debugging/testing purposes + // + Node getRoot() { + return root; + } + + // + // Guarantees: + // + // if (isLeaf() == true) => getChar() is a legal call + // if (isLeaf() == false) => getChild(i) is a legal call (though it can + // return null) + // + static class Node { + + Node left; + Node right; + boolean isEOSPath; + + boolean charIsSet; + char c; + + Node getChild(int selector) { + if (isLeaf()) { + throw new IllegalStateException("This is a leaf node"); + } + Node result = selector == 0 ? left : right; + if (result == null) { + throw new IllegalStateException(format( + "Node doesn't have a child (selector=%s)", selector)); + } + return result; + } + + boolean isLeaf() { + return charIsSet; + } + + char getChar() { + if (!isLeaf()) { + throw new IllegalStateException("This node is not a leaf node"); + } + return c; + } + + void setChar(char c) { + if (charIsSet) { + throw new IllegalStateException( + "This node has been taken already"); + } + if (left != null || right != null) { + throw new IllegalStateException("The node cannot be made " + + "a leaf as it's already has a child"); + } + this.c = c; + charIsSet = true; + } + + Node addChildIfAbsent(int i) { + if (charIsSet) { + throw new IllegalStateException("The node cannot have a child " + + "as it's already a leaf node"); + } + Node child; + if (i == 0) { + if ((child = left) == null) { + child = left = new Node(); + } + } else { + if ((child = right) == null) { + child = right = new Node(); + } + } + return child; + } + + @Override + public String toString() { + if (isLeaf()) { + if (isEOSPath) { + return "EOS"; + } else { + return format("char: (%3s) '%s'", (int) c, c); + } + } + return "/\\"; + } + } + + // TODO: value-based class? + // FIXME: can we re-use Node instead of this class? + private static final class Code { + + final int code; + final int length; + + private Code(int code, int length) { + this.code = code; + this.length = length; + } + + public int getCode() { + return code; + } + + public int getLength() { + return length; + } + + @Override + public String toString() { + long p = 1 << length; + return Long.toBinaryString(code + p).substring(1) + + ", length=" + length; + } + } +} diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/ISO_8859_1.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/ISO_8859_1.java new file mode 100644 index 0000000000000000000000000000000000000000..162c9839ae91d0df7b9e6cf9312ea253a0d40d51 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/ISO_8859_1.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.ByteBuffer; + +// +// Custom implementation of ISO/IEC 8859-1:1998 +// +// The rationale behind this is not to deal with CharsetEncoder/CharsetDecoder, +// basically because it would require wrapping every single CharSequence into a +// CharBuffer and then copying it back. +// +// But why not to give a CharBuffer instead of Appendable? Because I can choose +// an Appendable (e.g. StringBuilder) that adjusts its length when needed and +// therefore not to deal with pre-sized CharBuffers or copying. +// +// The encoding is simple and well known: 1 byte <-> 1 char +// +final class ISO_8859_1 { + + private ISO_8859_1() { } + + public static final class Reader { + + public void read(ByteBuffer source, Appendable destination) { + for (int i = 0, len = source.remaining(); i < len; i++) { + char c = (char) (source.get() & 0xff); + try { + destination.append(c); + } catch (IOException e) { + throw new UncheckedIOException + ("Error appending to the destination", e); + } + } + } + + public Reader reset() { + return this; + } + } + + public static final class Writer { + + private CharSequence source; + private int pos; + private int end; + + public Writer configure(CharSequence source, int start, int end) { + this.source = source; + this.pos = start; + this.end = end; + return this; + } + + public boolean write(ByteBuffer destination) { + for (; pos < end; pos++) { + char c = source.charAt(pos); + if (c > '\u00FF') { + throw new IllegalArgumentException( + "Illegal ISO-8859-1 char: " + (int) c); + } + if (destination.hasRemaining()) { + destination.put((byte) c); + } else { + return false; + } + } + return true; + } + + public Writer reset() { + source = null; + pos = -1; + end = -1; + return this; + } + } +} diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/IndexNameValueWriter.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/IndexNameValueWriter.java new file mode 100644 index 0000000000000000000000000000000000000000..01b4decca00f278538bf8fc250b2397d4d354d50 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/IndexNameValueWriter.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import java.nio.ByteBuffer; + +abstract class IndexNameValueWriter implements BinaryRepresentationWriter { + + private final int pattern; + private final int prefix; + private final IntegerWriter intWriter = new IntegerWriter(); + private final StringWriter nameWriter = new StringWriter(); + private final StringWriter valueWriter = new StringWriter(); + + protected boolean indexedRepresentation; + + private static final int NEW = 0; + private static final int NAME_PART_WRITTEN = 1; + private static final int VALUE_WRITTEN = 2; + + private int state = NEW; + + protected IndexNameValueWriter(int pattern, int prefix) { + this.pattern = pattern; + this.prefix = prefix; + } + + IndexNameValueWriter index(int index) { + indexedRepresentation = true; + intWriter.configure(index, prefix, pattern); + return this; + } + + IndexNameValueWriter name(CharSequence name, boolean useHuffman) { + indexedRepresentation = false; + intWriter.configure(0, prefix, pattern); + nameWriter.configure(name, useHuffman); + return this; + } + + IndexNameValueWriter value(CharSequence value, boolean useHuffman) { + valueWriter.configure(value, useHuffman); + return this; + } + + @Override + public boolean write(HeaderTable table, ByteBuffer destination) { + if (state < NAME_PART_WRITTEN) { + if (indexedRepresentation) { + if (!intWriter.write(destination)) { + return false; + } + } else { + if (!intWriter.write(destination) || !nameWriter.write(destination)) { + return false; + } + } + state = NAME_PART_WRITTEN; + } + if (state < VALUE_WRITTEN) { + if (!valueWriter.write(destination)) { + return false; + } + state = VALUE_WRITTEN; + } + return state == VALUE_WRITTEN; + } + + @Override + public IndexNameValueWriter reset() { + intWriter.reset(); + if (!indexedRepresentation) { + nameWriter.reset(); + } + valueWriter.reset(); + state = NEW; + return this; + } +} diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/IndexedWriter.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/IndexedWriter.java new file mode 100644 index 0000000000000000000000000000000000000000..4ccd9d76112955990511bebb0cf4c83fe2d1225d --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/IndexedWriter.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import java.nio.ByteBuffer; + +final class IndexedWriter implements BinaryRepresentationWriter { + + private final IntegerWriter intWriter = new IntegerWriter(); + + IndexedWriter() { } + + IndexedWriter index(int index) { + intWriter.configure(index, 7, 0b1000_0000); + return this; + } + + @Override + public boolean write(HeaderTable table, ByteBuffer destination) { + return intWriter.write(destination); + } + + @Override + public BinaryRepresentationWriter reset() { + intWriter.reset(); + return this; + } +} diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/IntegerReader.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/IntegerReader.java new file mode 100644 index 0000000000000000000000000000000000000000..0e7abcfd2f5aa06360fca4f7577858944109792d --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/IntegerReader.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import java.nio.ByteBuffer; +import java.util.Arrays; + +import static java.lang.String.format; + +final class IntegerReader { + + private static final int NEW = 0; + private static final int CONFIGURED = 1; + private static final int FIRST_BYTE_READ = 2; + private static final int DONE = 4; + + private int state = NEW; + + private int N; + private int maxValue; + private int value; + private long r; + private long b = 1; + + public IntegerReader configure(int N) { + return configure(N, Integer.MAX_VALUE); + } + + // + // Why is it important to configure 'maxValue' here. After all we can wait + // for the integer to be fully read and then check it. Can't we? + // + // Two reasons. + // + // 1. Value wraps around long won't be unnoticed. + // 2. It can spit out an exception as soon as it becomes clear there's + // an overflow. Therefore, no need to wait for the value to be fully read. + // + public IntegerReader configure(int N, int maxValue) { + if (state != NEW) { + throw new IllegalStateException("Already configured"); + } + checkPrefix(N); + if (maxValue < 0) { + throw new IllegalArgumentException( + "maxValue >= 0: maxValue=" + maxValue); + } + this.maxValue = maxValue; + this.N = N; + state = CONFIGURED; + return this; + } + + public boolean read(ByteBuffer input) { + if (state == NEW) { + throw new IllegalStateException("Configure first"); + } + if (state == DONE) { + return true; + } + if (!input.hasRemaining()) { + return false; + } + if (state == CONFIGURED) { + int max = (2 << (N - 1)) - 1; + int n = input.get() & max; + if (n != max) { + value = n; + state = DONE; + return true; + } else { + r = max; + } + state = FIRST_BYTE_READ; + } + if (state == FIRST_BYTE_READ) { + // variable-length quantity (VLQ) + byte i; + do { + if (!input.hasRemaining()) { + return false; + } + i = input.get(); + long increment = b * (i & 127); + if (r + increment > maxValue) { + throw new IllegalArgumentException(format( + "Integer overflow: maxValue=%,d, value=%,d", + maxValue, r + increment)); + } + r += increment; + b *= 128; + } while ((128 & i) == 128); + + value = (int) r; + state = DONE; + return true; + } + throw new InternalError(Arrays.toString( + new Object[]{state, N, maxValue, value, r, b})); + } + + public int get() throws IllegalStateException { + if (state != DONE) { + throw new IllegalStateException("Has not been fully read yet"); + } + return value; + } + + private static void checkPrefix(int N) { + if (N < 1 || N > 8) { + throw new IllegalArgumentException("1 <= N <= 8: N= " + N); + } + } + + public IntegerReader reset() { + b = 1; + state = NEW; + return this; + } +} diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/IntegerWriter.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/IntegerWriter.java new file mode 100644 index 0000000000000000000000000000000000000000..7fd1c108ab329ecdea77cde10b58076ec38f3d38 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/IntegerWriter.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import java.nio.ByteBuffer; +import java.util.Arrays; + +final class IntegerWriter { + + private static final int NEW = 0; + private static final int CONFIGURED = 1; + private static final int FIRST_BYTE_WRITTEN = 2; + private static final int DONE = 4; + + private int state = NEW; + + private int payload; + private int N; + private int value; + + // + // 0 1 2 3 4 5 6 7 + // +---+---+---+---+---+---+---+---+ + // | | | | | | | | | + // +---+---+---+-------------------+ + // |<--------->|<----------------->| + // payload N=5 + // + // payload is the contents of the left-hand side part of the octet; + // it is truncated to fit into 8-N bits, where 1 <= N <= 8; + // + public IntegerWriter configure(int value, int N, int payload) { + if (state != NEW) { + throw new IllegalStateException("Already configured"); + } + if (value < 0) { + throw new IllegalArgumentException("value >= 0: value=" + value); + } + checkPrefix(N); + this.value = value; + this.N = N; + this.payload = payload & 0xFF & (0xFFFFFFFF << N); + state = CONFIGURED; + return this; + } + + public boolean write(ByteBuffer output) { + if (state == NEW) { + throw new IllegalStateException("Configure first"); + } + if (state == DONE) { + return true; + } + + if (!output.hasRemaining()) { + return false; + } + if (state == CONFIGURED) { + int max = (2 << (N - 1)) - 1; + if (value < max) { + output.put((byte) (payload | value)); + state = DONE; + return true; + } + output.put((byte) (payload | max)); + value -= max; + state = FIRST_BYTE_WRITTEN; + } + if (state == FIRST_BYTE_WRITTEN) { + while (value >= 128 && output.hasRemaining()) { + output.put((byte) (value % 128 + 128)); + value /= 128; + } + if (!output.hasRemaining()) { + return false; + } + output.put((byte) value); + state = DONE; + return true; + } + throw new InternalError(Arrays.toString( + new Object[]{state, payload, N, value})); + } + + private static void checkPrefix(int N) { + if (N < 1 || N > 8) { + throw new IllegalArgumentException("1 <= N <= 8: N= " + N); + } + } + + public IntegerWriter reset() { + state = NEW; + return this; + } +} diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/LiteralNeverIndexedWriter.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/LiteralNeverIndexedWriter.java new file mode 100644 index 0000000000000000000000000000000000000000..92547ca13a98f175312b9f80dda1e74d6b4f678a --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/LiteralNeverIndexedWriter.java @@ -0,0 +1,32 @@ +/* + * 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 sun.net.httpclient.hpack; + +final class LiteralNeverIndexedWriter extends IndexNameValueWriter { + + LiteralNeverIndexedWriter() { + super(0b0001_0000, 4); + } +} diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/LiteralWithIndexingWriter.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/LiteralWithIndexingWriter.java new file mode 100644 index 0000000000000000000000000000000000000000..5926bd6820eaa2c4b2db0068162ada3a799d7a94 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/LiteralWithIndexingWriter.java @@ -0,0 +1,85 @@ +/* + * 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 sun.net.httpclient.hpack; + +import java.nio.ByteBuffer; + +final class LiteralWithIndexingWriter extends IndexNameValueWriter { + + private boolean tableUpdated; + + private CharSequence name; + private CharSequence value; + private int index; + + LiteralWithIndexingWriter() { + super(0b0100_0000, 6); + } + + @Override + LiteralWithIndexingWriter index(int index) { + super.index(index); + this.index = index; + return this; + } + + @Override + LiteralWithIndexingWriter name(CharSequence name, boolean useHuffman) { + super.name(name, useHuffman); + this.name = name; + return this; + } + + @Override + LiteralWithIndexingWriter value(CharSequence value, boolean useHuffman) { + super.value(value, useHuffman); + this.value = value; + return this; + } + + @Override + public boolean write(HeaderTable table, ByteBuffer destination) { + if (!tableUpdated) { + CharSequence n; + if (indexedRepresentation) { + n = table.get(index).name; + } else { + n = name; + } + table.put(n, value); + tableUpdated = true; + } + return super.write(table, destination); + } + + @Override + public IndexNameValueWriter reset() { + tableUpdated = false; + name = null; + value = null; + index = -1; + return super.reset(); + } +} diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/LiteralWriter.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/LiteralWriter.java new file mode 100644 index 0000000000000000000000000000000000000000..430dac4a384d9f8cd80e31ab0663bd69ce4aa39f --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/LiteralWriter.java @@ -0,0 +1,32 @@ +/* + * 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 sun.net.httpclient.hpack; + +final class LiteralWriter extends IndexNameValueWriter { + + LiteralWriter() { + super(0b0000_0000, 4); + } +} diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/SizeUpdateWriter.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/SizeUpdateWriter.java new file mode 100644 index 0000000000000000000000000000000000000000..5148afeeddc611e2bc85c365b22df0409cfc6bcd --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/SizeUpdateWriter.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import java.nio.ByteBuffer; + +final class SizeUpdateWriter implements BinaryRepresentationWriter { + + private final IntegerWriter intWriter = new IntegerWriter(); + private int maxSize; + private boolean tableUpdated; + + SizeUpdateWriter() { } + + SizeUpdateWriter maxHeaderTableSize(int size) { + intWriter.configure(size, 5, 0b0010_0000); + this.maxSize = size; + return this; + } + + @Override + public boolean write(HeaderTable table, ByteBuffer destination) { + if (!tableUpdated) { + table.setMaxSize(maxSize); + tableUpdated = true; + } + return intWriter.write(destination); + } + + @Override + public BinaryRepresentationWriter reset() { + intWriter.reset(); + maxSize = -1; + tableUpdated = false; + return this; + } +} diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/StringReader.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/StringReader.java new file mode 100644 index 0000000000000000000000000000000000000000..e2bbefb147350c0e69e86aec81f48545205cbb25 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/StringReader.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import java.nio.ByteBuffer; +import java.util.Arrays; + +// +// 0 1 2 3 4 5 6 7 +// +---+---+---+---+---+---+---+---+ +// | H | String Length (7+) | +// +---+---------------------------+ +// | String Data (Length octets) | +// +-------------------------------+ +// +final class StringReader { + + private static final int NEW = 0; + private static final int FIRST_BYTE_READ = 1; + private static final int LENGTH_READ = 2; + private static final int DONE = 4; + + private final IntegerReader intReader = new IntegerReader(); + private final Huffman.Reader huffmanReader = new Huffman.Reader(); + private final ISO_8859_1.Reader plainReader = new ISO_8859_1.Reader(); + + private int state = NEW; + + private boolean huffman; + private int remainingLength; + + boolean read(ByteBuffer input, Appendable output) { + if (state == DONE) { + return true; + } + if (!input.hasRemaining()) { + return false; + } + if (state == NEW) { + int p = input.position(); + huffman = (input.get(p) & 0b10000000) != 0; + state = FIRST_BYTE_READ; + intReader.configure(7); + } + if (state == FIRST_BYTE_READ) { + boolean lengthRead = intReader.read(input); + if (!lengthRead) { + return false; + } + remainingLength = intReader.get(); + state = LENGTH_READ; + } + if (state == LENGTH_READ) { + boolean isLast = input.remaining() >= remainingLength; + int oldLimit = input.limit(); + if (isLast) { + input.limit(input.position() + remainingLength); + } + if (huffman) { + huffmanReader.read(input, output, isLast); + } else { + plainReader.read(input, output); + } + if (isLast) { + input.limit(oldLimit); + } + return isLast; + } + throw new InternalError(Arrays.toString( + new Object[]{state, huffman, remainingLength})); + } + + boolean isHuffmanEncoded() { + if (state < FIRST_BYTE_READ) { + throw new IllegalStateException("Has not been fully read yet"); + } + return huffman; + } + + void reset() { + if (huffman) { + huffmanReader.reset(); + } else { + plainReader.reset(); + } + intReader.reset(); + state = NEW; + } +} diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/StringWriter.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/StringWriter.java new file mode 100644 index 0000000000000000000000000000000000000000..5c58e3710820fcd10f064927ac0fde6ad76eeca4 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/StringWriter.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import java.nio.ByteBuffer; +import java.util.Arrays; + +// +// 0 1 2 3 4 5 6 7 +// +---+---+---+---+---+---+---+---+ +// | H | String Length (7+) | +// +---+---------------------------+ +// | String Data (Length octets) | +// +-------------------------------+ +// +// StringWriter does not require a notion of endOfInput (isLast) in 'write' +// methods due to the nature of string representation in HPACK. Namely, the +// length of the string is put before string's contents. Therefore the length is +// always known beforehand. +// +// Expected use: +// +// configure write* (reset configure write*)* +// +final class StringWriter { + + private static final int NEW = 0; + private static final int CONFIGURED = 1; + private static final int LENGTH_WRITTEN = 2; + private static final int DONE = 4; + + private final IntegerWriter intWriter = new IntegerWriter(); + private final Huffman.Writer huffmanWriter = new Huffman.Writer(); + private final ISO_8859_1.Writer plainWriter = new ISO_8859_1.Writer(); + + private int state = NEW; + private boolean huffman; + + StringWriter configure(CharSequence input, boolean huffman) { + return configure(input, 0, input.length(), huffman); + } + + StringWriter configure(CharSequence input, int start, int end, + boolean huffman) { + if (start < 0 || end < 0 || end > input.length() || start > end) { + throw new IndexOutOfBoundsException( + String.format("input.length()=%s, start=%s, end=%s", + input.length(), start, end)); + } + if (!huffman) { + plainWriter.configure(input, start, end); + intWriter.configure(end - start, 7, 0b0000_0000); + } else { + huffmanWriter.from(input, start, end); + intWriter.configure(Huffman.INSTANCE.lengthOf(input, start, end), + 7, 0b1000_0000); + } + + this.huffman = huffman; + state = CONFIGURED; + return this; + } + + boolean write(ByteBuffer output) { + if (state == DONE) { + return true; + } + if (state == NEW) { + throw new IllegalStateException("Configure first"); + } + if (!output.hasRemaining()) { + return false; + } + if (state == CONFIGURED) { + if (intWriter.write(output)) { + state = LENGTH_WRITTEN; + } else { + return false; + } + } + if (state == LENGTH_WRITTEN) { + boolean written = huffman + ? huffmanWriter.write(output) + : plainWriter.write(output); + if (written) { + state = DONE; + return true; + } else { + return false; + } + } + throw new InternalError(Arrays.toString(new Object[]{state, huffman})); + } + + void reset() { + intWriter.reset(); + if (huffman) { + huffmanWriter.reset(); + } else { + plainWriter.reset(); + } + state = NEW; + } +} diff --git a/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/package-info.java b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/package-info.java new file mode 100644 index 0000000000000000000000000000000000000000..5c035ff466249f297f8cabe0e011674836bb1465 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/sun/net/httpclient/hpack/package-info.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * 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. + */ +/** + * HPACK (Header Compression for HTTP/2) implementation conforming to + * RFC 7541. + * + *

Headers can be decoded and encoded by {@link sun.net.httpclient.hpack.Decoder} + * and {@link sun.net.httpclient.hpack.Encoder} respectively. + * + *

Instances of these classes are not safe for use by multiple threads. + */ +package sun.net.httpclient.hpack; diff --git a/jdk/src/java.logging/share/classes/java/util/logging/LogManager.java b/jdk/src/java.logging/share/classes/java/util/logging/LogManager.java index 81f3387be8c2ab940768e709a3c27198a4e4b044..e15add5a4f84fdba38f1f9cd93052b5ad55fce38 100644 --- a/jdk/src/java.logging/share/classes/java/util/logging/LogManager.java +++ b/jdk/src/java.logging/share/classes/java/util/logging/LogManager.java @@ -42,7 +42,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import jdk.internal.misc.JavaAWTAccess; import jdk.internal.misc.SharedSecrets; -import sun.misc.ManagedLocalsThread; import sun.util.logging.internal.LoggingProviderImpl; /** @@ -254,9 +253,10 @@ public class LogManager { // This private class is used as a shutdown hook. // It does a "reset" to close all open handlers. - private class Cleaner extends ManagedLocalsThread { + private class Cleaner extends Thread { private Cleaner() { + super(null, null, "Logging-Cleaner", 0, false); /* Set context class loader to null in order to avoid * keeping a strong reference to an application classloader. */ diff --git a/jdk/src/java.logging/share/classes/module-info.java b/jdk/src/java.logging/share/classes/module-info.java index 0deda7677b5dea370b4eaa4de3eeecd0507a7922..47456e5ef5ba10cd2a7027ac815c446724d3854b 100644 --- a/jdk/src/java.logging/share/classes/module-info.java +++ b/jdk/src/java.logging/share/classes/module-info.java @@ -24,8 +24,6 @@ */ module java.logging { - // 8153158 - requires jdk.unsupported; exports java.util.logging; provides jdk.internal.logger.DefaultLoggerFinder with sun.util.logging.internal.LoggingProviderImpl; diff --git a/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ClientCommunicatorAdmin.java b/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ClientCommunicatorAdmin.java index 85f248311cb4d7fb7ff55034cfefc2760efdf8b5..5df5c2437828c454681a23603322152587e83f1a 100644 --- a/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ClientCommunicatorAdmin.java +++ b/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ClientCommunicatorAdmin.java @@ -30,7 +30,6 @@ import java.io.InterruptedIOException; import com.sun.jmx.remote.util.ClassLogger; import com.sun.jmx.remote.util.EnvHelp; -import sun.misc.ManagedLocalsThread; public abstract class ClientCommunicatorAdmin { private static volatile long threadNo = 1; @@ -41,10 +40,11 @@ public abstract class ClientCommunicatorAdmin { if (period > 0) { checker = new Checker(); - Thread t = new ManagedLocalsThread( - checker, - "JMX client heartbeat " + (++threadNo) - ); + Thread t = new Thread(null, + checker, + "JMX client heartbeat " + (++threadNo), + 0, + false); t.setDaemon(true); t.start(); diff --git a/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java b/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java index 05abd0ceeb569ce16e0f0466f29a1ee1c3354f7f..e0860f8e1f0f95c29eae29c3932d162b8b398813 100644 --- a/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java +++ b/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java @@ -52,7 +52,6 @@ import javax.management.remote.TargetedNotification; import com.sun.jmx.remote.util.ClassLogger; import com.sun.jmx.remote.util.EnvHelp; import java.rmi.UnmarshalException; -import sun.misc.ManagedLocalsThread; public abstract class ClientNotifForwarder { @@ -91,7 +90,8 @@ public abstract class ClientNotifForwarder { throw new IllegalArgumentException("More than one command"); this.command = command; if (thread == null) { - thread = new ManagedLocalsThread( + thread = new Thread( + null, ()-> { while (true) { Runnable r; @@ -107,7 +107,9 @@ public abstract class ClientNotifForwarder { r.run(); } }, - "ClientNotifForwarder-" + ++threadId + "ClientNotifForwarder-" + ++threadId, + 0, + false ); thread.setDaemon(true); thread.start(); diff --git a/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ServerCommunicatorAdmin.java b/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ServerCommunicatorAdmin.java index 6df86f5931be58503048d95f8b7aeece5504c162..74fbbd4c329e2bb2bac14595a2f76adb33a3662a 100644 --- a/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ServerCommunicatorAdmin.java +++ b/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ServerCommunicatorAdmin.java @@ -27,7 +27,6 @@ package com.sun.jmx.remote.internal; import com.sun.jmx.remote.util.ClassLogger; -import sun.misc.ManagedLocalsThread; public abstract class ServerCommunicatorAdmin { public ServerCommunicatorAdmin(long timeout) { @@ -42,7 +41,11 @@ public abstract class ServerCommunicatorAdmin { timestamp = 0; if (timeout < Long.MAX_VALUE) { Runnable timeoutTask = new Timeout(); - final Thread t = new ManagedLocalsThread(timeoutTask); + final Thread t = new Thread(null, + timeoutTask, + "JMX-Server-Admin-Timeout", + 0, + false); t.setName("JMX server connection timeout " + t.getId()); // If you change this name you will need to change a unit test // (NoServerTimeoutTest) diff --git a/jdk/src/java.management/share/classes/javax/management/monitor/Monitor.java b/jdk/src/java.management/share/classes/javax/management/monitor/Monitor.java index 6276fb33b509be67b920235a5f321a26a3dc40bc..eb2a59ac14ab297caa4587c0eaad06098093ddf3 100644 --- a/jdk/src/java.management/share/classes/javax/management/monitor/Monitor.java +++ b/jdk/src/java.management/share/classes/javax/management/monitor/Monitor.java @@ -61,7 +61,6 @@ import javax.management.NotificationBroadcasterSupport; import javax.management.ObjectName; import javax.management.ReflectionException; import static javax.management.monitor.MonitorNotification.*; -import sun.misc.ManagedLocalsThread; /** * Defines the part common to all monitor MBeans. @@ -1637,10 +1636,12 @@ public abstract class Monitor } public Thread newThread(Runnable r) { - Thread t = new ManagedLocalsThread( + Thread t = new Thread( group, r, - namePrefix + threadNumber.getAndIncrement() + nameSuffix + namePrefix + threadNumber.getAndIncrement() + nameSuffix, + 0, + false ); t.setDaemon(true); diff --git a/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIConnectorServer.java b/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIConnectorServer.java index fe90422c1937c059a589c9e522dca93522fd69c3..a71bef5b4035f289695ee337d357a407cedb70be 100644 --- a/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIConnectorServer.java +++ b/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIConnectorServer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,6 +45,7 @@ import java.util.Set; import javax.management.InstanceNotFoundException; import javax.management.MBeanServer; +import javax.management.remote.JMXAuthenticator; import javax.management.remote.JMXConnectionNotification; import javax.management.remote.JMXConnector; @@ -99,6 +100,21 @@ public class RMIConnectorServer extends JMXConnectorServer { public static final String RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE = "jmx.remote.rmi.server.socket.factory"; + /** + * Name of the attribute that specifies a list of class names acceptable + * as parameters to the {@link RMIServer#newClient(java.lang.Object) RMIServer.newClient()} + * remote method call. + *

+ * This list of classes should correspond to the transitive closure of the + * credentials class (or classes) used by the installed {@linkplain JMXAuthenticator} + * associated with the {@linkplain RMIServer} implementation. + *

+ * If the attribute is not set, or is null, then any class is + * deemed acceptable. + */ + public static final String CREDENTIAL_TYPES = + "jmx.remote.rmi.server.credential.types"; + /** *

Makes an RMIConnectorServer. * This is equivalent to calling {@link #RMIConnectorServer( diff --git a/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIJRMPServerImpl.java b/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIJRMPServerImpl.java index 0e45c966c9c1c1f667f0fc8adf3b2f757fd66b76..838c092ca4878729fe93eeee2e4f822f31a8b158 100644 --- a/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIJRMPServerImpl.java +++ b/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIJRMPServerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,13 @@ import javax.security.auth.Subject; import com.sun.jmx.remote.internal.RMIExporter; import com.sun.jmx.remote.util.EnvHelp; +import java.io.ObjectStreamClass; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import sun.reflect.misc.ReflectUtil; +import sun.rmi.server.DeserializationChecker; import sun.rmi.server.UnicastServerRef; import sun.rmi.server.UnicastServerRef2; @@ -52,6 +59,9 @@ import sun.rmi.server.UnicastServerRef2; * @since 1.5 */ public class RMIJRMPServerImpl extends RMIServerImpl { + + private final ExportedWrapper exportedWrapper; + /** *

Creates a new {@link RMIServer} object that will be exported * on the given port using the given socket factories.

@@ -89,10 +99,31 @@ public class RMIJRMPServerImpl extends RMIServerImpl { this.csf = csf; this.ssf = ssf; this.env = (env == null) ? Collections.emptyMap() : env; + + String[] credentialsTypes + = (String[]) this.env.get(RMIConnectorServer.CREDENTIAL_TYPES); + List types = null; + if (credentialsTypes != null) { + types = new ArrayList<>(); + for (String type : credentialsTypes) { + if (type == null) { + throw new IllegalArgumentException("A credential type is null."); + } + ReflectUtil.checkPackageAccess(type); + types.add(type); + } + } + exportedWrapper = types != null ? + new ExportedWrapper(this, types) : + null; } protected void export() throws IOException { - export(this); + if (exportedWrapper != null) { + export(exportedWrapper); + } else { + export(this); + } } private void export(Remote obj) throws RemoteException { @@ -142,7 +173,11 @@ public class RMIJRMPServerImpl extends RMIServerImpl { * RMIJRMPServerImpl has not been exported yet. */ public Remote toStub() throws IOException { - return RemoteObject.toStub(this); + if (exportedWrapper != null) { + return RemoteObject.toStub(exportedWrapper); + } else { + return RemoteObject.toStub(this); + } } /** @@ -189,11 +224,56 @@ public class RMIJRMPServerImpl extends RMIServerImpl { * server failed. */ protected void closeServer() throws IOException { - unexport(this, true); + if (exportedWrapper != null) { + unexport(exportedWrapper, true); + } else { + unexport(this, true); + } } private final int port; private final RMIClientSocketFactory csf; private final RMIServerSocketFactory ssf; private final Map env; + + private static class ExportedWrapper implements RMIServer, DeserializationChecker { + private final RMIServer impl; + private final List allowedTypes; + + private ExportedWrapper(RMIServer impl, List credentialsTypes) { + this.impl = impl; + allowedTypes = credentialsTypes; + } + + @Override + public String getVersion() throws RemoteException { + return impl.getVersion(); + } + + @Override + public RMIConnection newClient(Object credentials) throws IOException { + return impl.newClient(credentials); + } + + @Override + public void check(Method method, ObjectStreamClass descriptor, + int paramIndex, int callID) { + String type = descriptor.getName(); + if (!allowedTypes.contains(type)) { + throw new ClassCastException("Unsupported type: " + type); + } + } + + @Override + public void checkProxyClass(Method method, String[] ifaces, + int paramIndex, int callID) { + if (ifaces != null && ifaces.length > 0) { + for (String iface : ifaces) { + if (!allowedTypes.contains(iface)) { + throw new ClassCastException("Unsupported type: " + iface); + } + } + } + } + } } diff --git a/jdk/src/java.management/share/classes/module-info.java b/jdk/src/java.management/share/classes/module-info.java index 811c2de91bd85df90f2818fbf93dabd89457a7f8..8f7bd1b909e59fd4ccc6ad4f38ea0afa919acc63 100644 --- a/jdk/src/java.management/share/classes/module-info.java +++ b/jdk/src/java.management/share/classes/module-info.java @@ -27,8 +27,6 @@ module java.management { requires public java.rmi; requires java.logging; requires java.naming; - // 8147553 - requires jdk.unsupported; exports java.lang.management; exports javax.management; diff --git a/jdk/src/java.management/share/classes/sun/management/jdp/JdpController.java b/jdk/src/java.management/share/classes/sun/management/jdp/JdpController.java index 344d2db2b9e8952c0f070cdb2bbbc01503206678..f96227ce47128572ebd58050765e7106d821cee0 100644 --- a/jdk/src/java.management/share/classes/sun/management/jdp/JdpController.java +++ b/jdk/src/java.management/share/classes/sun/management/jdp/JdpController.java @@ -34,7 +34,6 @@ import java.lang.management.RuntimeMXBean; import java.lang.reflect.Field; import java.lang.reflect.Method; import sun.management.VMManagement; -import sun.misc.ManagedLocalsThread; /** * JdpController is responsible to create and manage a broadcast loop. @@ -219,7 +218,7 @@ public final class JdpController { controller = new JDPControllerRunner(bcast, packet, pause); - Thread t = new ManagedLocalsThread(controller, "JDP broadcaster"); + Thread t = new Thread(null, controller, "JDP broadcaster", 0, false); t.setDaemon(true); t.start(); } diff --git a/jdk/src/java.management/share/classes/sun/management/jmxremote/ConnectorBootstrap.java b/jdk/src/java.management/share/classes/sun/management/jmxremote/ConnectorBootstrap.java index 5ef0f7f17086e535153b504755df2f07aa4438c0..477b778642179ffe013efdaf96f7ad9d9d52bb8f 100644 --- a/jdk/src/java.management/share/classes/sun/management/jmxremote/ConnectorBootstrap.java +++ b/jdk/src/java.management/share/classes/sun/management/jmxremote/ConnectorBootstrap.java @@ -510,6 +510,9 @@ public final class ConnectorBootstrap { // This RMI server should not keep the VM alive Map env = new HashMap<>(); env.put(RMIExporter.EXPORTER_ATTRIBUTE, new PermanentExporter()); + env.put(RMIConnectorServer.CREDENTIAL_TYPES, new String[]{ + String[].class.getName(), String.class.getName() + }); // The local connector server need only be available via the // loopback connection. @@ -740,6 +743,9 @@ public final class ConnectorBootstrap { PermanentExporter exporter = new PermanentExporter(); env.put(RMIExporter.EXPORTER_ATTRIBUTE, exporter); + env.put(RMIConnectorServer.CREDENTIAL_TYPES, new String[]{ + String[].class.getName(), String.class.getName() + }); boolean useSocketFactory = bindAddress != null && !useSsl; diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/server/DeserializationChecker.java b/jdk/src/java.rmi/share/classes/sun/rmi/server/DeserializationChecker.java new file mode 100644 index 0000000000000000000000000000000000000000..8182b10bfbeeedc7a8b3c20b5c254e225d0a789f --- /dev/null +++ b/jdk/src/java.rmi/share/classes/sun/rmi/server/DeserializationChecker.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.rmi.server; + +import java.io.ObjectStreamClass; +import java.lang.reflect.Method; + +/** + * Implementing this interface to have a deserialization control when RMI + * dispatches a remote request. If an exported object implements this interface, + * RMI dispatching mechanism will call the method {@code check} every time + * deserialising a remote object for invoking a method of the exported object. + * + * @author sjiang + */ +public interface DeserializationChecker { + /** + * Will be called to check a descriptor. + * This method may be called 2 times, the first time is when a descriptor is read + * from the stream, the second is just before creating an object described + * by this descriptor. + * + * @param method the method invoked from a remote request. + * @param descriptor The descriptor of the class of any object deserialised + * while deserialising the parameter. The first descriptor will be that of + * the top level object (the concrete class of the parameter itself); + * Subsequent calls with the same {@code method}, {@code paramIndex} and + * {@code callID} will correspond to objects contained in the parameter. + * @param paramIndex an index indicates the position of a parameter in the + * method. This index will be reused for deserialising all + * objects contained in the parameter object. For example, the parameter + * being deserialised is a {@code List}, all deserialisation calls for its + * elements will have same index. + * @param callID a unique ID identifying one + * time method invocation, the same ID is used for deserialization call of + * all parameters within the method. + */ + public void check(Method method, + ObjectStreamClass descriptor, + int paramIndex, + int callID); + + /** + * Will be called to validate a Proxy interfaces from a remote user before loading it. + * @param method the method invoked from a remote request. + * @param ifaces a string table of all interfaces implemented by the proxy to be checked. + * @param paramIndex an index indicates the position of a parameter in the + * method. This index will be reused for deserialising all + * objects contained in the parameter object. For example, the parameter + * being deserialised is a {@code List}, all deserialisation calls for its + * elements will have same index. + * @param callID a unique ID identifying one + * time method invocation, the same ID is used for deserialization call of + * all parameters within the method. + */ + public void checkProxyClass(Method method, + String[] ifaces, + int paramIndex, + int callID); + + /** + * Inform of the completion of parameter deserialisation for a method invocation. + * This is useful if the last parameter is a complex object, like a {@code List} + * which elements are complex object too. + * + * The default implementation does nothing. + * @param callID the ID identifying a method invocation. + */ + public default void end(int callID) {} +} diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/server/MarshalInputStream.java b/jdk/src/java.rmi/share/classes/sun/rmi/server/MarshalInputStream.java index 3453e61f517ba46ca48ae37fd6773916b8a455c0..59c0be3360e607cc5e386eedbf2c433df03dd0a9 100644 --- a/jdk/src/java.rmi/share/classes/sun/rmi/server/MarshalInputStream.java +++ b/jdk/src/java.rmi/share/classes/sun/rmi/server/MarshalInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,13 +30,13 @@ import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectStreamClass; import java.io.StreamCorruptedException; -import java.net.URL; import java.util.*; import java.security.AccessControlException; import java.security.Permission; - import java.rmi.server.RMIClassLoader; import java.security.PrivilegedAction; +import jdk.internal.misc.ObjectStreamClassValidator; +import jdk.internal.misc.SharedSecrets; /** * MarshalInputStream is an extension of ObjectInputStream. When resolving @@ -54,6 +54,11 @@ import java.security.PrivilegedAction; * @author Peter Jones */ public class MarshalInputStream extends ObjectInputStream { + interface StreamChecker extends ObjectStreamClassValidator { + void checkProxyInterfaceNames(String[] ifaces); + } + + private volatile StreamChecker streamChecker = null; /** * Value of "java.rmi.server.useCodebaseOnly" property, @@ -123,7 +128,7 @@ public class MarshalInputStream extends ObjectInputStream { throws IOException, StreamCorruptedException { super(in); - } + } /** * Returns a callback previously registered via the setDoneCallback @@ -240,6 +245,11 @@ public class MarshalInputStream extends ObjectInputStream { protected Class resolveProxyClass(String[] interfaces) throws IOException, ClassNotFoundException { + StreamChecker checker = streamChecker; + if (checker != null) { + checker.checkProxyInterfaceNames(interfaces); + } + /* * Always read annotation written by MarshalOutputStream. */ @@ -319,4 +329,28 @@ public class MarshalInputStream extends ObjectInputStream { void useCodebaseOnly() { useCodebaseOnly = true; } + + synchronized void setStreamChecker(StreamChecker checker) { + streamChecker = checker; + SharedSecrets.getJavaObjectInputStreamAccess().setValidator(this, checker); + } + @Override + protected ObjectStreamClass readClassDescriptor() throws IOException, + ClassNotFoundException { + ObjectStreamClass descriptor = super.readClassDescriptor(); + + validateDesc(descriptor); + + return descriptor; + } + + private void validateDesc(ObjectStreamClass descriptor) { + StreamChecker checker; + synchronized (this) { + checker = streamChecker; + } + if (checker != null) { + checker.validateDescriptor(descriptor); + } + } } diff --git a/jdk/src/java.rmi/share/classes/sun/rmi/server/UnicastServerRef.java b/jdk/src/java.rmi/share/classes/sun/rmi/server/UnicastServerRef.java index b608f237cf500ba67d2ca96b72ebcf731502534c..3c57aa4b2d2a54dc2ed74a421caf2eb1e8d19541 100644 --- a/jdk/src/java.rmi/share/classes/sun/rmi/server/UnicastServerRef.java +++ b/jdk/src/java.rmi/share/classes/sun/rmi/server/UnicastServerRef.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,7 @@ package sun.rmi.server; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; -import java.io.PrintStream; +import java.io.ObjectStreamClass; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.rmi.MarshalException; @@ -52,6 +52,7 @@ import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.WeakHashMap; +import java.util.concurrent.atomic.AtomicInteger; import sun.rmi.runtime.Log; import sun.rmi.transport.LiveRef; import sun.rmi.transport.Target; @@ -116,6 +117,8 @@ public class UnicastServerRef extends UnicastRef private static final Map,?> withoutSkeletons = Collections.synchronizedMap(new WeakHashMap,Void>()); + private final AtomicInteger methodCallIDCount = new AtomicInteger(0); + /** * Create a new (empty) Unicast server remote reference. */ @@ -297,14 +300,11 @@ public class UnicastServerRef extends UnicastRef logCall(obj, method); // unmarshal parameters - Class[] types = method.getParameterTypes(); - Object[] params = new Object[types.length]; + Object[] params = null; try { unmarshalCustomCallData(in); - for (int i = 0; i < types.length; i++) { - params[i] = unmarshalValue(types[i], in); - } + params = unmarshalParameters(obj, method, marshalStream); } catch (java.io.IOException e) { throw new UnmarshalException( "error unmarshalling arguments", e); @@ -565,4 +565,85 @@ public class UnicastServerRef extends UnicastRef return map; } } + + /** + * Unmarshal parameters for the given method of the given instance over + * the given marshalinputstream. Perform any necessary checks. + */ + private Object[] unmarshalParameters(Object obj, Method method, MarshalInputStream in) + throws IOException, ClassNotFoundException { + return (obj instanceof DeserializationChecker) ? + unmarshalParametersChecked((DeserializationChecker)obj, method, in) : + unmarshalParametersUnchecked(method, in); + } + + /** + * Unmarshal parameters for the given method of the given instance over + * the given marshalinputstream. Do not perform any additional checks. + */ + private Object[] unmarshalParametersUnchecked(Method method, ObjectInput in) + throws IOException, ClassNotFoundException { + Class[] types = method.getParameterTypes(); + Object[] params = new Object[types.length]; + for (int i = 0; i < types.length; i++) { + params[i] = unmarshalValue(types[i], in); + } + return params; + } + + /** + * Unmarshal parameters for the given method of the given instance over + * the given marshalinputstream. Do perform all additional checks. + */ + private Object[] unmarshalParametersChecked( + DeserializationChecker checker, + Method method, MarshalInputStream in) + throws IOException, ClassNotFoundException { + int callID = methodCallIDCount.getAndIncrement(); + MyChecker myChecker = new MyChecker(checker, method, callID); + in.setStreamChecker(myChecker); + try { + Class[] types = method.getParameterTypes(); + Object[] values = new Object[types.length]; + for (int i = 0; i < types.length; i++) { + myChecker.setIndex(i); + values[i] = unmarshalValue(types[i], in); + } + myChecker.end(callID); + return values; + } finally { + in.setStreamChecker(null); + } + } + + private static class MyChecker implements MarshalInputStream.StreamChecker { + private final DeserializationChecker descriptorCheck; + private final Method method; + private final int callID; + private int parameterIndex; + + MyChecker(DeserializationChecker descriptorCheck, Method method, int callID) { + this.descriptorCheck = descriptorCheck; + this.method = method; + this.callID = callID; + } + + @Override + public void validateDescriptor(ObjectStreamClass descriptor) { + descriptorCheck.check(method, descriptor, parameterIndex, callID); + } + + @Override + public void checkProxyInterfaceNames(String[] ifaces) { + descriptorCheck.checkProxyClass(method, ifaces, parameterIndex, callID); + } + + void setIndex(int parameterIndex) { + this.parameterIndex = parameterIndex; + } + + void end(int callId) { + descriptorCheck.end(callId); + } + } } diff --git a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/SunProvider.java b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/SunProvider.java index ece97a92afd31e9c60b4a96b5a786c828d79ce46..3e664d7cccc7b13e621ee97445113a685f1e89c5 100644 --- a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/SunProvider.java +++ b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/SunProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * 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,8 +97,6 @@ public final class SunProvider extends Provider { } } - public static final SunProvider INSTANCE = new SunProvider(); - public SunProvider() { /* We are the Sun JGSS provider */ super("SunJGSS", 9.0d, INFO); diff --git a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/GSSNameElement.java b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/GSSNameElement.java index d09ca8d6a16f7e9df31b0ba0f1e3af5d88425bf3..3463fd69dfa5166ffb5e9f6ad5cfeee04d800e0d 100644 --- a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/GSSNameElement.java +++ b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/GSSNameElement.java @@ -159,7 +159,9 @@ public class GSSNameElement implements GSSNameSpi { int atPos = krbName.lastIndexOf('@'); if (atPos != -1) { String atRealm = krbName.substring(atPos); - if (nameType.equals(GSSUtil.NT_GSS_KRB5_PRINCIPAL) + // getNativeNameType() can modify NT_GSS_KRB5_PRINCIPAL to null + if ((nameType == null + || nameType.equals(GSSUtil.NT_GSS_KRB5_PRINCIPAL)) && new String(nameBytes).endsWith(atRealm)) { // Created from Kerberos name with realm, no need to check } else { diff --git a/jdk/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/Klist.java b/jdk/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/Klist.java index c32e9d0eea4df2a6f61f7cb486ffe884abe95b7b..a1abeac97631f1a429e85426894c4cfc30a1b06b 100644 --- a/jdk/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/Klist.java +++ b/jdk/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/Klist.java @@ -134,7 +134,7 @@ public class Klist { Character arg; for (int i = 0; i < args.length; i++) { if ((args[i].length() >= 2) && (args[i].startsWith("-"))) { - arg = new Character(args[i].charAt(1)); + arg = Character.valueOf(args[i].charAt(1)); switch (arg.charValue()) { case 'c': action = 'c'; diff --git a/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/CachedRowSetImpl.java b/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/CachedRowSetImpl.java index b17cd507e9eccae3bdaefe282593a554efbb0730..55179670edb7388cbcba7f0600873cf5216bb7a1 100644 --- a/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/CachedRowSetImpl.java +++ b/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/CachedRowSetImpl.java @@ -1963,7 +1963,7 @@ public class CachedRowSetImpl extends BaseRowSet implements RowSet, RowSetIntern return (float)0; } try { - return ((new Float(value.toString())).floatValue()); + return Float.parseFloat(value.toString()); } catch (NumberFormatException ex) { throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.floatfail").toString(), new Object[] {value.toString().trim(), columnIndex})); @@ -2007,7 +2007,7 @@ public class CachedRowSetImpl extends BaseRowSet implements RowSet, RowSetIntern return (double)0; } try { - return ((new Double(value.toString().trim())).doubleValue()); + return Double.parseDouble(value.toString().trim()); } catch (NumberFormatException ex) { throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.doublefail").toString(), new Object[] {value.toString().trim(), columnIndex})); @@ -4017,9 +4017,9 @@ public class CachedRowSetImpl extends BaseRowSet implements RowSet, RowSetIntern return new BigDecimal(srcObj.toString().trim()); case java.sql.Types.REAL: case java.sql.Types.FLOAT: - return new Float(srcObj.toString().trim()); + return Float.valueOf(srcObj.toString().trim()); case java.sql.Types.DOUBLE: - return new Double(srcObj.toString().trim()); + return Double.valueOf(srcObj.toString().trim()); case java.sql.Types.CHAR: case java.sql.Types.VARCHAR: case java.sql.Types.LONGVARCHAR: diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/Translator.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/Translator.java index 224b5375283aa3e69d889190c28e7f8b1a755941..bb762ad0b425d75f9e6b2b9f540e86ad7343db87 100644 --- a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/Translator.java +++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/Translator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. * 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,13 +26,11 @@ package com.sun.java.accessibility.util; -import java.lang.*; +import com.sun.java.accessibility.util.internal.*; import java.beans.*; import java.util.*; import java.awt.*; import java.awt.event.*; -import java.awt.image.*; -import java.security.AccessControlException; // Do not import Swing classes. This module is intended to work // with both Swing and AWT. // import javax.swing.*; @@ -77,12 +75,26 @@ public class Translator extends AccessibleContext if (c == null) { return null; } - try { - t = Class.forName("com.sun.java.accessibility.util.internal." - + c.getSimpleName() - + "Translator"); + switch (c.getSimpleName()) { + case "Button": + t = ButtonTranslator.class; + break; + case "Checkbox": + t = CheckboxTranslator.class; + break; + case "Label": + t = LabelTranslator.class; + break; + case "List": + t = ListTranslator.class; + break; + case "TextComponent": + t = TextComponentTranslator.class; + break; + } + if (t != null) { return t; - } catch (Exception e) { + } else { return getTranslatorClass(c.getSuperclass()); } } @@ -106,10 +118,6 @@ public class Translator extends AccessibleContext if (o instanceof Accessible) { a = (Accessible)o; } else { - // About to "newInstance" an object of a class of a restricted package - // so ensure the caller is allowed access to that package. - String pkg = "com.sun.java.accessibility.util.internal"; - System.getSecurityManager().checkPackageAccess(pkg); Class translatorClass = getTranslatorClass(o.getClass()); if (translatorClass != null) { try { diff --git a/jdk/src/jdk.accessibility/windows/native/jaccesswalker/jaccesswalker.cpp b/jdk/src/jdk.accessibility/windows/native/jaccesswalker/jaccesswalker.cpp index b8602f52f0d032eeea554bd885b3ca190dacc17c..7943374892cb491335ea28c196ddb08f0c111360 100644 --- a/jdk/src/jdk.accessibility/windows/native/jaccesswalker/jaccesswalker.cpp +++ b/jdk/src/jdk.accessibility/windows/native/jaccesswalker/jaccesswalker.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -543,7 +543,7 @@ void Jaccesswalker::addComponentNodes(long vmID, AccessibleContext context, } else { char s[LINE_BUFSIZE]; sprintf( s, - "ERROR calling GetAccessibleContextInfo; vmID = %X, context = %X", + "ERROR calling GetAccessibleContextInfo; vmID = %X, context = %p", vmID, context ); TVITEM tvi; diff --git a/jdk/src/jdk.accessibility/windows/native/libwindowsaccessbridge/WinAccessBridge.cpp b/jdk/src/jdk.accessibility/windows/native/libwindowsaccessbridge/WinAccessBridge.cpp index 45b47071fcd39ee280f5ae564d687371183e9082..3fa8fc6f67c392b42e8b1c0f5c350060b3244b41 100644 --- a/jdk/src/jdk.accessibility/windows/native/libwindowsaccessbridge/WinAccessBridge.cpp +++ b/jdk/src/jdk.accessibility/windows/native/libwindowsaccessbridge/WinAccessBridge.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1125,7 +1125,7 @@ WinAccessBridge::getAccessibleContextWithFocus(HWND window, long *vmID, JOBJECT6 PrintDebugString("WinAccessBridge::getAccessibleContextWithFocus(%p, %X, )", window, vmID); // find vmID, etc. from HWND; ask that VM for the AC w/Focus - HWND pkgVMID = (HWND)ABLongToHandle( pkg->rVMID ) ; + HWND pkgVMID; if (getAccessibleContextFromHWND(window, (long *)&(pkgVMID), &(pkg->rAccessibleContext)) == TRUE) { HWND destABWindow = javaVMs->findAccessBridgeWindow((long)pkgVMID); // ineffecient [[[FIXME]]] if (sendMemoryPackage(buffer, sizeof(buffer), destABWindow) == TRUE) { diff --git a/jdk/src/jdk.crypto.pkcs11/share/classes/module-info.java b/jdk/src/jdk.crypto.pkcs11/share/classes/module-info.java index 065b8d2f0005c138958a72294a8794e454d8d52d..07f4c1bf3e14f40b0239a8bed4a7bc3d8fa9201c 100644 --- a/jdk/src/jdk.crypto.pkcs11/share/classes/module-info.java +++ b/jdk/src/jdk.crypto.pkcs11/share/classes/module-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,8 +26,6 @@ module jdk.crypto.pkcs11 { // Depends on SunEC provider for EC related functionality requires jdk.crypto.ec; - // 8153371 - requires jdk.unsupported; provides java.security.Provider with sun.security.pkcs11.SunPKCS11; } diff --git a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/SunPKCS11.java b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/SunPKCS11.java index de0bef558971c2555b68dc90cbcc6b490222962a..890587ad7904318f70b93039c20e50c72d3d2bb3 100644 --- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/SunPKCS11.java +++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/SunPKCS11.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,7 +42,6 @@ import javax.security.auth.callback.ConfirmationCallback; import javax.security.auth.callback.PasswordCallback; import javax.security.auth.callback.TextOutputCallback; -import sun.misc.ManagedLocalsThread; import sun.security.util.Debug; import sun.security.util.ResourcesMgr; @@ -816,7 +815,7 @@ public final class SunPKCS11 extends AuthProvider { return; } final TokenPoller poller = new TokenPoller(this); - Thread t = new ManagedLocalsThread(poller, "Poller " + getName()); + Thread t = new Thread(null, poller, "Poller " + getName(), 0, false); t.setDaemon(true); t.setPriority(Thread.MIN_PRIORITY); t.start(); diff --git a/jdk/src/jdk.httpserver/share/classes/module-info.java b/jdk/src/jdk.httpserver/share/classes/module-info.java index e71e6a3f3c8cf71b1c83f891d687e8e23e4b2acb..e26758b66e9ed14d786151f0398228b24e802ab5 100644 --- a/jdk/src/jdk.httpserver/share/classes/module-info.java +++ b/jdk/src/jdk.httpserver/share/classes/module-info.java @@ -25,8 +25,7 @@ module jdk.httpserver { requires java.logging; - // 8153372 - requires jdk.unsupported; + exports com.sun.net.httpserver; exports com.sun.net.httpserver.spi; uses com.sun.net.httpserver.spi.HttpServerProvider; diff --git a/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java b/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java index 1c3ac29f93637ff97a96a851749391ebc46eefc4..a8566e8f7b6c7d057bb2c910e70994263e7bf04b 100644 --- a/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java +++ b/jdk/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java @@ -36,7 +36,6 @@ import javax.net.ssl.*; import com.sun.net.httpserver.*; import java.security.AccessController; import java.security.PrivilegedAction; -import sun.misc.ManagedLocalsThread; import sun.net.httpserver.HttpConnection.State; /** @@ -143,7 +142,7 @@ class ServerImpl implements TimeSource { if (executor == null) { executor = new DefaultExecutor(); } - dispatcherThread = new ManagedLocalsThread(dispatcher); + dispatcherThread = new Thread(null, dispatcher, "HTTP-Dispatcher", 0, false); started = true; dispatcherThread.start(); } diff --git a/jdk/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionExecuter.java b/jdk/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionExecuter.java index a9aece44e3074ceff1d272fc7e4c69dfa1fea0aa..c49cdf55502b1d05f6ca29936fefe042979a3957 100644 --- a/jdk/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionExecuter.java +++ b/jdk/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionExecuter.java @@ -83,14 +83,14 @@ public class ExpressionExecuter implements ExpressionEvaluator { if (op == null) { return evaluate(l); } else { - Double lval = new Double(((Number)evaluate(l)).doubleValue()); - Double rval = new Double(((Number)evaluate(r)).doubleValue()); - double result = op.eval(lval.doubleValue(), rval.doubleValue()); + double lval = ((Number)evaluate(l)).doubleValue(); + double rval = ((Number)evaluate(r)).doubleValue(); + double result = op.eval(lval, rval); if (debug) { System.out.println("Performed Operation: " + lval + op + rval + " = " + result); } - return new Double(result); + return Double.valueOf(result); } } } diff --git a/jdk/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionResolver.java b/jdk/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionResolver.java index c0e198438c64ba3699b48ec1353160860e90ea4c..63505988b8ef5a981c3bcf6011cf47a645569fe6 100644 --- a/jdk/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionResolver.java +++ b/jdk/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionResolver.java @@ -71,7 +71,7 @@ public class ExpressionResolver implements ExpressionEvaluator { if (m == null) { System.err.println("Warning: Unresolved Symbol: " + id.getName() + " substituted NaN"); - return new Literal(new Double(Double.NaN)); + return new Literal(Double.valueOf(Double.NaN)); } if (m.getVariability() == Variability.CONSTANT) { if (debug) { @@ -105,7 +105,7 @@ public class ExpressionResolver implements ExpressionEvaluator { Literal rl = (Literal)r; boolean warn = false; - Double nan = new Double(Double.NaN); + Double nan = Double.valueOf(Double.NaN); if (ll.getValue() instanceof String) { warn = true; ll.setValue(nan); } @@ -129,7 +129,7 @@ public class ExpressionResolver implements ExpressionEvaluator { + " (right = " + rn.doubleValue() + ")" + " to literal value " + result); } - return new Literal(new Double(result)); + return new Literal(Double.valueOf(result)); } } diff --git a/jdk/src/jdk.jcmd/share/classes/sun/tools/jstat/Parser.java b/jdk/src/jdk.jcmd/share/classes/sun/tools/jstat/Parser.java index 33b17b953232f5635d0d7af1aced791cb975020c..a9f9b203e205f42e177591a93db57ca3caa817db 100644 --- a/jdk/src/jdk.jcmd/share/classes/sun/tools/jstat/Parser.java +++ b/jdk/src/jdk.jcmd/share/classes/sun/tools/jstat/Parser.java @@ -324,7 +324,7 @@ public class Parser { case StreamTokenizer.TT_NUMBER: double literal = lookahead.nval; matchNumber(); - e = new Literal(new Double(literal)); + e = new Literal(Double.valueOf(literal)); log(pdebug, "Parsed: number -> " + literal); break; default: @@ -360,7 +360,7 @@ public class Parser { e1.setOperator(op); e1.setRight(e); log(pdebug, "Parsed: unary -> " + e1); - e1.setLeft(new Literal(new Double(0))); + e1.setLeft(new Literal(Double.valueOf(0))); e = e1; } } diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/VirtualMachineManager.java b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/VirtualMachineManager.java index 5a6fd8b596cd891801906f797c0a5a2d589504ef..58c435accf32fb3639b99ad21f7863e995e7a45d 100644 --- a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/VirtualMachineManager.java +++ b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/VirtualMachineManager.java @@ -257,11 +257,11 @@ import java.io.IOException; * delegate to the {@link com.sun.jdi.connect.spi.TransportService#description() * description()} method of the underlying transport service. Both * the AttachingConnector and the ListeningConnector will have two - * Connector {@link com.sun.jdi.connect.Connector$Argument Arguments}. - * A {@link com.sun.jdi.connect.Connector$StringArgument StringArgument} + * Connector {@link com.sun.jdi.connect.Connector.Argument Arguments}. + * A {@link com.sun.jdi.connect.Connector.StringArgument StringArgument} * named {@code address} is the connector argument to specify the * address to attach too, or to listen on. A - * {@link com.sun.jdi.connect.Connector$IntegerArgument IntegerArgument} + * {@link com.sun.jdi.connect.Connector.IntegerArgument IntegerArgument} * named {@code timeout} is the connector argument to specify the * timeout when attaching, or accepting. The timeout connector may be * ignored depending on if the transport service supports an attach diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/Commands.java b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/Commands.java index 61823822d0ecb6f3a53b889afdc7f969641c9bbd..bbae8bc44c87430b027823f2ec6190de78822550 100644 --- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/Commands.java +++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/Commands.java @@ -478,7 +478,7 @@ class Commands { ThreadGroupReference tg = it.nextThreadGroup(); ++cnt; MessageOutput.println("thread group number description name", - new Object [] { new Integer (cnt), + new Object [] { Integer.valueOf(cnt), Env.description(tg), tg.name()}); } @@ -1014,7 +1014,7 @@ class Commands { return MessageOutput.format("locationString", new Object [] {loc.declaringType().name(), loc.method().name(), - new Integer (loc.lineNumber()), + Integer.valueOf(loc.lineNumber()), Long.valueOf(loc.codeIndex())}); } @@ -1467,7 +1467,7 @@ class Commands { MessageOutput.println("Line number information not available for"); } else if (Env.sourceLine(loc, lineno) == null) { MessageOutput.println("is an invalid line number for", - new Object [] {new Integer (lineno), + new Object [] {Integer.valueOf(lineno), refType.name()}); } else { for (int i = startLine; i <= endLine; i++) { @@ -1477,11 +1477,11 @@ class Commands { } if (i == lineno) { MessageOutput.println("source line number current line and line", - new Object [] {new Integer (i), + new Object [] {Integer.valueOf(i), sourceLine}); } else { MessageOutput.println("source line number and line", - new Object [] {new Integer (i), + new Object [] {Integer.valueOf(i), sourceLine}); } } @@ -1725,7 +1725,7 @@ class Commands { } else { MessageOutput.println("Owned by:", new Object [] {owner.name(), - new Integer (object.entryCount())}); + Integer.valueOf(object.entryCount())}); } List waiters = object.waitingThreads(); if (waiters.size() == 0) { diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/MessageOutput.java b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/MessageOutput.java index 8de0675183c7f9689c91f874e703880915b56472..ac3decf432a1fb6b66a54a45b901a5ae77f40d35 100644 --- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/MessageOutput.java +++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/MessageOutput.java @@ -198,7 +198,7 @@ public class MessageOutput { (MessageOutput.format("jdb prompt thread name and current stack frame", new Object [] { threadInfo.getThread().name(), - new Integer (threadInfo.getCurrentFrameIndex() + 1)})); + Integer.valueOf(threadInfo.getCurrentFrameIndex() + 1)})); } System.out.flush(); } diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/ExtractedImage.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/ExtractedImage.java deleted file mode 100644 index 7090f768eb0b348b1cc4a81b8726932481af78d7..0000000000000000000000000000000000000000 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/ExtractedImage.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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 jdk.tools.jimage; - -import java.io.File; -import java.io.IOException; -import java.io.PrintWriter; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; -import java.util.function.Consumer; -import jdk.tools.jlink.internal.ImageFileCreator; -import jdk.tools.jlink.internal.Archive; -import jdk.tools.jlink.internal.ImagePluginStack; -import jdk.tools.jlink.internal.DirArchive; -/** - * - * Support for extracted image. - */ -public final class ExtractedImage { - - private Set archives = new HashSet<>(); - private final ImagePluginStack plugins; - - ExtractedImage(Path dirPath, ImagePluginStack plugins, PrintWriter log, - boolean verbose) throws IOException { - if (!Files.isDirectory(dirPath)) { - throw new IOException("Not a directory"); - } - Consumer cons = (String t) -> { - if (verbose) { - log.println(t); - } - }; - this.plugins = plugins; - Files.walk(dirPath, 1).forEach((p) -> { - if (!dirPath.equals(p)) { - if (Files.isDirectory(p)) { - Archive a = new DirArchive(p, cons); - archives.add(a); - } - } - }); - archives = Collections.unmodifiableSet(archives); - } - - void recreateJImage(Path path) throws IOException { - ImageFileCreator.recreateJimage(path, archives, plugins); - } - - private static String getPathName(Path path) { - return path.toString().replace(File.separatorChar, '/'); - } -} diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java index 44a6bcc4ce3bde4a0d0367550d67d490087edc67..b8a2d58c7fc2436dc140af33712a9408ef1015cb 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java @@ -32,7 +32,6 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.channels.FileChannel; import java.nio.file.Files; -import java.nio.file.Path; import static java.nio.file.StandardOpenOption.READ; import static java.nio.file.StandardOpenOption.WRITE; import java.util.LinkedList; @@ -44,8 +43,6 @@ import static jdk.internal.jimage.ImageHeader.MAJOR_VERSION; import static jdk.internal.jimage.ImageHeader.MINOR_VERSION; import jdk.internal.jimage.ImageLocation; import jdk.tools.jlink.internal.ImageResourcesTree; -import jdk.tools.jlink.internal.ImagePluginConfiguration; -import jdk.tools.jlink.internal.ImagePluginStack; import jdk.tools.jlink.internal.TaskHelper; import jdk.tools.jlink.internal.TaskHelper.BadArgs; import static jdk.tools.jlink.internal.TaskHelper.JIMAGE_BUNDLE; @@ -97,7 +94,6 @@ class JImageTask { EXTRACT, INFO, LIST, - RECREATE, SET, VERIFY }; @@ -152,21 +148,28 @@ class JImageTask { setLog(new PrintWriter(System.out)); } + if (args.length == 0) { + log.println(taskHelper.getMessage("main.usage.summary", PROGNAME)); + return EXIT_ABNORMAL; + } + try { List unhandled = optionsHelper.handleOptions(this, args); if(!unhandled.isEmpty()) { - options.task = Enum.valueOf(Task.class, unhandled.get(0).toUpperCase()); + try { + options.task = Enum.valueOf(Task.class, unhandled.get(0).toUpperCase()); + } catch (IllegalArgumentException ex) { + throw taskHelper.newBadArgs("err.not.a.task", unhandled.get(0)); + } for(int i = 1; i < unhandled.size(); i++) { options.jimages.add(new File(unhandled.get(i))); } + } else { + throw taskHelper.newBadArgs("err.not.a.task", ""); } if (options.help) { optionsHelper.showHelp(PROGNAME); } - if(optionsHelper.listPlugins()) { - optionsHelper.listPlugins(true); - return EXIT_OK; - } if (options.version || options.fullVersion) { taskHelper.showVersion(options.fullVersion); } @@ -186,49 +189,19 @@ class JImageTask { } } - private void recreate() throws Exception, BadArgs { - File directory = new File(options.directory); - if (!directory.isDirectory()) { - throw taskHelper.newBadArgs("err.not.a.dir", directory.getAbsolutePath()); - } - Path dirPath = directory.toPath(); - if (options.jimages.isEmpty()) { - throw taskHelper.newBadArgs("err.jimage.not.specified"); - } else if (options.jimages.size() != 1) { - throw taskHelper.newBadArgs("err.only.one.jimage"); - } - - Path jimage = options.jimages.get(0).toPath(); - - if (jimage.toFile().createNewFile()) { - ImagePluginStack pc = ImagePluginConfiguration.parseConfiguration(taskHelper. - getPluginsConfig(null, false)); - ExtractedImage img = new ExtractedImage(dirPath, pc, log, options.verbose); - img.recreateJImage(jimage); - } else { - throw taskHelper.newBadArgs("err.jimage.already.exists", jimage.getFileName()); - } - } - - private void title(File file, BasicImageReader reader) { - log.println("jimage: " + file.getName()); - } - private void listTitle(File file, BasicImageReader reader) { - title(file, reader); - - if (options.verbose) { - log.print(pad("Offset", OFFSET_WIDTH + 1)); - log.print(pad("Size", SIZE_WIDTH + 1)); - log.print(pad("Compressed", COMPRESSEDSIZE_WIDTH + 1)); - log.println(" Entry"); - } + log.println("jimage: " + file); } private interface JImageAction { public void apply(File file, BasicImageReader reader) throws IOException, BadArgs; } + private interface ModuleAction { + public void apply(BasicImageReader reader, + String oldModule, String newModule) throws IOException, BadArgs; + } + private interface ResourceAction { public void apply(BasicImageReader reader, String name, ImageLocation location) throws IOException, BadArgs; @@ -254,23 +227,32 @@ class JImageTask { } } - private static final int NUMBER_WIDTH = 12; - private static final int OFFSET_WIDTH = NUMBER_WIDTH; - private static final int SIZE_WIDTH = NUMBER_WIDTH; - private static final int COMPRESSEDSIZE_WIDTH = NUMBER_WIDTH; + private static final int OFFSET_WIDTH = 12; + private static final int SIZE_WIDTH = 10; + private static final int COMPRESSEDSIZE_WIDTH = 10; + + private String trimModule(String name) { + int offset = name.indexOf('/', 1); + + if (offset != -1 && offset + 1 < name.length()) { + return name.substring(offset + 1); + } + + return name; + } - private void print(String entry, ImageLocation location) { + private void print(String name, ImageLocation location) { log.print(pad(location.getContentOffset(), OFFSET_WIDTH) + " "); log.print(pad(location.getUncompressedSize(), SIZE_WIDTH) + " "); log.print(pad(location.getCompressedSize(), COMPRESSEDSIZE_WIDTH) + " "); - log.println(entry); + log.println(trimModule(name)); } - private void print(BasicImageReader reader, String entry) { + private void print(BasicImageReader reader, String name) { if (options.verbose) { - print(entry, reader.findLocation(entry)); + print(name, reader.findLocation(name)); } else { - log.println(entry); + log.println(" " + trimModule(name)); } } @@ -289,6 +271,18 @@ class JImageTask { log.println(" Index Size: " + header.getIndexSize()); } + private void listModule(BasicImageReader reader, String oldModule, String newModule) { + log.println(); + log.println("Module: " + newModule); + + if (options.verbose) { + log.print(pad("Offset", OFFSET_WIDTH) + " "); + log.print(pad("Size", SIZE_WIDTH) + " "); + log.print(pad("Compressed", COMPRESSEDSIZE_WIDTH) + " "); + log.println("Entry"); + } + } + private void list(BasicImageReader reader, String name, ImageLocation location) { print(reader, name); } @@ -338,7 +332,12 @@ class JImageTask { } private void iterate(JImageAction jimageAction, + ModuleAction moduleAction, ResourceAction resourceAction) throws IOException, BadArgs { + if (options.jimages.isEmpty()) { + throw taskHelper.newBadArgs("err.no.jimage"); + } + for (File file : options.jimages) { if (!file.exists() || !file.isFile()) { throw taskHelper.newBadArgs("err.not.a.jimage", file.getName()); @@ -351,9 +350,23 @@ class JImageTask { if (resourceAction != null) { String[] entryNames = reader.getEntryNames(); + String oldModule = ""; for (String name : entryNames) { if (!ImageResourcesTree.isTreeInfoResource(name)) { + if (moduleAction != null) { + int offset = name.indexOf('/', 1); + + String newModule = offset != -1 ? + name.substring(1, offset) : + ""; + + if (!oldModule.equals(newModule)) { + moduleAction.apply(reader, oldModule, newModule); + oldModule = newModule; + } + } + ImageLocation location = reader.findLocation(name); resourceAction.apply(reader, name, location); } @@ -366,22 +379,19 @@ class JImageTask { private boolean run() throws Exception, BadArgs { switch (options.task) { case EXTRACT: - iterate(null, this::extract); + iterate(null, null, this::extract); break; case INFO: - iterate(this::info, null); + iterate(this::info, null, null); break; case LIST: - iterate(this::listTitle, this::list); - break; - case RECREATE: - recreate(); + iterate(this::listTitle, this::listModule, this::list); break; case SET: - iterate(this::set, null); + iterate(this::set, null, null); break; case VERIFY: - iterate(this::title, this::verify); + iterate(this::listTitle, null, this::verify); break; default: throw taskHelper.newBadArgs("err.invalid.task", options.task.name()).showUsage(true); diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage.properties b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage.properties index 857d52b005a2318aa889df06c6aff08565aa0021..ef94fd376c69ef4b47722fb13d74cdd1f898c4e0 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage.properties +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage.properties @@ -1,30 +1,25 @@ main.usage.summary=\ -Usage: {0} jimage...\n\ +Usage: {0} jimage...\n\ use --help for a list of possible options main.usage=\ -Usage: {0} jimage...\n\ +Usage: {0} jimage...\n\ \n\ \ extract - Extract all jimage entries into separate files into the directory\n\ \ specified by --dir= (default='.')\n\ \ info - Prints information specified in the jimage header.\n\ \ list - Prints the names of all the entries in the jimage. When used with\n\ \ --verbose will also print entry attributes ex. size and offset.\n\ -\ recreate - Reconstructs a jimage from an extracted directory (--dir)\n\ \ set - sets the value of specific jimage header entries\n\ \ verify - Reports errors on any .class entries that don't verify as classes.\n\ \n\ Possible options include: -main.extended.help=\ -jimage recreate is extensible by the main of plugins. Following plugins have been discovered \ -thanks to ServiceLoader and can be used when re-creating a jimage. - error.prefix=Error: warn.prefix=Warning: main.opt.dir=\ -\ --dir Target directory for extract/recreate +\ --dir Target directory for extract main.opt.flags=\ \ --flags=value Set the jimage flags to value @@ -38,14 +33,8 @@ main.opt.verbose=\ main.opt.version=\ \ --version Version information -main.opt.configuration=\ -\ --configuration Path to properties file containing defaults\ -\ options for recreate - main.command.files=\ \ @ Read options from file - -err.cannot.create.dir=cannot create directory: {0} err.cannot.read.file=cannot read file: {0} err.cannot.update.file=cannot update file: {0} err.file.not.found=cannot find file: {0} @@ -53,12 +42,11 @@ err.file.error=cannot access file: {0} err.flags.not.int=--flags value not integer: {0} err.internal.error=internal error: {0} {1} {2} err.invalid.arg.for.option=invalid argument for option: {0} -err.invalid.task=task must be extract|recreate|info|list|verify: {0} -err.jimage.already.exists=jimage already exists: {0} -err.jimage.not.specified=no jimage specified +err.invalid.task=task must be extract|info|list|verify: {0} err.missing.arg=no value given for {0} err.not.a.dir=not a directory: {0} err.not.a.jimage=not a jimage file: {0} -err.only.one.jimage=only one jimage should be specified +err.no.jimage=no jimage provided +err.not.a.task=not a valid task: {0} err.option.unsupported={0} not supported: {1} err.unknown.option=unknown option: {0} diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Pool.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Pool.java index 3645f57c5f4df0bfd33d670ef0b363c1f2b0025b..380ca41ac1a9b2f60824b0c096a24a4b83876a8a 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Pool.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/Pool.java @@ -226,7 +226,7 @@ public abstract class Pool { *
  • For jimage content: /{module name}/{package1}/.../{packageN}/{file * name}
  • *
  • For other files (shared lib, launchers, config, ...):/{module name}/ - * {@literal bin|conf|native}/{dir1}>/.../{dirN}/{file name}
  • + * {@literal bin|conf|native}/{dir1}/.../{dirN}/{file name} * */ public static class ModuleData { diff --git a/jdk/src/jdk.unsupported/share/classes/sun/misc/ManagedLocalsThread.java b/jdk/src/jdk.unsupported/share/classes/sun/misc/ManagedLocalsThread.java deleted file mode 100644 index 58d9013c2614fbc477b2fbb7a8fd000f6e225761..0000000000000000000000000000000000000000 --- a/jdk/src/jdk.unsupported/share/classes/sun/misc/ManagedLocalsThread.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.misc; - -/** - * A thread that has it's thread locals, and inheritable thread - * locals erased on construction. - */ -public class ManagedLocalsThread extends Thread { - private static final jdk.internal.misc.Unsafe UNSAFE; - private static final long THREAD_LOCALS; - private static final long INHERITABLE_THREAD_LOCALS; - - public ManagedLocalsThread() { - eraseThreadLocals(); - } - - public ManagedLocalsThread(Runnable target) { - super(target); - eraseThreadLocals(); - } - - public ManagedLocalsThread(String name) { - super(name); - eraseThreadLocals(); - } - - public ManagedLocalsThread(ThreadGroup group, Runnable target) { - super(group, target); - eraseThreadLocals(); - } - - public ManagedLocalsThread(Runnable target, String name) { - super(target, name); - eraseThreadLocals(); - } - - public ManagedLocalsThread(ThreadGroup group, String name) { - super(group, name); - eraseThreadLocals(); - } - - public ManagedLocalsThread(ThreadGroup group, Runnable target, String name) { - super(group, target, name); - eraseThreadLocals(); - } - - /** - * Drops all thread locals (and inherited thread locals). - */ - public final void eraseThreadLocals() { - UNSAFE.putObject(this, THREAD_LOCALS, null); - UNSAFE.putObject(this, INHERITABLE_THREAD_LOCALS, null); - } - - static { - UNSAFE = jdk.internal.misc.Unsafe.getUnsafe(); - Class t = Thread.class; - try { - THREAD_LOCALS = UNSAFE.objectFieldOffset - (t.getDeclaredField("threadLocals")); - INHERITABLE_THREAD_LOCALS = UNSAFE.objectFieldOffset - (t.getDeclaredField("inheritableThreadLocals")); - } catch (Exception e) { - throw new Error(e); - } - } -} - diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index ee17885babdd3bea1dcc6c63474c3312c6b41590..696c9cd270fbf9c23df47a1425fe4ca092dde50b 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -335,10 +335,6 @@ com/sun/jdi/CatchPatternTest.sh 8068645 generic- com/sun/jdi/GetLocalVariables4Test.sh 8067354 windows-all -com/sun/jdi/InterfaceMethodsTest.java 8152586 generic-all - -com/sun/jdi/InvokeTest.java 8152586 generic-all - ############################################################################ # jdk_util diff --git a/jdk/test/TEST.groups b/jdk/test/TEST.groups index cf3f0abfd9dd1bb1e546c47e66b2f688edcf40de..673b0862d5c933d8dd8fe71c09d01b7003308a30 100644 --- a/jdk/test/TEST.groups +++ b/jdk/test/TEST.groups @@ -32,7 +32,6 @@ tier1 = \ -java/util/WeakHashMap/GCDuringIteration.java \ -java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java \ -java/util/concurrent/forkjoin/FJExceptionTableLeak.java \ - -java/util/TimeZone/Bug6772689.java \ sun/nio/cs/ISO8859x.java \ java/nio/Buffer \ com/sun/crypto/provider/Cipher \ @@ -43,7 +42,6 @@ tier2 = \ java/util/WeakHashMap/GCDuringIteration.java \ java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java \ java/util/concurrent/forkjoin/FJExceptionTableLeak.java \ - java/util/TimeZone/Bug6772689.java \ :jdk_io \ :jdk_nio \ -sun/nio/cs/ISO8859x.java \ diff --git a/jdk/test/com/sun/jdi/ShellScaffold.sh b/jdk/test/com/sun/jdi/ShellScaffold.sh index ed5f79e58ac405b9fa1bb56b1e19ac469f7efb01..eb7e6b453516799285053123d6a9f0600a0aa267 100644 --- a/jdk/test/com/sun/jdi/ShellScaffold.sh +++ b/jdk/test/com/sun/jdi/ShellScaffold.sh @@ -924,7 +924,7 @@ dojstack() # If jstack exists, so will jps # Show stack traces of jdb and debuggee as a possible debugging aid. jdbCmd=`$jdk/bin/jps -v | $grep $jdbKeyword` - realJdbPid=`echo "$jdbCmd" | sed -e 's@ TTY.*@@'` + realJdbPid=`echo "$jdbCmd" | sed -e 's@ .*@@'` if [ ! -z "$realJdbPid" ] ; then echo "-- jdb process info ----------------------" >&2 echo " $jdbCmd" >&2 diff --git a/jdk/test/com/sun/jdi/SunBootClassPathEmptyTest.java b/jdk/test/com/sun/jdi/SunBootClassPathEmptyTest.java new file mode 100644 index 0000000000000000000000000000000000000000..e062996ee6a57d36e8a656722834229d55e8d0c4 --- /dev/null +++ b/jdk/test/com/sun/jdi/SunBootClassPathEmptyTest.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.sun.jdi.connect.*; +import com.sun.jdi.*; +import java.util.Map; +import java.util.List; +import jdk.test.lib.Asserts; + +/* + * @test + * @summary Verifies that PathSearchingVirtualMachine.bootClassPath() + * returns an empty list in case no bootclass path specified + * regardless of sun.boot.class.path option, which is now obsolete + * @library /test/lib/share/classes + * @compile TestClass.java + * @compile SunBootClassPathEmptyTest.java + * @run main/othervm SunBootClassPathEmptyTest + */ +public class SunBootClassPathEmptyTest { + + /** + * Helper class to facilitate the debuggee VM launching + */ + private static class VmConnector { + + LaunchingConnector lc; + VirtualMachine vm; + + VmConnector() { + for (LaunchingConnector c : Bootstrap.virtualMachineManager().launchingConnectors()) { + System.out.println("name: " + c.name()); + if (c.name().equals("com.sun.jdi.CommandLineLaunch")) { + lc = c; + break; + } + } + if (lc == null) { + throw new RuntimeException("Connector not found"); + } + } + + PathSearchingVirtualMachine launchVm(String cmdLine, String options) throws Exception { + Map vmArgs = lc.defaultArguments(); + vmArgs.get("main").setValue(cmdLine); + if (options != null) { + vmArgs.get("options").setValue(options); + } + System.out.println("Debugger is launching vm ..."); + vm = lc.launch(vmArgs); + if (!(vm instanceof PathSearchingVirtualMachine)) { + throw new RuntimeException("VM is not a PathSearchingVirtualMachine"); + } + return (PathSearchingVirtualMachine) vm; + } + + } + + private static VmConnector connector = new VmConnector(); + + public static void main(String[] args) throws Exception { + testWithObsoleteClassPathOption(null); + testWithObsoleteClassPathOption("someclasspath"); + } + + private static void testWithObsoleteClassPathOption(String obsoleteClassPath) throws Exception { + PathSearchingVirtualMachine vm = connector.launchVm("TestClass", makeClassPathOptions(obsoleteClassPath)); + List bootClassPath = vm.bootClassPath(); + Asserts.assertNotNull(bootClassPath, "Expected bootClassPath to be empty but was null"); + Asserts.assertEquals(0, bootClassPath.size(), "Expected bootClassPath.size() 0 but was: " + bootClassPath.size()); + } + + private static String makeClassPathOptions(String obsoleteClassPath) { + return obsoleteClassPath == null ? null : "-Dsun.boot.class.path=" + obsoleteClassPath; + } + +} diff --git a/jdk/test/com/sun/jdi/TestClass.java b/jdk/test/com/sun/jdi/TestClass.java new file mode 100644 index 0000000000000000000000000000000000000000..dab6b66648ca7c16966454ae8a43495ba076c0ef --- /dev/null +++ b/jdk/test/com/sun/jdi/TestClass.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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. + */ + +public class TestClass { + + public static void main(String[] args) { + System.out.println("This is a test"); + } + +} diff --git a/jdk/test/java/awt/Button/ActionEventTest/ActionEventTest.java b/jdk/test/java/awt/Button/ActionEventTest/ActionEventTest.java new file mode 100644 index 0000000000000000000000000000000000000000..9c6317d9a7d3dac88e55370057455388c6ed4809 --- /dev/null +++ b/jdk/test/java/awt/Button/ActionEventTest/ActionEventTest.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 6191390 + * @summary Verify that ActionEvent is received with correct modifiers set. + * @run main/manual ActionEventTest + */ + +import java.awt.AWTException; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Button; +import java.awt.TextArea; +import java.awt.Robot; +import java.awt.Point; +import java.awt.event.InputEvent; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; + +public class ActionEventTest extends Frame { + Button button; + Robot robot; + TextArea instructions; + public static boolean isProgInterruption = false; + static Thread mainThread = null; + static int sleepTime = 300000; + + public ActionEventTest() { + try { + robot = new Robot(); + } catch(AWTException e) { + throw new RuntimeException(e.getMessage()); + } + + button = new Button("ClickMe"); + button.setEnabled(true); + + instructions = new TextArea(10, 50); + instructions.setText( + " This is a manual test\n" + + " Keep the Alt, Shift & Ctrl Keys pressed &\n" + + " Click 'ClickMe' button with left mouse button\n" + + " Test exits automatically after mouse click."); + + add(button); + add(instructions); + setSize(400,400); + setLayout(new FlowLayout()); + pack(); + setVisible(true); + robot.waitForIdle(); + + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent ae) { + int md = ae.getModifiers(); + int expectedMask = ActionEvent.ALT_MASK | ActionEvent.CTRL_MASK + | ActionEvent.SHIFT_MASK; + + isProgInterruption = true; + mainThread.interrupt(); + if ((md & expectedMask) != expectedMask) { + throw new RuntimeException("Action Event modifiers" + + " are not set correctly."); + } + } + }); + } + + public static void main(String args[]) throws Exception { + mainThread = Thread.currentThread(); + ActionEventTest test = new ActionEventTest(); + try { + mainThread.sleep(sleepTime); + } catch (InterruptedException e) { + if (!isProgInterruption) { + throw e; + } + } + test.dispose(); + if (!isProgInterruption) { + throw new RuntimeException("Timed out after " + sleepTime / 1000 + + " seconds"); + } + } +} diff --git a/jdk/test/java/awt/Component/CompEventOnHiddenComponent/CompEventOnHiddenComponent.java b/jdk/test/java/awt/Component/CompEventOnHiddenComponent/CompEventOnHiddenComponent.java index 43a6d3267028d3594731a65f967e121a29fa1450..cd74e128b7c4c0e1ca30e651d6e945ef0d4c1a92 100644 --- a/jdk/test/java/awt/Component/CompEventOnHiddenComponent/CompEventOnHiddenComponent.java +++ b/jdk/test/java/awt/Component/CompEventOnHiddenComponent/CompEventOnHiddenComponent.java @@ -25,7 +25,7 @@ /* @test - @bug 6383903 + @bug 6383903 8144166 @summary REGRESSION: componentMoved is now getting called for some hidden components @author andrei.dmitriev: area=awt.component @run main CompEventOnHiddenComponent diff --git a/jdk/test/java/awt/FontClass/CreateFont/CreateFontArrayTest.java b/jdk/test/java/awt/FontClass/CreateFont/CreateFontArrayTest.java index d68b2e4409f14d97dc74052570cd9d50f9807fd6..4dbff501d39b1344d8b9ff67b6bb10b473db9f18 100644 --- a/jdk/test/java/awt/FontClass/CreateFont/CreateFontArrayTest.java +++ b/jdk/test/java/awt/FontClass/CreateFont/CreateFontArrayTest.java @@ -23,9 +23,9 @@ /* * @test - * @bug 8055463 + * @bug 8055463 8153272 * @summary Test createFont APIs - * @run CreateFontArrayTest + * @run main CreateFontArrayTest */ import java.awt.Font; diff --git a/jdk/test/java/awt/FontClass/TextRequiresLayoutTest.java b/jdk/test/java/awt/FontClass/TextRequiresLayoutTest.java new file mode 100644 index 0000000000000000000000000000000000000000..99b2595c41b4275a1acaed7d7990c978fd66efac --- /dev/null +++ b/jdk/test/java/awt/FontClass/TextRequiresLayoutTest.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 8146324 + * @summary Test Font.textRequiresLayout + */ + +import java.awt.Font; + +public class TextRequiresLayoutTest { + + public static void main(String args[]) { + + String simpleStr = "Hello World"; + String complexStr = "\u0641\u0642\u0643"; + char[] simpleChars = simpleStr.toCharArray(); + char[] complexChars = complexStr.toCharArray(); + + if (Font.textRequiresLayout(simpleChars, 0, simpleChars.length)) { + throw new RuntimeException("Simple text should not need layout"); + } + + if (!Font.textRequiresLayout(complexChars, 0, complexChars.length)) { + throw new RuntimeException("Complex text should need layout"); + } + + if (Font.textRequiresLayout(complexChars, 0, 0)) { + throw new RuntimeException("Empty text should not need layout"); + } + + boolean except = false; + try { + Font.textRequiresLayout(null, 0, 0); + } catch (NullPointerException npe) { + except = true; + } + if (!except) { + throw new RuntimeException("No expected IllegalArgumentException"); + } + + except = false; + try { + Font.textRequiresLayout(complexChars, -1, 0); + } catch (ArrayIndexOutOfBoundsException aioobe) { + except = true; + } + if (!except) { + throw new + RuntimeException("No expected ArrayIndexOutOfBoundsException"); + } + + except = false; + try { + Font.textRequiresLayout(complexChars, 0, complexChars.length+1); + } catch (ArrayIndexOutOfBoundsException aioobe) { + except = true; + } + if (!except) { + throw new + RuntimeException("No expected ArrayIndexOutOfBoundsException"); + } + } +} diff --git a/jdk/test/java/awt/List/ActionEventTest/ActionEventTest.java b/jdk/test/java/awt/List/ActionEventTest/ActionEventTest.java new file mode 100644 index 0000000000000000000000000000000000000000..f1cd8e32a46640ef3b3940b7befe07aa17c3e279 --- /dev/null +++ b/jdk/test/java/awt/List/ActionEventTest/ActionEventTest.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 6191390 + * @summary Verify that ActionEvent is received with correct modifiers set. + * @run main ActionEventTest + */ + +import java.awt.AWTException; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.List; +import java.awt.Robot; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; + +public class ActionEventTest extends Frame { + List list; + Robot robot; + + public ActionEventTest() { + try { + robot = new Robot(); + } catch(AWTException e) { + throw new RuntimeException(e.getMessage()); + } + + list = new List(1, false); + list.add("0"); + add(list); + setSize(400,400); + setLayout(new FlowLayout()); + pack(); + setVisible(true); + robot.waitForIdle(); + } + + void performTest() { + list.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent ae) { + int md = ae.getModifiers(); + int expectedMask = ActionEvent.ALT_MASK | ActionEvent.CTRL_MASK + | ActionEvent.SHIFT_MASK; + + if ((md & expectedMask) != expectedMask) { + + robot.keyRelease(KeyEvent.VK_ALT); + robot.keyRelease(KeyEvent.VK_SHIFT); + robot.keyRelease(KeyEvent.VK_CONTROL); + dispose(); + throw new RuntimeException("Action Event modifiers are not" + + " set correctly."); + } + } + }); + + list.select(0); + robot.keyPress(KeyEvent.VK_ALT); + robot.keyPress(KeyEvent.VK_SHIFT); + robot.keyPress(KeyEvent.VK_CONTROL); + // Press Enter on list item, to generate action event. + robot.keyPress(KeyEvent.VK_ENTER); + robot.keyRelease(KeyEvent.VK_ENTER); + robot.waitForIdle(); + robot.keyRelease(KeyEvent.VK_ALT); + robot.keyRelease(KeyEvent.VK_SHIFT); + robot.keyRelease(KeyEvent.VK_CONTROL); + robot.waitForIdle(); + } + + public static void main(String args[]) { + ActionEventTest test = new ActionEventTest(); + test.performTest(); + test.dispose(); + } +} diff --git a/jdk/test/java/awt/List/ItemEventTest/ItemEventTest.java b/jdk/test/java/awt/List/ItemEventTest/ItemEventTest.java new file mode 100644 index 0000000000000000000000000000000000000000..c239b01360cbb3c2bf9d068d9f8578a1e4795862 --- /dev/null +++ b/jdk/test/java/awt/List/ItemEventTest/ItemEventTest.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 8033936 + * @summary Verify that correct ItemEvent is received while selection & + * deselection of multi select List items. + */ + +import java.awt.AWTException; +import java.awt.Event; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.List; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.event.KeyEvent; +import java.awt.event.InputEvent; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; + +public class ItemEventTest extends Frame +{ + List list; + final String expectedSelectionOrder; + StringBuilder actualSelectionOrder; + Robot robot; + + public ItemEventTest() + { + try { + robot = new Robot(); + } catch(AWTException e) { + throw new RuntimeException(e.getMessage()); + } + expectedSelectionOrder = "01230123"; + + list = new List(4, true); + list.add("0"); + list.add("1"); + list.add("2"); + list.add("3"); + + add(list); + setSize(400,400); + setLayout(new FlowLayout()); + pack(); + setVisible(true); + robot.waitForIdle(); + } + + @Override + public boolean handleEvent(Event e) { + if (e.target instanceof List) { + if (e.id == Event.LIST_DESELECT || e.id == Event.LIST_SELECT) { + actualSelectionOrder.append(e.arg); + } + } + return true; + } + + void testHandleEvent() { + // When no ItemListener is added to List, parent's handleEvent is + // called with ItemEvent. + performTest(); + } + + void testItemListener() { + list.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent ie) { + actualSelectionOrder.append(ie.getItem()); + } + }); + performTest(); + } + + void performTest() { + actualSelectionOrder = new StringBuilder(); + Point loc = list.getLocationOnScreen(); + Rectangle rect = list.getBounds(); + int dY = rect.height / list.getItemCount(); + loc = new Point(loc.x + 10, loc.y + 5); + + String osName = System.getProperty("os.name"); + boolean isMac = osName.contains("Mac") || osName.contains("mac"); + if(isMac) { + robot.keyPress(KeyEvent.VK_META); + } + + // First loop to select & Second loop to deselect the list items. + for (int j = 0; j < 2; ++j) { + for (int i = 0; i < list.getItemCount(); ++i) { + robot.mouseMove(loc.x, loc.y + i * dY); + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.delay(100); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + robot.waitForIdle(); + } + } + + if(isMac) { + robot.keyRelease(KeyEvent.VK_META); + } + + if (!expectedSelectionOrder.equals(actualSelectionOrder.toString())) { + dispose(); + throw new RuntimeException("ItemEvent for selection & deselection" + + " of multi select List's item is not correct" + + " Expected : " + expectedSelectionOrder + + " Actual : " + actualSelectionOrder); + } + } + + public static void main(String args[]) { + ItemEventTest test = new ItemEventTest(); + test.testHandleEvent(); + test.testItemListener(); + test.dispose(); + } +} diff --git a/jdk/test/java/awt/MenuBar/ActionEventTest/ActionEventTest.java b/jdk/test/java/awt/MenuBar/ActionEventTest/ActionEventTest.java new file mode 100644 index 0000000000000000000000000000000000000000..6af94798e315dc15328ff810ad68f8a09feb1c4f --- /dev/null +++ b/jdk/test/java/awt/MenuBar/ActionEventTest/ActionEventTest.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 6191390 + * @summary Verify that ActionEvent is received with correct modifiers set. + * @run main/manual ActionEventTest + */ + +import java.awt.Frame; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.MenuItem; +import java.awt.TextArea; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public final class ActionEventTest extends Frame { + + MenuBar menuBar; + TextArea instructions; + public static boolean isProgInterruption = false; + static Thread mainThread = null; + static int sleepTime = 300000; + + public ActionEventTest() { + menuBar = new MenuBar(); + Menu menu = new Menu("Menu1"); + MenuItem menuItem = new MenuItem("MenuItem"); + + menuItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent ae) { + System.out.println("actionPerformed"); + int md = ae.getModifiers(); + int expectedMask = ActionEvent.ALT_MASK | ActionEvent.CTRL_MASK + | ActionEvent.SHIFT_MASK; + + isProgInterruption = true; + mainThread.interrupt(); + if ((md & expectedMask) != expectedMask) { + throw new RuntimeException("Action Event modifiers are not" + + " set correctly."); + } + } + }); + menu.add(menuItem); + menuBar.add(menu); + setMenuBar(menuBar); + + instructions = new TextArea(10, 50); + instructions.setText( + " This is a manual test\n" + + " Keep the Alt, Shift & Ctrl Keys pressed while doing next steps\n" + + " Click 'Menu1' Menu from the Menu Bar\n" + + " It will show 'MenuItem'\n" + + " Left mouse Click the 'MenuItem'\n" + + " Test exits automatically after mouse click."); + add(instructions); + + setSize(400, 400); + setVisible(true); + validate(); + } + + + public static void main(final String[] args) throws Exception { + mainThread = Thread.currentThread(); + ActionEventTest test = new ActionEventTest(); + try { + mainThread.sleep(sleepTime); + } catch (InterruptedException e) { + if (!isProgInterruption) { + throw e; + } + } + test.dispose(); + if (!isProgInterruption) { + throw new RuntimeException("Timed out after " + sleepTime / 1000 + + " seconds"); + } + } +} diff --git a/jdk/test/java/awt/PrintJob/JobAttrUpdateTest.java b/jdk/test/java/awt/PrintJob/JobAttrUpdateTest.java new file mode 100644 index 0000000000000000000000000000000000000000..186b9a6d8bac01cf76fc9762aa1b609961222983 --- /dev/null +++ b/jdk/test/java/awt/PrintJob/JobAttrUpdateTest.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 6357905 + * @summary JobAttributes.getFromPage() and getToPage() always returns 1 + * @run main/manual JobAttrUpdateTest + */ +import java.awt.BorderLayout; +import java.awt.FlowLayout; +import java.awt.JobAttributes; +import java.awt.PrintJob; +import java.awt.Toolkit; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTextArea; +import javax.swing.SwingUtilities; + +public class JobAttrUpdateTest { + + private static Thread mainThread; + private static boolean testPassed; + private static boolean testGeneratedInterrupt; + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(() -> { + doTest(JobAttrUpdateTest::printTest); + }); + mainThread = Thread.currentThread(); + try { + Thread.sleep(30000); + } catch (InterruptedException e) { + if (!testPassed && testGeneratedInterrupt) { + throw new RuntimeException("" + + "JobAttributes.getFromPage(),getToPage() not updated correctly"); + } + } + if (!testGeneratedInterrupt) { + throw new RuntimeException("user has not executed the test"); + } + } + + private static void printTest() { + JobAttributes ja = new JobAttributes(); + + Toolkit tk = Toolkit.getDefaultToolkit(); + // ja.setToPage(4); + // ja.setFromPage(3); + // show dialog + PrintJob pjob = tk.getPrintJob(new JFrame(), "test", ja, null); + if (pjob == null) { + return; + } + + + if (ja.getDefaultSelection() == JobAttributes.DefaultSelectionType.RANGE) { + int fromPage = ja.getFromPage(); + int toPage = ja.getToPage(); + if (fromPage != 2 || toPage != 3) { + fail(); + } else { + pass(); + } + } + } + + public static synchronized void pass() { + testPassed = true; + testGeneratedInterrupt = true; + mainThread.interrupt(); + } + + public static synchronized void fail() { + testPassed = false; + testGeneratedInterrupt = true; + mainThread.interrupt(); + } + + private static void doTest(Runnable action) { + String description + = " A print dialog will be shown.\n " + + " Please select Pages within Page-range.\n" + + " and enter From 2 and To 3. Then Select OK."; + + final JDialog dialog = new JDialog(); + dialog.setTitle("JobAttribute Updation Test"); + JTextArea textArea = new JTextArea(description); + textArea.setEditable(false); + final JButton testButton = new JButton("Start Test"); + + testButton.addActionListener((e) -> { + testButton.setEnabled(false); + action.run(); + }); + JPanel mainPanel = new JPanel(new BorderLayout()); + mainPanel.add(textArea, BorderLayout.CENTER); + JPanel buttonPanel = new JPanel(new FlowLayout()); + buttonPanel.add(testButton); + mainPanel.add(buttonPanel, BorderLayout.SOUTH); + dialog.add(mainPanel); + dialog.pack(); + dialog.setVisible(true); + } +} diff --git a/jdk/test/java/awt/TrayIcon/ActionEventTest/ActionEventTest.java b/jdk/test/java/awt/TrayIcon/ActionEventTest/ActionEventTest.java new file mode 100644 index 0000000000000000000000000000000000000000..7a5f87a38f3409ab1efcb083f117a010234c84a8 --- /dev/null +++ b/jdk/test/java/awt/TrayIcon/ActionEventTest/ActionEventTest.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 6191390 + * @summary Verify that ActionEvent is received with correct modifiers set. + * @library ../../../../lib/testlibrary ../ + * @build ExtendedRobot SystemTrayIconHelper + */ + +import java.awt.Image; +import java.awt.TrayIcon; +import java.awt.SystemTray; +import java.awt.Robot; +import java.awt.EventQueue; +import java.awt.Point; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.image.BufferedImage; + +public class ActionEventTest { + + Image image; + TrayIcon icon; + Robot robot; + + public static void main(String[] args) throws Exception { + if (!SystemTray.isSupported()) { + System.out.println("SystemTray not supported on the platform." + + " Marking the test passed."); + } else { + if (System.getProperty("os.name").toLowerCase().startsWith("win")) { + System.err.println( + "Test can fail on Windows platform\n"+ + "On Windows 7, by default icon hides behind icon pool\n" + + "Due to which test might fail\n" + + "Set \"Right mouse click\" -> " + + "\"Customize notification icons\" -> \"Always show " + + "all icons and notifications on the taskbar\" true " + + "to avoid this problem.\nOR change behavior only for " + + "Java SE tray icon and rerun test."); + } + + ActionEventTest test = new ActionEventTest(); + test.doTest(); + test.clear(); + } + } + + public ActionEventTest() throws Exception { + robot = new Robot(); + EventQueue.invokeAndWait(this::initializeGUI); + } + + private void initializeGUI() { + + icon = new TrayIcon( + new BufferedImage(20, 20, BufferedImage.TYPE_INT_RGB), "ti"); + icon.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent ae) { + int md = ae.getModifiers(); + int expectedMask = ActionEvent.ALT_MASK | ActionEvent.CTRL_MASK + | ActionEvent.SHIFT_MASK; + + if ((md & expectedMask) != expectedMask) { + clear(); + throw new RuntimeException("Action Event modifiers are not" + + " set correctly."); + } + } + }); + + try { + SystemTray.getSystemTray().add(icon); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public void clear() { + SystemTray.getSystemTray().remove(icon); + } + + void doTest() throws Exception { + robot.keyPress(KeyEvent.VK_ALT); + robot.keyPress(KeyEvent.VK_SHIFT); + robot.keyPress(KeyEvent.VK_CONTROL); + + Point iconPosition = SystemTrayIconHelper.getTrayIconLocation(icon); + if (iconPosition == null) { + throw new RuntimeException("Unable to find the icon location!"); + } + + robot.mouseMove(iconPosition.x, iconPosition.y); + robot.waitForIdle(); + + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(100); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(100); + robot.waitForIdle(); + robot.keyRelease(KeyEvent.VK_ALT); + robot.keyRelease(KeyEvent.VK_SHIFT); + robot.keyRelease(KeyEvent.VK_CONTROL); + } +} diff --git a/jdk/test/java/awt/font/MonospacedGlyphWidth/MonospacedGlyphWidthTest.java b/jdk/test/java/awt/font/MonospacedGlyphWidth/MonospacedGlyphWidthTest.java new file mode 100644 index 0000000000000000000000000000000000000000..82dd8ab57f19346fe39f4ae927cbb35c85bd8839 --- /dev/null +++ b/jdk/test/java/awt/font/MonospacedGlyphWidth/MonospacedGlyphWidthTest.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 8073400 + * @summary Some Monospaced logical fonts have a different width + * @author Dmitry Markov + * @run main MonospacedGlyphWidthTest + */ +import java.awt.*; +import java.awt.font.FontRenderContext; + +public class MonospacedGlyphWidthTest { + private static final int START_INDEX = 0x2018; + private static final int END_INDEX = 0x201F; + + public static void main(String[] args) { + Font font = new Font(Font.MONOSPACED, Font.PLAIN, 12); + double width = getCharWidth(font, 'a'); + + for (int i = START_INDEX; i <= END_INDEX; i++) { + if (width != getCharWidth(font, (char)i)) { + throw new RuntimeException("Test Failed: characters have different width!"); + } + } + System.out.println("Test Passed!"); + } + + private static double getCharWidth(Font font, char c) { + FontRenderContext fontRenderContext = new FontRenderContext(null, false, false); + return font.getStringBounds(new char[] {c}, 0, 1, fontRenderContext).getWidth(); + } +} + diff --git a/jdk/test/java/awt/image/RasterCreationTest.java b/jdk/test/java/awt/image/RasterCreationTest.java new file mode 100644 index 0000000000000000000000000000000000000000..885fb8da76dbfd88fe072d8e16d71b8ea050bb80 --- /dev/null +++ b/jdk/test/java/awt/image/RasterCreationTest.java @@ -0,0 +1,352 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Point; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferByte; +import java.awt.image.DataBufferDouble; +import java.awt.image.DataBufferFloat; +import java.awt.image.DataBufferInt; +import java.awt.image.DataBufferShort; +import java.awt.image.DataBufferUShort; +import java.awt.image.Raster; +import java.awt.image.SampleModel; +import java.awt.image.MultiPixelPackedSampleModel; +import java.awt.image.PixelInterleavedSampleModel; +import java.awt.image.SinglePixelPackedSampleModel; + +/* + * @test + * @bug 6353518 + * @summary Test possible combinations of Raster creation + * Test fails if any of Raster.createXXX() method throws exception. + */ +public class RasterCreationTest { + + public static void main(String[] args) { + + final int width = 10; + final int height = 5; + final int imageSize = width * height; + Point location = new Point(0, 0); + int[] bandOffsets = {0}; + int[] bitMask = {0x00ff0000, 0x0000ff00, 0xff, 0x0}; + + SampleModel[] inputSampleModels = { + new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE, + 1, 1, 1, 1, bandOffsets), + new PixelInterleavedSampleModel(DataBuffer.TYPE_USHORT, + 1, 1, 1, 1, bandOffsets), + new PixelInterleavedSampleModel(DataBuffer.TYPE_INT, + 1, 1, 1, 1, bandOffsets), + new SinglePixelPackedSampleModel(DataBuffer.TYPE_BYTE, + width, height, bitMask), + new SinglePixelPackedSampleModel(DataBuffer.TYPE_USHORT, + width, height, bitMask), + new SinglePixelPackedSampleModel(DataBuffer.TYPE_INT, + width, height, bitMask), + new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE, + width, height, 4), + new MultiPixelPackedSampleModel(DataBuffer.TYPE_USHORT, + width, height, 2), + new MultiPixelPackedSampleModel(DataBuffer.TYPE_INT, + width, height, 2) + }; + + // --------------------------------------------------------------------- + // Test ability to create Raster & WritableRaster with DataBuffer + // classes + // --------------------------------------------------------------------- + DataBuffer[] inputDataBuffer = { + new DataBufferByte(imageSize), + new DataBufferUShort(imageSize), + new DataBufferInt(imageSize, 1), + new DataBufferShort(imageSize), + new DataBufferFloat(imageSize), + new DataBufferDouble(imageSize) + }; + + for (SampleModel sm : inputSampleModels) { + for (DataBuffer db : inputDataBuffer) { + // Test Raster creation + Raster.createRaster(sm, db, location); + + // Test writableRaster creation + Raster.createWritableRaster(sm, db, location); + Raster.createWritableRaster(sm, location); + } + } + + // --------------------------------------------------------------------- + // Test ability to create Raster & WritableRaster with custom DataBuffer + // classes + // --------------------------------------------------------------------- + DataBuffer[] myDataBuffer = { + new MyDataBufferByte(imageSize), + new MyDataBufferUShort(imageSize), + new MyDataBufferInt(imageSize), + new MyDataBufferShort(imageSize), + new MyDataBufferDouble(imageSize), + new MyDataBufferFloat(imageSize) + }; + + for (SampleModel sm : inputSampleModels) { + for (DataBuffer db : myDataBuffer) { + // Test Raster creation + Raster.createRaster(sm, db, location); + + // Test writableRaster creation + Raster.createWritableRaster(sm, db, location); + Raster.createWritableRaster(sm, location); + } + } + + // --------------------------------------------------------------------- + // Test ability to create InterleavedRaster + // --------------------------------------------------------------------- + int[] interleavedInputDataTypes = { + DataBuffer.TYPE_BYTE, + DataBuffer.TYPE_USHORT + }; + + int numBands = 1; + + for (int i : interleavedInputDataTypes) { + Raster.createInterleavedRaster(i, width, height, 1, location); + Raster.createInterleavedRaster(i, width, height, width * numBands, + numBands, bandOffsets, location); + } + + for (int i = 0; i < interleavedInputDataTypes.length ; i++) { + DataBuffer d1 = inputDataBuffer[i]; + DataBuffer d2 = myDataBuffer[i]; + + Raster.createInterleavedRaster(d1, width, height, width * numBands, + numBands, bandOffsets, location); + Raster.createInterleavedRaster(d2, width, height, width * numBands, + numBands, bandOffsets, location); + } + + // --------------------------------------------------------------------- + // Test ability to create BandedRaster + // --------------------------------------------------------------------- + int[] bankIndices = new int[numBands]; + bankIndices[0] = 0; + + int[] bandedInputDataTypes = { + DataBuffer.TYPE_BYTE, + DataBuffer.TYPE_USHORT, + DataBuffer.TYPE_INT + }; + + for (int i : bandedInputDataTypes) { + Raster.createBandedRaster(i, width, height, 1, location); + Raster.createBandedRaster(i, width, height, width, + bankIndices, bandOffsets, location); + } + + for (int i = 0; i < bandedInputDataTypes.length; i++) { + DataBuffer d1 = inputDataBuffer[i]; + DataBuffer d2 = myDataBuffer[i]; + + Raster.createBandedRaster(d1, width, height, width, + bankIndices, bandOffsets, location); + Raster.createBandedRaster(d2, width, height, width, + bankIndices, bandOffsets, location); + } + + // --------------------------------------------------------------------- + // Test ability to create PackedRaster + // --------------------------------------------------------------------- + int[] bandMasks = new int[numBands]; + bandMasks[0] = 0; + + int packedInputDataTypes[] = { + DataBuffer.TYPE_BYTE, + DataBuffer.TYPE_USHORT, + DataBuffer.TYPE_INT + }; + + for (int i : packedInputDataTypes) { + Raster.createPackedRaster(i, width, height, bandMasks, location); + + for (int bits = 1; bits < 5; bits *= 2) { + Raster.createPackedRaster(i, width, height, 1, bits, location); + } + } + + for (int i = 0; i < packedInputDataTypes.length; i++) { + DataBuffer d1 = inputDataBuffer[i]; + DataBuffer d2 = myDataBuffer[i]; + + for (int bits = 1; bits < 5; bits *= 2) { + Raster.createPackedRaster(d1, width, height, bits, location); + Raster.createPackedRaster(d2, width, height, bits, location); + } + + Raster.createPackedRaster(d1, width, height, 1,bandMasks, location); + Raster.createPackedRaster(d2, width, height, 1,bandMasks, location); + } + } +} + +// --------------------------------------------------------------------- +// Custom DataBuffer classes for testing purpose +// --------------------------------------------------------------------- +final class MyDataBufferByte extends DataBuffer { + + byte[] data; + byte[][] bankdata; + + public MyDataBufferByte(int size) { + super(TYPE_BYTE, size); + data = new byte[size]; + bankdata = new byte[1][]; + bankdata[0] = data; + } + + @Override + public int getElem(int bank, int i) { + return bankdata[bank][i + offsets[bank]]; + } + + @Override + public void setElem(int bank, int i, int val) { + bankdata[bank][i + offsets[bank]] = (byte) val; + } +} + +final class MyDataBufferDouble extends DataBuffer { + + double[] data; + double[][] bankdata; + + public MyDataBufferDouble(int size) { + super(TYPE_DOUBLE, size); + data = new double[size]; + bankdata = new double[1][]; + bankdata[0] = data; + } + + @Override + public int getElem(int bank, int i) { + return (int) bankdata[bank][i + offsets[bank]]; + } + + @Override + public void setElem(int bank, int i, int val) { + bankdata[bank][i + offsets[bank]] = (double) val; + } +} + +final class MyDataBufferFloat extends DataBuffer { + + float[] data; + float[][] bankdata; + + public MyDataBufferFloat(int size) { + super(TYPE_FLOAT, size); + data = new float[size]; + bankdata = new float[1][]; + bankdata[0] = data; + } + + @Override + public int getElem(int bank, int i) { + return (int) bankdata[bank][i + offsets[bank]]; + } + + @Override + public void setElem(int bank, int i, int val) { + bankdata[bank][i + offsets[bank]] = (float) val; + } +} + +final class MyDataBufferShort extends DataBuffer { + + short[] data; + short[][] bankdata; + + public MyDataBufferShort(int size) { + super(TYPE_SHORT, size); + data = new short[size]; + bankdata = new short[1][]; + bankdata[0] = data; + } + + @Override + public int getElem(int bank, int i) { + return bankdata[bank][i + offsets[bank]]; + } + + @Override + public void setElem(int bank, int i, int val) { + bankdata[bank][i + offsets[bank]] = (short) val; + } +} + +final class MyDataBufferUShort extends DataBuffer { + + short[] data; + short[][] bankdata; + + public MyDataBufferUShort(int size) { + super(TYPE_USHORT, size); + data = new short[size]; + bankdata = new short[1][]; + bankdata[0] = data; + } + + @Override + public int getElem(int bank, int i) { + return bankdata[bank][i + offsets[bank]]; + } + + @Override + public void setElem(int bank, int i, int val) { + bankdata[bank][i + offsets[bank]] = (short) val; + } +} + +final class MyDataBufferInt extends DataBuffer { + + int[] data; + int[][] bankdata; + + public MyDataBufferInt(int size) { + super(TYPE_INT, size); + data = new int[size]; + bankdata = new int[1][]; + bankdata[0] = data; + } + + @Override + public int getElem(int bank, int i) { + return bankdata[bank][i + offsets[bank]]; + } + + @Override + public void setElem(int bank, int i, int val) { + bankdata[bank][i + offsets[bank]] = (int) val; + } +} diff --git a/jdk/test/java/awt/image/multiresolution/MultiResolutionTrayIconTest/MultiResolutionTrayIconTest.java b/jdk/test/java/awt/image/multiresolution/MultiResolutionTrayIconTest/MultiResolutionTrayIconTest.java index 87a6de009172928c27d1d3ba0da514ecb3c95089..bb0a7525ec74a7aebe32f7d5714a62fe5c98cb76 100644 --- a/jdk/test/java/awt/image/multiresolution/MultiResolutionTrayIconTest/MultiResolutionTrayIconTest.java +++ b/jdk/test/java/awt/image/multiresolution/MultiResolutionTrayIconTest/MultiResolutionTrayIconTest.java @@ -24,8 +24,7 @@ /* @test - @bug 8150176 - @ignore 8150176 + @bug 8150176 8151773 @summary Check if correct resolution variant is used for tray icon. @author a.stepanov @run applet/manual=yesno MultiResolutionTrayIconTest.html diff --git a/jdk/test/java/awt/print/PrinterJob/DlgAttrsBug.java b/jdk/test/java/awt/print/PrinterJob/DlgAttrsBug.java new file mode 100644 index 0000000000000000000000000000000000000000..dc31ffda1fdf25f28d17e2966387546f1e0ac5d7 --- /dev/null +++ b/jdk/test/java/awt/print/PrinterJob/DlgAttrsBug.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 8061258 + * @summary PrinterJob's native Print Dialog does not reflect + * specified Copies or Page Ranges + * @run main/manual DlgAttrsBug + */ +import java.awt.BorderLayout; +import java.awt.FlowLayout; +import java.awt.Graphics; +import java.awt.print.PageFormat; +import java.awt.print.Printable; +import java.awt.print.PrinterException; +import java.awt.print.PrinterJob; +import javax.print.attribute.HashPrintRequestAttributeSet; +import javax.print.attribute.PrintRequestAttributeSet; +import javax.print.attribute.standard.Copies; +import javax.print.attribute.standard.PageRanges; +import javax.print.attribute.standard.DialogTypeSelection; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JPanel; +import javax.swing.JTextArea; +import javax.swing.SwingUtilities; + + +public class DlgAttrsBug implements Printable { + private static Thread mainThread; + private static boolean testPassed; + private static boolean testGeneratedInterrupt; + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(() -> { + doTest(DlgAttrsBug::printTest); + }); + mainThread = Thread.currentThread(); + try { + Thread.sleep(30000); + } catch (InterruptedException e) { + if (!testPassed && testGeneratedInterrupt) { + throw new RuntimeException("Print Dialog does not " + + "reflect Copies or Page Ranges"); + } + } + if (!testGeneratedInterrupt) { + throw new RuntimeException("user has not executed the test"); + } + } + + private static void printTest() { + PrinterJob job = PrinterJob.getPrinterJob(); + if (job.getPrintService() == null) { + System.out.println("No printers. Test cannot continue"); + return; + } + job.setPrintable(new DlgAttrsBug()); + PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet(); + aset.add(new Copies(5)); + aset.add(new PageRanges(3,4)); + aset.add(DialogTypeSelection.NATIVE); + job.printDialog(aset); + } + + public static synchronized void pass() { + testPassed = true; + testGeneratedInterrupt = true; + mainThread.interrupt(); + } + + public static synchronized void fail() { + testPassed = false; + testGeneratedInterrupt = true; + mainThread.interrupt(); + } + + private static void doTest(Runnable action) { + String description + = " Visual inspection of print dialog is required.\n" + + " A print dialog will be shown.\n " + + " Please verify Copies 5 is selected.\n" + + " Also verify, Page Range is selected with " + + " from page 3 and to Page 4.\n" + + " If ok, press PASS else press FAIL"; + + final JDialog dialog = new JDialog(); + dialog.setTitle("printSelectionTest"); + JTextArea textArea = new JTextArea(description); + textArea.setEditable(false); + final JButton testButton = new JButton("Start Test"); + final JButton passButton = new JButton("PASS"); + passButton.setEnabled(false); + passButton.addActionListener((e) -> { + dialog.dispose(); + pass(); + }); + final JButton failButton = new JButton("FAIL"); + failButton.setEnabled(false); + failButton.addActionListener((e) -> { + dialog.dispose(); + fail(); + }); + testButton.addActionListener((e) -> { + testButton.setEnabled(false); + action.run(); + passButton.setEnabled(true); + failButton.setEnabled(true); + }); + JPanel mainPanel = new JPanel(new BorderLayout()); + mainPanel.add(textArea, BorderLayout.CENTER); + JPanel buttonPanel = new JPanel(new FlowLayout()); + buttonPanel.add(testButton); + buttonPanel.add(passButton); + buttonPanel.add(failButton); + mainPanel.add(buttonPanel, BorderLayout.SOUTH); + dialog.add(mainPanel); + dialog.pack(); + dialog.setVisible(true); + } + + public int print(Graphics g, PageFormat pf, int pi) + throws PrinterException { + System.out.println("pi = " + pi); + if (pi >= 5) { + return NO_SUCH_PAGE; + } + g.drawString("Page : " + (pi+1), 200, 200); + return PAGE_EXISTS; + } + +} diff --git a/jdk/test/java/awt/print/PrinterJob/PrintAttributeUpdateTest.java b/jdk/test/java/awt/print/PrinterJob/PrintAttributeUpdateTest.java new file mode 100644 index 0000000000000000000000000000000000000000..f068964c4e1ecfcee719d087b433a7d5ecdef4c7 --- /dev/null +++ b/jdk/test/java/awt/print/PrinterJob/PrintAttributeUpdateTest.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 8042713 + @summary Print Dialog does not update attribute set with page range + @run main/manual PrintAttributeUpdateTest + */ +import java.awt.Component; +import java.awt.Graphics; +import java.awt.print.PageFormat; +import java.awt.print.Pageable; +import java.awt.print.Printable; +import java.awt.print.PrinterJob; +import javax.print.attribute.Attribute; +import javax.print.attribute.HashPrintRequestAttributeSet; +import javax.print.attribute.standard.DialogTypeSelection; +import javax.print.attribute.standard.PageRanges; +import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; + +public class PrintAttributeUpdateTest implements Pageable, Printable { + + public static void main(String args[]) throws Exception { + String[] instructions + = { + "Select Pages Range From instead of All in print dialog. ", + "Then select Print" + }; + SwingUtilities.invokeAndWait(() -> { + JOptionPane.showMessageDialog((Component) null, + instructions, "Instructions", + JOptionPane.INFORMATION_MESSAGE); + }); + HashPrintRequestAttributeSet as = new HashPrintRequestAttributeSet(); + PrinterJob j = PrinterJob.getPrinterJob(); + j.setPageable(new PrintAttributeUpdateTest()); + as.add(DialogTypeSelection.NATIVE); + j.printDialog(as); + if (as.containsKey(PageRanges.class) == false) { + throw new RuntimeException("Print Dialog did not update " + + " attribute set with page range"); + } + Attribute attrs[] = as.toArray(); + for (int i = 0; i < attrs.length; i++) { + System.out.println("attr " + attrs[i]); + } + j.print(as); + } + + public int getNumberOfPages() { + return UNKNOWN_NUMBER_OF_PAGES; + } + + public PageFormat getPageFormat(int pageIndex) { + PageFormat pf = new PageFormat(); + return pf; + } + + public Printable getPrintable(int pageIndex) { + return this; + } + + public int print(Graphics g, PageFormat pgFmt, int pi) { + g.drawString("Page : " + (pi + 1), 200, 200); + + return PAGE_EXISTS; + } + +} diff --git a/jdk/test/java/awt/xembed/server/TestXEmbedServerJava.java b/jdk/test/java/awt/xembed/server/TestXEmbedServerJava.java index 75898f4cbfea97d4794fac511b89374a080369cd..8e0c3d6774e979578f6a110407cd233c93950683 100644 --- a/jdk/test/java/awt/xembed/server/TestXEmbedServerJava.java +++ b/jdk/test/java/awt/xembed/server/TestXEmbedServerJava.java @@ -76,7 +76,23 @@ public class TestXEmbedServerJava extends TestXEmbedServer { public Process startClient(Rectangle[] bounds, long window) { try { String java_home = System.getProperty("java.home"); - return Runtime.getRuntime().exec(java_home + "/bin/java -XaddExports:java.desktop/sun.awt.X11=ALL-UNNAMED JavaClient " + window); + boolean hasModules = true; + try { + Class.class.getMethod("getModule"); + }catch(Exception hasModulesEx) { + hasModules = false; + } + if (hasModules) { + System.out.println(java_home + + "/bin/java -XaddExports:java.desktop/sun.awt.X11=ALL-UNNAMED "+ + "-XaddExports:java.desktop/sun.awt=ALL-UNNAMED JavaClient " + window); + return Runtime.getRuntime().exec(java_home + + "/bin/java -XaddExports:java.desktop/sun.awt.X11=ALL-UNNAMED "+ + "-XaddExports:java.desktop/sun.awt=ALL-UNNAMED JavaClient " + window); + }else{ + System.out.println(java_home + "/bin/java JavaClient " + window); + return Runtime.getRuntime().exec(java_home + "/bin/java JavaClient " + window); + } } catch (IOException ex1) { ex1.printStackTrace(); } diff --git a/jdk/test/java/lang/Class/GetPackageTest.java b/jdk/test/java/lang/Class/GetPackageTest.java index d1ffea75ecbbfb8020fe8ab96911e3ecdb2151f2..f9cb5fb31ff94e0cc76b165f06cbed919d040ab0 100644 --- a/jdk/test/java/lang/Class/GetPackageTest.java +++ b/jdk/test/java/lang/Class/GetPackageTest.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,7 +52,7 @@ public class GetPackageTest { assertEquals(fooClass.getClassLoader(), loader); } - @DataProvider(name = "testclasses") + @DataProvider(name = "testClasses") public Object[][] testClasses() { return new Object[][] { // primitive type, void, array types diff --git a/jdk/test/java/lang/StackWalker/DumpStackTest.java b/jdk/test/java/lang/StackWalker/DumpStackTest.java index e15a289381f2d30d2c4d5a7fa7f8e862c5bca995..c0ff99f9f681a4f42828c938e7f4b703cf0d5a1c 100644 --- a/jdk/test/java/lang/StackWalker/DumpStackTest.java +++ b/jdk/test/java/lang/StackWalker/DumpStackTest.java @@ -28,9 +28,6 @@ * This test should also been run against jdk9 successfully except of * VM option MemberNameInStackFrame. * @run main/othervm DumpStackTest - * @run main/othervm -Dstackwalk.newThrowable=false DumpStackTest - * @run main/othervm -Dstackwalk.newThrowable=true -XX:-MemberNameInStackFrame DumpStackTest - * @run main/othervm -Dstackwalk.newThrowable=true -XX:+MemberNameInStackFrame DumpStackTest */ import java.lang.invoke.MethodHandle; diff --git a/jdk/test/java/lang/StackWalker/GetCallerClassTest.java b/jdk/test/java/lang/StackWalker/GetCallerClassTest.java index 53a3f70c52a77afc6f56f8d9f3f15fc4ab170e65..8276d721087c183b94c474a83f343084a87dd700 100644 --- a/jdk/test/java/lang/StackWalker/GetCallerClassTest.java +++ b/jdk/test/java/lang/StackWalker/GetCallerClassTest.java @@ -25,8 +25,7 @@ * @test * @bug 8140450 * @summary Basic test for StackWalker.getCallerClass() - * @run main/othervm -XX:-MemberNameInStackFrame GetCallerClassTest - * @run main/othervm -XX:+MemberNameInStackFrame GetCallerClassTest + * @run main/othervm GetCallerClassTest * @run main/othervm GetCallerClassTest sm */ diff --git a/jdk/test/java/lang/StackWalker/StackWalkTest.java b/jdk/test/java/lang/StackWalker/StackWalkTest.java index b2f657f7cfa8813d62a1c2a6467e3ba54746ede2..711bd4bd5840e68ac39d3c52710fe387fd1f6d8c 100644 --- a/jdk/test/java/lang/StackWalker/StackWalkTest.java +++ b/jdk/test/java/lang/StackWalker/StackWalkTest.java @@ -44,10 +44,6 @@ import jdk.testlibrary.RandomFactory; * @run main/othervm/java.security.policy=stackwalktest.policy StackWalkTest * @run main/othervm StackWalkTest -random:50 * @run main/othervm/java.security.policy=stackwalktest.policy StackWalkTest -random:50 - * @run main/othervm -XX:-MemberNameInStackFrame -Dstackwalk.newThrowable=false StackWalkTest -random:50 - * @run main/othervm -XX:-MemberNameInStackFrame -Dstackwalk.newThrowable=true StackWalkTest -random:50 - * @run main/othervm -XX:+MemberNameInStackFrame -Dstackwalk.newThrowable=false StackWalkTest -random:50 - * @run main/othervm -XX:+MemberNameInStackFrame -Dstackwalk.newThrowable=true StackWalkTest -random:50 * @author danielfuchs, bchristi * @key randomness */ diff --git a/jdk/test/java/lang/StackWalker/VerifyStackTrace.java b/jdk/test/java/lang/StackWalker/VerifyStackTrace.java index d68f91c0257c77908eefeac493efd6a9e29d8e44..7d5c978b59fb3c0c65ce31c7a2272bec374a2e2d 100644 --- a/jdk/test/java/lang/StackWalker/VerifyStackTrace.java +++ b/jdk/test/java/lang/StackWalker/VerifyStackTrace.java @@ -40,8 +40,7 @@ import static java.lang.StackWalker.Option.*; * @summary Verify stack trace information obtained with respect to StackWalker * options, when the stack contains lambdas, method handle invoke * virtual calls, and reflection. - * @run main/othervm -XX:-MemberNameInStackFrame VerifyStackTrace - * @run main/othervm -XX:+MemberNameInStackFrame VerifyStackTrace + * @run main/othervm VerifyStackTrace * @run main/othervm/java.security.policy=stackwalk.policy VerifyStackTrace * @author danielfuchs */ diff --git a/jdk/test/java/lang/invoke/LoopCombinatorTest.java b/jdk/test/java/lang/invoke/LoopCombinatorTest.java index 71e4b0e89d891c4ee29f72dff81468f052f84d1a..625e55c611dc4792fe7963f55bf7f00e3d827763 100644 --- a/jdk/test/java/lang/invoke/LoopCombinatorTest.java +++ b/jdk/test/java/lang/invoke/LoopCombinatorTest.java @@ -26,8 +26,12 @@ /* @test * @bug 8139885 * @bug 8150635 + * @bug 8150956 * @bug 8150957 + * @bug 8152667 * @bug 8153637 + * @bug 8154751 + * @bug 8154754 * @run testng/othervm -ea -esa test.java.lang.invoke.LoopCombinatorTest */ @@ -265,6 +269,28 @@ public class LoopCombinatorTest { assertEquals(v, w.i); } + @Test + public static void testWhileVoidInit() throws Throwable { + While w = new While(); + int v = 5; + MethodHandle loop = MethodHandles.whileLoop(While.MH_voidInit.bindTo(w), While.MH_voidPred.bindTo(w), + While.MH_voidBody.bindTo(w)); + assertEquals(While.MT_void, loop.type()); + loop.invoke(v); + assertEquals(v, w.i); + } + + @Test + public static void testDoWhileVoidInit() throws Throwable { + While w = new While(); + int v = 5; + MethodHandle loop = MethodHandles.doWhileLoop(While.MH_voidInit.bindTo(w), While.MH_voidBody.bindTo(w), + While.MH_voidPred.bindTo(w)); + assertEquals(While.MT_void, loop.type()); + loop.invoke(v); + assertEquals(v, w.i); + } + @Test public static void testCountedLoop() throws Throwable { // String s = "Lambdaman!"; for (int i = 0; i < 13; ++i) { s = "na " + s; } return s; => a variation on a well known theme @@ -274,6 +300,14 @@ public class LoopCombinatorTest { assertEquals("na na na na na na na na na na na na na Lambdaman!", loop.invoke("Lambdaman!")); } + @Test + public static void testCountedLoopVoidInit() throws Throwable { + MethodHandle fit5 = MethodHandles.constant(int.class, 5); + MethodHandle loop = MethodHandles.countedLoop(fit5, MethodHandles.zero(void.class), Counted.MH_printHello); + assertEquals(Counted.MT_countedPrinting, loop.type()); + loop.invoke(); + } + @Test public static void testCountedArrayLoop() throws Throwable { // int[] a = new int[]{0}; for (int i = 0; i < 13; ++i) { ++a[0]; } => a[0] == 13 @@ -293,6 +327,74 @@ public class LoopCombinatorTest { loop.invoke(); } + @Test + public static void testCountedLoopNullBody() throws Throwable { + MethodHandle h5 = MethodHandles.constant(int.class, 5); + MethodHandle h13 = MethodHandles.constant(int.class, 13); + MethodHandle loop = MethodHandles.countedLoop(h5, h13, null); + assertEquals(methodType(int.class), loop.type()); + assertEquals(13, loop.invoke()); + } + + @Test + public static void testCountedLoopNullIterations() throws Throwable { + MethodHandle loop = MethodHandles.countedLoop(null, null, null); + assertEquals(methodType(void.class), loop.type()); + loop.invoke(); + } + + @Test + public static void testCountedLoopNullInitAndBody() throws Throwable { + MethodHandle loop = MethodHandles.countedLoop(MethodHandles.constant(int.class, 5), null, null); + assertEquals(methodType(void.class), loop.type()); + loop.invoke(); + } + + @DataProvider + static Object[][] countedLoopBodyParameters() { + return new Object[][] { + {methodType(String.class), methodType(String.class, int.class)}, + {methodType(String.class, List.class), methodType(String.class, int.class)}, + {methodType(String.class, List.class), methodType(String.class, int.class, String.class)} + }; + } + + @Test(dataProvider = "countedLoopBodyParameters") + public static void testCountedLoopBodyParameters(MethodType initType, MethodType bodyType) throws Throwable { + MethodHandle loop = MethodHandles.countedLoop(MethodHandles.constant(int.class, 5), + MethodHandles.empty(initType), MethodHandles.empty(bodyType)); + assertEquals(initType, loop.type()); + } + + @DataProvider + static Object[][] countedLoopTypes() { + return new Object[][]{{void.class}, {int.class}, {Object.class}, {String.class}, {List.class}}; + } + + @Test(dataProvider = "countedLoopTypes") + public static void testCountedLoopBodyParametersNullInit(Class t) throws Throwable { + MethodHandle loop = MethodHandles.countedLoop(MethodHandles.constant(int.class, 5), null, + MethodHandles.empty(methodType(t, int.class))); + assertEquals(methodType(t), loop.type()); + loop.invoke(); + } + + @Test + public static void testCountedLoopStateDefinedByBody() throws Throwable { + MethodHandle loop = MethodHandles.countedLoop(MethodHandles.constant(int.class, 5), null, Counted.MH_stateBody); + assertEquals(Counted.MT_bodyDeterminesState, loop.type()); + assertEquals("sssssnull01234", loop.invoke()); + } + + @Test + public static void testCountedLoopArgsDefinedByIterations() throws Throwable { + MethodHandle loop = MethodHandles.countedLoop( + MethodHandles.dropArguments(MethodHandles.constant(int.class, 3), 0, String.class), + null, Counted.MH_append); + assertEquals(Counted.MT_iterationsDefineArgs, loop.type()); + assertEquals("hello012", loop.invoke("hello")); + } + @Test public static void testCountedRangeLoop() throws Throwable { // String s = "Lambdaman!"; for (int i = -5; i < 8; ++i) { s = "na " + s; } return s; => a well known theme @@ -315,6 +417,23 @@ public class LoopCombinatorTest { assertEquals(10, loop.invoke()); } + @Test + public static void testCountedLoopEmpty() throws Throwable { + // for (int i = 0; i < 5; ++i) { /* empty */ } + MethodHandle loop = MethodHandles.countedLoop(MethodHandles.constant(int.class, 5), null, null); + assertEquals(methodType(void.class), loop.type()); + loop.invoke(); + } + + @Test + public static void testCountedRangeLoopEmpty() throws Throwable { + // for (int i = -5; i < 5; ++i) { /* empty */ } + MethodHandle loop = MethodHandles.countedLoop(MethodHandles.constant(int.class, -5), + MethodHandles.constant(int.class, 5), null, null); + assertEquals(methodType(void.class), loop.type()); + loop.invoke(); + } + @Test public static void testIterateSum() throws Throwable { // Integer[] a = new Integer[]{1,2,3,4,5,6}; int sum = 0; for (int e : a) { sum += e; } return sum; => 21 @@ -360,7 +479,8 @@ public class LoopCombinatorTest { public static void testIterateNullBody() { boolean caught = false; try { - MethodHandles.iteratedLoop(MethodHandles.identity(int.class), MethodHandles.identity(int.class), null); + MethodHandles.iteratedLoop(MethodHandles.empty(methodType(Iterator.class, int.class)), + MethodHandles.identity(int.class), null); } catch (IllegalArgumentException iae) { assertEquals("iterated loop body must not be null", iae.getMessage()); caught = true; @@ -368,6 +488,102 @@ public class LoopCombinatorTest { assertTrue(caught); } + @DataProvider + static Object[][] wrongIteratorTypes() { + return new Object[][]{{void.class}, {Object.class}, {Iterable.class}}; + } + + @Test(dataProvider = "wrongIteratorTypes") + public static void testIterateVoidIterator(Class it) { + boolean caught = false; + MethodType v = methodType(it); + try { + MethodHandles.iteratedLoop(MethodHandles.empty(v), null, MethodHandles.empty(v)); + } catch(IllegalArgumentException iae) { + assertEquals("iteratedLoop first argument must have Iterator return type", iae.getMessage()); + caught = true; + } + assertTrue(caught); + } + + @Test + public static void testIterateVoidInit() throws Throwable { + MethodHandle loop = MethodHandles.iteratedLoop(null, Iterate.MH_voidInit, Iterate.MH_printStep); + assertEquals(Iterate.MT_print, loop.type()); + loop.invoke(Arrays.asList("hello", "world")); + } + + @DataProvider + static Object[][] iterateParameters() { + MethodType i = methodType(int.class); + MethodType sil_i = methodType(int.class, String.class, int.class, List.class); + MethodType sl_v = methodType(void.class, String.class, List.class); + MethodType l_it = methodType(Iterator.class, List.class); + MethodType li_it = methodType(Iterator.class, List.class, int.class); + MethodType l_i = methodType(int.class, List.class); + MethodType _it = methodType(Iterator.class); + MethodType si_i = methodType(int.class, String.class, int.class); + MethodType s_i = methodType(int.class, String.class); + return new Object[][]{ + {null, null, sl_v}, + {null, i, sil_i}, + {null, l_i, sil_i}, + {l_it, null, sl_v}, + {l_it, i, sil_i}, + {li_it, l_i, sil_i}, + {l_it, null, sil_i}, + {li_it, null, sl_v}, + {_it, l_i, si_i}, + {_it, l_i, s_i} + }; + } + + @Test(dataProvider = "iterateParameters") + public static void testIterateParameters(MethodType it, MethodType in, MethodType bo) throws Throwable { + MethodHandle iterator = it == null ? null : MethodHandles.empty(it); + MethodHandle init = in == null ? null : MethodHandles.empty(in); + MethodHandle loop = MethodHandles.iteratedLoop(iterator, init, MethodHandles.empty(bo)); + MethodType lt = loop.type(); + if (it == null && in == null) { + assertEquals(bo.dropParameterTypes(0, 1), lt); + } else if (it == null) { + if (in.parameterCount() == 0) { + assertEquals(bo.dropParameterTypes(0, in.returnType() == void.class ? 1 : 2), lt); + } else { + assertEquals(methodType(bo.returnType(), in.parameterArray()), lt); + } + } else if (in == null) { + assertEquals(methodType(bo.returnType(), it.parameterArray()), lt); + } else if (it.parameterCount() > in.parameterCount()) { + assertEquals(methodType(bo.returnType(), it.parameterArray()), lt); + } else if (it.parameterCount() < in.parameterCount()) { + assertEquals(methodType(bo.returnType(), in.parameterArray()), lt); + } else { + // both it, in present; with equal parameter list lengths + assertEquals(it.parameterList(), lt.parameterList()); + assertEquals(in.parameterList(), lt.parameterList()); + assertEquals(bo.returnType(), lt.returnType()); + } + } + + @Test + public static void testIteratorSubclass() throws Throwable { + MethodHandle loop = MethodHandles.iteratedLoop(MethodHandles.empty(methodType(BogusIterator.class, List.class)), + null, MethodHandles.empty(methodType(void.class, String.class))); + assertEquals(methodType(void.class, List.class), loop.type()); + } + + static class BogusIterator implements Iterator { + @Override + public boolean hasNext() { + return false; + } + @Override + public Object next() { + return null; + } + } + static class Empty { static void f() { } @@ -604,6 +820,10 @@ public class LoopCombinatorTest { private int i = 0; + void voidInit(int k) { + // empty + } + void voidBody(int k) { ++i; } @@ -623,6 +843,7 @@ public class LoopCombinatorTest { static final MethodType MT_zipInitZip = methodType(List.class, Iterator.class, Iterator.class); static final MethodType MT_zipPred = methodType(boolean.class, List.class, Iterator.class, Iterator.class); static final MethodType MT_zipStep = methodType(List.class, List.class, Iterator.class, Iterator.class); + static final MethodType MT_voidInit = methodType(void.class, int.class); static final MethodType MT_voidBody = methodType(void.class, int.class); static final MethodType MT_voidPred = methodType(boolean.class, int.class); @@ -635,6 +856,7 @@ public class LoopCombinatorTest { static final MethodHandle MH_zipInitZip; static final MethodHandle MH_zipPred; static final MethodHandle MH_zipStep; + static final MethodHandle MH_voidInit; static final MethodHandle MH_voidBody; static final MethodHandle MH_voidPred; @@ -654,6 +876,7 @@ public class LoopCombinatorTest { MH_zipInitZip = LOOKUP.findStatic(WHILE, "zipInitZip", MT_zipInitZip); MH_zipPred = LOOKUP.findStatic(WHILE, "zipPred", MT_zipPred); MH_zipStep = LOOKUP.findStatic(WHILE, "zipStep", MT_zipStep); + MH_voidInit = LOOKUP.findVirtual(WHILE, "voidInit", MT_voidInit); MH_voidBody = LOOKUP.findVirtual(WHILE, "voidBody", MT_voidBody); MH_voidPred = LOOKUP.findVirtual(WHILE, "voidPred", MT_voidPred); } catch (Exception e) { @@ -685,6 +908,17 @@ public class LoopCombinatorTest { return x + counter; } + static String stateBody(int counter, String s) { + return "s" + s + counter; + } + + static String append(int counter, String localState, String loopArg) { + if (null == localState) { + return loopArg + counter; + } + return localState + counter; + } + static final Class COUNTED = Counted.class; static final MethodType MT_start = methodType(String.class, String.class); @@ -692,6 +926,8 @@ public class LoopCombinatorTest { static final MethodType MT_stepUpdateArray = methodType(void.class, int.class, int[].class); static final MethodType MT_printHello = methodType(void.class, int.class); static final MethodType MT_addCounter = methodType(int.class, int.class, int.class); + static final MethodType MT_stateBody = methodType(String.class, int.class, String.class); + static final MethodType MT_append = methodType(String.class, int.class, String.class, String.class); static final MethodHandle MH_13; static final MethodHandle MH_m5; @@ -701,11 +937,15 @@ public class LoopCombinatorTest { static final MethodHandle MH_stepUpdateArray; static final MethodHandle MH_printHello; static final MethodHandle MH_addCounter; + static final MethodHandle MH_stateBody; + static final MethodHandle MH_append; static final MethodType MT_counted = methodType(String.class, String.class); static final MethodType MT_arrayCounted = methodType(void.class, int[].class); static final MethodType MT_countedPrinting = methodType(void.class); static final MethodType MT_counterInit = methodType(int.class); + static final MethodType MT_bodyDeterminesState = methodType(String.class); + static final MethodType MT_iterationsDefineArgs = methodType(String.class, String.class); static { try { @@ -717,6 +957,8 @@ public class LoopCombinatorTest { MH_stepUpdateArray = LOOKUP.findStatic(COUNTED, "stepUpdateArray", MT_stepUpdateArray); MH_printHello = LOOKUP.findStatic(COUNTED, "printHello", MT_printHello); MH_addCounter = LOOKUP.findStatic(COUNTED, "addCounter", MT_addCounter); + MH_stateBody = LOOKUP.findStatic(COUNTED, "stateBody", MT_stateBody); + MH_append = LOOKUP.findStatic(COUNTED, "append", MT_append); } catch (Exception e) { throw new ExceptionInInitializerError(e); } @@ -768,6 +1010,10 @@ public class LoopCombinatorTest { System.out.print(s); } + static void voidInit() { + // empty + } + static final Class ITERATE = Iterate.class; static final MethodType MT_sumIterator = methodType(Iterator.class, Integer[].class); @@ -783,6 +1029,8 @@ public class LoopCombinatorTest { static final MethodType MT_mapStep = methodType(List.class, String.class, List.class, List.class); static final MethodType MT_printStep = methodType(void.class, String.class, List.class); + static final MethodType MT_voidInit = methodType(void.class); + static final MethodHandle MH_sumIterator; static final MethodHandle MH_sumInit; static final MethodHandle MH_sumStep; @@ -797,6 +1045,8 @@ public class LoopCombinatorTest { static final MethodHandle MH_mapInit; static final MethodHandle MH_mapStep; + static final MethodHandle MH_voidInit; + static final MethodType MT_sum = methodType(int.class, Integer[].class); static final MethodType MT_reverse = methodType(List.class, List.class); static final MethodType MT_length = methodType(int.class, List.class); @@ -815,6 +1065,7 @@ public class LoopCombinatorTest { MH_mapInit = LOOKUP.findStatic(ITERATE, "mapInit", MT_mapInit); MH_mapStep = LOOKUP.findStatic(ITERATE, "mapStep", MT_mapStep); MH_printStep = LOOKUP.findStatic(ITERATE, "printStep", MT_printStep); + MH_voidInit = LOOKUP.findStatic(ITERATE, "voidInit", MT_voidInit); } catch (Exception e) { throw new ExceptionInInitializerError(e); } diff --git a/jdk/test/java/net/NetworkInterface/NetworkInterfaceStreamTest.java b/jdk/test/java/net/NetworkInterface/NetworkInterfaceStreamTest.java index 7d8646d5361afde9aa38569942750f55453c245e..1fa3a55794103cdb5a286432b3edc648bc0030f1 100644 --- a/jdk/test/java/net/NetworkInterface/NetworkInterfaceStreamTest.java +++ b/jdk/test/java/net/NetworkInterface/NetworkInterfaceStreamTest.java @@ -28,7 +28,6 @@ * @build java.base/java.util.stream.OpTestCase * @run testng/othervm NetworkInterfaceStreamTest * @run testng/othervm -Djava.net.preferIPv4Stack=true NetworkInterfaceStreamTest - * @key intermittent */ import org.testng.annotations.Test; @@ -52,21 +51,27 @@ public class NetworkInterfaceStreamTest extends OpTestCase { public void testNetworkInterfaces() throws SocketException { Supplier> ss = () -> { try { - return NetworkInterface.networkInterfaces(); + return NetworkInterface.networkInterfaces() + .filter(ni -> isIncluded(ni)); } catch (SocketException e) { throw new RuntimeException(e); } }; - Collection expected = Collections.list(NetworkInterface.getNetworkInterfaces()); + Collection enums = Collections.list(NetworkInterface.getNetworkInterfaces()); + Collection expected = new ArrayList<>(); + enums.forEach(ni -> { + if (isIncluded(ni)) { + expected.add(ni); + } + }); withData(TestData.Factory.ofSupplier("Top-level network interfaces", ss)) .stream(s -> s) .expectedResult(expected) .exercise(); } - private Collection getAllNetworkInterfaces() throws SocketException { Collection anis = new ArrayList<>(); for (NetworkInterface ni : Collections.list(NetworkInterface.getNetworkInterfaces())) { diff --git a/jdk/test/java/net/httpclient/http2/HpackDriver.java b/jdk/test/java/net/httpclient/http2/HpackDriver.java new file mode 100644 index 0000000000000000000000000000000000000000..3bf1bc39a4bf52433fa02a26c2dae54321c19b9a --- /dev/null +++ b/jdk/test/java/net/httpclient/http2/HpackDriver.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 8153353 + * @modules java.httpclient/sun.net.httpclient.hpack + * @key randomness + * @compile/module=java.httpclient sun/net/httpclient/hpack/SpecHelper.java + * @compile/module=java.httpclient sun/net/httpclient/hpack/TestHelper.java + * @compile/module=java.httpclient sun/net/httpclient/hpack/BuffersTestingKit.java + * @run testng/othervm -XaddReads:java.httpclient=ALL-UNNAMED java.httpclient/sun.net.httpclient.hpack.BinaryPrimitivesTest + * @run testng/othervm -XaddReads:java.httpclient=ALL-UNNAMED java.httpclient/sun.net.httpclient.hpack.CircularBufferTest + * @run testng/othervm -XaddReads:java.httpclient=ALL-UNNAMED java.httpclient/sun.net.httpclient.hpack.DecoderTest + * @run testng/othervm -XaddReads:java.httpclient=ALL-UNNAMED java.httpclient/sun.net.httpclient.hpack.EncoderTest + * @run testng/othervm -XaddReads:java.httpclient=ALL-UNNAMED java.httpclient/sun.net.httpclient.hpack.HeaderTableTest + * @run testng/othervm -XaddReads:java.httpclient=ALL-UNNAMED java.httpclient/sun.net.httpclient.hpack.HuffmanTest + * @run testng/othervm -XaddReads:java.httpclient=ALL-UNNAMED java.httpclient/sun.net.httpclient.hpack.TestHelper + */ +public class HpackDriver { } diff --git a/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/BinaryPrimitivesTest.java b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/BinaryPrimitivesTest.java new file mode 100644 index 0000000000000000000000000000000000000000..dedd53329a83f7f650a4f5862ef7274d388089cd --- /dev/null +++ b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/BinaryPrimitivesTest.java @@ -0,0 +1,347 @@ +/* + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 sun.net.httpclient.hpack; + +import org.testng.annotations.Test; + +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.fail; +import static sun.net.httpclient.hpack.BuffersTestingKit.*; +import static sun.net.httpclient.hpack.TestHelper.newRandom; + +// +// Some of the tests below overlap in what they test. This allows to diagnose +// bugs quicker and with less pain by simply ruling out common working bits. +// +public final class BinaryPrimitivesTest { + + private final Random rnd = newRandom(); + + @Test + public void integerRead1() { + verifyRead(bytes(0b00011111, 0b10011010, 0b00001010), 1337, 5); + } + + @Test + public void integerRead2() { + verifyRead(bytes(0b00001010), 10, 5); + } + + @Test + public void integerRead3() { + verifyRead(bytes(0b00101010), 42, 8); + } + + @Test + public void integerWrite1() { + verifyWrite(bytes(0b00011111, 0b10011010, 0b00001010), 1337, 5); + } + + @Test + public void integerWrite2() { + verifyWrite(bytes(0b00001010), 10, 5); + } + + @Test + public void integerWrite3() { + verifyWrite(bytes(0b00101010), 42, 8); + } + + // + // Since readInteger(x) is the inverse of writeInteger(x), thus: + // + // for all x: readInteger(writeInteger(x)) == x + // + @Test + public void integerIdentity() { + final int MAX_VALUE = 1 << 22; + int totalCases = 0; + int maxFilling = 0; + IntegerReader r = new IntegerReader(); + IntegerWriter w = new IntegerWriter(); + ByteBuffer buf = ByteBuffer.allocate(8); + for (int N = 1; N < 9; N++) { + for (int expected = 0; expected <= MAX_VALUE; expected++) { + w.reset().configure(expected, N, 1).write(buf); + buf.flip(); + totalCases++; + maxFilling = Math.max(maxFilling, buf.remaining()); + r.reset().configure(N).read(buf); + assertEquals(r.get(), expected); + buf.clear(); + } + } + System.out.printf("totalCases: %,d, maxFilling: %,d, maxValue: %,d%n", + totalCases, maxFilling, MAX_VALUE); + } + + @Test + public void integerReadChunked() { + final int NUM_TESTS = 1024; + IntegerReader r = new IntegerReader(); + ByteBuffer bb = ByteBuffer.allocate(8); + IntegerWriter w = new IntegerWriter(); + for (int i = 0; i < NUM_TESTS; i++) { + final int N = 1 + rnd.nextInt(8); + final int expected = rnd.nextInt(Integer.MAX_VALUE) + 1; + w.reset().configure(expected, N, rnd.nextInt()).write(bb); + bb.flip(); + + forEachSplit(bb, + (buffers) -> { + Iterable buf = relocateBuffers(injectEmptyBuffers(buffers)); + r.configure(N); + for (ByteBuffer b : buf) { + r.read(b); + } + assertEquals(r.get(), expected); + r.reset(); + }); + bb.clear(); + } + } + + // FIXME: use maxValue in the test + + @Test + // FIXME: tune values for better coverage + public void integerWriteChunked() { + ByteBuffer bb = ByteBuffer.allocate(6); + IntegerWriter w = new IntegerWriter(); + IntegerReader r = new IntegerReader(); + for (int i = 0; i < 1024; i++) { // number of tests + final int N = 1 + rnd.nextInt(8); + final int payload = rnd.nextInt(255); + final int expected = rnd.nextInt(Integer.MAX_VALUE) + 1; + + forEachSplit(bb, + (buffers) -> { + List buf = new ArrayList<>(); + relocateBuffers(injectEmptyBuffers(buffers)).forEach(buf::add); + boolean written = false; + w.configure(expected, N, payload); // TODO: test for payload it can be read after written + for (ByteBuffer b : buf) { + int pos = b.position(); + written = w.write(b); + b.position(pos); + } + if (!written) { + fail("please increase bb size"); + } + r.configure(N).read(concat(buf)); + // TODO: check payload here + assertEquals(r.get(), expected); + w.reset(); + r.reset(); + bb.clear(); + }); + } + } + + + // + // Since readString(x) is the inverse of writeString(x), thus: + // + // for all x: readString(writeString(x)) == x + // + @Test + public void stringIdentity() { + final int MAX_STRING_LENGTH = 4096; + ByteBuffer bytes = ByteBuffer.allocate(MAX_STRING_LENGTH + 6); // it takes 6 bytes to encode string length of Integer.MAX_VALUE + CharBuffer chars = CharBuffer.allocate(MAX_STRING_LENGTH); + StringReader reader = new StringReader(); + StringWriter writer = new StringWriter(); + for (int len = 0; len <= MAX_STRING_LENGTH; len++) { + for (int i = 0; i < 64; i++) { + // not so much "test in isolation", I know... we're testing .reset() as well + bytes.clear(); + chars.clear(); + + byte[] b = new byte[len]; + rnd.nextBytes(b); + + String expected = new String(b, StandardCharsets.ISO_8859_1); // reference string + + boolean written = writer + .configure(CharBuffer.wrap(expected), 0, expected.length(), false) + .write(bytes); + + if (!written) { + fail("please increase 'bytes' size"); + } + bytes.flip(); + reader.read(bytes, chars); + chars.flip(); + assertEquals(chars.toString(), expected); + reader.reset(); + writer.reset(); + } + } + } + +// @Test +// public void huffmanStringWriteChunked() { +// fail(); +// } +// +// @Test +// public void huffmanStringReadChunked() { +// fail(); +// } + + @Test + public void stringWriteChunked() { + final int MAX_STRING_LENGTH = 8; + final ByteBuffer bytes = ByteBuffer.allocate(MAX_STRING_LENGTH + 6); + final CharBuffer chars = CharBuffer.allocate(MAX_STRING_LENGTH); + final StringReader reader = new StringReader(); + final StringWriter writer = new StringWriter(); + for (int len = 0; len <= MAX_STRING_LENGTH; len++) { + + byte[] b = new byte[len]; + rnd.nextBytes(b); + + String expected = new String(b, StandardCharsets.ISO_8859_1); // reference string + + forEachSplit(bytes, (buffers) -> { + writer.configure(expected, 0, expected.length(), false); + boolean written = false; + for (ByteBuffer buf : buffers) { + int p0 = buf.position(); + written = writer.write(buf); + buf.position(p0); + } + if (!written) { + fail("please increase 'bytes' size"); + } + reader.read(concat(buffers), chars); + chars.flip(); + assertEquals(chars.toString(), expected); + reader.reset(); + writer.reset(); + chars.clear(); + bytes.clear(); + }); + } + } + + @Test + public void stringReadChunked() { + final int MAX_STRING_LENGTH = 16; + final ByteBuffer bytes = ByteBuffer.allocate(MAX_STRING_LENGTH + 6); + final CharBuffer chars = CharBuffer.allocate(MAX_STRING_LENGTH); + final StringReader reader = new StringReader(); + final StringWriter writer = new StringWriter(); + for (int len = 0; len <= MAX_STRING_LENGTH; len++) { + + byte[] b = new byte[len]; + rnd.nextBytes(b); + + String expected = new String(b, StandardCharsets.ISO_8859_1); // reference string + + boolean written = writer + .configure(CharBuffer.wrap(expected), 0, expected.length(), false) + .write(bytes); + writer.reset(); + + if (!written) { + fail("please increase 'bytes' size"); + } + bytes.flip(); + + forEachSplit(bytes, (buffers) -> { + for (ByteBuffer buf : buffers) { + int p0 = buf.position(); + reader.read(buf, chars); + buf.position(p0); + } + chars.flip(); + assertEquals(chars.toString(), expected); + reader.reset(); + chars.clear(); + }); + + bytes.clear(); + } + } + +// @Test +// public void test_Huffman_String_Identity() { +// StringWriter writer = new StringWriter(); +// StringReader reader = new StringReader(); +// // 256 * 8 gives 2048 bits in case of plain 8 bit coding +// // 256 * 30 gives you 7680 bits or 960 bytes in case of almost +// // improbable event of 256 30 bits symbols in a row +// ByteBuffer binary = ByteBuffer.allocate(960); +// CharBuffer text = CharBuffer.allocate(960 / 5); // 5 = minimum code length +// for (int len = 0; len < 128; len++) { +// for (int i = 0; i < 256; i++) { +// // not so much "test in isolation", I know... +// binary.clear(); +// +// byte[] bytes = new byte[len]; +// rnd.nextBytes(bytes); +// +// String s = new String(bytes, StandardCharsets.ISO_8859_1); +// +// writer.write(CharBuffer.wrap(s), binary, true); +// binary.flip(); +// reader.read(binary, text); +// text.flip(); +// assertEquals(text.toString(), s); +// } +// } +// } + + // TODO: atomic failures: e.g. readonly/overflow + + private static byte[] bytes(int... data) { + byte[] bytes = new byte[data.length]; + for (int i = 0; i < data.length; i++) { + bytes[i] = (byte) data[i]; + } + return bytes; + } + + private static void verifyRead(byte[] data, int expected, int N) { + ByteBuffer buf = ByteBuffer.wrap(data, 0, data.length); + IntegerReader reader = new IntegerReader(); + reader.configure(N).read(buf); + assertEquals(expected, reader.get()); + } + + private void verifyWrite(byte[] expected, int data, int N) { + IntegerWriter w = new IntegerWriter(); + ByteBuffer buf = ByteBuffer.allocate(2 * expected.length); + w.configure(data, N, 1).write(buf); + buf.flip(); + assertEquals(ByteBuffer.wrap(expected), buf); + } +} diff --git a/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/BuffersTestingKit.java b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/BuffersTestingKit.java new file mode 100644 index 0000000000000000000000000000000000000000..4f9631647c7900134e0122e160ba53da5290b057 --- /dev/null +++ b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/BuffersTestingKit.java @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 sun.net.httpclient.hpack; + +import java.nio.ByteBuffer; +import java.util.*; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; + +import static java.nio.ByteBuffer.allocate; + +public final class BuffersTestingKit { + + /** + * Relocates a {@code [position, limit)} region of the given buffer to + * corresponding region in a new buffer starting with provided {@code + * newPosition}. + * + *

    Might be useful to make sure ByteBuffer's users do not rely on any + * absolute positions, but solely on what's reported by position(), limit(). + * + *

    The contents between the given buffer and the returned one are not + * shared. + */ + public static ByteBuffer relocate(ByteBuffer buffer, int newPosition, + int newCapacity) { + int oldPosition = buffer.position(); + int oldLimit = buffer.limit(); + + if (newPosition + oldLimit - oldPosition > newCapacity) { + throw new IllegalArgumentException(); + } + + ByteBuffer result; + if (buffer.isDirect()) { + result = ByteBuffer.allocateDirect(newCapacity); + } else { + result = allocate(newCapacity); + } + + result.position(newPosition); + result.put(buffer).limit(result.position()).position(newPosition); + buffer.position(oldPosition); + + if (buffer.isReadOnly()) { + return result.asReadOnlyBuffer(); + } + return result; + } + + public static Iterable relocateBuffers( + Iterable source) { + return () -> + new Iterator() { + + private final Iterator it = source.iterator(); + + @Override + public boolean hasNext() { + return it.hasNext(); + } + + @Override + public ByteBuffer next() { + ByteBuffer buf = it.next(); + int remaining = buf.remaining(); + int newCapacity = remaining + random.nextInt(17); + int newPosition = random.nextInt(newCapacity - remaining + 1); + return relocate(buf, newPosition, newCapacity); + } + }; + } + + // TODO: not always of size 0 (it's fine for buffer to report !b.hasRemaining()) + public static Iterable injectEmptyBuffers( + Iterable source) { + return injectEmptyBuffers(source, () -> allocate(0)); + } + + public static Iterable injectEmptyBuffers( + Iterable source, + Supplier emptyBufferFactory) { + + return () -> + new Iterator() { + + private final Iterator it = source.iterator(); + private ByteBuffer next = calculateNext(); + + private ByteBuffer calculateNext() { + if (random.nextBoolean()) { + return emptyBufferFactory.get(); + } else if (it.hasNext()) { + return it.next(); + } else { + return null; + } + } + + @Override + public boolean hasNext() { + return next != null; + } + + @Override + public ByteBuffer next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + ByteBuffer next = this.next; + this.next = calculateNext(); + return next; + } + }; + } + + public static ByteBuffer concat(Iterable split) { + return concat(split, ByteBuffer::allocate); + } + + public static ByteBuffer concat(Iterable split, + Function concatBufferFactory) { + int size = 0; + for (ByteBuffer bb : split) { + size += bb.remaining(); + } + + ByteBuffer result = concatBufferFactory.apply(size); + for (ByteBuffer bb : split) { + result.put(bb); + } + + result.flip(); + return result; + } + + public static void forEachSplit(ByteBuffer bb, + Consumer> action) { + forEachSplit(bb.remaining(), + (lengths) -> { + int end = bb.position(); + List buffers = new LinkedList<>(); + for (int len : lengths) { + ByteBuffer d = bb.duplicate(); + d.position(end); + d.limit(end + len); + end += len; + buffers.add(d); + } + action.accept(buffers); + }); + } + + private static void forEachSplit(int n, Consumer> action) { + forEachSplit(n, new Stack<>(), action); + } + + private static void forEachSplit(int n, Stack path, + Consumer> action) { + if (n == 0) { + action.accept(path); + } else { + for (int i = 1; i <= n; i++) { + path.push(i); + forEachSplit(n - i, path, action); + path.pop(); + } + } + } + + private static final Random random = new Random(); + + private BuffersTestingKit() { + throw new InternalError(); + } + +// public static void main(String[] args) { +// +// List buffers = Arrays.asList( +// (ByteBuffer) allocate(3).position(1).limit(2), +// allocate(0), +// allocate(7)); +// +// Iterable buf = relocateBuffers(injectEmptyBuffers(buffers)); +// List result = new ArrayList<>(); +// buf.forEach(result::add); +// System.out.println(result); +// } +} diff --git a/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/CircularBufferTest.java b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/CircularBufferTest.java new file mode 100644 index 0000000000000000000000000000000000000000..ebf1cb1d1eebc7605bc9ac634583a9864167a658 --- /dev/null +++ b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/CircularBufferTest.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 sun.net.httpclient.hpack; + +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; +import sun.net.httpclient.hpack.HeaderTable.CircularBuffer; + +import java.util.Queue; +import java.util.Random; +import java.util.concurrent.ArrayBlockingQueue; + +import static org.testng.Assert.assertEquals; +import static sun.net.httpclient.hpack.TestHelper.newRandom; + +public final class CircularBufferTest { + + private final Random r = newRandom(); + + @BeforeClass + public void setUp() { + r.setSeed(System.currentTimeMillis()); + } + + @Test + public void queue() { + for (int capacity = 1; capacity <= 2048; capacity++) { + queueOnce(capacity, 32); + } + } + + @Test + public void resize() { + for (int capacity = 1; capacity <= 4096; capacity++) { + resizeOnce(capacity); + } + } + + @Test + public void downSizeEmptyBuffer() { + CircularBuffer buffer = new CircularBuffer<>(16); + buffer.resize(15); + } + + private void resizeOnce(int capacity) { + + int nextNumberToPut = 0; + + Queue referenceQueue = new ArrayBlockingQueue<>(capacity); + CircularBuffer buffer = new CircularBuffer<>(capacity); + + // Fill full, so the next add will wrap + for (int i = 0; i < capacity; i++, nextNumberToPut++) { + buffer.add(nextNumberToPut); + referenceQueue.add(nextNumberToPut); + } + int gets = r.nextInt(capacity); // [0, capacity) + for (int i = 0; i < gets; i++) { + referenceQueue.poll(); + buffer.remove(); + } + int puts = r.nextInt(gets + 1); // [0, gets] + for (int i = 0; i < puts; i++, nextNumberToPut++) { + buffer.add(nextNumberToPut); + referenceQueue.add(nextNumberToPut); + } + + Integer[] expected = referenceQueue.toArray(new Integer[0]); + buffer.resize(expected.length); + + assertEquals(buffer.elements, expected); + } + + private void queueOnce(int capacity, int numWraps) { + + Queue referenceQueue = new ArrayBlockingQueue<>(capacity); + CircularBuffer buffer = new CircularBuffer<>(capacity); + + int nextNumberToPut = 0; + int totalPuts = 0; + int putsLimit = capacity * numWraps; + int remainingCapacity = capacity; + int size = 0; + + while (totalPuts < putsLimit) { + assert remainingCapacity + size == capacity; + int puts = r.nextInt(remainingCapacity + 1); // [0, remainingCapacity] + remainingCapacity -= puts; + size += puts; + for (int i = 0; i < puts; i++, nextNumberToPut++) { + referenceQueue.add(nextNumberToPut); + buffer.add(nextNumberToPut); + } + totalPuts += puts; + int gets = r.nextInt(size + 1); // [0, size] + size -= gets; + remainingCapacity += gets; + for (int i = 0; i < gets; i++) { + Integer expected = referenceQueue.poll(); + Integer actual = buffer.remove(); + assertEquals(actual, expected); + } + } + } +} diff --git a/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/DecoderTest.java b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/DecoderTest.java new file mode 100644 index 0000000000000000000000000000000000000000..29a651fb0f71fa95d6b5187778c680bfb62cf017 --- /dev/null +++ b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/DecoderTest.java @@ -0,0 +1,595 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 sun.net.httpclient.hpack; + +import org.testng.annotations.Test; + +import java.io.UncheckedIOException; +import java.net.ProtocolException; +import java.nio.ByteBuffer; +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Collectors; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; +import static sun.net.httpclient.hpack.TestHelper.*; + +public final class DecoderTest { + + // + // http://tools.ietf.org/html/rfc7541#appendix-C.2.1 + // + @Test + public void example1() { + // @formatter:off + test("400a 6375 7374 6f6d 2d6b 6579 0d63 7573\n" + + "746f 6d2d 6865 6164 6572", + + "[ 1] (s = 55) custom-key: custom-header\n" + + " Table size: 55", + + "custom-key: custom-header"); + // @formatter:on + } + + // + // http://tools.ietf.org/html/rfc7541#appendix-C.2.2 + // + @Test + public void example2() { + // @formatter:off + test("040c 2f73 616d 706c 652f 7061 7468", + "empty.", + ":path: /sample/path"); + // @formatter:on + } + + // + // http://tools.ietf.org/html/rfc7541#appendix-C.2.3 + // + @Test + public void example3() { + // @formatter:off + test("1008 7061 7373 776f 7264 0673 6563 7265\n" + + "74", + "empty.", + "password: secret"); + // @formatter:on + } + + // + // http://tools.ietf.org/html/rfc7541#appendix-C.2.4 + // + @Test + public void example4() { + // @formatter:off + test("82", + "empty.", + ":method: GET"); + // @formatter:on + } + + // + // http://tools.ietf.org/html/rfc7541#appendix-C.3 + // + @Test + public void example5() { + // @formatter:off + Decoder d = new Decoder(256); + + test(d, "8286 8441 0f77 7777 2e65 7861 6d70 6c65\n" + + "2e63 6f6d", + + "[ 1] (s = 57) :authority: www.example.com\n" + + " Table size: 57", + + ":method: GET\n" + + ":scheme: http\n" + + ":path: /\n" + + ":authority: www.example.com"); + + test(d, "8286 84be 5808 6e6f 2d63 6163 6865", + + "[ 1] (s = 53) cache-control: no-cache\n" + + "[ 2] (s = 57) :authority: www.example.com\n" + + " Table size: 110", + + ":method: GET\n" + + ":scheme: http\n" + + ":path: /\n" + + ":authority: www.example.com\n" + + "cache-control: no-cache"); + + test(d, "8287 85bf 400a 6375 7374 6f6d 2d6b 6579\n" + + "0c63 7573 746f 6d2d 7661 6c75 65", + + "[ 1] (s = 54) custom-key: custom-value\n" + + "[ 2] (s = 53) cache-control: no-cache\n" + + "[ 3] (s = 57) :authority: www.example.com\n" + + " Table size: 164", + + ":method: GET\n" + + ":scheme: https\n" + + ":path: /index.html\n" + + ":authority: www.example.com\n" + + "custom-key: custom-value"); + + // @formatter:on + } + + // + // http://tools.ietf.org/html/rfc7541#appendix-C.4 + // + @Test + public void example6() { + // @formatter:off + Decoder d = new Decoder(256); + + test(d, "8286 8441 8cf1 e3c2 e5f2 3a6b a0ab 90f4\n" + + "ff", + + "[ 1] (s = 57) :authority: www.example.com\n" + + " Table size: 57", + + ":method: GET\n" + + ":scheme: http\n" + + ":path: /\n" + + ":authority: www.example.com"); + + test(d, "8286 84be 5886 a8eb 1064 9cbf", + + "[ 1] (s = 53) cache-control: no-cache\n" + + "[ 2] (s = 57) :authority: www.example.com\n" + + " Table size: 110", + + ":method: GET\n" + + ":scheme: http\n" + + ":path: /\n" + + ":authority: www.example.com\n" + + "cache-control: no-cache"); + + test(d, "8287 85bf 4088 25a8 49e9 5ba9 7d7f 8925\n" + + "a849 e95b b8e8 b4bf", + + "[ 1] (s = 54) custom-key: custom-value\n" + + "[ 2] (s = 53) cache-control: no-cache\n" + + "[ 3] (s = 57) :authority: www.example.com\n" + + " Table size: 164", + + ":method: GET\n" + + ":scheme: https\n" + + ":path: /index.html\n" + + ":authority: www.example.com\n" + + "custom-key: custom-value"); + // @formatter:on + } + + // + // http://tools.ietf.org/html/rfc7541#appendix-C.5 + // + @Test + public void example7() { + // @formatter:off + Decoder d = new Decoder(256); + + test(d, "4803 3330 3258 0770 7269 7661 7465 611d\n" + + "4d6f 6e2c 2032 3120 4f63 7420 3230 3133\n" + + "2032 303a 3133 3a32 3120 474d 546e 1768\n" + + "7474 7073 3a2f 2f77 7777 2e65 7861 6d70\n" + + "6c65 2e63 6f6d", + + "[ 1] (s = 63) location: https://www.example.com\n" + + "[ 2] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT\n" + + "[ 3] (s = 52) cache-control: private\n" + + "[ 4] (s = 42) :status: 302\n" + + " Table size: 222", + + ":status: 302\n" + + "cache-control: private\n" + + "date: Mon, 21 Oct 2013 20:13:21 GMT\n" + + "location: https://www.example.com"); + + test(d, "4803 3330 37c1 c0bf", + + "[ 1] (s = 42) :status: 307\n" + + "[ 2] (s = 63) location: https://www.example.com\n" + + "[ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT\n" + + "[ 4] (s = 52) cache-control: private\n" + + " Table size: 222", + + ":status: 307\n" + + "cache-control: private\n" + + "date: Mon, 21 Oct 2013 20:13:21 GMT\n" + + "location: https://www.example.com"); + + test(d, "88c1 611d 4d6f 6e2c 2032 3120 4f63 7420\n" + + "3230 3133 2032 303a 3133 3a32 3220 474d\n" + + "54c0 5a04 677a 6970 7738 666f 6f3d 4153\n" + + "444a 4b48 514b 425a 584f 5157 454f 5049\n" + + "5541 5851 5745 4f49 553b 206d 6178 2d61\n" + + "6765 3d33 3630 303b 2076 6572 7369 6f6e\n" + + "3d31", + + "[ 1] (s = 98) set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1\n" + + "[ 2] (s = 52) content-encoding: gzip\n" + + "[ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:22 GMT\n" + + " Table size: 215", + + ":status: 200\n" + + "cache-control: private\n" + + "date: Mon, 21 Oct 2013 20:13:22 GMT\n" + + "location: https://www.example.com\n" + + "content-encoding: gzip\n" + + "set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"); + // @formatter:on + } + + // + // http://tools.ietf.org/html/rfc7541#appendix-C.6 + // + @Test + public void example8() { + // @formatter:off + Decoder d = new Decoder(256); + + test(d, "4882 6402 5885 aec3 771a 4b61 96d0 7abe\n" + + "9410 54d4 44a8 2005 9504 0b81 66e0 82a6\n" + + "2d1b ff6e 919d 29ad 1718 63c7 8f0b 97c8\n" + + "e9ae 82ae 43d3", + + "[ 1] (s = 63) location: https://www.example.com\n" + + "[ 2] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT\n" + + "[ 3] (s = 52) cache-control: private\n" + + "[ 4] (s = 42) :status: 302\n" + + " Table size: 222", + + ":status: 302\n" + + "cache-control: private\n" + + "date: Mon, 21 Oct 2013 20:13:21 GMT\n" + + "location: https://www.example.com"); + + test(d, "4883 640e ffc1 c0bf", + + "[ 1] (s = 42) :status: 307\n" + + "[ 2] (s = 63) location: https://www.example.com\n" + + "[ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT\n" + + "[ 4] (s = 52) cache-control: private\n" + + " Table size: 222", + + ":status: 307\n" + + "cache-control: private\n" + + "date: Mon, 21 Oct 2013 20:13:21 GMT\n" + + "location: https://www.example.com"); + + test(d, "88c1 6196 d07a be94 1054 d444 a820 0595\n" + + "040b 8166 e084 a62d 1bff c05a 839b d9ab\n" + + "77ad 94e7 821d d7f2 e6c7 b335 dfdf cd5b\n" + + "3960 d5af 2708 7f36 72c1 ab27 0fb5 291f\n" + + "9587 3160 65c0 03ed 4ee5 b106 3d50 07", + + "[ 1] (s = 98) set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1\n" + + "[ 2] (s = 52) content-encoding: gzip\n" + + "[ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:22 GMT\n" + + " Table size: 215", + + ":status: 200\n" + + "cache-control: private\n" + + "date: Mon, 21 Oct 2013 20:13:22 GMT\n" + + "location: https://www.example.com\n" + + "content-encoding: gzip\n" + + "set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"); + // @formatter:on + } + + @Test + // One of responses from Apache Server that helped to catch a bug + public void testX() { + Decoder d = new Decoder(4096); + // @formatter:off + test(d, "3fe1 1f88 6196 d07a be94 03ea 693f 7504\n" + + "00b6 a05c b827 2e32 fa98 b46f 769e 86b1\n" + + "9272 b025 da5c 2ea9 fd70 a8de 7fb5 3556\n" + + "5ab7 6ece c057 02e2 2ad2 17bf 6c96 d07a\n" + + "be94 0854 cb6d 4a08 0075 40bd 71b6 6e05\n" + + "a531 68df 0f13 8efe 4522 cd32 21b6 5686\n" + + "eb23 781f cf52 848f d24a 8f0f 0d02 3435\n" + + "5f87 497c a589 d34d 1f", + + "[ 1] (s = 53) content-type: text/html\n" + + "[ 2] (s = 50) accept-ranges: bytes\n" + + "[ 3] (s = 74) last-modified: Mon, 11 Jun 2007 18:53:14 GMT\n" + + "[ 4] (s = 77) server: Apache/2.4.17 (Unix) OpenSSL/1.0.2e-dev\n" + + "[ 5] (s = 65) date: Mon, 09 Nov 2015 16:26:39 GMT\n" + + " Table size: 319", + + ":status: 200\n" + + "date: Mon, 09 Nov 2015 16:26:39 GMT\n" + + "server: Apache/2.4.17 (Unix) OpenSSL/1.0.2e-dev\n" + + "last-modified: Mon, 11 Jun 2007 18:53:14 GMT\n" + + "etag: \"2d-432a5e4a73a80\"\n" + + "accept-ranges: bytes\n" + + "content-length: 45\n" + + "content-type: text/html"); + // @formatter:on + } + + // + // This test is missing in the spec + // + @Test + public void sizeUpdate() { + Decoder d = new Decoder(4096); + assertEquals(d.getTable().maxSize(), 4096); + d.decode(ByteBuffer.wrap(new byte[]{0b00111110}), true, nopCallback()); // newSize = 30 + assertEquals(d.getTable().maxSize(), 30); + } + + @Test + public void incorrectSizeUpdate() { + ByteBuffer b = ByteBuffer.allocate(8); + Encoder e = new Encoder(8192) { + @Override + protected int calculateCapacity(int maxCapacity) { + return maxCapacity; + } + }; + e.header("a", "b"); + e.encode(b); + b.flip(); + { + Decoder d = new Decoder(4096); + UncheckedIOException ex = assertVoidThrows(UncheckedIOException.class, + () -> d.decode(b, true, (name, value) -> { })); + + assertNotNull(ex.getCause()); + assertEquals(ex.getCause().getClass(), ProtocolException.class); + } + b.flip(); + { + Decoder d = new Decoder(4096); + UncheckedIOException ex = assertVoidThrows(UncheckedIOException.class, + () -> d.decode(b, false, (name, value) -> { })); + + assertNotNull(ex.getCause()); + assertEquals(ex.getCause().getClass(), ProtocolException.class); + } + } + + @Test + public void corruptedHeaderBlockInteger() { + Decoder d = new Decoder(4096); + ByteBuffer data = ByteBuffer.wrap(new byte[]{ + (byte) 0b11111111, // indexed + (byte) 0b10011010 // 25 + ... + }); + UncheckedIOException e = assertVoidThrows(UncheckedIOException.class, + () -> d.decode(data, true, nopCallback())); + assertNotNull(e.getCause()); + assertEquals(e.getCause().getClass(), ProtocolException.class); + assertExceptionMessageContains(e, "Unexpected end of header block"); + } + + // 5.1. Integer Representation + // ... + // Integer encodings that exceed implementation limits -- in value or octet + // length -- MUST be treated as decoding errors. Different limits can + // be set for each of the different uses of integers, based on + // implementation constraints. + @Test + public void headerBlockIntegerNoOverflow() { + Decoder d = new Decoder(4096); + ByteBuffer data = ByteBuffer.wrap(new byte[]{ + (byte) 0b11111111, // indexed + 127 + // Integer.MAX_VALUE - 127 (base 128, little-endian): + (byte) 0b10000000, + (byte) 0b11111111, + (byte) 0b11111111, + (byte) 0b11111111, + (byte) 0b00000111 + }); + + IllegalArgumentException e = assertVoidThrows(IllegalArgumentException.class, + () -> d.decode(data, true, nopCallback())); + + assertExceptionMessageContains(e, "index=2147483647"); + } + + @Test + public void headerBlockIntegerOverflow() { + Decoder d = new Decoder(4096); + ByteBuffer data = ByteBuffer.wrap(new byte[]{ + (byte) 0b11111111, // indexed + 127 + // Integer.MAX_VALUE - 127 + 1 (base 128, little endian): + (byte) 0b10000001, + (byte) 0b11111111, + (byte) 0b11111111, + (byte) 0b11111111, + (byte) 0b00000111 + }); + + IllegalArgumentException e = assertVoidThrows(IllegalArgumentException.class, + () -> d.decode(data, true, nopCallback())); + + assertExceptionMessageContains(e, "Integer overflow"); + } + + @Test + public void corruptedHeaderBlockString1() { + Decoder d = new Decoder(4096); + ByteBuffer data = ByteBuffer.wrap(new byte[]{ + 0b00001111, // literal, index=15 + 0b00000000, + 0b00001000, // huffman=false, length=8 + 0b00000000, // \ + 0b00000000, // but only 3 octets available... + 0b00000000 // / + }); + UncheckedIOException e = assertVoidThrows(UncheckedIOException.class, + () -> d.decode(data, true, nopCallback())); + assertNotNull(e.getCause()); + assertEquals(e.getCause().getClass(), ProtocolException.class); + assertExceptionMessageContains(e, "Unexpected end of header block"); + } + + @Test + public void corruptedHeaderBlockString2() { + Decoder d = new Decoder(4096); + ByteBuffer data = ByteBuffer.wrap(new byte[]{ + 0b00001111, // literal, index=15 + 0b00000000, + (byte) 0b10001000, // huffman=true, length=8 + 0b00000000, // \ + 0b00000000, // \ + 0b00000000, // but only 5 octets available... + 0b00000000, // / + 0b00000000 // / + }); + UncheckedIOException e = assertVoidThrows(UncheckedIOException.class, + () -> d.decode(data, true, nopCallback())); + assertNotNull(e.getCause()); + assertEquals(e.getCause().getClass(), ProtocolException.class); + assertExceptionMessageContains(e, "Unexpected end of header block"); + } + + // 5.2. String Literal Representation + // ...A Huffman-encoded string literal containing the EOS symbol MUST be + // treated as a decoding error... + @Test + public void corruptedHeaderBlockHuffmanStringEOS() { + Decoder d = new Decoder(4096); + ByteBuffer data = ByteBuffer.wrap(new byte[]{ + 0b00001111, // literal, index=15 + 0b00000000, + (byte) 0b10000110, // huffman=true, length=6 + 0b00011001, 0b01001101, (byte) 0b11111111, + (byte) 0b11111111, (byte) 0b11111111, (byte) 0b11111100 + }); + IllegalArgumentException e = assertVoidThrows(IllegalArgumentException.class, + () -> d.decode(data, true, nopCallback())); + + assertExceptionMessageContains(e, "Encountered EOS"); + } + + // 5.2. String Literal Representation + // ...A padding strictly longer than 7 bits MUST be treated as a decoding + // error... + @Test + public void corruptedHeaderBlockHuffmanStringLongPadding1() { + Decoder d = new Decoder(4096); + ByteBuffer data = ByteBuffer.wrap(new byte[]{ + 0b00001111, // literal, index=15 + 0b00000000, + (byte) 0b10000011, // huffman=true, length=3 + 0b00011001, 0b01001101, (byte) 0b11111111 + // len("aei") + len(padding) = (5 + 5 + 5) + (9) + }); + IllegalArgumentException e = assertVoidThrows(IllegalArgumentException.class, + () -> d.decode(data, true, nopCallback())); + + assertExceptionMessageContains(e, "Padding is too long", "len=9"); + } + + @Test + public void corruptedHeaderBlockHuffmanStringLongPadding2() { + Decoder d = new Decoder(4096); + ByteBuffer data = ByteBuffer.wrap(new byte[]{ + 0b00001111, // literal, index=15 + 0b00000000, + (byte) 0b10000011, // huffman=true, length=3 + 0b00011001, 0b01111010, (byte) 0b11111111 + // len("aek") + len(padding) = (5 + 5 + 7) + (7) + }); + assertVoidDoesNotThrow(() -> d.decode(data, true, nopCallback())); + } + + // 5.2. String Literal Representation + // ...A padding not corresponding to the most significant bits of the code + // for the EOS symbol MUST be treated as a decoding error... + @Test + public void corruptedHeaderBlockHuffmanStringNotEOSPadding() { + Decoder d = new Decoder(4096); + ByteBuffer data = ByteBuffer.wrap(new byte[]{ + 0b00001111, // literal, index=15 + 0b00000000, + (byte) 0b10000011, // huffman=true, length=3 + 0b00011001, 0b01111010, (byte) 0b11111110 + }); + IllegalArgumentException e = assertVoidThrows(IllegalArgumentException.class, + () -> d.decode(data, true, nopCallback())); + + assertExceptionMessageContains(e, "Not a EOS prefix"); + } + + @Test + public void argsTestBiConsumerIsNull() { + Decoder decoder = new Decoder(4096); + assertVoidThrows(NullPointerException.class, + () -> decoder.decode(ByteBuffer.allocate(16), true, null)); + } + + @Test + public void argsTestByteBufferIsNull() { + Decoder decoder = new Decoder(4096); + assertVoidThrows(NullPointerException.class, + () -> decoder.decode(null, true, nopCallback())); + } + + @Test + public void argsTestBothAreNull() { + Decoder decoder = new Decoder(4096); + assertVoidThrows(NullPointerException.class, + () -> decoder.decode(null, true, null)); + } + + private static void test(String hexdump, + String headerTable, String headerList) { + test(new Decoder(4096), hexdump, headerTable, headerList); + } + + // + // Sometimes we need to keep the same decoder along several runs, + // as it models the same connection + // + private static void test(Decoder d, String hexdump, + String expectedHeaderTable, String expectedHeaderList) { + + ByteBuffer source = SpecHelper.toBytes(hexdump); + + List actual = new LinkedList<>(); + d.decode(source, true, (name, value) -> { + if (value == null) { + actual.add(name.toString()); + } else { + actual.add(name + ": " + value); + } + }); + + assertEquals(d.getTable().getStateString(), expectedHeaderTable); + assertEquals(actual.stream().collect(Collectors.joining("\n")), expectedHeaderList); + } + + private static DecodingCallback nopCallback() { + return (t, u) -> { }; + } +} diff --git a/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/EncoderTest.java b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/EncoderTest.java new file mode 100644 index 0000000000000000000000000000000000000000..c7b375b1238a16e733f3f20c9cbbd02c557978df --- /dev/null +++ b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/EncoderTest.java @@ -0,0 +1,623 @@ +/* + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 sun.net.httpclient.hpack; + +import org.testng.annotations.Test; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.function.Function; + +import static java.util.Arrays.asList; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; +import static sun.net.httpclient.hpack.SpecHelper.toHexdump; +import static sun.net.httpclient.hpack.TestHelper.assertVoidThrows; + +// TODO: map textual representation of commands from the spec to actual +// calls to encoder (actually, this is a good idea for decoder as well) +public final class EncoderTest { + + // + // http://tools.ietf.org/html/rfc7541#appendix-C.2.1 + // + @Test + public void example1() { + + Encoder e = newCustomEncoder(256); + drainInitialUpdate(e); + + e.literalWithIndexing("custom-key", false, "custom-header", false); + // @formatter:off + test(e, + + "400a 6375 7374 6f6d 2d6b 6579 0d63 7573\n" + + "746f 6d2d 6865 6164 6572", + + "[ 1] (s = 55) custom-key: custom-header\n" + + " Table size: 55"); + // @formatter:on + } + + // + // http://tools.ietf.org/html/rfc7541#appendix-C.2.2 + // + @Test + public void example2() { + + Encoder e = newCustomEncoder(256); + drainInitialUpdate(e); + + e.literal(4, "/sample/path", false); + // @formatter:off + test(e, + + "040c 2f73 616d 706c 652f 7061 7468", + + "empty."); + // @formatter:on + } + + // + // http://tools.ietf.org/html/rfc7541#appendix-C.2.3 + // + @Test + public void example3() { + + Encoder e = newCustomEncoder(256); + drainInitialUpdate(e); + + e.literalNeverIndexed("password", false, "secret", false); + // @formatter:off + test(e, + + "1008 7061 7373 776f 7264 0673 6563 7265\n" + + "74", + + "empty."); + // @formatter:on + } + + // + // http://tools.ietf.org/html/rfc7541#appendix-C.2.4 + // + @Test + public void example4() { + + Encoder e = newCustomEncoder(256); + drainInitialUpdate(e); + + e.indexed(2); + // @formatter:off + test(e, + + "82", + + "empty."); + // @formatter:on + } + + // + // http://tools.ietf.org/html/rfc7541#appendix-C.3 + // + @Test + public void example5() { + Encoder e = newCustomEncoder(256); + drainInitialUpdate(e); + + ByteBuffer output = ByteBuffer.allocate(64); + e.indexed(2); + e.encode(output); + e.indexed(6); + e.encode(output); + e.indexed(4); + e.encode(output); + e.literalWithIndexing(1, "www.example.com", false); + e.encode(output); + + output.flip(); + + // @formatter:off + test(e, output, + + "8286 8441 0f77 7777 2e65 7861 6d70 6c65\n" + + "2e63 6f6d", + + "[ 1] (s = 57) :authority: www.example.com\n" + + " Table size: 57"); + + output.clear(); + + e.indexed( 2); + e.encode(output); + e.indexed( 6); + e.encode(output); + e.indexed( 4); + e.encode(output); + e.indexed(62); + e.encode(output); + e.literalWithIndexing(24, "no-cache", false); + e.encode(output); + + output.flip(); + + test(e, output, + + "8286 84be 5808 6e6f 2d63 6163 6865", + + "[ 1] (s = 53) cache-control: no-cache\n" + + "[ 2] (s = 57) :authority: www.example.com\n" + + " Table size: 110"); + + output.clear(); + + e.indexed( 2); + e.encode(output); + e.indexed( 7); + e.encode(output); + e.indexed( 5); + e.encode(output); + e.indexed(63); + e.encode(output); + e.literalWithIndexing("custom-key", false, "custom-value", false); + e.encode(output); + + output.flip(); + + test(e, output, + + "8287 85bf 400a 6375 7374 6f6d 2d6b 6579\n" + + "0c63 7573 746f 6d2d 7661 6c75 65", + + "[ 1] (s = 54) custom-key: custom-value\n" + + "[ 2] (s = 53) cache-control: no-cache\n" + + "[ 3] (s = 57) :authority: www.example.com\n" + + " Table size: 164"); + // @formatter:on + } + + // + // http://tools.ietf.org/html/rfc7541#appendix-C.4 + // + @Test + public void example6() { + Encoder e = newCustomEncoder(256); + drainInitialUpdate(e); + + ByteBuffer output = ByteBuffer.allocate(64); + e.indexed(2); + e.encode(output); + e.indexed(6); + e.encode(output); + e.indexed(4); + e.encode(output); + e.literalWithIndexing(1, "www.example.com", true); + e.encode(output); + + output.flip(); + + // @formatter:off + test(e, output, + + "8286 8441 8cf1 e3c2 e5f2 3a6b a0ab 90f4\n" + + "ff", + + "[ 1] (s = 57) :authority: www.example.com\n" + + " Table size: 57"); + + output.clear(); + + e.indexed( 2); + e.encode(output); + e.indexed( 6); + e.encode(output); + e.indexed( 4); + e.encode(output); + e.indexed(62); + e.encode(output); + e.literalWithIndexing(24, "no-cache", true); + e.encode(output); + + output.flip(); + + test(e, output, + + "8286 84be 5886 a8eb 1064 9cbf", + + "[ 1] (s = 53) cache-control: no-cache\n" + + "[ 2] (s = 57) :authority: www.example.com\n" + + " Table size: 110"); + + output.clear(); + + e.indexed( 2); + e.encode(output); + e.indexed( 7); + e.encode(output); + e.indexed( 5); + e.encode(output); + e.indexed(63); + e.encode(output); + e.literalWithIndexing("custom-key", true, "custom-value", true); + e.encode(output); + + output.flip(); + + test(e, output, + + "8287 85bf 4088 25a8 49e9 5ba9 7d7f 8925\n" + + "a849 e95b b8e8 b4bf", + + "[ 1] (s = 54) custom-key: custom-value\n" + + "[ 2] (s = 53) cache-control: no-cache\n" + + "[ 3] (s = 57) :authority: www.example.com\n" + + " Table size: 164"); + // @formatter:on + } + + // + // http://tools.ietf.org/html/rfc7541#appendix-C.5 + // + @Test + public void example7() { + Encoder e = newCustomEncoder(256); + drainInitialUpdate(e); + + ByteBuffer output = ByteBuffer.allocate(128); + // @formatter:off + e.literalWithIndexing( 8, "302", false); + e.encode(output); + e.literalWithIndexing(24, "private", false); + e.encode(output); + e.literalWithIndexing(33, "Mon, 21 Oct 2013 20:13:21 GMT", false); + e.encode(output); + e.literalWithIndexing(46, "https://www.example.com", false); + e.encode(output); + + output.flip(); + + test(e, output, + + "4803 3330 3258 0770 7269 7661 7465 611d\n" + + "4d6f 6e2c 2032 3120 4f63 7420 3230 3133\n" + + "2032 303a 3133 3a32 3120 474d 546e 1768\n" + + "7474 7073 3a2f 2f77 7777 2e65 7861 6d70\n" + + "6c65 2e63 6f6d", + + "[ 1] (s = 63) location: https://www.example.com\n" + + "[ 2] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT\n" + + "[ 3] (s = 52) cache-control: private\n" + + "[ 4] (s = 42) :status: 302\n" + + " Table size: 222"); + + output.clear(); + + e.literalWithIndexing( 8, "307", false); + e.encode(output); + e.indexed(65); + e.encode(output); + e.indexed(64); + e.encode(output); + e.indexed(63); + e.encode(output); + + output.flip(); + + test(e, output, + + "4803 3330 37c1 c0bf", + + "[ 1] (s = 42) :status: 307\n" + + "[ 2] (s = 63) location: https://www.example.com\n" + + "[ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT\n" + + "[ 4] (s = 52) cache-control: private\n" + + " Table size: 222"); + + output.clear(); + + e.indexed( 8); + e.encode(output); + e.indexed(65); + e.encode(output); + e.literalWithIndexing(33, "Mon, 21 Oct 2013 20:13:22 GMT", false); + e.encode(output); + e.indexed(64); + e.encode(output); + e.literalWithIndexing(26, "gzip", false); + e.encode(output); + e.literalWithIndexing(55, "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1", false); + e.encode(output); + + output.flip(); + + test(e, output, + + "88c1 611d 4d6f 6e2c 2032 3120 4f63 7420\n" + + "3230 3133 2032 303a 3133 3a32 3220 474d\n" + + "54c0 5a04 677a 6970 7738 666f 6f3d 4153\n" + + "444a 4b48 514b 425a 584f 5157 454f 5049\n" + + "5541 5851 5745 4f49 553b 206d 6178 2d61\n" + + "6765 3d33 3630 303b 2076 6572 7369 6f6e\n" + + "3d31", + + "[ 1] (s = 98) set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1\n" + + "[ 2] (s = 52) content-encoding: gzip\n" + + "[ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:22 GMT\n" + + " Table size: 215"); + // @formatter:on + } + + // + // http://tools.ietf.org/html/rfc7541#appendix-C.6 + // + @Test + public void example8() { + Encoder e = newCustomEncoder(256); + drainInitialUpdate(e); + + ByteBuffer output = ByteBuffer.allocate(128); + // @formatter:off + e.literalWithIndexing( 8, "302", true); + e.encode(output); + e.literalWithIndexing(24, "private", true); + e.encode(output); + e.literalWithIndexing(33, "Mon, 21 Oct 2013 20:13:21 GMT", true); + e.encode(output); + e.literalWithIndexing(46, "https://www.example.com", true); + e.encode(output); + + output.flip(); + + test(e, output, + + "4882 6402 5885 aec3 771a 4b61 96d0 7abe\n" + + "9410 54d4 44a8 2005 9504 0b81 66e0 82a6\n" + + "2d1b ff6e 919d 29ad 1718 63c7 8f0b 97c8\n" + + "e9ae 82ae 43d3", + + "[ 1] (s = 63) location: https://www.example.com\n" + + "[ 2] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT\n" + + "[ 3] (s = 52) cache-control: private\n" + + "[ 4] (s = 42) :status: 302\n" + + " Table size: 222"); + + output.clear(); + + e.literalWithIndexing( 8, "307", true); + e.encode(output); + e.indexed(65); + e.encode(output); + e.indexed(64); + e.encode(output); + e.indexed(63); + e.encode(output); + + output.flip(); + + test(e, output, + + "4883 640e ffc1 c0bf", + + "[ 1] (s = 42) :status: 307\n" + + "[ 2] (s = 63) location: https://www.example.com\n" + + "[ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT\n" + + "[ 4] (s = 52) cache-control: private\n" + + " Table size: 222"); + + output.clear(); + + e.indexed( 8); + e.encode(output); + e.indexed(65); + e.encode(output); + e.literalWithIndexing(33, "Mon, 21 Oct 2013 20:13:22 GMT", true); + e.encode(output); + e.indexed(64); + e.encode(output); + e.literalWithIndexing(26, "gzip", true); + e.encode(output); + e.literalWithIndexing(55, "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1", true); + e.encode(output); + + output.flip(); + + test(e, output, + + "88c1 6196 d07a be94 1054 d444 a820 0595\n" + + "040b 8166 e084 a62d 1bff c05a 839b d9ab\n" + + "77ad 94e7 821d d7f2 e6c7 b335 dfdf cd5b\n" + + "3960 d5af 2708 7f36 72c1 ab27 0fb5 291f\n" + + "9587 3160 65c0 03ed 4ee5 b106 3d50 07", + + "[ 1] (s = 98) set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1\n" + + "[ 2] (s = 52) content-encoding: gzip\n" + + "[ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:22 GMT\n" + + " Table size: 215"); + // @formatter:on + } + + @Test + public void initialSizeUpdateDefaultEncoder() { + Function e = Encoder::new; + testSizeUpdate(e, 1024, asList(), asList(0)); + testSizeUpdate(e, 1024, asList(1024), asList(0)); + testSizeUpdate(e, 1024, asList(1024, 1024), asList(0)); + testSizeUpdate(e, 1024, asList(1024, 512), asList(0)); + testSizeUpdate(e, 1024, asList(512, 1024), asList(0)); + testSizeUpdate(e, 1024, asList(512, 2048), asList(0)); + } + + @Test + public void initialSizeUpdateCustomEncoder() { + Function e = EncoderTest::newCustomEncoder; + testSizeUpdate(e, 1024, asList(), asList(1024)); + testSizeUpdate(e, 1024, asList(1024), asList(1024)); + testSizeUpdate(e, 1024, asList(1024, 1024), asList(1024)); + testSizeUpdate(e, 1024, asList(1024, 512), asList(512)); + testSizeUpdate(e, 1024, asList(512, 1024), asList(1024)); + testSizeUpdate(e, 1024, asList(512, 2048), asList(2048)); + } + + @Test + public void seriesOfSizeUpdatesDefaultEncoder() { + Function e = c -> { + Encoder encoder = new Encoder(c); + drainInitialUpdate(encoder); + return encoder; + }; + testSizeUpdate(e, 0, asList(0), asList()); + testSizeUpdate(e, 1024, asList(1024), asList()); + testSizeUpdate(e, 1024, asList(2048), asList()); + testSizeUpdate(e, 1024, asList(512), asList()); + testSizeUpdate(e, 1024, asList(1024, 1024), asList()); + testSizeUpdate(e, 1024, asList(1024, 2048), asList()); + testSizeUpdate(e, 1024, asList(2048, 1024), asList()); + testSizeUpdate(e, 1024, asList(1024, 512), asList()); + testSizeUpdate(e, 1024, asList(512, 1024), asList()); + } + + // + // https://tools.ietf.org/html/rfc7541#section-4.2 + // + @Test + public void seriesOfSizeUpdatesCustomEncoder() { + Function e = c -> { + Encoder encoder = newCustomEncoder(c); + drainInitialUpdate(encoder); + return encoder; + }; + testSizeUpdate(e, 0, asList(0), asList()); + testSizeUpdate(e, 1024, asList(1024), asList()); + testSizeUpdate(e, 1024, asList(2048), asList(2048)); + testSizeUpdate(e, 1024, asList(512), asList(512)); + testSizeUpdate(e, 1024, asList(1024, 1024), asList()); + testSizeUpdate(e, 1024, asList(1024, 2048), asList(2048)); + testSizeUpdate(e, 1024, asList(2048, 1024), asList()); + testSizeUpdate(e, 1024, asList(1024, 512), asList(512)); + testSizeUpdate(e, 1024, asList(512, 1024), asList(512, 1024)); + } + + @Test + public void callSequenceViolations() { + { // Hasn't set up a header + Encoder e = new Encoder(0); + assertVoidThrows(IllegalStateException.class, () -> e.encode(ByteBuffer.allocate(16))); + } + { // Can't set up header while there's an unfinished encoding + Encoder e = new Encoder(0); + e.indexed(32); + assertVoidThrows(IllegalStateException.class, () -> e.indexed(32)); + } + { // Can't setMaxCapacity while there's an unfinished encoding + Encoder e = new Encoder(0); + e.indexed(32); + assertVoidThrows(IllegalStateException.class, () -> e.setMaxCapacity(512)); + } + { // Hasn't set up a header + Encoder e = new Encoder(0); + e.setMaxCapacity(256); + assertVoidThrows(IllegalStateException.class, () -> e.encode(ByteBuffer.allocate(16))); + } + { // Hasn't set up a header after the previous encoding + Encoder e = new Encoder(0); + e.indexed(0); + boolean encoded = e.encode(ByteBuffer.allocate(16)); + assertTrue(encoded); // assumption + assertVoidThrows(IllegalStateException.class, () -> e.encode(ByteBuffer.allocate(16))); + } + } + + private static void test(Encoder encoder, + String expectedTableState, + String expectedHexdump) { + + ByteBuffer b = ByteBuffer.allocate(128); + encoder.encode(b); + b.flip(); + test(encoder, b, expectedTableState, expectedHexdump); + } + + private static void test(Encoder encoder, + ByteBuffer output, + String expectedHexdump, + String expectedTableState) { + + String actualTableState = encoder.getHeaderTable().getStateString(); + assertEquals(actualTableState, expectedTableState); + + String actualHexdump = toHexdump(output); + assertEquals(actualHexdump, expectedHexdump.replaceAll("\\n", " ")); + } + + // initial size - the size encoder is constructed with + // updates - a sequence of values for consecutive calls to encoder.setMaxCapacity + // expected - a sequence of values expected to be decoded by a decoder + private void testSizeUpdate(Function encoder, + int initialSize, + List updates, + List expected) { + Encoder e = encoder.apply(initialSize); + updates.forEach(e::setMaxCapacity); + ByteBuffer b = ByteBuffer.allocate(64); + e.header("a", "b"); + e.encode(b); + b.flip(); + Decoder d = new Decoder(updates.isEmpty() ? initialSize : Collections.max(updates)); + List actual = new ArrayList<>(); + d.decode(b, true, new DecodingCallback() { + @Override + public void onDecoded(CharSequence name, CharSequence value) { } + + @Override + public void onSizeUpdate(int capacity) { + actual.add(capacity); + } + }); + assertEquals(actual, expected); + } + + // + // Default encoder does not need any table, therefore a subclass that + // behaves differently is needed + // + private static Encoder newCustomEncoder(int maxCapacity) { + return new Encoder(maxCapacity) { + @Override + protected int calculateCapacity(int maxCapacity) { + return maxCapacity; + } + }; + } + + private static void drainInitialUpdate(Encoder e) { + ByteBuffer b = ByteBuffer.allocate(4); + e.header("a", "b"); + boolean done; + do { + done = e.encode(b); + b.flip(); + } while (!done); + } +} diff --git a/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/HeaderTableTest.java b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/HeaderTableTest.java new file mode 100644 index 0000000000000000000000000000000000000000..1bc12029ca6bb828c5833e05a7abad3cee1db6d9 --- /dev/null +++ b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/HeaderTableTest.java @@ -0,0 +1,375 @@ +/* + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 sun.net.httpclient.hpack; + +import org.testng.annotations.Test; +import sun.net.httpclient.hpack.HeaderTable.HeaderField; + +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static java.lang.String.format; +import static org.testng.Assert.assertEquals; +import static sun.net.httpclient.hpack.TestHelper.*; + +public class HeaderTableTest { + + // + // https://tools.ietf.org/html/rfc7541#appendix-A + // + // @formatter:off + private static final String SPEC = + " | 1 | :authority | |\n" + + " | 2 | :method | GET |\n" + + " | 3 | :method | POST |\n" + + " | 4 | :path | / |\n" + + " | 5 | :path | /index.html |\n" + + " | 6 | :scheme | http |\n" + + " | 7 | :scheme | https |\n" + + " | 8 | :status | 200 |\n" + + " | 9 | :status | 204 |\n" + + " | 10 | :status | 206 |\n" + + " | 11 | :status | 304 |\n" + + " | 12 | :status | 400 |\n" + + " | 13 | :status | 404 |\n" + + " | 14 | :status | 500 |\n" + + " | 15 | accept-charset | |\n" + + " | 16 | accept-encoding | gzip, deflate |\n" + + " | 17 | accept-language | |\n" + + " | 18 | accept-ranges | |\n" + + " | 19 | accept | |\n" + + " | 20 | access-control-allow-origin | |\n" + + " | 21 | age | |\n" + + " | 22 | allow | |\n" + + " | 23 | authorization | |\n" + + " | 24 | cache-control | |\n" + + " | 25 | content-disposition | |\n" + + " | 26 | content-encoding | |\n" + + " | 27 | content-language | |\n" + + " | 28 | content-length | |\n" + + " | 29 | content-location | |\n" + + " | 30 | content-range | |\n" + + " | 31 | content-type | |\n" + + " | 32 | cookie | |\n" + + " | 33 | date | |\n" + + " | 34 | etag | |\n" + + " | 35 | expect | |\n" + + " | 36 | expires | |\n" + + " | 37 | from | |\n" + + " | 38 | host | |\n" + + " | 39 | if-match | |\n" + + " | 40 | if-modified-since | |\n" + + " | 41 | if-none-match | |\n" + + " | 42 | if-range | |\n" + + " | 43 | if-unmodified-since | |\n" + + " | 44 | last-modified | |\n" + + " | 45 | link | |\n" + + " | 46 | location | |\n" + + " | 47 | max-forwards | |\n" + + " | 48 | proxy-authenticate | |\n" + + " | 49 | proxy-authorization | |\n" + + " | 50 | range | |\n" + + " | 51 | referer | |\n" + + " | 52 | refresh | |\n" + + " | 53 | retry-after | |\n" + + " | 54 | server | |\n" + + " | 55 | set-cookie | |\n" + + " | 56 | strict-transport-security | |\n" + + " | 57 | transfer-encoding | |\n" + + " | 58 | user-agent | |\n" + + " | 59 | vary | |\n" + + " | 60 | via | |\n" + + " | 61 | www-authenticate | |\n"; + // @formatter:on + + private static final int STATIC_TABLE_LENGTH = createStaticEntries().size(); + private final Random rnd = newRandom(); + + @Test + public void staticData() { + HeaderTable table = new HeaderTable(0); + Map staticHeaderFields = createStaticEntries(); + + Map minimalIndexes = new HashMap<>(); + + for (Map.Entry e : staticHeaderFields.entrySet()) { + Integer idx = e.getKey(); + String hName = e.getValue().name; + Integer midx = minimalIndexes.get(hName); + if (midx == null) { + minimalIndexes.put(hName, idx); + } else { + minimalIndexes.put(hName, Math.min(idx, midx)); + } + } + + staticHeaderFields.entrySet().forEach( + e -> { + // lookup + HeaderField actualHeaderField = table.get(e.getKey()); + HeaderField expectedHeaderField = e.getValue(); + assertEquals(actualHeaderField, expectedHeaderField); + + // reverse lookup (name, value) + String hName = expectedHeaderField.name; + String hValue = expectedHeaderField.value; + int expectedIndex = e.getKey(); + int actualIndex = table.indexOf(hName, hValue); + + assertEquals(actualIndex, expectedIndex); + + // reverse lookup (name) + int expectedMinimalIndex = minimalIndexes.get(hName); + int actualMinimalIndex = table.indexOf(hName, "blah-blah"); + + assertEquals(-actualMinimalIndex, expectedMinimalIndex); + } + ); + } + + @Test + public void constructorSetsMaxSize() { + int size = rnd.nextInt(64); + HeaderTable t = new HeaderTable(size); + assertEquals(t.size(), 0); + assertEquals(t.maxSize(), size); + } + + @Test + public void negativeMaximumSize() { + int maxSize = -(rnd.nextInt(100) + 1); // [-100, -1] + IllegalArgumentException e = + assertVoidThrows(IllegalArgumentException.class, + () -> new HeaderTable(0).setMaxSize(maxSize)); + assertExceptionMessageContains(e, "maxSize"); + } + + @Test + public void zeroMaximumSize() { + HeaderTable table = new HeaderTable(0); + table.setMaxSize(0); + assertEquals(table.maxSize(), 0); + } + + @Test + public void negativeIndex() { + int idx = -(rnd.nextInt(256) + 1); // [-256, -1] + IllegalArgumentException e = + assertVoidThrows(IllegalArgumentException.class, + () -> new HeaderTable(0).get(idx)); + assertExceptionMessageContains(e, "index"); + } + + @Test + public void zeroIndex() { + IllegalArgumentException e = + assertThrows(IllegalArgumentException.class, + () -> new HeaderTable(0).get(0)); + assertExceptionMessageContains(e, "index"); + } + + @Test + public void length() { + HeaderTable table = new HeaderTable(0); + assertEquals(table.length(), STATIC_TABLE_LENGTH); + } + + @Test + public void indexOutsideStaticRange() { + HeaderTable table = new HeaderTable(0); + int idx = table.length() + (rnd.nextInt(256) + 1); + IllegalArgumentException e = + assertThrows(IllegalArgumentException.class, + () -> table.get(idx)); + assertExceptionMessageContains(e, "index"); + } + + @Test + public void entryPutAfterStaticArea() { + HeaderTable table = new HeaderTable(256); + int idx = table.length() + 1; + assertThrows(IllegalArgumentException.class, () -> table.get(idx)); + + byte[] bytes = new byte[32]; + rnd.nextBytes(bytes); + String name = new String(bytes, StandardCharsets.ISO_8859_1); + String value = "custom-value"; + + table.put(name, value); + HeaderField f = table.get(idx); + assertEquals(name, f.name); + assertEquals(value, f.value); + } + + @Test + public void staticTableHasZeroSize() { + HeaderTable table = new HeaderTable(0); + assertEquals(0, table.size()); + } + + @Test + public void lowerIndexPriority() { + HeaderTable table = new HeaderTable(256); + int oldLength = table.length(); + table.put("bender", "rodriguez"); + table.put("bender", "rodriguez"); + table.put("bender", "rodriguez"); + + assertEquals(table.length(), oldLength + 3); // more like an assumption + int i = table.indexOf("bender", "rodriguez"); + assertEquals(oldLength + 1, i); + } + + @Test + public void lowerIndexPriority2() { + HeaderTable table = new HeaderTable(256); + int oldLength = table.length(); + int idx = rnd.nextInt(oldLength) + 1; + HeaderField f = table.get(idx); + table.put(f.name, f.value); + assertEquals(table.length(), oldLength + 1); + int i = table.indexOf(f.name, f.value); + assertEquals(idx, i); + } + + // TODO: negative indexes check + // TODO: ensure full table clearance when adding huge header field + // TODO: ensure eviction deletes minimum needed entries, not more + + @Test + public void fifo() { + HeaderTable t = new HeaderTable(Integer.MAX_VALUE); + // Let's add a series of header fields + int NUM_HEADERS = 32; + for (int i = 1; i <= NUM_HEADERS; i++) { + String s = String.valueOf(i); + t.put(s, s); + } + // They MUST appear in a FIFO order: + // newer entries are at lower indexes + // older entries are at higher indexes + for (int j = 1; j <= NUM_HEADERS; j++) { + HeaderField f = t.get(STATIC_TABLE_LENGTH + j); + int actualName = Integer.parseInt(f.name); + int expectedName = NUM_HEADERS - j + 1; + assertEquals(expectedName, actualName); + } + // Entries MUST be evicted in the order they were added: + // the newer the entry the later it is evicted + for (int k = 1; k <= NUM_HEADERS; k++) { + HeaderField f = t.evictEntry(); + assertEquals(String.valueOf(k), f.name); + } + } + + @Test + public void indexOf() { + HeaderTable t = new HeaderTable(Integer.MAX_VALUE); + // Let's put a series of header fields + int NUM_HEADERS = 32; + for (int i = 1; i <= NUM_HEADERS; i++) { + String s = String.valueOf(i); + t.put(s, s); + } + // and verify indexOf (reverse lookup) returns correct indexes for + // full lookup + for (int j = 1; j <= NUM_HEADERS; j++) { + String s = String.valueOf(j); + int actualIndex = t.indexOf(s, s); + int expectedIndex = STATIC_TABLE_LENGTH + NUM_HEADERS - j + 1; + assertEquals(expectedIndex, actualIndex); + } + // as well as for just a name lookup + for (int j = 1; j <= NUM_HEADERS; j++) { + String s = String.valueOf(j); + int actualIndex = t.indexOf(s, "blah"); + int expectedIndex = -(STATIC_TABLE_LENGTH + NUM_HEADERS - j + 1); + assertEquals(expectedIndex, actualIndex); + } + // lookup for non-existent name returns 0 + assertEquals(0, t.indexOf("chupacabra", "1")); + } + + @Test + public void testToString() { + HeaderTable table = new HeaderTable(0); + { + table.setMaxSize(2048); + assertEquals("entries: 0; used 0/2048 (0.0%)", table.toString()); + } + + { + String name = "custom-name"; + String value = "custom-value"; + int size = 512; + + table.setMaxSize(size); + table.put(name, value); + String s = table.toString(); + + int used = name.length() + value.length() + 32; + double ratio = used * 100.0 / size; + + String expected = format("entries: 1; used %s/%s (%.1f%%)", used, size, ratio); + assertEquals(expected, s); + } + + { + table.setMaxSize(78); + table.put(":method", ""); + table.put(":status", ""); + String s = table.toString(); + assertEquals("entries: 2; used 78/78 (100.0%)", s); + } + } + + @Test + public void stateString() { + HeaderTable table = new HeaderTable(256); + table.put("custom-key", "custom-header"); + // @formatter:off + assertEquals("[ 1] (s = 55) custom-key: custom-header\n" + + " Table size: 55", table.getStateString()); + // @formatter:on + } + + private static Map createStaticEntries() { + Pattern line = Pattern.compile( + "\\|\\s*(?\\d+?)\\s*\\|\\s*(?.+?)\\s*\\|\\s*(?.*?)\\s*\\|"); + Matcher m = line.matcher(SPEC); + Map result = new HashMap<>(); + while (m.find()) { + int index = Integer.parseInt(m.group("index")); + String name = m.group("name"); + String value = m.group("value"); + HeaderField f = new HeaderField(name, value); + result.put(index, f); + } + return Collections.unmodifiableMap(result); // lol + } +} diff --git a/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/HuffmanTest.java b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/HuffmanTest.java new file mode 100644 index 0000000000000000000000000000000000000000..502c7051a794a4f09e99a6a474ce67abcd9e71fa --- /dev/null +++ b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/HuffmanTest.java @@ -0,0 +1,623 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 sun.net.httpclient.hpack; + +import org.testng.annotations.Test; + +import java.nio.ByteBuffer; +import java.util.Stack; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static java.lang.Integer.parseInt; +import static org.testng.Assert.*; + +public final class HuffmanTest { + + // + // https://tools.ietf.org/html/rfc7541#appendix-B + // + private static final String SPEC = + // @formatter:off + " code as bits as hex len\n" + + " sym aligned to MSB aligned in\n" + + " to LSB bits\n" + + " ( 0) |11111111|11000 1ff8 [13]\n" + + " ( 1) |11111111|11111111|1011000 7fffd8 [23]\n" + + " ( 2) |11111111|11111111|11111110|0010 fffffe2 [28]\n" + + " ( 3) |11111111|11111111|11111110|0011 fffffe3 [28]\n" + + " ( 4) |11111111|11111111|11111110|0100 fffffe4 [28]\n" + + " ( 5) |11111111|11111111|11111110|0101 fffffe5 [28]\n" + + " ( 6) |11111111|11111111|11111110|0110 fffffe6 [28]\n" + + " ( 7) |11111111|11111111|11111110|0111 fffffe7 [28]\n" + + " ( 8) |11111111|11111111|11111110|1000 fffffe8 [28]\n" + + " ( 9) |11111111|11111111|11101010 ffffea [24]\n" + + " ( 10) |11111111|11111111|11111111|111100 3ffffffc [30]\n" + + " ( 11) |11111111|11111111|11111110|1001 fffffe9 [28]\n" + + " ( 12) |11111111|11111111|11111110|1010 fffffea [28]\n" + + " ( 13) |11111111|11111111|11111111|111101 3ffffffd [30]\n" + + " ( 14) |11111111|11111111|11111110|1011 fffffeb [28]\n" + + " ( 15) |11111111|11111111|11111110|1100 fffffec [28]\n" + + " ( 16) |11111111|11111111|11111110|1101 fffffed [28]\n" + + " ( 17) |11111111|11111111|11111110|1110 fffffee [28]\n" + + " ( 18) |11111111|11111111|11111110|1111 fffffef [28]\n" + + " ( 19) |11111111|11111111|11111111|0000 ffffff0 [28]\n" + + " ( 20) |11111111|11111111|11111111|0001 ffffff1 [28]\n" + + " ( 21) |11111111|11111111|11111111|0010 ffffff2 [28]\n" + + " ( 22) |11111111|11111111|11111111|111110 3ffffffe [30]\n" + + " ( 23) |11111111|11111111|11111111|0011 ffffff3 [28]\n" + + " ( 24) |11111111|11111111|11111111|0100 ffffff4 [28]\n" + + " ( 25) |11111111|11111111|11111111|0101 ffffff5 [28]\n" + + " ( 26) |11111111|11111111|11111111|0110 ffffff6 [28]\n" + + " ( 27) |11111111|11111111|11111111|0111 ffffff7 [28]\n" + + " ( 28) |11111111|11111111|11111111|1000 ffffff8 [28]\n" + + " ( 29) |11111111|11111111|11111111|1001 ffffff9 [28]\n" + + " ( 30) |11111111|11111111|11111111|1010 ffffffa [28]\n" + + " ( 31) |11111111|11111111|11111111|1011 ffffffb [28]\n" + + " ' ' ( 32) |010100 14 [ 6]\n" + + " '!' ( 33) |11111110|00 3f8 [10]\n" + + " '\"' ( 34) |11111110|01 3f9 [10]\n" + + " '#' ( 35) |11111111|1010 ffa [12]\n" + + " '$' ( 36) |11111111|11001 1ff9 [13]\n" + + " '%' ( 37) |010101 15 [ 6]\n" + + " '&' ( 38) |11111000 f8 [ 8]\n" + + " ''' ( 39) |11111111|010 7fa [11]\n" + + " '(' ( 40) |11111110|10 3fa [10]\n" + + " ')' ( 41) |11111110|11 3fb [10]\n" + + " '*' ( 42) |11111001 f9 [ 8]\n" + + " '+' ( 43) |11111111|011 7fb [11]\n" + + " ',' ( 44) |11111010 fa [ 8]\n" + + " '-' ( 45) |010110 16 [ 6]\n" + + " '.' ( 46) |010111 17 [ 6]\n" + + " '/' ( 47) |011000 18 [ 6]\n" + + " '0' ( 48) |00000 0 [ 5]\n" + + " '1' ( 49) |00001 1 [ 5]\n" + + " '2' ( 50) |00010 2 [ 5]\n" + + " '3' ( 51) |011001 19 [ 6]\n" + + " '4' ( 52) |011010 1a [ 6]\n" + + " '5' ( 53) |011011 1b [ 6]\n" + + " '6' ( 54) |011100 1c [ 6]\n" + + " '7' ( 55) |011101 1d [ 6]\n" + + " '8' ( 56) |011110 1e [ 6]\n" + + " '9' ( 57) |011111 1f [ 6]\n" + + " ':' ( 58) |1011100 5c [ 7]\n" + + " ';' ( 59) |11111011 fb [ 8]\n" + + " '<' ( 60) |11111111|1111100 7ffc [15]\n" + + " '=' ( 61) |100000 20 [ 6]\n" + + " '>' ( 62) |11111111|1011 ffb [12]\n" + + " '?' ( 63) |11111111|00 3fc [10]\n" + + " '@' ( 64) |11111111|11010 1ffa [13]\n" + + " 'A' ( 65) |100001 21 [ 6]\n" + + " 'B' ( 66) |1011101 5d [ 7]\n" + + " 'C' ( 67) |1011110 5e [ 7]\n" + + " 'D' ( 68) |1011111 5f [ 7]\n" + + " 'E' ( 69) |1100000 60 [ 7]\n" + + " 'F' ( 70) |1100001 61 [ 7]\n" + + " 'G' ( 71) |1100010 62 [ 7]\n" + + " 'H' ( 72) |1100011 63 [ 7]\n" + + " 'I' ( 73) |1100100 64 [ 7]\n" + + " 'J' ( 74) |1100101 65 [ 7]\n" + + " 'K' ( 75) |1100110 66 [ 7]\n" + + " 'L' ( 76) |1100111 67 [ 7]\n" + + " 'M' ( 77) |1101000 68 [ 7]\n" + + " 'N' ( 78) |1101001 69 [ 7]\n" + + " 'O' ( 79) |1101010 6a [ 7]\n" + + " 'P' ( 80) |1101011 6b [ 7]\n" + + " 'Q' ( 81) |1101100 6c [ 7]\n" + + " 'R' ( 82) |1101101 6d [ 7]\n" + + " 'S' ( 83) |1101110 6e [ 7]\n" + + " 'T' ( 84) |1101111 6f [ 7]\n" + + " 'U' ( 85) |1110000 70 [ 7]\n" + + " 'V' ( 86) |1110001 71 [ 7]\n" + + " 'W' ( 87) |1110010 72 [ 7]\n" + + " 'X' ( 88) |11111100 fc [ 8]\n" + + " 'Y' ( 89) |1110011 73 [ 7]\n" + + " 'Z' ( 90) |11111101 fd [ 8]\n" + + " '[' ( 91) |11111111|11011 1ffb [13]\n" + + " '\\' ( 92) |11111111|11111110|000 7fff0 [19]\n" + + " ']' ( 93) |11111111|11100 1ffc [13]\n" + + " '^' ( 94) |11111111|111100 3ffc [14]\n" + + " '_' ( 95) |100010 22 [ 6]\n" + + " '`' ( 96) |11111111|1111101 7ffd [15]\n" + + " 'a' ( 97) |00011 3 [ 5]\n" + + " 'b' ( 98) |100011 23 [ 6]\n" + + " 'c' ( 99) |00100 4 [ 5]\n" + + " 'd' (100) |100100 24 [ 6]\n" + + " 'e' (101) |00101 5 [ 5]\n" + + " 'f' (102) |100101 25 [ 6]\n" + + " 'g' (103) |100110 26 [ 6]\n" + + " 'h' (104) |100111 27 [ 6]\n" + + " 'i' (105) |00110 6 [ 5]\n" + + " 'j' (106) |1110100 74 [ 7]\n" + + " 'k' (107) |1110101 75 [ 7]\n" + + " 'l' (108) |101000 28 [ 6]\n" + + " 'm' (109) |101001 29 [ 6]\n" + + " 'n' (110) |101010 2a [ 6]\n" + + " 'o' (111) |00111 7 [ 5]\n" + + " 'p' (112) |101011 2b [ 6]\n" + + " 'q' (113) |1110110 76 [ 7]\n" + + " 'r' (114) |101100 2c [ 6]\n" + + " 's' (115) |01000 8 [ 5]\n" + + " 't' (116) |01001 9 [ 5]\n" + + " 'u' (117) |101101 2d [ 6]\n" + + " 'v' (118) |1110111 77 [ 7]\n" + + " 'w' (119) |1111000 78 [ 7]\n" + + " 'x' (120) |1111001 79 [ 7]\n" + + " 'y' (121) |1111010 7a [ 7]\n" + + " 'z' (122) |1111011 7b [ 7]\n" + + " '{' (123) |11111111|1111110 7ffe [15]\n" + + " '|' (124) |11111111|100 7fc [11]\n" + + " '}' (125) |11111111|111101 3ffd [14]\n" + + " '~' (126) |11111111|11101 1ffd [13]\n" + + " (127) |11111111|11111111|11111111|1100 ffffffc [28]\n" + + " (128) |11111111|11111110|0110 fffe6 [20]\n" + + " (129) |11111111|11111111|010010 3fffd2 [22]\n" + + " (130) |11111111|11111110|0111 fffe7 [20]\n" + + " (131) |11111111|11111110|1000 fffe8 [20]\n" + + " (132) |11111111|11111111|010011 3fffd3 [22]\n" + + " (133) |11111111|11111111|010100 3fffd4 [22]\n" + + " (134) |11111111|11111111|010101 3fffd5 [22]\n" + + " (135) |11111111|11111111|1011001 7fffd9 [23]\n" + + " (136) |11111111|11111111|010110 3fffd6 [22]\n" + + " (137) |11111111|11111111|1011010 7fffda [23]\n" + + " (138) |11111111|11111111|1011011 7fffdb [23]\n" + + " (139) |11111111|11111111|1011100 7fffdc [23]\n" + + " (140) |11111111|11111111|1011101 7fffdd [23]\n" + + " (141) |11111111|11111111|1011110 7fffde [23]\n" + + " (142) |11111111|11111111|11101011 ffffeb [24]\n" + + " (143) |11111111|11111111|1011111 7fffdf [23]\n" + + " (144) |11111111|11111111|11101100 ffffec [24]\n" + + " (145) |11111111|11111111|11101101 ffffed [24]\n" + + " (146) |11111111|11111111|010111 3fffd7 [22]\n" + + " (147) |11111111|11111111|1100000 7fffe0 [23]\n" + + " (148) |11111111|11111111|11101110 ffffee [24]\n" + + " (149) |11111111|11111111|1100001 7fffe1 [23]\n" + + " (150) |11111111|11111111|1100010 7fffe2 [23]\n" + + " (151) |11111111|11111111|1100011 7fffe3 [23]\n" + + " (152) |11111111|11111111|1100100 7fffe4 [23]\n" + + " (153) |11111111|11111110|11100 1fffdc [21]\n" + + " (154) |11111111|11111111|011000 3fffd8 [22]\n" + + " (155) |11111111|11111111|1100101 7fffe5 [23]\n" + + " (156) |11111111|11111111|011001 3fffd9 [22]\n" + + " (157) |11111111|11111111|1100110 7fffe6 [23]\n" + + " (158) |11111111|11111111|1100111 7fffe7 [23]\n" + + " (159) |11111111|11111111|11101111 ffffef [24]\n" + + " (160) |11111111|11111111|011010 3fffda [22]\n" + + " (161) |11111111|11111110|11101 1fffdd [21]\n" + + " (162) |11111111|11111110|1001 fffe9 [20]\n" + + " (163) |11111111|11111111|011011 3fffdb [22]\n" + + " (164) |11111111|11111111|011100 3fffdc [22]\n" + + " (165) |11111111|11111111|1101000 7fffe8 [23]\n" + + " (166) |11111111|11111111|1101001 7fffe9 [23]\n" + + " (167) |11111111|11111110|11110 1fffde [21]\n" + + " (168) |11111111|11111111|1101010 7fffea [23]\n" + + " (169) |11111111|11111111|011101 3fffdd [22]\n" + + " (170) |11111111|11111111|011110 3fffde [22]\n" + + " (171) |11111111|11111111|11110000 fffff0 [24]\n" + + " (172) |11111111|11111110|11111 1fffdf [21]\n" + + " (173) |11111111|11111111|011111 3fffdf [22]\n" + + " (174) |11111111|11111111|1101011 7fffeb [23]\n" + + " (175) |11111111|11111111|1101100 7fffec [23]\n" + + " (176) |11111111|11111111|00000 1fffe0 [21]\n" + + " (177) |11111111|11111111|00001 1fffe1 [21]\n" + + " (178) |11111111|11111111|100000 3fffe0 [22]\n" + + " (179) |11111111|11111111|00010 1fffe2 [21]\n" + + " (180) |11111111|11111111|1101101 7fffed [23]\n" + + " (181) |11111111|11111111|100001 3fffe1 [22]\n" + + " (182) |11111111|11111111|1101110 7fffee [23]\n" + + " (183) |11111111|11111111|1101111 7fffef [23]\n" + + " (184) |11111111|11111110|1010 fffea [20]\n" + + " (185) |11111111|11111111|100010 3fffe2 [22]\n" + + " (186) |11111111|11111111|100011 3fffe3 [22]\n" + + " (187) |11111111|11111111|100100 3fffe4 [22]\n" + + " (188) |11111111|11111111|1110000 7ffff0 [23]\n" + + " (189) |11111111|11111111|100101 3fffe5 [22]\n" + + " (190) |11111111|11111111|100110 3fffe6 [22]\n" + + " (191) |11111111|11111111|1110001 7ffff1 [23]\n" + + " (192) |11111111|11111111|11111000|00 3ffffe0 [26]\n" + + " (193) |11111111|11111111|11111000|01 3ffffe1 [26]\n" + + " (194) |11111111|11111110|1011 fffeb [20]\n" + + " (195) |11111111|11111110|001 7fff1 [19]\n" + + " (196) |11111111|11111111|100111 3fffe7 [22]\n" + + " (197) |11111111|11111111|1110010 7ffff2 [23]\n" + + " (198) |11111111|11111111|101000 3fffe8 [22]\n" + + " (199) |11111111|11111111|11110110|0 1ffffec [25]\n" + + " (200) |11111111|11111111|11111000|10 3ffffe2 [26]\n" + + " (201) |11111111|11111111|11111000|11 3ffffe3 [26]\n" + + " (202) |11111111|11111111|11111001|00 3ffffe4 [26]\n" + + " (203) |11111111|11111111|11111011|110 7ffffde [27]\n" + + " (204) |11111111|11111111|11111011|111 7ffffdf [27]\n" + + " (205) |11111111|11111111|11111001|01 3ffffe5 [26]\n" + + " (206) |11111111|11111111|11110001 fffff1 [24]\n" + + " (207) |11111111|11111111|11110110|1 1ffffed [25]\n" + + " (208) |11111111|11111110|010 7fff2 [19]\n" + + " (209) |11111111|11111111|00011 1fffe3 [21]\n" + + " (210) |11111111|11111111|11111001|10 3ffffe6 [26]\n" + + " (211) |11111111|11111111|11111100|000 7ffffe0 [27]\n" + + " (212) |11111111|11111111|11111100|001 7ffffe1 [27]\n" + + " (213) |11111111|11111111|11111001|11 3ffffe7 [26]\n" + + " (214) |11111111|11111111|11111100|010 7ffffe2 [27]\n" + + " (215) |11111111|11111111|11110010 fffff2 [24]\n" + + " (216) |11111111|11111111|00100 1fffe4 [21]\n" + + " (217) |11111111|11111111|00101 1fffe5 [21]\n" + + " (218) |11111111|11111111|11111010|00 3ffffe8 [26]\n" + + " (219) |11111111|11111111|11111010|01 3ffffe9 [26]\n" + + " (220) |11111111|11111111|11111111|1101 ffffffd [28]\n" + + " (221) |11111111|11111111|11111100|011 7ffffe3 [27]\n" + + " (222) |11111111|11111111|11111100|100 7ffffe4 [27]\n" + + " (223) |11111111|11111111|11111100|101 7ffffe5 [27]\n" + + " (224) |11111111|11111110|1100 fffec [20]\n" + + " (225) |11111111|11111111|11110011 fffff3 [24]\n" + + " (226) |11111111|11111110|1101 fffed [20]\n" + + " (227) |11111111|11111111|00110 1fffe6 [21]\n" + + " (228) |11111111|11111111|101001 3fffe9 [22]\n" + + " (229) |11111111|11111111|00111 1fffe7 [21]\n" + + " (230) |11111111|11111111|01000 1fffe8 [21]\n" + + " (231) |11111111|11111111|1110011 7ffff3 [23]\n" + + " (232) |11111111|11111111|101010 3fffea [22]\n" + + " (233) |11111111|11111111|101011 3fffeb [22]\n" + + " (234) |11111111|11111111|11110111|0 1ffffee [25]\n" + + " (235) |11111111|11111111|11110111|1 1ffffef [25]\n" + + " (236) |11111111|11111111|11110100 fffff4 [24]\n" + + " (237) |11111111|11111111|11110101 fffff5 [24]\n" + + " (238) |11111111|11111111|11111010|10 3ffffea [26]\n" + + " (239) |11111111|11111111|1110100 7ffff4 [23]\n" + + " (240) |11111111|11111111|11111010|11 3ffffeb [26]\n" + + " (241) |11111111|11111111|11111100|110 7ffffe6 [27]\n" + + " (242) |11111111|11111111|11111011|00 3ffffec [26]\n" + + " (243) |11111111|11111111|11111011|01 3ffffed [26]\n" + + " (244) |11111111|11111111|11111100|111 7ffffe7 [27]\n" + + " (245) |11111111|11111111|11111101|000 7ffffe8 [27]\n" + + " (246) |11111111|11111111|11111101|001 7ffffe9 [27]\n" + + " (247) |11111111|11111111|11111101|010 7ffffea [27]\n" + + " (248) |11111111|11111111|11111101|011 7ffffeb [27]\n" + + " (249) |11111111|11111111|11111111|1110 ffffffe [28]\n" + + " (250) |11111111|11111111|11111101|100 7ffffec [27]\n" + + " (251) |11111111|11111111|11111101|101 7ffffed [27]\n" + + " (252) |11111111|11111111|11111101|110 7ffffee [27]\n" + + " (253) |11111111|11111111|11111101|111 7ffffef [27]\n" + + " (254) |11111111|11111111|11111110|000 7fffff0 [27]\n" + + " (255) |11111111|11111111|11111011|10 3ffffee [26]\n" + + " EOS (256) |11111111|11111111|11111111|111111 3fffffff [30]"; + // @formatter:on + + @Test + public void read_table() { + Pattern line = Pattern.compile( + "\\(\\s*(?\\d+)\\s*\\)\\s*(?(\\|(0|1)+)+)\\s*" + + "(?[0-9a-zA-Z]+)\\s*\\[\\s*(?\\d+)\\s*\\]"); + Matcher m = line.matcher(SPEC); + int i = 0; + while (m.find()) { + String ascii = m.group("ascii"); + String binary = m.group("binary").replaceAll("\\|", ""); + String hex = m.group("hex"); + String len = m.group("len"); + + // Several sanity checks for the data read from the table, just to + // make sure what we read makes sense + assertEquals(parseInt(len), binary.length()); + assertEquals(parseInt(binary, 2), parseInt(hex, 16)); + + int expected = parseInt(ascii); + + // TODO: find actual eos, do not hardcode it! + byte[] bytes = intToBytes(0x3fffffff, 30, + parseInt(hex, 16), parseInt(len)); + + StringBuilder actual = new StringBuilder(); + Huffman.Reader t = new Huffman.Reader(); + t.read(ByteBuffer.wrap(bytes), actual, false, true); + + // What has been read MUST represent a single symbol + assertEquals(actual.length(), 1, "ascii: " + ascii); + + // It's a lot more visual to compare char as codes rather than + // characters (as some of them might not be visible) + assertEquals(actual.charAt(0), expected); + i++; + } + assertEquals(i, 257); // 256 + EOS + } + + // + // https://tools.ietf.org/html/rfc7541#appendix-C.4.1 + // + @Test + public void read_1() { + read("f1e3 c2e5 f23a 6ba0 ab90 f4ff", "www.example.com"); + } + + @Test + public void write_1() { + write("www.example.com", "f1e3 c2e5 f23a 6ba0 ab90 f4ff"); + } + + // + // https://tools.ietf.org/html/rfc7541#appendix-C.4.2 + // + @Test + public void read_2() { + read("a8eb 1064 9cbf", "no-cache"); + } + + @Test + public void write_2() { + write("no-cache", "a8eb 1064 9cbf"); + } + + // + // https://tools.ietf.org/html/rfc7541#appendix-C.4.3 + // + @Test + public void read_3() { + read("25a8 49e9 5ba9 7d7f", "custom-key"); + } + + @Test + public void write_3() { + write("custom-key", "25a8 49e9 5ba9 7d7f"); + } + + // + // https://tools.ietf.org/html/rfc7541#appendix-C.4.3 + // + @Test + public void read_4() { + read("25a8 49e9 5bb8 e8b4 bf", "custom-value"); + } + + @Test + public void write_4() { + write("custom-value", "25a8 49e9 5bb8 e8b4 bf"); + } + + // + // https://tools.ietf.org/html/rfc7541#appendix-C.6.1 + // + @Test + public void read_5() { + read("6402", "302"); + } + + @Test + public void write_5() { + write("302", "6402"); + } + + // + // https://tools.ietf.org/html/rfc7541#appendix-C.6.1 + // + @Test + public void read_6() { + read("aec3 771a 4b", "private"); + } + + @Test + public void write_6() { + write("private", "aec3 771a 4b"); + } + + // + // https://tools.ietf.org/html/rfc7541#appendix-C.6.1 + // + @Test + public void read_7() { + read("d07a be94 1054 d444 a820 0595 040b 8166 e082 a62d 1bff", + "Mon, 21 Oct 2013 20:13:21 GMT"); + } + + @Test + public void write_7() { + write("Mon, 21 Oct 2013 20:13:21 GMT", + "d07a be94 1054 d444 a820 0595 040b 8166 e082 a62d 1bff"); + } + + // + // https://tools.ietf.org/html/rfc7541#appendix-C.6.1 + // + @Test + public void read_8() { + read("9d29 ad17 1863 c78f 0b97 c8e9 ae82 ae43 d3", + "https://www.example.com"); + } + + @Test + public void write_8() { + write("https://www.example.com", + "9d29 ad17 1863 c78f 0b97 c8e9 ae82 ae43 d3"); + } + + // + // https://tools.ietf.org/html/rfc7541#appendix-C.6.2 + // + @Test + public void read_9() { + read("640e ff", "307"); + } + + @Test + public void write_9() { + write("307", "640e ff"); + } + + // + // https://tools.ietf.org/html/rfc7541#appendix-C.6.3 + // + @Test + public void read_10() { + read("d07a be94 1054 d444 a820 0595 040b 8166 e084 a62d 1bff", + "Mon, 21 Oct 2013 20:13:22 GMT"); + } + + @Test + public void write_10() { + write("Mon, 21 Oct 2013 20:13:22 GMT", + "d07a be94 1054 d444 a820 0595 040b 8166 e084 a62d 1bff"); + } + + // + // https://tools.ietf.org/html/rfc7541#appendix-C.6.3 + // + @Test + public void read_11() { + read("9bd9 ab", "gzip"); + } + + @Test + public void write_11() { + write("gzip", "9bd9 ab"); + } + + // + // https://tools.ietf.org/html/rfc7541#appendix-C.6.3 + // + @Test + public void read_12() { + read("94e7 821d d7f2 e6c7 b335 dfdf cd5b 3960 " + + "d5af 2708 7f36 72c1 ab27 0fb5 291f 9587 " + + "3160 65c0 03ed 4ee5 b106 3d50 07", + "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"); + } + + @Test + public void test_trie_has_no_empty_nodes() { + Huffman.Node root = Huffman.INSTANCE.getRoot(); + Stack backlog = new Stack<>(); + backlog.push(root); + while (!backlog.isEmpty()) { + Huffman.Node n = backlog.pop(); + // The only type of nodes we couldn't possibly catch during + // construction is an empty node: no children and no char + if (n.left != null) { + backlog.push(n.left); + } + if (n.right != null) { + backlog.push(n.right); + } + assertFalse(!n.charIsSet && n.left == null && n.right == null, + "Empty node in the trie"); + } + } + + @Test + public void test_trie_has_257_nodes() { + int count = 0; + Huffman.Node root = Huffman.INSTANCE.getRoot(); + Stack backlog = new Stack<>(); + backlog.push(root); + while (!backlog.isEmpty()) { + Huffman.Node n = backlog.pop(); + if (n.left != null) { + backlog.push(n.left); + } + if (n.right != null) { + backlog.push(n.right); + } + if (n.isLeaf()) { + count++; + } + } + assertEquals(count, 257); + } + + @Test + public void cant_encode_outside_byte() { + TestHelper.Block coding = + () -> new Huffman.Writer() + .from(((char) 256) + "", 0, 1) + .write(ByteBuffer.allocate(1)); + RuntimeException e = + TestHelper.assertVoidThrows(RuntimeException.class, coding); + TestHelper.assertExceptionMessageContains(e, "char"); + } + + private static void read(String hexdump, String decoded) { + ByteBuffer source = SpecHelper.toBytes(hexdump); + Appendable actual = new StringBuilder(); + new Huffman.Reader().read(source, actual, true); + assertEquals(actual.toString(), decoded); + } + + private static void write(String decoded, String hexdump) { + int n = Huffman.INSTANCE.lengthOf(decoded); + ByteBuffer destination = ByteBuffer.allocate(n); // Extra margin (1) to test having more bytes in the destination than needed is ok + Huffman.Writer writer = new Huffman.Writer(); + BuffersTestingKit.forEachSplit(destination, byteBuffers -> { + writer.from(decoded, 0, decoded.length()); + boolean written = false; + for (ByteBuffer b : byteBuffers) { + int pos = b.position(); + written = writer.write(b); + b.position(pos); + } + assertTrue(written); + ByteBuffer concated = BuffersTestingKit.concat(byteBuffers); + String actual = SpecHelper.toHexdump(concated); + assertEquals(actual, hexdump); + writer.reset(); + }); + } + + // + // It's not very pretty, yes I know that + // + // hex: + // + // |31|30|...|N-1|...|01|00| + // \ / + // codeLength + // + // hex <<= 32 - codeLength; (align to MSB): + // + // |31|30|...|32-N|...|01|00| + // \ / + // codeLength + // + // EOS: + // + // |31|30|...|M-1|...|01|00| + // \ / + // eosLength + // + // eos <<= 32 - eosLength; (align to MSB): + // + // pad with MSBs of EOS: + // + // |31|30|...|32-N|32-N-1|...|01|00| + // | 32|...| + // + // Finally, split into byte[] + // + private byte[] intToBytes(int eos, int eosLength, int hex, int codeLength) { + hex <<= 32 - codeLength; + eos >>= codeLength - (32 - eosLength); + hex |= eos; + int n = (int) Math.ceil(codeLength / 8.0); + byte[] result = new byte[n]; + for (int i = 0; i < n; i++) { + result[i] = (byte) (hex >> (32 - 8 * (i + 1))); + } + return result; + } +} diff --git a/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/SpecHelper.java b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/SpecHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..88bd906514e5f63c34ecb3f3fc90eac95bee93d1 --- /dev/null +++ b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/SpecHelper.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.net.httpclient.hpack; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +// +// THIS IS NOT A TEST +// +public final class SpecHelper { + + private SpecHelper() { + throw new AssertionError(); + } + + public static ByteBuffer toBytes(String hexdump) { + Pattern hexByte = Pattern.compile("[0-9a-fA-F]{2}"); + List bytes = new ArrayList<>(); + Matcher matcher = hexByte.matcher(hexdump); + while (matcher.find()) { + bytes.add(matcher.group(0)); + } + ByteBuffer result = ByteBuffer.allocate(bytes.size()); + for (String f : bytes) { + result.put((byte) Integer.parseInt(f, 16)); + } + result.flip(); + return result; + } + + public static String toHexdump(ByteBuffer bb) { + List words = new ArrayList<>(); + int i = 0; + while (bb.hasRemaining()) { + if (i % 2 == 0) { + words.add(""); + } + byte b = bb.get(); + String hex = Integer.toHexString(256 + Byte.toUnsignedInt(b)).substring(1); + words.set(i / 2, words.get(i / 2) + hex); + i++; + } + return words.stream().collect(Collectors.joining(" ")); + } +} diff --git a/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/TestHelper.java b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/TestHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..b042b5f4cee04cfe1fe0a99856fc49e0e130f977 --- /dev/null +++ b/jdk/test/java/net/httpclient/http2/java.httpclient/sun/net/httpclient/hpack/TestHelper.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * 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 sun.net.httpclient.hpack; + +import org.testng.annotations.Test; + +import java.util.Objects; +import java.util.Random; + +public final class TestHelper { + + public static Random newRandom() { + long seed = Long.getLong("jdk.test.lib.random.seed", System.currentTimeMillis()); + System.out.println("new java.util.Random(" + seed + ")"); + return new Random(seed); + } + + public static T assertVoidThrows(Class clazz, Block code) { + return assertThrows(clazz, () -> { + code.run(); + return null; + }); + } + + public static T assertThrows(Class clazz, ReturningBlock code) { + Objects.requireNonNull(clazz, "clazz == null"); + Objects.requireNonNull(code, "code == null"); + try { + code.run(); + } catch (Throwable t) { + if (clazz.isInstance(t)) { + return clazz.cast(t); + } + throw new AssertionError("Expected to catch exception of type " + + clazz.getCanonicalName() + ", instead caught " + + t.getClass().getCanonicalName(), t); + + } + throw new AssertionError( + "Expected to catch exception of type " + clazz.getCanonicalName() + + ", but caught nothing"); + } + + public static T assertDoesNotThrow(ReturningBlock code) { + Objects.requireNonNull(code, "code == null"); + try { + return code.run(); + } catch (Throwable t) { + throw new AssertionError( + "Expected code block to exit normally, instead " + + "caught " + t.getClass().getCanonicalName(), t); + } + } + + public static void assertVoidDoesNotThrow(Block code) { + Objects.requireNonNull(code, "code == null"); + try { + code.run(); + } catch (Throwable t) { + throw new AssertionError( + "Expected code block to exit normally, instead " + + "caught " + t.getClass().getCanonicalName(), t); + } + } + + + public static void assertExceptionMessageContains(Throwable t, + CharSequence firstSubsequence, + CharSequence... others) { + assertCharSequenceContains(t.getMessage(), firstSubsequence, others); + } + + public static void assertCharSequenceContains(CharSequence s, + CharSequence firstSubsequence, + CharSequence... others) { + if (s == null) { + throw new NullPointerException("Exception message is null"); + } + String str = s.toString(); + String missing = null; + if (!str.contains(firstSubsequence.toString())) { + missing = firstSubsequence.toString(); + } else { + for (CharSequence o : others) { + if (!str.contains(o.toString())) { + missing = o.toString(); + break; + } + } + } + if (missing != null) { + throw new AssertionError("CharSequence '" + s + "'" + " does not " + + "contain subsequence '" + missing + "'"); + } + } + + public interface ReturningBlock { + T run() throws Throwable; + } + + public interface Block { + void run() throws Throwable; + } + + // tests + + @Test + public void assertThrows() { + assertThrows(NullPointerException.class, () -> ((Object) null).toString()); + } + + @Test + public void assertThrowsWrongType() { + try { + assertThrows(IllegalArgumentException.class, () -> ((Object) null).toString()); + } catch (AssertionError e) { + Throwable cause = e.getCause(); + String message = e.getMessage(); + if (cause != null + && cause instanceof NullPointerException + && message != null + && message.contains("instead caught")) { + return; + } + } + throw new AssertionError(); + } + + @Test + public void assertThrowsNoneCaught() { + try { + assertThrows(IllegalArgumentException.class, () -> null); + } catch (AssertionError e) { + Throwable cause = e.getCause(); + String message = e.getMessage(); + if (cause == null + && message != null + && message.contains("but caught nothing")) { + return; + } + } + throw new AssertionError(); + } +} diff --git a/jdk/test/java/security/Signature/TestInitSignWithMyOwnRandom.java b/jdk/test/java/security/Signature/TestInitSignWithMyOwnRandom.java index 2a2121e249dce392ee18b8f49ecbeb632d44b693..0d2d7fd35a4e023eb95ea7e2c9db940d227badb0 100644 --- a/jdk/test/java/security/Signature/TestInitSignWithMyOwnRandom.java +++ b/jdk/test/java/security/Signature/TestInitSignWithMyOwnRandom.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -55,9 +55,9 @@ class TestRandomSource extends SecureRandom { int count = 0; - public int nextInt() { + @Override + public void nextBytes(byte[] rs) { count++; - return 0; } public boolean isUsed() { diff --git a/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java b/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java index 696ba8109cc753259125a21356a891cf293da703..14d7e0359d4c4e86d84b17047807601efb467c75 100644 --- a/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java +++ b/jdk/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * 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,6 +71,7 @@ import static org.testng.Assert.assertEquals; import java.text.ParsePosition; import java.time.LocalDate; +import java.time.LocalDateTime; import java.time.YearMonth; import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; @@ -661,6 +662,8 @@ public class TCKDateTimeFormatterBuilder { {"W"}, {"W"}, + {"g"}, + {"ggggg"}, }; } @@ -761,6 +764,37 @@ public class TCKDateTimeFormatterBuilder { return LocalDate.of(y, m, d); } + //----------------------------------------------------------------------- + @DataProvider(name="modJulianFieldPattern") + Object[][] data_modJuilanFieldPattern() { + return new Object[][] { + {"g", "1"}, + {"g", "123456"}, + {"gggggg", "123456"}, + }; + } + + @Test(dataProvider="modJulianFieldPattern") + public void test_modJulianFieldPattern(String pattern, String input) throws Exception { + DateTimeFormatter.ofPattern(pattern).parse(input); + } + + @DataProvider(name="modJulianFieldValues") + Object[][] data_modJuilanFieldValues() { + return new Object[][] { + {1970, 1, 1, "40587"}, + {1858, 11, 17, "0"}, + {1858, 11, 16, "-1"}, + }; + } + + @Test(dataProvider="modJulianFieldValues") + public void test_modJulianFieldValues(int y, int m, int d, String expected) throws Exception { + DateTimeFormatter df = new DateTimeFormatterBuilder().appendPattern("g").toFormatter(); + assertEquals(LocalDate.of(y, m, d).format(df), expected); + } + + //----------------------------------------------------------------------- @Test public void test_adjacent_strict_firstFixedWidth() throws Exception { @@ -897,7 +931,7 @@ public class TCKDateTimeFormatterBuilder { @Test public void test_adjacent_lenient_fractionFollows_0digit() throws Exception { - // succeeds because hour/min are fixed width + // succeeds because hour, min and fraction of seconds are fixed width DateTimeFormatter f = builder.parseLenient().appendValue(HOUR_OF_DAY, 2).appendValue(MINUTE_OF_HOUR, 2).appendFraction(NANO_OF_SECOND, 3, 3, false).toFormatter(Locale.UK); ParsePosition pp = new ParsePosition(0); TemporalAccessor parsed = f.parseUnresolved("1230", pp); @@ -907,6 +941,21 @@ public class TCKDateTimeFormatterBuilder { assertEquals(parsed.getLong(MINUTE_OF_HOUR), 30L); } + @DataProvider(name="adjacentFractionParseData") + Object[][] data_adjacent_fraction_parse() { + return new Object[][] { + {"20130812214600025", "yyyyMMddHHmmssSSS", LocalDateTime.of(2013, 8, 12, 21, 46, 00, 25000000)}, + {"201308122146000256", "yyyyMMddHHmmssSSSS", LocalDateTime.of(2013, 8, 12, 21, 46, 00, 25600000)}, + }; + } + + @Test(dataProvider = "adjacentFractionParseData") + public void test_adjacent_fraction(String input, String pattern, LocalDateTime expected) { + DateTimeFormatter dtf = DateTimeFormatter.ofPattern(pattern); + LocalDateTime actual = LocalDateTime.parse(input, dtf); + assertEquals(actual, expected); + } + @DataProvider(name="lenientOffsetParseData") Object[][] data_lenient_offset_parse() { return new Object[][] { diff --git a/jdk/test/java/time/tck/java/time/format/TCKLocalizedOffsetIdPrinterParser.java b/jdk/test/java/time/tck/java/time/format/TCKLocalizedOffsetIdPrinterParser.java new file mode 100644 index 0000000000000000000000000000000000000000..d0a1f189e92a3d0363fd73129aac4509a8bc2571 --- /dev/null +++ b/jdk/test/java/time/tck/java/time/format/TCKLocalizedOffsetIdPrinterParser.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 tck.java.time.format; + +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Locale; + +import org.testng.annotations.Test; + +/** + * Test localized behavior of formatter. + */ +@Test +public class TCKLocalizedOffsetIdPrinterParser { + @Test + public void test_localized_offset_parse() { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.S O") + .withLocale(Locale.ENGLISH); + String date = formatter.format(ZonedDateTime.now(ZoneOffset.UTC)); + formatter.parse(date) ; + } +} diff --git a/jdk/test/java/util/ServiceLoader/modules/BasicTest.java b/jdk/test/java/util/ServiceLoader/modules/MiscTests.java similarity index 82% rename from jdk/test/java/util/ServiceLoader/modules/BasicTest.java rename to jdk/test/java/util/ServiceLoader/modules/MiscTests.java index 3b64a1d7d9aab5bf31a1ee1519407f57231ed608..5a99a30737c0f7fc10b4b55d86f0b690813fb604 100644 --- a/jdk/test/java/util/ServiceLoader/modules/BasicTest.java +++ b/jdk/test/java/util/ServiceLoader/modules/MiscTests.java @@ -30,11 +30,11 @@ import static org.testng.Assert.*; /* * @test - * @run testng BasicTest + * @run testng MiscTests * @summary Basic test of ServiceLoader with modules */ -public class BasicTest { +public class MiscTests { @Test public void testEmptyLayer() { @@ -43,18 +43,6 @@ public class BasicTest { assertFalse(sl.iterator().hasNext()); } - @Test - public void testBootLayer() { - ServiceLoader sl - = ServiceLoader.load(Layer.boot(), Provider.class); - boolean found = false; - for (Provider provider : sl) { - if (provider.getName().equals("SunJCE")) - found = true; - } - assertTrue(found); - } - @Test(expectedExceptions = { NullPointerException.class }) public void testNullLayer() { ServiceLoader.load(null, Provider.class); diff --git a/jdk/test/java/util/TimeZone/Bug6772689.java b/jdk/test/java/util/TimeZone/Bug6772689.java index a1ce49682b48a0bc8c9fa50d29cf54ec0d9c8a2c..f730567013d35e7d29f4ef8554eb080796443fdd 100644 --- a/jdk/test/java/util/TimeZone/Bug6772689.java +++ b/jdk/test/java/util/TimeZone/Bug6772689.java @@ -24,7 +24,6 @@ /* * @test * @bug 6772689 - * @key intermittent * @summary Test for standard-to-daylight transitions at midnight: * date stays on the given day. */ diff --git a/jdk/test/javax/imageio/plugins/tiff/MultiPageImageTIFFFieldTest.java b/jdk/test/javax/imageio/plugins/tiff/MultiPageImageTIFFFieldTest.java new file mode 100644 index 0000000000000000000000000000000000000000..4a5757824fd1807cec39313e2b91ee509b321c1a --- /dev/null +++ b/jdk/test/javax/imageio/plugins/tiff/MultiPageImageTIFFFieldTest.java @@ -0,0 +1,378 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 + * @ignore 8148454 + * @bug 8152183 8148454 + * @author a.stepanov + * @summary check that TIFFields are derived properly for multi-page tiff + * @run main MultiPageImageTIFFFieldTest + */ + +import java.awt.*; +import java.awt.color.*; +import java.awt.image.BufferedImage; +import java.io.*; +import javax.imageio.*; +import javax.imageio.metadata.*; +import javax.imageio.stream.*; +import javax.imageio.plugins.tiff.*; + + +public class MultiPageImageTIFFFieldTest { + + private final static String FILENAME = "test.tiff"; + private final static int W1 = 20, H1 = 40, W2 = 100, H2 = 15; + private final static Color C1 = Color.BLACK, C2 = Color.RED; + + private final static int N_WIDTH = BaselineTIFFTagSet.TAG_IMAGE_WIDTH; + private final static int N_HEIGHT = BaselineTIFFTagSet.TAG_IMAGE_LENGTH; + + private static final String DESCRIPTION_1[] = {"Description-1", "abc ABC"}; + private static final String DESCRIPTION_2[] = {"Description-2", "1-2-3"}; + private final static int N_DESCRIPTION = + BaselineTIFFTagSet.TAG_IMAGE_DESCRIPTION; + + private final static String EXIF_DATA_1[] = {"2001:01:01 00:00:01"}; + private final static String EXIF_DATA_2[] = {"2002:02:02 00:00:02"}; + private final static int N_EXIF = ExifTIFFTagSet.TAG_DATE_TIME_ORIGINAL; + + private final static String GPS_DATA[] = { + ExifGPSTagSet.STATUS_MEASUREMENT_IN_PROGRESS}; + private final static int N_GPS = ExifGPSTagSet.TAG_GPS_STATUS; + + private final static short FAX_DATA = + FaxTIFFTagSet.CLEAN_FAX_DATA_ERRORS_UNCORRECTED; + private final static int N_FAX = FaxTIFFTagSet.TAG_CLEAN_FAX_DATA; + + private static final byte[] ICC_PROFILE_2 = + ICC_ProfileRGB.getInstance(ColorSpace.CS_sRGB).getData(); + private static final int N_ICC = BaselineTIFFTagSet.TAG_ICC_PROFILE; + + private static final int N_BPS = BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE; + + private static final int + COMPRESSION_1 = BaselineTIFFTagSet.COMPRESSION_DEFLATE, + COMPRESSION_2 = BaselineTIFFTagSet.COMPRESSION_LZW; + private static final int N_COMPRESSION = BaselineTIFFTagSet.TAG_COMPRESSION; + + private static final int + GRAY_1 = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO, + GRAY_2 = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO, + RGB = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_RGB; + + private static final int N_PHOTO = + BaselineTIFFTagSet.TAG_PHOTOMETRIC_INTERPRETATION; + + private ImageWriter getTIFFWriter() { + + java.util.Iterator writers = + ImageIO.getImageWritersByFormatName("TIFF"); + if (!writers.hasNext()) { + throw new RuntimeException("No writers available for TIFF format"); + } + return writers.next(); + } + + private ImageReader getTIFFReader() { + + java.util.Iterator readers = + ImageIO.getImageReadersByFormatName("TIFF"); + if (!readers.hasNext()) { + throw new RuntimeException("No readers available for TIFF format"); + } + return readers.next(); + } + + private void addASCIIField(TIFFDirectory d, + String name, + String data[], + int num) { + + d.addTIFFField(new TIFFField( + new TIFFTag(name, num, 1 << TIFFTag.TIFF_ASCII), + TIFFTag.TIFF_ASCII, data.length, data)); + } + + private void checkASCIIField(TIFFDirectory d, + String what, + String data[], + int num) { + + String notFound = what + " field was not found"; + check(d.containsTIFFField(num), notFound); + TIFFField f = d.getTIFFField(num); + check(f.getType() == TIFFTag.TIFF_ASCII, "field type != ASCII"); + check(f.getCount() == data.length, "invalid " + what + " data count"); + for (int i = 0; i < data.length; i++) { + check(f.getValueAsString(i).equals(data[i]), + "invalid " + what + " data"); + } + } + + private void writeImage() throws Exception { + + OutputStream s = new BufferedOutputStream(new FileOutputStream(FILENAME)); + try (ImageOutputStream ios = ImageIO.createImageOutputStream(s)) { + + ImageWriter writer = getTIFFWriter(); + writer.setOutput(ios); + + BufferedImage img1 = + new BufferedImage(W1, H1, BufferedImage.TYPE_BYTE_GRAY); + Graphics g = img1.getGraphics(); + g.setColor(C1); + g.fillRect(0, 0, W1, H1); + g.dispose(); + + BufferedImage img2 = + new BufferedImage(W2, H2, BufferedImage.TYPE_INT_RGB); + g = img2.getGraphics(); + g.setColor(C2); + g.fillRect(0, 0, W2, H2); + g.dispose(); + + ImageWriteParam param1 = writer.getDefaultWriteParam(); + param1.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); + param1.setCompressionType("Deflate"); + param1.setCompressionQuality(0.5f); + + ImageWriteParam param2 = writer.getDefaultWriteParam(); + param2.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); + param2.setCompressionType("LZW"); + param2.setCompressionQuality(0.5f); + + IIOMetadata + md1 = writer.getDefaultImageMetadata( + new ImageTypeSpecifier(img1), param1), + md2 = writer.getDefaultImageMetadata( + new ImageTypeSpecifier(img2), param2); + + TIFFDirectory + dir1 = TIFFDirectory.createFromMetadata(md1), + dir2 = TIFFDirectory.createFromMetadata(md2); + + addASCIIField(dir1, "ImageDescription", DESCRIPTION_1, N_DESCRIPTION); + addASCIIField(dir2, "ImageDescription", DESCRIPTION_2, N_DESCRIPTION); + + addASCIIField(dir1, "GPSStatus", GPS_DATA, N_GPS); + addASCIIField(dir2, "GPSStatus", GPS_DATA, N_GPS); + + addASCIIField(dir1, "DateTimeOriginal", EXIF_DATA_1, N_EXIF); + addASCIIField(dir2, "DateTimeOriginal", EXIF_DATA_2, N_EXIF); + + TIFFTag faxTag = new TIFFTag( + "CleanFaxData", N_FAX, 1 << TIFFTag.TIFF_SHORT); + dir1.addTIFFField(new TIFFField(faxTag, FAX_DATA)); + dir2.addTIFFField(new TIFFField(faxTag, FAX_DATA)); + + dir2.addTIFFField(new TIFFField( + new TIFFTag("ICC Profile", N_ICC, 1 << TIFFTag.TIFF_UNDEFINED), + TIFFTag.TIFF_UNDEFINED, ICC_PROFILE_2.length, ICC_PROFILE_2)); + + writer.prepareWriteSequence(null); + writer.writeToSequence( + new IIOImage(img1, null, dir1.getAsMetadata()), param1); + writer.writeToSequence( + new IIOImage(img2, null, dir2.getAsMetadata()), param2); + writer.endWriteSequence(); + + ios.flush(); + writer.dispose(); + } + s.close(); + } + + private void checkBufferedImages(BufferedImage im1, BufferedImage im2) { + + check(im1.getWidth() == W1, "invalid width for image 1"); + check(im1.getHeight() == H1, "invalid height for image 1"); + check(im2.getWidth() == W2, "invalid width for image 2"); + check(im2.getHeight() == H2, "invalid height for image 2"); + + Color + c1 = new Color(im1.getRGB(W1 / 2, H1 / 2)), + c2 = new Color(im2.getRGB(W2 / 2, H2 / 2)); + + check(c1.equals(C1), "invalid image 1 color"); + check(c2.equals(C2), "invalid image 2 color"); + } + + private void readAndCheckImage() throws Exception { + + ImageReader reader = getTIFFReader(); + + ImageInputStream s = ImageIO.createImageInputStream(new File(FILENAME)); + reader.setInput(s, false, true); + + int ni = reader.getNumImages(true); + check(ni == 2, "invalid number of images"); + + // check TIFFImageReadParam for multipage image + TIFFImageReadParam + param1 = new TIFFImageReadParam(), param2 = new TIFFImageReadParam(); + + param1.addAllowedTagSet(ExifTIFFTagSet.getInstance()); + param1.addAllowedTagSet(ExifGPSTagSet.getInstance()); + + param2.addAllowedTagSet(ExifTIFFTagSet.getInstance()); + param2.addAllowedTagSet(GeoTIFFTagSet.getInstance()); + + // FaxTIFFTagSet is allowed by default + param2.removeAllowedTagSet(FaxTIFFTagSet.getInstance()); + + + // read images and metadata + IIOImage i1 = reader.readAll(0, param1), i2 = reader.readAll(1, param2); + BufferedImage + bi1 = (BufferedImage) i1.getRenderedImage(), + bi2 = (BufferedImage) i2.getRenderedImage(); + + // check rendered images, just in case + checkBufferedImages(bi1, bi2); + + TIFFDirectory + dir1 = TIFFDirectory.createFromMetadata(i1.getMetadata()), + dir2 = TIFFDirectory.createFromMetadata(i2.getMetadata()); + + // check ASCII fields + checkASCIIField( + dir1, "image 1 description", DESCRIPTION_1, N_DESCRIPTION); + checkASCIIField( + dir2, "image 2 description", DESCRIPTION_2, N_DESCRIPTION); + + checkASCIIField(dir1, "image 1 datetime", EXIF_DATA_1, N_EXIF); + checkASCIIField(dir2, "image 2 datetime", EXIF_DATA_2, N_EXIF); + + // check sizes + TIFFField f = dir1.getTIFFField(N_WIDTH); + check((f.getCount() == 1) && (f.getAsInt(0) == W1), + "invalid width field for image 1"); + f = dir2.getTIFFField(N_WIDTH); + check((f.getCount() == 1) && (f.getAsInt(0) == W2), + "invalid width field for image 2"); + + f = dir1.getTIFFField(N_HEIGHT); + check((f.getCount() == 1) && (f.getAsInt(0) == H1), + "invalid height field for image 1"); + f = dir2.getTIFFField(N_HEIGHT); + check((f.getCount() == 1) && (f.getAsInt(0) == H2), + "invalid height field for image 2"); + + // check fax data + check(dir1.containsTIFFField(N_FAX), "image 2 TIFF directory " + + "must contain clean fax data"); + f = dir1.getTIFFField(N_FAX); + check( + (f.getCount() == 1) && f.isIntegral() && (f.getAsInt(0) == FAX_DATA), + "invalid clean fax data"); + + check(!dir2.containsTIFFField(N_FAX), "image 2 TIFF directory " + + "must not contain fax fields"); + + // check GPS data + checkASCIIField(dir1, "GPS status", GPS_DATA, N_GPS); + + check(!dir2.containsTIFFField(N_GPS), "image 2 TIFF directory " + + "must not contain GPS fields"); + + // check ICC profile data + check(!dir1.containsTIFFField(N_ICC), "image 1 TIFF directory " + + "must not contain ICC Profile field"); + check(dir2.containsTIFFField(N_ICC), "image 2 TIFF directory " + + "must contain ICC Profile field"); + + f = dir2.getTIFFField(N_ICC); + check(f.getType() == TIFFTag.TIFF_UNDEFINED, + "invalid ICC profile field type"); + int cnt = f.getCount(); + byte icc[] = f.getAsBytes(); + check((cnt == ICC_PROFILE_2.length) && (cnt == icc.length), + "invalid ICC profile"); + for (int i = 0; i < cnt; i++) { + check(icc[i] == ICC_PROFILE_2[i], "invalid ICC profile data"); + } + + // check component sizes + check(dir1.getTIFFField(N_BPS).isIntegral() && + dir2.getTIFFField(N_BPS).isIntegral(), + "invalid bits per sample type"); + int sz1[] = bi1.getColorModel().getComponentSize(), + sz2[] = bi2.getColorModel().getComponentSize(), + bps1[] = dir1.getTIFFField(N_BPS).getAsInts(), + bps2[] = dir2.getTIFFField(N_BPS).getAsInts(); + + check((bps1.length == sz1.length) && (bps2.length == sz2.length), + "invalid component size count"); + + for (int i = 0; i < bps1.length; i++) { + check(bps1[i] == sz1[i], "image 1: invalid bits per sample data"); + } + + for (int i = 0; i < bps2.length; i++) { + check(bps2[i] == sz2[i], "image 2: invalid bits per sample data"); + } + + // check compression data + check(dir1.containsTIFFField(N_COMPRESSION) && + dir2.containsTIFFField(N_COMPRESSION), + "compression info lost"); + f = dir1.getTIFFField(N_COMPRESSION); + check(f.isIntegral() && (f.getCount() == 1) && + (f.getAsInt(0) == COMPRESSION_1), "invalid image 1 compression data"); + + f = dir2.getTIFFField(N_COMPRESSION); + check(f.isIntegral() && (f.getCount() == 1) && + (f.getAsInt(0) == COMPRESSION_2), "invalid image 2 compression data"); + + // check photometric interpretation + f = dir1.getTIFFField(N_PHOTO); + check(f.isIntegral() && (f.getCount() == 1) && + ((f.getAsInt(0) == GRAY_1) || (f.getAsInt(0) == GRAY_2)), + "invalid photometric interpretation for image 1"); + + f = dir2.getTIFFField(N_PHOTO); + check(f.isIntegral() && (f.getCount() == 1) && (f.getAsInt(0) == RGB), + "invalid photometric interpretation for image 2"); + } + + public void run() { + + try { + writeImage(); + readAndCheckImage(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private void check(boolean ok, String msg) { + + if (!ok) { throw new RuntimeException(msg); } + } + + public static void main(String[] args) { + (new MultiPageImageTIFFFieldTest()).run(); + } +} diff --git a/jdk/test/javax/imageio/plugins/tiff/TIFFDirectoryTest.java b/jdk/test/javax/imageio/plugins/tiff/TIFFDirectoryTest.java new file mode 100644 index 0000000000000000000000000000000000000000..39c2474512c8007e44270408338370c5ac26504c --- /dev/null +++ b/jdk/test/javax/imageio/plugins/tiff/TIFFDirectoryTest.java @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 8149028 + * @author a.stepanov + * @summary some simple checks for TIFFDirectory + * @run main TIFFDirectoryTest + */ + +import java.util.List; +import java.util.ArrayList; +import javax.imageio.metadata.*; +import javax.imageio.plugins.tiff.*; + + +public class TIFFDirectoryTest { + + private static void check(boolean ok, String msg) { + if (!ok) { throw new RuntimeException(msg); } + } + + private void run() { + + int type = TIFFTag.TIFF_LONG, dt = 1 << type; + int n0 = 1000, n1 = 1001, n2 = 1002, n3 = 1003; + + TIFFTag tag1 = new TIFFTag(Integer.toString(n1), n1, dt); + TIFFTag tag2 = new TIFFTag(Integer.toString(n2), n2, dt); + TIFFTag tag3 = new TIFFTag(Integer.toString(n3), n3, dt); + TIFFTag parent = new TIFFTag(Integer.toString(n0), n0, dt); + + // tag sets array must not be null + boolean ok = false; + try { new TIFFDirectory(null, parent); } + catch (NullPointerException e) { ok = true; } + check(ok, "can construct TIFFDirectory with null tagsets array"); + + // but can be empty + TIFFTagSet emptySets[] = {}; + TIFFDirectory d = new TIFFDirectory(emptySets, parent); + check(d.getTagSets().length == 0, "invalid number of tag sets"); + check(d.getParentTag().getName().equals(Integer.toString(n0)) && + (d.getParentTag().getNumber() == n0), "invalid parent tag"); + + + // add tags + List tags = new ArrayList<>(); + tags.add(tag1); + tags.add(tag2); + TIFFTagSet ts1 = new TIFFTagSet(tags); + + tags.clear(); + tags.add(tag3); + TIFFTagSet ts2 = new TIFFTagSet(tags); + + TIFFTagSet sets[] = {ts1, ts2}; + d = new TIFFDirectory(sets, parent); + + check(d.getTagSets().length == sets.length, "invalid number of tag sets"); + + // check getTag() + for (int i = n1; i <= n3; i++) { + TIFFTag t = d.getTag(i); + check(t.getNumber() == i, "invalid tag number"); + check(t.getName().equals(Integer.toString(i)), "invalid tag name"); + check(t.getDataTypes() == dt, "invalid tag data types"); + } + + TIFFDirectory d2; + try { d2 = d.clone(); } + catch (CloneNotSupportedException e) { throw new RuntimeException(e); } + + // check removeTagSet() + d.removeTagSet(ts2); + check(d.getTagSets().length == 1, "invalid number of tag sets"); + check(d.getTagSets()[0].getTag(n1).getName().equals(Integer.toString(n1)), + "invalid tag name"); + check(d.getTagSets()[0].getTag(n2).getName().equals(Integer.toString(n2)), + "invalid tag name"); + + d.removeTagSet(ts1); + check(d.getTagSets().length == 0, "invalid number of tag sets"); + + // check cloned data + check(d2.getTagSets().length == sets.length, + "invalid number of tag sets"); + TIFFTagSet sets2[] = d2.getTagSets(); + check(sets2.length == sets.length, "invalid number of tag sets"); + check( + (sets2[0].getTag(Integer.toString(n1)).getNumber() == n1) && + (sets2[0].getTag(Integer.toString(n2)).getNumber() == n2) && + (sets2[0].getTag(Integer.toString(n0)) == null) && + (sets2[1].getTag(Integer.toString(n3)).getNumber() == n3) && + (sets2[1].getTag(Integer.toString(n0)) == null), "invalid data"); + + check( + (sets2[0].getTag(Integer.toString(n1)).getDataTypes() == dt) && + (sets2[0].getTag(Integer.toString(n2)).getDataTypes() == dt) && + (sets2[1].getTag(Integer.toString(n3)).getDataTypes() == dt), + "invalid data type"); + + // must not be able to call removeTagSet with null argument + ok = false; + try { d.removeTagSet(null); } + catch (NullPointerException e) { ok = true; } + check(ok, "must not be able to use null as an argument for remove"); + + // check parent tag + check( d.getParentTag().getName().equals(Integer.toString(n0)) && + d2.getParentTag().getName().equals(Integer.toString(n0)), + "invalid parent tag name"); + + check(( d.getParentTag().getNumber() == n0) && + (d2.getParentTag().getNumber() == n0), + "invalid parent tag number"); + + check(( d.getParentTag().getDataTypes() == dt) && + (d2.getParentTag().getDataTypes() == dt), + "invalid parent data type"); + + d.addTagSet(ts1); + d.addTagSet(ts2); + + // add the same tag set twice and check that nothing changed + d.addTagSet(ts2); + + check(d.getTagSets().length == 2, "invalid number of tag sets"); + + // check field operations + check(d.getNumTIFFFields() == 0, "invalid TIFFFields number"); + check(d.getTIFFField(Integer.MAX_VALUE) == null, + "must return null TIFFField"); + + long offset = 4L; + long a[] = {Long.MIN_VALUE, 0, Long.MAX_VALUE}; + int v = 100500; + TIFFField + f1 = new TIFFField(tag1, type, offset, d), + f2 = new TIFFField(tag2, v), + f3 = new TIFFField(tag3, type, a.length, a); + + d.addTIFFField(f1); + d.addTIFFField(f2); + d.addTIFFField(f3); + + check(d.containsTIFFField(n1) && + d.containsTIFFField(n2) && + d.containsTIFFField(n3) && + !d.containsTIFFField(n0), "invalid containsTIFFField() results"); + + check(d.getTIFFField(n0) == null, "can get unadded field"); + + check(d.getNumTIFFFields() == 3, "invalid TIFFFields number"); + + check(d.getTIFFField(n1).getCount() == 1, "invalid TIFFField count"); + check(d.getTIFFField(n1).getAsLong(0) == offset, "invalid offset"); + + check(d.getTIFFField(n2).getCount() == 1, "invalid TIFFField count"); + check(d.getTIFFField(n2).getAsInt(0) == v, "invalid TIFFField value"); + + check(d.getTIFFField(n3).getCount() == a.length, + "invalid TIFFField count"); + for (int i = 0; i < a.length; ++i) { + check(d.getTIFFField(n3).getAsLong(i) == a[i], + "invalid TIFFField value"); + } + + TIFFField nested = d.getTIFFField(n1).getDirectory().getTIFFField(n1); + check(nested.getTag().getNumber() == n1, "invalid tag number"); + check(nested.getCount() == 1, "invalid field count"); + check(nested.getAsLong(0) == offset, "invalid offset"); + + // check that the field is overwritten correctly + int v2 = 1 << 16; + d.addTIFFField(new TIFFField(tag3, v2)); + check(d.getTIFFField(n3).getCount() == 1, "invalid TIFFField count"); + check(d.getTIFFField(n3).getAsInt(0)== v2, "invalid TIFFField value"); + check(d.getNumTIFFFields() == 3, "invalid TIFFFields number"); + + // check removeTIFFField() + d.removeTIFFField(n3); + check(d.getNumTIFFFields() == 2, "invalid TIFFFields number"); + check(d.getTIFFField(n3) == null, "can get removed field"); + + d.removeTIFFFields(); + check((d.getTIFFField(n1) == null) && (d.getTIFFField(n2) == null), + "can get removed field"); + check((d.getNumTIFFFields() == 0) && (d.getTIFFFields().length == 0), + "invalid TIFFFields number"); + + // check that array returned by getTIFFFields() is sorted + // by tag number (as it stated in the docs) + d.addTIFFField(f3); + d.addTIFFField(f1); + d.addTIFFField(f2); + + TIFFField fa[] = d.getTIFFFields(); + check(fa.length == 3, "invalid number of fields"); + check((fa[0].getTagNumber() == n1) && + (fa[1].getTagNumber() == n2) && + (fa[2].getTagNumber() == n3), + "array of the fields must be sorted by tag number"); + + d.removeTIFFFields(); + d.addTIFFField(f2); + + // test getAsMetaData / createFromMetadata + try { + d2 = TIFFDirectory.createFromMetadata(d.getAsMetadata()); + } catch (IIOInvalidTreeException e) { + throw new RuntimeException(e); + } + + // check new data + check(d2.getTagSets().length == sets.length, + "invalid number of tag sets"); + sets2 = d2.getTagSets(); + check(sets2.length == sets.length, "invalid number of tag sets"); + check( + (sets2[0].getTag(Integer.toString(n1)).getNumber() == n1) && + (sets2[0].getTag(Integer.toString(n2)).getNumber() == n2) && + (sets2[0].getTag(Integer.toString(n0)) == null) && + (sets2[1].getTag(Integer.toString(n3)).getNumber() == n3) && + (sets2[1].getTag(Integer.toString(n0)) == null), "invalid data"); + + check( + (sets2[0].getTag(Integer.toString(n1)).getDataTypes() == dt) && + (sets2[0].getTag(Integer.toString(n2)).getDataTypes() == dt) && + (sets2[1].getTag(Integer.toString(n3)).getDataTypes() == dt), + "invalid data type"); + + check(!d2.containsTIFFField(n1) && + d2.containsTIFFField(n2) && + !d2.containsTIFFField(n3), "invalid containsTIFFField() results"); + check(d2.getTIFFField(n2).getCount() == 1, "invalid TIFFField count"); + check(d2.getTIFFField(n2).getAsInt(0) == v, "invalid TIFFField value"); + + check((d2.getParentTag().getNumber() == n0) && + d2.getParentTag().getName().equals(Integer.toString(n0)), + "invalid parent tag"); + } + + public static void main(String[] args) { (new TIFFDirectoryTest()).run(); } +} diff --git a/jdk/test/javax/imageio/plugins/tiff/TIFFDirectoryWriteReadTest.java b/jdk/test/javax/imageio/plugins/tiff/TIFFDirectoryWriteReadTest.java new file mode 100644 index 0000000000000000000000000000000000000000..4547760801699d936b6f753e253541305dba8acb --- /dev/null +++ b/jdk/test/javax/imageio/plugins/tiff/TIFFDirectoryWriteReadTest.java @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 8149028 + * @author a.stepanov + * @summary a simple write-read test for TIFFDirectory + * @run main TIFFDirectoryWriteReadTest + */ + +import java.awt.*; +import java.awt.color.*; +import java.awt.image.BufferedImage; +import java.io.*; +import javax.imageio.*; +import javax.imageio.metadata.*; +import javax.imageio.stream.*; +import javax.imageio.plugins.tiff.*; + + +public class TIFFDirectoryWriteReadTest { + + private final static String FILENAME = "test.tiff"; + private final static int SZ = 100; + private final static Color C = Color.RED; + + private static final String COPYRIGHT[] = {"Copyright 123ABC.."}; + private static final String DESCRIPTION[] = {"Test Image", "Description"}; + private static final String SOFTWARE[] = {"test", "software", "123"}; + + private static final long RES_X[][] = {{2, 1}}, RES_Y[][] = {{1, 1}}; + + private static final byte[] ICC_PROFILE = + ICC_ProfileRGB.getInstance(ColorSpace.CS_sRGB).getData(); + + + private ImageWriter getTIFFWriter() { + + java.util.Iterator writers = + ImageIO.getImageWritersByFormatName("TIFF"); + if (!writers.hasNext()) { + throw new RuntimeException("No writers available for TIFF format"); + } + return writers.next(); + } + + private ImageReader getTIFFReader() { + + java.util.Iterator readers = + ImageIO.getImageReadersByFormatName("TIFF"); + if (!readers.hasNext()) { + throw new RuntimeException("No readers available for TIFF format"); + } + return readers.next(); + } + + private void addASCIIField(TIFFDirectory d, + String name, + String data[], + int num) { + + d.addTIFFField(new TIFFField( + new TIFFTag(name, num, 1 << TIFFTag.TIFF_ASCII), + TIFFTag.TIFF_ASCII, data.length, data)); + } + + private void checkASCIIField(TIFFDirectory d, + String what, + String data[], + int num) { + + String notFound = what + " field was not found"; + check(d.containsTIFFField(num), notFound); + TIFFField f = d.getTIFFField(num); + check(f.getType() == TIFFTag.TIFF_ASCII, "field type != ASCII"); + check(f.getCount() == data.length, "invalid " + what + " data count"); + for (int i = 0; i < data.length; i++) { + check(f.getValueAsString(i).equals(data[i]), + "invalid " + what + " data"); + } + } + + private void writeImage() throws Exception { + + OutputStream s = new BufferedOutputStream(new FileOutputStream(FILENAME)); + try (ImageOutputStream ios = ImageIO.createImageOutputStream(s)) { + + ImageWriter writer = getTIFFWriter(); + writer.setOutput(ios); + + BufferedImage img = new BufferedImage( + SZ, SZ, BufferedImage.TYPE_INT_RGB); + Graphics g = img.getGraphics(); + g.setColor(C); + g.fillRect(0, 0, SZ, SZ); + g.dispose(); + + IIOMetadata metadata = writer.getDefaultImageMetadata( + new ImageTypeSpecifier(img), writer.getDefaultWriteParam()); + + TIFFDirectory dir = TIFFDirectory.createFromMetadata(metadata); + + addASCIIField(dir, "Copyright", + COPYRIGHT, BaselineTIFFTagSet.TAG_COPYRIGHT); + + addASCIIField(dir, "ImageDescription", + DESCRIPTION, BaselineTIFFTagSet.TAG_IMAGE_DESCRIPTION); + + addASCIIField(dir, "Software", + SOFTWARE, BaselineTIFFTagSet.TAG_SOFTWARE); + + dir.addTIFFField(new TIFFField( + new TIFFTag("XResolution", BaselineTIFFTagSet.TAG_X_RESOLUTION, + 1 << TIFFTag.TIFF_RATIONAL), TIFFTag.TIFF_RATIONAL, 1, RES_X)); + dir.addTIFFField(new TIFFField( + new TIFFTag("YResolution", BaselineTIFFTagSet.TAG_Y_RESOLUTION, + 1 << TIFFTag.TIFF_RATIONAL), TIFFTag.TIFF_RATIONAL, 1, RES_Y)); + + dir.addTIFFField(new TIFFField( + new TIFFTag("ICC Profile", BaselineTIFFTagSet.TAG_ICC_PROFILE, + 1 << TIFFTag.TIFF_UNDEFINED), + TIFFTag.TIFF_UNDEFINED, ICC_PROFILE.length, ICC_PROFILE)); + + IIOMetadata data = dir.getAsMetadata(); + writer.write(new IIOImage(img, null, data)); + + ios.flush(); + writer.dispose(); + } + s.close(); + } + + + + private void readAndCheckImage() throws Exception { + + ImageReader reader = getTIFFReader(); + + ImageInputStream s = ImageIO.createImageInputStream(new File(FILENAME)); + reader.setInput(s); + + int ni = reader.getNumImages(true); + check(ni == 1, "invalid number of images"); + + // check image + BufferedImage img = reader.read(0); + check(img.getWidth() == SZ && img.getHeight() == SZ, + "invalid image size"); + + Color c = new Color(img.getRGB(SZ / 2, SZ / 2)); + check(C.equals(c), "invalid image color"); + + IIOMetadata metadata = reader.readAll(0, null).getMetadata(); + TIFFDirectory dir = TIFFDirectory.createFromMetadata(metadata); + + reader.dispose(); + s.close(); + + // ===== perform tag checks ===== + + checkASCIIField(dir, "copyright", COPYRIGHT, + BaselineTIFFTagSet.TAG_COPYRIGHT); + + checkASCIIField(dir, "description", DESCRIPTION, + BaselineTIFFTagSet.TAG_IMAGE_DESCRIPTION); + + checkASCIIField(dir, "software", SOFTWARE, + BaselineTIFFTagSet.TAG_SOFTWARE); + + TIFFField f = dir.getTIFFField(BaselineTIFFTagSet.TAG_IMAGE_WIDTH); + check(f.getCount() == 1, "invalid width field count"); + int w = f.getAsInt(0); + check(w == SZ, "invalid width"); + + f = dir.getTIFFField(BaselineTIFFTagSet.TAG_IMAGE_LENGTH); + check(f.getCount() == 1, "invalid height field count"); + int h = f.getAsInt(0); + check(h == SZ, "invalid height"); + + f = dir.getTIFFField(BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE); + // RGB: 3 x 8 bits for R, G and B components + int bps[] = f.getAsInts(); + check((f.getCount() == 3) && (bps.length == 3), "invalid BPS count"); + for (int b: bps) { check(b == 8, "invalid bits per sample"); } + + // RGB: PhotometricInterpretation = 2 + f = dir.getTIFFField(BaselineTIFFTagSet.TAG_PHOTOMETRIC_INTERPRETATION); + check(f.getCount() == 1, "invalid count"); + check(f.getAsInt(0) == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_RGB, + "invalid photometric interpretation value"); + + String rat = " resolution must be rational"; + f = dir.getTIFFField(BaselineTIFFTagSet.TAG_X_RESOLUTION); + check(f.getType() == TIFFTag.TIFF_RATIONAL, "x" + rat); + check(f.getCount() == 1 && + f.getAsInt(0) == (int) (RES_X[0][0] / RES_X[0][1]), + "invalid x resolution"); + + f = dir.getTIFFField(BaselineTIFFTagSet.TAG_Y_RESOLUTION); + check(f.getType() == TIFFTag.TIFF_RATIONAL, "y" + rat); + check(f.getCount() == 1 && + f.getAsInt(0) == (int) (RES_Y[0][0] / RES_Y[0][1]), + "invalid y resolution"); + + f = dir.getTIFFField(BaselineTIFFTagSet.TAG_ICC_PROFILE); + check(f.getType() == TIFFTag.TIFF_UNDEFINED, + "invalid ICC profile field type"); + int cnt = f.getCount(); + byte icc[] = f.getAsBytes(); + check((cnt == ICC_PROFILE.length) && (cnt == icc.length), + "invalid ICC profile"); + for (int i = 0; i < cnt; i++) { + check(icc[i] == ICC_PROFILE[i], "invalid ICC profile"); + } + } + + public void run() { + + try { + writeImage(); + readAndCheckImage(); + } catch (Exception e) { + throw new RuntimeException(e); + } + + } + + private void check(boolean ok, String msg) { + if (!ok) { throw new RuntimeException(msg); } + } + + public static void main(String[] args) { + (new TIFFDirectoryWriteReadTest()).run(); + } +} diff --git a/jdk/test/javax/imageio/plugins/tiff/TIFFFieldTest.java b/jdk/test/javax/imageio/plugins/tiff/TIFFFieldTest.java new file mode 100644 index 0000000000000000000000000000000000000000..a50929e8a46b192c9c5d4848c6f31c509c696899 --- /dev/null +++ b/jdk/test/javax/imageio/plugins/tiff/TIFFFieldTest.java @@ -0,0 +1,502 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 8152183 + * @author a.stepanov + * @summary Some checks for TIFFField methods + * @run main TIFFFieldTest + */ + +import java.util.List; +import java.util.ArrayList; +import javax.imageio.metadata.IIOMetadataNode; +import javax.imageio.plugins.tiff.*; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; + +public class TIFFFieldTest { + + private final static String NAME = "tag"; // tag name + private final static int NUM = 12345; // tag number + private final static int MIN_TYPE = TIFFTag.MIN_DATATYPE; + private final static int MAX_TYPE = TIFFTag.MAX_DATATYPE; + private final static String CONSTRUCT = "can construct TIFFField with "; + + private void check(boolean ok, String msg) { + if (!ok) { throw new RuntimeException(msg); } + } + + private void testConstructors() { + + // test constructors + + TIFFTag tag = new TIFFTag( + NAME, NUM, 1 << TIFFTag.TIFF_SHORT | 1 << TIFFTag.TIFF_LONG); + TIFFField f; + + // constructor: TIFFField(tag, value) + boolean ok = false; + try { new TIFFField(null, 0); } + catch (NullPointerException e) { ok = true; } + check(ok, CONSTRUCT + "null tag"); + + ok = false; + try { new TIFFField(tag, -1); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, CONSTRUCT + "invalid count"); + + // check value type recognition + int v = 1 << 16; + f = new TIFFField(tag, v - 1); + check(f.getType() == TIFFTag.TIFF_SHORT, "must be treated as short"); + check(f.isIntegral(), "must be integral"); + f = new TIFFField(tag, v); + check(f.getType() == TIFFTag.TIFF_LONG, "must be treated as long"); + + // other checks + check(f.getAsLongs().length == 1, "invalid long[] size"); + check(f.isIntegral(), "must be integral"); + check((f.getDirectory() == null) && !f.hasDirectory(), + "must not have directory"); + check(f.getValueAsString(0).equals(String.valueOf(v)), + "invalid string representation of value"); + check(f.getTag().getNumber() == f.getTagNumber(), + "invalid tag number"); + check(f.getCount() == 1, "invalid count"); + check(f.getTagNumber() == NUM, "invalid tag number"); + + // constructor: TIFFField(tag, type, count) + int type = TIFFTag.TIFF_SHORT; + + ok = false; + try { new TIFFField(null, type, 1); } + catch (NullPointerException e) { ok = true; } + check(ok, CONSTRUCT + "null tag"); + + ok = false; + try { new TIFFField(tag, MAX_TYPE + 1, 1); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, CONSTRUCT + "invalid type tag"); + + // check that count == 1 for TIFF_IFD_POINTER + ok = false; + try { new TIFFField(tag, TIFFTag.TIFF_IFD_POINTER, 0); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, "only count = 1 should be allowed for IFDPointer"); + + ok = false; + try { new TIFFField(tag, TIFFTag.TIFF_IFD_POINTER, 2); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, "only count = 1 should be allowed for IFDPointer"); + + // check that count == 0 is not allowed for TIFF_RATIONAL, TIFF_SRATIONAL + // (see fix for JDK-8149120) + ok = false; + try { new TIFFField(tag, TIFFTag.TIFF_RATIONAL, 0); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, "count = 0 should not be allowed for Rational"); + + ok = false; + try { new TIFFField(tag, TIFFTag.TIFF_SRATIONAL, 0); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, "count = 0 should not be allowed for SRational"); + + ok = false; + try { new TIFFField(tag, type, -1); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, CONSTRUCT + "with invalid data count"); + + f = new TIFFField(tag, type, 0); + check(f.getCount() == 0, "invalid count"); + check(!f.hasDirectory(), "must not have directory"); + + // constructor: TIFFField(tag, type, count, data) + double a[] = {0.1, 0.2, 0.3}; + ok = false; + try { new TIFFField(null, TIFFTag.TIFF_DOUBLE, a.length, a); } + catch (NullPointerException e) { ok = true; } + check(ok, CONSTRUCT + "null tag"); + + ok = false; + try { new TIFFField(tag, type, a.length - 1, a); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, CONSTRUCT + "invalid data count"); + + String a2[] = {"one", "two"}; + ok = false; + try { new TIFFField(tag, type, 2, a2); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, CONSTRUCT + "invalid data type"); + check((f.getDirectory() == null) && !f.hasDirectory(), + "must not have directory"); + + // constructor: TIFFField(tag, type, offset, dir) + List tags = new ArrayList<>(); + tags.add(tag); + TIFFTagSet sets[] = {new TIFFTagSet(tags)}; + TIFFDirectory dir = new TIFFDirectory(sets, null); + + ok = false; + try { new TIFFField(null, type, 4L, dir); } + catch (NullPointerException e) { ok = true; } + check(ok, CONSTRUCT + "null tag"); + + ok = false; + try { new TIFFField(tag, type, 0L, dir); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, CONSTRUCT + "non-positive offset"); + + long offset = 4; + + for (int t = MIN_TYPE; t <= MAX_TYPE; t++) { + + tag = new TIFFTag(NAME, NUM, 1 << t); + + // only TIFF_LONG and TIFF_IFD_POINTER types are allowed + if (t == TIFFTag.TIFF_LONG || t == TIFFTag.TIFF_IFD_POINTER) { + + f = new TIFFField(tag, t, offset, dir); + check(f.hasDirectory(), "must have directory"); + + check(f.getDirectory().getTag(NUM).getName().equals(NAME), + "invalid tag name"); + + check(f.getCount() == 1, "invalid count"); + check(f.getAsLong(0) == offset, "invalid offset"); + } else { + ok = false; + try { new TIFFField(tag, t, offset, dir); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, CONSTRUCT + "invalid data type"); + } + } + + type = TIFFTag.TIFF_IFD_POINTER; + tag = new TIFFTag(NAME, NUM, 1 << type); + ok = false; + try { new TIFFField(tag, type, offset, null); } + catch (NullPointerException e) { ok = true; } + check(ok, CONSTRUCT + "null TIFFDirectory"); + + type = TIFFTag.TIFF_LONG; + tag = new TIFFTag(NAME, NUM, 1 << type); + ok = false; + try { new TIFFField(tag, type, offset, null); } + catch (NullPointerException e) { ok = true; } + check(ok, CONSTRUCT + "null TIFFDirectory"); + } + + private void testTypes() { + + // test getTypeName(), getTypeByName() methods + + boolean ok = false; + try { TIFFField.getTypeName(MIN_TYPE - 1); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, "invalid data type number used"); + + ok = false; + try { TIFFField.getTypeName(MAX_TYPE + 1); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, "invalid data type number used"); + + for (int type = MIN_TYPE; type <= MAX_TYPE; type++) { + String name = TIFFField.getTypeName(type); + check(TIFFField.getTypeByName(name) == type, "invalid type"); + } + + for (int type = MIN_TYPE; type <= MAX_TYPE; type++) { + + TIFFTag tag = new TIFFTag(NAME, NUM, 1 << type); + TIFFField f = new TIFFField(tag, type, 1); + check(f.getType() == type, "invalid type"); + + // check that invalid data types can not be used + for (int type2 = MIN_TYPE; type2 <= MAX_TYPE; ++type2) { + if (type2 != type) { + ok = false; + try { new TIFFField(tag, type2, 1); } // invalid type + catch (IllegalArgumentException e) { ok = true; } + check(ok, "invalid type was successfully set"); + } + } + } + } + + private void testGetAs() { + + // test getAs...() methods + + int type = TIFFTag.TIFF_SHORT; + TIFFTag tag = new TIFFTag(NAME, NUM, 1 << TIFFTag.TIFF_SHORT); + + short v = 123; + TIFFField f = new TIFFField(tag, v); + + check(f.getAsInt(0) == (int) v, "invalid int value"); + check(f.getAsLong(0) == (long) v, "invalid long value"); + check(f.getAsFloat(0) == (float) v, "invalid float value"); + check(f.getAsDouble(0) == (double) v, "invalid double value"); + check(f.getValueAsString(0).equals(Short.toString(v)), + "invalid string representation"); + + check(f.getAsInts().length == 1, "inavlid array size"); + check((int) v == f.getAsInts()[0], "invalid int value"); + + float fa[] = {0.01f, 1.01f}; + type = TIFFTag.TIFF_FLOAT; + f = new TIFFField( + new TIFFTag(NAME, NUM, 1 << type), type, fa.length, fa); + check(f.getCount() == fa.length, "invalid count"); + float fa2[] = f.getAsFloats(); + check(fa2.length == fa.length, "invalid array size"); + + for (int i = 0; i < fa.length; i++) { + check(fa2[i] == fa[i], "invalid value"); + check(f.getAsDouble(i) == fa[i], "invalid value"); + check(f.getAsInt(i) == (int) fa[i], "invalid value"); // cast to int + check(f.getValueAsString(i).equals(Float.toString(fa[i])), + "invalid string representation"); + } + + byte ba[] = {-1, -10, -100}; + type = TIFFTag.TIFF_BYTE; + f = new TIFFField( + new TIFFTag(NAME, NUM, 1 << type), type, ba.length, ba); + check(f.getCount() == ba.length, "invalid count"); + byte ba2[] = f.getAsBytes(); + check(ba2.length == ba.length, "invalid count"); + + for (int i = 0; i < ba.length; i++) { + check(ba[i] == ba2[i], "invalid value"); + check(ba[i] == (byte) f.getAsDouble(i), "invalid value"); + check(ba[i] == (byte) f.getAsLong(i), "invalid value"); + + int unsigned = ba[i] & 0xff; + check(f.getAsInt(i) == unsigned, "must be treated as unsigned"); + } + + char ca[] = {'a', 'z', 0xffff}; + type = TIFFTag.TIFF_SHORT; + f = new TIFFField( + new TIFFTag(NAME, NUM, 1 << type), type, ca.length, ca); + check(f.getCount() == ca.length, "invalid count"); + char ca2[] = f.getAsChars(); + check(ba2.length == ba.length, "invalid count"); + + for (int i = 0; i < ca.length; i++) { + check(ca[i] == ca2[i], "invalid value"); + check(ca[i] == (char) f.getAsDouble(i), "invalid value"); + check(ca[i] == (char) f.getAsLong(i), "invalid value"); + check(ca[i] == (char) f.getAsInt(i), "invalid value"); + } + + type = TIFFTag.TIFF_DOUBLE; + double da[] = {0.1, 0.2, 0.3}; + f = new TIFFField( + new TIFFTag(NAME, NUM, 1 << type), type, da.length, da); + check(!f.isIntegral(), "isIntegral must be false"); + + double da2[] = f.getAsDoubles(); + check(f.getData() instanceof double[], "invalid data type"); + double da3[] = (double[]) f.getData(); + check((da.length == da2.length) && + (da.length == da2.length) && + (da.length == f.getCount()), + "invalid data count"); + for (int i = 0; i < da.length; ++i) { + check(da[i] == da2[i], "invalid data"); + check(da[i] == da3[i], "invalid data"); + } + + boolean ok = false; + try { f.getAsShorts(); } + catch (ClassCastException e) { ok = true; } + check(ok, "invalid data cast"); + + ok = false; + try { f.getAsRationals(); } + catch (ClassCastException e) { ok = true; } + check(ok, "invalid data cast"); + + ok = false; + try { TIFFField.createArrayForType(TIFFTag.MIN_DATATYPE - 1, 1); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, "can create array with invalid datatype"); + + ok = false; + try { TIFFField.createArrayForType(TIFFTag.MAX_DATATYPE + 1, 1); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, "can create array with invalid datatype"); + + ok = false; + try { TIFFField.createArrayForType(TIFFTag.TIFF_FLOAT, -1); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, "can create array with negative count"); + + int n = 3; + Object + RA = TIFFField.createArrayForType(TIFFTag.TIFF_RATIONAL, n), + SRA = TIFFField.createArrayForType(TIFFTag.TIFF_SRATIONAL, n); + check(RA instanceof long[][], "invalid data type"); + check(SRA instanceof int[][], "invalid data type"); + + long ra[][] = (long[][]) RA; + int sra[][] = (int[][]) SRA; + check((ra.length == n) && (sra.length == n), "invalid data size"); + for (int i = 0; i < n; i++) { + check((ra[i].length == 2) && (sra[i].length == 2), + "invalid data size"); + ra[i][0] = 1; ra[i][1] = 5 + i; + sra[i][0] = -1; sra[i][1] = 5 + i; + } + + type = TIFFTag.TIFF_RATIONAL; + TIFFField f1 = new TIFFField( + new TIFFTag(NAME, NUM, 1 << type), type, n, ra); + type = TIFFTag.TIFF_SRATIONAL; + TIFFField f2 = new TIFFField( + new TIFFTag(NAME, NUM, 1 << type), type, n, sra); + + check((f1.getCount() == ra.length) && (f2.getCount() == sra.length), + "invalid data count"); + + check(f1.getAsRationals().length == n, "invalid data count"); + check(f2.getAsSRationals().length == n, "invalid data count"); + for (int i = 0; i < n; i++) { + long r[] = f1.getAsRational(i); + check(r.length == 2, "invalid data format"); + check((r[0] == 1) && (r[1] == i + 5), "invalid data"); + + int sr[] = f2.getAsSRational(i); + check(sr.length == 2, "invalid data format"); + check((sr[0] == -1) && (sr[1] == i + 5), "invalid data"); + + // check string representation + String s = Long.toString(r[0]) + "/" + Long.toString(r[1]); + check(s.equals(f1.getValueAsString(i)), + "invalid string representation"); + + s = Integer.toString(sr[0]) + "/" + Integer.toString(sr[1]); + check(s.equals(f2.getValueAsString(i)), + "invalid string representation"); + + // see the documentation for getAsInt: + // TIFF_SRATIONAL or TIFF_RATIONAL format are evaluated + // by dividing the numerator into the denominator using + // double-precision arithmetic and then casting to int + check(f1.getAsInt(i) == (int)(r[0] / r[1]), + "invalid result for getAsInt"); + check(f2.getAsInt(i) == (int)(r[0] / r[1]), + "invalid result for getAsInt"); + } + + ok = false; + try { f1.getAsRational(ra.length); } + catch (ArrayIndexOutOfBoundsException e) { ok = true; } + check(ok, "invalid index"); + + String sa[] = {"-1.e-25", "22", "-1.23E5"}; + type = TIFFTag.TIFF_ASCII; + f = new TIFFField( + new TIFFTag(NAME, NUM, 1 << type), type, sa.length, sa); + + // test clone() method + TIFFField cloned = null; + try { cloned = f.clone(); } catch (CloneNotSupportedException e) { + throw new RuntimeException(e); + } + + check(f.getCount() == cloned.getCount(), "invalid cloned field count"); + + check(f.getCount() == sa.length, "invalid data count"); + for (int i = 0; i < sa.length; i++) { + check(sa[i].equals(f.getAsString(i)), "invalid data"); + // see docs: "data in TIFF_ASCII format will be parsed as by + // the Double.parseDouble method, with the result cast to int" + check(f.getAsInt(i) == + (int) Double.parseDouble(sa[i]), "invalid data"); + check(f.getAsDouble(i) == Double.parseDouble(sa[i]), "invalid data"); + + check(sa[i].equals(cloned.getAsString(i)), "invalid cloned data"); + } + } + + private void testCreateFromNode() { + + int type = TIFFTag.TIFF_LONG; + + List tags = new ArrayList<>(); + int v = 1234567; + TIFFTag tag = new TIFFTag(NAME, NUM, 1 << type); + tags.add(tag); + TIFFTagSet ts = new TIFFTagSet(tags); + + boolean ok = false; + try { TIFFField.createFromMetadataNode(ts, null); } + catch (NullPointerException e) { ok = true; } + check(ok, "can create TIFFField from a null node"); + + TIFFField f = new TIFFField(tag, v); + Node node = f.getAsNativeNode(); + check(node.getNodeName().equals(f.getClass().getSimpleName()), + "invalid node name"); + + NamedNodeMap attrs = node.getAttributes(); + for (int i = 0; i < attrs.getLength(); i++) { + String an = attrs.item(i).getNodeName().toLowerCase(); + String av = attrs.item(i).getNodeValue(); + if (an.contains("name")) { + check(av.equals(NAME), "invalid tag name"); + } else if (an.contains("number")) { + check(av.equals(Integer.toString(NUM)), "invalid tag number"); + } + } + + // invalid node + IIOMetadataNode nok = new IIOMetadataNode("NOK"); + + ok = false; + try { TIFFField.createFromMetadataNode(ts, nok); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, CONSTRUCT + "invalid node name"); + + TIFFField f2 = TIFFField.createFromMetadataNode(ts, node); + check(f2.getType() == type, "invalid type"); + check(f2.getTagNumber() == NUM, "invalid tag number"); + check(f2.getTag().getName().equals(NAME), "invalid tag name"); + check(f2.getCount() == 1, "invalid count"); + check(f2.getAsInt(0) == v, "invalid value"); + } + + public static void main(String[] args) { + + TIFFFieldTest test = new TIFFFieldTest(); + test.testConstructors(); + test.testCreateFromNode(); + test.testTypes(); + test.testGetAs(); + } +} diff --git a/jdk/test/javax/imageio/plugins/tiff/TIFFImageReadParamTest.java b/jdk/test/javax/imageio/plugins/tiff/TIFFImageReadParamTest.java new file mode 100644 index 0000000000000000000000000000000000000000..34fd5ed8983e81f4c7a91678c24de967514c8d34 --- /dev/null +++ b/jdk/test/javax/imageio/plugins/tiff/TIFFImageReadParamTest.java @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 8149028 + * @author a.stepanov + * @summary check TIFFDirectory manipulation + * by means of TIFFImageReadParam + * @run main TIFFImageReadParamTest + */ + + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.image.BufferedImage; +import java.io.*; +import javax.imageio.*; +import javax.imageio.metadata.IIOMetadata; +import javax.imageio.plugins.tiff.*; +import javax.imageio.stream.ImageInputStream; +import javax.imageio.stream.ImageOutputStream; + +public class TIFFImageReadParamTest { + + private final static String FILENAME = "test.tiff"; + private final static int SZ = 100; + private final static Color C = Color.RED; + + private final static String GEO_DATA = "test params"; + private final static int GEO_N = GeoTIFFTagSet.TAG_GEO_ASCII_PARAMS; + + private final static String EXIF_DATA = "2000:01:01 00:00:01"; + private final static int EXIF_N = ExifTIFFTagSet.TAG_DATE_TIME_ORIGINAL; + + private final static String GPS_DATA = + ExifGPSTagSet.STATUS_MEASUREMENT_IN_PROGRESS; + private final static int GPS_N = ExifGPSTagSet.TAG_GPS_STATUS; + + private final static short FAX_DATA = + FaxTIFFTagSet.CLEAN_FAX_DATA_ERRORS_UNCORRECTED; + private final static int FAX_N = FaxTIFFTagSet.TAG_CLEAN_FAX_DATA; + + private ImageWriter getTIFFWriter() { + + java.util.Iterator writers = + ImageIO.getImageWritersByFormatName("TIFF"); + if (!writers.hasNext()) { + throw new RuntimeException("No writers available for TIFF format"); + } + return writers.next(); + } + + private ImageReader getTIFFReader() { + + java.util.Iterator readers = + ImageIO.getImageReadersByFormatName("TIFF"); + if (!readers.hasNext()) { + throw new RuntimeException("No readers available for TIFF format"); + } + return readers.next(); + } + + private void check(boolean ok, String msg) { + if (!ok) { throw new RuntimeException(msg); } + } + + private void addASCIIField(TIFFDirectory d, + String name, + String data, + int num) { + + String a[] = {data}; + d.addTIFFField(new TIFFField( + new TIFFTag(name, num, 1 << TIFFTag.TIFF_ASCII), + TIFFTag.TIFF_ASCII, 1, a)); + } + + private void checkASCIIValue(TIFFDirectory d, + String what, + String data, + int num) { + + TIFFField f = d.getTIFFField(num); + check(f.getType() == TIFFTag.TIFF_ASCII, "field type != ASCII"); + check(f.getCount() == 1, "invalid " + what + " data count"); + check(f.getValueAsString(0).equals(data), + "invalid " + what + " data"); + } + + + private void writeImage() throws Exception { + + OutputStream s = new BufferedOutputStream(new FileOutputStream(FILENAME)); + try (ImageOutputStream ios = ImageIO.createImageOutputStream(s)) { + ImageWriter writer = getTIFFWriter(); + writer.setOutput(ios); + + BufferedImage img = + new BufferedImage(SZ, SZ, BufferedImage.TYPE_INT_RGB); + Graphics g = img.getGraphics(); + g.setColor(C); + g.fillRect(0, 0, SZ, SZ); + g.dispose(); + + IIOMetadata metadata = writer.getDefaultImageMetadata( + new ImageTypeSpecifier(img), writer.getDefaultWriteParam()); + + TIFFDirectory dir = TIFFDirectory.createFromMetadata(metadata); + + // add some extension tags + addASCIIField(dir, "GeoAsciiParamsTag", GEO_DATA, GEO_N); + addASCIIField(dir, "DateTimeOriginal", EXIF_DATA, EXIF_N); + addASCIIField(dir, "GPSStatus", GPS_DATA, GPS_N); + + dir.addTIFFField(new TIFFField(new TIFFTag( + "CleanFaxData", FAX_N, 1 << TIFFTag.TIFF_SHORT), FAX_DATA)); + + IIOMetadata data = dir.getAsMetadata(); + + writer.write(new IIOImage(img, null, data)); + + ios.flush(); + writer.dispose(); + } + } + + private void checkImage(BufferedImage img) { + + check(img.getWidth() == SZ, "invalid image width"); + check(img.getHeight() == SZ, "invalid image height"); + Color c = new Color(img.getRGB(SZ / 2, SZ / 2)); + check(c.equals(C), "invalid image color"); + } + + private TIFFDirectory getDir(TIFFTagSet[] add, + TIFFTagSet[] remove) throws Exception { + + ImageReader reader = getTIFFReader(); + + ImageInputStream s = ImageIO.createImageInputStream(new File(FILENAME)); + reader.setInput(s, false, true); + + int ni = reader.getNumImages(true); + check(ni == 1, "invalid number of images: " + ni); + + TIFFImageReadParam param = new TIFFImageReadParam(); + for (TIFFTagSet ts: add) { param.addAllowedTagSet(ts); } + for (TIFFTagSet ts: remove) { param.removeAllowedTagSet(ts); } + + IIOImage img = reader.readAll(0, param); + + // just in case, check image + checkImage((BufferedImage) img.getRenderedImage()); + + IIOMetadata metadata = img.getMetadata(); + TIFFDirectory dir = TIFFDirectory.createFromMetadata(metadata); + + reader.dispose(); + s.close(); + + return dir; + } + + private void simpleChecks() { + + TIFFImageReadParam param = new TIFFImageReadParam(); + + java.util.List allowed = param.getAllowedTagSets(); + + // see docs + check(allowed.contains(BaselineTIFFTagSet.getInstance()), + "must contain BaselineTIFFTagSet"); + check(allowed.contains(FaxTIFFTagSet.getInstance()), + "must contain FaxTIFFTagSet"); + check(allowed.contains(ExifParentTIFFTagSet.getInstance()), + "must contain ExifParentTIFFTagSet"); + check(allowed.contains(GeoTIFFTagSet.getInstance()), + "must contain GeoTIFFTagSet"); + + TIFFTagSet gps = ExifGPSTagSet.getInstance(); + param.addAllowedTagSet(gps); + check(param.getAllowedTagSets().contains(gps), + "must contain ExifGPSTagSet"); + + param.removeAllowedTagSet(gps); + check(!param.getAllowedTagSets().contains(gps), + "must not contain ExifGPSTagSet"); + + // check that repeating remove goes properly + param.removeAllowedTagSet(gps); + + boolean ok = false; + try { param.addAllowedTagSet(null); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, "must not be able to add null tag set"); + + ok = false; + try { param.removeAllowedTagSet(null); } + catch (IllegalArgumentException e) { ok = true; } + check(ok, "must not be able to remove null tag set"); + } + + private void run() { + + simpleChecks(); + + try { + + writeImage(); + + TIFFTagSet + empty[] = {}, + geo[] = { GeoTIFFTagSet.getInstance() }, + exif[] = { ExifTIFFTagSet.getInstance() }, + gps[] = { ExifGPSTagSet.getInstance() }, + fax[] = { FaxTIFFTagSet.getInstance() }; + + // default param state + TIFFDirectory dir = getDir(empty, empty); + // Geo and Fax are default allowed tag sets + check(dir.containsTIFFField(GEO_N), "must contain Geo field"); + checkASCIIValue(dir, "Geo", GEO_DATA, GEO_N); + check(dir.containsTIFFField(FAX_N), "must contain Fax field"); + check( + (dir.getTIFFField(FAX_N).getCount() == 1) && + (dir.getTIFFField(FAX_N).getAsInt(0) == FAX_DATA), + "invalid Fax field value"); + + // corresponding tag sets are non-default + check(!dir.containsTIFFField(EXIF_N), "must not contain Geo field"); + check(!dir.containsTIFFField(GPS_N), "must not contain GPS field"); + + // remove Fax + dir = getDir(empty, fax); + check(!dir.containsTIFFField(FAX_N), "must not contain Fax field"); + + // add EXIF, remove Geo + dir = getDir(exif, geo); + check(dir.containsTIFFField(EXIF_N), "must contain EXIF field"); + checkASCIIValue(dir, "EXIF", EXIF_DATA, EXIF_N); + check(!dir.containsTIFFField(GEO_N), "must not contain Geo field"); + + // add GPS + dir = getDir(gps, empty); + check(dir.containsTIFFField(GPS_N), "must contain GPS field"); + checkASCIIValue(dir, "GPS", GPS_DATA, GPS_N); + + } catch (Exception e) { throw new RuntimeException(e); } + } + + public static void main(String[] args) { + (new TIFFImageReadParamTest()).run(); + } +} diff --git a/jdk/test/javax/imageio/stream/NullStreamCheckTest.java b/jdk/test/javax/imageio/stream/NullStreamCheckTest.java new file mode 100644 index 0000000000000000000000000000000000000000..f763b9de1e6ff4651e6a238a33a6c5c95fa970ce --- /dev/null +++ b/jdk/test/javax/imageio/stream/NullStreamCheckTest.java @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 8044289 + * @summary Test verifies that when some of the read() and write() methods + * are not able to get stream from createImageInputStream() and + * createImageOutputStream() are we doing null check for stream + * and throwing IOException as per specification. + * @run main NullStreamCheckTest + */ + +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.MalformedURLException; +import java.net.URL; +import javax.imageio.ImageIO; +import javax.imageio.spi.IIORegistry; +import javax.imageio.spi.ImageInputStreamSpi; +import javax.imageio.spi.ImageOutputStreamSpi; + +public class NullStreamCheckTest { + + // get ImageIORegistry default instance. + private static final IIORegistry localRegistry = IIORegistry. + getDefaultInstance(); + // stream variables needed for input and output. + static LocalOutputStream outputStream = new LocalOutputStream(); + static LocalInputStream inputStream = new LocalInputStream(); + + static final int width = 50, height = 50; + + // input and output BufferedImage needed while read and write. + static BufferedImage inputImage = new BufferedImage(width, height, + BufferedImage.TYPE_INT_ARGB); + + // creates test file needed for read and write in local directory. + private static File createTestFile(String name) throws IOException { + String sep = System.getProperty("file.separator"); + String dir = System.getProperty("test.src", "."); + String filePath = dir+sep; + File directory = new File(filePath); + File tmpTestFile = File.createTempFile(name, ".png", directory); + directory.delete(); + return tmpTestFile; + } + + /* if we catch expected IOException message return + * false otherwise return true. + */ + private static boolean verifyOutputExceptionMessage(IOException ex) { + String message = ex.getMessage(); + return (!message.equals("Can't create an ImageOutputStream!")); + } + + /* if we catch expected IOException message return + * false otherwise return true. + */ + private static boolean verifyInputExceptionMessage(IOException ex) { + String message = ex.getMessage(); + return (!message.equals("Can't create an ImageInputStream!")); + } + + private static void verifyFileWrite() throws IOException { + File outputTestFile = createTestFile("outputTestFile"); + try { + ImageIO.write(inputImage, "png", outputTestFile); + } catch (IOException ex) { + if (verifyOutputExceptionMessage(ex)) + throw ex; + } finally { + outputTestFile.delete(); + } + } + + private static void verifyStreamWrite() throws IOException { + try { + ImageIO.write(inputImage, "png", outputStream); + } catch (IOException ex) { + if (verifyOutputExceptionMessage(ex)) + throw ex; + } finally { + try { + outputStream.close(); + } catch (IOException ex) { + throw ex; + } + } + } + + private static void verifyFileRead() throws IOException { + File inputTestFile = createTestFile("inputTestFile"); + try { + ImageIO.read(inputTestFile); + } catch (IOException ex) { + if (verifyInputExceptionMessage(ex)) + throw ex; + } finally { + inputTestFile.delete(); + } + } + + private static void verifyStreamRead() throws IOException { + try { + ImageIO.read(inputStream); + } catch (IOException ex) { + if (verifyInputExceptionMessage(ex)) + throw ex; + } finally { + try { + inputStream.close(); + } catch (IOException ex) { + throw ex; + } + } + } + + private static void verifyUrlRead() throws IOException { + URL url; + File inputTestUrlFile = createTestFile("inputTestFile"); + try { + try { + url = inputTestUrlFile.toURI().toURL(); + } catch (MalformedURLException ex) { + throw ex; + } + + try { + ImageIO.read(url); + } catch (IOException ex) { + if (verifyInputExceptionMessage(ex)) + throw ex; + } + } finally { + inputTestUrlFile.delete(); + } + } + + public static void main(String[] args) throws IOException, + MalformedURLException { + + /* deregister ImageOutputStreamSpi so that we creatImageOutputStream + * returns null while writing. + */ + localRegistry.deregisterAll(ImageOutputStreamSpi.class); + /* verify possible ImageIO.write() scenario's for null stream output + * from createImageOutputStream() API in ImageIO class. + */ + verifyFileWrite(); + verifyStreamWrite(); + + /* deregister ImageInputStreamSpi so that we creatImageInputStream + * returns null while reading. + */ + localRegistry.deregisterAll(ImageInputStreamSpi.class); + /* verify possible ImageIO.read() scenario's for null stream output + * from createImageInputStream API in ImageIO class. + */ + verifyFileRead(); + verifyStreamRead(); + verifyUrlRead(); + } + + static class LocalOutputStream extends OutputStream { + + @Override + public void write(int i) throws IOException { + } + } + + static class LocalInputStream extends InputStream { + + @Override + public int read() throws IOException { + return 0; + } + } +} diff --git a/jdk/test/javax/net/ssl/ServerName/BestEffortOnLazyConnected.java b/jdk/test/javax/net/ssl/ServerName/BestEffortOnLazyConnected.java new file mode 100644 index 0000000000000000000000000000000000000000..ba3e5f10e50adcab0ae22293a0417a9ed215a306 --- /dev/null +++ b/jdk/test/javax/net/ssl/ServerName/BestEffortOnLazyConnected.java @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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. + */ + +// +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. +// + +/** + * @test + * @bug 8144566 + * @summary Custom HostnameVerifier disables SNI extension + * @run main/othervm BestEffortOnLazyConnected + */ + +import java.io.*; +import java.nio.*; +import java.nio.channels.*; +import java.util.*; +import java.net.*; +import javax.net.ssl.*; + +public class BestEffortOnLazyConnected { + + /* + * ============================================================= + * Set the various variables needed for the tests, then + * specify what tests to run on each side. + */ + + /* + * Should we run the client or server in a separate thread? + * Both sides can throw exceptions, but do you have a preference + * as to which side should be the main thread. + */ + private static final boolean separateServerThread = true; + + /* + * Where do we find the keystores? + */ + private static final String pathToStores = "../etc"; + private static final String keyStoreFile = "keystore"; + private static final String trustStoreFile = "truststore"; + private static final String passwd = "passphrase"; + + /* + * Is the server ready to serve? + */ + private static volatile boolean serverReady = false; + + /* + * Turn on SSL debugging? + */ + private static final boolean debug = false; + + /* + * the fully qualified domain name of localhost + */ + private static String hostname = null; + + /* + * If the client or server is doing some kind of object creation + * that the other side depends on, and that thread prematurely + * exits, you may experience a hang. The test harness will + * terminate all hung threads after its timeout has expired, + * currently 3 minutes by default, but you might try to be + * smart about it.... + */ + + /* + * Define the server side of the test. + * + * If the server prematurely exits, serverReady will be set to true + * to avoid infinite hangs. + */ + private void doServerSide() throws Exception { + SSLServerSocketFactory sslssf = + (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); + try (SSLServerSocket sslServerSocket = + (SSLServerSocket) sslssf.createServerSocket(serverPort)) { + + serverPort = sslServerSocket.getLocalPort(); + + /* + * Signal Client, we're ready for his connect. + */ + serverReady = true; + + try (SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept()) { + InputStream sslIS = sslSocket.getInputStream(); + OutputStream sslOS = sslSocket.getOutputStream(); + + sslIS.read(); + sslOS.write(85); + sslOS.flush(); + + ExtendedSSLSession session = + (ExtendedSSLSession)sslSocket.getSession(); + if (session.getRequestedServerNames().isEmpty()) { + throw new Exception("No expected Server Name Indication"); + } + } + } + } + + /* + * Define the client side of the test. + * + * If the server prematurely exits, serverReady will be set to true + * to avoid infinite hangs. + */ + private void doClientSide() throws Exception { + + /* + * Wait for server to get started. + */ + while (!serverReady) { + Thread.sleep(50); + } + + SSLSocketFactory sslsf = + (SSLSocketFactory) SSLSocketFactory.getDefault(); + + try (SSLSocket sslSocket = (SSLSocket)sslsf.createSocket()) { + + sslSocket.connect(new InetSocketAddress(hostname, serverPort), 0); + + InputStream sslIS = sslSocket.getInputStream(); + OutputStream sslOS = sslSocket.getOutputStream(); + + sslOS.write(280); + sslOS.flush(); + sslIS.read(); + } + } + + + /* + * ============================================================= + * The remainder is just support stuff + */ + + // use any free port by default + private volatile int serverPort = 0; + + private volatile Exception serverException = null; + private volatile Exception clientException = null; + + public static void main(String[] args) throws Exception { + String keyFilename = + System.getProperty("test.src", ".") + "/" + pathToStores + + "/" + keyStoreFile; + String trustFilename = + System.getProperty("test.src", ".") + "/" + pathToStores + + "/" + trustStoreFile; + + System.setProperty("javax.net.ssl.keyStore", keyFilename); + System.setProperty("javax.net.ssl.keyStorePassword", passwd); + System.setProperty("javax.net.ssl.trustStore", trustFilename); + System.setProperty("javax.net.ssl.trustStorePassword", passwd); + + if (debug) { + System.setProperty("javax.net.debug", "all"); + } + + try { + hostname = InetAddress.getLocalHost().getCanonicalHostName(); + } catch (UnknownHostException uhe) { + System.out.println( + "Ignore the test as the local hostname cannot be determined"); + + return; + } + + System.out.println( + "The fully qualified domain name of the local host is " + + hostname); + // Ignore the test if the hostname does not sound like a domain name. + if ((hostname == null) || hostname.isEmpty() || + hostname.startsWith("localhost") || + Character.isDigit(hostname.charAt(hostname.length() - 1))) { + + System.out.println("Ignore the test as the local hostname " + + "cannot be determined as fully qualified domain name"); + + return; + } + + /* + * Start the tests. + */ + new BestEffortOnLazyConnected(); + } + + private Thread clientThread = null; + private Thread serverThread = null; + + /* + * Primary constructor, used to drive remainder of the test. + * + * Fork off the other side, then do your work. + */ + BestEffortOnLazyConnected() throws Exception { + try { + if (separateServerThread) { + startServer(true); + startClient(false); + } else { + startClient(true); + startServer(false); + } + } catch (Exception e) { + // swallow for now. Show later + } + + /* + * Wait for other side to close down. + */ + if (separateServerThread) { + serverThread.join(); + } else { + clientThread.join(); + } + + /* + * When we get here, the test is pretty much over. + * Which side threw the error? + */ + Exception local; + Exception remote; + String whichRemote; + + if (separateServerThread) { + remote = serverException; + local = clientException; + whichRemote = "server"; + } else { + remote = clientException; + local = serverException; + whichRemote = "client"; + } + + /* + * If both failed, return the curthread's exception, but also + * print the remote side Exception + */ + if ((local != null) && (remote != null)) { + System.out.println(whichRemote + " also threw:"); + remote.printStackTrace(); + System.out.println(); + throw local; + } + + if (remote != null) { + throw remote; + } + + if (local != null) { + throw local; + } + } + + private void startServer(boolean newThread) throws Exception { + if (newThread) { + serverThread = new Thread() { + public void run() { + try { + doServerSide(); + } catch (Exception e) { + /* + * Our server thread just died. + * + * Release the client, if not active already... + */ + System.err.println("Server died..."); + serverReady = true; + serverException = e; + } + } + }; + serverThread.start(); + } else { + try { + doServerSide(); + } catch (Exception e) { + serverException = e; + } finally { + serverReady = true; + } + } + } + + private void startClient(boolean newThread) throws Exception { + if (newThread) { + clientThread = new Thread() { + public void run() { + try { + doClientSide(); + } catch (Exception e) { + /* + * Our client thread just died. + */ + System.err.println("Client died..."); + clientException = e; + } + } + }; + clientThread.start(); + } else { + try { + doClientSide(); + } catch (Exception e) { + clientException = e; + } + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits16ToFromFloatArray.java b/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits16ToFromFloatArray.java new file mode 100644 index 0000000000000000000000000000000000000000..54e404dcf6fd955c5c3a44b31d2bd8b39ff4d7d5 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits16ToFromFloatArray.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.Arrays; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioFormat.Encoding; + +import com.sun.media.sound.AudioFloatConverter; + +import static javax.sound.sampled.AudioFormat.Encoding.*; + +/** + * @test + * @bug 8152501 + * @modules java.desktop/com.sun.media.sound + */ +public final class Bits16ToFromFloatArray { + + private static final int SIZE = 16; + + private static final float[] FLOATS = {-1.0f, 0, 1.0f}; + + private static short MID_U = (short) (Short.MAX_VALUE + 1); + private static short MAX_U = -1; + + // BIG ENDIAN + private static final byte[] SIGNED_BIG = { + (byte) (Short.MIN_VALUE >> 8), (byte) (Short.MIN_VALUE & 0xff), 0, + 0, (byte) (Short.MAX_VALUE >> 8), (byte) (Short.MAX_VALUE & 0xff) + }; + + private static final byte[] UNSIGNED_BIG = { + 0, 0, (byte) (MID_U >> 8), (byte) (MID_U & 0xff), + (byte) (MAX_U >> 8), (byte) (MAX_U >> 8) + }; + + // LITTLE ENDIAN + private static final byte[] SIGNED_LITTLE = { + (byte) (Short.MIN_VALUE & 0xff), (byte) (Short.MIN_VALUE >> 8), 0, + 0, (byte) (Short.MAX_VALUE & 0xff), (byte) (Short.MAX_VALUE >> 8) + }; + + private static final byte[] UNSIGNED_LITTLE = { + 0, 0, (byte) (MID_U & 0xff), (byte) (MID_U >> 8), + (byte) (MAX_U >> 8), (byte) (MAX_U >> 8) + }; + + public static void main(final String[] args) { + test(PCM_UNSIGNED, UNSIGNED_BIG, true); + test(PCM_UNSIGNED, UNSIGNED_LITTLE, false); + test(PCM_SIGNED, SIGNED_LITTLE, false); + test(PCM_SIGNED, SIGNED_BIG, true); + } + + private static void test(final Encoding enc, final byte[] expected, + boolean end) { + System.err.println("enc = " + enc); + AudioFormat af = new AudioFormat(enc, 44100, SIZE, 1, SIZE / 8, 44100, + end); + byte[] bytes = new byte[FLOATS.length * af.getFrameSize()]; + AudioFloatConverter conv = AudioFloatConverter.getConverter(af); + + conv.toByteArray(FLOATS, bytes); + + if (!Arrays.equals(bytes, expected)) { + System.err.println("Actual: " + Arrays.toString(bytes)); + System.err.println("Expected: " + Arrays.toString(expected)); + throw new RuntimeException(); + } + + float[] floats = new float[bytes.length / af.getFrameSize()]; + conv.toFloatArray(bytes, floats); + + if (!Arrays.equals(floats, FLOATS)) { + System.err.println("Actual: " + Arrays.toString(floats)); + System.err.println("Expected: " + Arrays.toString(FLOATS)); + throw new RuntimeException(); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits24ToFromFloatArray.java b/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits24ToFromFloatArray.java new file mode 100644 index 0000000000000000000000000000000000000000..1bd215435d2140e06c7e309c5ac825d1f1e35cd9 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits24ToFromFloatArray.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.Arrays; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioFormat.Encoding; + +import com.sun.media.sound.AudioFloatConverter; + +import static javax.sound.sampled.AudioFormat.Encoding.PCM_SIGNED; +import static javax.sound.sampled.AudioFormat.Encoding.PCM_UNSIGNED; + +/** + * @test + * @bug 8152501 + * @modules java.desktop/com.sun.media.sound + */ +public final class Bits24ToFromFloatArray { + + private static final int SIZE = 24; + + private static final float[] FLOATS = {-1.0f, 0, 1.0f}; + + private static int MIN_S = -8_388_608; + private static int MAX_S = 8_388_607; + + private static int MID_U = 0xFFFFFF / 2 + 1; + private static int MAX_U = 0xFFFFFF; + + // BIG ENDIAN + private static final byte[] SIGNED_BIG = { + (byte) ((MIN_S >> 16) & 0xff), + (byte) ((MIN_S >> 8) & 0xff), + (byte) ((MIN_S >> 0) & 0xff), + 0, 0, 0, + (byte) ((MAX_S >> 16) & 0xff), + (byte) ((MAX_S >> 8) & 0xff), + (byte) ((MAX_S >> 0) & 0xff), + }; + + private static final byte[] UNSIGNED_BIG = { + 0, 0, 0, + (byte) ((MID_U >> 16) & 0xff), + (byte) ((MID_U >> 8) & 0xff), + (byte) ((MID_U >> 0) & 0xff), + (byte) ((MAX_U >> 16) & 0xff), + (byte) ((MAX_U >> 8) & 0xff), + (byte) ((MAX_U >> 0) & 0xff), + + }; + + // LITTLE ENDIAN + private static final byte[] SIGNED_LITTLE = { + (byte) ((MIN_S >> 0) & 0xff), + (byte) ((MIN_S >> 8) & 0xff), + (byte) ((MIN_S >> 16) & 0xff), + 0, 0, 0, + (byte) ((MAX_S >> 0) & 0xff), + (byte) ((MAX_S >> 8) & 0xff), + (byte) ((MAX_S >> 16) & 0xff), + }; + + private static final byte[] UNSIGNED_LITTLE = { + 0, 0, 0, + (byte) ((MID_U >> 0) & 0xff), + (byte) ((MID_U >> 8) & 0xff), + (byte) ((MID_U >> 16) & 0xff), + (byte) ((MAX_U >> 0) & 0xff), + (byte) ((MAX_U >> 8) & 0xff), + (byte) ((MAX_U >> 16) & 0xff), + }; + + public static void main(final String[] args) { + test(PCM_UNSIGNED, UNSIGNED_BIG, true); + test(PCM_UNSIGNED, UNSIGNED_LITTLE, false); + test(PCM_SIGNED, SIGNED_LITTLE, false); + test(PCM_SIGNED, SIGNED_BIG, true); + } + + private static void test(final Encoding enc, final byte[] expected, + boolean end) { + System.err.println(enc); + AudioFormat af = new AudioFormat(enc, 44100, SIZE, 1, SIZE / 8, 44100, + end); + byte[] bytes = new byte[FLOATS.length * af.getFrameSize()]; + AudioFloatConverter conv = AudioFloatConverter.getConverter(af); + + conv.toByteArray(FLOATS, bytes); + + if (!Arrays.equals(bytes, expected)) { + System.err.println("Actual: " + Arrays.toString(bytes)); + System.err.println("Expected: " + Arrays.toString(expected)); + throw new RuntimeException(); + } + + float[] floats = new float[bytes.length / af.getFrameSize()]; + conv.toFloatArray(bytes, floats); + + if (!Arrays.equals(floats, FLOATS)) { + System.err.println("Actual: " + Arrays.toString(floats)); + System.err.println("Expected: " + Arrays.toString(FLOATS)); + throw new RuntimeException(); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits32ToFromFloatArray.java b/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits32ToFromFloatArray.java new file mode 100644 index 0000000000000000000000000000000000000000..7a550a54df3969295d705cc6ab85f31cbbc7743d --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits32ToFromFloatArray.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.Arrays; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioFormat.Encoding; + +import com.sun.media.sound.AudioFloatConverter; + +import static javax.sound.sampled.AudioFormat.Encoding.PCM_SIGNED; +import static javax.sound.sampled.AudioFormat.Encoding.PCM_UNSIGNED; + +/** + * @test + * @bug 8152501 + * @modules java.desktop/com.sun.media.sound + */ +public final class Bits32ToFromFloatArray { + + private static final int SIZE = 32; + + private static final float[] FLOATS = {-1.0f, 0, 1.0f}; + + private static int MID_U = (int) (Integer.MAX_VALUE + 1); + private static int MAX_U = -1; + + // BIG ENDIAN + private static final byte[] SIGNED_BIG = { + (byte) ((Integer.MIN_VALUE >> 24) & 0xff), + (byte) ((Integer.MIN_VALUE >> 16) & 0xff), + (byte) ((Integer.MIN_VALUE >> 8) & 0xff), + (byte) ((Integer.MIN_VALUE >> 0) & 0xff), + 0, 0, 0, 0, + (byte) ((Integer.MAX_VALUE >> 24) & 0xff), + (byte) ((Integer.MAX_VALUE >> 16) & 0xff), + (byte) ((Integer.MAX_VALUE >> 8) & 0xff), + (byte) ((Integer.MAX_VALUE >> 0) & 0xff), + }; + + private static final byte[] UNSIGNED_BIG = { + 0, 0, 0, 0, + (byte) ((MID_U >> 24) & 0xff), + (byte) ((MID_U >> 16) & 0xff), + (byte) ((MID_U >> 8) & 0xff), + (byte) ((MID_U >> 0) & 0xff), + (byte) ((MAX_U >> 24) & 0xff), + (byte) ((MAX_U >> 16) & 0xff), + (byte) ((MAX_U >> 8) & 0xff), + (byte) ((MAX_U >> 0) & 0xff), + + }; + + // LITTLE ENDIAN + private static final byte[] SIGNED_LITTLE = { + (byte) ((Integer.MIN_VALUE >> 0) & 0xff), + (byte) ((Integer.MIN_VALUE >> 8) & 0xff), + (byte) ((Integer.MIN_VALUE >> 16) & 0xff), + (byte) ((Integer.MIN_VALUE >> 24) & 0xff), + 0, 0, 0, 0, + (byte) ((Integer.MAX_VALUE >> 0) & 0xff), + (byte) ((Integer.MAX_VALUE >> 8) & 0xff), + (byte) ((Integer.MAX_VALUE >> 16) & 0xff), + (byte) ((Integer.MAX_VALUE >> 24) & 0xff), + }; + + private static final byte[] UNSIGNED_LITTLE = { + 0, 0, 0, 0, + (byte) ((MID_U >> 0) & 0xff), + (byte) ((MID_U >> 8) & 0xff), + (byte) ((MID_U >> 16) & 0xff), + (byte) ((MID_U >> 24) & 0xff), + (byte) ((MAX_U >> 0) & 0xff), + (byte) ((MAX_U >> 8) & 0xff), + (byte) ((MAX_U >> 16) & 0xff), + (byte) ((MAX_U >> 24) & 0xff), + }; + + public static void main(final String[] args) { + test(PCM_UNSIGNED, UNSIGNED_BIG, true); + test(PCM_UNSIGNED, UNSIGNED_LITTLE, false); + test(PCM_SIGNED, SIGNED_LITTLE, false); + test(PCM_SIGNED, SIGNED_BIG, true); + } + + private static void test(final Encoding enc, final byte[] expected, + boolean end) { + AudioFormat af = new AudioFormat(enc, 44100, SIZE, 1, SIZE / 8, 44100, + end); + byte[] bytes = new byte[FLOATS.length * af.getFrameSize()]; + AudioFloatConverter conv = AudioFloatConverter.getConverter(af); + + conv.toByteArray(FLOATS, bytes); + + if (!Arrays.equals(bytes, expected)) { + System.err.println("Actual: " + Arrays.toString(bytes)); + System.err.println("Expected: " + Arrays.toString(expected)); + throw new RuntimeException(); + } + + float[] floats = new float[bytes.length / af.getFrameSize()]; + conv.toFloatArray(bytes, floats); + + if (!Arrays.equals(floats, FLOATS)) { + System.err.println("Actual: " + Arrays.toString(floats)); + System.err.println("Expected: " + Arrays.toString(FLOATS)); + throw new RuntimeException(); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits64ToFromFloatArray.java b/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits64ToFromFloatArray.java new file mode 100644 index 0000000000000000000000000000000000000000..558835bcb525332287c877bdc0650ba7c4e66572 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits64ToFromFloatArray.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.Arrays; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioFormat.Encoding; + +import com.sun.media.sound.AudioFloatConverter; + +import static javax.sound.sampled.AudioFormat.Encoding.PCM_SIGNED; +import static javax.sound.sampled.AudioFormat.Encoding.PCM_UNSIGNED; + +/** + * @test + * @bug 8152501 + * @modules java.desktop/com.sun.media.sound + */ +public final class Bits64ToFromFloatArray { + + private static final int SIZE = 64; + + private static final float[] FLOATS = {-1.0f, 0, 1.0f}; + + private static long MID_U = (long) (Long.MAX_VALUE + 1); + private static long MAX_U = -1; + + // BIG ENDIAN + private static final byte[] SIGNED_BIG = { + (byte) ((Long.MIN_VALUE >> 56) & 0xff), + (byte) ((Long.MIN_VALUE >> 48) & 0xff), + (byte) ((Long.MIN_VALUE >> 40) & 0xff), + (byte) ((Long.MIN_VALUE >> 32) & 0xff), + 0, 0, 0, 0, // current javasound impl will ignore this + 0, 0, 0, 0, + 0, 0, 0, 0, + (byte) ((Long.MAX_VALUE >> 56) & 0xff), + (byte) ((Long.MAX_VALUE >> 48) & 0xff), + (byte) ((Long.MAX_VALUE >> 40) & 0xff), + (byte) ((Long.MAX_VALUE >> 32) & 0xff), + 0, 0, 0, 0, // current javasound impl will ignore this + }; + + private static final byte[] UNSIGNED_BIG = { + 0, 0, 0, 0, + 0, 0, 0, 0, + (byte) ((MID_U >> 56) & 0xff), + (byte) ((MID_U >> 48) & 0xff), + (byte) ((MID_U >> 40) & 0xff), + (byte) ((MID_U >> 32) & 0xff), + 0, 0, 0, 0, // current javasound impl will ignore this + (byte) ((MAX_U >> 56) & 0xff), + (byte) ((MAX_U >> 48) & 0xff), + (byte) ((MAX_U >> 40) & 0xff), + (byte) ((MAX_U >> 32) & 0xff), + 0, 0, 0, 0, // current javasound impl will ignore this + }; + + // LITTLE ENDIAN + private static final byte[] SIGNED_LITTLE = { + 0, 0, 0, 0, // current javasound impl will ignore this + (byte) ((Long.MIN_VALUE >> 32) & 0xff), + (byte) ((Long.MIN_VALUE >> 40) & 0xff), + (byte) ((Long.MIN_VALUE >> 48) & 0xff), + (byte) ((Long.MIN_VALUE >> 56) & 0xff), + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, // current javasound impl will ignore this + (byte) ((Long.MAX_VALUE >> 32) & 0xff), + (byte) ((Long.MAX_VALUE >> 40) & 0xff), + (byte) ((Long.MAX_VALUE >> 48) & 0xff), + (byte) ((Long.MAX_VALUE >> 56) & 0xff), + }; + + private static final byte[] UNSIGNED_LITTLE = { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, // current javasound impl will ignore this + (byte) ((MID_U >> 32) & 0xff), + (byte) ((MID_U >> 40) & 0xff), + (byte) ((MID_U >> 48) & 0xff), + (byte) ((MID_U >> 56) & 0xff), + 0, 0, 0, 0, // current javasound impl will ignore this + (byte) ((MAX_U >> 32) & 0xff), + (byte) ((MAX_U >> 40) & 0xff), + (byte) ((MAX_U >> 48) & 0xff), + (byte) ((MAX_U >> 56) & 0xff), + }; + + public static void main(final String[] args) { + test(PCM_UNSIGNED, UNSIGNED_BIG, true); + test(PCM_UNSIGNED, UNSIGNED_LITTLE, false); + test(PCM_SIGNED, SIGNED_LITTLE, false); + test(PCM_SIGNED, SIGNED_BIG, true); + } + + private static void test(final Encoding enc, final byte[] expected, + boolean end) { + System.err.println(enc); + AudioFormat af = new AudioFormat(enc, 44100, SIZE, 1, SIZE / 8, 44100, + end); + byte[] bytes = new byte[FLOATS.length * af.getFrameSize()]; + AudioFloatConverter conv = AudioFloatConverter.getConverter(af); + + conv.toByteArray(FLOATS, bytes); + + if (!Arrays.equals(bytes, expected)) { + System.err.println("Actual: " + Arrays.toString(bytes)); + System.err.println("Expected: " + Arrays.toString(expected)); + throw new RuntimeException(); + } + + float[] floats = new float[bytes.length / af.getFrameSize()]; + conv.toFloatArray(bytes, floats); + + if (!Arrays.equals(floats, FLOATS)) { + System.err.println("Actual: " + Arrays.toString(floats)); + System.err.println("Expected: " + Arrays.toString(FLOATS)); + throw new RuntimeException(); + } + } +} diff --git a/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits8ToFromFloatArray.java b/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits8ToFromFloatArray.java new file mode 100644 index 0000000000000000000000000000000000000000..1d4ab6067451619126f30ddec54ad159d2fd8aa2 --- /dev/null +++ b/jdk/test/javax/sound/midi/Gervill/AudioFloatConverter/Bits8ToFromFloatArray.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.Arrays; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioFormat.Encoding; + +import com.sun.media.sound.AudioFloatConverter; + +import static javax.sound.sampled.AudioFormat.Encoding.*; + +/** + * @test + * @bug 8152501 + * @modules java.desktop/com.sun.media.sound + */ +public final class Bits8ToFromFloatArray { + + private static final int SIZE = 8; + + private static final float[] FLOATS = {-1.0f, 0, 1.0f}; + + private static final byte[] SIGNED = {Byte.MIN_VALUE, 0, Byte.MAX_VALUE}; + + private static final byte[] UNSIGNED = { + 0, (byte) (Byte.MAX_VALUE + 1), (byte) -1 + }; + + public static void main(final String[] args) { + test(PCM_UNSIGNED, UNSIGNED); + test(PCM_SIGNED, SIGNED); + } + + private static void test(final Encoding enc, final byte[] expected) { + AudioFormat af = new AudioFormat(enc, 44100, SIZE, 1, SIZE / 8, 44100, + true); + byte[] bytes = new byte[FLOATS.length * af.getFrameSize()]; + AudioFloatConverter conv = AudioFloatConverter.getConverter(af); + + conv.toByteArray(FLOATS, bytes); + + if (!Arrays.equals(bytes, expected)) { + System.err.println("Actual: " + Arrays.toString(bytes)); + System.err.println("Expected: " + Arrays.toString(expected)); + throw new RuntimeException(); + } + + float[] floats = new float[bytes.length / af.getFrameSize()]; + conv.toFloatArray(bytes, floats); + + if (!Arrays.equals(floats, FLOATS)) { + System.err.println("Actual: " + Arrays.toString(floats)); + System.err.println("Expected: " + Arrays.toString(FLOATS)); + throw new RuntimeException(); + } + } +} diff --git a/jdk/test/javax/swing/JFileChooser/DeserializedJFileChooser/DeserializedJFileChooserTest.java b/jdk/test/javax/swing/JFileChooser/DeserializedJFileChooser/DeserializedJFileChooserTest.java new file mode 100644 index 0000000000000000000000000000000000000000..122b819255c2638013a068f0ca5b7e0c5cd10931 --- /dev/null +++ b/jdk/test/javax/swing/JFileChooser/DeserializedJFileChooser/DeserializedJFileChooserTest.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 8146301 + * @summary Enter key does not work in a deserialized JFileChooser. + * @run main DeserializedJFileChooserTest + */ + +import javax.swing.*; +import java.awt.*; +import java.awt.event.KeyEvent; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +public class DeserializedJFileChooserTest { + + private static int state = -1; + private static JFileChooser deserialized; + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeLater( () -> { + try { + JFileChooser jfc = new JFileChooser(); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(bos); + oos.writeObject(jfc); + oos.close(); + ByteArrayInputStream bis = + new ByteArrayInputStream(bos.toByteArray()); + ObjectInputStream ois = new ObjectInputStream(bis); + deserialized = (JFileChooser) ois.readObject(); + state = deserialized.showOpenDialog(null); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + Robot robot = new Robot(); + robot.setAutoDelay(50); + robot.waitForIdle(); + robot.keyPress(KeyEvent.VK_A); + robot.keyRelease(KeyEvent.VK_A); + robot.keyPress(KeyEvent.VK_ENTER); + robot.keyRelease(KeyEvent.VK_ENTER); + robot.waitForIdle(); + robot.delay(1000); + if (state != JFileChooser.APPROVE_OPTION) { + deserialized.cancelSelection(); + throw new RuntimeException("Failed"); + } + } +} diff --git a/jdk/test/javax/swing/JInternalFrame/DockIconRepaint/DockIconRepaint.java b/jdk/test/javax/swing/JInternalFrame/DockIconRepaint/DockIconRepaint.java new file mode 100644 index 0000000000000000000000000000000000000000..6af5c95e4731e7771c5872223ba8c7355e6c34d1 --- /dev/null +++ b/jdk/test/javax/swing/JInternalFrame/DockIconRepaint/DockIconRepaint.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Color; +import java.awt.EventQueue; +import java.awt.Graphics; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.beans.PropertyVetoException; + +import javax.swing.JDesktopPane; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.JPanel; + +/** + * @test + * @bug 8144166 + * @requires (os.family == "mac") + */ +public final class DockIconRepaint { + + private static volatile Color color; + + private static JFrame frame; + + private static JInternalFrame jif; + + private static Robot robot; + + private static Point iconLoc; + + private static Rectangle iconBounds; + + public static void main(final String[] args) throws Exception { + robot = new Robot(); + EventQueue.invokeAndWait(DockIconRepaint::createUI); + try { + robot.waitForIdle(); + color = Color.BLUE; + test(); + color = Color.RED; + test(); + color = Color.GREEN; + test(); + } finally { + frame.dispose(); + } + } + + private static void test() throws Exception { + // maximize the frame to force repaint + EventQueue.invokeAndWait(() -> { + try { + jif.setIcon(false); + jif.setMaximum(true); + } catch (PropertyVetoException e) { + throw new RuntimeException(e); + } + }); + robot.waitForIdle(); + Thread.sleep(1000); + // minimize the frame to dock, the icon should be up2date + EventQueue.invokeAndWait(() -> { + try { + jif.setIcon(true); + } catch (PropertyVetoException e) { + throw new RuntimeException(e); + } + iconLoc = jif.getDesktopIcon().getLocationOnScreen(); + iconBounds = jif.getDesktopIcon().getBounds(); + }); + robot.waitForIdle(); + Thread.sleep(1000); + + final Color c = robot.getPixelColor(iconLoc.x + iconBounds.width / 2, + iconLoc.y + iconBounds.height / 2); + if (c.getRGB() != color.getRGB()) { + System.err.println("Exp: " + Integer.toHexString(color.getRGB())); + System.err.println("Actual: " + Integer.toHexString(c.getRGB())); + throw new RuntimeException("Wrong color."); + } + } + + private static void createUI() { + frame = new JFrame(); + frame.setUndecorated(true); + frame.setSize(300, 300); + frame.setLocationRelativeTo(null); + final JDesktopPane pane = new JDesktopPane(); + final JPanel panel = new JPanel() { + @Override + protected void paintComponent(Graphics g) { + g.setColor(color); + g.fillRect(0, 0, getWidth(), getHeight()); + } + }; + jif = new JInternalFrame(); + jif.add(panel); + jif.setVisible(true); + jif.setSize(300, 300); + pane.add(jif); + frame.add(pane); + frame.setVisible(true); + } +} diff --git a/jdk/test/javax/swing/JPopupMenu/6949414/JPopupMenuEndlessLoopTest.java b/jdk/test/javax/swing/JPopupMenu/6949414/JPopupMenuEndlessLoopTest.java new file mode 100644 index 0000000000000000000000000000000000000000..0a0df91379f4b114a7292128b046bbb2840e15bd --- /dev/null +++ b/jdk/test/javax/swing/JPopupMenu/6949414/JPopupMenuEndlessLoopTest.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; +import javax.swing.MenuElement; +import javax.swing.MenuSelectionManager; +import javax.swing.SwingUtilities; + +/** + * @test + * @bug 6949414 6424606 + * @summary JMenu.buildMenuElementArray() endless loop + * @run main/timeout=5 JPopupMenuEndlessLoopTest + */ +public class JPopupMenuEndlessLoopTest { + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(() -> { + + JPopupMenu popup = new JPopupMenu("Popup Menu"); + JMenu menu = new JMenu("Menu"); + menu.add(new JMenuItem("Menu Item")); + popup.add(menu); + menu.doClick(); + MenuElement[] elems = MenuSelectionManager + .defaultManager().getSelectedPath(); + + if (elems == null || elems.length == 0) { + throw new RuntimeException("Empty Selection"); + } + + if (elems[0] != popup || elems[1] != menu) { + throw new RuntimeException("Necessary menus are not selected!"); + } + }); + } +} diff --git a/jdk/test/javax/swing/JTabbedPane/8137169/ScrollableTabbedPaneTest.java b/jdk/test/javax/swing/JTabbedPane/8137169/ScrollableTabbedPaneTest.java new file mode 100644 index 0000000000000000000000000000000000000000..834da2ef5223c25a07d19ca1a7b43786b19206d1 --- /dev/null +++ b/jdk/test/javax/swing/JTabbedPane/8137169/ScrollableTabbedPaneTest.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 8137169 + * @summary verifies TabbedScrollPane minimum height for all Look and Feels + * @library ../../regtesthelpers + * @build Util + * @run main ScrollableTabbedPaneTest + */ + +import java.awt.Robot; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTabbedPane; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; + +public class ScrollableTabbedPaneTest { + + private static JFrame frame; + private static JTabbedPane pane; + private static Robot robot; + private static volatile String errorString = ""; + + public static void main(String[] args) throws Exception { + robot = new Robot(); + robot.delay(1000); + UIManager.LookAndFeelInfo[] lookAndFeelArray + = UIManager.getInstalledLookAndFeels(); + for (UIManager.LookAndFeelInfo lookAndFeelItem : lookAndFeelArray) { + executeCase(lookAndFeelItem.getClassName(), + lookAndFeelItem.getName()); + } + if (!"".equals(errorString)) { + throw new RuntimeException("Error Log:\n" + errorString); + } + } + + private static void executeCase(String lookAndFeelString, String shortLAF) + throws Exception { + if (tryLookAndFeel(lookAndFeelString)) { + createUI(shortLAF); + stepsToExecute(shortLAF); + + createLeftUI(shortLAF); + stepsToExecute(shortLAF); + + createRightUI(shortLAF); + stepsToExecute(shortLAF); + } + } + + private static void stepsToExecute(String shortLAF) throws Exception { + robot.delay(100); + runTestCase(shortLAF); + robot.delay(1000); + cleanUp(); + robot.delay(1000); + } + + private static boolean tryLookAndFeel(String lookAndFeelString) + throws Exception { + try { + UIManager.setLookAndFeel( + lookAndFeelString); + + } catch (UnsupportedLookAndFeelException + | ClassNotFoundException + | InstantiationException + | IllegalAccessException e) { + return false; + } + return true; + } + + private static void cleanUp() throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + frame.dispose(); + } + }); + } + + private static void createUI(final String shortLAF) + throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + frame = new JFrame(shortLAF); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setVisible(true); + pane = new JTabbedPane(); + pane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); + frame.add(pane); + frame.setSize(500, 500); + } + }); + } + private static void createLeftUI(final String shortLAF) + throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + frame = new JFrame(shortLAF); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setVisible(true); + pane = new JTabbedPane(); + pane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); + pane.setTabPlacement(SwingConstants.LEFT); + frame.add(pane); + frame.setSize(500, 500); + } + }); + } + + private static void createRightUI(final String shortLAF) + throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + frame = new JFrame(shortLAF); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setVisible(true); + pane = new JTabbedPane(); + pane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); + pane.setTabPlacement(SwingConstants.RIGHT); + frame.add(pane); + frame.setSize(500, 500); + } + }); + } + + private static void runTestCase(String shortLAF) throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + int i = 0; + int value= 0; + do { + String title = "Tab" + (i + 1); + pane.addTab(title, new JPanel()); + int tempValue = pane.getMinimumSize().height; + if(value==0) { + value = tempValue; + } + if(value != tempValue) { + String error = "[" + shortLAF + + "]: [Error]: TabbedScrollPane fails"; + errorString += error; + } + + ++i; + } while (i < 10); + } + }); + } +} + diff --git a/jdk/test/javax/swing/LookAndFeel/6897701/JMenuItemsTest.java b/jdk/test/javax/swing/LookAndFeel/6897701/JMenuItemsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..c8e2492de2f1b11e4e302cc78008b48b5610b46f --- /dev/null +++ b/jdk/test/javax/swing/LookAndFeel/6897701/JMenuItemsTest.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 6897701 + * @summary Verify JMenu and JMenuItem Disabled state for Nimbus LAF + * @run main JMenuItemsTest + */ +import java.awt.Color; +import java.awt.Rectangle; +import java.awt.image.BufferedImage; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; + +public class JMenuItemsTest { + + private static JFrame mainFrame; + private static JMenu disabledMenu; + private static JMenuItem disabledMenuItem; + + public JMenuItemsTest() { + createUI(); + } + + private void createUI() { + + mainFrame = new JFrame("Test"); + + disabledMenu = new JMenu("Disabled Menu"); + disabledMenu.setForeground(Color.BLUE); + disabledMenu.setEnabled(false); + + disabledMenuItem = new JMenuItem("Disabled MenuItem"); + disabledMenuItem.setForeground(Color.BLUE); + disabledMenuItem.setEnabled(false); + + JMenuBar menuBar = new JMenuBar(); + menuBar = new JMenuBar(); + menuBar.add(disabledMenu); + menuBar.add(disabledMenuItem); + + mainFrame.add(menuBar); + mainFrame.pack(); + mainFrame.setVisible(true); + } + + private void dispose() { + mainFrame.dispose(); + } + + private void testDisabledStateOfJMenu() { + + // Test disabled JMenu state + Rectangle rect = disabledMenu.getBounds(); + BufferedImage image = new BufferedImage(rect.width, rect.height, + BufferedImage.TYPE_INT_ARGB); + disabledMenu.paint(image.getGraphics()); + int y = image.getHeight() / 2; + for (int x = 0; x < image.getWidth(); x++) { + Color c = new Color(image.getRGB(x, y)); + if (c.equals(Color.BLUE)) { + dispose(); + throw new RuntimeException("JMenu Disabled" + + " State not Valid."); + } + } + + } + + private void testDisabledStateOfJMenuItem() { + + // Test disabled JMenuItem state + Rectangle rect = disabledMenuItem.getBounds(); + BufferedImage image = new BufferedImage(rect.width, rect.height, + BufferedImage.TYPE_INT_ARGB); + disabledMenuItem.paint(image.getGraphics()); + int y = image.getHeight() / 2; + for (int x = 0; x < image.getWidth(); x++) { + Color c = new Color(image.getRGB(x, y)); + if (c.equals(Color.BLUE)) { + dispose(); + throw new RuntimeException("JMenuItem Disabled" + + " State not Valid."); + } + } + + } + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel"); + SwingUtilities.invokeAndWait(() -> { + + try { + JMenuItemsTest obj = new JMenuItemsTest(); + obj.testDisabledStateOfJMenu(); + obj.testDisabledStateOfJMenuItem(); + obj.dispose(); + + } catch (Exception ex) { + throw ex; + } + + }); + } +} diff --git a/jdk/test/javax/swing/text/html/CSS/ColorValue/RGBColorValueTest.java b/jdk/test/javax/swing/text/html/CSS/ColorValue/RGBColorValueTest.java new file mode 100644 index 0000000000000000000000000000000000000000..fce9408717dca1cef9fe3e1369a7891ad26f90a1 --- /dev/null +++ b/jdk/test/javax/swing/text/html/CSS/ColorValue/RGBColorValueTest.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8149631 + * @summary rgb(...) CSS color values are not parsed properly + * @run main RGBColorValueTest + */ + +import javax.swing.text.AttributeSet; +import javax.swing.text.html.StyleSheet; + +import static javax.swing.text.html.CSS.Attribute.*; + +public class RGBColorValueTest { + + public static void main(String[] args) { + StyleSheet styleSheet = new StyleSheet(); + AttributeSet attributeSet = styleSheet. + getDeclaration("border-color: rgb(1, 2, 3) rgb(1, 2, 4);"); + if (!attributeSet.getAttribute(BORDER_TOP_COLOR).toString() + .equals("rgb(1, 2, 3)") || + !attributeSet.getAttribute(BORDER_BOTTOM_COLOR).toString() + .equals("rgb(1, 2, 3)") || + !attributeSet.getAttribute(BORDER_RIGHT_COLOR).toString() + .equals("rgb(1, 2, 4)") || + !attributeSet.getAttribute(BORDER_LEFT_COLOR).toString() + .equals("rgb(1, 2, 4)") ) { + throw new RuntimeException("Failed"); + } + } +} diff --git a/jdk/test/jdk/internal/jrtfs/WithSecurityManager.java b/jdk/test/jdk/internal/jrtfs/WithSecurityManager.java index f6d111475ef4ddd6ee4627123b6cae7d6134a657..81336e202991517e216eee8da5be71140848cb4a 100644 --- a/jdk/test/jdk/internal/jrtfs/WithSecurityManager.java +++ b/jdk/test/jdk/internal/jrtfs/WithSecurityManager.java @@ -31,6 +31,7 @@ import java.net.URI; import java.nio.file.FileSystems; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Collections; public class WithSecurityManager { public static void main(String[] args) throws Exception { @@ -61,7 +62,7 @@ public class WithSecurityManager { // check FileSystems.newFileSystem try { - FileSystems.newFileSystem(URI.create("jrt:/"), null); + FileSystems.newFileSystem(URI.create("jrt:/"), Collections.emptyMap()); if (!allow) throw new RuntimeException("access not expected"); } catch (SecurityException se) { if (allow) diff --git a/jdk/test/jdk/internal/jrtfs/remote/Main.java b/jdk/test/jdk/internal/jrtfs/remote/Main.java index 8ef6303526d73c122186edb055a8e834dab32091..9b22c8308d32a6cd8950e9f67472989686f715d8 100644 --- a/jdk/test/jdk/internal/jrtfs/remote/Main.java +++ b/jdk/test/jdk/internal/jrtfs/remote/Main.java @@ -30,6 +30,7 @@ import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Collections; import java.util.stream.Stream; /** @@ -69,11 +70,12 @@ public class Main { private static FileSystem createFsWithURLClassloader(String javaHome) throws IOException{ URL url = Paths.get(javaHome, "jrt-fs.jar").toUri().toURL(); URLClassLoader loader = new URLClassLoader(new URL[] { url }); - return FileSystems.newFileSystem(URI.create("jrt:/"), null, loader); + return FileSystems.newFileSystem(URI.create("jrt:/"), + Collections.emptyMap(), + loader); } private static FileSystem createFsByInstalledProvider() throws IOException { return FileSystems.getFileSystem(URI.create("jrt:/")); } } - diff --git a/jdk/test/jdk/internal/jrtfs/remote/RemoteRuntimeImageTest.java b/jdk/test/jdk/internal/jrtfs/remote/RemoteRuntimeImageTest.java index 2c3d588369fb9c0e0f0fcf0b1ab9fbb302d09230..7ea315ad5d64432c3c224c3a37ba0570fbf209ab 100644 --- a/jdk/test/jdk/internal/jrtfs/remote/RemoteRuntimeImageTest.java +++ b/jdk/test/jdk/internal/jrtfs/remote/RemoteRuntimeImageTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8141609 + * @bug 8141609 8154403 * @summary Verify JDK 8 can use jrt-fs.jar to work with jrt file system. * @run main RemoteRuntimeImageTest */ @@ -63,7 +63,6 @@ public class RemoteRuntimeImageTest { String java = jdk8Path.resolve("bin/java").toAbsolutePath().toString(); String javac = jdk8Path.resolve("bin/javac").toAbsolutePath().toString(); - Files.createDirectories(Paths.get(".", CLASSES_DIR)); String jrtJar = Paths.get(TEST_JAVAHOME, JRTFS_JAR).toAbsolutePath().toString(); @@ -121,4 +120,3 @@ public class RemoteRuntimeImageTest { return version.startsWith("\"1.8"); } } - diff --git a/jdk/test/sanity/client/lib/SwingSet3/README b/jdk/test/sanity/client/lib/SwingSet3/README index 1952a70cd26e4f6a4d623e909cd8273b48dda861..cf0406460ef4de9eaa4dc05b2a50c0db855f96de 100644 --- a/jdk/test/sanity/client/lib/SwingSet3/README +++ b/jdk/test/sanity/client/lib/SwingSet3/README @@ -1,4 +1,4 @@ This content of this src folder was originally taken from SwingSet3 demo project: https://java.net/projects/swingset3/. Then it was modified to increase testability and remove extra content and extra dependencies. -Do NOT modify files in it. \ No newline at end of file +This is NOT the official location of the SwingSet3 demo. \ No newline at end of file diff --git a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/button/ButtonDemo.java b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/button/ButtonDemo.java index 728e0543b6868c233bb37dbfae33dfe23b527d70..e3aa888e5f3f26c11e28c99c33309eb1b9f6c305 100644 --- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/button/ButtonDemo.java +++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/button/ButtonDemo.java @@ -215,7 +215,6 @@ public final class ButtonDemo extends JPanel { javax.swing.SwingUtilities.invokeLater(() -> { JFrame frame = new JFrame(DEMO_TITLE); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(buttonDemo); frame.pack(); frame.setVisible(true); diff --git a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/combobox/ComboBoxDemo.java b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/combobox/ComboBoxDemo.java index 5fc080f95bb136daafe84fde57cf782fd1c0298f..f204e64437de57d635e6591d5988c57d42ec39dc 100644 --- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/combobox/ComboBoxDemo.java +++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/combobox/ComboBoxDemo.java @@ -120,7 +120,6 @@ public class ComboBoxDemo extends JPanel implements ActionListener { public static void main(String[] args) { JFrame frame = new JFrame(DEMO_TITLE); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(new ComboBoxDemo()); frame.setPreferredSize(new Dimension(800, 600)); frame.pack(); diff --git a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/list/ListDemo.java b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/list/ListDemo.java index b8dce72ba9ea1819f5a042271dc3bcbeeda3eae3..02b55129f6098cd6d300cf81c1321cdde8a8ceb4 100644 --- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/list/ListDemo.java +++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/list/ListDemo.java @@ -90,7 +90,6 @@ public final class ListDemo extends JPanel { public static void main(String[] args) { JFrame frame = new JFrame(DEMO_TITLE); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(new ListDemo()); frame.setPreferredSize(new Dimension(800, 600)); frame.pack(); diff --git a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/optionpane/OptionPaneDemo.java b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/optionpane/OptionPaneDemo.java index 0e8c1e46a1331ec6c3d532f0f8308ac0f2bcc532..ca04135c2a15077d5bc25f89792d6372e6869295 100644 --- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/optionpane/OptionPaneDemo.java +++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/optionpane/OptionPaneDemo.java @@ -93,7 +93,6 @@ public class OptionPaneDemo extends JPanel { public static void main(String[] args) { JFrame frame = new JFrame(DEMO_TITLE); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(new OptionPaneDemo()); frame.setPreferredSize(new Dimension(800, 600)); frame.pack(); diff --git a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/progressbar/ProgressBarDemo.java b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/progressbar/ProgressBarDemo.java index e49b47926ea491b2b0502486df938e0c4279c817..5e9d38bd7a34d8e170a261b896e027e20eab2c50 100644 --- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/progressbar/ProgressBarDemo.java +++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/progressbar/ProgressBarDemo.java @@ -64,7 +64,6 @@ public class ProgressBarDemo extends JPanel { public static void main(String[] args) { JFrame frame = new JFrame(DEMO_TITLE); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(new ProgressBarDemo()); frame.setPreferredSize(new Dimension(800, 600)); frame.pack(); diff --git a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/scrollpane/ScrollPaneDemo.java b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/scrollpane/ScrollPaneDemo.java index 5a492ea53fdb5ab086b7f6360f18d90a61fd02e9..40fb29cfaa6454e4b71fee28adf8c4fa01f09865 100644 --- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/scrollpane/ScrollPaneDemo.java +++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/scrollpane/ScrollPaneDemo.java @@ -64,7 +64,6 @@ public class ScrollPaneDemo extends JPanel { public static void main(String[] args) { JFrame frame = new JFrame(DEMO_TITLE); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(new ScrollPaneDemo()); frame.setPreferredSize(new Dimension(800, 600)); frame.pack(); diff --git a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/spinner/SpinnerDemo.java b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/spinner/SpinnerDemo.java index 0694a8433410b6160ca08fa4fdbc7e88e5fcf9a3..97dbd2d50020be226c5bd7684270a31164073d47 100644 --- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/spinner/SpinnerDemo.java +++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/spinner/SpinnerDemo.java @@ -58,7 +58,6 @@ public class SpinnerDemo extends JPanel { public static void main(String[] args) { JFrame frame = new JFrame(DEMO_TITLE); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(new SpinnerDemo()); frame.setPreferredSize(new Dimension(800, 600)); frame.pack(); diff --git a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/splitpane/SplitPaneDemo.java b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/splitpane/SplitPaneDemo.java index 0bc0cd78f0f3cc88f9c773ba9c9c17c86af07535..64bc9b2ccafa5d8e72d9e67cadd9f941366fa5bd 100644 --- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/splitpane/SplitPaneDemo.java +++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/splitpane/SplitPaneDemo.java @@ -86,7 +86,6 @@ public class SplitPaneDemo extends JPanel { public static void main(String[] args) { JFrame frame = new JFrame(DEMO_TITLE); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(new SplitPaneDemo()); frame.setPreferredSize(new Dimension(800, 600)); frame.pack(); diff --git a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/textfield/TextFieldDemo.java b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/textfield/TextFieldDemo.java index be7c9a7e7d0a5ebd1ddf2f9f75081967b119740d..16537bfccf568a60328d0cef517466086a91b65c 100644 --- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/textfield/TextFieldDemo.java +++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/textfield/TextFieldDemo.java @@ -115,7 +115,6 @@ public class TextFieldDemo extends JPanel { public static void main(String[] args) { JFrame frame = new JFrame(DEMO_TITLE); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(new TextFieldDemo()); frame.setPreferredSize(new Dimension(800, 600)); frame.pack(); diff --git a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/togglebutton/ToggleButtonDemo.java b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/togglebutton/ToggleButtonDemo.java index 5adf5f7a62bf8b4d0d9e4c968644e5f6e4afa260..625c9fe1fda7993d29e7c3ae60914c1843af90db 100644 --- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/togglebutton/ToggleButtonDemo.java +++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/togglebutton/ToggleButtonDemo.java @@ -151,7 +151,6 @@ public class ToggleButtonDemo extends JPanel implements ChangeListener { public static void main(String[] args) { JFrame frame = new JFrame(ToggleButtonDemo.class.getAnnotation(DemoProperties.class).value()); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(new ToggleButtonDemo()); frame.setPreferredSize(new Dimension(800, 600)); frame.pack(); diff --git a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tree/TreeDemo.java b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tree/TreeDemo.java index 1a4c555945ed3bc440f25d0208b3fa80a19609e2..e6f8e326571fca0702a5312950727236b45dff26 100644 --- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tree/TreeDemo.java +++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tree/TreeDemo.java @@ -65,7 +65,6 @@ public class TreeDemo extends JPanel { public static void main(String[] args) { JFrame frame = new JFrame(DEMO_TITLE); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(new TreeDemo()); frame.setPreferredSize(new Dimension(800, 600)); frame.pack(); diff --git a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/window/WindowDemo.java b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/window/WindowDemo.java index cf83135d1e8bc269d66fb64a408359e1359b2077..89b87776ba282d83634a12381580e1cea4a82f31 100644 --- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/window/WindowDemo.java +++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/window/WindowDemo.java @@ -150,7 +150,6 @@ public final class WindowDemo extends JPanel { JFrame frame = new JFrame(); WindowDemo demo = new WindowDemo(); frame.add(demo); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setVisible(true); demo.start(); diff --git a/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/ImpactOnSNI.java b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/ImpactOnSNI.java new file mode 100644 index 0000000000000000000000000000000000000000..4e0f0bdac59564dd0f0732df63d4fdcf5dab1504 --- /dev/null +++ b/jdk/test/sun/net/www/protocol/https/HttpsURLConnection/ImpactOnSNI.java @@ -0,0 +1,390 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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. + */ + +// +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. +// + +/* + * @test + * @bug 8144566 + * @summary Custom HostnameVerifier disables SNI extension + * @run main/othervm ImpactOnSNI + */ + +import java.io.*; +import java.net.*; +import javax.net.ssl.*; + +public class ImpactOnSNI { + + /* + * ============================================================= + * Set the various variables needed for the tests, then + * specify what tests to run on each side. + */ + + /* + * Should we run the client or server in a separate thread? + * Both sides can throw exceptions, but do you have a preference + * as to which side should be the main thread. + */ + private static final boolean separateServerThread = true; + + /* + * Where do we find the keystores? + */ + private static final String pathToStores = + "../../../../../../javax/net/ssl/etc"; + private static final String keyStoreFile = "keystore"; + private static final String trustStoreFile = "truststore"; + private static final String passwd = "passphrase"; + + /* + * Is the server ready to serve? + */ + private static volatile boolean serverReady = false; + + /* + * Is the connection ready to close? + */ + private static volatile boolean closeReady = false; + + /* + * Turn on SSL debugging? + */ + private static final boolean debug = false; + + /* + * Message posted + */ + private static final String postMsg = "HTTP post on a https server"; + + /* + * the fully qualified domain name of localhost + */ + private static String hostname = null; + + /* + * If the client or server is doing some kind of object creation + * that the other side depends on, and that thread prematurely + * exits, you may experience a hang. The test harness will + * terminate all hung threads after its timeout has expired, + * currently 3 minutes by default, but you might try to be + * smart about it.... + */ + + /* + * Define the server side of the test. + * + * If the server prematurely exits, serverReady will be set to true + * to avoid infinite hangs. + */ + private void doServerSide() throws Exception { + SSLServerSocketFactory sslssf = + (SSLServerSocketFactory)SSLServerSocketFactory.getDefault(); + try (SSLServerSocket sslServerSocket = + (SSLServerSocket)sslssf.createServerSocket(serverPort)) { + + serverPort = sslServerSocket.getLocalPort(); + + /* + * Signal Client, we're ready for his connect. + */ + serverReady = true; + + /* + * Accept connections + */ + try (SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept()) { + InputStream sslIS = sslSocket.getInputStream(); + OutputStream sslOS = sslSocket.getOutputStream(); + BufferedReader br = + new BufferedReader(new InputStreamReader(sslIS)); + PrintStream ps = new PrintStream(sslOS); + + // process HTTP POST request from client + System.out.println("status line: " + br.readLine()); + String msg = null; + while ((msg = br.readLine()) != null && msg.length() > 0); + + msg = br.readLine(); + if (msg.equals(postMsg)) { + ps.println("HTTP/1.1 200 OK\n\n"); + } else { + ps.println("HTTP/1.1 500 Not OK\n\n"); + } + ps.flush(); + + ExtendedSSLSession session = + (ExtendedSSLSession)sslSocket.getSession(); + if (session.getRequestedServerNames().isEmpty()) { + throw new Exception("No expected Server Name Indication"); + } + + // close the socket + while (!closeReady) { + Thread.sleep(50); + } + } + } + } + + /* + * Define the client side of the test. + * + * If the server prematurely exits, serverReady will be set to true + * to avoid infinite hangs. + */ + private void doClientSide() throws Exception { + /* + * Wait for server to get started. + */ + while (!serverReady) { + Thread.sleep(50); + } + + // Send HTTP POST request to server + URL url = new URL("https://" + hostname + ":" + serverPort); + + HttpsURLConnection.setDefaultHostnameVerifier(new NameVerifier()); + HttpsURLConnection http = (HttpsURLConnection)url.openConnection(); + http.setDoOutput(true); + + http.setRequestMethod("POST"); + PrintStream ps = new PrintStream(http.getOutputStream()); + try { + ps.println(postMsg); + ps.flush(); + if (http.getResponseCode() != 200) { + throw new RuntimeException("test Failed"); + } + } finally { + ps.close(); + http.disconnect(); + closeReady = true; + } + } + + private static class NameVerifier implements HostnameVerifier { + public boolean verify(String hostname, SSLSession session) { + return true; + } + } + + /* + * ============================================================= + * The remainder is just support stuff + */ + + // use any free port by default + private volatile int serverPort = 0; + + private volatile Exception serverException = null; + private volatile Exception clientException = null; + + public static void main(String[] args) throws Exception { + String keyFilename = + System.getProperty("test.src", "./") + "/" + pathToStores + + "/" + keyStoreFile; + String trustFilename = + System.getProperty("test.src", "./") + "/" + pathToStores + + "/" + trustStoreFile; + + System.setProperty("javax.net.ssl.keyStore", keyFilename); + System.setProperty("javax.net.ssl.keyStorePassword", passwd); + System.setProperty("javax.net.ssl.trustStore", trustFilename); + System.setProperty("javax.net.ssl.trustStorePassword", passwd); + + if (debug) { + System.setProperty("javax.net.debug", "all"); + } + + try { + hostname = InetAddress.getLocalHost().getCanonicalHostName(); + } catch (UnknownHostException uhe) { + System.out.println( + "Ignore the test as the local hostname cannot be determined"); + + return; + } + + System.out.println( + "The fully qualified domain name of the local host is " + + hostname); + // Ignore the test if the hostname does not sound like a domain name. + if ((hostname == null) || hostname.isEmpty() || + hostname.startsWith("localhost") || + Character.isDigit(hostname.charAt(hostname.length() - 1))) { + + System.out.println("Ignore the test as the local hostname " + + "cannot be determined as fully qualified domain name"); + + return; + } + + /* + * Start the tests. + */ + new ImpactOnSNI(); + } + + private Thread clientThread = null; + private Thread serverThread = null; + + /* + * Primary constructor, used to drive remainder of the test. + * + * Fork off the other side, then do your work. + */ + ImpactOnSNI() throws Exception { + Exception startException = null; + try { + if (separateServerThread) { + startServer(true); + startClient(false); + } else { + startClient(true); + startServer(false); + } + } catch (Exception e) { + startException = e; + } + + /* + * Wait for other side to close down. + */ + if (separateServerThread) { + if (serverThread != null) { + serverThread.join(); + } + } else { + if (clientThread != null) { + clientThread.join(); + } + } + + /* + * When we get here, the test is pretty much over. + * Which side threw the error? + */ + Exception local; + Exception remote; + + if (separateServerThread) { + remote = serverException; + local = clientException; + } else { + remote = clientException; + local = serverException; + } + + Exception exception = null; + + /* + * Check various exception conditions. + */ + if ((local != null) && (remote != null)) { + // If both failed, return the curthread's exception. + local.initCause(remote); + exception = local; + } else if (local != null) { + exception = local; + } else if (remote != null) { + exception = remote; + } else if (startException != null) { + exception = startException; + } + + /* + * If there was an exception *AND* a startException, + * output it. + */ + if (exception != null) { + if (exception != startException && startException != null) { + exception.addSuppressed(startException); + } + throw exception; + } + + // Fall-through: no exception to throw! + } + + private void startServer(boolean newThread) throws Exception { + if (newThread) { + serverThread = new Thread() { + @Override + public void run() { + try { + doServerSide(); + } catch (Exception e) { + /* + * Our server thread just died. + * + * Release the client, if not active already... + */ + System.err.println("Server died..."); + serverReady = true; + serverException = e; + } + } + }; + serverThread.start(); + } else { + try { + doServerSide(); + } catch (Exception e) { + serverException = e; + } finally { + serverReady = true; + } + } + } + + private void startClient(boolean newThread) throws Exception { + if (newThread) { + clientThread = new Thread() { + @Override + public void run() { + try { + doClientSide(); + } catch (Exception e) { + /* + * Our client thread just died. + */ + System.err.println("Client died..."); + clientException = e; + } + } + }; + clientThread.start(); + } else { + try { + doClientSide(); + } catch (Exception e) { + clientException = e; + } + } + } +} diff --git a/jdk/test/sun/security/provider/DSA/TestDSA2.java b/jdk/test/sun/security/provider/DSA/TestDSA2.java index 00691535ac135e66ddd8ab0265a8199c48468170..320acce4880427b2e2ef4ae6d5ea84fecb3d66af 100644 --- a/jdk/test/sun/security/provider/DSA/TestDSA2.java +++ b/jdk/test/sun/security/provider/DSA/TestDSA2.java @@ -60,8 +60,8 @@ public class TestDSA2 { boolean[] expectedToPass = { true, true, true, true, true, true, true, true }; test(1024, expectedToPass); - boolean[] expectedToPass2 = { true, true, true, true, - true, true, true, true }; + boolean[] expectedToPass2 = { true, false, true, true, + true, false, true, true }; test(2048, expectedToPass2); } diff --git a/jdk/test/sun/security/rsa/SpecTest.java b/jdk/test/sun/security/rsa/SpecTest.java index c13f1d91989d11cb270efaea990115cca4580c25..24cddfe35915f95c57fffbb52e7d5824f8d6712b 100644 --- a/jdk/test/sun/security/rsa/SpecTest.java +++ b/jdk/test/sun/security/rsa/SpecTest.java @@ -20,32 +20,32 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -import java.math.BigInteger; -import java.security.InvalidAlgorithmParameterException; -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.interfaces.RSAKey; -import java.security.interfaces.RSAPrivateKey; -import java.security.interfaces.RSAPublicKey; -import java.security.spec.RSAKeyGenParameterSpec; /** * @test - * @bug 8044199 + * @bug 8044199 8137231 * @key intermittent * @summary Check same KeyPair's private key and public key have same modulus. - * also check public key's public exponent equals to given spec's public - * exponent. + * also check public key's public exponent equals to given spec's public + * exponent. Only key size 1024 is tested with RSAKeyGenParameterSpec.F0 (3). * @run main SpecTest 512 * @run main SpecTest 768 * @run main SpecTest 1024 + * @run main SpecTest 1024 3 * @run main SpecTest 2048 * @run main/timeout=240 SpecTest 4096 * @run main/timeout=240 SpecTest 5120 */ +import java.math.BigInteger; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.interfaces.RSAKey; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.RSAKeyGenParameterSpec; + public class SpecTest { + /** * ALGORITHM name, fixed as RSA. */ @@ -70,14 +70,14 @@ public class SpecTest { // test the getModulus method if ((priv instanceof RSAKey) && (pub instanceof RSAKey)) { if (!priv.getModulus().equals(pub.getModulus())) { - System.err.println("priv.getModulus() = " + priv.getModulus()); - System.err.println("pub.getModulus() = " + pub.getModulus()); + System.out.println("priv.getModulus() = " + priv.getModulus()); + System.out.println("pub.getModulus() = " + pub.getModulus()); passed = false; } if (!pubExponent.equals(pub.getPublicExponent())) { - System.err.println("pubExponent = " + pubExponent); - System.err.println("pub.getPublicExponent() = " + System.out.println("pubExponent = " + pubExponent); + System.out.println("pub.getPublicExponent() = " + pub.getPublicExponent()); passed = false; } @@ -85,36 +85,26 @@ public class SpecTest { return passed; } - public static void main(String[] args) { - int failCount = 0; + public static void main(String[] args) throws Exception { - // Test key size. - int size = Integer.parseInt(args[0]); + int size = 0; - try { - KeyPairGenerator kpg1 = KeyPairGenerator.getInstance(KEYALG, PROVIDER); - kpg1.initialize(new RSAKeyGenParameterSpec(size, - RSAKeyGenParameterSpec.F4)); - if (!specTest(kpg1.generateKeyPair(), - RSAKeyGenParameterSpec.F4)) { - failCount++; - } - - KeyPairGenerator kpg2 = KeyPairGenerator.getInstance(KEYALG, PROVIDER); - kpg2.initialize(new RSAKeyGenParameterSpec(size, - RSAKeyGenParameterSpec.F0)); - if (!specTest(kpg2.generateKeyPair(), RSAKeyGenParameterSpec.F0)) { - failCount++; - } - } catch (NoSuchAlgorithmException | NoSuchProviderException - | InvalidAlgorithmParameterException ex) { - ex.printStackTrace(System.err); - failCount++; + if (args.length >= 1) { + size = Integer.parseInt(args[0]); + } else { + throw new RuntimeException("Missing keysize to test with"); } - if (failCount != 0) { - throw new RuntimeException("There are " + failCount - + " tests failed."); + BigInteger publicExponent + = (args.length >= 2) ? new BigInteger(args[1]) : RSAKeyGenParameterSpec.F4; + + System.out.println("Running test with key size: " + size + + " and public exponent: " + publicExponent); + + KeyPairGenerator kpg1 = KeyPairGenerator.getInstance(KEYALG, PROVIDER); + kpg1.initialize(new RSAKeyGenParameterSpec(size, publicExponent)); + if (!specTest(kpg1.generateKeyPair(), publicExponent)) { + throw new RuntimeException("Test failed."); } } } diff --git a/jdk/test/sun/security/ssl/SSLContextImpl/MD2InTrustAnchor.java b/jdk/test/sun/security/ssl/SSLContextImpl/MD2InTrustAnchor.java index 9d8ee1d5287b28c87852fabaacfb69898d5dabce..f2e06337dd39f7f9153ad9f1c46b9d05703a0e22 100644 --- a/jdk/test/sun/security/ssl/SSLContextImpl/MD2InTrustAnchor.java +++ b/jdk/test/sun/security/ssl/SSLContextImpl/MD2InTrustAnchor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,106 +37,88 @@ * @run main/othervm MD2InTrustAnchor PKIX TLSv1.2 * @run main/othervm MD2InTrustAnchor SunX509 TLSv1.2 */ - -import java.net.*; -import java.util.*; -import java.io.*; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.OutputStream; import javax.net.ssl.*; import java.security.Security; import java.security.KeyStore; import java.security.KeyFactory; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; -import java.security.spec.*; -import java.security.interfaces.*; +import java.security.interfaces.RSAPrivateKey; +import java.security.spec.PKCS8EncodedKeySpec; import java.util.Base64; +import java.util.concurrent.CountDownLatch; public class MD2InTrustAnchor { - /* - * ============================================================= - * Set the various variables needed for the tests, then - * specify what tests to run on each side. - */ - - /* - * Should we run the client or server in a separate thread? - * Both sides can throw exceptions, but do you have a preference - * as to which side should be the main thread. - */ - static boolean separateServerThread = false; - /* * Certificates and key used in the test. */ - // It's a trust anchor signed with MD2 hash function. - static String trustedCertStr = - "-----BEGIN CERTIFICATE-----\n" + - "MIICkjCCAfugAwIBAgIBADANBgkqhkiG9w0BAQIFADA7MQswCQYDVQQGEwJVUzEN\n" + - "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" + - "MTExMTE4MTExNDA0WhcNMzIxMDI4MTExNDA0WjA7MQswCQYDVQQGEwJVUzENMAsG\n" + - "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwgZ8wDQYJ\n" + - "KoZIhvcNAQEBBQADgY0AMIGJAoGBAPGyB9tugUGgxtdeqe0qJEwf9x1Gy4BOi1yR\n" + - "wzDZY4H5LquvIfQ2V3J9X1MQENVsFvkvp65ZcFcy+ObOucXUUPFcd/iw2DVb5QXA\n" + - "ffyeVqWD56GPi8Qe37wrJO3L6fBhN9oxp/BbdRLgjU81zx8qLEyPODhPMxV4OkcA\n" + - "SDwZTSxxAgMBAAGjgaUwgaIwHQYDVR0OBBYEFLOAtr/YrYj9H04EDLA0fd14jisF\n" + - "MGMGA1UdIwRcMFqAFLOAtr/YrYj9H04EDLA0fd14jisFoT+kPTA7MQswCQYDVQQG\n" + - "EwJVUzENMAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2\n" + - "Y2WCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEC\n" + - "BQADgYEAr8ExpXu/FTIRiMzPm0ubqwME4lniilwQUiEOD/4DbksNjEIcUyS2hIk1\n" + - "qsmjJz3SHBnwhxl9dhJVwk2tZLkPGW86Zn0TPVRsttK4inTgCC9GFGeqQBdrU/uf\n" + - "lipBzXWljrfbg4N/kK8m2LabtKUMMnGysM8rN0Fx2PYm5xxGvtM=\n" + - "-----END CERTIFICATE-----"; + private static final String TRUSTED_CERT_STR = "-----BEGIN CERTIFICATE-----\n" + + "MIICkjCCAfugAwIBAgIBADANBgkqhkiG9w0BAQIFADA7MQswCQYDVQQGEwJVUzEN\n" + + "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" + + "MTExMTE4MTExNDA0WhcNMzIxMDI4MTExNDA0WjA7MQswCQYDVQQGEwJVUzENMAsG\n" + + "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwgZ8wDQYJ\n" + + "KoZIhvcNAQEBBQADgY0AMIGJAoGBAPGyB9tugUGgxtdeqe0qJEwf9x1Gy4BOi1yR\n" + + "wzDZY4H5LquvIfQ2V3J9X1MQENVsFvkvp65ZcFcy+ObOucXUUPFcd/iw2DVb5QXA\n" + + "ffyeVqWD56GPi8Qe37wrJO3L6fBhN9oxp/BbdRLgjU81zx8qLEyPODhPMxV4OkcA\n" + + "SDwZTSxxAgMBAAGjgaUwgaIwHQYDVR0OBBYEFLOAtr/YrYj9H04EDLA0fd14jisF\n" + + "MGMGA1UdIwRcMFqAFLOAtr/YrYj9H04EDLA0fd14jisFoT+kPTA7MQswCQYDVQQG\n" + + "EwJVUzENMAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2\n" + + "Y2WCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEC\n" + + "BQADgYEAr8ExpXu/FTIRiMzPm0ubqwME4lniilwQUiEOD/4DbksNjEIcUyS2hIk1\n" + + "qsmjJz3SHBnwhxl9dhJVwk2tZLkPGW86Zn0TPVRsttK4inTgCC9GFGeqQBdrU/uf\n" + + "lipBzXWljrfbg4N/kK8m2LabtKUMMnGysM8rN0Fx2PYm5xxGvtM=\n" + + "-----END CERTIFICATE-----"; // The certificate issued by above trust anchor, signed with MD5 - static String targetCertStr = - "-----BEGIN CERTIFICATE-----\n" + - "MIICeDCCAeGgAwIBAgIBAjANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" + - "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" + - "MTExMTE4MTExNDA2WhcNMzEwODA1MTExNDA2WjBPMQswCQYDVQQGEwJVUzENMAsG\n" + - "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxEjAQBgNV\n" + - "BAMTCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwDnm96mw\n" + - "fXCH4bgXk1US0VcJsQVxUtGMyncAveMuzBzNzOmKZPeqyYX1Fuh4q+cuza03WTJd\n" + - "G9nOkNr364e3Rn1aaHjCMcBmFflObnGnhhufNmIGYogJ9dJPmhUVPEVAXrMG+Ces\n" + - "NKy2E8woGnLMrqu6yiuTClbLBPK8fWzTXrECAwEAAaN4MHYwCwYDVR0PBAQDAgPo\n" + - "MB0GA1UdDgQWBBSdRrpocLPJXyGfDmMWJrcEf29WGDAfBgNVHSMEGDAWgBSzgLa/\n" + - "2K2I/R9OBAywNH3deI4rBTAnBgNVHSUEIDAeBggrBgEFBQcDAQYIKwYBBQUHAwIG\n" + - "CCsGAQUFBwMDMA0GCSqGSIb3DQEBBAUAA4GBAKJ71ZiCUykkJrCLYUxlFlhvUcr9\n" + - "sTcOc67QdroW5f412NI15SXWDiley/JOasIiuIFPjaJBjOKoHOvTjG/snVu9wEgq\n" + - "YNR8dPsO+NM8r79C6jO+Jx5fYAC7os2XxS75h3NX0ElJcbwIXGBJ6xRrsFh/BGYH\n" + - "yvudOlX4BkVR0l1K\n" + - "-----END CERTIFICATE-----"; + private static final String TARGET_CERT_STR = "-----BEGIN CERTIFICATE-----\n" + + "MIICeDCCAeGgAwIBAgIBAjANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" + + "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" + + "MTExMTE4MTExNDA2WhcNMzEwODA1MTExNDA2WjBPMQswCQYDVQQGEwJVUzENMAsG\n" + + "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxEjAQBgNV\n" + + "BAMTCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwDnm96mw\n" + + "fXCH4bgXk1US0VcJsQVxUtGMyncAveMuzBzNzOmKZPeqyYX1Fuh4q+cuza03WTJd\n" + + "G9nOkNr364e3Rn1aaHjCMcBmFflObnGnhhufNmIGYogJ9dJPmhUVPEVAXrMG+Ces\n" + + "NKy2E8woGnLMrqu6yiuTClbLBPK8fWzTXrECAwEAAaN4MHYwCwYDVR0PBAQDAgPo\n" + + "MB0GA1UdDgQWBBSdRrpocLPJXyGfDmMWJrcEf29WGDAfBgNVHSMEGDAWgBSzgLa/\n" + + "2K2I/R9OBAywNH3deI4rBTAnBgNVHSUEIDAeBggrBgEFBQcDAQYIKwYBBQUHAwIG\n" + + "CCsGAQUFBwMDMA0GCSqGSIb3DQEBBAUAA4GBAKJ71ZiCUykkJrCLYUxlFlhvUcr9\n" + + "sTcOc67QdroW5f412NI15SXWDiley/JOasIiuIFPjaJBjOKoHOvTjG/snVu9wEgq\n" + + "YNR8dPsO+NM8r79C6jO+Jx5fYAC7os2XxS75h3NX0ElJcbwIXGBJ6xRrsFh/BGYH\n" + + "yvudOlX4BkVR0l1K\n" + + "-----END CERTIFICATE-----"; // Private key in the format of PKCS#8. - static String targetPrivateKey = - "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMA55vepsH1wh+G4\n" + - "F5NVEtFXCbEFcVLRjMp3AL3jLswczczpimT3qsmF9RboeKvnLs2tN1kyXRvZzpDa\n" + - "9+uHt0Z9Wmh4wjHAZhX5Tm5xp4YbnzZiBmKICfXST5oVFTxFQF6zBvgnrDSsthPM\n" + - "KBpyzK6rusorkwpWywTyvH1s016xAgMBAAECgYEAn9bF3oRkdDoBU0i/mcww5I+K\n" + - "SH9tFt+WQbiojjz9ac49trkvUfu7MO1Jui2+QbrvaSkyj+HYGFOJd1wMsPXeB7ck\n" + - "5mOIYV4uZK8jfNMSQ8v0tFEeIPp5lKdw1XnrQfSe+abo2eL5Lwso437Y4s3w37+H\n" + - "aY3d76hR5qly+Ys+Ww0CQQDjeOoX89d/xhRqGXKjCx8ImE/dPmsI8O27cwtKrDYJ\n" + - "6t0v/xryVIdvOYcRBvKnqEogOH7T1kI+LnWKUTJ2ehJ7AkEA2FVloPVqCehXcc7e\n" + - "z3TDpU9w1B0JXklcV5HddYsRqp9RukN/VK4szKE7F1yoarIUtfE9Lr9082Jwyp3M\n" + - "L11xwwJBAKsZ+Hur3x0tUY29No2Nf/pnFyvEF57SGwA0uPmiL8Ol9lpz+UDudDEl\n" + - "hIM6Rqv12kwCMuQE9i7vo1o3WU3k5KECQEqhg1L49yD935TqiiFFpe0Ur9btQXse\n" + - "kdXAA4d2d5zGI7q/aGD9SYU6phkUJSHR16VA2RuUfzMrpb+wmm1IrmMCQFtLoKRT\n" + - "A5kokFb+E3Gplu29tJvCUpfwgBFRS+wmkvtiaU/tiyDcVgDO+An5DwedxxdVzqiE\n" + - "njWHoKY3axDQ8OU=\n"; - - - static char passphrase[] = "passphrase".toCharArray(); + private static final String TARGET_PRIV_KEY_STR = "MIICdwIBADANBgkqhkiG9w0B\n" + + "AQEFAASCAmEwggJdAgEAAoGBAMA55vepsH1wh+G4F5NVEtFXCbEFcVLRjMp3AL3j\n" + + "LswczczpimT3qsmF9RboeKvnLs2tN1kyXRvZzpDa9+uHt0Z9Wmh4wjHAZhX5Tm5x\n" + + "p4YbnzZiBmKICfXST5oVFTxFQF6zBvgnrDSsthPMKBpyzK6rusorkwpWywTyvH1s\n" + + "016xAgMBAAECgYEAn9bF3oRkdDoBU0i/mcww5I+KSH9tFt+WQbiojjz9ac49trkv\n" + + "Ufu7MO1Jui2+QbrvaSkyj+HYGFOJd1wMsPXeB7ck5mOIYV4uZK8jfNMSQ8v0tFEe\n" + + "IPp5lKdw1XnrQfSe+abo2eL5Lwso437Y4s3w37+HaY3d76hR5qly+Ys+Ww0CQQDj\n" + + "eOoX89d/xhRqGXKjCx8ImE/dPmsI8O27cwtKrDYJ6t0v/xryVIdvOYcRBvKnqEog\n" + + "OH7T1kI+LnWKUTJ2ehJ7AkEA2FVloPVqCehXcc7ez3TDpU9w1B0JXklcV5HddYsR\n" + + "qp9RukN/VK4szKE7F1yoarIUtfE9Lr9082Jwyp3ML11xwwJBAKsZ+Hur3x0tUY29\n" + + "No2Nf/pnFyvEF57SGwA0uPmiL8Ol9lpz+UDudDElhIM6Rqv12kwCMuQE9i7vo1o3\n" + + "WU3k5KECQEqhg1L49yD935TqiiFFpe0Ur9btQXsekdXAA4d2d5zGI7q/aGD9SYU6\n" + + "phkUJSHR16VA2RuUfzMrpb+wmm1IrmMCQFtLoKRTA5kokFb+E3Gplu29tJvCUpfw\n" + + "gBFRS+wmkvtiaU/tiyDcVgDO+An5DwedxxdVzqiEnjWHoKY3axDQ8OU="; + + private static final char PASSPHRASE[] = "passphrase".toCharArray(); /* * Is the server ready to serve? */ - volatile static boolean serverReady = false; + private static volatile CountDownLatch sync = new CountDownLatch(1); /* * Turn on SSL debugging? */ - static boolean debug = false; + private static final boolean DEBUG = false; /* * Define the server side of the test. @@ -144,29 +126,30 @@ public class MD2InTrustAnchor { * If the server prematurely exits, serverReady will be set to true * to avoid infinite hangs. */ - void doServerSide() throws Exception { - SSLContext context = generateSSLContext(trustedCertStr, targetCertStr, - targetPrivateKey); + private void doServerSide() throws Exception { + SSLContext context = generateSSLContext(TRUSTED_CERT_STR, TARGET_CERT_STR, + TARGET_PRIV_KEY_STR); SSLServerSocketFactory sslssf = context.getServerSocketFactory(); - SSLServerSocket sslServerSocket = - (SSLServerSocket)sslssf.createServerSocket(serverPort); - sslServerSocket.setNeedClientAuth(true); - serverPort = sslServerSocket.getLocalPort(); - - /* - * Signal Client, we're ready for his connect. - */ - serverReady = true; - - SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept(); - InputStream sslIS = sslSocket.getInputStream(); - OutputStream sslOS = sslSocket.getOutputStream(); - - sslIS.read(); - sslOS.write('A'); - sslOS.flush(); - - sslSocket.close(); + try (SSLServerSocket sslServerSocket + = (SSLServerSocket) sslssf.createServerSocket(serverPort)) { + sslServerSocket.setNeedClientAuth(true); + serverPort = sslServerSocket.getLocalPort(); + /* + * Signal Client, we're ready for his connect. + */ + System.out.println("Signal server ready"); + sync.countDown(); + + System.out.println("Waiting for client connection"); + try (SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept()) { + InputStream sslIS = sslSocket.getInputStream(); + OutputStream sslOS = sslSocket.getOutputStream(); + + sslIS.read(); + sslOS.write('A'); + sslOS.flush(); + } + } } /* @@ -175,33 +158,31 @@ public class MD2InTrustAnchor { * If the server prematurely exits, serverReady will be set to true * to avoid infinite hangs. */ - void doClientSide() throws Exception { + private void doClientSide() throws Exception { /* * Wait for server to get started. */ - while (!serverReady) { - Thread.sleep(50); - } + System.out.println("Waiting for server ready"); + sync.await(); - SSLContext context = generateSSLContext(trustedCertStr, targetCertStr, - targetPrivateKey); + SSLContext context = generateSSLContext(TRUSTED_CERT_STR, TARGET_CERT_STR, + TARGET_PRIV_KEY_STR); SSLSocketFactory sslsf = context.getSocketFactory(); - SSLSocket sslSocket = - (SSLSocket)sslsf.createSocket("localhost", serverPort); + System.out.println("Connect to server on port: " + serverPort); + try (SSLSocket sslSocket + = (SSLSocket) sslsf.createSocket("localhost", serverPort)) { + // enable the specified TLS protocol + sslSocket.setEnabledProtocols(new String[]{tlsProtocol}); - // enable the specified TLS protocol - sslSocket.setEnabledProtocols(new String[] {tlsProtocol}); + InputStream sslIS = sslSocket.getInputStream(); + OutputStream sslOS = sslSocket.getOutputStream(); - InputStream sslIS = sslSocket.getInputStream(); - OutputStream sslOS = sslSocket.getOutputStream(); - - sslOS.write('B'); - sslOS.flush(); - sslIS.read(); - - sslSocket.close(); + sslOS.write('B'); + sslOS.flush(); + sslIS.read(); + } } /* @@ -240,10 +221,10 @@ public class MD2InTrustAnchor { if (keyCertStr != null) { // generate the private key. PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec( - Base64.getMimeDecoder().decode(keySpecStr)); + Base64.getMimeDecoder().decode(keySpecStr)); KeyFactory kf = KeyFactory.getInstance("RSA"); - RSAPrivateKey priKey = - (RSAPrivateKey)kf.generatePrivate(priKeySpec); + RSAPrivateKey priKey + = (RSAPrivateKey) kf.generatePrivate(priKeySpec); // generate certificate chain is = new ByteArrayInputStream(keyCertStr.getBytes()); @@ -257,7 +238,7 @@ public class MD2InTrustAnchor { chain[0] = keyCert; // import the key entry. - ks.setKeyEntry("Whatever", priKey, passphrase, chain); + ks.setKeyEntry("Whatever", priKey, PASSPHRASE, chain); } // create SSL context @@ -267,7 +248,7 @@ public class MD2InTrustAnchor { SSLContext ctx = SSLContext.getInstance(tlsProtocol); if (keyCertStr != null && !keyCertStr.isEmpty()) { KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509"); - kmf.init(ks, passphrase); + kmf.init(ks, PASSPHRASE); ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); ks = null; @@ -278,12 +259,10 @@ public class MD2InTrustAnchor { return ctx; } - // use any free port by default - volatile int serverPort = 0; + private volatile int serverPort = 0; - volatile Exception serverException = null; - volatile Exception clientException = null; + private volatile Exception serverException = null; public static void main(String[] args) throws Exception { // MD5 is used in this test case, don't disable MD5 algorithm. @@ -292,140 +271,61 @@ public class MD2InTrustAnchor { Security.setProperty("jdk.tls.disabledAlgorithms", "SSLv3, RC4, DH keySize < 768"); - if (debug) + if (DEBUG) { System.setProperty("javax.net.debug", "all"); + } /* * Get the customized arguments. */ parseArguments(args); - /* * Start the tests. */ - new MD2InTrustAnchor(); + new MD2InTrustAnchor().runTest(); } - Thread clientThread = null; - Thread serverThread = null; + private Thread serverThread = null; /* - * Primary constructor, used to drive remainder of the test. + * Used to drive remainder of the test. * * Fork off the other side, then do your work. */ - MD2InTrustAnchor() throws Exception { - try { - if (separateServerThread) { - startServer(true); - startClient(false); - } else { - startClient(true); - startServer(false); - } - } catch (Exception e) { - // swallow for now. Show later - } + public void runTest() throws Exception { + startServerThread(); + doClientSide(); /* * Wait for other side to close down. */ - if (separateServerThread) { - serverThread.join(); - } else { - clientThread.join(); - } - - /* - * When we get here, the test is pretty much over. - * Which side threw the error? - */ - Exception local; - Exception remote; - String whichRemote; - - if (separateServerThread) { - remote = serverException; - local = clientException; - whichRemote = "server"; - } else { - remote = clientException; - local = serverException; - whichRemote = "client"; - } + serverThread.join(); - /* - * If both failed, return the curthread's exception, but also - * print the remote side Exception - */ - if ((local != null) && (remote != null)) { - System.out.println(whichRemote + " also threw:"); - remote.printStackTrace(); - System.out.println(); - throw local; - } - - if (remote != null) { - throw remote; - } - - if (local != null) { - throw local; + if (serverException != null) { + throw serverException; } } - void startServer(boolean newThread) throws Exception { - if (newThread) { - serverThread = new Thread() { - public void run() { - try { - doServerSide(); - } catch (Exception e) { - /* - * Our server thread just died. - * - * Release the client, if not active already... - */ - System.err.println("Server died..."); - serverReady = true; - serverException = e; - } + private void startServerThread() { + serverThread = new Thread() { + @Override + public void run() { + try { + doServerSide(); + } catch (Exception e) { + /* + * Our server thread just died. + * + * Release the client, if not active already... + */ + System.err.println("Server died..."); + e.printStackTrace(System.out); + serverException = e; + sync.countDown(); } - }; - serverThread.start(); - } else { - try { - doServerSide(); - } catch (Exception e) { - serverException = e; - } finally { - serverReady = true; } - } - } + }; - void startClient(boolean newThread) throws Exception { - if (newThread) { - clientThread = new Thread() { - public void run() { - try { - doClientSide(); - } catch (Exception e) { - /* - * Our client thread just died. - */ - System.err.println("Client died..."); - clientException = e; - } - } - }; - clientThread.start(); - } else { - try { - doClientSide(); - } catch (Exception e) { - clientException = e; - } - } + serverThread.start(); } } diff --git a/jdk/test/tools/jimage/JImageTest.java b/jdk/test/tools/jimage/JImageTest.java index be1e784c07031ef8809ce8762dadf3eee7736324..fa2c08b08ddc0cc8ec60f86f1531a09ae79fc914 100644 --- a/jdk/test/tools/jimage/JImageTest.java +++ b/jdk/test/tools/jimage/JImageTest.java @@ -110,54 +110,5 @@ public class JImageTest { .dir(helper.createNewExtractedDir("modules")) .image(image.resolve("lib").resolve("modules")) .extract().assertSuccess(); - - Path recreatedImage = JImageGenerator.getJImageTask() - .dir(extractedDir) - .image(helper.createNewRecreatedDir(extractedDir.getFileName().toString())) - .recreate().assertSuccess(); - JImageValidator.validate(recreatedImage, bootClasses, Collections.emptyList()); - - // Check replacing the boot image by recreated one - Path destFile = image.resolve("lib").resolve("modules"); - Files.copy(recreatedImage, destFile, REPLACE_EXISTING); - JImageValidator validator = new JImageValidator(module, Collections.emptyList(), - image.toFile(), Collections.emptyList(), Collections.emptyList()); - validator.validate(); - - Path recreatedImage2 = JImageGenerator.getJImageTask() - .dir(extractedDir) - .option("--compress").option("2") - .image(helper.createNewRecreatedDir(extractedDir.getFileName().toString())) - .recreate().assertSuccess(); - JImageValidator.validate(recreatedImage2, bootClasses, Collections.emptyList()); - - Path recreatedImage3 = JImageGenerator.getJImageTask() - .dir(extractedDir) - .option("--strip-debug") - .image(helper.createNewRecreatedDir(extractedDir.getFileName().toString())) - .recreate().assertSuccess(); - JImageValidator.validate(recreatedImage3, bootClasses, Collections.emptyList()); - - Path recreatedImage4 = JImageGenerator.getJImageTask() - .dir(extractedDir) - .option("--exclude-resources") - .option("*.jcov, */META-INF/*") - .image(helper.createNewRecreatedDir(extractedDir.getFileName().toString())) - .recreate().assertSuccess(); - List unexpectedPaths = new ArrayList<>(); - unexpectedPaths.add(".jcov"); - unexpectedPaths.add("/META-INF/"); - JImageValidator.validate(recreatedImage4, bootClasses, unexpectedPaths); - - Path recreatedImage5 = JImageGenerator.getJImageTask() - .dir(extractedDir) - .option("--compress") - .option("2") - .option("--strip-debug") - .option("--exclude-resources") - .option("*.jcov, */META-INF/*") - .image(helper.createNewRecreatedDir(extractedDir.getFileName().toString())) - .recreate().assertSuccess(); - JImageValidator.validate(recreatedImage5, bootClasses, unexpectedPaths); } } diff --git a/jdk/test/tools/jimage/JImageToolTest.java b/jdk/test/tools/jimage/JImageToolTest.java index 18f22f12fb1bc81354514279be63a119a676f63f..48195c4c1daf5b95d2eab69dda471b13d3c2f8e3 100644 --- a/jdk/test/tools/jimage/JImageToolTest.java +++ b/jdk/test/tools/jimage/JImageToolTest.java @@ -63,11 +63,7 @@ public class JImageToolTest { String jimage = jimagePath.toAbsolutePath().toString(); String bootimage = modulesimagePath.toAbsolutePath().toString(); String extractDir = Paths.get(".", "extract").toAbsolutePath().toString(); - String recreateImage = Paths.get(".", "recreate").toAbsolutePath().toString(); - String relativeRecreateImage = Paths.get(".", "recreate2").toString(); jimage("extract", "--dir", extractDir, bootimage); - jimage("recreate", "--dir", extractDir, recreateImage); - jimage("recreate", "--dir", extractDir, relativeRecreateImage); System.out.println("Test successful"); } else { System.out.println("Test skipped, not an images build"); diff --git a/jdk/test/tools/jlink/plugins/InstalledModuleDescriptors/src/m1/p1/Main.java b/jdk/test/tools/jlink/plugins/InstalledModuleDescriptors/src/m1/p1/Main.java index 4e516970d4dfba85df036fc4deb05416a932e53c..915416c0802ae2923d41229cc0eb90d6d7344c82 100644 --- a/jdk/test/tools/jlink/plugins/InstalledModuleDescriptors/src/m1/p1/Main.java +++ b/jdk/test/tools/jlink/plugins/InstalledModuleDescriptors/src/m1/p1/Main.java @@ -29,6 +29,7 @@ import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; +import java.util.Collections; import java.util.Set; public class Main { @@ -40,7 +41,8 @@ public class Main { validate(Main.class.getModule().getDescriptor()); // read m1/module-info.class - FileSystem fs = FileSystems.newFileSystem(URI.create("jrt:/"), null); + FileSystem fs = FileSystems.newFileSystem(URI.create("jrt:/"), + Collections.emptyMap()); Path path = fs.getPath("/", "modules", "m1", "module-info.class"); validate(ModuleDescriptor.read(Files.newInputStream(path))); } diff --git a/jdk/test/tools/launcher/Arrrghs.java b/jdk/test/tools/launcher/Arrrghs.java index cb36d2dfe8a4935997ea6e273353ea2d39d05b90..9045e0104733e6fea7072bb0d6b85ab12c76d2c5 100644 --- a/jdk/test/tools/launcher/Arrrghs.java +++ b/jdk/test/tools/launcher/Arrrghs.java @@ -489,7 +489,7 @@ public class Arrrghs extends TestHelper { return; } - TestResult tr = null; + TestResult tr; // a missing class createJar("MIA", new File("some.jar"), new File("Foo"), @@ -592,7 +592,7 @@ public class Arrrghs extends TestHelper { if (!isEnglishLocale()) { // only english version return; } - TestResult tr = null; + TestResult tr; // a missing class createJar("MIA", new File("some.jar"), new File("Foo"), (String[])null); diff --git a/jdk/test/tools/launcher/DefaultLocaleTestRun.java b/jdk/test/tools/launcher/DefaultLocaleTestRun.java index c1183e78814702116c9fe16bed5e7e3ca83f050d..2d4091912e229fb3cbd26318018b4262a5e174b0 100644 --- a/jdk/test/tools/launcher/DefaultLocaleTestRun.java +++ b/jdk/test/tools/launcher/DefaultLocaleTestRun.java @@ -41,7 +41,7 @@ public class DefaultLocaleTestRun extends TestHelper { System.out.println("Test passes vacuously on non-windows"); return; } - TestResult tr = null; + TestResult tr; tr = doExec(javaCmd, "-cp", TEST_CLASSES_DIR.getAbsolutePath(), "DefaultLocaleTest", "-w", "x.out"); diff --git a/jdk/test/tools/launcher/ExecutionEnvironment.java b/jdk/test/tools/launcher/ExecutionEnvironment.java index 58acf380b0ebcee89836a310849487ea4873f62c..62903b33ecbae3d5cc5cdf58fdada3c4c9745763 100644 --- a/jdk/test/tools/launcher/ExecutionEnvironment.java +++ b/jdk/test/tools/launcher/ExecutionEnvironment.java @@ -120,15 +120,14 @@ public class ExecutionEnvironment extends TestHelper { */ @Test void testEcoFriendly() { - TestResult tr = null; - Map env = new HashMap<>(); for (String x : LD_PATH_STRINGS) { String pairs[] = x.split("="); env.put(pairs[0], pairs[1]); } - tr = doExec(env, javaCmd, "-jar", testJarFile.getAbsolutePath()); + TestResult tr = + doExec(env, javaCmd, "-jar", testJarFile.getAbsolutePath()); if (!tr.isNotZeroOutput()) { flagError(tr, "Error: No output at all. Did the test execute ?"); @@ -180,7 +179,7 @@ public class ExecutionEnvironment extends TestHelper { */ @Test void testJavaLibraryPath() { - TestResult tr = null; + TestResult tr; Map env = new HashMap<>(); @@ -240,17 +239,14 @@ public class ExecutionEnvironment extends TestHelper { */ @Test void testVmSelection() { - - TestResult tr = null; - if (haveClientVM) { - tr = doExec(javaCmd, "-client", "-version"); + TestResult tr = doExec(javaCmd, "-client", "-version"); if (!tr.matches(".*Client VM.*")) { flagError(tr, "the expected vm -client did not launch"); } } if (haveServerVM) { - tr = doExec(javaCmd, "-server", "-version"); + TestResult tr = doExec(javaCmd, "-server", "-version"); if (!tr.matches(".*Server VM.*")) { flagError(tr, "the expected vm -server did not launch"); } diff --git a/jdk/test/tools/launcher/FXLauncherTest.java b/jdk/test/tools/launcher/FXLauncherTest.java index a885cb8dbf6091708506de8d0b0516abeb6e6d1d..0ee9d981cda747fbc2adb5b2d0e3e6ccb8fe2f86 100644 --- a/jdk/test/tools/launcher/FXLauncherTest.java +++ b/jdk/test/tools/launcher/FXLauncherTest.java @@ -239,7 +239,7 @@ public class FXLauncherTest extends TestHelper { createFile(ManifestFile, createManifestContents(StdMainClass, fxMC)); createJar(FXtestJar, ManifestFile); String sTestJar = FXtestJar.getAbsolutePath(); - TestResult tr; + final TestResult tr; if (useCP) { tr = doExec(javaCmd, "-cp", sTestJar, StdMainClass, APP_PARMS[0], APP_PARMS[1]); } else { @@ -290,7 +290,7 @@ public class FXLauncherTest extends TestHelper { createFile(ManifestFile, createManifestContents(ExtMainClass, fxMC)); createJar(FXtestJar, ManifestFile); String sTestJar = FXtestJar.getAbsolutePath(); - TestResult tr; + final TestResult tr; if (useCP) { tr = doExec(javaCmd, "-cp", sTestJar, ExtMainClass, APP_PARMS[0], APP_PARMS[1]); } else { @@ -359,7 +359,7 @@ public class FXLauncherTest extends TestHelper { createFile(ManifestFile, createManifestContents(NonFXMainClass, null)); createJar(FXtestJar, ManifestFile); String sTestJar = FXtestJar.getAbsolutePath(); - TestResult tr; + final TestResult tr; if (useCP) { tr = doExec(javaCmd, "-verbose:class", "-cp", sTestJar, NonFXMainClass, APP_PARMS[0], APP_PARMS[1]); diff --git a/jdk/test/tools/launcher/I18NTest.java b/jdk/test/tools/launcher/I18NTest.java index 3af5d593afc29fd27574d1ac50412407e4659ebb..aa1ce24e798c831229f93988611468517761d5ec 100644 --- a/jdk/test/tools/launcher/I18NTest.java +++ b/jdk/test/tools/launcher/I18NTest.java @@ -60,7 +60,7 @@ public class I18NTest extends TestHelper { // compile the generate code using the javac compiler vs. the api, to // as a bonus point to see if the argument is passed correctly - TestResult tr = null; + TestResult tr; tr = doExec(javacCmd, fileName + JAVA_FILE_EXT); if (!tr.isOK()) { System.out.println(tr); diff --git a/jdk/test/tools/launcher/MiscTests.java b/jdk/test/tools/launcher/MiscTests.java index 3769d117894f877b3617fa62d86b46fb1fd6937c..7b82abc4f4867228ee825c0b056f8c0ff25944d0 100644 --- a/jdk/test/tools/launcher/MiscTests.java +++ b/jdk/test/tools/launcher/MiscTests.java @@ -23,7 +23,7 @@ /* * @test - * @bug 6856415 8154212 + * @bug 6856415 8154212 8154470 * @summary Miscellaneous tests, Exceptions * @compile -XDignore.symbol.file MiscTests.java * @run main MiscTests @@ -95,30 +95,34 @@ public class MiscTests extends TestHelper { TestResult tr = doExec(javaCmd, "-Djava.security.manager", "-jar", testJar.getName(), "foo.bak"); - for (String s : tr.testOutput) { - System.out.println(s); - } if (!tr.contains("java.security.AccessControlException:" + " access denied (\"java.lang.RuntimePermission\"" + " \"accessClassInPackage.sun.security.pkcs11\")")) { - System.out.println(tr.status); + System.out.println(tr); } } - static void testJLDEnvWithTool() { - final Map envMap = new HashMap<>(); - envMap.put("_JAVA_LAUNCHER_DEBUG", "true"); - TestResult tr = doExec(envMap, javacCmd, "-version"); - tr.checkPositive(); - if (!tr.isOK()) { - System.out.println(tr); + static void testJLDEnv() { + final Map envToSet = new HashMap<>(); + envToSet.put("_JAVA_LAUNCHER_DEBUG", "true"); + for (String cmd : new String[] { javaCmd, javacCmd }) { + TestResult tr = doExec(envToSet, cmd, "-version"); + tr.checkPositive(); + String javargs = cmd.equals(javacCmd) ? "on" : "off"; + String progname = cmd.equals(javacCmd) ? "javac" : "java"; + if (!tr.isOK() + || !tr.matches("\\s*debug:on$") + || !tr.matches("\\s*javargs:" + javargs + "$") + || !tr.matches("\\s*program name:" + progname + "$")) { + System.out.println(tr); + } } } public static void main(String... args) throws IOException { testWithClassPathSetViaProperty(); test6856415(); - testJLDEnvWithTool(); + testJLDEnv(); if (testExitValue != 0) { throw new Error(testExitValue + " tests failed"); } diff --git a/jdk/test/tools/launcher/Settings.java b/jdk/test/tools/launcher/Settings.java index 8d45c8288b63e3acb23183cbee6d9782aeec1942..bd8f238108af4bffbf4b7cfdaa9a83134858de66 100644 --- a/jdk/test/tools/launcher/Settings.java +++ b/jdk/test/tools/launcher/Settings.java @@ -55,9 +55,9 @@ public class Settings extends TestHelper { } } - static void checkNoContains(TestResult tr, String str) { - if (tr.contains(str)) { - System.out.println(tr.status); + static void checkNotContains(TestResult tr, String str) { + if (!tr.notContains(str)) { + System.out.println(tr); throw new RuntimeException(str + " found"); } } @@ -77,84 +77,77 @@ public class Settings extends TestHelper { if (getArch().equals("ppc64") || getArch().equals("ppc64le")) { stackSize = "800"; } - TestResult tr = null; + TestResult tr; tr = doExec(javaCmd, "-Xms64m", "-Xmx512m", "-Xss" + stackSize + "k", "-XshowSettings", "-jar", testJar.getAbsolutePath()); containsAllOptions(tr); if (!tr.isOK()) { - System.out.println(tr.status); + System.out.println(tr); throw new RuntimeException("test fails"); } tr = doExec(javaCmd, "-Xms65536k", "-Xmx712m", "-Xss" + stackSize + "000", "-XshowSettings", "-jar", testJar.getAbsolutePath()); containsAllOptions(tr); if (!tr.isOK()) { - System.out.println(tr.status); + System.out.println(tr); throw new RuntimeException("test fails"); } } static void runTestOptionAll() throws IOException { init(); - TestResult tr = null; - tr = doExec(javaCmd, "-XshowSettings:all"); + TestResult tr = doExec(javaCmd, "-XshowSettings:all"); containsAllOptions(tr); } static void runTestOptionVM() throws IOException { - TestResult tr = null; - tr = doExec(javaCmd, "-XshowSettings:vm"); + TestResult tr = doExec(javaCmd, "-XshowSettings:vm"); checkContains(tr, VM_SETTINGS); - checkNoContains(tr, PROP_SETTINGS); - checkNoContains(tr, LOCALE_SETTINGS); + checkNotContains(tr, PROP_SETTINGS); + checkNotContains(tr, LOCALE_SETTINGS); } static void runTestOptionProperty() throws IOException { - TestResult tr = null; - tr = doExec(javaCmd, "-XshowSettings:properties"); - checkNoContains(tr, VM_SETTINGS); + TestResult tr = doExec(javaCmd, "-XshowSettings:properties"); + checkNotContains(tr, VM_SETTINGS); checkContains(tr, PROP_SETTINGS); - checkNoContains(tr, LOCALE_SETTINGS); + checkNotContains(tr, LOCALE_SETTINGS); } static void runTestOptionLocale() throws IOException { - TestResult tr = null; - tr = doExec(javaCmd, "-XshowSettings:locale"); - checkNoContains(tr, VM_SETTINGS); - checkNoContains(tr, PROP_SETTINGS); + TestResult tr = doExec(javaCmd, "-XshowSettings:locale"); + checkNotContains(tr, VM_SETTINGS); + checkNotContains(tr, PROP_SETTINGS); checkContains(tr, LOCALE_SETTINGS); } static void runTestBadOptions() throws IOException { - TestResult tr = null; - tr = doExec(javaCmd, "-XshowSettingsBadOption"); - checkNoContains(tr, VM_SETTINGS); - checkNoContains(tr, PROP_SETTINGS); - checkNoContains(tr, LOCALE_SETTINGS); + TestResult tr = doExec(javaCmd, "-XshowSettingsBadOption"); + checkNotContains(tr, VM_SETTINGS); + checkNotContains(tr, PROP_SETTINGS); + checkNotContains(tr, LOCALE_SETTINGS); checkContains(tr, "Unrecognized option: -XshowSettingsBadOption"); } static void runTest7123582() throws IOException { - TestResult tr = null; - tr = doExec(javaCmd, "-XshowSettings", "-version"); + TestResult tr = doExec(javaCmd, "-XshowSettings", "-version"); if (!tr.isOK()) { - System.out.println(tr.status); + System.out.println(tr); throw new RuntimeException("test fails"); } containsAllOptions(tr); } - public static void main(String... args) { - try { - runTestOptionAll(); - runTestOptionDefault(); - runTestOptionVM(); - runTestOptionProperty(); - runTestOptionLocale(); - runTestBadOptions(); - runTest7123582(); - } catch (IOException ioe) { - throw new RuntimeException(ioe); + public static void main(String... args) throws IOException { + runTestOptionAll(); + runTestOptionDefault(); + runTestOptionVM(); + runTestOptionProperty(); + runTestOptionLocale(); + runTestBadOptions(); + runTest7123582(); + if (testExitValue != 0) { + throw new Error(testExitValue + " tests failed"); } } } diff --git a/jdk/test/tools/launcher/TestHelper.java b/jdk/test/tools/launcher/TestHelper.java index 402102b2cd5d93467e3b9db12d743cec717b17d7..6724daf23966fc77f1457791c868431407bf48a7 100644 --- a/jdk/test/tools/launcher/TestHelper.java +++ b/jdk/test/tools/launcher/TestHelper.java @@ -603,23 +603,23 @@ public class TestHelper { return true; } - boolean matches(String stringToMatch) { + boolean matches(String regexToMatch) { for (String x : testOutput) { - if (x.matches(stringToMatch)) { + if (x.matches(regexToMatch)) { return true; } } - appendError("string <" + stringToMatch + "> not found"); + appendError("regex <" + regexToMatch + "> not matched"); return false; } - boolean notMatches(String stringToMatch) { + boolean notMatches(String regexToMatch) { for (String x : testOutput) { - if (!x.matches(stringToMatch)) { + if (!x.matches(regexToMatch)) { return true; } } - appendError("string <" + stringToMatch + "> found"); + appendError("regex <" + regexToMatch + "> matched"); return false; } } diff --git a/jdk/test/tools/launcher/TestSpecialArgs.java b/jdk/test/tools/launcher/TestSpecialArgs.java index 307a4e06fb449fbfcfa49ebd1966367b8dbd0334..0cb75908b8f5aa02d56025a1b0b29c0c31da4c45 100644 --- a/jdk/test/tools/launcher/TestSpecialArgs.java +++ b/jdk/test/tools/launcher/TestSpecialArgs.java @@ -241,7 +241,7 @@ public class TestSpecialArgs extends TestHelper { @Test void testNMArgumentProcessing() throws FileNotFoundException { - TestResult tr = null; + TestResult tr; // the direct invokers of the VM String options[] = { "-version", "-fullversion", "-help", "-?", "-X" diff --git a/jdk/test/tools/launcher/TooSmallStackSize.java b/jdk/test/tools/launcher/TooSmallStackSize.java index dac1c7f0325e59273ab55fd04d5edcb2ef66e091..7cc02ab56df3116179f4761203a4a3dd3f7e0e3d 100644 --- a/jdk/test/tools/launcher/TooSmallStackSize.java +++ b/jdk/test/tools/launcher/TooSmallStackSize.java @@ -85,11 +85,10 @@ public class TooSmallStackSize extends TestHelper { */ static String checkStack(String stackSize) { String min_stack_allowed; - TestResult tr; if (verbose) System.out.println("*** Testing " + stackSize); - tr = doExec(javaCmd, "-Xss" + stackSize, "-version"); + TestResult tr = doExec(javaCmd, "-Xss" + stackSize, "-version"); if (verbose) printTestOutput(tr); @@ -114,11 +113,9 @@ public class TooSmallStackSize extends TestHelper { * Run the JVM with the minimum allowed stack size. This should always succeed. */ static void checkMinStackAllowed(String stackSize) { - TestResult tr = null; - if (verbose) System.out.println("*** Testing " + stackSize); - tr = doExec(javaCmd, "-Xss" + stackSize, "-version"); + TestResult tr = doExec(javaCmd, "-Xss" + stackSize, "-version"); if (verbose) printTestOutput(tr); diff --git a/jdk/test/tools/launcher/ToolsOpts.java b/jdk/test/tools/launcher/ToolsOpts.java index bff769a54ff66aa1f465349d7b94c1ff68f5a831..a0f67d242031c7d05040821f0d2e1172ef5e06e5 100644 --- a/jdk/test/tools/launcher/ToolsOpts.java +++ b/jdk/test/tools/launcher/ToolsOpts.java @@ -149,7 +149,7 @@ public class ToolsOpts extends TestHelper { */ static void runTestOptions() throws IOException { init(); - TestResult tr = null; + TestResult tr; int jpos = -1; for (String arg[] : optionPatterns) { jpos = indexOfJoption(arg); diff --git a/jdk/test/tools/launcher/VersionCheck.java b/jdk/test/tools/launcher/VersionCheck.java index 08a18bd2a286f1fe845e2f658fc80036e11d4b93..13dac4f01be65707190b860fa4a3594dae6cb7c2 100644 --- a/jdk/test/tools/launcher/VersionCheck.java +++ b/jdk/test/tools/launcher/VersionCheck.java @@ -151,12 +151,11 @@ public class VersionCheck extends TestHelper { * of the -version output as they are inconsistent. */ static boolean testToolVersion() { - TestResult tr = null; TestHelper.testExitValue = 0; for (File f : new File(JAVA_BIN).listFiles(new ToolFilter(BLACKLIST_VERSION))) { String x = f.getAbsolutePath(); System.out.println("Testing (-version): " + x); - tr = doExec(x, "-version"); + TestResult tr = doExec(x, "-version"); tr.checkPositive(); } return TestHelper.testExitValue == 0; diff --git a/jdk/test/tools/launcher/modules/limitmods/LimitModsTest.java b/jdk/test/tools/launcher/modules/limitmods/LimitModsTest.java index f11aa003e008ecc459f61ff125b1a7787d1c7024..0cafaf42e66d87f9dde785d59768697659a07da2 100644 --- a/jdk/test/tools/launcher/modules/limitmods/LimitModsTest.java +++ b/jdk/test/tools/launcher/modules/limitmods/LimitModsTest.java @@ -103,10 +103,9 @@ public class LimitModsTest { public void testWithAddMods() throws Exception { int exitValue; - // java -limitmods java.base -addmods java.logging,jdk.unsupported -listmods + // java -limitmods java.base -addmods java.logging -listmods exitValue = executeTestJava("-limitmods", "java.base", - "-addmods", - "java.logging,jdk.unsupported", // TODO: add bug No. + "-addmods", "java.logging", "-listmods") .outputTo(System.out) .errorTo(System.out) diff --git a/jdk/test/tools/lib/tests/JImageGenerator.java b/jdk/test/tools/lib/tests/JImageGenerator.java index 77366aafb1301d2abe36e5b234a1df9105f3864c..c75164b69cc3e48b5951ad769922b35ab6810951 100644 --- a/jdk/test/tools/lib/tests/JImageGenerator.java +++ b/jdk/test/tools/lib/tests/JImageGenerator.java @@ -553,10 +553,6 @@ public class JImageGenerator { public Result extract() { return cmd("extract", dir); } - - public Result recreate() { - return cmd("recreate", image); - } } public static class JLinkTask { diff --git a/make/CompileJavaModules.gmk b/make/CompileJavaModules.gmk index c4275f863e3fadb2661dc0d88ce1ae088d5e05bc..4ce9cca25bf6e02cc486790254250ce17079ad20 100644 --- a/make/CompileJavaModules.gmk +++ b/make/CompileJavaModules.gmk @@ -98,7 +98,8 @@ java.datatransfer_COPY := flavormap.properties ################################################################################ -java.desktop_ADD_JAVAC_FLAGS := -Xdoclint:all/protected,-reference '-Xdoclint/package:java.*,javax.*' +java.desktop_ADD_JAVAC_FLAGS := -Xdoclint:all/protected,-reference \ + '-Xdoclint/package:java.*,javax.*' -Xlint:-deprecation java.desktop_COPY := .gif .png .wav .txt .xml .css .pf java.desktop_CLEAN := iio-plugin.properties cursors.properties diff --git a/make/InitSupport.gmk b/make/InitSupport.gmk index 493591ebbecb47c7f1666c887c4a16228925d010..cee30522d33a130edec6ee3c87136137d15bcef6 100644 --- a/make/InitSupport.gmk +++ b/make/InitSupport.gmk @@ -331,7 +331,7 @@ else # $(HAS_SPEC)=true BUILD_LOG := $(OUTPUT_ROOT)/build.log BUILD_TRACE_LOG := $(OUTPUT_ROOT)/build-trace-time.log - BUILD_LOG_PIPE := > >($(TEE) -a $(BUILD_LOG)) 2> >($(TEE) -a $(BUILD_LOG) >&2) + BUILD_LOG_PIPE := > >($(TEE) -a $(BUILD_LOG)) 2> >($(TEE) -a $(BUILD_LOG) >&2) && wait # Sanity check the spec file, so it matches this source code define CheckSpecSanity diff --git a/make/Jprt.gmk b/make/Jprt.gmk index 6b778293d2ad7b80a0e2732af4284957a6d5815c..e7eba24bd318196665fb710fc82667680c22bbf4 100644 --- a/make/Jprt.gmk +++ b/make/Jprt.gmk @@ -108,7 +108,9 @@ SRC_JDK_MACOSX_BUNDLE_DIR := $(JDK_MACOSX_BUNDLE_DIR) SRC_JRE_MACOSX_BUNDLE_DIR := $(JRE_MACOSX_BUNDLE_DIR) # Bundle up the images -bundles: all +JPRT_TARGET ?= all +ifeq ($(JPRT_TARGET), all) + bundles: $(JPRT_TARGET) @$(call TargetEnter) $(MKDIR) -p $(BUILD_OUTPUT)/bundles $(CD) $(SRC_JDK_IMAGE_DIR) && $(ZIP) -y -q -r \ @@ -128,9 +130,24 @@ bundles: all $(BUILD_OUTPUT)/bundles/$(SYMBOLS_IMAGE_SUBDIR).zip . ; \ fi @$(call TargetExit) +else + # Just fake the bundles + bundles: $(JPRT_TARGET) + @$(call TargetEnter) + $(MKDIR) -p $(BUILD_OUTPUT)/bundles + $(CD) $(TOPDIR) && $(ZIP) -y -q -r \ + $(BUILD_OUTPUT)/bundles/$(JDK_IMAGE_SUBDIR).zip README + $(CD) $(TOPDIR) && $(ZIP) -y -q -r \ + $(BUILD_OUTPUT)/bundles/$(JRE_IMAGE_SUBDIR).zip README + $(CD) $(TOPDIR) && $(ZIP) -y -q -r \ + $(BUILD_OUTPUT)/bundles/$(TEST_IMAGE_SUBDIR).zip README + $(CD) $(TOPDIR) && $(ZIP) -y -q -r \ + $(BUILD_OUTPUT)/bundles/modules.zip README + @$(call TargetExit) +endif # Copy images to one unified location regardless of platform etc. -final-images: all +final-images: $(JPRT_TARGET) @$(call TargetEnter) $(RM) -r $(BUILD_OUTPUT)/final-images $(MKDIR) -p $(BUILD_OUTPUT)/final-images/$(JDK_IMAGE_SUBDIR) diff --git a/make/Main.gmk b/make/Main.gmk index 2bb6bab68bff272d752dc81ac7050315f4e908f4..a693465ec4dfd5b46264033d2f160dd1fa72926e 100644 --- a/make/Main.gmk +++ b/make/Main.gmk @@ -229,10 +229,17 @@ ALL_TARGETS += $(LAUNCHER_TARGETS) ifeq ($(BUILD_HOTSPOT),true) hotspot: - +($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f HotspotWrapper.gmk) + ifeq ($(USE_NEW_HOTSPOT_BUILD), true) + +($(CD) $(HOTSPOT_TOPDIR)/makefiles && $(MAKE) $(MAKE_ARGS) -f BuildHotspot.gmk) + else + +($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f HotspotWrapper.gmk) + endif endif -ALL_TARGETS += hotspot +hotspot-ide-project: + +($(CD) $(HOTSPOT_TOPDIR)/makefiles && $(MAKE) $(MAKE_ARGS) -f ide/CreateVSProject.gmk) + +ALL_TARGETS += hotspot hotspot-ide-project ################################################################################ # Build demos and samples targets @@ -484,6 +491,8 @@ else $(JAVA_TARGETS): interim-langtools + hotspot-ide-project: hotspot exploded-image + import-hotspot: hotspot generate-exported-symbols: java.base-libs jdk.jdwp.agent-libs diff --git a/make/common/MakeBase.gmk b/make/common/MakeBase.gmk index d97169007e22beac92bfd4817abf248b3f376a05..f159b8fca63c66e8862ebc89ae1ba3eba200e2a6 100644 --- a/make/common/MakeBase.gmk +++ b/make/common/MakeBase.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -706,10 +706,10 @@ endif ExecuteWithLog = \ $(call LogCmdlines, Exececuting: [$(strip $2)]) \ $(call WriteFile, $2, $(strip $1).cmdline) \ - ( $(strip $2) > >($(TEE) $(strip $1).log) 2> >($(TEE) $(strip $1).log >&2) || \ + ( ( $(strip $2) > >($(TEE) $(strip $1).log) 2> >($(TEE) $(strip $1).log >&2) || \ ( exitcode=$(DOLLAR)? && \ $(CP) $(strip $1).log $(MAKESUPPORT_OUTPUTDIR)/failure-logs/$(subst /,_,$(patsubst $(BUILD_OUTPUT)/%,%,$(strip $1))).log && \ - exit $(DOLLAR)exitcode ) ) + exit $(DOLLAR)exitcode ) ) && wait ) ################################################################################ # Find lib dir for module @@ -731,6 +731,16 @@ endif PathList = \ "$(subst $(SPACE),$(PATH_SEP),$(strip $(subst $(DQUOTE),,$1)))" +################################################################################ +# Check if a specified hotspot variant is being built, or at least one of a +# list of variants. Will return 'true' or 'false'. +# $1 - the variant to test for +check-jvm-variant = \ + $(strip \ + $(if $(filter-out $(VALID_JVM_VARIANTS), $1), \ + $(error Internal error: Invalid variant tested: $1)) \ + $(if $(filter $1, $(JVM_VARIANTS)), true, false)) + ################################################################################ # Hook to include the corresponding custom file, if present. diff --git a/make/common/NativeCompilation.gmk b/make/common/NativeCompilation.gmk index d6a003a8c8ee310c780aa1aa3cb8805a80f65a74..d595e044013cd45368992042771ff1bbef994be7 100644 --- a/make/common/NativeCompilation.gmk +++ b/make/common/NativeCompilation.gmk @@ -197,14 +197,51 @@ define add_native_source $1_$2_THIS_FILE = -DTHIS_FILE='"$$( Disable the given warnings for the specified toolchain # DISABLED_WARNINGS_C_ Disable the given warnings for the specified toolchain # when compiling C code @@ -331,7 +372,11 @@ endef # toolchain when compiling C++ code # STRIP_SYMBOLS Set to true to strip the final binary if the toolchain allows for it # DEBUG_SYMBOLS Set to false to disable generation of debug symbols +# CFLAGS_DEBUG_SYMBOLS Overrides the default cflags for enabling debug symbols +# CXXFLAGS_DEBUG_SYMBOLS Overrides the default cxxflags for enabling debug symbols # STRIPFLAGS Optionally change the flags given to the strip command +# PRECOMPILED_HEADER Header file to use as precompiled header +# PRECOMPILED_HEADER_EXCLUDE List of source files that should not use PCH SetupNativeCompilation = $(NamedParamsMacroTemplate) define SetupNativeCompilationBody @@ -556,8 +601,10 @@ define SetupNativeCompilationBody endif ifeq ($(COMPILE_WITH_DEBUG_SYMBOLS), true) - $1_EXTRA_CFLAGS += $(CFLAGS_DEBUG_SYMBOLS) - $1_EXTRA_CXXFLAGS += $(CXXFLAGS_DEBUG_SYMBOLS) + $$(call SetIfEmpty, $1_CFLAGS_DEBUG_SYMBOLS, $(CFLAGS_DEBUG_SYMBOLS)) + $$(call SetIfEmpty, $1_CXXFLAGS_DEBUG_SYMBOLS, $(CXXFLAGS_DEBUG_SYMBOLS)) + $1_EXTRA_CFLAGS += $$($1_CFLAGS_DEBUG_SYMBOLS) + $1_EXTRA_CXXFLAGS += $$($1_CXXFLAGS_DEBUG_SYMBOLS) endif ifneq (,$$($1_REORDER)) @@ -597,17 +644,23 @@ define SetupNativeCompilationBody endif ifeq (NONE, $$($1_OPTIMIZATION)) - $1_EXTRA_CFLAGS += $(C_O_FLAG_NONE) - $1_EXTRA_CXXFLAGS += $(CXX_O_FLAG_NONE) + $1_OPT_CFLAGS := $(C_O_FLAG_NONE) + $1_OPT_CXXFLAGS := $(CXX_O_FLAG_NONE) else ifeq (LOW, $$($1_OPTIMIZATION)) - $1_EXTRA_CFLAGS += $(C_O_FLAG_NORM) - $1_EXTRA_CXXFLAGS += $(CXX_O_FLAG_NORM) + $1_OPT_CFLAGS := $(C_O_FLAG_NORM) + $1_OPT_CXXFLAGS := $(CXX_O_FLAG_NORM) else ifeq (HIGH, $$($1_OPTIMIZATION)) - $1_EXTRA_CFLAGS += $(C_O_FLAG_HI) - $1_EXTRA_CXXFLAGS += $(CXX_O_FLAG_HI) + $1_OPT_CFLAGS := $(C_O_FLAG_HI) + $1_OPT_CXXFLAGS := $(CXX_O_FLAG_HI) else ifeq (HIGHEST, $$($1_OPTIMIZATION)) - $1_EXTRA_CFLAGS += $(C_O_FLAG_HIGHEST) - $1_EXTRA_CXXFLAGS += $(CXX_O_FLAG_HIGHEST) + $1_OPT_CFLAGS := $(C_O_FLAG_HIGHEST) + $1_OPT_CXXFLAGS := $(CXX_O_FLAG_HIGHEST) + else ifeq (HIGHEST_JVM, $$($1_OPTIMIZATION)) + $1_OPT_CFLAGS := $(C_O_FLAG_HIGHEST_JVM) + $1_OPT_CXXFLAGS := $(CXX_O_FLAG_HIGHEST_JVM) + else ifeq (SIZE, $$($1_OPTIMIZATION)) + $1_OPT_CFLAGS := $(C_O_FLAG_SIZE) + $1_OPT_CXXFLAGS := $(CXX_O_FLAG_SIZE) else ifneq (, $$($1_OPTIMIZATION)) $$(error Unknown value for OPTIMIZATION: $$($1_OPTIMIZATION)) endif @@ -618,11 +671,65 @@ define SetupNativeCompilationBody # lines for all object files in this setup. This includes at least all the # variables used in the call to add_native_source below. $1_COMPILE_VARDEPS := $$($1_CFLAGS) $$($1_EXTRA_CFLAGS) $$($1_SYSROOT_CFLAGS) \ - $$($1_CXXFLAGS) $$($1_EXTRA_CXXFLAGS) \ + $$($1_CXXFLAGS) $$($1_EXTRA_CXXFLAGS) $$($1_OPT_CFLAGS) $$($1_OPT_CXXFLAGS) \ $$($1_CC) $$($1_CXX) $$($1_AS) $$($1_ASFLAGS) $1_COMPILE_VARDEPS_FILE := $$(call DependOnVariable, $1_COMPILE_VARDEPS, \ $$($1_OBJECT_DIR)/$$($1_NOSUFFIX).comp.vardeps) + ifneq ($$($1_PRECOMPILED_HEADER), ) + ifeq ($(USE_PRECOMPILED_HEADER), 1) + ifeq ($(TOOLCHAIN_TYPE), microsoft) + $1_PCH_FILE := $$($1_OBJECT_DIR)/$1.pch + $1_GENERATED_PCH_SRC := $$($1_OBJECT_DIR)/$1_pch.cpp + $1_GENERATED_PCH_OBJ := $$($1_OBJECT_DIR)/$1_pch.obj + + $$(eval $$(call add_native_source,$1,$$($1_GENERATED_PCH_SRC), \ + $$($1_OBJECT_DIR),,, \ + $$($1_CXXFLAGS) $$($1_EXTRA_CXXFLAGS) $$($1_SYSROOT_CFLAGS) \ + -Fp$$($1_PCH_FILE) -Yc$$(notdir $$($1_PRECOMPILED_HEADER)), \ + $$($1_CXX),,no_this_file)) + + $1_USE_PCH_FLAGS := \ + -Fp$$($1_PCH_FILE) -Yu$$(notdir $$($1_PRECOMPILED_HEADER)) + + $$($1_ALL_OBJS): $$($1_GENERATED_PCH_OBJ) + + # Explicitly add the pch obj file first to ease comparing to old + # hotspot build. + $1_ALL_OBJS := $$($1_GENERATED_PCH_OBJ) $$($1_ALL_OBJS) + + $$($1_GENERATED_PCH_SRC): + $(ECHO) "#include \"$$(notdir $$($1_PRECOMPILED_HEADER))\"" > $$@ + + else ifneq ($(findstring $(TOOLCHAIN_TYPE), gcc clang), ) + ifeq ($(TOOLCHAIN_TYPE), gcc) + $1_PCH_FILE := $$($1_OBJECT_DIR)/precompiled/$$(notdir $$($1_PRECOMPILED_HEADER)).gch + $1_USE_PCH_FLAGS := -I$$($1_OBJECT_DIR)/precompiled + else ifeq ($(TOOLCHAIN_TYPE), clang) + $1_PCH_FILE := $$($1_OBJECT_DIR)/precompiled/$$(notdir $$($1_PRECOMPILED_HEADER)).pch + $1_USE_PCH_FLAGS := -include-pch $$($1_PCH_FILE) + endif + $1_PCH_DEP := $$($1_PCH_FILE).d + $1_PCH_DEP_TARGETS := $$($1_PCH_FILE).d.targets + + -include $$($1_PCH_DEP) + -include $$($1_PCH_DEP_TARGETS) + + $$($1_PCH_FILE): $$($1_PRECOMPILED_HEADER) $$($1_COMPILE_VARDEPS_FILE) + $$(call LogInfo, Generating precompiled header) + $$(call MakeDir, $$(@D)) + $$(call ExecuteWithLog, $$@, \ + $$($1_CC) $$($1_CFLAGS) $$($1_EXTRA_CFLAGS) $$($1_SYSROOT_CFLAGS) \ + $$($1_OPT_CFLAGS) \ + -x c++-header -c $(C_FLAG_DEPS) $$($1_PCH_DEP) $$< -o $$@) + $(SED) $(DEPENDENCY_TARGET_SED_PATTERN) $$($1_PCH_DEP) > $$($1_PCH_DEP_TARGETS) + + $$($1_ALL_OBJS): $$($1_PCH_FILE) + + endif + endif + endif + # Now call add_native_source for each source file we are going to compile. $$(foreach p,$$($1_SRCS), \ $$(eval $$(call add_native_source,$1,$$p,$$($1_OBJECT_DIR), \ diff --git a/make/jprt.properties b/make/jprt.properties index 943f15b5be59c7aefb9c36815dd863aaf5e58c8f..40a75b1140fe35a25e17cc6a94441ea757be6294 100644 --- a/make/jprt.properties +++ b/make/jprt.properties @@ -129,9 +129,15 @@ jprt.build.flavor.optimized.target=jprt_bundle jprt.build.flavor.optimizedOpen.target=jprt_bundle jprt.build.flavor.slowdebug.target=jprt_bundle -# Use these configure args to define debug level +# Use these configure args to define debug level or provide specific +# configuration details not covered by Jib profiles. jprt.slowdebug.build.configure.args= jprt.fastdebug.build.configure.args=--disable-precompiled-headers +# Don't disable precompiled headers on windows. It's simply too slow. +jprt.windows_i586.fastdebug.build.configure.args= +jprt.windows_x64.fastdebug.build.configure.args= +jprt.windows_i586.fastdebugOpen.build.configure.args= +jprt.windows_x64.fastdebugOpen.build.configure.args= jprt.product.build.configure.args= jprt.optimized.build.configure.args=--with-debug-level=optimized jprt.slowdebugOpen.build.configure.args=${jprt.slowdebug.build.configure.args} diff --git a/nashorn/.hgtags b/nashorn/.hgtags index 5d1fa7fb25067c60d20ae515f4e5e1d557a6bd2c..78e30d77611f53e4d868ff07d4918896cb3442d7 100644 --- a/nashorn/.hgtags +++ b/nashorn/.hgtags @@ -348,3 +348,4 @@ cfb3167456932b14c16a6d4cffd5fe295fbe01ff jdk-9+106 c261f8440c5578b34596e6b0419a81aec431a884 jdk-9+112 a5d1990fd32d908da8154d79116fce8013ba4d40 jdk-9+113 ba21793a0e4816283cc0ecdab5142a4959363529 jdk-9+114 +295ac208a4443d433214d0c1f32d2ea45a3a32d2 jdk-9+115 diff --git a/test/jtreg-ext/requires/VMProps.java b/test/jtreg-ext/requires/VMProps.java new file mode 100644 index 0000000000000000000000000000000000000000..ef7de8faf39b849f8273569297409a915637b550 --- /dev/null +++ b/test/jtreg-ext/requires/VMProps.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * 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 requires; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Callable; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * The Class to be invoked by jtreg prior Test Suite execution to + * collect information about VM. + * Properties set by this Class will be available in the @requires expressions. + */ +public class VMProps implements Callable> { + + /** + * Collects information about VM properties. + * This method will be invoked by jtreg. + * + * @return Map of property-value pairs. + */ + @Override + public Map call() { + Map map = new HashMap<>(); + map.put("vm.flavor", vmFlavor()); + map.put("vm.compMode", vmCompMode()); + map.put("vm.bits", vmBits()); + dump(map); + return map; + } + + /** + * @return VM type value extracted from the "java.vm.name" property. + */ + protected String vmFlavor() { + // E.g. "Java HotSpot(TM) 64-Bit Server VM" + String vmName = System.getProperty("java.vm.name"); + if (vmName == null) { + return null; + } + + Pattern startP = Pattern.compile(".* (\\S+) VM"); + Matcher m = startP.matcher(vmName); + if (m.matches()) { + return m.group(1).toLowerCase(); + } + return null; + } + + /** + * @return VM compilation mode extracted from the "java.vm.info" property. + */ + protected String vmCompMode() { + // E.g. "mixed mode" + String vmInfo = System.getProperty("java.vm.info"); + if (vmInfo == null) { + return null; + } + int k = vmInfo.toLowerCase().indexOf(" mode"); + if (k < 0) { + return null; + } + vmInfo = vmInfo.substring(0, k); + switch (vmInfo) { + case "mixed" : return "Xmixed"; + case "compiled" : return "Xcomp"; + case "interpreted" : return "Xint"; + default: return null; + } + } + + /** + * @return VM bitness, the value of the "sun.arch.data.model" property. + */ + protected String vmBits() { + return System.getProperty("sun.arch.data.model"); + } + + /** + * Dumps the map to the file if the file name is given as the property. + * This functionality could be helpful to know context in the real + * execution. + * + * @param map + */ + protected void dump(Map map) { + String dumpFileName = System.getProperty("vmprops.dump"); + if (dumpFileName == null) { + return; + } + List lines = new ArrayList<>(); + map.forEach((k,v) -> lines.add(k + ":" + v)); + try { + Files.write(Paths.get(dumpFileName), lines); + } catch (IOException e) { + throw new RuntimeException("Failed to dump properties into '" + + dumpFileName + "'", e); + } + } + + /** + * This method is for the testing purpose only. + * @param args + */ + public static void main(String args[]) { + Map map = new VMProps().call(); + map.forEach((k,v) -> System.out.println(k + ": '" + v + "'")); + } +}