diff --git a/.hgtags b/.hgtags index 722db7c026c..0ce6f1acaf9 100644 --- a/.hgtags +++ b/.hgtags @@ -454,3 +454,4 @@ e5357aa85dadacc6562175ff74714fecfb4470cf jdk-10+22 b87d7b5d5dedc1185e5929470f945b7378cdb3ad jdk-10+27 92f08900cb3c0d694e5c529a676c1c9e5909193f jdk-10+28 a6e591e12f122768f675428e1e5a838fd0e9c7ec jdk-10+29 +8fee80b92e65149f7414250fd5e34b6f35d417b4 jdk-10+30 diff --git a/make/CompileToolsHotspot.gmk b/make/CompileToolsHotspot.gmk index 87d8bd5b3fc..1ccc3e2a31b 100644 --- a/make/CompileToolsHotspot.gmk +++ b/make/CompileToolsHotspot.gmk @@ -67,6 +67,7 @@ ifeq ($(INCLUDE_GRAAL), true) $(SRC_DIR)/org.graalvm.compiler.phases.common/src \ $(SRC_DIR)/org.graalvm.compiler.serviceprovider/src \ $(SRC_DIR)/org.graalvm.compiler.virtual/src \ + $(SRC_DIR)/org.graalvm.graphio/src \ $(SRC_DIR)/org.graalvm.util/src \ $(VM_CI_SRC_DIR)/jdk.vm.ci.code/src \ $(VM_CI_SRC_DIR)/jdk.vm.ci.common/src \ @@ -125,6 +126,7 @@ ifeq ($(INCLUDE_GRAAL), true) $(SRC_DIR)/org.graalvm.compiler.nodeinfo/src \ $(SRC_DIR)/org.graalvm.compiler.options/src \ $(SRC_DIR)/org.graalvm.compiler.serviceprovider/src \ + $(SRC_DIR)/org.graalvm.graphio/src \ $(SRC_DIR)/org.graalvm.util/src \ $(VM_CI_SRC_DIR)/jdk.vm.ci.code/src \ $(VM_CI_SRC_DIR)/jdk.vm.ci.common/src \ diff --git a/make/autoconf/basics.m4 b/make/autoconf/basics.m4 index ae148e5faad..7d5d47a3cf7 100644 --- a/make/autoconf/basics.m4 +++ b/make/autoconf/basics.m4 @@ -639,6 +639,14 @@ AC_DEFUN_ONCE([BASIC_SETUP_DEVKIT], elif test -d "$DEVKIT_ROOT/$host/sys-root"; then SYSROOT="$DEVKIT_ROOT/$host/sys-root" fi + + if test "x$DEVKIT_ROOT" != x; then + DEVKIT_LIB_DIR="$DEVKIT_ROOT/lib" + if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then + DEVKIT_LIB_DIR="$DEVKIT_ROOT/lib64" + fi + AC_SUBST(DEVKIT_LIB_DIR) + fi ] ) diff --git a/make/autoconf/configure.ac b/make/autoconf/configure.ac index 65398af0a61..26946f38152 100644 --- a/make/autoconf/configure.ac +++ b/make/autoconf/configure.ac @@ -1,5 +1,5 @@ SRC# -# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -203,6 +203,9 @@ FLAGS_SETUP_COMPILER_FLAGS_MISC JDKOPT_SETUP_DEBUG_SYMBOLS JDKOPT_SETUP_CODE_COVERAGE +# AddressSanitizer +JDKOPT_SETUP_ADDRESS_SANITIZER + # Need toolchain to setup dtrace HOTSPOT_SETUP_DTRACE HOTSPOT_ENABLE_DISABLE_AOT diff --git a/make/autoconf/generated-configure.sh b/make/autoconf/generated-configure.sh index 8fff0656927..26561660e09 100644 --- a/make/autoconf/generated-configure.sh +++ b/make/autoconf/generated-configure.sh @@ -690,6 +690,7 @@ FREETYPE_LICENSE FREETYPE_BUNDLE_LIB_PATH FREETYPE_LIBS FREETYPE_CFLAGS +FONTCONFIG_CFLAGS CUPS_CFLAGS X_EXTRA_LIBS X_LIBS @@ -704,6 +705,7 @@ FIXPATH BUILD_GTEST ENABLE_CDS ENABLE_AOT +ASAN_ENABLED GCOV_ENABLED ZIP_EXTERNAL_DEBUG_SYMBOLS COPY_DEBUG_SYMBOLS @@ -958,6 +960,7 @@ CONF_NAME SPEC SDKROOT XCODEBUILD +DEVKIT_LIB_DIR JVM_VARIANT_MAIN VALID_JVM_VARIANTS JVM_VARIANTS @@ -1171,6 +1174,7 @@ with_native_debug_symbols enable_debug_symbols enable_zip_debug_info enable_native_coverage +enable_asan enable_dtrace enable_aot enable_cds @@ -1181,6 +1185,8 @@ with_msvcp_dll with_x with_cups with_cups_include +with_fontconfig +with_fontconfig_include with_freetype with_freetype_include with_freetype_lib @@ -1976,6 +1982,7 @@ Optional Features: --enable-native-coverage enable native compilation with code coverage data[disabled] + --enable-asan enable AddressSanitizer if possible [disabled] --enable-dtrace[=yes/no/auto] enable dtrace. Default is auto, where dtrace is enabled if all dependencies are present. @@ -2109,6 +2116,10 @@ Optional Packages: --with-cups specify prefix directory for the cups package (expecting the headers under PATH/include) --with-cups-include specify directory for the cups include files + --with-fontconfig specify prefix directory for the fontconfig package + (expecting the headers under PATH/include) + --with-fontconfig-include + specify directory for the fontconfig include files --with-freetype specify prefix directory for the freetype package (expecting the libraries under PATH/lib and the headers under PATH/include) @@ -4166,6 +4177,8 @@ apt_help() { PKGHANDLER_COMMAND="sudo apt-get install libasound2-dev" ;; cups) PKGHANDLER_COMMAND="sudo apt-get install libcups2-dev" ;; + fontconfig) + PKGHANDLER_COMMAND="sudo apt-get install libfontconfig1-dev" ;; freetype) PKGHANDLER_COMMAND="sudo apt-get install libfreetype6-dev" ;; ffi) @@ -4189,6 +4202,8 @@ yum_help() { PKGHANDLER_COMMAND="sudo yum install alsa-lib-devel" ;; cups) PKGHANDLER_COMMAND="sudo yum install cups-devel" ;; + fontconfig) + PKGHANDLER_COMMAND="sudo yum install fontconfig-devel" ;; freetype) PKGHANDLER_COMMAND="sudo yum install freetype-devel" ;; x11) @@ -4403,6 +4418,12 @@ VALID_JVM_VARIANTS="server client minimal core zero zeroshark custom" # +############################################################################### +# +# AddressSanitizer +# + + ################################################################################ # # Static build support. When enabled will generate static @@ -4746,6 +4767,36 @@ VALID_JVM_VARIANTS="server client minimal core zero zeroshark custom" ################################################################################ +# +# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute 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 fontconfig +################################################################################ + + ################################################################################ # Determine which libraries are needed for this configuration @@ -5115,7 +5166,7 @@ VS_SDK_PLATFORM_NAME_2013= #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1509013542 +DATE_WHEN_GENERATED=1509128484 ############################################################################### # @@ -17273,6 +17324,14 @@ $as_echo "$DEVKIT_ROOT" >&6; } SYSROOT="$DEVKIT_ROOT/$host/sys-root" fi + if test "x$DEVKIT_ROOT" != x; then + DEVKIT_LIB_DIR="$DEVKIT_ROOT/lib" + if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then + DEVKIT_LIB_DIR="$DEVKIT_ROOT/lib64" + fi + + fi + fi @@ -54169,6 +54228,49 @@ $as_echo "no" >&6; } +# AddressSanitizer + + # Check whether --enable-asan was given. +if test "${enable_asan+set}" = set; then : + enableval=$enable_asan; +fi + + ASAN_ENABLED="no" + if test "x$enable_asan" = "xyes"; then + case $TOOLCHAIN_TYPE in + gcc | clang) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if asan is enabled" >&5 +$as_echo_n "checking if asan is enabled... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + ASAN_CFLAGS="-fsanitize=address -fno-omit-frame-pointer" + ASAN_LDFLAGS="-fsanitize=address" + JVM_CFLAGS="$JVM_CFLAGS $ASAN_CFLAGS" + JVM_LDFLAGS="$JVM_LDFLAGS $ASAN_LDFLAGS" + CFLAGS_JDKLIB="$CFLAGS_JDKLIB $ASAN_CFLAGS" + CFLAGS_JDKEXE="$CFLAGS_JDKEXE $ASAN_CFLAGS" + CXXFLAGS_JDKLIB="$CXXFLAGS_JDKLIB $ASAN_CFLAGS" + CXXFLAGS_JDKEXE="$CXXFLAGS_JDKEXE $ASAN_CFLAGS" + LDFLAGS_JDKLIB="$LDFLAGS_JDKLIB $ASAN_LDFLAGS" + LDFLAGS_JDKEXE="$LDFLAGS_JDKEXE $ASAN_LDFLAGS" + ASAN_ENABLED="yes" + ;; + *) + as_fn_error $? "--enable-asan only works with toolchain type gcc or clang" "$LINENO" 5 + ;; + esac + elif test "x$enable_asan" = "xno"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if asan is enabled" >&5 +$as_echo_n "checking if asan is enabled... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + elif test "x$enable_asan" != "x"; then + as_fn_error $? "--enable-asan can only be assigned \"yes\" or \"no\"" "$LINENO" 5 + fi + + + + # Need toolchain to setup dtrace # Test for dtrace dependencies @@ -54480,6 +54582,16 @@ $as_echo "yes" >&6; } NEEDS_LIB_X11=true fi + # Check if fontconfig is needed + if test "x$OPENJDK_TARGET_OS" = xwindows || test "x$OPENJDK_TARGET_OS" = xmacosx; then + # No fontconfig support on windows or macosx + NEEDS_LIB_FONTCONFIG=false + else + # All other instances need fontconfig, even if building headless only, + # libawt still needs fontconfig headers. + NEEDS_LIB_FONTCONFIG=true + fi + # Check if cups is needed if test "x$OPENJDK_TARGET_OS" = xwindows; then # Windows have a separate print system @@ -58297,6 +58409,116 @@ done +# Check whether --with-fontconfig was given. +if test "${with_fontconfig+set}" = set; then : + withval=$with_fontconfig; +fi + + +# Check whether --with-fontconfig-include was given. +if test "${with_fontconfig_include+set}" = set; then : + withval=$with_fontconfig_include; +fi + + + if test "x$NEEDS_LIB_FONTCONFIG" = xfalse; then + if (test "x${with_fontconfig}" != x && test "x${with_fontconfig}" != xno) || \ + (test "x${with_fontconfig_include}" != x && test "x${with_fontconfig_include}" != xno); then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: fontconfig not used, so --with-fontconfig[-*] is ignored" >&5 +$as_echo "$as_me: WARNING: fontconfig not used, so --with-fontconfig[-*] is ignored" >&2;} + fi + FONTCONFIG_CFLAGS= + else + FONTCONFIG_FOUND=no + + if test "x${with_fontconfig}" = xno || test "x${with_fontconfig_include}" = xno; then + as_fn_error $? "It is not possible to disable the use of fontconfig. Remove the --without-fontconfig option." "$LINENO" 5 + fi + + if test "x${with_fontconfig}" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fontconfig headers" >&5 +$as_echo_n "checking for fontconfig headers... " >&6; } + if test -s "${with_fontconfig}/include/fontconfig/fontconfig.h"; then + FONTCONFIG_CFLAGS="-I${with_fontconfig}/include" + FONTCONFIG_FOUND=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FONTCONFIG_FOUND" >&5 +$as_echo "$FONTCONFIG_FOUND" >&6; } + else + as_fn_error $? "Can't find 'include/fontconfig/fontconfig.h' under ${with_fontconfig} given with the --with-fontconfig option." "$LINENO" 5 + fi + fi + if test "x${with_fontconfig_include}" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fontconfig headers" >&5 +$as_echo_n "checking for fontconfig headers... " >&6; } + if test -s "${with_fontconfig_include}/fontconfig/fontconfig.h"; then + FONTCONFIG_CFLAGS="-I${with_fontconfig_include}" + FONTCONFIG_FOUND=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FONTCONFIG_FOUND" >&5 +$as_echo "$FONTCONFIG_FOUND" >&6; } + else + as_fn_error $? "Can't find 'fontconfig/fontconfig.h' under ${with_fontconfig_include} given with the --with-fontconfig-include option." "$LINENO" 5 + fi + fi + if test "x$FONTCONFIG_FOUND" = xno; then + # Are the fontconfig headers installed in the default /usr/include location? + for ac_header in fontconfig/fontconfig.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "fontconfig/fontconfig.h" "ac_cv_header_fontconfig_fontconfig_h" "$ac_includes_default" +if test "x$ac_cv_header_fontconfig_fontconfig_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_FONTCONFIG_FONTCONFIG_H 1 +_ACEOF + + FONTCONFIG_FOUND=yes + FONTCONFIG_CFLAGS= + DEFAULT_FONTCONFIG=yes + +fi + +done + + fi + if test "x$FONTCONFIG_FOUND" = xno; then + + # Print a helpful message on how to acquire the necessary build dependency. + # fontconfig is the help tag: freetype, cups, alsa etc + MISSING_DEPENDENCY=fontconfig + + 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 ;; + brew) + brew_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 $? "Could not find fontconfig! $HELP_MSG " "$LINENO" 5 + fi + fi + + + + + # Check whether --with-freetype was given. if test "${with_freetype+set}" = set; then : withval=$with_freetype; @@ -65831,6 +66053,7 @@ $as_echo "no, not found at $STLPORT_LIB" >&6; } + # Hotspot setup depends on lib checks. diff --git a/make/autoconf/help.m4 b/make/autoconf/help.m4 index 82dd898e52e..3937b93c15b 100644 --- a/make/autoconf/help.m4 +++ b/make/autoconf/help.m4 @@ -113,6 +113,8 @@ apt_help() { PKGHANDLER_COMMAND="sudo apt-get install libasound2-dev" ;; cups) PKGHANDLER_COMMAND="sudo apt-get install libcups2-dev" ;; + fontconfig) + PKGHANDLER_COMMAND="sudo apt-get install libfontconfig1-dev" ;; freetype) PKGHANDLER_COMMAND="sudo apt-get install libfreetype6-dev" ;; ffi) @@ -136,6 +138,8 @@ yum_help() { PKGHANDLER_COMMAND="sudo yum install alsa-lib-devel" ;; cups) PKGHANDLER_COMMAND="sudo yum install cups-devel" ;; + fontconfig) + PKGHANDLER_COMMAND="sudo yum install fontconfig-devel" ;; freetype) PKGHANDLER_COMMAND="sudo yum install freetype-devel" ;; x11) diff --git a/make/autoconf/jdk-options.m4 b/make/autoconf/jdk-options.m4 index 4df329fab08..30215ee372a 100644 --- a/make/autoconf/jdk-options.m4 +++ b/make/autoconf/jdk-options.m4 @@ -399,6 +399,46 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_CODE_COVERAGE], AC_SUBST(GCOV_ENABLED) ]) +############################################################################### +# +# AddressSanitizer +# +AC_DEFUN_ONCE([JDKOPT_SETUP_ADDRESS_SANITIZER], +[ + AC_ARG_ENABLE(asan, [AS_HELP_STRING([--enable-asan], + [enable AddressSanitizer if possible @<:@disabled@:>@])]) + ASAN_ENABLED="no" + if test "x$enable_asan" = "xyes"; then + case $TOOLCHAIN_TYPE in + gcc | clang) + AC_MSG_CHECKING([if asan is enabled]) + AC_MSG_RESULT([yes]) + ASAN_CFLAGS="-fsanitize=address -fno-omit-frame-pointer" + ASAN_LDFLAGS="-fsanitize=address" + JVM_CFLAGS="$JVM_CFLAGS $ASAN_CFLAGS" + JVM_LDFLAGS="$JVM_LDFLAGS $ASAN_LDFLAGS" + CFLAGS_JDKLIB="$CFLAGS_JDKLIB $ASAN_CFLAGS" + CFLAGS_JDKEXE="$CFLAGS_JDKEXE $ASAN_CFLAGS" + CXXFLAGS_JDKLIB="$CXXFLAGS_JDKLIB $ASAN_CFLAGS" + CXXFLAGS_JDKEXE="$CXXFLAGS_JDKEXE $ASAN_CFLAGS" + LDFLAGS_JDKLIB="$LDFLAGS_JDKLIB $ASAN_LDFLAGS" + LDFLAGS_JDKEXE="$LDFLAGS_JDKEXE $ASAN_LDFLAGS" + ASAN_ENABLED="yes" + ;; + *) + AC_MSG_ERROR([--enable-asan only works with toolchain type gcc or clang]) + ;; + esac + elif test "x$enable_asan" = "xno"; then + AC_MSG_CHECKING([if asan is enabled]) + AC_MSG_RESULT([no]) + elif test "x$enable_asan" != "x"; then + AC_MSG_ERROR([--enable-asan can only be assigned "yes" or "no"]) + fi + + AC_SUBST(ASAN_ENABLED) +]) + ################################################################################ # # Static build support. When enabled will generate static diff --git a/make/autoconf/lib-fontconfig.m4 b/make/autoconf/lib-fontconfig.m4 new file mode 100644 index 00000000000..c7be58b2a54 --- /dev/null +++ b/make/autoconf/lib-fontconfig.m4 @@ -0,0 +1,85 @@ +# +# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute 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 fontconfig +################################################################################ +AC_DEFUN_ONCE([LIB_SETUP_FONTCONFIG], +[ + AC_ARG_WITH(fontconfig, [AS_HELP_STRING([--with-fontconfig], + [specify prefix directory for the fontconfig package + (expecting the headers under PATH/include)])]) + AC_ARG_WITH(fontconfig-include, [AS_HELP_STRING([--with-fontconfig-include], + [specify directory for the fontconfig include files])]) + + if test "x$NEEDS_LIB_FONTCONFIG" = xfalse; then + if (test "x${with_fontconfig}" != x && test "x${with_fontconfig}" != xno) || \ + (test "x${with_fontconfig_include}" != x && test "x${with_fontconfig_include}" != xno); then + AC_MSG_WARN([[fontconfig not used, so --with-fontconfig[-*] is ignored]]) + fi + FONTCONFIG_CFLAGS= + else + FONTCONFIG_FOUND=no + + if test "x${with_fontconfig}" = xno || test "x${with_fontconfig_include}" = xno; then + AC_MSG_ERROR([It is not possible to disable the use of fontconfig. Remove the --without-fontconfig option.]) + fi + + if test "x${with_fontconfig}" != x; then + AC_MSG_CHECKING([for fontconfig headers]) + if test -s "${with_fontconfig}/include/fontconfig/fontconfig.h"; then + FONTCONFIG_CFLAGS="-I${with_fontconfig}/include" + FONTCONFIG_FOUND=yes + AC_MSG_RESULT([$FONTCONFIG_FOUND]) + else + AC_MSG_ERROR([Can't find 'include/fontconfig/fontconfig.h' under ${with_fontconfig} given with the --with-fontconfig option.]) + fi + fi + if test "x${with_fontconfig_include}" != x; then + AC_MSG_CHECKING([for fontconfig headers]) + if test -s "${with_fontconfig_include}/fontconfig/fontconfig.h"; then + FONTCONFIG_CFLAGS="-I${with_fontconfig_include}" + FONTCONFIG_FOUND=yes + AC_MSG_RESULT([$FONTCONFIG_FOUND]) + else + AC_MSG_ERROR([Can't find 'fontconfig/fontconfig.h' under ${with_fontconfig_include} given with the --with-fontconfig-include option.]) + fi + fi + if test "x$FONTCONFIG_FOUND" = xno; then + # Are the fontconfig headers installed in the default /usr/include location? + AC_CHECK_HEADERS([fontconfig/fontconfig.h], [ + FONTCONFIG_FOUND=yes + FONTCONFIG_CFLAGS= + DEFAULT_FONTCONFIG=yes + ]) + fi + if test "x$FONTCONFIG_FOUND" = xno; then + HELP_MSG_MISSING_DEPENDENCY([fontconfig]) + AC_MSG_ERROR([Could not find fontconfig! $HELP_MSG ]) + fi + fi + + AC_SUBST(FONTCONFIG_CFLAGS) +]) diff --git a/make/autoconf/libraries.m4 b/make/autoconf/libraries.m4 index 8b2321d7f07..7d10ea4dd7f 100644 --- a/make/autoconf/libraries.m4 +++ b/make/autoconf/libraries.m4 @@ -31,6 +31,7 @@ m4_include([lib-ffi.m4]) m4_include([lib-freetype.m4]) m4_include([lib-std.m4]) m4_include([lib-x11.m4]) +m4_include([lib-fontconfig.m4]) ################################################################################ # Determine which libraries are needed for this configuration @@ -47,6 +48,16 @@ AC_DEFUN_ONCE([LIB_DETERMINE_DEPENDENCIES], NEEDS_LIB_X11=true fi + # Check if fontconfig is needed + if test "x$OPENJDK_TARGET_OS" = xwindows || test "x$OPENJDK_TARGET_OS" = xmacosx; then + # No fontconfig support on windows or macosx + NEEDS_LIB_FONTCONFIG=false + else + # All other instances need fontconfig, even if building headless only, + # libawt still needs fontconfig headers. + NEEDS_LIB_FONTCONFIG=true + fi + # Check if cups is needed if test "x$OPENJDK_TARGET_OS" = xwindows; then # Windows have a separate print system @@ -83,6 +94,7 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBRARIES], LIB_SETUP_STD_LIBS LIB_SETUP_X11 LIB_SETUP_CUPS + LIB_SETUP_FONTCONFIG LIB_SETUP_FREETYPE LIB_SETUP_ALSA LIB_SETUP_LIBFFI diff --git a/make/autoconf/spec.gmk.in b/make/autoconf/spec.gmk.in index e9d34eecc3c..ac590a32bce 100644 --- a/make/autoconf/spec.gmk.in +++ b/make/autoconf/spec.gmk.in @@ -311,6 +311,16 @@ UNLIMITED_CRYPTO=@UNLIMITED_CRYPTO@ GCOV_ENABLED=@GCOV_ENABLED@ +# AddressSanitizer +export ASAN_ENABLED:=@ASAN_ENABLED@ +export DEVKIT_LIB_DIR:=@DEVKIT_LIB_DIR@ +ifeq ($(ASAN_ENABLED), yes) + export ASAN_OPTIONS="handle_segv=0 detect_leaks=0" + ifneq ($(DEVKIT_LIB_DIR),) + export LD_LIBRARY_PATH:=$(LD_LIBRARY_PATH):$(DEVKIT_LIB_DIR) + endif +endif + # Necessary additional compiler flags to compile X11 X_CFLAGS:=@X_CFLAGS@ X_LIBS:=@X_LIBS@ diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js index e5dd458f806..cdba1241893 100644 --- a/make/conf/jib-profiles.js +++ b/make/conf/jib-profiles.js @@ -1060,7 +1060,7 @@ var getJibProfilesDependencies = function (input, common) { jtreg: { server: "javare", revision: "4.2", - build_number: "b09", + build_number: "b10", checksum_file: "MD5_VALUES", file: "jtreg_bin-4.2.zip", environment_name: "JT_HOME", diff --git a/make/lib/Awt2dLibraries.gmk b/make/lib/Awt2dLibraries.gmk index 2fc2d67b06e..d34a2d3b341 100644 --- a/make/lib/Awt2dLibraries.gmk +++ b/make/lib/Awt2dLibraries.gmk @@ -317,6 +317,7 @@ ifeq ($(findstring $(OPENJDK_TARGET_OS),windows macosx),) LIBAWT_XAWT_CFLAGS += -DXAWT -DXAWT_HACK \ -DPACKAGE_PATH=\"$(PACKAGE_PATH)\" \ + $(FONTCONFIG_CFLAGS) \ $(CUPS_CFLAGS) ifeq ($(OPENJDK_TARGET_OS), solaris) @@ -555,6 +556,7 @@ ifeq ($(findstring $(OPENJDK_TARGET_OS), windows macosx),) -DHEADLESS=true \ -DPACKAGE_PATH=\"$(PACKAGE_PATH)\" \ $(CUPS_CFLAGS) \ + $(FONTCONFIG_CFLAGS) \ $(X_CFLAGS) \ $(LIBAWT_HEADLESS_CFLAGS), \ DISABLED_WARNINGS_xlc := 1506-356, \ diff --git a/src/hotspot/cpu/aarch64/frame_aarch64.cpp b/src/hotspot/cpu/aarch64/frame_aarch64.cpp index ab53d646d80..6df308b3eb5 100644 --- a/src/hotspot/cpu/aarch64/frame_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/frame_aarch64.cpp @@ -431,11 +431,11 @@ frame frame::sender_for_interpreter_frame(RegisterMap* map) const { // This is the sp before any possible extension (adapter/locals). intptr_t* unextended_sp = interpreter_frame_sender_sp(); -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI if (map->update_map()) { update_map_with_saved_link(map, (intptr_t**) addr_at(link_offset)); } -#endif // COMPILER2 || INCLUDE_JVMCI +#endif // COMPILER2_OR_JVMCI return frame(sender_sp, unextended_sp, link(), sender_pc()); } diff --git a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp index ac5eb020361..9b67fe7a5f2 100644 --- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp @@ -41,7 +41,7 @@ #ifdef COMPILER1 #include "c1/c1_Runtime1.hpp" #endif -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI #include "adfiles/ad_aarch64.hpp" #include "opto/runtime.hpp" #endif @@ -114,7 +114,7 @@ class RegisterSaver { }; OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words, bool save_vectors) { -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI if (save_vectors) { // Save upper half of vector registers int vect_words = 32 * 8 / wordSize; @@ -2688,7 +2688,7 @@ uint SharedRuntime::out_preserve_stack_slots() { return 0; } -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI //------------------------------generate_uncommon_trap_blob-------------------- void SharedRuntime::generate_uncommon_trap_blob() { // Allocate space for the code @@ -2894,7 +2894,7 @@ void SharedRuntime::generate_uncommon_trap_blob() { } #endif } -#endif // COMPILER2 +#endif // COMPILER2_OR_JVMCI //------------------------------generate_handler_blob------ @@ -3070,8 +3070,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const cha return RuntimeStub::new_runtime_stub(name, &buffer, frame_complete, frame_size_in_words, oop_maps, true); } - -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI // This is here instead of runtime_x86_64.cpp because it uses SimpleRuntimeFrame // //------------------------------generate_exception_blob--------------------------- @@ -3200,4 +3199,4 @@ void OptoRuntime::generate_exception_blob() { // Set exception blob _exception_blob = ExceptionBlob::create(&buffer, oop_maps, SimpleRuntimeFrame::framesize >> 1); } -#endif // COMPILER2 +#endif // COMPILER2_OR_JVMCI diff --git a/src/hotspot/cpu/arm/compiledIC_arm.cpp b/src/hotspot/cpu/arm/compiledIC_arm.cpp index abbd673b6ba..211f5d06963 100644 --- a/src/hotspot/cpu/arm/compiledIC_arm.cpp +++ b/src/hotspot/cpu/arm/compiledIC_arm.cpp @@ -33,7 +33,7 @@ #include "runtime/safepoint.hpp" // ---------------------------------------------------------------------------- -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI #define __ _masm. // emit call stub, compiled java to interpreter address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) { @@ -89,7 +89,7 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) int CompiledStaticCall::reloc_to_interp_stub() { return 10; // 4 in emit_to_interp_stub + 1 in Java_Static_Call } -#endif // COMPILER2 || JVMCI +#endif // COMPILER2_OR_JVMCI // size of C2 call stub, compiled java to interpretor int CompiledStaticCall::to_interp_stub_size() { diff --git a/src/hotspot/cpu/x86/frame_x86.cpp b/src/hotspot/cpu/x86/frame_x86.cpp index 918a413adee..26e24371adc 100644 --- a/src/hotspot/cpu/x86/frame_x86.cpp +++ b/src/hotspot/cpu/x86/frame_x86.cpp @@ -436,11 +436,11 @@ frame frame::sender_for_interpreter_frame(RegisterMap* map) const { // This is the sp before any possible extension (adapter/locals). intptr_t* unextended_sp = interpreter_frame_sender_sp(); -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI if (map->update_map()) { update_map_with_saved_link(map, (intptr_t**) addr_at(link_offset)); } -#endif // COMPILER2 || INCLUDE_JVMCI +#endif // COMPILER2_OR_JVMCI return frame(sender_sp, unextended_sp, link(), sender_pc()); } diff --git a/src/hotspot/cpu/x86/globals_x86.hpp b/src/hotspot/cpu/x86/globals_x86.hpp index 80344a3c8cf..b383af47006 100644 --- a/src/hotspot/cpu/x86/globals_x86.hpp +++ b/src/hotspot/cpu/x86/globals_x86.hpp @@ -46,11 +46,11 @@ define_pd_global(uintx, CodeCacheSegmentSize, 64 TIERED_ONLY(+64)); // Tiered // the the vep is aligned at CodeEntryAlignment whereas c2 only aligns // the uep and the vep doesn't get real alignment but just slops on by // only assured that the entry instruction meets the 5 byte size requirement. -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI define_pd_global(intx, CodeEntryAlignment, 32); #else define_pd_global(intx, CodeEntryAlignment, 16); -#endif // COMPILER2 +#endif // COMPILER2_OR_JVMCI define_pd_global(intx, OptoLoopAlignment, 16); define_pd_global(intx, InlineFrequencyCount, 100); define_pd_global(intx, InlineSmallCode, 1000); diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp index 996ae27cbc9..b7cf3ad898b 100644 --- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp +++ b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp @@ -151,7 +151,7 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ if (UseAVX < 3) { num_xmm_regs = num_xmm_regs/2; } -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI if (save_vectors) { assert(UseAVX > 0, "Vectors larger than 16 byte long are supported only with AVX"); assert(MaxVectorSize <= 64, "Only up to 64 byte long vectors are supported"); @@ -260,7 +260,7 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ } } -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI if (save_vectors) { off = ymm0_off; int delta = ymm1_off - off; @@ -270,7 +270,7 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ off += delta; } } -#endif // COMPILER2 || INCLUDE_JVMCI +#endif // COMPILER2_OR_JVMCI // %%% These should all be a waste but we'll keep things as they were for now if (true) { @@ -323,7 +323,7 @@ void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_ve __ addptr(rsp, frame::arg_reg_save_area_bytes); } -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI if (restore_vectors) { assert(UseAVX > 0, "Vectors larger than 16 byte long are supported only with AVX"); assert(MaxVectorSize <= 64, "Only up to 64 byte long vectors are supported"); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_32.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_32.cpp index 25eb6384c6b..677b018d838 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_32.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_32.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -3433,6 +3433,8 @@ class StubGenerator: public StubCodeGenerator { } address generate_libmExp() { + StubCodeMark mark(this, "StubRoutines", "libmExp"); + address start = __ pc(); const XMMRegister x0 = xmm0; @@ -3458,6 +3460,8 @@ class StubGenerator: public StubCodeGenerator { } address generate_libmLog() { + StubCodeMark mark(this, "StubRoutines", "libmLog"); + address start = __ pc(); const XMMRegister x0 = xmm0; @@ -3483,6 +3487,8 @@ class StubGenerator: public StubCodeGenerator { } address generate_libmLog10() { + StubCodeMark mark(this, "StubRoutines", "libmLog10"); + address start = __ pc(); const XMMRegister x0 = xmm0; @@ -3508,6 +3514,8 @@ class StubGenerator: public StubCodeGenerator { } address generate_libmPow() { + StubCodeMark mark(this, "StubRoutines", "libmPow"); + address start = __ pc(); const XMMRegister x0 = xmm0; @@ -3533,6 +3541,8 @@ class StubGenerator: public StubCodeGenerator { } address generate_libm_reduce_pi04l() { + StubCodeMark mark(this, "StubRoutines", "libm_reduce_pi04l"); + address start = __ pc(); BLOCK_COMMENT("Entry:"); @@ -3543,6 +3553,8 @@ class StubGenerator: public StubCodeGenerator { } address generate_libm_sin_cos_huge() { + StubCodeMark mark(this, "StubRoutines", "libm_sin_cos_huge"); + address start = __ pc(); const XMMRegister x0 = xmm0; @@ -3556,6 +3568,8 @@ class StubGenerator: public StubCodeGenerator { } address generate_libmSin() { + StubCodeMark mark(this, "StubRoutines", "libmSin"); + address start = __ pc(); const XMMRegister x0 = xmm0; @@ -3579,6 +3593,8 @@ class StubGenerator: public StubCodeGenerator { } address generate_libmCos() { + StubCodeMark mark(this, "StubRoutines", "libmCos"); + address start = __ pc(); const XMMRegister x0 = xmm0; @@ -3604,6 +3620,8 @@ class StubGenerator: public StubCodeGenerator { } address generate_libm_tan_cot_huge() { + StubCodeMark mark(this, "StubRoutines", "libm_tan_cot_huge"); + address start = __ pc(); const XMMRegister x0 = xmm0; @@ -3617,6 +3635,8 @@ class StubGenerator: public StubCodeGenerator { } address generate_libmTan() { + StubCodeMark mark(this, "StubRoutines", "libmTan"); + address start = __ pc(); const XMMRegister x0 = xmm0; diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp index fd8ee726abd..7db8ba32981 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp @@ -4619,6 +4619,8 @@ class StubGenerator: public StubCodeGenerator { } address generate_libmExp() { + StubCodeMark mark(this, "StubRoutines", "libmExp"); + address start = __ pc(); const XMMRegister x0 = xmm0; @@ -4646,6 +4648,8 @@ class StubGenerator: public StubCodeGenerator { } address generate_libmLog() { + StubCodeMark mark(this, "StubRoutines", "libmLog"); + address start = __ pc(); const XMMRegister x0 = xmm0; @@ -4674,6 +4678,8 @@ class StubGenerator: public StubCodeGenerator { } address generate_libmLog10() { + StubCodeMark mark(this, "StubRoutines", "libmLog10"); + address start = __ pc(); const XMMRegister x0 = xmm0; @@ -4701,6 +4707,8 @@ class StubGenerator: public StubCodeGenerator { } address generate_libmPow() { + StubCodeMark mark(this, "StubRoutines", "libmPow"); + address start = __ pc(); const XMMRegister x0 = xmm0; @@ -4731,6 +4739,8 @@ class StubGenerator: public StubCodeGenerator { } address generate_libmSin() { + StubCodeMark mark(this, "StubRoutines", "libmSin"); + address start = __ pc(); const XMMRegister x0 = xmm0; @@ -4770,6 +4780,8 @@ class StubGenerator: public StubCodeGenerator { } address generate_libmCos() { + StubCodeMark mark(this, "StubRoutines", "libmCos"); + address start = __ pc(); const XMMRegister x0 = xmm0; @@ -4809,6 +4821,8 @@ class StubGenerator: public StubCodeGenerator { } address generate_libmTan() { + StubCodeMark mark(this, "StubRoutines", "libmTan"); + address start = __ pc(); const XMMRegister x0 = xmm0; diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index 22e7b653f22..f322d60a6ed 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -944,7 +944,7 @@ void VM_Version::get_processor_features() { } } #endif -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI if (MaxVectorSize > 0) { if (!is_power_of_2(MaxVectorSize)) { warning("MaxVectorSize must be a power of 2"); @@ -996,7 +996,7 @@ void VM_Version::get_processor_features() { } #endif // COMPILER2 && ASSERT } -#endif // COMPILER2 || INCLUDE_JVMCI +#endif // COMPILER2_OR_JVMCI #ifdef COMPILER2 #ifdef _LP64 diff --git a/src/hotspot/os_cpu/bsd_x86/thread_bsd_x86.cpp b/src/hotspot/os_cpu/bsd_x86/thread_bsd_x86.cpp index 7f5838f806f..ea06c7d03bc 100644 --- a/src/hotspot/os_cpu/bsd_x86/thread_bsd_x86.cpp +++ b/src/hotspot/os_cpu/bsd_x86/thread_bsd_x86.cpp @@ -73,7 +73,7 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) frame ret_frame(ret_sp, ret_fp, addr.pc()); if (!ret_frame.safe_for_sender(jt)) { -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI // C2 and JVMCI use ebp as a general register see if NULL fp helps frame ret_frame2(ret_sp, NULL, addr.pc()); if (!ret_frame2.safe_for_sender(jt)) { @@ -84,7 +84,7 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) #else // nothing else to try if the frame isn't good return false; -#endif /* COMPILER2 || INCLUDE_JVMCI */ +#endif // COMPILER2_OR_JVMCI } *fr_addr = ret_frame; return true; diff --git a/src/hotspot/os_cpu/linux_x86/thread_linux_x86.cpp b/src/hotspot/os_cpu/linux_x86/thread_linux_x86.cpp index b98a851908f..fbdcef60406 100644 --- a/src/hotspot/os_cpu/linux_x86/thread_linux_x86.cpp +++ b/src/hotspot/os_cpu/linux_x86/thread_linux_x86.cpp @@ -74,7 +74,7 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) frame ret_frame(ret_sp, ret_fp, addr.pc()); if (!ret_frame.safe_for_sender(jt)) { -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI // C2 and JVMCI use ebp as a general register see if NULL fp helps frame ret_frame2(ret_sp, NULL, addr.pc()); if (!ret_frame2.safe_for_sender(jt)) { @@ -85,7 +85,7 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) #else // nothing else to try if the frame isn't good return false; -#endif /* COMPILER2 || INCLUDE_JVMCI */ +#endif // COMPILER2_OR_JVMCI } *fr_addr = ret_frame; return true; diff --git a/src/hotspot/os_cpu/windows_x86/thread_windows_x86.cpp b/src/hotspot/os_cpu/windows_x86/thread_windows_x86.cpp index 9926a89666f..1e457ce4bf9 100644 --- a/src/hotspot/os_cpu/windows_x86/thread_windows_x86.cpp +++ b/src/hotspot/os_cpu/windows_x86/thread_windows_x86.cpp @@ -81,7 +81,7 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) frame ret_frame(ret_sp, ret_fp, addr.pc()); if (!ret_frame.safe_for_sender(jt)) { -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI // C2 and JVMCI use ebp as a general register see if NULL fp helps frame ret_frame2(ret_sp, NULL, addr.pc()); if (!ret_frame2.safe_for_sender(jt)) { @@ -92,7 +92,7 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) #else // nothing else to try if the frame isn't good return false; -#endif /* COMPILER2 || INCLUDE_JVMCI */ +#endif // COMPILER2_OR_JVMCI } *fr_addr = ret_frame; return true; diff --git a/src/hotspot/share/aot/aotCodeHeap.cpp b/src/hotspot/share/aot/aotCodeHeap.cpp index 15c1e696ca4..2a9b3982cd2 100644 --- a/src/hotspot/share/aot/aotCodeHeap.cpp +++ b/src/hotspot/share/aot/aotCodeHeap.cpp @@ -490,6 +490,8 @@ void AOTCodeHeap::link_stub_routines_symbols() { SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_checkcast_arraycopy", address, StubRoutines::_checkcast_arraycopy); + SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_generic_arraycopy", address, StubRoutines::_generic_arraycopy); + SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_aescrypt_encryptBlock", address, StubRoutines::_aescrypt_encryptBlock); SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_aescrypt_decryptBlock", address, StubRoutines::_aescrypt_decryptBlock); SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_cipherBlockChaining_encryptAESCrypt", address, StubRoutines::_cipherBlockChaining_encryptAESCrypt); diff --git a/src/hotspot/share/code/scopeDesc.cpp b/src/hotspot/share/code/scopeDesc.cpp index 27eb37ad550..4807f61d74c 100644 --- a/src/hotspot/share/code/scopeDesc.cpp +++ b/src/hotspot/share/code/scopeDesc.cpp @@ -228,7 +228,7 @@ void ScopeDesc::print_on(outputStream* st, PcDesc* pd) const { } } -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI if (NOT_JVMCI(DoEscapeAnalysis &&) is_top() && _objects != NULL) { st->print_cr(" Objects"); for (int i = 0; i < _objects->length(); i++) { @@ -239,7 +239,7 @@ void ScopeDesc::print_on(outputStream* st, PcDesc* pd) const { st->cr(); } } -#endif // COMPILER2 || INCLUDE_JVMCI +#endif // COMPILER2_OR_JVMCI } #endif diff --git a/src/hotspot/share/compiler/oopMap.cpp b/src/hotspot/share/compiler/oopMap.cpp index e412e4bf2d0..c36c4ff3ff0 100644 --- a/src/hotspot/share/compiler/oopMap.cpp +++ b/src/hotspot/share/compiler/oopMap.cpp @@ -268,9 +268,9 @@ static void add_derived_oop(oop* base, oop* derived) { #if !defined(TIERED) && !defined(INCLUDE_JVMCI) COMPILER1_PRESENT(ShouldNotReachHere();) #endif // !defined(TIERED) && !defined(INCLUDE_JVMCI) -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI DerivedPointerTable::add(derived, base); -#endif // COMPILER2 || INCLUDE_JVMCI +#endif // COMPILER2_OR_JVMCI } @@ -461,12 +461,12 @@ bool ImmutableOopMap::has_derived_pointer() const { #if !defined(TIERED) && !defined(INCLUDE_JVMCI) COMPILER1_PRESENT(return false); #endif // !TIERED -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI OopMapStream oms(this,OopMapValue::derived_oop_value); return oms.is_done(); #else return false; -#endif // COMPILER2 || INCLUDE_JVMCI +#endif // COMPILER2_OR_JVMCI } #endif //PRODUCT @@ -726,7 +726,7 @@ ImmutableOopMapSet* ImmutableOopMapSet::build_from(const OopMapSet* oopmap_set) //------------------------------DerivedPointerTable--------------------------- -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI class DerivedPointerEntry : public CHeapObj { private: @@ -819,4 +819,4 @@ void DerivedPointerTable::update_pointers() { _active = false; } -#endif // COMPILER2 || INCLUDE_JVMCI +#endif // COMPILER2_OR_JVMCI diff --git a/src/hotspot/share/compiler/oopMap.hpp b/src/hotspot/share/compiler/oopMap.hpp index 5428f3bdee2..6c9fe4ee299 100644 --- a/src/hotspot/share/compiler/oopMap.hpp +++ b/src/hotspot/share/compiler/oopMap.hpp @@ -427,7 +427,7 @@ private: // oops, it is filled in with references to all locations that contains a // derived oop (assumed to be very few). When the GC is complete, the derived // pointers are updated based on their base pointers new value and an offset. -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI class DerivedPointerTable : public AllStatic { friend class VMStructs; private: @@ -463,6 +463,6 @@ class DerivedPointerTableDeactivate: public StackObj { } } }; -#endif // COMPILER2 || INCLUDE_JVMCI +#endif // COMPILER2_OR_JVMCI #endif // SHARE_VM_COMPILER_OOPMAP_HPP diff --git a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp index 0901117f646..c49112957b0 100644 --- a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp +++ b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp @@ -2296,7 +2296,7 @@ bool CMSCollector::verify_after_remark() { // way with the marking information used by GC. NoRefDiscovery no_discovery(ref_processor()); -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI DerivedPointerTableDeactivate dpt_deact; #endif @@ -2869,7 +2869,7 @@ void CMSCollector::checkpointRootsInitialWork() { print_eden_and_survivor_chunk_arrays(); { -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI DerivedPointerTableDeactivate dpt_deact; #endif if (CMSParallelInitialMarkEnabled) { @@ -4171,7 +4171,7 @@ void CMSCollector::checkpointRootsFinalWork() { print_eden_and_survivor_chunk_arrays(); { -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI DerivedPointerTableDeactivate dpt_deact; #endif diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index 8c2ea13bf4a..79bb1c91b1c 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -2597,7 +2597,7 @@ void G1CollectedHeap::gc_epilogue(bool full) { // FIXME: what is this about? // I'm ignoring the "fill_newgen()" call if "alloc_event_enabled" // is set. -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI assert(DerivedPointerTable::is_empty(), "derived pointer present"); #endif // always_do_update_barrier = true; @@ -3010,7 +3010,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { _verifier->check_bitmaps("GC Start"); -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI DerivedPointerTable::clear(); #endif @@ -4439,7 +4439,7 @@ void G1CollectedHeap::post_evacuate_collection_set(EvacuationInfo& evacuation_in purge_code_root_memory(); redirty_logged_cards(); -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI double start = os::elapsedTime(); DerivedPointerTable::update_pointers(); g1_policy()->phase_times()->record_derived_pointer_table_update_time((os::elapsedTime() - start) * 1000.0); diff --git a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp index c939a8459ab..979b4836d8c 100644 --- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp +++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp @@ -414,7 +414,7 @@ double G1GCPhaseTimes::print_post_evacuate_collection_set() const { debug_time("Redirty Cards", _recorded_redirty_logged_cards_time_ms); trace_phase(_gc_par_phases[RedirtyCards]); -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI debug_time("DerivedPointerTable Update", _cur_derived_pointer_table_update_time_ms); #endif diff --git a/src/hotspot/share/gc/g1/g1MarkSweep.cpp b/src/hotspot/share/gc/g1/g1MarkSweep.cpp index 9fd8fa62790..9b2b18274bb 100644 --- a/src/hotspot/share/gc/g1/g1MarkSweep.cpp +++ b/src/hotspot/share/gc/g1/g1MarkSweep.cpp @@ -62,7 +62,7 @@ void G1MarkSweep::invoke_at_safepoint(ReferenceProcessor* rp, assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint"); HandleMark hm; // Discard invalid handles created during gc -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI DerivedPointerTable::clear(); #endif #ifdef ASSERT @@ -96,7 +96,7 @@ void G1MarkSweep::invoke_at_safepoint(ReferenceProcessor* rp, // Prepare compaction. mark_sweep_phase2(); -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI // Don't add any more derived pointers during phase3 DerivedPointerTable::set_active(false); #endif @@ -111,7 +111,7 @@ void G1MarkSweep::invoke_at_safepoint(ReferenceProcessor* rp, BiasedLocking::restore_marks(); GenMarkSweep::deallocate_stacks(); -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI // Now update the derived pointers. DerivedPointerTable::update_pointers(); #endif @@ -204,7 +204,7 @@ void G1MarkSweep::mark_sweep_phase1(bool& marked_for_unloading, if (VerifyDuringGC) { HandleMark hm; // handle scope -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI DerivedPointerTableDeactivate dpt_deact; #endif g1h->prepare_for_verify(); diff --git a/src/hotspot/share/gc/parallel/psMarkSweep.cpp b/src/hotspot/share/gc/parallel/psMarkSweep.cpp index db566bf0ad0..185cbb2f62d 100644 --- a/src/hotspot/share/gc/parallel/psMarkSweep.cpp +++ b/src/hotspot/share/gc/parallel/psMarkSweep.cpp @@ -192,7 +192,7 @@ bool PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) { allocate_stacks(); -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI DerivedPointerTable::clear(); #endif @@ -203,7 +203,7 @@ bool PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) { mark_sweep_phase2(); -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI // Don't add any more derived pointers during phase3 assert(DerivedPointerTable::is_active(), "Sanity"); DerivedPointerTable::set_active(false); @@ -252,7 +252,7 @@ bool PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) { CodeCache::gc_epilogue(); JvmtiExport::gc_epilogue(); -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI DerivedPointerTable::update_pointers(); #endif diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.cpp b/src/hotspot/share/gc/parallel/psParallelCompact.cpp index 9fea2221bfc..c46f0d41aa0 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp @@ -1032,7 +1032,7 @@ void PSParallelCompact::post_compact() CodeCache::gc_epilogue(); JvmtiExport::gc_epilogue(); -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI DerivedPointerTable::update_pointers(); #endif @@ -1783,7 +1783,7 @@ bool PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) { CodeCache::gc_prologue(); -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI DerivedPointerTable::clear(); #endif @@ -1799,7 +1799,7 @@ bool PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) { && GCCause::is_user_requested_gc(gc_cause); summary_phase(vmthread_cm, maximum_heap_compaction || max_on_system_gc); -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI assert(DerivedPointerTable::is_active(), "Sanity"); DerivedPointerTable::set_active(false); #endif diff --git a/src/hotspot/share/gc/parallel/psScavenge.cpp b/src/hotspot/share/gc/parallel/psScavenge.cpp index 3cf3e2302a0..64c0b7486ab 100644 --- a/src/hotspot/share/gc/parallel/psScavenge.cpp +++ b/src/hotspot/share/gc/parallel/psScavenge.cpp @@ -331,7 +331,7 @@ bool PSScavenge::invoke_no_policy() { save_to_space_top_before_gc(); -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI DerivedPointerTable::clear(); #endif @@ -601,7 +601,7 @@ bool PSScavenge::invoke_no_policy() { assert(young_gen->to_space()->is_empty(), "to space should be empty now"); } -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI DerivedPointerTable::update_pointers(); #endif diff --git a/src/hotspot/share/gc/serial/genMarkSweep.cpp b/src/hotspot/share/gc/serial/genMarkSweep.cpp index 8f22aea7a19..70156a6b70d 100644 --- a/src/hotspot/share/gc/serial/genMarkSweep.cpp +++ b/src/hotspot/share/gc/serial/genMarkSweep.cpp @@ -92,7 +92,7 @@ void GenMarkSweep::invoke_at_safepoint(ReferenceProcessor* rp, bool clear_all_so mark_sweep_phase2(); // Don't add any more derived pointers during phase3 -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI assert(DerivedPointerTable::is_active(), "Sanity"); DerivedPointerTable::set_active(false); #endif diff --git a/src/hotspot/share/gc/shared/collectedHeap.cpp b/src/hotspot/share/gc/shared/collectedHeap.cpp index f5d93a400e6..5a0f729f80e 100644 --- a/src/hotspot/share/gc/shared/collectedHeap.cpp +++ b/src/hotspot/share/gc/shared/collectedHeap.cpp @@ -241,7 +241,7 @@ void CollectedHeap::set_barrier_set(BarrierSet* barrier_set) { void CollectedHeap::pre_initialize() { // Used for ReduceInitialCardMarks (when COMPILER2 is used); // otherwise remains unused. -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI _defer_initial_card_mark = is_server_compilation_mode_vm() && ReduceInitialCardMarks && can_elide_tlab_store_barriers() && (DeferInitialCardMark || card_mark_must_follow_store()); #else @@ -545,7 +545,7 @@ void CollectedHeap::ensure_parsability(bool retire_tlabs) { " to threads list is doomed to failure!"); for (JavaThread *thread = Threads::first(); thread; thread = thread->next()) { if (use_tlab) thread->tlab().make_parsable(retire_tlabs); -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI // The deferred store barriers must all have been flushed to the // card-table (or other remembered set structure) before GC starts // processing the card-table (or other remembered set). diff --git a/src/hotspot/share/gc/shared/genCollectedHeap.cpp b/src/hotspot/share/gc/shared/genCollectedHeap.cpp index d6624936a4a..6c9f07b9744 100644 --- a/src/hotspot/share/gc/shared/genCollectedHeap.cpp +++ b/src/hotspot/share/gc/shared/genCollectedHeap.cpp @@ -1067,11 +1067,11 @@ class GenGCEpilogueClosure: public GenCollectedHeap::GenClosure { }; void GenCollectedHeap::gc_epilogue(bool full) { -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI assert(DerivedPointerTable::is_empty(), "derived pointer present"); size_t actual_gap = pointer_delta((HeapWord*) (max_uintx-3), *(end_addr())); guarantee(is_client_compilation_mode_vm() || actual_gap > (size_t)FastAllocateSizeLimit, "inline allocation wraps"); -#endif /* COMPILER2 || INCLUDE_JVMCI */ +#endif // COMPILER2_OR_JVMCI resize_all_tlabs(); diff --git a/src/hotspot/share/interpreter/interpreterRuntime.cpp b/src/hotspot/share/interpreter/interpreterRuntime.cpp index 4288922afa3..d322cfd33af 100644 --- a/src/hotspot/share/interpreter/interpreterRuntime.cpp +++ b/src/hotspot/share/interpreter/interpreterRuntime.cpp @@ -921,6 +921,14 @@ nmethod* InterpreterRuntime::frequency_counter_overflow(JavaThread* thread, addr int bci = method->bci_from(last_frame.bcp()); nm = method->lookup_osr_nmethod_for(bci, CompLevel_none, false); } + if (nm != NULL && thread->is_interp_only_mode()) { + // Normally we never get an nm if is_interp_only_mode() is true, because + // policy()->event has a check for this and won't compile the method when + // true. However, it's possible for is_interp_only_mode() to become true + // during the compilation. We don't want to return the nm in that case + // because we want to continue to execute interpreted. + nm = NULL; + } #ifndef PRODUCT if (TraceOnStackReplacement) { if (nm != NULL) { diff --git a/src/hotspot/share/jvmci/jvmciCompiler.hpp b/src/hotspot/share/jvmci/jvmciCompiler.hpp index b1401e6d75f..fd246325f07 100644 --- a/src/hotspot/share/jvmci/jvmciCompiler.hpp +++ b/src/hotspot/share/jvmci/jvmciCompiler.hpp @@ -55,10 +55,13 @@ private: public: JVMCICompiler(); - static JVMCICompiler* instance(TRAPS) { + static JVMCICompiler* instance(bool require_non_null, TRAPS) { if (!EnableJVMCI) { THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "JVMCI is not enabled") } + if (_instance == NULL && require_non_null) { + THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "The JVMCI compiler instance has not been created"); + } return _instance; } diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index a01da7b52cc..c0509df788b 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -1018,7 +1018,7 @@ C2V_VMENTRY(jint, installCode, (JNIEnv *jniEnv, jobject, jobject target, jobject Handle installed_code_handle(THREAD, JNIHandles::resolve(installed_code)); Handle speculation_log_handle(THREAD, JNIHandles::resolve(speculation_log)); - JVMCICompiler* compiler = JVMCICompiler::instance(CHECK_JNI_ERR); + JVMCICompiler* compiler = JVMCICompiler::instance(true, CHECK_JNI_ERR); TraceTime install_time("installCode", JVMCICompiler::codeInstallTimer()); bool is_immutable_PIC = HotSpotCompiledCode::isImmutablePIC(compiled_code_handle) > 0; @@ -1136,7 +1136,7 @@ C2V_VMENTRY(jint, getMetadata, (JNIEnv *jniEnv, jobject, jobject target, jobject C2V_END C2V_VMENTRY(void, resetCompilationStatistics, (JNIEnv *jniEnv, jobject)) - JVMCICompiler* compiler = JVMCICompiler::instance(CHECK); + JVMCICompiler* compiler = JVMCICompiler::instance(true, CHECK); CompilerStatistics* stats = compiler->stats(); stats->_standard.reset(); stats->_osr.reset(); diff --git a/src/hotspot/share/jvmci/jvmciRuntime.cpp b/src/hotspot/share/jvmci/jvmciRuntime.cpp index 2f9678d1119..134ea685c83 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.cpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp @@ -821,7 +821,7 @@ void JVMCIRuntime::shutdown(TRAPS) { } CompLevel JVMCIRuntime::adjust_comp_level_inner(const methodHandle& method, bool is_osr, CompLevel level, JavaThread* thread) { - JVMCICompiler* compiler = JVMCICompiler::instance(thread); + JVMCICompiler* compiler = JVMCICompiler::instance(false, thread); if (compiler != NULL && compiler->is_bootstrapping()) { return level; } diff --git a/src/hotspot/share/memory/metachunk.cpp b/src/hotspot/share/memory/metachunk.cpp index 45528faa180..c9740e94537 100644 --- a/src/hotspot/share/memory/metachunk.cpp +++ b/src/hotspot/share/memory/metachunk.cpp @@ -55,8 +55,8 @@ Metachunk::Metachunk(size_t word_size, _container(container) { _top = initial_top(); -#ifdef ASSERT set_is_tagged_free(false); +#ifdef ASSERT mangle(uninitMetaWordVal); #endif } diff --git a/src/hotspot/share/memory/metachunk.hpp b/src/hotspot/share/memory/metachunk.hpp index 5b92827586f..d8b3d11900b 100644 --- a/src/hotspot/share/memory/metachunk.hpp +++ b/src/hotspot/share/memory/metachunk.hpp @@ -102,7 +102,7 @@ class Metachunk : public Metabase { // Current allocation top. MetaWord* _top; - DEBUG_ONLY(bool _is_tagged_free;) + bool _is_tagged_free; MetaWord* initial_top() const { return (MetaWord*)this + overhead(); } MetaWord* top() const { return _top; } @@ -138,10 +138,8 @@ class Metachunk : public Metabase { size_t used_word_size() const; size_t free_word_size() const; -#ifdef ASSERT bool is_tagged_free() { return _is_tagged_free; } void set_is_tagged_free(bool v) { _is_tagged_free = v; } -#endif bool contains(const void* ptr) { return bottom() <= ptr && ptr < _top; } diff --git a/src/hotspot/share/memory/metaspace.cpp b/src/hotspot/share/memory/metaspace.cpp index 9cbe3c07279..5671e12c2eb 100644 --- a/src/hotspot/share/memory/metaspace.cpp +++ b/src/hotspot/share/memory/metaspace.cpp @@ -108,6 +108,18 @@ static ChunkIndex next_chunk_index(ChunkIndex i) { return (ChunkIndex) (i+1); } +static const char* scale_unit(size_t scale) { + switch(scale) { + case 1: return "BYTES"; + case K: return "KB"; + case M: return "MB"; + case G: return "GB"; + default: + ShouldNotReachHere(); + return NULL; + } +} + volatile intptr_t MetaspaceGC::_capacity_until_GC = 0; uint MetaspaceGC::_shrink_factor = 0; bool MetaspaceGC::_should_concurrent_collect = false; @@ -176,7 +188,7 @@ class ChunkManager : public CHeapObj { void locked_get_statistics(ChunkManagerStatistics* stat) const; void get_statistics(ChunkManagerStatistics* stat) const; - static void print_statistics(const ChunkManagerStatistics* stat, outputStream* out); + static void print_statistics(const ChunkManagerStatistics* stat, outputStream* out, size_t scale); public: @@ -283,7 +295,7 @@ class ChunkManager : public CHeapObj { // Prints composition for both non-class and (if available) // class chunk manager. - static void print_all_chunkmanagers(outputStream* out); + static void print_all_chunkmanagers(outputStream* out, size_t scale = 1); }; class SmallBlocks : public CHeapObj { @@ -480,6 +492,7 @@ class VirtualSpaceNode : public CHeapObj { #endif void print_on(outputStream* st) const; + void print_map(outputStream* st, bool is_class) const; }; #define assert_is_aligned(value, alignment) \ @@ -531,6 +544,94 @@ void VirtualSpaceNode::purge(ChunkManager* chunk_manager) { } } +void VirtualSpaceNode::print_map(outputStream* st, bool is_class) const { + + // Format: + // + // . .. . . .. + // SSxSSMMMMMMMMMMMMMMMMsssXX + // 112114444444444444444 + // . .. . . .. + // SSxSSMMMMMMMMMMMMMMMMsssXX + // 112114444444444444444 + + if (bottom() == top()) { + return; + } + + // First line: dividers for every med-chunk-sized interval + // Second line: a dot for the start of a chunk + // Third line: a letter per chunk type (x,s,m,h), uppercase if in use. + + const size_t spec_chunk_size = is_class ? ClassSpecializedChunk : SpecializedChunk; + const size_t small_chunk_size = is_class ? ClassSmallChunk : SmallChunk; + const size_t med_chunk_size = is_class ? ClassMediumChunk : MediumChunk; + + int line_len = 100; + const size_t section_len = align_up(spec_chunk_size * line_len, med_chunk_size); + line_len = (int)(section_len / spec_chunk_size); + + char* line1 = (char*)os::malloc(line_len, mtInternal); + char* line2 = (char*)os::malloc(line_len, mtInternal); + char* line3 = (char*)os::malloc(line_len, mtInternal); + int pos = 0; + const MetaWord* p = bottom(); + const Metachunk* chunk = (const Metachunk*)p; + const MetaWord* chunk_end = p + chunk->word_size(); + while (p < top()) { + if (pos == line_len) { + pos = 0; + st->fill_to(22); + st->print_raw(line1, line_len); + st->cr(); + st->fill_to(22); + st->print_raw(line2, line_len); + st->cr(); + } + if (pos == 0) { + st->print(PTR_FORMAT ":", p2i(p)); + } + if (p == chunk_end) { + chunk = (Metachunk*)p; + chunk_end = p + chunk->word_size(); + } + if (p == (const MetaWord*)chunk) { + // chunk starts. + line1[pos] = '.'; + } else { + line1[pos] = ' '; + } + // Line 2: chunk type (x=spec, s=small, m=medium, h=humongous), uppercase if + // chunk is in use. + const bool chunk_is_free = ((Metachunk*)chunk)->is_tagged_free(); + if (chunk->word_size() == spec_chunk_size) { + line2[pos] = chunk_is_free ? 'x' : 'X'; + } else if (chunk->word_size() == small_chunk_size) { + line2[pos] = chunk_is_free ? 's' : 'S'; + } else if (chunk->word_size() == med_chunk_size) { + line2[pos] = chunk_is_free ? 'm' : 'M'; + } else if (chunk->word_size() > med_chunk_size) { + line2[pos] = chunk_is_free ? 'h' : 'H'; + } else { + ShouldNotReachHere(); + } + p += spec_chunk_size; + pos ++; + } + if (pos > 0) { + st->fill_to(22); + st->print_raw(line1, pos); + st->cr(); + st->fill_to(22); + st->print_raw(line2, pos); + st->cr(); + } + os::free(line1); + os::free(line2); + os::free(line3); +} + + #ifdef ASSERT uintx VirtualSpaceNode::container_count_slow() { uintx count = 0; @@ -637,6 +738,7 @@ class VirtualSpaceList : public CHeapObj { void purge(ChunkManager* chunk_manager); void print_on(outputStream* st) const; + void print_map(outputStream* st) const; class VirtualSpaceListIterator : public StackObj { VirtualSpaceNode* _virtual_spaces; @@ -1449,6 +1551,18 @@ void VirtualSpaceList::print_on(outputStream* st) const { } } +void VirtualSpaceList::print_map(outputStream* st) const { + VirtualSpaceNode* list = virtual_space_list(); + VirtualSpaceListIterator iter(list); + unsigned i = 0; + while (iter.repeat()) { + st->print_cr("Node %u:", i); + VirtualSpaceNode* node = iter.get_next(); + node->print_map(st, this->is_class()); + i ++; + } +} + // MetaspaceGC methods // VM_CollectForMetadataAllocation is the vm operation used to GC. @@ -1724,7 +1838,6 @@ bool Metadebug::test_metadata_failure() { #endif // ChunkManager methods - size_t ChunkManager::free_chunks_total_words() { return _free_chunks_total; } @@ -1923,11 +2036,10 @@ Metachunk* ChunkManager::free_chunks_get(size_t word_size) { // Remove it from the links to this freelist chunk->set_next(NULL); chunk->set_prev(NULL); -#ifdef ASSERT + // Chunk is no longer on any freelist. Setting to false make container_count_slow() // work. chunk->set_is_tagged_free(false); -#endif chunk->container()->inc_container_count(); slow_locked_verify(); @@ -1995,7 +2107,7 @@ void ChunkManager::return_single_chunk(ChunkIndex index, Metachunk* chunk) { chunk_size_name(index), p2i(chunk), chunk->word_size()); } chunk->container()->dec_container_count(); - DEBUG_ONLY(chunk->set_is_tagged_free(true);) + chunk->set_is_tagged_free(true); // Chunk has been added; update counters. account_for_added_chunk(chunk); @@ -2057,22 +2169,45 @@ void ChunkManager::get_statistics(ChunkManagerStatistics* stat) const { locked_get_statistics(stat); } -void ChunkManager::print_statistics(const ChunkManagerStatistics* stat, outputStream* out) { +void ChunkManager::print_statistics(const ChunkManagerStatistics* stat, outputStream* out, size_t scale) { size_t total = 0; + assert(scale == 1 || scale == K || scale == M || scale == G, "Invalid scale"); + + const char* unit = scale_unit(scale); for (ChunkIndex i = ZeroIndex; i < NumberOfFreeLists; i = next_chunk_index(i)) { - out->print_cr(" " SIZE_FORMAT " %s (" SIZE_FORMAT " bytes) chunks, total " SIZE_FORMAT " bytes", - stat->num_by_type[i], chunk_size_name(i), - stat->single_size_by_type[i], - stat->total_size_by_type[i]); + out->print(" " SIZE_FORMAT " %s (" SIZE_FORMAT " bytes) chunks, total ", + stat->num_by_type[i], chunk_size_name(i), + stat->single_size_by_type[i]); + if (scale == 1) { + out->print_cr(SIZE_FORMAT " bytes", stat->total_size_by_type[i]); + } else { + out->print_cr("%.2f%s", (float)stat->total_size_by_type[i] / scale, unit); + } + total += stat->total_size_by_type[i]; } - out->print_cr(" " SIZE_FORMAT " humongous chunks, total " SIZE_FORMAT " bytes", - stat->num_humongous_chunks, stat->total_size_humongous_chunks); + + total += stat->total_size_humongous_chunks; - out->print_cr(" total size: " SIZE_FORMAT ".", total); + + if (scale == 1) { + out->print_cr(" " SIZE_FORMAT " humongous chunks, total " SIZE_FORMAT " bytes", + stat->num_humongous_chunks, stat->total_size_humongous_chunks); + + out->print_cr(" total size: " SIZE_FORMAT " bytes.", total); + } else { + out->print_cr(" " SIZE_FORMAT " humongous chunks, total %.2f%s", + stat->num_humongous_chunks, + (float)stat->total_size_humongous_chunks / scale, unit); + + out->print_cr(" total size: %.2f%s.", (float)total / scale, unit); + } + } -void ChunkManager::print_all_chunkmanagers(outputStream* out) { +void ChunkManager::print_all_chunkmanagers(outputStream* out, size_t scale) { + assert(scale == 1 || scale == K || scale == M || scale == G, "Invalid scale"); + // Note: keep lock protection only to retrieving statistics; keep printing // out of lock protection ChunkManagerStatistics stat; @@ -2080,7 +2215,7 @@ void ChunkManager::print_all_chunkmanagers(outputStream* out) { const ChunkManager* const non_class_cm = Metaspace::chunk_manager_metadata(); if (non_class_cm != NULL) { non_class_cm->get_statistics(&stat); - ChunkManager::print_statistics(&stat, out); + ChunkManager::print_statistics(&stat, out, scale); } else { out->print_cr("unavailable."); } @@ -2088,7 +2223,7 @@ void ChunkManager::print_all_chunkmanagers(outputStream* out) { const ChunkManager* const class_cm = Metaspace::chunk_manager_class(); if (class_cm != NULL) { class_cm->get_statistics(&stat); - ChunkManager::print_statistics(&stat, out); + ChunkManager::print_statistics(&stat, out, scale); } else { out->print_cr("unavailable."); } @@ -2911,9 +3046,9 @@ void MetaspaceAux::print_on(outputStream* out, Metaspace::MetadataType mdtype) { size_t free_bytes = free_bytes_slow(mdtype); size_t used_and_free = used_bytes + free_bytes + free_chunks_capacity_bytes; - out->print_cr(" Chunk accounting: used in chunks " SIZE_FORMAT + out->print_cr(" Chunk accounting: (used in chunks " SIZE_FORMAT "K + unused in chunks " SIZE_FORMAT "K + " - " capacity in free chunks " SIZE_FORMAT "K = " SIZE_FORMAT + " capacity in free chunks " SIZE_FORMAT "K) = " SIZE_FORMAT "K capacity in allocated chunks " SIZE_FORMAT "K", used_bytes / K, free_bytes / K, @@ -2981,6 +3116,194 @@ void MetaspaceAux::print_waste(outputStream* out) { } } +class MetadataStats VALUE_OBJ_CLASS_SPEC { +private: + size_t _capacity; + size_t _used; + size_t _free; + size_t _waste; + +public: + MetadataStats() : _capacity(0), _used(0), _free(0), _waste(0) { } + MetadataStats(size_t capacity, size_t used, size_t free, size_t waste) + : _capacity(capacity), _used(used), _free(free), _waste(waste) { } + + void add(const MetadataStats& stats) { + _capacity += stats.capacity(); + _used += stats.used(); + _free += stats.free(); + _waste += stats.waste(); + } + + size_t capacity() const { return _capacity; } + size_t used() const { return _used; } + size_t free() const { return _free; } + size_t waste() const { return _waste; } + + void print_on(outputStream* out, size_t scale) const; +}; + + +void MetadataStats::print_on(outputStream* out, size_t scale) const { + const char* unit = scale_unit(scale); + out->print_cr("capacity=%10.2f%s used=%10.2f%s free=%10.2f%s waste=%10.2f%s", + (float)capacity() / scale, unit, + (float)used() / scale, unit, + (float)free() / scale, unit, + (float)waste() / scale, unit); +} + +class PrintCLDMetaspaceInfoClosure : public CLDClosure { +private: + outputStream* _out; + size_t _scale; + + size_t _total_count; + MetadataStats _total_metadata; + MetadataStats _total_class; + + size_t _total_anon_count; + MetadataStats _total_anon_metadata; + MetadataStats _total_anon_class; + +public: + PrintCLDMetaspaceInfoClosure(outputStream* out, size_t scale = K) + : _out(out), _scale(scale), _total_count(0), _total_anon_count(0) { } + + ~PrintCLDMetaspaceInfoClosure() { + print_summary(); + } + + void do_cld(ClassLoaderData* cld) { + assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint"); + + if (cld->is_unloading()) return; + Metaspace* msp = cld->metaspace_or_null(); + if (msp == NULL) { + return; + } + + bool anonymous = false; + if (cld->is_anonymous()) { + _out->print_cr("ClassLoader: for anonymous class"); + anonymous = true; + } else { + ResourceMark rm; + _out->print_cr("ClassLoader: %s", cld->loader_name()); + } + + print_metaspace(msp, anonymous); + _out->cr(); + } + +private: + void print_metaspace(Metaspace* msp, bool anonymous); + void print_summary() const; +}; + +void PrintCLDMetaspaceInfoClosure::print_metaspace(Metaspace* msp, bool anonymous){ + assert(msp != NULL, "Sanity"); + SpaceManager* vsm = msp->vsm(); + const char* unit = scale_unit(_scale); + + size_t capacity = vsm->sum_capacity_in_chunks_in_use() * BytesPerWord; + size_t used = vsm->sum_used_in_chunks_in_use() * BytesPerWord; + size_t free = vsm->sum_free_in_chunks_in_use() * BytesPerWord; + size_t waste = vsm->sum_waste_in_chunks_in_use() * BytesPerWord; + + _total_count ++; + MetadataStats metadata_stats(capacity, used, free, waste); + _total_metadata.add(metadata_stats); + + if (anonymous) { + _total_anon_count ++; + _total_anon_metadata.add(metadata_stats); + } + + _out->print(" Metadata "); + metadata_stats.print_on(_out, _scale); + + if (Metaspace::using_class_space()) { + vsm = msp->class_vsm(); + + capacity = vsm->sum_capacity_in_chunks_in_use() * BytesPerWord; + used = vsm->sum_used_in_chunks_in_use() * BytesPerWord; + free = vsm->sum_free_in_chunks_in_use() * BytesPerWord; + waste = vsm->sum_waste_in_chunks_in_use() * BytesPerWord; + + MetadataStats class_stats(capacity, used, free, waste); + _total_class.add(class_stats); + + if (anonymous) { + _total_anon_class.add(class_stats); + } + + _out->print(" Class data "); + class_stats.print_on(_out, _scale); + } +} + +void PrintCLDMetaspaceInfoClosure::print_summary() const { + const char* unit = scale_unit(_scale); + _out->cr(); + _out->print_cr("Summary:"); + + MetadataStats total; + total.add(_total_metadata); + total.add(_total_class); + + _out->print(" Total class loaders=" SIZE_FORMAT_W(6) " ", _total_count); + total.print_on(_out, _scale); + + _out->print(" Metadata "); + _total_metadata.print_on(_out, _scale); + + if (Metaspace::using_class_space()) { + _out->print(" Class data "); + _total_class.print_on(_out, _scale); + } + _out->cr(); + + MetadataStats total_anon; + total_anon.add(_total_anon_metadata); + total_anon.add(_total_anon_class); + + _out->print("For anonymous classes=" SIZE_FORMAT_W(6) " ", _total_anon_count); + total_anon.print_on(_out, _scale); + + _out->print(" Metadata "); + _total_anon_metadata.print_on(_out, _scale); + + if (Metaspace::using_class_space()) { + _out->print(" Class data "); + _total_anon_class.print_on(_out, _scale); + } +} + +void MetaspaceAux::print_metadata_for_nmt(outputStream* out, size_t scale) { + const char* unit = scale_unit(scale); + out->print_cr("Metaspaces:"); + out->print_cr(" Metadata space: reserved=" SIZE_FORMAT_W(10) "%s committed=" SIZE_FORMAT_W(10) "%s", + reserved_bytes(Metaspace::NonClassType) / scale, unit, + committed_bytes(Metaspace::NonClassType) / scale, unit); + if (Metaspace::using_class_space()) { + out->print_cr(" Class space: reserved=" SIZE_FORMAT_W(10) "%s committed=" SIZE_FORMAT_W(10) "%s", + reserved_bytes(Metaspace::ClassType) / scale, unit, + committed_bytes(Metaspace::ClassType) / scale, unit); + } + + out->cr(); + ChunkManager::print_all_chunkmanagers(out, scale); + + out->cr(); + out->print_cr("Per-classloader metadata:"); + out->cr(); + + PrintCLDMetaspaceInfoClosure cl(out, scale); + ClassLoaderDataGraph::cld_do(&cl); +} + + // Dump global metaspace things from the end of ClassLoaderDataGraph void MetaspaceAux::dump(outputStream* out) { out->print_cr("All Metaspace:"); @@ -2989,6 +3312,31 @@ void MetaspaceAux::dump(outputStream* out) { print_waste(out); } +// Prints an ASCII representation of the given space. +void MetaspaceAux::print_metaspace_map(outputStream* out, Metaspace::MetadataType mdtype) { + MutexLockerEx cl(SpaceManager::expand_lock(), Mutex::_no_safepoint_check_flag); + const bool for_class = mdtype == Metaspace::ClassType ? true : false; + VirtualSpaceList* const vsl = for_class ? Metaspace::class_space_list() : Metaspace::space_list(); + if (vsl != NULL) { + if (for_class) { + if (!Metaspace::using_class_space()) { + out->print_cr("No Class Space."); + return; + } + out->print_raw("---- Metaspace Map (Class Space) ----"); + } else { + out->print_raw("---- Metaspace Map (Non-Class Space) ----"); + } + // Print legend: + out->cr(); + out->print_cr("Chunk Types (uppercase chunks are in use): x-specialized, s-small, m-medium, h-humongous."); + out->cr(); + VirtualSpaceList* const vsl = for_class ? Metaspace::class_space_list() : Metaspace::space_list(); + vsl->print_map(out); + out->cr(); + } +} + void MetaspaceAux::verify_free_chunks() { Metaspace::chunk_manager_metadata()->verify(); if (Metaspace::using_class_space()) { @@ -3627,6 +3975,7 @@ void Metaspace::report_metadata_oome(ClassLoaderData* loader_data, size_t word_s } LogStream ls(log.info()); MetaspaceAux::dump(&ls); + MetaspaceAux::print_metaspace_map(&ls, mdtype); ChunkManager::print_all_chunkmanagers(&ls); } diff --git a/src/hotspot/share/memory/metaspace.hpp b/src/hotspot/share/memory/metaspace.hpp index bda5190c314..b9e86bd15b0 100644 --- a/src/hotspot/share/memory/metaspace.hpp +++ b/src/hotspot/share/memory/metaspace.hpp @@ -63,6 +63,7 @@ class MetaspaceTracer; class MetaWord; class Mutex; class outputStream; +class PrintCLDMetaspaceInfoClosure; class SpaceManager; class VirtualSpaceList; @@ -87,6 +88,7 @@ class Metaspace : public CHeapObj { friend class MetaspaceAux; friend class MetaspaceShared; friend class CollectorPolicy; + friend class PrintCLDMetaspaceInfoClosure; public: enum MetadataType { @@ -347,6 +349,8 @@ class MetaspaceAux : AllStatic { return min_chunk_size_words() * BytesPerWord; } + static void print_metadata_for_nmt(outputStream* out, size_t scale = K); + static bool has_chunk_free_list(Metaspace::MetadataType mdtype); static MetaspaceChunkFreeListSummary chunk_free_list_summary(Metaspace::MetadataType mdtype); @@ -357,6 +361,10 @@ class MetaspaceAux : AllStatic { static void print_class_waste(outputStream* out); static void print_waste(outputStream* out); + + // Prints an ASCII representation of the given space. + static void print_metaspace_map(outputStream* out, Metaspace::MetadataType mdtype); + static void dump(outputStream* out); static void verify_free_chunks(); // Checks that the values returned by allocated_capacity_bytes() and diff --git a/src/hotspot/share/oops/constantPool.cpp b/src/hotspot/share/oops/constantPool.cpp index f1aec2bff2e..9e1eefd5251 100644 --- a/src/hotspot/share/oops/constantPool.cpp +++ b/src/hotspot/share/oops/constantPool.cpp @@ -305,14 +305,9 @@ void ConstantPool::resolve_class_constants(TRAPS) { constantPoolHandle cp(THREAD, this); for (int index = 1; index < length(); index++) { // Index 0 is unused - if (tag_at(index).is_string()) { - Symbol* sym = cp->unresolved_string_at(index); - // Look up only. Only resolve references to already interned strings. - oop str = StringTable::lookup(sym); - if (str != NULL) { - int cache_index = cp->cp_to_object_index(index); - cp->string_at_put(index, cache_index, str); - } + if (tag_at(index).is_string() && !cp->is_pseudo_string_at(index)) { + int cache_index = cp->cp_to_object_index(index); + string_at_impl(cp, index, cache_index, CHECK); } } } diff --git a/src/hotspot/share/oops/method.hpp b/src/hotspot/share/oops/method.hpp index 0a7ee37f100..6866b833fdd 100644 --- a/src/hotspot/share/oops/method.hpp +++ b/src/hotspot/share/oops/method.hpp @@ -271,7 +271,7 @@ class Method : public Metadata { int highest_osr_comp_level() const; void set_highest_osr_comp_level(int level); -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI // Count of times method was exited via exception while interpreting void interpreter_throwout_increment(TRAPS) { MethodCounters* mcs = get_method_counters(CHECK); @@ -426,7 +426,7 @@ class Method : public Metadata { return (mcs == NULL) ? 0 : mcs->interpreter_invocation_count(); } } -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI int increment_interpreter_invocation_count(TRAPS) { if (TieredCompilation) ShouldNotReachHere(); MethodCounters* mcs = get_method_counters(CHECK_0); diff --git a/src/hotspot/share/oops/methodCounters.hpp b/src/hotspot/share/oops/methodCounters.hpp index 5b97cba61a8..1d526ca46d0 100644 --- a/src/hotspot/share/oops/methodCounters.hpp +++ b/src/hotspot/share/oops/methodCounters.hpp @@ -40,7 +40,7 @@ class MethodCounters : public Metadata { #if INCLUDE_AOT Method* _method; // Back link to Method #endif -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI int _interpreter_invocation_count; // Count of times invoked (reused as prev_event_count in tiered) u2 _interpreter_throwout_count; // Count of times method was exited via exception while interpreting #endif @@ -130,7 +130,7 @@ class MethodCounters : public Metadata { MetaspaceObj::Type type() const { return MethodCountersType; } void clear_counters(); -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI int interpreter_invocation_count() { return _interpreter_invocation_count; @@ -154,7 +154,7 @@ class MethodCounters : public Metadata { _interpreter_throwout_count = count; } -#else // defined(COMPILER2) || INCLUDE_JVMCI +#else // COMPILER2_OR_JVMCI int interpreter_invocation_count() { return 0; @@ -170,7 +170,7 @@ class MethodCounters : public Metadata { assert(count == 0, "count must be 0"); } -#endif // defined(COMPILER2) || INCLUDE_JVMCI +#endif // COMPILER2_OR_JVMCI #if INCLUDE_JVMTI u2 number_of_breakpoints() const { return _number_of_breakpoints; } @@ -213,7 +213,7 @@ class MethodCounters : public Metadata { return byte_offset_of(MethodCounters, _nmethod_age); } -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI static ByteSize interpreter_invocation_counter_offset() { return byte_offset_of(MethodCounters, _interpreter_invocation_count); @@ -223,14 +223,14 @@ class MethodCounters : public Metadata { return offset_of(MethodCounters, _interpreter_invocation_count); } -#else // defined(COMPILER2) || INCLUDE_JVMCI +#else // COMPILER2_OR_JVMCI static ByteSize interpreter_invocation_counter_offset() { ShouldNotReachHere(); return in_ByteSize(0); } -#endif // defined(COMPILER2) || INCLUDE_JVMCI +#endif // COMPILER2_OR_JVMCI static ByteSize invocation_counter_offset() { return byte_offset_of(MethodCounters, _invocation_counter); diff --git a/src/hotspot/share/prims/jni.cpp b/src/hotspot/share/prims/jni.cpp index ca0f634d7f5..15bc070fbfd 100644 --- a/src/hotspot/share/prims/jni.cpp +++ b/src/hotspot/share/prims/jni.cpp @@ -3949,7 +3949,7 @@ static jint JNI_CreateJavaVM_inner(JavaVM **vm, void **penv, void *args) { // JVMCI is initialized on a CompilerThread if (BootstrapJVMCI) { JavaThread* THREAD = thread; - JVMCICompiler* compiler = JVMCICompiler::instance(CATCH); + JVMCICompiler* compiler = JVMCICompiler::instance(true, CATCH); compiler->bootstrap(THREAD); if (HAS_PENDING_EXCEPTION) { HandleMark hm; diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp index f7cb20b9ab8..a6b04e79b37 100644 --- a/src/hotspot/share/prims/whitebox.cpp +++ b/src/hotspot/share/prims/whitebox.cpp @@ -1715,6 +1715,10 @@ WB_ENTRY(jobject, WB_GetResolvedReferences(JNIEnv* env, jobject wb, jclass clazz } WB_END +WB_ENTRY(jboolean, WB_AreOpenArchiveHeapObjectsMapped(JNIEnv* env)) + return MetaspaceShared::open_archive_heap_region_mapped(); +WB_END + WB_ENTRY(jboolean, WB_IsCDSIncludedInVmBuild(JNIEnv* env)) #if INCLUDE_CDS return true; @@ -2031,6 +2035,7 @@ static JNINativeMethod methods[] = { {CC"isSharedClass", CC"(Ljava/lang/Class;)Z", (void*)&WB_IsSharedClass }, {CC"areSharedStringsIgnored", CC"()Z", (void*)&WB_AreSharedStringsIgnored }, {CC"getResolvedReferences", CC"(Ljava/lang/Class;)Ljava/lang/Object;", (void*)&WB_GetResolvedReferences}, + {CC"areOpenArchiveHeapObjectsMapped", CC"()Z", (void*)&WB_AreOpenArchiveHeapObjectsMapped}, {CC"isCDSIncludedInVmBuild", CC"()Z", (void*)&WB_IsCDSIncludedInVmBuild }, {CC"clearInlineCaches0", CC"(Z)V", (void*)&WB_ClearInlineCaches }, {CC"addCompilerDirective", CC"(Ljava/lang/String;)I", diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index 263091cf981..b95ab1b00cd 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -396,6 +396,10 @@ static SpecialFlag const special_jvm_flags[] = { { "MinSleepInterval", JDK_Version::jdk(9), JDK_Version::jdk(10), JDK_Version::jdk(11) }, { "PermSize", JDK_Version::undefined(), JDK_Version::jdk(8), JDK_Version::undefined() }, { "MaxPermSize", JDK_Version::undefined(), JDK_Version::jdk(8), JDK_Version::undefined() }, + { "SharedReadWriteSize", JDK_Version::undefined(), JDK_Version::jdk(10), JDK_Version::undefined() }, + { "SharedReadOnlySize", JDK_Version::undefined(), JDK_Version::jdk(10), JDK_Version::undefined() }, + { "SharedMiscDataSize", JDK_Version::undefined(), JDK_Version::jdk(10), JDK_Version::undefined() }, + { "SharedMiscCodeSize", JDK_Version::undefined(), JDK_Version::jdk(10), JDK_Version::undefined() }, #ifdef TEST_VERIFY_SPECIAL_JVM_FLAGS { "dep > obs", JDK_Version::jdk(9), JDK_Version::jdk(8), JDK_Version::undefined() }, @@ -1860,7 +1864,7 @@ void Arguments::set_ergonomics_flags() { #endif select_gc(); -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI // Shared spaces work fine with other GCs but causes bytecode rewriting // to be disabled, which hurts interpreter performance and decreases // server performance. When -server is specified, keep the default off @@ -2089,9 +2093,10 @@ void Arguments::set_heap_size() { // respecting the maximum and minimum sizes of the heap. if (FLAG_IS_DEFAULT(MaxHeapSize)) { julong reasonable_max = (julong)((phys_mem * MaxRAMPercentage) / 100); - if (phys_mem <= (julong)((MaxHeapSize * MinRAMPercentage) / 100)) { + const julong reasonable_min = (julong)((phys_mem * MinRAMPercentage) / 100); + if (reasonable_min < MaxHeapSize) { // Small physical memory, so use a minimum fraction of it for the heap - reasonable_max = (julong)((phys_mem * MinRAMPercentage) / 100); + reasonable_max = reasonable_min; } else { // Not-small physical memory, so require a heap at least // as large as MaxHeapSize diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp index 087e26f5019..fb93fbdd712 100644 --- a/src/hotspot/share/runtime/deoptimization.cpp +++ b/src/hotspot/share/runtime/deoptimization.cpp @@ -192,7 +192,7 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread bool realloc_failures = false; -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI // Reallocate the non-escaping objects and restore their fields. Then // relock objects if synchronization on them was eliminated. #ifndef INCLUDE_JVMCI @@ -282,7 +282,7 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread } } #endif // INCLUDE_JVMCI -#endif // COMPILER2 || INCLUDE_JVMCI +#endif // COMPILER2_OR_JVMCI ScopeDesc* trap_scope = chunk->at(0)->scope(); Handle exceptionObject; @@ -303,7 +303,7 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread NoSafepointVerifier no_safepoint; vframeArray* array = create_vframeArray(thread, deoptee, &map, chunk, realloc_failures); -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI if (realloc_failures) { pop_frames_failed_reallocs(thread, array); } @@ -792,7 +792,7 @@ int Deoptimization::deoptimize_dependents() { Deoptimization::DeoptAction Deoptimization::_unloaded_action = Deoptimization::Action_reinterpret; -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI bool Deoptimization::realloc_objects(JavaThread* thread, frame* fr, GrowableArray* objects, TRAPS) { Handle pending_exception(THREAD, thread->pending_exception()); const char* exception_file = thread->exception_file(); @@ -1151,7 +1151,7 @@ void Deoptimization::print_objects(GrowableArray* objects, bool rea } } #endif -#endif // COMPILER2 || INCLUDE_JVMCI +#endif // COMPILER2_OR_JVMCI vframeArray* Deoptimization::create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray* chunk, bool realloc_failures) { Events::log(thread, "DEOPT PACKING pc=" INTPTR_FORMAT " sp=" INTPTR_FORMAT, p2i(fr.pc()), p2i(fr.sp())); @@ -1211,7 +1211,7 @@ vframeArray* Deoptimization::create_vframeArray(JavaThread* thread, frame fr, Re return array; } -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI void Deoptimization::pop_frames_failed_reallocs(JavaThread* thread, vframeArray* array) { // Reallocation of some scalar replaced objects failed. Record // that we need to pop all the interpreter frames for the @@ -1443,7 +1443,7 @@ Deoptimization::get_method_data(JavaThread* thread, const methodHandle& m, return mdo; } -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI void Deoptimization::load_class_by_index(const constantPoolHandle& constant_pool, int index, TRAPS) { // in case of an unresolved klass entry, load the class. if (constant_pool->tag_at(index).is_unresolved_klass()) { @@ -2350,7 +2350,7 @@ void Deoptimization::print_statistics() { if (xtty != NULL) xtty->tail("statistics"); } } -#else // COMPILER2 || INCLUDE_JVMCI +#else // COMPILER2_OR_JVMCI // Stubs for C1 only system. @@ -2386,4 +2386,4 @@ const char* Deoptimization::format_trap_state(char* buf, size_t buflen, return buf; } -#endif // COMPILER2 || INCLUDE_JVMCI +#endif // COMPILER2_OR_JVMCI diff --git a/src/hotspot/share/runtime/deoptimization.hpp b/src/hotspot/share/runtime/deoptimization.hpp index 0f151301e5c..2d4e9ee6f6e 100644 --- a/src/hotspot/share/runtime/deoptimization.hpp +++ b/src/hotspot/share/runtime/deoptimization.hpp @@ -151,7 +151,7 @@ class Deoptimization : AllStatic { // executing in a particular CodeBlob if UseBiasedLocking is enabled static void revoke_biases_of_monitors(CodeBlob* cb); -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI JVMCI_ONLY(public:) // Support for restoring non-escaping objects @@ -162,7 +162,7 @@ JVMCI_ONLY(public:) static void relock_objects(GrowableArray* monitors, JavaThread* thread, bool realloc_failures); static void pop_frames_failed_reallocs(JavaThread* thread, vframeArray* array); NOT_PRODUCT(static void print_objects(GrowableArray* objects, bool realloc_failures);) -#endif // COMPILER2 || INCLUDE_JVMCI +#endif // COMPILER2_OR_JVMCI public: static vframeArray* create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray* chunk, bool realloc_failures); diff --git a/src/hotspot/share/runtime/frame.cpp b/src/hotspot/share/runtime/frame.cpp index 1ae48bdedf9..49516ea8d40 100644 --- a/src/hotspot/share/runtime/frame.cpp +++ b/src/hotspot/share/runtime/frame.cpp @@ -1148,7 +1148,7 @@ void frame::verify(const RegisterMap* map) { // make sure we have the right receiver type } } -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI assert(DerivedPointerTable::is_empty(), "must be empty before verify"); #endif oops_do_internal(&VerifyOopClosure::verify_oop, NULL, (RegisterMap*)map, false); diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index 557605d2108..83a9088f5fc 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -99,11 +99,11 @@ define_pd_global(uint64_t,MaxRAM, 1ULL*G); #define CI_COMPILER_COUNT 0 #else -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI #define CI_COMPILER_COUNT 2 #else #define CI_COMPILER_COUNT 1 -#endif // COMPILER2 || INCLUDE_JVMCI +#endif // COMPILER2_OR_JVMCI #endif // no compilers @@ -3901,18 +3901,6 @@ public: "If PrintSharedArchiveAndExit is true, also print the shared " \ "dictionary") \ \ - product(size_t, SharedReadWriteSize, 0, \ - "Deprecated") \ - \ - product(size_t, SharedReadOnlySize, 0, \ - "Deprecated") \ - \ - product(size_t, SharedMiscDataSize, 0, \ - "Deprecated") \ - \ - product(size_t, SharedMiscCodeSize, 0, \ - "Deprecated") \ - \ product(size_t, SharedBaseAddress, LP64_ONLY(32*G) \ NOT_LP64(LINUX_ONLY(2*G) NOT_LINUX(0)), \ "Address to allocate shared memory region for class data") \ diff --git a/src/hotspot/share/runtime/rframe.cpp b/src/hotspot/share/runtime/rframe.cpp index 40283896d85..5b948ac48cb 100644 --- a/src/hotspot/share/runtime/rframe.cpp +++ b/src/hotspot/share/runtime/rframe.cpp @@ -155,7 +155,7 @@ void InterpretedRFrame::init() { void RFrame::print(const char* kind) { #ifndef PRODUCT -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI int cnt = top_method()->interpreter_invocation_count(); #else int cnt = top_method()->invocation_count(); diff --git a/src/hotspot/share/runtime/sharedRuntime.cpp b/src/hotspot/share/runtime/sharedRuntime.cpp index 7cb09c201e4..8e4c90f9199 100644 --- a/src/hotspot/share/runtime/sharedRuntime.cpp +++ b/src/hotspot/share/runtime/sharedRuntime.cpp @@ -102,13 +102,13 @@ void SharedRuntime::generate_stubs() { _resolve_static_call_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::resolve_static_call_C), "resolve_static_call"); _resolve_static_call_entry = _resolve_static_call_blob->entry_point(); -#if defined(COMPILER2) || INCLUDE_JVMCI +#if COMPILER2_OR_JVMCI // Vectors are generated only by C2 and JVMCI. bool support_wide = is_wide_vector(MaxVectorSize); if (support_wide) { _polling_page_vectors_safepoint_handler_blob = generate_handler_blob(CAST_FROM_FN_PTR(address, SafepointSynchronize::handle_polling_page_exception), POLL_AT_VECTOR_LOOP); } -#endif // COMPILER2 || INCLUDE_JVMCI +#endif // COMPILER2_OR_JVMCI _polling_page_safepoint_handler_blob = generate_handler_blob(CAST_FROM_FN_PTR(address, SafepointSynchronize::handle_polling_page_exception), POLL_AT_LOOP); _polling_page_return_handler_blob = generate_handler_blob(CAST_FROM_FN_PTR(address, SafepointSynchronize::handle_polling_page_exception), POLL_AT_RETURN); diff --git a/src/hotspot/share/runtime/thread.cpp b/src/hotspot/share/runtime/thread.cpp index 9ffff8a0405..635625b1655 100644 --- a/src/hotspot/share/runtime/thread.cpp +++ b/src/hotspot/share/runtime/thread.cpp @@ -3724,7 +3724,7 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { } // initialize compiler(s) -#if defined(COMPILER1) || defined(COMPILER2) || INCLUDE_JVMCI +#if defined(COMPILER1) || COMPILER2_OR_JVMCI CompileBroker::compilation_init(CHECK_JNI_ERR); #endif diff --git a/src/hotspot/share/runtime/vm_operations.cpp b/src/hotspot/share/runtime/vm_operations.cpp index 95c9943aefb..e9ad8af4314 100644 --- a/src/hotspot/share/runtime/vm_operations.cpp +++ b/src/hotspot/share/runtime/vm_operations.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -230,6 +230,10 @@ void VM_PrintJNI::doit() { JNIHandles::print_on(_out); } +void VM_PrintMetadata::doit() { + MetaspaceAux::print_metadata_for_nmt(_out, _scale); +} + VM_FindDeadlocks::~VM_FindDeadlocks() { if (_deadlocks != NULL) { DeadlockCycle* cycle = _deadlocks; diff --git a/src/hotspot/share/runtime/vm_operations.hpp b/src/hotspot/share/runtime/vm_operations.hpp index 52e4606cf35..b325d484a02 100644 --- a/src/hotspot/share/runtime/vm_operations.hpp +++ b/src/hotspot/share/runtime/vm_operations.hpp @@ -111,6 +111,7 @@ template(ThreadsSuspendJVMTI) \ template(ICBufferFull) \ template(ScavengeMonitors) \ + template(PrintMetadata) \ class VM_Operation: public CHeapObj { public: @@ -374,6 +375,17 @@ class VM_PrintJNI: public VM_Operation { void doit(); }; +class VM_PrintMetadata : public VM_Operation { + private: + outputStream* _out; + size_t _scale; + public: + VM_PrintMetadata(outputStream* out, size_t scale) : _out(out), _scale(scale) {}; + + VMOp_Type type() const { return VMOp_PrintMetadata; } + void doit(); +}; + class DeadlockCycle; class VM_FindDeadlocks: public VM_Operation { private: diff --git a/src/hotspot/share/services/nmtDCmd.cpp b/src/hotspot/share/services/nmtDCmd.cpp index 6620bde60b0..fe329b78f01 100644 --- a/src/hotspot/share/services/nmtDCmd.cpp +++ b/src/hotspot/share/services/nmtDCmd.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved. * 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,8 @@ #include "precompiled.hpp" #include "memory/resourceArea.hpp" #include "runtime/mutexLocker.hpp" +#include "runtime/vmThread.hpp" +#include "runtime/vm_operations.hpp" #include "services/nmtDCmd.hpp" #include "services/memReporter.hpp" #include "services/memTracker.hpp" @@ -38,6 +40,8 @@ NMTDCmd::NMTDCmd(outputStream* output, _detail("detail", "request runtime to report memory allocation >= " "1K by each callsite.", "BOOLEAN", false, "false"), + _metadata("metadata", "request runtime to report metadata information", + "BOOLEAN", false, "false"), _baseline("baseline", "request runtime to baseline current memory usage, " \ "so it can be compared against in later time.", "BOOLEAN", false, "false"), @@ -57,6 +61,7 @@ NMTDCmd::NMTDCmd(outputStream* output, "STRING", false, "KB") { _dcmdparser.add_dcmd_option(&_summary); _dcmdparser.add_dcmd_option(&_detail); + _dcmdparser.add_dcmd_option(&_metadata); _dcmdparser.add_dcmd_option(&_baseline); _dcmdparser.add_dcmd_option(&_summary_diff); _dcmdparser.add_dcmd_option(&_detail_diff); @@ -92,6 +97,7 @@ void NMTDCmd::execute(DCmdSource source, TRAPS) { int nopt = 0; if (_summary.is_set() && _summary.value()) { ++nopt; } if (_detail.is_set() && _detail.value()) { ++nopt; } + if (_metadata.is_set() && _metadata.value()) { ++nopt; } if (_baseline.is_set() && _baseline.value()) { ++nopt; } if (_summary_diff.is_set() && _summary_diff.value()) { ++nopt; } if (_detail_diff.is_set() && _detail_diff.value()) { ++nopt; } @@ -100,7 +106,7 @@ void NMTDCmd::execute(DCmdSource source, TRAPS) { if (nopt > 1) { output()->print_cr("At most one of the following option can be specified: " \ - "summary, detail, baseline, summary.diff, detail.diff, shutdown"); + "summary, detail, metadata, baseline, summary.diff, detail.diff, shutdown"); return; } else if (nopt == 0) { if (_summary.is_set()) { @@ -118,9 +124,13 @@ void NMTDCmd::execute(DCmdSource source, TRAPS) { report(true, scale_unit); } else if (_detail.value()) { if (!check_detail_tracking_level(output())) { - return; - } + return; + } report(false, scale_unit); + } else if (_metadata.value()) { + size_t scale = get_scale(_scale.value()); + VM_PrintMetadata op(output(), scale); + VMThread::execute(&op); } else if (_baseline.value()) { MemBaseline& baseline = MemTracker::get_baseline(); if (!baseline.baseline(MemTracker::tracking_level() != NMT_detail)) { diff --git a/src/hotspot/share/services/nmtDCmd.hpp b/src/hotspot/share/services/nmtDCmd.hpp index df1ab367fd1..c1ede016b8a 100644 --- a/src/hotspot/share/services/nmtDCmd.hpp +++ b/src/hotspot/share/services/nmtDCmd.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,7 @@ class NMTDCmd: public DCmdWithParser { protected: DCmdArgument _summary; DCmdArgument _detail; + DCmdArgument _metadata; DCmdArgument _baseline; DCmdArgument _summary_diff; DCmdArgument _detail_diff; diff --git a/src/java.base/share/classes/java/io/FilePermission.java b/src/java.base/share/classes/java/io/FilePermission.java index 39cded53b27..0cdb660145f 100644 --- a/src/java.base/share/classes/java/io/FilePermission.java +++ b/src/java.base/share/classes/java/io/FilePermission.java @@ -698,7 +698,7 @@ public final class FilePermission extends Permission implements Serializable { if (p2.equals(EMPTY_PATH)) { return 0; } else if (p2.getName(0).equals(DOTDOT_PATH)) { - // "." contains p2 iif p2 has no "..". Since a + // "." contains p2 iff p2 has no "..". Since // a normalized path can only have 0 or more // ".." at the beginning. We only need to look // at the head. @@ -711,7 +711,7 @@ public final class FilePermission extends Permission implements Serializable { } else if (p2.equals(EMPTY_PATH)) { int c1 = p1.getNameCount(); if (!p1.getName(c1 - 1).equals(DOTDOT_PATH)) { - // "." is inside p1 iif p1 is 1 or more "..". + // "." is inside p1 iff p1 is 1 or more "..". // For the same reason above, we only need to // look at the tail. return -1; diff --git a/src/java.base/share/classes/java/lang/Module.java b/src/java.base/share/classes/java/lang/Module.java index 82c83769ef0..2f942816ab5 100644 --- a/src/java.base/share/classes/java/lang/Module.java +++ b/src/java.base/share/classes/java/lang/Module.java @@ -57,8 +57,6 @@ import java.util.stream.Stream; import jdk.internal.loader.BuiltinClassLoader; import jdk.internal.loader.BootLoader; import jdk.internal.loader.ClassLoaders; -import jdk.internal.misc.JavaLangAccess; -import jdk.internal.misc.SharedSecrets; import jdk.internal.module.IllegalAccessLogger; import jdk.internal.module.ModuleLoaderMap; import jdk.internal.module.ServicesCatalog; @@ -68,6 +66,7 @@ import jdk.internal.org.objectweb.asm.Attribute; import jdk.internal.org.objectweb.asm.ClassReader; import jdk.internal.org.objectweb.asm.ClassVisitor; import jdk.internal.org.objectweb.asm.ClassWriter; +import jdk.internal.org.objectweb.asm.ModuleVisitor; import jdk.internal.org.objectweb.asm.Opcodes; import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.Reflection; @@ -1432,7 +1431,7 @@ public final class Module implements AnnotatedElement { ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES); - ClassVisitor cv = new ClassVisitor(Opcodes.ASM5, cw) { + ClassVisitor cv = new ClassVisitor(Opcodes.ASM6, cw) { @Override public void visit(int version, int access, @@ -1458,6 +1457,11 @@ public final class Module implements AnnotatedElement { public void visitAttribute(Attribute attr) { // drop non-annotation attributes } + @Override + public ModuleVisitor visitModule(String name, int flags, String version) { + // drop Module attribute + return null; + } }; ClassReader cr = new ClassReader(in); diff --git a/src/java.base/share/classes/java/lang/System.java b/src/java.base/share/classes/java/lang/System.java index 8388dce7562..86ec3c5cad3 100644 --- a/src/java.base/share/classes/java/lang/System.java +++ b/src/java.base/share/classes/java/lang/System.java @@ -1937,7 +1937,7 @@ public final class System { // initialization. So make sure the "props" is available at the // very beginning of the initialization and all system properties to // be put into it directly. - props = new Properties(); + props = new Properties(84); initProperties(props); // initialized by the VM // There are certain system configurations that may be controlled by diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandle.java b/src/java.base/share/classes/java/lang/invoke/MethodHandle.java index 60092d33d73..8b9c0ec9cc2 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandle.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandle.java @@ -765,7 +765,7 @@ public abstract class MethodHandle { * In every other case, all conversions are applied pairwise, * which means that each argument or return value is converted to * exactly one argument or return value (or no return value). - * The applied conversions are defined by consulting the + * The applied conversions are defined by consulting * the corresponding component types of the old and new * method handle types. *

