diff --git a/.hgtags-top-repo b/.hgtags-top-repo
index b24ec390424..3d81f131af0 100644
--- a/.hgtags-top-repo
+++ b/.hgtags-top-repo
@@ -397,3 +397,4 @@ b119012d1c2ab2570fe8718633840d0c1f1f441d jdk-9+149
ef056360ddf3977d7d2ddbeb456a4d612d19ea05 jdk-9+152
816a6d03a7c44edfbd8780110529f1bdc3964fb9 jdk-9+153
8d26916eaa21b689835ffc1c0dbf12470aa9be61 jdk-9+154
+688a3863c00ebc089ab17ee1fc46272cbbd96815 jdk-9+155
diff --git a/common/autoconf/basics.m4 b/common/autoconf/basics.m4
index 17c03533dd7..35e835c3994 100644
--- a/common/autoconf/basics.m4
+++ b/common/autoconf/basics.m4
@@ -746,7 +746,8 @@ AC_DEFUN_ONCE([BASIC_SETUP_DEVKIT],
fi
# set SDKROOT too, Xcode tools will pick it up
- AC_SUBST(SDKROOT,$SYSROOT)
+ SDKROOT="$SYSROOT"
+ AC_SUBST(SDKROOT)
fi
# Prepend the extra path to the global path
@@ -831,9 +832,10 @@ AC_DEFUN_ONCE([BASIC_SETUP_OUTPUT_DIR],
CONFIGURESUPPORT_OUTPUTDIR="$OUTPUT_ROOT/configure-support"
$MKDIR -p "$CONFIGURESUPPORT_OUTPUTDIR"
- AC_SUBST(SPEC, $OUTPUT_ROOT/spec.gmk)
- AC_SUBST(CONF_NAME, $CONF_NAME)
- AC_SUBST(OUTPUT_ROOT, $OUTPUT_ROOT)
+ SPEC="$OUTPUT_ROOT/spec.gmk"
+ AC_SUBST(SPEC)
+ AC_SUBST(CONF_NAME)
+ AC_SUBST(OUTPUT_ROOT)
AC_SUBST(CONFIGURESUPPORT_OUTPUTDIR)
# The spec.gmk file contains all variables for the make system.
diff --git a/common/autoconf/boot-jdk.m4 b/common/autoconf/boot-jdk.m4
index 7eafd2857d3..b7ae10542ed 100644
--- a/common/autoconf/boot-jdk.m4
+++ b/common/autoconf/boot-jdk.m4
@@ -1,5 +1,5 @@
#
-# 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
@@ -325,7 +325,6 @@ AC_DEFUN_ONCE([BOOTJDK_SETUP_BOOT_JDK],
fi
AC_MSG_CHECKING([if Boot JDK is 32 or 64 bits])
AC_MSG_RESULT([$BOOT_JDK_BITS])
- AC_SUBST(BOOT_JDK_BITS)
])
AC_DEFUN_ONCE([BOOTJDK_SETUP_BOOT_JDK_ARGUMENTS],
diff --git a/common/autoconf/build-performance.m4 b/common/autoconf/build-performance.m4
index fd77fe8c2b0..13578cfa867 100644
--- a/common/autoconf/build-performance.m4
+++ b/common/autoconf/build-performance.m4
@@ -224,7 +224,7 @@ AC_DEFUN([BPERF_SETUP_CCACHE_USAGE],
AC_MSG_ERROR([On macosx, ccache 3.2 or later is required, found $CCACHE_VERSION])
fi
fi
- if test "x$USE_PRECOMPILED_HEADER" = "x1"; then
+ if test "x$USE_PRECOMPILED_HEADER" = "xtrue"; then
HAS_BAD_CCACHE=[`$ECHO $CCACHE_VERSION | \
$GREP -e '^1.*' -e '^2.*' -e '^3\.0.*' -e '^3\.1\.[0123]$'`]
if test "x$HAS_BAD_CCACHE" != "x"; then
@@ -362,20 +362,20 @@ AC_DEFUN_ONCE([BPERF_SETUP_PRECOMPILED_HEADERS],
[disable using precompiled headers when compiling C++ @<:@enabled@:>@])],
[ENABLE_PRECOMPH=${enable_precompiled_headers}], [ENABLE_PRECOMPH=yes])
- USE_PRECOMPILED_HEADER=1
+ USE_PRECOMPILED_HEADER=true
AC_MSG_CHECKING([If precompiled header is enabled])
if test "x$ENABLE_PRECOMPH" = xno; then
AC_MSG_RESULT([no, forced])
- USE_PRECOMPILED_HEADER=0
+ USE_PRECOMPILED_HEADER=false
elif test "x$ICECC" != "x"; then
AC_MSG_RESULT([no, does not work effectively with icecc])
- USE_PRECOMPILED_HEADER=0
+ USE_PRECOMPILED_HEADER=false
elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then
AC_MSG_RESULT([no, does not work with Solaris Studio])
- USE_PRECOMPILED_HEADER=0
+ USE_PRECOMPILED_HEADER=false
elif test "x$TOOLCHAIN_TYPE" = xxlc; then
AC_MSG_RESULT([no, does not work with xlc])
- USE_PRECOMPILED_HEADER=0
+ USE_PRECOMPILED_HEADER=false
else
AC_MSG_RESULT([yes])
fi
@@ -387,7 +387,7 @@ AC_DEFUN_ONCE([BPERF_SETUP_PRECOMPILED_HEADERS],
echo "int alfa();" > conftest.h
$CXX -x c++-header conftest.h -o conftest.hpp.gch 2>&AS_MESSAGE_LOG_FD >&AS_MESSAGE_LOG_FD
if test ! -f conftest.hpp.gch; then
- USE_PRECOMPILED_HEADER=0
+ USE_PRECOMPILED_HEADER=false
AC_MSG_RESULT([no])
else
AC_MSG_RESULT([yes])
diff --git a/common/autoconf/flags.m4 b/common/autoconf/flags.m4
index e5ae8eed060..ca7f625664c 100644
--- a/common/autoconf/flags.m4
+++ b/common/autoconf/flags.m4
@@ -1,5 +1,5 @@
#
-# 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
@@ -808,7 +808,7 @@ AC_DEFUN([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK_HELPER],
IF_FALSE: [$2CXXSTD_CXXFLAG=""])
$2CXXFLAGS_JDK="${$2CXXFLAGS_JDK} ${$2CXXSTD_CXXFLAG}"
$2JVM_CFLAGS="${$2JVM_CFLAGS} ${$2CXXSTD_CXXFLAG}"
- AC_SUBST([$2CXXSTD_CXXFLAG])
+ AC_SUBST($2CXXSTD_CXXFLAG)
fi
if test "x$OPENJDK_TARGET_OS" = xsolaris; then
$2CFLAGS_JDK="${$2CFLAGS_JDK} -D__solaris__"
@@ -1440,18 +1440,6 @@ BASIC_DEFUN_NAMED([FLAGS_LINKER_CHECK_ARGUMENTS],
AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_MISC],
[
- # Some Zero and Shark settings.
- # ZERO_ARCHFLAG tells the compiler which mode to build for
- case "${OPENJDK_TARGET_CPU}" in
- s390)
- ZERO_ARCHFLAG="${COMPILER_TARGET_BITS_FLAG}31"
- ;;
- *)
- ZERO_ARCHFLAG="${COMPILER_TARGET_BITS_FLAG}${OPENJDK_TARGET_CPU_BITS}"
- esac
- FLAGS_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [$ZERO_ARCHFLAG], IF_FALSE: [ZERO_ARCHFLAG=""])
- AC_SUBST(ZERO_ARCHFLAG)
-
# Check that the compiler supports -mX (or -qX on AIX) flags
# Set COMPILER_SUPPORTS_TARGET_BITS_FLAG to 'true' if it does
FLAGS_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [${COMPILER_TARGET_BITS_FLAG}${OPENJDK_TARGET_CPU_BITS}],
@@ -1476,15 +1464,7 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_MISC],
AC_MSG_ERROR([--enable-warnings-as-errors accepts no argument])
fi
- if test "x$WARNINGS_AS_ERRORS" = "xfalse"; then
- # Set legacy hotspot variable
- HOTSPOT_SET_WARNINGS_AS_ERRORS="WARNINGS_ARE_ERRORS="
- else
- HOTSPOT_SET_WARNINGS_AS_ERRORS=""
- fi
-
AC_SUBST(WARNINGS_AS_ERRORS)
- AC_SUBST(HOTSPOT_SET_WARNINGS_AS_ERRORS)
case "${TOOLCHAIN_TYPE}" in
microsoft)
diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh
index 3c0f4644798..917181abf10 100644
--- a/common/autoconf/generated-configure.sh
+++ b/common/autoconf/generated-configure.sh
@@ -704,7 +704,6 @@ FIXPATH_DETACH_FLAG
FIXPATH
BUILD_GTEST
ENABLE_AOT
-INCLUDE_DTRACE
GCOV_ENABLED
ZIP_EXTERNAL_DEBUG_SYMBOLS
COPY_DEBUG_SYMBOLS
@@ -712,10 +711,8 @@ COMPILE_WITH_DEBUG_SYMBOLS
CFLAGS_WARNINGS_ARE_ERRORS
BUILD_CC_DISABLE_WARNING_PREFIX
DISABLE_WARNING_PREFIX
-HOTSPOT_SET_WARNINGS_AS_ERRORS
WARNINGS_AS_ERRORS
COMPILER_SUPPORTS_TARGET_BITS_FLAG
-ZERO_ARCHFLAG
LDFLAGS_TESTEXE
LDFLAGS_TESTLIB
CXXFLAGS_TESTEXE
@@ -884,7 +881,6 @@ BUILD_JDK
CREATE_BUILDJDK
JLINK
JMOD
-BOOT_JDK_BITS
JAVAC_FLAGS
BOOT_JDK_MODULAR
BOOT_JDK_SOURCETARGET
@@ -974,15 +970,12 @@ CANONICAL_TOPDIR
ORIGINAL_TOPDIR
TOPDIR
PATH_SEP
-ZERO_ARCHDEF
HOTSPOT_BUILD_CPU_DEFINE
HOTSPOT_BUILD_CPU_ARCH
HOTSPOT_BUILD_CPU
HOTSPOT_BUILD_OS_TYPE
HOTSPOT_BUILD_OS
OPENJDK_BUILD_BUNDLE_PLATFORM
-OPENJDK_BUILD_CPU_BUNDLE
-OPENJDK_BUILD_OS_BUNDLE
OPENJDK_BUILD_OS_EXPORT_DIR
OPENJDK_BUILD_CPU_OSARCH
OPENJDK_BUILD_CPU_ISADIR
@@ -994,10 +987,7 @@ HOTSPOT_TARGET_CPU
HOTSPOT_TARGET_OS_TYPE
HOTSPOT_TARGET_OS
DEFINE_CROSS_COMPILE_ARCH
-LP64
OPENJDK_TARGET_BUNDLE_PLATFORM
-OPENJDK_TARGET_CPU_BUNDLE
-OPENJDK_TARGET_OS_BUNDLE
OPENJDK_TARGET_OS_EXPORT_DIR
OPENJDK_TARGET_CPU_OSARCH
OPENJDK_TARGET_CPU_ISADIR
@@ -3818,7 +3808,7 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
# ... then the rest
#
-# 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
@@ -3998,7 +3988,7 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
#
-# 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
@@ -4273,7 +4263,7 @@ pkgadd_help() {
#
-# 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
@@ -4561,7 +4551,7 @@ VALID_JVM_VARIANTS="server client minimal core zero zeroshark custom"
#
-# 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
@@ -4841,7 +4831,7 @@ VALID_JVM_VARIANTS="server client minimal core zero zeroshark custom"
#
-# 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
@@ -5180,7 +5170,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=1485508515
+DATE_WHEN_GENERATED=1486175373
###############################################################################
#
@@ -15936,18 +15926,14 @@ $as_echo "$COMPILE_TYPE" >&6; }
OPENJDK_TARGET_BUNDLE_PLATFORM="${OPENJDK_TARGET_OS_BUNDLE}-${OPENJDK_TARGET_CPU_BUNDLE}"
-
-
if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
- A_LP64="LP64:="
# -D_LP64=1 is only set on linux and mac. Setting on windows causes diff in
- # unpack200.exe
+ # unpack200.exe. This variable is used in
+ # FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK_HELPER.
if test "x$OPENJDK_TARGET_OS" = xlinux || test "x$OPENJDK_TARGET_OS" = xmacosx; then
OPENJDK_TARGET_ADD_LP64="-D_LP64=1"
fi
fi
- LP64=$A_LP64
-
if test "x$COMPILE_TYPE" = "xcross"; then
# FIXME: ... or should this include reduced builds..?
@@ -16092,18 +16078,14 @@ $as_echo "$COMPILE_TYPE" >&6; }
OPENJDK_BUILD_BUNDLE_PLATFORM="${OPENJDK_BUILD_OS_BUNDLE}-${OPENJDK_BUILD_CPU_BUNDLE}"
-
-
if test "x$OPENJDK_BUILD_CPU_BITS" = x64; then
- A_LP64="LP64:="
# -D_LP64=1 is only set on linux and mac. Setting on windows causes diff in
- # unpack200.exe
+ # unpack200.exe. This variable is used in
+ # FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK_HELPER.
if test "x$OPENJDK_BUILD_OS" = xlinux || test "x$OPENJDK_BUILD_OS" = xmacosx; then
OPENJDK_BUILD_ADD_LP64="-D_LP64=1"
fi
fi
- LP64=$A_LP64
-
if test "x$COMPILE_TYPE" = "xcross"; then
# FIXME: ... or should this include reduced builds..?
@@ -16173,12 +16155,6 @@ $as_echo "$COMPILE_TYPE" >&6; }
- # ZERO_ARCHDEF is used to enable architecture-specific code.
- # This is used in legacy hotspot build.
- ZERO_ARCHDEF="$HOTSPOT_TARGET_CPU_DEFINE"
-
-
-
# Continue setting up basic stuff. Most remaining code require fundamental tools.
@@ -17280,7 +17256,7 @@ $as_echo "$as_me: WARNING: Both SYSROOT and --with-sdk-name are set, only SYSROO
fi
# set SDKROOT too, Xcode tools will pick it up
- SDKROOT=$SYSROOT
+ SDKROOT="$SYSROOT"
fi
@@ -17528,11 +17504,9 @@ $as_echo "$as_me: The path of OUTPUT_ROOT, which resolves as \"$path\", is inval
CONFIGURESUPPORT_OUTPUTDIR="$OUTPUT_ROOT/configure-support"
$MKDIR -p "$CONFIGURESUPPORT_OUTPUTDIR"
- SPEC=$OUTPUT_ROOT/spec.gmk
+ SPEC="$OUTPUT_ROOT/spec.gmk"
- CONF_NAME=$CONF_NAME
- OUTPUT_ROOT=$OUTPUT_ROOT
@@ -30730,7 +30704,6 @@ $as_echo "$BOOT_JDK_BITS" >&6; }
-
# Check whether --with-build-jdk was given.
if test "${with_build_jdk+set}" = set; then :
withval=$with_build_jdk;
@@ -51480,282 +51453,6 @@ OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} ${OPENJDK_BUILD_JA
- # Some Zero and Shark settings.
- # ZERO_ARCHFLAG tells the compiler which mode to build for
- case "${OPENJDK_TARGET_CPU}" in
- s390)
- ZERO_ARCHFLAG="${COMPILER_TARGET_BITS_FLAG}31"
- ;;
- *)
- ZERO_ARCHFLAG="${COMPILER_TARGET_BITS_FLAG}${OPENJDK_TARGET_CPU_BITS}"
- esac
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- # Execute function body
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- # Execute function body
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the C compiler supports \"$ZERO_ARCHFLAG\"" >&5
-$as_echo_n "checking if the C compiler supports \"$ZERO_ARCHFLAG\"... " >&6; }
- supports=yes
-
- saved_cflags="$CFLAGS"
- CFLAGS="$CFLAGS $ZERO_ARCHFLAG"
- ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-int i;
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-
-else
- supports=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- ac_ext=cpp
-ac_cpp='$CXXCPP $CPPFLAGS'
-ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
-
- CFLAGS="$saved_cflags"
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $supports" >&5
-$as_echo "$supports" >&6; }
- if test "x$supports" = "xyes" ; then
- :
- C_COMP_SUPPORTS="yes"
- else
- :
- C_COMP_SUPPORTS="no"
- fi
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- # Execute function body
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the C++ compiler supports \"$ZERO_ARCHFLAG\"" >&5
-$as_echo_n "checking if the C++ compiler supports \"$ZERO_ARCHFLAG\"... " >&6; }
- supports=yes
-
- saved_cxxflags="$CXXFLAGS"
- CXXFLAGS="$CXXFLAG $ZERO_ARCHFLAG"
- ac_ext=cpp
-ac_cpp='$CXXCPP $CPPFLAGS'
-ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
-
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-int i;
-_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
-
-else
- supports=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- ac_ext=cpp
-ac_cpp='$CXXCPP $CPPFLAGS'
-ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
-
- CXXFLAGS="$saved_cxxflags"
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $supports" >&5
-$as_echo "$supports" >&6; }
- if test "x$supports" = "xyes" ; then
- :
- CXX_COMP_SUPPORTS="yes"
- else
- :
- CXX_COMP_SUPPORTS="no"
- fi
-
-
-
-
-
-
-
-
-
-
-
-
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if both compilers support \"$ZERO_ARCHFLAG\"" >&5
-$as_echo_n "checking if both compilers support \"$ZERO_ARCHFLAG\"... " >&6; }
- supports=no
- if test "x$C_COMP_SUPPORTS" = "xyes" -a "x$CXX_COMP_SUPPORTS" = "xyes"; then supports=yes; fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $supports" >&5
-$as_echo "$supports" >&6; }
- if test "x$supports" = "xyes" ; then
- :
-
- else
- :
- ZERO_ARCHFLAG=""
- fi
-
-
-
-
-
-
-
-
# Check that the compiler supports -mX (or -qX on AIX) flags
# Set COMPILER_SUPPORTS_TARGET_BITS_FLAG to 'true' if it does
@@ -52054,14 +51751,6 @@ $as_echo "yes (default)" >&6; }
as_fn_error $? "--enable-warnings-as-errors accepts no argument" "$LINENO" 5
fi
- if test "x$WARNINGS_AS_ERRORS" = "xfalse"; then
- # Set legacy hotspot variable
- HOTSPOT_SET_WARNINGS_AS_ERRORS="WARNINGS_ARE_ERRORS="
- else
- HOTSPOT_SET_WARNINGS_AS_ERRORS=""
- fi
-
-
case "${TOOLCHAIN_TYPE}" in
@@ -52916,7 +52605,6 @@ $as_echo "yes, dependencies present" >&6; }
fi
-
# Check whether --enable-aot was given.
if test "${enable_aot+set}" = set; then :
enableval=$enable_aot;
@@ -63694,12 +63382,14 @@ $as_echo_n "checking for which libpng to use... " >&6; }
DEFAULT_LIBPNG=bundled
# if user didn't specify, use DEFAULT_LIBPNG
if test "x${with_libpng}" = "x"; then
- with_libpng=${DEFAULT_LIBPNG}
+ with_libpng=${DEFAULT_LIBPNG}
fi
if test "x${with_libpng}" = "xbundled"; then
- USE_EXTERNAL_LIBPNG=false
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: bundled" >&5
+ USE_EXTERNAL_LIBPNG=false
+ PNG_CFLAGS=""
+ PNG_LIBS=""
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: bundled" >&5
$as_echo "bundled" >&6; }
elif test "x${with_libpng}" = "xsystem"; then
@@ -63759,33 +63449,36 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
- LIBPNG_FOUND=no
+ LIBPNG_FOUND=no
elif test $pkg_failed = untried; then
- LIBPNG_FOUND=no
+ LIBPNG_FOUND=no
else
PNG_CFLAGS=$pkg_cv_PNG_CFLAGS
PNG_LIBS=$pkg_cv_PNG_LIBS
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
- LIBPNG_FOUND=yes
+ LIBPNG_FOUND=yes
fi
- if test "x${LIBPNG_FOUND}" = "xyes"; then
- USE_EXTERNAL_LIBPNG=true
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: system" >&5
+ if test "x${LIBPNG_FOUND}" = "xyes"; then
+ # PKG_CHECK_MODULES will set PNG_CFLAGS and PNG_LIBS
+ USE_EXTERNAL_LIBPNG=true
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: system" >&5
$as_echo "system" >&6; }
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: system not found" >&5
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: system not found" >&5
$as_echo "system not found" >&6; }
- as_fn_error $? "--with-libpng=system specified, but no libpng found!" "$LINENO" 5
- fi
+ as_fn_error $? "--with-libpng=system specified, but no libpng found!" "$LINENO" 5
+ fi
else
- as_fn_error $? "Invalid value of --with-libpng: ${with_libpng}, use 'system' or 'bundled'" "$LINENO" 5
+ as_fn_error $? "Invalid value of --with-libpng: ${with_libpng}, use 'system' or 'bundled'" "$LINENO" 5
fi
+
+
# Check whether --with-zlib was given.
if test "${with_zlib+set}" = set; then :
withval=$with_zlib;
@@ -63888,11 +63581,13 @@ $as_echo_n "checking for which lcms to use... " >&6; }
DEFAULT_LCMS=bundled
# If user didn't specify, use DEFAULT_LCMS
if test "x${with_lcms}" = "x"; then
- with_lcms=${DEFAULT_LCMS}
+ with_lcms=${DEFAULT_LCMS}
fi
if test "x${with_lcms}" = "xbundled"; then
USE_EXTERNAL_LCMS=false
+ LCMS_CFLAGS=""
+ LCMS_LIBS=""
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: bundled" >&5
$as_echo "bundled" >&6; }
elif test "x${with_lcms}" = "xsystem"; then
@@ -63966,6 +63661,7 @@ $as_echo "yes" >&6; }
LCMS_FOUND=yes
fi
if test "x${LCMS_FOUND}" = "xyes"; then
+ # PKG_CHECK_MODULES will set LCMS_CFLAGS and LCMS_LIBS
USE_EXTERNAL_LCMS=true
else
as_fn_error $? "--with-lcms=system specified, but no lcms found!" "$LINENO" 5
@@ -63984,6 +63680,8 @@ fi
+
+
# Setup libm (the maths library)
if test "x$OPENJDK_TARGET_OS" != "xwindows"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for cos in -lm" >&5
@@ -64768,11 +64466,11 @@ fi
$as_echo_n "checking if elliptic curve crypto implementation is present... " >&6; }
if test -d "${SRC_ROOT}/jdk/src/jdk.crypto.ec/share/native/libsunec/impl"; then
- ENABLE_INTREE_EC=yes
+ ENABLE_INTREE_EC=true
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
- ENABLE_INTREE_EC=no
+ ENABLE_INTREE_EC=false
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
@@ -66139,25 +65837,25 @@ else
fi
- USE_PRECOMPILED_HEADER=1
+ USE_PRECOMPILED_HEADER=true
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking If precompiled header is enabled" >&5
$as_echo_n "checking If precompiled header is enabled... " >&6; }
if test "x$ENABLE_PRECOMPH" = xno; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no, forced" >&5
$as_echo "no, forced" >&6; }
- USE_PRECOMPILED_HEADER=0
+ USE_PRECOMPILED_HEADER=false
elif test "x$ICECC" != "x"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no, does not work effectively with icecc" >&5
$as_echo "no, does not work effectively with icecc" >&6; }
- USE_PRECOMPILED_HEADER=0
+ USE_PRECOMPILED_HEADER=false
elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no, does not work with Solaris Studio" >&5
$as_echo "no, does not work with Solaris Studio" >&6; }
- USE_PRECOMPILED_HEADER=0
+ USE_PRECOMPILED_HEADER=false
elif test "x$TOOLCHAIN_TYPE" = xxlc; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no, does not work with xlc" >&5
$as_echo "no, does not work with xlc" >&6; }
- USE_PRECOMPILED_HEADER=0
+ USE_PRECOMPILED_HEADER=false
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
@@ -66171,7 +65869,7 @@ $as_echo_n "checking that precompiled headers work... " >&6; }
echo "int alfa();" > conftest.h
$CXX -x c++-header conftest.h -o conftest.hpp.gch 2>&5 >&5
if test ! -f conftest.hpp.gch; then
- USE_PRECOMPILED_HEADER=0
+ USE_PRECOMPILED_HEADER=false
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
else
@@ -66458,7 +66156,7 @@ $as_echo "$as_me: WARNING: --with-ccache-dir has no meaning when ccache is not e
as_fn_error $? "On macosx, ccache 3.2 or later is required, found $CCACHE_VERSION" "$LINENO" 5
fi
fi
- if test "x$USE_PRECOMPILED_HEADER" = "x1"; then
+ if test "x$USE_PRECOMPILED_HEADER" = "xtrue"; then
HAS_BAD_CCACHE=`$ECHO $CCACHE_VERSION | \
$GREP -e '^1.*' -e '^2.*' -e '^3\.0.*' -e '^3\.1\.[0123]$'`
if test "x$HAS_BAD_CCACHE" != "x"; then
diff --git a/common/autoconf/hotspot.m4 b/common/autoconf/hotspot.m4
index 79eb26c96c9..b295b015a9f 100644
--- a/common/autoconf/hotspot.m4
+++ b/common/autoconf/hotspot.m4
@@ -1,5 +1,5 @@
#
-# 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
@@ -189,7 +189,6 @@ AC_DEFUN_ONCE([HOTSPOT_SETUP_DTRACE],
else
AC_MSG_ERROR([Invalid value for --enable-dtrace: $enable_dtrace])
fi
- AC_SUBST(INCLUDE_DTRACE)
])
################################################################################
diff --git a/common/autoconf/jdk-options.m4 b/common/autoconf/jdk-options.m4
index 2c21000845b..bb2a49f4980 100644
--- a/common/autoconf/jdk-options.m4
+++ b/common/autoconf/jdk-options.m4
@@ -210,10 +210,10 @@ AC_DEFUN_ONCE([JDKOPT_DETECT_INTREE_EC],
AC_MSG_CHECKING([if elliptic curve crypto implementation is present])
if test -d "${SRC_ROOT}/jdk/src/jdk.crypto.ec/share/native/libsunec/impl"; then
- ENABLE_INTREE_EC=yes
+ ENABLE_INTREE_EC=true
AC_MSG_RESULT([yes])
else
- ENABLE_INTREE_EC=no
+ ENABLE_INTREE_EC=false
AC_MSG_RESULT([no])
fi
@@ -479,5 +479,5 @@ AC_DEFUN_ONCE([JDKOPT_ENABLE_DISABLE_GENERATE_CLASSLIST],
AC_MSG_ERROR([Invalid value for --enable-generate-classlist: $enable_generate_classlist])
fi
- AC_SUBST([ENABLE_GENERATE_CLASSLIST])
+ AC_SUBST(ENABLE_GENERATE_CLASSLIST)
])
diff --git a/common/autoconf/lib-bundled.m4 b/common/autoconf/lib-bundled.m4
index 218d3f87adf..92b9438014b 100644
--- a/common/autoconf/lib-bundled.m4
+++ b/common/autoconf/lib-bundled.m4
@@ -1,5 +1,5 @@
#
-# 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
@@ -119,28 +119,31 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBPNG],
DEFAULT_LIBPNG=bundled
# if user didn't specify, use DEFAULT_LIBPNG
if test "x${with_libpng}" = "x"; then
- with_libpng=${DEFAULT_LIBPNG}
+ with_libpng=${DEFAULT_LIBPNG}
fi
if test "x${with_libpng}" = "xbundled"; then
- USE_EXTERNAL_LIBPNG=false
- AC_MSG_RESULT([bundled])
+ USE_EXTERNAL_LIBPNG=false
+ PNG_CFLAGS=""
+ PNG_LIBS=""
+ AC_MSG_RESULT([bundled])
elif test "x${with_libpng}" = "xsystem"; then
- PKG_CHECK_MODULES(PNG, libpng,
- [ LIBPNG_FOUND=yes ],
- [ LIBPNG_FOUND=no ])
- if test "x${LIBPNG_FOUND}" = "xyes"; then
- USE_EXTERNAL_LIBPNG=true
- AC_MSG_RESULT([system])
- else
- AC_MSG_RESULT([system not found])
- AC_MSG_ERROR([--with-libpng=system specified, but no libpng found!])
- fi
+ PKG_CHECK_MODULES(PNG, libpng, [LIBPNG_FOUND=yes], [LIBPNG_FOUND=no])
+ if test "x${LIBPNG_FOUND}" = "xyes"; then
+ # PKG_CHECK_MODULES will set PNG_CFLAGS and PNG_LIBS
+ USE_EXTERNAL_LIBPNG=true
+ AC_MSG_RESULT([system])
+ else
+ AC_MSG_RESULT([system not found])
+ AC_MSG_ERROR([--with-libpng=system specified, but no libpng found!])
+ fi
else
- AC_MSG_ERROR([Invalid value of --with-libpng: ${with_libpng}, use 'system' or 'bundled'])
+ AC_MSG_ERROR([Invalid value of --with-libpng: ${with_libpng}, use 'system' or 'bundled'])
fi
AC_SUBST(USE_EXTERNAL_LIBPNG)
+ AC_SUBST(PNG_CFLAGS)
+ AC_SUBST(PNG_LIBS)
])
################################################################################
@@ -204,16 +207,19 @@ AC_DEFUN_ONCE([LIB_SETUP_LCMS],
DEFAULT_LCMS=bundled
# If user didn't specify, use DEFAULT_LCMS
if test "x${with_lcms}" = "x"; then
- with_lcms=${DEFAULT_LCMS}
+ with_lcms=${DEFAULT_LCMS}
fi
if test "x${with_lcms}" = "xbundled"; then
USE_EXTERNAL_LCMS=false
+ LCMS_CFLAGS=""
+ LCMS_LIBS=""
AC_MSG_RESULT([bundled])
elif test "x${with_lcms}" = "xsystem"; then
AC_MSG_RESULT([system])
PKG_CHECK_MODULES([LCMS], [lcms2], [LCMS_FOUND=yes], [LCMS_FOUND=no])
if test "x${LCMS_FOUND}" = "xyes"; then
+ # PKG_CHECK_MODULES will set LCMS_CFLAGS and LCMS_LIBS
USE_EXTERNAL_LCMS=true
else
AC_MSG_ERROR([--with-lcms=system specified, but no lcms found!])
@@ -223,4 +229,6 @@ AC_DEFUN_ONCE([LIB_SETUP_LCMS],
fi
AC_SUBST(USE_EXTERNAL_LCMS)
+ AC_SUBST(LCMS_CFLAGS)
+ AC_SUBST(LCMS_LIBS)
])
diff --git a/common/autoconf/platform.m4 b/common/autoconf/platform.m4
index 5217ca32e3e..61010279a0e 100644
--- a/common/autoconf/platform.m4
+++ b/common/autoconf/platform.m4
@@ -1,5 +1,5 @@
#
-# 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
@@ -276,12 +276,6 @@ AC_DEFUN([PLATFORM_SETUP_LEGACY_VARS],
[
PLATFORM_SETUP_LEGACY_VARS_HELPER([TARGET])
PLATFORM_SETUP_LEGACY_VARS_HELPER([BUILD])
-
- # ZERO_ARCHDEF is used to enable architecture-specific code.
- # This is used in legacy hotspot build.
- ZERO_ARCHDEF="$HOTSPOT_TARGET_CPU_DEFINE"
- AC_SUBST(ZERO_ARCHDEF)
-
])
# $1 - Either TARGET or BUILD to setup the variables for.
@@ -360,19 +354,16 @@ AC_DEFUN([PLATFORM_SETUP_LEGACY_VARS_HELPER],
OPENJDK_$1_CPU_BUNDLE="$OPENJDK_$1_CPU"
fi
OPENJDK_$1_BUNDLE_PLATFORM="${OPENJDK_$1_OS_BUNDLE}-${OPENJDK_$1_CPU_BUNDLE}"
- AC_SUBST(OPENJDK_$1_OS_BUNDLE)
- AC_SUBST(OPENJDK_$1_CPU_BUNDLE)
AC_SUBST(OPENJDK_$1_BUNDLE_PLATFORM)
if test "x$OPENJDK_$1_CPU_BITS" = x64; then
- A_LP64="LP64:="
# -D_LP64=1 is only set on linux and mac. Setting on windows causes diff in
- # unpack200.exe
+ # unpack200.exe. This variable is used in
+ # FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK_HELPER.
if test "x$OPENJDK_$1_OS" = xlinux || test "x$OPENJDK_$1_OS" = xmacosx; then
OPENJDK_$1_ADD_LP64="-D_LP64=1"
fi
fi
- AC_SUBST(LP64,$A_LP64)
if test "x$COMPILE_TYPE" = "xcross"; then
# FIXME: ... or should this include reduced builds..?
diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in
index 471f9096e01..bb6d2209c41 100644
--- a/common/autoconf/spec.gmk.in
+++ b/common/autoconf/spec.gmk.in
@@ -1,5 +1,5 @@
#
-# 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
@@ -87,9 +87,8 @@ HOTSPOT_TARGET_CPU := @HOTSPOT_TARGET_CPU@
HOTSPOT_TARGET_CPU_ARCH := @HOTSPOT_TARGET_CPU_ARCH@
HOTSPOT_TARGET_CPU_DEFINE := @HOTSPOT_TARGET_CPU_DEFINE@
-OPENJDK_TARGET_CPU_BUNDLE:=@OPENJDK_TARGET_CPU_BUNDLE@
-OPENJDK_TARGET_OS_BUNDLE:=@OPENJDK_TARGET_OS_BUNDLE@
OPENJDK_TARGET_BUNDLE_PLATFORM:=@OPENJDK_TARGET_BUNDLE_PLATFORM@
+JDK_ARCH_ABI_PROP_NAME := @JDK_ARCH_ABI_PROP_NAME@
# We are building on this build system.
# When not cross-compiling, it is the same as the target.
@@ -683,8 +682,7 @@ TAR_SUPPORTS_TRANSFORM:=@TAR_SUPPORTS_TRANSFORM@
# Build setup
ENABLE_AOT:=@ENABLE_AOT@
-ENABLE_JFR=@ENABLE_JFR@
-ENABLE_INTREE_EC=@ENABLE_INTREE_EC@
+ENABLE_INTREE_EC:=@ENABLE_INTREE_EC@
USE_EXTERNAL_LIBJPEG:=@USE_EXTERNAL_LIBJPEG@
USE_EXTERNAL_LIBGIF:=@USE_EXTERNAL_LIBGIF@
USE_EXTERNAL_LIBZ:=@USE_EXTERNAL_LIBZ@
diff --git a/common/bin/hgforest.sh b/common/bin/hgforest.sh
index 3007d3e8860..5d4f8eb7156 100644
--- a/common/bin/hgforest.sh
+++ b/common/bin/hgforest.sh
@@ -309,8 +309,8 @@ if [ "${command}" = "serve" ] ; then
echo "serving root repo ${serving}" > ${status_output}
- echo "hg${global_opts} serve" > ${status_output}
- (PYTHONUNBUFFERED=true hg${global_opts} serve -A ${status_output} -E ${status_output} --pid-file ${tmp}/serve.pid --web-conf ${tmp}/serve.web-conf; echo "$?" > ${tmp}/serve.pid.rc ) 2>&1 &
+ echo "hg${global_opts} serve ${@}" > ${status_output}
+ (PYTHONUNBUFFERED=true hg${global_opts} serve -A ${status_output} -E ${status_output} --pid-file ${tmp}/serve.pid --web-conf ${tmp}/serve.web-conf "${@}"; echo "$?" > ${tmp}/serve.pid.rc ) 2>&1 &
) 2>&1 | sed -e "s@^@serve: @" > ${status_output}
) &
else
diff --git a/common/bin/unshuffle_list.txt b/common/bin/unshuffle_list.txt
index a217a8f01f8..e5fe5af121d 100644
--- a/common/bin/unshuffle_list.txt
+++ b/common/bin/unshuffle_list.txt
@@ -60,7 +60,7 @@ jaxp/src/java.xml/share/classes/org/xml/sax : jaxp/src/org/xml/sax
jaxws/src/java.activation/share/classes/com/sun/activation/registries : jaxws/src/share/jaf_classes/com/sun/activation/registries
jaxws/src/java.activation/share/classes/javax/activation : jaxws/src/share/jaf_classes/javax/activation
jaxws/src/java.activation/share/classes/META-INF : jaxws/src/share/jaf_classes/META-INF
-jaxws/src/java.annotations.common/share/classes/javax/annotation : jaxws/src/share/jaxws_classes/javax/annotation
+jaxws/src/java.xml.ws.annotation/share/classes/javax/annotation : jaxws/src/share/jaxws_classes/javax/annotation
jaxws/src/java.xml.bind/share/classes/com/sun/istack/internal : jaxws/src/share/jaxws_classes/com/sun/istack/internal
jaxws/src/java.xml.bind/share/classes/com/sun/istack/internal/localization : jaxws/src/share/jaxws_classes/com/sun/istack/internal/localization
jaxws/src/java.xml.bind/share/classes/com/sun/istack/internal/logging/Logger.java : jaxws/src/share/jaxws_classes/com/sun/istack/internal/logging/Logger.java
@@ -1163,9 +1163,6 @@ jdk/src/java.management/share/classes/mgmt-overview.html : jdk/src/share/classes
jdk/src/java.management/share/classes/sun/management/counter : jdk/src/share/classes/sun/management/counter
jdk/src/java.management/share/classes/sun/management/counter/perf : jdk/src/share/classes/sun/management/counter/perf
jdk/src/java.management/share/classes/sun/management : jdk/src/share/classes/sun/management
-jdk/src/java.management/share/classes/sun/management/jdp : jdk/src/share/classes/sun/management/jdp
-jdk/src/java.management/share/classes/sun/management/jmxremote : jdk/src/share/classes/sun/management/jmxremote
-jdk/src/java.management/share/classes/sun/management/resources : jdk/src/share/classes/sun/management/resources
jdk/src/java.management/share/conf : jdk/src/share/lib/management
jdk/src/java.management/share/native/include/jmm.h : jdk/src/share/javavm/export/jmm.h
jdk/src/java.management/share/native/libmanagement : jdk/src/share/native/sun/management
@@ -1173,6 +1170,11 @@ jdk/src/java.management/unix/classes/sun/management : jdk/src/solaris/classes/su
jdk/src/java.management/unix/native/libmanagement : jdk/src/solaris/native/sun/management
jdk/src/java.management/windows/classes/sun/management : jdk/src/windows/classes/sun/management
jdk/src/java.management/windows/native/libmanagement : jdk/src/windows/native/sun/management
+jdk/src/java.management.rmi/share/classes/com/sun/jmx/remote/internal/rmi/ProxyRef.java : jdk/src/share/classes/com/sun/jmx/remote/internal/ProxyRef.java
+jdk/src/java.management.rmi/share/classes/com/sun/jmx/remote/internal/rmi/RMIExporter.java : jdk/src/share/classes/com/sun/jmx/remote/internal/RMIExporter.java
+jdk/src/java.management.rmi/share/classes/com/sun/jmx/remote/internal/rmi/Unmarshal.java : jdk/src/share/classes/com/sun/jmx/remote/internal/Unmarshal.java
+jdk/src/java.management.rmi/share/classes/com/sun/jmx/remote/protocol/rmi : jdk/src/share/classes/com/sun/jmx/remote/protocol/rmi
+jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi : jdk/src/share/classes/javax/management/remote/rmi
jdk/src/java.naming/share/classes/com/sun/jndi/ldap/ext : jdk/src/share/classes/com/sun/jndi/ldap/ext
jdk/src/java.naming/share/classes/com/sun/jndi/ldap : jdk/src/share/classes/com/sun/jndi/ldap
jdk/src/java.naming/share/classes/com/sun/jndi/ldap/pool : jdk/src/share/classes/com/sun/jndi/ldap/pool
@@ -1330,9 +1332,9 @@ jdk/src/jdk.jdwp.agent/unix/native/libdt_socket : jdk/src/solaris/transport/sock
jdk/src/jdk.jdwp.agent/unix/native/libjdwp : jdk/src/solaris/back
jdk/src/jdk.jdwp.agent/windows/native/libdt_socket : jdk/src/windows/transport/socket
jdk/src/jdk.jdwp.agent/windows/native/libjdwp : jdk/src/windows/back
-jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/monitor : jdk/src/share/classes/sun/jvmstat/monitor
-jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/perfdata : jdk/src/share/classes/sun/jvmstat/perfdata
-jdk/src/jdk.jvmstat/share/classes/sun/tools/jstatd : jdk/src/share/classes/sun/tools/jstatd
+jdk/src/jdk.internal.jvmstat/share/classes/sun/jvmstat/monitor : jdk/src/share/classes/sun/jvmstat/monitor
+jdk/src/jdk.internal.jvmstat/share/classes/sun/jvmstat/perfdata : jdk/src/share/classes/sun/jvmstat/perfdata
+jdk/src/jdk.internal.jvmstat/share/classes/sun/tools/jstatd : jdk/src/share/classes/sun/tools/jstatd
jdk/src/jdk.localedata/share/classes/sun/text/resources/ar : jdk/src/share/classes/sun/text/resources/ar
jdk/src/jdk.localedata/share/classes/sun/text/resources/be : jdk/src/share/classes/sun/text/resources/be
jdk/src/jdk.localedata/share/classes/sun/text/resources/bg : jdk/src/share/classes/sun/text/resources/bg
@@ -1421,6 +1423,9 @@ jdk/src/jdk.localedata/share/classes/sun/util/resources/uk : jdk/src/share/class
jdk/src/jdk.localedata/share/classes/sun/util/resources/vi : jdk/src/share/classes/sun/util/resources/vi
jdk/src/jdk.localedata/share/classes/sun/util/resources/zh : jdk/src/share/classes/sun/util/resources/zh
jdk/src/jdk.management/share/classes/com/sun/management : jdk/src/share/classes/com/sun/management
+jdk/src/jdk.management.agent/share/classes/jdk/internal/agent/resources : jdk/src/share/classes/sun/management/resources
+jdk/src/jdk.management.agent/share/classes/sun/management/jmxremote : jdk/src/share/classes/sun/management/jmxremote
+jdk/src/jdk.management.agent/share/classes/sun/management/jdp : jdk/src/share/classes/sun/management/jdp
jdk/src/jdk.naming.dns/share/classes/com/sun/jndi/dns : jdk/src/share/classes/com/sun/jndi/dns
jdk/src/jdk.naming.dns/share/classes/com/sun/jndi/url/dns : jdk/src/share/classes/com/sun/jndi/url/dns
jdk/src/jdk.naming.dns/share/classes/META-INF/services : jdk/src/share/classes/sun/net/spi/nameservice/dns/META-INF/services
diff --git a/corba/.hgtags b/corba/.hgtags
index dd78cf97c29..7a24e3f5f23 100644
--- a/corba/.hgtags
+++ b/corba/.hgtags
@@ -397,3 +397,4 @@ f95cc86b6ac22ec1ade5d4f825dc7782adeea228 jdk-9+148
ff8cb43c07c069b1debdee44cb88ca22db1ec757 jdk-9+152
68a8e8658511093b322a46ed04b2a321e1da2a43 jdk-9+153
078ebe23b584466dc8346e620d7821d91751e5a9 jdk-9+154
+a545f54babfa31aa7eb611f36031609acd617cbc jdk-9+155
diff --git a/hotspot/.hgtags b/hotspot/.hgtags
index 8a3f632ef26..66afb5ed54b 100644
--- a/hotspot/.hgtags
+++ b/hotspot/.hgtags
@@ -557,3 +557,4 @@ a82cb5350cad96a0b4de496afebe3ded89f27efa jdk-9+146
31f1d26c60df7b2e516a4f84160d76ba017d4e09 jdk-9+152
217ba81b9a4ce8698200370175aa2db86a39f66c jdk-9+153
a9fdfd55835ef9dccb7f317b07249bd66653b874 jdk-9+154
+f3b3d77a1751897413aae43ac340a130b6fa2ae1 jdk-9+155
diff --git a/hotspot/make/ide/CreateVSProject.gmk b/hotspot/make/ide/CreateVSProject.gmk
index d6f5324adb8..db0aca87e28 100644
--- a/hotspot/make/ide/CreateVSProject.gmk
+++ b/hotspot/make/ide/CreateVSProject.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2016, 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
@@ -121,7 +121,7 @@ ifeq ($(OPENJDK_TARGET_OS), windows)
-buildBase $(call FixPath, $(IDE_OUTPUTDIR)/vs-output) \
-buildSpace $(call FixPath, $(IDE_OUTPUTDIR)) \
-makeBinary $(call FixPath, $(MAKE)) \
- -makeOutput $(call FixPath, $(HOTSPOT_OUTPUTDIR)/variant-%f/libjvm) \
+ -makeOutput $(call FixPath, $(JDK_OUTPUTDIR)/bin/server) \
-absoluteInclude $(call FixPath, $(HOTSPOT_OUTPUTDIR)/variant-server/gensrc) \
-absoluteSrcInclude $(call FixPath, $(HOTSPOT_OUTPUTDIR)/variant-server/gensrc) \
$(EXTRACTED_DEFINES_client) \
diff --git a/hotspot/make/lib/CompileJvm.gmk b/hotspot/make/lib/CompileJvm.gmk
index 870dde18d78..36d955807ad 100644
--- a/hotspot/make/lib/CompileJvm.gmk
+++ b/hotspot/make/lib/CompileJvm.gmk
@@ -63,7 +63,7 @@ JVM_CFLAGS_INCLUDES += \
# INCLUDE_SUFFIX_* is only meant for including the proper
# platform files. Don't use it to guard code. Use the value of
# HOTSPOT_TARGET_CPU_DEFINE etc. instead.
-# Remaining TARGET_ARCH_* is needed to select the cpu specific
+# Remaining TARGET_ARCH_* is needed to select the cpu specific
# sources for 64-bit ARM ports (arm versus aarch64).
JVM_CFLAGS_TARGET_DEFINES += \
-DTARGET_ARCH_$(HOTSPOT_TARGET_CPU_ARCH) \
@@ -132,7 +132,7 @@ CFLAGS_VM_VERSION := \
#
# -DDONT_USE_PRECOMPILED_HEADER will exclude all includes in precompiled.hpp.
-ifeq ($(USE_PRECOMPILED_HEADER), 0)
+ifeq ($(USE_PRECOMPILED_HEADER), false)
JVM_CFLAGS += -DDONT_USE_PRECOMPILED_HEADER
endif
@@ -145,7 +145,7 @@ ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU), linux-arm)
JVM_EXCLUDE_PATTERNS += arm_64
else ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU), linux-aarch64)
- # For 64-bit arm builds, we use the 64 bit hotspot/src/cpu/arm
+ # For 64-bit arm builds, we use the 64 bit hotspot/src/cpu/arm
# hotspot sources if HOTSPOT_TARGET_CPU_ARCH is set to arm.
# Exclude the aarch64 and 32 bit arm files for this build.
ifeq ($(HOTSPOT_TARGET_CPU_ARCH), arm)
diff --git a/hotspot/make/src/classes/build/tools/projectcreator/WinGammaPlatformVC10.java b/hotspot/make/src/classes/build/tools/projectcreator/WinGammaPlatformVC10.java
index d44fb04c588..50413e52792 100644
--- a/hotspot/make/src/classes/build/tools/projectcreator/WinGammaPlatformVC10.java
+++ b/hotspot/make/src/classes/build/tools/projectcreator/WinGammaPlatformVC10.java
@@ -1,5 +1,5 @@
/*
- * 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
@@ -114,8 +114,8 @@ public class WinGammaPlatformVC10 extends WinGammaPlatform {
tag(cfg, "CodeAnalysisRuleAssemblies");
}
for (BuildConfig cfg : allConfigs) {
- tagData(cfg, "NMakeBuildCommandLine", cfg.get("MakeBinary") + " -f ../../Makefile import-hotspot LOG=info");
- tagData(cfg, "NMakeReBuildCommandLine", cfg.get("MakeBinary") + " -f ../../Makefile clean-hotspot import-hotspot LOG=info");
+ tagData(cfg, "NMakeBuildCommandLine", cfg.get("MakeBinary") + " -f ../../Makefile hotspot LOG=info");
+ tagData(cfg, "NMakeReBuildCommandLine", cfg.get("MakeBinary") + " -f ../../Makefile clean-hotspot hotspot LOG=info");
tagData(cfg, "NMakeCleanCommandLine", cfg.get("MakeBinary") + " -f ../../Makefile clean-hotspot LOG=info");
tagData(cfg, "NMakeOutput", cfg.get("MakeOutput") + Util.sep + "jvm.dll");
tagData(cfg, "NMakePreprocessorDefinitions", Util.join(";", cfg.getDefines()));
diff --git a/hotspot/make/symbols/symbols-unix b/hotspot/make/symbols/symbols-unix
index 90326d263dc..11add06efac 100644
--- a/hotspot/make/symbols/symbols-unix
+++ b/hotspot/make/symbols/symbols-unix
@@ -192,4 +192,3 @@ JVM_AddModulePackage
JVM_AddReadsModule
JVM_DefineModule
JVM_SetBootLoaderUnnamedModule
-JVM_GetModuleByPackageName
diff --git a/hotspot/src/cpu/aarch64/vm/aarch64.ad b/hotspot/src/cpu/aarch64/vm/aarch64.ad
index 2294bab8db8..37e63dc9aba 100644
--- a/hotspot/src/cpu/aarch64/vm/aarch64.ad
+++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad
@@ -1042,8 +1042,10 @@ class HandlerImpl {
bool is_card_mark_membar(const MemBarNode *barrier);
bool is_CAS(int opcode);
- MemBarNode *leading_to_trailing(MemBarNode *leading);
- MemBarNode *card_mark_to_leading(const MemBarNode *barrier);
+ MemBarNode *leading_to_normal(MemBarNode *leading);
+ MemBarNode *normal_to_leading(const MemBarNode *barrier);
+ MemBarNode *card_mark_to_trailing(const MemBarNode *barrier);
+ MemBarNode *trailing_to_card_mark(const MemBarNode *trailing);
MemBarNode *trailing_to_leading(const MemBarNode *trailing);
// predicates controlling emit of ldr/ldar and associated dmb
@@ -1420,28 +1422,23 @@ source %{
// leading MemBarRelease and a trailing MemBarVolatile as follows
//
// MemBarRelease
- // { || } -- optional
+ // { || } -- optional
// {MemBarCPUOrder}
- // || \\
- // || StoreX[mo_release]
- // | \ Bot / ???
- // | MergeMem
- // | /
+ // || \\
+ // || StoreX[mo_release]
+ // | \ /
+ // | MergeMem
+ // | /
// MemBarVolatile
//
// where
// || and \\ represent Ctl and Mem feeds via Proj nodes
// | \ and / indicate further routing of the Ctl and Mem feeds
//
- // Note that the memory feed from the CPUOrder membar to the
- // MergeMem node is an AliasIdxBot slice while the feed from the
- // StoreX is for a slice determined by the type of value being
- // written.
- //
- // the diagram above shows the graph we see for non-object stores.
- // for a volatile Object store (StoreN/P) we may see other nodes
- // below the leading membar because of the need for a GC pre- or
- // post-write barrier.
+ // this is the graph we see for non-object stores. however, for a
+ // volatile Object store (StoreN/P) we may see other nodes below the
+ // leading membar because of the need for a GC pre- or post-write
+ // barrier.
//
// with most GC configurations we with see this simple variant which
// includes a post-write barrier card mark.
@@ -1449,7 +1446,7 @@ source %{
// MemBarRelease______________________________
// || \\ Ctl \ \\
// || StoreN/P[mo_release] CastP2X StoreB/CM
- // | \ Bot / oop . . . /
+ // | \ / . . . /
// | MergeMem
// | /
// || /
@@ -1459,142 +1456,152 @@ source %{
// the object address to an int used to compute the card offset) and
// Ctl+Mem to a StoreB node (which does the actual card mark).
//
- // n.b. a StoreCM node is only ever used when CMS (with or without
- // CondCardMark) or G1 is configured. This abstract instruction
- // differs from a normal card mark write (StoreB) because it implies
- // a requirement to order visibility of the card mark (StoreCM)
- // after that of the object put (StoreP/N) using a StoreStore memory
- // barrier. Note that this is /not/ a requirement to order the
- // instructions in the generated code (that is already guaranteed by
- // the order of memory dependencies). Rather it is a requirement to
- // ensure visibility order which only applies on architectures like
- // AArch64 which do not implement TSO. This ordering is required for
- // both non-volatile and volatile puts.
- //
- // That implies that we need to translate a StoreCM using the
- // sequence
+ // n.b. a StoreCM node will only appear in this configuration when
+ // using CMS. StoreCM differs from a normal card mark write (StoreB)
+ // because it implies a requirement to order visibility of the card
+ // mark (StoreCM) relative to the object put (StoreP/N) using a
+ // StoreStore memory barrier (arguably this ought to be represented
+ // explicitly in the ideal graph but that is not how it works). This
+ // ordering is required for both non-volatile and volatile
+ // puts. Normally that means we need to translate a StoreCM using
+ // the sequence
//
// dmb ishst
// stlrb
//
- // This dmb cannot be omitted even when the associated StoreX or
- // CompareAndSwapX is implemented using stlr. However, as described
- // below there are circumstances where a specific GC configuration
- // requires a stronger barrier in which case it can be omitted.
- //
- // With the Serial or Parallel GC using +CondCardMark the card mark
- // is performed conditionally on it currently being unmarked in
- // which case the volatile put graph looks slightly different
+ // However, in the case of a volatile put if we can recognise this
+ // configuration and plant an stlr for the object write then we can
+ // omit the dmb and just plant an strb since visibility of the stlr
+ // is ordered before visibility of subsequent stores. StoreCM nodes
+ // also arise when using G1 or using CMS with conditional card
+ // marking. In these cases (as we shall see) we don't need to insert
+ // the dmb when translating StoreCM because there is already an
+ // intervening StoreLoad barrier between it and the StoreP/N.
+ //
+ // It is also possible to perform the card mark conditionally on it
+ // currently being unmarked in which case the volatile put graph
+ // will look slightly different
//
// MemBarRelease____________________________________________
// || \\ Ctl \ Ctl \ \\ Mem \
// || StoreN/P[mo_release] CastP2X If LoadB |
- // | \ Bot / oop \ |
+ // | \ / \ |
// | MergeMem . . . StoreB
// | / /
// || /
// MemBarVolatile
//
- // It is worth noting at this stage that all the above
+ // It is worth noting at this stage that both the above
// configurations can be uniquely identified by checking that the
// memory flow includes the following subgraph:
//
// MemBarRelease
// {MemBarCPUOrder}
- // | \ . . .
- // | StoreX[mo_release] . . .
- // Bot | / oop
- // MergeMem
- // |
+ // | \ . . .
+ // | StoreX[mo_release] . . .
+ // | /
+ // MergeMem
+ // |
// MemBarVolatile
//
- // This is referred to as a *normal* volatile store subgraph. It can
- // easily be detected starting from any candidate MemBarRelease,
- // StoreX[mo_release] or MemBarVolatile node.
+ // This is referred to as a *normal* subgraph. It can easily be
+ // detected starting from any candidate MemBarRelease,
+ // StoreX[mo_release] or MemBarVolatile.
//
- // A small variation on this normal case occurs for an unsafe CAS
- // operation. The basic memory flow subgraph for a non-object CAS is
- // as follows
+ // A simple variation on this normal case occurs for an unsafe CAS
+ // operation. The basic graph for a non-object CAS is
//
// MemBarRelease
// ||
// MemBarCPUOrder
- // | \\ . . .
- // | CompareAndSwapX
- // | |
- // Bot | SCMemProj
- // \ / Bot
- // MergeMem
- // /
+ // || \\ . . .
+ // || CompareAndSwapX
+ // || |
+ // || SCMemProj
+ // | \ /
+ // | MergeMem
+ // | /
// MemBarCPUOrder
// ||
// MemBarAcquire
//
// The same basic variations on this arrangement (mutatis mutandis)
- // occur when a card mark is introduced. i.e. the CPUOrder MemBar
- // feeds the extra CastP2X, LoadB etc nodes but the above memory
- // flow subgraph is still present.
- //
- // This is referred to as a *normal* CAS subgraph. It can easily be
- // detected starting from any candidate MemBarRelease,
- // StoreX[mo_release] or MemBarAcquire node.
+ // occur when a card mark is introduced. i.e. we se the same basic
+ // shape but the StoreP/N is replaced with CompareAndSawpP/N and the
+ // tail of the graph is a pair comprising a MemBarCPUOrder +
+ // MemBarAcquire.
//
- // The code below uses two helper predicates, leading_to_trailing
- // and trailing_to_leading to identify these normal graphs, one
- // validating the layout starting from the top membar and searching
- // down and the other validating the layout starting from the lower
- // membar and searching up.
+ // So, in the case of a CAS the normal graph has the variant form
//
- // There are two special case GC configurations when the simple
- // normal graphs above may not be generated: when using G1 (which
- // always employs a conditional card mark); and when using CMS with
- // conditional card marking (+CondCardMark) configured. These GCs
- // are both concurrent rather than stop-the world GCs. So they
- // introduce extra Ctl+Mem flow into the graph between the leading
- // and trailing membar nodes, in particular enforcing stronger
- // memory serialisation beween the object put and the corresponding
- // conditional card mark. CMS employs a post-write GC barrier while
- // G1 employs both a pre- and post-write GC barrier.
+ // MemBarRelease
+ // MemBarCPUOrder
+ // | \ . . .
+ // | CompareAndSwapX . . .
+ // | |
+ // | SCMemProj
+ // | / . . .
+ // MergeMem
+ // |
+ // MemBarCPUOrder
+ // MemBarAcquire
//
- // The post-write barrier subgraph for these configurations includes
- // a MemBarVolatile node -- referred to as a card mark membar --
- // which is needed to order the card write (StoreCM) operation in
- // the barrier, the preceding StoreX (or CompareAndSwapX) and Store
- // operations performed by GC threads i.e. a card mark membar
- // constitutes a StoreLoad barrier hence must be translated to a dmb
- // ish (whether or not it sits inside a volatile store sequence).
+ // This graph can also easily be detected starting from any
+ // candidate MemBarRelease, CompareAndSwapX or MemBarAcquire.
//
- // Of course, the use of the dmb ish for the card mark membar also
- // implies theat the StoreCM which follows can omit the dmb ishst
- // instruction. The necessary visibility ordering will already be
- // guaranteed by the dmb ish. In sum, the dmb ishst instruction only
- // needs to be generated for as part of the StoreCM sequence with GC
- // configuration +CMS -CondCardMark.
- //
- // Of course all these extra barrier nodes may well be absent --
- // they are only inserted for object puts. Their potential presence
- // significantly complicates the task of identifying whether a
- // MemBarRelease, StoreX[mo_release], MemBarVolatile or
- // MemBarAcquire forms part of a volatile put or CAS when using
- // these GC configurations (see below) and also complicates the
- // decision as to how to translate a MemBarVolatile and StoreCM.
+ // the code below uses two helper predicates, leading_to_normal and
+ // normal_to_leading to identify these normal graphs, one validating
+ // the layout starting from the top membar and searching down and
+ // the other validating the layout starting from the lower membar
+ // and searching up.
//
- // So, thjis means that a card mark MemBarVolatile occurring in the
- // post-barrier graph it needs to be distinguished from a normal
- // trailing MemBarVolatile. Resolving this is straightforward: a
- // card mark MemBarVolatile always projects a Mem feed to a StoreCM
- // node and that is a unique marker
+ // There are two special case GC configurations when a normal graph
+ // may not be generated: when using G1 (which always employs a
+ // conditional card mark); and when using CMS with conditional card
+ // marking configured. These GCs are both concurrent rather than
+ // stop-the world GCs. So they introduce extra Ctl+Mem flow into the
+ // graph between the leading and trailing membar nodes, in
+ // particular enforcing stronger memory serialisation beween the
+ // object put and the corresponding conditional card mark. CMS
+ // employs a post-write GC barrier while G1 employs both a pre- and
+ // post-write GC barrier. Of course the extra nodes may be absent --
+ // they are only inserted for object puts. This significantly
+ // complicates the task of identifying whether a MemBarRelease,
+ // StoreX[mo_release] or MemBarVolatile forms part of a volatile put
+ // when using these GC configurations (see below). It adds similar
+ // complexity to the task of identifying whether a MemBarRelease,
+ // CompareAndSwapX or MemBarAcquire forms part of a CAS.
+ //
+ // In both cases the post-write subtree includes an auxiliary
+ // MemBarVolatile (StoreLoad barrier) separating the object put and
+ // the read of the corresponding card. This poses two additional
+ // problems.
+ //
+ // Firstly, a card mark MemBarVolatile needs to be distinguished
+ // from a normal trailing MemBarVolatile. Resolving this first
+ // problem is straightforward: a card mark MemBarVolatile always
+ // projects a Mem feed to a StoreCM node and that is a unique marker
//
// MemBarVolatile (card mark)
// C | \ . . .
// | StoreCM . . .
// . . .
//
- // Returning to the task of translating the object put and the
- // leading/trailing membar nodes: what do the node graphs look like
- // for these 2 special cases? and how can we determine the status of
- // a MemBarRelease, StoreX[mo_release] or MemBarVolatile in both
- // normal and non-normal cases?
+ // The second problem is how the code generator is to translate the
+ // card mark barrier? It always needs to be translated to a "dmb
+ // ish" instruction whether or not it occurs as part of a volatile
+ // put. A StoreLoad barrier is needed after the object put to ensure
+ // i) visibility to GC threads of the object put and ii) visibility
+ // to the mutator thread of any card clearing write by a GC
+ // thread. Clearly a normal store (str) will not guarantee this
+ // ordering but neither will a releasing store (stlr). The latter
+ // guarantees that the object put is visible but does not guarantee
+ // that writes by other threads have also been observed.
+ //
+ // So, returning to the task of translating the object put and the
+ // leading/trailing membar nodes: what do the non-normal node graph
+ // look like for these 2 special cases? and how can we determine the
+ // status of a MemBarRelease, StoreX[mo_release] or MemBarVolatile
+ // in both normal and non-normal cases?
//
// A CMS GC post-barrier wraps its card write (StoreCM) inside an If
// which selects conditonal execution based on the value loaded
@@ -1605,117 +1612,91 @@ source %{
// which looks like this
//
// MemBarRelease
- // MemBarCPUOrder_(leading)____________________
- // C | | M \ \\ M | C \
- // | | \ StoreN/P[mo_release] | CastP2X
- // | | Bot \ / oop \ |
- // | | MergeMem \ /
- // | | / | /
- // MemBarVolatile (card mark) | /
- // C | || M | | /
- // | LoadB | Bot oop | / Bot
- // | | | / /
- // | Cmp |\ / /
- // | / | \ / /
- // If | \ / /
- // | \ | \ / /
- // IfFalse IfTrue | \ / /
- // \ / \ | | / /
- // \ / StoreCM | / /
- // \ / \ / / /
- // Region Phi / /
- // | \ Raw | / /
- // | . . . | / /
+ // MemBarCPUOrder_(leading)__________________
+ // C | M \ \\ C \
+ // | \ StoreN/P[mo_release] CastP2X
+ // | Bot \ /
+ // | MergeMem
+ // | /
+ // MemBarVolatile (card mark)
+ // C | || M |
+ // | LoadB |
+ // | | |
+ // | Cmp |\
+ // | / | \
+ // If | \
+ // | \ | \
+ // IfFalse IfTrue | \
+ // \ / \ | \
+ // \ / StoreCM |
+ // \ / | |
+ // Region . . . |
+ // | \ /
+ // | . . . \ / Bot
// | MergeMem
- // | |
+ // | |
// MemBarVolatile (trailing)
//
- // Notice that there are two MergeMem nodes below the leading
- // membar. The first MergeMem merges the AliasIdxBot Mem slice from
- // the leading membar and the oopptr Mem slice from the Store into
- // the card mark membar. The trailing MergeMem merges the
- // AliasIdxBot Mem slice from the leading membar, the AliasIdxRaw
- // slice from the StoreCM and an oop slice from the StoreN/P node
- // into the trailing membar (n.b. the raw slice proceeds via a Phi
- // associated with the If region).
+ // The first MergeMem merges the AliasIdxBot Mem slice from the
+ // leading membar and the oopptr Mem slice from the Store into the
+ // card mark membar. The trailing MergeMem merges the AliasIdxBot
+ // Mem slice from the card mark membar and the AliasIdxRaw slice
+ // from the StoreCM into the trailing membar (n.b. the latter
+ // proceeds via a Phi associated with the If region).
//
- // So, in the case of CMS + CondCardMark the volatile object store
- // graph still includes a normal volatile store subgraph from the
- // leading membar to the trailing membar. However, it also contains
- // the same shape memory flow to the card mark membar. The two flows
- // can be distinguished by testing whether or not the downstream
- // membar is a card mark membar.
- //
- // The graph for a CAS also varies with CMS + CondCardMark, in
- // particular employing a control feed from the CompareAndSwapX node
- // through a CmpI and If to the card mark membar and StoreCM which
- // updates the associated card. This avoids executing the card mark
- // if the CAS fails. However, it can be seen from the diagram below
- // that the presence of the barrier does not alter the normal CAS
- // memory subgraph where the leading membar feeds a CompareAndSwapX,
- // an SCMemProj, a MergeMem then a final trailing MemBarCPUOrder and
- // MemBarAcquire pair.
+ // The graph for a CAS varies slightly, the obvious difference being
+ // that the StoreN/P node is replaced by a CompareAndSwapP/N node
+ // and the trailing MemBarVolatile by a MemBarCPUOrder +
+ // MemBarAcquire pair. The other important difference is that the
+ // CompareAndSwap node's SCMemProj is not merged into the card mark
+ // membar - it still feeds the trailing MergeMem. This also means
+ // that the card mark membar receives its Mem feed directly from the
+ // leading membar rather than via a MergeMem.
//
// MemBarRelease
- // MemBarCPUOrder__(leading)_______________________
- // C / M | \\ C \
- // . . . | Bot CompareAndSwapN/P CastP2X
- // | C / M |
- // | CmpI |
- // | / |
- // | . . . |
- // | IfTrue |
- // | / |
- // MemBarVolatile (card mark) |
- // C | || M | |
- // | LoadB | Bot ______/|
- // | | | / |
- // | Cmp | / SCMemProj
- // | / | / |
- // If | / /
- // | \ | / / Bot
- // IfFalse IfTrue | / /
- // | / \ / / prec /
- // . . . | / StoreCM /
- // \ | / | raw /
- // Region . . . /
- // | \ /
- // | . . . \ / Bot
- // | MergeMem
- // | /
- // MemBarCPUOrder
- // MemBarAcquire (trailing)
+ // MemBarCPUOrder__(leading)_________________________
+ // || \\ C \
+ // MemBarVolatile (card mark) CompareAndSwapN/P CastP2X
+ // C | || M | |
+ // | LoadB | ______/|
+ // | | | / |
+ // | Cmp | / SCMemProj
+ // | / | / |
+ // If | / /
+ // | \ | / /
+ // IfFalse IfTrue | / /
+ // \ / \ |/ prec /
+ // \ / StoreCM /
+ // \ / | /
+ // Region . . . /
+ // | \ /
+ // | . . . \ / Bot
+ // | MergeMem
+ // | |
+ // MemBarCPUOrder
+ // MemBarAcquire (trailing)
//
// This has a slightly different memory subgraph to the one seen
- // previously but the core of it has a similar memory flow to the
- // CAS normal subgraph:
+ // previously but the core of it is the same as for the CAS normal
+ // sungraph
//
// MemBarRelease
// MemBarCPUOrder____
- // | \ . . .
- // | CompareAndSwapX . . .
- // | C / M |
- // | CmpI |
- // | / |
- // | . . /
- // Bot | IfTrue /
- // | / /
- // MemBarVolatile /
- // | ... /
- // StoreCM ... /
- // | /
- // . . . SCMemProj
- // Raw \ / Bot
- // MergeMem
- // |
+ // || \ . . .
+ // MemBarVolatile CompareAndSwapX . . .
+ // | \ |
+ // . . . SCMemProj
+ // | / . . .
+ // MergeMem
+ // |
// MemBarCPUOrder
// MemBarAcquire
//
- // The G1 graph for a volatile object put is a lot more complicated.
- // Nodes inserted on behalf of G1 may comprise: a pre-write graph
- // which adds the old value to the SATB queue; the releasing store
- // itself; and, finally, a post-write graph which performs a card
- // mark.
+ //
+ // G1 is quite a lot more complicated. The nodes inserted on behalf
+ // of G1 may comprise: a pre-write graph which adds the old value to
+ // the SATB queue; the releasing store itself; and, finally, a
+ // post-write graph which performs a card mark.
//
// The pre-write graph may be omitted, but only when the put is
// writing to a newly allocated (young gen) object and then only if
@@ -1753,60 +1734,25 @@ source %{
// | CastP2X | StoreN/P[mo_release] |
// | | | |
// C | M | M | M |
- // \ | Raw | oop / Bot
+ // \ | | /
// . . .
// (post write subtree elided)
// . . .
// C \ M /
// MemBarVolatile (trailing)
//
- // Note that the three memory feeds into the post-write tree are an
- // AliasRawIdx slice associated with the writes in the pre-write
- // tree, an oop type slice from the StoreX specific to the type of
- // the volatile field and the AliasBotIdx slice emanating from the
- // leading membar.
- //
// n.b. the LoadB in this subgraph is not the card read -- it's a
// read of the SATB queue active flag.
//
- // The CAS graph is once again a variant of the above with a
- // CompareAndSwapX node and SCMemProj in place of the StoreX. The
- // value from the CompareAndSwapX node is fed into the post-write
- // graph aling with the AliasIdxRaw feed from the pre-barrier and
- // the AliasIdxBot feeds from the leading membar and the ScMemProj.
- //
- // MemBarRelease (leading)____________
- // C | || M \ M \ M \ M \ . . .
- // | LoadB \ LoadL LoadN \
- // | / \ \
- // If |\ \
- // | \ | \ \
- // IfFalse IfTrue | \ \
- // | | | \ \
- // | If | \ |
- // | | \ |
- // | \ |
- // | . . . \ |
- // | / | / \ |
- // Region Phi[M] \ |
- // | \ | \ |
- // | \_____ | | |
- // C | C \ | | |
- // | CastP2X | CompareAndSwapX |
- // | | res | | |
- // C | M | | SCMemProj M |
- // \ | Raw | | Bot / Bot
- // . . .
- // (post write subtree elided)
- // . . .
- // C \ M /
- // MemBarVolatile (trailing)
+ // Once again the CAS graph is a minor variant on the above with the
+ // expected substitutions of CompareAndSawpX for StoreN/P and
+ // MemBarCPUOrder + MemBarAcquire for trailing MemBarVolatile.
//
// The G1 post-write subtree is also optional, this time when the
// new value being written is either null or can be identified as a
// newly allocated (young gen) object with no intervening control
// flow. The latter cannot happen but the former may, in which case
- // the card mark membar is omitted and the memory feeds from the
+ // the card mark membar is omitted and the memory feeds form the
// leading membar and the SToreN/P are merged direct into the
// trailing membar as per the normal subgraph. So, the only special
// case which arises is when the post-write subgraph is generated.
@@ -1828,106 +1774,94 @@ source %{
//
// (pre-write subtree elided)
// . . . . . . . . . . . .
- // C | M | M | M |
- // Region Phi[M] StoreN |
- // | Raw | oop | Bot |
- // / \_______ |\ |\ |\
- // C / C \ . . . | \ | \ | \
- // If CastP2X . . . | \ | \ | \
- // / \ | \ | \ | \
- // / \ | \ | \ | \
- // IfFalse IfTrue | | | \
- // | | \ | / |
- // | If \ | \ / \ |
- // | / \ \ | / \ |
- // | / \ \ | / \ | |
- // | IfFalse IfTrue MergeMem \ | |
- // | . . . / \ | \ | |
- // | / \ | | | |
- // | IfFalse IfTrue | | | |
- // | . . . | | | | |
- // | If / | | |
- // | / \ / | | |
- // | / \ / | | |
- // | IfFalse IfTrue / | | |
- // | . . . | / | | |
- // | \ / | | |
- // | \ / | | |
- // | MemBarVolatile__(card mark ) | | |
- // | || C | \ | | |
- // | LoadB If | / | |
- // | / \ Raw | / / /
- // | . . . | / / /
- // | \ | / / /
- // | StoreCM / / /
- // | | / / /
- // | . . . / /
- // | / /
- // | . . . / /
- // | | | / / /
- // | | Phi[M] / / /
- // | | | / / /
- // | | | / / /
- // | Region . . . Phi[M] / /
- // | | | / /
- // \ | | / /
- // \ | . . . | / /
- // \ | | / /
- // Region Phi[M] / /
- // | \ / /
- // \ MergeMem
- // \ /
- // MemBarVolatile
+ // C | M | M | M |
+ // Region Phi[M] StoreN |
+ // | / \ | |
+ // / \_______ / \ | |
+ // C / C \ . . . \ | |
+ // If CastP2X . . . | | |
+ // / \ | | |
+ // / \ | | |
+ // IfFalse IfTrue | | |
+ // | | | | /|
+ // | If | | / |
+ // | / \ | | / |
+ // | / \ \ | / |
+ // | IfFalse IfTrue MergeMem |
+ // | . . . / \ / |
+ // | / \ / |
+ // | IfFalse IfTrue / |
+ // | . . . | / |
+ // | If / |
+ // | / \ / |
+ // | / \ / |
+ // | IfFalse IfTrue / |
+ // | . . . | / |
+ // | \ / |
+ // | \ / |
+ // | MemBarVolatile__(card mark) |
+ // | || C | M \ M \ |
+ // | LoadB If | | |
+ // | / \ | | |
+ // | . . . | | |
+ // | \ | | /
+ // | StoreCM | /
+ // | . . . | /
+ // | _________/ /
+ // | / _____________/
+ // | . . . . . . | / /
+ // | | | / _________/
+ // | | Phi[M] / /
+ // | | | / /
+ // | | | / /
+ // | Region . . . Phi[M] _____/
+ // | / | /
+ // | | /
+ // | . . . . . . | /
+ // | / | /
+ // Region | | Phi[M]
+ // | | | / Bot
+ // \ MergeMem
+ // \ /
+ // MemBarVolatile
//
- // As with CMS + CondCardMark the first MergeMem merges the
- // AliasIdxBot Mem slice from the leading membar and the oopptr Mem
- // slice from the Store into the card mark membar. However, in this
- // case it may also merge an AliasRawIdx mem slice from the pre
- // barrier write.
+ // As with CMS the initial MergeMem merges the AliasIdxBot Mem slice
+ // from the leading membar and the oopptr Mem slice from the Store
+ // into the card mark membar i.e. the memory flow to the card mark
+ // membar still looks like a normal graph.
//
- // The trailing MergeMem merges an AliasIdxBot Mem slice from the
- // leading membar with an oop slice from the StoreN and an
- // AliasRawIdx slice from the post barrier writes. In this case the
- // AliasIdxRaw Mem slice is merged through a series of Phi nodes
- // which combine feeds from the If regions in the post barrier
- // subgraph.
+ // The trailing MergeMem merges an AliasIdxBot Mem slice with other
+ // Mem slices (from the StoreCM and other card mark queue stores).
+ // However in this case the AliasIdxBot Mem slice does not come
+ // direct from the card mark membar. It is merged through a series
+ // of Phi nodes. These are needed to merge the AliasIdxBot Mem flow
+ // from the leading membar with the Mem feed from the card mark
+ // membar. Each Phi corresponds to one of the Ifs which may skip
+ // around the card mark membar. So when the If implementing the NULL
+ // value check has been elided the total number of Phis is 2
+ // otherwise it is 3.
//
- // So, for G1 the same characteristic subgraph arises as for CMS +
- // CondCardMark. There is a normal subgraph feeding the card mark
- // membar and a normal subgraph feeding the trailing membar.
+ // The CAS graph when using G1GC also includes a pre-write subgraph
+ // and an optional post-write subgraph. Teh sam evarioations are
+ // introduced as for CMS with conditional card marking i.e. the
+ // StoreP/N is swapped for a CompareAndSwapP/N, the tariling
+ // MemBarVolatile for a MemBarCPUOrder + MemBarAcquire pair and the
+ // Mem feed from the CompareAndSwapP/N includes a precedence
+ // dependency feed to the StoreCM and a feed via an SCMemProj to the
+ // trailing membar. So, as before the configuration includes the
+ // normal CAS graph as a subgraph of the memory flow.
//
- // The CAS graph when using G1GC also includes an optional
- // post-write subgraph. It is very similar to the above graph except
- // for a few details.
- //
- // - The control flow is gated by an additonal If which tests the
- // result from the CompareAndSwapX node
- //
- // - The MergeMem which feeds the card mark membar only merges the
- // AliasIdxBot slice from the leading membar and the AliasIdxRaw
- // slice from the pre-barrier. It does not merge the SCMemProj
- // AliasIdxBot slice. So, this subgraph does not look like the
- // normal CAS subgraph.
- //
- // - The MergeMem which feeds the trailing membar merges the
- // AliasIdxBot slice from the leading membar, the AliasIdxRaw slice
- // from the post-barrier and the SCMemProj AliasIdxBot slice i.e. it
- // has two AliasIdxBot input slices. However, this subgraph does
- // still look like the normal CAS subgraph.
- //
- // So, the upshot is:
- //
- // In all cases a volatile put graph will include a *normal*
- // volatile store subgraph betwen the leading membar and the
- // trailing membar. It may also include a normal volatile store
- // subgraph betwen the leading membar and the card mark membar.
- //
- // In all cases a CAS graph will contain a unique normal CAS graph
- // feeding the trailing membar.
- //
- // In all cases where there is a card mark membar (either as part of
- // a volatile object put or CAS) it will be fed by a MergeMem whose
- // AliasIdxBot slice feed will be a leading membar.
+ // So, the upshot is that in all cases the volatile put graph will
+ // include a *normal* memory subgraph betwen the leading membar and
+ // its child membar, either a volatile put graph (including a
+ // releasing StoreX) or a CAS graph (including a CompareAndSwapX).
+ // When that child is not a card mark membar then it marks the end
+ // of the volatile put or CAS subgraph. If the child is a card mark
+ // membar then the normal subgraph will form part of a volatile put
+ // subgraph if and only if the child feeds an AliasIdxBot Mem feed
+ // to a trailing barrier via a MergeMem. That feed is either direct
+ // (for CMS) or via 2 or 3 Phi nodes merging the leading barrier
+ // memory flow (for G1).
//
// The predicates controlling generation of instructions for store
// and barrier nodes employ a few simple helper functions (described
@@ -1971,24 +1905,24 @@ source %{
}
- // leading_to_trailing
+ // leading_to_normal
//
//graph traversal helper which detects the normal case Mem feed from
// a release membar (or, optionally, its cpuorder child) to a
// dependent volatile membar i.e. it ensures that one or other of
// the following Mem flow subgraph is present.
//
- // MemBarRelease {leading}
- // {MemBarCPUOrder} {optional}
- // Bot | \ . . .
- // | StoreN/P[mo_release] . . .
- // | /
- // MergeMem
- // |
- // MemBarVolatile {not card mark}
+ // MemBarRelease
+ // MemBarCPUOrder {leading}
+ // | \ . . .
+ // | StoreN/P[mo_release] . . .
+ // | /
+ // MergeMem
+ // |
+ // MemBarVolatile {trailing or card mark}
//
- // MemBarRelease {leading}
- // {MemBarCPUOrder} {optional}
+ // MemBarRelease
+ // MemBarCPUOrder {leading}
// | \ . . .
// | CompareAndSwapX . . .
// |
@@ -1999,23 +1933,6 @@ source %{
// MemBarCPUOrder
// MemBarAcquire {trailing}
//
- // the predicate needs to be capable of distinguishing the following
- // volatile put graph which may arises when a GC post barrier
- // inserts a card mark membar
- //
- // MemBarRelease {leading}
- // {MemBarCPUOrder}__
- // Bot | \ \
- // | StoreN/P \
- // | / \ |
- // MergeMem \ |
- // | \ |
- // MemBarVolatile \ |
- // {card mark} \ |
- // MergeMem
- // |
- // {not card mark} MemBarVolatile
- //
// if the correct configuration is present returns the trailing
// membar otherwise NULL.
//
@@ -2026,7 +1943,7 @@ source %{
// the returned value may be a card mark or trailing membar
//
- MemBarNode *leading_to_trailing(MemBarNode *leading)
+ MemBarNode *leading_to_normal(MemBarNode *leading)
{
assert((leading->Opcode() == Op_MemBarRelease ||
leading->Opcode() == Op_MemBarCPUOrder),
@@ -2043,21 +1960,15 @@ source %{
StoreNode * st = NULL;
LoadStoreNode *cas = NULL;
MergeMemNode *mm = NULL;
- MergeMemNode *mm2 = NULL;
for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) {
x = mem->fast_out(i);
if (x->is_MergeMem()) {
if (mm != NULL) {
- if (mm2 != NULL) {
- // should not see more than 2 merge mems
- return NULL;
- } else {
- mm2 = x->as_MergeMem();
- }
- } else {
- mm = x->as_MergeMem();
+ return NULL;
}
+ // two merge mems is one too many
+ mm = x->as_MergeMem();
} else if (x->is_Store() && x->as_Store()->is_release() && x->Opcode() != Op_StoreCM) {
// two releasing stores/CAS nodes is one too many
if (st != NULL || cas != NULL) {
@@ -2077,13 +1988,13 @@ source %{
return NULL;
}
- // must have at least one merge if we also have st
+ // must have a merge if we also have st
if (st && !mm) {
return NULL;
}
+ Node *y = NULL;
if (cas) {
- Node *y = NULL;
// look for an SCMemProj
for (DUIterator_Fast imax, i = cas->fast_outs(imax); i < imax; i++) {
x = cas->fast_out(i);
@@ -2103,29 +2014,10 @@ source %{
break;
}
}
- if (mm == NULL) {
+ if (mm == NULL)
return NULL;
- }
- MemBarNode *mbar = NULL;
- // ensure the merge feeds a trailing membar cpuorder + acquire pair
- for (DUIterator_Fast imax, i = mm->fast_outs(imax); i < imax; i++) {
- x = mm->fast_out(i);
- if (x->is_MemBar()) {
- int opcode = x->Opcode();
- if (opcode == Op_MemBarCPUOrder) {
- MemBarNode *z = x->as_MemBar();
- z = child_membar(z);
- if (z != NULL && z->Opcode() == Op_MemBarAcquire) {
- mbar = z;
- }
- }
- break;
- }
- }
- return mbar;
} else {
- Node *y = NULL;
- // ensure the store feeds the first mergemem;
+ // ensure the store feeds the existing mergemem;
for (DUIterator_Fast imax, i = st->fast_outs(imax); i < imax; i++) {
if (st->fast_out(i) == mm) {
y = st;
@@ -2135,89 +2027,55 @@ source %{
if (y == NULL) {
return NULL;
}
- if (mm2 != NULL) {
- // ensure the store feeds the second mergemem;
- y = NULL;
- for (DUIterator_Fast imax, i = st->fast_outs(imax); i < imax; i++) {
- if (st->fast_out(i) == mm2) {
- y = st;
- }
- }
- if (y == NULL) {
- return NULL;
- }
- }
+ }
- MemBarNode *mbar = NULL;
- // ensure the first mergemem feeds a volatile membar
- for (DUIterator_Fast imax, i = mm->fast_outs(imax); i < imax; i++) {
- x = mm->fast_out(i);
- if (x->is_MemBar()) {
- int opcode = x->Opcode();
- if (opcode == Op_MemBarVolatile) {
- mbar = x->as_MemBar();
+ MemBarNode *mbar = NULL;
+ // ensure the merge feeds to the expected type of membar
+ for (DUIterator_Fast imax, i = mm->fast_outs(imax); i < imax; i++) {
+ x = mm->fast_out(i);
+ if (x->is_MemBar()) {
+ int opcode = x->Opcode();
+ if (opcode == Op_MemBarVolatile && st) {
+ mbar = x->as_MemBar();
+ } else if (cas && opcode == Op_MemBarCPUOrder) {
+ MemBarNode *y = x->as_MemBar();
+ y = child_membar(y);
+ if (y != NULL && y->Opcode() == Op_MemBarAcquire) {
+ mbar = y;
}
- break;
- }
- }
- if (mm2 == NULL) {
- // this is our only option for a trailing membar
- return mbar;
- }
- // ensure the second mergemem feeds a volatile membar
- MemBarNode *mbar2 = NULL;
- for (DUIterator_Fast imax, i = mm2->fast_outs(imax); i < imax; i++) {
- x = mm2->fast_out(i);
- if (x->is_MemBar()) {
- int opcode = x->Opcode();
- if (opcode == Op_MemBarVolatile) {
- mbar2 = x->as_MemBar();
- }
- break;
- }
- }
- // if we have two merge mems we must have two volatile membars
- if (mbar == NULL || mbar2 == NULL) {
- return NULL;
- }
- // return the trailing membar
- if (is_card_mark_membar(mbar2)) {
- return mbar;
- } else {
- if (is_card_mark_membar(mbar)) {
- return mbar2;
- } else {
- return NULL;
}
+ break;
}
}
+
+ return mbar;
}
- // trailing_to_leading
+ // normal_to_leading
//
// graph traversal helper which detects the normal case Mem feed
- // from a trailing membar to a preceding release membar (optionally
- // its cpuorder child) i.e. it ensures that one or other of the
- // following Mem flow subgraphs is present.
+ // from either a card mark or a trailing membar to a preceding
+ // release membar (optionally its cpuorder child) i.e. it ensures
+ // that one or other of the following Mem flow subgraphs is present.
//
- // MemBarRelease {leading}
- // MemBarCPUOrder {optional}
- // | Bot | \ . . .
- // | | StoreN/P[mo_release] . . .
- // | | /
- // | MergeMem
- // | |
- // MemBarVolatile {not card mark}
+ // MemBarRelease
+ // MemBarCPUOrder {leading}
+ // | \ . . .
+ // | StoreN/P[mo_release] . . .
+ // | /
+ // MergeMem
+ // |
+ // MemBarVolatile {card mark or trailing}
//
- // MemBarRelease {leading}
- // MemBarCPUOrder {optional}
+ // MemBarRelease
+ // MemBarCPUOrder {leading}
// | \ . . .
// | CompareAndSwapX . . .
// |
// . . . SCMemProj
// \ |
// | MergeMem
- // | |
+ // | /
// MemBarCPUOrder
// MemBarAcquire {trailing}
//
@@ -2227,20 +2085,15 @@ source %{
// if the configuration is present returns the cpuorder member for
// preference or when absent the release membar otherwise NULL.
//
- // n.b. the input membar is expected to be a MemBarVolatile or
- // MemBarAcquire. if it is a MemBarVolatile it must *not* be a card
- // mark membar.
+ // n.b. the input membar is expected to be a MemBarVolatile but
+ // need not be a card mark membar.
- MemBarNode *trailing_to_leading(const MemBarNode *barrier)
+ MemBarNode *normal_to_leading(const MemBarNode *barrier)
{
// input must be a volatile membar
assert((barrier->Opcode() == Op_MemBarVolatile ||
barrier->Opcode() == Op_MemBarAcquire),
"expecting a volatile or an acquire membar");
-
- assert((barrier->Opcode() != Op_MemBarVolatile) ||
- !is_card_mark_membar(barrier),
- "not expecting a card mark membar");
Node *x;
bool is_cas = barrier->Opcode() == Op_MemBarAcquire;
@@ -2353,35 +2206,169 @@ source %{
return NULL;
}
- // card_mark_to_leading
+ // card_mark_to_trailing
//
- // graph traversal helper which traverses from a card mark volatile
- // membar to a leading membar i.e. it ensures that the following Mem
- // flow subgraph is present.
+ // graph traversal helper which detects extra, non-normal Mem feed
+ // from a card mark volatile membar to a trailing membar i.e. it
+ // ensures that one of the following three GC post-write Mem flow
+ // subgraphs is present.
//
- // MemBarRelease {leading}
- // {MemBarCPUOrder} {optional}
- // | . . .
+ // 1)
+ // . . .
+ // |
+ // MemBarVolatile (card mark)
+ // | |
+ // | StoreCM
+ // | |
+ // | . . .
+ // Bot | /
+ // MergeMem
+ // |
+ // |
+ // MemBarVolatile {trailing}
+ //
+ // 2)
+ // MemBarRelease/CPUOrder (leading)
+ // |
+ // |
+ // |\ . . .
+ // | \ |
+ // | \ MemBarVolatile (card mark)
+ // | \ | |
+ // \ \ | StoreCM . . .
+ // \ \ |
+ // \ Phi
+ // \ /
+ // Phi . . .
// Bot | /
- // MergeMem
+ // MergeMem
// |
- // MemBarVolatile (card mark)
- // | \
- // . . . StoreCM
+ // MemBarVolatile {trailing}
//
- // if the configuration is present returns the cpuorder member for
- // preference or when absent the release membar otherwise NULL.
//
- // n.b. the input membar is expected to be a MemBarVolatile amd must
- // be a card mark membar.
+ // 3)
+ // MemBarRelease/CPUOrder (leading)
+ // |
+ // |\
+ // | \
+ // | \ . . .
+ // | \ |
+ // |\ \ MemBarVolatile (card mark)
+ // | \ \ | |
+ // | \ \ | StoreCM . . .
+ // | \ \ |
+ // \ \ Phi
+ // \ \ /
+ // \ Phi
+ // \ /
+ // Phi . . .
+ // Bot | /
+ // MergeMem
+ // |
+ // |
+ // MemBarVolatile {trailing}
+ //
+ // configuration 1 is only valid if UseConcMarkSweepGC &&
+ // UseCondCardMark
+ //
+ // configurations 2 and 3 are only valid if UseG1GC.
+ //
+ // if a valid configuration is present returns the trailing membar
+ // otherwise NULL.
+ //
+ // n.b. the supplied membar is expected to be a card mark
+ // MemBarVolatile i.e. the caller must ensure the input node has the
+ // correct operand and feeds Mem to a StoreCM node
- MemBarNode *card_mark_to_leading(const MemBarNode *barrier)
+ MemBarNode *card_mark_to_trailing(const MemBarNode *barrier)
{
// input must be a card mark volatile membar
assert(is_card_mark_membar(barrier), "expecting a card mark membar");
+ Node *feed = barrier->proj_out(TypeFunc::Memory);
+ Node *x;
+ MergeMemNode *mm = NULL;
+
+ const int MAX_PHIS = 3; // max phis we will search through
+ int phicount = 0; // current search count
+
+ bool retry_feed = true;
+ while (retry_feed) {
+ // see if we have a direct MergeMem feed
+ for (DUIterator_Fast imax, i = feed->fast_outs(imax); i < imax; i++) {
+ x = feed->fast_out(i);
+ // the correct Phi will be merging a Bot memory slice
+ if (x->is_MergeMem()) {
+ mm = x->as_MergeMem();
+ break;
+ }
+ }
+ if (mm) {
+ retry_feed = false;
+ } else if (UseG1GC & phicount++ < MAX_PHIS) {
+ // the barrier may feed indirectly via one or two Phi nodes
+ PhiNode *phi = NULL;
+ for (DUIterator_Fast imax, i = feed->fast_outs(imax); i < imax; i++) {
+ x = feed->fast_out(i);
+ // the correct Phi will be merging a Bot memory slice
+ if (x->is_Phi() && x->adr_type() == TypePtr::BOTTOM) {
+ phi = x->as_Phi();
+ break;
+ }
+ }
+ if (!phi) {
+ return NULL;
+ }
+ // look for another merge below this phi
+ feed = phi;
+ } else {
+ // couldn't find a merge
+ return NULL;
+ }
+ }
+
+ // sanity check this feed turns up as the expected slice
+ assert(mm->as_MergeMem()->in(Compile::AliasIdxBot) == feed, "expecting membar to feed AliasIdxBot slice to Merge");
+
+ MemBarNode *trailing = NULL;
+ // be sure we have a trailing membar the merge
+ for (DUIterator_Fast imax, i = mm->fast_outs(imax); i < imax; i++) {
+ x = mm->fast_out(i);
+ if (x->is_MemBar() && x->Opcode() == Op_MemBarVolatile) {
+ trailing = x->as_MemBar();
+ break;
+ }
+ }
+
+ return trailing;
+ }
+
+ // trailing_to_card_mark
+ //
+ // graph traversal helper which detects extra, non-normal Mem feed
+ // from a trailing volatile membar to a preceding card mark volatile
+ // membar i.e. it identifies whether one of the three possible extra
+ // GC post-write Mem flow subgraphs is present
+ //
+ // this predicate checks for the same flow as the previous predicate
+ // but starting from the bottom rather than the top.
+ //
+ // if the configuration is present returns the card mark membar
+ // otherwise NULL
+ //
+ // n.b. the supplied membar is expected to be a trailing
+ // MemBarVolatile i.e. the caller must ensure the input node has the
+ // correct opcode
+
+ MemBarNode *trailing_to_card_mark(const MemBarNode *trailing)
+ {
+ assert(trailing->Opcode() == Op_MemBarVolatile,
+ "expecting a volatile membar");
+ assert(!is_card_mark_membar(trailing),
+ "not expecting a card mark membar");
+
// the Mem feed to the membar should be a merge
- Node *x = barrier->in(TypeFunc::Memory);
+ Node *x = trailing->in(TypeFunc::Memory);
if (!x->is_MergeMem()) {
return NULL;
}
@@ -2389,20 +2376,118 @@ source %{
MergeMemNode *mm = x->as_MergeMem();
x = mm->in(Compile::AliasIdxBot);
+ // with G1 we may possibly see a Phi or two before we see a Memory
+ // Proj from the card mark membar
+ const int MAX_PHIS = 3; // max phis we will search through
+ int phicount = 0; // current search count
+
+ bool retry_feed = !x->is_Proj();
+
+ while (retry_feed) {
+ if (UseG1GC && x->is_Phi() && phicount++ < MAX_PHIS) {
+ PhiNode *phi = x->as_Phi();
+ ProjNode *proj = NULL;
+ PhiNode *nextphi = NULL;
+ bool found_leading = false;
+ for (uint i = 1; i < phi->req(); i++) {
+ x = phi->in(i);
+ if (x->is_Phi()) {
+ nextphi = x->as_Phi();
+ } else if (x->is_Proj()) {
+ int opcode = x->in(0)->Opcode();
+ if (opcode == Op_MemBarVolatile) {
+ proj = x->as_Proj();
+ } else if (opcode == Op_MemBarRelease ||
+ opcode == Op_MemBarCPUOrder) {
+ // probably a leading membar
+ found_leading = true;
+ }
+ }
+ }
+ // if we found a correct looking proj then retry from there
+ // otherwise we must see a leading and a phi or this the
+ // wrong config
+ if (proj != NULL) {
+ x = proj;
+ retry_feed = false;
+ } else if (found_leading && nextphi != NULL) {
+ // retry from this phi to check phi2
+ x = nextphi;
+ } else {
+ // not what we were looking for
+ return NULL;
+ }
+ } else {
+ return NULL;
+ }
+ }
+ // the proj has to come from the card mark membar
+ x = x->in(0);
if (!x->is_MemBar()) {
return NULL;
}
- MemBarNode *leading = x->as_MemBar();
+ MemBarNode *card_mark_membar = x->as_MemBar();
- if (leading_membar(leading)) {
+ if (!is_card_mark_membar(card_mark_membar)) {
+ return NULL;
+ }
+
+ return card_mark_membar;
+ }
+
+ // trailing_to_leading
+ //
+ // graph traversal helper which checks the Mem flow up the graph
+ // from a (non-card mark) trailing membar attempting to locate and
+ // return an associated leading membar. it first looks for a
+ // subgraph in the normal configuration (relying on helper
+ // normal_to_leading). failing that it then looks for one of the
+ // possible post-write card mark subgraphs linking the trailing node
+ // to a the card mark membar (relying on helper
+ // trailing_to_card_mark), and then checks that the card mark membar
+ // is fed by a leading membar (once again relying on auxiliary
+ // predicate normal_to_leading).
+ //
+ // if the configuration is valid returns the cpuorder member for
+ // preference or when absent the release membar otherwise NULL.
+ //
+ // n.b. the input membar is expected to be either a volatile or
+ // acquire membar but in the former case must *not* be a card mark
+ // membar.
+
+ MemBarNode *trailing_to_leading(const MemBarNode *trailing)
+ {
+ assert((trailing->Opcode() == Op_MemBarAcquire ||
+ trailing->Opcode() == Op_MemBarVolatile),
+ "expecting an acquire or volatile membar");
+ assert((trailing->Opcode() != Op_MemBarVolatile ||
+ !is_card_mark_membar(trailing)),
+ "not expecting a card mark membar");
+
+ MemBarNode *leading = normal_to_leading(trailing);
+
+ if (leading) {
return leading;
}
- return NULL;
+ // nothing more to do if this is an acquire
+ if (trailing->Opcode() == Op_MemBarAcquire) {
+ return NULL;
+ }
+
+ MemBarNode *card_mark_membar = trailing_to_card_mark(trailing);
+
+ if (!card_mark_membar) {
+ return NULL;
+ }
+
+ return normal_to_leading(card_mark_membar);
}
+ // predicates controlling emit of ldr/ldar and associated dmb
+
bool unnecessary_acquire(const Node *barrier)
{
assert(barrier->is_MemBar(), "expecting a membar");
@@ -2617,8 +2702,19 @@ bool unnecessary_release(const Node *n)
}
// must start with a normal feed
- MemBarNode *trailing = leading_to_trailing(barrier);
+ MemBarNode *child_barrier = leading_to_normal(barrier);
+ if (!child_barrier) {
+ return false;
+ }
+
+ if (!is_card_mark_membar(child_barrier)) {
+ // this is the trailing membar and we are done
+ return true;
+ }
+
+ // must be sure this card mark feeds a trailing membar
+ MemBarNode *trailing = card_mark_to_trailing(child_barrier);
return (trailing != NULL);
}
@@ -2640,7 +2736,7 @@ bool unnecessary_volatile(const Node *n)
}
// ok, if it's not a card mark then we still need to check if it is
- // a trailing membar of a volatile put graph.
+ // a trailing membar of a volatile put hgraph.
return (trailing_to_leading(mbvol) != NULL);
}
@@ -2690,9 +2786,20 @@ bool needs_releasing_store(const Node *n)
}
// does this lead a normal subgraph?
- MemBarNode *trailing = leading_to_trailing(barrier);
+ MemBarNode *mbvol = leading_to_normal(barrier);
- return (trailing != NULL);
+ if (!mbvol) {
+ return false;
+ }
+
+ // all done unless this is a card mark
+ if (!is_card_mark_membar(mbvol)) {
+ return true;
+ }
+
+ // we found a card mark -- just make sure we have a trailing barrier
+
+ return (card_mark_to_trailing(mbvol) != NULL);
}
// predicate controlling translation of CAS
@@ -2734,7 +2841,7 @@ bool needs_acquiring_load_exclusive(const Node *n)
"CAS not fed by cpuorder+release membar pair!");
// does this lead a normal subgraph?
- MemBarNode *mbar = leading_to_trailing(barrier);
+ MemBarNode *mbar = leading_to_normal(barrier);
assert(mbar != NULL, "CAS not embedded in normal graph!");
@@ -2755,27 +2862,48 @@ bool unnecessary_storestore(const Node *storecm)
// we only ever need to generate a dmb ishst between an object put
// and the associated card mark when we are using CMS without
- // conditional card marking. Any other occurence will happen when
- // performing a card mark using CMS with conditional card marking or
- // G1. In those cases the preceding MamBarVolatile will be
- // translated to a dmb ish which guarantes visibility of the
- // preceding StoreN/P before this StoreCM
+ // conditional card marking
if (!UseConcMarkSweepGC || UseCondCardMark) {
return true;
}
- // if we are implementing volatile puts using barriers then we must
- // insert the dmb ishst
+ // if we are implementing volatile puts using barriers then the
+ // object put as an str so we must insert the dmb ishst
if (UseBarriersForVolatile) {
return false;
}
- // we must be using CMS with conditional card marking so we ahve to
- // generate the StoreStore
+ // we can omit the dmb ishst if this StoreCM is part of a volatile
+ // put because in thta case the put will be implemented by stlr
+ //
+ // we need to check for a normal subgraph feeding this StoreCM.
+ // that means the StoreCM must be fed Memory from a leading membar,
+ // either a MemBarRelease or its dependent MemBarCPUOrder, and the
+ // leading membar must be part of a normal subgraph
- return false;
+ Node *x = storecm->in(StoreNode::Memory);
+
+ if (!x->is_Proj()) {
+ return false;
+ }
+
+ x = x->in(0);
+
+ if (!x->is_MemBar()) {
+ return false;
+ }
+
+ MemBarNode *leading = x->as_MemBar();
+
+ // reject invalid candidates
+ if (!leading_membar(leading)) {
+ return false;
+ }
+
+ // we can omit the StoreStore if it is the head of a normal subgraph
+ return (leading_to_normal(leading) != NULL);
}
@@ -3008,6 +3136,10 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
__ notify(Assembler::method_reentry);
}
+ if (StackReservedPages > 0 && C->has_reserved_stack_access()) {
+ __ reserved_stack_check();
+ }
+
if (do_polling() && C->is_method_compilation()) {
__ read_polling_page(rscratch1, os::get_polling_page(), relocInfo::poll_return_type);
}
@@ -9862,7 +9994,7 @@ instruct weakCompareAndSwapP(iRegINoSp res, indirect mem, iRegP oldval, iRegP ne
// END This section of the file is automatically generated. Do not edit --------------
// ---------------------------------------------------------------------
-instruct get_and_setI(indirect mem, iRegINoSp newv, iRegI prev) %{
+instruct get_and_setI(indirect mem, iRegI newv, iRegINoSp prev) %{
match(Set prev (GetAndSetI mem newv));
format %{ "atomic_xchgw $prev, $newv, [$mem]" %}
ins_encode %{
@@ -9871,7 +10003,7 @@ instruct get_and_setI(indirect mem, iRegINoSp newv, iRegI prev) %{
ins_pipe(pipe_serial);
%}
-instruct get_and_setL(indirect mem, iRegLNoSp newv, iRegL prev) %{
+instruct get_and_setL(indirect mem, iRegL newv, iRegLNoSp prev) %{
match(Set prev (GetAndSetL mem newv));
format %{ "atomic_xchg $prev, $newv, [$mem]" %}
ins_encode %{
@@ -9880,7 +10012,7 @@ instruct get_and_setL(indirect mem, iRegLNoSp newv, iRegL prev) %{
ins_pipe(pipe_serial);
%}
-instruct get_and_setN(indirect mem, iRegNNoSp newv, iRegI prev) %{
+instruct get_and_setN(indirect mem, iRegN newv, iRegINoSp prev) %{
match(Set prev (GetAndSetN mem newv));
format %{ "atomic_xchgw $prev, $newv, [$mem]" %}
ins_encode %{
@@ -9889,7 +10021,7 @@ instruct get_and_setN(indirect mem, iRegNNoSp newv, iRegI prev) %{
ins_pipe(pipe_serial);
%}
-instruct get_and_setP(indirect mem, iRegPNoSp newv, iRegP prev) %{
+instruct get_and_setP(indirect mem, iRegP newv, iRegPNoSp prev) %{
match(Set prev (GetAndSetP mem newv));
format %{ "atomic_xchg $prev, $newv, [$mem]" %}
ins_encode %{
diff --git a/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp
index 70c8f909337..b139a44f9a1 100644
--- a/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp
+++ b/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp
@@ -532,8 +532,14 @@ void LIR_Assembler::poll_for_safepoint(relocInfo::relocType rtype, CodeEmitInfo*
void LIR_Assembler::return_op(LIR_Opr result) {
assert(result->is_illegal() || !result->is_single_cpu() || result->as_register() == r0, "word returns are in r0,");
+
// Pop the stack before the safepoint code
__ remove_frame(initial_frame_size_in_bytes());
+
+ if (StackReservedPages > 0 && compilation()->has_reserved_stack_access()) {
+ __ reserved_stack_check();
+ }
+
address polling_page(os::get_polling_page());
__ read_polling_page(rscratch1, polling_page, relocInfo::poll_return_type);
__ ret(lr);
diff --git a/hotspot/src/cpu/aarch64/vm/c1_Runtime1_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/c1_Runtime1_aarch64.cpp
index 58ba9c0b613..8c83dc4125c 100644
--- a/hotspot/src/cpu/aarch64/vm/c1_Runtime1_aarch64.cpp
+++ b/hotspot/src/cpu/aarch64/vm/c1_Runtime1_aarch64.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -1179,6 +1179,15 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
Label done;
Label runtime;
+ // Is marking still active?
+ if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
+ __ ldrw(tmp, in_progress);
+ } else {
+ assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
+ __ ldrb(tmp, in_progress);
+ }
+ __ cbzw(tmp, done);
+
// Can we store original value in the thread's buffer?
__ ldr(tmp, queue_index);
__ cbz(tmp, runtime);
diff --git a/hotspot/src/cpu/aarch64/vm/frame_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/frame_aarch64.cpp
index b74bce2d415..fe48df281b1 100644
--- a/hotspot/src/cpu/aarch64/vm/frame_aarch64.cpp
+++ b/hotspot/src/cpu/aarch64/vm/frame_aarch64.cpp
@@ -375,7 +375,8 @@ void frame::verify_deopt_original_pc(CompiledMethod* nm, intptr_t* unextended_sp
fr._unextended_sp = unextended_sp;
address original_pc = nm->get_original_pc(&fr);
- assert(nm->insts_contains(original_pc), "original PC must be in nmethod");
+ assert(nm->insts_contains_inclusive(original_pc),
+ "original PC must be in the main code section of the the compiled method (or must be immediately following it)");
}
#endif
@@ -629,6 +630,7 @@ void frame::describe_pd(FrameValues& values, int frame_no) {
DESCRIBE_FP_OFFSET(interpreter_frame_last_sp);
DESCRIBE_FP_OFFSET(interpreter_frame_method);
DESCRIBE_FP_OFFSET(interpreter_frame_mdp);
+ DESCRIBE_FP_OFFSET(interpreter_frame_mirror);
DESCRIBE_FP_OFFSET(interpreter_frame_cache);
DESCRIBE_FP_OFFSET(interpreter_frame_locals);
DESCRIBE_FP_OFFSET(interpreter_frame_bcp);
diff --git a/hotspot/src/cpu/aarch64/vm/frame_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/frame_aarch64.hpp
index 5bcee325945..64a35bd3c30 100644
--- a/hotspot/src/cpu/aarch64/vm/frame_aarch64.hpp
+++ b/hotspot/src/cpu/aarch64/vm/frame_aarch64.hpp
@@ -46,6 +46,9 @@
// [pointer to locals ] = locals() locals_offset
// [constant pool cache ] = cache() cache_offset
+// [klass of method ] = mirror() mirror_offset
+// [padding ]
+
// [methodData ] = mdp() mdx_offset
// [methodOop ] = method() method_offset
diff --git a/hotspot/src/cpu/aarch64/vm/frame_aarch64.inline.hpp b/hotspot/src/cpu/aarch64/vm/frame_aarch64.inline.hpp
index 7c410aaa74b..4f6d2bef7f5 100644
--- a/hotspot/src/cpu/aarch64/vm/frame_aarch64.inline.hpp
+++ b/hotspot/src/cpu/aarch64/vm/frame_aarch64.inline.hpp
@@ -82,7 +82,8 @@ inline frame::frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address
address original_pc = CompiledMethod::get_deopt_original_pc(this);
if (original_pc != NULL) {
_pc = original_pc;
- assert(((CompiledMethod*)_cb)->insts_contains(_pc), "original PC must be in CompiledMethod");
+ assert(_cb->as_compiled_method()->insts_contains_inclusive(_pc),
+ "original PC must be in the main code section of the the compiled method (or must be immediately following it)");
_deopt_state = is_deoptimized;
} else {
_deopt_state = not_deoptimized;
diff --git a/hotspot/src/cpu/aarch64/vm/globalDefinitions_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/globalDefinitions_aarch64.hpp
index 4c9d377ff09..0d78e2da1fe 100644
--- a/hotspot/src/cpu/aarch64/vm/globalDefinitions_aarch64.hpp
+++ b/hotspot/src/cpu/aarch64/vm/globalDefinitions_aarch64.hpp
@@ -53,4 +53,6 @@ const bool CCallingConventionRequiresIntsAsLongs = false;
// evidence that it's worth doing.
#define DEOPTIMIZE_WHEN_PATCHING
+#define SUPPORT_RESERVED_STACK_AREA
+
#endif // CPU_AARCH64_VM_GLOBALDEFINITIONS_AARCH64_HPP
diff --git a/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp
index 926e06004dc..06ec817cd9b 100644
--- a/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp
+++ b/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp
@@ -50,7 +50,7 @@ define_pd_global(intx, InlineFrequencyCount, 100);
// stack if compiled for unix and LP64. To pass stack overflow tests we need
// 20 shadow pages.
#define DEFAULT_STACK_SHADOW_PAGES (20 DEBUG_ONLY(+5))
-#define DEFAULT_STACK_RESERVED_PAGES (0)
+#define DEFAULT_STACK_RESERVED_PAGES (1)
#define MIN_STACK_YELLOW_PAGES DEFAULT_STACK_YELLOW_PAGES
#define MIN_STACK_RED_PAGES DEFAULT_STACK_RED_PAGES
diff --git a/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.cpp
index ed95d410e36..81636fb8ea1 100644
--- a/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.cpp
+++ b/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.cpp
@@ -619,6 +619,22 @@ void InterpreterMacroAssembler::remove_activation(
// get sender esp
ldr(esp,
Address(rfp, frame::interpreter_frame_sender_sp_offset * wordSize));
+ if (StackReservedPages > 0) {
+ // testing if reserved zone needs to be re-enabled
+ Label no_reserved_zone_enabling;
+
+ ldr(rscratch1, Address(rthread, JavaThread::reserved_stack_activation_offset()));
+ cmp(esp, rscratch1);
+ br(Assembler::LS, no_reserved_zone_enabling);
+
+ call_VM_leaf(
+ CAST_FROM_FN_PTR(address, SharedRuntime::enable_stack_reserved_zone), rthread);
+ call_VM(noreg, CAST_FROM_FN_PTR(address,
+ InterpreterRuntime::throw_delayed_StackOverflowError));
+ should_not_reach_here();
+
+ bind(no_reserved_zone_enabling);
+ }
// remove frame anchor
leave();
// If we're returning to interpreted code we will shortly be
diff --git a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp
index dc90886ab68..1c955d5afe3 100644
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp
@@ -402,6 +402,30 @@ void MacroAssembler::far_jump(Address entry, CodeBuffer *cbuf, Register tmp) {
}
}
+void MacroAssembler::reserved_stack_check() {
+ // testing if reserved zone needs to be enabled
+ Label no_reserved_zone_enabling;
+
+ ldr(rscratch1, Address(rthread, JavaThread::reserved_stack_activation_offset()));
+ cmp(sp, rscratch1);
+ br(Assembler::LO, no_reserved_zone_enabling);
+
+ enter(); // LR and FP are live.
+ lea(rscratch1, CAST_FROM_FN_PTR(address, SharedRuntime::enable_stack_reserved_zone));
+ mov(c_rarg0, rthread);
+ blr(rscratch1);
+ leave();
+
+ // We have already removed our own frame.
+ // throw_delayed_StackOverflowError will think that it's been
+ // called by our caller.
+ lea(rscratch1, RuntimeAddress(StubRoutines::throw_delayed_StackOverflowError_entry()));
+ br(rscratch1);
+ should_not_reach_here();
+
+ bind(no_reserved_zone_enabling);
+}
+
int MacroAssembler::biased_locking_enter(Register lock_reg,
Register obj_reg,
Register swap_reg,
diff --git a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp
index 3418189f1b4..2f17699a262 100644
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp
@@ -957,6 +957,9 @@ public:
// stack overflow + shadow pages. Also, clobbers tmp
void bang_stack_size(Register size, Register tmp);
+ // Check for reserved stack access in method being exited (for JIT)
+ void reserved_stack_check();
+
virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr,
Register tmp,
int offset);
diff --git a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp
index 681ecf34277..3143fe97d88 100644
--- a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp
+++ b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp
@@ -4676,8 +4676,11 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_throw_StackOverflowError_entry =
generate_throw_exception("StackOverflowError throw_exception",
CAST_FROM_FN_PTR(address,
- SharedRuntime::
- throw_StackOverflowError));
+ SharedRuntime::throw_StackOverflowError));
+ StubRoutines::_throw_delayed_StackOverflowError_entry =
+ generate_throw_exception("delayed StackOverflowError throw_exception",
+ CAST_FROM_FN_PTR(address,
+ SharedRuntime::throw_delayed_StackOverflowError));
if (UseCRC32Intrinsics) {
// set table address before stub generation which use it
StubRoutines::_crc_table_adr = (address)StubRoutines::aarch64::_crc_table;
diff --git a/hotspot/src/cpu/arm/vm/c1_Runtime1_arm.cpp b/hotspot/src/cpu/arm/vm/c1_Runtime1_arm.cpp
index 937dfe91242..9f17c8fc810 100644
--- a/hotspot/src/cpu/arm/vm/c1_Runtime1_arm.cpp
+++ b/hotspot/src/cpu/arm/vm/c1_Runtime1_arm.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -551,6 +551,8 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
const Register r_index_1 = R1;
const Register r_buffer_2 = R2;
+ Address queue_active(Rthread, in_bytes(JavaThread::satb_mark_queue_offset() +
+ SATBMarkQueue::byte_offset_of_active()));
Address queue_index(Rthread, in_bytes(JavaThread::satb_mark_queue_offset() +
SATBMarkQueue::byte_offset_of_index()));
Address buffer(Rthread, in_bytes(JavaThread::satb_mark_queue_offset() +
@@ -559,6 +561,11 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
Label done;
Label runtime;
+ // Is marking still active?
+ assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
+ __ ldrb(R1, queue_active);
+ __ cbz(R1, done);
+
__ ldr(r_index_1, queue_index);
__ ldr(r_pre_val_0, Address(SP, nb_saved_regs*wordSize));
__ ldr(r_buffer_2, buffer);
diff --git a/hotspot/src/cpu/arm/vm/frame_arm.cpp b/hotspot/src/cpu/arm/vm/frame_arm.cpp
index 55f468fa74c..defe4a45a4a 100644
--- a/hotspot/src/cpu/arm/vm/frame_arm.cpp
+++ b/hotspot/src/cpu/arm/vm/frame_arm.cpp
@@ -364,7 +364,8 @@ void frame::verify_deopt_original_pc(CompiledMethod* nm, intptr_t* unextended_sp
fr._unextended_sp = unextended_sp;
address original_pc = nm->get_original_pc(&fr);
- assert(nm->insts_contains(original_pc), "original PC must be in nmethod");
+ assert(nm->insts_contains_inclusive(original_pc),
+ "original PC must be in the main code section of the the compiled method (or must be immediately following it)");
assert(nm->is_method_handle_return(original_pc) == is_method_handle_return, "must be");
}
#endif
diff --git a/hotspot/src/cpu/arm/vm/frame_arm.inline.hpp b/hotspot/src/cpu/arm/vm/frame_arm.inline.hpp
index 589d75be640..4bde8e7be08 100644
--- a/hotspot/src/cpu/arm/vm/frame_arm.inline.hpp
+++ b/hotspot/src/cpu/arm/vm/frame_arm.inline.hpp
@@ -75,7 +75,8 @@ inline frame::frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address
address original_pc = CompiledMethod::get_deopt_original_pc(this);
if (original_pc != NULL) {
_pc = original_pc;
- assert(_cb->as_compiled_method()->insts_contains(_pc), "original PC must be in CompiledMethod");
+ assert(_cb->as_compiled_method()->insts_contains_inclusive(_pc),
+ "original PC must be in the main code section of the the compiled method (or must be immediately following it)");
_deopt_state = is_deoptimized;
} else {
_deopt_state = not_deoptimized;
diff --git a/hotspot/src/cpu/ppc/vm/c1_Runtime1_ppc.cpp b/hotspot/src/cpu/ppc/vm/c1_Runtime1_ppc.cpp
index 1aa158b4a8f..3562a79825f 100644
--- a/hotspot/src/cpu/ppc/vm/c1_Runtime1_ppc.cpp
+++ b/hotspot/src/cpu/ppc/vm/c1_Runtime1_ppc.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2015 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -741,7 +741,10 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
Register tmp = R14;
Register tmp2 = R15;
- Label refill, restart;
+ Label refill, restart, marking_not_active;
+ int satb_q_active_byte_offset =
+ in_bytes(JavaThread::satb_mark_queue_offset() +
+ SATBMarkQueue::byte_offset_of_active());
int satb_q_index_byte_offset =
in_bytes(JavaThread::satb_mark_queue_offset() +
SATBMarkQueue::byte_offset_of_index());
@@ -753,6 +756,16 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
__ std(tmp, -16, R1_SP);
__ std(tmp2, -24, R1_SP);
+ // Is marking still active?
+ if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
+ __ lwz(tmp, satb_q_active_byte_offset, R16_thread);
+ } else {
+ assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
+ __ lbz(tmp, satb_q_active_byte_offset, R16_thread);
+ }
+ __ cmpdi(CCR0, tmp, 0);
+ __ beq(CCR0, marking_not_active);
+
__ bind(restart);
// Load the index into the SATB buffer. SATBMarkQueue::_index is a
// size_t so ld_ptr is appropriate.
@@ -769,6 +782,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
__ std(tmp, satb_q_index_byte_offset, R16_thread);
__ stdx(pre_val, tmp2, tmp); // [_buf + index] :=
+ __ bind(marking_not_active);
// Restore temp registers and return-from-leaf.
__ ld(tmp2, -24, R1_SP);
__ ld(tmp, -16, R1_SP);
diff --git a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp
index 2d1f0c7230b..a5d5613a414 100644
--- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp
+++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp
@@ -2569,7 +2569,7 @@ void MacroAssembler::rtm_retry_lock_on_abort(Register retry_count_Reg, Register
}
// Spin and retry if lock is busy.
-// inputs: box_Reg (monitor address)
+// inputs: owner_addr_Reg (monitor address)
// : retry_count_Reg
// output: retry_count_Reg decremented by 1
// CTR is killed
@@ -2577,15 +2577,22 @@ void MacroAssembler::rtm_retry_lock_on_busy(Register retry_count_Reg, Register o
Label SpinLoop, doneRetry;
addic_(retry_count_Reg, retry_count_Reg, -1);
blt(CCR0, doneRetry);
- li(R0, RTMSpinLoopCount);
- mtctr(R0);
+
+ if (RTMSpinLoopCount > 1) {
+ li(R0, RTMSpinLoopCount);
+ mtctr(R0);
+ }
bind(SpinLoop);
smt_yield(); // Can't use waitrsv(). No permission (SIGILL).
- bdz(retryLabel);
- ld(R0, 0, owner_addr_Reg);
- cmpdi(CCR0, R0, 0);
- bne(CCR0, SpinLoop);
+
+ if (RTMSpinLoopCount > 1) {
+ bdz(retryLabel);
+ ld(R0, 0, owner_addr_Reg);
+ cmpdi(CCR0, R0, 0);
+ bne(CCR0, SpinLoop);
+ }
+
b(retryLabel);
bind(doneRetry);
diff --git a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp
index 6c6b83d257f..5e8be1425fa 100644
--- a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp
+++ b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp
@@ -327,7 +327,10 @@ void VM_Version::initialize() {
warning("RTMAbortRatio must be in the range 0 to 100, resetting it to 50");
FLAG_SET_DEFAULT(RTMAbortRatio, 50);
}
- guarantee(RTMSpinLoopCount > 0, "unsupported");
+ if (RTMSpinLoopCount < 0) {
+ warning("RTMSpinLoopCount must not be a negative value, resetting it to 0");
+ FLAG_SET_DEFAULT(RTMSpinLoopCount, 0);
+ }
#else
// Only C2 does RTM locking optimization.
// Can't continue because UseRTMLocking affects UseBiasedLocking flag
diff --git a/hotspot/src/cpu/s390/vm/c1_LIRAssembler_s390.cpp b/hotspot/src/cpu/s390/vm/c1_LIRAssembler_s390.cpp
index 524a91fe07f..84fb4205099 100644
--- a/hotspot/src/cpu/s390/vm/c1_LIRAssembler_s390.cpp
+++ b/hotspot/src/cpu/s390/vm/c1_LIRAssembler_s390.cpp
@@ -1105,16 +1105,16 @@ void LIR_Assembler::reg2mem(LIR_Opr from, LIR_Opr dest_opr, BasicType type,
}
case T_FLOAT :
if (short_disp) {
- __ z_ste(from->as_float_reg(), disp_value, disp_reg, dest);
+ __ z_ste(from->as_float_reg(), disp_value, disp_reg, dest);
} else {
- __ z_stey(from->as_float_reg(), disp_value, disp_reg, dest);
+ __ z_stey(from->as_float_reg(), disp_value, disp_reg, dest);
}
break;
case T_DOUBLE:
if (short_disp) {
- __ z_std(from->as_double_reg(), disp_value, disp_reg, dest);
+ __ z_std(from->as_double_reg(), disp_value, disp_reg, dest);
} else {
- __ z_stdy(from->as_double_reg(), disp_value, disp_reg, dest);
+ __ z_stdy(from->as_double_reg(), disp_value, disp_reg, dest);
}
break;
default: ShouldNotReachHere();
@@ -1148,6 +1148,10 @@ void LIR_Assembler::return_op(LIR_Opr result) {
__ restore_return_pc();
}
+ if (StackReservedPages > 0 && compilation()->has_reserved_stack_access()) {
+ __ reserved_stack_check(Z_R14);
+ }
+
// We need to mark the code position where the load from the safepoint
// polling page was emitted as relocInfo::poll_return_type here.
__ relocate(relocInfo::poll_return_type);
diff --git a/hotspot/src/cpu/s390/vm/c1_Runtime1_s390.cpp b/hotspot/src/cpu/s390/vm/c1_Runtime1_s390.cpp
index c0fbee53da7..7b65476212f 100644
--- a/hotspot/src/cpu/s390/vm/c1_Runtime1_s390.cpp
+++ b/hotspot/src/cpu/s390/vm/c1_Runtime1_s390.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -784,7 +784,10 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
Register tmp = Z_R6; // Must be non-volatile because it is used to save pre_val.
Register tmp2 = Z_R7;
- Label refill, restart;
+ Label refill, restart, marking_not_active;
+ int satb_q_active_byte_offset =
+ in_bytes(JavaThread::satb_mark_queue_offset() +
+ SATBMarkQueue::byte_offset_of_active());
int satb_q_index_byte_offset =
in_bytes(JavaThread::satb_mark_queue_offset() +
SATBMarkQueue::byte_offset_of_index());
@@ -796,6 +799,15 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
__ z_stg(tmp, 0*BytesPerWord + FrameMap::first_available_sp_in_frame, Z_SP);
__ z_stg(tmp2, 1*BytesPerWord + FrameMap::first_available_sp_in_frame, Z_SP);
+ // Is marking still active?
+ if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
+ __ load_and_test_int(tmp, Address(Z_thread, satb_q_active_byte_offset));
+ } else {
+ assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
+ __ load_and_test_byte(tmp, Address(Z_thread, satb_q_active_byte_offset));
+ }
+ __ z_bre(marking_not_active); // Activity indicator is zero, so there is no marking going on currently.
+
__ bind(restart);
// Load the index into the SATB buffer. SATBMarkQueue::_index is a
// size_t so ld_ptr is appropriate.
@@ -810,6 +822,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
__ z_stg(pre_val, 0, tmp, tmp2); // [_buf + index] :=
__ z_stg(tmp, satb_q_index_byte_offset, Z_thread);
+ __ bind(marking_not_active);
// Restore tmp registers (see assertion in G1PreBarrierStub::emit_code()).
__ z_lg(tmp, 0*BytesPerWord + FrameMap::first_available_sp_in_frame, Z_SP);
__ z_lg(tmp2, 1*BytesPerWord + FrameMap::first_available_sp_in_frame, Z_SP);
diff --git a/hotspot/src/cpu/s390/vm/globalDefinitions_s390.hpp b/hotspot/src/cpu/s390/vm/globalDefinitions_s390.hpp
index 83261cfdf47..63a9cb5abef 100644
--- a/hotspot/src/cpu/s390/vm/globalDefinitions_s390.hpp
+++ b/hotspot/src/cpu/s390/vm/globalDefinitions_s390.hpp
@@ -52,4 +52,6 @@ const bool CCallingConventionRequiresIntsAsLongs = true;
// The expected size in bytes of a cache line, used to pad data structures.
#define DEFAULT_CACHE_LINE_SIZE 256
+#define SUPPORT_RESERVED_STACK_AREA
+
#endif // CPU_S390_VM_GLOBALDEFINITIONS_S390_HPP
diff --git a/hotspot/src/cpu/s390/vm/globals_s390.hpp b/hotspot/src/cpu/s390/vm/globals_s390.hpp
index fcd3ff45227..cb5adff3ef5 100644
--- a/hotspot/src/cpu/s390/vm/globals_s390.hpp
+++ b/hotspot/src/cpu/s390/vm/globals_s390.hpp
@@ -56,7 +56,7 @@ define_pd_global(intx, InlineSmallCode, 2000);
// Java_java_net_SocketOutputStream_socketWrite0() uses a 64k buffer on the
// stack. To pass stack overflow tests we need 20 shadow pages.
#define DEFAULT_STACK_SHADOW_PAGES (20 DEBUG_ONLY(+2))
-#define DEFAULT_STACK_RESERVED_PAGES (0)
+#define DEFAULT_STACK_RESERVED_PAGES (1)
#define MIN_STACK_YELLOW_PAGES DEFAULT_STACK_YELLOW_PAGES
#define MIN_STACK_RED_PAGES DEFAULT_STACK_RED_PAGES
diff --git a/hotspot/src/cpu/s390/vm/interp_masm_s390.cpp b/hotspot/src/cpu/s390/vm/interp_masm_s390.cpp
index c53fa419a27..8cec2da25ac 100644
--- a/hotspot/src/cpu/s390/vm/interp_masm_s390.cpp
+++ b/hotspot/src/cpu/s390/vm/interp_masm_s390.cpp
@@ -860,16 +860,39 @@ void InterpreterMacroAssembler::remove_activation(TosState state,
bool throw_monitor_exception,
bool install_monitor_exception,
bool notify_jvmti) {
-
+ BLOCK_COMMENT("remove_activation {");
unlock_if_synchronized_method(state, throw_monitor_exception, install_monitor_exception);
// Save result (push state before jvmti call and pop it afterwards) and notify jvmti.
notify_method_exit(false, state, notify_jvmti ? NotifyJVMTI : SkipNotifyJVMTI);
+ if (StackReservedPages > 0) {
+ BLOCK_COMMENT("reserved_stack_check:");
+ // Test if reserved zone needs to be enabled.
+ Label no_reserved_zone_enabling;
+
+ // Compare frame pointers. There is no good stack pointer, as with stack
+ // frame compression we can get different SPs when we do calls. A subsequent
+ // call could have a smaller SP, so that this compare succeeds for an
+ // inner call of the method annotated with ReservedStack.
+ z_lg(Z_R0, Address(Z_SP, (intptr_t)_z_abi(callers_sp)));
+ z_clg(Z_R0, Address(Z_thread, JavaThread::reserved_stack_activation_offset())); // Compare with frame pointer in memory.
+ z_brl(no_reserved_zone_enabling);
+
+ // Enable reserved zone again, throw stack overflow exception.
+ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::enable_stack_reserved_zone), Z_thread);
+ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_delayed_StackOverflowError));
+
+ should_not_reach_here();
+
+ bind(no_reserved_zone_enabling);
+ }
+
verify_oop(Z_tos, state);
verify_thread();
pop_interpreter_frame(return_pc, Z_ARG2, Z_ARG3);
+ BLOCK_COMMENT("} remove_activation");
}
// lock object
diff --git a/hotspot/src/cpu/s390/vm/macroAssembler_s390.cpp b/hotspot/src/cpu/s390/vm/macroAssembler_s390.cpp
index a7cbd706255..0f78e5a6250 100644
--- a/hotspot/src/cpu/s390/vm/macroAssembler_s390.cpp
+++ b/hotspot/src/cpu/s390/vm/macroAssembler_s390.cpp
@@ -2666,6 +2666,32 @@ void MacroAssembler::bang_stack_with_offset(int offset) {
}
}
+void MacroAssembler::reserved_stack_check(Register return_pc) {
+ // Test if reserved zone needs to be enabled.
+ Label no_reserved_zone_enabling;
+ assert(return_pc == Z_R14, "Return pc must be in R14 before z_br() to StackOverflow stub.");
+ BLOCK_COMMENT("reserved_stack_check {");
+
+ z_clg(Z_SP, Address(Z_thread, JavaThread::reserved_stack_activation_offset()));
+ z_brl(no_reserved_zone_enabling);
+
+ // Enable reserved zone again, throw stack overflow exception.
+ save_return_pc();
+ push_frame_abi160(0);
+ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::enable_stack_reserved_zone), Z_thread);
+ pop_frame();
+ restore_return_pc();
+
+ load_const_optimized(Z_R1, StubRoutines::throw_delayed_StackOverflowError_entry());
+ // Don't use call() or z_basr(), they will invalidate Z_R14 which contains the return pc.
+ z_br(Z_R1);
+
+ should_not_reach_here();
+
+ bind(no_reserved_zone_enabling);
+ BLOCK_COMMENT("} reserved_stack_check");
+}
+
// Defines obj, preserves var_size_in_bytes, okay for t2 == var_size_in_bytes.
void MacroAssembler::tlab_allocate(Register obj,
Register var_size_in_bytes,
diff --git a/hotspot/src/cpu/s390/vm/macroAssembler_s390.hpp b/hotspot/src/cpu/s390/vm/macroAssembler_s390.hpp
index c9540860958..588bde6207e 100644
--- a/hotspot/src/cpu/s390/vm/macroAssembler_s390.hpp
+++ b/hotspot/src/cpu/s390/vm/macroAssembler_s390.hpp
@@ -627,6 +627,11 @@ class MacroAssembler: public Assembler {
// Stack overflow checking
void bang_stack_with_offset(int offset);
+ // Check for reserved stack access in method being exited. If the reserved
+ // stack area was accessed, protect it again and throw StackOverflowError.
+ // Uses Z_R1.
+ void reserved_stack_check(Register return_pc);
+
// Atomics
// -- none?
diff --git a/hotspot/src/cpu/s390/vm/s390.ad b/hotspot/src/cpu/s390/vm/s390.ad
index 8ab6a5026d3..fd188525c46 100644
--- a/hotspot/src/cpu/s390/vm/s390.ad
+++ b/hotspot/src/cpu/s390/vm/s390.ad
@@ -909,15 +909,8 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
// If this does safepoint polling, then do it here.
bool need_polling = do_polling() && C->is_method_compilation();
- // Touch the polling page.
- // Part 1: get the page's address.
- if (need_polling) {
- AddressLiteral pp(os::get_polling_page());
- __ load_const_optimized(Z_R1_scratch, pp);
- }
-
// Pop frame, restore return_pc, and all stuff needed by interpreter.
- // Pop frame by add insted of load (a penny saved is a penny got :-).
+ // Pop frame by add instead of load (a penny saved is a penny got :-).
int frame_size_in_bytes = Assembler::align((C->frame_slots() << LogBytesPerInt), frame::alignment_in_bytes);
int retPC_offset = frame_size_in_bytes + _z_abi16(return_pc);
if (Displacement::is_validDisp(retPC_offset)) {
@@ -928,9 +921,14 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
__ restore_return_pc();
}
- // Touch the polling page,
- // part 2: touch the page now.
+ if (StackReservedPages > 0 && C->has_reserved_stack_access()) {
+ __ reserved_stack_check(Z_R14);
+ }
+
+ // Touch the polling page.
if (need_polling) {
+ AddressLiteral pp(os::get_polling_page());
+ __ load_const_optimized(Z_R1_scratch, pp);
// We need to mark the code position where the load from the safepoint
// polling page was emitted as relocInfo::poll_return_type here.
__ relocate(relocInfo::poll_return_type);
@@ -939,7 +937,7 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
}
uint MachEpilogNode::size(PhaseRegAlloc *ra_) const {
- // variable size. determine dynamically.
+ // Variable size. determine dynamically.
return MachNode::size(ra_);
}
diff --git a/hotspot/src/cpu/s390/vm/stubGenerator_s390.cpp b/hotspot/src/cpu/s390/vm/stubGenerator_s390.cpp
index 8b872c5c922..be107222636 100644
--- a/hotspot/src/cpu/s390/vm/stubGenerator_s390.cpp
+++ b/hotspot/src/cpu/s390/vm/stubGenerator_s390.cpp
@@ -2433,13 +2433,12 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_throw_StackOverflowError_entry =
generate_throw_exception("StackOverflowError throw_exception",
CAST_FROM_FN_PTR(address, SharedRuntime::throw_StackOverflowError), false);
+ StubRoutines::_throw_delayed_StackOverflowError_entry =
+ generate_throw_exception("delayed StackOverflowError throw_exception",
+ CAST_FROM_FN_PTR(address, SharedRuntime::throw_delayed_StackOverflowError), false);
//----------------------------------------------------------------------
// Entry points that are platform specific.
- // Build this early so it's available for the interpreter.
- StubRoutines::_throw_StackOverflowError_entry =
- generate_throw_exception("StackOverflowError throw_exception",
- CAST_FROM_FN_PTR(address, SharedRuntime::throw_StackOverflowError), false);
if (UseCRC32Intrinsics) {
// We have no CRC32 table on z/Architecture.
diff --git a/hotspot/src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp b/hotspot/src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp
index de266db04fc..2084f36006f 100644
--- a/hotspot/src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp
+++ b/hotspot/src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp
@@ -1112,16 +1112,21 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
// top_frame_size = TOP_IJAVA_FRAME_ABI + max_stack + size of interpreter state
__ add2reg(top_frame_size,
frame::z_top_ijava_frame_abi_size +
- frame::z_ijava_state_size +
- frame::interpreter_frame_monitor_size() * wordSize,
+ frame::z_ijava_state_size +
+ frame::interpreter_frame_monitor_size() * wordSize,
max_stack);
- // Check if there's room for the new frame...
- Register frame_size = max_stack; // Reuse the regiser for max_stack.
- __ z_lgr(frame_size, Z_SP);
- __ z_sgr(frame_size, sp_after_resize);
- __ z_agr(frame_size, top_frame_size);
- generate_stack_overflow_check(frame_size, fp/*tmp1*/);
+ if (!native_call) {
+ // Stack overflow check.
+ // Native calls don't need the stack size check since they have no
+ // expression stack and the arguments are already on the stack and
+ // we only add a handful of words to the stack.
+ Register frame_size = max_stack; // Reuse the regiser for max_stack.
+ __ z_lgr(frame_size, Z_SP);
+ __ z_sgr(frame_size, sp_after_resize);
+ __ z_agr(frame_size, top_frame_size);
+ generate_stack_overflow_check(frame_size, fp/*tmp1*/);
+ }
DEBUG_ONLY(__ z_cg(Z_R14, _z_abi16(return_pc), Z_SP));
__ asm_assert_eq("killed Z_R14", 0);
diff --git a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp
index 97fb2745a26..ae2942f19b5 100644
--- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp
+++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp
@@ -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
@@ -694,6 +694,7 @@ void LIR_Assembler::vtable_call(LIR_OpJavaCall* op) {
int LIR_Assembler::store(LIR_Opr from_reg, Register base, int offset, BasicType type, bool wide, bool unaligned) {
int store_offset;
if (!Assembler::is_simm13(offset + (type == T_LONG) ? wordSize : 0)) {
+ assert(base != O7, "destroying register");
assert(!unaligned, "can't handle this");
// for offsets larger than a simm13 we setup the offset in O7
__ set(offset, O7);
@@ -712,9 +713,12 @@ int LIR_Assembler::store(LIR_Opr from_reg, Register base, int offset, BasicType
case T_LONG :
#ifdef _LP64
if (unaligned || PatchALot) {
- __ srax(from_reg->as_register_lo(), 32, O7);
+ // Don't use O7 here because it may be equal to 'base' (see LIR_Assembler::reg2mem)
+ assert(G3_scratch != base, "can't handle this");
+ assert(G3_scratch != from_reg->as_register_lo(), "can't handle this");
+ __ srax(from_reg->as_register_lo(), 32, G3_scratch);
__ stw(from_reg->as_register_lo(), base, offset + lo_word_offset_in_bytes);
- __ stw(O7, base, offset + hi_word_offset_in_bytes);
+ __ stw(G3_scratch, base, offset + hi_word_offset_in_bytes);
} else {
__ stx(from_reg->as_register_lo(), base, offset);
}
@@ -821,7 +825,7 @@ int LIR_Assembler::load(Register base, int offset, LIR_Opr to_reg, BasicType typ
case T_SHORT : __ ldsh(base, offset, to_reg->as_register()); break;
case T_INT : __ ld(base, offset, to_reg->as_register()); break;
case T_LONG :
- if (!unaligned) {
+ if (!unaligned && !PatchALot) {
#ifdef _LP64
__ ldx(base, offset, to_reg->as_register_lo());
#else
@@ -1297,7 +1301,7 @@ void LIR_Assembler::mem2reg(LIR_Opr src_opr, LIR_Opr dest, BasicType type,
disp_reg = O7;
}
} else if (unaligned || PatchALot) {
- __ add(src, addr->index()->as_register(), O7);
+ __ add(src, addr->index()->as_pointer_register(), O7);
src = O7;
} else {
disp_reg = addr->index()->as_pointer_register();
@@ -1424,7 +1428,7 @@ void LIR_Assembler::reg2mem(LIR_Opr from_reg, LIR_Opr dest, BasicType type,
disp_reg = O7;
}
} else if (unaligned || PatchALot) {
- __ add(src, addr->index()->as_register(), O7);
+ __ add(src, addr->index()->as_pointer_register(), O7);
src = O7;
} else {
disp_reg = addr->index()->as_pointer_register();
diff --git a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp
index 5530a85cb4c..40e30551967 100644
--- a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp
+++ b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, 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
@@ -856,7 +856,9 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
Register tmp2 = G3_scratch;
Label refill, restart;
- bool with_frame = false; // I don't know if we can do with-frame.
+ int satb_q_active_byte_offset =
+ in_bytes(JavaThread::satb_mark_queue_offset() +
+ SATBMarkQueue::byte_offset_of_active());
int satb_q_index_byte_offset =
in_bytes(JavaThread::satb_mark_queue_offset() +
SATBMarkQueue::byte_offset_of_index());
@@ -864,6 +866,17 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
in_bytes(JavaThread::satb_mark_queue_offset() +
SATBMarkQueue::byte_offset_of_buf());
+ // Is marking still active?
+ if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
+ __ ld(G2_thread, satb_q_active_byte_offset, tmp);
+ } else {
+ assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
+ __ ldsb(G2_thread, satb_q_active_byte_offset, tmp);
+ }
+ __ cmp_and_br_short(tmp, G0, Assembler::notEqual, Assembler::pt, restart);
+ __ retl();
+ __ delayed()->nop();
+
__ bind(restart);
// Load the index into the SATB buffer. SATBMarkQueue::_index is a
// size_t so ld_ptr is appropriate
diff --git a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp
index 5fe455600d1..58db92dcd32 100644
--- a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, 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
@@ -1623,6 +1623,8 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
NOT_LP64(__ get_thread(thread);)
+ Address queue_active(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
+ SATBMarkQueue::byte_offset_of_active()));
Address queue_index(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
SATBMarkQueue::byte_offset_of_index()));
Address buffer(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
@@ -1631,6 +1633,15 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
Label done;
Label runtime;
+ // Is marking still active?
+ if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
+ __ cmpl(queue_active, 0);
+ } else {
+ assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
+ __ cmpb(queue_active, 0);
+ }
+ __ jcc(Assembler::equal, done);
+
// Can we store original value in the thread's buffer?
__ movptr(tmp, queue_index);
diff --git a/hotspot/src/cpu/x86/vm/frame_x86.cpp b/hotspot/src/cpu/x86/vm/frame_x86.cpp
index 9cbc29af4c9..11f28bdb6ca 100644
--- a/hotspot/src/cpu/x86/vm/frame_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/frame_x86.cpp
@@ -376,7 +376,8 @@ void frame::verify_deopt_original_pc(CompiledMethod* nm, intptr_t* unextended_sp
fr._unextended_sp = unextended_sp;
address original_pc = nm->get_original_pc(&fr);
- assert(nm->insts_contains(original_pc), "original PC must be in CompiledMethod");
+ assert(nm->insts_contains_inclusive(original_pc),
+ "original PC must be in the main code section of the the compiled method (or must be immediately following it)");
}
#endif
diff --git a/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp b/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp
index d7d8e47ea89..d0c72947e0f 100644
--- a/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp
+++ b/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp
@@ -75,7 +75,8 @@ inline frame::frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address
address original_pc = CompiledMethod::get_deopt_original_pc(this);
if (original_pc != NULL) {
_pc = original_pc;
- assert(((CompiledMethod*)_cb)->insts_contains(_pc), "original PC must be in CompiledMethod");
+ assert(_cb->as_compiled_method()->insts_contains_inclusive(_pc),
+ "original PC must be in the main code section of the the compiled method (or must be immediately following it)");
_deopt_state = is_deoptimized;
} else {
if (_cb->is_deoptimization_stub()) {
diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp
index 3d4dee751a5..b6d32631582 100644
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp
@@ -3499,12 +3499,12 @@ void MacroAssembler::movdqu(XMMRegister dst, XMMRegister src) {
}
}
-void MacroAssembler::movdqu(XMMRegister dst, AddressLiteral src) {
+void MacroAssembler::movdqu(XMMRegister dst, AddressLiteral src, Register scratchReg) {
if (reachable(src)) {
movdqu(dst, as_Address(src));
} else {
- lea(rscratch1, src);
- movdqu(dst, Address(rscratch1, 0));
+ lea(scratchReg, src);
+ movdqu(dst, Address(scratchReg, 0));
}
}
diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp
index 02fb401511e..a3e81e58dc5 100644
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp
@@ -1085,7 +1085,7 @@ public:
void movdqu(Address dst, XMMRegister src);
void movdqu(XMMRegister dst, Address src);
void movdqu(XMMRegister dst, XMMRegister src);
- void movdqu(XMMRegister dst, AddressLiteral src);
+ void movdqu(XMMRegister dst, AddressLiteral src, Register scratchReg = rscratch1);
// AVX Unaligned forms
void vmovdqu(Address dst, XMMRegister src);
void vmovdqu(XMMRegister dst, Address src);
diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86_sha.cpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86_sha.cpp
index 37d93a48f21..10935345f70 100644
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86_sha.cpp
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86_sha.cpp
@@ -817,7 +817,7 @@ enum {
movl(d, Address(CTX, 4*3));
movl(e, Address(CTX, 4*4));
movl(f, Address(CTX, 4*5));
- movl(g, Address(CTX, 4*6));
+ // load g - r10 after it is used as scratch
movl(h, Address(CTX, 4*7));
pshuffle_byte_flip_mask_addr = pshuffle_byte_flip_mask;
@@ -825,6 +825,8 @@ enum {
vmovdqu(SHUF_00BA, ExternalAddress(pshuffle_byte_flip_mask_addr + 32)); //[_SHUF_00BA wrt rip]
vmovdqu(SHUF_DC00, ExternalAddress(pshuffle_byte_flip_mask_addr + 64)); //[_SHUF_DC00 wrt rip]
+ movl(g, Address(CTX, 4*6));
+
movq(Address(rsp, _CTX), CTX); // store
bind(loop0);
@@ -977,7 +979,7 @@ bind(only_one_block);
movl(d, Address(CTX, 4*3)); // 0xa54ff53a
movl(e, Address(CTX, 4*4)); // 0x510e527f
movl(f, Address(CTX, 4*5)); // 0x9b05688c
- movl(g, Address(CTX, 4*6)); // 0x1f83d9ab
+ // load g - r10 after use as scratch
movl(h, Address(CTX, 4*7)); // 0x5be0cd19
@@ -986,6 +988,8 @@ bind(only_one_block);
vmovdqu(SHUF_00BA, ExternalAddress(pshuffle_byte_flip_mask_addr + 32)); //[_SHUF_00BA wrt rip]
vmovdqu(SHUF_DC00, ExternalAddress(pshuffle_byte_flip_mask_addr + 64)); //[_SHUF_DC00 wrt rip]
+ movl(g, Address(CTX, 4*6)); // 0x1f83d9ab
+
movq(Address(rsp, _CTX), CTX);
jmpb(do_last_block);
@@ -1154,9 +1158,8 @@ void MacroAssembler::sha512_AVX2_one_round_and_schedule(
// Move to appropriate lanes for calculating w[16] and w[17]
vperm2f128(xmm4, xmm0, xmm0, 0); //xmm4 = W[-16] + W[-7] + s0{ BABA }
- address MASK_YMM_LO = StubRoutines::x86::pshuffle_byte_flip_mask_addr_sha512();
//Move to appropriate lanes for calculating w[18] and w[19]
- vpand(xmm0, xmm0, ExternalAddress(MASK_YMM_LO + 32), AVX_256bit); //xmm0 = W[-16] + W[-7] + s0{ DC00 }
+ vpand(xmm0, xmm0, xmm10, AVX_256bit); //xmm0 = W[-16] + W[-7] + s0{ DC00 }
//Calculate w[16] and w[17] in both 128 bit lanes
//Calculate sigma1 for w[16] and w[17] on both 128 bit lanes
vperm2f128(xmm2, xmm7, xmm7, 17); //xmm2 = W[-2] {BABA}
@@ -1250,6 +1253,7 @@ void MacroAssembler::sha512_AVX2(XMMRegister msg, XMMRegister state0, XMMRegiste
const XMMRegister& XFER = xmm0; // YTMP0
const XMMRegister& BYTE_FLIP_MASK = xmm9; // ymm9
+ const XMMRegister& YMM_MASK_LO = xmm10; // ymm10
#ifdef _WIN64
const Register& INP = rcx; //1st arg
const Register& CTX = rdx; //2nd arg
@@ -1368,11 +1372,14 @@ void MacroAssembler::sha512_AVX2(XMMRegister msg, XMMRegister state0, XMMRegiste
movq(d, Address(CTX, 8 * 3));
movq(e, Address(CTX, 8 * 4));
movq(f, Address(CTX, 8 * 5));
- movq(g, Address(CTX, 8 * 6));
+ // load g - r10 after it is used as scratch
movq(h, Address(CTX, 8 * 7));
pshuffle_byte_flip_mask_addr = pshuffle_byte_flip_mask_sha512;
vmovdqu(BYTE_FLIP_MASK, ExternalAddress(pshuffle_byte_flip_mask_addr + 0)); //PSHUFFLE_BYTE_FLIP_MASK wrt rip
+ vmovdqu(YMM_MASK_LO, ExternalAddress(pshuffle_byte_flip_mask_addr + 32));
+
+ movq(g, Address(CTX, 8 * 6));
bind(loop0);
lea(TBL, ExternalAddress(K512_W));
diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp
index 1853cf9a42a..48be33ae526 100644
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp
@@ -3207,7 +3207,7 @@ class StubGenerator: public StubCodeGenerator {
const Register len_reg = c_rarg4; // src len (must be multiple of blocksize 16)
#else
const Address len_mem(rbp, 6 * wordSize); // length is on stack on Win64
- const Register len_reg = r10; // pick the first volatile windows register
+ const Register len_reg = r11; // pick the volatile windows register
#endif
const Register pos = rax;
@@ -3404,7 +3404,7 @@ class StubGenerator: public StubCodeGenerator {
const Register len_reg = c_rarg4; // src len (must be multiple of blocksize 16)
#else
const Address len_mem(rbp, 6 * wordSize); // length is on stack on Win64
- const Register len_reg = r10; // pick the first volatile windows register
+ const Register len_reg = r11; // pick the volatile windows register
#endif
const Register pos = rax;
@@ -3930,7 +3930,7 @@ class StubGenerator: public StubCodeGenerator {
__ push(rbx); // Save RBX
__ movdqu(xmm_curr_counter, Address(counter, 0x00)); // initialize counter with initial counter
- __ movdqu(xmm_counter_shuf_mask, ExternalAddress(StubRoutines::x86::counter_shuffle_mask_addr()));
+ __ movdqu(xmm_counter_shuf_mask, ExternalAddress(StubRoutines::x86::counter_shuffle_mask_addr()), pos); // pos as scratch
__ pshufb(xmm_curr_counter, xmm_counter_shuf_mask); //counter is shuffled
__ movptr(pos, 0);
@@ -3953,7 +3953,7 @@ class StubGenerator: public StubCodeGenerator {
__ movl(Address(used_addr, 0), used);
// key length could be only {11, 13, 15} * 4 = {44, 52, 60}
- __ movdqu(xmm_key_shuf_mask, ExternalAddress(StubRoutines::x86::key_shuffle_mask_addr()));
+ __ movdqu(xmm_key_shuf_mask, ExternalAddress(StubRoutines::x86::key_shuffle_mask_addr()), rbx); // rbx as scratch
__ movl(rbx, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT)));
__ cmpl(rbx, 52);
__ jcc(Assembler::equal, L_multiBlock_loopTop[1]);
diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java
index 7be7a80192e..6cd7a4ad8b0 100644
--- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java
@@ -37,6 +37,7 @@ import jdk.tools.jaotc.binformat.Symbol.Binding;
import jdk.tools.jaotc.binformat.Symbol.Kind;
import jdk.tools.jaotc.binformat.elf.JELFRelocObject;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
/**
* A format-agnostic container class that holds various components of a binary.
@@ -257,9 +258,9 @@ public class BinaryContainer implements SymbolTable {
* prefix {@code prefix}. It also initializes internal code container, symbol table and
* relocation tables.
*/
- public BinaryContainer(GraalHotSpotVMConfig config, String jvmVersion) {
- this.codeSegmentSize = config.codeSegmentSize;
- this.codeEntryAlignment = config.codeEntryAlignment;
+ public BinaryContainer(GraalHotSpotVMConfig graalHotSpotVMConfig, GraphBuilderConfiguration graphBuilderConfig, String jvmVersion) {
+ this.codeSegmentSize = graalHotSpotVMConfig.codeSegmentSize;
+ this.codeEntryAlignment = graalHotSpotVMConfig.codeEntryAlignment;
// read only, code
codeContainer = new CodeContainer(".text", this);
@@ -289,30 +290,31 @@ public class BinaryContainer implements SymbolTable {
addGlobalSymbols();
- recordConfiguration(config);
+ recordConfiguration(graalHotSpotVMConfig, graphBuilderConfig);
}
- private void recordConfiguration(GraalHotSpotVMConfig config) {
+ private void recordConfiguration(GraalHotSpotVMConfig graalHotSpotVMConfig, GraphBuilderConfiguration graphBuilderConfig) {
// @formatter:off
- boolean[] booleanFlags = { config.cAssertions, // Debug VM
- config.useCompressedOops,
- config.useCompressedClassPointers,
- config.compactFields,
- config.useG1GC,
- config.useCMSGC,
- config.useTLAB,
- config.useBiasedLocking,
+ boolean[] booleanFlags = { graalHotSpotVMConfig.cAssertions, // Debug VM
+ graalHotSpotVMConfig.useCompressedOops,
+ graalHotSpotVMConfig.useCompressedClassPointers,
+ graalHotSpotVMConfig.compactFields,
+ graalHotSpotVMConfig.useG1GC,
+ graalHotSpotVMConfig.useCMSGC,
+ graalHotSpotVMConfig.useTLAB,
+ graalHotSpotVMConfig.useBiasedLocking,
TieredAOT.getValue(),
- config.enableContended,
- config.restrictContended,
+ graalHotSpotVMConfig.enableContended,
+ graalHotSpotVMConfig.restrictContended,
+ graphBuilderConfig.omitAssertions()
};
- int[] intFlags = { config.narrowOopShift,
- config.narrowKlassShift,
- config.contendedPaddingWidth,
- config.fieldsAllocationStyle,
- config.objectAlignment,
- config.codeSegmentSize,
+ int[] intFlags = { graalHotSpotVMConfig.getOopEncoding().shift,
+ graalHotSpotVMConfig.getKlassEncoding().shift,
+ graalHotSpotVMConfig.contendedPaddingWidth,
+ graalHotSpotVMConfig.fieldsAllocationStyle,
+ 1 << graalHotSpotVMConfig.getOopEncoding().alignment,
+ graalHotSpotVMConfig.codeSegmentSize,
};
// @formatter:on
@@ -395,6 +397,10 @@ public class BinaryContainer implements SymbolTable {
return "_aot_narrow_klass_base_address";
}
+ public String getNarrowOopBaseAddressSymbolName() {
+ return "_aot_narrow_oop_base_address";
+ }
+
public String getLogOfHeapRegionGrainBytesSymbolName() {
return "_aot_log_of_heap_region_grain_bytes";
}
@@ -445,6 +451,7 @@ public class BinaryContainer implements SymbolTable {
createGotSymbol(getHeapTopAddressSymbolName());
createGotSymbol(getHeapEndAddressSymbolName());
createGotSymbol(getNarrowKlassBaseAddressSymbolName());
+ createGotSymbol(getNarrowOopBaseAddressSymbolName());
createGotSymbol(getPollingPageSymbolName());
createGotSymbol(getLogOfHeapRegionGrainBytesSymbolName());
createGotSymbol(getInlineContiguousAllocationSupportedSymbolName());
diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java
index b5d081a51ca..3ba1067b959 100644
--- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java
@@ -77,10 +77,14 @@ public class AOTBackend {
this.filters = filters;
providers = backend.getProviders();
codeCache = providers.getCodeCache();
- graphBuilderSuite = initGraphBuilderSuite(backend);
+ graphBuilderSuite = initGraphBuilderSuite(backend, main.options.compileWithAssertions);
highTierContext = new HighTierContext(providers, graphBuilderSuite, OptimisticOptimizations.ALL);
}
+ public PhaseSuite getGraphBuilderSuite() {
+ return graphBuilderSuite;
+ }
+
private Suites getSuites() {
// create suites every time, as we modify options for the compiler
return backend.getSuites().getDefaultSuites();
@@ -146,14 +150,14 @@ public class AOTBackend {
return backend.getRuntime().getVMConfig().cAssertions;
}
- private static PhaseSuite initGraphBuilderSuite(HotSpotBackend backend) {
+ private static PhaseSuite initGraphBuilderSuite(HotSpotBackend backend, boolean compileWithAssertions) {
PhaseSuite graphBuilderSuite = backend.getSuites().getDefaultGraphBuilderSuite().copy();
ListIterator> iterator = graphBuilderSuite.findPhase(GraphBuilderPhase.class);
GraphBuilderConfiguration baseConfig = ((GraphBuilderPhase) iterator.previous()).getGraphBuilderConfig();
// Use all default plugins.
Plugins plugins = baseConfig.getPlugins();
- GraphBuilderConfiguration aotConfig = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true);
+ GraphBuilderConfiguration aotConfig = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true).withOmitAssertions(!compileWithAssertions);
iterator.next();
iterator.remove();
diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiledClass.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiledClass.java
index cbf26294b0d..68fb146b8ce 100644
--- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiledClass.java
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiledClass.java
@@ -293,12 +293,18 @@ public class AOTCompiledClass {
// Record methods holder
methodInfo.addDependentKlassData(binaryContainer, resolvedJavaType);
// Record inlinee classes
- for (ResolvedJavaMethod m : methodInfo.getCompilationResult().getMethods()) {
- methodInfo.addDependentKlassData(binaryContainer, (HotSpotResolvedObjectType) m.getDeclaringClass());
+ ResolvedJavaMethod[] inlinees = methodInfo.getCompilationResult().getMethods();
+ if (inlinees != null) {
+ for (ResolvedJavaMethod m : inlinees) {
+ methodInfo.addDependentKlassData(binaryContainer, (HotSpotResolvedObjectType) m.getDeclaringClass());
+ }
}
// Record classes of fields that were accessed
- for (ResolvedJavaField f : methodInfo.getCompilationResult().getFields()) {
- methodInfo.addDependentKlassData(binaryContainer, (HotSpotResolvedObjectType) f.getDeclaringClass());
+ ResolvedJavaField[] fields = methodInfo.getCompilationResult().getFields();
+ if (fields != null) {
+ for (ResolvedJavaField f : fields) {
+ methodInfo.addDependentKlassData(binaryContainer, (HotSpotResolvedObjectType) f.getDeclaringClass());
+ }
}
}
}
diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/LoadedClass.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/LoadedClass.java
new file mode 100644
index 00000000000..a0a01f7c1c9
--- /dev/null
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/LoadedClass.java
@@ -0,0 +1,64 @@
+package jdk.tools.jaotc;/*
+ * Copyright (c) 2015, 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+public class LoadedClass {
+ private final String name;
+ private final Class> clz;
+
+ public LoadedClass(String name, Class> clz) {
+ this.name = name;
+ this.clz = clz;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Class> getLoadedClass() {
+ return clz;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof LoadedClass)) return false;
+
+ LoadedClass that = (LoadedClass) o;
+
+ if (name != null ? !name.equals(that.name) : that.name != null) return false;
+ return clz != null ? clz.equals(that.clz) : that.clz == null;
+
+ }
+
+ @Override
+ public int hashCode() {
+ int result = name != null ? name.hashCode() : 0;
+ result = 31 * result + (clz != null ? clz.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java
index a1257b7a013..a98dc8d2d81 100644
--- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -43,19 +43,31 @@ import java.nio.file.Paths;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
+import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
+import java.util.ListIterator;
import java.util.Set;
import java.util.stream.Stream;
import jdk.tools.jaotc.binformat.BinaryContainer;
import jdk.tools.jaotc.binformat.ByteContainer;
-import jdk.tools.jaotc.collect.ClassCollector;
+import jdk.tools.jaotc.collect.*;
+import jdk.tools.jaotc.collect.classname.ClassNameSourceProvider;
+import jdk.tools.jaotc.collect.directory.DirectorySourceProvider;
+import jdk.tools.jaotc.collect.jar.JarSourceProvider;
+import jdk.tools.jaotc.collect.module.ModuleSourceProvider;
import jdk.tools.jaotc.utils.Timer;
import org.graalvm.compiler.api.runtime.GraalJVMCICompiler;
+import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
import org.graalvm.compiler.hotspot.HotSpotHostBackend;
+import org.graalvm.compiler.java.GraphBuilderPhase;
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
+import org.graalvm.compiler.phases.BasePhase;
+import org.graalvm.compiler.phases.PhaseSuite;
+import org.graalvm.compiler.phases.tiers.HighTierContext;
import org.graalvm.compiler.runtime.RuntimeProvider;
import jdk.vm.ci.meta.MetaAccessProvider;
@@ -120,17 +132,7 @@ public class Main implements LogPrinter {
abstract void process(Main task, String opt, String arg) throws BadArgs;
}
- static Option[] recognizedOptions = {new Option(" --module Module to compile", true, "--module") {
- @Override
- void process(Main task, String opt, String arg) {
- task.options.module = arg;
- }
- }, new Option(" --module-path Specify where to find module to compile", true, "--module-path") {
- @Override
- void process(Main task, String opt, String arg) {
- task.options.modulepath = arg;
- }
- }, new Option(" --output Output file name", true, "--output") {
+ static Option[] recognizedOptions = { new Option(" --output Output file name", true, "--output") {
@Override
void process(Main task, String opt, String arg) {
String name = arg;
@@ -139,22 +141,48 @@ public class Main implements LogPrinter {
}
task.options.outputName = name;
}
+ }, new Option(" --class-name List of classes to compile", true, "--class-name", "--classname") {
+ @Override
+ void process(Main task, String opt, String arg) {
+ task.options.files.addAll(ClassSearch.makeList(ClassNameSourceProvider.TYPE, arg));
+ }
+ }, new Option(" --jar List of jar files to compile", true, "--jar") {
+ @Override
+ void process(Main task, String opt, String arg) {
+ task.options.files.addAll(ClassSearch.makeList(JarSourceProvider.TYPE, arg));
+ }
+ }, new Option(" --module List of modules to compile", true, "--module") {
+ @Override
+ void process(Main task, String opt, String arg) {
+ task.options.files.addAll(ClassSearch.makeList(ModuleSourceProvider.TYPE, arg));
+ }
+ }, new Option(" --directory List of directories where to search for files to compile", true, "--directory") {
+ @Override
+ void process(Main task, String opt, String arg) {
+ task.options.files.addAll(ClassSearch.makeList(DirectorySourceProvider.TYPE, arg));
+ }
+ }, new Option(" --search-path List of directories where to search for specified files", true, "--search-path") {
+ @Override
+ void process(Main task, String opt, String arg) {
+ String[] elements = arg.split(":");
+ task.options.searchPath.add(elements);
+ }
}, new Option(" --compile-commands Name of file with compile commands", true, "--compile-commands") {
@Override
void process(Main task, String opt, String arg) {
task.options.methodList = arg;
}
- }, new Option(" --compile-for-tiered Generated profiling code for tiered compilation", false, "--compile-for-tiered") {
+ }, new Option(" --compile-for-tiered Generate profiling code for tiered compilation", false, "--compile-for-tiered") {
@Override
void process(Main task, String opt, String arg) {
TieredAOT.setValue(true);
}
- }, new Option(" --classpath Specify where to find user class files", true, "--classpath", "--class-path") {
+ }, new Option(" --compile-with-assertions Compile with java assertions", false, "--compile-with-assertions") {
@Override
void process(Main task, String opt, String arg) {
- task.options.classpath = arg;
+ task.options.compileWithAssertions = true;
}
- }, new Option(" --threads Number of compilation threads to be used", true, "--threads") {
+ }, new Option(" --compile-threads Number of compilation threads to be used", true, "--compile-threads", "--threads") {
@Override
void process(Main task, String opt, String arg) {
int threads = Integer.parseInt(arg);
@@ -213,27 +241,27 @@ public class Main implements LogPrinter {
}};
public static class Options {
- public List files = new LinkedList<>();
- public String module = null;
- public String modulepath = "modules";
+ public List files = new LinkedList<>();
public String outputName = "unnamed";
public String methodList;
- public String classpath = ".";
+ public List sources = new ArrayList<>();
+ public SearchPath searchPath = new SearchPath();
/**
* We don't see scaling beyond 16 threads.
*/
private static final int COMPILER_THREADS = 16;
- int threads = Integer.min(COMPILER_THREADS, Runtime.getRuntime().availableProcessors());
+ public int threads = Integer.min(COMPILER_THREADS, Runtime.getRuntime().availableProcessors());
public boolean ignoreClassLoadingErrors;
public boolean exitOnError;
- boolean info;
- boolean verbose;
- boolean debug;
- boolean help;
- boolean version;
+ public boolean info;
+ public boolean verbose;
+ public boolean debug;
+ public boolean help;
+ public boolean version;
+ public boolean compileWithAssertions;
}
/* package */final Options options = new Options();
@@ -275,7 +303,9 @@ public class Main implements LogPrinter {
printlnInfo("Compiling " + options.outputName + "...");
final long start = System.currentTimeMillis();
- run();
+ if (!run()) {
+ return EXIT_ABNORMAL;
+ }
final long end = System.currentTimeMillis();
printlnInfo("Total time: " + (end - start) + " ms");
@@ -318,17 +348,34 @@ public class Main implements LogPrinter {
}
@SuppressWarnings("try")
- private void run() throws Exception {
+ private boolean run() throws Exception {
openLog();
try {
CompilationSpec compilationRestrictions = collectSpecifiedMethods();
- Set> classesToCompile;
+ Set> classesToCompile = new HashSet<>();
try (Timer t = new Timer(this, "")) {
- ClassCollector collector = new ClassCollector(this.options, this);
- classesToCompile = collector.collectClassesToCompile();
+ FileSupport fileSupport = new FileSupport();
+ ClassSearch lookup = new ClassSearch();
+ lookup.addProvider(new ModuleSourceProvider());
+ lookup.addProvider(new ClassNameSourceProvider(fileSupport));
+ lookup.addProvider(new JarSourceProvider());
+ lookup.addProvider(new DirectorySourceProvider(fileSupport));
+
+ List found = null;
+ try {
+ found = lookup.search(options.files, options.searchPath);
+ } catch (InternalError e) {
+ reportError(e);
+ return false;
+ }
+
+ for (LoadedClass loadedClass : found) {
+ classesToCompile.add(loadedClass.getLoadedClass());
+ }
+
printInfo(classesToCompile.size() + " classes found");
}
@@ -356,6 +403,11 @@ public class Main implements LogPrinter {
AOTCompiler compiler = new AOTCompiler(this, aotBackend, options.threads);
classes = compiler.compileClasses(classes);
+ GraalHotSpotVMConfig graalHotSpotVMConfig = runtime.getVMConfig();
+ PhaseSuite graphBuilderSuite = aotBackend.getGraphBuilderSuite();
+ ListIterator> iterator = graphBuilderSuite.findPhase(GraphBuilderPhase.class);
+ GraphBuilderConfiguration graphBuilderConfig = ((GraphBuilderPhase) iterator.previous()).getGraphBuilderConfig();
+
// Free memory!
try (Timer t = options.verbose ? new Timer(this, "Freeing memory") : null) {
printMemoryUsage();
@@ -364,7 +416,7 @@ public class Main implements LogPrinter {
System.gc();
}
- BinaryContainer binaryContainer = new BinaryContainer(runtime.getVMConfig(), JVM_VERSION);
+ BinaryContainer binaryContainer = new BinaryContainer(graalHotSpotVMConfig, graphBuilderConfig, JVM_VERSION);
DataBuilder dataBuilder = new DataBuilder(this, backend, classes, binaryContainer);
dataBuilder.prepareData();
@@ -446,6 +498,7 @@ public class Main implements LogPrinter {
} finally {
closeLog();
}
+ return true;
}
private void addMethods(AOTCompiledClass aotClass, ResolvedJavaMethod[] methods, CompilationSpec compilationRestrictions, GraalFilters filters) {
@@ -509,7 +562,7 @@ public class Main implements LogPrinter {
break;
}
} else {
- options.files.add(arg);
+ options.files.add(new SearchFor(arg));
}
}
}
@@ -570,6 +623,12 @@ public class Main implements LogPrinter {
log.flush();
}
+ private void reportError(Throwable e) {
+ log.println("Error: " + e.getMessage());
+ e.printStackTrace(log);
+ log.flush();
+ }
+
private void reportError(String key, Object... args) {
printError(MessageFormat.format(key, args));
}
@@ -580,17 +639,17 @@ public class Main implements LogPrinter {
}
private void showUsage() {
- log.println("Usage: " + PROGNAME + " list...");
+ log.println("Usage: " + PROGNAME + " list");
log.println("use --help for a list of possible options");
}
private void showHelp() {
- log.println("Usage: " + PROGNAME + " <--module name> | ");
+ log.println("Usage: " + PROGNAME + " list");
log.println();
- log.println(" list A list of class files, jar files or directories which");
- log.println(" contains class files.");
+ log.println(" list A : separated list of class names, modules, jar files");
+ log.println(" or directories which contain class files.");
log.println();
- log.println("where possible options include:");
+ log.println("where options include:");
for (Option o : recognizedOptions) {
String name = o.aliases[0].substring(1); // there must always be at least one name
name = name.charAt(0) == '-' ? name.substring(1) : name;
diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MarkId.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MarkId.java
index 4bbd4665434..eedeac3b720 100644
--- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MarkId.java
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MarkId.java
@@ -48,6 +48,7 @@ enum MarkId {
HEAP_TOP_ADDRESS("CodeInstaller::HEAP_TOP_ADDRESS"),
HEAP_END_ADDRESS("CodeInstaller::HEAP_END_ADDRESS"),
NARROW_KLASS_BASE_ADDRESS("CodeInstaller::NARROW_KLASS_BASE_ADDRESS"),
+ NARROW_OOP_BASE_ADDRESS("CodeInstaller::NARROW_OOP_BASE_ADDRESS"),
CRC_TABLE_ADDRESS("CodeInstaller::CRC_TABLE_ADDRESS"),
LOG_OF_HEAP_REGION_GRAIN_BYTES("CodeInstaller::LOG_OF_HEAP_REGION_GRAIN_BYTES"),
INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED("CodeInstaller::INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED");
diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MarkProcessor.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MarkProcessor.java
index 1e1944bc274..7a833c13914 100644
--- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MarkProcessor.java
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MarkProcessor.java
@@ -57,6 +57,7 @@ class MarkProcessor {
case HEAP_TOP_ADDRESS:
case HEAP_END_ADDRESS:
case NARROW_KLASS_BASE_ADDRESS:
+ case NARROW_OOP_BASE_ADDRESS:
case CRC_TABLE_ADDRESS:
case LOG_OF_HEAP_REGION_GRAIN_BYTES:
case INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED:
@@ -78,6 +79,9 @@ class MarkProcessor {
case NARROW_KLASS_BASE_ADDRESS:
vmSymbolName = binaryContainer.getNarrowKlassBaseAddressSymbolName();
break;
+ case NARROW_OOP_BASE_ADDRESS:
+ vmSymbolName = binaryContainer.getNarrowOopBaseAddressSymbolName();
+ break;
case CRC_TABLE_ADDRESS:
vmSymbolName = binaryContainer.getCrcTableAddressSymbolName();
break;
diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassCollector.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassCollector.java
deleted file mode 100644
index c46b3bfd062..00000000000
--- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassCollector.java
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.tools.jaotc.collect;
-
-import jdk.tools.jaotc.LogPrinter;
-import jdk.tools.jaotc.Main;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.*;
-import java.nio.file.*;
-import java.nio.file.attribute.BasicFileAttributes;
-import java.util.*;
-
-import static java.nio.file.FileVisitResult.CONTINUE;
-
-public class ClassCollector {
- private final Main.Options options;
- private final LogPrinter log;
-
- public ClassCollector(Main.Options options, LogPrinter log) {
- this.options = options;
- this.log = log;
- }
-
- /**
- * Collect all class names passed by the user.
- *
- * @return array list of classes
- */
- public Set> collectClassesToCompile() {
- Set> classes = new HashSet<>();
- List filesToScan = new LinkedList<>(options.files);
-
- if (options.module != null) {
- classes.addAll(scanModule(filesToScan));
- }
-
- classes.addAll(scanFiles(filesToScan));
- return classes;
- }
-
- private Set> scanModule(List filesToScan) {
- String module = options.module;
- // Search module in standard JDK installation.
- Path dir = getModuleDirectory(options.modulepath, module);
-
- if (Files.isDirectory(dir)) {
- return loadFromModuleDirectory(dir);
- } else {
- findFilesToScan(filesToScan, module);
- return new HashSet<>();
- }
- }
-
- private Set> loadFromModuleDirectory(Path dir) {
- log.printInfo("Scanning module: " + dir + " ...");
- log.printlnVerbose(" "); // Break line
-
- FileSystemFinder finder = new FileSystemFinder(dir, pathname -> entryIsClassFile(pathname.toString()));
- Set> cls = loadWithClassLoader(() -> ClassLoader.getSystemClassLoader(), dir, finder);
- log.printlnInfo(" " + cls.size() + " classes loaded.");
- return cls;
- }
-
- private void findFilesToScan(List filesToScan, String module) {
- // Try to search regular directory, .jar or .class files
- Path path = Paths.get(options.modulepath, module);
-
- if (Files.isDirectory(path)) {
- filesToScan.add(".");
- options.classpath = path.toString();
- } else if (path.endsWith(".jar") || path.endsWith(".class")) {
- filesToScan.add(path.toString());
- } else {
- path = Paths.get(options.modulepath, module + ".jar");
- if (Files.exists(path)) {
- filesToScan.add(path.toString());
- } else {
- path = Paths.get(options.modulepath, module + ".class");
- if (Files.exists(path)) {
- filesToScan.add(path.toString());
- } else {
- throw new InternalError("Expecting a .class, .jar or directory: " + path);
- }
- }
- }
- }
-
- private boolean entryIsClassFile(String entry) {
- return entry.endsWith(".class") && !entry.endsWith("module-info.class");
- }
-
- private Set> scanFiles(List filesToScan) {
- Set> classes = new HashSet<>();
- for (String fileName : filesToScan) {
- Set> loaded = scanFile(fileName);
- log.printlnInfo(" " + loaded.size() + " classes loaded.");
- classes.addAll(loaded);
- }
- return classes;
- }
-
- interface ClassLoaderFactory {
- ClassLoader create() throws IOException;
- }
-
- private Set> loadWithClassLoader(ClassLoaderFactory factory, Path root, FileSystemFinder finder) {
- ClassLoader loader = null;
- try {
- loader = factory.create();
- return loadClassFiles(root, finder, loader);
- } catch (IOException e) {
- throw new InternalError(e);
- } finally {
- if (loader instanceof AutoCloseable) {
- try {
- ((AutoCloseable) loader).close();
- } catch (Exception e) {
- throw new InternalError(e);
- }
- }
- }
- }
-
- private Set> scanFile(String fileName) {
- log.printInfo("Scanning: " + fileName + " ...");
- log.printlnVerbose(" "); // Break line
-
- if (fileName.endsWith(".jar")) {
- return loadFromJarFile(fileName);
- } else if (fileName.endsWith(".class")) {
- Set> classes = new HashSet<>();
- loadFromClassFile(fileName, classes);
- return classes;
- } else {
- return scanClassPath(fileName);
- }
- }
-
- private Set> loadFromJarFile(String fileName) {
- FileSystem fs = makeFileSystem(fileName);
- FileSystemFinder finder = new FileSystemFinder(fs.getPath("/"), pathname -> entryIsClassFile(pathname.toString()));
- return loadWithClassLoader(() -> URLClassLoader.newInstance(buildUrls(fileName)), fs.getPath("/"), finder);
- }
-
- private void loadFromClassFile(String fileName, Set> classes) {
- Class> result;
- File file = new File(options.classpath);
- try (URLClassLoader loader = URLClassLoader.newInstance(buildUrls(file))) {
- result = loadClassFile(loader, fileName);
- } catch (IOException e) {
- throw new InternalError(e);
- }
- Class> c = result;
- addClass(classes, fileName, c);
- }
-
- private Set> scanClassPath(String fileName) {
- Path classPath = Paths.get(options.classpath);
- if (!Files.exists(classPath)) {
- throw new InternalError("Path does not exist: " + classPath);
- }
- if (!Files.isDirectory(classPath)) {
- throw new InternalError("Path must be a directory: " + classPath);
- }
-
- // Combine class path and file name and see what it is.
- Path combinedPath = Paths.get(options.classpath + File.separator + fileName);
- if (combinedPath.endsWith(".class")) {
- throw new InternalError("unimplemented");
- } else if (Files.isDirectory(combinedPath)) {
- return scanDirectory(classPath, combinedPath);
- } else {
- throw new InternalError("Expecting a .class, .jar or directory: " + fileName);
- }
- }
-
- private FileSystem makeFileSystem(String fileName) {
- try {
- return FileSystems.newFileSystem(makeJarFileURI(fileName), new HashMap<>());
- } catch (IOException e) {
- throw new InternalError(e);
- }
- }
-
- private URI makeJarFileURI(String fileName) {
- try {
- return new URI("jar:file:" + Paths.get(fileName).toAbsolutePath() + "!/");
- } catch (URISyntaxException e) {
- throw new InternalError(e);
- }
- }
-
- private PathMatcher combine(PathMatcher m1, PathMatcher m2) {
- return path -> m1.matches(path) && m2.matches(path);
- }
-
- private Set> scanDirectory(Path classPath, Path combinedPath) {
- String dir = options.classpath;
-
- FileSystem fileSystem = FileSystems.getDefault();
- PathMatcher matcher = fileSystem.getPathMatcher("glob:" + "*.class");
- FileSystemFinder finder = new FileSystemFinder(combinedPath,
- combine(matcher, pathname -> entryIsClassFile(pathname.toString())));
-
- File file = new File(dir);
- try (URLClassLoader loader = URLClassLoader.newInstance(buildUrls(file))) {
- return loadClassFiles(classPath, finder, loader);
- } catch (IOException e) {
- throw new InternalError(e);
- }
- }
-
- private Set> loadClassFiles(Path root, FileSystemFinder finder, ClassLoader loader) {
- Set> classes = new HashSet<>();
- for (Path name : finder.done()) {
- // Now relativize to the class path so we get the actual class names.
- String entry = root.relativize(name).normalize().toString();
- Class> c = loadClassFile(loader, entry);
- addClass(classes, entry, c);
- }
- return classes;
- }
-
- private void addClass(Set> classes, String name, Class> c) {
- if (c != null) {
- classes.add(c);
- log.printlnVerbose(" loaded " + name);
- }
- }
-
- private URL[] buildUrls(String fileName) throws MalformedURLException {
- return new URL[]{ new URL("jar:file:" + Paths.get(fileName).toAbsolutePath() + "!/") };
- }
-
- private URL[] buildUrls(File file) throws MalformedURLException {
- return new URL[] {file.toURI().toURL() };
- }
-
- private Path getModuleDirectory(String modulepath, String module) {
- FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
- return fs.getPath(modulepath, module);
- }
-
- /**
- * Loads a class with the given file name from the specified {@link URLClassLoader}.
- */
- private Class> loadClassFile(final ClassLoader loader, final String fileName) {
- int start = 0;
- if (fileName.startsWith("/")) {
- start = 1;
- }
- String className = fileName.substring(start, fileName.length() - ".class".length());
- className = className.replace('/', '.');
- try {
- return loader.loadClass(className);
- } catch (Throwable e) {
- // If we are running in JCK mode we ignore all exceptions.
- if (options.ignoreClassLoadingErrors) {
- log.printError(className + ": " + e);
- return null;
- }
- throw new InternalError(e);
- }
- }
-
- /**
- * {@link FileVisitor} implementation to find class files recursively.
- */
- private static class FileSystemFinder extends SimpleFileVisitor {
- private final ArrayList fileNames = new ArrayList<>();
- private final PathMatcher filter;
-
- FileSystemFinder(Path combinedPath, PathMatcher filter) {
- this.filter = filter;
- try {
- Files.walkFileTree(combinedPath, this);
- } catch (IOException e) {
- throw new InternalError(e);
- }
- }
-
- /**
- * Compares the glob pattern against the file name.
- */
- void find(Path file) {
- Path name = file.getFileName();
- if (name != null && filter.matches(name)) {
- fileNames.add(file);
- }
- }
-
- List done() {
- return fileNames;
- }
-
- @Override
- public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
- find(file);
- return CONTINUE;
- }
-
- @Override
- public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
- find(dir);
- return CONTINUE;
- }
-
- }
-}
diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSearch.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSearch.java
new file mode 100644
index 00000000000..3fd63b2c0b8
--- /dev/null
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSearch.java
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.collect;
+
+import jdk.tools.jaotc.LoadedClass;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ClassSearch {
+ private List providers = new ArrayList<>();
+
+ public void addProvider(SourceProvider provider) {
+ providers.add(provider);
+ }
+
+ public List search(List search, SearchPath searchPath) {
+ List loaded = new ArrayList<>();
+
+ List sources = new ArrayList<>();
+
+ for (SearchFor entry : search) {
+ sources.add(findSource(entry, searchPath));
+ }
+
+ for (ClassSource source : sources) {
+ source.eachClass((name, loader) -> loaded.add(loadClass(name, loader)));
+ }
+
+ return loaded;
+ }
+
+ private LoadedClass loadClass(String name, ClassLoader loader) {
+ try {
+ Class> clzz = loader.loadClass(name);
+ return new LoadedClass(name, clzz);
+ } catch (ClassNotFoundException e) {
+ throw new InternalError("Failed to load with: " + loader, e);
+ }
+ }
+
+ private ClassSource findSource(SearchFor searchFor, SearchPath searchPath) {
+ ClassSource found = null;
+
+ for (SourceProvider provider : providers) {
+ if (!searchFor.isUnknown() && !provider.supports(searchFor.getType())) {
+ continue;
+ }
+
+ ClassSource source = provider.findSource(searchFor.getName(), searchPath);
+ if (source != null) {
+ if (found != null) {
+ throw new InternalError("Multiple possible sources: " + source + " and: " + found);
+ }
+ found = source;
+ }
+ }
+
+ if (found == null) {
+ throw new InternalError("Failed to find: " + searchFor.toString());
+ }
+ return found;
+ }
+
+ public static List makeList(String type, String argument) {
+ List list = new ArrayList<>();
+ String[] elements = argument.split(":");
+ for (String element : elements) {
+ list.add(new SearchFor(element, type));
+ }
+ return list;
+ }
+}
diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSource.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSource.java
new file mode 100644
index 00000000000..8d9b8439760
--- /dev/null
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSource.java
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.collect;
+
+import java.nio.file.Path;
+import java.util.function.BiConsumer;
+
+public interface ClassSource {
+ static boolean pathIsClassFile(Path entry) {
+ String fileName = entry.getFileName().toString();
+ return fileName.endsWith(".class") && !fileName.endsWith("module-info.class");
+ }
+
+ static String makeClassName(Path path) {
+ String fileName = path.toString();
+
+ if (!fileName.endsWith(".class")) {
+ throw new IllegalArgumentException("File doesn't end with .class: '" + fileName + "'");
+ }
+
+ int start = 0;
+ if (fileName.startsWith("/")) {
+ start = 1;
+ }
+
+ String className = fileName.substring(start, fileName.length() - ".class".length());
+ className = className.replace('/', '.');
+ return className;
+ }
+
+ void eachClass(BiConsumer consumer);
+}
diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/FileSupport.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/FileSupport.java
new file mode 100644
index 00000000000..0761c0ae8e1
--- /dev/null
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/FileSupport.java
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.collect;
+
+import java.io.IOException;
+import java.net.*;
+import java.nio.file.*;
+import java.util.HashMap;
+
+public class FileSupport {
+ public boolean exists(Path path) {
+ return Files.exists(path);
+ }
+
+ public boolean isDirectory(Path path) {
+ return Files.isDirectory(path);
+ }
+
+ private FileSystem makeJarFileSystem(Path path) {
+ try {
+ return FileSystems.newFileSystem(makeJarFileURI(path), new HashMap<>());
+ } catch (IOException e) {
+ throw new InternalError(e);
+ }
+ }
+
+ private URI makeJarFileURI(Path path) {
+ try {
+ return new URI("jar:file:" + path.toAbsolutePath() + "!/");
+ } catch (URISyntaxException e) {
+ throw new InternalError(e);
+ }
+ }
+
+ public ClassLoader createClassLoader(Path path, ClassLoader parent) {
+ try {
+ return URLClassLoader.newInstance(buildUrls(path), parent);
+ } catch (MalformedURLException e) {
+ throw new InternalError(e);
+ }
+ }
+
+ public ClassLoader createClassLoader(Path path) throws MalformedURLException {
+ return URLClassLoader.newInstance(buildUrls(path));
+ }
+
+ private URL[] buildUrls(Path path) throws MalformedURLException {
+ return new URL[] { path.toUri().toURL() };
+ }
+
+ public Path getJarFileSystemRoot(Path jarFile) {
+ FileSystem fileSystem = makeJarFileSystem(jarFile);
+ return fileSystem.getPath("/");
+ }
+
+ public boolean isAbsolute(Path entry) {
+ return entry.isAbsolute();
+ }
+
+ public Path getSubDirectory(FileSystem fileSystem, Path root, Path path) throws IOException {
+ DirectoryStream paths = fileSystem.provider().newDirectoryStream(root,null);
+ for (Path entry : paths) {
+ Path relative = root.relativize(entry);
+ if (relative.equals(path)) {
+ return entry;
+ }
+ }
+ return null;
+ }
+}
diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/FileSystemFinder.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/FileSystemFinder.java
new file mode 100644
index 00000000000..7838104b89c
--- /dev/null
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/FileSystemFinder.java
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.collect;
+
+import java.io.IOException;
+import java.nio.file.*;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import static java.nio.file.FileVisitResult.CONTINUE;
+
+/**
+ * {@link FileVisitor} implementation to find class files recursively.
+ */
+public class FileSystemFinder extends SimpleFileVisitor implements Iterable {
+ private final ArrayList fileNames = new ArrayList<>();
+ private final PathMatcher filter;
+
+ public FileSystemFinder(Path combinedPath, PathMatcher filter) {
+ this.filter = filter;
+ try {
+ Files.walkFileTree(combinedPath, this);
+ } catch (IOException e) {
+ throw new InternalError(e);
+ }
+ }
+
+ /**
+ * Compares the glob pattern against the file name.
+ */
+ private void find(Path file) {
+ Path name = file.getFileName();
+ if (name != null && filter.matches(name)) {
+ fileNames.add(file);
+ }
+ }
+
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
+ find(file);
+ return CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
+ find(dir);
+ return CONTINUE;
+ }
+
+
+ @Override
+ public Iterator iterator() {
+ return fileNames.iterator();
+ }
+}
diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/SearchFor.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/SearchFor.java
new file mode 100644
index 00000000000..49e0cdd9945
--- /dev/null
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/SearchFor.java
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.collect;
+
+public class SearchFor {
+ private final String name;
+ private final String type;
+
+ public SearchFor(String name) {
+ this(name, "unknown");
+ }
+
+ public SearchFor(String name, String type) {
+ this.name = name;
+ this.type = type;
+ }
+
+ public boolean isUnknown() {
+ return "unknown".equals(type);
+ }
+
+ public String getType() {
+ return this.type;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ @Override
+ public String toString() {
+ return type + ":" + name;
+ }
+}
diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/SearchPath.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/SearchPath.java
new file mode 100644
index 00000000000..19442069f16
--- /dev/null
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/SearchPath.java
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.collect;
+
+import java.nio.file.FileSystem;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+
+public class SearchPath {
+ private final List searchPaths = new ArrayList<>();
+ private final FileSupport fileSupport;
+
+ public SearchPath() {
+ this(new FileSupport());
+ }
+
+ public SearchPath(FileSupport fileSupport) {
+ this.fileSupport = fileSupport;
+ }
+
+ public Path find(FileSystem fileSystem, Path entry, String... defaults) {
+ if (isAbsolute(entry)) {
+ if (exists(entry)) {
+ return entry;
+ }
+ return null;
+ }
+
+ if (exists(entry)) {
+ return entry;
+ }
+
+ for (String searchPath : defaults) {
+ Path newPath = fileSystem.getPath(searchPath, entry.toString());
+ if (exists(newPath)) {
+ return newPath;
+ }
+ }
+
+ for (Path searchPath : searchPaths) {
+ Path newPath = fileSystem.getPath(searchPath.toString(), entry.toString());
+ if (exists(newPath)) {
+ return newPath;
+ }
+ }
+
+ return null;
+ }
+
+ private boolean isAbsolute(Path entry) {
+ return fileSupport.isAbsolute(entry);
+ }
+
+ private boolean exists(Path entry) {
+ return fileSupport.exists(entry);
+ }
+
+ public void add(String... paths) {
+ for (String name : paths) {
+ Path path = Paths.get(name);
+ searchPaths.add(path);
+ }
+ }
+}
+
diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/SourceProvider.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/SourceProvider.java
new file mode 100644
index 00000000000..5effa83c8fa
--- /dev/null
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/SourceProvider.java
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.collect;
+
+public interface SourceProvider {
+ ClassSource findSource(String name, SearchPath searchPath);
+
+ boolean supports(String type);
+}
diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/classname/ClassNameSource.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/classname/ClassNameSource.java
new file mode 100644
index 00000000000..22227d03882
--- /dev/null
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/classname/ClassNameSource.java
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.collect.classname;
+
+import jdk.tools.jaotc.collect.ClassSource;
+
+import java.util.function.BiConsumer;
+
+public class ClassNameSource implements ClassSource {
+ private final String name;
+ private final ClassLoader classLoader;
+
+ public ClassNameSource(String name, ClassLoader classLoader) {
+ this.name = name;
+ this.classLoader = classLoader;
+ }
+
+ @Override
+ public void eachClass(BiConsumer consumer) {
+ consumer.accept(name, classLoader);
+ }
+}
diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/classname/ClassNameSourceProvider.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/classname/ClassNameSourceProvider.java
new file mode 100644
index 00000000000..b5bc2804ed4
--- /dev/null
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/classname/ClassNameSourceProvider.java
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.collect.classname;
+
+import jdk.tools.jaotc.collect.ClassSource;
+import jdk.tools.jaotc.collect.FileSupport;
+import jdk.tools.jaotc.collect.SearchPath;
+import jdk.tools.jaotc.collect.SourceProvider;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class ClassNameSourceProvider implements SourceProvider {
+ public final static String TYPE = "classname";
+ private final ClassLoader classLoader;
+
+ public ClassNameSourceProvider(FileSupport fileSupport) {
+ String classPath = System.getProperty("java.class.path");
+ ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
+ if (classPath != null && !classPath.isEmpty()) {
+ classLoader = systemClassLoader;
+ } else {
+ Path path = Paths.get(".").toAbsolutePath();
+ classLoader = fileSupport.createClassLoader(path, systemClassLoader);
+ }
+ }
+
+ @Override
+ public ClassSource findSource(String name, SearchPath searchPath) {
+ try {
+ classLoader.loadClass(name);
+ return new ClassNameSource(name, classLoader);
+ } catch (ClassNotFoundException e) {
+ return null;
+ }
+ }
+
+ @Override
+ public boolean supports(String type) {
+ return TYPE.equals(type);
+ }
+}
diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/directory/DirectorySource.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/directory/DirectorySource.java
new file mode 100644
index 00000000000..8e5cdb5bc47
--- /dev/null
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/directory/DirectorySource.java
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.collect.directory;
+
+import jdk.tools.jaotc.collect.ClassSource;
+import jdk.tools.jaotc.collect.FileSystemFinder;
+
+import java.nio.file.Path;
+import java.util.function.BiConsumer;
+
+public class DirectorySource implements ClassSource {
+ private final Path directoryPath;
+ private final ClassLoader classLoader;
+
+ public DirectorySource(Path directoryPath, ClassLoader classLoader) {
+ this.directoryPath = directoryPath;
+ this.classLoader = classLoader;
+ }
+
+ @Override
+ public void eachClass(BiConsumer consumer) {
+ FileSystemFinder finder = new FileSystemFinder(directoryPath, ClassSource::pathIsClassFile);
+
+ for (Path path : finder) {
+ consumer.accept(ClassSource.makeClassName(directoryPath.relativize(path).normalize()), classLoader);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "directory:" + directoryPath.toString();
+ }
+}
diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/directory/DirectorySourceProvider.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/directory/DirectorySourceProvider.java
new file mode 100644
index 00000000000..013e3858830
--- /dev/null
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/directory/DirectorySourceProvider.java
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.collect.directory;
+
+import jdk.tools.jaotc.collect.ClassSource;
+import jdk.tools.jaotc.collect.FileSupport;
+import jdk.tools.jaotc.collect.SearchPath;
+import jdk.tools.jaotc.collect.SourceProvider;
+
+import java.net.MalformedURLException;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+
+public class DirectorySourceProvider implements SourceProvider {
+ private final FileSupport fileSupport;
+ private final FileSystem fileSystem;
+ public final static String TYPE = "directory";
+
+ public DirectorySourceProvider(FileSupport fileSupport) {
+ this.fileSupport = fileSupport;
+ fileSystem = FileSystems.getDefault();
+ }
+
+ @Override
+ public ClassSource findSource(String name, SearchPath searchPath) {
+ Path directoryPath = fileSystem.getPath(name);
+
+ if (!fileSupport.exists(directoryPath)) {
+ return null;
+ }
+ if (!fileSupport.isDirectory(directoryPath)) {
+ return null;
+ }
+
+ try {
+ ClassLoader classLoader = fileSupport.createClassLoader(directoryPath);
+ return new DirectorySource(directoryPath, classLoader);
+ } catch (MalformedURLException e) {
+ return null;
+ }
+ }
+
+ @Override
+ public boolean supports(String type) {
+ return TYPE.equals(type);
+ }
+}
diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/jar/JarFileSource.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/jar/JarFileSource.java
new file mode 100644
index 00000000000..af7330a53b8
--- /dev/null
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/jar/JarFileSource.java
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.collect.jar;
+
+import jdk.tools.jaotc.collect.ClassSource;
+import jdk.tools.jaotc.collect.FileSystemFinder;
+
+import java.nio.file.Path;
+import java.util.function.BiConsumer;
+
+public class JarFileSource implements ClassSource {
+ private final Path jarFile;
+ private final Path jarRootPath;
+ private final ClassLoader classLoader;
+
+
+ public JarFileSource(Path jarFile, Path jarRootPath, ClassLoader classLoader) {
+ this.jarFile = jarFile;
+ this.jarRootPath = jarRootPath;
+ this.classLoader = classLoader;
+ }
+
+ public void eachClass(BiConsumer consumer) {
+ FileSystemFinder finder = new FileSystemFinder(jarRootPath, ClassSource::pathIsClassFile);
+
+ for (Path path : finder) {
+ consumer.accept(ClassSource.makeClassName(jarRootPath.relativize(path).normalize()), classLoader);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "jar:" + jarFile.toString();
+ }
+}
diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/jar/JarSourceProvider.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/jar/JarSourceProvider.java
new file mode 100644
index 00000000000..f876c740b74
--- /dev/null
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/jar/JarSourceProvider.java
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.collect.jar;
+
+import jdk.tools.jaotc.collect.ClassSource;
+import jdk.tools.jaotc.collect.FileSupport;
+import jdk.tools.jaotc.collect.SearchPath;
+import jdk.tools.jaotc.collect.SourceProvider;
+
+import java.net.MalformedURLException;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.nio.file.ProviderNotFoundException;
+
+public class JarSourceProvider implements SourceProvider {
+ private final FileSystem fileSystem;
+ private final FileSupport fileSupport;
+ public final static String TYPE = "jar";
+
+ public JarSourceProvider() {
+ this(new FileSupport());
+ }
+
+ public JarSourceProvider(FileSupport fileSupport) {
+ this.fileSupport = fileSupport;
+ fileSystem = FileSystems.getDefault();
+ }
+
+ @Override
+ public ClassSource findSource(String name, SearchPath searchPath) {
+ Path fileName = fileSystem.getPath(name);
+ Path jarFile = searchPath.find(fileSystem, fileName);
+
+ if (!validPath(jarFile)) {
+ return null;
+ }
+
+ return createSource(jarFile);
+ }
+
+ private ClassSource createSource(Path jarFile) {
+ try {
+ Path jarRootPath = fileSupport.getJarFileSystemRoot(jarFile);
+ if (jarRootPath == null) {
+ return null;
+ }
+ ClassLoader classLoader = fileSupport.createClassLoader(jarFile);
+ return new JarFileSource(jarFile, jarRootPath, classLoader);
+ } catch (ProviderNotFoundException | MalformedURLException e) {
+ }
+ return null;
+ }
+
+ @Override
+ public boolean supports(String type) {
+ return TYPE.equals(type);
+ }
+
+ private boolean validPath(Path jarFile) {
+ return jarFile != null && !fileSupport.isDirectory(jarFile);
+ }
+}
diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/module/ModuleSource.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/module/ModuleSource.java
new file mode 100644
index 00000000000..bac5624ab6a
--- /dev/null
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/module/ModuleSource.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.collect.module;
+
+import jdk.tools.jaotc.collect.ClassSource;
+import jdk.tools.jaotc.collect.FileSystemFinder;
+
+import java.nio.file.Path;
+import java.util.function.BiConsumer;
+
+public class ModuleSource implements ClassSource {
+ private final Path modulePath;
+ private final ClassLoader classLoader;
+
+ public ModuleSource(Path modulePath, ClassLoader classLoader) {
+ this.modulePath = modulePath;
+ this.classLoader = classLoader;
+ }
+
+ @Override
+ public void eachClass(BiConsumer consumer) {
+ FileSystemFinder finder = new FileSystemFinder(modulePath, ClassSource::pathIsClassFile);
+
+ for (Path path : finder) {
+ consumer.accept(ClassSource.makeClassName(modulePath.relativize(path).normalize()), classLoader);
+ }
+ }
+
+ public Path getModulePath() {
+ return modulePath;
+ }
+
+ @Override
+ public String toString() {
+ return "module:" + modulePath.toString();
+ }
+}
diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/module/ModuleSourceProvider.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/module/ModuleSourceProvider.java
new file mode 100644
index 00000000000..cd1a464b6f9
--- /dev/null
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/module/ModuleSourceProvider.java
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.collect.module;
+
+import jdk.tools.jaotc.collect.ClassSource;
+import jdk.tools.jaotc.collect.FileSupport;
+import jdk.tools.jaotc.collect.SearchPath;
+import jdk.tools.jaotc.collect.SourceProvider;
+
+import java.io.IOException;
+import java.net.URI;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+
+public class ModuleSourceProvider implements SourceProvider {
+ private final FileSystem fileSystem;
+ private final ClassLoader classLoader;
+ private final FileSupport fileSupport;
+ public final static String TYPE = "module";
+
+ public ModuleSourceProvider() {
+ this(FileSystems.getFileSystem(URI.create("jrt:/")), ClassLoader.getSystemClassLoader(), new FileSupport());
+ }
+
+ public ModuleSourceProvider(FileSystem fileSystem, ClassLoader classLoader, FileSupport fileSupport) {
+ this.fileSystem = fileSystem;
+ this.classLoader = classLoader;
+ this.fileSupport = fileSupport;
+ }
+
+ @Override
+ public ClassSource findSource(String name, SearchPath searchPath) {
+ Path path = fileSystem.getPath(name);
+ Path dir = fileSystem.getPath("modules");
+
+ if (dir == null || !fileSupport.isDirectory(dir)) {
+ return null;
+ }
+
+ Path found = findModuleDirectory(dir, path);
+
+ if (found == null) {
+ return null;
+ }
+
+ return new ModuleSource(found, classLoader);
+ }
+
+ private Path findModuleDirectory(Path root, Path path) {
+ try {
+ return fileSupport.getSubDirectory(fileSystem, root, path);
+ } catch (IOException e) {
+ throw new InternalError(e);
+ }
+ }
+
+ @Override
+ public boolean supports(String type) {
+ return TYPE.equals(type);
+ }
+}
diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java
index f92f91b7c78..e0b5acb426f 100644
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java
@@ -100,15 +100,19 @@ final class CompilerToVM {
native long getExceptionTableStart(HotSpotResolvedJavaMethodImpl method);
/**
- * Determines if {@code method} can be inlined. A method may not be inlinable for a number of
- * reasons such as:
- *
- * - a CompileOracle directive may prevent inlining or compilation of methods
- * - the method may have a bytecode breakpoint set
- * - the method may have other bytecode features that require special handling by the VM
- *
+ * Determines whether {@code method} is currently compilable by the JVMCI compiler being used by
+ * the VM. This can return false if JVMCI compilation failed earlier for {@code method}, a
+ * breakpoint is currently set in {@code method} or {@code method} contains other bytecode
+ * features that require special handling by the VM.
*/
- native boolean canInlineMethod(HotSpotResolvedJavaMethodImpl method);
+ native boolean isCompilable(HotSpotResolvedJavaMethodImpl method);
+
+ /**
+ * Determines if {@code method} is targeted by a VM directive (e.g.,
+ * {@code -XX:CompileCommand=dontinline,}) or annotation (e.g.,
+ * {@code jdk.internal.vm.annotation.DontInline}) that specifies it should not be inlined.
+ */
+ native boolean hasNeverInlineDirective(HotSpotResolvedJavaMethodImpl method);
/**
* Determines if {@code method} should be inlined at any cost. This could be because:
diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethod.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethod.java
index dc56435038a..af75f81a2ff 100644
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethod.java
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethod.java
@@ -49,13 +49,6 @@ public interface HotSpotResolvedJavaMethod extends ResolvedJavaMethod {
*/
boolean isForceInline();
- /**
- * Returns true if this method has a {@code DontInline} annotation.
- *
- * @return true if DontInline annotation present, false otherwise
- */
- boolean isDontInline();
-
/**
* Returns true if this method has a {@code ReservedStackAccess} annotation.
*
diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java
index ad4c67d0275..393b740a71e 100644
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java
@@ -298,15 +298,6 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp
return (getFlags() & config().methodFlagsForceInline) != 0;
}
- /**
- * Returns true if this method has a {@code DontInline} annotation.
- *
- * @return true if DontInline annotation present, false otherwise
- */
- public boolean isDontInline() {
- return (getFlags() & config().methodFlagsDontInline) != 0;
- }
-
/**
* Returns true if this method has a {@code ReservedStackAccess} annotation.
*
@@ -582,10 +573,15 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp
@Override
public boolean canBeInlined() {
- if (isDontInline()) {
+ if (hasNeverInlineDirective()) {
return false;
}
- return compilerToVM().canInlineMethod(this);
+ return compilerToVM().isCompilable(this);
+ }
+
+ @Override
+ public boolean hasNeverInlineDirective() {
+ return compilerToVM().hasNeverInlineDirective(this);
}
@Override
diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaMethod.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaMethod.java
index 6d13d911398..dee43ffbc6a 100644
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaMethod.java
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaMethod.java
@@ -346,6 +346,13 @@ public interface ResolvedJavaMethod extends JavaMethod, InvokeTarget, ModifiersP
*/
boolean canBeInlined();
+ /**
+ * Determines if this method is targeted by a VM directive (e.g.,
+ * {@code -XX:CompileCommand=dontinline,}) or VM recognized annotation (e.g.,
+ * {@code jdk.internal.vm.annotation.DontInline}) that specifies it should not be inlined.
+ */
+ boolean hasNeverInlineDirective();
+
/**
* Returns {@code true} if the inlining of this method should be forced.
*/
diff --git a/hotspot/src/jdk.vm.compiler/.mx.graal/suite.py b/hotspot/src/jdk.vm.compiler/.mx.graal/suite.py
index 402eae2dae5..dda989acedf 100644
--- a/hotspot/src/jdk.vm.compiler/.mx.graal/suite.py
+++ b/hotspot/src/jdk.vm.compiler/.mx.graal/suite.py
@@ -638,6 +638,7 @@ suite = {
"annotationProcessors" : [
"GRAAL_NODEINFO_PROCESSOR",
"GRAAL_REPLACEMENTS_VERIFIER",
+ "GRAAL_OPTIONS_PROCESSOR",
],
"workingSets" : "Graal,Graph",
},
diff --git a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Debug.java b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Debug.java
index f5a3758f066..cd5e7fca7ae 100644
--- a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Debug.java
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Debug.java
@@ -116,6 +116,7 @@ public class Debug {
public static final int INFO_LOG_LEVEL = 2;
public static final int VERBOSE_LOG_LEVEL = 3;
public static final int DETAILED_LOG_LEVEL = 4;
+ public static final int VERY_DETAILED_LOG_LEVEL = 5;
public static boolean isDumpEnabled(int dumpLevel) {
return ENABLED && DebugScope.getInstance().isDumpEnabled(dumpLevel);
diff --git a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java
index 4ccc1bbc9ef..7cb4b03b27e 100644
--- a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java
@@ -267,10 +267,15 @@ public class AMD64HotSpotBackend extends HotSpotHostBackend {
if (config.useCompressedClassPointers) {
Register register = r10;
- AMD64HotSpotMove.decodeKlassPointer(asm, register, providers.getRegisters().getHeapBaseRegister(), src, config.getKlassEncoding());
- if (config.narrowKlassBase != 0) {
- // The heap base register was destroyed above, so restore it
- asm.movq(providers.getRegisters().getHeapBaseRegister(), config.narrowOopBase);
+ AMD64HotSpotMove.decodeKlassPointer(crb, asm, register, providers.getRegisters().getHeapBaseRegister(), src, config);
+ if (GeneratePIC.getValue()) {
+ asm.movq(providers.getRegisters().getHeapBaseRegister(), asm.getPlaceholder(-1));
+ crb.recordMark(config.MARKID_NARROW_OOP_BASE_ADDRESS);
+ } else {
+ if (config.narrowKlassBase != 0) {
+ // The heap base register was destroyed above, so restore it
+ asm.movq(providers.getRegisters().getHeapBaseRegister(), config.narrowOopBase);
+ }
}
asm.cmpq(inlineCacheKlass, register);
} else {
diff --git a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMove.java b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMove.java
index f7a5f205c26..168282ebcbf 100644
--- a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMove.java
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMove.java
@@ -265,14 +265,21 @@ public class AMD64HotSpotMove {
}
}
- public static void decodeKlassPointer(AMD64MacroAssembler masm, Register register, Register scratch, AMD64Address address, CompressEncoding encoding) {
+ public static void decodeKlassPointer(CompilationResultBuilder crb, AMD64MacroAssembler masm, Register register, Register scratch, AMD64Address address, GraalHotSpotVMConfig config) {
+ CompressEncoding encoding = config.getKlassEncoding();
masm.movl(register, address);
if (encoding.shift != 0) {
assert encoding.alignment == encoding.shift : "Decode algorithm is wrong";
masm.shlq(register, encoding.alignment);
}
- if (encoding.base != 0) {
- masm.movq(scratch, encoding.base);
+ if (GeneratePIC.getValue() || encoding.base != 0) {
+ if (GeneratePIC.getValue()) {
+ masm.movq(scratch, masm.getPlaceholder(-1));
+ crb.recordMark(config.MARKID_NARROW_KLASS_BASE_ADDRESS);
+ } else {
+ assert encoding.base != 0;
+ masm.movq(scratch, encoding.base);
+ }
masm.addq(register, scratch);
}
}
diff --git a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/AOTGraalHotSpotVMConfig.java b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/AOTGraalHotSpotVMConfig.java
new file mode 100644
index 00000000000..3a93d463936
--- /dev/null
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/AOTGraalHotSpotVMConfig.java
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.compiler.hotspot;
+
+import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
+
+public class AOTGraalHotSpotVMConfig extends GraalHotSpotVMConfig {
+ private final CompressEncoding aotOopEncoding;
+ private final CompressEncoding aotKlassEncoding;
+
+ public AOTGraalHotSpotVMConfig(HotSpotVMConfigStore store) {
+ super(store);
+ // In AOT, force the shift to be always equal to alignment therefore avoiding zero-shift.
+ CompressEncoding vmOopEncoding = super.getOopEncoding();
+ aotOopEncoding = new CompressEncoding(vmOopEncoding.base, vmOopEncoding.alignment, vmOopEncoding.alignment);
+ CompressEncoding vmKlassEncoding = super.getKlassEncoding();
+ aotKlassEncoding = new CompressEncoding(vmKlassEncoding.base, vmKlassEncoding.alignment, vmKlassEncoding.alignment);
+ assert check();
+ }
+
+ @Override
+ public CompressEncoding getOopEncoding() {
+ return aotOopEncoding;
+ }
+
+ @Override
+ public CompressEncoding getKlassEncoding() {
+ return aotKlassEncoding;
+ }
+}
diff --git a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java
index e7ce8f68cce..898d688747d 100644
--- a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java
@@ -479,7 +479,6 @@ public class GraalHotSpotVMConfig extends HotSpotVMConfigAccess {
public final int methodCompiledEntryOffset = getFieldOffset("Method::_from_compiled_entry", Integer.class, "address");
public final int methodCodeOffset = getFieldOffset("Method::_code", Integer.class, isJDK8 ? "nmethod*" : "CompiledMethod*");
- public final int methodFlagsJfrTowrite = getConstant("Method::_jfr_towrite", Integer.class);
public final int methodFlagsCallerSensitive = getConstant("Method::_caller_sensitive", Integer.class);
public final int methodFlagsForceInline = getConstant("Method::_force_inline", Integer.class);
public final int methodFlagsDontInline = getConstant("Method::_dont_inline", Integer.class);
@@ -773,13 +772,14 @@ public class GraalHotSpotVMConfig extends HotSpotVMConfigAccess {
public final int MARKID_HEAP_TOP_ADDRESS = getConstant("CodeInstaller::HEAP_TOP_ADDRESS", Integer.class, 17);
public final int MARKID_HEAP_END_ADDRESS = getConstant("CodeInstaller::HEAP_END_ADDRESS", Integer.class, 18);
public final int MARKID_NARROW_KLASS_BASE_ADDRESS = getConstant("CodeInstaller::NARROW_KLASS_BASE_ADDRESS", Integer.class, 19);
- public final int MARKID_CRC_TABLE_ADDRESS = getConstant("CodeInstaller::CRC_TABLE_ADDRESS", Integer.class, 20);
- public final int MARKID_LOG_OF_HEAP_REGION_GRAIN_BYTES = getConstant("CodeInstaller::LOG_OF_HEAP_REGION_GRAIN_BYTES", Integer.class, 21);
- public final int MARKID_INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED = getConstant("CodeInstaller::INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED", Integer.class, 22);
+ public final int MARKID_NARROW_OOP_BASE_ADDRESS = getConstant("CodeInstaller::NARROW_OOP_BASE_ADDRESS", Integer.class, 20);
+ public final int MARKID_CRC_TABLE_ADDRESS = getConstant("CodeInstaller::CRC_TABLE_ADDRESS", Integer.class, 21);
+ public final int MARKID_LOG_OF_HEAP_REGION_GRAIN_BYTES = getConstant("CodeInstaller::LOG_OF_HEAP_REGION_GRAIN_BYTES", Integer.class, 22);
+ public final int MARKID_INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED = getConstant("CodeInstaller::INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED", Integer.class, 23);
// Checkstyle: resume
- private boolean check() {
+ protected boolean check() {
for (Field f : getClass().getDeclaredFields()) {
int modifiers = f.getModifiers();
if (Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers)) {
diff --git a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java
index 01401eafd4a..401169124f4 100644
--- a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java
@@ -22,6 +22,7 @@
*/
package org.graalvm.compiler.hotspot;
+import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
import static org.graalvm.compiler.debug.GraalDebugConfig.areScopedGlobalMetricsEnabled;
import static org.graalvm.compiler.debug.GraalDebugConfig.Options.DebugValueSummary;
import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Dump;
@@ -99,7 +100,7 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider {
HotSpotGraalRuntime(HotSpotJVMCIRuntime jvmciRuntime, CompilerConfigurationFactory compilerConfigurationFactory) {
HotSpotVMConfigStore store = jvmciRuntime.getConfigStore();
- config = new GraalHotSpotVMConfig(store);
+ config = GeneratePIC.getValue() ? new AOTGraalHotSpotVMConfig(store) : new GraalHotSpotVMConfig(store);
CompileTheWorldOptions.overrideWithNativeOptions(config);
// Only set HotSpotPrintInlining if it still has its default value (false).
diff --git a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotNodePlugin.java b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotNodePlugin.java
index 89729e7e3f4..10b2255a3dc 100644
--- a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotNodePlugin.java
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotNodePlugin.java
@@ -22,7 +22,6 @@
*/
package org.graalvm.compiler.hotspot.meta;
-import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode;
import static org.graalvm.compiler.hotspot.meta.HotSpotGraalConstantFieldProvider.FieldReadEnabledInImmutableCode;
@@ -112,11 +111,6 @@ public final class HotSpotNodePlugin implements NodePlugin, TypePlugin {
return true;
}
}
- if (GeneratePIC.getValue()) {
- if (field.isSynthetic() && field.getName().startsWith("$assertionsDisabled")) {
- return tryReadField(b, field, null);
- }
- }
if (b.parsingIntrinsic() && wordOperationPlugin.handleLoadStaticField(b, field)) {
return true;
}
diff --git a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java
index bba5c70cfe4..7ace642641e 100644
--- a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java
@@ -1738,9 +1738,8 @@ public class BytecodeParser implements GraphBuilderContext {
} else {
// Intrinsic was not applied: remove intrinsic guard
// and restore the original receiver node in the arguments array
- for (Node node : graph.getNewNodes(intrinsicGuard.mark)) {
- GraphUtil.killCFG(node);
- }
+ intrinsicGuard.lastInstr.setNext(null);
+ GraphUtil.removeNewNodes(graph, intrinsicGuard.mark);
lastInstr = intrinsicGuard.lastInstr;
args[0] = intrinsicGuard.receiver;
}
diff --git a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/SimplifyingGraphDecoder.java b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/SimplifyingGraphDecoder.java
index f26b3004799..f2f833d2a90 100644
--- a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/SimplifyingGraphDecoder.java
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/SimplifyingGraphDecoder.java
@@ -153,9 +153,7 @@ public class SimplifyingGraphDecoder extends GraphDecoder {
}
for (Node node : methodScope.graph.getNewNodes(methodScope.methodStartMark)) {
- if (!(node instanceof FixedNode) && node.hasNoUsages()) {
- GraphUtil.killCFG(node);
- }
+ GraphUtil.tryKillUnused(node);
}
}
diff --git a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java
index af89e2711de..61603208b96 100644
--- a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java
@@ -506,7 +506,7 @@ public class StructuredGraph extends Graph implements JavaMethodContext {
for (Node successor : snapshot) {
if (successor != null && successor.isAlive()) {
if (successor != survivingSuccessor) {
- GraphUtil.killCFG(successor, tool);
+ GraphUtil.killCFG((FixedNode) successor, tool);
}
}
}
@@ -566,6 +566,9 @@ public class StructuredGraph extends Graph implements JavaMethodContext {
reduceTrivialMerge(begin);
} else { // convert to merge
AbstractMergeNode merge = this.add(new MergeNode());
+ for (EndNode end : begin.forwardEnds()) {
+ merge.addForwardEnd(end);
+ }
this.replaceFixedWithFixed(begin, merge);
}
}
@@ -576,7 +579,14 @@ public class StructuredGraph extends Graph implements JavaMethodContext {
for (PhiNode phi : merge.phis().snapshot()) {
assert phi.valueCount() == 1;
ValueNode singleValue = phi.valueAt(0);
- phi.replaceAtUsagesAndDelete(singleValue);
+ if (phi.hasUsages()) {
+ phi.replaceAtUsagesAndDelete(singleValue);
+ } else {
+ phi.safeDelete();
+ if (singleValue != null) {
+ GraphUtil.tryKillUnused(singleValue);
+ }
+ }
}
// remove loop exits
if (merge instanceof LoopBeginNode) {
diff --git a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java
index f942d8c2358..210c5f793da 100644
--- a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java
@@ -1,5 +1,5 @@
/*
- * 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
@@ -22,18 +22,30 @@
*/
package org.graalvm.compiler.nodes.util;
+import static org.graalvm.compiler.graph.Graph.Options.VerifyGraalGraphEdges;
+import static org.graalvm.compiler.nodes.util.GraphUtil.Options.VerifyKillCFGUnusedNodes;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
+import java.util.Set;
import org.graalvm.compiler.bytecode.Bytecode;
import org.graalvm.compiler.code.SourceStackTraceBailoutException;
+import org.graalvm.compiler.core.common.CollectionsFactory;
import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
+import org.graalvm.compiler.core.common.type.StampFactory;
+import org.graalvm.compiler.debug.Debug;
+import org.graalvm.compiler.graph.Graph;
import org.graalvm.compiler.graph.Node;
+import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.NodeWorkList;
+import org.graalvm.compiler.graph.Position;
import org.graalvm.compiler.graph.iterators.NodeIterable;
import org.graalvm.compiler.graph.spi.SimplifierTool;
+import org.graalvm.compiler.nodeinfo.InputType;
+import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodes.AbstractBeginNode;
import org.graalvm.compiler.nodes.AbstractEndNode;
import org.graalvm.compiler.nodes.AbstractMergeNode;
@@ -48,11 +60,15 @@ import org.graalvm.compiler.nodes.ProxyNode;
import org.graalvm.compiler.nodes.StateSplit;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.calc.FloatingNode;
import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
import org.graalvm.compiler.nodes.spi.ArrayLengthProvider;
import org.graalvm.compiler.nodes.spi.LimitedValueProxy;
import org.graalvm.compiler.nodes.spi.LoweringProvider;
import org.graalvm.compiler.nodes.spi.ValueProxy;
+import org.graalvm.compiler.options.Option;
+import org.graalvm.compiler.options.OptionType;
+import org.graalvm.compiler.options.OptionValue;
import jdk.vm.ci.code.BailoutException;
import jdk.vm.ci.code.BytecodePosition;
@@ -64,22 +80,78 @@ import jdk.vm.ci.meta.ResolvedJavaMethod;
public class GraphUtil {
- public static void killCFG(Node node, SimplifierTool tool) {
- NodeWorkList worklist = killCFG(node, tool, null);
- if (worklist != null) {
- for (Node successor : worklist) {
- killCFG(successor, tool, worklist);
+ public static class Options {
+ @Option(help = "Verify that there are no new unused nodes when performing killCFG", type = OptionType.Debug)//
+ public static final OptionValue VerifyKillCFGUnusedNodes = new OptionValue<>(false);
+ }
+
+ @SuppressWarnings("try")
+ public static void killCFG(FixedNode node, SimplifierTool tool) {
+ try (Debug.Scope scope = Debug.scope("KillCFG", node)) {
+ Set unusedNodes = null;
+ Set unsafeNodes = null;
+ Graph.NodeEventScope nodeEventScope = null;
+ if (VerifyGraalGraphEdges.getValue()) {
+ unsafeNodes = collectUnsafeNodes(node.graph());
+ }
+ if (VerifyKillCFGUnusedNodes.getValue()) {
+ Set collectedUnusedNodes = unusedNodes = CollectionsFactory.newSet();
+ nodeEventScope = node.graph().trackNodeEvents(new Graph.NodeEventListener() {
+ @Override
+ public void event(Graph.NodeEvent e, Node n) {
+ if (e == Graph.NodeEvent.ZERO_USAGES && isFloatingNode(n)) {
+ collectedUnusedNodes.add(n);
+ }
+ }
+ });
+ }
+ Debug.dump(Debug.VERY_DETAILED_LOG_LEVEL, node.graph(), "Before killCFG %s", node);
+ NodeWorkList worklist = killCFG(node, tool, null);
+ if (worklist != null) {
+ for (Node n : worklist) {
+ killCFG(n, tool, worklist);
+ }
+ }
+ if (VerifyGraalGraphEdges.getValue()) {
+ Set newUnsafeNodes = collectUnsafeNodes(node.graph());
+ newUnsafeNodes.removeAll(unsafeNodes);
+ assert newUnsafeNodes.isEmpty() : "New unsafe nodes: " + newUnsafeNodes;
+ }
+ if (VerifyKillCFGUnusedNodes.getValue()) {
+ nodeEventScope.close();
+ unusedNodes.removeIf(n -> n.isDeleted());
+ assert unusedNodes.isEmpty() : "New unused nodes: " + unusedNodes;
+ }
+ } catch (Throwable t) {
+ throw Debug.handle(t);
+ }
+ }
+
+ /**
+ * Collects all node in the graph which have non-optional inputs that are null.
+ */
+ private static Set collectUnsafeNodes(Graph graph) {
+ Set unsafeNodes = CollectionsFactory.newSet();
+ for (Node n : graph.getNodes()) {
+ for (Position pos : n.inputPositions()) {
+ Node input = pos.get(n);
+ if (input == null) {
+ if (!pos.isInputOptional()) {
+ unsafeNodes.add(n);
+ }
+ }
}
}
+ return unsafeNodes;
}
private static NodeWorkList killCFG(Node node, SimplifierTool tool, NodeWorkList worklist) {
NodeWorkList newWorklist = worklist;
- // DebugScope.forceDump(node.graph(), "kill CFG %s", node);
if (node instanceof FixedNode) {
newWorklist = killCFGLinear((FixedNode) node, newWorklist, tool);
} else {
- propagateKill(node);
+ newWorklist = propagateKill(node, newWorklist);
+ Debug.dump(Debug.VERY_DETAILED_LOG_LEVEL, node.graph(), "killCFG (Floating) %s", node);
}
return newWorklist;
}
@@ -93,19 +165,20 @@ public class GraphUtil {
if (current instanceof AbstractEndNode) {
// We reached a control flow end.
AbstractEndNode end = (AbstractEndNode) current;
- killEnd(end, tool);
+ newWorklist = killEnd(end, newWorklist, tool);
} else if (current instanceof FixedWithNextNode) {
- next = ((FixedWithNextNode) current).next();
+ // Node guaranteed to have a single successor
+ FixedWithNextNode fixedWithNext = (FixedWithNextNode) current;
+ assert fixedWithNext.successors().count() == 1 || fixedWithNext.successors().count() == 0;
+ assert fixedWithNext.successors().first() == fixedWithNext.next();
+ next = fixedWithNext.next();
} else {
- // Normal control flow node.
/*
* We do not take a successor snapshot because this iterator supports concurrent
* modifications as long as they do not change the size of the successor list. Not
* taking a snapshot allows us to see modifications to other branches that may
* happen while processing one branch.
*/
- // assert node.successors().count() > 1 || node.successors().count() == 0 :
- // node.getClass();
Iterator successors = current.successors().iterator();
if (successors.hasNext()) {
Node first = successors.next();
@@ -126,100 +199,158 @@ public class GraphUtil {
}
}
current.replaceAtPredecessor(null);
- propagateKill(current);
+ newWorklist = propagateKill(current, newWorklist);
+ Debug.dump(Debug.VERY_DETAILED_LOG_LEVEL, current.graph(), "killCFGLinear %s", current);
current = next;
}
+ Debug.dump(Debug.DETAILED_LOG_LEVEL, in.graph(), "killCFGLinear %s", in);
return newWorklist;
}
- public static void killCFG(Node node) {
+ public static void killCFG(FixedNode node) {
killCFG(node, null);
}
- private static void killEnd(AbstractEndNode end, SimplifierTool tool) {
+ /**
+ * Node type used temporarily while deleting loops.
+ *
+ * It is used as replacement for the loop {@link PhiNode PhiNodes} in order to break data-flow
+ * cycles before deleting the loop. The control-flow of the whole loop is killed before killing
+ * the poison node if they are still alive.
+ */
+ @NodeInfo(allowedUsageTypes = InputType.Unchecked)
+ private static final class PoisonNode extends FloatingNode {
+ public static final NodeClass TYPE = NodeClass.create(PoisonNode.class);
+
+ protected PoisonNode() {
+ super(TYPE, StampFactory.forVoid());
+ }
+ }
+
+ private static NodeWorkList killEnd(AbstractEndNode end, NodeWorkList worklist, SimplifierTool tool) {
+ NodeWorkList newWorklist = worklist;
AbstractMergeNode merge = end.merge();
if (merge != null) {
merge.removeEnd(end);
StructuredGraph graph = end.graph();
if (merge instanceof LoopBeginNode && merge.forwardEndCount() == 0) {
// dead loop
- for (PhiNode phi : merge.phis().snapshot()) {
- propagateKill(phi);
- }
LoopBeginNode begin = (LoopBeginNode) merge;
// disconnect and delete loop ends & loop exits
for (LoopEndNode loopend : begin.loopEnds().snapshot()) {
loopend.predecessor().replaceFirstSuccessor(loopend, null);
loopend.safeDelete();
}
- begin.removeExits();
- FixedNode loopBody = begin.next();
- if (loopBody != null) { // for small infinite loops, the body may be killed while
- // killing the loop ends
- killCFG(loopBody);
+ // clean unused proxies to avoid creating new unused nodes
+ for (LoopExitNode exit : begin.loopExits()) {
+ for (ProxyNode vpn : exit.proxies().snapshot()) {
+ tryKillUnused(vpn);
+ }
}
+ begin.removeExits();
+ PoisonNode poison = null;
+ if (merge.phis().isNotEmpty()) {
+ poison = graph.unique(new PoisonNode());
+ for (PhiNode phi : merge.phis()) {
+ phi.replaceAtUsages(poison);
+ }
+ for (PhiNode phi : merge.phis().snapshot()) {
+ killWithUnusedFloatingInputs(phi);
+ }
+ }
+ FixedNode loopBody = begin.next();
+ Debug.dump(Debug.VERY_DETAILED_LOG_LEVEL, end.graph(), "killEnd (Loop) %s after initial loop cleanup", end);
+ if (loopBody != null) {
+ // for small infinite loops, the body may already be killed while killing the
+ // LoopEnds
+ newWorklist = killCFG(loopBody, tool, worklist);
+ }
+ FrameState frameState = begin.stateAfter();
begin.safeDelete();
+ if (frameState != null) {
+ tryKillUnused(frameState);
+ }
+ if (poison != null && poison.isAlive()) {
+ if (newWorklist == null) {
+ newWorklist = graph.createNodeWorkList();
+ }
+ // drain the worklist to finish the loop before adding the poison
+ for (Node n : newWorklist) {
+ killCFG(n, tool, newWorklist);
+ }
+ if (poison.isAlive()) {
+ newWorklist.add(poison);
+ }
+ }
} else if (merge instanceof LoopBeginNode && ((LoopBeginNode) merge).loopEnds().isEmpty()) {
// not a loop anymore
if (tool != null) {
- merge.phis().forEach(phi -> tool.addToWorkList(phi.usages()));
+ for (PhiNode phi : merge.phis()) {
+ tool.addToWorkList(phi.usages());
+ }
}
graph.reduceDegenerateLoopBegin((LoopBeginNode) merge);
} else if (merge.phiPredecessorCount() == 1) {
// not a merge anymore
if (tool != null) {
- merge.phis().forEach(phi -> tool.addToWorkList(phi.usages()));
+ for (PhiNode phi : merge.phis()) {
+ tool.addToWorkList(phi.usages());
+ }
}
graph.reduceTrivialMerge(merge);
}
}
+ return newWorklist;
}
public static boolean isFloatingNode(Node n) {
return !(n instanceof FixedNode);
}
- private static void propagateKill(Node node) {
+ private static NodeWorkList propagateKill(Node node, NodeWorkList workList) {
+ NodeWorkList newWorkList = workList;
if (node != null && node.isAlive()) {
- node.markDeleted();
-
- for (Node in : node.inputs()) {
- if (in.isAlive()) {
- in.removeUsage(node);
- if (in.hasNoUsages() && !(in instanceof FixedNode)) {
- killWithUnusedFloatingInputs(in);
- }
- }
- }
-
- ArrayList usageToKill = null;
- for (Node usage : node.usages()) {
- if (usage.isAlive() && !(usage instanceof FixedNode)) {
- if (usageToKill == null) {
- usageToKill = new ArrayList<>();
- }
- usageToKill.add(usage);
- }
- }
- if (usageToKill != null) {
- for (Node usage : usageToKill) {
- if (usage.isAlive()) {
- if (usage instanceof PhiNode) {
- PhiNode phiNode = (PhiNode) usage;
- usage.replaceFirstInput(node, null);
- if (phiNode.merge() == null || !phiNode.hasValidInput()) {
- propagateKill(usage);
- }
+ for (Node usage : node.usages().snapshot()) {
+ assert usage.isAlive();
+ if (isFloatingNode(usage)) {
+ boolean addUsage = false;
+ if (usage instanceof PhiNode) {
+ PhiNode phi = (PhiNode) usage;
+ assert phi.merge() != null;
+ if (phi.merge() == node) {
+ // we reach the phi directly through he merge, queue it.
+ addUsage = true;
} else {
- propagateKill(usage);
+ // we reach it though a value
+ assert phi.values().contains(node);
+ // let that be handled when we reach the corresponding End node
}
+ } else {
+ addUsage = true;
+ }
+ if (addUsage) {
+ if (newWorkList == null) {
+ newWorkList = node.graph().createNodeWorkList();
+ }
+ newWorkList.add(usage);
}
}
+ usage.replaceFirstInput(node, null);
}
+ killWithUnusedFloatingInputs(node);
}
+ return newWorkList;
+ }
+
+ private static boolean checkKill(Node node) {
+ node.assertTrue(node.isAlive(), "must be alive");
+ node.assertTrue(node.hasNoUsages(), "cannot kill node %s because of usages: %s", node, node.usages());
+ node.assertTrue(node.predecessor() == null, "cannot kill node %s because of predecessor: %s", node, node.predecessor());
+ return true;
}
public static void killWithUnusedFloatingInputs(Node node) {
+ assert checkKill(node);
node.markDeleted();
outer: for (Node in : node.inputs()) {
if (in.isAlive()) {
@@ -227,7 +358,7 @@ public class GraphUtil {
if (in.hasNoUsages()) {
node.maybeNotifyZeroUsages(in);
}
- if (!(in instanceof FixedNode)) {
+ if (isFloatingNode(in)) {
if (in.hasNoUsages()) {
killWithUnusedFloatingInputs(in);
} else if (in instanceof PhiNode) {
@@ -244,6 +375,35 @@ public class GraphUtil {
}
}
+ /**
+ * Removes all nodes created after the {@code mark}, assuming no "old" nodes point to "new"
+ * nodes.
+ */
+ public static void removeNewNodes(Graph graph, Graph.Mark mark) {
+ assert checkNoOldToNewEdges(graph, mark);
+ for (Node n : graph.getNewNodes(mark)) {
+ n.markDeleted();
+ for (Node in : n.inputs()) {
+ in.removeUsage(n);
+ }
+ }
+ }
+
+ private static boolean checkNoOldToNewEdges(Graph graph, Graph.Mark mark) {
+ for (Node old : graph.getNodes()) {
+ if (graph.isNew(mark, old)) {
+ break;
+ }
+ for (Node n : old.successors()) {
+ assert !graph.isNew(mark, n) : old + " -> " + n;
+ }
+ for (Node n : old.inputs()) {
+ assert !graph.isNew(mark, n) : old + " -> " + n;
+ }
+ }
+ return true;
+ }
+
public static void removeFixedWithUnusedInputs(FixedWithNextNode fixed) {
if (fixed instanceof StateSplit) {
FrameState stateAfter = ((StateSplit) fixed).stateAfter();
@@ -688,8 +848,9 @@ public class GraphUtil {
@Override
public void deleteBranch(Node branch) {
- branch.predecessor().replaceFirstSuccessor(branch, null);
- GraphUtil.killCFG(branch, this);
+ FixedNode fixedBranch = (FixedNode) branch;
+ fixedBranch.predecessor().replaceFirstSuccessor(fixedBranch, null);
+ GraphUtil.killCFG(fixedBranch, this);
}
@Override
diff --git a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/CanonicalizerPhase.java b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/CanonicalizerPhase.java
index 35c0a41a7fb..d57d0d45c7a 100644
--- a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/CanonicalizerPhase.java
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/CanonicalizerPhase.java
@@ -444,8 +444,9 @@ public class CanonicalizerPhase extends BasePhase {
@Override
public void deleteBranch(Node branch) {
- branch.predecessor().replaceFirstSuccessor(branch, null);
- GraphUtil.killCFG(branch, this);
+ FixedNode fixedBranch = (FixedNode) branch;
+ fixedBranch.predecessor().replaceFirstSuccessor(fixedBranch, null);
+ GraphUtil.killCFG(fixedBranch, this);
}
@Override
diff --git a/hotspot/src/os/aix/vm/os_aix.cpp b/hotspot/src/os/aix/vm/os_aix.cpp
index e900ce0af77..014d306e37f 100644
--- a/hotspot/src/os/aix/vm/os_aix.cpp
+++ b/hotspot/src/os/aix/vm/os_aix.cpp
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2016 SAP SE. All rights reserved.
+ * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -632,7 +632,6 @@ void os::Aix::signal_sets_init() {
sigaddset(&unblocked_sigs, SIGBUS);
sigaddset(&unblocked_sigs, SIGFPE);
sigaddset(&unblocked_sigs, SIGTRAP);
- sigaddset(&unblocked_sigs, SIGDANGER);
sigaddset(&unblocked_sigs, SR_signum);
if (!ReduceSignalUsage) {
@@ -1553,6 +1552,8 @@ void os::print_signal_handlers(outputStream* st, char* buf, size_t buflen) {
print_signal_handler(st, SHUTDOWN3_SIGNAL , buf, buflen);
print_signal_handler(st, BREAK_SIGNAL, buf, buflen);
print_signal_handler(st, SIGTRAP, buf, buflen);
+ // We also want to know if someone else adds a SIGDANGER handler because
+ // that will interfere with OOM killling.
print_signal_handler(st, SIGDANGER, buf, buflen);
}
@@ -3156,7 +3157,6 @@ void os::Aix::install_signal_handlers() {
set_signal_handler(SIGFPE, true);
set_signal_handler(SIGTRAP, true);
set_signal_handler(SIGXFSZ, true);
- set_signal_handler(SIGDANGER, true);
if (libjsig_is_loaded) {
// Tell libjsig jvm finishes setting signal handlers.
@@ -3273,7 +3273,6 @@ void os::run_periodic_checks() {
if (UseSIGTRAP) {
DO_SIGNAL_CHECK(SIGTRAP);
}
- DO_SIGNAL_CHECK(SIGDANGER);
// ReduceSignalUsage allows the user to override these handlers
// see comments at the very top and jvm_solaris.h
diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp
index 5142cd37a25..23ad8e209cb 100644
--- a/hotspot/src/os/windows/vm/os_windows.cpp
+++ b/hotspot/src/os/windows/vm/os_windows.cpp
@@ -778,6 +778,11 @@ void os::set_native_thread_name(const char *name) {
// is already attached to a debugger; debugger must observe
// the exception below to show the correct name.
+ // If there is no debugger attached skip raising the exception
+ if (!IsDebuggerPresent()) {
+ return;
+ }
+
const DWORD MS_VC_EXCEPTION = 0x406D1388;
struct {
DWORD dwType; // must be 0x1000
diff --git a/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp b/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp
index 9bbb9387c54..721d99668b4 100644
--- a/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp
+++ b/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2016 SAP SE. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -258,13 +258,6 @@ JVM_handle_aix_signal(int sig, siginfo_t* info, void* ucVoid, int abort_if_unrec
}
}
- // Handle SIGDANGER right away. AIX would raise SIGDANGER whenever available swap
- // space falls below 30%. This is only a chance for the process to gracefully abort.
- // We can't hope to proceed after SIGDANGER since SIGKILL tailgates.
- if (sig == SIGDANGER) {
- goto report_and_die;
- }
-
if (info == NULL || uc == NULL || thread == NULL && vmthread == NULL) {
goto run_chained_handler;
}
diff --git a/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp b/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp
index 24c124a4e8d..7767cecf0e4 100644
--- a/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp
+++ b/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp
@@ -87,6 +87,7 @@
#define SPELL_REG_FP "rbp"
#else
#define REG_FP 29
+#define REG_LR 30
#define SPELL_REG_SP "sp"
#define SPELL_REG_FP "x29"
@@ -182,6 +183,46 @@ frame os::fetch_frame_from_context(const void* ucVoid) {
return frame(sp, fp, epc.pc());
}
+bool os::Linux::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr) {
+ address pc = (address) os::Linux::ucontext_get_pc(uc);
+ if (Interpreter::contains(pc)) {
+ // interpreter performs stack banging after the fixed frame header has
+ // been generated while the compilers perform it before. To maintain
+ // semantic consistency between interpreted and compiled frames, the
+ // method returns the Java sender of the current frame.
+ *fr = os::fetch_frame_from_context(uc);
+ if (!fr->is_first_java_frame()) {
+ assert(fr->safe_for_sender(thread), "Safety check");
+ *fr = fr->java_sender();
+ }
+ } else {
+ // more complex code with compiled code
+ assert(!Interpreter::contains(pc), "Interpreted methods should have been handled above");
+ CodeBlob* cb = CodeCache::find_blob(pc);
+ if (cb == NULL || !cb->is_nmethod() || cb->is_frame_complete_at(pc)) {
+ // Not sure where the pc points to, fallback to default
+ // stack overflow handling
+ return false;
+ } else {
+ // In compiled code, the stack banging is performed before LR
+ // has been saved in the frame. LR is live, and SP and FP
+ // belong to the caller.
+ intptr_t* fp = os::Linux::ucontext_get_fp(uc);
+ intptr_t* sp = os::Linux::ucontext_get_sp(uc);
+ address pc = (address)(uc->uc_mcontext.regs[REG_LR]
+ - NativeInstruction::instruction_size);
+ *fr = frame(sp, fp, pc);
+ if (!fr->is_java_frame()) {
+ assert(fr->safe_for_sender(thread), "Safety check");
+ assert(!fr->is_first_frame(), "Safety check");
+ *fr = fr->java_sender();
+ }
+ }
+ }
+ assert(fr->is_java_frame(), "Safety check");
+ return true;
+}
+
// By default, gcc always saves frame pointer rfp on this stack. This
// may get turned off by -fomit-frame-pointer.
frame os::get_sender_for_C_frame(frame* fr) {
@@ -313,6 +354,24 @@ JVM_handle_linux_signal(int sig,
if (thread->in_stack_yellow_reserved_zone(addr)) {
thread->disable_stack_yellow_reserved_zone();
if (thread->thread_state() == _thread_in_Java) {
+ if (thread->in_stack_reserved_zone(addr)) {
+ frame fr;
+ if (os::Linux::get_frame_at_stack_banging_point(thread, uc, &fr)) {
+ assert(fr.is_java_frame(), "Must be a Java frame");
+ frame activation =
+ SharedRuntime::look_for_reserved_stack_annotated_method(thread, fr);
+ if (activation.sp() != NULL) {
+ thread->disable_stack_reserved_zone();
+ if (activation.is_interpreted_frame()) {
+ thread->set_reserved_stack_activation((address)(
+ activation.fp() + frame::interpreter_frame_initial_sp_offset));
+ } else {
+ thread->set_reserved_stack_activation((address)activation.unextended_sp());
+ }
+ return 1;
+ }
+ }
+ }
// Throw a stack overflow exception. Guard pages will be reenabled
// while unwinding the stack.
stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW);
diff --git a/hotspot/src/os_cpu/linux_s390/vm/os_linux_s390.cpp b/hotspot/src/os_cpu/linux_s390/vm/os_linux_s390.cpp
index 684853cfd34..e9120a8b696 100644
--- a/hotspot/src/os_cpu/linux_s390/vm/os_linux_s390.cpp
+++ b/hotspot/src/os_cpu/linux_s390/vm/os_linux_s390.cpp
@@ -144,6 +144,42 @@ frame os::fetch_frame_from_context(const void* ucVoid) {
return frame(sp, epc.pc());
}
+bool os::Linux::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr) {
+ address pc = (address) os::Linux::ucontext_get_pc(uc);
+ if (Interpreter::contains(pc)) {
+ // Interpreter performs stack banging after the fixed frame header has
+ // been generated while the compilers perform it before. To maintain
+ // semantic consistency between interpreted and compiled frames, the
+ // method returns the Java sender of the current frame.
+ *fr = os::fetch_frame_from_context(uc);
+ if (!fr->is_first_java_frame()) {
+ assert(fr->safe_for_sender(thread), "Safety check");
+ *fr = fr->java_sender();
+ }
+ } else {
+ // More complex code with compiled code.
+ assert(!Interpreter::contains(pc), "Interpreted methods should have been handled above");
+ CodeBlob* cb = CodeCache::find_blob(pc);
+ if (cb == NULL || !cb->is_nmethod() || cb->is_frame_complete_at(pc)) {
+ // Not sure where the pc points to, fallback to default
+ // stack overflow handling. In compiled code, we bang before
+ // the frame is complete.
+ return false;
+ } else {
+ intptr_t* fp = os::Linux::ucontext_get_fp(uc);
+ intptr_t* sp = os::Linux::ucontext_get_sp(uc);
+ *fr = frame(sp, (address)*sp);
+ if (!fr->is_java_frame()) {
+ assert(fr->safe_for_sender(thread), "Safety check");
+ assert(!fr->is_first_frame(), "Safety check");
+ *fr = fr->java_sender();
+ }
+ }
+ }
+ assert(fr->is_java_frame(), "Safety check");
+ return true;
+}
+
frame os::get_sender_for_C_frame(frame* fr) {
if (*fr->sp() == 0) {
// fr is the last C frame.
@@ -279,13 +315,31 @@ JVM_handle_linux_signal(int sig,
if (thread->on_local_stack(addr)) {
// stack overflow
if (thread->in_stack_yellow_reserved_zone(addr)) {
- thread->disable_stack_yellow_reserved_zone();
if (thread->thread_state() == _thread_in_Java) {
+ if (thread->in_stack_reserved_zone(addr)) {
+ frame fr;
+ if (os::Linux::get_frame_at_stack_banging_point(thread, uc, &fr)) {
+ assert(fr.is_java_frame(), "Must be a Javac frame");
+ frame activation =
+ SharedRuntime::look_for_reserved_stack_annotated_method(thread, fr);
+ if (activation.sp() != NULL) {
+ thread->disable_stack_reserved_zone();
+ if (activation.is_interpreted_frame()) {
+ thread->set_reserved_stack_activation((address)activation.fp());
+ } else {
+ thread->set_reserved_stack_activation((address)activation.unextended_sp());
+ }
+ return 1;
+ }
+ }
+ }
// Throw a stack overflow exception.
// Guard pages will be reenabled while unwinding the stack.
+ thread->disable_stack_yellow_reserved_zone();
stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW);
} else {
// Thread was in the vm or native code. Return and try to finish.
+ thread->disable_stack_yellow_reserved_zone();
return 1;
}
} else if (thread->in_stack_red_zone(addr)) {
diff --git a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp
index f5c0ff370a0..5fcd2de83df 100644
--- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp
+++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp
@@ -89,7 +89,10 @@
// Minimum usable stack sizes required to get to user code. Space for
// HotSpot guard pages is added later.
#ifdef _LP64
-size_t os::Posix::_compiler_thread_min_stack_allowed = 202 * K;
+// The adlc generated method 'State::MachNodeGenerator(int)' used by the C2 compiler
+// threads requires a large stack with the Solaris Studio C++ compiler version 5.13
+// and product VM builds (debug builds require significantly less stack space).
+size_t os::Posix::_compiler_thread_min_stack_allowed = 325 * K;
size_t os::Posix::_java_thread_min_stack_allowed = 48 * K;
size_t os::Posix::_vm_internal_thread_min_stack_allowed = 224 * K;
#else
diff --git a/hotspot/src/share/vm/adlc/formssel.cpp b/hotspot/src/share/vm/adlc/formssel.cpp
index d9e8726bb58..3bc1fa6aec8 100644
--- a/hotspot/src/share/vm/adlc/formssel.cpp
+++ b/hotspot/src/share/vm/adlc/formssel.cpp
@@ -650,6 +650,7 @@ bool InstructForm::is_wide_memory_kill(FormDict &globals) const {
if( strcmp(_matrule->_opType,"MemBarReleaseLock") == 0 ) return true;
if( strcmp(_matrule->_opType,"MemBarAcquireLock") == 0 ) return true;
if( strcmp(_matrule->_opType,"MemBarStoreStore") == 0 ) return true;
+ if( strcmp(_matrule->_opType,"MemBarVolatile") == 0 ) return true;
if( strcmp(_matrule->_opType,"StoreFence") == 0 ) return true;
if( strcmp(_matrule->_opType,"LoadFence") == 0 ) return true;
diff --git a/hotspot/src/share/vm/aot/aotCodeHeap.cpp b/hotspot/src/share/vm/aot/aotCodeHeap.cpp
index 08283a92fbe..52e2c8d55b1 100644
--- a/hotspot/src/share/vm/aot/aotCodeHeap.cpp
+++ b/hotspot/src/share/vm/aot/aotCodeHeap.cpp
@@ -25,6 +25,7 @@
#include "aot/aotCodeHeap.hpp"
#include "aot/aotLoader.hpp"
+#include "classfile/javaAssertions.hpp"
#include "gc/g1/heapRegion.hpp"
#include "gc/shared/gcLocker.hpp"
#include "interpreter/abstractInterpreter.hpp"
@@ -294,6 +295,8 @@ void AOTCodeHeap::publish_aot(const methodHandle& mh, AOTMethodData* method_data
// When the AOT compiler compiles something big we fail to generate metadata
// in CodeInstaller::gather_metadata. In that case the scopes_pcs_begin == scopes_pcs_end.
// In all successful cases we always have 2 entries of scope pcs.
+ log_info(aot, class, resolve)("Failed to load %s (no metadata available)", mh->name_and_sig_as_C_string());
+ _code_to_aot[code_id]._state = invalid;
return;
}
@@ -536,6 +539,7 @@ void AOTCodeHeap::link_global_lib_symbols() {
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_heap_end_address", address, (heap->supports_inline_contig_alloc() ? heap->end_addr() : NULL));
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_polling_page", address, os::get_polling_page());
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_narrow_klass_base_address", address, Universe::narrow_klass_base());
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_narrow_oop_base_address", address, Universe::narrow_oop_base());
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_log_of_heap_region_grain_bytes", int, HeapRegion::LogOfHRGrainBytes);
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_inline_contiguous_allocation_supported", bool, heap->supports_inline_contig_alloc());
link_shared_runtime_symbols();
@@ -706,6 +710,12 @@ bool AOTCodeHeap::load_klass_data(instanceKlassHandle kh, Thread* thread) {
return false;
}
+ if (_lib->config()->_omitAssertions && JavaAssertions::enabled(kh->name()->as_C_string(), kh->class_loader() == NULL)) {
+ log_trace(aot, class, load)("class %s in %s does not have java assertions in compiled code, but assertions are enabled for this execution.", kh->internal_name(), _lib->name());
+ sweep_dependent_methods(klass_data);
+ return false;
+ }
+
NOT_PRODUCT( aot_klasses_found++; )
log_trace(aot, class, load)("found %s in %s for classloader %p tid=" INTPTR_FORMAT, kh->internal_name(), _lib->name(), kh->class_loader_data(), p2i(thread));
@@ -714,7 +724,7 @@ bool AOTCodeHeap::load_klass_data(instanceKlassHandle kh, Thread* thread) {
// Set klass's Resolve (second) got cell.
_metaspace_got[klass_data->_got_index] = kh();
- // Initialize global symbols of the DSO to the correspondingVM symbol values.
+ // Initialize global symbols of the DSO to the corresponding VM symbol values.
link_global_lib_symbols();
int methods_offset = klass_data->_compiled_methods_offset;
diff --git a/hotspot/src/share/vm/aot/aotCodeHeap.hpp b/hotspot/src/share/vm/aot/aotCodeHeap.hpp
index 21ce9a042f0..0e0d0038d10 100644
--- a/hotspot/src/share/vm/aot/aotCodeHeap.hpp
+++ b/hotspot/src/share/vm/aot/aotCodeHeap.hpp
@@ -88,7 +88,7 @@ typedef struct {
} AOTHeader;
typedef struct {
- enum { CONFIG_SIZE = 11 + 7 * 4 };
+ enum { CONFIG_SIZE = 12 + 7 * 4 };
int _config_size;
int _narrowOopShift;
int _narrowKlassShift;
@@ -108,6 +108,7 @@ typedef struct {
bool _tieredAOT;
bool _enableContended;
bool _restrictContended;
+ bool _omitAssertions;
} AOTConfiguration;
class AOTLib : public CHeapObj {
diff --git a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp
index 75a4f8aa3de..1a0a5f63687 100644
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp
@@ -3298,7 +3298,9 @@ GraphBuilder::GraphBuilder(Compilation* compilation, IRScope* scope)
// for osr compile, bailout if some requirements are not fulfilled
if (osr_bci != -1) {
BlockBegin* osr_block = blm.bci2block()->at(osr_bci);
- assert(osr_block->is_set(BlockBegin::was_visited_flag),"osr entry must have been visited for osr compile");
+ if (!osr_block->is_set(BlockBegin::was_visited_flag)) {
+ BAILOUT("osr entry must have been visited for osr compile");
+ }
// check if osr entry point has empty stack - we cannot handle non-empty stacks at osr entry points
if (!osr_block->state()->stack_is_empty()) {
diff --git a/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp b/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp
index f7916cb1dab..e960d142abe 100644
--- a/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp
+++ b/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp
@@ -895,8 +895,32 @@ void BCEscapeAnalyzer::iterate_one_block(ciBlock *blk, StateInfo &state, Growabl
ciMethod* target = s.get_method(ignored_will_link, &declared_signature);
ciKlass* holder = s.get_declared_method_holder();
assert(declared_signature != NULL, "cannot be null");
- // Push appendix argument, if one.
- if (s.has_appendix()) {
+ // If the current bytecode has an attached appendix argument,
+ // push an unknown object to represent that argument. (Analysis
+ // of dynamic call sites, especially invokehandle calls, needs
+ // the appendix argument on the stack, in addition to "regular" arguments
+ // pushed onto the stack by bytecode instructions preceding the call.)
+ //
+ // The escape analyzer does _not_ use the ciBytecodeStream::has_appendix(s)
+ // method to determine whether the current bytecode has an appendix argument.
+ // The has_appendix() method obtains the appendix from the
+ // ConstantPoolCacheEntry::_f1 field, which can happen concurrently with
+ // resolution of dynamic call sites. Callees in the
+ // ciBytecodeStream::get_method() call above also access the _f1 field;
+ // interleaving the get_method() and has_appendix() calls in the current
+ // method with call site resolution can lead to an inconsistent view of
+ // the current method's argument count. In particular, some interleaving(s)
+ // can cause the method's argument count to not include the appendix, which
+ // then leads to stack over-/underflow in the escape analyzer.
+ //
+ // Instead of pushing the argument if has_appendix() is true, the escape analyzer
+ // pushes an appendix for all call sites targeted by invokedynamic and invokehandle
+ // instructions, except if the call site is the _invokeBasic intrinsic
+ // (that intrinsic is always targeted by an invokehandle instruction but does
+ // not have an appendix argument).
+ if (target->is_loaded() &&
+ Bytecodes::has_optional_appendix(s.cur_bc_raw()) &&
+ target->intrinsic_id() != vmIntrinsics::_invokeBasic) {
state.apush(unknown_obj);
}
// Pass in raw bytecode because we need to see invokehandle instructions.
diff --git a/hotspot/src/share/vm/ci/ciMethod.hpp b/hotspot/src/share/vm/ci/ciMethod.hpp
index 2580f40f3ea..f16948e71d7 100644
--- a/hotspot/src/share/vm/ci/ciMethod.hpp
+++ b/hotspot/src/share/vm/ci/ciMethod.hpp
@@ -136,15 +136,19 @@ class ciMethod : public ciMetadata {
check_is_loaded();
return _signature->size() + (_flags.is_static() ? 0 : 1);
}
- // Report the number of elements on stack when invoking this method.
- // This is different than the regular arg_size because invokedynamic
- // has an implicit receiver.
+ // Report the number of elements on stack when invoking the current method.
+ // If the method is loaded, arg_size() gives precise information about the
+ // number of stack elements (using the method's signature and its flags).
+ // However, if the method is not loaded, the number of stack elements must
+ // be determined differently, as the method's flags are not yet available.
+ // The invoke_arg_size() method assumes in that case that all bytecodes except
+ // invokestatic and invokedynamic have a receiver that is also pushed onto the
+ // stack by the caller of the current method.
int invoke_arg_size(Bytecodes::Code code) const {
if (is_loaded()) {
return arg_size();
} else {
int arg_size = _signature->size();
- // Add a receiver argument, maybe:
if (code != Bytecodes::_invokestatic &&
code != Bytecodes::_invokedynamic) {
arg_size++;
diff --git a/hotspot/src/share/vm/classfile/classLoader.cpp b/hotspot/src/share/vm/classfile/classLoader.cpp
index e0b7c84e45b..0b036181d31 100644
--- a/hotspot/src/share/vm/classfile/classLoader.cpp
+++ b/hotspot/src/share/vm/classfile/classLoader.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
@@ -364,7 +364,12 @@ u1* ClassPathZipEntry::open_versioned_entry(const char* name, jint* filesize, TR
if (verstr != NULL) {
version = atoi(verstr);
if (version < base_version || version > cur_ver) {
- is_multi_ver = false;
+ // If the specified version is lower than the base version, the base
+ // entry will be used; if the version is higher than the current
+ // jdk version, the highest versioned entry will be used.
+ if (version < base_version) {
+ is_multi_ver = false;
+ }
// print out warning, do not use assertion here since it will continue to look
// for proper version.
warning("JDK%d is not supported in multiple version jars", version);
diff --git a/hotspot/src/share/vm/classfile/classLoaderData.cpp b/hotspot/src/share/vm/classfile/classLoaderData.cpp
index fbafa936950..d1e37d82761 100644
--- a/hotspot/src/share/vm/classfile/classLoaderData.cpp
+++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp
@@ -94,7 +94,7 @@ ClassLoaderData::ClassLoaderData(Handle h_class_loader, bool is_anonymous, Depen
_metaspace(NULL), _unloading(false), _klasses(NULL),
_modules(NULL), _packages(NULL),
_claimed(0), _jmethod_ids(NULL), _handles(NULL), _deallocate_list(NULL),
- _next(NULL), _dependencies(dependencies), _shared_class_loader_id(-1),
+ _next(NULL), _dependencies(dependencies),
_metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true,
Monitor::_safepoint_check_never)) {
TRACE_INIT_ID(this);
diff --git a/hotspot/src/share/vm/classfile/classLoaderData.hpp b/hotspot/src/share/vm/classfile/classLoaderData.hpp
index b69c4e681d4..8c8df5187a7 100644
--- a/hotspot/src/share/vm/classfile/classLoaderData.hpp
+++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp
@@ -204,9 +204,6 @@ class ClassLoaderData : public CHeapObj {
// Support for walking class loader data objects
ClassLoaderData* _next; /// Next loader_datas created
- // CDS
- int _shared_class_loader_id;
-
// ReadOnly and ReadWrite metaspaces (static because only on the null
// class loader for now).
static Metaspace* _ro_metaspace;
@@ -338,15 +335,6 @@ class ClassLoaderData : public CHeapObj {
Metaspace* rw_metaspace();
void initialize_shared_metaspaces();
- int shared_class_loader_id() const {
- return _shared_class_loader_id;
- }
- void set_shared_class_loader_id(int id) {
- assert(id >= 0, "sanity");
- assert(_shared_class_loader_id <0, "cannot be assigned more than once");
- _shared_class_loader_id = id;
- }
-
TRACE_DEFINE_TRACE_ID_METHODS;
};
diff --git a/hotspot/src/share/vm/classfile/javaClasses.cpp b/hotspot/src/share/vm/classfile/javaClasses.cpp
index 91b51404489..b7fe590eee1 100644
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp
@@ -163,8 +163,8 @@ void java_lang_String::compute_offsets() {
Klass* k = SystemDictionary::String_klass();
compute_offset(value_offset, k, vmSymbols::value_name(), vmSymbols::byte_array_signature());
- compute_optional_offset(hash_offset, k, vmSymbols::hash_name(), vmSymbols::int_signature());
- compute_optional_offset(coder_offset, k, vmSymbols::coder_name(), vmSymbols::byte_signature());
+ compute_offset(hash_offset, k, vmSymbols::hash_name(), vmSymbols::int_signature());
+ compute_offset(coder_offset, k, vmSymbols::coder_name(), vmSymbols::byte_signature());
initialized = true;
}
@@ -3977,12 +3977,8 @@ void JavaClasses::check_offsets() {
// java.lang.String
CHECK_OFFSET("java/lang/String", java_lang_String, value, "[B");
- if (java_lang_String::has_hash_field()) {
- CHECK_OFFSET("java/lang/String", java_lang_String, hash, "I");
- }
- if (java_lang_String::has_coder_field()) {
- CHECK_OFFSET("java/lang/String", java_lang_String, coder, "B");
- }
+ CHECK_OFFSET("java/lang/String", java_lang_String, hash, "I");
+ CHECK_OFFSET("java/lang/String", java_lang_String, coder, "B");
// java.lang.Class
diff --git a/hotspot/src/share/vm/classfile/javaClasses.hpp b/hotspot/src/share/vm/classfile/javaClasses.hpp
index 0cf0090e851..f05db4c79b7 100644
--- a/hotspot/src/share/vm/classfile/javaClasses.hpp
+++ b/hotspot/src/share/vm/classfile/javaClasses.hpp
@@ -81,15 +81,6 @@ class java_lang_String : AllStatic {
static Handle create_from_platform_dependent_str(const char* str, TRAPS);
static Handle char_converter(Handle java_string, jchar from_char, jchar to_char, TRAPS);
- static bool has_hash_field() {
- assert(initialized, "Must be initialized");
- return (hash_offset > 0);
- }
- static bool has_coder_field() {
- assert(initialized, "Must be initialized");
- return (coder_offset > 0);
- }
-
static void set_compact_strings(bool value);
static int value_offset_in_bytes() {
diff --git a/hotspot/src/share/vm/classfile/javaClasses.inline.hpp b/hotspot/src/share/vm/classfile/javaClasses.inline.hpp
index b1c4a3f9224..b388bb157d3 100644
--- a/hotspot/src/share/vm/classfile/javaClasses.inline.hpp
+++ b/hotspot/src/share/vm/classfile/javaClasses.inline.hpp
@@ -30,10 +30,8 @@
#include "oops/oopsHierarchy.hpp"
void java_lang_String::set_coder(oop string, jbyte coder) {
- assert(initialized, "Must be initialized");
- if (coder_offset > 0) {
- string->byte_field_put(coder_offset, coder);
- }
+ assert(initialized && (coder_offset > 0), "Must be initialized");
+ string->byte_field_put(coder_offset, coder);
}
void java_lang_String::set_value_raw(oop string, typeArrayOop buffer) {
@@ -61,15 +59,11 @@ unsigned int java_lang_String::hash(oop java_string) {
return java_string->int_field(hash_offset);
}
bool java_lang_String::is_latin1(oop java_string) {
- assert(initialized, "Must be initialized");
+ assert(initialized && (coder_offset > 0), "Must be initialized");
assert(is_instance(java_string), "must be java_string");
- if (coder_offset > 0) {
- jbyte coder = java_string->byte_field(coder_offset);
- assert(CompactStrings || coder == CODER_UTF16, "Must be UTF16 without CompactStrings");
- return coder == CODER_LATIN1;
- } else {
- return false;
- }
+ jbyte coder = java_string->byte_field(coder_offset);
+ assert(CompactStrings || coder == CODER_UTF16, "Must be UTF16 without CompactStrings");
+ return coder == CODER_LATIN1;
}
int java_lang_String::length(oop java_string) {
assert(initialized, "Must be initialized");
diff --git a/hotspot/src/share/vm/classfile/modules.cpp b/hotspot/src/share/vm/classfile/modules.cpp
index becda5363a6..afa3553af1c 100644
--- a/hotspot/src/share/vm/classfile/modules.cpp
+++ b/hotspot/src/share/vm/classfile/modules.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+* Copyright (c) 2016, 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,8 +39,6 @@
#include "logging/log.hpp"
#include "memory/resourceArea.hpp"
#include "oops/instanceKlass.hpp"
-#include "oops/objArrayKlass.hpp"
-#include "oops/objArrayOop.inline.hpp"
#include "runtime/arguments.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/javaCalls.hpp"
@@ -48,17 +46,17 @@
#include "utilities/stringUtils.hpp"
#include "utilities/utf8.hpp"
-static bool verify_module_name(char *module_name) {
+static bool verify_module_name(const char *module_name) {
if (module_name == NULL) return false;
int len = (int)strlen(module_name);
return (len > 0 && len <= Symbol::max_length());
}
-bool Modules::verify_package_name(char *package_name) {
+bool Modules::verify_package_name(const char* package_name) {
if (package_name == NULL) return false;
int len = (int)strlen(package_name);
return (len > 0 && len <= Symbol::max_length() &&
- UTF8::is_legal_utf8((unsigned char *)package_name, len, false) &&
+ UTF8::is_legal_utf8((const unsigned char *)package_name, len, false) &&
ClassFileParser::verify_unqualified_name(package_name, len,
ClassFileParser::LegalClass));
}
@@ -107,10 +105,8 @@ static ModuleEntry* get_module_entry(jobject module, TRAPS) {
return java_lang_reflect_Module::module_entry(module_h(), CHECK_NULL);
}
-static PackageEntry* get_package_entry(ModuleEntry* module_entry, jstring package, TRAPS) {
+static PackageEntry* get_package_entry(ModuleEntry* module_entry, const char* package_name, TRAPS) {
ResourceMark rm(THREAD);
- if (package == NULL) return NULL;
- const char *package_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
if (package_name == NULL) return NULL;
TempNewSymbol pkg_symbol = SymbolTable::new_symbol(package_name, CHECK_NULL);
PackageEntryTable* package_entry_table = module_entry->loader_data()->packages();
@@ -139,7 +135,8 @@ bool Modules::is_package_defined(Symbol* package, Handle h_loader, TRAPS) {
}
static void define_javabase_module(jobject module, jstring version,
- jstring location, jobjectArray packages, TRAPS) {
+ jstring location, const char* const* packages,
+ jsize num_packages, TRAPS) {
ResourceMark rm(THREAD);
Handle module_handle(THREAD, JNIHandles::resolve(module));
@@ -164,21 +161,12 @@ static void define_javabase_module(jobject module, jstring version,
}
}
- objArrayOop packages_oop = objArrayOop(JNIHandles::resolve(packages));
- objArrayHandle packages_h(THREAD, packages_oop);
- int num_packages = (packages_h == NULL ? 0 : packages_h->length());
// Check that the list of packages has no duplicates and that the
// packages are syntactically ok.
GrowableArray* pkg_list = new GrowableArray(num_packages);
for (int x = 0; x < num_packages; x++) {
- oop string_obj = packages_h->obj_at(x);
-
- if (string_obj == NULL || !string_obj->is_a(SystemDictionary::String_klass())) {
- THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
- "Bad package name for module: " JAVA_BASE_NAME);
- }
- char *package_name = java_lang_String::as_utf8_string(string_obj);
+ const char *package_name = packages[x];
if (!Modules::verify_package_name(package_name)) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Invalid package name: %s for module: " JAVA_BASE_NAME, package_name));
@@ -239,7 +227,7 @@ static void define_javabase_module(jobject module, jstring version,
}
}
if (duplicate_javabase) {
- THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+ THROW_MSG(vmSymbols::java_lang_InternalError(),
"Module " JAVA_BASE_NAME " is already defined");
}
@@ -262,13 +250,39 @@ static void define_javabase_module(jobject module, jstring version,
}
}
+// Caller needs ResourceMark.
+void throw_dup_pkg_exception(const char* module_name, PackageEntry* package, TRAPS) {
+ const char* package_name = package->name()->as_C_string();
+ if (package->module()->is_named()) {
+ THROW_MSG(vmSymbols::java_lang_IllegalStateException(),
+ err_msg("Package %s for module %s is already in another module, %s, defined to the class loader",
+ package_name, module_name, package->module()->name()->as_C_string()));
+ } else {
+ THROW_MSG(vmSymbols::java_lang_IllegalStateException(),
+ err_msg("Package %s for module %s is already in the unnamed module defined to the class loader",
+ package_name, module_name));
+ }
+}
+
void Modules::define_module(jobject module, jstring version,
- jstring location, jobjectArray packages, TRAPS) {
+ jstring location, const char* const* packages,
+ jsize num_packages, TRAPS) {
ResourceMark rm(THREAD);
if (module == NULL) {
THROW_MSG(vmSymbols::java_lang_NullPointerException(), "Null module object");
}
+
+ if (num_packages < 0) {
+ THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+ "num_packages must be >= 0");
+ }
+
+ if (packages == NULL && num_packages > 0) {
+ THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+ "num_packages should be zero if packages is null");
+ }
+
Handle module_handle(THREAD, JNIHandles::resolve(module));
if (!java_lang_reflect_Module::is_instance(module_handle())) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
@@ -283,7 +297,7 @@ void Modules::define_module(jobject module, jstring version,
// Special handling of java.base definition
if (strcmp(module_name, JAVA_BASE_NAME) == 0) {
- define_javabase_module(module, version, location, packages, CHECK);
+ define_javabase_module(module, version, location, packages, num_packages, CHECK);
return;
}
@@ -297,21 +311,11 @@ void Modules::define_module(jobject module, jstring version,
}
Handle h_loader = Handle(THREAD, loader);
- objArrayOop packages_oop = objArrayOop(JNIHandles::resolve(packages));
- objArrayHandle packages_h(THREAD, packages_oop);
- int num_packages = (packages_h == NULL ? 0 : packages_h->length());
-
// Check that the list of packages has no duplicates and that the
// packages are syntactically ok.
GrowableArray* pkg_list = new GrowableArray(num_packages);
for (int x = 0; x < num_packages; x++) {
- oop string_obj = packages_h->obj_at(x);
-
- if (string_obj == NULL || !string_obj->is_a(SystemDictionary::String_klass())) {
- THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
- err_msg("Bad package name for module: %s", module_name));
- }
- char *package_name = java_lang_String::as_utf8_string(string_obj);
+ const char* package_name = packages[x];
if (!verify_package_name(package_name)) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Invalid package name: %s for module: %s",
@@ -323,12 +327,15 @@ void Modules::define_module(jobject module, jstring version,
!SystemDictionary::is_platform_class_loader(h_loader) &&
strncmp(package_name, JAVAPKG, JAVAPKG_LEN) == 0) {
const char* class_loader_name = SystemDictionary::loader_name(h_loader());
- StringUtils::replace_no_expand(package_name, "/", ".");
+ size_t pkg_len = strlen(package_name);
+ char* pkg_name = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, pkg_len);
+ strncpy(pkg_name, package_name, pkg_len);
+ StringUtils::replace_no_expand(pkg_name, "/", ".");
const char* msg_text1 = "Class loader (instance of): ";
const char* msg_text2 = " tried to define prohibited package name: ";
- size_t len = strlen(msg_text1) + strlen(class_loader_name) + strlen(msg_text2) + strlen(package_name) + 1;
+ size_t len = strlen(msg_text1) + strlen(class_loader_name) + strlen(msg_text2) + pkg_len + 1;
char* message = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, len);
- jio_snprintf(message, len, "%s%s%s%s", msg_text1, class_loader_name, msg_text2, package_name);
+ jio_snprintf(message, len, "%s%s%s%s", msg_text1, class_loader_name, msg_text2, pkg_name);
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), message);
}
@@ -347,7 +354,6 @@ void Modules::define_module(jobject module, jstring version,
// Create symbol* entry for module name.
TempNewSymbol module_symbol = SymbolTable::new_symbol(module_name, CHECK);
- int dupl_pkg_index = -1;
bool dupl_modules = false;
// Create symbol* entry for module version.
@@ -373,6 +379,7 @@ void Modules::define_module(jobject module, jstring version,
assert(loader_data != NULL, "class loader data shouldn't be null");
PackageEntryTable* package_table = NULL;
+ PackageEntry* existing_pkg = NULL;
{
MutexLocker ml(Module_lock, THREAD);
@@ -382,13 +389,12 @@ void Modules::define_module(jobject module, jstring version,
// Check that none of the packages exist in the class loader's package table.
for (int x = 0; x < pkg_list->length(); x++) {
- if (package_table->lookup_only(pkg_list->at(x)) != NULL) {
+ existing_pkg = package_table->lookup_only(pkg_list->at(x));
+ if (existing_pkg != NULL) {
// This could be because the module was already defined. If so,
// report that error instead of the package error.
if (module_table->lookup_only(module_symbol) != NULL) {
dupl_modules = true;
- } else {
- dupl_pkg_index = x;
}
break;
}
@@ -396,9 +402,8 @@ void Modules::define_module(jobject module, jstring version,
} // if (num_packages > 0)...
// Add the module and its packages.
- if (!dupl_modules && dupl_pkg_index == -1) {
+ if (!dupl_modules && existing_pkg == NULL) {
// Create the entry for this module in the class loader's module entry table.
-
ModuleEntry* module_entry = module_table->locked_create_entry_or_null(module_handle, module_symbol,
version_symbol, location_symbol, loader_data);
@@ -426,13 +431,10 @@ void Modules::define_module(jobject module, jstring version,
// any errors ?
if (dupl_modules) {
- THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+ THROW_MSG(vmSymbols::java_lang_IllegalStateException(),
err_msg("Module %s is already defined", module_name));
- }
- if (dupl_pkg_index != -1) {
- THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
- err_msg("Package %s for module %s already exists for class loader",
- pkg_list->at(dupl_pkg_index)->as_C_string(), module_name));
+ } else if (existing_pkg != NULL) {
+ throw_dup_pkg_exception(module_name, existing_pkg, CHECK);
}
if (log_is_enabled(Debug, modules)) {
@@ -497,8 +499,8 @@ void Modules::set_bootloader_unnamed_module(jobject module, TRAPS) {
java_lang_reflect_Module::set_module_entry(module_handle(), unnamed_module);
}
-void Modules::add_module_exports(jobject from_module, jstring package, jobject to_module, TRAPS) {
- if (package == NULL) {
+void Modules::add_module_exports(jobject from_module, const char* package_name, jobject to_module, TRAPS) {
+ if (package_name == NULL) {
THROW_MSG(vmSymbols::java_lang_NullPointerException(),
"package is null");
}
@@ -526,10 +528,9 @@ void Modules::add_module_exports(jobject from_module, jstring package, jobject t
}
}
- PackageEntry *package_entry = get_package_entry(from_module_entry, package, CHECK);
+ PackageEntry *package_entry = get_package_entry(from_module_entry, package_name, CHECK);
ResourceMark rm(THREAD);
if (package_entry == NULL) {
- const char *package_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Package %s not found in from_module %s",
package_name != NULL ? package_name : "",
@@ -557,7 +558,7 @@ void Modules::add_module_exports(jobject from_module, jstring package, jobject t
}
-void Modules::add_module_exports_qualified(jobject from_module, jstring package,
+void Modules::add_module_exports_qualified(jobject from_module, const char* package,
jobject to_module, TRAPS) {
if (to_module == NULL) {
THROW_MSG(vmSymbols::java_lang_NullPointerException(),
@@ -649,21 +650,15 @@ jobject Modules::get_module(jclass clazz, TRAPS) {
}
-jobject Modules::get_module_by_package_name(jobject loader, jstring package, TRAPS) {
+jobject Modules::get_module_by_package_name(jobject loader, const char* package_name, TRAPS) {
ResourceMark rm(THREAD);
assert(ModuleEntryTable::javabase_defined(),
"Attempt to call get_module_from_pkg before " JAVA_BASE_NAME " is defined");
- if (NULL == package) {
+ if (package_name == NULL) {
THROW_MSG_(vmSymbols::java_lang_NullPointerException(),
"package is null", JNI_FALSE);
}
- const char* package_str =
- java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
- if (NULL == package_str) {
- THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
- "Invalid package", JNI_FALSE);
- }
Handle h_loader (THREAD, JNIHandles::resolve(loader));
// Check that loader is a subclass of java.lang.ClassLoader.
@@ -672,7 +667,7 @@ jobject Modules::get_module_by_package_name(jobject loader, jstring package, TRA
"Class loader is not a subclass of java.lang.ClassLoader", JNI_FALSE);
}
- if (strlen(package_str) == 0) {
+ if (strlen(package_name) == 0) {
// Return the unnamed module
ModuleEntryTable* module_table = get_module_entry_table(h_loader, CHECK_NULL);
if (NULL == module_table) return NULL;
@@ -680,24 +675,24 @@ jobject Modules::get_module_by_package_name(jobject loader, jstring package, TRA
return JNIHandles::make_local(THREAD, JNIHandles::resolve(unnamed_module->module()));
} else {
- TempNewSymbol package_sym = SymbolTable::new_symbol(package_str, CHECK_NULL);
+ TempNewSymbol package_sym = SymbolTable::new_symbol(package_name, CHECK_NULL);
return get_module(package_sym, h_loader, CHECK_NULL);
}
return NULL;
}
-jobject Modules::get_named_module(Handle h_loader, const char* package_str, TRAPS) {
+jobject Modules::get_named_module(Handle h_loader, const char* package_name, TRAPS) {
assert(ModuleEntryTable::javabase_defined(),
"Attempt to call get_named_module before " JAVA_BASE_NAME " is defined");
assert(h_loader.is_null() || java_lang_ClassLoader::is_subclass(h_loader->klass()),
"Class loader is not a subclass of java.lang.ClassLoader");
- assert(package_str != NULL, "the package_str should not be NULL");
+ assert(package_name != NULL, "the package_name should not be NULL");
- if (strlen(package_str) == 0) {
+ if (strlen(package_name) == 0) {
return NULL;
}
- TempNewSymbol package_sym = SymbolTable::new_symbol(package_str, CHECK_NULL);
+ TempNewSymbol package_sym = SymbolTable::new_symbol(package_name, CHECK_NULL);
const PackageEntry* const pkg_entry =
get_package_entry_by_name(package_sym, h_loader, THREAD);
const ModuleEntry* const module_entry = (pkg_entry != NULL ? pkg_entry->module() : NULL);
@@ -723,14 +718,14 @@ jobject Modules::get_module(Symbol* package_name, Handle h_loader, TRAPS) {
return NULL;
}
-void Modules::add_module_package(jobject module, jstring package, TRAPS) {
+void Modules::add_module_package(jobject module, const char* package_name, TRAPS) {
ResourceMark rm(THREAD);
if (module == NULL) {
THROW_MSG(vmSymbols::java_lang_NullPointerException(),
"module is null");
}
- if (package == NULL) {
+ if (package_name == NULL) {
THROW_MSG(vmSymbols::java_lang_NullPointerException(),
"package is null");
}
@@ -743,11 +738,6 @@ void Modules::add_module_package(jobject module, jstring package, TRAPS) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"module cannot be an unnamed module");
}
- char *package_name = java_lang_String::as_utf8_string(
- JNIHandles::resolve_non_null(package));
- if (package_name == NULL) {
- THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "Bad package");
- }
if (!verify_package_name(package_name)) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Invalid package name: %s", package_name));
@@ -760,12 +750,15 @@ void Modules::add_module_package(jobject module, jstring package, TRAPS) {
!loader_data->is_platform_class_loader_data() &&
strncmp(package_name, JAVAPKG, JAVAPKG_LEN) == 0) {
const char* class_loader_name = SystemDictionary::loader_name(loader_data);
- StringUtils::replace_no_expand(package_name, "/", ".");
+ size_t pkg_len = strlen(package_name);
+ char* pkg_name = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, pkg_len);
+ strncpy(pkg_name, package_name, pkg_len);
+ StringUtils::replace_no_expand(pkg_name, "/", ".");
const char* msg_text1 = "Class loader (instance of): ";
const char* msg_text2 = " tried to define prohibited package name: ";
- size_t len = strlen(msg_text1) + strlen(class_loader_name) + strlen(msg_text2) + strlen(package_name) + 1;
+ size_t len = strlen(msg_text1) + strlen(class_loader_name) + strlen(msg_text2) + pkg_len + 1;
char* message = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, len);
- jio_snprintf(message, len, "%s%s%s%s", msg_text1, class_loader_name, msg_text2, package_name);
+ jio_snprintf(message, len, "%s%s%s%s", msg_text1, class_loader_name, msg_text2, pkg_name);
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), message);
}
@@ -776,31 +769,29 @@ void Modules::add_module_package(jobject module, jstring package, TRAPS) {
PackageEntryTable* package_table = loader_data->packages();
assert(package_table != NULL, "Missing package_table");
- bool pkg_exists = false;
+ PackageEntry* existing_pkg = NULL;
{
MutexLocker ml(Module_lock, THREAD);
// Check that the package does not exist in the class loader's package table.
- if (!package_table->lookup_only(pkg_symbol)) {
+ existing_pkg = package_table->lookup_only(pkg_symbol);
+ if (existing_pkg == NULL) {
PackageEntry* pkg = package_table->locked_create_entry_or_null(pkg_symbol, module_entry);
assert(pkg != NULL, "Unable to create a module's package entry");
- } else {
- pkg_exists = true;
}
}
- if (pkg_exists) {
- THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
- err_msg("Package %s already exists for class loader", package_name));
+ if (existing_pkg != NULL) {
+ throw_dup_pkg_exception(module_entry->name()->as_C_string(), existing_pkg, CHECK);
}
}
// Export package in module to all unnamed modules.
-void Modules::add_module_exports_to_all_unnamed(jobject module, jstring package, TRAPS) {
+void Modules::add_module_exports_to_all_unnamed(jobject module, const char* package_name, TRAPS) {
if (module == NULL) {
THROW_MSG(vmSymbols::java_lang_NullPointerException(),
"module is null");
}
- if (package == NULL) {
+ if (package_name == NULL) {
THROW_MSG(vmSymbols::java_lang_NullPointerException(),
"package is null");
}
@@ -811,10 +802,9 @@ void Modules::add_module_exports_to_all_unnamed(jobject module, jstring package,
}
if (module_entry->is_named()) { // No-op for unnamed module.
- PackageEntry *package_entry = get_package_entry(module_entry, package, CHECK);
+ PackageEntry *package_entry = get_package_entry(module_entry, package_name, CHECK);
ResourceMark rm(THREAD);
if (package_entry == NULL) {
- const char *package_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Package %s not found in module %s",
package_name != NULL ? package_name : "",
@@ -833,10 +823,7 @@ void Modules::add_module_exports_to_all_unnamed(jobject module, jstring package,
package_entry->name()->as_C_string(),
module_entry->name()->as_C_string());
- // Mark package as exported to all unnamed modules, unless already
- // unqualifiedly exported.
- if (!package_entry->is_unqual_exported()) {
- package_entry->set_is_exported_allUnnamed();
- }
+ // Mark package as exported to all unnamed modules.
+ package_entry->set_is_exported_allUnnamed();
}
}
diff --git a/hotspot/src/share/vm/classfile/modules.hpp b/hotspot/src/share/vm/classfile/modules.hpp
index 25d02bf845c..4f5e089a065 100644
--- a/hotspot/src/share/vm/classfile/modules.hpp
+++ b/hotspot/src/share/vm/classfile/modules.hpp
@@ -48,9 +48,12 @@ public:
// * Packages contains a duplicate package name
// * A package already exists in another module for this class loader
// * Module is an unnamed module
+ // * num_packages is negative
+ // * num_packages is non-zero when packages is null
// NullPointerExceptions are thrown if module is null.
static void define_module(jobject module, jstring version,
- jstring location, jobjectArray packages, TRAPS);
+ jstring location, const char* const* packages,
+ jsize num_packages, TRAPS);
// Provides the java.lang.reflect.Module for the unnamed module defined
// to the boot loader.
@@ -72,7 +75,7 @@ public:
// * Package is not syntactically correct
// * Package is not defined for from_module's class loader
// * Package is not in module from_module.
- static void add_module_exports(jobject from_module, jstring package, jobject to_module, TRAPS);
+ static void add_module_exports(jobject from_module, const char* package, jobject to_module, TRAPS);
// This does a qualified export of package in module from_module to module
// to_module. The format for the package name must use "/' not ".".
@@ -83,7 +86,7 @@ public:
// * Package is not syntactically correct
// * Package is not defined for from_module's class loader
// * Package is not in module from_module.
- static void add_module_exports_qualified(jobject from_module, jstring package, jobject to_module, TRAPS);
+ static void add_module_exports_qualified(jobject from_module, const char* package, jobject to_module, TRAPS);
// add_reads_module adds module to_module to the list of modules that from_module
// can read. If from_module is the same as to_module then this is a no-op.
@@ -102,7 +105,7 @@ public:
// NullPointerException is thrown if package is null.
// IllegalArgumentException is thrown if loader is neither null nor a subtype of
// java/lang/ClassLoader.
- static jobject get_module_by_package_name(jobject loader, jstring package, TRAPS);
+ static jobject get_module_by_package_name(jobject loader, const char* package, TRAPS);
static jobject get_named_module(Handle h_loader, const char* package, TRAPS);
// If package is defined by loader, return the
@@ -116,16 +119,16 @@ public:
// * Module is unnamed
// * Package is not syntactically correct
// * Package is already defined for module's class loader.
- static void add_module_package(jobject module, jstring package, TRAPS);
+ static void add_module_package(jobject module, const char* package, TRAPS);
// Marks the specified package as exported to all unnamed modules.
// If either module or package is null then NullPointerException is thrown.
// If module or package is bad, or module is unnamed, or package is not in
// module then IllegalArgumentException is thrown.
- static void add_module_exports_to_all_unnamed(jobject module, jstring package, TRAPS);
+ static void add_module_exports_to_all_unnamed(jobject module, const char* package, TRAPS);
// Return TRUE if package_name is syntactically valid, false otherwise.
- static bool verify_package_name(char *package_name);
+ static bool verify_package_name(const char *package_name);
// Return TRUE iff package is defined by loader
static bool is_package_defined(Symbol* package_name, Handle h_loader, TRAPS);
diff --git a/hotspot/src/share/vm/classfile/packageEntry.cpp b/hotspot/src/share/vm/classfile/packageEntry.cpp
index 7ee6c52dd4e..ab80fcb732b 100644
--- a/hotspot/src/share/vm/classfile/packageEntry.cpp
+++ b/hotspot/src/share/vm/classfile/packageEntry.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -37,8 +37,8 @@
// Returns true if this package specifies m as a qualified export, including through an unnamed export
bool PackageEntry::is_qexported_to(ModuleEntry* m) const {
+ assert(Module_lock->owned_by_self(), "should have the Module_lock");
assert(m != NULL, "No module to lookup in this package's qualified exports list");
- MutexLocker m1(Module_lock);
if (is_exported_allUnnamed() && !m->is_named()) {
return true;
} else if (!has_qual_exports_list()) {
@@ -98,15 +98,8 @@ void PackageEntry::set_exported(ModuleEntry* m) {
}
if (m == NULL) {
- // NULL indicates the package is being unqualifiedly exported
- if (has_qual_exports_list()) {
- // Legit to transition a package from being qualifiedly exported
- // to unqualified. Clean up the qualified lists at the next
- // safepoint.
- _exported_pending_delete = _qualified_exports;
- }
-
- // Mark package as unqualifiedly exported
+ // NULL indicates the package is being unqualifiedly exported. Clean up
+ // the qualified list at the next safepoint.
set_unqual_exported();
} else {
@@ -115,14 +108,19 @@ void PackageEntry::set_exported(ModuleEntry* m) {
}
}
+// Set the package as exported to all unnamed modules unless the package is
+// already unqualifiedly exported.
void PackageEntry::set_is_exported_allUnnamed() {
MutexLocker m1(Module_lock);
if (!is_unqual_exported()) {
- _is_exported_allUnnamed = true;
+ _export_flags = PKG_EXP_ALLUNNAMED;
}
}
-// Remove dead module entries within the package's exported list.
+// Remove dead module entries within the package's exported list. Note that
+// if all of the modules on the _qualified_exports get purged the list does not
+// get deleted. This prevents the package from illegally transitioning from
+// exported to non-exported.
void PackageEntry::purge_qualified_exports() {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
if (_must_walk_exports &&
@@ -160,18 +158,9 @@ void PackageEntry::purge_qualified_exports() {
void PackageEntry::delete_qualified_exports() {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
- if (_exported_pending_delete != NULL) {
- // If a transition occurred from qualified to unqualified, the _qualified_exports
- // field should have been NULL'ed out.
- assert(_qualified_exports == NULL, "Package's exported pending delete, exported list should not be active");
- delete _exported_pending_delete;
- }
-
if (_qualified_exports != NULL) {
delete _qualified_exports;
}
-
- _exported_pending_delete = NULL;
_qualified_exports = NULL;
}
@@ -314,6 +303,11 @@ void PackageEntry::package_exports_do(ModuleClosure* const f) {
}
}
+bool PackageEntry::exported_pending_delete() const {
+ assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
+ return (is_unqual_exported() && _qualified_exports != NULL);
+}
+
// Remove dead entries from all packages' exported list
void PackageEntryTable::purge_all_package_exports() {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
@@ -344,13 +338,17 @@ void PackageEntryTable::print(outputStream* st) {
}
}
+// This function may be called from debuggers so access private fields directly
+// to prevent triggering locking-related asserts that could result from calling
+// getter methods.
void PackageEntry::print(outputStream* st) {
ResourceMark rm;
st->print_cr("package entry " PTR_FORMAT " name %s module %s classpath_index "
INT32_FORMAT " is_exported_unqualified %d is_exported_allUnnamed %d " "next " PTR_FORMAT,
p2i(this), name()->as_C_string(),
(module()->is_named() ? module()->name()->as_C_string() : UNNAMED_MODULE),
- _classpath_index, _is_exported_unqualified, _is_exported_allUnnamed, p2i(next()));
+ _classpath_index, _export_flags == PKG_EXP_UNQUALIFIED,
+ _export_flags == PKG_EXP_ALLUNNAMED, p2i(next()));
}
void PackageEntryTable::verify() {
diff --git a/hotspot/src/share/vm/classfile/packageEntry.hpp b/hotspot/src/share/vm/classfile/packageEntry.hpp
index a379bf9de3b..aaafa54bb6d 100644
--- a/hotspot/src/share/vm/classfile/packageEntry.hpp
+++ b/hotspot/src/share/vm/classfile/packageEntry.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -34,8 +34,8 @@
// A PackageEntry basically represents a Java package. It contains:
// - Symbol* containing the package's name.
// - ModuleEntry* for this package's containing module.
-// - a flag indicating if package is exported unqualifiedly
-// - a flag indicating if this package is exported to all unnamed modules.
+// - a field indicating if the package is exported unqualifiedly or to all
+// unnamed modules.
// - a growable array containing other module entries that this
// package is exported to.
//
@@ -44,9 +44,9 @@
// - qualified exports: the package has been explicitly qualified to at least
// one particular module or has been qualifiedly exported
// to all unnamed modules.
-// Note: _is_exported_allUnnamed is a form of a qualified
-// export. It is equivalent to the package being
-// explicitly exported to all current and future unnamed modules.
+// Note: being exported to all unnamed is a form of a qualified
+// export. It is equivalent to the package being explicitly
+// exported to all current and future unnamed modules.
// - unqualified exports: the package is exported to all modules.
//
// A package can transition from:
@@ -56,21 +56,53 @@
// A package cannot transition from:
// - being unqualifiedly exported, to exported qualifiedly to a specific module.
// This transition attempt is silently ignored in set_exported.
+// - being qualifiedly exported to not exported.
+// Because transitions are only allowed from less exposure to greater exposure,
+// the transition from qualifiedly exported to not exported would be considered
+// a backward direction. Therefore the implementation considers a package as
+// qualifiedly exported even if its export-list exists but is empty.
//
// The Mutex Module_lock is shared between ModuleEntry and PackageEntry, to lock either
// data structure.
+
+// PKG_EXP_UNQUALIFIED and PKG_EXP_ALLUNNAMED indicate whether the package is
+// exported unqualifiedly or exported to all unnamed modules. They are used to
+// set the value of _export_flags. Field _export_flags and the _qualified_exports
+// list are used to determine a package's export state.
+// Valid states are:
+//
+// 1. Package is not exported
+// _export_flags is zero and _qualified_exports is null
+// 2. Package is unqualifiedly exported
+// _export_flags is set to PKG_EXP_UNQUALIFIED
+// _qualified_exports may or may not be null depending on whether the package
+// transitioned from qualifiedly exported to unqualifiedly exported.
+// 3. Package is qualifiedly exported
+// _export_flags may be set to PKG_EXP_ALLUNNAMED if the package is also
+// exported to all unnamed modules
+// _qualified_exports will be non-null
+// 4. Package is exported to all unnamed modules
+// _export_flags is set to PKG_EXP_ALLUNNAMED
+// _qualified_exports may or may not be null depending on whether the package
+// is also qualifiedly exported to one or more named modules.
+#define PKG_EXP_UNQUALIFIED 0x0001
+#define PKG_EXP_ALLUNNAMED 0x0002
+#define PKG_EXP_UNQUALIFIED_OR_ALL_UNAMED (PKG_EXP_UNQUALIFIED | PKG_EXP_ALLUNNAMED)
+
class PackageEntry : public HashtableEntry {
private:
ModuleEntry* _module;
+ // Indicates if package is exported unqualifiedly or to all unnamed. Access to
+ // this field is protected by the Module_lock.
+ int _export_flags;
// Used to indicate for packages with classes loaded by the boot loader that
// a class in that package has been loaded. And, for packages with classes
// loaded by the boot loader from -Xbootclasspath/a in an unnamed module, it
// indicates from which class path entry.
s2 _classpath_index;
- bool _is_exported_unqualified;
- bool _is_exported_allUnnamed;
bool _must_walk_exports;
- GrowableArray* _exported_pending_delete; // transitioned from qualified to unqualified, delete at safepoint
+ // Contains list of modules this package is qualifiedly exported to. Access
+ // to this list is protected by the Module_lock.
GrowableArray* _qualified_exports;
TRACE_DEFINE_TRACE_ID_FIELD;
@@ -80,17 +112,14 @@ private:
public:
void init() {
_module = NULL;
+ _export_flags = 0;
_classpath_index = -1;
- _is_exported_unqualified = false;
- _is_exported_allUnnamed = false;
_must_walk_exports = false;
- _exported_pending_delete = NULL;
_qualified_exports = NULL;
}
// package name
Symbol* name() const { return literal(); }
- void set_name(Symbol* n) { set_literal(n); }
// the module containing the package definition
ModuleEntry* module() const { return _module; }
@@ -98,37 +127,39 @@ public:
// package's export state
bool is_exported() const { // qualifiedly or unqualifiedly exported
- return (is_unqual_exported() || has_qual_exports_list() || is_exported_allUnnamed());
+ assert_locked_or_safepoint(Module_lock);
+ return ((_export_flags & PKG_EXP_UNQUALIFIED_OR_ALL_UNAMED) != 0) || has_qual_exports_list();
}
// Returns true if the package has any explicit qualified exports or is exported to all unnamed
bool is_qual_exported() const {
+ assert_locked_or_safepoint(Module_lock);
return (has_qual_exports_list() || is_exported_allUnnamed());
}
- // Returns true if there are any explicit qualified exports
+ // Returns true if there are any explicit qualified exports. Note that even
+ // if the _qualified_exports list is now empty (because the modules that were
+ // on the list got gc-ed and deleted from the list) this method may still
+ // return true.
bool has_qual_exports_list() const {
- assert(!(_qualified_exports != NULL && _is_exported_unqualified),
- "_qualified_exports set at same time as _is_exported_unqualified");
- return (_qualified_exports != NULL);
+ assert_locked_or_safepoint(Module_lock);
+ return (!is_unqual_exported() && _qualified_exports != NULL);
}
bool is_exported_allUnnamed() const {
- assert(!(_is_exported_allUnnamed && _is_exported_unqualified),
- "_is_exported_allUnnamed set at same time as _is_exported_unqualified");
- return _is_exported_allUnnamed;
+ assert_locked_or_safepoint(Module_lock);
+ return (_export_flags == PKG_EXP_ALLUNNAMED);
}
bool is_unqual_exported() const {
- assert(!(_qualified_exports != NULL && _is_exported_unqualified),
- "_qualified_exports set at same time as _is_exported_unqualified");
- assert(!(_is_exported_allUnnamed && _is_exported_unqualified),
- "_is_exported_allUnnamed set at same time as _is_exported_unqualified");
- return _is_exported_unqualified;
+ assert_locked_or_safepoint(Module_lock);
+ return (_export_flags == PKG_EXP_UNQUALIFIED);
}
+
+ // Explicitly set _export_flags to PKG_EXP_UNQUALIFIED and clear
+ // PKG_EXP_ALLUNNAMED, if it was set.
void set_unqual_exported() {
assert(Module_lock->owned_by_self(), "should have the Module_lock");
- _is_exported_unqualified = true;
- _is_exported_allUnnamed = false;
- _qualified_exports = NULL;
+ _export_flags = PKG_EXP_UNQUALIFIED;
}
- bool exported_pending_delete() const { return (_exported_pending_delete != NULL); }
+
+ bool exported_pending_delete() const;
void set_exported(ModuleEntry* m);
diff --git a/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp b/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp
index 4da4869cef2..764e1eaa348 100644
--- a/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp
+++ b/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp
@@ -29,7 +29,6 @@
#include "classfile/dictionary.hpp"
class ClassFileStream;
-class SerializeClosure;
class SystemDictionaryShared: public SystemDictionary {
public:
@@ -79,8 +78,6 @@ public:
return NULL;
}
- static void serialize(SerializeClosure* soc) {}
-
// The (non-application) CDS implementation supports only classes in the boot
// class loader, which ensures that the verification constraints are the same
// during archive creation time and runtime. Thus we can do the constraint checks
diff --git a/hotspot/src/share/vm/classfile/vmSymbols.hpp b/hotspot/src/share/vm/classfile/vmSymbols.hpp
index 3e902d9f18e..0ef86447c4e 100644
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp
@@ -590,11 +590,11 @@
template(java_lang_management_ThreadState, "java/lang/management/ThreadState") \
template(java_lang_management_MemoryUsage, "java/lang/management/MemoryUsage") \
template(java_lang_management_ThreadInfo, "java/lang/management/ThreadInfo") \
+ template(jdk_internal_agent_Agent, "jdk/internal/agent/Agent") \
template(sun_management_Sensor, "sun/management/Sensor") \
- template(sun_management_Agent, "sun/management/Agent") \
+ template(sun_management_ManagementFactoryHelper, "sun/management/ManagementFactoryHelper") \
template(com_sun_management_internal_DiagnosticCommandImpl, "com/sun/management/internal/DiagnosticCommandImpl") \
template(com_sun_management_internal_GarbageCollectorExtImpl,"com/sun/management/internal/GarbageCollectorExtImpl") \
- template(sun_management_ManagementFactoryHelper, "sun/management/ManagementFactoryHelper") \
template(getDiagnosticCommandMBean_name, "getDiagnosticCommandMBean") \
template(getDiagnosticCommandMBean_signature, "()Lcom/sun/management/DiagnosticCommandMBean;") \
template(getGcInfoBuilder_name, "getGcInfoBuilder") \
diff --git a/hotspot/src/share/vm/code/codeCache.cpp b/hotspot/src/share/vm/code/codeCache.cpp
index 80ce54f847e..bfe643ab683 100644
--- a/hotspot/src/share/vm/code/codeCache.cpp
+++ b/hotspot/src/share/vm/code/codeCache.cpp
@@ -149,16 +149,17 @@ void CodeCache::check_heap_sizes(size_t non_nmethod_size, size_t profiled_size,
size_t total_size = non_nmethod_size + profiled_size + non_profiled_size;
// Prepare error message
const char* error = "Invalid code heap sizes";
- err_msg message("NonNMethodCodeHeapSize (%zuK) + ProfiledCodeHeapSize (%zuK) + NonProfiledCodeHeapSize (%zuK) = %zuK",
+ err_msg message("NonNMethodCodeHeapSize (" SIZE_FORMAT "K) + ProfiledCodeHeapSize (" SIZE_FORMAT "K)"
+ " + NonProfiledCodeHeapSize (" SIZE_FORMAT "K) = " SIZE_FORMAT "K",
non_nmethod_size/K, profiled_size/K, non_profiled_size/K, total_size/K);
if (total_size > cache_size) {
// Some code heap sizes were explicitly set: total_size must be <= cache_size
- message.append(" is greater than ReservedCodeCacheSize (%zuK).", cache_size/K);
+ message.append(" is greater than ReservedCodeCacheSize (" SIZE_FORMAT "K).", cache_size/K);
vm_exit_during_initialization(error, message);
} else if (all_set && total_size != cache_size) {
// All code heap sizes were explicitly set: total_size must equal cache_size
- message.append(" is not equal to ReservedCodeCacheSize (%zuK).", cache_size/K);
+ message.append(" is not equal to ReservedCodeCacheSize (" SIZE_FORMAT "K).", cache_size/K);
vm_exit_during_initialization(error, message);
}
}
@@ -267,7 +268,7 @@ void CodeCache::initialize_heaps() {
uint min_code_cache_size = CodeCacheMinimumUseSpace DEBUG_ONLY(* 3);
if (non_nmethod_size < (min_code_cache_size + code_buffers_size)) {
vm_exit_during_initialization(err_msg(
- "Not enough space in non-nmethod code heap to run VM: %zuK < %zuK",
+ "Not enough space in non-nmethod code heap to run VM: " SIZE_FORMAT "K < " SIZE_FORMAT "K",
non_nmethod_size/K, (min_code_cache_size + code_buffers_size)/K));
}
diff --git a/hotspot/src/share/vm/code/compiledMethod.hpp b/hotspot/src/share/vm/code/compiledMethod.hpp
index 863e8cfa610..f260835384a 100644
--- a/hotspot/src/share/vm/code/compiledMethod.hpp
+++ b/hotspot/src/share/vm/code/compiledMethod.hpp
@@ -250,7 +250,11 @@ public:
address insts_begin() const { return code_begin(); }
address insts_end() const { return stub_begin(); }
+ // Returns true if a given address is in the 'insts' section. The method
+ // insts_contains_inclusive() is end-inclusive.
bool insts_contains(address addr) const { return insts_begin() <= addr && addr < insts_end(); }
+ bool insts_contains_inclusive(address addr) const { return insts_begin() <= addr && addr <= insts_end(); }
+
int insts_size() const { return insts_end() - insts_begin(); }
virtual address consts_begin() const = 0;
diff --git a/hotspot/src/share/vm/compiler/compilerDefinitions.cpp b/hotspot/src/share/vm/compiler/compilerDefinitions.cpp
index a0d379773eb..00c2e64f851 100644
--- a/hotspot/src/share/vm/compiler/compilerDefinitions.cpp
+++ b/hotspot/src/share/vm/compiler/compilerDefinitions.cpp
@@ -23,6 +23,8 @@
*/
#include "precompiled.hpp"
+#include "runtime/globals.hpp"
+#include "runtime/globals_extension.hpp"
#include "compiler/compilerDefinitions.hpp"
const char* compilertype2name_tab[compiler_number_of_types] = {
@@ -32,3 +34,82 @@ const char* compilertype2name_tab[compiler_number_of_types] = {
"jvmci",
"shark"
};
+
+#if defined(COMPILER2) || defined(SHARK)
+CompLevel CompLevel_highest_tier = CompLevel_full_optimization; // pure C2 and tiered or JVMCI and tiered
+#elif defined(COMPILER1)
+CompLevel CompLevel_highest_tier = CompLevel_simple; // pure C1 or JVMCI
+#else
+CompLevel CompLevel_highest_tier = CompLevel_none;
+#endif
+
+#if defined(TIERED)
+CompLevel CompLevel_initial_compile = CompLevel_full_profile; // tiered
+#elif defined(COMPILER1) || INCLUDE_JVMCI
+CompLevel CompLevel_initial_compile = CompLevel_simple; // pure C1 or JVMCI
+#elif defined(COMPILER2) || defined(SHARK)
+CompLevel CompLevel_initial_compile = CompLevel_full_optimization; // pure C2
+#else
+CompLevel CompLevel_initial_compile = CompLevel_none;
+#endif
+
+#if defined(COMPILER2)
+CompMode Compilation_mode = CompMode_server;
+#elif defined(COMPILER1)
+CompMode Compilation_mode = CompMode_client;
+#else
+CompMode Compilation_mode = CompMode_none;
+#endif
+
+#ifdef TIERED
+void set_client_compilation_mode() {
+ Compilation_mode = CompMode_client;
+ CompLevel_highest_tier = CompLevel_simple;
+ CompLevel_initial_compile = CompLevel_simple;
+ FLAG_SET_ERGO(bool, TieredCompilation, false);
+ FLAG_SET_ERGO(bool, ProfileInterpreter, false);
+#if INCLUDE_JVMCI
+ FLAG_SET_ERGO(bool, EnableJVMCI, false);
+ FLAG_SET_ERGO(bool, UseJVMCICompiler, false);
+#endif
+#if INCLUDE_AOT
+ FLAG_SET_ERGO(bool, UseAOT, false);
+#endif
+ if (FLAG_IS_DEFAULT(NeverActAsServerClassMachine)) {
+ FLAG_SET_ERGO(bool, NeverActAsServerClassMachine, true);
+ }
+ if (FLAG_IS_DEFAULT(InitialCodeCacheSize)) {
+ FLAG_SET_ERGO(uintx, InitialCodeCacheSize, 160*K);
+ }
+ if (FLAG_IS_DEFAULT(ReservedCodeCacheSize)) {
+ FLAG_SET_ERGO(uintx, ReservedCodeCacheSize, 32*M);
+ }
+ if (FLAG_IS_DEFAULT(NonProfiledCodeHeapSize)) {
+ FLAG_SET_ERGO(uintx, NonProfiledCodeHeapSize, 27*M);
+ }
+ if (FLAG_IS_DEFAULT(ProfiledCodeHeapSize)) {
+ FLAG_SET_ERGO(uintx, ProfiledCodeHeapSize, 0);
+ }
+ if (FLAG_IS_DEFAULT(NonNMethodCodeHeapSize)) {
+ FLAG_SET_ERGO(uintx, NonNMethodCodeHeapSize, 5*M);
+ }
+ if (FLAG_IS_DEFAULT(CodeCacheExpansionSize)) {
+ FLAG_SET_ERGO(uintx, CodeCacheExpansionSize, 32*K);
+ }
+ if (FLAG_IS_DEFAULT(MetaspaceSize)) {
+ FLAG_SET_ERGO(size_t, MetaspaceSize, 12*M);
+ }
+ if (FLAG_IS_DEFAULT(MaxRAM)) {
+ FLAG_SET_ERGO(uint64_t, MaxRAM, 1ULL*G);
+ }
+ if (FLAG_IS_DEFAULT(CompileThreshold)) {
+ FLAG_SET_ERGO(intx, CompileThreshold, 1500);
+ }
+ if (FLAG_IS_DEFAULT(OnStackReplacePercentage)) {
+ FLAG_SET_ERGO(intx, OnStackReplacePercentage, 933);
+ }
+ if (FLAG_IS_DEFAULT(CICompilerCount)) {
+ FLAG_SET_ERGO(intx, CICompilerCount, 1);
+ }
+}
+#endif // TIERED
diff --git a/hotspot/src/share/vm/compiler/compilerDefinitions.hpp b/hotspot/src/share/vm/compiler/compilerDefinitions.hpp
index 9a08a97b303..a2378ea1e92 100644
--- a/hotspot/src/share/vm/compiler/compilerDefinitions.hpp
+++ b/hotspot/src/share/vm/compiler/compilerDefinitions.hpp
@@ -54,27 +54,30 @@ enum CompLevel {
CompLevel_simple = 1, // C1
CompLevel_limited_profile = 2, // C1, invocation & backedge counters
CompLevel_full_profile = 3, // C1, invocation & backedge counters + mdo
- CompLevel_full_optimization = 4, // C2, Shark or JVMCI
-
-#if defined(COMPILER2) || defined(SHARK)
- CompLevel_highest_tier = CompLevel_full_optimization, // pure C2 and tiered or JVMCI and tiered
-#elif defined(COMPILER1)
- CompLevel_highest_tier = CompLevel_simple, // pure C1 or JVMCI
-#else
- CompLevel_highest_tier = CompLevel_none,
-#endif
-
-#if defined(TIERED)
- CompLevel_initial_compile = CompLevel_full_profile // tiered
-#elif defined(COMPILER1) || INCLUDE_JVMCI
- CompLevel_initial_compile = CompLevel_simple // pure C1 or JVMCI
-#elif defined(COMPILER2) || defined(SHARK)
- CompLevel_initial_compile = CompLevel_full_optimization // pure C2
-#else
- CompLevel_initial_compile = CompLevel_none
-#endif
+ CompLevel_full_optimization = 4 // C2, Shark or JVMCI
};
+extern CompLevel CompLevel_highest_tier;
+extern CompLevel CompLevel_initial_compile;
+
+enum CompMode {
+ CompMode_none = 0,
+ CompMode_client = 1,
+ CompMode_server = 2
+};
+
+extern CompMode Compilation_mode;
+
+inline bool is_server_compilation_mode_vm() {
+ return Compilation_mode == CompMode_server;
+}
+
+inline bool is_client_compilation_mode_vm() {
+ return Compilation_mode == CompMode_client;
+}
+
+extern void set_client_compilation_mode();
+
inline bool is_c1_compile(int comp_level) {
return comp_level > CompLevel_none && comp_level < CompLevel_full_optimization;
}
diff --git a/hotspot/src/share/vm/compiler/compilerDirectives.cpp b/hotspot/src/share/vm/compiler/compilerDirectives.cpp
index ed224cea90f..4388f348e92 100644
--- a/hotspot/src/share/vm/compiler/compilerDirectives.cpp
+++ b/hotspot/src/share/vm/compiler/compilerDirectives.cpp
@@ -445,7 +445,9 @@ void DirectivesStack::init() {
_default_directives->_c1_store->EnableOption = true;
#endif
#ifdef COMPILER2
- _default_directives->_c2_store->EnableOption = true;
+ if (is_server_compilation_mode_vm()) {
+ _default_directives->_c2_store->EnableOption = true;
+ }
#endif
assert(error_msg == NULL, "Must succeed.");
push(_default_directives);
diff --git a/hotspot/src/share/vm/compiler/compilerDirectives.hpp b/hotspot/src/share/vm/compiler/compilerDirectives.hpp
index 283fd48127e..7c4efa650a5 100644
--- a/hotspot/src/share/vm/compiler/compilerDirectives.hpp
+++ b/hotspot/src/share/vm/compiler/compilerDirectives.hpp
@@ -60,13 +60,12 @@
cflags(BlockLayoutByFrequency, bool, BlockLayoutByFrequency, BlockLayoutByFrequency) \
cflags(PrintOptoAssembly, bool, PrintOptoAssembly, PrintOptoAssembly) \
cflags(PrintIntrinsics, bool, PrintIntrinsics, PrintIntrinsics) \
- cflags(TraceOptoPipelining, bool, false, TraceOptoPipelining) \
- cflags(TraceOptoOutput, bool, false, TraceOptoOutput) \
+NOT_PRODUCT(cflags(TraceOptoPipelining, bool, TraceOptoPipelining, TraceOptoPipelining)) \
+NOT_PRODUCT(cflags(TraceOptoOutput, bool, TraceOptoOutput, TraceOptoOutput)) \
cflags(TraceSpilling, bool, TraceSpilling, TraceSpilling) \
cflags(Vectorize, bool, false, Vectorize) \
cflags(VectorizeDebug, uintx, 0, VectorizeDebug) \
cflags(CloneMapDebug, bool, false, CloneMapDebug) \
- cflags(DoReserveCopyInSuperWordDebug, bool, false, DoReserveCopyInSuperWordDebug) \
cflags(IGVPrintLevel, intx, PrintIdealGraphLevel, IGVPrintLevel) \
cflags(MaxNodeLimit, intx, MaxNodeLimit, MaxNodeLimit)
#else
diff --git a/hotspot/src/share/vm/gc/g1/g1BiasedArray.hpp b/hotspot/src/share/vm/gc/g1/g1BiasedArray.hpp
index 42069703b27..93b07b21e2d 100644
--- a/hotspot/src/share/vm/gc/g1/g1BiasedArray.hpp
+++ b/hotspot/src/share/vm/gc/g1/g1BiasedArray.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -69,12 +69,12 @@ protected:
void initialize(HeapWord* bottom, HeapWord* end, size_t target_elem_size_in_bytes, size_t mapping_granularity_in_bytes) {
assert(mapping_granularity_in_bytes > 0, "just checking");
assert(is_power_of_2(mapping_granularity_in_bytes),
- "mapping granularity must be power of 2, is %zd", mapping_granularity_in_bytes);
+ "mapping granularity must be power of 2, is " SIZE_FORMAT, mapping_granularity_in_bytes);
assert((uintptr_t)bottom % mapping_granularity_in_bytes == 0,
- "bottom mapping area address must be a multiple of mapping granularity %zd, is " PTR_FORMAT,
+ "bottom mapping area address must be a multiple of mapping granularity " SIZE_FORMAT ", is " PTR_FORMAT,
mapping_granularity_in_bytes, p2i(bottom));
assert((uintptr_t)end % mapping_granularity_in_bytes == 0,
- "end mapping area address must be a multiple of mapping granularity %zd, is " PTR_FORMAT,
+ "end mapping area address must be a multiple of mapping granularity " SIZE_FORMAT ", is " PTR_FORMAT,
mapping_granularity_in_bytes, p2i(end));
size_t num_target_elems = pointer_delta(end, bottom, mapping_granularity_in_bytes);
idx_t bias = (uintptr_t)bottom / mapping_granularity_in_bytes;
diff --git a/hotspot/src/share/vm/gc/shared/collectedHeap.cpp b/hotspot/src/share/vm/gc/shared/collectedHeap.cpp
index 4f2c46913db..737c57c117d 100644
--- a/hotspot/src/share/vm/gc/shared/collectedHeap.cpp
+++ b/hotspot/src/share/vm/gc/shared/collectedHeap.cpp
@@ -233,7 +233,7 @@ void CollectedHeap::pre_initialize() {
// Used for ReduceInitialCardMarks (when COMPILER2 is used);
// otherwise remains unused.
#if defined(COMPILER2) || INCLUDE_JVMCI
- _defer_initial_card_mark = ReduceInitialCardMarks && can_elide_tlab_store_barriers()
+ _defer_initial_card_mark = is_server_compilation_mode_vm() && ReduceInitialCardMarks && can_elide_tlab_store_barriers()
&& (DeferInitialCardMark || card_mark_must_follow_store());
#else
assert(_defer_initial_card_mark == false, "Who would set it?");
diff --git a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp
index 5248654f2f7..0119e115104 100644
--- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp
+++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp
@@ -1209,7 +1209,7 @@ void GenCollectedHeap::gc_epilogue(bool full) {
#if defined(COMPILER2) || INCLUDE_JVMCI
assert(DerivedPointerTable::is_empty(), "derived pointer present");
size_t actual_gap = pointer_delta((HeapWord*) (max_uintx-3), *(end_addr()));
- guarantee(actual_gap > (size_t)FastAllocateSizeLimit, "inline allocation wraps");
+ guarantee(is_client_compilation_mode_vm() || actual_gap > (size_t)FastAllocateSizeLimit, "inline allocation wraps");
#endif /* COMPILER2 || INCLUDE_JVMCI */
resize_all_tlabs();
diff --git a/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp b/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp
index 38df96ddd4c..5d6d160a4ee 100644
--- a/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp
+++ b/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp
@@ -57,11 +57,11 @@ void ReferenceProcessor::init_statics() {
java_lang_ref_SoftReference::set_clock(_soft_ref_timestamp_clock);
_always_clear_soft_ref_policy = new AlwaysClearPolicy();
-#if defined(COMPILER2) || INCLUDE_JVMCI
- _default_soft_ref_policy = new LRUMaxHeapPolicy();
-#else
- _default_soft_ref_policy = new LRUCurrentHeapPolicy();
-#endif
+ if (is_server_compilation_mode_vm()) {
+ _default_soft_ref_policy = new LRUMaxHeapPolicy();
+ } else {
+ _default_soft_ref_policy = new LRUCurrentHeapPolicy();
+ }
if (_always_clear_soft_ref_policy == NULL || _default_soft_ref_policy == NULL) {
vm_exit_during_initialization("Could not allocate reference policy object");
}
diff --git a/hotspot/src/share/vm/gc/shared/threadLocalAllocBuffer.cpp b/hotspot/src/share/vm/gc/shared/threadLocalAllocBuffer.cpp
index 0df1ba020a2..b004ba58c89 100644
--- a/hotspot/src/share/vm/gc/shared/threadLocalAllocBuffer.cpp
+++ b/hotspot/src/share/vm/gc/shared/threadLocalAllocBuffer.cpp
@@ -233,9 +233,11 @@ void ThreadLocalAllocBuffer::startup_initialization() {
// If the C2 compiler is not present, no space is reserved.
// +1 for rounding up to next cache line, +1 to be safe
- int lines = MAX2(AllocatePrefetchLines, AllocateInstancePrefetchLines) + 2;
- _reserve_for_allocation_prefetch = (AllocatePrefetchDistance + AllocatePrefetchStepSize * lines) /
- (int)HeapWordSize;
+ if (is_server_compilation_mode_vm()) {
+ int lines = MAX2(AllocatePrefetchLines, AllocateInstancePrefetchLines) + 2;
+ _reserve_for_allocation_prefetch = (AllocatePrefetchDistance + AllocatePrefetchStepSize * lines) /
+ (int)HeapWordSize;
+ }
#endif
// During jvm startup, the main (primordial) thread is initialized
diff --git a/hotspot/src/share/vm/interpreter/bytecode.cpp b/hotspot/src/share/vm/interpreter/bytecode.cpp
index 80b95d627b5..6cc38a5a0cd 100644
--- a/hotspot/src/share/vm/interpreter/bytecode.cpp
+++ b/hotspot/src/share/vm/interpreter/bytecode.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, 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
@@ -112,7 +112,7 @@ void Bytecode::assert_native_index(Bytecodes::Code bc, bool is_wide) {
// Implementation of Bytecode_tableupswitch
int Bytecode_tableswitch::dest_offset_at(int i) const {
- return get_Java_u4_at(aligned_offset(1 + (3 + i)*jintSize));
+ return get_aligned_Java_u4_at(1 + (3 + i)*jintSize);
}
diff --git a/hotspot/src/share/vm/interpreter/bytecode.hpp b/hotspot/src/share/vm/interpreter/bytecode.hpp
index f3fc9ea9d6a..5c53ab4121f 100644
--- a/hotspot/src/share/vm/interpreter/bytecode.hpp
+++ b/hotspot/src/share/vm/interpreter/bytecode.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, 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
@@ -45,11 +45,11 @@ class Bytecode: public StackObj {
address addr_at (int offset) const { return (address)_bcp + offset; }
u_char byte_at(int offset) const { return *addr_at(offset); }
address aligned_addr_at (int offset) const { return (address)round_to((intptr_t)addr_at(offset), jintSize); }
- int aligned_offset (int offset) const { return aligned_addr_at(offset) - addr_at(0); }
// Word access:
int get_Java_u2_at (int offset) const { return Bytes::get_Java_u2(addr_at(offset)); }
int get_Java_u4_at (int offset) const { return Bytes::get_Java_u4(addr_at(offset)); }
+ int get_aligned_Java_u4_at(int offset) const { return Bytes::get_Java_u4(aligned_addr_at(offset)); }
int get_native_u2_at (int offset) const { return Bytes::get_native_u2(addr_at(offset)); }
int get_native_u4_at (int offset) const { return Bytes::get_native_u4(addr_at(offset)); }
@@ -150,8 +150,8 @@ class Bytecode_lookupswitch: public Bytecode {
void verify() const PRODUCT_RETURN;
// Attributes
- int default_offset() const { return get_Java_u4_at(aligned_offset(1 + 0*jintSize)); }
- int number_of_pairs() const { return get_Java_u4_at(aligned_offset(1 + 1*jintSize)); }
+ int default_offset() const { return get_aligned_Java_u4_at(1 + 0*jintSize); }
+ int number_of_pairs() const { return get_aligned_Java_u4_at(1 + 1*jintSize); }
LookupswitchPair pair_at(int i) const {
assert(0 <= i && i < number_of_pairs(), "pair index out of bounds");
return LookupswitchPair(aligned_addr_at(1 + (1 + i)*2*jintSize));
@@ -166,9 +166,9 @@ class Bytecode_tableswitch: public Bytecode {
void verify() const PRODUCT_RETURN;
// Attributes
- int default_offset() const { return get_Java_u4_at(aligned_offset(1 + 0*jintSize)); }
- int low_key() const { return get_Java_u4_at(aligned_offset(1 + 1*jintSize)); }
- int high_key() const { return get_Java_u4_at(aligned_offset(1 + 2*jintSize)); }
+ int default_offset() const { return get_aligned_Java_u4_at(1 + 0*jintSize); }
+ int low_key() const { return get_aligned_Java_u4_at(1 + 1*jintSize); }
+ int high_key() const { return get_aligned_Java_u4_at(1 + 2*jintSize); }
int dest_offset_at(int i) const;
int length() { return high_key()-low_key()+1; }
};
diff --git a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp
index 745fb5199ec..cca40f1aeb2 100644
--- a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp
+++ b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp
@@ -554,7 +554,7 @@ JVMCIEnv::CodeInstallResult CodeInstaller::gather_metadata(Handle target, Handle
_constants = buffer.consts();
initialize_fields(target(), JNIHandles::resolve(compiled_code_obj), CHECK_OK);
- JVMCIEnv::CodeInstallResult result = initialize_buffer(buffer, CHECK_OK);
+ JVMCIEnv::CodeInstallResult result = initialize_buffer(buffer, false, CHECK_OK);
if (result != JVMCIEnv::ok) {
return result;
}
@@ -587,7 +587,7 @@ JVMCIEnv::CodeInstallResult CodeInstaller::install(JVMCICompiler* compiler, Hand
_constants = buffer.consts();
initialize_fields(target(), JNIHandles::resolve(compiled_code_obj), CHECK_OK);
- JVMCIEnv::CodeInstallResult result = initialize_buffer(buffer, CHECK_OK);
+ JVMCIEnv::CodeInstallResult result = initialize_buffer(buffer, true, CHECK_OK);
if (result != JVMCIEnv::ok) {
return result;
}
@@ -726,7 +726,7 @@ int CodeInstaller::estimate_stubs_size(TRAPS) {
}
// perform data and call relocation on the CodeBuffer
-JVMCIEnv::CodeInstallResult CodeInstaller::initialize_buffer(CodeBuffer& buffer, TRAPS) {
+JVMCIEnv::CodeInstallResult CodeInstaller::initialize_buffer(CodeBuffer& buffer, bool check_size, TRAPS) {
HandleMark hm;
objArrayHandle sites = this->sites();
int locs_buffer_size = sites->length() * (relocInfo::length_limit + sizeof(relocInfo));
@@ -738,7 +738,7 @@ JVMCIEnv::CodeInstallResult CodeInstaller::initialize_buffer(CodeBuffer& buffer,
int stubs_size = estimate_stubs_size(CHECK_OK);
int total_size = round_to(_code_size, buffer.insts()->alignment()) + round_to(_constants_size, buffer.consts()->alignment()) + round_to(stubs_size, buffer.stubs()->alignment());
- if (total_size > JVMCINMethodSizeLimit) {
+ if (check_size && total_size > JVMCINMethodSizeLimit) {
return JVMCIEnv::code_too_large;
}
@@ -1258,6 +1258,7 @@ void CodeInstaller::site_Mark(CodeBuffer& buffer, jint pc_offset, Handle site, T
case HEAP_TOP_ADDRESS:
case HEAP_END_ADDRESS:
case NARROW_KLASS_BASE_ADDRESS:
+ case NARROW_OOP_BASE_ADDRESS:
case CRC_TABLE_ADDRESS:
case LOG_OF_HEAP_REGION_GRAIN_BYTES:
case INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED:
diff --git a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.hpp b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.hpp
index 775a8c19f40..a700174de1d 100644
--- a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.hpp
+++ b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.hpp
@@ -133,9 +133,10 @@ private:
HEAP_TOP_ADDRESS = 17,
HEAP_END_ADDRESS = 18,
NARROW_KLASS_BASE_ADDRESS = 19,
- CRC_TABLE_ADDRESS = 20,
- LOG_OF_HEAP_REGION_GRAIN_BYTES = 21,
- INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED = 22,
+ NARROW_OOP_BASE_ADDRESS = 20,
+ CRC_TABLE_ADDRESS = 21,
+ LOG_OF_HEAP_REGION_GRAIN_BYTES = 22,
+ INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED = 23,
INVOKE_INVALID = -1
};
@@ -227,7 +228,7 @@ protected:
int estimate_stubs_size(TRAPS);
// perform data and call relocation on the CodeBuffer
- JVMCIEnv::CodeInstallResult initialize_buffer(CodeBuffer& buffer, TRAPS);
+ JVMCIEnv::CodeInstallResult initialize_buffer(CodeBuffer& buffer, bool check_size, TRAPS);
void assumption_NoFinalizableSubclass(Handle assumption);
void assumption_ConcreteSubtype(Handle assumption);
diff --git a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp
index f7eb56ff404..2fe6b45b79e 100644
--- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp
+++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp
@@ -591,12 +591,16 @@ C2V_VMENTRY(jboolean, methodIsIgnoredBySecurityStackWalk,(JNIEnv *, jobject, job
return method->is_ignored_by_security_stack_walk();
C2V_END
-C2V_VMENTRY(jboolean, canInlineMethod,(JNIEnv *, jobject, jobject jvmci_method))
+C2V_VMENTRY(jboolean, isCompilable,(JNIEnv *, jobject, jobject jvmci_method))
methodHandle method = CompilerToVM::asMethod(jvmci_method);
- // In hosted mode ignore the not_compilable flags since they are never set by
+ // Ignore the not_compilable flags in hosted mode since they are never set by
// the JVMCI compiler.
- bool is_compilable = UseJVMCICompiler ? !method->is_not_compilable(CompLevel_full_optimization) : true;
- return is_compilable && !CompilerOracle::should_not_inline(method) && !method->dont_inline();
+ return UseJVMCICompiler || !method->is_not_compilable(CompLevel_full_optimization);
+C2V_END
+
+C2V_VMENTRY(jboolean, hasNeverInlineDirective,(JNIEnv *, jobject, jobject jvmci_method))
+ methodHandle method = CompilerToVM::asMethod(jvmci_method);
+ return CompilerOracle::should_not_inline(method) || method->dont_inline();
C2V_END
C2V_VMENTRY(jboolean, shouldInlineMethod,(JNIEnv *, jobject, jobject jvmci_method))
@@ -1591,7 +1595,8 @@ JNINativeMethod CompilerToVM::methods[] = {
{CC "getStackTraceElement", CC "(" HS_RESOLVED_METHOD "I)" STACK_TRACE_ELEMENT, FN_PTR(getStackTraceElement)},
{CC "methodIsIgnoredBySecurityStackWalk", CC "(" HS_RESOLVED_METHOD ")Z", FN_PTR(methodIsIgnoredBySecurityStackWalk)},
{CC "doNotInlineOrCompile", CC "(" HS_RESOLVED_METHOD ")V", FN_PTR(doNotInlineOrCompile)},
- {CC "canInlineMethod", CC "(" HS_RESOLVED_METHOD ")Z", FN_PTR(canInlineMethod)},
+ {CC "isCompilable", CC "(" HS_RESOLVED_METHOD ")Z", FN_PTR(isCompilable)},
+ {CC "hasNeverInlineDirective", CC "(" HS_RESOLVED_METHOD ")Z", FN_PTR(hasNeverInlineDirective)},
{CC "shouldInlineMethod", CC "(" HS_RESOLVED_METHOD ")Z", FN_PTR(shouldInlineMethod)},
{CC "lookupType", CC "(" STRING CLASS "Z)" HS_RESOLVED_KLASS, FN_PTR(lookupType)},
{CC "lookupNameInPool", CC "(" HS_CONSTANT_POOL "I)" STRING, FN_PTR(lookupNameInPool)},
diff --git a/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp
index 2dad27fdfd9..a01651f55aa 100644
--- a/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp
+++ b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp
@@ -429,6 +429,7 @@
declare_constant(CodeInstaller::HEAP_TOP_ADDRESS) \
declare_constant(CodeInstaller::HEAP_END_ADDRESS) \
declare_constant(CodeInstaller::NARROW_KLASS_BASE_ADDRESS) \
+ declare_constant(CodeInstaller::NARROW_OOP_BASE_ADDRESS) \
declare_constant(CodeInstaller::CRC_TABLE_ADDRESS) \
declare_constant(CodeInstaller::LOG_OF_HEAP_REGION_GRAIN_BYTES) \
declare_constant(CodeInstaller::INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED) \
@@ -534,7 +535,6 @@
\
declare_constant(markOopDesc::no_hash) \
\
- declare_constant(Method::_jfr_towrite) \
declare_constant(Method::_caller_sensitive) \
declare_constant(Method::_force_inline) \
declare_constant(Method::_dont_inline) \
diff --git a/hotspot/src/share/vm/logging/logConfiguration.cpp b/hotspot/src/share/vm/logging/logConfiguration.cpp
index b8a5932ba0e..9b77b220e70 100644
--- a/hotspot/src/share/vm/logging/logConfiguration.cpp
+++ b/hotspot/src/share/vm/logging/logConfiguration.cpp
@@ -478,7 +478,7 @@ void LogConfiguration::describe(outputStream* out) {
void LogConfiguration::print_command_line_help(FILE* out) {
jio_fprintf(out, "-Xlog Usage: -Xlog[:[what][:[output][:[decorators][:output-options]]]]\n"
- "\t where 'what' is a combination of tags and levels on the form tag1[+tag2...][*][=level][,...]\n"
+ "\t where 'what' is a combination of tags and levels of the form tag1[+tag2...][*][=level][,...]\n"
"\t Unless wildcard (*) is specified, only log messages tagged with exactly the tags specified will be matched.\n\n");
jio_fprintf(out, "Available log levels:\n");
@@ -514,6 +514,14 @@ void LogConfiguration::print_command_line_help(FILE* out) {
" -Xlog:gc\n"
"\t Log messages tagged with 'gc' tag using 'info' level to stdout, with default decorations.\n\n"
+ " -Xlog:gc,safepoint\n"
+ "\t Log messages tagged either with 'gc' or 'safepoint' tags, both using 'info' level, to stdout, with default decorations.\n"
+ "\t (Messages tagged with both 'gc' and 'safepoint' will not be logged.)\n\n"
+
+ " -Xlog:gc+ref=debug\n"
+ "\t Log messages tagged with both 'gc' and 'ref' tags, using 'debug' level, to stdout, with default decorations.\n"
+ "\t (Messages tagged only with one of the two tags will not be logged.)\n\n"
+
" -Xlog:gc=debug:file=gc.txt:none\n"
"\t Log messages tagged with 'gc' tag using 'debug' level to file 'gc.txt' with no decorations.\n\n"
diff --git a/hotspot/src/share/vm/memory/metaspaceShared.cpp b/hotspot/src/share/vm/memory/metaspaceShared.cpp
index 61d6fa37b41..446517fd426 100644
--- a/hotspot/src/share/vm/memory/metaspaceShared.cpp
+++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp
@@ -145,10 +145,6 @@ void MetaspaceShared::serialize(SerializeClosure* soc, GrowableArray
StringTable::serialize(soc, string_space, space_size);
soc->do_tag(--tag);
- // Dump/restore the misc information for system dictionary
- SystemDictionaryShared::serialize(soc);
- soc->do_tag(--tag);
-
soc->do_tag(666);
}
diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp
index 5b2180f945c..41f5fd143a8 100644
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp
+++ b/hotspot/src/share/vm/oops/instanceKlass.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
@@ -2139,8 +2139,6 @@ void InstanceKlass::release_C_heap_structures(InstanceKlass* ik) {
}
void InstanceKlass::release_C_heap_structures() {
- assert(!this->is_shared(), "should not be called for a shared class");
-
// Can't release the constant pool here because the constant pool can be
// deallocated separately from the InstanceKlass for default methods and
// redefine classes.
@@ -2191,7 +2189,7 @@ void InstanceKlass::release_C_heap_structures() {
}
// deallocate the cached class file
- if (_cached_class_file != NULL) {
+ if (_cached_class_file != NULL && !MetaspaceShared::is_in_shared_space(_cached_class_file)) {
os::free(_cached_class_file);
_cached_class_file = NULL;
}
diff --git a/hotspot/src/share/vm/oops/method.cpp b/hotspot/src/share/vm/oops/method.cpp
index 4e3dcf03bd8..f37278edd13 100644
--- a/hotspot/src/share/vm/oops/method.cpp
+++ b/hotspot/src/share/vm/oops/method.cpp
@@ -85,7 +85,6 @@ Method::Method(ConstMethod* xconst, AccessFlags access_flags) {
set_constMethod(xconst);
set_access_flags(access_flags);
set_intrinsic_id(vmIntrinsics::_none);
- set_jfr_towrite(false);
set_force_inline(false);
set_hidden(false);
set_dont_inline(false);
diff --git a/hotspot/src/share/vm/oops/method.hpp b/hotspot/src/share/vm/oops/method.hpp
index 1c6e72df0fc..ebd5f0feef2 100644
--- a/hotspot/src/share/vm/oops/method.hpp
+++ b/hotspot/src/share/vm/oops/method.hpp
@@ -75,18 +75,19 @@ class Method : public Metadata {
// Flags
enum Flags {
- _jfr_towrite = 1 << 0,
- _caller_sensitive = 1 << 1,
- _force_inline = 1 << 2,
- _dont_inline = 1 << 3,
- _hidden = 1 << 4,
- _has_injected_profile = 1 << 5,
- _running_emcp = 1 << 6,
- _intrinsic_candidate = 1 << 7,
- _reserved_stack_access = 1 << 8
+ _caller_sensitive = 1 << 0,
+ _force_inline = 1 << 1,
+ _dont_inline = 1 << 2,
+ _hidden = 1 << 3,
+ _has_injected_profile = 1 << 4,
+ _running_emcp = 1 << 5,
+ _intrinsic_candidate = 1 << 6,
+ _reserved_stack_access = 1 << 7
};
mutable u2 _flags;
+ TRACE_DEFINE_FLAG;
+
#ifndef PRODUCT
int _compiled_invocation_count; // Number of nmethod invocations so far (for perf. debugging)
#endif
@@ -833,13 +834,6 @@ class Method : public Metadata {
void init_intrinsic_id(); // updates from _none if a match
static vmSymbols::SID klass_id_for_intrinsics(const Klass* holder);
- bool jfr_towrite() const {
- return (_flags & _jfr_towrite) != 0;
- }
- void set_jfr_towrite(bool x) const {
- _flags = x ? (_flags | _jfr_towrite) : (_flags & ~_jfr_towrite);
- }
-
bool caller_sensitive() {
return (_flags & _caller_sensitive) != 0;
}
@@ -890,6 +884,8 @@ class Method : public Metadata {
_flags = x ? (_flags | _reserved_stack_access) : (_flags & ~_reserved_stack_access);
}
+ TRACE_DEFINE_FLAG_ACCESSOR;
+
ConstMethod::MethodType method_type() const {
return _constMethod->method_type();
}
diff --git a/hotspot/src/share/vm/oops/methodData.cpp b/hotspot/src/share/vm/oops/methodData.cpp
index 85f7c9b6098..a99000aabcf 100644
--- a/hotspot/src/share/vm/oops/methodData.cpp
+++ b/hotspot/src/share/vm/oops/methodData.cpp
@@ -717,9 +717,9 @@ MethodData* MethodData::allocate(ClassLoaderData* loader_data, const methodHandl
}
int MethodData::bytecode_cell_count(Bytecodes::Code code) {
-#if defined(COMPILER1) && !(defined(COMPILER2) || INCLUDE_JVMCI)
- return no_profile_data;
-#else
+ if (is_client_compilation_mode_vm()) {
+ return no_profile_data;
+ }
switch (code) {
case Bytecodes::_checkcast:
case Bytecodes::_instanceof:
@@ -778,7 +778,6 @@ int MethodData::bytecode_cell_count(Bytecodes::Code code) {
return variable_cell_count;
}
return no_profile_data;
-#endif
}
// Compute the size of the profiling information corresponding to
@@ -840,7 +839,9 @@ bool MethodData::is_speculative_trap_bytecode(Bytecodes::Code code) {
case Bytecodes::_ifnonnull:
case Bytecodes::_invokestatic:
#ifdef COMPILER2
- return UseTypeSpeculation;
+ if (is_server_compilation_mode_vm()) {
+ return UseTypeSpeculation;
+ }
#endif
default:
return false;
@@ -942,9 +943,9 @@ int MethodData::compute_allocation_size_in_words(const methodHandle& method) {
// the segment in bytes.
int MethodData::initialize_data(BytecodeStream* stream,
int data_index) {
-#if defined(COMPILER1) && !(defined(COMPILER2) || INCLUDE_JVMCI)
- return 0;
-#else
+ if (is_client_compilation_mode_vm()) {
+ return 0;
+ }
int cell_count = -1;
int tag = DataLayout::no_tag;
DataLayout* data_layout = data_layout_at(data_index);
@@ -1061,7 +1062,6 @@ int MethodData::initialize_data(BytecodeStream* stream,
assert(!bytecode_has_profile(c), "agree w/ !BHP");
return 0;
}
-#endif
}
// Get the data at an arbitrary (sort of) data index.
diff --git a/hotspot/src/share/vm/oops/methodData.hpp b/hotspot/src/share/vm/oops/methodData.hpp
index a85b64e8801..627fba527e2 100644
--- a/hotspot/src/share/vm/oops/methodData.hpp
+++ b/hotspot/src/share/vm/oops/methodData.hpp
@@ -2183,7 +2183,7 @@ private:
uint _nof_overflow_traps; // trap count, excluding _trap_hist
union {
intptr_t _align;
- u1 _array[_trap_hist_limit];
+ u1 _array[JVMCI_ONLY(2 *) _trap_hist_limit];
} _trap_hist;
// Support for interprocedural escape analysis, from Thomas Kotzmann.
diff --git a/hotspot/src/share/vm/opto/cfgnode.cpp b/hotspot/src/share/vm/opto/cfgnode.cpp
index 47606b6a599..de85b1cb155 100644
--- a/hotspot/src/share/vm/opto/cfgnode.cpp
+++ b/hotspot/src/share/vm/opto/cfgnode.cpp
@@ -2097,6 +2097,7 @@ const RegMask &PhiNode::out_RegMask() const {
uint ideal_reg = _type->ideal_reg();
assert( ideal_reg != Node::NotAMachineReg, "invalid type at Phi" );
if( ideal_reg == 0 ) return RegMask::Empty;
+ assert(ideal_reg != Op_RegFlags, "flags register is not spillable");
return *(Compile::current()->matcher()->idealreg2spillmask[ideal_reg]);
}
diff --git a/hotspot/src/share/vm/opto/coalesce.cpp b/hotspot/src/share/vm/opto/coalesce.cpp
index 1e8af4e27ee..fb45d92df42 100644
--- a/hotspot/src/share/vm/opto/coalesce.cpp
+++ b/hotspot/src/share/vm/opto/coalesce.cpp
@@ -292,7 +292,14 @@ void PhaseAggressiveCoalesce::insert_copies( Matcher &matcher ) {
// Copy any flags as well
_phc.clone_projs(pred, pred->end_idx(), m, copy, _phc._lrg_map);
} else {
- const RegMask *rm = C->matcher()->idealreg2spillmask[m->ideal_reg()];
+ int ireg = m->ideal_reg();
+ if (ireg == 0 || ireg == Op_RegFlags) {
+ assert(false, "attempted to spill a non-spillable item: %d: %s, ireg = %d, spill_type: %s",
+ m->_idx, m->Name(), ireg, MachSpillCopyNode::spill_type(MachSpillCopyNode::PhiInput));
+ C->record_method_not_compilable("attempted to spill a non-spillable item");
+ return;
+ }
+ const RegMask *rm = C->matcher()->idealreg2spillmask[ireg];
copy = new MachSpillCopyNode(MachSpillCopyNode::PhiInput, m, *rm, *rm);
// Find a good place to insert. Kinda tricky, use a subroutine
insert_copy_with_overlap(pred,copy,phi_name,src_name);
@@ -326,7 +333,14 @@ void PhaseAggressiveCoalesce::insert_copies( Matcher &matcher ) {
b->insert_node(copy, l++);
l += _phc.clone_projs(b, l, m, copy, _phc._lrg_map);
} else {
- const RegMask *rm = C->matcher()->idealreg2spillmask[m->ideal_reg()];
+ int ireg = m->ideal_reg();
+ if (ireg == 0 || ireg == Op_RegFlags) {
+ assert(false, "attempted to spill a non-spillable item: %d: %s, ireg = %d, spill_type: %s",
+ m->_idx, m->Name(), ireg, MachSpillCopyNode::spill_type(MachSpillCopyNode::TwoAddress));
+ C->record_method_not_compilable("attempted to spill a non-spillable item");
+ return;
+ }
+ const RegMask *rm = C->matcher()->idealreg2spillmask[ireg];
copy = new MachSpillCopyNode(MachSpillCopyNode::TwoAddress, m, *rm, *rm);
// Insert the copy in the basic block, just before us
b->insert_node(copy, l++);
@@ -373,7 +387,14 @@ void PhaseAggressiveCoalesce::insert_copies( Matcher &matcher ) {
if( k < b->_num_succs )
continue; // Live out; do not pre-split
// Split the lrg at this use
- const RegMask *rm = C->matcher()->idealreg2spillmask[inp->ideal_reg()];
+ int ireg = inp->ideal_reg();
+ if (ireg == 0 || ireg == Op_RegFlags) {
+ assert(false, "attempted to spill a non-spillable item: %d: %s, ireg = %d, spill_type: %s",
+ inp->_idx, inp->Name(), ireg, MachSpillCopyNode::spill_type(MachSpillCopyNode::DebugUse));
+ C->record_method_not_compilable("attempted to spill a non-spillable item");
+ return;
+ }
+ const RegMask *rm = C->matcher()->idealreg2spillmask[ireg];
Node* copy = new MachSpillCopyNode(MachSpillCopyNode::DebugUse, inp, *rm, *rm);
// Insert the copy in the use-def chain
n->set_req(inpidx, copy );
diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp
index 77e20b264cb..4c84b0339ec 100644
--- a/hotspot/src/share/vm/opto/compile.cpp
+++ b/hotspot/src/share/vm/opto/compile.cpp
@@ -971,7 +971,7 @@ Compile::Compile( ciEnv* ci_env,
_java_calls(0),
_inner_loops(0),
#ifndef PRODUCT
- _trace_opto_output(TraceOptoOutput),
+ _trace_opto_output(directive->TraceOptoOutputOption),
_in_dump_cnt(0),
_printer(NULL),
#endif
diff --git a/hotspot/src/share/vm/opto/graphKit.cpp b/hotspot/src/share/vm/opto/graphKit.cpp
index c879137d882..1c328b7bb75 100644
--- a/hotspot/src/share/vm/opto/graphKit.cpp
+++ b/hotspot/src/share/vm/opto/graphKit.cpp
@@ -3152,19 +3152,6 @@ Node* GraphKit::insert_mem_bar_volatile(int opcode, int alias_idx, Node* precede
return membar;
}
-void GraphKit::insert_store_load_for_barrier() {
- Node* mem = reset_memory();
- MemBarNode* mb = MemBarNode::make(C, Op_MemBarVolatile, Compile::AliasIdxBot);
- mb->init_req(TypeFunc::Control, control());
- mb->init_req(TypeFunc::Memory, mem);
- Node* membar = _gvn.transform(mb);
- set_control(_gvn.transform(new ProjNode(membar, TypeFunc::Control)));
- Node* newmem = _gvn.transform(new ProjNode(membar, TypeFunc::Memory));
- set_all_memory(mem);
- set_memory(newmem, Compile::AliasIdxRaw);
-}
-
-
//------------------------------shared_lock------------------------------------
// Emit locking code.
FastLockNode* GraphKit::shared_lock(Node* obj) {
@@ -3854,7 +3841,7 @@ void GraphKit::write_barrier_post(Node* oop_store,
BasicType bt = T_BYTE;
if (UseConcMarkSweepGC && UseCondCardMark) {
- insert_store_load_for_barrier();
+ insert_mem_bar(Op_MemBarVolatile); // StoreLoad barrier
__ sync_kit(this);
}
@@ -4294,7 +4281,8 @@ void GraphKit::g1_write_barrier_post(Node* oop_store,
__ if_then(card_val, BoolTest::ne, young_card); {
sync_kit(ideal);
- insert_store_load_for_barrier();
+ // Use Op_MemBarVolatile to achieve the effect of a StoreLoad barrier.
+ insert_mem_bar(Op_MemBarVolatile, oop_store);
__ sync_kit(this);
Node* card_val_reload = __ load(__ ctrl(), card_adr, TypeInt::INT, T_BYTE, Compile::AliasIdxRaw);
@@ -4348,20 +4336,16 @@ Node* GraphKit::load_String_value(Node* ctrl, Node* str) {
}
Node* GraphKit::load_String_coder(Node* ctrl, Node* str) {
- if (java_lang_String::has_coder_field()) {
- if (!CompactStrings) {
- return intcon(java_lang_String::CODER_UTF16);
- }
- int coder_offset = java_lang_String::coder_offset_in_bytes();
- const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
- false, NULL, 0);
- const TypePtr* coder_field_type = string_type->add_offset(coder_offset);
- int coder_field_idx = C->get_alias_index(coder_field_type);
- return make_load(ctrl, basic_plus_adr(str, str, coder_offset),
- TypeInt::BYTE, T_BYTE, coder_field_idx, MemNode::unordered);
- } else {
- return intcon(0); // false
+ if (!CompactStrings) {
+ return intcon(java_lang_String::CODER_UTF16);
}
+ int coder_offset = java_lang_String::coder_offset_in_bytes();
+ const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
+ false, NULL, 0);
+ const TypePtr* coder_field_type = string_type->add_offset(coder_offset);
+ int coder_field_idx = C->get_alias_index(coder_field_type);
+ return make_load(ctrl, basic_plus_adr(str, str, coder_offset),
+ TypeInt::BYTE, T_BYTE, coder_field_idx, MemNode::unordered);
}
void GraphKit::store_String_value(Node* ctrl, Node* str, Node* value) {
diff --git a/hotspot/src/share/vm/opto/graphKit.hpp b/hotspot/src/share/vm/opto/graphKit.hpp
index 6d60539b527..cbae7ce3761 100644
--- a/hotspot/src/share/vm/opto/graphKit.hpp
+++ b/hotspot/src/share/vm/opto/graphKit.hpp
@@ -837,7 +837,6 @@ class GraphKit : public Phase {
int next_monitor();
Node* insert_mem_bar(int opcode, Node* precedent = NULL);
Node* insert_mem_bar_volatile(int opcode, int alias_idx, Node* precedent = NULL);
- void insert_store_load_for_barrier();
// Optional 'precedent' is appended as an extra edge, to force ordering.
FastLockNode* shared_lock(Node* obj);
void shared_unlock(Node* box, Node* obj);
diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp
index c298e318ab5..5d837d6ecb0 100644
--- a/hotspot/src/share/vm/opto/library_call.cpp
+++ b/hotspot/src/share/vm/opto/library_call.cpp
@@ -6335,7 +6335,7 @@ bool LibraryCallKit::inline_counterMode_AESCrypt(vmIntrinsics::ID id) {
//------------------------------get_key_start_from_aescrypt_object-----------------------
Node * LibraryCallKit::get_key_start_from_aescrypt_object(Node *aescrypt_object) {
-#ifdef PPC64
+#if defined(PPC64) || defined(S390)
// MixColumns for decryption can be reduced by preprocessing MixColumns with round keys.
// Intel's extention is based on this optimization and AESCrypt generates round keys by preprocessing MixColumns.
// However, ppc64 vncipher processes MixColumns and requires the same round keys with encryption.
diff --git a/hotspot/src/share/vm/opto/machnode.cpp b/hotspot/src/share/vm/opto/machnode.cpp
index cd0839c3294..07f791d05d1 100644
--- a/hotspot/src/share/vm/opto/machnode.cpp
+++ b/hotspot/src/share/vm/opto/machnode.cpp
@@ -643,6 +643,7 @@ const RegMask &MachSafePointNode::in_RegMask( uint idx ) const {
}
// Values outside the domain represent debug info
+ assert(in(idx)->ideal_reg() != Op_RegFlags, "flags register is not spillable");
return *Compile::current()->matcher()->idealreg2spillmask[in(idx)->ideal_reg()];
}
diff --git a/hotspot/src/share/vm/opto/macro.cpp b/hotspot/src/share/vm/opto/macro.cpp
index 9bae43a4e28..bd0a1b75c9a 100644
--- a/hotspot/src/share/vm/opto/macro.cpp
+++ b/hotspot/src/share/vm/opto/macro.cpp
@@ -426,7 +426,7 @@ static Node *scan_mem_chain(Node *mem, int alias_idx, int offset, Node *start_me
// Generate loads from source of the arraycopy for fields of
// destination needed at a deoptimization point
-Node* PhaseMacroExpand::make_arraycopy_load(ArrayCopyNode* ac, intptr_t offset, Node* ctl, BasicType ft, const Type *ftype, AllocateNode *alloc) {
+Node* PhaseMacroExpand::make_arraycopy_load(ArrayCopyNode* ac, intptr_t offset, Node* ctl, Node* mem, BasicType ft, const Type *ftype, AllocateNode *alloc) {
BasicType bt = ft;
const Type *type = ftype;
if (ft == T_NARROWOOP) {
@@ -438,8 +438,7 @@ Node* PhaseMacroExpand::make_arraycopy_load(ArrayCopyNode* ac, intptr_t offset,
Node* base = ac->in(ArrayCopyNode::Src)->in(AddPNode::Base);
Node* adr = _igvn.transform(new AddPNode(base, base, MakeConX(offset)));
const TypePtr* adr_type = _igvn.type(base)->is_ptr()->add_offset(offset);
- Node* m = ac->in(TypeFunc::Memory);
- res = LoadNode::make(_igvn, ctl, m, adr, adr_type, type, bt, MemNode::unordered, LoadNode::Pinned);
+ res = LoadNode::make(_igvn, ctl, mem, adr, adr_type, type, bt, MemNode::unordered, LoadNode::Pinned);
} else {
if (ac->modifies(offset, offset, &_igvn, true)) {
assert(ac->in(ArrayCopyNode::Dest) == alloc->result_cast(), "arraycopy destination should be allocation's result");
@@ -454,8 +453,7 @@ Node* PhaseMacroExpand::make_arraycopy_load(ArrayCopyNode* ac, intptr_t offset,
Node* base = ac->in(ArrayCopyNode::Src);
Node* adr = _igvn.transform(new AddPNode(base, base, off));
const TypePtr* adr_type = _igvn.type(base)->is_ptr()->add_offset(offset);
- Node* m = ac->in(TypeFunc::Memory);
- res = LoadNode::make(_igvn, ctl, m, adr, adr_type, type, bt, MemNode::unordered, LoadNode::Pinned);
+ res = LoadNode::make(_igvn, ctl, mem, adr, adr_type, type, bt, MemNode::unordered, LoadNode::Pinned);
}
}
if (res != NULL) {
@@ -544,7 +542,7 @@ Node *PhaseMacroExpand::value_from_mem_phi(Node *mem, BasicType ft, const Type *
assert(false, "Object is not scalar replaceable if a LoadStore node accesses its field");
return NULL;
} else if (val->is_ArrayCopy()) {
- Node* res = make_arraycopy_load(val->as_ArrayCopy(), offset, val->in(0), ft, phi_type, alloc);
+ Node* res = make_arraycopy_load(val->as_ArrayCopy(), offset, val->in(0), val->in(TypeFunc::Memory), ft, phi_type, alloc);
if (res == NULL) {
return NULL;
}
@@ -657,11 +655,13 @@ Node *PhaseMacroExpand::value_from_mem(Node *sfpt_mem, Node *sfpt_ctl, BasicType
}
} else if (mem->is_ArrayCopy()) {
Node* ctl = mem->in(0);
+ Node* m = mem->in(TypeFunc::Memory);
if (sfpt_ctl->is_Proj() && sfpt_ctl->as_Proj()->is_uncommon_trap_proj(Deoptimization::Reason_none)) {
// pin the loads in the uncommon trap path
ctl = sfpt_ctl;
+ m = sfpt_mem;
}
- return make_arraycopy_load(mem->as_ArrayCopy(), offset, ctl, ft, ftype, alloc);
+ return make_arraycopy_load(mem->as_ArrayCopy(), offset, ctl, m, ft, ftype, alloc);
}
}
// Something go wrong.
diff --git a/hotspot/src/share/vm/opto/macro.hpp b/hotspot/src/share/vm/opto/macro.hpp
index ba8e9eac8e4..5482a1d8282 100644
--- a/hotspot/src/share/vm/opto/macro.hpp
+++ b/hotspot/src/share/vm/opto/macro.hpp
@@ -200,7 +200,7 @@ private:
Node* old_eden_top, Node* new_eden_top,
Node* length);
- Node* make_arraycopy_load(ArrayCopyNode* ac, intptr_t offset, Node* ctl, BasicType ft, const Type *ftype, AllocateNode *alloc);
+ Node* make_arraycopy_load(ArrayCopyNode* ac, intptr_t offset, Node* ctl, Node* mem, BasicType ft, const Type *ftype, AllocateNode *alloc);
public:
PhaseMacroExpand(PhaseIterGVN &igvn) : Phase(Macro_Expand), _igvn(igvn), _has_locks(false) {
diff --git a/hotspot/src/share/vm/opto/matcher.cpp b/hotspot/src/share/vm/opto/matcher.cpp
index 7c7ed8dd493..698b0bae068 100644
--- a/hotspot/src/share/vm/opto/matcher.cpp
+++ b/hotspot/src/share/vm/opto/matcher.cpp
@@ -85,6 +85,7 @@ Matcher::Matcher()
idealreg2spillmask [Op_VecX] = NULL;
idealreg2spillmask [Op_VecY] = NULL;
idealreg2spillmask [Op_VecZ] = NULL;
+ idealreg2spillmask [Op_RegFlags] = NULL;
idealreg2debugmask [Op_RegI] = NULL;
idealreg2debugmask [Op_RegN] = NULL;
@@ -97,6 +98,7 @@ Matcher::Matcher()
idealreg2debugmask [Op_VecX] = NULL;
idealreg2debugmask [Op_VecY] = NULL;
idealreg2debugmask [Op_VecZ] = NULL;
+ idealreg2debugmask [Op_RegFlags] = NULL;
idealreg2mhdebugmask[Op_RegI] = NULL;
idealreg2mhdebugmask[Op_RegN] = NULL;
@@ -109,6 +111,7 @@ Matcher::Matcher()
idealreg2mhdebugmask[Op_VecX] = NULL;
idealreg2mhdebugmask[Op_VecY] = NULL;
idealreg2mhdebugmask[Op_VecZ] = NULL;
+ idealreg2mhdebugmask[Op_RegFlags] = NULL;
debug_only(_mem_node = NULL;) // Ideal memory node consumed by mach node
}
diff --git a/hotspot/src/share/vm/precompiled/precompiled.hpp b/hotspot/src/share/vm/precompiled/precompiled.hpp
index 6e92398898a..5f516c5e7e2 100644
--- a/hotspot/src/share/vm/precompiled/precompiled.hpp
+++ b/hotspot/src/share/vm/precompiled/precompiled.hpp
@@ -23,7 +23,7 @@
*/
// Precompiled headers are turned off for Sun Studion,
-// or if the user passes USE_PRECOMPILED_HEADER=0 to the makefiles.
+// or if the user passes --disable-precompiled-headers to configure.
#ifndef DONT_USE_PRECOMPILED_HEADER
# include "asm/assembler.hpp"
diff --git a/hotspot/src/share/vm/prims/jniCheck.cpp b/hotspot/src/share/vm/prims/jniCheck.cpp
index ea80b5b8110..9ba9e1ad419 100644
--- a/hotspot/src/share/vm/prims/jniCheck.cpp
+++ b/hotspot/src/share/vm/prims/jniCheck.cpp
@@ -238,8 +238,8 @@ functionExit(JavaThread* thr)
size_t live_handles = handles->get_number_of_live_handles();
if (live_handles > planned_capacity) {
IN_VM(
- tty->print_cr("WARNING: JNI local refs: %zu, exceeds capacity: %zu",
- live_handles, planned_capacity);
+ tty->print_cr("WARNING: JNI local refs: " SIZE_FORMAT ", exceeds capacity: " SIZE_FORMAT,
+ live_handles, planned_capacity);
thr->print_stack();
)
// Complain just the once, reset to current + warn threshold
diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp
index 6a1b4dda087..2955463852e 100644
--- a/hotspot/src/share/vm/prims/jvm.cpp
+++ b/hotspot/src/share/vm/prims/jvm.cpp
@@ -1009,9 +1009,9 @@ JVM_END
// Module support //////////////////////////////////////////////////////////////////////////////
JVM_ENTRY(void, JVM_DefineModule(JNIEnv *env, jobject module, jboolean is_open, jstring version,
- jstring location, jobjectArray packages))
+ jstring location, const char* const* packages, jsize num_packages))
JVMWrapper("JVM_DefineModule");
- Modules::define_module(module, version, location, packages, CHECK);
+ Modules::define_module(module, version, location, packages, num_packages, CHECK);
JVM_END
JVM_ENTRY(void, JVM_SetBootLoaderUnnamedModule(JNIEnv *env, jobject module))
@@ -1019,17 +1019,17 @@ JVM_ENTRY(void, JVM_SetBootLoaderUnnamedModule(JNIEnv *env, jobject module))
Modules::set_bootloader_unnamed_module(module, CHECK);
JVM_END
-JVM_ENTRY(void, JVM_AddModuleExports(JNIEnv *env, jobject from_module, jstring package, jobject to_module))
+JVM_ENTRY(void, JVM_AddModuleExports(JNIEnv *env, jobject from_module, const char* package, jobject to_module))
JVMWrapper("JVM_AddModuleExports");
Modules::add_module_exports_qualified(from_module, package, to_module, CHECK);
JVM_END
-JVM_ENTRY(void, JVM_AddModuleExportsToAllUnnamed(JNIEnv *env, jobject from_module, jstring package))
+JVM_ENTRY(void, JVM_AddModuleExportsToAllUnnamed(JNIEnv *env, jobject from_module, const char* package))
JVMWrapper("JVM_AddModuleExportsToAllUnnamed");
Modules::add_module_exports_to_all_unnamed(from_module, package, CHECK);
JVM_END
-JVM_ENTRY(void, JVM_AddModuleExportsToAll(JNIEnv *env, jobject from_module, jstring package))
+JVM_ENTRY(void, JVM_AddModuleExportsToAll(JNIEnv *env, jobject from_module, const char* package))
JVMWrapper("JVM_AddModuleExportsToAll");
Modules::add_module_exports(from_module, package, NULL, CHECK);
JVM_END
@@ -1039,16 +1039,11 @@ JVM_ENTRY (void, JVM_AddReadsModule(JNIEnv *env, jobject from_module, jobject so
Modules::add_reads_module(from_module, source_module, CHECK);
JVM_END
-JVM_ENTRY (void, JVM_AddModulePackage(JNIEnv *env, jobject module, jstring package))
+JVM_ENTRY (void, JVM_AddModulePackage(JNIEnv *env, jobject module, const char* package))
JVMWrapper("JVM_AddModulePackage");
Modules::add_module_package(module, package, CHECK);
JVM_END
-JVM_ENTRY (jobject, JVM_GetModuleByPackageName(JNIEnv *env, jobject loader, jstring package))
- JVMWrapper("JVM_GetModuleByPackageName");
- return Modules::get_module_by_package_name(loader, package, THREAD);
-JVM_END
-
// Reflection support //////////////////////////////////////////////////////////////////////////////
JVM_ENTRY(jstring, JVM_GetClassName(JNIEnv *env, jclass cls))
diff --git a/hotspot/src/share/vm/prims/jvm.h b/hotspot/src/share/vm/prims/jvm.h
index c713645024e..e105c97766d 100644
--- a/hotspot/src/share/vm/prims/jvm.h
+++ b/hotspot/src/share/vm/prims/jvm.h
@@ -412,30 +412,67 @@ JVM_DefineClassWithSource(JNIEnv *env, const char *name, jobject loader,
* Module support funcions
*/
+/*
+ * Define a module with the specified packages and bind the module to the
+ * given class loader.
+ * module: module to define
+ * is_open: specifies if module is open (currently ignored)
+ * version: the module version
+ * location: the module location
+ * packages: list of packages in the module
+ * num_packages: number of packages in the module
+ */
JNIEXPORT void JNICALL
JVM_DefineModule(JNIEnv *env, jobject module, jboolean is_open, jstring version,
- jstring location, jobjectArray packages);
+ jstring location, const char* const* packages, jsize num_packages);
+/*
+ * Set the boot loader's unnamed module.
+ * module: boot loader's unnamed module
+ */
JNIEXPORT void JNICALL
JVM_SetBootLoaderUnnamedModule(JNIEnv *env, jobject module);
+/*
+ * Do a qualified export of a package.
+ * from_module: module containing the package to export
+ * package: name of the package to export
+ * to_module: module to export the package to
+ */
JNIEXPORT void JNICALL
-JVM_AddModuleExports(JNIEnv *env, jobject from_module, jstring package, jobject to_module);
+JVM_AddModuleExports(JNIEnv *env, jobject from_module, const char* package, jobject to_module);
+/*
+ * Do an export of a package to all unnamed modules.
+ * from_module: module containing the package to export
+ * package: name of the package to export to all unnamed modules
+ */
JNIEXPORT void JNICALL
-JVM_AddModuleExportsToAllUnnamed(JNIEnv *env, jobject from_module, jstring package);
+JVM_AddModuleExportsToAllUnnamed(JNIEnv *env, jobject from_module, const char* package);
+/*
+ * Do an unqualified export of a package.
+ * from_module: module containing the package to export
+ * package: name of the package to export
+ */
JNIEXPORT void JNICALL
-JVM_AddModuleExportsToAll(JNIEnv *env, jobject from_module, jstring package);
+JVM_AddModuleExportsToAll(JNIEnv *env, jobject from_module, const char* package);
+/*
+ * Add a module to the list of modules that a given module can read.
+ * from_module: module requesting read access
+ * source_module: module that from_module wants to read
+ */
JNIEXPORT void JNICALL
JVM_AddReadsModule(JNIEnv *env, jobject from_module, jobject source_module);
+/*
+ * Add a package to a module.
+ * module: module that will contain the package
+ * package: package to add to the module
+ */
JNIEXPORT void JNICALL
-JVM_AddModulePackage(JNIEnv* env, jobject module, jstring package);
-
-JNIEXPORT jobject JNICALL
-JVM_GetModuleByPackageName(JNIEnv* env, jobject loader, jstring package);
+JVM_AddModulePackage(JNIEnv* env, jobject module, const char* package);
/*
* Reflection support functions
diff --git a/hotspot/src/share/vm/prims/jvmti.xml b/hotspot/src/share/vm/prims/jvmti.xml
index 0f390214eb2..7a0515c2bc4 100644
--- a/hotspot/src/share/vm/prims/jvmti.xml
+++ b/hotspot/src/share/vm/prims/jvmti.xml
@@ -1,7 +1,7 @@
defines first_mod --> no packages
+// defines second_mod --> packages p2
+//
+// first_mod can read second_mod
+// package p2 in second_mod is exported to first_mod
+//
+// class p1.c1 defined in an unnamed module tries to access p2.c2 defined in second_mod
+// Access is not allowed, even after p2 is exported to all unnamed modules.
+
+public class AccessExportTwice {
+
+ // Create a Layer over the boot layer.
+ // Define modules within this layer to test access between
+ // publicly defined classes within packages of those modules.
+ public void createLayerOnBoot() throws Throwable {
+
+ // Define module: first_mod
+ // Can read: java.base, second_mod
+ // Packages: none
+ // Packages exported: none
+ ModuleDescriptor descriptor_first_mod =
+ ModuleDescriptor.module("first_mod")
+ .requires("java.base")
+ .requires("second_mod")
+ .build();
+
+ // Define module: second_mod
+ // Can read: java.base
+ // Packages: p2
+ // Packages exported: p2 is exported to first_mod
+ ModuleDescriptor descriptor_second_mod =
+ ModuleDescriptor.module("second_mod")
+ .requires("java.base")
+ .exports("p2", Set.of("first_mod"))
+ .build();
+
+ // Set up a ModuleFinder containing all modules for this layer
+ ModuleFinder finder = ModuleLibrary.of(descriptor_first_mod, descriptor_second_mod);
+
+ // Resolves "first_mod"
+ Configuration cf = Layer.boot()
+ .configuration()
+ .resolveRequires(finder, ModuleFinder.of(), Set.of("first_mod"));
+
+ // Map each module to the same class loader
+ Map map = new HashMap<>();
+ map.put("first_mod", MySameClassLoader.loader1);
+ map.put("second_mod", MySameClassLoader.loader1);
+
+ // Create Layer that contains first_mod & second_mod
+ Layer layer = Layer.boot().defineModules(cf, map::get);
+
+ assertTrue(layer.findLoader("first_mod") == MySameClassLoader.loader1);
+ assertTrue(layer.findLoader("second_mod") == MySameClassLoader.loader1);
+ assertTrue(layer.findLoader("java.base") == null);
+
+ Class p2_c2_class = MySameClassLoader.loader1.loadClass("p2.c2");
+ // Use the same loader to load class p1.c1
+ Class p1_c1_class = MySameClassLoader.loader1.loadClass("p1.c1");
+ // First access check for p1.c1
+ try {
+ p1_c1_class.newInstance();
+ throw new RuntimeException("Test Failed, the unnamed module should not have access to public type p2.c2");
+ } catch (IllegalAccessError e) {
+ String message = e.getMessage();
+ if (!(message.contains("cannot access") &&
+ message.contains("because module second_mod does not export p2 to unnamed module"))) {
+ throw new RuntimeException("Wrong message: " + message);
+ } else {
+ System.out.println("Test Succeeded at attempt #1");
+ }
+ }
+
+ // Export second_mod/p2 to all unnamed modules.
+ Module second_mod = p2_c2_class.getModule();
+ jdk.internal.module.Modules.addExportsToAllUnnamed(second_mod, "p2");
+
+ // Second access check for p1.c1, should have same result as first
+ try {
+ p1_c1_class.newInstance();
+ throw new RuntimeException("Test Failed, access should have been cached above");
+ } catch (IllegalAccessError e) {
+ String message = e.getMessage();
+ if (!(message.contains("cannot access") &&
+ message.contains("because module second_mod does not export p2 to unnamed module"))) {
+ throw new RuntimeException("Wrong message: " + message);
+ } else {
+ System.out.println("Test Succeeded at attempt #2");
+ }
+ }
+ }
+
+ public static void main(String args[]) throws Throwable {
+ AccessExportTwice test = new AccessExportTwice();
+ test.createLayerOnBoot();
+ }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/AccessReadTwice.java b/hotspot/test/runtime/modules/AccessCheck/AccessReadTwice.java
new file mode 100644
index 00000000000..5d1a690a740
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/AccessReadTwice.java
@@ -0,0 +1,154 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/*
+ * @test
+ * @summary Class p1.c1 in module first_mod cannot read p2.c2 in module second_mod,
+ * even after a read edge is added between first_mod and second_mod.
+ * Ensures constant access check answers when not accessible due to readability.
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.module
+ * @compile p2/c2.java
+ * @compile p1/c1.java
+ * @compile p4/c4.java
+ * @run main/othervm AccessReadTwice
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.lang.reflect.Layer;
+import java.lang.reflect.Module;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+//
+// ClassLoader1 --> defines first_mod --> packages p1, p4
+// defines second_mod --> package p2
+//
+// package p2 in second_mod is exported to first_mod
+//
+// class p1.c1 defined in first_mod tries to access p2.c2 defined in second_mod
+// Access is not allowed, even after a read edge is added between first_mod and second_mod.
+
+public class AccessReadTwice {
+
+ // Create a Layer over the boot layer.
+ // Define modules within this layer to test access between
+ // publicly defined classes within packages of those modules.
+ public void createLayerOnBoot() throws Throwable {
+
+ // Define module: first_mod
+ // Can read: java.base
+ // Packages: p1, p4
+ // Packages exported: none
+ ModuleDescriptor descriptor_first_mod =
+ ModuleDescriptor.module("first_mod")
+ .requires("java.base")
+ .contains(Set.of("p1", "p4"))
+ .build();
+
+ // Define module: second_mod
+ // Can read: java.base
+ // Packages: p2
+ // Packages exported: p2 is exported to first_mod
+ ModuleDescriptor descriptor_second_mod =
+ ModuleDescriptor.module("second_mod")
+ .requires("java.base")
+ .exports("p2", Set.of("first_mod"))
+ .build();
+
+ // Set up a ModuleFinder containing all modules for this layer
+ ModuleFinder finder = ModuleLibrary.of(descriptor_first_mod, descriptor_second_mod);
+
+ // Resolves "first_mod" and "second_mod"
+ Configuration cf = Layer.boot()
+ .configuration()
+ .resolveRequires(finder, ModuleFinder.of(), Set.of("first_mod", "second_mod"));
+
+ // Map each module to this class loader
+ Map map = new HashMap<>();
+ ClassLoader loader = AccessReadTwice.class.getClassLoader();
+ map.put("first_mod", loader);
+ map.put("second_mod", loader);
+
+ // Create Layer that contains first_mod & second_mod
+ Layer layer = Layer.boot().defineModules(cf, map::get);
+
+ assertTrue(layer.findLoader("first_mod") == loader);
+ assertTrue(layer.findLoader("second_mod") == loader);
+ assertTrue(layer.findLoader("java.base") == null);
+
+ Class p2_c2_class = loader.loadClass("p2.c2");
+ Class p1_c1_class = loader.loadClass("p1.c1");
+ Class p4_c4_class = loader.loadClass("p4.c4");
+
+ Module first_mod = p1_c1_class.getModule();
+ Module second_mod = p2_c2_class.getModule();
+
+ // Export first_mod/p1 and first_mod/p4 to all unnamed modules so that
+ // this test can use them
+ jdk.internal.module.Modules.addExportsToAllUnnamed(first_mod, "p1");
+ jdk.internal.module.Modules.addExportsToAllUnnamed(first_mod, "p4");
+
+ // First access check for p1.c1
+ try {
+ p1_c1_class.newInstance();
+ throw new RuntimeException("Test Failed, module first_mod should not have access to p2.c2");
+ } catch (IllegalAccessError e) {
+ String message = e.getMessage();
+ if (!(message.contains("cannot access") &&
+ message.contains("because module first_mod does not read module second_mod"))) {
+ throw new RuntimeException("Wrong message: " + message);
+ } else {
+ System.out.println("Test Succeeded at attempt #1");
+ }
+ }
+
+ // Add a read edge from p4/c4's module (first_mod) to second_mod
+ p4.c4 c4_obj = new p4.c4();
+ c4_obj.addReads(second_mod);
+
+ // Second access check for p1.c1, should have same result as first
+ try {
+ p1_c1_class.newInstance();
+ throw new RuntimeException("Test Failed, access should have been cached above");
+ } catch (IllegalAccessError e) {
+ String message = e.getMessage();
+ if (!(message.contains("cannot access") &&
+ message.contains("because module first_mod does not read module second_mod"))) {
+ throw new RuntimeException("Wrong message: " + message);
+ } else {
+ System.out.println("Test Succeeded at attempt #2");
+ }
+ }
+ }
+
+ public static void main(String args[]) throws Throwable {
+ AccessReadTwice test = new AccessReadTwice();
+ test.createLayerOnBoot();
+ }
+}
diff --git a/hotspot/test/runtime/modules/AccessCheck/p4/c4.java b/hotspot/test/runtime/modules/AccessCheck/p4/c4.java
new file mode 100644
index 00000000000..d0098674672
--- /dev/null
+++ b/hotspot/test/runtime/modules/AccessCheck/p4/c4.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+// Small class used by multiple hotspot/runtime/modules/AccessCheck/* tests.
+
+package p4;
+
+import java.lang.reflect.Module;
+
+public class c4 {
+ // Add a read edge from c4's module to given module m
+ public void addReads(Module m) {
+ c4.class.getModule().addReads(m);
+ }
+}
diff --git a/hotspot/test/runtime/modules/JVMAddModulePackage.java b/hotspot/test/runtime/modules/JVMAddModulePackage.java
index 62106f8597f..3f7f2fd29a0 100644
--- a/hotspot/test/runtime/modules/JVMAddModulePackage.java
+++ b/hotspot/test/runtime/modules/JVMAddModulePackage.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -84,11 +84,11 @@ public class JVMAddModulePackage {
// Expected
}
- // Existing package, expect an IAE
+ // Existing package, expect an ISE
try {
ModuleHelper.AddModulePackage(module1, "yourpackage");
- throw new RuntimeException("Failed to get the expected IAE");
- } catch(IllegalArgumentException e) {
+ throw new RuntimeException("Failed to get the expected ISE");
+ } catch(IllegalStateException e) {
// Expected
}
diff --git a/hotspot/test/runtime/modules/JVMDefineModule.java b/hotspot/test/runtime/modules/JVMDefineModule.java
index dd19770ee98..9e44878490d 100644
--- a/hotspot/test/runtime/modules/JVMDefineModule.java
+++ b/hotspot/test/runtime/modules/JVMDefineModule.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -127,27 +127,27 @@ public class JVMDefineModule {
}
}
- // Duplicate module name, expect an IAE
- m = ModuleHelper.ModuleObject("module.name", cl, new String[] { "mypackage6" });
+ // Duplicate module name, expect an ISE
+ m = ModuleHelper.ModuleObject("Module_A", cl, new String[] { "mypackage6" });
assertNotNull(m, "Module should not be null");
ModuleHelper.DefineModule(m, "9.0", "module.name/here", new String[] { "mypackage6" });
try {
ModuleHelper.DefineModule(m, "9.0", "module.name/here", new String[] { "mypackage6a" });
- throw new RuntimeException("Failed to get IAE for duplicate module");
- } catch(IllegalArgumentException e) {
- if (!e.getMessage().contains("Module module.name is already defined")) {
- throw new RuntimeException("Failed to get expected IAE message for duplicate module: " + e.getMessage());
+ throw new RuntimeException("Failed to get ISE for duplicate module");
+ } catch(IllegalStateException e) {
+ if (!e.getMessage().contains("Module Module_A is already defined")) {
+ throw new RuntimeException("Failed to get expected ISE message for duplicate module: " + e.getMessage());
}
}
- // Package is already defined for class loader, expect an IAE
+ // Package is already defined for class loader, expect an ISE
m = ModuleHelper.ModuleObject("dupl.pkg.module", cl, new String[] { "mypackage6b" });
try {
ModuleHelper.DefineModule(m, "9.0", "module.name/here", new String[] { "mypackage6" });
- throw new RuntimeException("Failed to get IAE for existing package");
- } catch(IllegalArgumentException e) {
- if (!e.getMessage().contains("Package mypackage6 for module dupl.pkg.module already exists for class loader")) {
- throw new RuntimeException("Failed to get expected IAE message for duplicate package: " + e.getMessage());
+ throw new RuntimeException("Failed to get ISE for existing package");
+ } catch(IllegalStateException e) {
+ if (!e.getMessage().contains("Package mypackage6 for module dupl.pkg.module is already in another module, Module_A, defined to the class loader")) {
+ throw new RuntimeException("Failed to get expected ISE message for duplicate package: " + e.getMessage());
}
}
diff --git a/hotspot/test/serviceability/attach/AttachSetGetFlag.java b/hotspot/test/serviceability/attach/AttachSetGetFlag.java
index 3b48759cc23..2d6a28cfce3 100644
--- a/hotspot/test/serviceability/attach/AttachSetGetFlag.java
+++ b/hotspot/test/serviceability/attach/AttachSetGetFlag.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -30,7 +30,7 @@
* java.compiler
* java.management
* jdk.attach/sun.tools.attach
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run main AttachSetGetFlag
*/
diff --git a/hotspot/test/serviceability/dcmd/compiler/CodeCacheTest.java b/hotspot/test/serviceability/dcmd/compiler/CodeCacheTest.java
index c22be26f951..8b3a8d8a47d 100644
--- a/hotspot/test/serviceability/dcmd/compiler/CodeCacheTest.java
+++ b/hotspot/test/serviceability/dcmd/compiler/CodeCacheTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -28,7 +28,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run testng/othervm -XX:+SegmentedCodeCache CodeCacheTest
* @run testng/othervm -XX:-SegmentedCodeCache CodeCacheTest
* @run testng/othervm -Xint -XX:+SegmentedCodeCache CodeCacheTest
diff --git a/hotspot/test/serviceability/dcmd/compiler/CodelistTest.java b/hotspot/test/serviceability/dcmd/compiler/CodelistTest.java
index e0bdd408012..11a28ec9a85 100644
--- a/hotspot/test/serviceability/dcmd/compiler/CodelistTest.java
+++ b/hotspot/test/serviceability/dcmd/compiler/CodelistTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -28,7 +28,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
diff --git a/hotspot/test/serviceability/dcmd/compiler/CompilerDirectivesDCMDTest.java b/hotspot/test/serviceability/dcmd/compiler/CompilerDirectivesDCMDTest.java
index c43dfafa56f..8d40423b5e8 100644
--- a/hotspot/test/serviceability/dcmd/compiler/CompilerDirectivesDCMDTest.java
+++ b/hotspot/test/serviceability/dcmd/compiler/CompilerDirectivesDCMDTest.java
@@ -49,7 +49,7 @@ public class CompilerDirectivesDCMDTest {
public void run(CommandExecutor executor) {
- if (Platform.isServer()) {
+ if (Platform.isServer() && !Platform.isEmulatedClient()) {
filename = System.getProperty("test.src", ".") + File.separator + "control2.txt";
} else {
filename = System.getProperty("test.src", ".") + File.separator + "control1.txt";
diff --git a/hotspot/test/serviceability/dcmd/compiler/CompilerQueueTest.java b/hotspot/test/serviceability/dcmd/compiler/CompilerQueueTest.java
index 3640bbcebbb..a1b79533a3a 100644
--- a/hotspot/test/serviceability/dcmd/compiler/CompilerQueueTest.java
+++ b/hotspot/test/serviceability/dcmd/compiler/CompilerQueueTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -28,7 +28,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @summary Test of diagnostic command Compiler.queue
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
diff --git a/hotspot/test/serviceability/dcmd/framework/HelpTest.java b/hotspot/test/serviceability/dcmd/framework/HelpTest.java
index b172db8e7ca..d88ddffce71 100644
--- a/hotspot/test/serviceability/dcmd/framework/HelpTest.java
+++ b/hotspot/test/serviceability/dcmd/framework/HelpTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -36,7 +36,7 @@ import org.testng.annotations.Test;
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run testng/othervm -XX:+UsePerfData HelpTest
*/
public class HelpTest {
diff --git a/hotspot/test/serviceability/dcmd/framework/InvalidCommandTest.java b/hotspot/test/serviceability/dcmd/framework/InvalidCommandTest.java
index be8a4d8560d..2536b4125aa 100644
--- a/hotspot/test/serviceability/dcmd/framework/InvalidCommandTest.java
+++ b/hotspot/test/serviceability/dcmd/framework/InvalidCommandTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -36,7 +36,7 @@ import org.testng.annotations.Test;
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run testng/othervm -XX:+UsePerfData InvalidCommandTest
*/
public class InvalidCommandTest {
diff --git a/hotspot/test/serviceability/dcmd/framework/VMVersionTest.java b/hotspot/test/serviceability/dcmd/framework/VMVersionTest.java
index dadaf3113b2..d39f0de5263 100644
--- a/hotspot/test/serviceability/dcmd/framework/VMVersionTest.java
+++ b/hotspot/test/serviceability/dcmd/framework/VMVersionTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -37,7 +37,7 @@ import org.testng.annotations.Test;
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run testng/othervm -XX:+UsePerfData VMVersionTest
*/
public class VMVersionTest {
diff --git a/hotspot/test/serviceability/dcmd/gc/ClassHistogramAllTest.java b/hotspot/test/serviceability/dcmd/gc/ClassHistogramAllTest.java
index bc2f3e2eb15..a3d244cef4e 100644
--- a/hotspot/test/serviceability/dcmd/gc/ClassHistogramAllTest.java
+++ b/hotspot/test/serviceability/dcmd/gc/ClassHistogramAllTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -28,7 +28,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run testng ClassHistogramAllTest
*/
public class ClassHistogramAllTest extends ClassHistogramTest {
diff --git a/hotspot/test/serviceability/dcmd/gc/ClassHistogramTest.java b/hotspot/test/serviceability/dcmd/gc/ClassHistogramTest.java
index 5b4f017ec40..fec990e5a10 100644
--- a/hotspot/test/serviceability/dcmd/gc/ClassHistogramTest.java
+++ b/hotspot/test/serviceability/dcmd/gc/ClassHistogramTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -36,7 +36,7 @@ import jdk.test.lib.dcmd.JMXExecutor;
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run testng ClassHistogramTest
*/
public class ClassHistogramTest {
diff --git a/hotspot/test/serviceability/dcmd/gc/HeapDumpAllTest.java b/hotspot/test/serviceability/dcmd/gc/HeapDumpAllTest.java
index 257acea6b10..d811493c1d3 100644
--- a/hotspot/test/serviceability/dcmd/gc/HeapDumpAllTest.java
+++ b/hotspot/test/serviceability/dcmd/gc/HeapDumpAllTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -28,7 +28,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run testng HeapDumpAllTest
*/
public class HeapDumpAllTest extends HeapDumpTest {
diff --git a/hotspot/test/serviceability/dcmd/gc/HeapDumpTest.java b/hotspot/test/serviceability/dcmd/gc/HeapDumpTest.java
index 257a30f899c..60444ae358c 100644
--- a/hotspot/test/serviceability/dcmd/gc/HeapDumpTest.java
+++ b/hotspot/test/serviceability/dcmd/gc/HeapDumpTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -44,7 +44,7 @@ import jdk.test.lib.dcmd.PidJcmdExecutor;
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run testng HeapDumpTest
*/
public class HeapDumpTest {
diff --git a/hotspot/test/serviceability/dcmd/gc/RunFinalizationTest.java b/hotspot/test/serviceability/dcmd/gc/RunFinalizationTest.java
index 22af05f0523..f49e4165688 100644
--- a/hotspot/test/serviceability/dcmd/gc/RunFinalizationTest.java
+++ b/hotspot/test/serviceability/dcmd/gc/RunFinalizationTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -34,7 +34,7 @@ import jdk.test.lib.process.ProcessTools;
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @build FinalizationRunner
* @run main RunFinalizationTest
*/
diff --git a/hotspot/test/serviceability/dcmd/gc/RunGCTest.java b/hotspot/test/serviceability/dcmd/gc/RunGCTest.java
index 44bd09a6268..267e91381a5 100644
--- a/hotspot/test/serviceability/dcmd/gc/RunGCTest.java
+++ b/hotspot/test/serviceability/dcmd/gc/RunGCTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -40,7 +40,7 @@ import jdk.test.lib.dcmd.JMXExecutor;
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run testng/othervm -Xlog:gc=debug:RunGC.gclog -XX:-ExplicitGCInvokesConcurrent RunGCTest
*/
public class RunGCTest {
diff --git a/hotspot/test/serviceability/dcmd/jvmti/LoadAgentDcmdTest.java b/hotspot/test/serviceability/dcmd/jvmti/LoadAgentDcmdTest.java
index 373edf07857..c190353803f 100644
--- a/hotspot/test/serviceability/dcmd/jvmti/LoadAgentDcmdTest.java
+++ b/hotspot/test/serviceability/dcmd/jvmti/LoadAgentDcmdTest.java
@@ -41,7 +41,7 @@ import org.testng.annotations.Test;
* java.compiler
* java.instrument
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @build SimpleJvmtiAgent
* @run main ClassFileInstaller SimpleJvmtiAgent
* @run testng LoadAgentDcmdTest
diff --git a/hotspot/test/serviceability/dcmd/thread/PrintConcurrentLocksTest.java b/hotspot/test/serviceability/dcmd/thread/PrintConcurrentLocksTest.java
index b931c42019e..c1ca3a35442 100644
--- a/hotspot/test/serviceability/dcmd/thread/PrintConcurrentLocksTest.java
+++ b/hotspot/test/serviceability/dcmd/thread/PrintConcurrentLocksTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -28,7 +28,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run testng PrintConcurrentLocksTest
*/
public class PrintConcurrentLocksTest extends PrintTest {
diff --git a/hotspot/test/serviceability/dcmd/thread/PrintTest.java b/hotspot/test/serviceability/dcmd/thread/PrintTest.java
index 77e22e1d8c5..e4af11c3261 100644
--- a/hotspot/test/serviceability/dcmd/thread/PrintTest.java
+++ b/hotspot/test/serviceability/dcmd/thread/PrintTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -41,7 +41,7 @@ import java.util.regex.Pattern;
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run testng PrintTest
*/
public class PrintTest {
diff --git a/hotspot/test/serviceability/dcmd/vm/ClassHierarchyTest.java b/hotspot/test/serviceability/dcmd/vm/ClassHierarchyTest.java
index aee55b5cc31..7c77a2d2a82 100644
--- a/hotspot/test/serviceability/dcmd/vm/ClassHierarchyTest.java
+++ b/hotspot/test/serviceability/dcmd/vm/ClassHierarchyTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -28,7 +28,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run testng ClassHierarchyTest
*/
diff --git a/hotspot/test/serviceability/dcmd/vm/ClassLoaderStatsTest.java b/hotspot/test/serviceability/dcmd/vm/ClassLoaderStatsTest.java
index d2230e33d8b..60f94069986 100644
--- a/hotspot/test/serviceability/dcmd/vm/ClassLoaderStatsTest.java
+++ b/hotspot/test/serviceability/dcmd/vm/ClassLoaderStatsTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -28,7 +28,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run testng ClassLoaderStatsTest
*/
diff --git a/hotspot/test/serviceability/dcmd/vm/CommandLineTest.java b/hotspot/test/serviceability/dcmd/vm/CommandLineTest.java
index ac04d02b382..72f009d75e4 100644
--- a/hotspot/test/serviceability/dcmd/vm/CommandLineTest.java
+++ b/hotspot/test/serviceability/dcmd/vm/CommandLineTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -34,7 +34,7 @@ import jdk.test.lib.dcmd.JMXExecutor;
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run testng/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+ThereShouldNotBeAnyVMOptionNamedLikeThis CommandLineTest
*/
public class CommandLineTest {
diff --git a/hotspot/test/serviceability/dcmd/vm/DynLibsTest.java b/hotspot/test/serviceability/dcmd/vm/DynLibsTest.java
index 3b4cfce1b60..4bda8a8f4c6 100644
--- a/hotspot/test/serviceability/dcmd/vm/DynLibsTest.java
+++ b/hotspot/test/serviceability/dcmd/vm/DynLibsTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -36,7 +36,7 @@ import jdk.test.lib.dcmd.JMXExecutor;
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run testng DynLibsTest
*/
diff --git a/hotspot/test/serviceability/dcmd/vm/FlagsTest.java b/hotspot/test/serviceability/dcmd/vm/FlagsTest.java
index f83ab760a49..3554a696119 100644
--- a/hotspot/test/serviceability/dcmd/vm/FlagsTest.java
+++ b/hotspot/test/serviceability/dcmd/vm/FlagsTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -33,7 +33,7 @@ import org.testng.annotations.Test;
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run testng/othervm -Xmx129m -XX:+UnlockDiagnosticVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+ThereShouldNotBeAnyVMOptionNamedLikeThis_Right -XX:-TieredCompilation FlagsTest
*/
public class FlagsTest {
diff --git a/hotspot/test/serviceability/dcmd/vm/SystemPropertiesTest.java b/hotspot/test/serviceability/dcmd/vm/SystemPropertiesTest.java
index 71ec4e17139..8325dc85f39 100644
--- a/hotspot/test/serviceability/dcmd/vm/SystemPropertiesTest.java
+++ b/hotspot/test/serviceability/dcmd/vm/SystemPropertiesTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -34,7 +34,7 @@ import jdk.test.lib.dcmd.JMXExecutor;
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run testng SystemPropertiesTest
*/
public class SystemPropertiesTest {
diff --git a/hotspot/test/serviceability/dcmd/vm/UptimeTest.java b/hotspot/test/serviceability/dcmd/vm/UptimeTest.java
index a907421d5da..77ff300ee2f 100644
--- a/hotspot/test/serviceability/dcmd/vm/UptimeTest.java
+++ b/hotspot/test/serviceability/dcmd/vm/UptimeTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -38,7 +38,7 @@ import java.text.ParseException;
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run testng UptimeTest
*/
public class UptimeTest {
diff --git a/hotspot/test/serviceability/jvmti/GetObjectSizeClass.java b/hotspot/test/serviceability/jvmti/GetObjectSizeClass.java
index 1030675d8f3..0b30a67dd52 100644
--- a/hotspot/test/serviceability/jvmti/GetObjectSizeClass.java
+++ b/hotspot/test/serviceability/jvmti/GetObjectSizeClass.java
@@ -35,7 +35,7 @@ import jdk.test.lib.process.ProcessTools;
* java.compiler
* java.instrument
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @build GetObjectSizeClassAgent
* @run main ClassFileInstaller GetObjectSizeClassAgent
* @run main GetObjectSizeClass
diff --git a/hotspot/test/serviceability/jvmti/GetObjectSizeOverflow.java b/hotspot/test/serviceability/jvmti/GetObjectSizeOverflow.java
index e2a801aaef8..57eabb72e8a 100644
--- a/hotspot/test/serviceability/jvmti/GetObjectSizeOverflow.java
+++ b/hotspot/test/serviceability/jvmti/GetObjectSizeOverflow.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -36,7 +36,7 @@ import jdk.test.lib.process.ProcessTools;
* java.compiler
* java.instrument
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @build GetObjectSizeOverflowAgent
* @run main ClassFileInstaller GetObjectSizeOverflowAgent
* @run main GetObjectSizeOverflow
diff --git a/hotspot/test/serviceability/jvmti/TestRedefineWithUnresolvedClass.java b/hotspot/test/serviceability/jvmti/TestRedefineWithUnresolvedClass.java
index 4a9bb2606fe..c6a203e86bc 100644
--- a/hotspot/test/serviceability/jvmti/TestRedefineWithUnresolvedClass.java
+++ b/hotspot/test/serviceability/jvmti/TestRedefineWithUnresolvedClass.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -31,7 +31,7 @@
* java.instrument
* java.management
* jdk.jartool/sun.tools.jar
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @build UnresolvedClassAgent
* @run main TestRedefineWithUnresolvedClass
*/
diff --git a/hotspot/test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapProc.java b/hotspot/test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapProc.java
index c3dced229db..855fbad95c6 100644
--- a/hotspot/test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapProc.java
+++ b/hotspot/test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapProc.java
@@ -21,12 +21,9 @@
* questions.
*/
-import java.lang.management.ManagementFactory;
-import java.lang.management.RuntimeMXBean;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
+import jdk.test.lib.process.ProcessTools;
import sun.management.VMManagement;
@@ -38,7 +35,7 @@ public class JMapHProfLargeHeapProc {
buildLargeHeap(args);
// Print our pid on stdout
- System.out.println("PID[" + getProcessId() + "]");
+ System.out.println("PID[" + ProcessTools.getProcessId() + "]");
// Wait for input before termination
System.in.read();
@@ -50,22 +47,4 @@ public class JMapHProfLargeHeapProc {
}
}
- public static int getProcessId() throws Exception {
-
- // Get the current process id using a reflection hack
- RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
- Field jvm = runtime.getClass().getDeclaredField("jvm");
-
- jvm.setAccessible(true);
- VMManagement mgmt = (sun.management.VMManagement) jvm.get(runtime);
-
- Method pid_method = mgmt.getClass().getDeclaredMethod("getProcessId");
-
- pid_method.setAccessible(true);
-
- int pid = (Integer) pid_method.invoke(mgmt);
-
- return pid;
- }
-
}
diff --git a/hotspot/test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java b/hotspot/test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java
index d2e64f75d34..2a46621d118 100644
--- a/hotspot/test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java
+++ b/hotspot/test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -46,7 +46,7 @@ import jdk.test.lib.process.ProcessTools;
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management/sun.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @build JMapHProfLargeHeapProc
* @run main JMapHProfLargeHeapTest
*/
@@ -90,6 +90,9 @@ public class JMapHProfLargeHeapTest {
try (Scanner largeHeapScanner = new Scanner(
largeHeapProc.getInputStream());) {
String pidstring = null;
+ if (!largeHeapScanner.hasNext()) {
+ throw new RuntimeException ("Test failed: could not open largeHeapScanner.");
+ }
while ((pidstring = largeHeapScanner.findInLine("PID\\[[0-9].*\\]")) == null) {
Thread.sleep(500);
}
diff --git a/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/CompileTheWorld.java b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/CompileTheWorld.java
index 88a94f66cdf..98a3d29bfa4 100644
--- a/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/CompileTheWorld.java
+++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/CompileTheWorld.java
@@ -59,6 +59,8 @@ public class CompileTheWorld {
OUT = os;
}
+ boolean passed = false;
+
try {
try {
if (ManagementFactory.getCompilationMXBean() == null) {
@@ -84,10 +86,10 @@ public class CompileTheWorld {
PathHandler.getClassCount(),
Compiler.getMethodCount(),
System.currentTimeMillis() - start);
+ passed = true;
} finally {
- if (os != null) {
- os.close();
- }
+ // might have started new threads
+ System.exit(passed ? 0 : 1);
}
}
diff --git a/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/Utils.java b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/Utils.java
index 4159c483408..75d82dd1ebd 100644
--- a/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/Utils.java
+++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/Utils.java
@@ -101,10 +101,12 @@ public class Utils {
INITIAL_COMP_LEVEL = 1;
} else {
String vmName = System.getProperty("java.vm.name");
- if (Utils.endsWithIgnoreCase(vmName, " Server VM")) {
+ String vmInfo = System.getProperty("java.vm.info");
+ boolean isEmulatedClient = (vmInfo != null) && vmInfo.contains("emulated-client");
+ if (Utils.endsWithIgnoreCase(vmName, " Server VM") && !isEmulatedClient) {
INITIAL_COMP_LEVEL = 4;
} else if (Utils.endsWithIgnoreCase(vmName, " Client VM")
- || Utils.endsWithIgnoreCase(vmName, " Minimal VM")) {
+ || Utils.endsWithIgnoreCase(vmName, " Minimal VM") || isEmulatedClient) {
INITIAL_COMP_LEVEL = 1;
} else {
throw new RuntimeException("Unknown VM: " + vmName);
diff --git a/hotspot/test/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java b/hotspot/test/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java
index 43c9715a95e..5e56d66bd4a 100644
--- a/hotspot/test/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java
+++ b/hotspot/test/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java
@@ -50,7 +50,7 @@ public class TestMutuallyExclusivePlatformPredicates {
OS("isAix", "isLinux", "isOSX", "isSolaris", "isWindows"),
VM_TYPE("isClient", "isServer", "isGraal", "isMinimal", "isZero", "isEmbedded"),
MODE("isInt", "isMixed", "isComp"),
- IGNORED("isDebugBuild", "isFastDebugBuild", "isSlowDebugBuild",
+ IGNORED("isEmulatedClient", "isDebugBuild", "isFastDebugBuild", "isSlowDebugBuild",
"shouldSAAttach", "canPtraceAttachLinux", "canAttachOSX",
"isTieredSupported");
diff --git a/hotspot/test/testlibrary_tests/ctw/ClassesDirTest.java b/hotspot/test/testlibrary_tests/ctw/ClassesDirTest.java
index 31f24081fa1..e24461cdac9 100644
--- a/hotspot/test/testlibrary_tests/ctw/ClassesDirTest.java
+++ b/hotspot/test/testlibrary_tests/ctw/ClassesDirTest.java
@@ -30,11 +30,11 @@
* java.base/jdk.internal.reflect
* java.management
* @build sun.hotspot.WhiteBox Foo Bar
- * @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar
- * sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main ClassesDirTest prepare
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Dsun.hotspot.tools.ctw.logfile=ctw.log sun.hotspot.tools.ctw.CompileTheWorld classes
- * @run main ClassesDirTest check ctw.log
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox Foo Bar
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run driver ClassesDirTest prepare
+ * @run driver ClassesDirTest compile classes
+ * @run driver ClassesDirTest check
* @summary testing of CompileTheWorld :: classes in directory
* @author igor.ignatyev@oracle.com
*/
diff --git a/hotspot/test/testlibrary_tests/ctw/ClassesListTest.java b/hotspot/test/testlibrary_tests/ctw/ClassesListTest.java
index c2823de598c..5ffe27ba0c6 100644
--- a/hotspot/test/testlibrary_tests/ctw/ClassesListTest.java
+++ b/hotspot/test/testlibrary_tests/ctw/ClassesListTest.java
@@ -30,11 +30,11 @@
* java.base/jdk.internal.reflect
* java.management
* @build sun.hotspot.WhiteBox Foo Bar
- * @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar
- * sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main ClassesListTest prepare
- * @run main/othervm/timeout=600 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Dsun.hotspot.tools.ctw.logfile=ctw.log sun.hotspot.tools.ctw.CompileTheWorld classes.lst
- * @run main ClassesListTest check ctw.log
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox Foo Bar
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run driver ClassesListTest prepare
+ * @run driver/timeout=600 ClassesListTest compile classes.lst
+ * @run driver ClassesListTest check
* @summary testing of CompileTheWorld :: list of classes in file
* @author igor.ignatyev@oracle.com
*/
diff --git a/hotspot/test/testlibrary_tests/ctw/CtwTest.java b/hotspot/test/testlibrary_tests/ctw/CtwTest.java
index 06b16b631b9..eb6aedc1fbe 100644
--- a/hotspot/test/testlibrary_tests/ctw/CtwTest.java
+++ b/hotspot/test/testlibrary_tests/ctw/CtwTest.java
@@ -21,6 +21,7 @@
* questions.
*/
+import java.util.Arrays;
import java.util.List;
import java.util.Collections;
import java.util.ArrayList;
@@ -38,8 +39,20 @@ import java.nio.charset.Charset;
import jdk.test.lib.JDKToolFinder;
import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
public abstract class CtwTest {
+ private static final String LOG_FILE = "ctw.log";
+ private static final String[] CTW_COMMAND = {
+ "-Xbootclasspath/a:.",
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-XX:+WhiteBoxAPI",
+ "-Dsun.hotspot.tools.ctw.logfile=" + LOG_FILE,
+ "--add-exports", "java.base/jdk.internal.jimage=ALL-UNNAMED",
+ "--add-exports", "java.base/jdk.internal.misc=ALL-UNNAMED",
+ "--add-exports", "java.base/jdk.internal.reflect=ALL-UNNAMED",
+ sun.hotspot.tools.ctw.CompileTheWorld.class.getName(),
+ };
protected final String[] shouldContain;
protected CtwTest(String[] shouldContain) {
this.shouldContain = shouldContain;
@@ -54,7 +67,10 @@ public abstract class CtwTest {
prepare();
break;
case "check":
- check(args);
+ check();
+ break;
+ case "compile":
+ compile(args);
break;
default:
throw new Error("unregonized action -- " + args[0]);
@@ -63,20 +79,27 @@ public abstract class CtwTest {
protected void prepare() throws Exception { }
- protected void check(String[] args) throws Exception {
- if (args.length < 2) {
- throw new Error("logfile isn't specified");
- }
- String logfile = args[1];
- try (BufferedReader r = Files.newBufferedReader(Paths.get(logfile),
+ protected void check() throws Exception {
+ try (BufferedReader r = Files.newBufferedReader(Paths.get(LOG_FILE),
Charset.defaultCharset())) {
OutputAnalyzer output = readOutput(r);
- for (String test : shouldContain) {
+ for (String test : shouldContain) {
output.shouldContain(test);
}
}
}
+ protected void compile(String[] args) throws Exception {
+ // concat CTW_COMMAND and args w/o 0th element
+ String[] cmd = Arrays.copyOf(CTW_COMMAND, CTW_COMMAND.length + args.length - 1);
+ System.arraycopy(args, 1, cmd, CTW_COMMAND.length, args.length - 1);
+
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, cmd);
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ dump(output, "compile");
+ output.shouldHaveExitValue(0);
+ }
+
private static OutputAnalyzer readOutput(BufferedReader reader)
throws IOException {
StringBuilder builder = new StringBuilder();
diff --git a/hotspot/test/testlibrary_tests/ctw/JarDirTest.java b/hotspot/test/testlibrary_tests/ctw/JarDirTest.java
index a784bda84ad..18ce6347b81 100644
--- a/hotspot/test/testlibrary_tests/ctw/JarDirTest.java
+++ b/hotspot/test/testlibrary_tests/ctw/JarDirTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -30,13 +30,13 @@
* java.base/jdk.internal.reflect
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @build sun.hotspot.WhiteBox Foo Bar
- * @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar
- * sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main JarDirTest prepare
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Dsun.hotspot.tools.ctw.logfile=ctw.log sun.hotspot.tools.ctw.CompileTheWorld jars/*
- * @run main JarDirTest check ctw.log
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox Foo Bar
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run driver JarDirTest prepare
+ * @run driver JarDirTest compile jars/*
+ * @run driver JarDirTest check
* @summary testing of CompileTheWorld :: jars in directory
* @author igor.ignatyev@oracle.com
*/
diff --git a/hotspot/test/testlibrary_tests/ctw/JarsTest.java b/hotspot/test/testlibrary_tests/ctw/JarsTest.java
index 16af1639854..cae3f7b7193 100644
--- a/hotspot/test/testlibrary_tests/ctw/JarsTest.java
+++ b/hotspot/test/testlibrary_tests/ctw/JarsTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -30,13 +30,13 @@
* java.base/jdk.internal.reflect
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @build sun.hotspot.WhiteBox Foo Bar
- * @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar
- * sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main JarsTest prepare
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Dsun.hotspot.tools.ctw.logfile=ctw.log sun.hotspot.tools.ctw.CompileTheWorld foo.jar bar.jar
- * @run main JarsTest check ctw.log
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox Foo Bar
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run driver JarsTest prepare
+ * @run driver JarsTest compile foo.jar bar.jar
+ * @run driver JarsTest check
* @summary testing of CompileTheWorld :: jars
* @author igor.ignatyev@oracle.com
*/
diff --git a/hotspot/test/testlibrary_tests/whitebox/vm_flags/BooleanTest.java b/hotspot/test/testlibrary_tests/whitebox/vm_flags/BooleanTest.java
index 302f77c3d31..79830375479 100644
--- a/hotspot/test/testlibrary_tests/whitebox/vm_flags/BooleanTest.java
+++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/BooleanTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -28,7 +28,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management/sun.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @build sun.hotspot.WhiteBox
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
diff --git a/jdk/.hgtags b/jdk/.hgtags
index 8140d627ca0..5a7c6ba2850 100644
--- a/jdk/.hgtags
+++ b/jdk/.hgtags
@@ -397,3 +397,4 @@ d27bab22ff62823902d93d1d35ca397cfd50d059 jdk-9+151
a20f2cf90762673e1bc4980fd6597e70a2578045 jdk-9+152
1c4411322327aea3f91011ec3977a12a05b09629 jdk-9+153
c97e7a8b8da062b9070df442f9cf308e10845fb7 jdk-9+154
+e170c858888e83d5c0994504599b6ed7a1fb0cfc jdk-9+155
diff --git a/jdk/make/copy/Copy-java.management.gmk b/jdk/make/copy/Copy-jdk.management.agent.gmk
similarity index 96%
rename from jdk/make/copy/Copy-java.management.gmk
rename to jdk/make/copy/Copy-jdk.management.agent.gmk
index 32348570198..6910ca2caa1 100644
--- a/jdk/make/copy/Copy-java.management.gmk
+++ b/jdk/make/copy/Copy-jdk.management.agent.gmk
@@ -28,7 +28,7 @@ include CopyCommon.gmk
################################################################################
MGMT_CONF_DIR := $(CONF_DST_DIR)/management
-MGMT_CONF_SRC := $(JDK_TOPDIR)/src/java.management/share/conf
+MGMT_CONF_SRC := $(JDK_TOPDIR)/src/jdk.management.agent/share/conf
MGMT_SRC_FILES := $(wildcard $(MGMT_CONF_SRC)/*)
MGMT_TARGET_FILES := $(subst $(MGMT_CONF_SRC),$(MGMT_CONF_DIR),$(MGMT_SRC_FILES))
diff --git a/jdk/make/gensrc/Gensrc-java.management.gmk b/jdk/make/gensrc/Gensrc-jdk.management.agent.gmk
similarity index 87%
rename from jdk/make/gensrc/Gensrc-java.management.gmk
rename to jdk/make/gensrc/Gensrc-jdk.management.agent.gmk
index 771392466fd..726a6f3cb57 100644
--- a/jdk/make/gensrc/Gensrc-java.management.gmk
+++ b/jdk/make/gensrc/Gensrc-jdk.management.agent.gmk
@@ -25,15 +25,12 @@
include GensrcCommon.gmk
-# Hook to include the corresponding custom file, if present.
-$(eval $(call IncludeCustomExtension, jdk, gensrc/Gensrc-java.management.gmk))
-
################################################################################
include GensrcProperties.gmk
$(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \
- SRC_DIRS := $(JDK_TOPDIR)/src/java.management/share/classes/sun/management/resources, \
+ SRC_DIRS := $(JDK_TOPDIR)/src/jdk.management.agent/share/classes/jdk/internal/agent/resources, \
CLASS := ListResourceBundle, \
))
diff --git a/jdk/make/lib/Lib-java.management.gmk b/jdk/make/lib/Lib-java.management.gmk
index 2533f786ec3..1847e2eb681 100644
--- a/jdk/make/lib/Lib-java.management.gmk
+++ b/jdk/make/lib/Lib-java.management.gmk
@@ -30,8 +30,7 @@ $(eval $(call IncludeCustomExtension, jdk, lib/Lib-java.management.gmk))
################################################################################
-LIBMANAGEMENT_SRC += $(JDK_TOPDIR)/src/java.management/share/native/libmanagement \
- $(JDK_TOPDIR)/src/java.management/$(OPENJDK_TARGET_OS_TYPE)/native/libmanagement
+LIBMANAGEMENT_SRC += $(JDK_TOPDIR)/src/java.management/share/native/libmanagement
LIBMANAGEMENT_CFLAGS := -I$(JDK_TOPDIR)/src/java.management/share/native/include \
$(addprefix -I,$(LIBMANAGEMENT_SRC)) \
-I$(SUPPORT_OUTPUTDIR)/headers/java.management \
diff --git a/jdk/make/lib/Lib-java.security.jgss.gmk b/jdk/make/lib/Lib-java.security.jgss.gmk
index 6f37b623288..56b290bbe3b 100644
--- a/jdk/make/lib/Lib-java.security.jgss.gmk
+++ b/jdk/make/lib/Lib-java.security.jgss.gmk
@@ -53,7 +53,7 @@ endif
################################################################################
-ifneq ($(BUILD_CRYPTO), no)
+ifneq ($(BUILD_CRYPTO), false)
BUILD_LIBKRB5_NAME :=
ifeq ($(OPENJDK_TARGET_OS), windows)
BUILD_LIBKRB5_NAME := w2k_lsa_auth
diff --git a/jdk/make/lib/Lib-jdk.crypto.ec.gmk b/jdk/make/lib/Lib-jdk.crypto.ec.gmk
index fa0d1ff8893..8f592374f91 100644
--- a/jdk/make/lib/Lib-jdk.crypto.ec.gmk
+++ b/jdk/make/lib/Lib-jdk.crypto.ec.gmk
@@ -27,7 +27,7 @@ include LibCommon.gmk
################################################################################
-ifeq ($(ENABLE_INTREE_EC), yes)
+ifeq ($(ENABLE_INTREE_EC), true)
LIBSUNEC_SRC := $(JDK_TOPDIR)/src/jdk.crypto.ec/share/native/libsunec
BUILD_LIBSUNEC_FLAGS := $(addprefix -I, $(SUNEC_SRC))
diff --git a/jdk/make/lib/Lib-jdk.management.agent.gmk b/jdk/make/lib/Lib-jdk.management.agent.gmk
new file mode 100644
index 00000000000..46e77281acc
--- /dev/null
+++ b/jdk/make/lib/Lib-jdk.management.agent.gmk
@@ -0,0 +1,59 @@
+#
+# 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.
+#
+
+include LibCommon.gmk
+
+################################################################################
+
+LIBMANAGEMENT_AGENT_SRC += $(JDK_TOPDIR)/src/jdk.management.agent/$(OPENJDK_TARGET_OS_TYPE)/native/libmanagement_agent
+LIBMANAGEMENT_AGENT_CFLAGS := $(addprefix -I,$(LIBMANAGEMENT_AGENT_SRC)) \
+ -I$(SUPPORT_OUTPUTDIR)/headers/jdk.management.agent \
+ $(LIBJAVA_HEADER_FLAGS) \
+ #
+
+$(eval $(call SetupNativeCompilation,BUILD_LIBMANAGEMENT_AGENT, \
+ LIBRARY := management_agent, \
+ OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
+ SRC := $(LIBMANAGEMENT_AGENT_SRC), \
+ OPTIMIZATION := LOW, \
+ CFLAGS := $(CFLAGS_JDKLIB) $(LIBMANAGEMENT_AGENT_CFLAGS), \
+ MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libmanagement_agent/mapfile-vers, \
+ LDFLAGS := $(LDFLAGS_JDKLIB) \
+ $(call SET_SHARED_LIBRARY_ORIGIN), \
+ LIBS := $(JDKLIB_LIBS), \
+ LIBS_windows := $(WIN_JAVA_LIB) advapi32.lib, \
+ VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
+ RC_FLAGS := $(RC_FLAGS) \
+ -D "JDK_FNAME=management_agent.dll" \
+ -D "JDK_INTERNAL_NAME=management_agent" \
+ -D "JDK_FTYPE=0x2L", \
+ OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libmanagement_agent, \
+))
+
+$(BUILD_LIBMANAGEMENT_AGENT): $(call FindLib, java.base, java)
+
+TARGETS += $(BUILD_LIBMANAGEMENT_AGENT)
+
+################################################################################
diff --git a/jdk/make/lib/NetworkingLibraries.gmk b/jdk/make/lib/NetworkingLibraries.gmk
index 6b110f8d72e..90257b25ff0 100644
--- a/jdk/make/lib/NetworkingLibraries.gmk
+++ b/jdk/make/lib/NetworkingLibraries.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2015, 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
@@ -44,8 +44,9 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBNET, \
LIBS_linux := $(LIBDL) -lpthread, \
LIBS_solaris := -lnsl -lsocket $(LIBDL) -lc, \
LIBS_aix := $(LIBDL),\
- LIBS_windows := ws2_32.lib jvm.lib secur32.lib iphlpapi.lib \
+ LIBS_windows := ws2_32.lib jvm.lib secur32.lib iphlpapi.lib winhttp.lib \
delayimp.lib $(WIN_JAVA_LIB) advapi32.lib, \
+ LIBS_macosx := -framework CoreFoundation -framework CoreServices, \
VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
RC_FLAGS := $(RC_FLAGS) \
-D "JDK_FNAME=net.dll" \
diff --git a/jdk/make/mapfiles/libmanagement/mapfile-vers b/jdk/make/mapfiles/libmanagement/mapfile-vers
index 228ef93abb6..2b3a81302ba 100644
--- a/jdk/make/mapfiles/libmanagement/mapfile-vers
+++ b/jdk/make/mapfiles/libmanagement/mapfile-vers
@@ -28,7 +28,6 @@
SUNWprivate_1.1 {
global:
Java_sun_management_ClassLoadingImpl_setVerboseClass;
- Java_sun_management_FileSystemImpl_isAccessUserOnly0;
Java_sun_management_GarbageCollectorImpl_getCollectionCount;
Java_sun_management_GarbageCollectorImpl_getCollectionTime;
Java_sun_management_HotspotThread_getInternalThreadCount;
diff --git a/jdk/make/mapfiles/libmanagement_agent/mapfile-vers b/jdk/make/mapfiles/libmanagement_agent/mapfile-vers
new file mode 100644
index 00000000000..935690c3b64
--- /dev/null
+++ b/jdk/make/mapfiles/libmanagement_agent/mapfile-vers
@@ -0,0 +1,34 @@
+#
+# 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.
+#
+
+# Define library interface.
+
+SUNWprivate_1.1 {
+ global:
+ Java_jdk_internal_agent_FileSystemImpl_isAccessUserOnly0;
+ JNI_OnLoad;
+ local:
+ *;
+};
diff --git a/jdk/make/mapfiles/libnet/mapfile-vers b/jdk/make/mapfiles/libnet/mapfile-vers
index e3c1087afb9..6967a4dcfcc 100644
--- a/jdk/make/mapfiles/libnet/mapfile-vers
+++ b/jdk/make/mapfiles/libnet/mapfile-vers
@@ -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
@@ -97,7 +97,7 @@ SUNWprivate_1.1 {
Java_sun_net_sdp_SdpSupport_convert0;
Java_sun_net_sdp_SdpSupport_create0;
Java_sun_net_spi_DefaultProxySelector_init;
- Java_sun_net_spi_DefaultProxySelector_getSystemProxy;
+ Java_sun_net_spi_DefaultProxySelector_getSystemProxies;
NET_SockaddrToInetAddress;
NET_SockaddrEqualsInetAddress;
NET_InetAddressToSockaddr;
diff --git a/jdk/make/mapfiles/libunpack/mapfile-vers-unpack200-solaris-sparc b/jdk/make/mapfiles/libunpack/mapfile-vers-unpack200-solaris-sparc
index 63f2a41a478..d8942de5c25 100644
--- a/jdk/make/mapfiles/libunpack/mapfile-vers-unpack200-solaris-sparc
+++ b/jdk/make/mapfiles/libunpack/mapfile-vers-unpack200-solaris-sparc
@@ -28,6 +28,7 @@
SUNWprivate_1.1 {
global:
# These are needed by the c runtime in SS12u4
+ environ;
_environ;
__environ_lock;
___Argv;
diff --git a/jdk/make/rmic/Rmic-java.management.gmk b/jdk/make/rmic/Rmic-java.management.rmi.gmk
similarity index 94%
rename from jdk/make/rmic/Rmic-java.management.gmk
rename to jdk/make/rmic/Rmic-java.management.rmi.gmk
index 0feaac3b88b..50c090c1deb 100644
--- a/jdk/make/rmic/Rmic-java.management.gmk
+++ b/jdk/make/rmic/Rmic-java.management.rmi.gmk
@@ -39,8 +39,8 @@ JMX_RMI_CLASSES := javax.management.remote.rmi.RMIConnectionImpl \
# into the stub classes dir.
$(eval $(call SetupRMICompilation,RMI_GEN, \
CLASSES := $(JMX_RMI_CLASSES), \
- CLASSES_DIR := $(CLASSES_DIR)/java.management, \
- STUB_CLASSES_DIR := $(RMIC_GENSRC_DIR)/java.management, \
+ CLASSES_DIR := $(CLASSES_DIR)/java.management.rmi, \
+ STUB_CLASSES_DIR := $(RMIC_GENSRC_DIR)/java.management.rmi, \
RUN_V12 := true, \
KEEP_GENERATED := true, \
))
diff --git a/jdk/make/src/classes/build/tools/jigsaw/GenGraphs.java b/jdk/make/src/classes/build/tools/jigsaw/GenGraphs.java
index 99f6d0f8bd7..4de7b5c719a 100644
--- a/jdk/make/src/classes/build/tools/jigsaw/GenGraphs.java
+++ b/jdk/make/src/classes/build/tools/jigsaw/GenGraphs.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -126,7 +126,7 @@ public class GenGraphs {
ranks.add(Set.of("java.compiler", "java.instrument"));
ranks.add(Set.of("java.desktop", "java.management"));
ranks.add(Set.of("java.corba", "java.xml.ws"));
- ranks.add(Set.of("java.xml.bind", "java.annotations.common"));
+ ranks.add(Set.of("java.xml.bind", "java.xml.ws.annotation"));
}
diff --git a/jdk/make/src/classes/build/tools/jigsaw/technology-summary.html b/jdk/make/src/classes/build/tools/jigsaw/technology-summary.html
index 8414f3521ec..e42ed25b728 100644
--- a/jdk/make/src/classes/build/tools/jigsaw/technology-summary.html
+++ b/jdk/make/src/classes/build/tools/jigsaw/technology-summary.html
@@ -588,7 +588,7 @@ td { font-family: monospace; padding: 4px; border: 1px solid; }
Common Annotations |
250 |
Java SE,EE |
-java.annotations.common |
+java.xml.ws.annotation |
Original JSR |
Formerly a Standalone Technology (unlisted) |
SE |
diff --git a/jdk/src/java.base/aix/classes/sun/nio/fs/DefaultFileSystemProvider.java b/jdk/src/java.base/aix/classes/sun/nio/fs/DefaultFileSystemProvider.java
new file mode 100644
index 00000000000..8c33d7e5a59
--- /dev/null
+++ b/jdk/src/java.base/aix/classes/sun/nio/fs/DefaultFileSystemProvider.java
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+package sun.nio.fs;
+
+import java.nio.file.spi.FileSystemProvider;
+
+/**
+ * Creates this platform's default FileSystemProvider.
+ */
+
+public class DefaultFileSystemProvider {
+ private DefaultFileSystemProvider() { }
+
+ /**
+ * Returns the default FileSystemProvider.
+ */
+ public static FileSystemProvider create() {
+ return new AixFileSystemProvider();
+ }
+}
diff --git a/jdk/src/java.base/linux/classes/sun/nio/fs/DefaultFileSystemProvider.java b/jdk/src/java.base/linux/classes/sun/nio/fs/DefaultFileSystemProvider.java
new file mode 100644
index 00000000000..82a06b7ea50
--- /dev/null
+++ b/jdk/src/java.base/linux/classes/sun/nio/fs/DefaultFileSystemProvider.java
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+package sun.nio.fs;
+
+import java.nio.file.spi.FileSystemProvider;
+
+/**
+ * Creates this platform's default FileSystemProvider.
+ */
+
+public class DefaultFileSystemProvider {
+ private DefaultFileSystemProvider() { }
+
+ /**
+ * Returns the default FileSystemProvider.
+ */
+ public static FileSystemProvider create() {
+ return new LinuxFileSystemProvider();
+ }
+}
diff --git a/jdk/src/java.base/macosx/classes/sun/nio/fs/DefaultFileSystemProvider.java b/jdk/src/java.base/macosx/classes/sun/nio/fs/DefaultFileSystemProvider.java
new file mode 100644
index 00000000000..917d9f3a25b
--- /dev/null
+++ b/jdk/src/java.base/macosx/classes/sun/nio/fs/DefaultFileSystemProvider.java
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+package sun.nio.fs;
+
+import java.nio.file.spi.FileSystemProvider;
+
+/**
+ * Creates this platform's default FileSystemProvider.
+ */
+
+public class DefaultFileSystemProvider {
+ private DefaultFileSystemProvider() { }
+
+ /**
+ * Returns the default FileSystemProvider.
+ */
+ public static FileSystemProvider create() {
+ return new MacOSXFileSystemProvider();
+ }
+}
diff --git a/jdk/src/java.base/macosx/native/libnet/DefaultProxySelector.c b/jdk/src/java.base/macosx/native/libnet/DefaultProxySelector.c
new file mode 100644
index 00000000000..ab6f465da40
--- /dev/null
+++ b/jdk/src/java.base/macosx/native/libnet/DefaultProxySelector.c
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017 SAP SE. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include
+#include
+#include
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jvm.h"
+#include "jvm_md.h"
+
+#include "proxy_util.h"
+
+#include "sun_net_spi_DefaultProxySelector.h"
+
+
+/**
+ * For more information on how to use the APIs in "CFProxySupport.h" see:
+ * https://developer.apple.com/legacy/library/samplecode/CFProxySupportTool/Introduction/Intro.html
+ */
+
+#define kResolveProxyRunLoopMode CFSTR("sun.net.spi.DefaultProxySelector")
+
+#define BUFFER_SIZE 1024
+
+/* Callback for CFNetworkExecuteProxyAutoConfigurationURL. */
+static void proxyUrlCallback(void * client, CFArrayRef proxies, CFErrorRef error) {
+ /* client is a pointer to a CFTypeRef and holds either proxies or an error. */
+ CFTypeRef* resultPtr = (CFTypeRef *)client;
+
+ if (error != NULL) {
+ *resultPtr = CFRetain(error);
+ } else {
+ *resultPtr = CFRetain(proxies);
+ }
+ CFRunLoopStop(CFRunLoopGetCurrent());
+}
+
+/*
+ * Returns a new array of proxies containing all the given non-PAC proxies as
+ * well as the results of executing all the given PAC-based proxies, for the
+ * specified URL. 'proxies' is a list that may contain both PAC and non-PAC
+ * proxies.
+ */
+static CFArrayRef createExpandedProxiesArray(CFArrayRef proxies, CFURLRef url) {
+
+ CFIndex count;
+ CFIndex index;
+ CFMutableArrayRef expandedProxiesArray;
+
+ expandedProxiesArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ if (expandedProxiesArray == NULL)
+ return NULL;
+
+ /* Iterate over the array of proxies */
+ count = CFArrayGetCount(proxies);
+ for (index = 0; index < count ; index++) {
+ CFDictionaryRef currentProxy;
+ CFStringRef proxyType;
+
+ currentProxy = (CFDictionaryRef) CFArrayGetValueAtIndex(proxies, index);
+ if(currentProxy == NULL) {
+ CFRelease(expandedProxiesArray);
+ return NULL;
+ }
+ proxyType = (CFStringRef) CFDictionaryGetValue(currentProxy, kCFProxyTypeKey);
+ if (proxyType == NULL) {
+ CFRelease(expandedProxiesArray);
+ return NULL;
+ }
+
+ if (!CFEqual(proxyType, kCFProxyTypeAutoConfigurationURL)) {
+ /* Non-PAC entry, just copy it to the new array */
+ CFArrayAppendValue(expandedProxiesArray, currentProxy);
+ } else {
+ /* PAC-based URL, execute its script append its results */
+ CFRunLoopSourceRef runLoop;
+ CFURLRef scriptURL;
+ CFTypeRef result = NULL;
+ CFStreamClientContext context = { 0, &result, NULL, NULL, NULL };
+ CFTimeInterval timeout = 5;
+
+ scriptURL = CFDictionaryGetValue(currentProxy, kCFProxyAutoConfigurationURLKey);
+
+ runLoop = CFNetworkExecuteProxyAutoConfigurationURL(scriptURL, url, proxyUrlCallback,
+ &context);
+ if (runLoop != NULL) {
+ /*
+ * Despite the fact that CFNetworkExecuteProxyAutoConfigurationURL has
+ * neither a "Create" nor a "Copy" in the name, we are required to
+ * release the return CFRunLoopSourceRef .
+ */
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoop, kResolveProxyRunLoopMode);
+ CFRunLoopRunInMode(kResolveProxyRunLoopMode, timeout, false);
+ CFRunLoopRemoveSource(CFRunLoopGetCurrent(), runLoop, kResolveProxyRunLoopMode);
+
+ /*
+ * Once the runloop returns, there will be either an error result or
+ * a proxies array result. Do the appropriate thing with that result.
+ */
+ if (result != NULL) {
+ if (CFGetTypeID(result) == CFArrayGetTypeID()) {
+ /*
+ * Append the new array from the PAC list - it contains
+ * only non-PAC entries.
+ */
+ CFArrayAppendArray(expandedProxiesArray, result,
+ CFRangeMake(0, CFArrayGetCount(result)));
+ }
+ CFRelease(result);
+ }
+ CFRelease(runLoop);
+ }
+ }
+ }
+ return expandedProxiesArray;
+}
+
+
+/*
+ * Class: sun_net_spi_DefaultProxySelector
+ * Method: init
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL
+Java_sun_net_spi_DefaultProxySelector_init(JNIEnv *env, jclass clazz) {
+ if (!initJavaClass(env)) {
+ return JNI_FALSE;
+ }
+ return JNI_TRUE;
+}
+
+
+/*
+ * Class: sun_net_spi_DefaultProxySelector
+ * Method: getSystemProxies
+ * Signature: ([Ljava/lang/String;Ljava/lang/String;)[Ljava/net/Proxy;
+ */
+JNIEXPORT jobjectArray JNICALL
+Java_sun_net_spi_DefaultProxySelector_getSystemProxies(JNIEnv *env,
+ jobject this,
+ jstring proto,
+ jstring host)
+{
+ CFDictionaryRef proxyDicRef = NULL;
+ CFURLRef urlRef = NULL;
+ bool proxyFound = false;
+ jobjectArray proxyArray = NULL;
+ const char *cproto;
+ const char *chost;
+
+ /* Get system proxy settings */
+ proxyDicRef = CFNetworkCopySystemProxySettings();
+ if (proxyDicRef == NULL) {
+ return NULL;
+ }
+
+ /* Create CFURLRef from proto and host */
+ cproto = (*env)->GetStringUTFChars(env, proto, NULL);
+ if (cproto != NULL) {
+ chost = (*env)->GetStringUTFChars(env, host, NULL);
+ if (chost != NULL) {
+ char* uri = NULL;
+ size_t protoLen = 0;
+ size_t hostLen = 0;
+
+ protoLen = strlen(cproto);
+ hostLen = strlen(chost);
+
+ /* Construct the uri, cproto + "://" + chost */
+ uri = malloc(protoLen + hostLen + 4);
+ if (uri != NULL) {
+ memcpy(uri, cproto, protoLen);
+ memcpy(uri + protoLen, "://", 3);
+ memcpy(uri + protoLen + 3, chost, hostLen + 1);
+
+ urlRef = CFURLCreateWithBytes(NULL, (const UInt8 *) uri, strlen(uri),
+ kCFStringEncodingUTF8, NULL);
+ free(uri);
+ }
+ (*env)->ReleaseStringUTFChars(env, host, chost);
+ }
+ (*env)->ReleaseStringUTFChars(env, proto, cproto);
+ }
+ if (urlRef != NULL) {
+ CFArrayRef urlProxyArrayRef = CFNetworkCopyProxiesForURL(urlRef, proxyDicRef);
+ if (urlProxyArrayRef != NULL) {
+ CFIndex count;
+ CFIndex index;
+
+ CFArrayRef expandedProxyArray = createExpandedProxiesArray(urlProxyArrayRef, urlRef);
+ CFRelease(urlProxyArrayRef);
+
+ if (expandedProxyArray == NULL) {
+ CFRelease(urlRef);
+ CFRelease(proxyDicRef);
+ return NULL;
+ }
+
+ count = CFArrayGetCount(expandedProxyArray);
+
+ proxyArray = (*env)->NewObjectArray(env, count, proxy_class, NULL);
+ if (proxyArray != NULL || (*env)->ExceptionCheck(env)) {
+ /* Iterate over the expanded array of proxies */
+ for (index = 0; index < count ; index++) {
+ CFDictionaryRef currentProxy;
+ CFStringRef proxyType;
+ jobject proxy = NULL;
+
+ currentProxy = (CFDictionaryRef) CFArrayGetValueAtIndex(expandedProxyArray,
+ index);
+ proxyType = (CFStringRef) CFDictionaryGetValue(currentProxy, kCFProxyTypeKey);
+ if (CFEqual(proxyType, kCFProxyTypeNone)) {
+ /* This entry states no proxy, therefore just add a NO_PROXY object. */
+ proxy = (*env)->GetStaticObjectField(env, proxy_class, pr_no_proxyID);
+ } else {
+ /*
+ * Create a proxy object for this entry.
+ * Differentiate between SOCKS and HTTP type.
+ */
+ jfieldID typeID = ptype_httpID;
+ if (CFEqual(proxyType, kCFProxyTypeSOCKS)) {
+ typeID = ptype_socksID;
+ }
+ CFNumberRef portNumberRef = (CFNumberRef)CFDictionaryGetValue(currentProxy,
+ (const void*)kCFProxyPortNumberKey);
+ if (portNumberRef != NULL) {
+ int port = 0;
+ if (CFNumberGetValue(portNumberRef, kCFNumberSInt32Type, &port)) {
+ CFStringRef hostNameRef = (CFStringRef)CFDictionaryGetValue(
+ currentProxy, (const void*)kCFProxyHostNameKey);
+ if (hostNameRef != NULL) {
+ char hostNameBuffer[BUFFER_SIZE];
+ if (CFStringGetCString(hostNameRef, hostNameBuffer,
+ BUFFER_SIZE, kCFStringEncodingUTF8)) {
+ proxy = createProxy(env, typeID, &hostNameBuffer[0], port);
+ }
+ }
+ }
+ }
+ }
+ if (proxy == NULL || (*env)->ExceptionCheck(env)) {
+ proxyArray = NULL;
+ break;
+ }
+ (*env)->SetObjectArrayElement(env, proxyArray, index, proxy);
+ if ((*env)->ExceptionCheck(env)) {
+ proxyArray = NULL;
+ break;
+ }
+ }
+ }
+ CFRelease(expandedProxyArray);
+ }
+ CFRelease(urlRef);
+ }
+ CFRelease(proxyDicRef);
+
+ return proxyArray;
+}
diff --git a/jdk/src/java.base/share/classes/com/sun/net/ssl/HostnameVerifier.java b/jdk/src/java.base/share/classes/com/sun/net/ssl/HostnameVerifier.java
index 1a78995ec01..f6413802395 100644
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/HostnameVerifier.java
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/HostnameVerifier.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, 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
@@ -38,9 +38,8 @@ package com.sun.net.ssl;
* @deprecated As of JDK 1.4, this implementation-specific class was
* replaced by {@link javax.net.ssl.HostnameVerifier} and
* {@link javax.net.ssl.CertificateHostnameVerifier}.
- * This class is subject to removal in a future version of JDK.
*/
-@Deprecated(since="1.4", forRemoval=true)
+@Deprecated(since="1.4")
public interface HostnameVerifier {
/**
* Verify that the hostname from the URL is an acceptable
diff --git a/jdk/src/java.base/share/classes/com/sun/net/ssl/HttpsURLConnection.java b/jdk/src/java.base/share/classes/com/sun/net/ssl/HttpsURLConnection.java
index 895b17ac578..8a1e69f9d5f 100644
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/HttpsURLConnection.java
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/HttpsURLConnection.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, 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
@@ -44,9 +44,8 @@ import javax.net.ssl.SSLPeerUnverifiedException;
*
* @deprecated As of JDK 1.4, this implementation-specific class was
* replaced by {@link javax.net.ssl.HttpsURLConnection}.
- * This class is subject to removal in a future version of JDK.
*/
-@Deprecated(since="1.4", forRemoval=true)
+@Deprecated(since="1.4")
public abstract
class HttpsURLConnection extends HttpURLConnection
{
diff --git a/jdk/src/java.base/share/classes/com/sun/net/ssl/KeyManager.java b/jdk/src/java.base/share/classes/com/sun/net/ssl/KeyManager.java
index 814d619db8d..903e2578e79 100644
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/KeyManager.java
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/KeyManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, 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
@@ -36,8 +36,7 @@ package com.sun.net.ssl;
*
* @deprecated As of JDK 1.4, this implementation-specific class was
* replaced by {@link javax.net.ssl.KeyManager}.
- * This class is subject to removal in a future version of JDK.
*/
-@Deprecated(since="1.4", forRemoval=true)
+@Deprecated(since="1.4")
public interface KeyManager {
}
diff --git a/jdk/src/java.base/share/classes/com/sun/net/ssl/KeyManagerFactory.java b/jdk/src/java.base/share/classes/com/sun/net/ssl/KeyManagerFactory.java
index 8c0caed6b0e..c79ef43c2b6 100644
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/KeyManagerFactory.java
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/KeyManagerFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, 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
@@ -39,9 +39,8 @@ import java.security.*;
*
* @deprecated As of JDK 1.4, this implementation-specific class was
* replaced by {@link javax.net.ssl.KeyManagerFactory}.
- * This class is subject to removal in a future version of JDK.
*/
-@Deprecated(since="1.4", forRemoval=true)
+@Deprecated(since="1.4")
public class KeyManagerFactory {
// The provider
private Provider provider;
diff --git a/jdk/src/java.base/share/classes/com/sun/net/ssl/KeyManagerFactorySpi.java b/jdk/src/java.base/share/classes/com/sun/net/ssl/KeyManagerFactorySpi.java
index 19b2a68b6f5..eb72c96954d 100644
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/KeyManagerFactorySpi.java
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/KeyManagerFactorySpi.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, 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
@@ -41,9 +41,8 @@ import java.security.*;
*
* @deprecated As of JDK 1.4, this implementation-specific class was
* replaced by {@link javax.net.ssl.KeyManagerFactorySpi}.
- * This class is subject to removal in a future version of JDK.
*/
-@Deprecated(since="1.4", forRemoval=true)
+@Deprecated(since="1.4")
public abstract class KeyManagerFactorySpi {
/**
* Initializes this factory with a source of key material. The
diff --git a/jdk/src/java.base/share/classes/com/sun/net/ssl/SSLContext.java b/jdk/src/java.base/share/classes/com/sun/net/ssl/SSLContext.java
index 6f0cbf9fd9b..d23148b18f8 100644
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/SSLContext.java
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/SSLContext.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, 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
@@ -44,9 +44,8 @@ import sun.security.ssl.SSLServerSocketFactoryImpl;
*
* @deprecated As of JDK 1.4, this implementation-specific class was
* replaced by {@link javax.net.ssl.SSLContext}.
- * This class is subject to removal in a future version of JDK.
*/
-@Deprecated(since="1.4", forRemoval=true)
+@Deprecated(since="1.4")
public class SSLContext {
private Provider provider;
diff --git a/jdk/src/java.base/share/classes/com/sun/net/ssl/SSLContextSpi.java b/jdk/src/java.base/share/classes/com/sun/net/ssl/SSLContextSpi.java
index 0a663b8ff3f..993f86f614d 100644
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/SSLContextSpi.java
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/SSLContextSpi.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, 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
@@ -43,9 +43,8 @@ import javax.net.ssl.*;
*
* @deprecated As of JDK 1.4, this implementation-specific class was
* replaced by {@link javax.net.ssl.SSLContextSpi}.
- * This class is subject to removal in a future version of JDK.
*/
-@Deprecated(since="1.4", forRemoval=true)
+@Deprecated(since="1.4")
public abstract class SSLContextSpi {
/**
* Initializes this context.
diff --git a/jdk/src/java.base/share/classes/com/sun/net/ssl/SSLPermission.java b/jdk/src/java.base/share/classes/com/sun/net/ssl/SSLPermission.java
index 9fd480b93f3..93469a0c867 100644
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/SSLPermission.java
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/SSLPermission.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, 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
@@ -97,9 +97,8 @@ import java.lang.SecurityManager;
*
* @deprecated As of JDK 1.4, this implementation-specific class was
* replaced by {@link javax.net.ssl.SSLPermission}.
- * This class is subject to removal in a future version of JDK.
*/
-@Deprecated(since="1.4", forRemoval=true)
+@Deprecated(since="1.4")
public final class SSLPermission extends BasicPermission {
private static final long serialVersionUID = -2583684302506167542L;
diff --git a/jdk/src/java.base/share/classes/com/sun/net/ssl/TrustManager.java b/jdk/src/java.base/share/classes/com/sun/net/ssl/TrustManager.java
index 2856e30be40..376b111fd81 100644
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/TrustManager.java
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/TrustManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, 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
@@ -36,8 +36,7 @@ package com.sun.net.ssl;
*
* @deprecated As of JDK 1.4, this implementation-specific class was
* replaced by {@link javax.net.ssl.TrustManager}.
- * This class is subject to removal in a future version of JDK.
*/
-@Deprecated(since="1.4", forRemoval=true)
+@Deprecated(since="1.4")
public interface TrustManager {
}
diff --git a/jdk/src/java.base/share/classes/com/sun/net/ssl/TrustManagerFactory.java b/jdk/src/java.base/share/classes/com/sun/net/ssl/TrustManagerFactory.java
index 934210c618b..d011ce74ed1 100644
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/TrustManagerFactory.java
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/TrustManagerFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, 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
@@ -39,9 +39,8 @@ import java.security.*;
*
* @deprecated As of JDK 1.4, this implementation-specific class was
* replaced by {@link javax.net.ssl.TrustManagerFactory}.
- * This class is subject to removal in a future version of JDK.
*/
-@Deprecated(since="1.4", forRemoval=true)
+@Deprecated(since="1.4")
public class TrustManagerFactory {
// The provider
private Provider provider;
diff --git a/jdk/src/java.base/share/classes/com/sun/net/ssl/TrustManagerFactorySpi.java b/jdk/src/java.base/share/classes/com/sun/net/ssl/TrustManagerFactorySpi.java
index 62698a42d32..8ab1901c4ea 100644
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/TrustManagerFactorySpi.java
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/TrustManagerFactorySpi.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, 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
@@ -41,9 +41,8 @@ import java.security.*;
*
* @deprecated As of JDK 1.4, this implementation-specific class was
* replaced by {@link javax.net.ssl.TrustManagerFactorySpi}.
- * This class is subject to removal in a future version of JDK.
*/
-@Deprecated(since="1.4", forRemoval=true)
+@Deprecated(since="1.4")
public abstract class TrustManagerFactorySpi {
/**
* Initializes this factory with a source of certificate
diff --git a/jdk/src/java.base/share/classes/com/sun/net/ssl/X509KeyManager.java b/jdk/src/java.base/share/classes/com/sun/net/ssl/X509KeyManager.java
index cb4903171a7..8d4019c8721 100644
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/X509KeyManager.java
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/X509KeyManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, 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
@@ -41,9 +41,8 @@ import java.security.cert.X509Certificate;
*
* @deprecated As of JDK 1.4, this implementation-specific class was
* replaced by {@link javax.net.ssl.X509KeyManager}.
- * This class is subject to removal in a future version of JDK.
*/
-@Deprecated(since="1.4", forRemoval=true)
+@Deprecated(since="1.4")
public interface X509KeyManager extends KeyManager {
/**
* Get the matching aliases for authenticating the client side of a secure
diff --git a/jdk/src/java.base/share/classes/com/sun/net/ssl/X509TrustManager.java b/jdk/src/java.base/share/classes/com/sun/net/ssl/X509TrustManager.java
index 024d33a16f5..041c3e6f587 100644
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/X509TrustManager.java
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/X509TrustManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, 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
@@ -40,9 +40,8 @@ import java.security.cert.X509Certificate;
*
* @deprecated As of JDK 1.4, this implementation-specific class was
* replaced by {@link javax.net.ssl.X509TrustManager}.
- * This class is subject to removal in a future version of JDK.
*/
-@Deprecated(since="1.4", forRemoval=true)
+@Deprecated(since="1.4")
public interface X509TrustManager extends TrustManager {
/**
* Given the partial or complete certificate chain
diff --git a/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/ssl/Provider.java b/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/ssl/Provider.java
index f438e6401fd..f158f88bda1 100644
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/ssl/Provider.java
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/ssl/Provider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -31,10 +31,8 @@ import sun.security.ssl.SunJSSE;
* Main class for the SunJSSE provider. The actual code was moved to the
* class sun.security.ssl.SunJSSE, but for backward compatibility we
* continue to use this class as the main Provider class.
- *
- * @deprecated This class is subject to removal in a future version of JDK.
*/
-@Deprecated(since="9", forRemoval=true)
+@Deprecated(since="9")
public final class Provider extends SunJSSE {
private static final long serialVersionUID = 3231825739635378733L;
diff --git a/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/ssl/X509ExtendedTrustManager.java b/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/ssl/X509ExtendedTrustManager.java
index 3db161b83e4..2af41b97fe5 100644
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/ssl/X509ExtendedTrustManager.java
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/ssl/X509ExtendedTrustManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -54,9 +54,8 @@ import java.security.cert.CertificateException;
*
* @since 1.6
* @author Xuelei Fan
- * @deprecated This class is subject to removal in a future version of JDK.
*/
-@Deprecated(since="9", forRemoval=true)
+@Deprecated(since="9")
public abstract class X509ExtendedTrustManager implements X509TrustManager {
/**
* Constructor used by subclasses only.
diff --git a/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/www/protocol/https/DelegateHttpsURLConnection.java b/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/www/protocol/https/DelegateHttpsURLConnection.java
index 8cb1de2b22c..872694f6176 100644
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/www/protocol/https/DelegateHttpsURLConnection.java
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/www/protocol/https/DelegateHttpsURLConnection.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -52,9 +52,8 @@ import sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection;
* of protocol implementation (this one)
* com.sun.net.ssl.HttpURLConnection is used in the com.sun version.
*
- * @deprecated This class is subject to removal in a future version of JDK.
*/
-@Deprecated(since="9", forRemoval=true)
+@Deprecated(since="9")
@SuppressWarnings("deprecation") // HttpsURLConnection is deprecated
public class DelegateHttpsURLConnection extends AbstractDelegateHttpsURLConnection {
diff --git a/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/www/protocol/https/Handler.java b/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/www/protocol/https/Handler.java
index d52e972646e..42874841bfc 100644
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/www/protocol/https/Handler.java
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/www/protocol/https/Handler.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -34,9 +34,8 @@ import java.net.Proxy;
* only. The HTTPS implementation can now be found in
* sun.net.www.protocol.https.
*
- * @deprecated This class is subject to removal in a future version of JDK.
*/
-@Deprecated(since="9", forRemoval=true)
+@Deprecated(since="9")
public class Handler extends sun.net.www.protocol.https.Handler {
public Handler() {
diff --git a/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnectionOldImpl.java b/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnectionOldImpl.java
index 7ae757fe6f2..fc9f7ce861b 100644
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnectionOldImpl.java
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnectionOldImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -60,13 +60,12 @@ import sun.net.www.http.HttpClient;
* needs to implement all public methods in it's super class and all
* the way to Object.
*
- * @deprecated This class is subject to removal in a future version of JDK.
*/
// For both copies of the file, uncomment one line and comment the other
// public class HttpsURLConnectionImpl
// extends javax.net.ssl.HttpsURLConnection {
-@Deprecated(since="9", forRemoval=true)
+@Deprecated(since="9")
@SuppressWarnings("deprecation") // HttpsURLConnection is deprecated
public class HttpsURLConnectionOldImpl
extends com.sun.net.ssl.HttpsURLConnection {
diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/Layer.java b/jdk/src/java.base/share/classes/java/lang/reflect/Layer.java
index 4b4588c3c01..9eaf90d0ca8 100644
--- a/jdk/src/java.base/share/classes/java/lang/reflect/Layer.java
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/Layer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -458,7 +458,7 @@ public final class Layer {
loader.initRemotePackageMap(cf, parents);
Layer layer = new Layer(cf, parents, mn -> loader);
return new Controller(layer);
- } catch (IllegalArgumentException e) {
+ } catch (IllegalArgumentException | IllegalStateException e) {
throw new LayerInstantiationException(e.getMessage());
}
}
@@ -526,7 +526,7 @@ public final class Layer {
try {
Layer layer = new Layer(cf, parents, pool::loaderFor);
return new Controller(layer);
- } catch (IllegalArgumentException e) {
+ } catch (IllegalArgumentException | IllegalStateException e) {
throw new LayerInstantiationException(e.getMessage());
}
}
@@ -610,9 +610,8 @@ public final class Layer {
try {
Layer layer = new Layer(cf, parents, clf);
return new Controller(layer);
- } catch (IllegalArgumentException iae) {
- // IAE is thrown by VM when defining the module fails
- throw new LayerInstantiationException(iae.getMessage());
+ } catch (IllegalArgumentException | IllegalStateException e) {
+ throw new LayerInstantiationException(e.getMessage());
}
}
diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/Module.java b/jdk/src/java.base/share/classes/java/lang/reflect/Module.java
index a71b4b320ab..5134b64caf8 100644
--- a/jdk/src/java.base/share/classes/java/lang/reflect/Module.java
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/Module.java
@@ -128,14 +128,8 @@ public final class Module implements AnnotatedElement {
Version version = descriptor.version().orElse(null);
String vs = Objects.toString(version, null);
String loc = Objects.toString(uri, null);
- Set packages = descriptor.packages();
- int n = packages.size();
- String[] array = new String[n];
- int i = 0;
- for (String pn : packages) {
- array[i++] = pn.replace('.', '/');
- }
- defineModule0(this, isOpen, vs, loc, array);
+ String[] packages = descriptor.packages().toArray(new String[0]);
+ defineModule0(this, isOpen, vs, loc, packages);
}
@@ -789,13 +783,12 @@ public final class Module implements AnnotatedElement {
// update VM first, just in case it fails
if (syncVM) {
- String pkgInternalForm = pn.replace('.', '/');
if (other == EVERYONE_MODULE) {
- addExportsToAll0(this, pkgInternalForm);
+ addExportsToAll0(this, pn);
} else if (other == ALL_UNNAMED_MODULE) {
- addExportsToAllUnnamed0(this, pkgInternalForm);
+ addExportsToAllUnnamed0(this, pn);
} else {
- addExports0(this, pkgInternalForm, other);
+ addExports0(this, pn, other);
}
}
@@ -1021,7 +1014,7 @@ public final class Module implements AnnotatedElement {
// update VM first, just in case it fails
if (syncVM)
- addPackage0(this, pn.replace('.', '/'));
+ addPackage0(this, pn);
// replace with new set
this.extraPackages = extraPackages; // volatile write
@@ -1180,8 +1173,7 @@ public final class Module implements AnnotatedElement {
if (descriptor.isOpen()) {
assert descriptor.opens().isEmpty();
for (String source : descriptor.packages()) {
- String sourceInternalForm = source.replace('.', '/');
- addExportsToAll0(m, sourceInternalForm);
+ addExportsToAll0(m, source);
}
return;
}
@@ -1192,7 +1184,6 @@ public final class Module implements AnnotatedElement {
// process the open packages first
for (Opens opens : descriptor.opens()) {
String source = opens.source();
- String sourceInternalForm = source.replace('.', '/');
if (opens.isQualified()) {
// qualified opens
@@ -1201,7 +1192,7 @@ public final class Module implements AnnotatedElement {
// only open to modules that are in this configuration
Module m2 = nameToModule.get(target);
if (m2 != null) {
- addExports0(m, sourceInternalForm, m2);
+ addExports0(m, source, m2);
targets.add(m2);
}
}
@@ -1210,7 +1201,7 @@ public final class Module implements AnnotatedElement {
}
} else {
// unqualified opens
- addExportsToAll0(m, sourceInternalForm);
+ addExportsToAll0(m, source);
openPackages.put(source, EVERYONE_SET);
}
}
@@ -1218,7 +1209,6 @@ public final class Module implements AnnotatedElement {
// next the exports, skipping exports when the package is open
for (Exports exports : descriptor.exports()) {
String source = exports.source();
- String sourceInternalForm = source.replace('.', '/');
// skip export if package is already open to everyone
Set openToTargets = openPackages.get(source);
@@ -1234,7 +1224,7 @@ public final class Module implements AnnotatedElement {
if (m2 != null) {
// skip qualified export if already open to m2
if (openToTargets == null || !openToTargets.contains(m2)) {
- addExports0(m, sourceInternalForm, m2);
+ addExports0(m, source, m2);
targets.add(m2);
}
}
@@ -1245,7 +1235,7 @@ public final class Module implements AnnotatedElement {
} else {
// unqualified exports
- addExportsToAll0(m, sourceInternalForm);
+ addExportsToAll0(m, source);
exportedPackages.put(source, EVERYONE_SET);
}
}
diff --git a/jdk/src/java.base/share/classes/java/net/doc-files/net-properties.html b/jdk/src/java.base/share/classes/java/net/doc-files/net-properties.html
index 76c82b5b81e..f4bf1243681 100644
--- a/jdk/src/java.base/share/classes/java/net/doc-files/net-properties.html
+++ b/jdk/src/java.base/share/classes/java/net/doc-files/net-properties.html
@@ -149,7 +149,7 @@ of proxies.
the user.name property will be used with no password.
java.net.useSystemProxies (default: false)
- On recent Windows systems and on Gnome 2.x systems it is possible to
+ On Windows systems, macOS systems and on Gnome systems it is possible to
tell the java.net stack, setting this property to true, to use
the system proxy settings (both these systems let you set proxies
globally through their user interface). Note that this property is
diff --git a/jdk/src/java.base/share/classes/java/security/Certificate.java b/jdk/src/java.base/share/classes/java/security/Certificate.java
index 4fe278aa431..2d3db8f0383 100644
--- a/jdk/src/java.base/share/classes/java/security/Certificate.java
+++ b/jdk/src/java.base/share/classes/java/security/Certificate.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -60,10 +60,9 @@ import java.util.Date;
* This Certificate interface is entirely deprecated and
* is here to allow for a smooth transition to the new
* package.
- * This class is subject to removal in a future version of Java SE.
* @see java.security.cert.Certificate
*/
-@Deprecated(since="1.2", forRemoval=true)
+@Deprecated(since="1.2")
public interface Certificate {
/**
diff --git a/jdk/src/java.base/share/classes/java/security/Identity.java b/jdk/src/java.base/share/classes/java/security/Identity.java
index 44713c4906f..d091b942e26 100644
--- a/jdk/src/java.base/share/classes/java/security/Identity.java
+++ b/jdk/src/java.base/share/classes/java/security/Identity.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -52,12 +52,11 @@ import java.util.*;
*
* @author Benjamin Renaud
* @deprecated This class is no longer used. Its functionality has been
- * replaced by {@link java.security.KeyStore}, the
- * {@link java.security.cert} package, and
- * {@link java.security.Principal}.
- * This class is subject to removal in a future version of Java SE.
+ * replaced by {@code java.security.KeyStore}, the
+ * {@code java.security.cert} package, and
+ * {@code java.security.Principal}.
*/
-@Deprecated(since="1.2", forRemoval=true)
+@Deprecated(since="1.2")
public abstract class Identity implements Principal, Serializable {
/** use serialVersionUID from JDK 1.1.x for interoperability */
diff --git a/jdk/src/java.base/share/classes/java/security/IdentityScope.java b/jdk/src/java.base/share/classes/java/security/IdentityScope.java
index e07d724438a..107fe0861ad 100644
--- a/jdk/src/java.base/share/classes/java/security/IdentityScope.java
+++ b/jdk/src/java.base/share/classes/java/security/IdentityScope.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -57,15 +57,11 @@ import java.util.Properties;
* @author Benjamin Renaud
*
* @deprecated This class is no longer used. Its functionality has been
- * replaced by {@link java.security.KeyStore}, the
- * {@link java.security.cert} package, and
- * {@link java.security.Principal}.
- * This class is subject to removal in a future version of Java SE.
- *
- * Note that the security property {@code policy.ignoreIdentityScope}
- * is only applicable to these APIs and is also a candidate for removal.
+ * replaced by {@code java.security.KeyStore}, the
+ * {@code java.security.cert} package, and
+ * {@code java.security.Principal}.
*/
-@Deprecated(since="1.2", forRemoval=true)
+@Deprecated(since="1.2")
public abstract
class IdentityScope extends Identity {
diff --git a/jdk/src/java.base/share/classes/java/security/Signer.java b/jdk/src/java.base/share/classes/java/security/Signer.java
index 93c6ff73af5..3c53f6c055f 100644
--- a/jdk/src/java.base/share/classes/java/security/Signer.java
+++ b/jdk/src/java.base/share/classes/java/security/Signer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -40,12 +40,11 @@ import java.io.*;
* @author Benjamin Renaud
*
* @deprecated This class is no longer used. Its functionality has been
- * replaced by {@link java.security.KeyStore}, the
- * {@link java.security.cert} package, and
- * {@link java.security.Principal}.
- * This class is subject to removal in a future version of Java SE.
+ * replaced by {@code java.security.KeyStore}, the
+ * {@code java.security.cert} package, and
+ * {@code java.security.Principal}.
*/
-@Deprecated(since="1.2", forRemoval=true)
+@Deprecated(since="1.2")
public abstract class Signer extends Identity {
private static final long serialVersionUID = -1763464102261361480L;
diff --git a/jdk/src/java.base/share/classes/java/security/acl/Acl.java b/jdk/src/java.base/share/classes/java/security/acl/Acl.java
index 1a00125879c..0b2f374a2c9 100644
--- a/jdk/src/java.base/share/classes/java/security/acl/Acl.java
+++ b/jdk/src/java.base/share/classes/java/security/acl/Acl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -85,10 +85,9 @@ import java.security.Principal;
*
* @deprecated This package has been replaced by {@code java.security.Policy}
* and related classes since 1.2.
- * This class is subject to removal in a future version of Java SE.
*/
-@Deprecated(since="9", forRemoval=true)
+@Deprecated(since="9")
public interface Acl extends Owner {
/**
diff --git a/jdk/src/java.base/share/classes/java/security/acl/AclEntry.java b/jdk/src/java.base/share/classes/java/security/acl/AclEntry.java
index 212b7341784..b785a05f3d7 100644
--- a/jdk/src/java.base/share/classes/java/security/acl/AclEntry.java
+++ b/jdk/src/java.base/share/classes/java/security/acl/AclEntry.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -53,9 +53,8 @@ import java.security.Principal;
*
* @deprecated This package has been replaced by {@code java.security.Policy}
* and related classes since 1.2.
- * This class is subject to removal in a future version of Java SE.
*/
-@Deprecated(since="9", forRemoval=true)
+@Deprecated(since="9")
public interface AclEntry extends Cloneable {
/**
diff --git a/jdk/src/java.base/share/classes/java/security/acl/AclNotFoundException.java b/jdk/src/java.base/share/classes/java/security/acl/AclNotFoundException.java
index c1bf55a3aa8..c07852c5490 100644
--- a/jdk/src/java.base/share/classes/java/security/acl/AclNotFoundException.java
+++ b/jdk/src/java.base/share/classes/java/security/acl/AclNotFoundException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -33,9 +33,8 @@ package java.security.acl;
*
* @deprecated This package has been replaced by {@code java.security.Policy}
* and related classes since 1.2.
- * This class is subject to removal in a future version of Java SE.
*/
-@Deprecated(since="9", forRemoval=true)
+@Deprecated(since="9")
public class AclNotFoundException extends Exception {
private static final long serialVersionUID = 5684295034092681791L;
diff --git a/jdk/src/java.base/share/classes/java/security/acl/Group.java b/jdk/src/java.base/share/classes/java/security/acl/Group.java
index 50bf2dd4e38..f68d5dae13c 100644
--- a/jdk/src/java.base/share/classes/java/security/acl/Group.java
+++ b/jdk/src/java.base/share/classes/java/security/acl/Group.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -42,9 +42,8 @@ import java.security.Principal;
*
* @deprecated This package has been replaced by {@code java.security.Policy}
* and related classes since 1.2.
- * This class is subject to removal in a future version of Java SE.
*/
-@Deprecated(since="9", forRemoval=true)
+@Deprecated(since="9")
public interface Group extends Principal {
/**
diff --git a/jdk/src/java.base/share/classes/java/security/acl/LastOwnerException.java b/jdk/src/java.base/share/classes/java/security/acl/LastOwnerException.java
index bae12d06795..dab93db9c1e 100644
--- a/jdk/src/java.base/share/classes/java/security/acl/LastOwnerException.java
+++ b/jdk/src/java.base/share/classes/java/security/acl/LastOwnerException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -35,9 +35,8 @@ package java.security.acl;
*
* @deprecated This package has been replaced by {@code java.security.Policy}
* and related classes since 1.2.
- * This class is subject to removal in a future version of Java SE.
*/
-@Deprecated(since="9", forRemoval=true)
+@Deprecated(since="9")
public class LastOwnerException extends Exception {
private static final long serialVersionUID = -5141997548211140359L;
diff --git a/jdk/src/java.base/share/classes/java/security/acl/NotOwnerException.java b/jdk/src/java.base/share/classes/java/security/acl/NotOwnerException.java
index 74519606bf6..3c7da3ebc8a 100644
--- a/jdk/src/java.base/share/classes/java/security/acl/NotOwnerException.java
+++ b/jdk/src/java.base/share/classes/java/security/acl/NotOwnerException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -34,9 +34,8 @@ package java.security.acl;
*
* @deprecated This package has been replaced by {@code java.security.Policy}
* and related classes since 1.2.
- * This class is subject to removal in a future version of Java SE.
*/
-@Deprecated(since="9", forRemoval=true)
+@Deprecated(since="9")
public class NotOwnerException extends Exception {
private static final long serialVersionUID = -5555597911163362399L;
diff --git a/jdk/src/java.base/share/classes/java/security/acl/Owner.java b/jdk/src/java.base/share/classes/java/security/acl/Owner.java
index 8f88a1150a9..476af4a0a80 100644
--- a/jdk/src/java.base/share/classes/java/security/acl/Owner.java
+++ b/jdk/src/java.base/share/classes/java/security/acl/Owner.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -38,9 +38,8 @@ import java.security.Principal;
*
* @deprecated This package has been replaced by {@code java.security.Policy}
* and related classes since 1.2.
- * This class is subject to removal in a future version of Java SE.
*/
-@Deprecated(since="9", forRemoval=true)
+@Deprecated(since="9")
public interface Owner {
/**
diff --git a/jdk/src/java.base/share/classes/java/security/acl/Permission.java b/jdk/src/java.base/share/classes/java/security/acl/Permission.java
index bcccf167cce..15b77429413 100644
--- a/jdk/src/java.base/share/classes/java/security/acl/Permission.java
+++ b/jdk/src/java.base/share/classes/java/security/acl/Permission.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -34,9 +34,8 @@ package java.security.acl;
*
* @deprecated This package has been replaced by {@code java.security.Policy}
* and related classes since 1.2.
- * This class is subject to removal in a future version of Java SE.
*/
-@Deprecated(since="9", forRemoval=true)
+@Deprecated(since="9")
public interface Permission {
/**
diff --git a/jdk/src/java.base/share/classes/java/security/acl/package-info.java b/jdk/src/java.base/share/classes/java/security/acl/package-info.java
index fdbb6dcd268..25c17392241 100644
--- a/jdk/src/java.base/share/classes/java/security/acl/package-info.java
+++ b/jdk/src/java.base/share/classes/java/security/acl/package-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -27,8 +27,7 @@
* The classes and interfaces in this package have been deprecated. New
* classes should not be added to this package. The {@code java.security}
* package contains suitable replacements. See {@link java.security.Policy}
- * and related classes for details. This package is subject to removal in a
- * future version of Java SE.
+ * and related classes for details.
*
* @since 1.1
*/
diff --git a/jdk/src/java.base/share/classes/java/util/PriorityQueue.java b/jdk/src/java.base/share/classes/java/util/PriorityQueue.java
index db0cfd70913..829eb01efea 100644
--- a/jdk/src/java.base/share/classes/java/util/PriorityQueue.java
+++ b/jdk/src/java.base/share/classes/java/util/PriorityQueue.java
@@ -734,12 +734,12 @@ public class PriorityQueue extends AbstractQueue
@SuppressWarnings("unchecked")
private void heapify() {
final Object[] es = queue;
- final int half = (size >>> 1) - 1;
+ int i = (size >>> 1) - 1;
if (comparator == null)
- for (int i = half; i >= 0; i--)
+ for (; i >= 0; i--)
siftDownComparable(i, (E) es[i]);
else
- for (int i = half; i >= 0; i--)
+ for (; i >= 0; i--)
siftDownUsingComparator(i, (E) es[i]);
}
diff --git a/jdk/src/java.base/share/classes/java/util/Vector.java b/jdk/src/java.base/share/classes/java/util/Vector.java
index 59add640a01..fb6c938c226 100644
--- a/jdk/src/java.base/share/classes/java/util/Vector.java
+++ b/jdk/src/java.base/share/classes/java/util/Vector.java
@@ -307,8 +307,9 @@ public class Vector
if (newSize > elementData.length)
grow(newSize);
final Object[] es = elementData;
- for (int to = elementCount, i = elementCount = newSize; i < to; i++)
+ for (int to = elementCount, i = newSize; i < to; i++)
es[i] = null;
+ elementCount = newSize;
}
/**
@@ -1443,9 +1444,8 @@ public class Vector
@SuppressWarnings("unchecked")
public boolean tryAdvance(Consumer super E> action) {
+ Objects.requireNonNull(action);
int i;
- if (action == null)
- throw new NullPointerException();
if (getFence() > (i = index)) {
index = i + 1;
action.accept((E)array[i]);
@@ -1458,8 +1458,7 @@ public class Vector
@SuppressWarnings("unchecked")
public void forEachRemaining(Consumer super E> action) {
- if (action == null)
- throw new NullPointerException();
+ Objects.requireNonNull(action);
final int hi = getFence();
final Object[] a = array;
int i;
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java b/jdk/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java
index d2eddf9af3f..6af7c7a98bc 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java
@@ -72,9 +72,8 @@ import java.util.function.Predicate;
* generally decreases throughput but reduces variability and avoids
* starvation.
*
- * This class and its iterator implement all of the
- * optional methods of the {@link Collection} and {@link
- * Iterator} interfaces.
+ *
This class and its iterator implement all of the optional
+ * methods of the {@link Collection} and {@link Iterator} interfaces.
*
*
This class is a member of the
*
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java
index c2667e2082c..58e16ae83b8 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java
@@ -67,12 +67,12 @@ import java.util.function.Predicate;
* asynchronous nature of these deques, determining the current number
* of elements requires a traversal of the elements, and so may report
* inaccurate results if this collection is modified during traversal.
- * Additionally, the bulk operations {@code addAll},
- * {@code removeAll}, {@code retainAll}, {@code containsAll},
- * and {@code toArray} are not guaranteed
- * to be performed atomically. For example, an iterator operating
- * concurrently with an {@code addAll} operation might view only some
- * of the added elements.
+ *
+ * Bulk operations that add, remove, or examine multiple elements,
+ * such as {@link #addAll}, {@link #removeIf} or {@link #forEach},
+ * are not guaranteed to be performed atomically.
+ * For example, a {@code forEach} traversal concurrent with an {@code
+ * addAll} operation might observe only some of the added elements.
*
*
This class and its iterator implement all of the optional
* methods of the {@link Deque} and {@link Iterator} interfaces.
@@ -683,8 +683,9 @@ public class ConcurrentLinkedDeque
*/
final Node succ(Node p) {
// TODO: should we skip deleted nodes here?
- Node q = p.next;
- return (p == q) ? first() : q;
+ if (p == (p = p.next))
+ p = first();
+ return p;
}
/**
@@ -1416,65 +1417,55 @@ public class ConcurrentLinkedDeque
boolean exhausted; // true when no more nodes
public Spliterator trySplit() {
- Node p;
- int b = batch;
- int n = (b <= 0) ? 1 : (b >= MAX_BATCH) ? MAX_BATCH : b + 1;
- if (!exhausted &&
- ((p = current) != null || (p = first()) != null)) {
- if (p.item == null && p == (p = p.next))
- current = p = first();
- if (p != null && p.next != null) {
- Object[] a = new Object[n];
- int i = 0;
- do {
- if ((a[i] = p.item) != null)
- ++i;
- if (p == (p = p.next))
- p = first();
- } while (p != null && i < n);
- if ((current = p) == null)
- exhausted = true;
- if (i > 0) {
- batch = i;
- return Spliterators.spliterator
- (a, 0, i, (Spliterator.ORDERED |
- Spliterator.NONNULL |
- Spliterator.CONCURRENT));
- }
+ Node p, q;
+ if ((p = current()) == null || (q = p.next) == null)
+ return null;
+ int i = 0, n = batch = Math.min(batch + 1, MAX_BATCH);
+ Object[] a = null;
+ do {
+ final E e;
+ if ((e = p.item) != null) {
+ if (a == null)
+ a = new Object[n];
+ a[i++] = e;
}
- }
- return null;
+ if (p == (p = q))
+ p = first();
+ } while (p != null && (q = p.next) != null && i < n);
+ setCurrent(p);
+ return (i == 0) ? null :
+ Spliterators.spliterator(a, 0, i, (Spliterator.ORDERED |
+ Spliterator.NONNULL |
+ Spliterator.CONCURRENT));
}
public void forEachRemaining(Consumer super E> action) {
+ Objects.requireNonNull(action);
Node p;
- if (action == null) throw new NullPointerException();
- if (!exhausted &&
- ((p = current) != null || (p = first()) != null)) {
+ if ((p = current()) != null) {
+ current = null;
exhausted = true;
do {
- E e = p.item;
+ final E e;
+ if ((e = p.item) != null)
+ action.accept(e);
if (p == (p = p.next))
p = first();
- if (e != null)
- action.accept(e);
} while (p != null);
}
}
public boolean tryAdvance(Consumer super E> action) {
+ Objects.requireNonNull(action);
Node p;
- if (action == null) throw new NullPointerException();
- if (!exhausted &&
- ((p = current) != null || (p = first()) != null)) {
+ if ((p = current()) != null) {
E e;
do {
e = p.item;
if (p == (p = p.next))
p = first();
} while (e == null && p != null);
- if ((current = p) == null)
- exhausted = true;
+ setCurrent(p);
if (e != null) {
action.accept(e);
return true;
@@ -1483,11 +1474,24 @@ public class ConcurrentLinkedDeque
return false;
}
+ private void setCurrent(Node p) {
+ if ((current = p) == null)
+ exhausted = true;
+ }
+
+ private Node current() {
+ Node p;
+ if ((p = current) == null && !exhausted)
+ setCurrent(p = first());
+ return p;
+ }
+
public long estimateSize() { return Long.MAX_VALUE; }
public int characteristics() {
- return Spliterator.ORDERED | Spliterator.NONNULL |
- Spliterator.CONCURRENT;
+ return (Spliterator.ORDERED |
+ Spliterator.NONNULL |
+ Spliterator.CONCURRENT);
}
}
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java
index b3dd5df8e73..6ce61b8f4ab 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java
@@ -81,12 +81,12 @@ import java.util.function.Predicate;
* asynchronous nature of these queues, determining the current number
* of elements requires a traversal of the elements, and so may report
* inaccurate results if this collection is modified during traversal.
- * Additionally, the bulk operations {@code addAll},
- * {@code removeAll}, {@code retainAll}, {@code containsAll},
- * and {@code toArray} are not guaranteed
- * to be performed atomically. For example, an iterator operating
- * concurrently with an {@code addAll} operation might view only some
- * of the added elements.
+ *
+ * Bulk operations that add, remove, or examine multiple elements,
+ * such as {@link #addAll}, {@link #removeIf} or {@link #forEach},
+ * are not guaranteed to be performed atomically.
+ * For example, a {@code forEach} traversal concurrent with an {@code
+ * addAll} operation might observe only some of the added elements.
*
*
This class and its iterator implement all of the optional
* methods of the {@link Queue} and {@link Iterator} interfaces.
@@ -184,16 +184,30 @@ public class ConcurrentLinkedQueue extends AbstractQueue
static final class Node {
volatile E item;
volatile Node next;
- }
- /**
- * Returns a new node holding item. Uses relaxed write because item
- * can only be seen after piggy-backing publication via CAS.
- */
- static Node newNode(E item) {
- Node node = new Node();
- ITEM.set(node, item);
- return node;
+ /**
+ * Constructs a node holding item. Uses relaxed write because
+ * item can only be seen after piggy-backing publication via CAS.
+ */
+ Node(E item) {
+ ITEM.set(this, item);
+ }
+
+ /** Constructs a dead dummy node. */
+ Node() {}
+
+ void appendRelaxed(Node next) {
+ // assert next != null;
+ // assert this.next == null;
+ NEXT.set(this, next);
+ }
+
+ boolean casItem(E cmp, E val) {
+ // assert item == cmp || item == null;
+ // assert cmp != null;
+ // assert val == null;
+ return ITEM.compareAndSet(this, cmp, val);
+ }
}
/**
@@ -220,7 +234,7 @@ public class ConcurrentLinkedQueue extends AbstractQueue
* - tail.item may or may not be null.
* - it is permitted for tail to lag behind head, that is, for tail
* to not be reachable from head!
- * - tail.next may or may not be self-pointing to tail.
+ * - tail.next may or may not be self-linked.
*/
private transient volatile Node tail;
@@ -228,7 +242,7 @@ public class ConcurrentLinkedQueue extends AbstractQueue
* Creates a {@code ConcurrentLinkedQueue} that is initially empty.
*/
public ConcurrentLinkedQueue() {
- head = tail = newNode(null);
+ head = tail = new Node();
}
/**
@@ -243,16 +257,14 @@ public class ConcurrentLinkedQueue extends AbstractQueue
public ConcurrentLinkedQueue(Collection extends E> c) {
Node h = null, t = null;
for (E e : c) {
- Node newNode = newNode(Objects.requireNonNull(e));
+ Node newNode = new Node(Objects.requireNonNull(e));
if (h == null)
h = t = newNode;
- else {
- NEXT.set(t, newNode);
- t = newNode;
- }
+ else
+ t.appendRelaxed(t = newNode);
}
if (h == null)
- h = t = newNode(null);
+ h = t = new Node();
head = h;
tail = t;
}
@@ -287,14 +299,17 @@ public class ConcurrentLinkedQueue extends AbstractQueue
* stale pointer that is now off the list.
*/
final Node succ(Node p) {
- Node next = p.next;
- return (p == next) ? head : next;
+ if (p == (p = p.next))
+ p = head;
+ return p;
}
/**
* Tries to CAS pred.next (or head, if pred is null) from c to p.
+ * Caller must ensure that we're not unlinking the trailing node.
*/
private boolean tryCasSuccessor(Node pred, Node c, Node p) {
+ // assert p != null;
// assert c.item == null;
// assert c != p;
if (pred != null)
@@ -306,6 +321,29 @@ public class ConcurrentLinkedQueue extends AbstractQueue
return false;
}
+ /**
+ * Collapse dead nodes between pred and q.
+ * @param pred the last known live node, or null if none
+ * @param c the first dead node
+ * @param p the last dead node
+ * @param q p.next: the next live node, or null if at end
+ * @return either old pred or p if pred dead or CAS failed
+ */
+ private Node skipDeadNodes(Node pred, Node c, Node p, Node q) {
+ // assert pred != c;
+ // assert p != q;
+ // assert c.item == null;
+ // assert p.item == null;
+ if (q == null) {
+ // Never unlink trailing node.
+ if (c == p) return pred;
+ q = p;
+ }
+ return (tryCasSuccessor(pred, c, q)
+ && (pred == null || ITEM.get(pred) != null))
+ ? pred : p;
+ }
+
/**
* Inserts the specified element at the tail of this queue.
* As the queue is unbounded, this method will never return {@code false}.
@@ -314,7 +352,7 @@ public class ConcurrentLinkedQueue extends AbstractQueue
* @throws NullPointerException if the specified element is null
*/
public boolean offer(E e) {
- final Node newNode = newNode(Objects.requireNonNull(e));
+ final Node newNode = new Node(Objects.requireNonNull(e));
for (Node t = tail, p = t;;) {
Node q = p.next;
@@ -346,8 +384,7 @@ public class ConcurrentLinkedQueue extends AbstractQueue
restartFromHead: for (;;) {
for (Node h = head, p = h, q;; p = q) {
final E item;
- if ((item = p.item) != null
- && ITEM.compareAndSet(p, item, null)) {
+ if ((item = p.item) != null && p.casItem(item, null)) {
// Successful CAS is the linearization point
// for item to be removed from this queue.
if (p != h) // hop two nodes at a time
@@ -451,19 +488,20 @@ public class ConcurrentLinkedQueue extends AbstractQueue
public boolean contains(Object o) {
if (o == null) return false;
restartFromHead: for (;;) {
- for (Node p = head, c = p, pred = null, q; p != null; p = q) {
+ for (Node p = head, pred = null; p != null; ) {
+ Node q = p.next;
final E item;
- if ((item = p.item) != null && o.equals(item))
- return true;
- if (c != p && tryCasSuccessor(pred, c, p))
- c = p;
- q = p.next;
- if (item != null || c != p) {
- pred = p;
- c = q;
+ if ((item = p.item) != null) {
+ if (o.equals(item))
+ return true;
+ pred = p; p = q; continue;
+ }
+ for (Node c = p;; q = p.next) {
+ if (q == null || q.item != null) {
+ pred = skipDeadNodes(pred, c, p, q); p = q; break;
+ }
+ if (p == (p = q)) continue restartFromHead;
}
- else if (p == q)
- continue restartFromHead;
}
return false;
}
@@ -483,23 +521,22 @@ public class ConcurrentLinkedQueue extends AbstractQueue
public boolean remove(Object o) {
if (o == null) return false;
restartFromHead: for (;;) {
- for (Node p = head, c = p, pred = null, q; p != null; p = q) {
+ for (Node p = head, pred = null; p != null; ) {
+ Node q = p.next;
final E item;
- final boolean removed =
- (item = p.item) != null
- && o.equals(item)
- && ITEM.compareAndSet(p, item, null);
- if (c != p && tryCasSuccessor(pred, c, p))
- c = p;
- if (removed)
- return true;
- q = p.next;
- if (item != null || c != p) {
- pred = p;
- c = q;
+ if ((item = p.item) != null) {
+ if (o.equals(item) && p.casItem(item, null)) {
+ skipDeadNodes(pred, p, p, q);
+ return true;
+ }
+ pred = p; p = q; continue;
+ }
+ for (Node c = p;; q = p.next) {
+ if (q == null || q.item != null) {
+ pred = skipDeadNodes(pred, c, p, q); p = q; break;
+ }
+ if (p == (p = q)) continue restartFromHead;
}
- else if (p == q)
- continue restartFromHead;
}
return false;
}
@@ -525,13 +562,11 @@ public class ConcurrentLinkedQueue extends AbstractQueue
// Copy c into a private chain of Nodes
Node beginningOfTheEnd = null, last = null;
for (E e : c) {
- Node newNode = newNode(Objects.requireNonNull(e));
+ Node newNode = new Node(Objects.requireNonNull(e));
if (beginningOfTheEnd == null)
beginningOfTheEnd = last = newNode;
- else {
- NEXT.set(last, newNode);
- last = newNode;
- }
+ else
+ last.appendRelaxed(last = newNode);
}
if (beginningOfTheEnd == null)
return false;
@@ -677,7 +712,7 @@ public class ConcurrentLinkedQueue extends AbstractQueue
*/
@SuppressWarnings("unchecked")
public T[] toArray(T[] a) {
- if (a == null) throw new NullPointerException();
+ Objects.requireNonNull(a);
return (T[]) toArrayInternal(a);
}
@@ -757,6 +792,8 @@ public class ConcurrentLinkedQueue extends AbstractQueue
}
}
+ // Default implementation of forEachRemaining is "good enough".
+
public void remove() {
Node l = lastRet;
if (l == null) throw new IllegalStateException();
@@ -806,16 +843,14 @@ public class ConcurrentLinkedQueue extends AbstractQueue
Node h = null, t = null;
for (Object item; (item = s.readObject()) != null; ) {
@SuppressWarnings("unchecked")
- Node newNode = newNode((E) item);
+ Node newNode = new Node((E) item);
if (h == null)
h = t = newNode;
- else {
- NEXT.set(t, newNode);
- t = newNode;
- }
+ else
+ t.appendRelaxed(t = newNode);
}
if (h == null)
- h = t = newNode(null);
+ h = t = new Node();
head = h;
tail = t;
}
@@ -828,62 +863,49 @@ public class ConcurrentLinkedQueue extends AbstractQueue
boolean exhausted; // true when no more nodes
public Spliterator trySplit() {
- Node p;
- int b = batch;
- int n = (b <= 0) ? 1 : (b >= MAX_BATCH) ? MAX_BATCH : b + 1;
- if (!exhausted &&
- ((p = current) != null || (p = first()) != null) &&
- p.next != null) {
- Object[] a = new Object[n];
- int i = 0;
- do {
- if ((a[i] = p.item) != null)
- ++i;
- if (p == (p = p.next))
- p = first();
- } while (p != null && i < n);
- if ((current = p) == null)
- exhausted = true;
- if (i > 0) {
- batch = i;
- return Spliterators.spliterator
- (a, 0, i, (Spliterator.ORDERED |
- Spliterator.NONNULL |
- Spliterator.CONCURRENT));
+ Node p, q;
+ if ((p = current()) == null || (q = p.next) == null)
+ return null;
+ int i = 0, n = batch = Math.min(batch + 1, MAX_BATCH);
+ Object[] a = null;
+ do {
+ final E e;
+ if ((e = p.item) != null) {
+ if (a == null)
+ a = new Object[n];
+ a[i++] = e;
}
- }
- return null;
+ if (p == (p = q))
+ p = first();
+ } while (p != null && (q = p.next) != null && i < n);
+ setCurrent(p);
+ return (i == 0) ? null :
+ Spliterators.spliterator(a, 0, i, (Spliterator.ORDERED |
+ Spliterator.NONNULL |
+ Spliterator.CONCURRENT));
}
public void forEachRemaining(Consumer super E> action) {
- Node p;
- if (action == null) throw new NullPointerException();
- if (!exhausted &&
- ((p = current) != null || (p = first()) != null)) {
+ Objects.requireNonNull(action);
+ final Node p;
+ if ((p = current()) != null) {
+ current = null;
exhausted = true;
- do {
- E e = p.item;
- if (p == (p = p.next))
- p = first();
- if (e != null)
- action.accept(e);
- } while (p != null);
+ forEachFrom(action, p);
}
}
public boolean tryAdvance(Consumer super E> action) {
+ Objects.requireNonNull(action);
Node p;
- if (action == null) throw new NullPointerException();
- if (!exhausted &&
- ((p = current) != null || (p = first()) != null)) {
+ if ((p = current()) != null) {
E e;
do {
e = p.item;
if (p == (p = p.next))
p = first();
} while (e == null && p != null);
- if ((current = p) == null)
- exhausted = true;
+ setCurrent(p);
if (e != null) {
action.accept(e);
return true;
@@ -892,11 +914,24 @@ public class ConcurrentLinkedQueue extends AbstractQueue
return false;
}
+ private void setCurrent(Node p) {
+ if ((current = p) == null)
+ exhausted = true;
+ }
+
+ private Node current() {
+ Node p;
+ if ((p = current) == null && !exhausted)
+ setCurrent(p = first());
+ return p;
+ }
+
public long estimateSize() { return Long.MAX_VALUE; }
public int characteristics() {
- return Spliterator.ORDERED | Spliterator.NONNULL |
- Spliterator.CONCURRENT;
+ return (Spliterator.ORDERED |
+ Spliterator.NONNULL |
+ Spliterator.CONCURRENT);
}
}
@@ -963,22 +998,22 @@ public class ConcurrentLinkedQueue extends AbstractQueue
// c will be CASed to collapse intervening dead nodes between
// pred (or head if null) and p.
for (Node p = head, c = p, pred = null, q; p != null; p = q) {
+ q = p.next;
final E item; boolean pAlive;
if (pAlive = ((item = p.item) != null)) {
if (filter.test(item)) {
- if (ITEM.compareAndSet(p, item, null))
+ if (p.casItem(item, null))
removed = true;
pAlive = false;
}
}
- if ((q = p.next) == null || pAlive || --hops == 0) {
+ if (pAlive || q == null || --hops == 0) {
// p might already be self-linked here, but if so:
// - CASing head will surely fail
// - CASing pred's next will be useless but harmless.
- if (c != p && tryCasSuccessor(pred, c, p))
- c = p;
- // if c != p, CAS failed, so abandon old pred
- if (pAlive || c != p) {
+ if ((c != p && !tryCasSuccessor(pred, c, c = p))
+ || pAlive) {
+ // if CAS failed or alive, abandon old pred
hops = MAX_HOPS;
pred = p;
c = q;
@@ -990,35 +1025,40 @@ public class ConcurrentLinkedQueue extends AbstractQueue
}
}
+ /**
+ * Runs action on each element found during a traversal starting at p.
+ * If p is null, the action is not run.
+ */
+ void forEachFrom(Consumer super E> action, Node p) {
+ for (Node pred = null; p != null; ) {
+ Node q = p.next;
+ final E item;
+ if ((item = p.item) != null) {
+ action.accept(item);
+ pred = p; p = q; continue;
+ }
+ for (Node c = p;; q = p.next) {
+ if (q == null || q.item != null) {
+ pred = skipDeadNodes(pred, c, p, q); p = q; break;
+ }
+ if (p == (p = q)) { pred = null; p = head; break; }
+ }
+ }
+ }
+
/**
* @throws NullPointerException {@inheritDoc}
*/
public void forEach(Consumer super E> action) {
Objects.requireNonNull(action);
- restartFromHead: for (;;) {
- for (Node p = head, c = p, pred = null, q; p != null; p = q) {
- final E item;
- if ((item = p.item) != null)
- action.accept(item);
- if (c != p && tryCasSuccessor(pred, c, p))
- c = p;
- q = p.next;
- if (item != null || c != p) {
- pred = p;
- c = q;
- }
- else if (p == q)
- continue restartFromHead;
- }
- return;
- }
+ forEachFrom(action, head);
}
// VarHandle mechanics
private static final VarHandle HEAD;
private static final VarHandle TAIL;
- private static final VarHandle ITEM;
- private static final VarHandle NEXT;
+ static final VarHandle ITEM;
+ static final VarHandle NEXT;
static {
try {
MethodHandles.Lookup l = MethodHandles.lookup();
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java
index 45bde4215c5..86be622c78b 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java
@@ -72,12 +72,12 @@ import java.util.Spliterator;
* asynchronous nature of these sets, determining the current number
* of elements requires a traversal of the elements, and so may report
* inaccurate results if this collection is modified during traversal.
- * Additionally, the bulk operations {@code addAll},
- * {@code removeAll}, {@code retainAll}, {@code containsAll},
- * {@code equals}, and {@code toArray} are not guaranteed
- * to be performed atomically. For example, an iterator operating
- * concurrently with an {@code addAll} operation might view only some
- * of the added elements.
+ *
+ * Bulk operations that add, remove, or examine multiple elements,
+ * such as {@link #addAll}, {@link #removeIf} or {@link #forEach},
+ * are not guaranteed to be performed atomically.
+ * For example, a {@code forEach} traversal concurrent with an {@code
+ * addAll} operation might observe only some of the added elements.
*
*
This class and its iterators implement all of the
* optional methods of the {@link Set} and {@link Iterator}
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java b/jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java
index d52a515eb9a..63bd252868d 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java
@@ -797,7 +797,7 @@ public class CopyOnWriteArrayList
* @throws NullPointerException {@inheritDoc}
*/
public void forEach(Consumer super E> action) {
- if (action == null) throw new NullPointerException();
+ Objects.requireNonNull(action);
for (Object x : getArray()) {
@SuppressWarnings("unchecked") E e = (E) x;
action.accept(e);
@@ -808,7 +808,7 @@ public class CopyOnWriteArrayList
* @throws NullPointerException {@inheritDoc}
*/
public boolean removeIf(Predicate super E> filter) {
- if (filter == null) throw new NullPointerException();
+ Objects.requireNonNull(filter);
return bulkRemove(filter);
}
@@ -865,7 +865,7 @@ public class CopyOnWriteArrayList
}
public void replaceAll(UnaryOperator operator) {
- if (operator == null) throw new NullPointerException();
+ Objects.requireNonNull(operator);
synchronized (lock) {
replaceAll(operator, 0, getArray().length);
}
@@ -1329,7 +1329,7 @@ public class CopyOnWriteArrayList
}
public void forEach(Consumer super E> action) {
- if (action == null) throw new NullPointerException();
+ Objects.requireNonNull(action);
int i, end; final Object[] es;
synchronized (l.lock) {
es = getArrayChecked();
@@ -1341,7 +1341,7 @@ public class CopyOnWriteArrayList
}
public void replaceAll(UnaryOperator operator) {
- if (operator == null) throw new NullPointerException();
+ Objects.requireNonNull(operator);
synchronized (l.lock) {
checkForComodification();
l.replaceAll(operator, offset, offset + size);
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/DelayQueue.java b/jdk/src/java.base/share/classes/java/util/concurrent/DelayQueue.java
index 03c52ff08a1..50997f7abda 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/DelayQueue.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/DelayQueue.java
@@ -41,6 +41,7 @@ import java.util.AbstractQueue;
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
+import java.util.Objects;
import java.util.PriorityQueue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
@@ -59,11 +60,11 @@ import java.util.concurrent.locks.ReentrantLock;
* returns the count of both expired and unexpired elements.
* This queue does not permit null elements.
*
- * This class and its iterator implement all of the
- * optional methods of the {@link Collection} and {@link
- * Iterator} interfaces. The Iterator provided in method {@link
- * #iterator()} is not guaranteed to traverse the elements of
- * the DelayQueue in any particular order.
+ *
This class and its iterator implement all of the optional
+ * methods of the {@link Collection} and {@link Iterator} interfaces.
+ * The Iterator provided in method {@link #iterator()} is not
+ * guaranteed to traverse the elements of the DelayQueue in any
+ * particular order.
*
*
This class is a member of the
*
@@ -339,8 +340,7 @@ public class DelayQueue extends AbstractQueue
* @throws IllegalArgumentException {@inheritDoc}
*/
public int drainTo(Collection super E> c) {
- if (c == null)
- throw new NullPointerException();
+ Objects.requireNonNull(c);
if (c == this)
throw new IllegalArgumentException();
final ReentrantLock lock = this.lock;
@@ -365,8 +365,7 @@ public class DelayQueue extends AbstractQueue
* @throws IllegalArgumentException {@inheritDoc}
*/
public int drainTo(Collection super E> c, int maxElements) {
- if (c == null)
- throw new NullPointerException();
+ Objects.requireNonNull(c);
if (c == this)
throw new IllegalArgumentException();
if (maxElements <= 0)
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java
index c549dbdb30f..330f4fb78a3 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java
@@ -40,6 +40,7 @@ import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.security.AccessController;
import java.security.AccessControlContext;
+import java.security.Permission;
import java.security.Permissions;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
@@ -132,24 +133,30 @@ import java.util.concurrent.locks.LockSupport;
*
*
*
- * The common pool is by default constructed with default
- * parameters, but these may be controlled by setting the following
- * {@linkplain System#getProperty system properties}:
+ *
The parameters used to construct the common pool may be controlled by
+ * setting the following {@linkplain System#getProperty system properties}:
*
* - {@code java.util.concurrent.ForkJoinPool.common.parallelism}
* - the parallelism level, a non-negative integer
*
- {@code java.util.concurrent.ForkJoinPool.common.threadFactory}
- * - the class name of a {@link ForkJoinWorkerThreadFactory}
+ * - the class name of a {@link ForkJoinWorkerThreadFactory}.
+ * The {@linkplain ClassLoader#getSystemClassLoader() system class loader}
+ * is used to load this class.
*
- {@code java.util.concurrent.ForkJoinPool.common.exceptionHandler}
- * - the class name of a {@link UncaughtExceptionHandler}
+ * - the class name of a {@link UncaughtExceptionHandler}.
+ * The {@linkplain ClassLoader#getSystemClassLoader() system class loader}
+ * is used to load this class.
*
- {@code java.util.concurrent.ForkJoinPool.common.maximumSpares}
* - the maximum number of allowed extra threads to maintain target
* parallelism (default 256).
*
- * If a {@link SecurityManager} is present and no factory is
- * specified, then the default pool uses a factory supplying
- * threads that have no {@link Permissions} enabled.
- * The system class loader is used to load these classes.
+ * If no thread factory is supplied via a system property, then the
+ * common pool uses a factory that uses the system class loader as the
+ * {@linkplain Thread#getContextClassLoader() thread context class loader}.
+ * In addition, if a {@link SecurityManager} is present, then
+ * the common pool uses a factory supplying threads that have no
+ * {@link Permissions} enabled.
+ *
* Upon any error in establishing these settings, default parameters
* are used. It is possible to disable or limit the use of threads in
* the common pool by setting the parallelism property to zero, and/or
@@ -638,20 +645,38 @@ public class ForkJoinPool extends AbstractExecutorService {
*
* @param pool the pool this thread works in
* @return the new worker thread, or {@code null} if the request
- * to create a thread is rejected.
+ * to create a thread is rejected
* @throws NullPointerException if the pool is null
*/
public ForkJoinWorkerThread newThread(ForkJoinPool pool);
}
+ static AccessControlContext contextWithPermissions(Permission ... perms) {
+ Permissions permissions = new Permissions();
+ for (Permission perm : perms)
+ permissions.add(perm);
+ return new AccessControlContext(
+ new ProtectionDomain[] { new ProtectionDomain(null, permissions) });
+ }
+
/**
* Default ForkJoinWorkerThreadFactory implementation; creates a
- * new ForkJoinWorkerThread.
+ * new ForkJoinWorkerThread using the system class loader as the
+ * thread context class loader.
*/
private static final class DefaultForkJoinWorkerThreadFactory
implements ForkJoinWorkerThreadFactory {
+ private static final AccessControlContext ACC = contextWithPermissions(
+ new RuntimePermission("getClassLoader"),
+ new RuntimePermission("setContextClassLoader"));
+
public final ForkJoinWorkerThread newThread(ForkJoinPool pool) {
- return new ForkJoinWorkerThread(pool);
+ return AccessController.doPrivileged(
+ new PrivilegedAction<>() {
+ public ForkJoinWorkerThread run() {
+ return new ForkJoinWorkerThread(
+ pool, ClassLoader.getSystemClassLoader()); }},
+ ACC);
}
}
@@ -3244,26 +3269,20 @@ public class ForkJoinPool extends AbstractExecutorService {
* An ACC to restrict permissions for the factory itself.
* The constructed workers have no permissions set.
*/
- private static final AccessControlContext INNOCUOUS_ACC;
- static {
- Permissions innocuousPerms = new Permissions();
- innocuousPerms.add(modifyThreadPermission);
- innocuousPerms.add(new RuntimePermission(
- "enableContextClassLoaderOverride"));
- innocuousPerms.add(new RuntimePermission(
- "modifyThreadGroup"));
- INNOCUOUS_ACC = new AccessControlContext(new ProtectionDomain[] {
- new ProtectionDomain(null, innocuousPerms)
- });
- }
+ private static final AccessControlContext ACC = contextWithPermissions(
+ modifyThreadPermission,
+ new RuntimePermission("enableContextClassLoaderOverride"),
+ new RuntimePermission("modifyThreadGroup"),
+ new RuntimePermission("getClassLoader"),
+ new RuntimePermission("setContextClassLoader"));
public final ForkJoinWorkerThread newThread(ForkJoinPool pool) {
- return AccessController.doPrivileged(new PrivilegedAction<>() {
- public ForkJoinWorkerThread run() {
- return new ForkJoinWorkerThread.
- InnocuousForkJoinWorkerThread(pool);
- }}, INNOCUOUS_ACC);
+ return AccessController.doPrivileged(
+ new PrivilegedAction<>() {
+ public ForkJoinWorkerThread run() {
+ return new ForkJoinWorkerThread.
+ InnocuousForkJoinWorkerThread(pool); }},
+ ACC);
}
}
-
}
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java
index 93bb08dd48f..a3054b865ba 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java
@@ -36,6 +36,8 @@
package java.util.concurrent;
import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
/**
@@ -87,12 +89,27 @@ public class ForkJoinWorkerThread extends Thread {
this.workQueue = pool.registerWorker(this);
}
+ /**
+ * Version for use by the default pool. Supports setting the
+ * context class loader. This is a separate constructor to avoid
+ * affecting the protected constructor.
+ */
+ ForkJoinWorkerThread(ForkJoinPool pool, ClassLoader ccl) {
+ super("aForkJoinWorkerThread");
+ super.setContextClassLoader(ccl);
+ this.pool = pool;
+ this.workQueue = pool.registerWorker(this);
+ }
+
/**
* Version for InnocuousForkJoinWorkerThread.
*/
- ForkJoinWorkerThread(ForkJoinPool pool, ThreadGroup threadGroup,
+ ForkJoinWorkerThread(ForkJoinPool pool,
+ ClassLoader ccl,
+ ThreadGroup threadGroup,
AccessControlContext acc) {
super(threadGroup, null, "aForkJoinWorkerThread");
+ super.setContextClassLoader(ccl);
ThreadLocalRandom.setInheritedAccessControlContext(this, acc);
ThreadLocalRandom.eraseThreadLocals(this); // clear before registering
this.pool = pool;
@@ -179,20 +196,21 @@ public class ForkJoinWorkerThread extends Thread {
/**
* A worker thread that has no permissions, is not a member of any
- * user-defined ThreadGroup, and erases all ThreadLocals after
+ * user-defined ThreadGroup, uses the system class loader as
+ * thread context class loader, and erases all ThreadLocals after
* running each top-level task.
*/
static final class InnocuousForkJoinWorkerThread extends ForkJoinWorkerThread {
/** The ThreadGroup for all InnocuousForkJoinWorkerThreads */
private static final ThreadGroup innocuousThreadGroup =
- java.security.AccessController.doPrivileged(
- new java.security.PrivilegedAction<>() {
- public ThreadGroup run() {
- ThreadGroup group = Thread.currentThread().getThreadGroup();
- for (ThreadGroup p; (p = group.getParent()) != null; )
- group = p;
- return new ThreadGroup(group, "InnocuousForkJoinWorkerThreadGroup");
- }});
+ java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedAction<>() {
+ public ThreadGroup run() {
+ ThreadGroup group = Thread.currentThread().getThreadGroup();
+ for (ThreadGroup p; (p = group.getParent()) != null; )
+ group = p;
+ return new ThreadGroup(group, "InnocuousForkJoinWorkerThreadGroup");
+ }});
/** An AccessControlContext supporting no privileges */
private static final AccessControlContext INNOCUOUS_ACC =
@@ -202,7 +220,10 @@ public class ForkJoinWorkerThread extends Thread {
});
InnocuousForkJoinWorkerThread(ForkJoinPool pool) {
- super(pool, innocuousThreadGroup, INNOCUOUS_ACC);
+ super(pool,
+ ClassLoader.getSystemClassLoader(),
+ innocuousThreadGroup,
+ INNOCUOUS_ACC);
}
@Override // to erase ThreadLocals
@@ -210,11 +231,6 @@ public class ForkJoinWorkerThread extends Thread {
ThreadLocalRandom.eraseThreadLocals(this);
}
- @Override // to always report system loader
- public ClassLoader getContextClassLoader() {
- return ClassLoader.getSystemClassLoader();
- }
-
@Override // to silently fail
public void setUncaughtExceptionHandler(UncaughtExceptionHandler x) { }
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java b/jdk/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java
index 7f653e844b5..1db30b3b440 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java
@@ -45,6 +45,7 @@ import java.util.Spliterators;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
+import java.util.function.Predicate;
/**
* An optionally-bounded {@linkplain BlockingDeque blocking deque} based on
@@ -63,9 +64,8 @@ import java.util.function.Consumer;
* contains}, {@link #iterator iterator.remove()}, and the bulk
* operations, all of which run in linear time.
*
- * This class and its iterator implement all of the
- * optional methods of the {@link Collection} and {@link
- * Iterator} interfaces.
+ *
This class and its iterator implement all of the optional
+ * methods of the {@link Collection} and {@link Iterator} interfaces.
*
*
This class is a member of the
*
@@ -195,18 +195,7 @@ public class LinkedBlockingDeque
*/
public LinkedBlockingDeque(Collection extends E> c) {
this(Integer.MAX_VALUE);
- final ReentrantLock lock = this.lock;
- lock.lock(); // Never contended, but necessary for visibility
- try {
- for (E e : c) {
- if (e == null)
- throw new NullPointerException();
- if (!linkLast(new Node(e)))
- throw new IllegalStateException("Deque full");
- }
- } finally {
- lock.unlock();
- }
+ addAll(c);
}
@@ -299,6 +288,7 @@ public class LinkedBlockingDeque
*/
void unlink(Node x) {
// assert lock.isHeldByCurrentThread();
+ // assert x.item != null;
Node p = x.prev;
Node n = x.next;
if (p == null) {
@@ -834,46 +824,65 @@ public class LinkedBlockingDeque
}
}
- /*
- * TODO: Add support for more efficient bulk operations.
+ /**
+ * Appends all of the elements in the specified collection to the end of
+ * this deque, in the order that they are returned by the specified
+ * collection's iterator. Attempts to {@code addAll} of a deque to
+ * itself result in {@code IllegalArgumentException}.
*
- * We don't want to acquire the lock for every iteration, but we
- * also want other threads a chance to interact with the
- * collection, especially when count is close to capacity.
+ * @param c the elements to be inserted into this deque
+ * @return {@code true} if this deque changed as a result of the call
+ * @throws NullPointerException if the specified collection or any
+ * of its elements are null
+ * @throws IllegalArgumentException if the collection is this deque
+ * @throws IllegalStateException if this deque is full
+ * @see #add(Object)
*/
+ public boolean addAll(Collection extends E> c) {
+ if (c == this)
+ // As historically specified in AbstractQueue#addAll
+ throw new IllegalArgumentException();
-// /**
-// * Adds all of the elements in the specified collection to this
-// * queue. Attempts to addAll of a queue to itself result in
-// * {@code IllegalArgumentException}. Further, the behavior of
-// * this operation is undefined if the specified collection is
-// * modified while the operation is in progress.
-// *
-// * @param c collection containing elements to be added to this queue
-// * @return {@code true} if this queue changed as a result of the call
-// * @throws ClassCastException {@inheritDoc}
-// * @throws NullPointerException {@inheritDoc}
-// * @throws IllegalArgumentException {@inheritDoc}
-// * @throws IllegalStateException if this deque is full
-// * @see #add(Object)
-// */
-// public boolean addAll(Collection extends E> c) {
-// if (c == null)
-// throw new NullPointerException();
-// if (c == this)
-// throw new IllegalArgumentException();
-// final ReentrantLock lock = this.lock;
-// lock.lock();
-// try {
-// boolean modified = false;
-// for (E e : c)
-// if (linkLast(e))
-// modified = true;
-// return modified;
-// } finally {
-// lock.unlock();
-// }
-// }
+ // Copy c into a private chain of Nodes
+ Node beg = null, end = null;
+ int n = 0;
+ for (E e : c) {
+ Objects.requireNonNull(e);
+ n++;
+ Node newNode = new Node(e);
+ if (beg == null)
+ beg = end = newNode;
+ else {
+ end.next = newNode;
+ newNode.prev = end;
+ end = newNode;
+ }
+ }
+ if (beg == null)
+ return false;
+
+ // Atomically append the chain at the end
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ if (count + n <= capacity) {
+ beg.prev = last;
+ if (first == null)
+ first = beg;
+ else
+ last.next = beg;
+ last = end;
+ count += n;
+ notEmpty.signalAll();
+ return true;
+ }
+ } finally {
+ lock.unlock();
+ }
+ // Fall back to historic non-atomic implementation, failing
+ // with IllegalStateException when the capacity is exceeded.
+ return super.addAll(c);
+ }
/**
* Returns an array containing all of the elements in this deque, in
@@ -992,7 +1001,9 @@ public class LinkedBlockingDeque
* - (possibly multiple) interior removed nodes (p.item == null)
*/
Node succ(Node p) {
- return (p == (p = p.next)) ? first : p;
+ if (p == (p = p.next))
+ p = first;
+ return p;
}
/**
@@ -1049,7 +1060,9 @@ public class LinkedBlockingDeque
abstract Node nextNode(Node n);
private Node succ(Node p) {
- return (p == (p = nextNode(p))) ? firstNode() : p;
+ if (p == (p = nextNode(p)))
+ p = firstNode();
+ return p;
}
AbstractItr() {
@@ -1096,7 +1109,7 @@ public class LinkedBlockingDeque
lastRet = p;
next = null;
final ReentrantLock lock = LinkedBlockingDeque.this.lock;
- final int batchSize = 32;
+ final int batchSize = 64;
Object[] es = null;
int n, len = 1;
do {
@@ -1175,11 +1188,10 @@ public class LinkedBlockingDeque
public Spliterator trySplit() {
Node h;
- int b = batch;
- int n = (b <= 0) ? 1 : (b >= MAX_BATCH) ? MAX_BATCH : b + 1;
if (!exhausted &&
((h = current) != null || (h = first) != null)
&& h.next != null) {
+ int n = batch = Math.min(batch + 1, MAX_BATCH);
Object[] a = new Object[n];
final ReentrantLock lock = LinkedBlockingDeque.this.lock;
int i = 0;
@@ -1199,13 +1211,11 @@ public class LinkedBlockingDeque
}
else if ((est -= i) < 0L)
est = 0L;
- if (i > 0) {
- batch = i;
+ if (i > 0)
return Spliterators.spliterator
(a, 0, i, (Spliterator.ORDERED |
Spliterator.NONNULL |
Spliterator.CONCURRENT));
- }
}
return null;
}
@@ -1223,7 +1233,8 @@ public class LinkedBlockingDeque
e = p.item;
p = succ(p);
} while (e == null && p != null);
- exhausted = ((current = p) == null);
+ if ((current = p) == null)
+ exhausted = true;
} finally {
lock.unlock();
}
@@ -1288,7 +1299,7 @@ public class LinkedBlockingDeque
// Extract batches of elements while holding the lock; then
// run the action on the elements while not
final ReentrantLock lock = this.lock;
- final int batchSize = 32; // max number of elements per batch
+ final int batchSize = 64; // max number of elements per batch
Object[] es = null; // container for batch of elements
int n, len = 0;
do {
@@ -1314,6 +1325,83 @@ public class LinkedBlockingDeque
} while (n > 0 && p != null);
}
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean removeIf(Predicate super E> filter) {
+ Objects.requireNonNull(filter);
+ return bulkRemove(filter);
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean removeAll(Collection> c) {
+ Objects.requireNonNull(c);
+ return bulkRemove(e -> c.contains(e));
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean retainAll(Collection> c) {
+ Objects.requireNonNull(c);
+ return bulkRemove(e -> !c.contains(e));
+ }
+
+ /** Implementation of bulk remove methods. */
+ @SuppressWarnings("unchecked")
+ private boolean bulkRemove(Predicate super E> filter) {
+ boolean removed = false;
+ Node p = null;
+ final ReentrantLock lock = this.lock;
+ Node[] nodes = null;
+ int n, len = 0;
+ do {
+ // 1. Extract batch of up to 64 elements while holding the lock.
+ long deathRow = 0; // "bitset" of size 64
+ lock.lock();
+ try {
+ if (nodes == null) {
+ if (p == null) p = first;
+ for (Node q = p; q != null; q = succ(q))
+ if (q.item != null && ++len == 64)
+ break;
+ nodes = (Node[]) new Node>[len];
+ }
+ for (n = 0; p != null && n < len; p = succ(p))
+ nodes[n++] = p;
+ } finally {
+ lock.unlock();
+ }
+
+ // 2. Run the filter on the elements while lock is free.
+ for (int i = 0; i < n; i++) {
+ final E e;
+ if ((e = nodes[i].item) != null && filter.test(e))
+ deathRow |= 1L << i;
+ }
+
+ // 3. Remove any filtered elements while holding the lock.
+ if (deathRow != 0) {
+ lock.lock();
+ try {
+ for (int i = 0; i < n; i++) {
+ final Node q;
+ if ((deathRow & (1L << i)) != 0L
+ && (q = nodes[i]).item != null) {
+ unlink(q);
+ removed = true;
+ }
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+ } while (n > 0 && p != null);
+ return removed;
+ }
+
/**
* Saves this deque to a stream (that is, serializes it).
*
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java b/jdk/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java
index f60b4f6bfa0..7a1a2138073 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java
@@ -46,6 +46,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
+import java.util.function.Predicate;
/**
* An optionally-bounded {@linkplain BlockingQueue blocking queue} based on
@@ -66,9 +67,8 @@ import java.util.function.Consumer;
* dynamically created upon each insertion unless this would bring the
* queue above capacity.
*
- * This class and its iterator implement all of the
- * optional methods of the {@link Collection} and {@link
- * Iterator} interfaces.
+ *
This class and its iterator implement all of the optional
+ * methods of the {@link Collection} and {@link Iterator} interfaces.
*
*
This class is a member of the
*
@@ -507,17 +507,17 @@ public class LinkedBlockingQueue extends AbstractQueue
}
/**
- * Unlinks interior Node p with predecessor trail.
+ * Unlinks interior Node p with predecessor pred.
*/
- void unlink(Node p, Node trail) {
+ void unlink(Node p, Node pred) {
// assert putLock.isHeldByCurrentThread();
// assert takeLock.isHeldByCurrentThread();
// p.next is not changed, to allow iterators that are
// traversing p to maintain their weak-consistency guarantee.
p.item = null;
- trail.next = p.next;
+ pred.next = p.next;
if (last == p)
- last = trail;
+ last = pred;
if (count.getAndDecrement() == capacity)
notFull.signal();
}
@@ -537,11 +537,11 @@ public class LinkedBlockingQueue extends AbstractQueue
if (o == null) return false;
fullyLock();
try {
- for (Node trail = head, p = trail.next;
+ for (Node pred = head, p = pred.next;
p != null;
- trail = p, p = p.next) {
+ pred = p, p = p.next) {
if (o.equals(p.item)) {
- unlink(p, trail);
+ unlink(p, pred);
return true;
}
}
@@ -740,7 +740,9 @@ public class LinkedBlockingQueue extends AbstractQueue
* - (possibly multiple) interior removed nodes (p.item == null)
*/
Node succ(Node p) {
- return (p == (p = p.next)) ? head.next : p;
+ if (p == (p = p.next))
+ p = head.next;
+ return p;
}
/**
@@ -756,16 +758,18 @@ public class LinkedBlockingQueue extends AbstractQueue
return new Itr();
}
+ /**
+ * Weakly-consistent iterator.
+ *
+ * Lazily updated ancestor field provides expected O(1) remove(),
+ * but still O(n) in the worst case, whenever the saved ancestor
+ * is concurrently deleted.
+ */
private class Itr implements Iterator {
- /*
- * Basic weakly-consistent iterator. At all times hold the next
- * item to hand out so that if hasNext() reports true, we will
- * still have it to return even if lost race with a take etc.
- */
-
- private Node next;
- private E nextItem;
+ private Node next; // Node holding nextItem
+ private E nextItem; // next item to hand out
private Node lastRet;
+ private Node ancestor; // Helps unlink lastRet on remove()
Itr() {
fullyLock();
@@ -807,7 +811,7 @@ public class LinkedBlockingQueue extends AbstractQueue
if ((p = next) == null) return;
lastRet = p;
next = null;
- final int batchSize = 32;
+ final int batchSize = 64;
Object[] es = null;
int n, len = 1;
do {
@@ -840,19 +844,17 @@ public class LinkedBlockingQueue extends AbstractQueue
}
public void remove() {
- if (lastRet == null)
+ Node p = lastRet;
+ if (p == null)
throw new IllegalStateException();
+ lastRet = null;
fullyLock();
try {
- Node node = lastRet;
- lastRet = null;
- for (Node trail = head, p = trail.next;
- p != null;
- trail = p, p = p.next) {
- if (p == node) {
- unlink(p, trail);
- break;
- }
+ if (p.item != null) {
+ if (ancestor == null)
+ ancestor = head;
+ ancestor = findPred(p, ancestor);
+ unlink(p, ancestor);
}
} finally {
fullyUnlock();
@@ -877,11 +879,10 @@ public class LinkedBlockingQueue extends AbstractQueue
public Spliterator trySplit() {
Node h;
- int b = batch;
- int n = (b <= 0) ? 1 : (b >= MAX_BATCH) ? MAX_BATCH : b + 1;
if (!exhausted &&
((h = current) != null || (h = head.next) != null)
&& h.next != null) {
+ int n = batch = Math.min(batch + 1, MAX_BATCH);
Object[] a = new Object[n];
int i = 0;
Node p = current;
@@ -900,13 +901,11 @@ public class LinkedBlockingQueue extends AbstractQueue
}
else if ((est -= i) < 0L)
est = 0L;
- if (i > 0) {
- batch = i;
+ if (i > 0)
return Spliterators.spliterator
(a, 0, i, (Spliterator.ORDERED |
Spliterator.NONNULL |
Spliterator.CONCURRENT));
- }
}
return null;
}
@@ -923,7 +922,8 @@ public class LinkedBlockingQueue extends AbstractQueue
e = p.item;
p = succ(p);
} while (e == null && p != null);
- exhausted = ((current = p) == null);
+ if ((current = p) == null)
+ exhausted = true;
} finally {
fullyUnlock();
}
@@ -987,7 +987,7 @@ public class LinkedBlockingQueue extends AbstractQueue
void forEachFrom(Consumer super E> action, Node p) {
// Extract batches of elements while holding the lock; then
// run the action on the elements while not
- final int batchSize = 32; // max number of elements per batch
+ final int batchSize = 64; // max number of elements per batch
Object[] es = null; // container for batch of elements
int n, len = 0;
do {
@@ -1013,6 +1013,97 @@ public class LinkedBlockingQueue extends AbstractQueue
} while (n > 0 && p != null);
}
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean removeIf(Predicate super E> filter) {
+ Objects.requireNonNull(filter);
+ return bulkRemove(filter);
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean removeAll(Collection> c) {
+ Objects.requireNonNull(c);
+ return bulkRemove(e -> c.contains(e));
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean retainAll(Collection> c) {
+ Objects.requireNonNull(c);
+ return bulkRemove(e -> !c.contains(e));
+ }
+
+ /**
+ * Returns the predecessor of live node p, given a node that was
+ * once a live ancestor of p (or head); allows unlinking of p.
+ */
+ Node findPred(Node p, Node ancestor) {
+ // assert p.item != null;
+ if (ancestor.item == null)
+ ancestor = head;
+ // Fails with NPE if precondition not satisfied
+ for (Node q; (q = ancestor.next) != p; )
+ ancestor = q;
+ return ancestor;
+ }
+
+ /** Implementation of bulk remove methods. */
+ @SuppressWarnings("unchecked")
+ private boolean bulkRemove(Predicate super E> filter) {
+ boolean removed = false;
+ Node p = null, ancestor = head;
+ Node[] nodes = null;
+ int n, len = 0;
+ do {
+ // 1. Extract batch of up to 64 elements while holding the lock.
+ long deathRow = 0; // "bitset" of size 64
+ fullyLock();
+ try {
+ if (nodes == null) {
+ if (p == null) p = head.next;
+ for (Node q = p; q != null; q = succ(q))
+ if (q.item != null && ++len == 64)
+ break;
+ nodes = (Node[]) new Node>[len];
+ }
+ for (n = 0; p != null && n < len; p = succ(p))
+ nodes[n++] = p;
+ } finally {
+ fullyUnlock();
+ }
+
+ // 2. Run the filter on the elements while lock is free.
+ for (int i = 0; i < n; i++) {
+ final E e;
+ if ((e = nodes[i].item) != null && filter.test(e))
+ deathRow |= 1L << i;
+ }
+
+ // 3. Remove any filtered elements while holding the lock.
+ if (deathRow != 0) {
+ fullyLock();
+ try {
+ for (int i = 0; i < n; i++) {
+ final Node q;
+ if ((deathRow & (1L << i)) != 0L
+ && (q = nodes[i]).item != null) {
+ ancestor = findPred(q, ancestor);
+ unlink(q, ancestor);
+ removed = true;
+ }
+ }
+ } finally {
+ fullyUnlock();
+ }
+ }
+ } while (n > 0 && p != null);
+ return removed;
+ }
+
/**
* Saves this queue to a stream (that is, serializes it).
*
diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java b/jdk/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java
index 9433af6a72f..3a919c1efad 100644
--- a/jdk/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java
@@ -42,11 +42,13 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
+import java.util.Objects;
import java.util.Queue;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.concurrent.locks.LockSupport;
import java.util.function.Consumer;
+import java.util.function.Predicate;
/**
* An unbounded {@link TransferQueue} based on linked nodes.
@@ -61,16 +63,15 @@ import java.util.function.Consumer;
* asynchronous nature of these queues, determining the current number
* of elements requires a traversal of the elements, and so may report
* inaccurate results if this collection is modified during traversal.
- * Additionally, the bulk operations {@code addAll},
- * {@code removeAll}, {@code retainAll}, {@code containsAll},
- * and {@code toArray} are not guaranteed
- * to be performed atomically. For example, an iterator operating
- * concurrently with an {@code addAll} operation might view only some
- * of the added elements.
*
- * This class and its iterator implement all of the
- * optional methods of the {@link Collection} and {@link
- * Iterator} interfaces.
+ *
Bulk operations that add, remove, or examine multiple elements,
+ * such as {@link #addAll}, {@link #removeIf} or {@link #forEach},
+ * are not guaranteed to be performed atomically.
+ * For example, a {@code forEach} traversal concurrent with an {@code
+ * addAll} operation might observe only some of the added elements.
+ *
+ *
This class and its iterator implement all of the optional
+ * methods of the {@link Collection} and {@link Iterator} interfaces.
*
*
Memory consistency effects: As with other concurrent
* collections, actions in a thread prior to placing an object into a
@@ -158,9 +159,8 @@ public class LinkedTransferQueue extends AbstractQueue
* correctly perform enqueue and dequeue operations by traversing
* from a pointer to the initial node; CASing the item of the
* first unmatched node on match and CASing the next field of the
- * trailing node on appends. (Plus some special-casing when
- * initially empty). While this would be a terrible idea in
- * itself, it does have the benefit of not requiring ANY atomic
+ * trailing node on appends. While this would be a terrible idea
+ * in itself, it does have the benefit of not requiring ANY atomic
* updates on head/tail fields.
*
* We introduce here an approach that lies between the extremes of
@@ -196,15 +196,15 @@ public class LinkedTransferQueue extends AbstractQueue
* with a given probability per traversal step.
*
* In any strategy along these lines, because CASes updating
- * fields may fail, the actual slack may exceed targeted
- * slack. However, they may be retried at any time to maintain
- * targets. Even when using very small slack values, this
- * approach works well for dual queues because it allows all
- * operations up to the point of matching or appending an item
- * (hence potentially allowing progress by another thread) to be
- * read-only, thus not introducing any further contention. As
- * described below, we implement this by performing slack
- * maintenance retries only after these points.
+ * fields may fail, the actual slack may exceed targeted slack.
+ * However, they may be retried at any time to maintain targets.
+ * Even when using very small slack values, this approach works
+ * well for dual queues because it allows all operations up to the
+ * point of matching or appending an item (hence potentially
+ * allowing progress by another thread) to be read-only, thus not
+ * introducing any further contention. As described below, we
+ * implement this by performing slack maintenance retries only
+ * after these points.
*
* As an accompaniment to such techniques, traversal overhead can
* be further reduced without increasing contention of head
@@ -223,7 +223,7 @@ public class LinkedTransferQueue extends AbstractQueue
* (Similar issues arise in non-GC environments.) To cope with
* this in our implementation, upon CASing to advance the head
* pointer, we set the "next" link of the previous head to point
- * only to itself; thus limiting the length of connected dead lists.
+ * only to itself; thus limiting the length of chains of dead nodes.
* (We also take similar care to wipe out possibly garbage
* retaining values held in other Node fields.) However, doing so
* adds some further complexity to traversal: If any "next"
@@ -266,15 +266,6 @@ public class LinkedTransferQueue extends AbstractQueue
* interior nodes) except in the case of cancellation/removal (see
* below).
*
- * We allow both the head and tail fields to be null before any
- * nodes are enqueued; initializing upon first append. This
- * simplifies some other logic, as well as providing more
- * efficient explicit control paths instead of letting JVMs insert
- * implicit NullPointerExceptions when they are null. While not
- * currently fully implemented, we also leave open the possibility
- * of re-nulling these fields when empty (which is complicated to
- * arrange, for little benefit.)
- *
* All enqueue/dequeue operations are handled by the single method
* "xfer" with parameters indicating whether to act as some form
* of offer, put, poll, take, or transfer (each possibly with
@@ -282,44 +273,40 @@ public class LinkedTransferQueue extends AbstractQueue
* method outweighs the code bulk and maintenance problems of
* using separate methods for each case.
*
- * Operation consists of up to three phases. The first is
- * implemented within method xfer, the second in tryAppend, and
- * the third in method awaitMatch.
+ * Operation consists of up to two phases. The first is implemented
+ * in method xfer, the second in method awaitMatch.
*
- * 1. Try to match an existing node
+ * 1. Traverse until matching or appending (method xfer)
*
- * Starting at head, skip already-matched nodes until finding
- * an unmatched node of opposite mode, if one exists, in which
- * case matching it and returning, also if necessary updating
- * head to one past the matched node (or the node itself if the
- * list has no other unmatched nodes). If the CAS misses, then
- * a loop retries advancing head by two steps until either
- * success or the slack is at most two. By requiring that each
- * attempt advances head by two (if applicable), we ensure that
- * the slack does not grow without bound. Traversals also check
- * if the initial head is now off-list, in which case they
- * start at the new head.
+ * Conceptually, we simply traverse all nodes starting from head.
+ * If we encounter an unmatched node of opposite mode, we match
+ * it and return, also updating head (by at least 2 hops) to
+ * one past the matched node (or the node itself if it's the
+ * pinned trailing node). Traversals also check for the
+ * possibility of falling off-list, in which case they restart.
*
- * If no candidates are found and the call was untimed
- * poll/offer, (argument "how" is NOW) return.
+ * If the trailing node of the list is reached, a match is not
+ * possible. If this call was untimed poll or tryTransfer
+ * (argument "how" is NOW), return empty-handed immediately.
+ * Else a new node is CAS-appended. On successful append, if
+ * this call was ASYNC (e.g. offer), an element was
+ * successfully added to the end of the queue and we return.
*
- * 2. Try to append a new node (method tryAppend)
+ * Of course, this naive traversal is O(n) when no match is
+ * possible. We optimize the traversal by maintaining a tail
+ * pointer, which is expected to be "near" the end of the list.
+ * It is only safe to fast-forward to tail (in the presence of
+ * arbitrary concurrent changes) if it is pointing to a node of
+ * the same mode, even if it is dead (in this case no preceding
+ * node could still be matchable by this traversal). If we
+ * need to restart due to falling off-list, we can again
+ * fast-forward to tail, but only if it has changed since the
+ * last traversal (else we might loop forever). If tail cannot
+ * be used, traversal starts at head (but in this case we
+ * expect to be able to match near head). As with head, we
+ * CAS-advance the tail pointer by at least two hops.
*
- * Starting at current tail pointer, find the actual last node
- * and try to append a new node (or if head was null, establish
- * the first node). Nodes can be appended only if their
- * predecessors are either already matched or are of the same
- * mode. If we detect otherwise, then a new node with opposite
- * mode must have been appended during traversal, so we must
- * restart at phase 1. The traversal and update steps are
- * otherwise similar to phase 1: Retrying upon CAS misses and
- * checking for staleness. In particular, if a self-link is
- * encountered, then we can safely jump to a node on the list
- * by continuing the traversal at current head.
- *
- * On successful append, if the call was ASYNC, return.
- *
- * 3. Await match or cancellation (method awaitMatch)
+ * 2. Await match or cancellation (method awaitMatch)
*
* Wait for another thread to match node; instead cancelling if
* the current thread was interrupted or the wait timed out. On
@@ -373,12 +360,12 @@ public class LinkedTransferQueue extends AbstractQueue
* from, the head of list.
*
* Without taking these into account, it would be possible for an
- * unbounded number of supposedly removed nodes to remain
- * reachable. Situations leading to such buildup are uncommon but
- * can occur in practice; for example when a series of short timed
- * calls to poll repeatedly time out but never otherwise fall off
- * the list because of an untimed call to take at the front of the
- * queue.
+ * unbounded number of supposedly removed nodes to remain reachable.
+ * Situations leading to such buildup are uncommon but can occur
+ * in practice; for example when a series of short timed calls to
+ * poll repeatedly time out at the trailing node but otherwise
+ * never fall off the list because of an untimed call to take() at
+ * the front of the queue.
*
* When these cases arise, rather than always retraversing the
* entire list to find an actual predecessor to unlink (which
@@ -391,10 +378,9 @@ public class LinkedTransferQueue extends AbstractQueue
* We perform sweeps by the thread hitting threshold (rather than
* background threads or by spreading work to other threads)
* because in the main contexts in which removal occurs, the
- * caller is already timed-out, cancelled, or performing a
- * potentially O(n) operation (e.g. remove(x)), none of which are
- * time-critical enough to warrant the overhead that alternatives
- * would impose on other threads.
+ * caller is timed-out or cancelled, which are not time-critical
+ * enough to warrant the overhead that alternatives would impose
+ * on other threads.
*
* Because the sweepVotes estimate is conservative, and because
* nodes become unlinked "naturally" as they fall off the head of
@@ -406,6 +392,13 @@ public class LinkedTransferQueue extends AbstractQueue
* quiescent queues. The value defined below was chosen
* empirically to balance these under various timeout scenarios.
*
+ * Because traversal operations on the linked list of nodes are a
+ * natural opportunity to sweep dead nodes, we generally do so,
+ * including all the operations that might remove elements as they
+ * traverse, such as removeIf and Iterator.remove. This largely
+ * eliminates long chains of dead interior nodes, except from
+ * cancelled or timed out blocking operations.
+ *
* Note that we cannot self-link unlinked interior nodes during
* sweeps. However, the associated garbage chains terminate when
* some successor ultimately falls off the head of the list and is
@@ -446,54 +439,71 @@ public class LinkedTransferQueue extends AbstractQueue
/**
* Queue nodes. Uses Object, not E, for items to allow forgetting
- * them after use. Relies heavily on VarHandles to minimize
- * unnecessary ordering constraints: Writes that are intrinsically
- * ordered wrt other accesses or CASes use simple relaxed forms.
+ * them after use. Writes that are intrinsically ordered wrt
+ * other accesses or CASes use simple relaxed forms.
*/
static final class Node {
final boolean isData; // false if this is a request node
volatile Object item; // initially non-null if isData; CASed to match
volatile Node next;
- volatile Thread waiter; // null until waiting
+ volatile Thread waiter; // null when not waiting for a match
+
+ /**
+ * Constructs a data node holding item if item is non-null,
+ * else a request node. Uses relaxed write because item can
+ * only be seen after piggy-backing publication via CAS.
+ */
+ Node(Object item) {
+ ITEM.set(this, item);
+ isData = (item != null);
+ }
+
+ /** Constructs a (matched data) dummy node. */
+ Node() {
+ isData = true;
+ }
- // CAS methods for fields
final boolean casNext(Node cmp, Node val) {
+ // assert val != null;
return NEXT.compareAndSet(this, cmp, val);
}
final boolean casItem(Object cmp, Object val) {
- // assert cmp == null || cmp.getClass() != Node.class;
+ // assert isData == (cmp != null);
+ // assert isData == (val == null);
+ // assert !(cmp instanceof Node);
return ITEM.compareAndSet(this, cmp, val);
}
- /**
- * Constructs a new node. Uses relaxed write because item can
- * only be seen after publication via casNext.
- */
- Node(Object item, boolean isData) {
- ITEM.set(this, item); // relaxed write
- this.isData = isData;
- }
-
/**
* Links node to itself to avoid garbage retention. Called
* only after CASing head field, so uses relaxed write.
*/
- final void forgetNext() {
- NEXT.set(this, this);
+ final void selfLink() {
+ // assert isMatched();
+ NEXT.setRelease(this, this);
+ }
+
+ final void appendRelaxed(Node next) {
+ // assert next != null;
+ // assert this.next == null;
+ NEXT.set(this, next);
}
/**
- * Sets item to self and waiter to null, to avoid garbage
- * retention after matching or cancelling. Uses relaxed writes
- * because order is already constrained in the only calling
- * contexts: item is forgotten only after volatile/atomic
- * mechanics that extract items. Similarly, clearing waiter
- * follows either CAS or return from park (if ever parked;
- * else we don't care).
+ * Sets item (of a request node) to self and waiter to null,
+ * to avoid garbage retention after matching or cancelling.
+ * Uses relaxed writes because order is already constrained in
+ * the only calling contexts: item is forgotten only after
+ * volatile/atomic mechanics that extract items, and visitors
+ * of request nodes only ever check whether item is null.
+ * Similarly, clearing waiter follows either CAS or return
+ * from park (if ever parked; else we don't care).
*/
final void forgetContents() {
- ITEM.set(this, this);
+ // assert isMatched();
+ if (!isData)
+ ITEM.set(this, this);
WAITER.set(this, null);
}
@@ -502,15 +512,16 @@ public class LinkedTransferQueue extends AbstractQueue
* case of artificial matches due to cancellation.
*/
final boolean isMatched() {
- Object x = item;
- return (x == this) || ((x == null) == isData);
+ return isData == (item == null);
}
- /**
- * Returns true if this is an unmatched request node.
- */
- final boolean isUnmatchedRequest() {
- return !isData && item == null;
+ /** Tries to CAS-match this node; if successful, wakes waiter. */
+ final boolean tryMatch(Object cmp, Object val) {
+ if (casItem(cmp, val)) {
+ LockSupport.unpark(waiter);
+ return true;
+ }
+ return false;
}
/**
@@ -520,52 +531,46 @@ public class LinkedTransferQueue extends AbstractQueue
*/
final boolean cannotPrecede(boolean haveData) {
boolean d = isData;
- Object x;
- return d != haveData && (x = item) != this && (x != null) == d;
- }
-
- /**
- * Tries to artificially match a data node -- used by remove.
- */
- final boolean tryMatchData() {
- // assert isData;
- Object x = item;
- if (x != null && x != this && casItem(x, null)) {
- LockSupport.unpark(waiter);
- return true;
- }
- return false;
+ return d != haveData && d != (item == null);
}
private static final long serialVersionUID = -3375979862319811754L;
-
- // VarHandle mechanics
- private static final VarHandle ITEM;
- private static final VarHandle NEXT;
- private static final VarHandle WAITER;
- static {
- try {
- MethodHandles.Lookup l = MethodHandles.lookup();
- ITEM = l.findVarHandle(Node.class, "item", Object.class);
- NEXT = l.findVarHandle(Node.class, "next", Node.class);
- WAITER = l.findVarHandle(Node.class, "waiter", Thread.class);
- } catch (ReflectiveOperationException e) {
- throw new Error(e);
- }
- }
}
- /** head of the queue; null until first enqueue */
+ /**
+ * A node from which the first live (non-matched) node (if any)
+ * can be reached in O(1) time.
+ * Invariants:
+ * - all live nodes are reachable from head via .next
+ * - head != null
+ * - (tmp = head).next != tmp || tmp != head
+ * Non-invariants:
+ * - head may or may not be live
+ * - it is permitted for tail to lag behind head, that is, for tail
+ * to not be reachable from head!
+ */
transient volatile Node head;
- /** tail of the queue; null until first append */
+ /**
+ * A node from which the last node on list (that is, the unique
+ * node with node.next == null) can be reached in O(1) time.
+ * Invariants:
+ * - the last node is always reachable from tail via .next
+ * - tail != null
+ * Non-invariants:
+ * - tail may or may not be live
+ * - it is permitted for tail to lag behind head, that is, for tail
+ * to not be reachable from head!
+ * - tail.next may or may not be self-linked.
+ */
private transient volatile Node tail;
- /** The number of apparent failures to unsplice removed nodes */
+ /** The number of apparent failures to unsplice cancelled nodes */
private transient volatile int sweepVotes;
- // CAS methods for fields
private boolean casTail(Node cmp, Node val) {
+ // assert cmp != null;
+ // assert val != null;
return TAIL.compareAndSet(this, cmp, val);
}
@@ -573,13 +578,71 @@ public class LinkedTransferQueue extends AbstractQueue
return HEAD.compareAndSet(this, cmp, val);
}
- private boolean casSweepVotes(int cmp, int val) {
- return SWEEPVOTES.compareAndSet(this, cmp, val);
+ /** Atomic version of ++sweepVotes. */
+ private int incSweepVotes() {
+ return (int) SWEEPVOTES.getAndAdd(this, 1) + 1;
}
- /*
- * Possible values for "how" argument in xfer method.
+ /**
+ * Tries to CAS pred.next (or head, if pred is null) from c to p.
+ * Caller must ensure that we're not unlinking the trailing node.
*/
+ private boolean tryCasSuccessor(Node pred, Node c, Node p) {
+ // assert p != null;
+ // assert c.isData != (c.item != null);
+ // assert c != p;
+ if (pred != null)
+ return pred.casNext(c, p);
+ if (casHead(c, p)) {
+ c.selfLink();
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Collapses dead (matched) nodes between pred and q.
+ * @param pred the last known live node, or null if none
+ * @param c the first dead node
+ * @param p the last dead node
+ * @param q p.next: the next live node, or null if at end
+ * @return pred if pred still alive and CAS succeeded; else p
+ */
+ private Node skipDeadNodes(Node pred, Node c, Node p, Node q) {
+ // assert pred != c;
+ // assert p != q;
+ // assert c.isMatched();
+ // assert p.isMatched();
+ if (q == null) {
+ // Never unlink trailing node.
+ if (c == p) return pred;
+ q = p;
+ }
+ return (tryCasSuccessor(pred, c, q)
+ && (pred == null || !pred.isMatched()))
+ ? pred : p;
+ }
+
+ /**
+ * Collapses dead (matched) nodes from h (which was once head) to p.
+ * Caller ensures all nodes from h up to and including p are dead.
+ */
+ private void skipDeadNodesNearHead(Node h, Node p) {
+ // assert h != null;
+ // assert h != p;
+ // assert p.isMatched();
+ for (;;) {
+ final Node q;
+ if ((q = p.next) == null) break;
+ else if (!q.isMatched()) { p = q; break; }
+ else if (p == (p = q)) return;
+ }
+ if (casHead(h, p))
+ h.selfLink();
+ }
+
+ /* Possible values for "how" argument in xfer method. */
+
private static final int NOW = 0; // for untimed poll, tryTransfer
private static final int ASYNC = 1; // for offer, put, add
private static final int SYNC = 2; // for transfer, take
@@ -595,84 +658,32 @@ public class LinkedTransferQueue extends AbstractQueue
* @return an item if matched, else e
* @throws NullPointerException if haveData mode but e is null
*/
+ @SuppressWarnings("unchecked")
private E xfer(E e, boolean haveData, int how, long nanos) {
if (haveData && (e == null))
throw new NullPointerException();
- Node s = null; // the node to append, if needed
- retry:
- for (;;) { // restart on append race
-
- for (Node h = head, p = h; p != null;) { // find & match first node
- boolean isData = p.isData;
- Object item = p.item;
- if (item != p && (item != null) == isData) { // unmatched
- if (isData == haveData) // can't match
- break;
- if (p.casItem(item, e)) { // match
- for (Node q = p; q != h;) {
- Node n = q.next; // update by 2 unless singleton
- if (head == h && casHead(h, n == null ? q : n)) {
- h.forgetNext();
- break;
- } // advance and retry
- if ((h = head) == null ||
- (q = h.next) == null || !q.isMatched())
- break; // unless slack < 2
- }
- LockSupport.unpark(p.waiter);
- @SuppressWarnings("unchecked") E itemE = (E) item;
- return itemE;
+ restart: for (Node s = null, t = null, h = null;;) {
+ for (Node p = (t != (t = tail) && t.isData == haveData) ? t
+ : (h = head);; ) {
+ final Node q; final Object item;
+ if (p.isData != haveData
+ && haveData == ((item = p.item) == null)) {
+ if (h == null) h = head;
+ if (p.tryMatch(item, e)) {
+ if (h != p) skipDeadNodesNearHead(h, p);
+ return (E) item;
}
}
- Node n = p.next;
- p = (p != n) ? n : (h = head); // Use head if p offlist
- }
-
- if (how != NOW) { // No matches available
- if (s == null)
- s = new Node(e, haveData);
- Node pred = tryAppend(s, haveData);
- if (pred == null)
- continue retry; // lost race vs opposite mode
- if (how != ASYNC)
- return awaitMatch(s, pred, e, (how == TIMED), nanos);
- }
- return e; // not waiting
- }
- }
-
- /**
- * Tries to append node s as tail.
- *
- * @param s the node to append
- * @param haveData true if appending in data mode
- * @return null on failure due to losing race with append in
- * different mode, else s's predecessor, or s itself if no
- * predecessor
- */
- private Node tryAppend(Node s, boolean haveData) {
- for (Node t = tail, p = t;;) { // move p to last node and append
- Node n, u; // temps for reads of next & tail
- if (p == null && (p = head) == null) {
- if (casHead(null, s))
- return s; // initialize
- }
- else if (p.cannotPrecede(haveData))
- return null; // lost race vs opposite mode
- else if ((n = p.next) != null) // not last; keep traversing
- p = p != t && t != (u = tail) ? (t = u) : // stale tail
- (p != n) ? n : null; // restart if off list
- else if (!p.casNext(null, s))
- p = p.next; // re-read on CAS failure
- else {
- if (p != t) { // update if slack now >= 2
- while ((tail != t || !casTail(t, s)) &&
- (t = tail) != null &&
- (s = t.next) != null && // advance and retry
- (s = s.next) != null && s != t);
+ if ((q = p.next) == null) {
+ if (how == NOW) return e;
+ if (s == null) s = new Node(e);
+ if (!p.casNext(null, s)) continue;
+ if (p != t) casTail(t, s);
+ if (how == ASYNC) return e;
+ return awaitMatch(s, p, e, (how == TIMED), nanos);
}
- return p;
+ if (p == (p = q)) continue restart;
}
}
}
@@ -681,9 +692,9 @@ public class LinkedTransferQueue