diff --git a/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java b/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java index 4bc58803c90..72feb9f1ca0 100644 --- a/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java +++ b/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java @@ -194,7 +194,7 @@ public final class StringConcatFactory { static { // In case we need to double-back onto the StringConcatFactory during this // static initialization, make sure we have the reasonable defaults to complete - // the static initialization properly. After that, actual users would use the + // the static initialization properly. After that, actual users would use // the proper values we have read from the properties. STRATEGY = DEFAULT_STRATEGY; // CACHE_ENABLE = false; // implied diff --git a/src/java.base/share/classes/java/lang/invoke/VarHandle.java b/src/java.base/share/classes/java/lang/invoke/VarHandle.java index 9f24c2907a4..5194d6ee981 100644 --- a/src/java.base/share/classes/java/lang/invoke/VarHandle.java +++ b/src/java.base/share/classes/java/lang/invoke/VarHandle.java @@ -205,7 +205,7 @@ import static java.lang.invoke.MethodHandleStatics.newInternalError; * and {@code double} on 32-bit platforms. * *

Access modes will override any memory ordering effects specified at - * the declaration site of a variable. For example, a VarHandle accessing a + * the declaration site of a variable. For example, a VarHandle accessing * a field using the {@code get} access mode will access the field as * specified by its access mode even if that field is declared * {@code volatile}. When mixed access is performed extreme care should be @@ -423,7 +423,7 @@ import static java.lang.invoke.MethodHandleStatics.newInternalError; * {@link java.lang.invoke.MethodHandles#varHandleInvoker}. * *

Interoperation between VarHandles and Java generics

- * A VarHandle can be obtained for a variable, such as a a field, which is + * A VarHandle can be obtained for a variable, such as a field, which is * declared with Java generic types. As with the Core Reflection API, the * VarHandle's variable type will be constructed from the erasure of the * source-level type. When a VarHandle access mode method is invoked, the diff --git a/src/java.base/share/classes/java/net/DatagramSocket.java b/src/java.base/share/classes/java/net/DatagramSocket.java index 7a447cb0acd..43e42e38042 100644 --- a/src/java.base/share/classes/java/net/DatagramSocket.java +++ b/src/java.base/share/classes/java/net/DatagramSocket.java @@ -988,7 +988,7 @@ class DatagramSocket implements java.io.Closeable { /** * Sets the SO_RCVBUF option to the specified value for this - * {@code DatagramSocket}. The SO_RCVBUF option is used by the + * {@code DatagramSocket}. The SO_RCVBUF option is used by * the network implementation as a hint to size the underlying * network I/O buffers. The SO_RCVBUF setting may also be used * by the network implementation to determine the maximum size diff --git a/src/java.base/share/classes/java/net/Inet4Address.java b/src/java.base/share/classes/java/net/Inet4Address.java index 25c5ab41224..daf7d86bc05 100644 --- a/src/java.base/share/classes/java/net/Inet4Address.java +++ b/src/java.base/share/classes/java/net/Inet4Address.java @@ -143,7 +143,7 @@ class Inet4Address extends InetAddress { /** * Prior to 1.4 an InetAddress was created with a family * based on the platform AF_INET value (usually 2). - * For compatibility reasons we must therefore write the + * For compatibility reasons we must therefore write * the InetAddress with this family. */ inet.holder().family = 2; diff --git a/src/java.base/share/classes/java/net/SocketImpl.java b/src/java.base/share/classes/java/net/SocketImpl.java index 60fe083445a..1c2060c7f15 100644 --- a/src/java.base/share/classes/java/net/SocketImpl.java +++ b/src/java.base/share/classes/java/net/SocketImpl.java @@ -333,7 +333,7 @@ public abstract class SocketImpl implements SocketOptions { * latency, and low latency above short connection time, then it could * invoke this method with the values {@code (0, 1, 2)}. * - * By default, this method does nothing, unless it is overridden in a + * By default, this method does nothing, unless it is overridden in * a sub-class. * * @param connectionTime diff --git a/src/java.base/share/classes/java/net/SocksSocketImpl.java b/src/java.base/share/classes/java/net/SocksSocketImpl.java index f8ea9ce6c16..3fe64a9c849 100644 --- a/src/java.base/share/classes/java/net/SocksSocketImpl.java +++ b/src/java.base/share/classes/java/net/SocksSocketImpl.java @@ -657,7 +657,7 @@ class SocksSocketImpl extends PlainSocketImpl implements SocksConsts { /** * Sends the Bind request to the SOCKS proxy. In the SOCKS protocol, bind - * means "accept incoming connection from", so the SocketAddress is the + * means "accept incoming connection from", so the SocketAddress is * the one of the host we do accept connection from. * * @param saddr the Socket address of the remote host. diff --git a/src/java.base/share/classes/java/net/URLConnection.java b/src/java.base/share/classes/java/net/URLConnection.java index a5c30df3d4b..2b52e07e921 100644 --- a/src/java.base/share/classes/java/net/URLConnection.java +++ b/src/java.base/share/classes/java/net/URLConnection.java @@ -785,7 +785,7 @@ public abstract class URLConnection { * required to make the connection. By default, this method * returns {@code java.security.AllPermission}. Subclasses * should override this method and return the permission - * that best represents the permission required to make a + * that best represents the permission required to make * a connection to the URL. For example, a {@code URLConnection} * representing a {@code file:} URL would return a * {@code java.io.FilePermission} object. diff --git a/src/java.base/share/classes/java/nio/channels/AsynchronousFileChannel.java b/src/java.base/share/classes/java/nio/channels/AsynchronousFileChannel.java index 0c0d0e6d3b5..26d2313f5f8 100644 --- a/src/java.base/share/classes/java/nio/channels/AsynchronousFileChannel.java +++ b/src/java.base/share/classes/java/nio/channels/AsynchronousFileChannel.java @@ -165,7 +165,7 @@ public abstract class AsynchronousFileChannel * * {@link StandardOpenOption#DELETE_ON_CLOSE DELETE_ON_CLOSE} * When this option is present then the implementation makes a - * best effort attempt to delete the file when closed by the + * best effort attempt to delete the file when closed by * the {@link #close close} method. If the {@code close} method is not * invoked then a best effort attempt is made to delete the file * when the Java virtual machine terminates. diff --git a/src/java.base/share/classes/java/nio/channels/Channels.java b/src/java.base/share/classes/java/nio/channels/Channels.java index 20a8cdd476d..2a4254711b3 100644 --- a/src/java.base/share/classes/java/nio/channels/Channels.java +++ b/src/java.base/share/classes/java/nio/channels/Channels.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -368,6 +368,10 @@ public final class Channels { @Override public int read(ByteBuffer dst) throws IOException { + if (!isOpen()) { + throw new ClosedChannelException(); + } + int len = dst.remaining(); int totalRead = 0; int bytesRead = 0; @@ -442,6 +446,10 @@ public final class Channels { @Override public int write(ByteBuffer src) throws IOException { + if (!isOpen()) { + throw new ClosedChannelException(); + } + int len = src.remaining(); int totalWritten = 0; synchronized (writeLock) { diff --git a/src/java.base/share/classes/java/nio/channels/FileChannel.java b/src/java.base/share/classes/java/nio/channels/FileChannel.java index 9ee447dbaf6..4463e5a5d82 100644 --- a/src/java.base/share/classes/java/nio/channels/FileChannel.java +++ b/src/java.base/share/classes/java/nio/channels/FileChannel.java @@ -216,7 +216,7 @@ public abstract class FileChannel * * {@link StandardOpenOption#DELETE_ON_CLOSE DELETE_ON_CLOSE} * When this option is present then the implementation makes a - * best effort attempt to delete the file when closed by the + * best effort attempt to delete the file when closed by * the {@link #close close} method. If the {@code close} method is not * invoked then a best effort attempt is made to delete the file * when the Java virtual machine terminates. diff --git a/src/java.base/share/classes/java/nio/file/Files.java b/src/java.base/share/classes/java/nio/file/Files.java index f5dbba9c358..c7e0dcf9938 100644 --- a/src/java.base/share/classes/java/nio/file/Files.java +++ b/src/java.base/share/classes/java/nio/file/Files.java @@ -2401,7 +2401,7 @@ public final class Files { * *

Note that the result of this method is immediately outdated. If this * method indicates the file exists then there is no guarantee that a - * subsequence access will succeed. Care should be taken when using this + * subsequent access will succeed. Care should be taken when using this * method in security sensitive applications. * * @param path @@ -2458,7 +2458,7 @@ public final class Files { * or not then both methods return {@code false}. As with the {@code exists} * method, the result of this method is immediately outdated. If this * method indicates the file does exist then there is no guarantee that a - * subsequence attempt to create the file will succeed. Care should be taken + * subsequent attempt to create the file will succeed. Care should be taken * when using this method in security sensitive applications. * * @param path @@ -3301,7 +3301,7 @@ public final class Files { } /** - * Writes bytes to a file. The {@code options} parameter specifies how the + * Writes bytes to a file. The {@code options} parameter specifies how * the file is created or opened. If no options are present then this method * works as if the {@link StandardOpenOption#CREATE CREATE}, {@link * StandardOpenOption#TRUNCATE_EXISTING TRUNCATE_EXISTING}, and {@link diff --git a/src/java.base/share/classes/java/security/KeyPairGenerator.java b/src/java.base/share/classes/java/security/KeyPairGenerator.java index cd9a0a51263..eee081ae51e 100644 --- a/src/java.base/share/classes/java/security/KeyPairGenerator.java +++ b/src/java.base/share/classes/java/security/KeyPairGenerator.java @@ -84,7 +84,7 @@ import sun.security.util.Debug; * exists (e.g., so-called community parameters in DSA), there are two * {@link #initialize(java.security.spec.AlgorithmParameterSpec) * initialize} methods that have an {@code AlgorithmParameterSpec} - * argument. One also has a {@code SecureRandom} argument, while the + * argument. One also has a {@code SecureRandom} argument, while * the other uses the {@code SecureRandom} * implementation of the highest-priority installed provider as the source * of randomness. (If none of the installed providers supply an implementation diff --git a/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java b/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java index f734fdd9d02..ebf044919a4 100644 --- a/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java +++ b/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java @@ -4775,7 +4775,7 @@ public final class DateTimeFormatterBuilder { //----------------------------------------------------------------------- /** * Prints or parses a localized pattern from a localized field. - * The specific formatter and parameters is not selected until the + * The specific formatter and parameters is not selected until * the field is to be printed or parsed. * The locale is needed to select the proper WeekFields from which * the field for day-of-week, week-of-month, or week-of-year is selected. diff --git a/src/java.base/share/classes/java/time/temporal/WeekFields.java b/src/java.base/share/classes/java/time/temporal/WeekFields.java index 60478772d9f..0046bef9b68 100644 --- a/src/java.base/share/classes/java/time/temporal/WeekFields.java +++ b/src/java.base/share/classes/java/time/temporal/WeekFields.java @@ -311,7 +311,7 @@ public final class WeekFields implements Serializable { * the new month or year. *

* WeekFields instances are singletons; for each unique combination - * of {@code firstDayOfWeek} and {@code minimalDaysInFirstWeek} the + * of {@code firstDayOfWeek} and {@code minimalDaysInFirstWeek} * the same instance will be returned. * * @param firstDayOfWeek the first day of the week, not null diff --git a/src/java.base/share/classes/java/util/Base64.java b/src/java.base/share/classes/java/util/Base64.java index 43e3d0690cd..0973a63844c 100644 --- a/src/java.base/share/classes/java/util/Base64.java +++ b/src/java.base/share/classes/java/util/Base64.java @@ -56,7 +56,7 @@ import java.nio.charset.StandardCharsets; * base64 alphabet.

* *
  • MIME - *

    Uses the "The Base64 Alphabet" as specified in Table 1 of + *

    Uses "The Base64 Alphabet" as specified in Table 1 of * RFC 2045 for encoding and decoding operation. The encoded output * must be represented in lines of no more than 76 characters each * and uses a carriage return {@code '\r'} followed immediately by diff --git a/src/java.base/share/classes/java/util/DoubleSummaryStatistics.java b/src/java.base/share/classes/java/util/DoubleSummaryStatistics.java index 066c5d2d115..192a5bcb985 100644 --- a/src/java.base/share/classes/java/util/DoubleSummaryStatistics.java +++ b/src/java.base/share/classes/java/util/DoubleSummaryStatistics.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ package java.util; import java.util.function.DoubleConsumer; import java.util.stream.Collector; +import java.util.stream.DoubleStream; /** * A state object for collecting statistics such as count, min, max, sum, and @@ -69,12 +70,65 @@ public class DoubleSummaryStatistics implements DoubleConsumer { private double max = Double.NEGATIVE_INFINITY; /** - * Construct an empty instance with zero count, zero sum, + * Constructs an empty instance with zero count, zero sum, * {@code Double.POSITIVE_INFINITY} min, {@code Double.NEGATIVE_INFINITY} * max and zero average. */ public DoubleSummaryStatistics() { } + /** + * Constructs a non-empty instance with the specified {@code count}, + * {@code min}, {@code max}, and {@code sum}. + * + *

    If {@code count} is zero then the remaining arguments are ignored and + * an empty instance is constructed. + * + *

    If the arguments are inconsistent then an {@code IllegalArgumentException} + * is thrown. The necessary consistent argument conditions are: + *

      + *
    • {@code count >= 0}
    • + *
    • {@code (min <= max && !isNaN(sum)) || (isNaN(min) && isNaN(max) && isNaN(sum))}
    • + *
    + * @apiNote + * The enforcement of argument correctness means that the retrieved set of + * recorded values obtained from a {@code DoubleSummaryStatistics} source + * instance may not be a legal set of arguments for this constructor due to + * arithmetic overflow of the source's recorded count of values. + * The consistent argument conditions are not sufficient to prevent the + * creation of an internally inconsistent instance. An example of such a + * state would be an instance with: {@code count} = 2, {@code min} = 1, + * {@code max} = 2, and {@code sum} = 0. + * + * @param count the count of values + * @param min the minimum value + * @param max the maximum value + * @param sum the sum of all values + * @throws IllegalArgumentException if the arguments are inconsistent + * @since 10 + */ + public DoubleSummaryStatistics(long count, double min, double max, double sum) + throws IllegalArgumentException { + if (count < 0L) { + throw new IllegalArgumentException("Negative count value"); + } else if (count > 0L) { + if (min > max) + throw new IllegalArgumentException("Minimum greater than maximum"); + + // All NaN or non NaN + var ncount = DoubleStream.of(min, max, sum).filter(Double::isNaN).count(); + if (ncount > 0 && ncount < 3) + throw new IllegalArgumentException("Some, not all, of the minimum, maximum, or sum is NaN"); + + this.count = count; + this.sum = sum; + this.simpleSum = sum; + this.sumCompensation = 0.0d; + this.min = min; + this.max = max; + } + // Use default field values if count == 0 + } + /** * Records another value into the summary information. * diff --git a/src/java.base/share/classes/java/util/EventObject.java b/src/java.base/share/classes/java/util/EventObject.java index 99f58eb434e..ff89754a185 100644 --- a/src/java.base/share/classes/java/util/EventObject.java +++ b/src/java.base/share/classes/java/util/EventObject.java @@ -43,13 +43,13 @@ public class EventObject implements java.io.Serializable { /** * The object on which the Event initially occurred. */ - protected transient Object source; + protected transient Object source; /** * Constructs a prototypical Event. * - * @param source The object on which the Event initially occurred. - * @exception IllegalArgumentException if source is null. + * @param source the object on which the Event initially occurred + * @throws IllegalArgumentException if source is null */ public EventObject(Object source) { if (source == null) @@ -61,7 +61,7 @@ public class EventObject implements java.io.Serializable { /** * The object on which the Event initially occurred. * - * @return The object on which the Event initially occurred. + * @return the object on which the Event initially occurred */ public Object getSource() { return source; @@ -70,7 +70,7 @@ public class EventObject implements java.io.Serializable { /** * Returns a String representation of this EventObject. * - * @return A a String representation of this EventObject. + * @return a String representation of this EventObject */ public String toString() { return getClass().getName() + "[source=" + source + "]"; diff --git a/src/java.base/share/classes/java/util/FormattableFlags.java b/src/java.base/share/classes/java/util/FormattableFlags.java index 6c9962c3dba..92c020f9991 100644 --- a/src/java.base/share/classes/java/util/FormattableFlags.java +++ b/src/java.base/share/classes/java/util/FormattableFlags.java @@ -26,7 +26,7 @@ package java.util; /** - * FomattableFlags are passed to the {@link Formattable#formatTo + * FormattableFlags are passed to the {@link Formattable#formatTo * Formattable.formatTo()} method and modify the output format for {@linkplain * Formattable Formattables}. Implementations of {@link Formattable} are * responsible for interpreting and validating any flags. diff --git a/src/java.base/share/classes/java/util/IntSummaryStatistics.java b/src/java.base/share/classes/java/util/IntSummaryStatistics.java index f5691a8b672..9043c8a15cd 100644 --- a/src/java.base/share/classes/java/util/IntSummaryStatistics.java +++ b/src/java.base/share/classes/java/util/IntSummaryStatistics.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -69,12 +69,57 @@ public class IntSummaryStatistics implements IntConsumer { private int max = Integer.MIN_VALUE; /** - * Construct an empty instance with zero count, zero sum, + * Constructs an empty instance with zero count, zero sum, * {@code Integer.MAX_VALUE} min, {@code Integer.MIN_VALUE} max and zero * average. */ public IntSummaryStatistics() { } + /** + * Constructs a non-empty instance with the specified {@code count}, + * {@code min}, {@code max}, and {@code sum}. + * + *

    If {@code count} is zero then the remaining arguments are ignored and + * an empty instance is constructed. + * + *

    If the arguments are inconsistent then an {@code IllegalArgumentException} + * is thrown. The necessary consistent argument conditions are: + *

      + *
    • {@code count >= 0}
    • + *
    • {@code min <= max}
    • + *
    + * @apiNote + * The enforcement of argument correctness means that the retrieved set of + * recorded values obtained from a {@code IntSummaryStatistics} source + * instance may not be a legal set of arguments for this constructor due to + * arithmetic overflow of the source's recorded count of values. + * The consistent argument conditions are not sufficient to prevent the + * creation of an internally inconsistent instance. An example of such a + * state would be an instance with: {@code count} = 2, {@code min} = 1, + * {@code max} = 2, and {@code sum} = 0. + * + * @param count the count of values + * @param min the minimum value + * @param max the maximum value + * @param sum the sum of all values + * @throws IllegalArgumentException if the arguments are inconsistent + * @since 10 + */ + public IntSummaryStatistics(long count, int min, int max, long sum) + throws IllegalArgumentException { + if (count < 0L) { + throw new IllegalArgumentException("Negative count value"); + } else if (count > 0L) { + if (min > max) throw new IllegalArgumentException("Minimum greater than maximum"); + + this.count = count; + this.sum = sum; + this.min = min; + this.max = max; + } + // Use default field values if count == 0 + } + /** * Records a new value into the summary information * diff --git a/src/java.base/share/classes/java/util/LongSummaryStatistics.java b/src/java.base/share/classes/java/util/LongSummaryStatistics.java index 1ae091c1102..06ad64795da 100644 --- a/src/java.base/share/classes/java/util/LongSummaryStatistics.java +++ b/src/java.base/share/classes/java/util/LongSummaryStatistics.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved. * 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,12 +70,57 @@ public class LongSummaryStatistics implements LongConsumer, IntConsumer { private long max = Long.MIN_VALUE; /** - * Construct an empty instance with zero count, zero sum, + * Constructs an empty instance with zero count, zero sum, * {@code Long.MAX_VALUE} min, {@code Long.MIN_VALUE} max and zero * average. */ public LongSummaryStatistics() { } + /** + * Constructs a non-empty instance with the specified {@code count}, + * {@code min}, {@code max}, and {@code sum}. + * + *

    If {@code count} is zero then the remaining arguments are ignored and + * an empty instance is constructed. + * + *

    If the arguments are inconsistent then an {@code IllegalArgumentException} + * is thrown. The necessary consistent argument conditions are: + *

      + *
    • {@code count >= 0}
    • + *
    • {@code min <= max}
    • + *
    + * @apiNote + * The enforcement of argument correctness means that the retrieved set of + * recorded values obtained from a {@code LongSummaryStatistics} source + * instance may not be a legal set of arguments for this constructor due to + * arithmetic overflow of the source's recorded count of values. + * The consistent argument conditions are not sufficient to prevent the + * creation of an internally inconsistent instance. An example of such a + * state would be an instance with: {@code count} = 2, {@code min} = 1, + * {@code max} = 2, and {@code sum} = 0. + * + * @param count the count of values + * @param min the minimum value + * @param max the maximum value + * @param sum the sum of all values + * @throws IllegalArgumentException if the arguments are inconsistent + * @since 10 + */ + public LongSummaryStatistics(long count, long min, long max, long sum) + throws IllegalArgumentException { + if (count < 0L) { + throw new IllegalArgumentException("Negative count value"); + } else if (count > 0L) { + if (min > max) throw new IllegalArgumentException("Minimum greater than maximum"); + + this.count = count; + this.sum = sum; + this.min = min; + this.max = max; + } + // Use default field values if count == 0 + } + /** * Records a new {@code int} value into the summary information. * diff --git a/src/java.base/share/classes/java/util/Properties.java b/src/java.base/share/classes/java/util/Properties.java index fd7ee9ce6b3..1ae9a49a028 100644 --- a/src/java.base/share/classes/java/util/Properties.java +++ b/src/java.base/share/classes/java/util/Properties.java @@ -122,6 +122,10 @@ import jdk.internal.util.xml.PropertiesDefaultHandler; *

    This class is thread-safe: multiple threads can share a single * {@code Properties} object without the need for external synchronization. * + * @apiNote + * The {@code Properties} class does not inherit the concept of a load factor + * from its superclass, {@code Hashtable}. + * * @author Arthur van Hoff * @author Michael McCloskey * @author Xueming Shen @@ -148,25 +152,49 @@ class Properties extends Hashtable { * simple read operations. Writes and bulk operations remain synchronized, * as in Hashtable. */ - private transient ConcurrentHashMap map = - new ConcurrentHashMap<>(8); + private transient ConcurrentHashMap map; /** * Creates an empty property list with no default values. + * + * @implNote The initial capacity of a {@code Properties} object created + * with this constructor is unspecified. */ public Properties() { - this(null); + this(null, 8); + } + + /** + * Creates an empty property list with no default values, and with an + * initial size accommodating the specified number of elements without the + * need to dynamically resize. + * + * @param initialCapacity the {@code Properties} will be sized to + * accommodate this many elements + * @throws IllegalArgumentException if the initial capacity is less than + * zero. + */ + public Properties(int initialCapacity) { + this(null, initialCapacity); } /** * Creates an empty property list with the specified defaults. * + * @implNote The initial capacity of a {@code Properties} object created + * with this constructor is unspecified. + * * @param defaults the defaults. */ public Properties(Properties defaults) { + this(defaults, 8); + } + + private Properties(Properties defaults, int initialCapacity) { // use package-private constructor to // initialize unused fields with dummy values super((Void) null); + map = new ConcurrentHashMap<>(initialCapacity); this.defaults = defaults; } diff --git a/src/java.base/share/classes/java/util/ResourceBundle.java b/src/java.base/share/classes/java/util/ResourceBundle.java index 1e8141fe14b..b361ceefff4 100644 --- a/src/java.base/share/classes/java/util/ResourceBundle.java +++ b/src/java.base/share/classes/java/util/ResourceBundle.java @@ -2743,7 +2743,7 @@ public abstract class ResourceBundle { * of multiple subtags separated by underscore, generate candidate * Locales by omitting the variant subtags one by one, then * insert them after every occurrence of Locales with the - * full variant value in the original list. For example, if the + * full variant value in the original list. For example, if * the variant consists of two subtags V1 and V2: * *